From 9ba3ccd51d94e2db6920351eccb9050d1a2c41e1 Mon Sep 17 00:00:00 2001 From: LLLL Colonq Date: Fri, 10 Jul 2026 05:19:06 -0400 Subject: 6502: Lua bindings for testing --- 6502/src/test.c | 142 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 142 insertions(+) create mode 100644 6502/src/test.c (limited to '6502/src/test.c') diff --git a/6502/src/test.c b/6502/src/test.c new file mode 100644 index 0000000..1b4e241 --- /dev/null +++ b/6502/src/test.c @@ -0,0 +1,142 @@ +/* test harness - we build this to a shared object and then run it from Lua */ +/* see the ../test directory */ + +#include +#include +#include +#include + +static l6502_emu *get_emu(lua_State *l) { + l6502_emu *e = lua_touserdata(l, 1); + if (!e) { lua_pushliteral(l, "expected emulator as first argument"); lua_error(l); } + return e; +} + +int emu_summary(lua_State *l); +int emu_summary(lua_State *l) { + l6502_emu *e = get_emu(l); + lua_newtable(l); + lua_pushinteger(l, e->pc); lua_setfield(l, -2, "pc"); + lua_newtable(l); + lua_pushinteger(l, e->regs[L6502_REG_SP]); lua_setfield(l, -2, "sp"); + lua_pushinteger(l, e->regs[L6502_REG_A]); lua_setfield(l, -2, "a"); + lua_pushinteger(l, e->regs[L6502_REG_X]); lua_setfield(l, -2, "x"); + lua_pushinteger(l, e->regs[L6502_REG_Y]); lua_setfield(l, -2, "y"); + lua_setfield(l, -2, "regs"); + lua_newtable(l); + lua_pushinteger(l, l6502_flag_get(e, L6502_FLAG_CARRY)); lua_setfield(l, -2, "carry"); + lua_pushinteger(l, l6502_flag_get(e, L6502_FLAG_ZERO)); lua_setfield(l, -2, "zero"); + lua_pushinteger(l, l6502_flag_get(e, L6502_FLAG_INTERRUPT_DISABLE)); lua_setfield(l, -2, "interrupt_disable"); + lua_pushinteger(l, l6502_flag_get(e, L6502_FLAG_DECIMAL)); lua_setfield(l, -2, "decimal"); + lua_pushinteger(l, l6502_flag_get(e, L6502_FLAG_BREAK_COMMAND)); lua_setfield(l, -2, "break_command"); + lua_pushinteger(l, l6502_flag_get(e, L6502_FLAG_OVERFLOW)); lua_setfield(l, -2, "overflow"); + lua_pushinteger(l, l6502_flag_get(e, L6502_FLAG_NEGATIVE)); lua_setfield(l, -2, "negative"); + lua_setfield(l, -2, "flags"); + return 1; +} + +int emu_get_reg(lua_State *l); +int emu_get_reg(lua_State *l) { + l6502_emu *e = get_emu(l); + l6502_reg r = lua_tointeger(l, 2); + if (r >= 0 && r < L6502_REG__MARKER) lua_pushinteger(l, e->regs[r]); + else { lua_pushliteral(l, "invalid register"); lua_error(l); } + return 1; +} +int emu_set_reg(lua_State *l); +int emu_set_reg(lua_State *l) { + l6502_emu *e = get_emu(l); + l6502_reg r = lua_tointeger(l, 2); + u8 v = (u8) lua_tointeger(l, 3); + if (r >= 0 && r < L6502_REG__MARKER) e->regs[r] = v; + else { lua_pushliteral(l, "invalid register"); lua_error(l); } + lua_pushvalue(l, 1); + return 1; +} + +int emu_get_flag(lua_State *l); +int emu_get_flag(lua_State *l) { + l6502_emu *e = get_emu(l); + l6502_flag f = lua_tointeger(l, 2); + lua_pushinteger(l, l6502_flag_get(e, f)); + return 1; +} +int emu_set_flag(lua_State *l); +int emu_set_flag(lua_State *l) { + l6502_emu *e = get_emu(l); + l6502_flag f = lua_tointeger(l, 2); + u8 v = (u8) lua_tointeger(l, 3); + l6502_flag_set(e, f, v); + lua_pushvalue(l, 1); + return 1; +} + +int emu_get_pc(lua_State *l); +int emu_get_pc(lua_State *l) { + l6502_emu *e = get_emu(l); + lua_pushinteger(l, e->pc); + return 1; +} + +int emu_set_pc(lua_State *l); +int emu_set_pc(lua_State *l) { + l6502_emu *e = get_emu(l); + e->pc = (u16) lua_tointeger(l, 2); + lua_pushvalue(l, 1); + return 1; +} + +int emu_emulate(lua_State *l); +int emu_emulate(lua_State *l) { + l6502_emu *e = get_emu(l); + l6502_emulate(e); + return 1; +} + +int new(lua_State *l); +int new(lua_State *l) { + l6502_emu *e = lua_newuserdata(l, sizeof(l6502_emu)); + l6502_mem_basic_new(&e->mem); + lua_newtable(l); + lua_newtable(l); + lua_pushcfunction(l, emu_summary); lua_setfield(l, -2, "summary"); + lua_pushcfunction(l, emu_get_reg); lua_setfield(l, -2, "reg"); + lua_pushcfunction(l, emu_set_reg); lua_setfield(l, -2, "set-reg"); + lua_pushcfunction(l, emu_get_flag); lua_setfield(l, -2, "flag"); + lua_pushcfunction(l, emu_set_flag); lua_setfield(l, -2, "set-flag"); + lua_pushcfunction(l, emu_get_pc); lua_setfield(l, -2, "pc"); + lua_pushcfunction(l, emu_set_pc); lua_setfield(l, -2, "set-pc"); + lua_pushcfunction(l, emu_emulate); lua_setfield(l, -2, "emulate"); + lua_setfield(l, -2, "__index"); + lua_setmetatable(l, -2); + return 1; +} + +#define PUSH_ENUM(enum, field) { lua_pushinteger(l, enum ## _ ## field); lua_setfield(l, -2, #field); } +static void push_enum_flag(lua_State *l) { + lua_newtable(l); + PUSH_ENUM(L6502_FLAG, CARRY); + PUSH_ENUM(L6502_FLAG, ZERO); + PUSH_ENUM(L6502_FLAG, INTERRUPT_DISABLE); + PUSH_ENUM(L6502_FLAG, DECIMAL); + PUSH_ENUM(L6502_FLAG, BREAK_COMMAND); + PUSH_ENUM(L6502_FLAG, OVERFLOW); + PUSH_ENUM(L6502_FLAG, NEGATIVE); +} +static void push_enum_reg(lua_State *l) { + lua_newtable(l); + PUSH_ENUM(L6502_REG, SP); + PUSH_ENUM(L6502_REG, A); + PUSH_ENUM(L6502_REG, X); + PUSH_ENUM(L6502_REG, Y); + PUSH_ENUM(L6502_REG, FLAGS); +} + +int luaopen_l6502(lua_State *l); +int luaopen_l6502(lua_State *l) { + lua_newtable(l); + push_enum_flag(l); lua_setfield(l, -2, "flag"); + push_enum_reg(l); lua_setfield(l, -2, "reg"); + lua_pushcfunction(l, new); lua_setfield(l, -2, "new"); + return 1; +} -- cgit v1.3.1