From 4ce641eada02f3ec24a30a8329c2eb9921c96ae7 Mon Sep 17 00:00:00 2001 From: Stefan Arentz Date: Fri, 15 Sep 2017 22:41:23 -0400 Subject: [PATCH] Massive WIP --- src/Makefile | 22 ++++---- src/cpu.c | 138 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/cpu.h | 9 ++++ src/lua.c | 50 +++++++++++++++++++ src/lua.h | 39 +++++++++++++++ src/two.c | 44 +++++++++++++++- src/two.h | 2 + 7 files changed, 292 insertions(+), 12 deletions(-) create mode 100644 src/lua.c create mode 100644 src/lua.h diff --git a/src/Makefile b/src/Makefile index 2513e87..1fd7b6b 100644 --- a/src/Makefile +++ b/src/Makefile @@ -21,33 +21,33 @@ # SOFTWARE. CC?=cc -CFLAGS=-std=gnu11 -O3 -Wall -Wextra -Werror -Wno-unused-parameter +CFLAGS=-std=gnu11 -g -Wall -Wextra -Werror -Wno-unused-parameter LDFLAGS=-g -L/usr/local/lib EWM_EXECUTABLE=ewm -EWM_SOURCES=cpu.c ins.c pia.c mem.c ewm.c fmt.c two.c scr.c dsk.c chr.c alc.c one.c tty.c utl.c boo.c +EWM_SOURCES=cpu.c ins.c pia.c mem.c ewm.c fmt.c two.c scr.c dsk.c chr.c alc.c one.c tty.c utl.c boo.c lua.c EWM_OBJECTS=$(EWM_SOURCES:.c=.o) -EWM_LIBS=-lSDL2 +EWM_LIBS=-lSDL2 -llua CPU_TEST_EXECUTABLE=cpu_test -CPU_TEST_SOURCES=cpu.c ins.c mem.c fmt.c utl.c cpu_test.c +CPU_TEST_SOURCES=cpu.c ins.c mem.c fmt.c utl.c cpu_test.c lua.c CPU_TEST_OBJECTS=$(CPU_TEST_SOURCES:.c=.o) -CPU_TEST_LIBS= +CPU_TEST_LIBS=-llua SCR_TEST_EXECUTABLE=scr_test -SCR_TEST_SOURCES=cpu.c ins.c mem.c fmt.c two.c scr.c dsk.c chr.c alc.c utl.c scr_test.c +SCR_TEST_SOURCES=cpu.c ins.c mem.c fmt.c two.c scr.c dsk.c chr.c alc.c utl.c scr_test.c lua.c SCR_TEST_OBJECTS=$(SCR_TEST_SOURCES:.c=.o) -SCR_TEST_LIBS=-lSDL2 +SCR_TEST_LIBS=-lSDL2 -llua CPU_BENCH=cpu_bench -CPU_BENCH_SOURCES=cpu.c ins.c mem.c fmt.c utl.c cpu_bench.c +CPU_BENCH_SOURCES=cpu.c ins.c mem.c fmt.c utl.c cpu_bench.c lua.c CPU_BENCH_OBJECTS=$(CPU_BENCH_SOURCES:.c=.o) -CPU_BENCH_LIBS= +CPU_BENCH_LIBS=-llua MEM_BENCH=mem_bench -MEM_BENCH_SOURCES=cpu.c ins.c mem.c fmt.c utl.c mem_bench.c +MEM_BENCH_SOURCES=cpu.c ins.c mem.c fmt.c utl.c mem_bench.c lua.c MEM_BENCH_OBJECTS=$(MEM_BENCH_SOURCES:.c=.o) -MEM_BENCH_LIBS= +MEM_BENCH_LIBS=-llua all: $(EWM_SOURCES) $(EWM_EXECUTABLE) $(CPU_TEST_SOURCES) $(CPU_TEST_EXECUTABLE) $(SCR_TEST_EXECUTABLE) $(CPU_BENCH) $(MEM_BENCH) diff --git a/src/cpu.c b/src/cpu.c index 0ff4d95..3866cb7 100644 --- a/src/cpu.c +++ b/src/cpu.c @@ -36,6 +36,10 @@ #include "ins.h" #include "mem.h" #include "fmt.h" +#include "lua.h" + +uint8_t xxx_op; +int xxx_fn; // Stack management. @@ -92,6 +96,21 @@ void _cpu_set_status(struct cpu_t *cpu, uint8_t status) { cpu->state.c = (status & (1 << 0)); } + +// TODO This does not belong here I think + + + +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 */ char trace_instruction[256]; @@ -131,6 +150,34 @@ static int cpu_execute_instruction(struct cpu_t *cpu) { cpu->state.pc += i->bytes; } + if (cpu->lua != NULL) { + if (i->opcode == xxx_op) { + switch (i->bytes) { + case 1: + lua_rawgeti(cpu->lua->state, LUA_REGISTRYINDEX, xxx_fn); + 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); + 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); + 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; + } + } + } + /* Execute instruction */ switch (i->bytes) { case 1: @@ -442,3 +489,94 @@ int cpu_nmi(struct cpu_t *cpu) { int cpu_step(struct cpu_t *cpu) { return cpu_execute_instruction(cpu); } + +// Lua support + +// cpu state functions + +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); + + if (lua_gettop(state) == 2) { + if(!lua_isnumber(state, lua_gettop(state))) { + printf("First arg fail\n"); + return 0; + } + int n = lua_tointeger(state, lua_gettop(state)); + cpu->state.a = (uint8_t) n; + return 0; + } else { + lua_pushnumber(state, cpu->state.a); + return 1; + } +} + +static int lua_cpu_get_pc(lua_State *state) { + void *cpu_data = luaL_checkudata(state, 1, "cpu_meta_table"); + struct cpu_t *cpu = *((struct cpu_t**) cpu_data); + lua_pushnumber(state, cpu->state.pc); + return 1; +} + +// cpu module functions + +static int ewm_cpu_lua_hello(lua_State *lua) { + printf("This is cpu.hello()\n"); + return 0; +} + +// onBeforeExecution(op, fn) +static int ewm_cpu_lua_onBeforeExecuteInstruction(lua_State *state) { + printf("This is cpu.onBeforeExecuteInstruction\n"); + + if(!lua_isnumber(state, lua_gettop(state) - 1)) { + printf("First arg fail\n"); + return 0; + } + xxx_op = lua_tointeger(state, lua_gettop(state) - 1); + + if(!lua_isfunction(state, lua_gettop(state) - 0)) { + printf("Second arg fail\n"); + return 0; + } + + lua_pushvalue(state, lua_gettop(state) - 0); + xxx_fn = luaL_ref(state, LUA_REGISTRYINDEX); + + return 0; +} + +static int ewm_cpu_luaopen(lua_State *state) { + luaL_Reg cpu_functions[] = { + {"hello", ewm_cpu_lua_hello}, + {"onBeforeExecuteInstruction", ewm_cpu_lua_onBeforeExecuteInstruction}, + {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 + 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}, + {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 + + return 0; +} diff --git a/src/cpu.h b/src/cpu.h index 0cb230e..bc1b5fe 100644 --- a/src/cpu.h +++ b/src/cpu.h @@ -27,6 +27,10 @@ #include #include +#include +#include +#include + #define EWM_CPU_MODEL_6502 0 #define EWM_CPU_MODEL_65C02 1 @@ -39,6 +43,7 @@ #define EWM_VECTOR_IRQ 0xfffe struct cpu_instruction_t; +struct ewm_lua_t; struct cpu_state_t { uint8_t a, x, y, s, sp; @@ -57,6 +62,8 @@ struct cpu_t { uint8_t *page0; uint8_t *page1; + + struct ewm_lua_t *lua; }; typedef void (*cpu_instruction_handler_t)(struct cpu_t *cpu); @@ -122,4 +129,6 @@ uint8_t cpu_memory_get_byte(struct cpu_t *cpu, uint16_t addr); void cpu_memory_set_word(struct cpu_t *cpu, uint16_t addr, uint16_t v); void cpu_memory_set_byte(struct cpu_t *cpu, uint16_t addr, uint8_t v); +int ewm_cpu_init_lua(struct cpu_t *cpu, struct ewm_lua_t *lua); + #endif diff --git a/src/lua.c b/src/lua.c new file mode 100644 index 0000000..6152a1b --- /dev/null +++ b/src/lua.c @@ -0,0 +1,50 @@ +// The MIT License (MIT) +// +// Copyright (c) 2015 Stefan Arentz - http://github.com/st3fan/ewm +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +#include +#include + +#include +#include +#include + +#include "lua.h" + +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) { + free(lua); + lua = NULL; + } + return lua; +} diff --git a/src/lua.h b/src/lua.h new file mode 100644 index 0000000..5d0dcd8 --- /dev/null +++ b/src/lua.h @@ -0,0 +1,39 @@ +// The MIT License (MIT) +// +// Copyright (c) 2015 Stefan Arentz - http://github.com/st3fan/ewm +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +#ifndef LUA_H +#define LUA_H + +#include +#include +#include + +struct cpu_t; + +struct ewm_lua_t { + lua_State *state; +}; + +struct ewm_lua_t *ewm_lua_create(); +int ewm_lua_load_script(struct ewm_lua_t *lua, char *script_path); + +#endif // LUA_H diff --git a/src/two.c b/src/two.c index fd3e888..589d3e7 100644 --- a/src/two.c +++ b/src/two.c @@ -34,9 +34,9 @@ #include "alc.h" #include "chr.h" #include "scr.h" +#include "lua.h" #include "two.h" - #define EWM_A2P_SS_KBD 0xc000 #define EWM_A2P_SS_KBDSTRB 0xc010 #define EWM_A2P_SS_SPKR 0xc030 @@ -537,6 +537,7 @@ static void ewm_two_update_status_bar(struct ewm_two_t *two, double mhz) { #define EWM_TWO_OPT_TRACE (6) #define EWM_TWO_OPT_STRICT (7) #define EWM_TWO_OPT_DEBUG (8) +#define EWM_TWO_OPT_LUA (9) static struct option one_options[] = { { "help", no_argument, NULL, EWM_TWO_OPT_HELP }, @@ -548,6 +549,7 @@ static struct option one_options[] = { { "trace", optional_argument, NULL, EWM_TWO_OPT_TRACE }, { "strict", no_argument, NULL, EWM_TWO_OPT_STRICT }, { "debug", no_argument, NULL, EWM_TWO_OPT_DEBUG }, + { "lua", required_argument, NULL, EWM_TWO_OPT_LUA }, { NULL, 0, NULL, 0 } }; @@ -561,8 +563,11 @@ static void usage() { fprintf(stderr, " --trace trace cpu to file\n"); fprintf(stderr, " --strict run emulator in strict mode\n"); fprintf(stderr, " --debug print debug info\n"); + fprintf(stderr, " --lua