WIP: guile support
This commit is contained in:
parent
7369fcac75
commit
746b94599a
|
@ -197,6 +197,7 @@ set(TIC80CORE_SRC
|
|||
${TIC80CORE_DIR}/luaapi.c
|
||||
${TIC80CORE_DIR}/wrenapi.c
|
||||
${TIC80CORE_DIR}/squirrelapi.c
|
||||
${TIC80CORE_DIR}/guileapi.c
|
||||
${TIC80CORE_DIR}/ext/gif.c
|
||||
3rd-party/blip-buf/blip_buf.c # TODO: link it as lib?
|
||||
3rd-party/duktape-2.2.0/src/duktape.c # TODO: link it as lib?
|
||||
|
@ -637,3 +638,11 @@ foreach(TIC80_OUTPUT ${TIC80_OUTPUTS})
|
|||
endif()
|
||||
|
||||
endforeach()
|
||||
|
||||
# LMAO GUILE
|
||||
# include_directories(/gnu/store/9alic3caqhay3h8mx4iihpmyj6ymqpcx-guile-2.2.4/include/guile/2.2)
|
||||
# link_directories(/gnu/store/9alic3caqhay3h8mx4iihpmyj6ymqpcx-guile-2.2.4/include/guile/2.2 /gnu/store/04vqghzmpqzxpd94h1q931xpmazp5s7g-libgc-7.6.6/lib)
|
||||
include_directories(/usr/include/guile/2.2)
|
||||
target_link_libraries(tic80core guile-2.2 pthread gc)
|
||||
SET(CMAKE_C_COMPILER /usr/bin/gcc)
|
||||
SET(CMAKE_CXX_COMPILER /usr/bin/c++)
|
||||
|
|
|
@ -26,7 +26,8 @@
|
|||
!defined(TIC_BUILD_WITH_MOON) && \
|
||||
!defined(TIC_BUILD_WITH_FENNEL) && \
|
||||
!defined(TIC_BUILD_WITH_JS) && \
|
||||
!defined(TIC_BUILD_WITH_WREN)
|
||||
!defined(TIC_BUILD_WITH_WREN) && \
|
||||
!defined(TIC_BUILD_WITH_GUILE)
|
||||
|
||||
#define TIC_BUILD_WITH_LUA 1
|
||||
#define TIC_BUILD_WITH_MOON 1
|
||||
|
@ -34,7 +35,7 @@
|
|||
#define TIC_BUILD_WITH_JS 1
|
||||
#define TIC_BUILD_WITH_WREN 1
|
||||
#define TIC_BUILD_WITH_SQUIRREL 1
|
||||
|
||||
#define TIC_BUILD_WITH_GUILE 1
|
||||
#endif
|
||||
|
||||
#if defined(__APPLE__)
|
||||
|
|
|
@ -77,6 +77,10 @@ typedef enum
|
|||
SquirrelScript,
|
||||
#endif
|
||||
|
||||
#if defined(TIC_BUILD_WITH_GUILE)
|
||||
Guile,
|
||||
#endif
|
||||
|
||||
} ScriptLang;
|
||||
|
||||
#if defined(__TIC_WINDOWS__) || defined(__TIC_LINUX__) || defined(__TIC_MACOSX__)
|
||||
|
@ -490,6 +494,10 @@ static void* getDemoCart(Console* console, ScriptLang script, s32* size)
|
|||
case JavaScript: strcpy(path, DefaultJSTicPath); break;
|
||||
#endif
|
||||
|
||||
#if defined(TIC_BUILD_WITH_GUILE)
|
||||
case Guile: strcpy(path, DefaultFennelTicPath); break;
|
||||
#endif
|
||||
|
||||
#if defined(TIC_BUILD_WITH_WREN)
|
||||
case WrenScript: strcpy(path, DefaultWrenTicPath); break;
|
||||
#endif
|
||||
|
@ -695,6 +703,7 @@ static bool hasProjectExt(const char* name)
|
|||
|| hasExt(name, PROJECT_JS_EXT)
|
||||
|| hasExt(name, PROJECT_WREN_EXT)
|
||||
|| hasExt(name, PROJECT_SQUIRREL_EXT)
|
||||
|| hasExt(name, PROJECT_GUILE_EXT)
|
||||
|| hasExt(name, PROJECT_FENNEL_EXT);
|
||||
}
|
||||
|
||||
|
@ -706,7 +715,8 @@ static const char* projectComment(const char* name)
|
|||
|| hasExt(name, PROJECT_WREN_EXT)
|
||||
|| hasExt(name, PROJECT_SQUIRREL_EXT))
|
||||
comment = "//";
|
||||
else if(hasExt(name, PROJECT_FENNEL_EXT))
|
||||
else if(hasExt(name, PROJECT_FENNEL_EXT)
|
||||
|| hasExt(name, PROJECT_GUILE_EXT))
|
||||
comment = ";;";
|
||||
else
|
||||
comment = "--";
|
||||
|
@ -1089,6 +1099,9 @@ static void onConsoleLoadCommandConfirmed(Console* console, const char* param)
|
|||
if(!fsExistsFile(console->fs, name))
|
||||
name = getName(param, PROJECT_FENNEL_EXT);
|
||||
|
||||
if(!fsExistsFile(console->fs, name))
|
||||
name = getName(param, PROJECT_GUILE_EXT);
|
||||
|
||||
if(!fsExistsFile(console->fs, name))
|
||||
name = getName(param, PROJECT_SQUIRREL_EXT);
|
||||
|
||||
|
@ -1265,6 +1278,14 @@ static void onConsoleNewCommandConfirmed(Console* console, const char* param)
|
|||
|
||||
#endif /* defined(TIC_BUILD_WITH_LUA) */
|
||||
|
||||
#if defined(TIC_BUILD_WITH_GUILE)
|
||||
if(strcmp(param, "guile") == 0)
|
||||
{
|
||||
loadDemo(console, Guile);
|
||||
done = true;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(TIC_BUILD_WITH_JS)
|
||||
if(strcmp(param, "js") == 0 || strcmp(param, "javascript") == 0)
|
||||
{
|
||||
|
|
|
@ -0,0 +1,205 @@
|
|||
#include "machine.h"
|
||||
|
||||
//#if defined(TIC_BUILD_WITH_GUILE)
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <libguile.h>
|
||||
|
||||
static const char TicMachine[] = "_TIC80";
|
||||
|
||||
// this wouldn't work with multiple guile instances
|
||||
// pls hide this inside the guile interpreter
|
||||
tic_mem* memory = NULL;
|
||||
|
||||
/* Utils */
|
||||
static s32 getGuileNumber(SCM num)
|
||||
{
|
||||
return (s32)scm_to_signed_integer(num, INT_MIN, INT_MAX);
|
||||
}
|
||||
|
||||
/* Implementing the TIC-80 API */
|
||||
static SCM guile_btn(SCM id)
|
||||
{
|
||||
int r = 0;
|
||||
if (id != SCM_UNDEFINED)
|
||||
{
|
||||
u32 c_id = getGuileNumber(id);
|
||||
r = memory->ram.input.gamepads.data & (1 << c_id);
|
||||
}
|
||||
else
|
||||
{
|
||||
r = (int)memory->ram.input.gamepads.data;
|
||||
}
|
||||
return scm_from_bool(r);
|
||||
}
|
||||
|
||||
static SCM guile_btnp(SCM id, SCM hold, SCM period)
|
||||
{
|
||||
s32 c_id = -1;
|
||||
s32 c_hold = -1;
|
||||
s32 c_period = -1;
|
||||
|
||||
if (id != SCM_UNDEFINED) c_id = getGuileNumber(id);
|
||||
if (hold != SCM_UNDEFINED) c_hold = getGuileNumber(hold);
|
||||
if (period != SCM_UNDEFINED) c_period = getGuileNumber(period);
|
||||
int r = (int)memory->api.btnp(memory, c_id, c_hold, c_period);
|
||||
return scm_from_bool(r);
|
||||
}
|
||||
|
||||
static SCM guile_cls(SCM c)
|
||||
{
|
||||
if(c != SCM_UNDEFINED)
|
||||
memory->api.clear(memory, getGuileNumber(c));
|
||||
else
|
||||
memory->api.clear(memory, 0);
|
||||
return SCM_UNDEFINED;
|
||||
}
|
||||
|
||||
static SCM guile_print(SCM text, SCM x, SCM y, SCM color,
|
||||
SCM fixed, SCM scale, SCM smallfont)
|
||||
{
|
||||
if (text == SCM_UNDEFINED) return scm_from_int(0);
|
||||
char * c_txt = scm_to_stringn(text,NULL,"UTF-8",SCM_FAILED_CONVERSION_QUESTION_MARK);
|
||||
s32 c_x = 0;
|
||||
if (x != SCM_UNDEFINED) c_x = scm_to_int(x);
|
||||
s32 c_y = 0;
|
||||
if (y != SCM_UNDEFINED) c_y = scm_to_int(y);
|
||||
s32 c_color = TIC_PALETTE_SIZE-1;
|
||||
if (color != SCM_UNDEFINED) c_color = scm_to_int(color) % TIC_PALETTE_SIZE;
|
||||
bool c_fixed = false;
|
||||
if (fixed != SCM_UNDEFINED) c_fixed = scm_to_bool(fixed);
|
||||
s32 c_scale = 1;
|
||||
if (scale != SCM_UNDEFINED) c_scale = scm_to_int(scale);
|
||||
bool alt = false;
|
||||
if (smallfont != SCM_UNDEFINED) alt = scm_to_bool(smallfont);
|
||||
s32 width = memory->api.text_ex(memory, c_txt ? c_txt : "nil",
|
||||
c_x, c_y, c_color, c_fixed, c_scale, alt);
|
||||
return scm_from_int(width);
|
||||
}
|
||||
|
||||
static SCM guile_rect(SCM x, SCM y, SCM w, SCM h, SCM color)
|
||||
{
|
||||
s32 c_x = -1;
|
||||
s32 c_y = -1;
|
||||
s32 c_w = -1;
|
||||
s32 c_h = -1;
|
||||
s32 c_color = -1;
|
||||
if (x != SCM_UNDEFINED) c_x = getGuileNumber(x);
|
||||
if (y != SCM_UNDEFINED) c_y = getGuileNumber(y);
|
||||
if (w != SCM_UNDEFINED) c_w = getGuileNumber(w);
|
||||
if (h != SCM_UNDEFINED) c_h = getGuileNumber(h);
|
||||
if (color != SCM_UNDEFINED) c_color = getGuileNumber(color);
|
||||
memory->api.rect(memory, c_x, c_y, c_w, c_h, c_color);
|
||||
return scm_from_bool(1);
|
||||
}
|
||||
|
||||
|
||||
static void* guile_register_functions(void * data) {
|
||||
scm_c_define_gsubr("btnp", 0, 3, 0, &guile_btnp);
|
||||
scm_c_define_gsubr("cls", 0, 1, 0, &guile_cls);
|
||||
scm_c_define_gsubr("rect", 5, 0, 0, &guile_rect);
|
||||
scm_c_define_gsubr("print", 1, 6, 0, &guile_print);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// TODO: pre-compilation
|
||||
// TODO: error handling much?
|
||||
static void evalGuile(tic_mem* tic, const char* code)
|
||||
{
|
||||
scm_c_eval_string(code);
|
||||
}
|
||||
|
||||
static bool initGuile(tic_mem* tic, const char* code)
|
||||
{
|
||||
memory = tic;
|
||||
scm_with_guile (&guile_register_functions, NULL);
|
||||
evalGuile(tic, code);
|
||||
return true;
|
||||
}
|
||||
|
||||
static void closeGuile(tic_mem* tic)
|
||||
{
|
||||
}
|
||||
|
||||
static void callGuileTick(tic_mem* tic)
|
||||
{
|
||||
SCM ticProc = scm_c_eval_string("TIC");
|
||||
// TODO, pre-load this in init
|
||||
if (scm_procedure_p(ticProc))
|
||||
{
|
||||
// TODO: check for errors
|
||||
scm_call_0(ticProc);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("OwO not a procedure heh");
|
||||
}
|
||||
}
|
||||
|
||||
static void callGuileScanline(tic_mem* memory, s32 row, void* data)
|
||||
{
|
||||
}
|
||||
|
||||
static void callGuileOverline(tic_mem* memory, void* data)
|
||||
{
|
||||
}
|
||||
|
||||
static const tic_outline_item* getGuileOutline(const char* code, s32* size)
|
||||
{
|
||||
static tic_outline_item* items = NULL;
|
||||
|
||||
if(items)
|
||||
{
|
||||
free(items);
|
||||
items = NULL;
|
||||
}
|
||||
|
||||
printf("UwU..\n");
|
||||
return items;
|
||||
}
|
||||
|
||||
|
||||
static const char* const GuileKeywords [] =
|
||||
{
|
||||
"do", "values", "if", "when", "each", "for", "fn", "lambda", "partial",
|
||||
"while", "set", "global", "var", "local", "let", "tset",
|
||||
"or", "and", "true", "false", "nil", "#", ":", "->", "->>"
|
||||
};
|
||||
|
||||
static const char* const ApiKeywords[] = API_KEYWORDS;
|
||||
|
||||
static const tic_script_config GuileSyntaxConfig =
|
||||
{
|
||||
.init = initGuile,
|
||||
.close = closeGuile,
|
||||
.tick = callGuileTick,
|
||||
.scanline = callGuileScanline,
|
||||
.overline = callGuileOverline,
|
||||
|
||||
.getOutline = getGuileOutline,
|
||||
.parse = parseCode,
|
||||
.eval = evalGuile,
|
||||
|
||||
.blockCommentStart = NULL,
|
||||
.blockCommentEnd = NULL,
|
||||
.blockStringStart = NULL,
|
||||
.blockStringEnd = NULL,
|
||||
.singleComment = ";",
|
||||
|
||||
.keywords = GuileKeywords,
|
||||
.keywordsCount = COUNT_OF(GuileKeywords),
|
||||
|
||||
.api = ApiKeywords,
|
||||
.apiCount = COUNT_OF(ApiKeywords),
|
||||
};
|
||||
|
||||
const tic_script_config* getGuileConfig()
|
||||
{
|
||||
return &GuileSyntaxConfig;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//#endif /* defined(TIC_BUILD_WITH_GUILE) */
|
|
@ -198,6 +198,10 @@ const tic_script_config* getFennelConfig();
|
|||
const tic_script_config* getJsScriptConfig();
|
||||
#endif
|
||||
|
||||
#if defined(TIC_BUILD_WITH_GUILE)
|
||||
const tic_script_config* getGuileConfig();
|
||||
#endif
|
||||
|
||||
#if defined(TIC_BUILD_WITH_WREN)
|
||||
const tic_script_config* getWrenScriptConfig();
|
||||
#endif
|
||||
|
|
|
@ -61,6 +61,7 @@
|
|||
#define PROJECT_WREN_EXT ".wren"
|
||||
#define PROJECT_SQUIRREL_EXT ".nut"
|
||||
#define PROJECT_FENNEL_EXT ".fnl"
|
||||
#define PROJECT_GUILE_EXT ".scm"
|
||||
|
||||
typedef enum
|
||||
{
|
||||
|
|
|
@ -398,6 +398,7 @@ static bool addMenuItem(const char* name, const char* info, s32 id, void* ptr, b
|
|||
|| hasExt(name, PROJECT_WREN_EXT)
|
||||
|| hasExt(name, PROJECT_FENNEL_EXT)
|
||||
|| hasExt(name, PROJECT_SQUIRREL_EXT)
|
||||
|| hasExt(name, PROJECT_GUILE_EXT)
|
||||
#endif
|
||||
)
|
||||
{
|
||||
|
|
|
@ -1635,6 +1635,11 @@ static const tic_script_config* getScriptConfig(const char* code)
|
|||
return getFennelConfig();
|
||||
#endif
|
||||
|
||||
#if defined(TIC_BUILD_WITH_GUILE)
|
||||
if(compareMetatag(code, "script", "guile", getGuileConfig()->singleComment))
|
||||
return getGuileConfig();
|
||||
#endif
|
||||
|
||||
#if defined(TIC_BUILD_WITH_JS)
|
||||
if(compareMetatag(code, "script", "js", getJsScriptConfig()->singleComment) ||
|
||||
compareMetatag(code, "script", "javascript", getJsScriptConfig()->singleComment))
|
||||
|
|
|
@ -0,0 +1,44 @@
|
|||
;; title: game title
|
||||
;; author: game developer
|
||||
;; desc: short description
|
||||
;; script: guile
|
||||
|
||||
(use-modules (srfi srfi-28))
|
||||
|
||||
(define c 2)
|
||||
(define (TIC)
|
||||
(if (btnp 0)
|
||||
(set! c (+ c 1)))
|
||||
(if (btnp 1)
|
||||
(set! c (- c 1)))
|
||||
(cls c)
|
||||
(rect 0 0 240 8 0)
|
||||
(print (string-append
|
||||
"cls(" (format "~a" c)
|
||||
") -- Use Up/Down to change")))
|
||||
|
||||
;; <TILES>
|
||||
;; 001:efffffffff222222f8888888f8222222f8fffffff8ff0ffff8ff0ffff8ff0fff
|
||||
;; 002:fffffeee2222ffee88880fee22280feefff80fff0ff80f0f0ff80f0f0ff80f0f
|
||||
;; 003:efffffffff222222f8888888f8222222f8fffffff8fffffff8ff0ffff8ff0fff
|
||||
;; 004:fffffeee2222ffee88880fee22280feefff80ffffff80f0f0ff80f0f0ff80f0f
|
||||
;; 017:f8fffffff8888888f888f888f8888ffff8888888f2222222ff000fffefffffef
|
||||
;; 018:fff800ff88880ffef8880fee88880fee88880fee2222ffee000ffeeeffffeeee
|
||||
;; 019:f8fffffff8888888f888f888f8888ffff8888888f2222222ff000fffefffffef
|
||||
;; 020:fff800ff88880ffef8880fee88880fee88880fee2222ffee000ffeeeffffeeee
|
||||
;; </TILES>
|
||||
|
||||
;; <WAVES>
|
||||
;; 000:00000000ffffffff00000000ffffffff
|
||||
;; 001:0123456789abcdeffedcba9876543210
|
||||
;; 002:0123456789abcdef0123456789abcdef
|
||||
;; </WAVES>
|
||||
|
||||
;; <SFX>
|
||||
;; 000:000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000304000000000
|
||||
;; </SFX>
|
||||
|
||||
;; <PALETTE>
|
||||
;; 000:140c1c44243430346d4e4a4e854c30346524d04648757161597dced27d2c8595a16daa2cd2aa996dc2cadad45edeeed6
|
||||
;; </PALETTE>
|
||||
|
Loading…
Reference in New Issue