summaryrefslogtreecommitdiff
path: root/6502/src/test.c
blob: 1b4e241e6ee9e166b61225c8165dc8b84b63becd (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
/* test harness - we build this to a shared object and then run it from Lua */
/* see the ../test directory */

#include <stdlib.h>
#include <stdio.h>
#include <lua.h>
#include <lcq/6502.h>

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;
}