OSDN Git Service

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