diff --git a/.travis.yml b/.travis.yml index 38dffc2..0399c49 100644 --- a/.travis.yml +++ b/.travis.yml @@ -24,7 +24,7 @@ os: osx language: c before_install: - brew update - - brew install sdl2 + - brew install sdl2 lua before_script: - cd src script: diff --git a/src/cpu.c b/src/cpu.c index 3866cb7..e7ca067 100644 --- a/src/cpu.c +++ b/src/cpu.c @@ -21,6 +21,7 @@ // SOFTWARE. #include +#include #include #include #include @@ -101,15 +102,6 @@ void _cpu_set_status(struct cpu_t *cpu, uint8_t status) { -static void ewm_lua_push_cpu(struct ewm_lua_t *lua, struct cpu_t *cpu) { - void *cpu_data = lua_newuserdata(lua->state, sizeof(struct cpu_t*)); - *((struct cpu_t**) cpu_data) = cpu; - luaL_getmetatable(lua->state, "cpu_meta_table"); - lua_setmetatable(lua->state, -2); -} - - - static int cpu_execute_instruction(struct cpu_t *cpu) { /* Trace code - Refactor into its own function or module */ @@ -155,23 +147,23 @@ static int cpu_execute_instruction(struct cpu_t *cpu) { switch (i->bytes) { case 1: lua_rawgeti(cpu->lua->state, LUA_REGISTRYINDEX, xxx_fn); + ewm_lua_push_cpu(cpu->lua, cpu); lua_pushinteger(cpu->lua->state, i->opcode); lua_pushinteger(cpu->lua->state, 0); - ewm_lua_push_cpu(cpu->lua, cpu); lua_call(cpu->lua->state, 3, 0); break; case 2: lua_rawgeti(cpu->lua->state, LUA_REGISTRYINDEX, xxx_fn); + ewm_lua_push_cpu(cpu->lua, cpu); lua_pushinteger(cpu->lua->state, i->opcode); lua_pushinteger(cpu->lua->state, mem_get_byte(cpu, pc+1)); - ewm_lua_push_cpu(cpu->lua, cpu); lua_call(cpu->lua->state, 3, 0); break; case 3: lua_rawgeti(cpu->lua->state, LUA_REGISTRYINDEX, xxx_fn); + ewm_lua_push_cpu(cpu->lua, cpu); lua_pushinteger(cpu->lua->state, i->opcode); lua_pushinteger(cpu->lua->state, mem_get_word(cpu, pc+1)); - ewm_lua_push_cpu(cpu->lua, cpu); lua_call(cpu->lua->state, 3, 0); break; } @@ -494,6 +486,7 @@ int cpu_step(struct cpu_t *cpu) { // cpu state functions +#if 0 static int lua_cpu_get_a(lua_State *state) { void *cpu_data = luaL_checkudata(state, 1, "cpu_meta_table"); struct cpu_t *cpu = *((struct cpu_t**) cpu_data); @@ -518,6 +511,94 @@ static int lua_cpu_get_pc(lua_State *state) { lua_pushnumber(state, cpu->state.pc); return 1; } +#endif + +static int lua_cpu_reset(lua_State *state) { + printf("This is cpu.reset()\n"); + return 0; +} + +static int lua_cpu_index(lua_State *state) { + printf("This is cpu.__index()\n"); + + void *cpu_data = luaL_checkudata(state, 1, "cpu_meta_table"); + struct cpu_t *cpu = *((struct cpu_t**) cpu_data); + + if(!lua_isstring(state, 2)) { + printf("TODO lua_cpu_index: arg 2 is not a string\n"); + return 0; + } + + const char *name = lua_tostring(state, 2); + + if (strcmp(name, "a") == 0) { + lua_pushnumber(state, cpu->state.a); + return 1; + } + + if (strcmp(name, "x") == 0) { + lua_pushnumber(state, cpu->state.x); + return 1; + } + + if (strcmp(name, "y") == 0) { + lua_pushnumber(state, cpu->state.y); + return 1; + } + + if (strcmp(name, "pc") == 0) { + lua_pushnumber(state, cpu->state.pc); + return 1; + } + + printf("TODO lua_cpu_index: Unknown property so what do we do?\n"); + + return 0; +} + +static int lua_cpu_new_index(lua_State *state) { + printf("This is cpu.__newindex()\n"); + + void *cpu_data = luaL_checkudata(state, 1, "cpu_meta_table"); + struct cpu_t *cpu = *((struct cpu_t**) cpu_data); + + if(!lua_isstring(state, 2)) { + printf("TODO lua_cpu_new_index: arg 2 is not a string\n"); + return 0; + } + const char *name = lua_tostring(state, 2); + + if(!lua_isnumber(state, 3)) { + printf("TODO lua_cpu_new_index: arg 3 is not a string\n"); + + return 0; + } + int value = lua_tointeger(state, 3); + + if (strcmp(name, "a") == 0) { + cpu->state.a = (uint8_t) value; + return 0; + } + + if (strcmp(name, "x") == 0) { + cpu->state.x = (uint8_t) value; + return 0; + } + + if (strcmp(name, "y") == 0) { + cpu->state.y = (uint8_t) value; + return 0; + } + + if (strcmp(name, "pc") == 0) { + cpu->state.pc = (uint16_t) value; // TODO Does this actually work? + return 0; + } + + printf("TODO lua_cpu_newindex: Unknown property so what do we do?\n"); + + return 0; +} // cpu module functions @@ -554,29 +635,26 @@ static int ewm_cpu_luaopen(lua_State *state) { {NULL, NULL} }; luaL_newlib(state, cpu_functions); + return 1; } int ewm_cpu_init_lua(struct cpu_t *cpu, struct ewm_lua_t *lua) { - cpu->lua = lua; - - // Register the module + cpu->lua = lua; // TODO This needs to move to cpu_luaopen so that + // we don't actually enable lua support until this + // module is required in a script. Same for other + // components. luaL_requiref(cpu->lua->state, "cpu", ewm_cpu_luaopen, 0); - // Register the cpu meta table - luaL_newmetatable(cpu->lua->state, "cpu_meta_table"); - luaL_Reg cpu_functions[] = { - {"a", lua_cpu_get_a}, - {"pc", lua_cpu_get_pc}, + luaL_Reg functions[] = { + //{"a", lua_cpu_get_a}, + //{"pc", lua_cpu_get_pc}, + {"reset", lua_cpu_reset}, + {"__index", lua_cpu_index}, + {"__newindex", lua_cpu_new_index}, {NULL, NULL} }; - luaL_setfuncs(cpu->lua->state, cpu_functions, 0); - - lua_pushvalue(cpu->lua->state, -1); - lua_setfield(cpu->lua->state, -1, "__index"); - - // Keep it around - lua_setglobal(cpu->lua->state, "CPU"); // TODO I don't think we actually need this + ewm_lua_register_component(lua->state, "cpu", functions); return 0; } diff --git a/src/cpu.h b/src/cpu.h index bc1b5fe..21a1124 100644 --- a/src/cpu.h +++ b/src/cpu.h @@ -27,10 +27,6 @@ #include #include -#include -#include -#include - #define EWM_CPU_MODEL_6502 0 #define EWM_CPU_MODEL_65C02 1 diff --git a/src/dsk.c b/src/dsk.c index 5684630..761222e 100644 --- a/src/dsk.c +++ b/src/dsk.c @@ -30,6 +30,7 @@ #include "mem.h" #include "cpu.h" #include "utl.h" +#include "lua.h" #include "dsk.h" // @@ -553,3 +554,25 @@ int ewm_dsk_set_disk_file(struct ewm_dsk_t *dsk, uint8_t drive, bool readonly, c return result; } + +// Lua Support + +static int ewm_dsk_lua_hello(lua_State *lua) { + printf("This is dsk.hello()\n"); + return 0; +} + +int ewm_dsk_luaopen(lua_State *state) { + luaL_Reg functions[] = { + {"hello", ewm_dsk_lua_hello}, + {NULL, NULL} + }; + luaL_newlib(state, functions); + return 1; +} + +int ewm_dsk_init_lua(struct ewm_dsk_t *dsk, struct ewm_lua_t *lua) { + dsk->lua = lua; + luaL_requiref(dsk->lua->state, "dsk", ewm_dsk_luaopen, 0); + return 0; +} diff --git a/src/dsk.h b/src/dsk.h index d63fa70..c48e2cb 100644 --- a/src/dsk.h +++ b/src/dsk.h @@ -28,6 +28,7 @@ struct cpu_t; struct mem_t; +struct ewm_lua_t; #define EWM_DSK_DRIVE1 (0) #define EWM_DSK_DRIVE2 (1) @@ -61,6 +62,7 @@ struct ewm_dsk_t { struct ewm_dsk_drive_t drives[2]; uint8_t drive; // 0 based int skip; + struct ewm_lua_t *lua; }; #define EWM_DSK_TYPE_UNKNOWN (-1) @@ -72,4 +74,6 @@ struct ewm_dsk_t *ewm_dsk_create(struct cpu_t *cpu); int ewm_dsk_set_disk_data(struct ewm_dsk_t *dsk, uint8_t index, bool readonly, void *data, size_t length, int type); int ewm_dsk_set_disk_file(struct ewm_dsk_t *dsk, uint8_t index, bool readonly, char *path); +int ewm_dsk_init_lua(struct ewm_dsk_t *dsk, struct ewm_lua_t *lua); + #endif diff --git a/src/lua.c b/src/lua.c index 6152a1b..834ad35 100644 --- a/src/lua.c +++ b/src/lua.c @@ -28,18 +28,17 @@ #include #include "lua.h" +#include "two.h" +#include "cpu.h" +#include "dsk.h" -int ewm_lua_init(struct ewm_lua_t *lua) { +static int ewm_lua_init(struct ewm_lua_t *lua) { memset(lua, 0x00, sizeof(struct ewm_lua_t)); lua->state = luaL_newstate(); luaL_openlibs(lua->state); return 0; } -int ewm_lua_load_script(struct ewm_lua_t *lua, char *script_path) { - return luaL_dofile(lua->state, script_path); -} - struct ewm_lua_t *ewm_lua_create() { struct ewm_lua_t *lua = malloc(sizeof(struct ewm_lua_t)); if (ewm_lua_init(lua) != 0) { @@ -48,3 +47,50 @@ struct ewm_lua_t *ewm_lua_create() { } return lua; } + +int ewm_lua_load_script(struct ewm_lua_t *lua, char *script_path) { + return luaL_dofile(lua->state, script_path); +} + +void ewm_lua_push_cpu(struct ewm_lua_t *lua, struct cpu_t *cpu) { + void *cpu_data = lua_newuserdata(lua->state, sizeof(struct cpu_t*)); + *((struct cpu_t**) cpu_data) = cpu; + luaL_getmetatable(lua->state, "cpu_meta_table"); + lua_setmetatable(lua->state, -2); +} + +void ewm_lua_push_two(struct ewm_lua_t *lua, struct ewm_two_t *two) { + void *two_data = lua_newuserdata(lua->state, sizeof(struct ewm_two_t*)); + *((struct ewm_two_t**) two_data) = two; + luaL_getmetatable(lua->state, "two_meta_table"); + lua_setmetatable(lua->state, -2); +} + +void ewm_lua_push_dsk(struct ewm_lua_t *lua, struct ewm_dsk_t *dsk) { + void *dsk_data = lua_newuserdata(lua->state, sizeof(struct ewm_dsk_t*)); + *((struct ewm_dsk_t**) dsk_data) = dsk; + luaL_getmetatable(lua->state, "dsk_meta_table"); + lua_setmetatable(lua->state, -2); +} + +void ewm_lua_register_component(lua_State *state, char *name, luaL_Reg *functions) { + char table_name[64]; + strncpy(table_name, name, sizeof(table_name)-1); + strncat(table_name, "_meta_table", sizeof(table_name)-1); + + char global_name[64]; + strncpy(global_name, name, sizeof(global_name)-1); + for (size_t i = 0; i < strlen(global_name); i++) { + global_name[i] = toupper(global_name[i]); + } + + // Register the cpu meta table + luaL_newmetatable(state, table_name); + luaL_setfuncs(state, functions, 0); + + //lua_pushvalue(state, -1); + //lua_setfield(state, -1, "__index"); + + // Keep it around + lua_setglobal(state, "CPU"); // TODO I don't think we actually need this +} diff --git a/src/lua.h b/src/lua.h index 5d0dcd8..5be5758 100644 --- a/src/lua.h +++ b/src/lua.h @@ -28,6 +28,8 @@ #include struct cpu_t; +struct ewm_two_t; +struct ewm_dsk_t; struct ewm_lua_t { lua_State *state; @@ -36,4 +38,10 @@ struct ewm_lua_t { struct ewm_lua_t *ewm_lua_create(); int ewm_lua_load_script(struct ewm_lua_t *lua, char *script_path); +void ewm_lua_push_cpu(struct ewm_lua_t *lua, struct cpu_t *cpu); +void ewm_lua_push_two(struct ewm_lua_t *lua, struct ewm_two_t *two); +void ewm_lua_push_dsk(struct ewm_lua_t *lua, struct ewm_dsk_t *dsk); + +void ewm_lua_register_component(lua_State *state, char *name, luaL_Reg *functions); + #endif // LUA_H diff --git a/src/test.lua b/src/test.lua new file mode 100644 index 0000000..0cfd43f --- /dev/null +++ b/src/test.lua @@ -0,0 +1,53 @@ +-- EWM Meets Lua + +local function myerrhandler(err) + print(err) + print(debug.traceback()) + return false +end + +xpcall(function() + + local two = require 'two' + two.hello() + + local cpu = require 'cpu' + cpu.hello() + + local dsk = require 'dsk' + dsk.hello() + + -- Intercept JSR COUT calls + -- cpu.onBeforeExecuteInstruction(0x20, function(cpu, opcode, operand) + -- if operand == 0xfded then + -- print(string.format("COUT was called from %.4x with A=%.2x", cpu:pc(), cpu:a())) + -- if cpu:a() >= 0xc1 and cpu:a() <= 0xda then + -- -- Lets inverse this character + -- cpu:a(cpu:a() - 0xC0) + -- end + -- end + -- end) + + cpu.onBeforeExecuteInstruction(0x20, function(state, opcode, operand) + if operand == 0xfded then + print(string.format("COUT was called from %.4x with A=%.2x", state.a, state.pc)) + if state.a >= 0xc1 and state.a <= 0xda then + -- Lets inverse this character + state.a = state.a - 0xC0 + end + end + end) + + -- Reset when the R key is pressed + --two.onKeyDown('R', function(two, key) + -- print('You pressed R') + -- two.reset() + --end) + + -- Enter the Monitor when the M key is pressed + --two.onKeyDown('M', function(two, key) + -- print('You pressed B') + -- two.monitor() + --end) + +end , myerrhandler ) diff --git a/src/two.c b/src/two.c index 589d3e7..82d2b58 100644 --- a/src/two.c +++ b/src/two.c @@ -350,12 +350,34 @@ void ewm_two_destroy(struct ewm_two_t *two) { // TODO } +// Lua support + +static int ewm_two_lua_hello(lua_State *lua) { + printf("This is two.hello()\n"); + return 0; +} + +int ewm_two_luaopen(lua_State *state) { + luaL_Reg ewm_two_functions[] = { + {"hello", ewm_two_lua_hello}, + {NULL, NULL} + }; + luaL_newlib(state, ewm_two_functions); + return 1; +} + +int ewm_two_init_lua(struct ewm_two_t *two, struct ewm_lua_t *lua) { + two->lua = lua; + luaL_requiref(two->lua->state, "two", ewm_two_luaopen, 0); + return 0; +} + +// External API + int ewm_two_load_disk(struct ewm_two_t *two, int drive, char *path) { return ewm_dsk_set_disk_file(two->dsk, drive, false, path); } - - static bool ewm_two_poll_event(struct ewm_two_t *two, SDL_Window *window) { // TODO Should window be part of ewm_two_t? SDL_Event event; while (SDL_PollEvent(&event) != 0) { @@ -566,8 +588,6 @@ static void usage() { fprintf(stderr, " --lua