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("%d:%s opcode %s not allowed on current mode\n", s->line, 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("%d:%s parameter number not much %s\n", s->line, 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("%d:%s ARGV_NULL select\n", s->line, SYNTAX_ERROR_PREFIX);
268 case SYNTAX_ARGVTYPE_VALUE:
269 if(value_get(word[j + 1], &(s->value[j])) == NG){
270 printf("%d:%s value error %s %s\n", s->line, 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("%d:%s unknown scroll mirroring type %s\n", s->line, 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("%d:%s expression error\n", s->line, 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("%d:%s variable must use [A-Za-z] %s\n", s->line, 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);
337 if(word[0][0] == '#'){
338 s->opcode = SCRIPT_OPCODE_COMMENT;
340 error += syntax_check_phase(word, n, s, mode);
348 logical_check() ÍÑ¥µ¥Ö´Ø¿ô¤È¥Ç¡¼¥¿
350 static const char LOGICAL_ERROR_PREFIX[] = "logical error:";
352 static inline void logical_print_illgalarea(const char *area, long address)
354 printf("%s illgal %s area $%06x\n", LOGICAL_ERROR_PREFIX, area, (int) address);
357 static inline void logical_print_illgallength(const char *area, long length)
359 printf("%s illgal %s length $%04x\n", LOGICAL_ERROR_PREFIX, area, (int) length);
362 static inline void logical_print_overdump(const char *area, long start, long end)
364 printf("%s %s area over dump $%06x-$%06x\n", LOGICAL_ERROR_PREFIX, area, (int)start ,(int)end);
367 static inline void logical_print_access(const char *area, const char *rw, long addr, long len)
369 printf("%s %s $%04x $%02x\n", area, rw, (int) addr, (int) len);
372 static inline void logical_print_byteerror(const char *area, long data)
374 printf("%s write data byte range over, %s $%x\n", LOGICAL_ERROR_PREFIX, area, (int) data);
377 static int dump_length_conform(const char *name, long logicallength, long configlength)
379 if(configlength != logicallength){
380 printf("%s %s dump length error\n", LOGICAL_ERROR_PREFIX, name);
381 printf("%s: 0x%06x, dump length: 0x%06x\n", name, (int) configlength, (int) logicallength);
386 static inline int is_region_cpurom(long address)
388 return (address >= 0x8000) && (address < 0x10000);
391 static inline int is_region_cpuram(long address)
393 return (address >= 0x6000) && (address < 0x8000);
396 static inline int is_region_ppurom(long address)
398 return (address >= 0) && (address < 0x2000);
401 static inline int is_data_byte(long data)
403 return (data >= 0) && (data < 0x100);
406 //¤³¤ì¤À¤± is ·Ï¤Ç <= ±é»»»Ò¤ò»ÈÍѤ·¤Æ¤¤¤ë¤Î¤ÇÃí°Õ
407 static inline int is_range(long data, long start, long end)
409 return (data >= start) && (data <= end);
411 static const char STR_REGION_CPU[] = "cpu";
412 static const char STR_REGION_PPU[] = "ppu";
413 static const char STR_ACCESS_READ[] = "read";
414 static const char STR_ACCESS_WRITE[] = "write";
419 static int command_mask(const int region, const long address, const long offset, long size, struct flash_order *f)
421 const char *str_region = STR_REGION_CPU;
422 if(region == MEMORY_AREA_PPU){
423 str_region = STR_REGION_PPU;
426 case MEMORY_AREA_CPU_ROM:
428 case 0x8000: case 0xa000: case 0xc000:
431 printf("%s %s_COMMAND area offset error\n", LOGICAL_ERROR_PREFIX, str_region);
435 case 0x2000: case 0x4000: case 0x8000:
438 printf("%s %s_COMMAND area mask error\n", LOGICAL_ERROR_PREFIX, str_region);
442 case MEMORY_AREA_PPU:
444 case 0x0000: case 0x0400: case 0x0800: case 0x0c00:
445 case 0x1000: case 0x1400: case 0x1800: case 0x1c00:
448 printf("%s %s_COMMAND area offset error\n", LOGICAL_ERROR_PREFIX, str_region);
452 case 0x0400: case 0x0800: case 0x1000: case 0x2000:
455 printf("%s %s_COMMAND area mask error\n", LOGICAL_ERROR_PREFIX, str_region);
460 assert(0); //unknown memory area
463 const long mask = size - 1;
464 const long data = (address & mask) | offset;
467 f->command_0000 = data;
469 case 0x2aaa: case 0x02aa:
470 f->command_2aaa = data;
472 case 0x5555: case 0x0555:
473 f->command_5555 = data;
476 printf("%s %s_COMMAND unknown commnand address\n", LOGICAL_ERROR_PREFIX, str_region);
482 static int logical_check(const struct script *s, const struct st_config *c, struct romimage *r)
484 long cpu_romsize = 0, cpu_ramsize = 0, ppu_romsize = 0;
485 int imagesize = 0; //for write or program mode
486 int setting = SETTING;
490 while(s->opcode != SCRIPT_OPCODE_DUMP_END){
491 //printf("opcode exec %s\n", SCRIPT_SYNTAX[s->opcode].name);
492 if((setting == DUMP) && (s->opcode < SCRIPT_OPCODE_DUMP_START)){
493 printf("%s config script include DUMP_START area\n", LOGICAL_ERROR_PREFIX);
497 //romimage open for write or program mode
498 if((imagesize == 0) && (setting == DUMP)){
501 assert(r->cpu_ram.attribute == MEMORY_ATTR_READ);
502 r->cpu_ram.data = buf_load_full(c->ramimage, &imagesize);
503 if(r->cpu_ram.data == NULL){
504 printf("%s RAM image open error\n", LOGICAL_ERROR_PREFIX);
507 }else if(r->cpu_ram.size != imagesize){
508 printf("%s RAM image size is not same\n", LOGICAL_ERROR_PREFIX);
509 free(r->cpu_ram.data);
510 r->cpu_ram.data = NULL;
515 case MODE_ROM_PROGRAM:
516 assert(c->cpu_flash_driver->write != NULL);
517 assert(r->cpu_rom.attribute == MEMORY_ATTR_READ);
518 assert(r->ppu_rom.attribute == MEMORY_ATTR_READ);
519 if(nesfile_load(LOGICAL_ERROR_PREFIX, c->romimage, r)== NG){
531 case SCRIPT_OPCODE_COMMENT:
533 case SCRIPT_OPCODE_MAPPER:
534 r->mappernum = s->value[0];
536 case SCRIPT_OPCODE_MIRROR:
537 r->mirror = s->value[0];
539 case SCRIPT_OPCODE_CPU_ROMSIZE:{
540 const long size = s->value[0];
541 r->cpu_rom.size = size;
542 if(memorysize_check(size, MEMORY_AREA_CPU_ROM)){
543 printf("%s %s length error\n", LOGICAL_ERROR_PREFIX, OPSTR_CPU_ROMSIZE);
546 //flash memory capacity check
547 //¤¤¤Þ¤Î¤È¤³¤í == ¤Ë¤·¤Æ¾®¤µ¤¤ÍÆÎ̤⤽¤Î¤¦¤ÁÂбþ
548 else if((c->mode == MODE_ROM_PROGRAM) && (size > c->cpu_flash_driver->capacity)){
549 printf("%s flash memory capacity error\n", LOGICAL_ERROR_PREFIX);
553 case SCRIPT_OPCODE_CPU_RAMSIZE:
554 //memory size ¤Ï̤³ÎÄêÍ×ÁǤ¬Â¿¤¤¤Î¤Ç check ¤òÈ´¤¯
555 r->cpu_ram.size = s->value[0];
557 case SCRIPT_OPCODE_CPU_COMMAND:
558 if(command_mask(MEMORY_AREA_CPU_ROM, s->value[0], s->value[1], s->value[2], &(r->cpu_flash)) == NG){
562 case SCRIPT_OPCODE_PPU_ROMSIZE:{
563 const long size = s->value[0];
564 r->ppu_rom.size = size;
565 if(memorysize_check(size, MEMORY_AREA_PPU)){
566 printf("%s %s length error\n", LOGICAL_ERROR_PREFIX, OPSTR_PPU_ROMSIZE);
569 else if((c->mode == MODE_ROM_PROGRAM) && (size > c->ppu_flash_driver->capacity)){
570 printf("%s flash memory capacity error\n", LOGICAL_ERROR_PREFIX);
575 case SCRIPT_OPCODE_PPU_COMMAND:
576 if(command_mask(MEMORY_AREA_PPU, s->value[0], s->value[1], s->value[2], &(r->ppu_flash)) == NG){
580 case SCRIPT_OPCODE_DUMP_START:
583 case SCRIPT_OPCODE_CPU_READ:{
584 const long address = s->value[0];
585 const long length = s->value[1];
586 const long end = address + length - 1;
588 assert(r->cpu_rom.attribute == MEMORY_ATTR_WRITE);
589 //length filter. 0 ¤Ï¤À¤á
590 if(!is_range(length, 1, 0x4000)){
591 logical_print_illgallength(STR_REGION_CPU, length);
595 else if(!is_region_cpurom(address)){
596 logical_print_illgalarea(STR_REGION_CPU, address);
598 }else if(end >= 0x10000){
599 logical_print_overdump(STR_REGION_CPU, address, end);
602 cpu_romsize += length;
606 case SCRIPT_OPCODE_CPU_WRITE:{
607 const long address = s->value[0];
609 if(expression_calc(&s->expression, &data) == NG){
610 printf("%s expression calc error\n", LOGICAL_ERROR_PREFIX);
613 if(address < 0x5000 || address >= 0x10000){
614 logical_print_illgalarea(STR_REGION_CPU, address);
616 }else if(!is_data_byte(data)){
617 logical_print_byteerror(STR_REGION_CPU, data);
623 case SCRIPT_OPCODE_CPU_RAMRW:{
624 const long address = s->value[0];
625 const long length = s->value[1];
626 const long end = address + length - 1;
629 assert(r->cpu_ram.attribute == MEMORY_ATTR_WRITE);
632 assert(r->cpu_ram.attribute = MEMORY_ATTR_READ);
635 //length filter. 0 ¤Ï¤À¤á
636 if(!is_range(length, 1, 0x2000)){
637 logical_print_illgallength(STR_REGION_CPU, length);
641 else if(address < 0x6000 || address >= 0x8000){
642 logical_print_illgalarea(STR_REGION_CPU, address);
644 }else if(end >= 0x8000){
645 logical_print_overdump(STR_REGION_CPU, address, end);
648 cpu_ramsize += length;
652 case SCRIPT_OPCODE_CPU_PROGRAM:{
653 const long address = s->value[0];
654 const long length = s->value[1];
655 const long end = address + length - 1;
657 assert(r->cpu_rom.attribute == MEMORY_ATTR_READ);
658 assert(r->ppu_rom.attribute == MEMORY_ATTR_READ);
660 if(!is_range(length, 0x80, 0x4000)){
661 logical_print_illgallength(STR_REGION_CPU, length);
665 else if(!is_region_cpurom(address)){
666 logical_print_illgalarea(STR_REGION_CPU, address);
668 }else if(end >= 0x10000){
669 logical_print_overdump(STR_REGION_CPU, address, end);
672 cpu_romsize += length;
676 case SCRIPT_OPCODE_PPU_RAMFIND:
677 //¥ë¡¼¥×ÆâÉô¤ËÆþ¤Ã¤Æ¤¿¤é¥¨¥é¡¼
678 if(variable_num != 0){
679 printf("%s PPU_RAMTEST must use outside loop\n", LOGICAL_ERROR_PREFIX);
683 case SCRIPT_OPCODE_PPU_SRAMTEST:
684 case SCRIPT_OPCODE_PPU_READ:{
685 const long address = s->value[0];
686 const long length = s->value[1];
687 const long end = address + length - 1;
688 assert(r->ppu_rom.attribute == MEMORY_ATTR_WRITE);
689 //length filter. 0 ¤òÍÆǧ¤¹¤ë
691 if(s->opcode == SCRIPT_OPCODE_PPU_SRAMTEST){
694 if(!is_range(length, min, 0x2000)){
695 logical_print_illgallength(STR_REGION_PPU, length);
699 else if(!is_region_ppurom(address)){
700 logical_print_illgalarea(STR_REGION_PPU, address);
702 }else if (end >= 0x2000){
703 logical_print_overdump(STR_REGION_PPU, address, end);
707 if((s->opcode == SCRIPT_OPCODE_PPU_READ) && is_region_ppurom(address)){
708 ppu_romsize += length;
713 case SCRIPT_OPCODE_PPU_WRITE:{
717 const long address = s->value[0];
719 if(expression_calc(&s->expression, &data) == NG){
720 printf("%s expression calc error\n", LOGICAL_ERROR_PREFIX);
724 if(!is_region_ppurom(address)){
725 logical_print_illgalarea(STR_REGION_PPU, address);
727 }else if(!is_data_byte(data)){
728 logical_print_byteerror(STR_REGION_PPU, data);
734 case SCRIPT_OPCODE_PPU_PROGRAM:{
735 const long address = s->value[0];
736 const long length = s->value[1];
737 const long end = address + length - 1;
739 assert(r->ppu_rom.attribute == MEMORY_ATTR_READ);
741 if(!is_range(length, 0x80, 0x1000)){
742 logical_print_illgallength(STR_REGION_PPU, length);
746 else if(!is_region_ppurom(address)){
747 logical_print_illgalarea(STR_REGION_PPU, address);
749 }else if(end >= 0x2000){
750 logical_print_overdump(STR_REGION_PPU, address, end);
753 ppu_romsize += length;
757 case SCRIPT_OPCODE_STEP_START:{
760 const int v = s->value[1];
761 if((v < 0) || (v > 0xff)){
762 printf("%s step start must 0-0xff 0x%x\n", LOGICAL_ERROR_PREFIX, v);
766 for(i = 2; i <4; i++){
767 const int v = s->value[i];
768 if((v < 1) || (v > 0x100)){
769 printf("%s end or next must 1-0x100 0x%x\n", LOGICAL_ERROR_PREFIX, v);
773 //¥ë¡¼¥×¤ÎÌá¤êÀè¤Ï¤³¤ÎÌ¿Îá¤Î¼¡¤Ê¤Î¤Ç s[1]
774 if(step_new(s->variable, s->value[1], s->value[2], s->value[3], &s[1]) == NG){
775 printf("%s step loop too much\n", LOGICAL_ERROR_PREFIX);
781 case SCRIPT_OPCODE_DUMP_END:
788 if(s->opcode == SCRIPT_OPCODE_STEP_END){
789 if(variable_num == 0){
790 printf("%s loop closed, missing STEP_START\n", LOGICAL_ERROR_PREFIX);
801 if(variable_num != 0){
802 printf("%s loop opened, missing STEP_END\n", LOGICAL_ERROR_PREFIX);
805 //dump length conform
806 error += dump_length_conform(OPSTR_CPU_ROMSIZE, cpu_romsize, r->cpu_rom.size);
807 error += dump_length_conform(OPSTR_CPU_RAMSIZE, cpu_ramsize, r->cpu_ram.size);
808 error += dump_length_conform(OPSTR_PPU_ROMSIZE, ppu_romsize, r->ppu_rom.size);
810 //command line config override
811 if(c->mirror != CONFIG_OVERRIDE_UNDEF){
812 r->mirror = c->mirror;
814 if(c->backupram != CONFIG_OVERRIDE_UNDEF){
817 if(c->mapper != CONFIG_OVERRIDE_UNDEF){
818 //program mode ¤Ç mapper Êѹ¹¤òËɤ°
819 assert(c->mode == MODE_ROM_DUMP);
820 r->mappernum = c->mapper;
822 if(c->syntaxtest == 1){
824 printf("syntax ok!\n");
832 execute() ÍÑ¥µ¥Ö´Ø¿ô¤È¥Ç¡¼¥¿
834 static int execute_connection_check(const struct reader_driver *d)
837 const int testsize = 0x80;
840 master = malloc(testsize);
841 reload = malloc(testsize);
843 d->cpu_read(0xfee0, testsize, master);
845 while(testcount != 0){
846 d->cpu_read(0xfee0, testsize, reload);
847 if(memcmp(master, reload, testsize) != 0){
859 enum {PPU_TEST_RAM, PPU_TEST_ROM};
860 const u8 PPU_TEST_DATA[] = "PPU_TEST_DATA";
861 static int ppu_ramfind(const struct reader_driver *d)
863 const int length = sizeof(PPU_TEST_DATA);
864 const long testaddr = 123;
865 //ppu ram data fill 0
868 long address = testaddr;
870 d->ppu_write(address++, 0);
875 //ppu test data write
879 long address = testaddr;
880 data = PPU_TEST_DATA;
882 d->ppu_write(address++, (long) *data);
888 u8 writedata[length];
889 d->ppu_read(testaddr, length, writedata);
890 if(memcmp(writedata, PPU_TEST_DATA, length) == 0){
896 static int ramtest(const int region, const struct reader_driver *d, long address, long length, u8 *writedata, u8 *testdata, const long filldata)
902 case MEMORY_AREA_CPU_RAM:
903 d->cpu_6502_write(a, filldata, 0);
905 case MEMORY_AREA_PPU:
906 d->ppu_write(a, filldata);
915 case MEMORY_AREA_CPU_RAM:
916 d->cpu_read(address, length, testdata);
918 case MEMORY_AREA_PPU:
919 d->ppu_read(address, length, testdata);
924 memset(writedata, filldata, length);
925 if(memcmp(writedata, testdata, length) == 0){
931 static const long SRAMTESTDATA[] = {0xff, 0xaa, 0x55, 0x00};
932 static int sramtest(const int region, const struct reader_driver *d, long address, long length)
934 u8 *writedata, *testdata;
937 testdata = malloc(length);
938 writedata = malloc(length);
939 for(i = 0; i < sizeof(SRAMTESTDATA) / sizeof(long); i++){
940 const long filldata = SRAMTESTDATA[i];
941 error += ramtest(region, d, address, length, testdata, writedata, filldata);
948 static void readbuffer_print(const struct memory *m, long length)
953 printf("%s ROM 0x%05x:", m->name, m->offset);
959 switch(offset & 0xf){
970 printf("%02x%c", (int) *data, safix);
977 static void checksum_print(const u8 *data, long length)
985 printf(" 0x%06x\n", sum);
988 static void read_result_print(const struct memory *m, long length)
990 readbuffer_print(m, length);
991 checksum_print(m->data, length);
995 static void execute_program_begin(const struct memory *m)
1000 printf("writing %s area 0x%06x ... ", m->name, m->offset);
1004 static const char STR_OK[] = "OK";
1005 static const char STR_NG[] = "NG";
1007 //memcmp ¤ÎÌá¤êÃͤ¬Æþ¤ë¤Î¤Ç 0 ¤¬Àµ¾ï
1008 static void execute_program_finish(int result)
1015 printf("%s\n", str);
1018 static const char EXECUTE_ERROR_PREFIX[] = "execute error:";
1019 static const char EXECUTE_PROGRAM_PREPARE[] = "%s device initialize ... ";
1020 static const char EXECUTE_PROGRAM_DONE[] = "done\n";
1021 static void execute_cpu_ramrw(const struct reader_driver *d, const struct memory *ram, int mode, long address, long length, long wait)
1023 if(mode == MODE_RAM_WRITE){
1024 const u8 *writedata;
1027 writedata = ram->data;
1029 d->cpu_6502_write(a++, *writedata, wait);
1034 compare = malloc(length);
1035 d->cpu_read(address, length, compare);
1036 if(memcmp(ram->data, compare, length) == 0){
1037 printf("RAM data write success\n");
1039 printf("RAM data write failed\n");
1043 d->cpu_read(address, length, ram->data);
1047 static int execute(const struct script *s, const struct st_config *c, struct romimage *r)
1049 const struct reader_driver *const d = c->reader;
1050 switch(d->open_or_close(READER_OPEN)){
1055 printf("%s driver open error\n", EXECUTE_ERROR_PREFIX);
1060 if(execute_connection_check(d) == NG){
1061 printf("%s maybe connection error\n", EXECUTE_ERROR_PREFIX);
1062 d->open_or_close(READER_CLOSE);
1065 u8 *program_compare;
1066 program_compare = NULL;
1067 if(c->mode == MODE_ROM_PROGRAM){
1068 printf("flashmemory/SRAM program mode. To abort programming, press Ctrl+C\n");
1069 int size = r->cpu_rom.size;
1070 if(size < r->ppu_rom.size){
1071 size = r->ppu_rom.size;
1073 program_compare = malloc(size);
1075 struct memory cpu_rom, ppu_rom, cpu_ram;
1076 cpu_rom = r->cpu_rom;
1077 ppu_rom = r->ppu_rom;
1078 cpu_ram = r->cpu_ram;
1080 int programcount_cpu = 0, programcount_ppu = 0;
1081 variable_init_all();
1082 while(s->opcode != SCRIPT_OPCODE_DUMP_END){
1085 case SCRIPT_OPCODE_CPU_COMMAND:
1086 command_mask(MEMORY_AREA_CPU_ROM, s->value[0], s->value[1], s->value[2], &(r->cpu_flash));
1088 case SCRIPT_OPCODE_CPU_READ:{
1090 const long address = s->value[0];
1091 const long length = s->value[1];
1093 d->cpu_read(address, length, m->data);
1094 read_result_print(m, length);
1096 m->offset += length;
1098 case SCRIPT_OPCODE_CPU_WRITE:{
1100 expression_calc(&s->expression, &data);
1101 d->cpu_6502_write(s->value[0], data, c->write_wait);
1104 case SCRIPT_OPCODE_CPU_RAMRW:{
1105 const long address = s->value[0];
1106 const long length = s->value[1];
1107 if(c->mode == MODE_RAM_WRITE){
1108 if(sramtest(MEMORY_AREA_CPU_RAM, d, address, length) != 0){
1109 printf("SRAM test NG\n");
1114 execute_cpu_ramrw(d, &cpu_ram, c->mode, address, length, c->write_wait);
1115 read_result_print(&cpu_ram, length);
1116 cpu_ram.data += length;
1117 cpu_ram.offset += length;
1120 case SCRIPT_OPCODE_CPU_PROGRAM:{
1121 if(c->cpu_flash_driver->id_device == FLASH_ID_DEVICE_DUMMY){
1124 if(programcount_cpu++ == 0){
1125 printf(EXECUTE_PROGRAM_PREPARE, cpu_rom.name);
1127 //device ¤Ë¤è¤Ã¤Æ¤Ï erase
1128 c->cpu_flash_driver->init(&(r->cpu_flash));
1129 printf(EXECUTE_PROGRAM_DONE);
1132 const long address = s->value[0];
1133 const long length = s->value[1];
1134 execute_program_begin(&cpu_rom);
1135 c->cpu_flash_driver->write(
1140 d->cpu_read(address, length, program_compare);
1141 const int result = memcmp(program_compare, cpu_rom.data, length);
1142 execute_program_finish(result);
1143 cpu_rom.data += length;
1144 cpu_rom.offset += length;
1146 if((DEBUG==0) && (result != 0)){
1151 case SCRIPT_OPCODE_PPU_COMMAND:
1152 command_mask(MEMORY_AREA_PPU, s->value[0], s->value[1], s->value[2], &(r->ppu_flash));
1153 case SCRIPT_OPCODE_PPU_RAMFIND:
1154 if(ppu_ramfind(d) == PPU_TEST_RAM){
1155 printf("PPU_RAMFIND: charcter RAM found\n");
1156 r->ppu_rom.size = 0;
1160 case SCRIPT_OPCODE_PPU_SRAMTEST:{
1161 const long address = s->value[0];
1162 const long length = s->value[1];
1163 printf("PPU_SRAMTEST: 0x%06x-0x%06x ", (int)ppu_rom.offset, (int) (ppu_rom.offset + length) - 1);
1164 if(sramtest(MEMORY_AREA_PPU, d, address, length) == 0){
1165 printf("%s\n", STR_OK);
1167 printf("%s\n", STR_NG);
1171 case SCRIPT_OPCODE_PPU_READ:{
1172 const long address = s->value[0];
1173 const long length = s->value[1];
1175 /*for mmc2,4 protect.
1176 ¤³¤Î¤È¤¤Ï1byteÆɤ߹þ¤ó¤Ç¡¢¤½¤ÎÆâÍƤϥХåե¡¤Ë¤¤¤ì¤Ê¤¤*/
1178 d->ppu_read(address, 1, &dummy);
1180 d->ppu_read(address, length, ppu_rom.data);
1181 read_result_print(&ppu_rom, length);
1183 ppu_rom.data += length;
1184 ppu_rom.offset += length;
1187 case SCRIPT_OPCODE_PPU_WRITE:
1190 expression_calc(&s->expression, &data);
1191 d->ppu_write(s->value[0], data);
1194 case SCRIPT_OPCODE_PPU_PROGRAM:{
1195 if(c->ppu_flash_driver->id_device == FLASH_ID_DEVICE_DUMMY){
1198 if(programcount_ppu++ == 0){
1199 printf(EXECUTE_PROGRAM_PREPARE, ppu_rom.name);
1201 c->ppu_flash_driver->init(&(r->ppu_flash));
1202 printf(EXECUTE_PROGRAM_DONE);
1205 const long address = s->value[0];
1206 const long length = s->value[1];
1207 execute_program_begin(&ppu_rom);
1208 c->ppu_flash_driver->write(
1213 d->ppu_read(address, length, program_compare);
1214 const int result = memcmp(program_compare, ppu_rom.data, length);
1215 execute_program_finish(result);
1216 ppu_rom.data += length;
1217 ppu_rom.offset += length;
1219 if((DEBUG==0) && (result != 0)){
1224 case SCRIPT_OPCODE_STEP_START:
1225 //¥ë¡¼¥×¤ÎÌá¤êÀè¤Ï¤³¤ÎÌ¿Îá¤Î¼¡¤Ê¤Î¤Ç &s[1]
1226 step_new(s->variable, s->value[1], s->value[2], s->value[3], &s[1]);
1228 case SCRIPT_OPCODE_DUMP_END:
1235 if(s->opcode == SCRIPT_OPCODE_STEP_END){
1241 d->open_or_close(READER_CLOSE);
1242 if(program_compare != NULL){
1243 free(program_compare);
1248 void script_load(const struct st_config *c)
1255 buf = buf_load_full(c->script, &scriptsize);
1257 printf("scriptfile open error\n");
1261 text = malloc(sizeof(char*) * TEXT_MAXLINE);
1262 const int text_num = text_load(buf, scriptsize, text);
1264 printf("script line too much\n");
1269 s = malloc(sizeof(struct script) * (text_num + 1));
1270 //logical_check, execute ¶¦¤Ë s->opcode ¤¬ DUMP_END ¤Ë¤Ê¤ë¤Þ¤Ç³¤±¤ë¡£DUMP_END ¤ÎÆþ¤ì˺¤ìÍѤËËöÈø¤Îscript¤Ëɬ¤º DUMP_END ¤ò¤¤¤ì¤ë
1275 k->opcode = SCRIPT_OPCODE_DUMP_END;
1277 const int error = syntax_check(text, text_num, s, c->mode);
1285 struct romimage r = {
1287 .size = 0, .offset = 0,
1289 .attribute = MEMORY_ATTR_NOTUSE,
1293 .size = 0, .offset = 0,
1295 .attribute = MEMORY_ATTR_NOTUSE,
1299 .size = 0, .offset = 0,
1301 .attribute = MEMORY_ATTR_NOTUSE,
1302 .name = STR_REGION_CPU
1304 //device ¤Ë±þ¤¸¤¿´Ø¿ô¥Ý¥¤¥ó¥¿¤ò flash_order ¤ËÅϤ¹
1309 .pagesize = c->cpu_flash_driver->pagesize,
1310 .erase_wait = c->cpu_flash_driver->erase_wait,
1311 .command_mask = c->cpu_flash_driver->command_mask,
1312 .flash_write = c->reader->cpu_flash_write,
1313 .read = c->reader->cpu_read
1319 .pagesize = c->ppu_flash_driver->pagesize,
1320 .erase_wait = c->ppu_flash_driver->erase_wait,
1321 .command_mask = c->ppu_flash_driver->command_mask,
1322 .flash_write = c->reader->ppu_write,
1323 .read = c->reader->ppu_read
1326 .mirror = MIRROR_PROGRAMABLE
1328 //attribute ¤Ï¤½¤Î struct data ¤ËÂФ·¤Æ¤Î RW ¤Ê¤Î¤ÇÍ×Ãí°Õ
1331 r.cpu_rom.attribute = MEMORY_ATTR_WRITE;
1332 r.ppu_rom.attribute = MEMORY_ATTR_WRITE;
1335 r.cpu_ram.attribute = MEMORY_ATTR_WRITE;
1337 case MODE_RAM_WRITE:
1338 r.cpu_ram.attribute = MEMORY_ATTR_READ;
1340 case MODE_ROM_PROGRAM:
1341 r.cpu_rom.attribute = MEMORY_ATTR_READ;
1342 r.ppu_rom.attribute = MEMORY_ATTR_READ;
1348 if(logical_check(s, c, &r) == 0){
1350 if(nesbuffer_malloc(&r, c->mode) == NG){
1352 if((c->mode == MODE_RAM_WRITE) && (r.cpu_ram.data != NULL)){
1353 free(r.cpu_ram.data);
1358 if(execute(s, c, &r) == OK){
1362 nesfile_create(&r, c->romimage);
1365 backupram_create(&(r.cpu_ram), c->ramimage);
1370 nesbuffer_free(&r, c->mode);
1371 if((c->mode == MODE_RAM_WRITE) && (r.cpu_ram.data != NULL)){
1372 free(r.cpu_ram.data);