OSDN Git Service

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