mirror of
https://github.com/st3fan/ewm.git
synced 2025-04-12 14:37:03 +00:00
Massive WIP
This commit is contained in:
parent
c68fc356c6
commit
4ce641eada
22
src/Makefile
22
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)
|
||||
|
||||
|
138
src/cpu.c
138
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;
|
||||
}
|
||||
|
@ -27,6 +27,10 @@
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <lua.h>
|
||||
#include <lauxlib.h>
|
||||
#include <lualib.h>
|
||||
|
||||
#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
|
||||
|
50
src/lua.c
Normal file
50
src/lua.c
Normal file
@ -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 <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <lua.h>
|
||||
#include <lauxlib.h>
|
||||
#include <lualib.h>
|
||||
|
||||
#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;
|
||||
}
|
39
src/lua.h
Normal file
39
src/lua.h
Normal file
@ -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 <lua.h>
|
||||
#include <lauxlib.h>
|
||||
#include <lualib.h>
|
||||
|
||||
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
|
44
src/two.c
44
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 <file> trace cpu to file\n");
|
||||
fprintf(stderr, " --strict run emulator in strict mode\n");
|
||||
fprintf(stderr, " --debug print debug info\n");
|
||||
fprintf(stderr, " --lua <script> load lua script into the emulator\n");
|
||||
}
|
||||
|
||||
int ewm_two_luaopen(lua_State *state);
|
||||
|
||||
int ewm_two_main(int argc, char **argv) {
|
||||
// Parse options
|
||||
|
||||
@ -574,6 +579,7 @@ int ewm_two_main(int argc, char **argv) {
|
||||
char *trace_path = NULL;
|
||||
bool strict = false;
|
||||
bool debug = false;
|
||||
char *lua_script_path = NULL;
|
||||
|
||||
int ch;
|
||||
while ((ch = getopt_long_only(argc, argv, "", one_options, NULL)) != -1) {
|
||||
@ -612,6 +618,9 @@ int ewm_two_main(int argc, char **argv) {
|
||||
case EWM_TWO_OPT_DEBUG:
|
||||
debug = true;
|
||||
break;
|
||||
case EWM_TWO_OPT_LUA:
|
||||
lua_script_path = optarg;
|
||||
break;
|
||||
default: {
|
||||
usage();
|
||||
exit(1);
|
||||
@ -719,6 +728,22 @@ int ewm_two_main(int argc, char **argv) {
|
||||
cpu_strict(two->cpu, strict);
|
||||
cpu_trace(two->cpu, trace_path);
|
||||
|
||||
// Setup a Lua environment if we were asked to
|
||||
|
||||
if (lua_script_path != NULL) {
|
||||
two->lua = ewm_lua_create();
|
||||
|
||||
luaL_requiref(two->lua->state, "ewm", ewm_two_luaopen, 0); // ewm_two_init_lua? that calls it for all its components?
|
||||
ewm_cpu_init_lua(two->cpu, two->lua);
|
||||
|
||||
if (ewm_lua_load_script(two->lua, lua_script_path) != 0) {
|
||||
printf("Lua script failed to load\n"); // TODO Errors would be nice
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
// Reset things to a known state
|
||||
|
||||
cpu_reset(two->cpu);
|
||||
|
||||
//
|
||||
@ -779,3 +804,20 @@ int ewm_two_main(int argc, char **argv) {
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Lua support
|
||||
|
||||
static int ewm_two_lua_hello(lua_State *lua) {
|
||||
printf("This is ewm.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;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user