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"
17 static SQInteger cpu_write(HSQUIRRELVM v)
19 struct dump_config *d;
21 SQRESULT r = qr_userpointer_get(v, (SQUserPointer) &d);
25 cpu_write_execute(v, d->handle, d->cpu.access);
29 //ここの printf は debug 用に残しておく
30 static void buffer_show(struct memory *t, long length)
33 const uint8_t *buf = t->data + t->offset;
35 wprintf(L"%s 0x%06x:", t->name, t->offset);
37 printf("%s 0x%06x:", t->name, t->offset);
39 for(i = 0; i < 0x10; i++){
42 //wsprintf(dump, L"%02x", buf[i]);
44 sprintf(dump, "%02x", buf[i]);
71 wprintf(L":0x%06x\n", sum);
73 printf(":0x%06x\n", sum);
78 static SQInteger read_memory(HSQUIRRELVM v, const struct reader_handle *h, struct dump_memory_driver *t, bool progress)
81 SQRESULT r = qr_argument_get(v, 2, &address, &length);
85 assert(t->memory.attribute == MEMORY_ATTR_WRITE);
86 t->access->memory_read(h, &t->gauge, address, length == 0 ? 1: length, t->memory.data + t->memory.offset);
87 if((length != 0) && (progress == false)){
88 buffer_show(&t->memory, length);
90 t->memory.offset += length;
94 static SQInteger cpu_read(HSQUIRRELVM v)
96 struct dump_config *d;
97 SQRESULT r = qr_userpointer_get(v, (SQUserPointer) &d);
101 r = read_memory(v, d->handle, &d->cpu, d->progress);
105 static SQInteger ppu_read(HSQUIRRELVM v)
107 struct dump_config *d;
108 SQRESULT r = qr_userpointer_get(v, (SQUserPointer) &d);
112 r = read_memory(v, d->handle, &d->ppu, d->progress);
116 static SQInteger ppu_ramfind(HSQUIRRELVM v)
118 struct dump_config *d;
123 static const uint8_t test_val[testsize] = {0xaa, 0x55, 0, 0xff, 0x46, 0x49, 0x07, 0x21};
124 static const uint8_t test_str[testsize] = "pputest";
125 uint8_t test_result[testsize];
126 SQRESULT r = qr_userpointer_get(v, (SQUserPointer) &d);
127 struct dump_memory_driver *p = &d->ppu;
132 p->access->memory_write(d->handle, testaddress, testsize, test_val);
133 p->access->memory_read(d->handle, &GAUGE_DUMMY, testaddress, testsize, test_result);
134 if(memcmp(test_val, test_result, testsize) != 0){
135 sq_pushbool(v, SQFalse);
138 p->access->memory_write(d->handle, testaddress, testsize, test_str);
139 p->access->memory_read(d->handle, &GAUGE_DUMMY, testaddress, testsize, test_result);
140 if(memcmp(test_str, test_result, testsize) != 0){
141 sq_pushbool(v, SQFalse);
144 p->memory.offset = 0;
146 sq_pushbool(v, SQTrue);
150 static SQInteger return_true(HSQUIRRELVM v)
152 sq_pushbool(v, SQFalse);
156 static void memory_new_init(struct dump_memory_driver *d)
158 d->memory.offset = 0;
159 d->memory.data = Malloc(d->memory.size);
160 d->gauge.range_set(d->gauge.bar, d->memory.size);
161 d->gauge.value_set(d->gauge.bar, d->gauge.label, 0);
164 //test 時/1度目の call で使用
165 static SQInteger memory_new(HSQUIRRELVM v)
167 struct dump_config *d;
168 SQRESULT r = qr_userpointer_get(v, (SQUserPointer) &d);
172 r = qr_argument_get(v, 2, &d->cpu.memory.size, &d->ppu.memory.size);
177 memory_new_init(&d->cpu);
178 if(d->mode == MODE_ROM_DUMP){
179 memory_new_init(&d->ppu);
184 //dump 時/2度目の call で nesfile_save として使用
185 static SQInteger nesfile_save(HSQUIRRELVM v)
187 struct dump_config *d;
188 SQRESULT r = qr_userpointer_get(v, (SQUserPointer) &d);
192 struct romimage image;
194 r = qr_argument_get(v, 2, &image.mappernum, &mirrorfind);
198 image.cpu_rom = d->cpu.memory;
199 image.cpu_ram.data = NULL;
200 image.ppu_rom = d->ppu.memory;
201 image.mirror = MIRROR_PROGRAMABLE;
203 uint8_t c = d->control->vram_connection(d->handle);
205 d->log.append(d->log.object, wgT("vram connection %x\n"), c);
208 image.mirror = MIRROR_VERTICAL;
210 image.mirror = MIRROR_HORIZONAL;
214 if(d->battery == true){
217 d->crc = nesfile_create(&d->log, &image, d->target);
218 nesbuffer_free(&image, 0); //0 is MODE_xxx_xxxx
220 d->cpu.memory.data = NULL;
221 d->ppu.memory.data = NULL;
225 //dump 時/1度目の call で nesfile_save として使用
226 static SQInteger length_check(HSQUIRRELVM v)
228 struct dump_config *d;
229 SQRESULT r = qr_userpointer_get(v, (SQUserPointer) &d);
233 bool cpu = true, ppu = true;
235 if(d->cpu.memory.size != d->cpu.read_count){
239 d->log.append(d->log.object, wgT("cpu_romsize is not connected 0x%06x/0x%06x\n"), (int) d->cpu.read_count, (int) d->cpu.memory.size);
241 if(d->ppu.memory.size != d->ppu.read_count){
245 d->log.append(d->log.object, wgT("ppu_romsize is not connected 0x%06x/0x%06x\n"), (int) d->ppu.read_count, (int) d->ppu.memory.size);
247 if(cpu == false || ppu == false){
248 r = sq_throwerror(v, wgT("script logical error"));
253 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)
255 long address, length;
256 SQRESULT r = qr_argument_get(v, 2, &address, &length);
260 r = range_check(v, wgT("length"), length, range_length);
264 if((address < range_address->start) || ((address + length) > range_address->end)){
265 l->append(l->object, wgT("address range must be 0x%06x to 0x%06x"), (int) range_address->start, (int) range_address->end);
266 return sq_throwerror(v, wgT("script logical error"));;
268 t->read_count += length;
271 static SQInteger cpu_read_count(HSQUIRRELVM v)
273 static const struct range range_address = {0x8000, 0x10000};
274 //length == 0 は 対象アドレスを呼んで、バッファにいれない。mmc2, mmc4 で使用する。
275 static const struct range range_length = {0x0000, 0x4000};
276 struct dump_config *d;
277 SQRESULT r = qr_userpointer_get(v, (SQUserPointer) &d);
281 return read_count(v, &d->log, &d->cpu, &range_address, &range_length);
284 static SQInteger ppu_read_count(HSQUIRRELVM v)
286 static const struct range range_address = {0x0000, 0x2000};
287 static const struct range range_length = {0x0001, 0x2000};
288 struct dump_config *d;
289 SQRESULT r = qr_userpointer_get(v, (SQUserPointer) &d);
293 return read_count(v, &d->log, &d->ppu, &range_address, &range_length);
296 static SQInteger memory_size_set(HSQUIRRELVM v)
298 struct dump_config *d;
299 SQRESULT r = qr_userpointer_get(v, (SQUserPointer) &d);
303 r = qr_argument_get(v, 2, &d->cpu.memory.size, &d->ppu.memory.size);
307 static bool script_execute(HSQUIRRELVM v, struct dump_config *d)
310 if(SQ_FAILED(sqstd_dofile(v, wgT("dumpcore.nut"), SQFalse, SQTrue))){
311 d->log.append(d->log.object, wgT("dump core script error\n"));
314 SQRESULT r = qr_call(
315 v, wgT("dump"), (SQUserPointer) d, d->script,
316 3, d->mappernum, d->cpu.increase, d->ppu.increase
320 Free(d->cpu.memory.data);
321 Free(d->ppu.memory.data);
322 d->cpu.memory.data = NULL;
323 d->ppu.memory.data = NULL;
329 static void dump_memory_driver_init(struct dump_memory_driver *dd, enum memory_attribute at)
332 dd->memory.offset = 0;
333 dd->memory.attribute = at;
334 dd->memory.transtype = TRANSTYPE_FULL;
335 dd->memory.data = NULL;
339 bool script_dump_execute(struct dump_config *d)
341 dump_memory_driver_init(&d->cpu, MEMORY_ATTR_WRITE);
342 d->cpu.memory.name = wgT("Program");
344 dump_memory_driver_init(&d->ppu, MEMORY_ATTR_WRITE);
345 d->ppu.memory.name = wgT("Charcter");
348 HSQUIRRELVM v = qr_open(&d->log);
349 qr_function_register_global(v, wgT("cpu_write"), cpu_write_check);
350 qr_function_register_global(v, wgT("memory_new"), memory_size_set);
351 qr_function_register_global(v, wgT("nesfile_save"), length_check);
352 qr_function_register_global(v, wgT("cpu_read"), cpu_read_count);
353 qr_function_register_global(v, wgT("ppu_read"), ppu_read_count);
354 qr_function_register_global(v, wgT("ppu_ramfind"), return_true);
355 if(script_execute(v, d) == false){
362 d->handle = d->control->open(d->except, &d->log);
363 if(d->handle == NULL){
364 d->log.append(d->log.object, wgT("reader open error\n"));
367 d->control->init(d->handle);
368 if(connection_check(d->handle, &d->log, d->cpu.access, d->ppu.access) == false){
369 d->control->close(d->handle);
373 HSQUIRRELVM v = qr_open(&d->log);
374 qr_function_register_global(v, wgT("memory_new"), memory_new);
375 qr_function_register_global(v, wgT("nesfile_save"), nesfile_save);
376 qr_function_register_global(v, wgT("cpu_write"), cpu_write);
377 qr_function_register_global(v, wgT("cpu_read"), cpu_read);
378 qr_function_register_global(v, wgT("ppu_read"), ppu_read);
379 qr_function_register_global(v, wgT("ppu_ramfind"), ppu_ramfind);
380 script_execute(v, d);
383 d->control->close(d->handle);
388 static bool workram_execute(HSQUIRRELVM v, struct dump_config *d)
391 if(SQ_FAILED(sqstd_dofile(v, wgT("dumpcore.nut"), SQFalse, SQTrue))){
392 d->log.append(d->log.object, wgT("dump core script error\n"));
395 SQRESULT r = qr_call(
396 v, wgT("workram_rw"), (SQUserPointer) d, d->script,
401 Free(d->cpu.memory.data);
402 d->cpu.memory.data = NULL;
403 // Free(d->ppu.memory.data);
404 // d->ppu.memory.data = NULL;
410 static SQInteger cpu_ramrw_check(HSQUIRRELVM v)
412 static const struct range range_address = {0x6000, 0xdfff};
413 static const struct range range_length = {1, 0x2000};
414 struct dump_config *d;
415 SQRESULT r = qr_userpointer_get(v, (SQUserPointer) &d);
419 return read_count(v, &d->log, &d->cpu, &range_address, &range_length);
422 static SQInteger ramimage_open(HSQUIRRELVM v)
424 struct dump_config *d;
425 SQRESULT r = qr_userpointer_get(v, (SQUserPointer) &d);
429 if(buf_load(d->cpu.memory.data, d->target, d->cpu.memory.size) == NG){
430 return r = sq_throwerror(v, wgT("RAM image open error"));
435 static SQInteger memory_finalize(HSQUIRRELVM v)
437 struct dump_config *d;
438 SQRESULT r = qr_userpointer_get(v, (SQUserPointer) &d);
442 if(d->mode == MODE_RAM_READ){
443 buf_save(d->cpu.memory.data, d->target, d->cpu.memory.size);
445 Free(d->cpu.memory.data);
446 d->cpu.memory.data = NULL;
447 // Free(d->ppu.memory.data);
448 // d->ppu.memory.data = NULL;
453 static SQInteger cpu_write_ramimage(HSQUIRRELVM v)
455 struct dump_config *d;
456 SQRESULT r = qr_userpointer_get(v, (SQUserPointer) &d);
461 long address, length;
463 const uint8_t *writedata = d->cpu.memory.data;
464 writedata += d->cpu.memory.offset;
466 r = qr_argument_get(v, 2, &address, &length);
470 cmp = Malloc(length);
471 assert(d->cpu.memory.attribute == MEMORY_ATTR_READ);
473 d->cpu.access->memory_write(
474 d->handle, address, length, writedata
476 d->cpu.access->memory_read(
477 d->handle, &d->cpu.gauge, address, length, cmp
479 d->cpu.memory.offset += length;
481 r = memcmp(cmp, writedata, length);
484 r = sq_throwerror(v, wgT("memory write failed"));
489 bool script_workram_execute(struct dump_config *d)
491 dump_memory_driver_init(&d->cpu, d->mode == MODE_RAM_READ ? MEMORY_ATTR_WRITE : MEMORY_ATTR_READ);
492 dump_memory_driver_init(&d->ppu, MEMORY_ATTR_NOTUSE);
493 d->cpu.memory.name = wgT("Workram");
494 d->ppu.memory.name = wgT("N/A");
497 HSQUIRRELVM v = qr_open(&d->log);
498 qr_function_register_global(v, wgT("memory_new"), memory_new);
499 qr_function_register_global(v, wgT("cpu_write"), cpu_write_check);
500 qr_function_register_global(v, wgT("cpu_ramrw"), cpu_ramrw_check);
501 qr_function_register_global(v, wgT("memory_finalize"), length_check);
502 if(workram_execute(v, d) == false){
509 d->handle = d->control->open(d->except, &d->log);
510 if(d->handle == NULL){
511 d->log.append(d->log.object, wgT("reader open error\n"));
514 d->control->init(d->handle);
515 if(connection_check(d->handle, &d->log, d->cpu.access, d->ppu.access) == false){
516 d->control->close(d->handle);
520 HSQUIRRELVM v = qr_open(&d->log);
521 qr_function_register_global(v, wgT("cpu_write"), cpu_write);
524 qr_function_register_global(v, wgT("memory_new"), script_nop);
525 qr_function_register_global(v, wgT("cpu_ramrw"), cpu_read);
528 qr_function_register_global(v, wgT("memory_new"), ramimage_open);
529 qr_function_register_global(v, wgT("cpu_ramrw"), cpu_write_ramimage);
535 qr_function_register_global(v, wgT("memory_finalize"), memory_finalize);
536 workram_execute(v, d);
539 d->control->close(d->handle);