OSDN Git Service

gui をレイアウトを整理、script 実行を別スレッド化
[unagi/old-svn-converted.git] / client / trunk / anago / script_dump.c
1 #include <assert.h>
2 #include <stdio.h>
3 #include <string.h>
4 #include <squirrel.h>
5 #include <sqstdio.h>
6 #include <sqstdaux.h>
7 #include "type.h"
8 #include "widget.h"
9 #include "header.h"
10 #include "progress.h"
11 #include "memory_manage.h"
12 #include "reader_master.h"
13 #include "squirrel_wrap.h"
14 #include "script_common.h"
15 #include "script_dump.h"
16
17 struct dump_driver{
18         const char *target;
19         struct memory_driver{
20                 struct memory memory;
21                 long read_count;
22                 void (*const write)(long address, long length, const uint8_t *data);
23                 void (*const read)(long address, long length, u8 *data);
24                 struct gauge *const gauge;
25         }cpu, ppu;
26         uint8_t (*const vram_connection)(void);
27         bool progress;
28         struct textcontrol *const log;
29 };
30 static SQInteger write_memory(HSQUIRRELVM v, struct memory_driver *t)
31 {
32         long address, data;
33         SQRESULT r = qr_argument_get(v, 2, &address, &data);
34         if(SQ_FAILED(r)){
35                 return r;
36         }
37         uint8_t d8 = (uint8_t) data;
38         t->write(address, 1, &d8);
39         return 0;
40 }
41 static SQInteger cpu_write(HSQUIRRELVM v)
42 {
43         struct dump_driver *d;
44         SQRESULT r =  qr_userpointer_get(v, (SQUserPointer) &d);
45         if(SQ_FAILED(r)){
46                 return r;
47         }
48         return write_memory(v, &d->cpu);
49 }
50
51 //¤³¤³¤Î printf ¤Ï debug ÍѤ˻Ĥ·¤Æ¤ª¤¯
52 static void buffer_show(struct memory *t, long length)
53 {
54         int i;
55         const uint8_t *buf = t->data + t->offset;
56         printf("%s 0x%06x:", t->name, t->offset);
57         for(i = 0; i < 0x10; i++){
58                 char dump[3+1];
59                 sprintf(dump, "%02x", buf[i]);
60                 switch(i){
61                 case 7:
62                         dump[2] = '-';
63                         break;
64                 case 0x0f:
65                         dump[2] = '\0';
66                         break;
67                 default:
68                         dump[2] = ' ';
69                         break;
70                 }
71                 dump[3] = '\0';
72                 printf("%s", dump);
73         }
74         int sum = 0;
75         while(length != 0){
76                 sum += (int) *buf;
77                 buf++;
78                 length--;
79         }
80         printf(":0x%06x\n", sum);
81         fflush(stdout);
82 }
83
84 static void progress_show(struct memory_driver *d, const char *area)
85 {
86         char str[80];
87         d->gauge->value_set(d->gauge->bar, d->memory.offset);
88         snprintf(str, 80, "%s 0x%06x/0x%06x", area, d->memory.offset, d->memory.size);
89         d->gauge->label_set(d->gauge->label, str);
90 }
91 static SQInteger read_memory(HSQUIRRELVM v, struct memory_driver *t, bool progress)
92 {
93         long address, length;
94         SQRESULT r = qr_argument_get(v, 2, &address, &length);
95         if(SQ_FAILED(r)){
96                 return r;
97         }
98         t->read(address, length == 0 ? 1: length, t->memory.data + t->memory.offset);
99         if((length != 0) && (progress == false)){
100                 buffer_show(&t->memory, length);
101         }
102         t->memory.offset += length;
103         return 0;
104 }
105 static SQInteger cpu_read(HSQUIRRELVM v)
106 {
107         struct dump_driver *d;
108         SQRESULT r =  qr_userpointer_get(v, (SQUserPointer) &d);
109         if(SQ_FAILED(r)){
110                 return r;
111         }
112         r = read_memory(v, &d->cpu, d->progress);
113         progress_show(&d->cpu, "CPU");
114         return r;
115 }
116
117 static SQInteger ppu_read(HSQUIRRELVM v)
118 {
119         struct dump_driver *d;
120         SQRESULT r =  qr_userpointer_get(v, (SQUserPointer) &d);
121         if(SQ_FAILED(r)){
122                 return r;
123         }
124         r = read_memory(v, &d->ppu, d->progress);
125         progress_show(&d->ppu, "PPU");
126         return r;
127 }
128
129 static SQInteger ppu_ramfind(HSQUIRRELVM v)
130 {
131         struct dump_driver *d;
132         enum{
133                 testsize = 8,
134                 testaddress = 1234
135         };
136         static const uint8_t test_val[testsize] = {0xaa, 0x55, 0, 0xff, 0x46, 0x49, 0x07, 0x21};
137         static const uint8_t test_str[testsize] = "pputest";
138         uint8_t test_result[testsize];
139
140         SQRESULT r =  qr_userpointer_get(v, (SQUserPointer) &d);
141         if(SQ_FAILED(r)){
142                 return r;
143         }
144         d->ppu.write(testaddress, testsize, test_val);
145         d->ppu.read(testaddress, testsize, test_result);
146         if(memcmp(test_val, test_result, testsize) != 0){
147                 sq_pushbool(v, SQFalse);
148                 return 1;
149         }
150         d->ppu.write(testaddress, testsize, test_str);
151         d->ppu.read(testaddress, testsize, test_result);
152         if(memcmp(test_str, test_result, testsize) != 0){
153                 sq_pushbool(v, SQFalse);
154                 return 1;
155         }
156         d->ppu.memory.offset = 0;
157         d->ppu.memory.size = 0;
158         sq_pushbool(v, SQTrue);
159         return 1;
160 }
161
162 static void memory_new_init(struct memory_driver *d, const char *area)
163 {
164         d->memory.offset = 0;
165         d->memory.data = Malloc(d->memory.size);
166         d->gauge->value_set(d->gauge->bar, 0);
167         d->gauge->range_set(d->gauge->bar, d->memory.size);
168         d->gauge->label_set(d->gauge->label, area);
169 }
170
171 //test »þ/1ÅÙÌܤΠcall ¤Ç»ÈÍÑ
172 static SQInteger memory_new(HSQUIRRELVM v)
173 {
174         struct dump_driver *d;
175         SQRESULT r =  qr_userpointer_get(v, (SQUserPointer) &d);
176         if(SQ_FAILED(r)){
177                 return r;
178         }
179         r = qr_argument_get(v, 2, &d->cpu.memory.size, &d->ppu.memory.size);
180         if(SQ_FAILED(r)){
181                 return r;
182         }
183 /*      d->cpu.memory.offset = 0;
184         d->cpu.memory.data = Malloc(d->cpu.memory.size);
185         d->cpu.gauge->value_set(0);
186         d->cpu.gauge->range_set(d->cpu.gauge->object, d->cpu.memory.size);
187         d->ppu.memory.offset = 0;
188         d->ppu.memory.data = Malloc(d->ppu.memory.size);
189         d->cpu.gauge->value_set(0);
190         d->ppu.gauge->range_set(d->ppu.gauge->object, d->ppu.memory.size);*/
191         memory_new_init(&d->cpu, "CPU");
192         memory_new_init(&d->ppu, "PPU");
193         return 0;
194 }
195
196 //dump »þ/2ÅÙÌܤΠcall ¤Ç nesfile_save ¤È¤·¤Æ»ÈÍÑ
197 static SQInteger nesfile_save(HSQUIRRELVM v)
198 {
199         struct dump_driver *d;
200         SQRESULT r =  qr_userpointer_get(v, (SQUserPointer) &d);
201         if(SQ_FAILED(r)){
202                 return r;
203         }
204         struct romimage image;
205         long mirrorfind;
206         r = qr_argument_get(v, 2, &image.mappernum, &mirrorfind);
207         if(SQ_FAILED(r)){
208                 return r;
209         }
210         image.cpu_rom = d->cpu.memory;
211         image.cpu_ram.data = NULL;
212         image.ppu_rom = d->ppu.memory;
213         image.mirror = MIRROR_PROGRAMABLE;
214         if(mirrorfind == 1){
215                 if(d->vram_connection() == 0x05){
216                         image.mirror = MIRROR_VERTICAL;
217                 }else{
218                         image.mirror = MIRROR_HORIZONAL;
219                 }
220         }
221         image.backupram = 0;
222         nesfile_create(d->log, &image, d->target);
223         nesbuffer_free(&image, 0); //0 is MODE_xxx_xxxx
224         
225         d->cpu.memory.data = NULL;
226         d->ppu.memory.data = NULL;
227         return 0;
228 }
229
230 //dump »þ/1ÅÙÌܤΠcall ¤Ç nesfile_save ¤È¤·¤Æ»ÈÍÑ
231 static SQInteger length_check(HSQUIRRELVM v)
232 {
233         struct dump_driver *d;
234         SQRESULT r =  qr_userpointer_get(v, (SQUserPointer) &d);
235         if(SQ_FAILED(r)){
236                 return r;
237         }
238         bool cpu = true, ppu = true;
239         r = 0;
240         if(d->cpu.memory.size != d->cpu.read_count){
241                 cpu = false;
242         }
243         char str[80];
244         if(cpu == false){
245                 snprintf(str, 80, "cpu_romsize is not connected 0x%06x/0x%06x\n", (int) d->cpu.read_count, (int) d->cpu.memory.size);
246                 d->log->append(d->log->object, str);
247         }
248         if(d->ppu.memory.size != d->ppu.read_count){
249                 ppu = false;
250         }
251         if(ppu == false){
252                 snprintf(str, 80, "ppu_romsize is not connected 0x%06x/0x%06x\n", (int) d->ppu.read_count, (int) d->ppu.memory.size);
253                 d->log->append(d->log->object, str);
254         }
255         if(cpu == false || ppu == false){
256                 r = sq_throwerror(v, "script logical error");
257         }
258         return r;
259 }
260
261 static SQInteger read_count(HSQUIRRELVM v, struct textcontrol *l, struct memory_driver *t, const struct range *range_address, const struct range *range_length)
262 {
263         long address, length;
264         SQRESULT r = qr_argument_get(v, 2, &address, &length);
265         if(SQ_FAILED(r)){
266                 return r;
267         }
268         r = range_check(v, "length", length, range_length);
269         if(SQ_FAILED(r)){
270                 return r;
271         }
272         if((address < range_address->start) || ((address + length) > range_address->end)){
273                 char str[80];
274                 snprintf(str, 80, "address range must be 0x%06x to 0x%06x", (int) range_address->start, (int) range_address->end);
275                 l->append(l->object, str);
276                 return sq_throwerror(v, "script logical error");;
277         }
278         t->read_count += length;
279         return 0;
280 }
281 static SQInteger cpu_read_count(HSQUIRRELVM v)
282 {
283         static const struct range range_address = {0x8000, 0x10000};
284         //length == 0 ¤Ï Âоݥ¢¥É¥ì¥¹¤ò¸Æ¤ó¤Ç¡¢¥Ð¥Ã¥Õ¥¡¤Ë¤¤¤ì¤Ê¤¤¡£mmc2, mmc4 ¤Ç»ÈÍѤ¹¤ë¡£
285         static const struct range range_length = {0x0000, 0x4000};
286         struct dump_driver *d;
287         SQRESULT r =  qr_userpointer_get(v, (SQUserPointer) &d);
288         if(SQ_FAILED(r)){
289                 return r;
290         }
291         return read_count(v, d->log, &d->cpu, &range_address, &range_length);
292 }
293
294 static SQInteger ppu_read_count(HSQUIRRELVM v)
295 {
296         static const struct range range_address = {0x0000, 0x2000};
297         static const struct range range_length = {0x0001, 0x2000};
298         struct dump_driver *d;
299         SQRESULT r =  qr_userpointer_get(v, (SQUserPointer) &d);
300         if(SQ_FAILED(r)){
301                 return r;
302         }
303         return read_count(v, d->log, &d->ppu, &range_address, &range_length);
304 }
305
306 static bool script_execute(HSQUIRRELVM v, struct config_dump *c, struct dump_driver *d)
307 {
308         bool ret = true;
309         if(SQ_FAILED(sqstd_dofile(v, _SC("dumpcore.nut"), SQFalse, SQTrue))){
310                 d->log->append(d->log->object, "dump core script error\n");
311                 ret = false;
312         }else if(SQ_FAILED(sqstd_dofile(v, _SC(c->script), SQFalse, SQTrue))){
313                 char str[80];
314                 snprintf(str, 80, "%s open error\n", c->script);
315                 d->log->append(d->log->object, str);
316                 ret = false;
317         }else{
318                 SQRESULT r = qr_call(
319                         v, "dump", (SQUserPointer) d, true, 
320                         3, c->mappernum, c->increase.cpu, c->increase.ppu
321                 );
322                 if(SQ_FAILED(r)){
323                         ret = false;
324                         Free(d->cpu.memory.data);
325                         Free(d->ppu.memory.data);
326                         d->cpu.memory.data = NULL;
327                         d->ppu.memory.data = NULL;
328                 }
329         }
330         return ret;
331 }
332 void script_dump_execute(struct config_dump *c)
333 {
334         struct dump_driver d = {
335                 .cpu = {
336                         .memory = {
337                                 .name = "program",
338                                 .size = 0, .offset = 0,
339                                 .attribute = MEMORY_ATTR_WRITE,
340                                 .transtype = TRANSTYPE_FULL,
341                                 .data = NULL
342                         },
343                         .read_count = 0,
344                         .write = c->reader->cpu_write_6502,
345                         .read = c->reader->cpu_read,
346                         .gauge = &c->gauge_cpu
347                 },
348                 .ppu = {
349                         .memory = {
350                                 .name = "charcter",
351                                 .size = 0, .offset = 0,
352                                 .attribute = MEMORY_ATTR_WRITE,
353                                 .transtype = TRANSTYPE_FULL,
354                                 .data = NULL
355                         },
356                         .read_count = 0,
357                         .write = c->reader->ppu_write,
358                         .read = c->reader->ppu_read,
359                         .gauge = &c->gauge_ppu
360                 },
361                 .vram_connection = c->reader->vram_connection,
362                 .target = c->target,
363                 .progress = c->progress,
364                 .log = &c->log
365         };
366         {
367                 HSQUIRRELVM v = qr_open(&c->log); 
368                 qr_function_register_global(v, "ppu_ramfind", script_nop);
369                 qr_function_register_global(v, "cpu_write", cpu_write_check);
370                 qr_function_register_global(v, "memory_new", memory_new);
371                 qr_function_register_global(v, "nesfile_save", length_check);
372                 qr_function_register_global(v, "cpu_read", cpu_read_count);
373                 qr_function_register_global(v, "ppu_read", ppu_read_count);
374                 qr_function_register_global(v, "require", script_require);
375                 if(script_execute(v, c, &d) == false){
376                         qr_close(v);
377                         return;
378                 }
379                 qr_close(v);
380         }
381         if(c->progress == true){
382                 progress_init();
383         }
384         {
385                 HSQUIRRELVM v = qr_open(&c->log); 
386                 qr_function_register_global(v, "memory_new", script_nop);
387                 qr_function_register_global(v, "nesfile_save", nesfile_save);
388                 qr_function_register_global(v, "cpu_write", cpu_write);
389                 qr_function_register_global(v, "cpu_read", cpu_read);
390                 qr_function_register_global(v, "ppu_read", ppu_read);
391                 qr_function_register_global(v, "ppu_ramfind", ppu_ramfind);
392                 qr_function_register_global(v, "require", script_require);
393                 script_execute(v, c, &d);
394                 qr_close(v);
395         }
396 }