OSDN Git Service

e1a2dca57e5f763fbaded2e0a3f422607e93ea28
[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
84         return 0;
85 }
86
87 static SQInteger cpu_read(HSQUIRRELVM v)
88 {
89         struct dump_config *d;
90         SQRESULT r =  qr_userpointer_get(v, (SQUserPointer) &d);
91         if(SQ_FAILED(r)){
92                 return r;
93         }
94         r = read_memory(v, d->handle, &d->cpu, d->progress);
95         return r;
96 }
97
98 static SQInteger ppu_read(HSQUIRRELVM v)
99 {
100         struct dump_config *d;
101         SQRESULT r =  qr_userpointer_get(v, (SQUserPointer) &d);
102         if(SQ_FAILED(r)){
103                 return r;
104         }
105         r = read_memory(v, d->handle, &d->ppu, d->progress);
106         return r;
107 }
108
109 static SQInteger ppu_ramfind(HSQUIRRELVM v)
110 {
111         struct dump_config *d;
112         enum{
113                 testsize = 8,
114                 testaddress = 1234
115         };
116         static const uint8_t test_val[testsize] = {0xaa, 0x55, 0, 0xff, 0x46, 0x49, 0x07, 0x21};
117         static const uint8_t test_str[testsize] = "pputest";
118         uint8_t test_result[testsize];
119         SQRESULT r =  qr_userpointer_get(v, (SQUserPointer) &d);
120         struct dump_memory_driver *p = &d->ppu;
121
122         if(SQ_FAILED(r)){
123                 return r;
124         }
125         p->access->memory_write(d->handle, testaddress, testsize, test_val);
126         p->access->memory_read(d->handle, &GAUGE_DUMMY, testaddress, testsize, test_result);
127         if(memcmp(test_val, test_result, testsize) != 0){
128                 sq_pushbool(v, SQFalse);
129                 return 1;
130         }
131         p->access->memory_write(d->handle, testaddress, testsize, test_str);
132         p->access->memory_read(d->handle, &GAUGE_DUMMY, testaddress, testsize, test_result);
133         if(memcmp(test_str, test_result, testsize) != 0){
134                 sq_pushbool(v, SQFalse);
135                 return 1;
136         }
137         p->memory.offset = 0;
138         p->memory.size = 0;
139         sq_pushbool(v, SQTrue);
140         return 1;
141 }
142
143 static void memory_new_init(struct dump_memory_driver *d)
144 {
145         d->memory.offset = 0;
146         d->memory.data = Malloc(d->memory.size);
147         d->gauge.range_set(d->gauge.bar, d->memory.size);
148         d->gauge.value_set(d->gauge.bar, d->gauge.label, 0);
149 }
150
151 //test »þ/1ÅÙÌܤΠcall ¤Ç»ÈÍÑ
152 static SQInteger memory_new(HSQUIRRELVM v)
153 {
154         struct dump_config *d;
155         SQRESULT r =  qr_userpointer_get(v, (SQUserPointer) &d);
156         if(SQ_FAILED(r)){
157                 return r;
158         }
159         r = qr_argument_get(v, 2, &d->cpu.memory.size, &d->ppu.memory.size);
160         if(SQ_FAILED(r)){
161                 return r;
162         }
163
164         memory_new_init(&d->cpu);
165         memory_new_init(&d->ppu);
166         return 0;
167 }
168
169 //dump »þ/2ÅÙÌܤΠcall ¤Ç nesfile_save ¤È¤·¤Æ»ÈÍÑ
170 static SQInteger nesfile_save(HSQUIRRELVM v)
171 {
172         struct dump_config *d;
173         SQRESULT r =  qr_userpointer_get(v, (SQUserPointer) &d);
174         if(SQ_FAILED(r)){
175                 return r;
176         }
177         struct romimage image;
178         long mirrorfind;
179         r = qr_argument_get(v, 2, &image.mappernum, &mirrorfind);
180         if(SQ_FAILED(r)){
181                 return r;
182         }
183         image.cpu_rom = d->cpu.memory;
184         image.cpu_ram.data = NULL;
185         image.ppu_rom = d->ppu.memory;
186         image.mirror = MIRROR_PROGRAMABLE;
187         if(mirrorfind == 1){
188                 if(d->control->vram_connection(d->handle) == 0x05){
189                         image.mirror = MIRROR_VERTICAL;
190                 }else{
191                         image.mirror = MIRROR_HORIZONAL;
192                 }
193         }
194         image.backupram = 0;
195         if(d->battery == true){
196                 image.backupram = 1;
197         }
198         nesfile_create(&d->log, &image, d->target);
199         nesbuffer_free(&image, 0); //0 is MODE_xxx_xxxx
200         
201         d->cpu.memory.data = NULL;
202         d->ppu.memory.data = NULL;
203         return 0;
204 }
205
206 //dump »þ/1ÅÙÌܤΠcall ¤Ç nesfile_save ¤È¤·¤Æ»ÈÍÑ
207 static SQInteger length_check(HSQUIRRELVM v)
208 {
209         struct dump_config *d;
210         SQRESULT r =  qr_userpointer_get(v, (SQUserPointer) &d);
211         if(SQ_FAILED(r)){
212                 return r;
213         }
214         bool cpu = true, ppu = true;
215         r = 0;
216         if(d->cpu.memory.size != d->cpu.read_count){
217                 cpu = false;
218         }
219         if(cpu == false){
220                 d->log.append(d->log.object, "cpu_romsize is not connected 0x%06x/0x%06x\n", (int) d->cpu.read_count, (int) d->cpu.memory.size);
221         }
222         if(d->ppu.memory.size != d->ppu.read_count){
223                 ppu = false;
224         }
225         if(ppu == false){
226                 d->log.append(d->log.object, "ppu_romsize is not connected 0x%06x/0x%06x\n", (int) d->ppu.read_count, (int) d->ppu.memory.size);
227         }
228         if(cpu == false || ppu == false){
229                 r = sq_throwerror(v, "script logical error");
230         }
231         return r;
232 }
233
234 static SQInteger read_count(HSQUIRRELVM v, const struct textcontrol *l, struct dump_memory_driver *t, const struct range *range_address, const struct range *range_length)
235 {
236         long address, length;
237         SQRESULT r = qr_argument_get(v, 2, &address, &length);
238         if(SQ_FAILED(r)){
239                 return r;
240         }
241         r = range_check(v, "length", length, range_length);
242         if(SQ_FAILED(r)){
243                 return r;
244         }
245         if((address < range_address->start) || ((address + length) > range_address->end)){
246                 l->append(l->object, "address range must be 0x%06x to 0x%06x", (int) range_address->start, (int) range_address->end);
247                 return sq_throwerror(v, "script logical error");;
248         }
249         t->read_count += length;
250         return 0;
251 }
252 static SQInteger cpu_read_count(HSQUIRRELVM v)
253 {
254         static const struct range range_address = {0x8000, 0x10000};
255         //length == 0 ¤Ï Âоݥ¢¥É¥ì¥¹¤ò¸Æ¤ó¤Ç¡¢¥Ð¥Ã¥Õ¥¡¤Ë¤¤¤ì¤Ê¤¤¡£mmc2, mmc4 ¤Ç»ÈÍѤ¹¤ë¡£
256         static const struct range range_length = {0x0000, 0x4000};
257         struct dump_config *d;
258         SQRESULT r =  qr_userpointer_get(v, (SQUserPointer) &d);
259         if(SQ_FAILED(r)){
260                 return r;
261         }
262         return read_count(v, &d->log, &d->cpu, &range_address, &range_length);
263 }
264
265 static SQInteger ppu_read_count(HSQUIRRELVM v)
266 {
267         static const struct range range_address = {0x0000, 0x2000};
268         static const struct range range_length = {0x0001, 0x2000};
269         struct dump_config *d;
270         SQRESULT r =  qr_userpointer_get(v, (SQUserPointer) &d);
271         if(SQ_FAILED(r)){
272                 return r;
273         }
274         return read_count(v, &d->log, &d->ppu, &range_address, &range_length);
275 }
276
277 static SQInteger memory_size_set(HSQUIRRELVM v)
278 {
279         struct dump_config *d;
280         SQRESULT r =  qr_userpointer_get(v, (SQUserPointer) &d);
281         if(SQ_FAILED(r)){
282                 return r;
283         }
284         r = qr_argument_get(v, 2, &d->cpu.memory.size, &d->ppu.memory.size);
285         return r;
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                 d->log.append(d->log.object, "%s open error\n", d->script);
296                 ret = false;
297         }else{
298                 SQRESULT r = qr_call(
299                         v, "dump", (SQUserPointer) d, true, 
300                         3, d->mappernum, d->cpu.increase, d->ppu.increase
301                 );
302                 if(SQ_FAILED(r)){
303                         ret = false;
304                         Free(d->cpu.memory.data);
305                         Free(d->ppu.memory.data);
306                         d->cpu.memory.data = NULL;
307                         d->ppu.memory.data = NULL;
308                 }
309         }
310         return ret;
311 }
312
313 static void dump_memory_driver_init(struct dump_memory_driver *dd)
314 {
315         dd->memory.size = 0;
316         dd->memory.offset = 0;
317         dd->memory.attribute = MEMORY_ATTR_WRITE;
318         dd->memory.transtype = TRANSTYPE_FULL;
319         dd->memory.data = NULL;
320         dd->read_count = 0;
321 }
322
323 void script_dump_execute(struct dump_config *d)
324 {
325         dump_memory_driver_init(&d->cpu);
326         d->cpu.memory.name = "Program";
327         
328         dump_memory_driver_init(&d->ppu);
329         d->ppu.memory.name = "Charcter";
330         
331         {
332                 HSQUIRRELVM v = qr_open(&d->log); 
333                 qr_function_register_global(v, "ppu_ramfind", script_nop);
334                 qr_function_register_global(v, "cpu_write", cpu_write_check);
335                 qr_function_register_global(v, "memory_new", memory_size_set);
336                 qr_function_register_global(v, "nesfile_save", length_check);
337                 qr_function_register_global(v, "cpu_read", cpu_read_count);
338                 qr_function_register_global(v, "ppu_read", ppu_read_count);
339                 qr_function_register_global(v, "require", script_require);
340                 if(script_execute(v, d) == false){
341                         qr_close(v);
342                         return;
343                 }
344                 qr_close(v);
345         }
346 /*      if(d->progress == true){
347                 progress_init();
348         }*/
349         d->handle = d->control->open(d->except);
350         if(d->handle == NULL){
351                 d->log.append(d->log.object, "reader open error\n");
352                 return;
353         }
354         d->control->init(d->handle);
355         if(connection_check(d->handle, &d->log, d->cpu.access, d->ppu.access) == false){
356                 return;
357         }
358         {
359                 HSQUIRRELVM v = qr_open(&d->log); 
360                 qr_function_register_global(v, "memory_new", memory_new);
361                 qr_function_register_global(v, "nesfile_save", nesfile_save);
362                 qr_function_register_global(v, "cpu_write", cpu_write);
363                 qr_function_register_global(v, "cpu_read", cpu_read);
364                 qr_function_register_global(v, "ppu_read", ppu_read);
365                 qr_function_register_global(v, "ppu_ramfind", ppu_ramfind);
366                 qr_function_register_global(v, "require", script_require);
367                 script_execute(v, d);
368                 qr_close(v);
369         }
370         d->control->close(d->handle);
371         d->handle = NULL;
372 }