OSDN Git Service

unicode support
[unagi/old-svn-converted.git] / client / trunk / anago / script_program.c
1 #include <assert.h>
2 #include <string.h>
3 #include <squirrel.h>
4 #include <sqstdio.h>
5 #include <sqstdaux.h>
6 #include <kazzo_task.h>
7 #include "type.h"
8 #include "widget.h"
9 #include "header.h"
10 #include "memory_manage.h"
11 #include "reader_master.h"
12 #include "squirrel_wrap.h"
13 #include "flash_device.h"
14 #include "progress.h"
15 #include "script_common.h"
16 #include "script_program.h"
17
18 static SQInteger vram_mirrorfind(HSQUIRRELVM v)
19 {
20         struct flash_config *d;
21         SQRESULT r =  qr_userpointer_get(v, (SQUserPointer) &d);
22         if(SQ_FAILED(r)){
23                 return r;
24         }
25         return 0;
26 }
27 static SQInteger command_set(HSQUIRRELVM v, struct flash_memory_driver *t)
28 {
29         long command, address ,mask;
30         SQRESULT r = qr_argument_get(v, 3, &command, &address, &mask);
31         if(SQ_FAILED(r)){
32                 return r;
33         }
34         long d = command & (mask - 1);
35         d |= address;
36         switch(command){
37         case 0x0000:
38                 t->c000x = d;
39                 break;
40         case 0x02aa: case 0x2aaa:
41                 t->c2aaa = d;
42                 break;
43         case 0x0555: case 0x5555:
44                 t->c5555 = d;
45                 break;
46         default:
47                 return sq_throwerror(v, wgT("unknown command address"));
48         }
49         t->command_change = true;
50         return 0;
51 }
52 static SQInteger cpu_command(HSQUIRRELVM v)
53 {
54         struct program_config *d;
55         SQRESULT r =  qr_userpointer_get(v, (SQUserPointer) &d);
56         if(SQ_FAILED(r)){
57                 return r;
58         }
59         return command_set(v, &d->cpu);
60 }
61 static SQInteger ppu_command(HSQUIRRELVM v)
62 {
63         struct program_config *d;
64         SQRESULT r =  qr_userpointer_get(v, (SQUserPointer) &d);
65         if(SQ_FAILED(r)){
66                 return r;
67         }
68         return command_set(v, &d->ppu);
69 }
70 static SQInteger write_memory(HSQUIRRELVM v, const struct reader_handle *h, struct flash_memory_driver *t)
71 {
72         long address, data;
73         SQRESULT r = qr_argument_get(v, 2, &address, &data);
74         if(SQ_FAILED(r)){
75                 return r;
76         }
77         uint8_t d8 = (uint8_t) data;
78         t->access->memory_write(h, address, 1, &d8);
79         return 0;
80 }
81 static SQInteger cpu_write(HSQUIRRELVM v)
82 {
83         struct program_config *d;
84         SQRESULT r =  qr_userpointer_get(v, (SQUserPointer) &d);
85         if(SQ_FAILED(r)){
86                 return r;
87         }
88         return write_memory(v, d->handle, &d->cpu);
89 }
90 static SQInteger erase_set(HSQUIRRELVM v, const struct reader_handle *h, struct flash_memory_driver *t, struct textcontrol *log)
91 {
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 "));
97         }
98         return 0;
99 }
100 static SQInteger cpu_erase(HSQUIRRELVM v)
101 {
102         struct program_config *d;
103         SQRESULT r =  qr_userpointer_get(v, (SQUserPointer) &d);
104         if(SQ_FAILED(r)){
105                 return r;
106         }
107         return erase_set(v, d->handle, &d->cpu, &d->log);
108 }
109 static SQInteger ppu_erase(HSQUIRRELVM v)
110 {
111         struct program_config *d;
112         SQRESULT r =  qr_userpointer_get(v, (SQUserPointer) &d);
113         if(SQ_FAILED(r)){
114                 return r;
115         }
116         return erase_set(v, d->handle, &d->ppu, &d->log);
117 }
118 static SQInteger program_regist(HSQUIRRELVM v, const struct reader_handle *h, struct flash_memory_driver *t)
119 {
120         SQRESULT r = qr_argument_get(v, 2, &t->programming.address, &t->programming.length);
121         if(SQ_FAILED(r)){
122                 return r;
123         }
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
130                 );
131                 t->command_change = false;
132         }
133         
134 /*      printf("programming %s ROM area 0x%06x...\n", name, t->memory->offset);
135         fflush(stdout);*/
136         return sq_suspendvm(v);
137 }
138 static void program_execute(const struct reader_handle *h, struct flash_memory_driver *t)
139 {
140         const long w = t->access->flash_program(
141                 h, &t->gauge, 
142                 t->programming.address, t->programming.length, 
143                 t->memory.data + t->memory.offset, false, 
144                 t->flash.erase_require
145         );
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;
151 }
152
153 static bool program_compare(const struct reader_handle *h, struct flash_memory_driver *t)
154 {
155         uint8_t *comparea = Malloc(t->compare.length);
156         bool ret = false;
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);
160                 if(0){
161                         memset(comparea, 0, t->compare.length);
162                         doread &= memcmp(comparea, t->memory.data + t->compare.offset, t->compare.length);
163                 }
164                 if(doread == 0){
165                         Free(comparea);
166                         return true;
167                 }
168         }
169         
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){
172                 ret = true;
173         }
174         Free(comparea);
175         return ret;
176 }
177 static SQInteger cpu_program_memory(HSQUIRRELVM v)
178 {
179         struct program_config *d;
180         SQRESULT r =  qr_userpointer_get(v, (SQUserPointer) &d);
181         if(SQ_FAILED(r)){
182                 return r;
183         }
184         return program_regist(v, d->handle, &d->cpu);
185 }
186 static SQInteger ppu_program_memory(HSQUIRRELVM v)
187 {
188         struct program_config *d;
189         SQRESULT r =  qr_userpointer_get(v, (SQUserPointer) &d);
190         if(SQ_FAILED(r)){
191                 return r;
192         }
193         return program_regist(v, d->handle, &d->ppu);
194 }
195
196 static long erase_timer_get(const struct reader_handle *h, struct flash_memory_driver *t)
197 {
198         if(
199                 (t->memory.transtype != TRANSTYPE_EMPTY) && 
200                 (t->flash.erase_require == true)
201         ){
202                 return t->flash.erase_wait;
203         }else{
204                 return 0;
205         }
206 }
207 static SQInteger erase_wait(HSQUIRRELVM v)
208 {
209         struct program_config *d;
210         SQRESULT r =  qr_userpointer_get(v, (SQUserPointer) &d);
211         if(SQ_FAILED(r)){
212                 return r;
213         }
214         if(0){
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;
219                 }
220                 wait(timer_wait);
221         }else{
222                 uint8_t s[2];
223                 do{
224                         wait(2);
225                         d->control->flash_status(d->handle, s);
226                 //ËÜÍè¤Î°Õ¿Þ¤«¤é¤Ç¤Ï¤³¤³¤Î¾ò·ï¼°¤Ï && ¤Ç¤Ï¤Ê¤¯ || ¤À¤¬¡¢Àè¤Ë erase ¤¬½ª¤ï¤Ã¤¿¥Ç¥Ð¥¤¥¹¤¬Æ°¤«¤»¤ë¤Î¤Ç»Ä¤·¤Æ¤ª¤¯
227                 }while((s[0] != KAZZO_TASK_FLASH_IDLE) && (s[1] != KAZZO_TASK_FLASH_IDLE));
228         }
229         return 0;
230 }
231
232 static void gauge_init(struct flash_memory_driver *t)
233 {
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"));
238         }
239 }
240
241 static bool program_memoryarea(HSQUIRRELVM co, const struct reader_handle *h, struct flash_memory_driver *t, bool compare, SQInteger *state, struct textcontrol *log)
242 {
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);
247                                 return false;
248                         }
249                 }
250
251                 sq_wakeupvm(co, SQFalse, SQFalse, SQTrue/*, SQTrue*/);
252                 *state = sq_getvmstate(co);
253         }else{
254                 program_execute(h, t);
255         }
256         return true;
257 }
258
259 static SQInteger program_main(HSQUIRRELVM v)
260 {
261         if(sq_gettop(v) != (1 + 3)){ //roottable, userpointer, co_cpu, co_ppu
262                 return sq_throwerror(v, wgT("argument number error"));
263         }
264         struct program_config *d;
265         SQRESULT r =  qr_userpointer_get(v, (SQUserPointer) &d);
266         if(SQ_FAILED(r)){
267                 return r;
268         }
269         HSQUIRRELVM co_cpu, co_ppu;
270         if(SQ_FAILED(sq_getthread(v, 3, &co_cpu))){
271                 return sq_throwerror(v, wgT("thread error"));
272         }
273         if(SQ_FAILED(sq_getthread(v, 4, &co_ppu))){
274                 return sq_throwerror(v, wgT("thread error"));
275         }
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 ¤¬½Ð¤ë¤Î¤Ç½Ð¤Ê¤¤ÃͤËÄ´À° (¤ä¤Ã¤Ä¤±Âбþ)
279         
280         while((state_cpu != SQ_VMSTATE_IDLE) || (state_ppu != SQ_VMSTATE_IDLE)){
281                 uint8_t s[2];
282 //              bool console_update = false;
283                 wait(sleepms);
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){
287                                 return 0;
288                         }
289                 }
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){
292                                 return 0;
293                         }
294                 }
295         }
296         return 0;
297 }
298
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)
300 {
301         SQRESULT r = qr_argument_get(v, 2, &t->programming.address, &t->programming.length);
302         if(SQ_FAILED(r)){
303                 return r;
304         }
305         r = range_check(v, wgT("length"), t->programming.length, range_length);
306         if(SQ_FAILED(r)){
307                 return r;
308         }
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"));
312         }
313         t->programming.count += t->programming.length;
314         return 0;
315 }
316 static SQInteger cpu_program_count(HSQUIRRELVM v)
317 {
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);
322         if(SQ_FAILED(r)){
323                 return r;
324         }
325         return program_count(v, &d->cpu, &range_address, &range_length, &d->log);
326 }
327
328 static SQInteger ppu_program_count(HSQUIRRELVM v)
329 {
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);
334         if(SQ_FAILED(r)){
335                 return r;
336         }
337         return program_count(v, &d->ppu, &range_address, &range_length, &d->log);
338 }
339
340 static bool script_execute(HSQUIRRELVM v, const wgChar *function, struct program_config *c)
341 {
342         bool ret = true;
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"));
345                 ret = false;
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);
348                 ret = false;
349         }else{
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
355                 );
356                 if(SQ_FAILED(r)){
357                         ret = false;
358                 }
359         }
360         return ret;
361 }
362
363 static void zendan(struct program_config *c)
364 {
365 //script test run
366         {
367                 static const wgChar *functionname[] = {
368                         wgT("cpu_erase"), wgT("ppu_erase"),
369                         wgT("erase_wait"), wgT("program_main")
370                 };
371                 HSQUIRRELVM v = qr_open(&c->log);
372                 int i;
373                 for(i = 0; i < sizeof(functionname)/sizeof(wgChar *); i++){
374                         qr_function_register_global(v, functionname[i], script_nop);
375                 }
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);
379                 
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);
383                 
384                 if(script_execute(v, wgT("testrun"), c) == false){
385                         qr_close(v);
386                         return;
387                 }
388                 qr_close(v);
389                 assert(c->cpu.memory.size != 0);
390
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);
393                         return;
394                 }
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);
398                                 return;
399                         }
400                 }
401         }
402 //script execute 
403         c->cpu.command_change = true;
404         gauge_init(&c->cpu);
405         c->ppu.command_change = true;
406         gauge_init(&c->ppu);
407         {
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);
420                 qr_close(v);
421         }
422 }
423
424 static bool memory_image_init(const struct memory *from, struct flash_memory_driver *t, struct textcontrol *log)
425 {
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;
434         }
435         if(t->flash.capacity < from->size){
436                 log->append(log->object, t->memory.name);
437                 
438                 log->append(log->object, wgT(" image size is larger than target device"));
439                 return false;
440         }
441         return true;
442 }
443
444 void script_program_execute(struct program_config *c)
445 {
446 //rom image load
447         struct romimage rom;
448         if(nesfile_load(&c->log, c->target, &rom) == false){
449                 c->log.append(c->log.object, wgT("ROM image open error"));
450                 return;
451         }
452 //variable init
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);
457                 return;
458         }
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);
462                 return;
463         }
464 //reader initalize
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);
469                 return;
470         }
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);
474                 return;
475         }
476         zendan(c);
477         c->control->close(c->handle);
478         c->handle = NULL;
479         nesbuffer_free(&rom, 0);
480 }