--- /dev/null
+#include <assert.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include "memory_manage.h"
+#include "type.h"
+#include "widget.h"
+#include "cui_gauge.h"
+#include "romimage.h"
+#include "reader_master.h"
+#include "reader_kazzo.h"
+#include "reader_dummy.h"
+#include "script_dump.h"
+#include "flash_device.h"
+#include "script_program.h"
+
+#ifdef _UNICODE
+ #define PUTS _putws
+ #define PRINTF wprintf
+#else
+ #define PUTS puts
+ #define PRINTF printf
+#endif
+
+static void text_append_va(void *obj, const wgChar *format, va_list list)
+{
+#ifdef _UNICODE
+ vwprintf(format, list);
+#else
+ vprintf(format, list);
+#endif
+}
+
+static void text_append(void *obj, const wgChar *format, ...)
+{
+ va_list list;
+ va_start(list, format);
+ text_append_va(obj, format, list);
+ va_end(list);
+}
+
+static void log_set(struct textcontrol *log)
+{
+ log->object = NULL;
+ log->append = text_append;
+ log->append_va = text_append_va;
+}
+
+static void except(const wgChar *str)
+{
+ PUTS(str);
+ exit(0);
+}
+
+static bool program_rom_set(const wgChar *device, wgChar trans, struct memory *m, struct flash_device *f)
+{
+ m->offset = 0;
+ if(flash_device_get(device, f) == false){
+ PRINTF(wgT("unknown flash memory device %s\n"), device);
+ return false;
+ }
+ switch(trans){
+ case 'f':
+ m->transtype = TRANSTYPE_FULL;
+ break;
+ case 't':
+ m->transtype = TRANSTYPE_TOP;
+ break;
+ case 'b':
+ m->transtype = TRANSTYPE_BOTTOM;
+ break;
+ case 'e':
+ default:
+ m->transtype = TRANSTYPE_EMPTY;
+ break;
+ }
+ return true;
+}
+
+static void program(int c, wgChar **v, const struct reader_driver *r)
+{
+ struct program_config config;
+ config.cpu.memory.data = NULL;
+ config.ppu.memory.data = NULL;
+ config.script = v[2];
+ config.target = v[3];
+ config.control = &r->control;
+ config.cpu.access = &r->cpu;
+ config.ppu.access = &r->ppu;
+ config.compare = false;
+ switch(v[1][0]){
+ case wgT('F'): case wgT('X'):
+ config.compare = true;
+ break;
+ }
+
+ switch(c){
+ case 5: {//mode script target cpu_flash_device
+ wgChar trans = wgT('f');
+ if(v[1][1] != wgT('\0')){
+ trans = v[1][1];
+ }
+ if(program_rom_set(v[4], trans, &config.cpu.memory, &config.cpu.flash) == false){
+ return;
+ }
+ if(program_rom_set(wgT("dummy"), wgT('e'), &config.ppu.memory, &config.ppu.flash) == false){
+ assert(0);
+ return;
+ }
+ }break;
+ case 6: { //mode script target cpu_flash_device ppu_flash_device
+ wgChar trans = wgT('f');
+ if(v[1][1] != wgT('\0')){
+ trans = v[1][1];
+ }
+ if(program_rom_set(v[4], trans, &config.cpu.memory, &config.cpu.flash) == false){
+ return;
+ }
+ trans = wgT('f');
+ if(v[1][1] != wgT('\0') && v[1][2] != wgT('\0')){
+ trans = v[1][2];
+ }
+ if(program_rom_set(v[5], trans, &config.ppu.memory, &config.ppu.flash) == false){
+ return;
+ }
+ }break;
+ default:
+ PUTS(wgT("mode script target cpu_flash_device ppu_flash_device"));
+ return;
+ }
+ log_set(&config.log);
+ cui_gauge_new(&config.cpu.gauge, wgT("Program Flash"), 2, -2);
+ cui_gauge_new(&config.ppu.gauge, wgT("Charcter Flash"), 1, -1);
+ config.except = except;
+ script_program_execute(&config);
+ cui_gauge_destory(&config.cpu.gauge);
+ cui_gauge_destory(&config.ppu.gauge);
+}
+
+static void dump(int c, wgChar **v, const struct reader_driver *r)
+{
+ struct dump_config config;
+ if(c < 4){
+ PUTS(wgT("argument error"));
+ return;
+ }
+ config.cpu.increase = INCREASE_AUTO;
+ config.ppu.increase = 1;
+ config.progress = true;
+ switch(v[1][0]){
+ case wgT('d'): case wgT('z'):
+ config.mode = MODE_ROM_DUMP;
+ break;
+ case wgT('D'):
+ config.mode = MODE_ROM_DUMP;
+ config.progress = false;
+ break;
+ case wgT('r'): case wgT('R'):
+ config.mode = MODE_RAM_READ;
+ break;
+ case wgT('w'): case wgT('W'):
+ config.mode = MODE_RAM_WRITE;
+ break;
+ }
+ switch(v[1][1]){
+ case wgT('1'):
+ config.cpu.increase = 1;
+ break;
+ case wgT('2'):
+ config.cpu.increase = 2;
+ break;
+ case wgT('4'):
+ config.cpu.increase = 4;
+ break;
+ }
+ if(v[1][1] != wgT('\0')){
+ switch(v[1][2]){
+ case wgT('2'):
+ config.ppu.increase = 2;
+ break;
+ case wgT('4'):
+ config.ppu.increase = 4;
+ break;
+ }
+ }
+ config.script = v[2];
+ config.target = v[3];
+ config.control = &r->control;
+ config.cpu.access = &r->cpu;
+ config.ppu.access = &r->ppu;
+ if(config.mode == MODE_ROM_DUMP){
+ cui_gauge_new(&config.cpu.gauge, wgT("Program ROM"), 2, -2);
+ }else{
+ cui_gauge_new(&config.cpu.gauge, wgT("Work RAM"), 2, -2);
+ }
+ cui_gauge_new(&config.ppu.gauge, wgT("Charcter ROM"), 1, -1);
+ config.except = except;
+ config.mappernum = -1;
+ if(c == 5){
+#ifdef _UNICODE
+ config.mappernum = _wtoi(v[4]);
+#else
+ config.mappernum = atoi(v[4]);
+#endif
+ }
+ config.battery = false;
+ log_set(&config.log);
+ if(config.mode == MODE_ROM_DUMP){
+ script_dump_execute(&config);
+ }else{
+ script_workram_execute(&config);
+ }
+ cui_gauge_destory(&config.cpu.gauge);
+ cui_gauge_destory(&config.ppu.gauge);
+}
+
+static void usage(const wgChar *v)
+{
+ PUTS(wgT("famicom bus simluator 'anago'"));
+ PRINTF(wgT("%s [mode] [script] [target] ....\n"), v);
+ PUTS(wgT("d - ROM dump with kazzo"));
+ PUTS(wgT("fF- flash program with kazzo"));
+ PUTS(wgT("r - workram read with kazzo"));
+ PUTS(wgT("w - workram write with kazzo"));
+ if(DEBUG == 1){
+ PUTS(wgT("z - ROM dump for test"));
+ PUTS(wgT("xX- flash program for test"));
+ PUTS(wgT("R - workram read for test"));
+ PUTS(wgT("W - workram write for test"));
+ }
+}
+
+#ifdef WIN32
+int main(int c, char **vv)
+#else
+int anago_cui(int c, wgChar **v)
+#endif
+{
+ mm_init();
+ if(c >= 2){
+ const struct reader_driver *r = &DRIVER_KAZZO;
+#ifdef _UNICODE
+ int i;
+ wchar_t **v;
+ v = Malloc(sizeof(wchar_t *) * c);
+ for(i = 0; i < c; i++){
+ size_t len = strlen(vv[i]) + 1;
+ v[i] = Malloc(sizeof(wchar_t) * len);
+ mbstowcs(v[i], vv[i], len);
+ }
+#endif
+ switch(v[1][0]){
+ case wgT('x'): case wgT('X'):
+ r = &DRIVER_DUMMY; //though down
+ case wgT('f'): case wgT('F'):
+ program(c, v, r);
+ break;
+ case wgT('z'): case wgT('R'): case wgT('W'):
+ r = &DRIVER_DUMMY; //though down
+ case wgT('d'): case wgT('D'):
+ case wgT('r'): case wgT('w'):
+ dump(c,v, r);
+ break;
+ default:
+ usage(v[0]);
+ PUTS(wgT("mode are d, D, f, g"));
+ break;
+ }
+#ifdef _UNICODE
+ for(i = 0; i < c; i++){
+ Free(v[i]);
+ }
+ Free(v);
+#endif
+ }else{ //usage
+#ifdef _UNICODE
+ size_t len = strlen(vv[0]) + 1;
+ wchar_t *t = Malloc(sizeof(wchar_t) * len);
+ mbstowcs(t, vv[0], len);
+ usage(t);
+ Free(t);
+#else
+ usage(v[0]);
+#endif
+ }
+ mm_end();
+ return 0;
+}