OSDN Git Service

flash device dummy での書き込み処理と文字出力の変更
[unagi/old-svn-converted.git] / client / trunk / script.c
index da3fee0..cf40be6 100644 (file)
@@ -2,7 +2,7 @@
 famicom ROM cartridge utility - unagi
 script engine
 
-Copyright (C) 2008  sato_tiff
+Copyright (C) 2008 ±·³«È¯¶¨Æ±Áȹç
 
 This library is free software; you can redistribute it and/or
 modify it under the terms of the GNU Lesser General Public
@@ -21,18 +21,18 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 todo: 
 * ÊÑ¿ô´ÉÍý¤Î¥°¥í¡¼¥Ð¥ëÃͤò¡¢logical_test(), excute() ¥í¡¼¥«¥ë¤Ë¤·¤¿¤¤
 */
+#include <assert.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include "type.h"
 #include "file.h"
 #include "reader_master.h"
-#include "giveio.h"
 #include "textutil.h"
+#include "config.h"
 #include "header.h"
 #include "script.h"
 
-#define OP_PPU_WRITE_ENABLE (0)
 /*
 MAPPER num
 MIRROR [HV]
@@ -47,65 +47,7 @@ STEP_START variable start end step -> for(i=start;i<end;i+=step)
 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{
@@ -121,8 +63,10 @@ enum{
 };
 
 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;
@@ -284,7 +228,10 @@ static int syntax_check_expression(char **word, int word_num, struct st_expressi
 
 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;
@@ -294,6 +241,10 @@ static int syntax_check_phase(char **word, int word_num, struct script *s)
                        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){
@@ -360,6 +311,7 @@ static int syntax_check_phase(char **word, int word_num, struct script *s)
                                        }break;
                                }
                        }
+                       //opcode found and ÆþÎÏʸ»ú¼ïÀµ¾ï
                        return 0;
                }
                syntax++;
@@ -369,10 +321,14 @@ static int syntax_check_phase(char **word, int word_num, struct script *s)
        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];
@@ -380,7 +336,7 @@ static int syntax_check(char **text, int text_num, struct script *s)
                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++;
        }
@@ -459,11 +415,76 @@ static const char STR_ACCESS_WRITE[] = "write";
 enum{
        SETTING, DUMP, END
 };
+static int command_mask(const int region, const long address, const long offset, long size, 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);
@@ -471,6 +492,40 @@ static int logical_check(const struct script *s, const struct st_config *c, stru
                        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;
@@ -480,15 +535,46 @@ static int logical_check(const struct script *s, const struct st_config *c, stru
                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;
@@ -497,30 +583,22 @@ static int logical_check(const struct script *s, const struct st_config *c, stru
                        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;
@@ -542,13 +620,17 @@ static int logical_check(const struct script *s, const struct st_config *c, stru
                        }
                        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);
@@ -563,34 +645,52 @@ static int logical_check(const struct script *s, const struct st_config *c, stru
                                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;
                        }
@@ -603,18 +703,22 @@ static int logical_check(const struct script *s, const struct st_config *c, stru
                                error += 1;
                        }
                        //dump length update
-                       if(is_region_ppurom(address)){
+                       if((s->opcode == SCRIPT_OPCODE_PPU_READ) && is_region_ppurom(address)){
                                ppu_romsize += length;
                        }
                        setting = DUMP;
                        }
                        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);
@@ -623,6 +727,30 @@ static int logical_check(const struct script *s, const struct st_config *c, stru
                                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:{
@@ -675,7 +803,7 @@ static int logical_check(const struct script *s, const struct st_config *c, stru
        }
        //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
@@ -686,8 +814,16 @@ static int logical_check(const struct script *s, const struct st_config *c, stru
                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;
 }
 
@@ -721,10 +857,7 @@ static int execute_connection_check(const struct reader_driver *d)
 
 enum {PPU_TEST_RAM, PPU_TEST_ROM};
 const u8 PPU_TEST_DATA[] = "PPU_TEST_DATA";
-#if DEBUG==0
-static 
-#endif
-int ppu_ramtest(const struct reader_driver *d)
+static int ppu_ramfind(const struct reader_driver *d)
 {
        const int length = sizeof(PPU_TEST_DATA);
        const long testaddr = 123;
@@ -759,6 +892,40 @@ int ppu_ramtest(const struct reader_driver *d)
        return PPU_TEST_ROM;
 }
 
+static int ramtest(const struct reader_driver *d, long address, long length, u8 *writedata, u8 *testdata, const long filldata)
+{
+       long i = length;
+       long a = address;
+       while(i != 0){
+               d->ppu_write(a, filldata);
+               a++;
+               i--;
+       }
+       d->ppu_read(address, length, testdata);
+       memset(writedata, filldata, length);
+       if(memcmp(writedata, testdata, length) == 0){
+               return 0;
+       }
+       return 1;
+}
+
+static const long SRAMTESTDATA[] = {0xff, 0xaa, 0x55, 0x00};
+static int ppu_sramtest(const struct reader_driver *d, long address, long length)
+{
+       u8 *writedata, *testdata;
+       int error = 0;
+       int i;
+       testdata = malloc(length);
+       writedata = malloc(length);
+       for(i = 0; i < sizeof(SRAMTESTDATA) / sizeof(long); i++){
+               const long filldata = SRAMTESTDATA[i];
+               error += ramtest(d, address, length, testdata, writedata, filldata);
+       }
+       free(testdata);
+       free(writedata);
+       return error;
+}
+
 static void readbuffer_print(const struct memory *m, long length)
 {
        if(length >= 0x10){
@@ -797,69 +964,99 @@ static void checksum_print(const u8 *data, long length)
                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 reader_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_6502_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 reader_driver *d;
-       d = reader_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){
@@ -867,13 +1064,10 @@ static int execute(const struct script *s, const struct st_config *c, struct rom
                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;
@@ -881,28 +1075,58 @@ static int execute(const struct script *s, const struct st_config *c, struct rom
                case SCRIPT_OPCODE_CPU_WRITE:{
                        long data;
                        expression_calc(&s->expression, &data);
-                       d->cpu_6502_write(s->value[0], data);
+                       d->cpu_6502_write(s->value[0], data, c->write_wait);
                        }
                        break;
                case SCRIPT_OPCODE_CPU_RAMRW:{
                        const long length = s->value[1];
-                       execute_cpu_ramrw(d, &cpu_ram_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];
@@ -920,8 +1144,33 @@ static int execute(const struct script *s, const struct st_config *c, struct rom
                        }
                        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:
@@ -941,8 +1190,9 @@ static int execute(const struct script *s, const struct st_config *c, struct rom
                        s++;
                }
        }
-       if(gg != GIVEIO_WIN95){
-               giveio_stop(GIVEIO_STOP);
+       d->open_or_close(READER_CLOSE);
+       if(program_compare != NULL){
+               free(program_compare);
        }
        return OK;
 }
@@ -976,7 +1226,7 @@ void script_load(const struct st_config *c)
                        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){
@@ -985,39 +1235,74 @@ void script_load(const struct st_config *c)
                }
        }
        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){
@@ -1025,14 +1310,14 @@ void script_load(const struct st_config *c)
                                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);