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 == 0 ? 1: length, t->memory.data + t->memory.offset);
90 if((length != 0) && (progress == false)){
91 buffer_show(&t->memory, length);
93 t->memory.offset += length;
97 static SQInteger cpu_read(HSQUIRRELVM v)
100 r = read_memory(v, d->handle, &d->cpu, d->progress);
104 static SQInteger ppu_read(HSQUIRRELVM v)
106 USERPOINTER_GET(d, r)
107 r = read_memory(v, d->handle, &d->ppu, d->progress);
111 static SQInteger ppu_ramfind(HSQUIRRELVM v)
113 struct dump_config *d;
118 static const uint8_t test_val[testsize] = {0xaa, 0x55, 0, 0xff, 0x46, 0x49, 0x07, 0x21};
119 static const uint8_t test_str[testsize] = "pputest";
120 uint8_t test_result[testsize];
121 SQRESULT r = qr_userpointer_get(v, (SQUserPointer) &d);
122 struct dump_memory_driver *p = &d->ppu;
127 p->access->memory_write(d->handle, testaddress, testsize, test_val);
128 p->access->memory_read(d->handle, &GAUGE_DUMMY, testaddress, testsize, test_result);
129 if(memcmp(test_val, test_result, testsize) != 0){
130 sq_pushbool(v, SQFalse);
133 p->access->memory_write(d->handle, testaddress, testsize, test_str);
134 p->access->memory_read(d->handle, &GAUGE_DUMMY, testaddress, testsize, test_result);
135 if(memcmp(test_str, test_result, testsize) != 0){
136 sq_pushbool(v, SQFalse);
139 p->memory.offset = 0;
141 sq_pushbool(v, SQTrue);
145 static SQInteger return_true(HSQUIRRELVM v)
147 sq_pushbool(v, SQFalse);
151 static void memory_new_init(struct dump_memory_driver *d)
153 d->memory.offset = 0;
154 d->memory.data = Malloc(d->memory.size);
155 d->gauge.range_set(d->gauge.bar, d->memory.size);
156 d->gauge.value_set(d->gauge.bar, d->gauge.label, 0);
159 //test 時/1度目の call で使用
160 static SQInteger memory_new(HSQUIRRELVM v)
162 USERPOINTER_GET(d, r)
164 r = qr_argument_get(v, 2, &d->cpu.memory.size, &d->ppu.memory.size);
169 memory_new_init(&d->cpu);
170 if(d->mode == MODE_ROM_DUMP){
171 memory_new_init(&d->ppu);
176 //dump 時/2度目の call で nesfile_save として使用
177 static SQInteger nesfile_save(HSQUIRRELVM v)
179 USERPOINTER_GET(d, r)
181 struct romimage image;
183 r = qr_argument_get(v, 2, &image.mappernum, &mirrorfind);
187 image.cpu_rom = d->cpu.memory;
188 image.cpu_ram.data = NULL;
189 image.ppu_rom = d->ppu.memory;
190 image.mirror = MIRROR_PROGRAMABLE;
192 uint8_t c = d->control->vram_connection(d->handle);
194 d->log.append(d->log.object, wgT("vram connection %x\n"), c);
197 kazzo 1.0 return value H:9 V:5
198 kazzo 2.x return value H:C V:A
200 if(c == 0x05 || c == 0x0a){
201 image.mirror = MIRROR_VERTICAL;
203 image.mirror = MIRROR_HORIZONAL;
207 if(d->battery == true){
210 d->crc = nesfile_create(&d->log, &image, d->target);
211 nesbuffer_free(&image, 0); //0 is MODE_xxx_xxxx
213 d->cpu.memory.data = NULL;
214 d->ppu.memory.data = NULL;
218 static bool length_check_core(struct dump_config *d, struct dump_memory_driver *m, const wgChar * str)
221 if((m->read_count_bit & 0x7) != 0){
224 m->read_count_byte += m->read_count_bit >> 3;
225 if(m->memory.size != m->read_count_byte){
229 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);
235 //dump 時/1度目の call で nesfile_save として使用
236 static SQInteger length_check(HSQUIRRELVM v)
238 USERPOINTER_GET(d, r)
240 bool cpu = true, ppu = true;
242 cpu = length_check_core(d, &d->cpu, d->mode == MODE_ROM_DUMP ? wgT("board.cpu_rom.size") : wgT("board.cpu_ram.size"));
243 ppu = length_check_core(d, &d->ppu, wgT("board.ppu_rom.size"));
244 if(cpu == false || ppu == false){
245 r = sq_throwerror(v, wgT("script logical error"));
250 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)
252 long address, length;
253 SQRESULT r = qr_argument_get(v, 2, &address, &length);
257 r = range_check(v, wgT("length"), length, range_length);
261 if((address < range_address->start) || ((address + length) > range_address->end)){
262 l->append(l->object, wgT("address range must be 0x%06x to 0x%06x"), (int) range_address->start, (int) range_address->end);
263 return sq_throwerror(v, wgT("script logical error"));;
265 t->read_count_byte += length;
268 static SQInteger cpu_read_count(HSQUIRRELVM v)
270 static const struct range range_address = {0x8000, 0x10000};
271 //length == 0 は 対象アドレスを呼んで、バッファにいれない。mmc2, mmc4 で使用する。
272 static const struct range range_length = {0x0000, 0x4000};
273 USERPOINTER_GET(d, r)
275 return read_count(v, &d->log, &d->cpu, &range_address, &range_length);
278 static SQInteger ppu_read_count(HSQUIRRELVM v)
280 static const struct range range_address = {0x0000, 0x2000};
281 static const struct range range_length = {0x0001, 0x2000};
282 USERPOINTER_GET(d, r)
284 return read_count(v, &d->log, &d->ppu, &range_address, &range_length);
287 static SQInteger cpu_read_register_check(HSQUIRRELVM v)
289 static const struct range range_address = {0x4800, 0x7fff};
290 static const struct range range_byte = {0, 0xff};
291 USERPOINTER_GET(d, r)
294 r = qr_argument_get(v, 2, &address, &byte);
298 r = range_check(v, wgT("address"), address, &range_address);
302 r = range_check(v, wgT("byte"), byte, &range_byte);
307 sq_pushinteger(v, byte);
311 static SQInteger cpu_read_register(HSQUIRRELVM v)
313 USERPOINTER_GET(d, r)
315 r = qr_argument_get(v, 2, &address, &dummy);
321 d->cpu.access->memory_read(d->handle, &GAUGE_DUMMY, address, 1, &readdata);
323 sq_pushinteger(v, readdata);
327 static SQInteger memory_size_set(HSQUIRRELVM v)
329 USERPOINTER_GET(d, r)
330 r = qr_argument_get(v, 2, &d->cpu.memory.size, &d->ppu.memory.size);
334 static bool script_execute(HSQUIRRELVM v, struct dump_config *d)
337 if(SQ_FAILED(sqstd_dofile(v, wgT("dumpcore.nut"), SQFalse, SQTrue))){
338 d->log.append(d->log.object, wgT("dump core script error\n"));
341 SQRESULT r = qr_call(
342 v, wgT("dump"), (SQUserPointer) d, d->script,
343 3, d->mappernum, d->cpu.increase, d->ppu.increase
347 Free(d->cpu.memory.data);
348 Free(d->ppu.memory.data);
349 d->cpu.memory.data = NULL;
350 d->ppu.memory.data = NULL;
356 static void dump_memory_driver_init(struct dump_memory_driver *dd, enum memory_attribute at)
359 dd->memory.offset = 0;
360 dd->memory.attribute = at;
361 dd->memory.transtype = TRANSTYPE_FULL;
362 dd->memory.data = NULL;
363 dd->read_count_byte = 0;
364 dd->read_count_bit = 0;
367 bool script_dump_execute(struct dump_config *d)
369 dump_memory_driver_init(&d->cpu, MEMORY_ATTR_WRITE);
370 d->cpu.memory.name = wgT("Program");
372 dump_memory_driver_init(&d->ppu, MEMORY_ATTR_WRITE);
373 d->ppu.memory.name = wgT("Charcter");
376 HSQUIRRELVM v = qr_open(&d->log);
377 qr_function_register_global(v, wgT("cpu_write"), cpu_write_check);
378 qr_function_register_global(v, wgT("memory_new"), memory_size_set);
379 qr_function_register_global(v, wgT("nesfile_save"), length_check);
380 qr_function_register_global(v, wgT("cpu_read"), cpu_read_count);
381 qr_function_register_global(v, wgT("ppu_read"), ppu_read_count);
382 qr_function_register_global(v, wgT("ppu_ramfind"), return_true);
383 if(script_execute(v, d) == false){
390 d->handle = d->control->open(d->except, &d->log);
391 if(d->handle == NULL){
392 d->log.append(d->log.object, wgT("reader open error\n"));
395 /* d->control->init(d->handle);
396 if(connection_check(d->handle, &d->log, d->cpu.access, d->ppu.access) == false){
397 d->control->close(d->handle);
401 HSQUIRRELVM v = qr_open(&d->log);
402 qr_function_register_global(v, wgT("memory_new"), memory_new);
403 qr_function_register_global(v, wgT("nesfile_save"), nesfile_save);
404 qr_function_register_global(v, wgT("cpu_write"), cpu_write);
405 qr_function_register_global(v, wgT("cpu_read"), cpu_read);
406 qr_function_register_global(v, wgT("ppu_read"), ppu_read);
407 qr_function_register_global(v, wgT("ppu_ramfind"), ppu_ramfind);
408 script_execute(v, d);
411 d->control->close(d->handle);
416 static bool workram_execute(HSQUIRRELVM v, struct dump_config *d)
419 if(SQ_FAILED(sqstd_dofile(v, wgT("dumpcore.nut"), SQFalse, SQTrue))){
420 d->log.append(d->log.object, wgT("dump core script error\n"));
423 SQRESULT r = qr_call(
424 v, wgT("workram_rw"), (SQUserPointer) d, d->script,
429 Free(d->cpu.memory.data);
430 d->cpu.memory.data = NULL;
431 // Free(d->ppu.memory.data);
432 // d->ppu.memory.data = NULL;
438 static SQInteger cpu_ramrw_check(HSQUIRRELVM v)
440 static const struct range range_address = {0x4800, 0xdfff};
441 static const struct range range_length = {1, 0x2000};
442 USERPOINTER_GET(d, r)
444 return read_count(v, &d->log, &d->cpu, &range_address, &range_length);
447 static SQInteger ramimage_open(HSQUIRRELVM v)
449 USERPOINTER_GET(d, r)
451 if(buf_load(d->cpu.memory.data, d->target, d->cpu.memory.size) == NG){
452 return r = sq_throwerror(v, wgT("RAM image open error"));
457 static SQInteger memory_finalize(HSQUIRRELVM v)
459 USERPOINTER_GET(d, r)
461 if(d->mode == MODE_RAM_READ){
462 buf_save(d->cpu.memory.data, d->target, d->cpu.memory.size);
464 Free(d->cpu.memory.data);
465 d->cpu.memory.data = NULL;
466 // Free(d->ppu.memory.data);
467 // d->ppu.memory.data = NULL;
472 static SQInteger cpu_write_ramimage(HSQUIRRELVM v)
474 USERPOINTER_GET(d, r)
476 long address, length;
478 const uint8_t *writedata = d->cpu.memory.data;
479 writedata += d->cpu.memory.offset;
481 r = qr_argument_get(v, 2, &address, &length);
485 cmp = Malloc(length);
486 assert(d->cpu.memory.attribute == MEMORY_ATTR_READ);
488 d->cpu.access->memory_write(
489 d->handle, address, length, writedata
491 d->cpu.access->memory_read(
492 d->handle, &d->cpu.gauge, address, length, cmp
494 d->cpu.memory.offset += length;
496 r = memcmp(cmp, writedata, length);
499 r = sq_throwerror(v, wgT("memory write failed"));
504 static SQInteger mode_is_read(HSQUIRRELVM v)
506 USERPOINTER_GET(d, r)
507 sq_pushbool(v, d->mode == MODE_RAM_READ ? SQTrue : SQFalse);
511 static SQInteger cpu_read_bit_check(HSQUIRRELVM v)
513 static const struct range range_address = {0x4800, 0xdfff};
514 static const struct range range_bit = {0, 7};
515 USERPOINTER_GET(d, r)
518 r = qr_argument_get(v, 2, &address, &bit);
522 r = range_check(v, wgT("address"), address, &range_address);
526 r = range_check(v, wgT("bit"), bit, &range_bit);
530 d->cpu.read_count_bit += 1;
534 static inline void gauge_increment(const struct gauge *g)
536 g->value_add(g->bar, g->label, 1);
539 static SQInteger cpu_read_bit_msb(HSQUIRRELVM v)
541 USERPOINTER_GET(d, r)
543 r = qr_argument_get(v, 2, &address, &bit);
548 assert(d->cpu.memory.attribute == MEMORY_ATTR_WRITE);
551 d->cpu.access->memory_read(d->handle, &GAUGE_DUMMY, address, 1, &readdata);
555 if(d->cpu.read_count_bit == 0){
556 d->cpu.bitbuffer = 0;
558 d->cpu.bitbuffer |= readdata;
560 d->cpu.read_count_bit += 1;
562 if(d->cpu.read_count_bit == 8){
563 d->cpu.read_count_bit = 0;
564 d->cpu.memory.data[d->cpu.memory.offset] = d->cpu.bitbuffer;
565 d->cpu.memory.offset += 1;
566 gauge_increment(&d->cpu.gauge);
568 d->cpu.bitbuffer <<= 1;
573 static SQInteger cpu_fetch_bit_check(HSQUIRRELVM v)
575 USERPOINTER_GET(d, r)
576 d->cpu.read_count_bit += 1;
580 static SQInteger cpu_fetch_bit_msb(HSQUIRRELVM v)
582 USERPOINTER_GET(d, r)
584 if(d->cpu.read_count_bit == 0){
585 d->cpu.bitbuffer = d->cpu.memory.data[d->cpu.memory.offset];
587 sq_pushinteger(v, d->cpu.bitbuffer & 0x80);
589 d->cpu.read_count_bit += 1;
590 if(d->cpu.read_count_bit == 8){
591 d->cpu.read_count_bit = 0;
592 d->cpu.memory.offset += 1;
593 gauge_increment(&d->cpu.gauge);
595 d->cpu.bitbuffer <<= 1;
600 bool script_workram_execute(struct dump_config *d)
602 dump_memory_driver_init(&d->cpu, d->mode == MODE_RAM_READ ? MEMORY_ATTR_WRITE : MEMORY_ATTR_READ);
603 dump_memory_driver_init(&d->ppu, MEMORY_ATTR_NOTUSE);
604 d->cpu.memory.name = wgT("Workram");
605 d->ppu.memory.name = wgT("N/A");
608 HSQUIRRELVM v = qr_open(&d->log);
609 qr_function_register_global(v, wgT("memory_new"), memory_size_set);
610 qr_function_register_global(v, wgT("cpu_write"), cpu_write_check);
611 qr_function_register_global(v, wgT("cpu_ramrw"), cpu_ramrw_check);
612 qr_function_register_global(v, wgT("memory_finalize"), length_check);
613 qr_function_register_global(v, wgT("mode_is_read"), mode_is_read);
614 qr_function_register_global(v, wgT("cpu_read_register"), cpu_read_register_check);
617 qr_function_register_global(v, wgT("cpu_read_bit_msb"), cpu_read_bit_check);
620 qr_function_register_global(v, wgT("cpu_fetch_bit_msb"), cpu_fetch_bit_check);
625 if(workram_execute(v, d) == false){
632 d->handle = d->control->open(d->except, &d->log);
633 if(d->handle == NULL){
634 d->log.append(d->log.object, wgT("reader open error\n"));
637 assert((d->cpu.read_count_bit & 7) == 0);
638 d->cpu.read_count_bit = 0;
639 d->control->init(d->handle);
640 if(connection_check(d->handle, &d->log, d->cpu.access, d->ppu.access) == false){
641 d->control->close(d->handle);
645 HSQUIRRELVM v = qr_open(&d->log);
646 qr_function_register_global(v, wgT("cpu_write"), cpu_write);
647 qr_function_register_global(v, wgT("cpu_read_register"), cpu_read_register);
648 qr_function_register_global(v, wgT("mode_is_read"), mode_is_read);
651 qr_function_register_global(v, wgT("memory_new"), memory_new);
652 qr_function_register_global(v, wgT("cpu_ramrw"), cpu_read);
653 qr_function_register_global(v, wgT("cpu_read_bit_msb"), cpu_read_bit_msb);
656 qr_function_register_global(v, wgT("memory_new"), ramimage_open);
657 qr_function_register_global(v, wgT("cpu_ramrw"), cpu_write_ramimage);
658 qr_function_register_global(v, wgT("cpu_fetch_bit_msb"), cpu_fetch_bit_msb);
664 qr_function_register_global(v, wgT("memory_finalize"), memory_finalize);
665 workram_execute(v, d);
668 d->control->close(d->handle);