OSDN Git Service

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