OSDN Git Service

flash device dummy での書き込み処理と文字出力の変更
[unagi/old-svn-converted.git] / client / trunk / script.c
index 50a5565..cf40be6 100644 (file)
@@ -2,7 +2,7 @@
 famicom ROM cartridge utility - unagi
 script engine
 
-Copyright (C) 2008  sato_tiff
+Copyright (C) 2008 ±·³«È¯¶¨Æ±Áȹç
 
 This library is free software; you can redistribute it and/or
 modify it under the terms of the GNU Lesser General Public
@@ -415,22 +415,26 @@ static const char STR_ACCESS_WRITE[] = "write";
 enum{
        SETTING, DUMP, END
 };
-static int command_mask(const int region, const long address, const long offset, long size, long *data)
+static int command_mask(const int region, const long address, const long offset, long size, struct flash_order *f)
 {
+       const char *str_region = STR_REGION_CPU;
+       if(region == MEMORY_AREA_PPU){
+               str_region = STR_REGION_PPU;
+       }
        switch(region){
        case MEMORY_AREA_CPU_ROM:
                switch(offset){
                case 0x8000: case 0xa000: case 0xc000:
                        break;
                default:
-                       printf("%s %s_COMMAND area offset error\n", LOGICAL_ERROR_PREFIX, STR_REGION_CPU);
+                       printf("%s %s_COMMAND area offset error\n", LOGICAL_ERROR_PREFIX, str_region);
                        return NG;
                }
                switch(size){
                case 0x2000: case 0x4000: case 0x8000:
                        break;
                default:
-                       printf("%s %s_COMMAND area mask error\n", LOGICAL_ERROR_PREFIX, STR_REGION_CPU);
+                       printf("%s %s_COMMAND area mask error\n", LOGICAL_ERROR_PREFIX, str_region);
                        return NG;
                }
                break;
@@ -440,28 +444,37 @@ static int command_mask(const int region, const long address, const long offset,
                case 0x1000: case 0x1400: case 0x1800: case 0x1c00:
                        break;
                default:
-                       printf("%s %s_COMMAND area offset error\n", LOGICAL_ERROR_PREFIX, STR_REGION_CPU);
+                       printf("%s %s_COMMAND area offset error\n", LOGICAL_ERROR_PREFIX, str_region);
                        return NG;
                }
                switch(size){
                case 0x0400: case 0x0800: case 0x1000: case 0x2000: 
                        break;
                default:
-                       printf("%s %s_COMMAND area mask error\n", LOGICAL_ERROR_PREFIX, STR_REGION_CPU);
+                       printf("%s %s_COMMAND area mask error\n", LOGICAL_ERROR_PREFIX, str_region);
                        return NG;
                }
                break;
        default:
                assert(0); //unknown memory area
        }
+
+       const long mask = size - 1;
+       const long data = (address & mask) | offset;
        switch(address){
-       case 0: case 0x2aaa: case 0x5555:
+       case 0:
+               f->command_0000 = data;
+               break;
+       case 0x2aaa: case 0x02aa: 
+               f->command_2aaa = data;
+               break;
+       case 0x5555: case 0x0555:
+               f->command_5555 = data;
                break;
        default:
-               assert(0); //unknown command address
+               printf("%s %s_COMMAND unknown commnand address\n", LOGICAL_ERROR_PREFIX, str_region);
+               return NG;
        }
-       long mask = size - 1;
-       *data = (address & mask) | offset;
        return OK;
 }
 
@@ -499,6 +512,7 @@ static int logical_check(const struct script *s, const struct st_config *c, stru
                                }
                                break;
                        case MODE_ROM_PROGRAM:
+                               assert(c->cpu_flash_driver->write != NULL);
                                assert(r->cpu_rom.attribute == MEMORY_ATTR_READ);
                                assert(r->ppu_rom.attribute == MEMORY_ATTR_READ);
                                if(nesfile_load(LOGICAL_ERROR_PREFIX, c->romimage, r)== NG){
@@ -530,7 +544,7 @@ static int logical_check(const struct script *s, const struct st_config *c, stru
                        }
                        //flash memory capacity check
                        //¤¤¤Þ¤Î¤È¤³¤í == ¤Ë¤·¤Æ¾®¤µ¤¤ÍÆÎ̤⤽¤Î¤¦¤ÁÂбþ
-                       else if((c->mode == MODE_ROM_PROGRAM) && (size != c->cpu_flash_driver->capacity)){
+                       else if((c->mode == MODE_ROM_PROGRAM) && (size > c->cpu_flash_driver->capacity)){
                                printf("%s flash memory capacity error\n", LOGICAL_ERROR_PREFIX);
                                error += 1;
                        }
@@ -539,18 +553,8 @@ static int logical_check(const struct script *s, const struct st_config *c, stru
                        //memory size ¤Ï̤³ÎÄêÍ×ÁǤ¬Â¿¤¤¤Î¤Ç check ¤òÈ´¤¯
                        r->cpu_ram.size = s->value[0];
                        break;
-               case SCRIPT_OPCODE_CPU_COMMAND_0000:
-                       if(command_mask(MEMORY_AREA_CPU_ROM, 0, s->value[0], s->value[1], &(r->cpu_flash.command_0000)) == NG){
-                               error += 1;
-                       }
-                       break;
-               case SCRIPT_OPCODE_CPU_COMMAND_2AAA:
-                       if(command_mask(MEMORY_AREA_CPU_ROM, 0x2aaa, s->value[0], s->value[1], &(r->cpu_flash.command_2aaa)) == NG){
-                               error += 1;
-                       }
-                       break;
-               case SCRIPT_OPCODE_CPU_COMMAND_5555:
-                       if(command_mask(MEMORY_AREA_CPU_ROM, 0x5555, s->value[0], s->value[1], &(r->cpu_flash.command_5555)) == NG){
+               case SCRIPT_OPCODE_CPU_COMMAND:
+                       if(command_mask(MEMORY_AREA_CPU_ROM, s->value[0], s->value[1], s->value[2], &(r->cpu_flash)) == NG){
                                error += 1;
                        }
                        break;
@@ -561,20 +565,14 @@ static int logical_check(const struct script *s, const struct st_config *c, stru
                                printf("%s %s length error\n", LOGICAL_ERROR_PREFIX, OPSTR_PPU_ROMSIZE);
                                error += 1;
                        }
-                       }
-                       break;
-               case SCRIPT_OPCODE_PPU_COMMAND_0000:
-                       if(command_mask(MEMORY_AREA_PPU, 0, s->value[0], s->value[1], &(r->ppu_flash.command_0000)) == NG){
+                       else if((c->mode == MODE_ROM_PROGRAM) && (size > c->ppu_flash_driver->capacity)){
+                               printf("%s flash memory capacity error\n", LOGICAL_ERROR_PREFIX);
                                error += 1;
                        }
-                       break;
-               case SCRIPT_OPCODE_PPU_COMMAND_2AAA:
-                       if(command_mask(MEMORY_AREA_PPU, 0x2aaa, s->value[0], s->value[1], &(r->ppu_flash.command_2aaa)) == NG){
-                               error += 1;
                        }
                        break;
-               case SCRIPT_OPCODE_PPU_COMMAND_5555:
-                       if(command_mask(MEMORY_AREA_PPU, 0x5555, s->value[0], s->value[1], &(r->ppu_flash.command_5555)) == NG){
+               case SCRIPT_OPCODE_PPU_COMMAND:
+                       if(command_mask(MEMORY_AREA_PPU, s->value[0], s->value[1], s->value[2], &(r->ppu_flash)) == NG){
                                error += 1;
                        }
                        break;
@@ -674,20 +672,25 @@ static int logical_check(const struct script *s, const struct st_config *c, stru
                        setting = DUMP;
                        }
                        break;
-               case SCRIPT_OPCODE_PPU_RAMTEST:
+               case SCRIPT_OPCODE_PPU_RAMFIND:
                        //¥ë¡¼¥×ÆâÉô¤ËÆþ¤Ã¤Æ¤¿¤é¥¨¥é¡¼
                        if(variable_num != 0){
                                printf("%s PPU_RAMTEST must use outside loop\n", LOGICAL_ERROR_PREFIX);
                                error += 1;
                        }
                        break;
+               case SCRIPT_OPCODE_PPU_SRAMTEST:
                case SCRIPT_OPCODE_PPU_READ:{
                        const long address = s->value[0];
                        const long length = s->value[1];
                        const long end = address + length - 1;
                        assert(r->ppu_rom.attribute == MEMORY_ATTR_WRITE);
                        //length filter. 0 ¤òÍÆǧ¤¹¤ë
-                       if(!is_range(length, 0, 0x2000)){
+                       long min = 0;
+                       if(s->opcode == SCRIPT_OPCODE_PPU_SRAMTEST){
+                               min = 1;
+                       }
+                       if(!is_range(length, min, 0x2000)){
                                logical_print_illgallength(STR_REGION_PPU, length);
                                error += 1;
                        }
@@ -700,7 +703,7 @@ static int logical_check(const struct script *s, const struct st_config *c, stru
                                error += 1;
                        }
                        //dump length update
-                       if(is_region_ppurom(address)){
+                       if((s->opcode == SCRIPT_OPCODE_PPU_READ) && is_region_ppurom(address)){
                                ppu_romsize += length;
                        }
                        setting = DUMP;
@@ -727,6 +730,29 @@ static int logical_check(const struct script *s, const struct st_config *c, stru
                        setting = DUMP;
                        }
                        break;
+               case SCRIPT_OPCODE_PPU_PROGRAM:{
+                       const long address = s->value[0];
+                       const long length = s->value[1];
+                       const long end = address + length - 1;
+                       
+                       assert(r->ppu_rom.attribute == MEMORY_ATTR_READ);
+                       //length filter.
+                       if(!is_range(length, 0x80, 0x1000)){
+                               logical_print_illgallength(STR_REGION_PPU, length);
+                               error += 1;
+                       }
+                       //address filter
+                       else if(!is_region_ppurom(address)){
+                               logical_print_illgalarea(STR_REGION_PPU, address);
+                               error += 1;
+                       }else if(end >= 0x2000){
+                               logical_print_overdump(STR_REGION_PPU, address, end);
+                               error += 1;
+                       }
+                       ppu_romsize += length;
+                       setting = DUMP;
+                       }
+                       break;
                case SCRIPT_OPCODE_STEP_START:{
                        int i;
                        {
@@ -831,10 +857,7 @@ static int execute_connection_check(const struct reader_driver *d)
 
 enum {PPU_TEST_RAM, PPU_TEST_ROM};
 const u8 PPU_TEST_DATA[] = "PPU_TEST_DATA";
-#if DEBUG==0
-static 
-#endif
-int ppu_ramtest(const struct reader_driver *d)
+static int ppu_ramfind(const struct reader_driver *d)
 {
        const int length = sizeof(PPU_TEST_DATA);
        const long testaddr = 123;
@@ -869,6 +892,40 @@ int ppu_ramtest(const struct reader_driver *d)
        return PPU_TEST_ROM;
 }
 
+static int ramtest(const struct reader_driver *d, long address, long length, u8 *writedata, u8 *testdata, const long filldata)
+{
+       long i = length;
+       long a = address;
+       while(i != 0){
+               d->ppu_write(a, filldata);
+               a++;
+               i--;
+       }
+       d->ppu_read(address, length, testdata);
+       memset(writedata, filldata, length);
+       if(memcmp(writedata, testdata, length) == 0){
+               return 0;
+       }
+       return 1;
+}
+
+static const long SRAMTESTDATA[] = {0xff, 0xaa, 0x55, 0x00};
+static int ppu_sramtest(const struct reader_driver *d, long address, long length)
+{
+       u8 *writedata, *testdata;
+       int error = 0;
+       int i;
+       testdata = malloc(length);
+       writedata = malloc(length);
+       for(i = 0; i < sizeof(SRAMTESTDATA) / sizeof(long); i++){
+               const long filldata = SRAMTESTDATA[i];
+               error += ramtest(d, address, length, testdata, writedata, filldata);
+       }
+       free(testdata);
+       free(writedata);
+       return error;
+}
+
 static void readbuffer_print(const struct memory *m, long length)
 {
        if(length >= 0x10){
@@ -916,8 +973,28 @@ static void read_result_print(const struct memory *m, long length)
        fflush(stdout);
 }
 
+static void execute_program_begin(const struct memory *m)
+{
+       if(0){ //DEBUG==1){
+               return;
+       }
+       printf("writing %s area 0x%06x ... ", m->name, m->offset);
+       fflush(stdout);
+}
+
+//memcmp ¤ÎÌá¤êÃͤ¬Æþ¤ë¤Î¤Ç 0 ¤¬Àµ¾ï
+static void execute_program_finish(int result)
+{
+       const char *str;
+       str = "NG";
+       if(result == 0){
+               str = "OK";
+       }
+       printf("%s\n", str);
+       fflush(stdout);
+}
 const char EXECUTE_ERROR_PREFIX[] = "execute error:";
-static void execute_cpu_ramrw(const struct reader_driver *d, const struct memory *ram, int mode, long address, long length)
+static void execute_cpu_ramrw(const struct reader_driver *d, const struct memory *ram, int mode, long address, long length, long wait)
 {
        if(mode == MODE_RAM_WRITE){
                const u8 *writedata;
@@ -925,7 +1002,7 @@ static void execute_cpu_ramrw(const struct reader_driver *d, const struct memory
                long l = length;
                writedata = ram->data;
                while(l != 0){
-                       d->cpu_6502_write(a++, *writedata);
+                       d->cpu_6502_write(a++, *writedata, wait);
                        writedata += 1;
                        l--;
                }
@@ -961,6 +1038,21 @@ static int execute(const struct script *s, const struct st_config *c, struct rom
                d->open_or_close(READER_CLOSE);
                return NG;
        }
+       u8 *program_compare;
+       program_compare = NULL;
+       if(c->mode == MODE_ROM_PROGRAM){
+               //device ¤è¤Ã¤Æ¤Ï erase
+               c->cpu_flash_driver->init(&(r->cpu_flash));
+               if(r->ppu_rom.size != 0){
+                       c->ppu_flash_driver->init(&(r->ppu_flash));
+               }
+               printf("flashmemory/SRAM program mode. you can abort programming Ctrl+C\n");
+               int size = r->cpu_rom.size;
+               if(size < r->ppu_rom.size){
+                       size = r->ppu_rom.size;
+               }
+               program_compare = malloc(size);
+       }
        struct memory cpu_rom, ppu_rom, cpu_ram;
        cpu_rom = r->cpu_rom;
        ppu_rom = r->ppu_rom;
@@ -983,36 +1075,58 @@ static int execute(const struct script *s, const struct st_config *c, struct rom
                case SCRIPT_OPCODE_CPU_WRITE:{
                        long data;
                        expression_calc(&s->expression, &data);
-                       d->cpu_6502_write(s->value[0], data);
+                       d->cpu_6502_write(s->value[0], data, c->write_wait);
                        }
                        break;
                case SCRIPT_OPCODE_CPU_RAMRW:{
                        const long length = s->value[1];
-                       execute_cpu_ramrw(d, &cpu_ram, c->mode, s->value[0], length);
+                       execute_cpu_ramrw(d, &cpu_ram, c->mode, s->value[0], length, c->write_wait);
                        read_result_print(&cpu_ram, length);
                        cpu_ram.data += length;
                        cpu_ram.offset += length;
                        }
                        break;
                case SCRIPT_OPCODE_CPU_PROGRAM:{
+                       if(c->cpu_flash_driver->id_device == FLASH_ID_DEVICE_DUMMY){
+                               break;
+                       }
                        const long address = s->value[0];
                        const long length = s->value[1];
+                       execute_program_begin(&cpu_rom);
                        c->cpu_flash_driver->write(
                                &(r->cpu_flash),
                                address, length,
-                               cpu_rom.data
+                               &cpu_rom
                        );
+                       d->cpu_read(address, length, program_compare);
+                       const int result = memcmp(program_compare, cpu_rom.data, length);
+                       execute_program_finish(result);
                        cpu_rom.data += length;
                        cpu_rom.offset += length;
+                       
+                       if((DEBUG==0) && (result != 0)){
+                               end = 0;
+                       }
                        }
                        break;
-               case SCRIPT_OPCODE_PPU_RAMTEST:
-                       if(ppu_ramtest(d) == PPU_TEST_RAM){
-                               printf("PPU_RAMTEST: charcter RAM found\n");
+               case SCRIPT_OPCODE_PPU_RAMFIND:
+                       if(ppu_ramfind(d) == PPU_TEST_RAM){
+                               printf("PPU_RAMFIND: charcter RAM found\n");
                                r->ppu_rom.size = 0;
                                end = 0;
                        }
                        break;
+               case SCRIPT_OPCODE_PPU_SRAMTEST:{
+                       const long address = s->value[0];
+                       const long length = s->value[1];
+                       printf("PPU_SRAMTEST: 0x%06x-0x%06x ", (int)ppu_rom.offset, (int) (ppu_rom.offset + length) - 1);
+                       if(ppu_sramtest(d, address, length) == 0){
+                               printf("ok\n");
+                       }else{
+                               printf("ng\n");
+                               //end = 0;
+                       }
+                       }break;
                case SCRIPT_OPCODE_PPU_READ:{
                        const long address = s->value[0];
                        const long length = s->value[1];
@@ -1036,6 +1150,29 @@ static int execute(const struct script *s, const struct st_config *c, struct rom
                                d->ppu_write(s->value[0], data);
                        }
                        break;
+               case SCRIPT_OPCODE_PPU_PROGRAM:{
+                       if(c->ppu_flash_driver->id_device == FLASH_ID_DEVICE_DUMMY){
+                               break;
+                       }
+                       const long address = s->value[0];
+                       const long length = s->value[1];
+                       execute_program_begin(&ppu_rom);
+                       c->ppu_flash_driver->write(
+                               &(r->ppu_flash),
+                               address, length,
+                               &ppu_rom
+                       );
+                       d->ppu_read(address, length, program_compare);
+                       const int result = memcmp(program_compare, ppu_rom.data, length);
+                       execute_program_finish(result);
+                       ppu_rom.data += length;
+                       ppu_rom.offset += length;
+                       
+                       if((DEBUG==0) && (result != 0)){
+                               end = 0;
+                       }
+                       }
+                       break;
                case SCRIPT_OPCODE_STEP_START:
                        //¥ë¡¼¥×¤ÎÌá¤êÀè¤Ï¤³¤ÎÌ¿Îá¤Î¼¡¤Ê¤Î¤Ç &s[1]
                        step_new(s->variable, s->value[1], s->value[2], s->value[3], &s[1]);
@@ -1054,6 +1191,9 @@ static int execute(const struct script *s, const struct st_config *c, struct rom
                }
        }
        d->open_or_close(READER_CLOSE);
+       if(program_compare != NULL){
+               free(program_compare);
+       }
        return OK;
 }
 
@@ -1099,13 +1239,13 @@ void script_load(const struct st_config *c)
                        .size = 0, .offset = 0,
                        .data = NULL,
                        .attribute = MEMORY_ATTR_NOTUSE,
-                       .name = STR_REGION_CPU
+                       .name = "program ROM"
                },
                .ppu_rom = {
                        .size = 0, .offset = 0,
                        .data = NULL,
                        .attribute = MEMORY_ATTR_NOTUSE,
-                       .name = STR_REGION_PPU
+                       .name = "charcter ROM"
                },
                .cpu_ram = {
                        .size = 0, .offset = 0,
@@ -1118,6 +1258,7 @@ void script_load(const struct st_config *c)
                        .command_0000 = 0,
                        .command_2aaa = 0,
                        .command_5555 = 0,
+                       .pagesize = c->cpu_flash_driver->pagesize,
                        .flash_write = c->reader->cpu_flash_write,
                        .read = c->reader->cpu_read
                },
@@ -1125,6 +1266,7 @@ void script_load(const struct st_config *c)
                        .command_0000 = 0,
                        .command_2aaa = 0,
                        .command_5555 = 0,
+                       .pagesize = c->ppu_flash_driver->pagesize,
                        .flash_write = c->reader->ppu_write,
                        .read = c->reader->ppu_read
                },