2 famicom ROM cartridge utility - unagi
5 Copyright (C) 2008 ±·³«È¯¶¨Æ±Áȹç
7 This library is free software; you can redistribute it and/or
8 modify it under the terms of the GNU Lesser General Public
9 License as published by the Free Software Foundation; either
10 version 2.1 of the License any later version.
12 This library is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
17 You should have received a copy of the GNU Lesser General Public
18 License along with this library; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 * ÊÑ¿ô´ÉÍý¤Î¥°¥í¡¼¥Ð¥ëÃͤò¡¢logical_test(), excute() ¥í¡¼¥«¥ë¤Ë¤·¤¿¤¤
30 #include "reader_master.h"
44 CPU_WRITE address data -> ÊÑ¿ôŸ³«+±é»»»Ò»ÈÍѲÄǽ
46 STEP_START variable start end step -> for(i=start;i<end;i+=step)
53 struct variable_manage{
57 const struct script *Continue;
62 VARIABLE_MAX = STEP_MAX
65 static const struct variable_manage VARIABLE_INIT = {
67 .start = 0, .end = 0, .step = 0,
71 static struct variable_manage variable_bank[VARIABLE_MAX];
72 static int variable_num = 0;
74 static void variable_init_single(int num)
76 memcpy(&variable_bank[num], &VARIABLE_INIT, sizeof(struct variable_manage));
79 static void variable_init_all(void)
83 for(i = 0; i < VARIABLE_MAX; i++){
84 variable_init_single(i);
88 static int variable_get(char name, long *val)
91 struct variable_manage *v;
93 for(i = 0; i < variable_num; i++){
104 static int expression_calc(const struct st_expression *e, long *val)
107 if(e->left.type == EXPRESSION_TYPE_VARIABLE){
108 if(variable_get(e->left.variable, &left) == NG){
112 left = e->left.value;
114 if(e->operator == OPERATOR_NONE){
118 if(e->right.type == EXPRESSION_TYPE_VARIABLE){
119 if(variable_get(e->right.variable, &right) == NG){
123 right = e->right.value;
129 case OPERATOR_SHIFT_LEFT:
130 *val = left >> right;
133 case OPERATOR_SHIFT_RIGHT:
134 *val = left << right;
150 static int step_new(char name, long start, long end, long step, const struct script *Continue)
152 if(variable_num >= VARIABLE_MAX){
153 return NG; //ÊÑ¿ôÄêµÁ¤¬Â¿¤¹¤®
155 struct variable_manage *v;
158 for(i = 0; i < variable_num; i++){
160 return NG; //ÊÑ¿ô̾½ÅÊ£
171 v->Continue = Continue;
176 static const struct script *step_end(const struct script *Break)
178 //¸½ºß¤Î¥ë¡¼¥×¤ÎÂоÝÊÑ¿ô¤òÆÀ¤ë
179 struct variable_manage *v;
181 v += (variable_num - 1);
187 //¥ë¡¼¥×¤¬½ª¤ï¤Ã¤¿¤Î¤Ç¤½¤ÎÊÑ¿ô¤òÇË´þ¤¹¤ë
188 variable_init_single(variable_num - 1);
193 static int syntax_check_expression(char **word, int word_num, struct st_expression *e)
199 if(value_get(word[0], &(e->left.value)) == OK){
200 e->left.type = EXPRESSION_TYPE_VALUE;
202 e->left.type = EXPRESSION_TYPE_VARIABLE;
203 e->left.variable = word[0][0];
207 e->operator = OPERATOR_NONE;
211 e->operator = operator_get(word[1]);
212 if(e->operator == OPERATOR_ERROR){
220 if(value_get(word[2], &(e->right.value)) == OK){
221 e->right.type = EXPRESSION_TYPE_VALUE;
223 e->right.type = EXPRESSION_TYPE_VARIABLE;
224 e->right.variable = word[2][0];
229 static const char SYNTAX_ERROR_PREFIX[] = "syntax error:";
232 return: error count, ¤³¤³¤Ç¤Ï 0 or 1
234 static int syntax_check_phase(char **word, int word_num, struct script *s, const int mode)
236 int i = sizeof(SCRIPT_SYNTAX) / sizeof(SCRIPT_SYNTAX[0]);
237 const struct script_syntax *syntax;
238 syntax = SCRIPT_SYNTAX;
240 if(strcmp(syntax->name, word[0]) == 0){
243 s->opcode = syntax->script_opcode;
244 if((mode & syntax->permittion) == 0){
245 printf("%s opcode %s not allowed on current mode\n", SYNTAX_ERROR_PREFIX, syntax->name);
250 switch(syntax->compare){
251 case SYNTAX_COMPARE_EQ:
252 compare = (syntax->argc == (word_num - 1));
254 case SYNTAX_COMPARE_GT:
255 compare = (syntax->argc <= (word_num - 1));
259 printf("%s parameter number not much %s\n", SYNTAX_ERROR_PREFIX, word[0]);
263 for(j = 0; j < syntax->argc; j++){
264 switch(syntax->argv_type[j]){
265 case SYNTAX_ARGVTYPE_NULL:
266 printf("%s ARGV_NULL select\n", SYNTAX_ERROR_PREFIX);
268 case SYNTAX_ARGVTYPE_VALUE:
269 if(value_get(word[j + 1], &(s->value[j])) == NG){
270 printf("%s value error %s %s\n", SYNTAX_ERROR_PREFIX, word[0], word[j+1]);
274 case SYNTAX_ARGVTYPE_HV:
275 switch(word[j + 1][0]){
278 s->value[j] = MIRROR_HORIZONAL;
282 s->value[j] = MIRROR_VERTICAL;
286 s->value[j] = MIRROR_PROGRAMABLE;
289 printf("%s unknown scroll mirroring type %s\n", SYNTAX_ERROR_PREFIX, word[j+1]);
293 case SYNTAX_ARGVTYPE_EXPRESSION:
294 s->value[j] = VALUE_EXPRESSION;
295 //Ì¿Îá̾¤Îñ¸ì¤Èñ¸ì¿ô¤ò½ü³°¤·¤ÆÅϤ¹
296 if(syntax_check_expression(&word[j+1], word_num - 2, &s->expression) == NG){
297 printf("%s expression error\n", SYNTAX_ERROR_PREFIX);
300 //²ÄÊѤ˰ú¿ô¤ò¼è¤ë¤Î¤Ç¤³¤³¤Ç½ª¤ï¤ê
302 case SYNTAX_ARGVTYPE_VARIABLE:{
303 const char v = word[j+1][0];
304 if((v >= 'a' && v <= 'z') || (v >= 'A' && v <= 'Z')){
305 s->value[j] = VALUE_VARIABLE;
308 printf("%s variable must use [A-Za-z] %s\n", SYNTAX_ERROR_PREFIX, word[j+1]);
314 //opcode found and ÆþÎÏʸ»ú¼ïÀµ¾ï
320 printf("%s unknown opcode %s\n", SYNTAX_ERROR_PREFIX, word[0]);
327 static int syntax_check(char **text, int text_num, struct script *s, int mode)
331 mode = 1<< mode; //permittion ¤Ï bitflag ¤Ê¤Î¤Ç¤³¤³¤ÇÊÑ´¹¤¹¤ë
333 for(i = 0; i < text_num; i++){
334 char *word[TEXT_MAXWORD];
335 const int n = word_load(text[i], word);
336 if(word[0][0] == '#'){
337 s->opcode = SCRIPT_OPCODE_COMMENT;
339 error += syntax_check_phase(word, n, s, mode);
347 logical_check() ÍÑ¥µ¥Ö´Ø¿ô¤È¥Ç¡¼¥¿
349 static const char LOGICAL_ERROR_PREFIX[] = "logical error:";
351 static inline void logical_print_illgalarea(const char *area, long address)
353 printf("%s illgal %s area $%06x\n", LOGICAL_ERROR_PREFIX, area, (int) address);
356 static inline void logical_print_illgallength(const char *area, long length)
358 printf("%s illgal %s length $%04x\n", LOGICAL_ERROR_PREFIX, area, (int) length);
361 static inline void logical_print_overdump(const char *area, long start, long end)
363 printf("%s %s area over dump $%06x-$%06x\n", LOGICAL_ERROR_PREFIX, area, (int)start ,(int)end);
366 static inline void logical_print_access(const char *area, const char *rw, long addr, long len)
368 printf("%s %s $%04x $%02x\n", area, rw, (int) addr, (int) len);
371 static inline void logical_print_byteerror(const char *area, long data)
373 printf("%s write data byte range over, %s $%x\n", LOGICAL_ERROR_PREFIX, area, (int) data);
376 static int dump_length_conform(const char *name, long logicallength, long configlength)
378 if(configlength != logicallength){
379 printf("%s %s dump length error\n", LOGICAL_ERROR_PREFIX, name);
380 printf("%s: 0x%06x, dump length: 0x%06x\n", name, (int) configlength, (int) logicallength);
385 static inline int is_region_cpurom(long address)
387 return (address >= 0x8000) && (address < 0x10000);
390 static inline int is_region_cpuram(long address)
392 return (address >= 0x6000) && (address < 0x8000);
395 static inline int is_region_ppurom(long address)
397 return (address >= 0) && (address < 0x2000);
400 static inline int is_data_byte(long data)
402 return (data >= 0) && (data < 0x100);
405 //¤³¤ì¤À¤± is ·Ï¤Ç <= ±é»»»Ò¤ò»ÈÍѤ·¤Æ¤¤¤ë¤Î¤ÇÃí°Õ
406 static inline int is_range(long data, long start, long end)
408 return (data >= start) && (data <= end);
410 static const char STR_REGION_CPU[] = "cpu";
411 static const char STR_REGION_PPU[] = "ppu";
412 static const char STR_ACCESS_READ[] = "read";
413 static const char STR_ACCESS_WRITE[] = "write";
418 static int command_mask(const int region, const long address, const long offset, long size, struct flash_order *f)
420 const char *str_region = STR_REGION_CPU;
421 if(region == MEMORY_AREA_PPU){
422 str_region = STR_REGION_PPU;
425 case MEMORY_AREA_CPU_ROM:
427 case 0x8000: case 0xa000: case 0xc000:
430 printf("%s %s_COMMAND area offset error\n", LOGICAL_ERROR_PREFIX, str_region);
434 case 0x2000: case 0x4000: case 0x8000:
437 printf("%s %s_COMMAND area mask error\n", LOGICAL_ERROR_PREFIX, str_region);
441 case MEMORY_AREA_PPU:
443 case 0x0000: case 0x0400: case 0x0800: case 0x0c00:
444 case 0x1000: case 0x1400: case 0x1800: case 0x1c00:
447 printf("%s %s_COMMAND area offset error\n", LOGICAL_ERROR_PREFIX, str_region);
451 case 0x0400: case 0x0800: case 0x1000: case 0x2000:
454 printf("%s %s_COMMAND area mask error\n", LOGICAL_ERROR_PREFIX, str_region);
459 assert(0); //unknown memory area
462 const long mask = size - 1;
463 const long data = (address & mask) | offset;
466 f->command_0000 = data;
468 case 0x2aaa: case 0x02aa:
469 f->command_2aaa = data;
471 case 0x5555: case 0x0555:
472 f->command_5555 = data;
475 printf("%s %s_COMMAND unknown commnand address\n", LOGICAL_ERROR_PREFIX, str_region);
481 static int logical_check(const struct script *s, const struct st_config *c, struct romimage *r)
483 long cpu_romsize = 0, cpu_ramsize = 0, ppu_romsize = 0;
484 int imagesize = 0; //for write or program mode
485 int setting = SETTING;
489 while(s->opcode != SCRIPT_OPCODE_DUMP_END){
490 //printf("opcode exec %s\n", SCRIPT_SYNTAX[s->opcode].name);
491 if((setting == DUMP) && (s->opcode < SCRIPT_OPCODE_DUMP_START)){
492 printf("%s config script include DUMPSTART area\n", LOGICAL_ERROR_PREFIX);
496 //romimage open for write or program mode
497 if((imagesize == 0) && (setting == DUMP)){
500 assert(r->cpu_ram.attribute == MEMORY_ATTR_READ);
501 r->cpu_ram.data = buf_load_full(c->ramimage, &imagesize);
502 if(r->cpu_ram.data == NULL){
503 printf("%s RAM image open error\n", LOGICAL_ERROR_PREFIX);
506 }else if(r->cpu_ram.size != imagesize){
507 printf("%s RAM image size is not same\n", LOGICAL_ERROR_PREFIX);
508 free(r->cpu_ram.data);
509 r->cpu_ram.data = NULL;
514 case MODE_ROM_PROGRAM:
515 assert(c->cpu_flash_driver->write != NULL);
516 assert(r->cpu_rom.attribute == MEMORY_ATTR_READ);
517 assert(r->ppu_rom.attribute == MEMORY_ATTR_READ);
518 if(nesfile_load(LOGICAL_ERROR_PREFIX, c->romimage, r)== NG){
530 case SCRIPT_OPCODE_COMMENT:
532 case SCRIPT_OPCODE_MAPPER:
533 r->mappernum = s->value[0];
535 case SCRIPT_OPCODE_MIRROR:
536 r->mirror = s->value[0];
538 case SCRIPT_OPCODE_CPU_ROMSIZE:{
539 const long size = s->value[0];
540 r->cpu_rom.size = size;
541 if(memorysize_check(size, MEMORY_AREA_CPU_ROM)){
542 printf("%s %s length error\n", LOGICAL_ERROR_PREFIX, OPSTR_CPU_ROMSIZE);
545 //flash memory capacity check
546 //¤¤¤Þ¤Î¤È¤³¤í == ¤Ë¤·¤Æ¾®¤µ¤¤ÍÆÎ̤⤽¤Î¤¦¤ÁÂбþ
547 else if((c->mode == MODE_ROM_PROGRAM) && (size > c->cpu_flash_driver->capacity)){
548 printf("%s flash memory capacity error\n", LOGICAL_ERROR_PREFIX);
552 case SCRIPT_OPCODE_CPU_RAMSIZE:
553 //memory size ¤Ï̤³ÎÄêÍ×ÁǤ¬Â¿¤¤¤Î¤Ç check ¤òÈ´¤¯
554 r->cpu_ram.size = s->value[0];
556 case SCRIPT_OPCODE_CPU_COMMAND:
557 if(command_mask(MEMORY_AREA_CPU_ROM, s->value[0], s->value[1], s->value[2], &(r->cpu_flash)) == NG){
561 case SCRIPT_OPCODE_PPU_ROMSIZE:{
562 const long size = s->value[0];
563 r->ppu_rom.size = size;
564 if(memorysize_check(size, MEMORY_AREA_PPU)){
565 printf("%s %s length error\n", LOGICAL_ERROR_PREFIX, OPSTR_PPU_ROMSIZE);
568 else if((c->mode == MODE_ROM_PROGRAM) && (size > c->ppu_flash_driver->capacity)){
569 printf("%s flash memory capacity error\n", LOGICAL_ERROR_PREFIX);
574 case SCRIPT_OPCODE_PPU_COMMAND:
575 if(command_mask(MEMORY_AREA_PPU, s->value[0], s->value[1], s->value[2], &(r->ppu_flash)) == NG){
579 case SCRIPT_OPCODE_DUMP_START:
582 case SCRIPT_OPCODE_CPU_READ:{
583 const long address = s->value[0];
584 const long length = s->value[1];
585 const long end = address + length - 1;
587 assert(r->cpu_rom.attribute == MEMORY_ATTR_WRITE);
588 //length filter. 0 ¤Ï¤À¤á
589 if(!is_range(length, 1, 0x4000)){
590 logical_print_illgallength(STR_REGION_CPU, length);
594 else if(!is_region_cpurom(address)){
595 logical_print_illgalarea(STR_REGION_CPU, address);
597 }else if(end >= 0x10000){
598 logical_print_overdump(STR_REGION_CPU, address, end);
601 cpu_romsize += length;
605 case SCRIPT_OPCODE_CPU_WRITE:{
606 const long address = s->value[0];
608 if(expression_calc(&s->expression, &data) == NG){
609 printf("%s expression calc error\n", LOGICAL_ERROR_PREFIX);
612 if(address < 0x5000 || address >= 0x10000){
613 logical_print_illgalarea(STR_REGION_CPU, address);
615 }else if(!is_data_byte(data)){
616 logical_print_byteerror(STR_REGION_CPU, data);
622 case SCRIPT_OPCODE_CPU_RAMRW:{
623 const long address = s->value[0];
624 const long length = s->value[1];
625 const long end = address + length - 1;
628 assert(r->cpu_ram.attribute == MEMORY_ATTR_WRITE);
631 assert(r->cpu_ram.attribute = MEMORY_ATTR_READ);
634 //length filter. 0 ¤Ï¤À¤á
635 if(!is_range(length, 1, 0x2000)){
636 logical_print_illgallength(STR_REGION_CPU, length);
640 else if(address < 0x6000 || address >= 0x8000){
641 logical_print_illgalarea(STR_REGION_CPU, address);
643 }else if(end >= 0x8000){
644 logical_print_overdump(STR_REGION_CPU, address, end);
647 cpu_ramsize += length;
651 case SCRIPT_OPCODE_CPU_PROGRAM:{
652 const long address = s->value[0];
653 const long length = s->value[1];
654 const long end = address + length - 1;
656 assert(r->cpu_rom.attribute == MEMORY_ATTR_READ);
657 assert(r->ppu_rom.attribute == MEMORY_ATTR_READ);
659 if(!is_range(length, 0x80, 0x2000)){
660 logical_print_illgallength(STR_REGION_CPU, length);
664 else if(!is_region_cpurom(address)){
665 logical_print_illgalarea(STR_REGION_CPU, address);
667 }else if(end >= 0x10000){
668 logical_print_overdump(STR_REGION_CPU, address, end);
671 cpu_romsize += length;
675 case SCRIPT_OPCODE_PPU_RAMFIND:
676 //¥ë¡¼¥×ÆâÉô¤ËÆþ¤Ã¤Æ¤¿¤é¥¨¥é¡¼
677 if(variable_num != 0){
678 printf("%s PPU_RAMTEST must use outside loop\n", LOGICAL_ERROR_PREFIX);
682 case SCRIPT_OPCODE_PPU_SRAMTEST:
683 case SCRIPT_OPCODE_PPU_READ:{
684 const long address = s->value[0];
685 const long length = s->value[1];
686 const long end = address + length - 1;
687 assert(r->ppu_rom.attribute == MEMORY_ATTR_WRITE);
688 //length filter. 0 ¤òÍÆǧ¤¹¤ë
690 if(s->opcode == SCRIPT_OPCODE_PPU_SRAMTEST){
693 if(!is_range(length, min, 0x2000)){
694 logical_print_illgallength(STR_REGION_PPU, length);
698 else if(!is_region_ppurom(address)){
699 logical_print_illgalarea(STR_REGION_PPU, address);
701 }else if (end >= 0x2000){
702 logical_print_overdump(STR_REGION_PPU, address, end);
706 if((s->opcode == SCRIPT_OPCODE_PPU_READ) && is_region_ppurom(address)){
707 ppu_romsize += length;
712 case SCRIPT_OPCODE_PPU_WRITE:{
716 const long address = s->value[0];
718 if(expression_calc(&s->expression, &data) == NG){
719 printf("%s expression calc error\n", LOGICAL_ERROR_PREFIX);
723 if(!is_region_ppurom(address)){
724 logical_print_illgalarea(STR_REGION_PPU, address);
726 }else if(!is_data_byte(data)){
727 logical_print_byteerror(STR_REGION_PPU, data);
733 case SCRIPT_OPCODE_PPU_PROGRAM:{
734 const long address = s->value[0];
735 const long length = s->value[1];
736 const long end = address + length - 1;
738 assert(r->ppu_rom.attribute == MEMORY_ATTR_READ);
740 if(!is_range(length, 0x80, 0x2000)){
741 logical_print_illgallength(STR_REGION_PPU, length);
745 else if(!is_region_ppurom(address)){
746 logical_print_illgalarea(STR_REGION_PPU, address);
748 }else if(end >= 0x2000){
749 logical_print_overdump(STR_REGION_PPU, address, end);
752 ppu_romsize += length;
756 case SCRIPT_OPCODE_STEP_START:{
759 const int v = s->value[1];
760 if((v < 0) || (v > 0xff)){
761 printf("%s step start must 0-0xff 0x%x\n", LOGICAL_ERROR_PREFIX, v);
765 for(i = 2; i <4; i++){
766 const int v = s->value[i];
767 if((v < 1) || (v > 0x100)){
768 printf("%s end or next must 1-0x100 0x%x\n", LOGICAL_ERROR_PREFIX, v);
772 //¥ë¡¼¥×¤ÎÌá¤êÀè¤Ï¤³¤ÎÌ¿Îá¤Î¼¡¤Ê¤Î¤Ç s[1]
773 if(step_new(s->variable, s->value[1], s->value[2], s->value[3], &s[1]) == NG){
774 printf("%s step loop too much\n", LOGICAL_ERROR_PREFIX);
780 case SCRIPT_OPCODE_DUMP_END:
787 if(s->opcode == SCRIPT_OPCODE_STEP_END){
788 if(variable_num == 0){
789 printf("%s loop closed, missing STEP_START\n", LOGICAL_ERROR_PREFIX);
800 if(variable_num != 0){
801 printf("%s loop opened, missing STEP_END\n", LOGICAL_ERROR_PREFIX);
804 //dump length conform
805 error += dump_length_conform(OPSTR_CPU_ROMSIZE, cpu_romsize, r->cpu_rom.size);
806 error += dump_length_conform(OPSTR_CPU_RAMSIZE, cpu_ramsize, r->cpu_ram.size);
807 error += dump_length_conform(OPSTR_PPU_ROMSIZE, ppu_romsize, r->ppu_rom.size);
809 //command line config override
810 if(c->mirror != CONFIG_OVERRIDE_UNDEF){
811 r->mirror = c->mirror;
813 if(c->backupram != CONFIG_OVERRIDE_UNDEF){
816 if(c->mapper != CONFIG_OVERRIDE_UNDEF){
817 //program mode ¤Ç mapper Êѹ¹¤òËɤ°
818 assert(c->mode == MODE_ROM_DUMP);
819 r->mappernum = c->mapper;
821 if(c->syntaxtest == 1){
823 printf("syntax ok!\n");
831 execute() ÍÑ¥µ¥Ö´Ø¿ô¤È¥Ç¡¼¥¿
833 static int execute_connection_check(const struct reader_driver *d)
836 const int testsize = 0x80;
839 master = malloc(testsize);
840 reload = malloc(testsize);
842 d->cpu_read(0xfee0, testsize, master);
844 while(testcount != 0){
845 d->cpu_read(0xfee0, testsize, reload);
846 if(memcmp(master, reload, testsize) != 0){
858 enum {PPU_TEST_RAM, PPU_TEST_ROM};
859 const u8 PPU_TEST_DATA[] = "PPU_TEST_DATA";
860 static int ppu_ramfind(const struct reader_driver *d)
862 const int length = sizeof(PPU_TEST_DATA);
863 const long testaddr = 123;
864 //ppu ram data fill 0
867 long address = testaddr;
869 d->ppu_write(address++, 0);
874 //ppu test data write
878 long address = testaddr;
879 data = PPU_TEST_DATA;
881 d->ppu_write(address++, (long) *data);
887 u8 writedata[length];
888 d->ppu_read(testaddr, length, writedata);
889 if(memcmp(writedata, PPU_TEST_DATA, length) == 0){
895 static int ramtest(const struct reader_driver *d, long address, long length, u8 *writedata, u8 *testdata, const long filldata)
900 d->ppu_write(a, filldata);
904 d->ppu_read(address, length, testdata);
905 memset(writedata, filldata, length);
906 if(memcmp(writedata, testdata, length) == 0){
912 static const long SRAMTESTDATA[] = {0xff, 0xaa, 0x55, 0x00};
913 static int ppu_sramtest(const struct reader_driver *d, long address, long length)
915 u8 *writedata, *testdata;
918 testdata = malloc(length);
919 writedata = malloc(length);
920 for(i = 0; i < sizeof(SRAMTESTDATA) / sizeof(long); i++){
921 const long filldata = SRAMTESTDATA[i];
922 error += ramtest(d, address, length, testdata, writedata, filldata);
929 static void readbuffer_print(const struct memory *m, long length)
934 printf("%s 0x%05x:", m->name, m->offset);
940 switch(offset & 0xf){
951 printf("%02x%c", (int) *data, safix);
958 static void checksum_print(const u8 *data, long length)
966 printf(" 0x%06x\n", sum);
969 static void read_result_print(const struct memory *m, long length)
971 readbuffer_print(m, length);
972 checksum_print(m->data, length);
976 const char EXECUTE_ERROR_PREFIX[] = "execute error:";
977 static void execute_cpu_ramrw(const struct reader_driver *d, const struct memory *ram, int mode, long address, long length)
979 if(mode == MODE_RAM_WRITE){
983 writedata = ram->data;
985 d->cpu_6502_write(a++, *writedata);
990 compare = malloc(length);
991 d->cpu_read(address, length, compare);
992 if(memcmp(ram->data, compare, length) == 0){
993 printf("RAM data write success\n");
995 printf("RAM data write failed\n");
999 d->cpu_read(address, length, ram->data);
1003 static int execute(const struct script *s, const struct st_config *c, struct romimage *r)
1005 const struct reader_driver *const d = c->reader;
1006 switch(d->open_or_close(READER_OPEN)){
1011 printf("%s driver open error\n", EXECUTE_ERROR_PREFIX);
1016 if(execute_connection_check(d) == NG){
1017 printf("%s maybe connection error\n", EXECUTE_ERROR_PREFIX);
1018 d->open_or_close(READER_CLOSE);
1021 if(c->mode == MODE_ROM_PROGRAM){
1022 //device ¤è¤Ã¤Æ¤Ï erase
1023 c->cpu_flash_driver->init(&(r->cpu_flash));
1024 if(r->ppu_rom.size != 0){
1025 c->ppu_flash_driver->init(&(r->ppu_flash));
1028 struct memory cpu_rom, ppu_rom, cpu_ram;
1029 cpu_rom = r->cpu_rom;
1030 ppu_rom = r->ppu_rom;
1031 cpu_ram = r->cpu_ram;
1033 variable_init_all();
1034 while(s->opcode != SCRIPT_OPCODE_DUMP_END){
1037 case SCRIPT_OPCODE_CPU_READ:{
1039 const long address = s->value[0];
1040 const long length = s->value[1];
1042 d->cpu_read(address, length, m->data);
1043 read_result_print(m, length);
1045 m->offset += length;
1047 case SCRIPT_OPCODE_CPU_WRITE:{
1049 expression_calc(&s->expression, &data);
1050 d->cpu_6502_write(s->value[0], data);
1053 case SCRIPT_OPCODE_CPU_RAMRW:{
1054 const long length = s->value[1];
1055 execute_cpu_ramrw(d, &cpu_ram, c->mode, s->value[0], length);
1056 read_result_print(&cpu_ram, length);
1057 cpu_ram.data += length;
1058 cpu_ram.offset += length;
1061 case SCRIPT_OPCODE_CPU_PROGRAM:{
1062 const long address = s->value[0];
1063 const long length = s->value[1];
1064 c->cpu_flash_driver->write(
1069 cpu_rom.data += length;
1070 cpu_rom.offset += length;
1073 case SCRIPT_OPCODE_PPU_RAMFIND:
1074 if(ppu_ramfind(d) == PPU_TEST_RAM){
1075 printf("PPU_RAMFIND: charcter RAM found\n");
1076 r->ppu_rom.size = 0;
1080 case SCRIPT_OPCODE_PPU_SRAMTEST:{
1081 const long address = s->value[0];
1082 const long length = s->value[1];
1083 if(ppu_sramtest(d, address, length) == 0){
1084 printf("PPU_SRAMTEST: ok\n");
1086 printf("PPU_SRAMTEST: ng\n");
1090 case SCRIPT_OPCODE_PPU_READ:{
1091 const long address = s->value[0];
1092 const long length = s->value[1];
1094 /*for mmc2,4 protect.
1095 ¤³¤Î¤È¤¤Ï1byteÆɤ߹þ¤ó¤Ç¡¢¤½¤ÎÆâÍƤϥХåե¡¤Ë¤¤¤ì¤Ê¤¤*/
1097 d->ppu_read(address, 1, &dummy);
1099 d->ppu_read(address, length, ppu_rom.data);
1100 read_result_print(&ppu_rom, length);
1102 ppu_rom.data += length;
1103 ppu_rom.offset += length;
1106 case SCRIPT_OPCODE_PPU_WRITE:
1109 expression_calc(&s->expression, &data);
1110 d->ppu_write(s->value[0], data);
1113 case SCRIPT_OPCODE_PPU_PROGRAM:{
1114 const long address = s->value[0];
1115 const long length = s->value[1];
1116 c->ppu_flash_driver->write(
1121 ppu_rom.data += length;
1122 ppu_rom.offset += length;
1125 case SCRIPT_OPCODE_STEP_START:
1126 //¥ë¡¼¥×¤ÎÌá¤êÀè¤Ï¤³¤ÎÌ¿Îá¤Î¼¡¤Ê¤Î¤Ç &s[1]
1127 step_new(s->variable, s->value[1], s->value[2], s->value[3], &s[1]);
1129 case SCRIPT_OPCODE_DUMP_END:
1136 if(s->opcode == SCRIPT_OPCODE_STEP_END){
1142 d->open_or_close(READER_CLOSE);
1146 void script_load(const struct st_config *c)
1153 buf = buf_load_full(c->script, &scriptsize);
1155 printf("scriptfile open error\n");
1159 text = malloc(sizeof(char*) * TEXT_MAXLINE);
1160 const int text_num = text_load(buf, scriptsize, text);
1162 printf("script line too much\n");
1167 s = malloc(sizeof(struct script) * (text_num + 1));
1168 //logical_check, execute ¶¦¤Ë s->opcode ¤¬ DUMP_END ¤Ë¤Ê¤ë¤Þ¤Ç³¤±¤ë¡£DUMP_END ¤ÎÆþ¤ì˺¤ìÍѤËËöÈø¤Îscript¤Ëɬ¤º DUMP_END ¤ò¤¤¤ì¤ë
1173 k->opcode = SCRIPT_OPCODE_DUMP_END;
1175 const int error = syntax_check(text, text_num, s, c->mode);
1183 struct romimage r = {
1185 .size = 0, .offset = 0,
1187 .attribute = MEMORY_ATTR_NOTUSE,
1188 .name = STR_REGION_CPU
1191 .size = 0, .offset = 0,
1193 .attribute = MEMORY_ATTR_NOTUSE,
1194 .name = STR_REGION_PPU
1197 .size = 0, .offset = 0,
1199 .attribute = MEMORY_ATTR_NOTUSE,
1200 .name = STR_REGION_CPU
1202 //device ¤Ë±þ¤¸¤¿´Ø¿ô¥Ý¥¤¥ó¥¿¤ò flash_order ¤ËÅϤ¹
1207 .pagesize = c->cpu_flash_driver->pagesize,
1208 .flash_write = c->reader->cpu_flash_write,
1209 //.flash_write = c->reader->cpu_6502_write,
1210 .read = c->reader->cpu_read
1216 .pagesize = c->ppu_flash_driver->pagesize,
1217 .flash_write = c->reader->ppu_write,
1218 .read = c->reader->ppu_read
1221 .mirror = MIRROR_PROGRAMABLE
1223 //attribute ¤Ï¤½¤Î struct data ¤ËÂФ·¤Æ¤Î RW ¤Ê¤Î¤ÇÍ×Ãí°Õ
1226 r.cpu_rom.attribute = MEMORY_ATTR_WRITE;
1227 r.ppu_rom.attribute = MEMORY_ATTR_WRITE;
1230 r.cpu_ram.attribute = MEMORY_ATTR_WRITE;
1232 case MODE_RAM_WRITE:
1233 r.cpu_ram.attribute = MEMORY_ATTR_READ;
1235 case MODE_ROM_PROGRAM:
1236 r.cpu_rom.attribute = MEMORY_ATTR_READ;
1237 r.ppu_rom.attribute = MEMORY_ATTR_READ;
1243 if(logical_check(s, c, &r) == 0){
1245 if(nesbuffer_malloc(&r, c->mode) == NG){
1247 if((c->mode == MODE_RAM_WRITE) && (r.cpu_ram.data != NULL)){
1248 free(r.cpu_ram.data);
1253 if(execute(s, c, &r) == OK){
1257 nesfile_create(&r, c->romimage);
1260 backupram_create(&(r.cpu_ram), c->ramimage);
1265 nesbuffer_free(&r, c->mode);
1266 if((c->mode == MODE_RAM_WRITE) && (r.cpu_ram.data != NULL)){
1267 free(r.cpu_ram.data);