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 #define USERPOINTER_GET(Pointer, Result) \
18 struct dump_config *Pointer; \
19 SQRESULT Result = qr_userpointer_get(v, (SQUserPointer) &Pointer); \
20 if(SQ_FAILED(Result)){ \
25 static SQInteger cpu_write(HSQUIRRELVM v)
28 cpu_write_execute(v, d->handle, d->cpu.access);
32 //ここの printf は debug 用に残しておく
33 static void buffer_show(struct memory *t, long length)
36 const uint8_t *buf = t->data + t->offset;
38 wprintf(L"%s 0x%06x:", t->name, t->offset);
40 printf("%s 0x%06x:", t->name, t->offset);
42 for(i = 0; i < 0x10; i++){
45 //wsprintf(dump, L"%02x", buf[i]);
47 sprintf(dump, "%02x", buf[i]);
74 wprintf(L":0x%06x\n", sum);
76 printf(":0x%06x\n", sum);
81 static SQInteger read_memory(HSQUIRRELVM v, const struct reader_handle *h, struct dump_memory_driver *t, bool progress)
84 SQRESULT r = qr_argument_get(v, 2, &address, &length);
88 assert(t->memory.attribute == MEMORY_ATTR_WRITE);
89 t->access->memory_read(h, &t->gauge, address, length, t->memory.data + t->memory.offset);
91 if((length != 0) && (progress == false)){
92 buffer_show(&t->memory, length);
94 t->memory.offset += length;
98 static SQInteger cpu_read(HSQUIRRELVM v)
100 USERPOINTER_GET(d, r)
101 r = read_memory(v, d->handle, &d->cpu, d->progress);
105 static SQInteger ppu_read(HSQUIRRELVM v)
107 USERPOINTER_GET(d, r)
108 r = read_memory(v, d->handle, &d->ppu, d->progress);
112 static SQInteger ppu_ramfind(HSQUIRRELVM v)
114 struct dump_config *d;
119 static const uint8_t test_val[testsize] = {0xaa, 0x55, 0, 0xff, 0x46, 0x49, 0x07, 0x21};
120 static const uint8_t test_str[testsize] = "pputest";
121 uint8_t test_result[testsize];
122 SQRESULT r = qr_userpointer_get(v, (SQUserPointer) &d);
123 struct dump_memory_driver *p = &d->ppu;
128 p->access->memory_write(d->handle, testaddress, testsize, test_val);
129 p->access->memory_read(d->handle, &GAUGE_DUMMY, testaddress, testsize, test_result);
130 if(memcmp(test_val, test_result, testsize) != 0){
131 sq_pushbool(v, SQFalse);
134 p->access->memory_write(d->handle, testaddress, testsize, test_str);
135 p->access->memory_read(d->handle, &GAUGE_DUMMY, testaddress, testsize, test_result);
136 if(memcmp(test_str, test_result, testsize) != 0){
137 sq_pushbool(v, SQFalse);
140 p->memory.offset = 0;
142 sq_pushbool(v, SQTrue);
146 static SQInteger return_true(HSQUIRRELVM v)
148 sq_pushbool(v, SQFalse);
152 static void memory_new_init(struct dump_memory_driver *d)
154 d->memory.offset = 0;
155 d->memory.data = Malloc(d->memory.size);
156 d->gauge.range_set(d->gauge.bar, d->memory.size);
157 d->gauge.value_set(d->gauge.bar, d->gauge.label, 0);
160 //test 時/1度目の call で使用
161 static SQInteger memory_new(HSQUIRRELVM v)
163 USERPOINTER_GET(d, r)
165 r = qr_argument_get(v, 2, &d->cpu.memory.size, &d->ppu.memory.size);
170 memory_new_init(&d->cpu);
171 if(d->mode == MODE_ROM_DUMP){
172 memory_new_init(&d->ppu);
177 //dump 時/2度目の call で nesfile_save として使用
178 static SQInteger nesfile_save(HSQUIRRELVM v)
180 USERPOINTER_GET(d, r)
182 struct romimage image;
184 r = qr_argument_get(v, 2, &image.mappernum, &mirrorfind);
188 image.cpu_rom = d->cpu.memory;
189 image.cpu_ram.data = NULL;
190 image.ppu_rom = d->ppu.memory;
191 image.mirror = MIRROR_PROGRAMABLE;
193 uint8_t c = d->control->vram_connection(d->handle);
195 d->log.append(d->log.object, wgT("vram connection %x\n"), c);
198 kazzo 1.0 return value H:9 V:5
199 kazzo 2.x return value H:C V:A
201 if(c == 0x05 || c == 0x0a){
202 image.mirror = MIRROR_VERTICAL;
204 image.mirror = MIRROR_HORIZONAL;
208 if(d->battery == true){
211 d->crc = nesfile_create(&d->log, &image, d->target);
212 nesbuffer_free(&image, 0); //0 is MODE_xxx_xxxx
214 d->cpu.memory.data = NULL;
215 d->ppu.memory.data = NULL;
219 static bool length_check_core(struct dump_config *d, struct dump_memory_driver *m, const wgChar * str)
222 if((m->read_count_bit & 0x7) != 0){
225 m->read_count_byte += m->read_count_bit >> 3;
226 if(m->memory.size != m->read_count_byte){
230 d->log.append(d->log.object, wgT("%s is not connected 0x%06x.%d/0x%06x\n"), str, (int) m->read_count_byte, (int) m->read_count_bit & 7, (int) m->memory.size);
236 //dump 時/1度目の call で nesfile_save として使用
237 static SQInteger length_check(HSQUIRRELVM v)
239 USERPOINTER_GET(d, r)
241 bool cpu = true, ppu = true;
243 cpu = length_check_core(d, &d->cpu, d->mode == MODE_ROM_DUMP ? wgT("board.cpu_rom.size") : wgT("board.cpu_ram.size"));
244 ppu = length_check_core(d, &d->ppu, wgT("board.ppu_rom.size"));
245 if(cpu == false || ppu == false){
246 r = sq_throwerror(v, wgT("script logical error"));
251 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)
253 long address, length;
254 SQRESULT r = qr_argument_get(v, 2, &address, &length);
258 r = range_check(v, wgT("length"), length, range_length);
262 if((address < range_address->start) || ((address + length) > range_address->end)){
263 l->append(l->object, wgT("address range must be 0x%06x to 0x%06x"), (int) range_address->start, (int) range_address->end);
264 return sq_throwerror(v, wgT("script logical error"));;
266 t->read_count_byte += length;
269 static SQInteger cpu_read_count(HSQUIRRELVM v)
272 static const struct range range_address = {0x6000, 0x10000}; //for Sunsoft-5 series test
274 static const struct range range_address = {0x8000, 0x10000};
276 static const struct range range_length = {0x0001, 0x4000};
277 USERPOINTER_GET(d, r)
279 return read_count(v, &d->log, &d->cpu, &range_address, &range_length);
282 static SQInteger ppu_read_count(HSQUIRRELVM v)
285 static const struct range range_address = {0x0000, 0x2800};
287 static const struct range range_address = {0x0000, 0x2000};
289 //length == 0 は 対象アドレスを呼んで、バッファにいれない。mmc2, mmc4 で使用する。
290 static const struct range range_length = {0x0000, 0x2000};
291 USERPOINTER_GET(d, r)
293 return read_count(v, &d->log, &d->ppu, &range_address, &range_length);
296 static SQInteger cpu_read_register_check(HSQUIRRELVM v)
298 static const struct range range_address = {0x4800, 0x8000};
299 static const struct range range_byte = {0, 0xff};
300 USERPOINTER_GET(d, r)
303 r = qr_argument_get(v, 2, &address, &byte);
307 r = range_check(v, wgT("address"), address, &range_address);
311 r = range_check(v, wgT("byte"), byte, &range_byte);
316 sq_pushinteger(v, byte);
320 static SQInteger cpu_read_register(HSQUIRRELVM v)
322 USERPOINTER_GET(d, r)
324 r = qr_argument_get(v, 2, &address, &dummy);
330 d->cpu.access->memory_read(d->handle, &GAUGE_DUMMY, address, 1, &readdata);
332 sq_pushinteger(v, readdata);
336 static SQInteger memory_size_set(HSQUIRRELVM v)
338 USERPOINTER_GET(d, r)
339 r = qr_argument_get(v, 2, &d->cpu.memory.size, &d->ppu.memory.size);
343 static bool script_execute(HSQUIRRELVM v, struct dump_config *d)
346 if(SQ_FAILED(sqstd_dofile(v, wgT("dumpcore.nut"), SQFalse, SQTrue))){
347 d->log.append(d->log.object, wgT("dump core script error\n"));
350 SQRESULT r = qr_call(
351 v, wgT("dump"), (SQUserPointer) d, d->script,
352 3, d->mappernum, d->cpu.increase, d->ppu.increase
356 Free(d->cpu.memory.data);
357 Free(d->ppu.memory.data);
358 d->cpu.memory.data = NULL;
359 d->ppu.memory.data = NULL;
365 static void dump_memory_driver_init(struct dump_memory_driver *dd, enum memory_attribute at)
368 dd->memory.offset = 0;
369 dd->memory.attribute = at;
370 dd->memory.transtype = TRANSTYPE_FULL;
371 dd->memory.data = NULL;
372 dd->read_count_byte = 0;
373 dd->read_count_bit = 0;
376 bool script_dump_execute(struct dump_config *d)
378 dump_memory_driver_init(&d->cpu, MEMORY_ATTR_WRITE);
379 d->cpu.memory.name = wgT("Program");
381 dump_memory_driver_init(&d->ppu, MEMORY_ATTR_WRITE);
382 d->ppu.memory.name = wgT("Charcter");
385 HSQUIRRELVM v = qr_open(&d->log);
386 qr_function_register_global(v, wgT("cpu_write"), cpu_write_check);
387 qr_function_register_global(v, wgT("memory_new"), memory_size_set);
388 qr_function_register_global(v, wgT("nesfile_save"), length_check);
389 qr_function_register_global(v, wgT("cpu_read"), cpu_read_count);
390 qr_function_register_global(v, wgT("ppu_read"), ppu_read_count);
391 qr_function_register_global(v, wgT("ppu_ramfind"), return_true);
392 if(script_execute(v, d) == false){
399 d->handle = d->control->open(d->except, &d->log);
400 if(d->handle == NULL){
401 d->log.append(d->log.object, wgT("reader open error\n"));
404 /* d->control->init(d->handle);
405 if(connection_check(d->handle, &d->log, d->cpu.access, d->ppu.access) == false){
406 d->control->close(d->handle);
410 HSQUIRRELVM v = qr_open(&d->log);
411 qr_function_register_global(v, wgT("memory_new"), memory_new);
412 qr_function_register_global(v, wgT("nesfile_save"), nesfile_save);
413 qr_function_register_global(v, wgT("cpu_write"), cpu_write);
414 qr_function_register_global(v, wgT("cpu_read"), cpu_read);
415 qr_function_register_global(v, wgT("ppu_read"), ppu_read);
416 qr_function_register_global(v, wgT("ppu_ramfind"), ppu_ramfind);
417 script_execute(v, d);
420 d->control->close(d->handle);
425 static bool workram_execute(HSQUIRRELVM v, struct dump_config *d)
428 if(SQ_FAILED(sqstd_dofile(v, wgT("dumpcore.nut"), SQFalse, SQTrue))){
429 d->log.append(d->log.object, wgT("dump core script error\n"));
432 SQRESULT r = qr_call(
433 v, wgT("workram_rw"), (SQUserPointer) d, d->script,
438 Free(d->cpu.memory.data);
439 d->cpu.memory.data = NULL;
440 // Free(d->ppu.memory.data);
441 // d->ppu.memory.data = NULL;
447 static SQInteger cpu_ramrw_check(HSQUIRRELVM v)
449 static const struct range range_address = {0x4800, 0xdfff};
450 static const struct range range_length = {1, 0x2000};
451 USERPOINTER_GET(d, r)
453 return read_count(v, &d->log, &d->cpu, &range_address, &range_length);
456 static SQInteger ramimage_open(HSQUIRRELVM v)
458 USERPOINTER_GET(d, r)
460 if(buf_load(d->cpu.memory.data, d->target, d->cpu.memory.size) == NG){
461 return r = sq_throwerror(v, wgT("RAM image open error"));
466 static SQInteger memory_finalize(HSQUIRRELVM v)
468 USERPOINTER_GET(d, r)
470 if(d->mode == MODE_RAM_READ){
471 buf_save(d->cpu.memory.data, d->target, d->cpu.memory.size);
473 Free(d->cpu.memory.data);
474 d->cpu.memory.data = NULL;
475 // Free(d->ppu.memory.data);
476 // d->ppu.memory.data = NULL;
481 static SQInteger cpu_write_ramimage(HSQUIRRELVM v)
483 USERPOINTER_GET(d, r)
485 long address, length;
487 const uint8_t *writedata = d->cpu.memory.data;
488 writedata += d->cpu.memory.offset;
490 r = qr_argument_get(v, 2, &address, &length);
494 cmp = Malloc(length);
495 assert(d->cpu.memory.attribute == MEMORY_ATTR_READ);
497 d->cpu.access->memory_write(
498 d->handle, address, length, writedata
500 d->cpu.access->memory_read(
501 d->handle, &d->cpu.gauge, address, length, cmp
503 d->cpu.memory.offset += length;
505 r = memcmp(cmp, writedata, length);
508 r = sq_throwerror(v, wgT("memory write failed"));
513 static SQInteger mode_is_read(HSQUIRRELVM v)
515 USERPOINTER_GET(d, r)
516 sq_pushbool(v, d->mode == MODE_RAM_READ ? SQTrue : SQFalse);
520 static SQInteger cpu_read_bit_check(HSQUIRRELVM v)
522 static const struct range range_address = {0x4800, 0xdfff};
523 static const struct range range_bit = {0, 7};
524 USERPOINTER_GET(d, r)
527 r = qr_argument_get(v, 2, &address, &bit);
531 r = range_check(v, wgT("address"), address, &range_address);
535 r = range_check(v, wgT("bit"), bit, &range_bit);
539 d->cpu.read_count_bit += 1;
543 static inline void gauge_increment(const struct gauge *g)
545 g->value_add(g->bar, g->label, 1);
548 static SQInteger cpu_read_bit_msb(HSQUIRRELVM v)
550 USERPOINTER_GET(d, r)
552 r = qr_argument_get(v, 2, &address, &bit);
557 assert(d->cpu.memory.attribute == MEMORY_ATTR_WRITE);
560 d->cpu.access->memory_read(d->handle, &GAUGE_DUMMY, address, 1, &readdata);
564 if(d->cpu.read_count_bit == 0){
565 d->cpu.bitbuffer = 0;
567 d->cpu.bitbuffer |= readdata;
569 d->cpu.read_count_bit += 1;
571 if(d->cpu.read_count_bit == 8){
572 d->cpu.read_count_bit = 0;
573 d->cpu.memory.data[d->cpu.memory.offset] = d->cpu.bitbuffer;
574 d->cpu.memory.offset += 1;
575 gauge_increment(&d->cpu.gauge);
577 d->cpu.bitbuffer <<= 1;
582 static SQInteger cpu_fetch_bit_check(HSQUIRRELVM v)
584 USERPOINTER_GET(d, r)
585 d->cpu.read_count_bit += 1;
589 static SQInteger cpu_fetch_bit_msb(HSQUIRRELVM v)
591 USERPOINTER_GET(d, r)
593 if(d->cpu.read_count_bit == 0){
594 d->cpu.bitbuffer = d->cpu.memory.data[d->cpu.memory.offset];
596 sq_pushinteger(v, d->cpu.bitbuffer & 0x80);
598 d->cpu.read_count_bit += 1;
599 if(d->cpu.read_count_bit == 8){
600 d->cpu.read_count_bit = 0;
601 d->cpu.memory.offset += 1;
602 gauge_increment(&d->cpu.gauge);
604 d->cpu.bitbuffer <<= 1;
609 bool script_workram_execute(struct dump_config *d)
611 dump_memory_driver_init(&d->cpu, d->mode == MODE_RAM_READ ? MEMORY_ATTR_WRITE : MEMORY_ATTR_READ);
612 dump_memory_driver_init(&d->ppu, MEMORY_ATTR_NOTUSE);
613 d->cpu.memory.name = wgT("Workram");
614 d->ppu.memory.name = wgT("N/A");
617 HSQUIRRELVM v = qr_open(&d->log);
618 qr_function_register_global(v, wgT("memory_new"), memory_size_set);
619 qr_function_register_global(v, wgT("cpu_write"), cpu_write_check);
620 qr_function_register_global(v, wgT("cpu_ramrw"), cpu_ramrw_check);
621 qr_function_register_global(v, wgT("memory_finalize"), length_check);
622 qr_function_register_global(v, wgT("mode_is_read"), mode_is_read);
623 qr_function_register_global(v, wgT("cpu_read_register"), cpu_read_register_check);
626 qr_function_register_global(v, wgT("cpu_read_bit_msb"), cpu_read_bit_check);
629 qr_function_register_global(v, wgT("cpu_fetch_bit_msb"), cpu_fetch_bit_check);
634 if(workram_execute(v, d) == false){
641 d->handle = d->control->open(d->except, &d->log);
642 if(d->handle == NULL){
643 d->log.append(d->log.object, wgT("reader open error\n"));
646 assert((d->cpu.read_count_bit & 7) == 0);
647 d->cpu.read_count_bit = 0;
648 d->control->init(d->handle);
649 if(connection_check(d->handle, &d->log, d->cpu.access, d->ppu.access) == false){
650 d->control->close(d->handle);
654 HSQUIRRELVM v = qr_open(&d->log);
655 qr_function_register_global(v, wgT("cpu_write"), cpu_write);
656 qr_function_register_global(v, wgT("cpu_read_register"), cpu_read_register);
657 qr_function_register_global(v, wgT("mode_is_read"), mode_is_read);
660 qr_function_register_global(v, wgT("memory_new"), memory_new);
661 qr_function_register_global(v, wgT("cpu_ramrw"), cpu_read);
662 qr_function_register_global(v, wgT("cpu_read_bit_msb"), cpu_read_bit_msb);
665 qr_function_register_global(v, wgT("memory_new"), ramimage_open);
666 qr_function_register_global(v, wgT("cpu_ramrw"), cpu_write_ramimage);
667 qr_function_register_global(v, wgT("cpu_fetch_bit_msb"), cpu_fetch_bit_msb);
673 qr_function_register_global(v, wgT("memory_finalize"), memory_finalize);
674 workram_execute(v, d);
677 d->control->close(d->handle);