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
todo:
* ÊÑ¿ô´ÉÍý¤Î¥°¥í¡¼¥Ð¥ëÃͤò¡¢logical_test(), excute() ¥í¡¼¥«¥ë¤Ë¤·¤¿¤¤
*/
+#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "type.h"
#include "file.h"
-#include "driver_master.h"
-#include "giveio.h"
+#include "reader_master.h"
#include "textutil.h"
+#include "config.h"
#include "header.h"
#include "script.h"
-#define OP_PPU_WRITE_ENABLE (0)
/*
MAPPER num
MIRROR [HV]
STEP_END
DUMP_END
*/
-struct script_syntax{
- const char *name;
- int script_opcode;
- int argc, compare;
- int argv_type[4];
-};
-enum{
- SYNTAX_ARGVTYPE_NULL,
- SYNTAX_ARGVTYPE_VALUE,
- SYNTAX_ARGVTYPE_HV,
- SYNTAX_ARGVTYPE_EXPRESSION,
- SYNTAX_ARGVTYPE_VARIABLE
-};
-enum{
- SYNTAX_COMPARE_EQ,
- SYNTAX_COMPARE_GT
-};
-enum{
- SCRIPT_OPCODE_MAPPER,
- SCRIPT_OPCODE_MIRROR,
- SCRIPT_OPCODE_CPU_ROMSIZE,
- SCRIPT_OPCODE_CPU_RAMSIZE,
- SCRIPT_OPCODE_PPU_ROMSIZE,
- SCRIPT_OPCODE_DUMP_START,
- SCRIPT_OPCODE_CPU_READ,
- SCRIPT_OPCODE_CPU_WRITE,
- SCRIPT_OPCODE_CPU_RAMRW,
- SCRIPT_OPCODE_PPU_RAMTEST,
- SCRIPT_OPCODE_PPU_READ,
- SCRIPT_OPCODE_PPU_WRITE,
- SCRIPT_OPCODE_STEP_START,
- SCRIPT_OPCODE_STEP_END,
- SCRIPT_OPCODE_DUMP_END,
- SCRIPT_OPCODE_COMMENT,
- SCRIPT_OPCODE_NUM
-};
-static const char OPSTR_CPU_ROMSIZE[] = "CPU_ROMSIZE";
-static const char OPSTR_CPU_RAMSIZE[] = "CPU_RAMSIZE";
-static const char OPSTR_PPU_ROMSIZE[] = "PPU_ROMSIZE";
-static const char OPSTR_CPU_RAMRW[] = "CPU_RAMRW";
-static const struct script_syntax SCRIPT_SYNTAX[] = {
- {"MAPPER", SCRIPT_OPCODE_MAPPER, 1, SYNTAX_COMPARE_EQ, {SYNTAX_ARGVTYPE_VALUE, SYNTAX_ARGVTYPE_NULL, SYNTAX_ARGVTYPE_NULL, SYNTAX_ARGVTYPE_NULL}},
- {"MIRROR", SCRIPT_OPCODE_MIRROR, 1, SYNTAX_COMPARE_EQ, {SYNTAX_ARGVTYPE_HV, SYNTAX_ARGVTYPE_NULL, SYNTAX_ARGVTYPE_NULL, SYNTAX_ARGVTYPE_NULL}},
- {OPSTR_CPU_ROMSIZE, SCRIPT_OPCODE_CPU_ROMSIZE, 1, SYNTAX_COMPARE_EQ, {SYNTAX_ARGVTYPE_VALUE, SYNTAX_ARGVTYPE_NULL, SYNTAX_ARGVTYPE_NULL, SYNTAX_ARGVTYPE_NULL}},
- {OPSTR_CPU_RAMSIZE, SCRIPT_OPCODE_CPU_RAMSIZE, 1, SYNTAX_COMPARE_EQ, {SYNTAX_ARGVTYPE_VALUE, SYNTAX_ARGVTYPE_NULL, SYNTAX_ARGVTYPE_NULL, SYNTAX_ARGVTYPE_NULL}},
- {OPSTR_PPU_ROMSIZE, SCRIPT_OPCODE_PPU_ROMSIZE, 1, SYNTAX_COMPARE_EQ, {SYNTAX_ARGVTYPE_VALUE, SYNTAX_ARGVTYPE_NULL, SYNTAX_ARGVTYPE_NULL, SYNTAX_ARGVTYPE_NULL}},
- {"DUMP_START", SCRIPT_OPCODE_DUMP_START, 0, SYNTAX_COMPARE_EQ, {SYNTAX_ARGVTYPE_NULL, SYNTAX_ARGVTYPE_NULL, SYNTAX_ARGVTYPE_NULL, SYNTAX_ARGVTYPE_NULL}},
- {"CPU_READ", SCRIPT_OPCODE_CPU_READ, 2, SYNTAX_COMPARE_EQ, {SYNTAX_ARGVTYPE_VALUE, SYNTAX_ARGVTYPE_VALUE, SYNTAX_ARGVTYPE_NULL, SYNTAX_ARGVTYPE_NULL}},
- {"CPU_WRITE", SCRIPT_OPCODE_CPU_WRITE, 2, SYNTAX_COMPARE_GT, {SYNTAX_ARGVTYPE_VALUE, SYNTAX_ARGVTYPE_EXPRESSION, SYNTAX_ARGVTYPE_EXPRESSION, SYNTAX_ARGVTYPE_EXPRESSION}},
- {OPSTR_CPU_RAMRW, SCRIPT_OPCODE_CPU_RAMRW, 2, SYNTAX_COMPARE_EQ, {SYNTAX_ARGVTYPE_VALUE, SYNTAX_ARGVTYPE_VALUE, SYNTAX_ARGVTYPE_NULL, SYNTAX_ARGVTYPE_NULL}},
- {"PPU_RAMTEST", SCRIPT_OPCODE_PPU_RAMTEST, 0, SYNTAX_COMPARE_EQ, {SYNTAX_ARGVTYPE_NULL, SYNTAX_ARGVTYPE_NULL, SYNTAX_ARGVTYPE_NULL, SYNTAX_ARGVTYPE_NULL}},
- {"PPU_READ", SCRIPT_OPCODE_PPU_READ, 2, SYNTAX_COMPARE_EQ, {SYNTAX_ARGVTYPE_VALUE, SYNTAX_ARGVTYPE_VALUE, SYNTAX_ARGVTYPE_NULL, SYNTAX_ARGVTYPE_NULL}},
-#if OP_PPU_WRITE_ENABLE==1
- {"PPU_WRITE", SCRIPT_OPCODE_PPU_WRITE, 2, SYNTAX_COMPARE_EQ, {SYNTAX_ARGVTYPE_VALUE, SYNTAX_ARGVTYPE_VALUE, SYNTAX_ARGVTYPE_NULL, SYNTAX_ARGVTYPE_NULL}},
-#endif
- {"STEP_START", SCRIPT_OPCODE_STEP_START, 4, SYNTAX_COMPARE_EQ, {SYNTAX_ARGVTYPE_VARIABLE, SYNTAX_ARGVTYPE_VALUE, SYNTAX_ARGVTYPE_VALUE, SYNTAX_ARGVTYPE_VALUE}},
- {"STEP_END", SCRIPT_OPCODE_STEP_END, 0, SYNTAX_COMPARE_EQ, {SYNTAX_ARGVTYPE_NULL, SYNTAX_ARGVTYPE_NULL, SYNTAX_ARGVTYPE_NULL, SYNTAX_ARGVTYPE_NULL}},
- {"DUMP_END", SCRIPT_OPCODE_DUMP_END, 0, SYNTAX_COMPARE_EQ, {SYNTAX_ARGVTYPE_NULL, SYNTAX_ARGVTYPE_NULL, SYNTAX_ARGVTYPE_NULL, SYNTAX_ARGVTYPE_NULL}}
-};
+#include "syntax.h"
//ÊÑ¿ô´ÉÍý
struct variable_manage{
};
static const struct variable_manage VARIABLE_INIT = {
- '\0', 0, 0, 0, 0,
- NULL
+ .name = '\0',
+ .start = 0, .end = 0, .step = 0,
+ .val = 0,
+ .Continue = NULL
};
static struct variable_manage variable_bank[VARIABLE_MAX];
static int variable_num = 0;
static const char SYNTAX_ERROR_PREFIX[] = "syntax error:";
-static int syntax_check_phase(char **word, int word_num, struct script *s)
+/*
+return: error count, ¤³¤³¤Ç¤Ï 0 or 1
+*/
+static int syntax_check_phase(char **word, int word_num, struct script *s, const int mode)
{
int i = sizeof(SCRIPT_SYNTAX) / sizeof(SCRIPT_SYNTAX[0]);
const struct script_syntax *syntax;
int j;
s->opcode = syntax->script_opcode;
+ if((mode & syntax->permittion) == 0){
+ printf("%s opcode %s not allowed on current mode\n", SYNTAX_ERROR_PREFIX, syntax->name);
+ return 1;
+ };
{
int compare = 0;
switch(syntax->compare){
}break;
}
}
+ //opcode found and ÆþÎÏʸ»ú¼ïÀµ¾ï
return 0;
}
syntax++;
return 1;
}
-static int syntax_check(char **text, int text_num, struct script *s)
+/*
+return: error count
+*/
+static int syntax_check(char **text, int text_num, struct script *s, int mode)
{
int error = 0;
int i;
+ mode = 1<< mode; //permittion ¤Ï bitflag ¤Ê¤Î¤Ç¤³¤³¤ÇÊÑ´¹¤¹¤ë
variable_init_all();
for(i = 0; i < text_num; i++){
char *word[TEXT_MAXWORD];
if(word[0][0] == '#'){
s->opcode = SCRIPT_OPCODE_COMMENT;
}else{
- error += syntax_check_phase(word, n, s);
+ error += syntax_check_phase(word, n, s, mode);
}
s++;
}
enum{
SETTING, DUMP, END
};
+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);
+ 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);
+ return NG;
+ }
+ break;
+ case MEMORY_AREA_PPU:
+ switch(offset){
+ case 0x0000: case 0x0400: case 0x0800: case 0x0c00:
+ case 0x1000: case 0x1400: case 0x1800: case 0x1c00:
+ break;
+ default:
+ 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);
+ return NG;
+ }
+ break;
+ default:
+ assert(0); //unknown memory area
+ }
+
+ const long mask = size - 1;
+ const long data = (address & mask) | offset;
+ switch(address){
+ 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:
+ printf("%s %s_COMMAND unknown commnand address\n", LOGICAL_ERROR_PREFIX, str_region);
+ return NG;
+ }
+ return OK;
+}
+
static int logical_check(const struct script *s, const struct st_config *c, struct romimage *r)
{
long cpu_romsize = 0, cpu_ramsize = 0, ppu_romsize = 0;
- int setting = SETTING, error = 0;
- //romimage init
+ int imagesize = 0; //for write or program mode
+ int setting = SETTING;
+ int error = 0;
+
variable_init_all();
while(s->opcode != SCRIPT_OPCODE_DUMP_END){
//printf("opcode exec %s\n", SCRIPT_SYNTAX[s->opcode].name);
printf("%s config script include DUMPSTART area\n", LOGICAL_ERROR_PREFIX);
error += 1;
}
+
+ //romimage open for write or program mode
+ if((imagesize == 0) && (setting == DUMP)){
+ switch(c->mode){
+ case MODE_RAM_WRITE:
+ assert(r->cpu_ram.attribute == MEMORY_ATTR_READ);
+ r->cpu_ram.data = buf_load_full(c->ramimage, &imagesize);
+ if(r->cpu_ram.data == NULL){
+ printf("%s RAM image open error\n", LOGICAL_ERROR_PREFIX);
+ imagesize = -1;
+ error += 1;
+ }else if(r->cpu_ram.size != imagesize){
+ printf("%s RAM image size is not same\n", LOGICAL_ERROR_PREFIX);
+ free(r->cpu_ram.data);
+ r->cpu_ram.data = NULL;
+ imagesize = -1;
+ error += 1;
+ }
+ 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){
+ error += 1;
+ }
+ imagesize = -1;
+ break;
+ default:
+ imagesize = -1;
+ break;
+ }
+ }
+
switch(s->opcode){
case SCRIPT_OPCODE_COMMENT:
break;
case SCRIPT_OPCODE_MIRROR:
r->mirror = s->value[0];
break;
- case SCRIPT_OPCODE_CPU_ROMSIZE:
- r->cpu_rom.size = s->value[0];
- break;
+ case SCRIPT_OPCODE_CPU_ROMSIZE:{
+ const long size = s->value[0];
+ r->cpu_rom.size = size;
+ if(memorysize_check(size, MEMORY_AREA_CPU_ROM)){
+ printf("%s %s length error\n", LOGICAL_ERROR_PREFIX, OPSTR_CPU_ROMSIZE);
+ error += 1;
+ }
+ //flash memory capacity check
+ //¤¤¤Þ¤Î¤È¤³¤í == ¤Ë¤·¤Æ¾®¤µ¤¤ÍÆÎ̤⤽¤Î¤¦¤ÁÂбþ
+ 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;
+ }
+ }break;
case SCRIPT_OPCODE_CPU_RAMSIZE:
- r->cpu_ram_read.size = s->value[0];
- r->cpu_ram_write.size = s->value[0];
+ //memory size ¤Ï̤³ÎÄêÍ×ÁǤ¬Â¿¤¤¤Î¤Ç check ¤òÈ´¤¯
+ r->cpu_ram.size = s->value[0];
break;
- case SCRIPT_OPCODE_PPU_ROMSIZE:
- r->ppu_rom.size = s->value[0];
+ 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;
+ case SCRIPT_OPCODE_PPU_ROMSIZE:{
+ const long size = s->value[0];
+ r->ppu_rom.size = size;
+ if(memorysize_check(size, MEMORY_AREA_PPU)){
+ printf("%s %s length error\n", LOGICAL_ERROR_PREFIX, OPSTR_PPU_ROMSIZE);
+ error += 1;
+ }
+ 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:
+ if(command_mask(MEMORY_AREA_PPU, s->value[0], s->value[1], s->value[2], &(r->ppu_flash)) == NG){
+ error += 1;
+ }
break;
case SCRIPT_OPCODE_DUMP_START:
setting = DUMP;
const long address = s->value[0];
const long length = s->value[1];
const long end = address + length - 1;
+
+ assert(r->cpu_rom.attribute == MEMORY_ATTR_WRITE);
//length filter. 0 ¤Ï¤À¤á
if(!is_range(length, 1, 0x4000)){
logical_print_illgallength(STR_REGION_CPU, length);
error += 1;
}
//address filter
- else if(address < 0x6000 || address >= 0x10000){
+ else if(!is_region_cpurom(address)){
logical_print_illgalarea(STR_REGION_CPU, address);
error += 1;
}else if(end >= 0x10000){
logical_print_overdump(STR_REGION_CPU, address, end);
error += 1;
}
- //$7fff-$8000¤òϢ³¤Ç¤Þ¤¿¤¬¤»¤Ê¤¤
- else if((address <= 0x7fff) && (end >= 0x8000)){
- printf("%s address cannot over $7fff-$8000. divide CPU_READ.\n", LOGICAL_ERROR_PREFIX);
- error += 1;
- }
- //dump length update
- if(is_region_cpuram(address)){
- cpu_ramsize += length;
- }else if(is_region_cpurom(address)){
- cpu_romsize += length;
- }
+ cpu_romsize += length;
setting = DUMP;
}
break;
}
break;
case SCRIPT_OPCODE_CPU_RAMRW:{
- if(c->mode == MODE_ROM_DUMP){
- printf("%s cannot use %s on ROMDUMP mode\n", LOGICAL_ERROR_PREFIX, OPSTR_CPU_RAMRW);
- error += 1;
- }
const long address = s->value[0];
const long length = s->value[1];
const long end = address + length - 1;
+ switch(c->mode){
+ case MODE_RAM_READ:
+ assert(r->cpu_ram.attribute == MEMORY_ATTR_WRITE);
+ break;
+ case MODE_RAM_WRITE:
+ assert(r->cpu_ram.attribute = MEMORY_ATTR_READ);
+ break;
+ }
//length filter. 0 ¤Ï¤À¤á
if(!is_range(length, 1, 0x2000)){
logical_print_illgallength(STR_REGION_CPU, length);
error += 1;
}
cpu_ramsize += length;
- if(c->mode == MODE_RAM_WRITE){
- r->cpu_ram_write.data = buf_load_full(c->ramimage_write, &(r->cpu_ram_write.size));
- if(r->cpu_ram_write.data == NULL){
- printf("%s RAM image open error\n", LOGICAL_ERROR_PREFIX);
- error += 1;
- }else if(r->cpu_ram_read.size != r->cpu_ram_write.size){
- printf("%s RAM image size is not same\n", LOGICAL_ERROR_PREFIX);
- free(r->cpu_ram_write.data);
- r->cpu_ram_write.data = NULL;
- error += 1;
- }
+ setting = DUMP;
}
+ break;
+ case SCRIPT_OPCODE_CPU_PROGRAM:{
+ const long address = s->value[0];
+ const long length = s->value[1];
+ const long end = address + length - 1;
+
+ assert(r->cpu_rom.attribute == MEMORY_ATTR_READ);
+ assert(r->ppu_rom.attribute == MEMORY_ATTR_READ);
+ //length filter.
+ if(!is_range(length, 0x80, 0x2000)){
+ logical_print_illgallength(STR_REGION_CPU, length);
+ error += 1;
+ }
+ //address filter
+ else if(!is_region_cpurom(address)){
+ logical_print_illgalarea(STR_REGION_CPU, address);
+ error += 1;
+ }else if(end >= 0x10000){
+ logical_print_overdump(STR_REGION_CPU, address, end);
+ error += 1;
+ }
+ cpu_romsize += length;
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;
}
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;
}
break;
case SCRIPT_OPCODE_PPU_WRITE:{
- if(OP_PPU_WRITE_ENABLE==0){
+ if(DEBUG==0){
break;
}
const long address = s->value[0];
- const long data = s->value[1];
+ long data;
+ if(expression_calc(&s->expression, &data) == NG){
+ printf("%s expression calc error\n", LOGICAL_ERROR_PREFIX);
+ error += 1;
+ }
setting = DUMP;
if(!is_region_ppurom(address)){
logical_print_illgalarea(STR_REGION_PPU, address);
logical_print_byteerror(STR_REGION_PPU, data);
error += 1;
}
+ 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:{
}
//dump length conform
error += dump_length_conform(OPSTR_CPU_ROMSIZE, cpu_romsize, r->cpu_rom.size);
- error += dump_length_conform(OPSTR_CPU_RAMSIZE, cpu_ramsize, r->cpu_ram_read.size);
+ error += dump_length_conform(OPSTR_CPU_RAMSIZE, cpu_ramsize, r->cpu_ram.size);
error += dump_length_conform(OPSTR_PPU_ROMSIZE, ppu_romsize, r->ppu_rom.size);
//command line config override
r->backupram = 1;
}
if(c->mapper != CONFIG_OVERRIDE_UNDEF){
+ //program mode ¤Ç mapper Êѹ¹¤òËɤ°
+ assert(c->mode == MODE_ROM_DUMP);
r->mappernum = c->mapper;
}
+ if(c->syntaxtest == 1){
+ if(error == 0){
+ printf("syntax ok!\n");
+ }
+ error += 1;
+ }
return error;
}
/*
execute() ÍÑ¥µ¥Ö´Ø¿ô¤È¥Ç¡¼¥¿
*/
-static int execute_connection_check(const struct driver *d)
+static int execute_connection_check(const struct reader_driver *d)
{
int ret = OK;
const int testsize = 0x80;
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 driver *d)
+static int ppu_ramfind(const struct reader_driver *d)
{
const int length = sizeof(PPU_TEST_DATA);
const long testaddr = 123;
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){
length--;
}
printf(" 0x%06x\n", sum);
- fflush(stdout);
}
static void read_result_print(const struct memory *m, long length)
{
readbuffer_print(m, length);
checksum_print(m->data, 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 driver *d, const struct memory *w, struct memory *r, 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;
long a = address;
long l = length;
- writedata = w->data;
+ writedata = ram->data;
while(l != 0){
- d->cpu_write(a++, *writedata);
+ d->cpu_6502_write(a++, *writedata, wait);
writedata += 1;
l--;
}
- }
- d->cpu_read(address, length, r->data);
- if(mode == MODE_RAM_READ){
- return;
- }
- if(memcmp(r->data, w->data, length) == 0){
- printf("RAM data write success\n");
+ u8 *compare;
+ compare = malloc(length);
+ d->cpu_read(address, length, compare);
+ if(memcmp(ram->data, compare, length) == 0){
+ printf("RAM data write success\n");
+ }else{
+ printf("RAM data write failed\n");
+ }
+ free(compare);
}else{
- printf("RAM data write failed\n");
+ d->cpu_read(address, length, ram->data);
}
}
static int execute(const struct script *s, const struct st_config *c, struct romimage *r)
{
- const struct driver *d;
- d = driver_get(c->driver);
- if(d == NULL){
- printf("%s driver not found\n", EXECUTE_ERROR_PREFIX);
- return NG;
- }
- const int gg = giveio_start();
- switch(gg){
- case GIVEIO_OPEN:
- case GIVEIO_START:
- case GIVEIO_WIN95:
+ const struct reader_driver *const d = c->reader;
+ switch(d->open_or_close(READER_OPEN)){
+ case OK:
d->init();
break;
- default:
- case GIVEIO_ERROR:
- printf("%s Can't Access Direct IO %d\n", EXECUTE_ERROR_PREFIX, gg);
+ case NG:
+ printf("%s driver open error\n", EXECUTE_ERROR_PREFIX);
return NG;
+ default:
+ assert(0);
}
if(execute_connection_check(d) == NG){
printf("%s maybe connection error\n", EXECUTE_ERROR_PREFIX);
+ d->open_or_close(READER_CLOSE);
return NG;
}
- struct memory cpu_rom, ppu_rom, cpu_ram_read, cpu_ram_write;
+ 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;
- cpu_ram_read = r->cpu_ram_read;
- cpu_ram_write = r->cpu_ram_write;
+ cpu_ram = r->cpu_ram;
variable_init_all();
while(s->opcode != SCRIPT_OPCODE_DUMP_END){
switch(s->opcode){
case SCRIPT_OPCODE_CPU_READ:{
struct memory *m;
- const long addr = s->value[0];
+ const long address = s->value[0];
const long length = s->value[1];
m = &cpu_rom;
- if(is_region_cpuram(addr)){
- m = &cpu_ram_read;
- }
- d->cpu_read(addr, length, m->data);
+ d->cpu_read(address, length, m->data);
read_result_print(m, length);
m->data += length;
m->offset += length;
case SCRIPT_OPCODE_CPU_WRITE:{
long data;
expression_calc(&s->expression, &data);
- d->cpu_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_write, &cpu_ram_read, c->mode, s->value[0], length);
- read_result_print(&cpu_ram_read, length);
- cpu_ram_read.data += length;
- cpu_ram_read.offset += length;
- if(c->mode == MODE_RAM_WRITE){
- cpu_ram_write.data += length;
- cpu_ram_write.offset += 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
+ );
+ 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];
}
break;
case SCRIPT_OPCODE_PPU_WRITE:
- if(OP_PPU_WRITE_ENABLE == 1){
- d->ppu_write(s->value[0], s->value[1]);
+ if(DEBUG == 1){
+ long data;
+ expression_calc(&s->expression, &data);
+ 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++;
}
}
- if(gg != GIVEIO_WIN95){
- giveio_stop(GIVEIO_STOP);
+ d->open_or_close(READER_CLOSE);
+ if(program_compare != NULL){
+ free(program_compare);
}
return OK;
}
k += text_num;
k->opcode = SCRIPT_OPCODE_DUMP_END;
}
- const int error = syntax_check(text, text_num, s);
+ const int error = syntax_check(text, text_num, s, c->mode);
free(buf);
free(text);
if(error != 0){
}
}
struct romimage r = {
- cpu_rom: {
- size: 0, offset: 0,
- data: NULL,
- name: STR_REGION_CPU
+ .cpu_rom = {
+ .size = 0, .offset = 0,
+ .data = NULL,
+ .attribute = MEMORY_ATTR_NOTUSE,
+ .name = "program ROM"
+ },
+ .ppu_rom = {
+ .size = 0, .offset = 0,
+ .data = NULL,
+ .attribute = MEMORY_ATTR_NOTUSE,
+ .name = "charcter ROM"
},
- ppu_rom: {
- size: 0, offset: 0,
- data: NULL,
- name: STR_REGION_PPU
+ .cpu_ram = {
+ .size = 0, .offset = 0,
+ .data = NULL,
+ .attribute = MEMORY_ATTR_NOTUSE,
+ .name = STR_REGION_CPU
},
- cpu_ram_read: {
- size: 0, offset: 0,
- data: NULL,
- name: STR_REGION_CPU
+ //device ¤Ë±þ¤¸¤¿´Ø¿ô¥Ý¥¤¥ó¥¿¤ò flash_order ¤ËÅϤ¹
+ .cpu_flash = {
+ .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
},
- cpu_ram_write: {
- size: 0, offset: 0,
- data: NULL,
- name: STR_REGION_CPU
+ .ppu_flash = {
+ .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
},
- mappernum: 0,
- mirror: MIRROR_PROGRAMABLE
+ .mappernum = 0,
+ .mirror = MIRROR_PROGRAMABLE
};
+ //attribute ¤Ï¤½¤Î struct data ¤ËÂФ·¤Æ¤Î RW ¤Ê¤Î¤ÇÍ×Ãí°Õ
+ switch(c->mode){
+ case MODE_ROM_DUMP:
+ r.cpu_rom.attribute = MEMORY_ATTR_WRITE;
+ r.ppu_rom.attribute = MEMORY_ATTR_WRITE;
+ break;
+ case MODE_RAM_READ:
+ r.cpu_ram.attribute = MEMORY_ATTR_WRITE;
+ break;
+ case MODE_RAM_WRITE:
+ r.cpu_ram.attribute = MEMORY_ATTR_READ;
+ break;
+ case MODE_ROM_PROGRAM:
+ r.cpu_rom.attribute = MEMORY_ATTR_READ;
+ r.ppu_rom.attribute = MEMORY_ATTR_READ;
+ break;
+ default:
+ assert(0);
+ }
+
if(logical_check(s, c, &r) == 0){
//dump RAM Îΰè¼èÆÀ
- if(nesbuffer_malloc(&r) == NG){
+ if(nesbuffer_malloc(&r, c->mode) == NG){
free(s);
- if(r.cpu_ram_write.data != NULL){
- free(r.cpu_ram_write.data);
+ if((c->mode == MODE_RAM_WRITE) && (r.cpu_ram.data != NULL)){
+ free(r.cpu_ram.data);
}
return;
}
- //dump
+ //script execute!!
if(execute(s, c, &r) == OK){
//À®²Ì½ÐÎÏ
switch(c->mode){
nesfile_create(&r, c->romimage);
break;
case MODE_RAM_READ:
- backupram_create(&(r.cpu_ram_read), c->ramimage_read);
+ backupram_create(&(r.cpu_ram), c->ramimage);
break;
}
}
//dump RAM Îΰè²òÊü
- nesbuffer_free(&r);
- if(r.cpu_ram_write.data != NULL){
- free(r.cpu_ram_write.data);
+ nesbuffer_free(&r, c->mode);
+ if((c->mode == MODE_RAM_WRITE) && (r.cpu_ram.data != NULL)){
+ free(r.cpu_ram.data);
}
}
free(s);