OSDN Git Service

client 0.6.2 release
[unagi/old-svn-converted.git] / client / tag / 0.6.2 / script_engine.c
1 /*
2 famicom ROM cartridge utility - unagi
3 script engine
4
5 Copyright (C) 2008-2009 ±·³«È¯¶¨Æ±Áȹç
6
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.
11
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.
16
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
20
21 todo: 
22 * ÊÑ¿ô´ÉÍý¤Î¥°¥í¡¼¥Ð¥ëÃͤò¡¢logical_test(), excute() ¥í¡¼¥«¥ë¤Ë¤·¤¿¤¤
23 */
24 #include <assert.h>
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include "memory_manage.h"
29 #include "type.h"
30 #include "file.h"
31 #include "reader_master.h"
32 #include "textutil.h"
33 #include "config.h"
34 #include "header.h"
35 #include "script_syntax.h"
36 #include "script.h"
37
38 /*
39 MAPPER num
40 MIRROR [HV]
41 CPU_ROMSIZE num
42 CPU_RAMSIZE num
43 PPU_ROMSIZE num
44 DUMP_START
45 CPU_READ address size
46 CPU_WRITE address data -> ÊÑ¿ôŸ³«+±é»»»Ò»ÈÍѲÄǽ
47 PPU_READ address size
48 STEP_START variable start end step -> for(i=start;i<end;i+=step)
49 STEP_END
50 DUMP_END
51 */
52 //#include "syntax.h"
53
54 //ÊÑ¿ô´ÉÍý
55 //step ¤ÎÊÑ¿ô¤Ï¾®Ê¸»ú¤Î a-z ¤Ç¤Ï¤¸¤Þ¤ë¤³¤È¡£2ʸ»úÌܰʹߤÏ̵»ë¤¹¤ë
56 struct variable_manage{
57         char name;
58         long start,end,step;
59         long val;
60         const struct script *Continue;
61 };
62
63 enum{
64         STEP_MAX = 3,
65         VARIABLE_MAX = STEP_MAX
66 };
67
68 static const struct variable_manage VARIABLE_INIT = {
69         .name = '\0', 
70         .start = 0, .end = 0, .step = 0,
71         .val = 0,
72         .Continue = NULL
73 };
74 static struct variable_manage variable_bank[VARIABLE_MAX];
75 static int variable_num = 0;
76
77 static void variable_init_single(int num)
78 {
79         memcpy(&variable_bank[num], &VARIABLE_INIT, sizeof(struct variable_manage));
80 }
81
82 static void variable_init_all(void)
83 {
84         int i;
85         variable_num = 0;
86         for(i = 0; i < VARIABLE_MAX; i++){
87                 variable_init_single(i);
88         }
89 }
90
91 static int variable_get(char name, long *val)
92 {
93         int i;
94         struct variable_manage *v;
95         v = variable_bank;
96         for(i = 0; i < variable_num; i++){
97                 if(v->name == name){
98                         *val = v->val;
99                         return OK;
100                 }
101                 v++;
102         }
103         return NG;
104 }
105
106 static int expression_value_get(const struct st_variable *v, long *data)
107 {
108         if(v->type == EXPRESSION_TYPE_VARIABLE){
109                 if(variable_get(v->variable, data) == NG){
110                         return NG;
111                 }
112         }else{
113                 *data = v->value;
114         }
115         return OK;
116 }
117
118 //ÊÑ¿ôŸ³«
119 static int expression_calc(const struct st_expression *e, long *val)
120 {
121         long left, right;
122         if(expression_value_get(&e->left, &left) == NG){
123                 return NG;
124         }
125         if(e->operator == OPERATOR_NONE){
126                 *val = left;
127                 return OK;
128         }
129         if(expression_value_get(&e->right, &right) == NG){
130                 return NG;
131         }
132         switch(e->operator){
133         case OPERATOR_PLUS:
134                 *val = left + right;
135                 break;
136         case OPERATOR_SHIFT_LEFT:
137                 *val = left >> right;
138                 //*val &= 1;
139                 break;
140         case OPERATOR_SHIFT_RIGHT:
141                 *val = left << right;
142                 break;
143         case OPERATOR_AND:
144                 *val = left & right;
145                 break;
146         case OPERATOR_OR:
147                 *val = left | right;
148                 break;
149         case OPERATOR_XOR:
150                 *val = left ^ right;
151                 break;
152         }
153         
154         return OK;
155 }
156
157 static int step_new(char name, long start, long end, long step, const struct script *Continue)
158 {
159         if(variable_num >= VARIABLE_MAX){
160                 return NG; //ÊÑ¿ôÄêµÁ¤¬Â¿¤¹¤®
161         }
162         struct variable_manage *v;
163         int i;
164         v = variable_bank;
165         for(i = 0; i < variable_num; i++){
166                 if(v->name == name){
167                         return NG; //ÊÑ¿ô̾½ÅÊ£
168                 }
169                 v++;
170         }
171         v = variable_bank;
172         v += variable_num;
173         v->name = name;
174         v->start = start;
175         v->end = end;
176         v->step = step;
177         v->val = start;
178         v->Continue = Continue;
179         variable_num++;
180         return OK;
181 }
182
183 static const struct script *step_end(const struct script *Break)
184 {
185         //¸½ºß¤Î¥ë¡¼¥×¤ÎÂоÝÊÑ¿ô¤òÆÀ¤ë
186         struct variable_manage *v;
187         v = variable_bank;
188         v += (variable_num - 1);
189         //ÊÑ¿ô¹¹¿·
190         v->val += v->step;
191         if(v->val < v->end){
192                 return v->Continue;
193         }
194         //¥ë¡¼¥×¤¬½ª¤ï¤Ã¤¿¤Î¤Ç¤½¤ÎÊÑ¿ô¤òÇË´þ¤¹¤ë
195         variable_init_single(variable_num - 1);
196         variable_num--;
197         return Break;
198 }
199
200 //int syntax_check(char **text, int text_num, struct script *s, int mode);
201 /*
202 logical_check() ÍÑ¥µ¥Ö´Ø¿ô¤È¥Ç¡¼¥¿
203 */
204 static const char LOGICAL_ERROR_PREFIX[] = "logical error:";
205 enum{
206         SCRIPT_PPUSIZE_0 = 0,
207         SCRIPT_MEMORYSIZE = 10,
208 };
209 struct logical_romsize{
210         const struct script *data[SCRIPT_MEMORYSIZE], *constant;
211         int count;
212 };
213 static int logical_flashsize_set(int region, struct logical_romsize *l, const struct script *s)
214 {
215         //PPU Íѥǡ¼¥¿¤Î 0 ¤Ï size 0, Äê¿ô 0 ¤È¤·¤ÆͽÌ󤵤ì¤Æ¤ª¤ê¡¢0¤Î¾ì¹ç¤Ï¤³¤³¤ò¾å½ñ¤­¤¹¤ë
216         if((region == MEMORY_AREA_PPU) && (s->value[0] == 0)){
217                 l->data[SCRIPT_PPUSIZE_0] = s;
218                 return OK;
219         }
220         if(l->count >= SCRIPT_MEMORYSIZE){
221                 const char *opstr;
222                 opstr = OPSTR_CPU_ROMSIZE; //warning Âкö
223                 switch(region){
224                 case MEMORY_AREA_CPU_ROM:
225                         opstr = OPSTR_CPU_ROMSIZE;
226                         break;
227                 case MEMORY_AREA_PPU:
228                         opstr = OPSTR_PPU_ROMSIZE;
229                         break;
230                 default:
231                         assert(0);
232                 }
233                 printf("%d:%s %s override count over\n", s->line, LOGICAL_ERROR_PREFIX, opstr);
234                 return NG;
235         }
236         l->data[l->count] = s;
237         l->count += 1;
238         return OK;
239 }
240
241 static int logical_flashsize_get(long transtype, long size, struct logical_romsize *l)
242 {
243         int i;
244         for(i = 0; i < l->count; i++){
245                 const struct script *s;
246                 s = l->data[i];
247                 if((s->value[0] == size) && (
248                         (s->value[1] == transtype) || 
249                         (s->value[1] == VALUE_TRANSTYPE_FULL)
250                 )){
251                         l->constant = s;
252                         return OK;
253                 }else if((s->value[0] == size) && (s->value[1] == VALUE_TRANSTYPE_EMPTY)){
254                         l->constant = s;
255                         return OK;
256                 }
257         }
258         printf("%s flashsize not found\n", LOGICAL_ERROR_PREFIX);
259         return NG;
260 }
261
262 static long constant_get(long val, const struct script *cpu, const struct script *ppu)
263 {
264         switch(val){
265         case VALUE_CONTANT_CPU_STEP_START:
266                 return cpu->value[2];
267         case VALUE_CONTANT_CPU_STEP_END:
268                 return cpu->value[3];
269         case VALUE_CONTANT_PPU_STEP_START:
270                 return ppu->value[2];
271         case VALUE_CONTANT_PPU_STEP_END:
272                 return ppu->value[3];
273         }
274         assert(0);
275         return -1;
276 }
277
278 static void logical_print_capacityerror(int line, const char *area)
279 {
280         printf("%d:%s %s area flash memory capacity error\n", line, LOGICAL_ERROR_PREFIX, area);
281 }
282
283 static inline void logical_print_illgalarea(int line, const char *area, long address)
284 {
285         printf("%d:%s illgal %s area $%06x\n", line, LOGICAL_ERROR_PREFIX, area, (int) address);
286 }
287
288 static inline void logical_print_illgallength(int line, const char *area, long length)
289 {
290         printf("%d:%s illgal %s length $%04x\n", line, LOGICAL_ERROR_PREFIX, area, (int) length);
291 }
292
293 static inline void logical_print_overdump(int line, const char *area, long start, long end)
294 {
295         printf("%d:%s %s area over dump $%06x-$%06x\n", line, LOGICAL_ERROR_PREFIX, area, (int)start ,(int)end);
296 }
297
298 static inline void logical_print_access(int line, const char *area, const char *rw, long addr, long len)
299 {
300         printf("%d:%s %s $%04x $%02x\n", line, area, rw, (int) addr, (int) len);
301 }
302
303 static inline void logical_print_byteerror(int line, const char *area, long data)
304 {
305         printf("%d:%s write data byte range over, %s $%x\n", line, LOGICAL_ERROR_PREFIX, area, (int) data);
306 }
307
308 static int dump_length_conform(const char *name, long logicallength, long configlength)
309 {
310         if(configlength != logicallength){
311                 printf("%s %s dump length error\n", LOGICAL_ERROR_PREFIX, name);
312                 printf("%s: 0x%06x, dump length: 0x%06x\n", name, (int) configlength, (int) logicallength);
313                 return 1;
314         }
315         return 0;
316 }
317 static inline int is_region_cpurom(long address)
318 {
319         return (address >= 0x8000) && (address < 0x10000);
320 }
321
322 static inline int is_region_cpuram(long address)
323 {
324         return (address >= 0x6000) && (address < 0x8000);
325 }
326
327 static inline int is_region_ppurom(long address)
328 {
329         return (address >= 0) && (address < 0x2000);
330 }
331
332 static inline int is_data_byte(long data)
333 {
334         return (data >= 0) && (data < 0x100);
335 }
336
337 //¤³¤ì¤À¤± is ·Ï¤Ç <= ±é»»»Ò¤ò»ÈÍѤ·¤Æ¤¤¤ë¤Î¤ÇÃí°Õ
338 static inline int is_range(long data, long start, long end)
339 {
340         return (data >= start) && (data <= end);
341 }
342 static const char STR_REGION_CPU[] = "cpu";
343 static const char STR_REGION_PPU[] = "ppu";
344 static const char STR_ACCESS_READ[] = "read";
345 static const char STR_ACCESS_WRITE[] = "write";
346
347 enum{
348         SETTING, DUMP, END, STEP_THOUGH
349 };
350 static int command_mask(const int region, const long address, const long offset, long size, struct flash_order *f)
351 {
352         const char *str_region = STR_REGION_CPU;
353         if(region == MEMORY_AREA_PPU){
354                 str_region = STR_REGION_PPU;
355         }
356         switch(region){
357         case MEMORY_AREA_CPU_ROM:
358                 switch(offset){
359                 case 0x8000: case 0xa000: case 0xc000:
360                         break;
361                 default:
362                         printf("%s %s_COMMAND area offset error\n", LOGICAL_ERROR_PREFIX, str_region);
363                         return NG;
364                 }
365                 switch(size){
366                 case 0x2000: case 0x4000: case 0x8000:
367                         break;
368                 default:
369                         printf("%s %s_COMMAND area mask error\n", LOGICAL_ERROR_PREFIX, str_region);
370                         return NG;
371                 }
372                 break;
373         case MEMORY_AREA_PPU:
374                 switch(offset){
375                 case 0x0000: case 0x0400: case 0x0800: case 0x0c00:
376                 case 0x1000: case 0x1400: case 0x1800: case 0x1c00:
377                         break;
378                 default:
379                         printf("%s %s_COMMAND area offset error\n", LOGICAL_ERROR_PREFIX, str_region);
380                         return NG;
381                 }
382                 switch(size){
383                 case 0x0400: case 0x0800: case 0x1000: case 0x2000: 
384                         break;
385                 default:
386                         printf("%s %s_COMMAND area mask error\n", LOGICAL_ERROR_PREFIX, str_region);
387                         return NG;
388                 }
389                 break;
390         default:
391                 assert(0); //unknown memory area
392         }
393
394         const long mask = size - 1;
395         const long data = (address & mask) | offset;
396         switch(address){
397         case 0:
398                 f->command_0000 = data;
399                 break;
400         case 0x2aaa: case 0x02aa: 
401                 f->command_2aaa = data;
402                 break;
403         case 0x5555: case 0x0555:
404                 f->command_5555 = data;
405                 break;
406         default:
407                 printf("%s %s_COMMAND unknown commnand address\n", LOGICAL_ERROR_PREFIX, str_region);
408                 return NG;
409         }
410         return OK;
411 }
412
413 enum{
414         STEP_VALIABLE = 0, STEP_START, STEP_END, STEP_NEXT,
415         STEP_NUM
416 };
417 static const struct script SCRIPT_PPU_ROMSIZE_0 = {
418         .opcode = SCRIPT_OPCODE_PPU_ROMSIZE,
419         .line = -1,
420         .value = {0, VALUE_TRANSTYPE_EMPTY, 0, 0},
421         //.expression, .variable Ì¤ÄêµÁ
422 };
423
424 static int logical_check(const struct script *s, const struct st_config *c, struct romimage *r)
425 {
426         //(CPU|PPU)_(READ|PROGRAM|RAMRW) ¤Î length ²Ã»»ÃÍ
427         long cpu_romsize = 0, cpu_ramsize = 0, ppu_romsize = 0;
428         //DUMP_START Ä¾¸å¤Ë ROM or RAM image ¤ò³«¤¯¥Õ¥é¥°
429         //use program mode or ram write mode
430         int imagesize = 0; //for write or program mode
431         int status = SETTING;
432         //override (CPU|PPU)_ROMSIZE pointer. Program mode only
433         struct logical_romsize script_cpu_flashsize = {
434                 .constant = NULL,
435                 .count = 0
436         };
437         struct logical_romsize script_ppu_flashsize = {
438                 .constant = NULL,
439                 .count = 1
440         };
441         script_ppu_flashsize.data[0] = &SCRIPT_PPU_ROMSIZE_0;
442         //logical error count. Ìá¤êÃÍ
443         int error = 0;
444         
445         variable_init_all();
446         while(s->opcode != SCRIPT_OPCODE_DUMP_END){
447                 if((status == DUMP) && (s->opcode < SCRIPT_OPCODE_DUMP_START)){
448                         printf("%d:%s config script include DUMP_START area\n", s->line, LOGICAL_ERROR_PREFIX);
449                         error += 1;
450                 }
451
452                 //romimage open for write or program mode
453                 if((imagesize == 0) && (status == DUMP)){
454                         switch(c->mode){
455                         case MODE_RAM_WRITE: //CPU_RAMSIZE check
456                                 assert(r->cpu_ram.attribute == MEMORY_ATTR_READ);
457                                 r->cpu_ram.data = buf_load_full(c->ramimage, &imagesize);
458                                 if(r->cpu_ram.data == NULL){
459                                         printf("%s RAM image open error\n", LOGICAL_ERROR_PREFIX);
460                                         imagesize = -1;
461                                         error += 1;
462                                 }else if(r->cpu_ram.size != imagesize){
463                                         printf("%s RAM image size is not same\n", LOGICAL_ERROR_PREFIX);
464                                         Free(r->cpu_ram.data);
465                                         r->cpu_ram.data = NULL;
466                                         imagesize = -1;
467                                         error += 1;
468                                 }
469                                 break;
470                         case MODE_ROM_PROGRAM: //MAPPER check
471                                 assert(c->cpu_flash_driver->program != NULL);
472                                 assert(r->cpu_rom.attribute == MEMORY_ATTR_READ);
473                                 assert(r->ppu_rom.attribute == MEMORY_ATTR_READ);
474                                 if(nesfile_load(LOGICAL_ERROR_PREFIX, c->romimage, r)== false){
475                                         error += 1;
476                                 }
477                                 //Äê¿ôÀë¸À¥¨¥é¡¼¤Ï̵¸Â¥ë¡¼¥×¤Î²ÄǽÀ­¤¬¤¢¤ë¤Î¤Ç¥¹¥¯¥ê¥×¥ÈÆâÉô¥Á¥§¥Ã¥¯¤ò¤»¤º¤Ë»ß¤á¤ë
478                                 if(logical_flashsize_get(c->transtype_cpu, r->cpu_rom.size, &script_cpu_flashsize) == NG){
479                                         return error + 1;
480                                 }
481                                 if(logical_flashsize_get(c->transtype_ppu, r->ppu_rom.size, &script_ppu_flashsize) == NG){
482                                         return error + 1;
483                                 }
484                                 //flash memory capacity check
485                                 if(r->cpu_rom.size > c->cpu_flash_driver->capacity){
486                                         logical_print_capacityerror(s->line, r->cpu_rom.name);
487                                         error += 1;
488                                 }
489                                 if((r->ppu_rom.size != 0) && (r->ppu_rom.size > c->ppu_flash_driver->capacity)){
490                                         logical_print_capacityerror(s->line, r->ppu_rom.name);
491                                         error += 1;
492                                 }
493                                 imagesize = -1;
494                                 break;
495                         default: 
496                                 imagesize = -1;
497                                 break;
498                         }
499                 }
500         
501                 switch(s->opcode){
502                 case SCRIPT_OPCODE_COMMENT:
503                         break;
504                 case SCRIPT_OPCODE_MAPPER:
505                         r->mappernum = s->value[0];
506                         break;
507                 case SCRIPT_OPCODE_MIRROR:
508                         r->mirror = s->value[0];
509                         break;
510                 case SCRIPT_OPCODE_CPU_ROMSIZE:{
511                         const long size = s->value[0];
512                         r->cpu_rom.size = size;
513                         if(memorysize_check(size, MEMORY_AREA_CPU_ROM)){
514                                 printf("%s %s length error\n", LOGICAL_ERROR_PREFIX, OPSTR_CPU_ROMSIZE);
515                                 error += 1;
516                         }
517                         }break;
518                 case SCRIPT_OPCODE_CPU_FLASHSIZE:
519                         if(logical_flashsize_set(MEMORY_AREA_CPU_ROM, &script_cpu_flashsize, s) == NG){
520                                 error += 1;
521                         }break;
522                 case SCRIPT_OPCODE_CPU_RAMSIZE:
523                         //memory size ¤Ï̤³ÎÄêÍ×ÁǤ¬Â¿¤¤¤Î¤Ç check ¤òÈ´¤¯
524                         r->cpu_ram.size = s->value[0];
525                         break;
526                 case SCRIPT_OPCODE_CPU_COMMAND:
527                         if(command_mask(MEMORY_AREA_CPU_ROM, s->value[0], s->value[1], s->value[2], &(r->cpu_flash)) == NG){
528                                 error += 1;
529                         }
530                         break;
531                 case SCRIPT_OPCODE_PPU_ROMSIZE:{
532                         const long size = s->value[0];
533                         r->ppu_rom.size = size;
534                         if(memorysize_check(size, MEMORY_AREA_PPU)){
535                                 printf("%s %s length error\n", LOGICAL_ERROR_PREFIX, OPSTR_PPU_ROMSIZE);
536                                 error += 1;
537                         }
538                         }break;
539                 case SCRIPT_OPCODE_PPU_FLASHSIZE:
540                         if(logical_flashsize_set(MEMORY_AREA_PPU, &script_ppu_flashsize, s) == NG){
541                                 error += 1;
542                         }
543                         break;
544                 case SCRIPT_OPCODE_PPU_COMMAND:
545                         if(command_mask(MEMORY_AREA_PPU, s->value[0], s->value[1], s->value[2], &(r->ppu_flash)) == NG){
546                                 error += 1;
547                         }
548                         break;
549                 case SCRIPT_OPCODE_DUMP_START:
550                         status = DUMP;
551                         break;
552                 case SCRIPT_OPCODE_CPU_READ:{
553                         const long address = s->value[0];
554                         const long length = s->value[1];
555                         const long end = address + length - 1;
556                         
557                         assert(r->cpu_rom.attribute == MEMORY_ATTR_WRITE);
558                         //length filter. 0 ¤Ï¤À¤á
559                         if(!is_range(length, 1, 0x4000)){
560                                 logical_print_illgallength(s->line, STR_REGION_CPU, length);
561                                 error += 1;
562                         }
563                         //address filter
564                         else if(!is_region_cpurom(address)){
565                                 logical_print_illgalarea(s->line, STR_REGION_CPU, address);
566                                 error += 1;
567                         }else if(end >= 0x10000){
568                                 logical_print_overdump(s->line, STR_REGION_CPU, address, end);
569                                 error += 1;
570                         }
571                         cpu_romsize += length;
572                         status = DUMP;
573                         }
574                         break;
575                 case SCRIPT_OPCODE_CPU_WRITE:{
576                         const long address = s->value[0];
577                         long data;
578                         if(expression_calc(&s->expression, &data) == NG){
579                                 printf("%d:%s expression calc error\n", s->line, LOGICAL_ERROR_PREFIX);
580                                 error += 1;
581                         }
582                         if(address < 0x5000 || address >= 0x10000){
583                                 logical_print_illgalarea(s->line, STR_REGION_CPU, address);
584                                 error += 1;
585                         }else if(!is_data_byte(data)){
586                                 logical_print_byteerror(s->line, STR_REGION_CPU, data);
587                                 error += 1;
588                         }
589                         status = DUMP;
590                         }
591                         break;
592                 case SCRIPT_OPCODE_CPU_RAMRW:{
593                         const long address = s->value[0];
594                         const long length = s->value[1];
595                         const long end = address + length - 1;
596                         switch(c->mode){
597                         case MODE_RAM_READ:
598                                 assert(r->cpu_ram.attribute == MEMORY_ATTR_WRITE);
599                                 break;
600                         case MODE_RAM_WRITE:
601                                 assert(r->cpu_ram.attribute == MEMORY_ATTR_READ);
602                                 break;
603                         }
604                         //length filter. 0 ¤Ï¤À¤á
605                         if(!is_range(length, 1, 0x2000)){
606                                 logical_print_illgallength(s->line, STR_REGION_CPU, length);
607                                 error += 1;
608                         }
609                         //address filter
610                         else if(address < 0x5c00 || address >= 0xc000){
611                                 logical_print_illgalarea(s->line, STR_REGION_CPU, address);
612                                 error += 1;
613                         }else if(0 && end >= 0x8000){
614                                 logical_print_overdump(s->line, STR_REGION_CPU, address, end);
615                                 error += 1;
616                         }
617                         cpu_ramsize += length;
618                         status = DUMP;
619                         }
620                         break;
621                 case SCRIPT_OPCODE_CPU_PROGRAM:{
622                         const long address = s->value[0];
623                         const long length = s->value[1];
624                         const long end = address + length - 1;
625                         
626                         assert(r->cpu_rom.attribute == MEMORY_ATTR_READ);
627                         assert(r->ppu_rom.attribute == MEMORY_ATTR_READ);
628                         //length filter.
629                         if(!is_range(length, 0x80, 0x4000)){
630                                 logical_print_illgallength(s->line, STR_REGION_CPU, length);
631                                 error += 1;
632                         }
633                         //address filter
634                         else if(!is_region_cpurom(address)){
635                                 logical_print_illgalarea(s->line, STR_REGION_CPU, address);
636                                 error += 1;
637                         }else if(end >= 0x10000){
638                                 logical_print_overdump(s->line, STR_REGION_CPU, address, end);
639                                 error += 1;
640                         }
641                         cpu_romsize += length;
642                         status = DUMP;
643                         }
644                         break;
645                 case SCRIPT_OPCODE_PPU_RAMFIND:
646                         //¥ë¡¼¥×ÆâÉô¤ËÆþ¤Ã¤Æ¤¿¤é¥¨¥é¡¼
647                         if(variable_num != 0){
648                                 printf("%d:%s PPU_RAMTEST must use outside loop\n", s->line, LOGICAL_ERROR_PREFIX);
649                                 error += 1;
650                         }
651                         break;
652                 case SCRIPT_OPCODE_PPU_SRAMTEST:
653                 case SCRIPT_OPCODE_PPU_READ:{
654                         const long address = s->value[0];
655                         const long length = s->value[1];
656                         const long end = address + length - 1;
657                         assert(r->ppu_rom.attribute == MEMORY_ATTR_WRITE);
658                         //length filter. 0 ¤òÍÆǧ¤¹¤ë
659                         long min = 0;
660                         if(s->opcode == SCRIPT_OPCODE_PPU_SRAMTEST){
661                                 min = 1;
662                         }
663                         if(!is_range(length, min, 0x2000)){
664                                 logical_print_illgallength(s->line, STR_REGION_PPU, length);
665                                 error += 1;
666                         }
667                         //address filter
668                         else if(!is_region_ppurom(address)){
669                                 logical_print_illgalarea(s->line, STR_REGION_PPU, address);
670                                 error += 1;
671                         }else if (end >= 0x2000){
672                                 logical_print_overdump(s->line, STR_REGION_PPU, address, end);
673                                 error += 1;
674                         }
675                         //dump length update
676                         if((s->opcode == SCRIPT_OPCODE_PPU_READ) && is_region_ppurom(address)){
677                                 ppu_romsize += length;
678                         }
679                         status = DUMP;
680                         }
681                         break;
682                 case SCRIPT_OPCODE_PPU_WRITE:{
683                         if(DEBUG==0){
684                                 break;
685                         }
686                         const long address = s->value[0];
687                         long data;
688                         if(expression_calc(&s->expression, &data) == NG){
689                                 printf("%d:%s expression calc error\n", s->line, LOGICAL_ERROR_PREFIX);
690                                 error += 1;
691                         }
692                         status = DUMP;
693                         if(!is_region_ppurom(address)){
694                                 logical_print_illgalarea(s->line, STR_REGION_PPU, address);
695                                 error += 1;
696                         }else if(!is_data_byte(data)){
697                                 logical_print_byteerror(s->line, STR_REGION_PPU, data);
698                                 error += 1;
699                         }
700                         status = DUMP;
701                         }
702                         break;
703                 case SCRIPT_OPCODE_PPU_PROGRAM:{
704                         const long address = s->value[0];
705                         const long length = s->value[1];
706                         const long end = address + length - 1;
707                         
708                         assert(r->ppu_rom.attribute == MEMORY_ATTR_READ);
709                         assert(r->ppu_rom.size != 0);
710
711                         //length filter.
712                         if(!is_range(length, 0x80, 0x1000)){
713                                 logical_print_illgallength(s->line, STR_REGION_PPU, length);
714                                 error += 1;
715                         }
716                         //address filter
717                         else if(!is_region_ppurom(address)){
718                                 logical_print_illgalarea(s->line, STR_REGION_PPU, address);
719                                 error += 1;
720                         }else if(end >= 0x2000){
721                                 logical_print_overdump(s->line, STR_REGION_PPU, address, end);
722                                 error += 1;
723                         }
724                         ppu_romsize += length;
725                         status = DUMP;
726                         }
727                         break;
728                 case SCRIPT_OPCODE_STEP_START:{
729                         const struct step_syntax{
730                                 long start, end;
731                                 int constant;
732                                 const char *name;
733                         } RANGE[STEP_NUM] = {
734                                 {.start = 0, .end = 0, .constant = NG, .name = "variable"},
735                                 {.start = 0, .end = 0xff, .constant = OK, .name = "start"},
736                                 {.start = 0, .end = 0x100, .constant = OK, .name = "end"},
737                                 {.start = 1, .end = 0x100, .constant = NG, .name = "next"}
738                         };
739                         int i;
740                         for(i = STEP_START; i < STEP_NUM; i++){
741                                 const struct step_syntax *ss;
742                                 ss = &RANGE[i];
743                                 //Äê¿ôobject ¤ò¼Â¿ô¤ËÊÑ´¹¤¹¤ë¤¿¤á¡¢const ¤ò³°¤·¤Æ½ñ¤­´¹¤¨¤ë
744                                 long *v;
745                                 v = (long *) &s->value[i];
746                                 if((ss->constant == OK) && (is_range(*v, VALUE_CONTANT_CPU_STEP_START, VALUE_CONTANT_PPU_STEP_END))){
747                                         //VALUE_CONSTANT_xxx ¤ò¼ÂºÝ¤Ë»È¤ï¤ì¤ëÄê¿ô¤Ë¤·¤Æ¡¢¥¹¥¯¥ê¥×¥È¥Ç¡¼¥¿¤òÄ¥¤êÂؤ¨¤ë
748                                         *v = constant_get(*v, script_cpu_flashsize.constant, script_ppu_flashsize.constant);
749                                 }
750                                 if(!is_range(*v, ss->start, ss->end)){
751                                         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);
752                                         error += 1;
753                                 }
754                         }
755                         //charcter RAM ¤ÎÍͤˠstep ÆâÉô¤ò¹Ô¤ï¤Ê¤¤¾ì¹ç¤Îscript¾õÂÖ¤ÎÊѹ¹
756                         if(s->value[STEP_START] >= s->value[STEP_END]){
757                                 status = STEP_THOUGH;
758                         }
759                         //¥ë¡¼¥×¤ÎÌá¤êÀè¤Ï¤³¤ÎÌ¿Îá¤Î¼¡¤Ê¤Î¤Ç s[1]
760                         else if(step_new(s->variable, s->value[STEP_START], s->value[STEP_END], s->value[STEP_NEXT], &s[1]) == NG){
761                                 printf("%d:%s step loop too much\n", s->line, LOGICAL_ERROR_PREFIX);
762                                 error += 1;
763                                 return error;
764                         }else{
765                                 status = DUMP;
766                         }
767                         }break;
768                 case SCRIPT_OPCODE_DUMP_END:
769                         status = END;
770                         break;
771                 }
772                 
773                 //status Ê̤ˠscript ¤ÎÀ©¸æ. while ¤òÈ´¤±¤ë¤Î¤Ç switch ¤ò»È¤¨¤Ê¤¤
774                 if(status == END){
775                         break;
776                 }else if(status == STEP_THOUGH){
777                         int stepcount = 1;
778                         int end = 0;
779                         while(s->opcode != SCRIPT_OPCODE_DUMP_END){
780                                 switch(s->opcode){
781                                 case SCRIPT_OPCODE_STEP_START:
782                                         stepcount++;
783                                         break;
784                                 case SCRIPT_OPCODE_STEP_END:
785                                         stepcount--;
786                                         if(stepcount == 0){
787                                                 end = 1;
788                                         }
789                                         break;
790                                 }
791                                 s++;
792                                 if(end == 1){
793                                         break;
794                                 }
795                         }
796                         status = DUMP;
797                 }
798                 //opcode Ê̤ˠscript ¤ÎÀ©¸æ. while ¤òÈ´¤±¤ë¤Î¤Ç switch ¤ò»È¤¨¤Ê¤¤
799                 if(s->opcode == SCRIPT_OPCODE_STEP_END){
800                         if(variable_num == 0){
801                                 printf("%d:%s loop closed, missing STEP_START\n", s->line, LOGICAL_ERROR_PREFIX);
802                                 return error + 1;
803                         }
804                         s = step_end(&s[1]);
805                         status = DUMP;
806                 }else if(s->opcode == SCRIPT_OPCODE_DUMP_END){
807                         break;
808                 }else{
809                         s++;
810                 }
811         }
812         
813         //loop open conform
814         if(variable_num != 0){
815                 printf("%d:%s loop opened, missing STEP_END\n", s->line, LOGICAL_ERROR_PREFIX);
816                 error += 1;
817         }
818         //dump length conform
819         error += dump_length_conform(OPSTR_CPU_ROMSIZE, cpu_romsize, r->cpu_rom.size);
820         error += dump_length_conform(OPSTR_CPU_RAMSIZE, cpu_ramsize, r->cpu_ram.size);
821         error += dump_length_conform(OPSTR_PPU_ROMSIZE, ppu_romsize, r->ppu_rom.size);
822         
823         //command line config override
824         if(c->mirror != CONFIG_OVERRIDE_UNDEF){
825                 r->mirror = c->mirror;
826         }
827         if(c->backupram != CONFIG_OVERRIDE_UNDEF){
828                 r->backupram = 1;
829         }
830         if(c->mapper != CONFIG_OVERRIDE_UNDEF){
831                 //program mode ¤Ç mapper Êѹ¹¤òËɤ°
832                 assert(c->mode == MODE_ROM_DUMP);
833                 r->mappernum = c->mapper;
834         }
835         if(c->syntaxtest == 1){
836                 if(error == 0){
837                         printf("syntax ok!\n");
838                 }
839                 error += 1;
840         }
841         return error;
842 }
843
844 /*
845 execute() ÍÑ¥µ¥Ö´Ø¿ô¤È¥Ç¡¼¥¿
846 */
847 static int execute_connection_check(const struct reader_driver *d)
848 {
849         int ret = OK;
850         const int testsize = 0x80;
851         int testcount = 3;
852         uint8_t *master, *reload;
853         master = Malloc(testsize);
854         reload = Malloc(testsize);
855
856         d->cpu_read(0xfee0, testsize, master);
857         
858         while(testcount != 0){
859                 d->cpu_read(0xfee0, testsize, reload);
860                 if(memcmp(master, reload, testsize) != 0){
861                         ret = NG;
862                         break;
863                 }
864                 testcount--;
865         }
866         
867         Free(master);
868         Free(reload);
869         return ret;
870 }
871
872 enum {PPU_TEST_RAM, PPU_TEST_ROM};
873 const uint8_t PPU_TEST_DATA[] = "PPU_TEST_DATA";
874 static int ppu_ramfind(const struct reader_driver *d)
875 {
876         const long length = sizeof(PPU_TEST_DATA);
877         const long testaddr = 123;
878         uint8_t writedata[length];
879         //ppu ram data fill 0
880         memset(writedata, 0, length);
881         d->ppu_write(testaddr, length, writedata);
882         
883         //ppu test data write
884         d->ppu_write(testaddr, length, PPU_TEST_DATA);
885
886         d->ppu_read(testaddr, length, writedata);
887         if(memcmp(writedata, PPU_TEST_DATA, length) == 0){
888                 return PPU_TEST_RAM;
889         }
890         return PPU_TEST_ROM;
891 }
892
893 static int ramtest(const int region, const struct reader_driver *d, long address, long length, uint8_t *writedata, uint8_t *testdata, const long filldata)
894 {
895         memset(writedata, filldata, length);
896         switch(region){
897         case MEMORY_AREA_CPU_RAM:
898                 d->cpu_write_6502(address, length, writedata);
899                 break;
900         case MEMORY_AREA_PPU:
901                 d->ppu_write(address, length, writedata);
902                 break;
903         default:
904                 assert(0);
905         }
906         switch(region){
907         case MEMORY_AREA_CPU_RAM:
908                 d->cpu_read(address, length, testdata);
909                 break;
910         case MEMORY_AREA_PPU:
911                 d->ppu_read(address, length, testdata);
912                 break;
913         default:
914                 assert(0);
915         }
916         if(memcmp(writedata, testdata, length) == 0){
917                 return 0;
918         }
919         return 1;
920 }
921
922 static const long SRAMTESTDATA[] = {0xff, 0xaa, 0x55, 0x00};
923 static int sramtest(const int region, const struct reader_driver *d, long address, long length)
924 {
925         uint8_t *writedata, *testdata;
926         int error = 0;
927         int i;
928         testdata = Malloc(length);
929         writedata = Malloc(length);
930         for(i = 0; i < sizeof(SRAMTESTDATA) / sizeof(long); i++){
931                 const long filldata = SRAMTESTDATA[i];
932                 error += ramtest(region, d, address, length, testdata, writedata, filldata);
933         }
934         Free(testdata);
935         Free(writedata);
936         return error;
937 }
938
939 static void readbuffer_print(const struct memory *m, long length)
940 {
941         if(length >= 0x10){
942                 length = 0x10;
943         }
944         printf("%s ROM 0x%05x:", m->name, m->offset);
945         int offset = 0;
946         const uint8_t *data;
947         data = m->data;
948         while(length != 0){
949                 char safix;
950                 switch(offset & 0xf){
951                 default:
952                         safix = ' ';
953                         break;
954                 case 0x7:
955                         safix = '-';
956                         break;
957                 case 0xf:
958                         safix = ';';
959                         break;
960                 }
961                 printf("%02x%c", (int) *data, safix);
962                 data++;
963                 offset++;
964                 length--;
965         }
966 }
967
968 static void checksum_print(const uint8_t *data, long length)
969 {
970         int sum = 0;
971         while(length != 0){
972                 sum += (int) *data;
973                 data++;
974                 length--;
975         }
976         printf(" 0x%06x\n", sum);
977 }
978
979 static void read_result_print(const struct memory *m, long length)
980 {
981         readbuffer_print(m, length);
982         checksum_print(m->data, length);
983         fflush(stdout);
984 }
985
986 static void execute_program_begin(const struct memory *m, const long length)
987 {
988         int tail = m->offset + (int) length - 1;
989         printf("writing %s area 0x%06x-0x%06x ... ", m->name, m->offset, tail);
990         fflush(stdout);
991 }
992
993 static const char STR_OK[] = "OK";
994 static const char STR_NG[] = "NG";
995
996 //memcmp ¤ÎÌá¤êÃͤ¬Æþ¤ë¤Î¤Ç 0 ¤¬Àµ¾ï
997 static void execute_program_finish(int result)
998 {
999         const char *str;
1000         str = STR_NG;
1001         if(result == 0){
1002                 str = STR_OK;
1003         }
1004         printf("%s\n", str);
1005         fflush(stdout);
1006 }
1007 static const char EXECUTE_ERROR_PREFIX[] = "execute error:";
1008 static const char EXECUTE_PROGRAM_PREPARE[] = "%s device initialize ... ";
1009 static const char EXECUTE_PROGRAM_DONE[] = "done\n";
1010 static void execute_cpu_ramrw(const struct reader_driver *d, const struct memory *ram, int mode, long address, long length)
1011 {
1012         if(mode == MODE_RAM_WRITE){
1013                 d->cpu_write_6502(address, length, ram->data);
1014 /*              const uint8_t *writedata;
1015                 long a = address;
1016                 long l = length;
1017                 writedata = ram->data;
1018                 while(l != 0){
1019                         d->cpu_write_6502(a++, *writedata, wait);
1020                         writedata += 1;
1021                         l--;
1022                 }*/
1023                 uint8_t *compare;
1024                 compare = Malloc(length);
1025                 d->cpu_read(address, length, compare);
1026                 if(memcmp(ram->data, compare, length) == 0){
1027                         printf("RAM data write success\n");
1028                 }else{
1029                         printf("RAM data write failed\n");
1030                 }
1031                 Free(compare);
1032         }else{
1033                 d->cpu_read(address, length, ram->data);
1034         }
1035 }
1036
1037 static int execute(const struct script *s, const struct st_config *c, struct romimage *r)
1038 {
1039         const struct reader_driver *const d = c->reader;
1040         switch(d->open_or_close(READER_OPEN)){
1041         case OK:
1042                 d->init();
1043                 break;
1044         case NG:
1045                 printf("%s driver open error\n", EXECUTE_ERROR_PREFIX);
1046                 return NG;
1047         default:
1048                 assert(0);
1049         }
1050         if(execute_connection_check(d) == NG){
1051                 printf("%s maybe connection error\n", EXECUTE_ERROR_PREFIX);
1052                 d->open_or_close(READER_CLOSE);
1053                 return NG;
1054         }
1055         uint8_t *program_compare;
1056         program_compare = NULL;
1057         if(c->mode == MODE_ROM_PROGRAM){
1058                 printf("flashmemory/SRAM program mode. To abort programming, press Ctrl+C\n");
1059                 int size = r->cpu_rom.size;
1060                 if(size < r->ppu_rom.size){
1061                         size = r->ppu_rom.size;
1062                 }
1063                 program_compare = Malloc(size);
1064         }
1065         struct memory cpu_rom, ppu_rom, cpu_ram;
1066         cpu_rom = r->cpu_rom;
1067         ppu_rom = r->ppu_rom;
1068         cpu_ram = r->cpu_ram;
1069         
1070         int status = DUMP;
1071         int programcount_cpu = 0, programcount_ppu = 0;
1072         int flashcommand_change_cpu = 0, flashcommand_change_ppu = 0;
1073         variable_init_all();
1074         while(s->opcode != SCRIPT_OPCODE_DUMP_END){
1075                 //printf("%s\n", SCRIPT_SYNTAX[s->opcode].name);
1076                 switch(s->opcode){
1077                 case SCRIPT_OPCODE_CPU_COMMAND:
1078                         command_mask(MEMORY_AREA_CPU_ROM, s->value[0], s->value[1], s->value[2], &(r->cpu_flash));
1079                         flashcommand_change_cpu = 1;
1080                         break;
1081                 case SCRIPT_OPCODE_CPU_READ:{
1082                         struct memory *m;
1083                         const long address = s->value[0];
1084                         const long length = s->value[1];
1085                         m = &cpu_rom;
1086                         d->cpu_read(address, length, m->data);
1087                         read_result_print(m, length);
1088                         m->data += length;
1089                         m->offset += length;
1090                         }break;
1091                 case SCRIPT_OPCODE_CPU_WRITE:{
1092                         long data;
1093                         uint8_t d8;
1094                         expression_calc(&s->expression, &data);
1095                         d8 = data & 0xff;
1096                         d->cpu_write_6502(s->value[0], 1, &d8);
1097                         }
1098                         break;
1099                 case SCRIPT_OPCODE_CPU_RAMRW:{
1100                         const long address = s->value[0];
1101                         const long length = s->value[1];
1102                         if(c->mode == MODE_RAM_WRITE){
1103                                 if(sramtest(MEMORY_AREA_CPU_RAM, d, address, length) != 0){
1104                                         printf("SRAM test NG\n");
1105                                         status = END;
1106                                         break;
1107                                 }
1108                         }
1109                         execute_cpu_ramrw(d, &cpu_ram, c->mode, address, length);
1110                         read_result_print(&cpu_ram, length);
1111                         cpu_ram.data += length;
1112                         cpu_ram.offset += length;
1113                         }
1114                         break;
1115                 case SCRIPT_OPCODE_CPU_PROGRAM:{
1116                         if(c->cpu_flash_driver->id_device == FLASH_ID_DEVICE_DUMMY){
1117                                 break;
1118                         }
1119                         if(flashcommand_change_cpu != 0){
1120                                 r->cpu_flash.config(
1121                                         r->cpu_flash.command_0000,
1122                                         r->cpu_flash.command_2aaa,
1123                                         r->cpu_flash.command_5555,
1124                                         r->cpu_flash.pagesize,
1125                                         false
1126                                 );
1127                                 flashcommand_change_cpu = 0;
1128                         }
1129                         if(programcount_cpu++ == 0){
1130                                 printf(EXECUTE_PROGRAM_PREPARE, cpu_rom.name);
1131                                 fflush(stdout);
1132                                 //device ¤Ë¤è¤Ã¤Æ¤Ï erase
1133                                 c->cpu_flash_driver->init(&(r->cpu_flash), c->cpu_flash_driver->erase_wait);
1134                                 printf(EXECUTE_PROGRAM_DONE);
1135                                 fflush(stdout);
1136                         }
1137                         const long address = s->value[0];
1138                         const long length = s->value[1];
1139                         execute_program_begin(&cpu_rom, length);
1140                         c->cpu_flash_driver->program(
1141                                 &(r->cpu_flash),
1142                                 address, length,
1143                                 &cpu_rom
1144                         );
1145                         int result;
1146                         if(1){
1147                                 d->cpu_read(address, length, program_compare);
1148                                 result = memcmp(program_compare, cpu_rom.data, length);
1149                                 execute_program_finish(result);
1150                         }else{
1151                                 puts("skip");
1152                                 result = 1;
1153                         }
1154                         cpu_rom.data += length;
1155                         cpu_rom.offset += length;
1156                         
1157                         if((DEBUG==0) && (result != 0)){
1158                                 status = END;
1159                         }
1160                         }
1161                         break;
1162                 case SCRIPT_OPCODE_PPU_COMMAND:
1163                         command_mask(MEMORY_AREA_PPU, s->value[0], s->value[1], s->value[2], &(r->ppu_flash));
1164                         flashcommand_change_ppu = 1;
1165                         break;
1166                 case SCRIPT_OPCODE_PPU_RAMFIND:
1167                         if(ppu_ramfind(d) == PPU_TEST_RAM){
1168                                 printf("PPU_RAMFIND: charcter RAM found\n");
1169                                 r->ppu_rom.size = 0;
1170                                 status = END;
1171                         }
1172                         break;
1173                 case SCRIPT_OPCODE_PPU_SRAMTEST:{
1174                         const long address = s->value[0];
1175                         const long length = s->value[1];
1176                         printf("PPU_SRAMTEST: 0x%06x-0x%06x ", (int)ppu_rom.offset, (int) (ppu_rom.offset + length) - 1);
1177                         if(sramtest(MEMORY_AREA_PPU, d, address, length) == 0){
1178                                 printf("%s\n", STR_OK);
1179                         }else{
1180                                 printf("%s\n", STR_NG);
1181                                 //status = END;
1182                         }
1183                         }break;
1184                 case SCRIPT_OPCODE_PPU_READ:{
1185                         const long address = s->value[0];
1186                         const long length = s->value[1];
1187                         if(length == 0){
1188                                 /*for mmc2,4 protect.
1189                                 ¤³¤Î¤È¤­¤Ï1byteÆɤ߹þ¤ó¤Ç¡¢¤½¤ÎÆâÍƤϥХåե¡¤Ë¤¤¤ì¤Ê¤¤*/
1190                                 uint8_t dummy;
1191                                 d->ppu_read(address, 1, &dummy);
1192                         }else{
1193                                 d->ppu_read(address, length, ppu_rom.data);
1194                                 read_result_print(&ppu_rom, length);
1195                         }
1196                         ppu_rom.data += length;
1197                         ppu_rom.offset += length;
1198                         }
1199                         break;
1200                 case SCRIPT_OPCODE_PPU_WRITE:
1201                         if(DEBUG == 1){
1202                                 long data;
1203                                 uint8_t d8;
1204                                 expression_calc(&s->expression, &data);
1205                                 d8 = data;
1206                                 d->ppu_write(s->value[0], 1, &d8);
1207                         }
1208                         break;
1209                 case SCRIPT_OPCODE_PPU_PROGRAM:{
1210                         if(c->ppu_flash_driver->id_device == FLASH_ID_DEVICE_DUMMY){
1211                                 break;
1212                         }
1213                         if(flashcommand_change_ppu != 0){
1214                                 r->ppu_flash.config(
1215                                         r->ppu_flash.command_0000,
1216                                         r->ppu_flash.command_2aaa,
1217                                         r->ppu_flash.command_5555,
1218                                         r->ppu_flash.pagesize,
1219                                         false
1220                                 );
1221                                 flashcommand_change_ppu = 0;
1222                         }
1223                         if(programcount_ppu++ == 0){
1224                                 printf(EXECUTE_PROGRAM_PREPARE, ppu_rom.name);
1225                                 fflush(stdout);
1226                                 c->ppu_flash_driver->init(&(r->ppu_flash), c->ppu_flash_driver->erase_wait);
1227                                 printf(EXECUTE_PROGRAM_DONE);
1228                                 fflush(stdout);
1229                         }
1230                         const long address = s->value[0];
1231                         const long length = s->value[1];
1232                         execute_program_begin(&ppu_rom, length);
1233                         c->ppu_flash_driver->program(
1234                                 &(r->ppu_flash),
1235                                 address, length,
1236                                 &ppu_rom
1237                         );
1238                         d->ppu_read(address, length, program_compare);
1239                         const int result = memcmp(program_compare, ppu_rom.data, length);
1240                         execute_program_finish(result);
1241                         ppu_rom.data += length;
1242                         ppu_rom.offset += length;
1243                         
1244                         if((DEBUG==0) && (result != 0)){
1245                                 status = END;
1246                         }
1247                         }
1248                         break;
1249                 case SCRIPT_OPCODE_STEP_START:{
1250                         if(s->value[STEP_START] >= s->value[STEP_END]){
1251                                 status = STEP_THOUGH;
1252                         }else{
1253                                 //¥ë¡¼¥×¤ÎÌá¤êÀè¤Ï¤³¤ÎÌ¿Îá¤Î¼¡¤Ê¤Î¤Ç &s[1]
1254                                 step_new(s->variable, s->value[STEP_START], s->value[STEP_END], s->value[STEP_NEXT], &s[1]);
1255                         }
1256                         }break;
1257                 case SCRIPT_OPCODE_DUMP_END:
1258                         status = END;
1259                         break;
1260                 }
1261                 if(status == END){
1262                         break;
1263                 }else if(status == STEP_THOUGH){
1264                         //¤³¤Ô¤Ú
1265                         int stepcount = 1;
1266                         int end = 0;
1267                         while(s->opcode != SCRIPT_OPCODE_DUMP_END){
1268                                 switch(s->opcode){
1269                                 case SCRIPT_OPCODE_STEP_START:
1270                                         stepcount++;
1271                                         break;
1272                                 case SCRIPT_OPCODE_STEP_END:
1273                                         stepcount--;
1274                                         if(stepcount == 0){
1275                                                 end = 1;
1276                                         }
1277                                         break;
1278                                 }
1279                                 s++;
1280                                 if(end == 1){
1281                                         break;
1282                                 }
1283                         }
1284                         status = DUMP;
1285                 }
1286                 
1287                 if(s->opcode == SCRIPT_OPCODE_STEP_END){
1288                         s = step_end(++s);
1289                 }else{
1290                         s++;
1291                 }
1292         }
1293         d->open_or_close(READER_CLOSE);
1294         if(program_compare != NULL){
1295                 Free(program_compare);
1296         }
1297         return OK;
1298 }
1299
1300 void script_load(const struct st_config *c)
1301 {
1302         struct script *s;
1303         {
1304                 int scriptsize = 0;
1305                 char *buf;
1306                 
1307                 buf = buf_load_full(c->script, &scriptsize);
1308                 if(buf == NULL){
1309                         printf("scriptfile open error\n");
1310                         return;
1311                 }
1312                 char **text;
1313                 text = Malloc(sizeof(char*) * TEXT_MAXLINE);
1314                 const int text_num = text_load(buf, scriptsize, text);
1315                 if(text_num == 0){
1316                         printf("script line too much\n");
1317                         Free(buf);
1318                         Free(text);
1319                         return;
1320                 }
1321                 s = Malloc(sizeof(struct script) * (text_num + 1));
1322                 //logical_check, execute ¶¦¤Ë s->opcode ¤¬ DUMP_END ¤Ë¤Ê¤ë¤Þ¤Ç³¤±¤ë¡£DUMP_END ¤ÎÆþ¤ì˺¤ìÍѤËËöÈø¤Îscript¤Ëɬ¤º DUMP_END ¤ò¤¤¤ì¤ë
1323                 {
1324                         struct script *k;
1325                         k = s;
1326                         k += text_num;
1327                         k->opcode = SCRIPT_OPCODE_DUMP_END;
1328                 }
1329                 const int error = syntax_check(text, text_num, s, c->mode);
1330                 Free(buf);
1331                 Free(text);
1332                 if(error != 0){
1333                         Free(s);
1334                         return;
1335                 }
1336         }
1337         struct romimage r = {
1338                 .cpu_rom = {
1339                         .size = 0, .offset = 0,
1340                         .data = NULL,
1341                         .attribute = MEMORY_ATTR_NOTUSE,
1342                         .name = "program"
1343                 },
1344                 .ppu_rom = {
1345                         .size = 0, .offset = 0,
1346                         .data = NULL,
1347                         .attribute = MEMORY_ATTR_NOTUSE,
1348                         .name = "charcter"
1349                 },
1350                 .cpu_ram = {
1351                         .size = 0, .offset = 0,
1352                         .data = NULL,
1353                         .attribute = MEMORY_ATTR_NOTUSE,
1354                         .name = STR_REGION_CPU
1355                 },
1356                 //device ¤Ë±þ¤¸¤¿´Ø¿ô¥Ý¥¤¥ó¥¿¤ò flash_order ¤ËÅϤ¹
1357                 .cpu_flash = {
1358                         .command_0000 = 0x8000,
1359                         .command_2aaa = 0,
1360                         .command_5555 = 0,
1361                         .pagesize = c->cpu_flash_driver->pagesize,
1362                         .command_mask = c->cpu_flash_driver->command_mask,
1363                         .config = c->reader->cpu_flash_config,
1364                         .erase = c->reader->cpu_flash_erase,
1365                         .program = c->reader->cpu_flash_program,
1366                         .write = NULL //c->reader->cpu_write_6502
1367                 },
1368                 .ppu_flash = {
1369                         .command_0000 = 0,
1370                         .command_2aaa = 0,
1371                         .command_5555 = 0,
1372                         .pagesize = c->ppu_flash_driver->pagesize,
1373                         .command_mask = c->ppu_flash_driver->command_mask,
1374                         .config = c->reader->ppu_flash_config,
1375                         .erase = c->reader->ppu_flash_erase,
1376                         .program = c->reader->ppu_flash_program,
1377                         .write = NULL //c->reader->ppu_write
1378                 },
1379                 .mappernum = 0,
1380                 .mirror = MIRROR_PROGRAMABLE
1381         };
1382         //attribute ¤Ï¤½¤Î struct data ¤ËÂФ·¤Æ¤Î RW ¤Ê¤Î¤ÇÍ×Ãí°Õ
1383         switch(c->mode){
1384         case MODE_ROM_DUMP:
1385                 r.cpu_rom.attribute = MEMORY_ATTR_WRITE;
1386                 r.ppu_rom.attribute = MEMORY_ATTR_WRITE;
1387                 break;
1388         case MODE_RAM_READ:
1389                 r.cpu_ram.attribute = MEMORY_ATTR_WRITE;
1390                 break;
1391         case MODE_RAM_WRITE:
1392                 r.cpu_ram.attribute = MEMORY_ATTR_READ;
1393                 break;
1394         case MODE_ROM_PROGRAM:
1395                 r.cpu_rom.attribute = MEMORY_ATTR_READ;
1396                 r.ppu_rom.attribute = MEMORY_ATTR_READ;
1397                 break;
1398         default:
1399                 assert(0);
1400         }
1401         
1402         if(logical_check(s, c, &r) == 0){
1403                 //dump RAM Îΰè¼èÆÀ
1404                 if(nesbuffer_malloc(&r, c->mode) == false){
1405                         Free(s);
1406                         if((c->mode == MODE_RAM_WRITE) && (r.cpu_ram.data != NULL)){
1407                                 Free(r.cpu_ram.data);
1408                         }
1409                         return;
1410                 }
1411                 //script execute!!
1412                 if(execute(s, c, &r) == OK){
1413                         //À®²Ì½ÐÎÏ
1414                         switch(c->mode){
1415                         case MODE_ROM_DUMP:
1416                                 nesfile_create(&r, c->romimage);
1417                                 break;
1418                         case MODE_RAM_READ:
1419                                 backupram_create(&(r.cpu_ram), c->ramimage);
1420                                 break;
1421                         }
1422                 }
1423                 //dump RAM Îΰè²òÊü
1424                 nesbuffer_free(&r, c->mode);
1425                 if((c->mode == MODE_RAM_WRITE) && (r.cpu_ram.data != NULL)){
1426                         Free(r.cpu_ram.data);
1427                 }
1428         }
1429         Free(s);
1430 }