6 #include <kazzo_task.h>
10 #include "memory_manage.h"
11 #include "reader_master.h"
12 #include "squirrel_wrap.h"
13 #include "flash_device.h"
15 #include "script_common.h"
16 #include "script_program.h"
18 static SQInteger vram_mirrorfind(HSQUIRRELVM v)
20 struct flash_config *d;
21 SQRESULT r = qr_userpointer_get(v, (SQUserPointer) &d);
27 static SQInteger command_set(HSQUIRRELVM v, struct flash_memory_driver *t)
29 long command, address ,mask;
30 SQRESULT r = qr_argument_get(v, 3, &command, &address, &mask);
34 long d = command & (mask - 1);
40 case 0x02aa: case 0x2aaa:
43 case 0x0555: case 0x5555:
47 return sq_throwerror(v, wgT("unknown command address"));
49 t->command_change = true;
52 static SQInteger cpu_command(HSQUIRRELVM v)
54 struct program_config *d;
55 SQRESULT r = qr_userpointer_get(v, (SQUserPointer) &d);
59 return command_set(v, &d->cpu);
61 static SQInteger ppu_command(HSQUIRRELVM v)
63 struct program_config *d;
64 SQRESULT r = qr_userpointer_get(v, (SQUserPointer) &d);
68 return command_set(v, &d->ppu);
70 static SQInteger write_memory(HSQUIRRELVM v, const struct reader_handle *h, struct flash_memory_driver *t)
73 SQRESULT r = qr_argument_get(v, 2, &address, &data);
77 uint8_t d8 = (uint8_t) data;
78 t->access->memory_write(h, address, 1, &d8);
81 static SQInteger cpu_write(HSQUIRRELVM v)
83 struct program_config *d;
84 SQRESULT r = qr_userpointer_get(v, (SQUserPointer) &d);
88 return write_memory(v, d->handle, &d->cpu);
90 static SQInteger erase_set(HSQUIRRELVM v, const struct reader_handle *h, struct flash_memory_driver *t, struct textcontrol *log)
92 t->access->flash_config(h, t->c000x, t->c2aaa, t->c5555, t->flash.pagesize, t->flash.retry);
93 t->command_change = false;
94 if(t->flash.erase_require == true){
95 t->access->flash_erase(h, t->c2aaa, false);
96 t->gauge.label_set(t->gauge.label, wgT("erasing "));
100 static SQInteger cpu_erase(HSQUIRRELVM v)
102 struct program_config *d;
103 SQRESULT r = qr_userpointer_get(v, (SQUserPointer) &d);
107 return erase_set(v, d->handle, &d->cpu, &d->log);
109 static SQInteger ppu_erase(HSQUIRRELVM v)
111 struct program_config *d;
112 SQRESULT r = qr_userpointer_get(v, (SQUserPointer) &d);
116 return erase_set(v, d->handle, &d->ppu, &d->log);
118 static SQInteger program_regist(HSQUIRRELVM v, const struct reader_handle *h, struct flash_memory_driver *t)
120 SQRESULT r = qr_argument_get(v, 2, &t->programming.address, &t->programming.length);
124 t->compare = t->programming;
125 t->compare.offset = t->memory.offset & (t->memory.size - 1);
126 if(t->command_change == true){
127 t->access->flash_config(
128 h, t->c000x, t->c2aaa, t->c5555,
129 t->flash.pagesize, t->flash.retry
131 t->command_change = false;
134 /* printf("programming %s ROM area 0x%06x...\n", name, t->memory->offset);
136 return sq_suspendvm(v);
138 static void program_execute(const struct reader_handle *h, struct flash_memory_driver *t)
140 const long w = t->access->flash_program(
142 t->programming.address, t->programming.length,
143 t->memory.data + t->memory.offset, false,
144 t->flash.erase_require
146 t->programming.address += w;
147 t->programming.length -= w;
148 t->memory.offset += w;
149 t->memory.offset &= t->memory.size - 1;
150 t->programming.offset += w;
153 static bool program_compare(const struct reader_handle *h, struct flash_memory_driver *t)
155 uint8_t *comparea = Malloc(t->compare.length);
157 if(t->flash.erase_require == true){
158 memset(comparea, 0xff, t->compare.length);
159 int doread = memcmp(comparea, t->memory.data + t->compare.offset, t->compare.length);
161 memset(comparea, 0, t->compare.length);
162 doread &= memcmp(comparea, t->memory.data + t->compare.offset, t->compare.length);
170 t->access->memory_read(h, &GAUGE_DUMMY, t->compare.address, t->compare.length, comparea);
171 if(memcmp(comparea, t->memory.data + t->compare.offset, t->compare.length) == 0){
177 static SQInteger cpu_program_memory(HSQUIRRELVM v)
179 struct program_config *d;
180 SQRESULT r = qr_userpointer_get(v, (SQUserPointer) &d);
184 return program_regist(v, d->handle, &d->cpu);
186 static SQInteger ppu_program_memory(HSQUIRRELVM v)
188 struct program_config *d;
189 SQRESULT r = qr_userpointer_get(v, (SQUserPointer) &d);
193 return program_regist(v, d->handle, &d->ppu);
196 static long erase_timer_get(const struct reader_handle *h, struct flash_memory_driver *t)
199 (t->memory.transtype != TRANSTYPE_EMPTY) &&
200 (t->flash.erase_require == true)
202 return t->flash.erase_wait;
207 static SQInteger erase_wait(HSQUIRRELVM v)
209 struct program_config *d;
210 SQRESULT r = qr_userpointer_get(v, (SQUserPointer) &d);
215 long timer_wait = erase_timer_get(d->handle, &d->cpu);
216 long timer_ppu = erase_timer_get(d->handle, &d->ppu);
217 if(timer_wait < timer_ppu){
218 timer_wait = timer_ppu;
225 d->control->flash_status(d->handle, s);
226 //ËÜÍè¤Î°Õ¿Þ¤«¤é¤Ç¤Ï¤³¤³¤Î¾ò·ï¼°¤Ï && ¤Ç¤Ï¤Ê¤¯ || ¤À¤¬¡¢Àè¤Ë erase ¤¬½ª¤ï¤Ã¤¿¥Ç¥Ð¥¤¥¹¤¬Æ°¤«¤»¤ë¤Î¤Ç»Ä¤·¤Æ¤ª¤¯
227 }while((s[0] != KAZZO_TASK_FLASH_IDLE) && (s[1] != KAZZO_TASK_FLASH_IDLE));
232 static void gauge_init(struct flash_memory_driver *t)
234 t->gauge.range_set(t->gauge.bar, t->programming.count);
235 t->gauge.value_set(t->gauge.bar, t->gauge.label, t->programming.offset);
236 if(t->programming.count == 0){
237 t->gauge.label_set(t->gauge.label, wgT("skip"));
241 static bool program_memoryarea(HSQUIRRELVM co, const struct reader_handle *h, struct flash_memory_driver *t, bool compare, SQInteger *state, struct textcontrol *log)
243 if(t->programming.length == 0){
244 if(t->programming.offset != 0 && compare == true){
245 if(program_compare(h, t) == false){
246 log->append(log->object, wgT("%s memory compare error\n"), t->memory.name);
251 sq_wakeupvm(co, SQFalse, SQFalse, SQTrue/*, SQTrue*/);
252 *state = sq_getvmstate(co);
254 program_execute(h, t);
259 static SQInteger program_main(HSQUIRRELVM v)
261 if(sq_gettop(v) != (1 + 3)){ //roottable, userpointer, co_cpu, co_ppu
262 return sq_throwerror(v, wgT("argument number error"));
264 struct program_config *d;
265 SQRESULT r = qr_userpointer_get(v, (SQUserPointer) &d);
269 HSQUIRRELVM co_cpu, co_ppu;
270 if(SQ_FAILED(sq_getthread(v, 3, &co_cpu))){
271 return sq_throwerror(v, wgT("thread error"));
273 if(SQ_FAILED(sq_getthread(v, 4, &co_ppu))){
274 return sq_throwerror(v, wgT("thread error"));
276 SQInteger state_cpu = sq_getvmstate(co_cpu);
277 SQInteger state_ppu = sq_getvmstate(co_ppu);
278 const long sleepms = d->compare == true ? 6 : 2; //W29C040 ¤Ç compare ¤ò¤¹¤ë¤È¡¢error ¤¬½Ð¤ë¤Î¤Ç½Ð¤Ê¤¤ÃͤËÄ´À° (¤ä¤Ã¤Ä¤±Âбþ)
280 while((state_cpu != SQ_VMSTATE_IDLE) || (state_ppu != SQ_VMSTATE_IDLE)){
282 // bool console_update = false;
284 d->control->flash_status(d->handle, s);
285 if(state_cpu != SQ_VMSTATE_IDLE && s[0] == KAZZO_TASK_FLASH_IDLE){
286 if(program_memoryarea(co_cpu, d->handle, &d->cpu, d->compare, &state_cpu, &d->log) == false){
290 if(state_ppu != SQ_VMSTATE_IDLE && s[1] == KAZZO_TASK_FLASH_IDLE){
291 if(program_memoryarea(co_ppu, d->handle, &d->ppu, d->compare, &state_ppu, &d->log) == false){
299 static SQInteger program_count(HSQUIRRELVM v, struct flash_memory_driver *t, const struct range *range_address, const struct range *range_length, struct textcontrol *log)
301 SQRESULT r = qr_argument_get(v, 2, &t->programming.address, &t->programming.length);
305 r = range_check(v, wgT("length"), t->programming.length, range_length);
309 if((t->programming.address < range_address->start) || ((t->programming.address + t->programming.length) > range_address->end)){
310 log->append(log->object, wgT("address range must be 0x%06x to 0x%06x"), (int) range_address->start, (int) range_address->end - 1);
311 return sq_throwerror(v, wgT("script logical error"));
313 t->programming.count += t->programming.length;
316 static SQInteger cpu_program_count(HSQUIRRELVM v)
318 static const struct range range_address = {0x8000, 0x10000};
319 static const struct range range_length = {0x0100, 0x4000};
320 struct program_config *d;
321 SQRESULT r = qr_userpointer_get(v, (SQUserPointer) &d);
325 return program_count(v, &d->cpu, &range_address, &range_length, &d->log);
328 static SQInteger ppu_program_count(HSQUIRRELVM v)
330 static const struct range range_address = {0x0000, 0x2000};
331 static const struct range range_length = {0x0100, 0x2000};
332 struct program_config *d;
333 SQRESULT r = qr_userpointer_get(v, (SQUserPointer) &d);
337 return program_count(v, &d->ppu, &range_address, &range_length, &d->log);
340 static bool script_execute(HSQUIRRELVM v, const wgChar *function, struct program_config *c)
343 if(SQ_FAILED(sqstd_dofile(v, _SC("flashcore.nut"), SQFalse, SQTrue))){
344 c->log.append(c->log.object, wgT("flash core script error\n"));
346 }else if(SQ_FAILED(sqstd_dofile(v, c->script, SQFalse, SQTrue))){
347 c->log.append(c->log.object, wgT("%s open error\n"), c->script);
350 SQRESULT r = qr_call(
351 v, function, (SQUserPointer) c, true,
352 1 + 3 * 2, c->mappernum,
353 c->cpu.memory.transtype, c->cpu.memory.size, c->cpu.flash.capacity,
354 c->ppu.memory.transtype, c->ppu.memory.size, c->cpu.flash.capacity
363 static void zendan(struct program_config *c)
367 static const wgChar *functionname[] = {
368 wgT("cpu_erase"), wgT("ppu_erase"),
369 wgT("erase_wait"), wgT("program_main")
371 HSQUIRRELVM v = qr_open(&c->log);
373 for(i = 0; i < sizeof(functionname)/sizeof(wgChar *); i++){
374 qr_function_register_global(v, functionname[i], script_nop);
376 qr_function_register_global(v, _SC("cpu_write"), cpu_write_check);
377 qr_function_register_global(v, _SC("cpu_command"), cpu_command);
378 qr_function_register_global(v, _SC("cpu_program"), cpu_program_count);
380 qr_function_register_global(v, _SC("ppu_program"), ppu_program_count);
381 qr_function_register_global(v, _SC("ppu_command"), ppu_command);
382 qr_function_register_global(v, _SC("vram_mirrorfind"), vram_mirrorfind);
384 if(script_execute(v, wgT("testrun"), c) == false){
389 assert(c->cpu.memory.size != 0);
391 if(c->cpu.programming.count % c->cpu.memory.size != 0){
392 c->log.append(c->log.object, wgT("logical error: cpu_programsize is not connected 0x%06x/0x%06x\n"), (int) c->cpu.programming.count, (int) c->cpu.memory.size);
395 if(c->ppu.memory.size != 0){
396 if(c->ppu.programming.count % c->ppu.memory.size != 0){
397 c->log.append(c->log.object, wgT("logical error: ppu_programsize is not connected 0x%06x/0x%06x\n"), (int) c->ppu.programming.count, (int) c->ppu.memory.size);
403 c->cpu.command_change = true;
405 c->ppu.command_change = true;
408 HSQUIRRELVM v = qr_open(&c->log);
409 qr_function_register_global(v, _SC("cpu_write"), cpu_write);
410 qr_function_register_global(v, _SC("cpu_erase"), cpu_erase);
411 qr_function_register_global(v, _SC("cpu_program"), cpu_program_memory);
412 qr_function_register_global(v, _SC("cpu_command"), cpu_command);
413 qr_function_register_global(v, _SC("ppu_erase"), ppu_erase);
414 qr_function_register_global(v, _SC("ppu_program"), ppu_program_memory);
415 qr_function_register_global(v, _SC("ppu_command"), ppu_command);
416 qr_function_register_global(v, _SC("program_main"), program_main);
417 qr_function_register_global(v, _SC("erase_wait"), erase_wait);
418 qr_function_register_global(v, _SC("vram_mirrorfind"), script_nop);
419 script_execute(v, wgT("program"), c);
424 static bool memory_image_init(const struct memory *from, struct flash_memory_driver *t, struct textcontrol *log)
426 t->memory.data = from->data;
427 t->memory.size = from->size;
428 t->memory.attribute = MEMORY_ATTR_READ;
429 t->command_change = true;
430 t->programming.count = 0;
431 t->programming.offset = 0;
432 if(t->memory.size == 0){
433 t->memory.transtype = TRANSTYPE_EMPTY;
435 if(t->flash.capacity < from->size){
436 log->append(log->object, t->memory.name);
438 log->append(log->object, wgT(" image size is larger than target device"));
444 void script_program_execute(struct program_config *c)
448 if(nesfile_load(&c->log, c->target, &rom) == false){
449 c->log.append(c->log.object, wgT("ROM image open error"));
453 c->mappernum = rom.mappernum;
454 c->cpu.memory.name = wgT("Program Flash");
455 if(memory_image_init(&rom.cpu_rom, &c->cpu, &c->log) == false){
456 nesbuffer_free(&rom, 0);
459 c->ppu.memory.name = wgT("Charcter Flash");
460 if(memory_image_init(&rom.ppu_rom, &c->ppu, &c->log) == false){
461 nesbuffer_free(&rom, 0);
465 c->handle = c->control->open(c->except);
466 if(c->handle == NULL){
467 c->log.append(c->log.object, wgT("reader open error\n"));
468 nesbuffer_free(&rom, 0);
471 //program start, reader finalize
472 if(connection_check(c->handle, &c->log, c->cpu.access, c->ppu.access) == false){
473 nesbuffer_free(&rom, 0);
477 c->control->close(c->handle);
479 nesbuffer_free(&rom, 0);