OSDN Git Service

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