OSDN Git Service

flash programming is supported
[unagi/old-svn-converted.git] / client / trunk / anago / anago_cui.c
1 #include <assert.h>
2 #include <stdio.h>
3 #include <stdarg.h>
4 #include <stdlib.h>
5 #include <string.h>
6 #include "memory_manage.h"
7 #include "type.h"
8 #include "widget.h"
9 #include "cui_gauge.h"
10 #include "romimage.h"
11 #include "reader_master.h"
12 #include "reader_kazzo.h"
13 #include "reader_dummy.h"
14 #include "script_dump.h"
15 #include "flash_device.h"
16 #include "script_program.h"
17 #include "crc32.h"
18
19 #ifdef _UNICODE
20   #define PUTS _putws
21   #define PRINTF wprintf
22   #define STRTOUL wcstoul
23  #else
24   #define PUTS puts
25   #define PRINTF printf
26   #define STRTOUL strtoul
27 #endif
28
29 static void text_append_va(void *obj, const wgChar *format, va_list list)
30 {
31 #ifdef _UNICODE
32         vwprintf(format, list);
33 #else
34         vprintf(format, list);
35 #endif
36 }
37
38 static void text_append(void *obj, const wgChar *format, ...)
39 {
40         va_list list;
41         va_start(list, format);
42         text_append_va(obj, format, list);
43         va_end(list);
44 }
45
46 static void log_set(struct textcontrol *log)
47 {
48         log->object = NULL;
49         log->append = text_append;
50         log->append_va = text_append_va;
51 }
52
53 static void except(const wgChar *str)
54 {
55         PUTS(str);
56         exit(0);
57 }
58
59 static bool program_rom_set(const wgChar *device, wgChar trans, struct memory *m, struct flash_device *f)
60 {
61         m->offset = 0;
62         if(flash_device_get(device, f) == false){
63                 PRINTF(wgT("unknown flash memory device %s\n"), device);
64                 return false;
65         }
66         switch(trans){
67         case 'f':
68                 m->transtype = TRANSTYPE_FULL;
69                 break;
70         case 't':
71                 m->transtype = TRANSTYPE_TOP;
72                 break;
73         case 'b':
74                 m->transtype = TRANSTYPE_BOTTOM;
75                 break;
76         case 'e':
77         default: 
78                 m->transtype = TRANSTYPE_EMPTY;
79                 break;
80         }
81         return true;
82 }
83
84 static void program(int c, wgChar **v, const struct reader_driver *r)
85 {
86         struct program_config config;
87         config.cpu.memory.data = NULL;
88         config.ppu.memory.data = NULL;
89         config.script = v[2];
90         config.target = v[3];
91         config.control = &r->control;
92         config.cpu.access = &r->cpu;
93         config.ppu.access = &r->ppu;
94         config.compare = false;
95         switch(v[1][0]){
96         case wgT('F'): case wgT('X'):
97                 config.compare = true;
98                 break;
99         }
100
101         switch(c){
102         case 5: {//mode script target cpu_flash_device
103                 wgChar trans = wgT('f');
104                 if(v[1][1] != wgT('\0')){
105                         trans = v[1][1];
106                 }
107                 if(program_rom_set(v[4], trans, &config.cpu.memory, &config.cpu.flash) == false){
108                         return;
109                 }
110                 if(program_rom_set(wgT("dummy"), wgT('e'), &config.ppu.memory, &config.ppu.flash) == false){
111                         assert(0);
112                         return;
113                 }
114                 }break;
115         case 6: { //mode script target cpu_flash_device ppu_flash_device
116                 wgChar trans = wgT('f');
117                 if(v[1][1] != wgT('\0')){
118                         trans = v[1][1];
119                 }
120                 if(program_rom_set(v[4], trans, &config.cpu.memory, &config.cpu.flash) == false){
121                         return;
122                 }
123                 trans = wgT('f');
124                 if(v[1][1] != wgT('\0') && v[1][2] != wgT('\0')){
125                         trans = v[1][2];
126                 }
127                 if(program_rom_set(v[5], trans, &config.ppu.memory, &config.ppu.flash) == false){
128                         return;
129                 }
130                 }break;
131         default:
132                 PUTS(wgT("mode script target cpu_flash_device ppu_flash_device"));
133                 return;
134         }
135         log_set(&config.log);
136         cui_gauge_new(&config.cpu.gauge, wgT("Program  Flash"), 2, -2);
137         cui_gauge_new(&config.ppu.gauge, wgT("Charcter Flash"), 1, -1);
138         config.except = except;
139         script_program_execute(&config);
140         cui_gauge_destory(&config.cpu.gauge);
141         cui_gauge_destory(&config.ppu.gauge);
142 }
143
144 static void dump(int c, wgChar **v, const struct reader_driver *r)
145 {
146         struct dump_config config;
147         if(c < 4){
148                 PUTS(wgT("argument error"));
149                 return;
150         }
151         config.cpu.increase = INCREASE_AUTO;
152         config.ppu.increase = 1;
153         config.progress = true;
154         switch(v[1][0]){
155         case wgT('d'): case wgT('z'):
156                 config.mode = MODE_ROM_DUMP;
157                 break;
158         case wgT('D'):
159                 config.mode = MODE_ROM_DUMP;
160                 config.progress = false;
161                 break;
162         case wgT('r'): case wgT('R'):
163                 config.mode = MODE_RAM_READ;
164                 break;
165         case wgT('w'): case wgT('W'):
166                 config.mode = MODE_RAM_WRITE;
167                 break;
168         }
169         switch(v[1][1]){
170         case wgT('1'):
171                 config.cpu.increase = 1;
172                 break;
173         case wgT('2'):
174                 config.cpu.increase = 2;
175                 break;
176         case wgT('4'):
177                 config.cpu.increase = 4;
178                 break;
179         }
180         if(v[1][1] != wgT('\0')){
181                 switch(v[1][2]){
182                 case wgT('2'):
183                         config.ppu.increase = 2;
184                         break;
185                 case wgT('4'):
186                         config.ppu.increase = 4;
187                         break;
188                 }
189         }
190         config.script = v[2];
191         config.target = v[3];
192         config.control = &r->control;
193         config.cpu.access = &r->cpu;
194         config.ppu.access = &r->ppu;
195         if(config.mode == MODE_ROM_DUMP){
196                 cui_gauge_new(&config.cpu.gauge, wgT("Program  ROM"), 2, -2);
197         }else{
198                 cui_gauge_new(&config.cpu.gauge, wgT("Work RAM"), 2, -2);
199         }
200         cui_gauge_new(&config.ppu.gauge, wgT("Charcter ROM"), 1, -1);
201         config.except = except;
202         config.mappernum = -1;
203         config.battery = false;
204         if(c == 5){
205                 const wgChar *t = v[4];
206                 if(*t == 'b' || *t == 'B'){
207                         config.battery = true;
208                         t += 1;
209                 }
210                 if(*t != '\0'){
211 #ifdef _UNICODE
212                         config.mappernum = _wtoi(t);
213 #else
214                         config.mappernum = atoi(t);
215 #endif
216                 }
217         }
218         log_set(&config.log);
219         if(config.mode == MODE_ROM_DUMP){
220                 script_dump_execute(&config);
221         }else{
222                 script_workram_execute(&config);
223         }
224         cui_gauge_destory(&config.cpu.gauge);
225         cui_gauge_destory(&config.ppu.gauge);
226 }
227
228 static void vram_scan(int c, wgChar **v, const struct reader_driver *r)
229 {
230         const struct reader_handle *h;
231         struct textcontrol log;
232         if(c == 3){
233                 PUTS(wgT("anago F [address] [data]..."));
234                 return;
235         }
236         log_set(&log);
237         h = r->control.open(except, &log);
238         
239         if(c == 2){
240                 PRINTF(wgT("%02x\n"), r->control.vram_connection(h));
241         }else{
242                 const long address = STRTOUL(v[2], NULL, 0x10);
243                 int i;
244                 for(i = 3; i < c; i++){
245                         const uint8_t d = STRTOUL(v[i], NULL, 0x10);
246                         r->cpu.memory_write(h, address, 1, &d);
247                         PRINTF(wgT("$%04x = 0x%02x->0x%02x\n"), address, (int) d, r->control.vram_connection(h));
248                 }
249         }
250         r->control.close(h);
251 }
252
253 static void crc32_dump(const wgChar *name, const wgChar *str, struct memory *m)
254 {
255         long banksize = STRTOUL(str, NULL, 0x10);
256         if(banksize < 0x400 || (banksize & 0xff) != 0){
257                 PUTS(wgT("banksize requires over 0x400"));
258                 return;
259         }
260         if(banksize > m->size){
261                 banksize = m->size;
262         }
263         int i, j;
264         PRINTF(wgT("%s 0x%x byte\n"), name, m->size);
265         for(i = 0, j = 0; i < m->size; i += banksize, j++){
266                 PRINTF(wgT("%02x:%08x\n"), j, crc32_get(m->data + i, banksize));
267         }
268 }
269
270 static void crc32_display(int c, wgChar **v)
271 {
272         if(c <= 3){
273                 PUTS(wgT("anago b [filename] [program ROM banksize]"));
274                 return;
275         }
276         struct romimage r;
277         struct textcontrol log;
278         log_set(&log);
279         if(nesfile_load(&log, v[2], &r) == false){
280                 return;
281         }
282         crc32_dump(wgT("Program ROM"), v[3], &r.cpu_rom);
283         if(c == 5 && r.ppu_rom.size != 0){
284                 crc32_dump(wgT("Charcter ROM"), v[4], &r.ppu_rom);
285         }
286         nesbuffer_free(&r, 0);
287 }
288
289 static void usage(const wgChar *v)
290 {
291         PUTS(wgT("famicom bus simluator 'anago'"));
292         PRINTF(wgT("%s [mode] [script] [target] ....\n"), v);
293         PUTS(wgT("d - ROM dump with kazzo"));
294         PUTS(wgT("fF- flash program with kazzo"));
295         PUTS(wgT("r - workram read with kazzo"));
296         PUTS(wgT("w - workram write with kazzo"));
297         PUTS(wgT("v - VRAM A10 scan with kazzo"));
298         PUTS(wgT("b - display each CRC32s by required size"));
299         if(DEBUG == 1){
300                 PUTS(wgT("z - ROM dump for test"));
301                 PUTS(wgT("xX- flash program for test"));
302                 PUTS(wgT("R - workram read for test"));
303                 PUTS(wgT("W - workram write for test"));
304         }
305 }
306
307 #ifdef WIN32
308 int main(int c, char **vv)
309 #else
310 int anago_cui(int c, wgChar **v)
311 #endif
312 {
313         mm_init();
314         if(c >= 2){
315                 const struct reader_driver *r = &DRIVER_KAZZO;
316 #ifdef _UNICODE
317                 int i;
318                 wchar_t **v;
319                 v = Malloc(sizeof(wchar_t *) * c);
320                 for(i = 0; i < c; i++){
321                         size_t len = strlen(vv[i]) + 1;
322                         v[i] = Malloc(sizeof(wchar_t) * len);
323                         mbstowcs(v[i], vv[i], len);
324                 }
325 #endif
326                 switch(v[1][0]){
327                 case wgT('x'): case wgT('X'):
328                         r = &DRIVER_DUMMY; //though down
329                 case wgT('f'): case wgT('F'):
330                         program(c, v, r);
331                         break;
332                 case wgT('z'): case wgT('R'): case wgT('W'): 
333                         r = &DRIVER_DUMMY; //though down
334                 case wgT('d'): case wgT('D'):
335                 case wgT('r'): case wgT('w'):
336                         dump(c, v, r);
337                         break;
338                 case wgT('V'):
339                         r = &DRIVER_DUMMY;
340                 case wgT('v'):
341                         vram_scan(c, v, r);
342                         break;
343                 case wgT('b'):
344                         crc32_display(c, v);
345                         break;
346                 default:
347                         usage(v[0]);
348                         PUTS(wgT("mode are d, D, f, g"));
349                         break;
350                 }
351 #ifdef _UNICODE
352                 for(i = 0; i < c; i++){
353                         Free(v[i]);
354                 }
355                 Free(v);
356 #endif
357         }else{ //usage
358 #ifdef _UNICODE
359                 size_t len = strlen(vv[0]) + 1;
360                 wchar_t *t = Malloc(sizeof(wchar_t) * len);
361                 mbstowcs(t, vv[0], len);
362                 usage(t);
363                 Free(t);
364 #else
365                 usage(v[0]);
366 #endif
367         }
368         mm_end();
369         return 0;
370 }