OSDN Git Service

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