OSDN Git Service

struct memory に attr メンバを追加し、scipt 実行時の assert を強化
[unagi/old-svn-converted.git] / client / trunk / script.c
1 /*
2 famicom ROM cartridge utility - unagi
3 script engine
4
5 Copyright (C) 2008  sato_tiff
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 #define OP_PPU_WRITE_ENABLE (0)
37 /*
38 MAPPER num
39 MIRROR [HV]
40 CPU_ROMSIZE num
41 CPU_RAMSIZE num
42 PPU_ROMSIZE num
43 DUMP_START
44 CPU_READ address size
45 CPU_WRITE address data -> ÊÑ¿ôŸ³«+±é»»»Ò»ÈÍѲÄǽ
46 PPU_READ address size
47 STEP_START variable start end step -> for(i=start;i<end;i+=step)
48 STEP_END
49 DUMP_END
50 */
51 #include "syntax.h"
52
53 //ÊÑ¿ô´ÉÍý
54 struct variable_manage{
55         char name;
56         long start,end,step;
57         long val;
58         const struct script *Continue;
59 };
60
61 enum{
62         STEP_MAX = 2,
63         VARIABLE_MAX = STEP_MAX
64 };
65
66 static const struct variable_manage VARIABLE_INIT = {
67         .name = '\0', 
68         .start = 0, .end = 0, .step = 0,
69         .val = 0,
70         .Continue = NULL
71 };
72 static struct variable_manage variable_bank[VARIABLE_MAX];
73 static int variable_num = 0;
74
75 static void variable_init_single(int num)
76 {
77         memcpy(&variable_bank[num], &VARIABLE_INIT, sizeof(struct variable_manage));
78 }
79
80 static void variable_init_all(void)
81 {
82         int i;
83         variable_num = 0;
84         for(i = 0; i < VARIABLE_MAX; i++){
85                 variable_init_single(i);
86         }
87 }
88
89 static int variable_get(char name, long *val)
90 {
91         int i;
92         struct variable_manage *v;
93         v = variable_bank;
94         for(i = 0; i < variable_num; i++){
95                 if(v->name == name){
96                         *val = v->val;
97                         return OK;
98                 }
99                 v++;
100         }
101         return NG;
102 }
103
104 //ÊÑ¿ôŸ³«
105 static int expression_calc(const struct st_expression *e, long *val)
106 {
107         long left, right;
108         if(e->left.type == EXPRESSION_TYPE_VARIABLE){
109                 if(variable_get(e->left.variable, &left) == NG){
110                         return NG;
111                 }
112         }else{
113                 left = e->left.value;
114         }
115         if(e->operator == OPERATOR_NONE){
116                 *val = left;
117                 return OK;
118         }
119         if(e->right.type == EXPRESSION_TYPE_VARIABLE){
120                 if(variable_get(e->right.variable, &right) == NG){
121                         return NG;
122                 }
123         }else{
124                 right = e->right.value;
125         }
126         switch(e->operator){
127         case OPERATOR_PLUS:
128                 *val = left + right;
129                 break;
130         case OPERATOR_SHIFT_LEFT:
131                 *val = left >> right;
132                 //*val &= 1;
133                 break;
134         case OPERATOR_SHIFT_RIGHT:
135                 *val = left << right;
136                 break;
137         case OPERATOR_AND:
138                 *val = left & right;
139                 break;
140         case OPERATOR_OR:
141                 *val = left | right;
142                 break;
143         case OPERATOR_XOR:
144                 *val = left ^ right;
145                 break;
146         }
147         
148         return OK;
149 }
150
151 static int step_new(char name, long start, long end, long step, const struct script *Continue)
152 {
153         if(variable_num >= VARIABLE_MAX){
154                 return NG; //ÊÑ¿ôÄêµÁ¤¬Â¿¤¹¤®
155         }
156         struct variable_manage *v;
157         int i;
158         v = variable_bank;
159         for(i = 0; i < variable_num; i++){
160                 if(v->name == name){
161                         return NG; //ÊÑ¿ô̾½ÅÊ£
162                 }
163                 v++;
164         }
165         v = variable_bank;
166         v += variable_num;
167         v->name = name;
168         v->start = start;
169         v->end = end;
170         v->step = step;
171         v->val = start;
172         v->Continue = Continue;
173         variable_num++;
174         return OK;
175 }
176
177 static const struct script *step_end(const struct script *Break)
178 {
179         //¸½ºß¤Î¥ë¡¼¥×¤ÎÂоÝÊÑ¿ô¤òÆÀ¤ë
180         struct variable_manage *v;
181         v = variable_bank;
182         v += (variable_num - 1);
183         //ÊÑ¿ô¹¹¿·
184         v->val += v->step;
185         if(v->val < v->end){
186                 return v->Continue;
187         }
188         //¥ë¡¼¥×¤¬½ª¤ï¤Ã¤¿¤Î¤Ç¤½¤ÎÊÑ¿ô¤òÇË´þ¤¹¤ë
189         variable_init_single(variable_num - 1);
190         variable_num--;
191         return Break;
192 }
193
194 static int syntax_check_expression(char **word, int word_num, struct st_expression *e)
195 {
196         if(word_num == 0){
197                 return NG;
198         }
199         //left
200         if(value_get(word[0], &(e->left.value)) == OK){
201                 e->left.type = EXPRESSION_TYPE_VALUE;
202         }else{
203                 e->left.type = EXPRESSION_TYPE_VARIABLE;
204                 e->left.variable = word[0][0];
205         }
206         word_num--;
207         if(word_num == 0){
208                 e->operator = OPERATOR_NONE;
209                 return OK;
210         }
211         //operator
212         e->operator = operator_get(word[1]);
213         if(e->operator == OPERATOR_ERROR){
214                 return NG;
215         }
216         word_num--;
217         if(word_num == 0){
218                 return NG;
219         }
220         //right
221         if(value_get(word[2], &(e->right.value)) == OK){
222                 e->right.type = EXPRESSION_TYPE_VALUE;
223         }else{
224                 e->right.type = EXPRESSION_TYPE_VARIABLE;
225                 e->right.variable = word[2][0];
226         }
227         return OK;
228 }
229
230 static const char SYNTAX_ERROR_PREFIX[] = "syntax error:";
231
232 /*
233 return: error count, ¤³¤³¤Ç¤Ï 0 or 1
234 */
235 static int syntax_check_phase(char **word, int word_num, struct script *s, const int mode)
236 {
237         int i = sizeof(SCRIPT_SYNTAX) / sizeof(SCRIPT_SYNTAX[0]);
238         const struct script_syntax *syntax;
239         syntax = SCRIPT_SYNTAX;
240         while(i != 0){
241                 if(strcmp(syntax->name, word[0]) == 0){
242                         int j;
243                         
244                         s->opcode = syntax->script_opcode;
245                         if((mode & syntax->permittion) == 0){
246                                 printf("%s opcode %s not allowed on current mode\n", SYNTAX_ERROR_PREFIX, syntax->name);
247                                 return 1;
248                         };
249                         {
250                                 int compare = 0;
251                                 switch(syntax->compare){
252                                 case SYNTAX_COMPARE_EQ:
253                                         compare = (syntax->argc == (word_num - 1));
254                                         break;
255                                 case SYNTAX_COMPARE_GT:
256                                         compare = (syntax->argc <= (word_num - 1));
257                                         break;
258                                 }
259                                 if(!compare){
260                                         printf("%s parameter number not much %s\n", SYNTAX_ERROR_PREFIX, word[0]);
261                                         return 1;
262                                 }
263                         }
264                         for(j = 0; j < syntax->argc; j++){
265                                 switch(syntax->argv_type[j]){
266                                 case SYNTAX_ARGVTYPE_NULL:
267                                         printf("%s ARGV_NULL select\n", SYNTAX_ERROR_PREFIX);
268                                         return 1;
269                                 case SYNTAX_ARGVTYPE_VALUE:
270                                         if(value_get(word[j + 1], &(s->value[j])) == NG){
271                                                 printf("%s value error %s %s\n", SYNTAX_ERROR_PREFIX, word[0], word[j+1]);
272                                                 return 1;
273                                         }
274                                         break;
275                                 case SYNTAX_ARGVTYPE_HV:
276                                         switch(word[j + 1][0]){
277                                         case 'H':
278                                         case 'h':
279                                                 s->value[j] = MIRROR_HORIZONAL;
280                                                 break;
281                                         case 'V':
282                                         case 'v':
283                                                 s->value[j] = MIRROR_VERTICAL;
284                                                 break;
285                                         case 'A':
286                                         case 'a':
287                                                 s->value[j] = MIRROR_PROGRAMABLE;
288                                                 break;
289                                         default:
290                                                 printf("%s unknown scroll mirroring type %s\n", SYNTAX_ERROR_PREFIX, word[j+1]);
291                                                 return 1;
292                                         }
293                                         break;
294                                 case SYNTAX_ARGVTYPE_EXPRESSION:
295                                         s->value[j] = VALUE_EXPRESSION;
296                                         //Ì¿Îá̾¤Îñ¸ì¤Èñ¸ì¿ô¤ò½ü³°¤·¤ÆÅϤ¹
297                                         if(syntax_check_expression(&word[j+1], word_num - 2, &s->expression) == NG){
298                                                 printf("%s expression error\n", SYNTAX_ERROR_PREFIX);
299                                                 return 1;
300                                         }
301                                         //²ÄÊѤ˰ú¿ô¤ò¼è¤ë¤Î¤Ç¤³¤³¤Ç½ª¤ï¤ê
302                                         return 0;
303                                 case SYNTAX_ARGVTYPE_VARIABLE:{
304                                         const char v = word[j+1][0];
305                                         if((v >= 'a' && v <= 'z') || (v >= 'A' && v <= 'Z')){
306                                                 s->value[j] = VALUE_VARIABLE;
307                                                 s->variable = v;
308                                         }else{
309                                                 printf("%s variable must use [A-Za-z] %s\n", SYNTAX_ERROR_PREFIX, word[j+1]);
310                                                 return 1;
311                                         }
312                                         }break;
313                                 }
314                         }
315                         //opcode found and ÆþÎÏʸ»ú¼ïÀµ¾ï
316                         return 0;
317                 }
318                 syntax++;
319                 i--;
320         }
321         printf("%s unknown opcode %s\n", SYNTAX_ERROR_PREFIX, word[0]);
322         return 1;
323 }
324
325 /*
326 return: error count
327 */
328 static int syntax_check(char **text, int text_num, struct script *s, int mode)
329 {
330         int error = 0;
331         int i;
332         mode = 1<< mode; //permittion ¤Ï bitflag ¤Ê¤Î¤Ç¤³¤³¤ÇÊÑ´¹¤¹¤ë
333         variable_init_all();
334         for(i = 0; i < text_num; i++){
335                 char *word[TEXT_MAXWORD];
336                 const int n = word_load(text[i], word);
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, long *data)
420 {
421         switch(region){
422         case MEMORY_AREA_CPU_ROM:
423                 switch(offset){
424                 case 0x8000: case 0xa000: case 0xc000:
425                         break;
426                 default:
427                         printf("%s %s_COMMAND area offset error\n", LOGICAL_ERROR_PREFIX, STR_REGION_CPU);
428                         return NG;
429                 }
430                 switch(size){
431                 case 0x2000: case 0x4000: case 0x8000:
432                         break;
433                 default:
434                         printf("%s %s_COMMAND area mask error\n", LOGICAL_ERROR_PREFIX, STR_REGION_CPU);
435                         return NG;
436                 }
437                 break;
438         case MEMORY_AREA_PPU:
439                 switch(offset){
440                 case 0x0000: case 0x0400: case 0x0800: case 0x0c00:
441                 case 0x1000: case 0x1400: case 0x1800: case 0x1c00:
442                         break;
443                 default:
444                         printf("%s %s_COMMAND area offset error\n", LOGICAL_ERROR_PREFIX, STR_REGION_CPU);
445                         return NG;
446                 }
447                 switch(size){
448                 case 0x0400: case 0x0800: case 0x1000: case 0x2000: 
449                         break;
450                 default:
451                         printf("%s %s_COMMAND area mask error\n", LOGICAL_ERROR_PREFIX, STR_REGION_CPU);
452                         return NG;
453                 }
454                 break;
455         default:
456                 assert(0); //unknown memory area
457         }
458         switch(address){
459         case 0: case 0x2aaa: case 0x5555:
460                 break;
461         default:
462                 assert(0); //unknown command address
463         }
464         long mask = size - 1;
465         *data = (address & mask) | offset;
466         return OK;
467 }
468
469 static int logical_check(const struct script *s, const struct st_config *c, struct romimage *r)
470 {
471         long cpu_romsize = 0, cpu_ramsize = 0, ppu_romsize = 0;
472         int imagesize = 0; //for write or program mode
473         int setting = SETTING;
474         int error = 0;
475         
476         variable_init_all();
477         while(s->opcode != SCRIPT_OPCODE_DUMP_END){
478                 //printf("opcode exec %s\n", SCRIPT_SYNTAX[s->opcode].name);
479                 if((setting == DUMP) && (s->opcode < SCRIPT_OPCODE_DUMP_START)){
480                         printf("%s config script include DUMPSTART area\n", LOGICAL_ERROR_PREFIX);
481                         error += 1;
482                 }
483
484                 //romimage open for write or program mode
485                 if((imagesize == 0) && (setting == DUMP)){
486                         switch(c->mode){
487                         case MODE_RAM_WRITE:
488                                 assert(r->cpu_ram.attribute != MEMORY_ATTR_READ);
489                                 r->cpu_ram.data = buf_load_full(c->ramimage, &imagesize);
490                                 if(r->cpu_ram.data == NULL){
491                                         printf("%s RAM image open error\n", LOGICAL_ERROR_PREFIX);
492                                         imagesize = -1;
493                                         error += 1;
494                                 }else if(r->cpu_ram.size != imagesize){
495                                         printf("%s RAM image size is not same\n", LOGICAL_ERROR_PREFIX);
496                                         free(r->cpu_ram.data);
497                                         r->cpu_ram.data = NULL;
498                                         imagesize = -1;
499                                         error += 1;
500                                 }
501                                 break;
502                         case MODE_ROM_PROGRAM:
503                                 assert(r->cpu_rom.attribute != MEMORY_ATTR_READ);
504                                 assert(r->ppu_rom.attribute != MEMORY_ATTR_READ);
505                                 if(nesfile_load(LOGICAL_ERROR_PREFIX, c->romimage, r)== NG){
506                                         error += 1;
507                                 }
508                                 imagesize = -1;
509                                 break;
510                         default: 
511                                 imagesize = -1;
512                                 break;
513                         }
514                 }
515         
516                 switch(s->opcode){
517                 case SCRIPT_OPCODE_COMMENT:
518                         break;
519                 case SCRIPT_OPCODE_MAPPER:
520                         r->mappernum = s->value[0];
521                         break;
522                 case SCRIPT_OPCODE_MIRROR:
523                         r->mirror = s->value[0];
524                         break;
525                 case SCRIPT_OPCODE_CPU_ROMSIZE:
526                         if(memorysize_check(s->value[0], MEMORY_AREA_CPU_ROM)){
527                                 printf("%s %s length error\n", LOGICAL_ERROR_PREFIX, OPSTR_CPU_ROMSIZE);
528                                 error += 1;
529                         }
530                         r->cpu_rom.size = s->value[0];
531                         break;
532                 case SCRIPT_OPCODE_CPU_RAMSIZE:
533                         //̤³ÎÄêÍ×ÁǤ¬Â¿¤¤¤Î¤Ç check ¤òÈ´¤¯
534                         r->cpu_ram.size = s->value[0];
535                         break;
536                 case SCRIPT_OPCODE_CPU_COMMAND_0000:
537                         if(command_mask(MEMORY_AREA_CPU_ROM, 0, s->value[0], s->value[1], &(r->cpu_flash.command_0000)) == NG){
538                                 error += 1;
539                         }
540                         break;
541                 case SCRIPT_OPCODE_CPU_COMMAND_2AAA:
542                         if(command_mask(MEMORY_AREA_CPU_ROM, 0x2aaa, s->value[0], s->value[1], &(r->cpu_flash.command_2aaa)) == NG){
543                                 error += 1;
544                         }
545                         break;
546                 case SCRIPT_OPCODE_CPU_COMMAND_5555:
547                         if(command_mask(MEMORY_AREA_CPU_ROM, 0x5555, s->value[0], s->value[1], &(r->cpu_flash.command_5555)) == NG){
548                                 error += 1;
549                         }
550                         break;
551                 case SCRIPT_OPCODE_PPU_ROMSIZE:
552                         if(memorysize_check(s->value[0], MEMORY_AREA_PPU)){
553                                 printf("%s %s length error\n", LOGICAL_ERROR_PREFIX, OPSTR_PPU_ROMSIZE);
554                                 error += 1;
555                         }
556                         r->ppu_rom.size = s->value[0];
557                         break;
558                 case SCRIPT_OPCODE_PPU_COMMAND_0000:
559                         if(command_mask(MEMORY_AREA_PPU, 0, s->value[0], s->value[1], &(r->ppu_flash.command_0000)) == NG){
560                                 error += 1;
561                         }
562                         break;
563                 case SCRIPT_OPCODE_PPU_COMMAND_2AAA:
564                         if(command_mask(MEMORY_AREA_PPU, 0x2aaa, s->value[0], s->value[1], &(r->ppu_flash.command_2aaa)) == NG){
565                                 error += 1;
566                         }
567                         break;
568                 case SCRIPT_OPCODE_PPU_COMMAND_5555:
569                         if(command_mask(MEMORY_AREA_PPU, 0x5555, s->value[0], s->value[1], &(r->ppu_flash.command_5555)) == NG){
570                                 error += 1;
571                         }
572                         break;
573                 case SCRIPT_OPCODE_DUMP_START:
574                         setting = DUMP;
575                         break;
576                 case SCRIPT_OPCODE_CPU_READ:{
577                         const long address = s->value[0];
578                         const long length = s->value[1];
579                         const long end = address + length - 1;
580                         
581                         assert(r->cpu_rom.attribute != MEMORY_ATTR_WRITE);
582                         //length filter. 0 ¤Ï¤À¤á
583                         if(!is_range(length, 1, 0x4000)){
584                                 logical_print_illgallength(STR_REGION_CPU, length);
585                                 error += 1;
586                         }
587                         //address filter
588                         else if(!is_region_cpurom(address)){
589                                 logical_print_illgalarea(STR_REGION_CPU, address);
590                                 error += 1;
591                         }else if(end >= 0x10000){
592                                 logical_print_overdump(STR_REGION_CPU, address, end);
593                                 error += 1;
594                         }
595                         cpu_romsize += length;
596                         setting = DUMP;
597                         }
598                         break;
599                 case SCRIPT_OPCODE_CPU_WRITE:{
600                         const long address = s->value[0];
601                         long data;
602                         if(expression_calc(&s->expression, &data) == NG){
603                                 printf("%s expression calc error\n", LOGICAL_ERROR_PREFIX);
604                                 error += 1;
605                         }
606                         if(address < 0x5000 || address >= 0x10000){
607                                 logical_print_illgalarea(STR_REGION_CPU, address);
608                                 error += 1;
609                         }else if(!is_data_byte(data)){
610                                 logical_print_byteerror(STR_REGION_CPU, data);
611                                 error += 1;
612                         }
613                         setting = DUMP;
614                         }
615                         break;
616                 case SCRIPT_OPCODE_CPU_RAMRW:{
617                         const long address = s->value[0];
618                         const long length = s->value[1];
619                         const long end = address + length - 1;
620                         switch(c->mode){
621                         case MODE_RAM_READ:
622                                 assert(r->cpu_ram.attribute != MEMORY_ATTR_WRITE);
623                                 break;
624                         case MODE_RAM_WRITE:
625                                 assert(r->cpu_ram.attribute = MEMORY_ATTR_READ);
626                                 break;
627                         }
628                         //length filter. 0 ¤Ï¤À¤á
629                         if(!is_range(length, 1, 0x2000)){
630                                 logical_print_illgallength(STR_REGION_CPU, length);
631                                 error += 1;
632                         }
633                         //address filter
634                         else if(address < 0x6000 || address >= 0x8000){
635                                 logical_print_illgalarea(STR_REGION_CPU, address);
636                                 error += 1;
637                         }else if(end >= 0x8000){
638                                 logical_print_overdump(STR_REGION_CPU, address, end);
639                                 error += 1;
640                         }
641                         cpu_ramsize += length;
642                         setting = DUMP;
643                         }
644                         break;
645                 case SCRIPT_OPCODE_CPU_PROGRAM:{
646                         const long address = s->value[0];
647                         const long length = s->value[1];
648                         const long end = address + length - 1;
649                         
650                         assert(r->cpu_rom.attribute != MEMORY_ATTR_READ);
651                         assert(r->ppu_rom.attribute = MEMORY_ATTR_READ);
652                         //length filter.
653                         if(!is_range(length, 0x80, 0x2000)){
654                                 logical_print_illgallength(STR_REGION_CPU, length);
655                                 error += 1;
656                         }
657                         //address filter
658                         else if(!is_region_cpurom(address)){
659                                 logical_print_illgalarea(STR_REGION_CPU, address);
660                                 error += 1;
661                         }else if(end >= 0x10000){
662                                 logical_print_overdump(STR_REGION_CPU, address, end);
663                                 error += 1;
664                         }
665                         cpu_romsize += length;
666                         setting = DUMP;
667                         }
668                         break;
669                 case SCRIPT_OPCODE_PPU_RAMTEST:
670                         //¥ë¡¼¥×ÆâÉô¤ËÆþ¤Ã¤Æ¤¿¤é¥¨¥é¡¼
671                         if(variable_num != 0){
672                                 printf("%s PPU_RAMTEST must use outside loop\n", LOGICAL_ERROR_PREFIX);
673                                 error += 1;
674                         }
675                         break;
676                 case SCRIPT_OPCODE_PPU_READ:{
677                         const long address = s->value[0];
678                         const long length = s->value[1];
679                         const long end = address + length - 1;
680                         assert(r->ppu_rom.attribute != MEMORY_ATTR_WRITE);
681                         //length filter. 0 ¤òÍÆǧ¤¹¤ë
682                         if(!is_range(length, 0, 0x2000)){
683                                 logical_print_illgallength(STR_REGION_PPU, length);
684                                 error += 1;
685                         }
686                         //address filter
687                         else if(!is_region_ppurom(address)){
688                                 logical_print_illgalarea(STR_REGION_PPU, address);
689                                 error += 1;
690                         }else if (end >= 0x2000){
691                                 logical_print_overdump(STR_REGION_PPU, address, end);
692                                 error += 1;
693                         }
694                         //dump length update
695                         if(is_region_ppurom(address)){
696                                 ppu_romsize += length;
697                         }
698                         setting = DUMP;
699                         }
700                         break;
701                 case SCRIPT_OPCODE_PPU_WRITE:{
702                         if(OP_PPU_WRITE_ENABLE==0){
703                                 break;
704                         }
705                         const long address = s->value[0];
706                         const long data = s->value[1];
707                         setting = DUMP;
708                         if(!is_region_ppurom(address)){
709                                 logical_print_illgalarea(STR_REGION_PPU, address);
710                                 error += 1;
711                         }else if(!is_data_byte(data)){
712                                 logical_print_byteerror(STR_REGION_PPU, data);
713                                 error += 1;
714                         }
715                         }
716                         break;
717                 case SCRIPT_OPCODE_STEP_START:{
718                         int i;
719                         {
720                                 const int v = s->value[1];
721                                 if((v < 0) || (v > 0xff)){
722                                         printf("%s step start must 0-0xff 0x%x\n", LOGICAL_ERROR_PREFIX, v);
723                                         error += 1;
724                                 }
725                         }
726                         for(i = 2; i <4; i++){
727                                 const int v = s->value[i];
728                                 if((v < 1) || (v > 0x100)){
729                                         printf("%s end or next must 1-0x100 0x%x\n", LOGICAL_ERROR_PREFIX, v);
730                                         error += 1;
731                                 }
732                         }
733                         //¥ë¡¼¥×¤ÎÌá¤êÀè¤Ï¤³¤ÎÌ¿Îá¤Î¼¡¤Ê¤Î¤Ç s[1]
734                         if(step_new(s->variable, s->value[1], s->value[2], s->value[3], &s[1]) == NG){
735                                 printf("%s step loop too much\n", LOGICAL_ERROR_PREFIX);
736                                 error += 1;
737                                 return error;
738                         }
739                         setting = DUMP;
740                         }break;
741                 case SCRIPT_OPCODE_DUMP_END:
742                         setting = END;
743                         break;
744                 }
745                 if(setting == END){
746                         break;
747                 }
748                 if(s->opcode == SCRIPT_OPCODE_STEP_END){
749                         if(variable_num == 0){
750                                 printf("%s loop closed, missing STEP_START\n", LOGICAL_ERROR_PREFIX);
751                                 return error + 1;
752                         }
753                         s = step_end(&s[1]);
754                         setting = DUMP;
755                 }else{
756                         s++;
757                 }
758         }
759         
760         //loop open conform
761         if(variable_num != 0){
762                 printf("%s loop opened, missing STEP_END\n", LOGICAL_ERROR_PREFIX);
763                 error += 1;
764         }
765         //dump length conform
766         error += dump_length_conform(OPSTR_CPU_ROMSIZE, cpu_romsize, r->cpu_rom.size);
767         error += dump_length_conform(OPSTR_CPU_RAMSIZE, cpu_ramsize, r->cpu_ram.size);
768         error += dump_length_conform(OPSTR_PPU_ROMSIZE, ppu_romsize, r->ppu_rom.size);
769         
770         //command line config override
771         if(c->mirror != CONFIG_OVERRIDE_UNDEF){
772                 r->mirror = c->mirror;
773         }
774         if(c->backupram != CONFIG_OVERRIDE_UNDEF){
775                 r->backupram = 1;
776         }
777         if(c->mapper != CONFIG_OVERRIDE_UNDEF){
778                 //program mode ¤Ç mapper Êѹ¹¤òËɤ°
779                 assert(c->mode == MODE_ROM_DUMP);
780                 r->mappernum = c->mapper;
781         }
782         return error;
783 }
784
785 /*
786 execute() ÍÑ¥µ¥Ö´Ø¿ô¤È¥Ç¡¼¥¿
787 */
788 static int execute_connection_check(const struct reader_driver *d)
789 {
790         int ret = OK;
791         const int testsize = 0x80;
792         int testcount = 3;
793         u8 *master, *reload;
794         master = malloc(testsize);
795         reload = malloc(testsize);
796
797         d->cpu_read(0xfee0, testsize, master);
798         
799         while(testcount != 0){
800                 d->cpu_read(0xfee0, testsize, reload);
801                 if(memcmp(master, reload, testsize) != 0){
802                         ret = NG;
803                         break;
804                 }
805                 testcount--;
806         }
807         
808         free(master);
809         free(reload);
810         return ret;
811 }
812
813 enum {PPU_TEST_RAM, PPU_TEST_ROM};
814 const u8 PPU_TEST_DATA[] = "PPU_TEST_DATA";
815 #if DEBUG==0
816 static 
817 #endif
818 int ppu_ramtest(const struct reader_driver *d)
819 {
820         const int length = sizeof(PPU_TEST_DATA);
821         const long testaddr = 123;
822         //ppu ram data fill 0
823         {
824                 int i = length;
825                 long address = testaddr;
826                 while(i != 0){
827                         d->ppu_write(address++, 0);
828                         i--;
829                 }
830         }
831         
832         //ppu test data write
833         {
834                 const u8 *data;
835                 int i = length;
836                 long address = testaddr;
837                 data = PPU_TEST_DATA;
838                 while(i != 0){
839                         d->ppu_write(address++, (long) *data);
840                         data++;
841                         i--;
842                 }
843         }
844
845         u8 writedata[length];
846         d->ppu_read(testaddr, length, writedata);
847         if(memcmp(writedata, PPU_TEST_DATA, length) == 0){
848                 return PPU_TEST_RAM;
849         }
850         return PPU_TEST_ROM;
851 }
852
853 static void readbuffer_print(const struct memory *m, long length)
854 {
855         if(length >= 0x10){
856                 length = 0x10;
857         }
858         printf("%s 0x%05x:", m->name, m->offset);
859         int offset = 0;
860         const u8 *data;
861         data = m->data;
862         while(length != 0){
863                 char safix;
864                 switch(offset & 0xf){
865                 default:
866                         safix = ' ';
867                         break;
868                 case 0x7:
869                         safix = '-';
870                         break;
871                 case 0xf:
872                         safix = ';';
873                         break;
874                 }
875                 printf("%02x%c", (int) *data, safix);
876                 data++;
877                 offset++;
878                 length--;
879         }
880 }
881
882 static void checksum_print(const u8 *data, long length)
883 {
884         int sum = 0;
885         while(length != 0){
886                 sum += (int) *data;
887                 data++;
888                 length--;
889         }
890         printf(" 0x%06x\n", sum);
891 }
892
893 static void read_result_print(const struct memory *m, long length)
894 {
895         readbuffer_print(m, length);
896         checksum_print(m->data, length);
897         fflush(stdout);
898 }
899
900 const char EXECUTE_ERROR_PREFIX[] = "execute error:";
901 static void execute_cpu_ramrw(const struct reader_driver *d, const struct memory *ram, int mode, long address, long length)
902 {
903         if(mode == MODE_RAM_WRITE){
904                 const u8 *writedata;
905                 long a = address;
906                 long l = length;
907                 writedata = ram->data;
908                 while(l != 0){
909                         d->cpu_6502_write(a++, *writedata);
910                         writedata += 1;
911                         l--;
912                 }
913                 u8 *compare;
914                 compare = malloc(length);
915                 d->cpu_read(address, length, compare);
916                 if(memcmp(ram->data, compare, length) == 0){
917                         printf("RAM data write success\n");
918                 }else{
919                         printf("RAM data write failed\n");
920                 }
921                 free(compare);
922         }else{
923                 d->cpu_read(address, length, ram->data);
924         }
925 }
926
927 static int execute(const struct script *s, const struct st_config *c, struct romimage *r)
928 {
929         const struct reader_driver *const d = c->reader;
930         switch(d->open_or_close(READER_OPEN)){
931         case OK:
932                 d->init();
933                 break;
934         case NG:
935                 printf("%s driver open error\n", EXECUTE_ERROR_PREFIX);
936                 return NG;
937         default:
938                 assert(0);
939         }
940         if(execute_connection_check(d) == NG){
941                 printf("%s maybe connection error\n", EXECUTE_ERROR_PREFIX);
942                 d->open_or_close(READER_CLOSE);
943                 return NG;
944         }
945         struct memory cpu_rom, ppu_rom, cpu_ram;
946         cpu_rom = r->cpu_rom;
947         ppu_rom = r->ppu_rom;
948         cpu_ram = r->cpu_ram;
949         
950         variable_init_all();
951         while(s->opcode != SCRIPT_OPCODE_DUMP_END){
952                 int end = 1;
953                 switch(s->opcode){
954                 case SCRIPT_OPCODE_CPU_READ:{
955                         struct memory *m;
956                         const long addr = s->value[0];
957                         const long length = s->value[1];
958                         m = &cpu_rom;
959                         d->cpu_read(addr, length, m->data);
960                         read_result_print(m, length);
961                         m->data += length;
962                         m->offset += length;
963                         }break;
964                 case SCRIPT_OPCODE_CPU_WRITE:{
965                         long data;
966                         expression_calc(&s->expression, &data);
967                         d->cpu_6502_write(s->value[0], data);
968                         }
969                         break;
970                 case SCRIPT_OPCODE_CPU_RAMRW:{
971                         const long length = s->value[1];
972                         execute_cpu_ramrw(d, &cpu_ram, c->mode, s->value[0], length);
973                         read_result_print(&cpu_ram, length);
974                         cpu_ram.data += length;
975                         cpu_ram.offset += length;
976                         }
977                         break;
978                 case SCRIPT_OPCODE_CPU_PROGRAM:{
979                         struct flash_order *order;
980                         order = &(r->cpu_flash);
981                         order->address = s->value[0];
982                         order->length = s->value[1];
983                         order->data = cpu_rom.data;
984                         c->cpu_flash_driver->write(order);
985                         cpu_rom.data += order->length;
986                         cpu_rom.offset += order->length;
987                         }
988                         break;
989                 case SCRIPT_OPCODE_PPU_RAMTEST:
990                         if(ppu_ramtest(d) == PPU_TEST_RAM){
991                                 printf("PPU_RAMTEST: charcter RAM found\n");
992                                 r->ppu_rom.size = 0;
993                                 end = 0;
994                         }
995                         break;
996                 case SCRIPT_OPCODE_PPU_READ:{
997                         const long address = s->value[0];
998                         const long length = s->value[1];
999                         if(length == 0){
1000                                 /*for mmc2,4 protect.
1001                                 ¤³¤Î¤È¤­¤Ï1byteÆɤ߹þ¤ó¤Ç¡¢¤½¤ÎÆâÍƤϥХåե¡¤Ë¤¤¤ì¤Ê¤¤*/
1002                                 u8 dummy;
1003                                 d->ppu_read(address, 1, &dummy);
1004                         }else{
1005                                 d->ppu_read(address, length, ppu_rom.data);
1006                                 read_result_print(&ppu_rom, length);
1007                         }
1008                         ppu_rom.data += length;
1009                         ppu_rom.offset += length;
1010                         }
1011                         break;
1012                 case SCRIPT_OPCODE_PPU_WRITE:
1013                         if(OP_PPU_WRITE_ENABLE == 1){
1014                                 d->ppu_write(s->value[0], s->value[1]);
1015                         }
1016                         break;
1017                 case SCRIPT_OPCODE_STEP_START:
1018                         //¥ë¡¼¥×¤ÎÌá¤êÀè¤Ï¤³¤ÎÌ¿Îá¤Î¼¡¤Ê¤Î¤Ç &s[1]
1019                         step_new(s->variable, s->value[1], s->value[2], s->value[3], &s[1]);
1020                         break;
1021                 case SCRIPT_OPCODE_DUMP_END:
1022                         end = 0;
1023                         break;
1024                 }
1025                 if(end == 0){
1026                         break;
1027                 }
1028                 if(s->opcode == SCRIPT_OPCODE_STEP_END){
1029                         s = step_end(++s);
1030                 }else{
1031                         s++;
1032                 }
1033         }
1034         d->open_or_close(READER_CLOSE);
1035         return OK;
1036 }
1037
1038 void script_load(const struct st_config *c)
1039 {
1040         struct script *s;
1041         {
1042                 int scriptsize = 0;
1043                 char *buf;
1044                 
1045                 buf = buf_load_full(c->script, &scriptsize);
1046                 if(buf == NULL){
1047                         printf("scriptfile open error\n");
1048                         return;
1049                 }
1050                 char **text;
1051                 text = malloc(sizeof(char*) * TEXT_MAXLINE);
1052                 const int text_num = text_load(buf, scriptsize, text);
1053                 if(text_num == 0){
1054                         printf("script line too much\n");
1055                         free(buf);
1056                         free(text);
1057                         return;
1058                 }
1059                 s = malloc(sizeof(struct script) * (text_num + 1));
1060                 //logical_check, execute ¶¦¤Ë s->opcode ¤¬ DUMP_END ¤Ë¤Ê¤ë¤Þ¤Ç³¤±¤ë¡£DUMP_END ¤ÎÆþ¤ì˺¤ìÍѤËËöÈø¤Îscript¤Ëɬ¤º DUMP_END ¤ò¤¤¤ì¤ë
1061                 {
1062                         struct script *k;
1063                         k = s;
1064                         k += text_num;
1065                         k->opcode = SCRIPT_OPCODE_DUMP_END;
1066                 }
1067                 const int error = syntax_check(text, text_num, s, c->mode);
1068                 free(buf);
1069                 free(text);
1070                 if(error != 0){
1071                         free(s);
1072                         return;
1073                 }
1074         }
1075         struct romimage r = {
1076                 .cpu_rom = {
1077                         .size = 0, .offset = 0,
1078                         .data = NULL,
1079                         .attribute = MEMORY_ATTR_NOTUSE,
1080                         .name = STR_REGION_CPU
1081                 },
1082                 .ppu_rom = {
1083                         .size = 0, .offset = 0,
1084                         .data = NULL,
1085                         .attribute = MEMORY_ATTR_NOTUSE,
1086                         .name = STR_REGION_PPU
1087                 },
1088                 .cpu_ram = {
1089                         .size = 0, .offset = 0,
1090                         .data = NULL,
1091                         .attribute = MEMORY_ATTR_NOTUSE,
1092                         .name = STR_REGION_CPU
1093                 },
1094                 .mappernum = 0,
1095                 .mirror = MIRROR_PROGRAMABLE
1096         };
1097         //attribute ¤Ï¤½¤Î struct data ¤ËÂФ·¤Æ¤Î RW ¤Ê¤Î¤ÇÍ×Ãí°Õ
1098         switch(c->mode){
1099         case MODE_ROM_DUMP:
1100                 r.cpu_rom.attribute = MEMORY_ATTR_WRITE;
1101                 r.ppu_rom.attribute = MEMORY_ATTR_WRITE;
1102                 break;
1103         case MODE_RAM_READ:
1104                 r.cpu_ram.attribute = MEMORY_ATTR_WRITE;
1105                 break;
1106         case MODE_RAM_WRITE:
1107                 r.cpu_ram.attribute = MEMORY_ATTR_READ;
1108                 break;
1109         case MODE_ROM_PROGRAM:
1110                 r.cpu_rom.attribute = MEMORY_ATTR_READ;
1111                 r.ppu_rom.attribute = MEMORY_ATTR_READ;
1112                 break;
1113         default:
1114                 assert(0);
1115         }
1116         
1117         if(logical_check(s, c, &r) == 0){
1118                 //dump RAM Îΰè¼èÆÀ
1119                 if(nesbuffer_malloc(&r, c->mode) == NG){
1120                         free(s);
1121                         if((c->mode == MODE_RAM_WRITE) && (r.cpu_ram.data != NULL)){
1122                                 free(r.cpu_ram.data);
1123                         }
1124                         return;
1125                 }
1126                 //script execute!!
1127                 if(execute(s, c, &r) == OK){
1128                         //À®²Ì½ÐÎÏ
1129                         switch(c->mode){
1130                         case MODE_ROM_DUMP:
1131                                 nesfile_create(&r, c->romimage);
1132                                 break;
1133                         case MODE_RAM_READ:
1134                                 backupram_create(&(r.cpu_ram), c->ramimage);
1135                                 break;
1136                         }
1137                 }
1138                 //dump RAM Îΰè²òÊü
1139                 nesbuffer_free(&r, c->mode);
1140                 if((c->mode == MODE_RAM_WRITE) && (r.cpu_ram.data != NULL)){
1141                         free(r.cpu_ram.data);
1142                 }
1143         }
1144         free(s);
1145 }