OSDN Git Service

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