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"
21 void (*const write)(long address, long length, const uint8_t *data);
22 void (*const read)(long address, long length, u8 *data);
24 uint8_t (*const vram_connection)(void);
27 static SQInteger write_memory(HSQUIRRELVM v, struct memory_driver *t)
30 SQRESULT r = qr_argument_get(v, 2, &address, &data);
34 uint8_t d8 = (uint8_t) data;
35 t->write(address, 1, &d8);
38 static SQInteger cpu_write(HSQUIRRELVM v)
40 struct dump_driver *d;
41 SQRESULT r = qr_userpointer_get(v, (SQUserPointer) &d);
45 return write_memory(v, &d->cpu);
48 static void buffer_show(struct memory *t, long length)
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++){
55 sprintf(dump, "%02x", buf[i]);
76 printf(":0x%06x\n", sum);
80 static void progress_show(struct dump_driver *d)
82 if(d->progress == true){
83 progress_draw(d->cpu.memory.offset, d->cpu.memory.size, d->ppu.memory.offset, d->ppu.memory.size);
86 static SQInteger read_memory(HSQUIRRELVM v, struct memory_driver *t, bool progress)
89 SQRESULT r = qr_argument_get(v, 2, &address, &length);
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);
97 t->memory.offset += length;
100 static SQInteger cpu_read(HSQUIRRELVM v)
102 struct dump_driver *d;
103 SQRESULT r = qr_userpointer_get(v, (SQUserPointer) &d);
107 r = read_memory(v, &d->cpu, d->progress);
112 static SQInteger ppu_read(HSQUIRRELVM v)
114 struct dump_driver *d;
115 SQRESULT r = qr_userpointer_get(v, (SQUserPointer) &d);
119 r = read_memory(v, &d->ppu, d->progress);
124 static SQInteger ppu_ramfind(HSQUIRRELVM v)
126 struct dump_driver *d;
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];
135 SQRESULT r = qr_userpointer_get(v, (SQUserPointer) &d);
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);
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);
151 d->ppu.memory.offset = 0;
152 d->ppu.memory.size = 0;
153 sq_pushbool(v, SQTrue);
157 //test »þ/1ÅÙÌܤΠcall ¤Ç»ÈÍÑ
158 static SQInteger memory_new(HSQUIRRELVM v)
160 struct dump_driver *d;
161 SQRESULT r = qr_userpointer_get(v, (SQUserPointer) &d);
165 r = qr_argument_get(v, 2, &d->cpu.memory.size, &d->ppu.memory.size);
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);
176 //dump »þ/2ÅÙÌܤΠcall ¤Ç nesfile_save ¤È¤·¤Æ»ÈÍÑ
177 static SQInteger nesfile_save(HSQUIRRELVM v)
179 struct dump_driver *d;
180 SQRESULT r = qr_userpointer_get(v, (SQUserPointer) &d);
184 struct romimage image;
186 r = qr_argument_get(v, 2, &image.mappernum, &mirrorfind);
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;
195 if(d->vram_connection() == 0x05){
196 image.mirror = MIRROR_VERTICAL;
198 image.mirror = MIRROR_HORIZONAL;
202 nesfile_create(&image, d->target);
203 nesbuffer_free(&image, 0); //0 is MODE_xxx_xxxx
205 d->cpu.memory.data = NULL;
206 d->ppu.memory.data = NULL;
210 //dump »þ/1ÅÙÌܤΠcall ¤Ç nesfile_save ¤È¤·¤Æ»ÈÍÑ
211 static SQInteger length_check(HSQUIRRELVM v)
213 struct dump_driver *d;
214 SQRESULT r = qr_userpointer_get(v, (SQUserPointer) &d);
218 bool cpu = true, ppu = true;
220 if(d->cpu.memory.size != d->cpu.read_count){
224 printf("cpu_romsize is not connected 0x%06x/0x%06x\n", (int) d->cpu.read_count, (int) d->cpu.memory.size);
226 if(d->ppu.memory.size != d->ppu.read_count){
230 printf("ppu_romsize is not connected 0x%06x/0x%06x\n", (int) d->ppu.read_count, (int) d->ppu.memory.size);
232 if(cpu == false || ppu == false){
233 r = sq_throwerror(v, "script logical error");
238 static SQInteger read_count(HSQUIRRELVM v, struct memory_driver *t, const struct range *range_address, const struct range *range_length)
240 long address, length;
241 SQRESULT r = qr_argument_get(v, 2, &address, &length);
245 r = range_check(v, "length", length, range_length);
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");;
253 t->read_count += length;
256 static SQInteger cpu_read_count(HSQUIRRELVM v)
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);
266 return read_count(v, &d->cpu, &range_address, &range_length);
269 static SQInteger ppu_read_count(HSQUIRRELVM v)
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);
278 return read_count(v, &d->ppu, &range_address, &range_length);
281 static bool script_execute(HSQUIRRELVM v, struct config_dump *c, struct dump_driver *d)
284 if(SQ_FAILED(sqstd_dofile(v, _SC("dumpcore.nut"), SQFalse, SQTrue))){
285 printf("dump core script error\n");
287 }else if(SQ_FAILED(sqstd_dofile(v, _SC(c->script), SQFalse, SQTrue))){
288 printf("%s open error\n", c->script);
291 SQRESULT r = qr_call(
292 v, "dump", (SQUserPointer) d, true,
293 3, c->mappernum, c->increase.cpu, c->increase.ppu
297 Free(d->cpu.memory.data);
298 Free(d->ppu.memory.data);
299 d->cpu.memory.data = NULL;
300 d->ppu.memory.data = NULL;
305 void script_dump_execute(struct config_dump *c)
307 struct dump_driver d = {
311 .size = 0, .offset = 0,
312 .attribute = MEMORY_ATTR_WRITE,
313 .transtype = TRANSTYPE_FULL,
317 .write = c->reader->cpu_write_6502,
318 .read = c->reader->cpu_read
323 .size = 0, .offset = 0,
324 .attribute = MEMORY_ATTR_WRITE,
325 .transtype = TRANSTYPE_FULL,
329 .write = c->reader->ppu_write,
330 .read = c->reader->ppu_read
332 .vram_connection = c->reader->vram_connection,
334 .progress = c->progress
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){
351 if(c->progress == true){
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);