2 famicom ROM cartridge utility - unagi
5 Copyright (C) 2008-2009 ±·³«È¯¶¨Æ±Áȹç
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"
34 #include "script_syntax.h"
45 CPU_WRITE address data -> ÊÑ¿ôŸ³«+±é»»»Ò»ÈÍѲÄǽ
47 STEP_START variable start end step -> for(i=start;i<end;i+=step)
54 //step ¤ÎÊÑ¿ô¤Ï¾®Ê¸»ú¤Î a-z ¤Ç¤Ï¤¸¤Þ¤ë¤³¤È¡£2ʸ»úÌܰʹߤÏ̵»ë¤¹¤ë
55 struct variable_manage{
59 const struct script *Continue;
64 VARIABLE_MAX = STEP_MAX
67 static const struct variable_manage VARIABLE_INIT = {
69 .start = 0, .end = 0, .step = 0,
73 static struct variable_manage variable_bank[VARIABLE_MAX];
74 static int variable_num = 0;
76 static void variable_init_single(int num)
78 memcpy(&variable_bank[num], &VARIABLE_INIT, sizeof(struct variable_manage));
81 static void variable_init_all(void)
85 for(i = 0; i < VARIABLE_MAX; i++){
86 variable_init_single(i);
90 static int variable_get(char name, long *val)
93 struct variable_manage *v;
95 for(i = 0; i < variable_num; i++){
106 static int expression_calc(const struct st_expression *e, long *val)
109 if(e->left.type == EXPRESSION_TYPE_VARIABLE){
110 if(variable_get(e->left.variable, &left) == NG){
114 left = e->left.value;
116 if(e->operator == OPERATOR_NONE){
120 if(e->right.type == EXPRESSION_TYPE_VARIABLE){
121 if(variable_get(e->right.variable, &right) == NG){
125 right = e->right.value;
131 case OPERATOR_SHIFT_LEFT:
132 *val = left >> right;
135 case OPERATOR_SHIFT_RIGHT:
136 *val = left << right;
152 static int step_new(char name, long start, long end, long step, const struct script *Continue)
154 if(variable_num >= VARIABLE_MAX){
155 return NG; //ÊÑ¿ôÄêµÁ¤¬Â¿¤¹¤®
157 struct variable_manage *v;
160 for(i = 0; i < variable_num; i++){
162 return NG; //ÊÑ¿ô̾½ÅÊ£
173 v->Continue = Continue;
178 static const struct script *step_end(const struct script *Break)
180 //¸½ºß¤Î¥ë¡¼¥×¤ÎÂоÝÊÑ¿ô¤òÆÀ¤ë
181 struct variable_manage *v;
183 v += (variable_num - 1);
189 //¥ë¡¼¥×¤¬½ª¤ï¤Ã¤¿¤Î¤Ç¤½¤ÎÊÑ¿ô¤òÇË´þ¤¹¤ë
190 variable_init_single(variable_num - 1);
195 //int syntax_check(char **text, int text_num, struct script *s, int mode);
197 logical_check() ÍÑ¥µ¥Ö´Ø¿ô¤È¥Ç¡¼¥¿
199 static const char LOGICAL_ERROR_PREFIX[] = "logical error:";
201 SCRIPT_PPUSIZE_0 = 0,
202 SCRIPT_MEMORYSIZE = 10,
204 struct logical_romsize{
205 const struct script *data[SCRIPT_MEMORYSIZE], *constant;
208 static int logical_flashsize_set(int region, struct logical_romsize *l, const struct script *s)
210 //PPU Íѥǡ¼¥¿¤Î 0 ¤Ï size 0, Äê¿ô 0 ¤È¤·¤ÆͽÌ󤵤ì¤Æ¤ª¤ê¡¢0¤Î¾ì¹ç¤Ï¤³¤³¤ò¾å½ñ¤¤¹¤ë
211 if((region == MEMORY_AREA_PPU) && (s->value[0] == 0)){
212 l->data[SCRIPT_PPUSIZE_0] = s;
215 if(l->count >= SCRIPT_MEMORYSIZE){
217 opstr = OPSTR_CPU_ROMSIZE; //warning Âкö
219 case MEMORY_AREA_CPU_ROM:
220 opstr = OPSTR_CPU_ROMSIZE;
222 case MEMORY_AREA_PPU:
223 opstr = OPSTR_PPU_ROMSIZE;
228 printf("%d:%s %s override count over\n", s->line, LOGICAL_ERROR_PREFIX, opstr);
231 l->data[l->count] = s;
236 static int logical_flashsize_get(long transtype, long size, struct logical_romsize *l)
239 for(i = 0; i < l->count; i++){
240 const struct script *s;
242 if((s->value[0] == size) && (
243 (s->value[1] == transtype) ||
244 (s->value[1] == VALUE_TRANSTYPE_FULL)
248 }else if((s->value[0] == size) && (s->value[1] == VALUE_TRANSTYPE_EMPTY)){
253 printf("%s flashsize not found\n", LOGICAL_ERROR_PREFIX);
257 static long constant_get(long val, const struct script *cpu, const struct script *ppu)
260 case VALUE_CONTANT_CPU_STEP_START:
261 return cpu->value[2];
262 case VALUE_CONTANT_CPU_STEP_END:
263 return cpu->value[3];
264 case VALUE_CONTANT_PPU_STEP_START:
265 return ppu->value[2];
266 case VALUE_CONTANT_PPU_STEP_END:
267 return ppu->value[3];
273 static void logical_print_capacityerror(int line, const char *area)
275 printf("%d:%s %s area flash memory capacity error\n", line, LOGICAL_ERROR_PREFIX, area);
278 static inline void logical_print_illgalarea(int line, const char *area, long address)
280 printf("%d:%s illgal %s area $%06x\n", line, LOGICAL_ERROR_PREFIX, area, (int) address);
283 static inline void logical_print_illgallength(int line, const char *area, long length)
285 printf("%d:%s illgal %s length $%04x\n", line, LOGICAL_ERROR_PREFIX, area, (int) length);
288 static inline void logical_print_overdump(int line, const char *area, long start, long end)
290 printf("%d:%s %s area over dump $%06x-$%06x\n", line, LOGICAL_ERROR_PREFIX, area, (int)start ,(int)end);
293 static inline void logical_print_access(int line, const char *area, const char *rw, long addr, long len)
295 printf("%d:%s %s $%04x $%02x\n", line, area, rw, (int) addr, (int) len);
298 static inline void logical_print_byteerror(int line, const char *area, long data)
300 printf("%d:%s write data byte range over, %s $%x\n", line, LOGICAL_ERROR_PREFIX, area, (int) data);
303 static int dump_length_conform(const char *name, long logicallength, long configlength)
305 if(configlength != logicallength){
306 printf("%s %s dump length error\n", LOGICAL_ERROR_PREFIX, name);
307 printf("%s: 0x%06x, dump length: 0x%06x\n", name, (int) configlength, (int) logicallength);
312 static inline int is_region_cpurom(long address)
314 return (address >= 0x8000) && (address < 0x10000);
317 static inline int is_region_cpuram(long address)
319 return (address >= 0x6000) && (address < 0x8000);
322 static inline int is_region_ppurom(long address)
324 return (address >= 0) && (address < 0x2000);
327 static inline int is_data_byte(long data)
329 return (data >= 0) && (data < 0x100);
332 //¤³¤ì¤À¤± is ·Ï¤Ç <= ±é»»»Ò¤ò»ÈÍѤ·¤Æ¤¤¤ë¤Î¤ÇÃí°Õ
333 static inline int is_range(long data, long start, long end)
335 return (data >= start) && (data <= end);
337 static const char STR_REGION_CPU[] = "cpu";
338 static const char STR_REGION_PPU[] = "ppu";
339 static const char STR_ACCESS_READ[] = "read";
340 static const char STR_ACCESS_WRITE[] = "write";
343 SETTING, DUMP, END, STEP_THOUGH
345 static int command_mask(const int region, const long address, const long offset, long size, struct flash_order *f)
347 const char *str_region = STR_REGION_CPU;
348 if(region == MEMORY_AREA_PPU){
349 str_region = STR_REGION_PPU;
352 case MEMORY_AREA_CPU_ROM:
354 case 0x8000: case 0xa000: case 0xc000:
357 printf("%s %s_COMMAND area offset error\n", LOGICAL_ERROR_PREFIX, str_region);
361 case 0x2000: case 0x4000: case 0x8000:
364 printf("%s %s_COMMAND area mask error\n", LOGICAL_ERROR_PREFIX, str_region);
368 case MEMORY_AREA_PPU:
370 case 0x0000: case 0x0400: case 0x0800: case 0x0c00:
371 case 0x1000: case 0x1400: case 0x1800: case 0x1c00:
374 printf("%s %s_COMMAND area offset error\n", LOGICAL_ERROR_PREFIX, str_region);
378 case 0x0400: case 0x0800: case 0x1000: case 0x2000:
381 printf("%s %s_COMMAND area mask error\n", LOGICAL_ERROR_PREFIX, str_region);
386 assert(0); //unknown memory area
389 const long mask = size - 1;
390 const long data = (address & mask) | offset;
393 f->command_0000 = data;
395 case 0x2aaa: case 0x02aa:
396 f->command_2aaa = data;
398 case 0x5555: case 0x0555:
399 f->command_5555 = data;
402 printf("%s %s_COMMAND unknown commnand address\n", LOGICAL_ERROR_PREFIX, str_region);
409 STEP_VALIABLE = 0, STEP_START, STEP_END, STEP_NEXT,
412 static const struct script SCRIPT_PPU_ROMSIZE_0 = {
413 .opcode = SCRIPT_OPCODE_PPU_ROMSIZE,
415 .value = {0, VALUE_TRANSTYPE_EMPTY, 0, 0},
416 //.expression, .variable ̤ÄêµÁ
419 static int logical_check(const struct script *s, const struct st_config *c, struct romimage *r)
421 //(CPU|PPU)_(READ|PROGRAM|RAMRW) ¤Î length ²Ã»»ÃÍ
422 long cpu_romsize = 0, cpu_ramsize = 0, ppu_romsize = 0;
423 //DUMP_START ľ¸å¤Ë ROM or RAM image ¤ò³«¤¯¥Õ¥é¥°
424 //use program mode or ram write mode
425 int imagesize = 0; //for write or program mode
426 int status = SETTING;
427 //override (CPU|PPU)_ROMSIZE pointer. Program mode only
428 struct logical_romsize script_cpu_flashsize = {
432 struct logical_romsize script_ppu_flashsize = {
436 script_ppu_flashsize.data[0] = &SCRIPT_PPU_ROMSIZE_0;
437 //logical error count. Ìá¤êÃÍ
441 while(s->opcode != SCRIPT_OPCODE_DUMP_END){
442 if((status == DUMP) && (s->opcode < SCRIPT_OPCODE_DUMP_START)){
443 printf("%d:%s config script include DUMP_START area\n", s->line, LOGICAL_ERROR_PREFIX);
447 //romimage open for write or program mode
448 if((imagesize == 0) && (status == DUMP)){
450 case MODE_RAM_WRITE: //CPU_RAMSIZE check
451 assert(r->cpu_ram.attribute == MEMORY_ATTR_READ);
452 r->cpu_ram.data = buf_load_full(c->ramimage, &imagesize);
453 if(r->cpu_ram.data == NULL){
454 printf("%s RAM image open error\n", LOGICAL_ERROR_PREFIX);
457 }else if(r->cpu_ram.size != imagesize){
458 printf("%s RAM image size is not same\n", LOGICAL_ERROR_PREFIX);
459 free(r->cpu_ram.data);
460 r->cpu_ram.data = NULL;
465 case MODE_ROM_PROGRAM: //MAPPER check
466 assert(c->cpu_flash_driver->write != NULL);
467 assert(r->cpu_rom.attribute == MEMORY_ATTR_READ);
468 assert(r->ppu_rom.attribute == MEMORY_ATTR_READ);
469 if(nesfile_load(LOGICAL_ERROR_PREFIX, c->romimage, r)== NG){
472 //Äê¿ôÀë¸À¥¨¥é¡¼¤Ï̵¸Â¥ë¡¼¥×¤Î²ÄǽÀ¤¬¤¢¤ë¤Î¤Ç¥¹¥¯¥ê¥×¥ÈÆâÉô¥Á¥§¥Ã¥¯¤ò¤»¤º¤Ë»ß¤á¤ë
473 if(logical_flashsize_get(c->transtype_cpu, r->cpu_rom.size, &script_cpu_flashsize) == NG){
476 if(logical_flashsize_get(c->transtype_ppu, r->ppu_rom.size, &script_ppu_flashsize) == NG){
479 //flash memory capacity check
480 if(r->cpu_rom.size > c->cpu_flash_driver->capacity){
481 logical_print_capacityerror(s->line, r->cpu_rom.name);
484 if((r->ppu_rom.size != 0) && (r->ppu_rom.size > c->ppu_flash_driver->capacity)){
485 logical_print_capacityerror(s->line, r->ppu_rom.name);
497 case SCRIPT_OPCODE_COMMENT:
499 case SCRIPT_OPCODE_MAPPER:
500 r->mappernum = s->value[0];
502 case SCRIPT_OPCODE_MIRROR:
503 r->mirror = s->value[0];
505 case SCRIPT_OPCODE_CPU_ROMSIZE:{
506 const long size = s->value[0];
507 r->cpu_rom.size = size;
508 if(memorysize_check(size, MEMORY_AREA_CPU_ROM)){
509 printf("%s %s length error\n", LOGICAL_ERROR_PREFIX, OPSTR_CPU_ROMSIZE);
513 case SCRIPT_OPCODE_CPU_FLASHSIZE:
514 if(logical_flashsize_set(MEMORY_AREA_CPU_ROM, &script_cpu_flashsize, s) == NG){
517 case SCRIPT_OPCODE_CPU_RAMSIZE:
518 //memory size ¤Ï̤³ÎÄêÍ×ÁǤ¬Â¿¤¤¤Î¤Ç check ¤òÈ´¤¯
519 r->cpu_ram.size = s->value[0];
521 case SCRIPT_OPCODE_CPU_COMMAND:
522 if(command_mask(MEMORY_AREA_CPU_ROM, s->value[0], s->value[1], s->value[2], &(r->cpu_flash)) == NG){
526 case SCRIPT_OPCODE_PPU_ROMSIZE:{
527 const long size = s->value[0];
528 r->ppu_rom.size = size;
529 if(memorysize_check(size, MEMORY_AREA_PPU)){
530 printf("%s %s length error\n", LOGICAL_ERROR_PREFIX, OPSTR_PPU_ROMSIZE);
534 case SCRIPT_OPCODE_PPU_FLASHSIZE:
535 if(logical_flashsize_set(MEMORY_AREA_PPU, &script_ppu_flashsize, s) == NG){
539 case SCRIPT_OPCODE_PPU_COMMAND:
540 if(command_mask(MEMORY_AREA_PPU, s->value[0], s->value[1], s->value[2], &(r->ppu_flash)) == NG){
544 case SCRIPT_OPCODE_DUMP_START:
547 case SCRIPT_OPCODE_CPU_READ:{
548 const long address = s->value[0];
549 const long length = s->value[1];
550 const long end = address + length - 1;
552 assert(r->cpu_rom.attribute == MEMORY_ATTR_WRITE);
553 //length filter. 0 ¤Ï¤À¤á
554 if(!is_range(length, 1, 0x4000)){
555 logical_print_illgallength(s->line, STR_REGION_CPU, length);
559 else if(!is_region_cpurom(address)){
560 logical_print_illgalarea(s->line, STR_REGION_CPU, address);
562 }else if(end >= 0x10000){
563 logical_print_overdump(s->line, STR_REGION_CPU, address, end);
566 cpu_romsize += length;
570 case SCRIPT_OPCODE_CPU_WRITE:{
571 const long address = s->value[0];
573 if(expression_calc(&s->expression, &data) == NG){
574 printf("%d:%s expression calc error\n", s->line, LOGICAL_ERROR_PREFIX);
577 if(address < 0x5000 || address >= 0x10000){
578 logical_print_illgalarea(s->line, STR_REGION_CPU, address);
580 }else if(!is_data_byte(data)){
581 logical_print_byteerror(s->line, STR_REGION_CPU, data);
587 case SCRIPT_OPCODE_CPU_RAMRW:{
588 const long address = s->value[0];
589 const long length = s->value[1];
590 const long end = address + length - 1;
593 assert(r->cpu_ram.attribute == MEMORY_ATTR_WRITE);
596 assert(r->cpu_ram.attribute = MEMORY_ATTR_READ);
599 //length filter. 0 ¤Ï¤À¤á
600 if(!is_range(length, 1, 0x2000)){
601 logical_print_illgallength(s->line, STR_REGION_CPU, length);
605 else if(address < 0x6000 || address >= 0x8000){
606 logical_print_illgalarea(s->line, STR_REGION_CPU, address);
608 }else if(end >= 0x8000){
609 logical_print_overdump(s->line, STR_REGION_CPU, address, end);
612 cpu_ramsize += length;
616 case SCRIPT_OPCODE_CPU_PROGRAM:{
617 const long address = s->value[0];
618 const long length = s->value[1];
619 const long end = address + length - 1;
621 assert(r->cpu_rom.attribute == MEMORY_ATTR_READ);
622 assert(r->ppu_rom.attribute == MEMORY_ATTR_READ);
624 if(!is_range(length, 0x80, 0x4000)){
625 logical_print_illgallength(s->line, STR_REGION_CPU, length);
629 else if(!is_region_cpurom(address)){
630 logical_print_illgalarea(s->line, STR_REGION_CPU, address);
632 }else if(end >= 0x10000){
633 logical_print_overdump(s->line, STR_REGION_CPU, address, end);
636 cpu_romsize += length;
640 case SCRIPT_OPCODE_PPU_RAMFIND:
641 //¥ë¡¼¥×ÆâÉô¤ËÆþ¤Ã¤Æ¤¿¤é¥¨¥é¡¼
642 if(variable_num != 0){
643 printf("%d:%s PPU_RAMTEST must use outside loop\n", s->line, LOGICAL_ERROR_PREFIX);
647 case SCRIPT_OPCODE_PPU_SRAMTEST:
648 case SCRIPT_OPCODE_PPU_READ:{
649 const long address = s->value[0];
650 const long length = s->value[1];
651 const long end = address + length - 1;
652 assert(r->ppu_rom.attribute == MEMORY_ATTR_WRITE);
653 //length filter. 0 ¤òÍÆǧ¤¹¤ë
655 if(s->opcode == SCRIPT_OPCODE_PPU_SRAMTEST){
658 if(!is_range(length, min, 0x2000)){
659 logical_print_illgallength(s->line, STR_REGION_PPU, length);
663 else if(!is_region_ppurom(address)){
664 logical_print_illgalarea(s->line, STR_REGION_PPU, address);
666 }else if (end >= 0x2000){
667 logical_print_overdump(s->line, STR_REGION_PPU, address, end);
671 if((s->opcode == SCRIPT_OPCODE_PPU_READ) && is_region_ppurom(address)){
672 ppu_romsize += length;
677 case SCRIPT_OPCODE_PPU_WRITE:{
681 const long address = s->value[0];
683 if(expression_calc(&s->expression, &data) == NG){
684 printf("%d:%s expression calc error\n", s->line, LOGICAL_ERROR_PREFIX);
688 if(!is_region_ppurom(address)){
689 logical_print_illgalarea(s->line, STR_REGION_PPU, address);
691 }else if(!is_data_byte(data)){
692 logical_print_byteerror(s->line, STR_REGION_PPU, data);
698 case SCRIPT_OPCODE_PPU_PROGRAM:{
699 const long address = s->value[0];
700 const long length = s->value[1];
701 const long end = address + length - 1;
703 assert(r->ppu_rom.attribute == MEMORY_ATTR_READ);
704 assert(r->ppu_rom.size != 0);
707 if(!is_range(length, 0x80, 0x1000)){
708 logical_print_illgallength(s->line, STR_REGION_PPU, length);
712 else if(!is_region_ppurom(address)){
713 logical_print_illgalarea(s->line, STR_REGION_PPU, address);
715 }else if(end >= 0x2000){
716 logical_print_overdump(s->line, STR_REGION_PPU, address, end);
719 ppu_romsize += length;
723 case SCRIPT_OPCODE_STEP_START:{
724 const struct step_syntax{
728 } RANGE[STEP_NUM] = {
729 {.start = 0, .end = 0, .constant = NG, .name = "variable"},
730 {.start = 0, .end = 0xff, .constant = OK, .name = "start"},
731 {.start = 0, .end = 0x100, .constant = OK, .name = "end"},
732 {.start = 1, .end = 0x100, .constant = NG, .name = "next"}
735 for(i = STEP_START; i < STEP_NUM; i++){
736 const struct step_syntax *ss;
738 //Äê¿ôobject ¤ò¼Â¿ô¤ËÊÑ´¹¤¹¤ë¤¿¤á¡¢const ¤ò³°¤·¤Æ½ñ¤´¹¤¨¤ë
740 v = (long *) &s->value[i];
741 if((ss->constant == OK) && (is_range(*v, VALUE_CONTANT_CPU_STEP_START, VALUE_CONTANT_PPU_STEP_END))){
742 //VALUE_CONSTANT_xxx ¤ò¼ÂºÝ¤Ë»È¤ï¤ì¤ëÄê¿ô¤Ë¤·¤Æ¡¢¥¹¥¯¥ê¥×¥È¥Ç¡¼¥¿¤òÄ¥¤êÂؤ¨¤ë
743 *v = constant_get(*v, script_cpu_flashsize.constant, script_ppu_flashsize.constant);
745 if(!is_range(*v, ss->start, ss->end)){
746 printf("%d:%s step %s must %d-0x%x 0x%x\n", s->line, ss->name, LOGICAL_ERROR_PREFIX, (int) ss->start, (int) ss->end, (int) *v);
750 //charcter RAM ¤ÎÍÍ¤Ë step ÆâÉô¤ò¹Ô¤ï¤Ê¤¤¾ì¹ç¤Îscript¾õÂÖ¤ÎÊѹ¹
751 if(s->value[STEP_START] >= s->value[STEP_END]){
752 status = STEP_THOUGH;
754 //¥ë¡¼¥×¤ÎÌá¤êÀè¤Ï¤³¤ÎÌ¿Îá¤Î¼¡¤Ê¤Î¤Ç s[1]
755 else if(step_new(s->variable, s->value[STEP_START], s->value[STEP_END], s->value[STEP_NEXT], &s[1]) == NG){
756 printf("%d:%s step loop too much\n", s->line, LOGICAL_ERROR_PREFIX);
763 case SCRIPT_OPCODE_DUMP_END:
768 //status ÊÌ¤Ë script ¤ÎÀ©¸æ. while ¤òÈ´¤±¤ë¤Î¤Ç switch ¤ò»È¤¨¤Ê¤¤
771 }else if(status == STEP_THOUGH){
774 while(s->opcode != SCRIPT_OPCODE_DUMP_END){
776 case SCRIPT_OPCODE_STEP_START:
779 case SCRIPT_OPCODE_STEP_END:
793 //opcode ÊÌ¤Ë script ¤ÎÀ©¸æ. while ¤òÈ´¤±¤ë¤Î¤Ç switch ¤ò»È¤¨¤Ê¤¤
794 if(s->opcode == SCRIPT_OPCODE_STEP_END){
795 if(variable_num == 0){
796 printf("%d:%s loop closed, missing STEP_START\n", s->line, LOGICAL_ERROR_PREFIX);
801 }else if(s->opcode == SCRIPT_OPCODE_DUMP_END){
809 if(variable_num != 0){
810 printf("%d:%s loop opened, missing STEP_END\n", s->line, LOGICAL_ERROR_PREFIX);
813 //dump length conform
814 error += dump_length_conform(OPSTR_CPU_ROMSIZE, cpu_romsize, r->cpu_rom.size);
815 error += dump_length_conform(OPSTR_CPU_RAMSIZE, cpu_ramsize, r->cpu_ram.size);
816 error += dump_length_conform(OPSTR_PPU_ROMSIZE, ppu_romsize, r->ppu_rom.size);
818 //command line config override
819 if(c->mirror != CONFIG_OVERRIDE_UNDEF){
820 r->mirror = c->mirror;
822 if(c->backupram != CONFIG_OVERRIDE_UNDEF){
825 if(c->mapper != CONFIG_OVERRIDE_UNDEF){
826 //program mode ¤Ç mapper Êѹ¹¤òËɤ°
827 assert(c->mode == MODE_ROM_DUMP);
828 r->mappernum = c->mapper;
830 if(c->syntaxtest == 1){
832 printf("syntax ok!\n");
840 execute() ÍÑ¥µ¥Ö´Ø¿ô¤È¥Ç¡¼¥¿
842 static int execute_connection_check(const struct reader_driver *d)
845 const int testsize = 0x80;
848 master = malloc(testsize);
849 reload = malloc(testsize);
851 d->cpu_read(0xfee0, testsize, master);
853 while(testcount != 0){
854 d->cpu_read(0xfee0, testsize, reload);
855 if(memcmp(master, reload, testsize) != 0){
867 enum {PPU_TEST_RAM, PPU_TEST_ROM};
868 const u8 PPU_TEST_DATA[] = "PPU_TEST_DATA";
869 static int ppu_ramfind(const struct reader_driver *d)
871 const int length = sizeof(PPU_TEST_DATA);
872 const long testaddr = 123;
873 //ppu ram data fill 0
876 long address = testaddr;
878 d->ppu_write(address++, 0);
883 //ppu test data write
887 long address = testaddr;
888 data = PPU_TEST_DATA;
890 d->ppu_write(address++, (long) *data);
896 u8 writedata[length];
897 d->ppu_read(testaddr, length, writedata);
898 if(memcmp(writedata, PPU_TEST_DATA, length) == 0){
904 static int ramtest(const int region, const struct reader_driver *d, long address, long length, u8 *writedata, u8 *testdata, const long filldata)
910 case MEMORY_AREA_CPU_RAM:
911 d->cpu_6502_write(a, filldata, 0);
913 case MEMORY_AREA_PPU:
914 d->ppu_write(a, filldata);
923 case MEMORY_AREA_CPU_RAM:
924 d->cpu_read(address, length, testdata);
926 case MEMORY_AREA_PPU:
927 d->ppu_read(address, length, testdata);
932 memset(writedata, filldata, length);
933 if(memcmp(writedata, testdata, length) == 0){
939 static const long SRAMTESTDATA[] = {0xff, 0xaa, 0x55, 0x00};
940 static int sramtest(const int region, const struct reader_driver *d, long address, long length)
942 u8 *writedata, *testdata;
945 testdata = malloc(length);
946 writedata = malloc(length);
947 for(i = 0; i < sizeof(SRAMTESTDATA) / sizeof(long); i++){
948 const long filldata = SRAMTESTDATA[i];
949 error += ramtest(region, d, address, length, testdata, writedata, filldata);
956 static void readbuffer_print(const struct memory *m, long length)
961 printf("%s ROM 0x%05x:", m->name, m->offset);
967 switch(offset & 0xf){
978 printf("%02x%c", (int) *data, safix);
985 static void checksum_print(const u8 *data, long length)
993 printf(" 0x%06x\n", sum);
996 static void read_result_print(const struct memory *m, long length)
998 readbuffer_print(m, length);
999 checksum_print(m->data, length);
1003 static void execute_program_begin(const struct memory *m, const long length)
1005 int tail = m->offset + (int) length - 1;
1006 printf("writing %s area 0x%06x-0x%06x ... ", m->name, m->offset, tail);
1010 static const char STR_OK[] = "OK";
1011 static const char STR_NG[] = "NG";
1013 //memcmp ¤ÎÌá¤êÃͤ¬Æþ¤ë¤Î¤Ç 0 ¤¬Àµ¾ï
1014 static void execute_program_finish(int result)
1021 printf("%s\n", str);
1024 static const char EXECUTE_ERROR_PREFIX[] = "execute error:";
1025 static const char EXECUTE_PROGRAM_PREPARE[] = "%s device initialize ... ";
1026 static const char EXECUTE_PROGRAM_DONE[] = "done\n";
1027 static void execute_cpu_ramrw(const struct reader_driver *d, const struct memory *ram, int mode, long address, long length, long wait)
1029 if(mode == MODE_RAM_WRITE){
1030 const u8 *writedata;
1033 writedata = ram->data;
1035 d->cpu_6502_write(a++, *writedata, wait);
1040 compare = malloc(length);
1041 d->cpu_read(address, length, compare);
1042 if(memcmp(ram->data, compare, length) == 0){
1043 printf("RAM data write success\n");
1045 printf("RAM data write failed\n");
1049 d->cpu_read(address, length, ram->data);
1053 static int execute(const struct script *s, const struct st_config *c, struct romimage *r)
1055 const struct reader_driver *const d = c->reader;
1056 switch(d->open_or_close(READER_OPEN)){
1061 printf("%s driver open error\n", EXECUTE_ERROR_PREFIX);
1066 if(execute_connection_check(d) == NG){
1067 printf("%s maybe connection error\n", EXECUTE_ERROR_PREFIX);
1068 d->open_or_close(READER_CLOSE);
1071 u8 *program_compare;
1072 program_compare = NULL;
1073 if(c->mode == MODE_ROM_PROGRAM){
1074 printf("flashmemory/SRAM program mode. To abort programming, press Ctrl+C\n");
1075 int size = r->cpu_rom.size;
1076 if(size < r->ppu_rom.size){
1077 size = r->ppu_rom.size;
1079 program_compare = malloc(size);
1081 struct memory cpu_rom, ppu_rom, cpu_ram;
1082 cpu_rom = r->cpu_rom;
1083 ppu_rom = r->ppu_rom;
1084 cpu_ram = r->cpu_ram;
1087 int programcount_cpu = 0, programcount_ppu = 0;
1088 variable_init_all();
1089 while(s->opcode != SCRIPT_OPCODE_DUMP_END){
1090 //printf("%s\n", SCRIPT_SYNTAX[s->opcode].name);
1092 case SCRIPT_OPCODE_CPU_COMMAND:
1093 command_mask(MEMORY_AREA_CPU_ROM, s->value[0], s->value[1], s->value[2], &(r->cpu_flash));
1095 case SCRIPT_OPCODE_CPU_READ:{
1097 const long address = s->value[0];
1098 const long length = s->value[1];
1100 d->cpu_read(address, length, m->data);
1101 read_result_print(m, length);
1103 m->offset += length;
1105 case SCRIPT_OPCODE_CPU_WRITE:{
1107 expression_calc(&s->expression, &data);
1108 d->cpu_6502_write(s->value[0], data, c->write_wait);
1111 case SCRIPT_OPCODE_CPU_RAMRW:{
1112 const long address = s->value[0];
1113 const long length = s->value[1];
1114 if(c->mode == MODE_RAM_WRITE){
1115 if(sramtest(MEMORY_AREA_CPU_RAM, d, address, length) != 0){
1116 printf("SRAM test NG\n");
1121 execute_cpu_ramrw(d, &cpu_ram, c->mode, address, length, c->write_wait);
1122 read_result_print(&cpu_ram, length);
1123 cpu_ram.data += length;
1124 cpu_ram.offset += length;
1127 case SCRIPT_OPCODE_CPU_PROGRAM:{
1128 if(c->cpu_flash_driver->id_device == FLASH_ID_DEVICE_DUMMY){
1131 if(programcount_cpu++ == 0){
1132 printf(EXECUTE_PROGRAM_PREPARE, cpu_rom.name);
1134 //device ¤Ë¤è¤Ã¤Æ¤Ï erase
1135 c->cpu_flash_driver->init(&(r->cpu_flash));
1136 printf(EXECUTE_PROGRAM_DONE);
1139 const long address = s->value[0];
1140 const long length = s->value[1];
1141 execute_program_begin(&cpu_rom, length);
1142 c->cpu_flash_driver->write(
1147 d->cpu_read(address, length, program_compare);
1148 const int result = memcmp(program_compare, cpu_rom.data, length);
1149 execute_program_finish(result);
1150 cpu_rom.data += length;
1151 cpu_rom.offset += length;
1153 if((DEBUG==0) && (result != 0)){
1158 case SCRIPT_OPCODE_PPU_COMMAND:
1159 command_mask(MEMORY_AREA_PPU, s->value[0], s->value[1], s->value[2], &(r->ppu_flash));
1161 case SCRIPT_OPCODE_PPU_RAMFIND:
1162 if(ppu_ramfind(d) == PPU_TEST_RAM){
1163 printf("PPU_RAMFIND: charcter RAM found\n");
1164 r->ppu_rom.size = 0;
1168 case SCRIPT_OPCODE_PPU_SRAMTEST:{
1169 const long address = s->value[0];
1170 const long length = s->value[1];
1171 printf("PPU_SRAMTEST: 0x%06x-0x%06x ", (int)ppu_rom.offset, (int) (ppu_rom.offset + length) - 1);
1172 if(sramtest(MEMORY_AREA_PPU, d, address, length) == 0){
1173 printf("%s\n", STR_OK);
1175 printf("%s\n", STR_NG);
1179 case SCRIPT_OPCODE_PPU_READ:{
1180 const long address = s->value[0];
1181 const long length = s->value[1];
1183 /*for mmc2,4 protect.
1184 ¤³¤Î¤È¤¤Ï1byteÆɤ߹þ¤ó¤Ç¡¢¤½¤ÎÆâÍƤϥХåե¡¤Ë¤¤¤ì¤Ê¤¤*/
1186 d->ppu_read(address, 1, &dummy);
1188 d->ppu_read(address, length, ppu_rom.data);
1189 read_result_print(&ppu_rom, length);
1191 ppu_rom.data += length;
1192 ppu_rom.offset += length;
1195 case SCRIPT_OPCODE_PPU_WRITE:
1198 expression_calc(&s->expression, &data);
1199 d->ppu_write(s->value[0], data);
1202 case SCRIPT_OPCODE_PPU_PROGRAM:{
1203 if(c->ppu_flash_driver->id_device == FLASH_ID_DEVICE_DUMMY){
1206 if(programcount_ppu++ == 0){
1207 printf(EXECUTE_PROGRAM_PREPARE, ppu_rom.name);
1209 c->ppu_flash_driver->init(&(r->ppu_flash));
1210 printf(EXECUTE_PROGRAM_DONE);
1213 const long address = s->value[0];
1214 const long length = s->value[1];
1215 execute_program_begin(&ppu_rom, length);
1216 c->ppu_flash_driver->write(
1221 d->ppu_read(address, length, program_compare);
1222 const int result = memcmp(program_compare, ppu_rom.data, length);
1223 execute_program_finish(result);
1224 ppu_rom.data += length;
1225 ppu_rom.offset += length;
1227 if((DEBUG==0) && (result != 0)){
1232 case SCRIPT_OPCODE_STEP_START:{
1233 if(s->value[STEP_START] >= s->value[STEP_END]){
1234 status = STEP_THOUGH;
1236 //¥ë¡¼¥×¤ÎÌá¤êÀè¤Ï¤³¤ÎÌ¿Îá¤Î¼¡¤Ê¤Î¤Ç &s[1]
1237 step_new(s->variable, s->value[STEP_START], s->value[STEP_END], s->value[STEP_NEXT], &s[1]);
1240 case SCRIPT_OPCODE_DUMP_END:
1246 }else if(status == STEP_THOUGH){
1250 while(s->opcode != SCRIPT_OPCODE_DUMP_END){
1252 case SCRIPT_OPCODE_STEP_START:
1255 case SCRIPT_OPCODE_STEP_END:
1270 if(s->opcode == SCRIPT_OPCODE_STEP_END){
1276 d->open_or_close(READER_CLOSE);
1277 if(program_compare != NULL){
1278 free(program_compare);
1283 void script_load(const struct st_config *c)
1290 buf = buf_load_full(c->script, &scriptsize);
1292 printf("scriptfile open error\n");
1296 text = malloc(sizeof(char*) * TEXT_MAXLINE);
1297 const int text_num = text_load(buf, scriptsize, text);
1299 printf("script line too much\n");
1304 s = malloc(sizeof(struct script) * (text_num + 1));
1305 //logical_check, execute ¶¦¤Ë s->opcode ¤¬ DUMP_END ¤Ë¤Ê¤ë¤Þ¤Ç³¤±¤ë¡£DUMP_END ¤ÎÆþ¤ì˺¤ìÍѤËËöÈø¤Îscript¤Ëɬ¤º DUMP_END ¤ò¤¤¤ì¤ë
1310 k->opcode = SCRIPT_OPCODE_DUMP_END;
1312 const int error = syntax_check(text, text_num, s, c->mode);
1320 struct romimage r = {
1322 .size = 0, .offset = 0,
1324 .attribute = MEMORY_ATTR_NOTUSE,
1328 .size = 0, .offset = 0,
1330 .attribute = MEMORY_ATTR_NOTUSE,
1334 .size = 0, .offset = 0,
1336 .attribute = MEMORY_ATTR_NOTUSE,
1337 .name = STR_REGION_CPU
1339 //device ¤Ë±þ¤¸¤¿´Ø¿ô¥Ý¥¤¥ó¥¿¤ò flash_order ¤ËÅϤ¹
1344 .pagesize = c->cpu_flash_driver->pagesize,
1345 .erase_wait = c->cpu_flash_driver->erase_wait,
1346 .command_mask = c->cpu_flash_driver->command_mask,
1347 .flash_write = c->reader->cpu_flash_write,
1348 .read = c->reader->cpu_read
1354 .pagesize = c->ppu_flash_driver->pagesize,
1355 .erase_wait = c->ppu_flash_driver->erase_wait,
1356 .command_mask = c->ppu_flash_driver->command_mask,
1357 .flash_write = c->reader->ppu_write,
1358 .read = c->reader->ppu_read
1361 .mirror = MIRROR_PROGRAMABLE
1363 //attribute ¤Ï¤½¤Î struct data ¤ËÂФ·¤Æ¤Î RW ¤Ê¤Î¤ÇÍ×Ãí°Õ
1366 r.cpu_rom.attribute = MEMORY_ATTR_WRITE;
1367 r.ppu_rom.attribute = MEMORY_ATTR_WRITE;
1370 r.cpu_ram.attribute = MEMORY_ATTR_WRITE;
1372 case MODE_RAM_WRITE:
1373 r.cpu_ram.attribute = MEMORY_ATTR_READ;
1375 case MODE_ROM_PROGRAM:
1376 r.cpu_rom.attribute = MEMORY_ATTR_READ;
1377 r.ppu_rom.attribute = MEMORY_ATTR_READ;
1383 if(logical_check(s, c, &r) == 0){
1385 if(nesbuffer_malloc(&r, c->mode) == NG){
1387 if((c->mode == MODE_RAM_WRITE) && (r.cpu_ram.data != NULL)){
1388 free(r.cpu_ram.data);
1393 if(execute(s, c, &r) == OK){
1397 nesfile_create(&r, c->romimage);
1400 backupram_create(&(r.cpu_ram), c->ramimage);
1405 nesbuffer_free(&r, c->mode);
1406 if((c->mode == MODE_RAM_WRITE) && (r.cpu_ram.data != NULL)){
1407 free(r.cpu_ram.data);