OSDN Git Service

0f45377f6febd4078990977fcbb71d2cb5a7c274
[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 "romimage.h"
10 #include "memory_manage.h"
11 #include "reader_master.h"
12 #include "squirrel_wrap.h"
13 #include "flash_device.h"
14 #include "script_common.h"
15 #include "script_program.h"
16
17 static SQInteger vram_mirrorfind(HSQUIRRELVM v)
18 {
19         struct flash_config *d;
20         SQRESULT r =  qr_userpointer_get(v, (SQUserPointer) &d);
21         if(SQ_FAILED(r)){
22                 return r;
23         }
24         return 0;
25 }
26 static SQInteger command_set(HSQUIRRELVM v, struct flash_memory_driver *t)
27 {
28         long command, address ,mask;
29         SQRESULT r = qr_argument_get(v, 3, &command, &address, &mask);
30         if(SQ_FAILED(r)){
31                 return r;
32         }
33         long d = command & (mask - 1);
34         d |= address;
35         switch(command){
36         case 0x0000:
37                 t->c000x = d;
38                 break;
39         case 0x02aa: case 0x2aaa:
40                 t->c2aaa = d;
41                 break;
42         case 0x0555: case 0x5555:
43                 t->c5555 = d;
44                 break;
45         default:
46                 return sq_throwerror(v, wgT("unknown command address"));
47         }
48         t->command_change = true;
49         return 0;
50 }
51 static SQInteger cpu_command(HSQUIRRELVM v)
52 {
53         struct program_config *d;
54         SQRESULT r =  qr_userpointer_get(v, (SQUserPointer) &d);
55         if(SQ_FAILED(r)){
56                 return r;
57         }
58         return command_set(v, &d->cpu);
59 }
60 static SQInteger ppu_command(HSQUIRRELVM v)
61 {
62         struct program_config *d;
63         SQRESULT r =  qr_userpointer_get(v, (SQUserPointer) &d);
64         if(SQ_FAILED(r)){
65                 return r;
66         }
67         return command_set(v, &d->ppu);
68 }
69
70 static SQInteger cpu_write(HSQUIRRELVM v)
71 {
72         struct program_config *d;
73         SQRESULT r =  qr_userpointer_get(v, (SQUserPointer) &d);
74         if(SQ_FAILED(r)){
75                 return r;
76         }
77         cpu_write_execute(v, d->handle, d->cpu.access);
78         return 0;
79 }
80
81 static SQInteger erase_set(HSQUIRRELVM v, const struct reader_handle *h, struct flash_memory_driver *t, struct textcontrol *log)
82 {
83         t->access->flash_config(h, t->c000x, t->c2aaa, t->c5555, t->flash.pagesize, t->flash.retry);
84         t->command_change = false;
85         if(t->flash.erase_require == true){
86                 t->access->flash_erase(h, t->c2aaa, false);
87                 t->gauge.label_set(t->gauge.label, wgT("erasing "));
88         }
89         return 0;
90 }
91 static SQInteger cpu_erase(HSQUIRRELVM v)
92 {
93         struct program_config *d;
94         SQRESULT r =  qr_userpointer_get(v, (SQUserPointer) &d);
95         if(SQ_FAILED(r)){
96                 return r;
97         }
98         return erase_set(v, d->handle, &d->cpu, &d->log);
99 }
100 static SQInteger ppu_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->ppu, &d->log);
108 }
109 static SQInteger program_regist(HSQUIRRELVM v, const struct reader_handle *h, struct flash_memory_driver *t)
110 {
111         SQRESULT r = qr_argument_get(v, 2, &t->programming.address, &t->programming.length);
112         if(SQ_FAILED(r)){
113                 return r;
114         }
115         t->compare = t->programming;
116         t->compare.offset = t->memory.offset & (t->memory.size - 1);
117         if(t->command_change == true){
118                 t->access->flash_config(
119                         h, t->c000x, t->c2aaa, t->c5555, 
120                         t->flash.pagesize, t->flash.retry
121                 );
122                 t->command_change = false;
123         }
124         
125         return sq_suspendvm(v);
126 }
127
128 static void program_execute(const struct reader_handle *h, struct flash_memory_driver *t)
129 {
130         const long w = t->access->flash_program(
131                 h, &t->gauge, 
132                 t->programming.address, t->programming.length, 
133                 t->memory.data + t->memory.offset, false, 
134                 t->flash.erase_require
135         );
136         t->programming.address += w;
137         t->programming.length -= w;
138         t->memory.offset += w;
139         t->memory.offset &= t->memory.size - 1;
140         t->programming.offset += w;
141 }
142
143 static bool program_compare(const struct reader_handle *h, struct flash_memory_driver *t)
144 {
145         uint8_t *comparea = Malloc(t->compare.length);
146         bool ret = false;
147         if(t->flash.erase_require == true){
148                 memset(comparea, 0xff, t->compare.length);
149                 int doread = memcmp(comparea, t->memory.data + t->compare.offset, t->compare.length);
150                 if(0){
151                         memset(comparea, 0, t->compare.length);
152                         doread &= memcmp(comparea, t->memory.data + t->compare.offset, t->compare.length);
153                 }
154                 if(doread == 0){
155                         Free(comparea);
156                         return true;
157                 }
158         }
159         
160         t->access->memory_read(h, &GAUGE_DUMMY, t->compare.address, t->compare.length, comparea);
161         if(memcmp(comparea, t->memory.data + t->compare.offset, t->compare.length) == 0){
162                 ret = true;
163         }
164         Free(comparea);
165         return ret;
166 }
167 static SQInteger cpu_program_memory(HSQUIRRELVM v)
168 {
169         struct program_config *d;
170         SQRESULT r =  qr_userpointer_get(v, (SQUserPointer) &d);
171         if(SQ_FAILED(r)){
172                 return r;
173         }
174         return program_regist(v, d->handle, &d->cpu);
175 }
176 static SQInteger ppu_program_memory(HSQUIRRELVM v)
177 {
178         struct program_config *d;
179         SQRESULT r =  qr_userpointer_get(v, (SQUserPointer) &d);
180         if(SQ_FAILED(r)){
181                 return r;
182         }
183         return program_regist(v, d->handle, &d->ppu);
184 }
185
186 static long erase_timer_get(const struct reader_handle *h, struct flash_memory_driver *t)
187 {
188         if(
189                 (t->memory.transtype != TRANSTYPE_EMPTY) && 
190                 (t->flash.erase_require == true)
191         ){
192                 return t->flash.erase_wait;
193         }else{
194                 return 0;
195         }
196 }
197 static SQInteger erase_wait(HSQUIRRELVM v)
198 {
199         struct program_config *d;
200         SQRESULT r =  qr_userpointer_get(v, (SQUserPointer) &d);
201         if(SQ_FAILED(r)){
202                 return r;
203         }
204         if(0){
205                 long timer_wait = erase_timer_get(d->handle, &d->cpu);
206                 long timer_ppu = erase_timer_get(d->handle, &d->ppu);
207                 if(timer_wait < timer_ppu){
208                         timer_wait = timer_ppu;
209                 }
210                 wait(timer_wait);
211         }else{
212                 uint8_t s[2];
213                 do{
214                         wait(2);
215                         d->control->flash_status(d->handle, s);
216                 //ËÜÍè¤Î°Õ¿Þ¤«¤é¤Ç¤Ï¤³¤³¤Î¾ò·ï¼°¤Ï && ¤Ç¤Ï¤Ê¤¯ || ¤À¤¬¡¢Àè¤Ë erase ¤¬½ª¤ï¤Ã¤¿¥Ç¥Ð¥¤¥¹¤¬Æ°¤«¤»¤ë¤Î¤Ç»Ä¤·¤Æ¤ª¤¯
217                 }while((s[0] != KAZZO_TASK_FLASH_IDLE) && (s[1] != KAZZO_TASK_FLASH_IDLE));
218         }
219         return 0;
220 }
221
222 static void gauge_init(struct flash_memory_driver *t)
223 {
224         t->gauge.range_set(t->gauge.bar, t->programming.count);
225
226         t->gauge.value_set(t->gauge.bar, t->gauge.label, 0);
227 }
228
229 static bool program_memoryarea(HSQUIRRELVM co, const struct reader_handle *h, struct flash_memory_driver *t, bool compare, SQInteger *state, struct textcontrol *log)
230 {
231         if(t->programming.length == 0){
232                 if(t->programming.offset != 0 && compare == true){
233                         if(program_compare(h, t) == false){
234                                 log->append(log->object, wgT("%s memory compare error, offset 0x%06x\n"), t->memory.name, t->programming.offset);
235                                 return false;
236                         }
237                 }
238
239                 sq_wakeupvm(co, SQFalse, SQFalse, SQTrue, SQFalse);
240                 *state = sq_getvmstate(co);
241         }else{
242                 program_execute(h, t);
243         }
244         return true;
245 }
246
247 static SQInteger program_main(HSQUIRRELVM v)
248 {
249         if(sq_gettop(v) != (1 + 3)){ //roottable, userpointer, co_cpu, co_ppu
250                 return sq_throwerror(v, wgT("argument number error"));
251         }
252         struct program_config *d;
253         SQRESULT r =  qr_userpointer_get(v, (SQUserPointer) &d);
254         if(SQ_FAILED(r)){
255                 return r;
256         }
257         HSQUIRRELVM co_cpu, co_ppu;
258         if(SQ_FAILED(sq_getthread(v, 3, &co_cpu))){
259                 return sq_throwerror(v, wgT("thread error"));
260         }
261         if(SQ_FAILED(sq_getthread(v, 4, &co_ppu))){
262                 return sq_throwerror(v, wgT("thread error"));
263         }
264         SQInteger state_cpu = sq_getvmstate(co_cpu);
265         SQInteger state_ppu = sq_getvmstate(co_ppu);
266         const long sleepms = d->compare == true ? 6 : 2; //W29C040 ¤Ç compare ¤ò¤¹¤ë¤È¡¢error ¤¬½Ð¤ë¤Î¤Ç½Ð¤Ê¤¤ÃͤËÄ´À° (¤ä¤Ã¤Ä¤±Âбþ)
267         
268         while((state_cpu != SQ_VMSTATE_IDLE) || (state_ppu != SQ_VMSTATE_IDLE)){
269                 uint8_t s[2];
270 //              bool console_update = false;
271                 wait(sleepms);
272                 d->control->flash_status(d->handle, s);
273                 if(state_cpu != SQ_VMSTATE_IDLE && s[0] == KAZZO_TASK_FLASH_IDLE){
274                         if(program_memoryarea(co_cpu, d->handle, &d->cpu, d->compare, &state_cpu, &d->log) == false){
275                                 return 0;
276                         }
277                 }
278                 if(state_ppu != SQ_VMSTATE_IDLE && s[1] == KAZZO_TASK_FLASH_IDLE){
279                         if(program_memoryarea(co_ppu, d->handle, &d->ppu, d->compare, &state_ppu, &d->log) == false){
280                                 return 0;
281                         }
282                 }
283         }
284         return 0;
285 }
286
287 static SQInteger program_count(HSQUIRRELVM v, struct flash_memory_driver *t, const struct range *range_address, const struct range *range_length, struct textcontrol *log)
288 {
289         SQRESULT r = qr_argument_get(v, 2, &t->programming.address, &t->programming.length);
290         if(SQ_FAILED(r)){
291                 return r;
292         }
293         r = range_check(v, wgT("length"), t->programming.length, range_length);
294         if(SQ_FAILED(r)){
295                 return r;
296         }
297         if((t->programming.address < range_address->start) || ((t->programming.address + t->programming.length) > range_address->end)){
298                 log->append(log->object, wgT("address range must be 0x%06x to 0x%06x"), (int) range_address->start, (int) range_address->end - 1);
299                 return sq_throwerror(v, wgT("script logical error"));
300         }
301         t->programming.count += t->programming.length;
302         return 0;
303 }
304 static SQInteger cpu_program_count(HSQUIRRELVM v)
305 {
306         static const struct range range_address = {0x8000, 0x10000};
307         static const struct range range_length = {0x0100, 0x4000};
308         struct program_config *d;
309         SQRESULT r =  qr_userpointer_get(v, (SQUserPointer) &d);
310         if(SQ_FAILED(r)){
311                 return r;
312         }
313         return program_count(v, &d->cpu, &range_address, &range_length, &d->log);
314 }
315
316 static SQInteger ppu_program_count(HSQUIRRELVM v)
317 {
318         static const struct range range_address = {0x0000, 0x2000};
319         static const struct range range_length = {0x0100, 0x2000};
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->ppu, &range_address, &range_length, &d->log);
326 }
327
328 static bool script_execute(HSQUIRRELVM v, const wgChar *function, struct program_config *c)
329 {
330         bool ret = true;
331         if(SQ_FAILED(sqstd_dofile(v, _SC("programcore.nut"), SQFalse, SQTrue))){
332                 c->log.append(c->log.object, wgT("flash core script error\n"));
333                 ret = false;
334         }else{
335                 SQRESULT r = qr_call(
336                         v, function, (SQUserPointer) c, c->script,
337                         1 + 3 * 2, c->mappernum, 
338                         c->cpu.memory.transtype, c->cpu.memory.size, c->cpu.flash.capacity,
339                         c->ppu.memory.transtype, c->ppu.memory.size, c->cpu.flash.capacity
340                 );
341                 if(SQ_FAILED(r)){
342                         ret = false;
343                 }
344         }
345         return ret;
346 }
347
348 static bool zendan(struct program_config *c)
349 {
350 //script test run
351         {
352                 static const wgChar *functionname[] = {
353                         wgT("cpu_erase"), wgT("ppu_erase"),
354                         wgT("erase_wait"), wgT("program_main")
355                 };
356                 HSQUIRRELVM v = qr_open(&c->log);
357                 int i;
358                 for(i = 0; i < sizeof(functionname)/sizeof(wgChar *); i++){
359                         qr_function_register_global(v, functionname[i], script_nop);
360                 }
361                 qr_function_register_global(v, _SC("cpu_write"), cpu_write_check);
362                 qr_function_register_global(v, _SC("cpu_command"), cpu_command);
363                 qr_function_register_global(v, _SC("cpu_program"), cpu_program_count);
364                 
365                 qr_function_register_global(v, _SC("ppu_program"), ppu_program_count);
366                 qr_function_register_global(v, _SC("ppu_command"), ppu_command);
367                 qr_function_register_global(v, _SC("vram_mirrorfind"), vram_mirrorfind);
368                 
369                 if(script_execute(v, wgT("testrun"), c) == false){
370                         qr_close(v);
371                         return false;
372                 }
373                 qr_close(v);
374                 assert(c->cpu.memory.size != 0);
375
376                 if(c->cpu.programming.count % c->cpu.memory.size  != 0){
377                         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);
378                         return false;
379                 }
380                 if(c->ppu.memory.size != 0){
381                         if(c->ppu.programming.count % c->ppu.memory.size != 0){
382                                 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);
383                                 return false;
384                         }
385                 }
386         }
387 //script execute 
388         c->cpu.command_change = true;
389         gauge_init(&c->cpu);
390         c->ppu.command_change = true;
391         gauge_init(&c->ppu);
392         {
393                 HSQUIRRELVM v = qr_open(&c->log); 
394                 qr_function_register_global(v, _SC("cpu_write"), cpu_write);
395                 qr_function_register_global(v, _SC("cpu_erase"), cpu_erase);
396                 qr_function_register_global(v, _SC("cpu_program"), cpu_program_memory);
397                 qr_function_register_global(v, _SC("cpu_command"), cpu_command);
398                 qr_function_register_global(v, _SC("ppu_erase"), ppu_erase);
399                 qr_function_register_global(v, _SC("ppu_program"), ppu_program_memory);
400                 qr_function_register_global(v, _SC("ppu_command"), ppu_command);
401                 qr_function_register_global(v, _SC("program_main"), program_main);
402                 qr_function_register_global(v, _SC("erase_wait"), erase_wait);
403                 qr_function_register_global(v, _SC("vram_mirrorfind"), script_nop);
404                 script_execute(v, wgT("program"), c);
405                 qr_close(v);
406         }
407         return true;
408 }
409
410 static bool memory_image_init(const struct memory *from, struct flash_memory_driver *t, struct textcontrol *log)
411 {
412         t->memory.data = from->data;
413         t->memory.size = from->size;
414         t->memory.attribute = MEMORY_ATTR_READ;
415         t->command_change = true;
416         t->programming.count = 0;
417         t->programming.offset = 0;
418         if(t->memory.size == 0){
419                 t->memory.transtype = TRANSTYPE_EMPTY;
420         }
421         if(t->flash.capacity < from->size){
422                 log->append(log->object, t->memory.name);
423                 
424                 log->append(log->object, wgT(" image size is larger than target device"));
425                 return false;
426         }
427         return true;
428 }
429
430 bool script_program_execute(struct program_config *c)
431 {
432 //rom image load
433         struct romimage rom;
434         if(nesfile_load(&c->log, c->target, &rom) == false){
435                 c->log.append(c->log.object, wgT("ROM image open error"));
436                 return false;
437         }
438 //variable init
439         c->mappernum = rom.mappernum;
440         c->cpu.memory.name = wgT("Program Flash");
441         if(memory_image_init(&rom.cpu_rom, &c->cpu, &c->log) == false){
442                 nesbuffer_free(&rom, 0);
443                 return false;
444         }
445         c->ppu.memory.name = wgT("Charcter Flash");
446         if(memory_image_init(&rom.ppu_rom, &c->ppu, &c->log) == false){
447                 nesbuffer_free(&rom, 0);
448                 return false;
449         }
450 //reader initalize
451         c->handle = c->control->open(c->except, &c->log);
452         if(c->handle == NULL){
453                 c->log.append(c->log.object, wgT("reader open error\n"));
454                 nesbuffer_free(&rom, 0);
455                 return false;
456         }
457 //program start, reader finalize
458         if(connection_check(c->handle, &c->log, c->cpu.access, c->ppu.access) == false){
459                 nesbuffer_free(&rom, 0);
460                 c->control->close(c->handle);
461                 return false;
462         }
463         bool ret = zendan(c);
464         c->control->close(c->handle);
465         c->handle = NULL;
466         nesbuffer_free(&rom, 0);
467         return ret;
468 }