/* 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_pushboolean(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); bool v = lua_toboolean(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_read(lua_State *l); int emu_read(lua_State *l) { l6502_emu *e = get_emu(l); u16 addr = (u16) lua_tointeger(l, 2); lua_pushinteger(l, l6502_read(e, addr)); return 1; } int emu_write(lua_State *l); int emu_write(lua_State *l) { l6502_emu *e = get_emu(l); u16 addr = (u16) lua_tointeger(l, 2); u8 v = (u8) lua_tointeger(l, 3); l6502_write(e, addr, v); 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_read); lua_setfield(l, -2, "read"); lua_pushcfunction(l, emu_write); lua_setfield(l, -2, "write"); 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; }