--- /dev/null
+all: anago.exe
+LIBUSB = d:/dev/LibUSB-Win32
+SQUIRREL = ../SQUIRREL2
+VPATH = ..
+CFLAGS = -g -O0 -Wall -I.. -I$(LIBUSB)/include -I$(SQUIRREL)/include -DDEBUG=1 -DANAGO=1
+LDFLAG = -L. -L$(LIBUSB)/lib/gcc -L$(SQUIRREL)/lib
+CC = gcc
+OBJ = anago.o flashmemory.o header.o crc32.o file.o script.o \
+ reader_dummy.o reader_kazzo.o usb_device.o squirrel_wrap.o memory_manage.o
+clean:
+ rm -f $(OBJ)
+anago.exe: $(OBJ)
+ g++ -o $@ $(LDFLAG) $(OBJ) -lusb -lsqstdlib -lsquirrel
--- /dev/null
+#include <stdio.h>
+#include <stdbool.h>
+#include "memory_manage.h"
+#include "type.h"
+#include "flashmemory.h"
+#include "header.h"
+#include "reader_master.h"
+#include "reader_kazzo.h"
+#include "reader_dummy.h"
+#include "script.h"
+
+static bool transtype_flash_set(char mode, struct memory *t)
+{
+ switch(mode){
+ case 't':
+ t->transtype = TRANSTYPE_TOP;
+ break;
+ case 'e':
+ t->transtype = TRANSTYPE_EMPTY;
+ break;
+ case 'b':
+ t->transtype = TRANSTYPE_BOTTOM;
+ break;
+ case 'f':
+ t->transtype = TRANSTYPE_FULL;
+ break;
+ default:
+ return false;
+ }
+ return true;
+}
+static bool transtype_set(const char *mode, struct romimage *t)
+{
+ switch(mode[0]){
+ case 'd': case 'f':
+ if(mode[1] == '\0'){
+ t->cpu_rom.transtype = TRANSTYPE_FULL;
+ t->ppu_rom.transtype = TRANSTYPE_FULL;
+ return true;
+ }
+ if(transtype_flash_set(mode[1], &t->cpu_rom) == false){
+ return false;
+ }
+ if(mode[2] == '\0'){
+ t->ppu_rom.transtype = TRANSTYPE_FULL;
+ return true;
+ }
+ if(transtype_flash_set(mode[2], &t->ppu_rom) == false){
+ return false;
+ }
+ return true;
+ }
+ return false;
+}
+static bool config_parse(const char *romimage, const char *device_cpu, const char *device_ppu, struct config *c)
+{
+ c->target = romimage;
+ if(nesfile_load(__FUNCTION__, romimage, &c->rom) == false){
+ return false;
+ }
+ c->rom.cpu_rom.offset = 0;
+ c->rom.ppu_rom.offset = 0;
+ c->flash_cpu = flash_driver_get(device_cpu);
+ if(device_ppu != NULL){
+ c->flash_ppu = flash_driver_get(device_ppu);
+ }else{
+ c->flash_ppu = flash_driver_get("dummy");
+ }
+ if(c->flash_cpu == NULL || c->flash_ppu == NULL){
+ return false;
+ }
+ if(c->flash_cpu->id_device == FLASH_ID_DEVICE_DUMMY){
+ c->rom.cpu_rom.transtype = TRANSTYPE_EMPTY;
+ }
+ if(
+ (c->flash_ppu->id_device == FLASH_ID_DEVICE_DUMMY) ||
+ (c->rom.ppu_rom.size == 0)
+ ){
+ c->rom.ppu_rom.transtype = TRANSTYPE_EMPTY;
+ }
+ return true;
+}
+static void anago(int c, char **v)
+{
+ struct config config;
+ config.script = v[2];
+ config.flash_ppu = &FLASH_DRIVER_UNDEF;
+ config.reader = &DRIVER_KAZZO;
+ if(v[1][0] == 'd'){
+ config.reader = &DRIVER_DUMMY;
+ }
+ if(transtype_set(v[1], &config.rom) == false){
+ puts("mode argument error");
+ return;
+ }
+ switch(c){
+ case 5: //mode script target cpu_flash_device
+ if(config_parse(v[3], v[4], NULL, &config) == false){
+ nesbuffer_free(&config.rom, 0);
+ return;
+ }
+ break;
+ case 6: //mode script target cpu_flash_device ppu_flash_device
+ if(config_parse(v[3], v[4], v[5], &config) == false){
+ nesbuffer_free(&config.rom, 0);
+ return;
+ }
+ break;
+ default:
+ puts("mode script target cpu_flash_device ppu_flash_device");
+ return;
+ }
+ if(config.reader->open_or_close(READER_OPEN) == NG){
+ puts("reader open error");
+ nesbuffer_free(&config.rom, 0);
+ return;
+ }
+ script_execute(&config);
+ nesbuffer_free(&config.rom, 0);
+ config.reader->open_or_close(READER_CLOSE);
+}
+int main(int c, char **v)
+{
+ mm_init();
+ anago(c, v);
+ mm_end();
+ return 0;
+}
--- /dev/null
+mega <- 0x20000;
+local trans_empty = 0;
+function loopsize_get(flashsize, trans, size)
+{
+ local trans_full = 3, trans_top = 1, trans_bottom = 2; //header.h enum transtype
+ local loop;
+ switch(trans){
+ case trans_full:
+ loop = flashsize.full;
+ break;
+ case trans_top:
+ loop = flashsize.top[size];
+ break;
+ case trans_bottom:
+ loop = flashsize.bottom[size];
+ break;
+ default:
+ loop = {start = 0, end = 0};
+ break;
+ }
+ return loop;
+}
+function program_init(mapper, cpu_trans, cpu_size, ppu_trans, ppu_size)
+{
+ if(board.mapper != mapper){
+ print("mapper number not connected");
+ return;
+ }
+ local cpu_loop = loopsize_get(board.cpu_flashsize, cpu_trans, cpu_size);
+ local ppu_loop = loopsize_get(board.ppu_flashsize, ppu_trans, ppu_size);
+ local co_cpu = newthread(program_cpu);
+ local co_ppu = newthread(program_ppu);
+ initalize();
+ if(cpu_trans != trans_empty){
+ cpu_erase();
+ }
+ if(ppu_trans != trans_empty){
+ ppu_erase();
+ }
+ erase_wait();
+ if(cpu_trans != 0){
+ co_cpu.call(cpu_loop);
+ }
+ if(ppu_trans != trans_empty){
+ co_ppu.call(ppu_loop);
+ }
+ program_main(co_cpu, co_ppu)
+}
+
--- /dev/null
+#include <stdbool.h>
+#include <stdio.h>
+#include <string.h>
+#include "reader_master.h"
+#include "reader_dummy.h"
+
+static void dummy_init(void)
+{
+}
+static int dummy_open_close(enum reader_control oc)
+{
+ return OK;
+}
+//---- cpu ----
+static void dummy_cpu_read(long address, long length, uint8_t *data)
+{
+ printf("%s %06x %04x\n", __FUNCTION__, (int) address, (int) length);
+ memset(data, 0x55, length);
+}
+static void dummy_cpu_write_6502(long address, long length, const uint8_t *data)
+{
+ printf("%s %04x %04x %02x\n", __FUNCTION__, (int) address, (int) length, (int) *data);
+}
+static void dummy_cpu_flash_config(long c000x, long c2aaa, long c5555, long unit)
+{
+ printf("%s %04x %04x %04x %04x\n", __FUNCTION__, (int) c000x, (int) c2aaa, (int) c5555, (int) unit);
+}
+static long dummy_cpu_flash_program(long address, long length, u8 *data, bool dowait)
+{
+ int i = 0x10;
+ printf("%s %06x\n", __FUNCTION__, (int) address);
+ while(i != 0){
+ printf("%02x ", *data);
+ data++;
+ i--;
+ }
+ printf("\n");
+ return 0x100;
+}
+
+static void dummy_cpu_flash_erase(long address, bool dowait)
+{
+ printf("%s %04x\n", __FUNCTION__, (int) address);
+}
+
+//---- ppu ----
+static void dummy_ppu_read(long address, long length, u8 *data)
+{
+ printf("%s %06x %04x\n", __FUNCTION__, (int) address, (int) length);
+ memset(data, 0x55, length);
+}
+static void dummy_ppu_write(long address, long length, const uint8_t *data)
+{
+ printf("%s %04x %04x %02x\n", __FUNCTION__, (int) address, (int) length, (int) *data);
+}
+static void dummy_ppu_flash_config(long c000x, long c2aaa, long c5555, long unit)
+{
+ printf("%s %04x %04x %04x %04x\n", __FUNCTION__, (int) c000x, (int) c2aaa, (int) c5555, (int) unit);
+}
+static long dummy_ppu_flash_program(long address, long length, u8 *data, bool dowait)
+{
+ int i = 0x10;
+ printf("%s %06x\n", __FUNCTION__, (int) address);
+ while(i != 0){
+ printf("%02x ", *data);
+ data++;
+ i--;
+ }
+ printf("\n");
+ return 0x100;
+}
+
+static void dummy_ppu_flash_erase(long address, bool dowait)
+{
+ printf("%s %04x\n", __FUNCTION__, (int) address);
+}
+
+static void dummy_flash_status(uint8_t s[2])
+{
+ s[0] = 0;
+ s[1] = 0;
+}
+static void dummy_flash_device_get(uint8_t s[2])
+{
+ s[0] = 0x01;
+ s[1] = 0xa4;
+}
+const struct reader_driver DRIVER_DUMMY = {
+ .name = "tester",
+ .open_or_close = dummy_open_close,
+ .init = dummy_init,
+ .cpu_read = dummy_cpu_read, .ppu_read = dummy_ppu_read,
+ .cpu_write_6502 = dummy_cpu_write_6502,
+ .flash_support = OK,
+ .ppu_write = dummy_ppu_write,
+ .cpu_flash_config = dummy_cpu_flash_config,
+ .cpu_flash_erase = dummy_cpu_flash_erase,
+ .cpu_flash_program = dummy_cpu_flash_program,
+ .cpu_flash_device_get = dummy_flash_device_get,
+ .ppu_flash_config = dummy_ppu_flash_config,
+ .ppu_flash_erase = dummy_ppu_flash_erase,
+ .ppu_flash_program = dummy_ppu_flash_program,
+ .ppu_flash_device_get = dummy_flash_device_get,
+ .flash_status = dummy_flash_status
+};
--- /dev/null
+#ifndef _READER_DUMMY_H_
+#define _READER_DUMMY_H_
+const struct reader_driver DRIVER_DUMMY;
+#endif
--- /dev/null
+#include <stdio.h>
+#include <squirrel.h>
+#include <sqstdio.h>
+#include <sqstdaux.h>
+#include "type.h"
+#include "header.h"
+#include "reader_master.h"
+#include "squirrel_wrap.h"
+#include "script.h"
+
+static struct anago_flash_order{
+ bool command_change;
+ long address, length;
+ long c000x, c2aaa, c5555, unit;
+ struct memory *memory;
+ void (*config)(long c000x, long c2aaa, long c5555, long unit);
+ void (*device_get)(uint8_t s[2]);
+ void (*flash_status)(uint8_t s[2]);
+ void (*write)(long address, long length, const uint8_t *data);
+ void (*read)(long address, long length, u8 *data);
+ void (*erase)(long address, bool dowait);
+ long (*program)(long address, long length, const u8 *data, bool dowait);
+}order_cpu, order_ppu;
+
+static SQInteger command_set(HSQUIRRELVM v, struct anago_flash_order *t)
+{
+ long command, address ,mask;
+ SQRESULT r = qr_argument_get(v, 3, &command, &address, &mask);
+ if(SQ_FAILED(r)){
+ return r;
+ }
+ long d = command & (mask - 1);
+ d |= address;
+ switch(command){
+ case 0x0000:
+ t->c000x = d;
+ break;
+ case 0x02aa: case 0x2aaa:
+ t->c2aaa = d;
+ break;
+ case 0x0555: case 0x5555:
+ t->c5555 = d;
+ break;
+ default:
+ return sq_throwerror(v, "unknown command address");
+ }
+ t->command_change = true;
+ return 0;
+}
+static SQInteger cpu_command(HSQUIRRELVM v)
+{
+ return command_set(v, &order_cpu);
+}
+static SQInteger ppu_command(HSQUIRRELVM v)
+{
+ return command_set(v, &order_ppu);
+}
+static SQInteger write(HSQUIRRELVM v, struct anago_flash_order *t)
+{
+ long address, data;
+ SQRESULT r = qr_argument_get(v, 2, &address, &data);
+ if(SQ_FAILED(r)){
+ return r;
+ }
+ uint8_t d8 = (uint8_t) data;
+ t->write(address, 1, &d8);
+ return 0;
+}
+static SQInteger cpu_write(HSQUIRRELVM v)
+{
+ return write(v, &order_cpu);
+}
+static SQInteger erase_set(HSQUIRRELVM v, struct anago_flash_order *t, const char *region)
+{
+ t->config(t->c000x, t->c2aaa, t->c5555, t->unit);
+ t->command_change = false;
+ t->erase(t->c2aaa, false);
+ printf("erasing %s memory...\n", region);
+ fflush(stdout);
+ return 0; //sq_suspendvm(v);
+}
+static SQInteger cpu_erase(HSQUIRRELVM v)
+{
+ return erase_set(v, &order_cpu, "program");
+}
+static SQInteger ppu_erase(HSQUIRRELVM v)
+{
+ return erase_set(v, &order_ppu, "charcter");
+}
+static SQInteger program_regist(HSQUIRRELVM v, const char *name, struct anago_flash_order *t)
+{
+ SQRESULT r = qr_argument_get(v, 2, &t->address, &t->length);
+ if(SQ_FAILED(r)){
+ return r;
+ }
+ if(t->command_change == true){
+ t->config(t->c000x, t->c2aaa, t->c5555, t->unit);
+ t->command_change = false;
+ }
+
+ printf("programming %s ROM area 0x%06x...\n", name, t->memory->offset);
+ fflush(stdout);
+ return sq_suspendvm(v);
+}
+static void program_execute(struct anago_flash_order *t)
+{
+/* printf("writing %06x\n", t->memory->offset);
+ fflush(stdout);*/
+ const long w = t->program(t->address, t->length, t->memory->data + t->memory->offset, false);
+ t->address += w;
+ t->length -= w;
+ t->memory->offset += w;
+}
+static SQInteger cpu_program(HSQUIRRELVM v)
+{
+ return program_regist(v, "program", &order_cpu);
+}
+static SQInteger ppu_program(HSQUIRRELVM v)
+{
+ return program_regist(v, "charcter", &order_ppu);
+}
+
+static SQInteger erase_wait(HSQUIRRELVM v)
+{
+ uint8_t s[2];
+ do{
+ Sleep(2);
+ order_cpu.flash_status(s);
+ }while((s[0] != 0) && (s[1] != 0));
+ return 0;
+}
+static void execute_main(HSQUIRRELVM v, struct config *c)
+{
+ if(SQ_FAILED(sqstd_dofile(v, _SC("flashmode.nut"), SQFalse, SQTrue)))
+ {
+ return;
+ }
+ if(SQ_FAILED(sqstd_dofile(v, _SC(c->script), SQFalse, SQTrue)))
+ {
+ return;
+ }
+ qr_call(
+ v, "program_init", true, 5, c->rom.mappernum,
+ order_cpu.memory->transtype, order_cpu.memory->size,
+ order_ppu.memory->transtype, order_ppu.memory->size
+ );
+}
+#if 0
+ HSQUIRRELVM co_cpu = sq_newthread(v, 0x400);
+ HSQUIRRELVM co_ppu = sq_newthread(v, 0x400);
+ SQInteger state_cpu, state_ppu;
+ qr_call(v, "initalize", true);
+ if(order_cpu.memory->size == 0 || c->flash_cpu->id_device == FLASH_ID_DEVICE_DUMMY){
+ state_cpu = SQ_VMSTATE_IDLE;
+ }else{
+ qr_call(co_cpu, "program_cpu", false);
+ state_cpu = sq_getvmstate(co_cpu);
+/* config.reader->ppu_flash_device_get(s);
+ printf("ppu device %02x %02x\n", s[0], s[1]);*/
+ }
+ if(order_ppu.memory->size == 0 || c->flash_ppu->id_device == FLASH_ID_DEVICE_DUMMY){
+ state_ppu = SQ_VMSTATE_IDLE;
+ }else{
+ qr_call(co_ppu, "program_ppu", false);
+ state_ppu = sq_getvmstate(co_ppu);
+ }
+#endif
+static SQInteger program_main(HSQUIRRELVM v)
+{
+ if(sq_gettop(v) != (2 + 1)){
+ return sq_throwerror(v, "argument number error");
+ }
+ HSQUIRRELVM co_cpu, co_ppu;
+ if(SQ_FAILED(sq_getthread(v, 2, &co_cpu))){
+ return sq_throwerror(v, "thread error");
+ }
+ if(SQ_FAILED(sq_getthread(v, 3, &co_ppu))){
+ return sq_throwerror(v, "thread error");
+ }
+ SQInteger state_cpu = sq_getvmstate(co_cpu);
+ SQInteger state_ppu = sq_getvmstate(co_ppu);
+ while(state_cpu != SQ_VMSTATE_IDLE || state_ppu != SQ_VMSTATE_IDLE){
+ uint8_t s[2];
+ Sleep(2);
+ order_cpu.flash_status(s);
+ if(state_cpu != SQ_VMSTATE_IDLE && s[0] == 0){
+ if(order_cpu.length == 0){
+ sq_wakeupvm(co_cpu, SQFalse, SQFalse, SQTrue/*, SQTrue*/);
+ state_cpu = sq_getvmstate(co_cpu);
+ }else{
+ program_execute(&order_cpu);
+ }
+ }
+ if(state_ppu != SQ_VMSTATE_IDLE && s[1] == 0){
+ if(order_ppu.length == 0){
+ sq_wakeupvm(co_ppu, SQFalse, SQFalse, SQTrue/*, SQTrue*/);
+ state_ppu = sq_getvmstate(co_ppu);
+ }else{
+ program_execute(&order_ppu);
+ }
+ }
+ }
+ return 0;
+}
+void script_execute(struct config *c)
+{
+ order_cpu.command_change = true;
+ order_cpu.unit = c->flash_cpu->pagesize;
+ order_cpu.memory = &c->rom.cpu_rom;
+ order_cpu.config = c->reader->cpu_flash_config;
+ order_cpu.device_get = c->reader->cpu_flash_device_get;
+ order_cpu.write = c->reader->cpu_write_6502;
+ order_cpu.read = c->reader->cpu_read;
+ order_cpu.erase = c->reader->cpu_flash_erase;
+ order_cpu.program = c->reader->cpu_flash_program;
+ order_cpu.flash_status = c->reader->flash_status;
+
+ order_ppu.command_change = true;
+ order_ppu.unit = c->flash_ppu->pagesize;
+ order_ppu.memory = &c->rom.ppu_rom;
+ order_ppu.config = c->reader->ppu_flash_config;
+ order_ppu.device_get = c->reader->ppu_flash_device_get;
+ order_ppu.write = c->reader->ppu_write; //warning ¤Ï̵»ë
+ order_ppu.read = c->reader->ppu_read;
+ order_ppu.erase = c->reader->ppu_flash_erase;
+ order_ppu.program = c->reader->ppu_flash_program;
+ order_ppu.flash_status = c->reader->flash_status;
+
+ HSQUIRRELVM v = qr_open();
+ qr_function_register_global(v, "cpu_write", cpu_write);
+ qr_function_register_global(v, "cpu_erase", cpu_erase);
+ qr_function_register_global(v, "cpu_program", cpu_program);
+ qr_function_register_global(v, "cpu_command", cpu_command);
+ qr_function_register_global(v, "ppu_erase", ppu_erase);
+ qr_function_register_global(v, "ppu_program", ppu_program);
+ qr_function_register_global(v, "ppu_command", ppu_command);
+ qr_function_register_global(v, "program_main", program_main);
+ qr_function_register_global(v, "erase_wait", erase_wait);
+
+ execute_main(v, c);
+
+ qr_close(v);
+}
--- /dev/null
+#ifndef _SCRIPT_H_
+#define _SCRIPT_H_
+struct config{
+ const char *script, *target;
+ const struct flash_driver *flash_cpu, *flash_ppu;
+ const struct reader_driver *reader;
+ struct romimage rom;
+};
+void script_execute(struct config *c);
+#endif
--- /dev/null
+#include <stdio.h>
+#include <stdbool.h>
+#include "lua.h"
+#include "lualib.h"
+#include "lauxlib.h"
+#include "type.h"
+#include "header.h"
+#include "reader_master.h"
+#include "script.h"
+
+static struct anago_flash_order{
+ int program_count, command_change;
+ long address, length;
+ long c2aaa, c5555, unit;
+ struct memory *memory;
+ void (*config)(long c2aaa, long c5555, long unit);
+ void (*write)(long address, long length, const uint8_t *data);
+ void (*read)(long address, long length, u8 *data);
+ void (*erase)(long address, bool dowait);
+ long (*program)(long address, long length, u8 *data, bool dowait);
+}order_cpu, order_ppu;
+static inline long long_get(lua_State *t, int index)
+{
+ lua_Number d = lua_tonumber(t, index);
+ return (long) d;
+}
+static void command_set(lua_State *l, struct anago_flash_order *t)
+{
+ long command = long_get(l, 1);
+ long address = long_get(l, 2);
+ long mask = long_get(l, 3);
+ long d = command & (mask - 1);
+ d |= address;
+ switch(command){
+ case 0x02aa: case 0x2aaa:
+ t->c2aaa = d;
+ break;
+ case 0x0555: case 0x5555:
+ t->c5555 = d;
+ break;
+ default:
+ puts("unknown command address");
+ return;
+ }
+ t->command_change += 1;
+}
+static int cpu_command(lua_State *l)
+{
+ command_set(l, &order_cpu);
+ return 0;
+}
+static int ppu_command(lua_State *l)
+{
+ command_set(l, &order_ppu);
+ return 0;
+}
+static int write(lua_State *l, struct anago_flash_order *t)
+{
+ long address = long_get(l, 1);
+ long data = long_get(l, 2);
+ uint8_t d8 = (uint8_t) data;
+ t->write(address, 1, &d8);
+ return 0;
+}
+static int cpu_write(lua_State *l)
+{
+ return write(l, &order_cpu);
+}
+static int program_regist(lua_State *l, const char *name, struct anago_flash_order *t)
+{
+ t->address = long_get(l, 1);
+ t->length = long_get(l, 2);
+ if(t->command_change != 0){
+ t->config(t->c2aaa, t->c5555, t->unit);
+ t->command_change = 0;
+ }
+
+ printf("programming %s area 0x%06x...\n", name, t->memory->offset);
+ fflush(stdout);
+ return lua_yield(l, 0);
+}
+static void program_execute(struct anago_flash_order *t)
+{
+ if(t->program_count == 0){
+ t->erase(t->c2aaa, false);
+ t->program_count += 1;
+ printf("erase...\n");
+ fflush(stdout);
+ return;
+ }
+ t->program_count += 1;
+// printf("writing %06x\n", t->memory->offset);
+// fflush(stdout);
+ const long w = t->program(t->address, t->length, t->memory->data + t->memory->offset, false);
+ t->address += w;
+ t->length -= w;
+ t->memory->offset += w;
+}
+static int cpu_program(lua_State *l)
+{
+ return program_regist(l, "program ROM", &order_cpu);
+}
+static int ppu_program(lua_State *l)
+{
+ return program_regist(l, "charcter ROM", &order_ppu);
+}
+static int mmc1_write(lua_State *l)
+{
+ long address = long_get(l, 1);
+ uint8_t data = (uint8_t) long_get(l, 2);
+ int i = 5;
+ while(i != 0){
+ order_cpu.write(address, 1, &data);
+ data >>= 1;
+ i--;
+ }
+ return 0;
+}
+
+void script_execute(struct config *c)
+{
+ order_cpu.command_change = 0;
+ order_cpu.program_count = 0;
+ order_cpu.unit = c->flash_cpu->pagesize;
+ order_cpu.memory = &c->rom.cpu_rom;
+ order_cpu.config = c->reader->cpu_flash_config;
+ order_cpu.write = c->reader->cpu_write_6502;
+ order_cpu.read = c->reader->cpu_read;
+ order_cpu.erase = c->reader->cpu_flash_erase;
+ order_cpu.program = c->reader->cpu_flash_program;
+
+ order_ppu.command_change = 0;
+ order_ppu.program_count = 0;
+ order_ppu.unit = c->flash_ppu->pagesize;
+ order_ppu.memory = &c->rom.ppu_rom;
+ order_ppu.config = c->reader->ppu_flash_config;
+ order_ppu.write = c->reader->ppu_write; //warning ¤Ï̵»ë
+ order_ppu.read = c->reader->ppu_read;
+ order_ppu.erase = c->reader->ppu_flash_erase;
+ order_ppu.program = c->reader->ppu_flash_program;
+
+ lua_State *const l = lua_open();
+ luaL_openlibs(l);
+ lua_register(l, "cpu_write", cpu_write);
+ lua_register(l, "cpu_program", cpu_program);
+ lua_register(l, "cpu_command", cpu_command);
+ lua_register(l, "ppu_program", ppu_program);
+ lua_register(l, "ppu_command", ppu_command);
+ lua_register(l, "mmc1_write", mmc1_write);
+ if(luaL_loadfile(l, c->script) == LUA_ERRFILE){
+ lua_close(l);
+ return;
+ }
+ if(lua_pcall(l, 0, 0, 0) != 0){
+ puts(lua_tostring(l, -1));
+ return;
+ }
+ lua_getfield(l, LUA_GLOBALSINDEX, "initalize");
+ lua_getglobal(l, "initalize");
+ lua_call(l, 0, 0);
+ lua_State *const co_cpu = lua_newthread(l);
+ lua_State *const co_ppu = lua_newthread(l);
+ lua_getglobal(co_cpu, "program_cpu");
+ lua_getglobal(co_ppu, "program_ppu");
+ int state_cpu = LUA_YIELD, state_ppu = LUA_YIELD;
+ if(order_cpu.memory->size == 0 || c->flash_cpu->id_device == FLASH_ID_DEVICE_DUMMY){
+ state_cpu = 0;
+ }
+ if(order_ppu.memory->size == 0 || c->flash_ppu->id_device == FLASH_ID_DEVICE_DUMMY){
+ state_ppu = 0;
+ }
+ if(state_cpu != 0){
+ state_cpu = lua_resume(co_cpu, 0);
+ }
+ if(state_ppu != 0){
+ state_ppu = lua_resume(co_ppu, 0);
+ }
+ do{
+ uint8_t s[2];
+ Sleep(2);
+ c->reader->flash_status(s);
+ if(state_cpu != 0 && s[0] == 0){
+ if(order_cpu.length == 0){
+ state_cpu = lua_resume(co_cpu, 0);
+ }else{
+ program_execute(&order_cpu);
+ }
+ }
+ if(state_ppu != 0 && s[1] == 0){
+ if(order_ppu.length == 0){
+ state_ppu = lua_resume(co_ppu, 0);
+ }else{
+ program_execute(&order_ppu);
+ }
+ }
+ }while(state_cpu != 0 || state_ppu != 0);
+ lua_close(l);
+}
--- /dev/null
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdbool.h>
+#include <squirrel.h>
+#include <sqstdio.h>
+#include <sqstdaux.h>
+
+#ifdef SQUNICODE
+#define scvprintf vwprintf
+#else
+#define scvprintf vprintf
+#endif
+static void printfunc(HSQUIRRELVM v, const SQChar *s, ...)
+{
+ va_list arglist;
+ va_start(arglist, s);
+ scvprintf(s, arglist);
+ va_end(arglist);
+}
+
+HSQUIRRELVM qr_open(void)
+{
+ HSQUIRRELVM v = sq_open(0x400);
+ sqstd_seterrorhandlers(v);
+ sq_setprintfunc(v, printfunc);
+ sq_pushroottable(v);
+ return v;
+}
+
+//SQInteger
+void qr_function_register_global(HSQUIRRELVM v, const char *name, SQFUNCTION f)
+{
+ sq_pushroottable(v);
+ sq_pushstring(v, name, -1);
+ sq_newclosure(v, f, 0);
+ sq_createslot(v, -3);
+ sq_pop(v, 1);
+}
+
+void qr_call(HSQUIRRELVM v, const SQChar *functionname, bool settop, int argnum, ...)
+{
+ SQInteger top = sq_gettop(v);
+ sq_pushroottable(v);
+ sq_pushstring(v, _SC(functionname), -1);
+ if(SQ_SUCCEEDED(sq_get(v,-2))){
+ int i;
+ va_list ap;
+ va_start(ap, argnum);
+ sq_pushroottable(v);
+ for(i = 0; i < argnum; i++){
+ sq_pushinteger(v, va_arg(ap, long));
+ }
+ sq_call(v, 1 + argnum, SQFalse, SQTrue); //calls the function
+ }
+ if(settop == true){
+ sq_settop(v, top); //restores the original stack size
+ }
+}
+
+void qr_close(HSQUIRRELVM v)
+{
+ sq_pop(v, 1);
+ sq_close(v);
+}
+
+static bool long_get(HSQUIRRELVM v, SQInteger index, long *d)
+{
+ if(sq_gettype(v, index) != OT_INTEGER){
+ return false;
+ }
+ SQInteger i;
+ if(SQ_FAILED(sq_getinteger(v, index, &i))){
+ return false;
+ }
+ *d = (long) i;
+ return true;
+}
+
+SQRESULT qr_argument_get(HSQUIRRELVM v, SQInteger num, ...)
+{
+ va_list ap;
+ if(sq_gettop(v) != (num + 1)){
+ return sq_throwerror(v, "argument number error");
+ }
+ va_start(ap, num);
+ SQInteger i;
+ for(i = 0; i < num; i++){
+ if(long_get(v, i + 2, va_arg(ap, long *)) == false){
+ return sq_throwerror(v, "argument type error");
+ }
+ }
+ return 0;
+}
--- /dev/null
+#ifndef _SQUIRREL_WRAP_H_
+#define _SQUIRREL_WRAP_H_
+HSQUIRRELVM qr_open(void);
+void qr_function_register_global(HSQUIRRELVM v, const char *name, SQFUNCTION f);
+void qr_call(HSQUIRRELVM v, const SQChar *functionname, bool settop, int argnum, ...);
+void qr_close(HSQUIRRELVM v);
+SQRESULT qr_argument_get(HSQUIRRELVM v, SQInteger num, ...);
+#endif