OSDN Git Service

dump mode support
authornaruko <naruko@24ea1065-a21e-4ca1-99c9-f5125deb0858>
Mon, 16 Nov 2009 19:00:27 +0000 (19:00 +0000)
committernaruko <naruko@24ea1065-a21e-4ca1-99c9-f5125deb0858>
Mon, 16 Nov 2009 19:00:27 +0000 (19:00 +0000)
git-svn-id: svn+ssh://svn.osdn.net/svnroot/unagi@308 24ea1065-a21e-4ca1-99c9-f5125deb0858

client/trunk/anago/Makefile
client/trunk/anago/anago.c
client/trunk/anago/flashcore.nut
client/trunk/anago/script_dump.c [new file with mode: 0644]
client/trunk/anago/script_dump.h [new file with mode: 0644]
client/trunk/anago/script_flash.c [moved from client/trunk/anago/script.c with 98% similarity]
client/trunk/anago/script_flash.h [moved from client/trunk/anago/script.h with 53% similarity]
client/trunk/anago/squirrel_wrap.c
client/trunk/anago/squirrel_wrap.h

index b6fc265..0967a9b 100644 (file)
@@ -5,12 +5,13 @@ VPATH = ..
 CFLAGS = -g -O0 -Wall -Werror -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 header.o crc32.o file.o script.o progress.o \
-       flash_device.o \
+OBJ = anago.o header.o crc32.o file.o script_flash.o script_dump.o \
+       progress.o flash_device.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
 
-script.o: squirrel_wrap.h
+script_flash.o: squirrel_wrap.h
+script_dump.o: squirrel_wrap.h
index 68b9ea9..411babc 100644 (file)
@@ -8,7 +8,8 @@
 #include "reader_master.h"
 #include "reader_kazzo.h"
 #include "reader_dummy.h"
-#include "script.h"
+#include "script_flash.h"
+#include "script_dump.h"
 
 static bool transtype_flash_set(char mode, struct memory *t)
 {
@@ -33,7 +34,7 @@ static bool transtype_flash_set(char mode, struct memory *t)
 static bool transtype_set(const char *mode, struct romimage *t)
 {
        switch(mode[0]){
-       case 'd': case 'f':
+       case 'a': case 'f':
                if(mode[1] == '\0'){
                        t->cpu_rom.transtype = TRANSTYPE_FULL;
                        t->ppu_rom.transtype = TRANSTYPE_FULL;
@@ -53,7 +54,7 @@ static bool transtype_set(const char *mode, struct romimage *t)
        }
        return false;
 }
-static bool config_parse(const char *romimage, const char *device_cpu, const char *device_ppu, struct config *c)
+static bool config_parse(const char *romimage, const char *device_cpu, const char *device_ppu, struct config_flash *c)
 {
        c->target = romimage;
        if(nesfile_load(__FUNCTION__, romimage, &c->rom) == false){
@@ -80,12 +81,12 @@ static bool config_parse(const char *romimage, const char *device_cpu, const cha
        }
        return true;
 }
-static void anago(int c, char **v)
+static void program(int c, char **v)
 {
-       struct config config;
+       struct config_flash config;
        config.script = v[2];
        config.reader = &DRIVER_KAZZO;
-       if(v[1][0] == 'd'){
+       if(v[1][0] == 'a'){
                config.reader = &DRIVER_DUMMY;
        }       
        if(transtype_set(v[1], &config.rom) == false){
@@ -114,14 +115,78 @@ static void anago(int c, char **v)
                nesbuffer_free(&config.rom, 0);
                return;
        }
-       script_execute(&config);
+       script_flash_execute(&config);
        nesbuffer_free(&config.rom, 0);
        config.reader->open_or_close(READER_CLOSE);
 }
+static void dump(int c, char **v)
+{
+       struct config_dump config;
+       if(c != 4){
+               puts("argument error");
+               return;
+       }
+       config.increase.cpu = 1;
+       config.increase.ppu = 1;
+       config.progress = true;
+       switch(v[1][0]){
+       case 'D':
+               config.progress = false;
+               break;
+       }
+       switch(v[1][1]){
+       case '2':
+               config.increase.cpu = 2;
+               break;
+       case '4':
+               config.increase.cpu = 4;
+               break;
+       }
+       if(v[1][1] != '\0'){
+               switch(v[1][2]){
+               case '2':
+                       config.increase.ppu = 2;
+                       break;
+               case '4':
+                       config.increase.ppu = 4;
+                       break;
+               }
+       }
+       config.script = v[2];
+       config.target = v[3];
+       config.reader = &DRIVER_KAZZO;
+       config.mappernum = -1;
+       if(config.reader->open_or_close(READER_OPEN) == NG){
+               puts("reader open error");
+               return;
+       }
+       script_dump_execute(&config);
+       config.reader->open_or_close(READER_CLOSE);
+}
+static void usage(const char *v)
+{
+       puts("famicom bus simluator 'anago'");
+       printf("%s [mode] [script] [target] ....\n", v);
+}
 int main(int c, char **v)
 {
        mm_init();
-       anago(c, v);
+       if(c >= 2){
+               switch(v[1][0]){
+               case 'a': case 'f':
+                       program(c, v);
+                       break;
+               case 'd': case 'D':
+                       dump(c,v);
+                       break;
+               default:
+                       usage(v[0]);
+                       puts("mode are a, d, f");
+                       break;
+               }
+       }else{
+               usage(v[0]);
+       }
        mm_end();
        return 0;
 }
index 6e90ce3..1e394cc 100644 (file)
@@ -46,7 +46,7 @@ function program(d, mapper, cpu_trans, cpu_size, ppu_trans, ppu_size)
                ppu_erase(d);
        }
        erase_wait(d);
-       if(cpu_trans != 0){
+       if(cpu_trans != trans_empty){
                co_cpu.call(d, cpu_loop);
        }
        if(ppu_trans != trans_empty){
diff --git a/client/trunk/anago/script_dump.c b/client/trunk/anago/script_dump.c
new file mode 100644 (file)
index 0000000..e91e5de
--- /dev/null
@@ -0,0 +1,382 @@
+#include <assert.h>
+#include <stdio.h>
+#include <squirrel.h>
+#include <sqstdio.h>
+#include <sqstdaux.h>
+#include "type.h"
+#include "header.h"
+#include "progress.h"
+#include "memory_manage.h"
+#include "reader_master.h"
+#include "squirrel_wrap.h"
+#include "script_dump.h"
+
+struct dump_driver{
+       const char *target;
+       struct memory_driver{
+               struct memory memory;
+               long read_count;
+               void (*const write)(long address, long length, const uint8_t *data);
+               void (*const read)(long address, long length, u8 *data);
+       }cpu, ppu;
+       bool progress;
+};
+static SQInteger write(HSQUIRRELVM v, struct memory_driver *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)
+{
+       struct dump_driver *d;
+       SQRESULT r =  qr_userpointer_get(v, (SQUserPointer *) &d);
+       if(SQ_FAILED(r)){
+               return r;
+       }
+       return write(v, &d->cpu);
+}
+
+static void buffer_show(struct memory *t, long length)
+{
+       int i;
+       const uint8_t *buf = t->data + t->offset;
+       printf("%s 0x%06x:", t->name, t->offset);
+       for(i = 0; i < 0x10; i++){
+               char dump[3+1];
+               sprintf(dump, "%02x", buf[i]);
+               switch(i){
+               case 7:
+                       dump[2] = '-';
+                       break;
+               case 0x0f:
+                       dump[2] = '\0';
+                       break;
+               default:
+                       dump[2] = ' ';
+                       break;
+               }
+               dump[3] = '\0';
+               printf("%s", dump);
+       }
+       int sum = 0;
+       while(length != 0){
+               sum += (int) *buf;
+               buf++;
+               length--;
+       }
+       printf(":0x%06x\n", sum);
+       fflush(stdout);
+}
+
+static void progress_show(struct dump_driver *d)
+{
+       if(d->progress == true){
+               progress_draw(d->cpu.memory.offset, d->cpu.memory.size, d->ppu.memory.offset, d->ppu.memory.size);
+       }
+}
+static SQInteger read(HSQUIRRELVM v, struct memory_driver *t, bool progress)
+{
+       long address, length;
+       SQRESULT r = qr_argument_get(v, 2, &address, &length);
+       if(SQ_FAILED(r)){
+               return r;
+       }
+       t->read(address, length == 0 ? 1: length, t->memory.data + t->memory.offset);
+       if((length != 0) && (progress == false)){
+               buffer_show(&t->memory, length);
+       }
+       t->memory.offset += length;
+       return 0;
+}
+static SQInteger cpu_read(HSQUIRRELVM v)
+{
+       struct dump_driver *d;
+       SQRESULT r =  qr_userpointer_get(v, (SQUserPointer *) &d);
+       if(SQ_FAILED(r)){
+               return r;
+       }
+       r = read(v, &d->cpu, d->progress);
+       progress_show(d);
+       return r;
+}
+
+static SQInteger ppu_read(HSQUIRRELVM v)
+{
+       struct dump_driver *d;
+       SQRESULT r =  qr_userpointer_get(v, (SQUserPointer *) &d);
+       if(SQ_FAILED(r)){
+               return r;
+       }
+       r = read(v, &d->ppu, d->progress);
+       progress_show(d);
+       return r;
+}
+
+static SQInteger ppu_ramfind(HSQUIRRELVM v)
+{
+       struct dump_driver *d;
+       enum{
+               testsize = 8,
+               testaddress = 1234
+       };
+       static const uint8_t test_val[testsize] = {0xaa, 0x55, 0, 0xff, 0x46, 0x49, 0x07, 0x21};
+       static const uint8_t test_str[testsize] = "pputest";
+       uint8_t test_result[testsize];
+
+       SQRESULT r =  qr_userpointer_get(v, (SQUserPointer *) &d);
+       if(SQ_FAILED(r)){
+               return r;
+       }
+       d->ppu.write(testaddress, testsize, test_val);
+       d->ppu.read(testaddress, testsize, test_result);
+       if(memcmp(test_val, test_result, testsize) != 0){
+               sq_pushbool(v, SQFalse);
+               return 1;
+       }
+       d->ppu.write(testaddress, testsize, test_str);
+       d->ppu.read(testaddress, testsize, test_result);
+       if(memcmp(test_str, test_result, testsize) != 0){
+               sq_pushbool(v, SQFalse);
+               return 1;
+       }
+       d->ppu.memory.offset = 0;
+       d->ppu.memory.size = 0;
+       sq_pushbool(v, SQTrue);
+       return 1;
+}
+
+//test »þ/1ÅÙÌܤΠcall ¤Ç»ÈÍÑ
+static SQInteger memory_new(HSQUIRRELVM v)
+{
+       struct dump_driver *d;
+       SQRESULT r =  qr_userpointer_get(v, (SQUserPointer *) &d);
+       if(SQ_FAILED(r)){
+               return r;
+       }
+       r = qr_argument_get(v, 2, &d->cpu.memory.size, &d->ppu.memory.size);
+       if(SQ_FAILED(r)){
+               return r;
+       }
+       d->cpu.memory.offset = 0;
+       d->cpu.memory.data = Malloc(d->cpu.memory.size);
+       d->ppu.memory.offset = 0;
+       d->ppu.memory.data = Malloc(d->ppu.memory.size);
+       return 0;
+}
+
+//dump »þ/2ÅÙÌܤΠcall ¤Ç nesfile_save ¤È¤·¤Æ»ÈÍÑ
+static SQInteger nesfile_save(HSQUIRRELVM v)
+{
+       struct dump_driver *d;
+       SQRESULT r =  qr_userpointer_get(v, (SQUserPointer *) &d);
+       if(SQ_FAILED(r)){
+               return r;
+       }
+       struct romimage image;
+       r = qr_argument_get(v, 1, &image.mappernum);
+       if(SQ_FAILED(r)){
+               return r;
+       }
+       image.cpu_rom = d->cpu.memory;
+       image.cpu_ram.data = NULL;
+       image.ppu_rom = d->ppu.memory;
+       image.mirror = MIRROR_PROGRAMABLE;
+       image.backupram = 0;
+       nesfile_create(&image, d->target);
+       nesbuffer_free(&image, 0); //0 is MODE_xxx_xxxx
+       
+       d->cpu.memory.data = NULL;
+       d->ppu.memory.data = NULL;
+       return 0;
+}
+
+//dump »þ/1ÅÙÌܤΠcall ¤Ç nesfile_save ¤È¤·¤Æ»ÈÍÑ
+static SQInteger length_check(HSQUIRRELVM v)
+{
+       struct dump_driver *d;
+       SQRESULT r =  qr_userpointer_get(v, (SQUserPointer *) &d);
+       if(SQ_FAILED(r)){
+               return r;
+       }
+       bool cpu = true, ppu = true;
+       r = 0;
+       if(d->cpu.memory.size != d->cpu.read_count){
+               cpu = false;
+       }
+       if(cpu == false){
+               printf("cpu_romsize is not connected 0x%06x/0x%06x\n", (int) d->cpu.read_count, (int) d->cpu.memory.size);
+       }
+       if(d->ppu.memory.size != d->ppu.read_count){
+               ppu = false;
+       }
+       if(ppu == false){
+               printf("ppu_romsize is not connected 0x%06x/0x%06x\n", (int) d->ppu.read_count, (int) d->ppu.memory.size);
+       }
+       if(cpu == false || ppu == false){
+               r = sq_throwerror(v, "script logical error");
+       }
+       return r;
+}
+static SQInteger script_nop(HSQUIRRELVM v)
+{
+       return 0;
+}
+
+struct range{
+       long start, end;
+};
+static SQInteger range_check(HSQUIRRELVM v, const char *name, long target, const struct range *range)
+{
+       if((target < range->start) || (target > range->end)){
+               printf("%s range must be 0x%06x to 0x%06x", name, (int) range->start, (int) range->end);
+               return sq_throwerror(v, "script logical error");
+       }
+       return 0;
+}
+static SQInteger read_count(HSQUIRRELVM v, struct memory_driver *t, const struct range *range_address, const struct range *range_length)
+{
+       long address, length;
+       SQRESULT r = qr_argument_get(v, 2, &address, &length);
+       if(SQ_FAILED(r)){
+               return r;
+       }
+       r = range_check(v, "length", length, range_length);
+       if(SQ_FAILED(r)){
+               return r;
+       }
+       if((address < range_address->start) || ((address + length) > range_address->end)){
+               printf("address range must be 0x%06x to 0x%06x", (int) range_address->start, (int) range_address->end);
+               return sq_throwerror(v, "script logical error");;
+       }
+       t->read_count += length;
+       return 0;
+}
+static SQInteger cpu_read_count(HSQUIRRELVM v)
+{
+       static const struct range range_address = {0x8000, 0x10000};
+       //length == 0 ¤Ï Âоݥ¢¥É¥ì¥¹¤ò¸Æ¤ó¤Ç¡¢¥Ð¥Ã¥Õ¥¡¤Ë¤¤¤ì¤Ê¤¤¡£mmc2, mmc4 ¤Ç»ÈÍѤ¹¤ë¡£
+       static const struct range range_length = {0x0000, 0x4000};
+       struct dump_driver *d;
+       SQRESULT r =  qr_userpointer_get(v, (SQUserPointer *) &d);
+       if(SQ_FAILED(r)){
+               return r;
+       }
+       return read_count(v, &d->cpu, &range_address, &range_length);
+}
+
+static SQInteger ppu_read_count(HSQUIRRELVM v)
+{
+       static const struct range range_address = {0x0000, 0x2000};
+       static const struct range range_length = {0x0001, 0x2000};
+       struct dump_driver *d;
+       SQRESULT r =  qr_userpointer_get(v, (SQUserPointer *) &d);
+       if(SQ_FAILED(r)){
+               return r;
+       }
+       return read_count(v, &d->ppu, &range_address, &range_length);
+}
+
+static SQInteger cpu_write_check(HSQUIRRELVM v)
+{
+       static const struct range range_address = {0x4000, 0x10000};
+       static const struct range range_data = {0x0, 0xff};
+       long address, data;
+       SQRESULT r = qr_argument_get(v, 2, &address, &data);
+       if(SQ_FAILED(r)){
+               return r;
+       }
+       r = range_check(v, "address", address, &range_address);
+       if(SQ_FAILED(r)){
+               return r;
+       }
+       return range_check(v, "data", data, &range_data);
+}
+static bool script_execute(HSQUIRRELVM v, struct config_dump *c, struct dump_driver *d)
+{
+       bool ret = true;
+       if(SQ_FAILED(sqstd_dofile(v, _SC("dumpcore.nut"), SQFalse, SQTrue))){
+               printf("dump core script error\n");
+               ret = false;
+       }else if(SQ_FAILED(sqstd_dofile(v, _SC(c->script), SQFalse, SQTrue))){
+               printf("%s open error\n", c->script);
+               ret = false;
+       }else{
+               SQRESULT r = qr_call(
+                       v, "dump", (SQUserPointer) d, true, 
+                       3, c->mappernum, c->increase.cpu, c->increase.ppu
+               );
+               if(SQ_FAILED(r)){
+                       ret = false;
+                       Free(d->cpu.memory.data);
+                       Free(d->ppu.memory.data);
+                       d->cpu.memory.data = NULL;
+                       d->ppu.memory.data = NULL;
+               }
+       }
+       return ret;
+}
+void script_dump_execute(struct config_dump *c)
+{
+       struct dump_driver d = {
+               .cpu = {
+                       .memory = {
+                               .name = "program",
+                               .size = 0, .offset = 0,
+                               .attribute = MEMORY_ATTR_WRITE,
+                               .transtype = TRANSTYPE_FULL,
+                               .data = NULL
+                       },
+                       .read_count = 0,
+                       .write = c->reader->cpu_write_6502,
+                       .read = c->reader->cpu_read
+               },
+               .ppu = {
+                       .memory = {
+                               .name = "charcter",
+                               .size = 0, .offset = 0,
+                               .attribute = MEMORY_ATTR_WRITE,
+                               .transtype = TRANSTYPE_FULL,
+                               .data = NULL
+                       },
+                       .read_count = 0,
+                       .write = c->reader->ppu_write,
+                       .read = c->reader->ppu_read
+               },
+               .target = c->target,
+               .progress = c->progress
+       };
+       {
+               HSQUIRRELVM v = qr_open(); 
+               qr_function_register_global(v, "ppu_ramfind", script_nop);
+               qr_function_register_global(v, "cpu_write", cpu_write_check);
+               qr_function_register_global(v, "memory_new", memory_new);
+               qr_function_register_global(v, "nesfile_save", length_check);
+               qr_function_register_global(v, "cpu_read", cpu_read_count);
+               qr_function_register_global(v, "ppu_read", ppu_read_count);
+               if(script_execute(v, c, &d) == false){
+                       qr_close(v);
+                       return;
+               }
+               qr_close(v);
+       }
+       if(c->progress == true){
+               progress_init();
+       }
+       {
+               HSQUIRRELVM v = qr_open(); 
+               qr_function_register_global(v, "memory_new", script_nop);
+               qr_function_register_global(v, "nesfile_save", nesfile_save);
+               qr_function_register_global(v, "cpu_write", cpu_write);
+               qr_function_register_global(v, "cpu_read", cpu_read);
+               qr_function_register_global(v, "ppu_read", ppu_read);
+               qr_function_register_global(v, "ppu_ramfind", ppu_ramfind);
+               script_execute(v, c, &d);
+               qr_close(v);
+       }
+}
diff --git a/client/trunk/anago/script_dump.h b/client/trunk/anago/script_dump.h
new file mode 100644 (file)
index 0000000..c05eddb
--- /dev/null
@@ -0,0 +1,12 @@
+#ifndef _SCRIPT_DUMP_H_
+#define _SCRIPT_DUMP_H_
+struct config_dump{
+       const char *script, *target;
+       const struct reader_driver *reader;
+       long mappernum;
+       //struct romimage rom;
+       struct {long cpu, ppu;} increase;
+       bool progress;
+};
+void script_dump_execute(struct config_dump *c);
+#endif
similarity index 98%
rename from client/trunk/anago/script.c
rename to client/trunk/anago/script_flash.c
index 7e4c0ae..38ae17f 100644 (file)
@@ -8,7 +8,7 @@
 #include "squirrel_wrap.h"
 #include "flash_device.h"
 #include "progress.h"
-#include "script.h"
+#include "script_flash.h"
 
 struct anago_driver{
        struct anago_flash_order{
@@ -284,7 +284,7 @@ static SQInteger ppu_program_count(HSQUIRRELVM v)
        return program_count(v, &d->order_ppu);
 }
 
-static bool script_testrun(struct config *c, struct anago_driver *d)
+static bool script_testrun(struct config_flash *c, struct anago_driver *d)
 {
        static const char *functionname[] = {
                "cpu_write", "cpu_erase", "cpu_command",
@@ -318,7 +318,7 @@ static bool script_testrun(struct config *c, struct anago_driver *d)
        qr_close(v);
        return ret;
 }
-void script_execute(struct config *c)
+void script_flash_execute(struct config_flash *c)
 {
        struct anago_driver d = {
                .order_cpu = {
similarity index 53%
rename from client/trunk/anago/script.h
rename to client/trunk/anago/script_flash.h
index dd850ec..f5f7bdc 100644 (file)
@@ -1,10 +1,10 @@
-#ifndef _SCRIPT_H_
-#define _SCRIPT_H_
-struct config{
+#ifndef _SCRIPT_FLASH_H_
+#define _SCRIPT_FLASH_H_
+struct config_flash{
        const char *script, *target;
        struct flash_device flash_cpu, flash_ppu;
        const struct reader_driver *reader;
        struct romimage rom;
 };
-void script_execute(struct config *c);
+void script_flash_execute(struct config_flash *c);
 #endif
index c708dfa..df9213d 100644 (file)
@@ -38,8 +38,9 @@ void qr_function_register_global(HSQUIRRELVM v, const char *name, SQFUNCTION f)
        sq_pop(v, 1);
 }
 
-void qr_call(HSQUIRRELVM v, const SQChar *functionname, SQUserPointer up, bool settop, int argnum, ...)
+SQRESULT qr_call(HSQUIRRELVM v, const SQChar *functionname, SQUserPointer up, bool settop, int argnum, ...)
 {
+       SQRESULT r = SQ_ERROR;
        SQInteger top = sq_gettop(v);
        sq_pushroottable(v);
        sq_pushstring(v, _SC(functionname), -1);
@@ -52,11 +53,12 @@ void qr_call(HSQUIRRELVM v, const SQChar *functionname, SQUserPointer up, bool s
                for(i = 0; i < argnum; i++){
                        sq_pushinteger(v, va_arg(ap, long));
                }
-               sq_call(v, 2 + argnum, SQFalse, SQTrue); //calls the function 
+               r = sq_call(v, 2 + argnum, SQFalse, SQTrue); //calls the function 
        }
        if(settop == true){
                sq_settop(v, top); //restores the original stack size
        }
+       return r;
 }
 
 void qr_close(HSQUIRRELVM v)
index 64436b1..4d64df1 100644 (file)
@@ -2,7 +2,7 @@
 #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, SQUserPointer up, bool settop, int argnum, ...);
+SQRESULT qr_call(HSQUIRRELVM v, const SQChar *functionname, SQUserPointer up, bool settop, int argnum, ...);
 void qr_close(HSQUIRRELVM v);
 SQRESULT qr_argument_get(HSQUIRRELVM v, SQInteger num, ...);
 SQRESULT qr_userpointer_get(HSQUIRRELVM v, SQUserPointer *up);