OSDN Git Service

DB ファイル名を変更
[unagi/old-svn-converted.git] / client / trunk / anago / anago_frame.cpp
1 #include <wx/wx.h>
2 #include <wx/app.h>
3 #include <wx/thread.h>
4 #include <wx/dir.h>
5 #include <wx/sound.h>
6 #include <wx/fileconf.h>
7 #include <wx/filename.h>
8 #include <cassert>
9 #include <cstdarg>
10 #include "type.h"
11 #include "anago_gui.h"
12 #include "nescartxml.hh"
13 #include "widget.h"
14 #include "reader_master.h"
15 #include "reader_kazzo.h"
16 #include "reader_dummy.h"
17 extern "C"{
18   #include "romimage.h"
19   #include "flash_device.h"
20   #include "script_dump.h"
21   #include "script_program.h"
22   void qr_version_print(const struct textcontrol *l);
23 }
24 #ifdef _UNICODE
25   #define STRNCPY wcsncpy
26 #else
27   #define STRNCPY strncpy
28 #endif
29 //---- C++ -> C -> C++ wrapping static functions ----
30 namespace c_wrapper{
31         static void throw_error(const wxChar *t)
32         {
33                 throw t;
34         }
35
36         static void value_set(void *gauge, void *label, int value)
37         {
38                 wxGauge *g = static_cast<wxGauge *>(gauge);
39                 wxStaticText *l = static_cast<wxStaticText *>(label);
40                 wxString str;
41                 if(g->GetRange() == 1){
42                         str = wxT("skip             ");
43                 }else{
44                         str.Printf(wxT("0x%06x/0x%06x"), value, g->GetRange());
45                 }
46                 
47                 wxMutexGuiEnter();
48                 g->SetValue(value);
49                 if(label != NULL){
50                         l->SetLabel(str);
51                 }
52                 wxMutexGuiLeave();
53         }
54
55         static void value_add(void *gauge, void *label, int value)
56         {
57                 wxGauge *g = static_cast<wxGauge *>(gauge);
58                 value += g->GetValue();
59                 
60                 value_set(gauge, label, value);
61         }
62
63         static void range_set(void *gauge, int value)
64         {
65                 wxGauge *g = static_cast<wxGauge *>(gauge);
66                 if(value == 0){
67                         value = 1;
68                 }
69                 g->SetRange(value);
70         }
71
72         static void text_append_va(void *log, const wxChar *format, va_list list)
73         {
74                 wxTextCtrl *l = static_cast<wxTextCtrl *>(log);
75                 wxString str;
76                 str.PrintfV(format, list);
77
78                 wxMutexGuiEnter();
79                 *l << str;
80                 wxMutexGuiLeave();
81         }
82
83         static void text_append(void *log, const wxChar *format, ...)
84         {
85                 va_list list;
86                 va_start(list, format);
87                 text_append_va(log, format, list);
88                 va_end(list);
89         }
90
91         static void version_append_va(void *log, const wxChar *format, va_list list)
92         {
93                 wxTextCtrl *l = static_cast<wxTextCtrl *>(log);
94                 wxString str;
95                 str.PrintfV(format, list);
96
97                 *l << str;
98         }
99
100         static void version_append(void *log, const wxChar *format, ...)
101         {
102                 va_list list;
103                 va_start(list, format);
104                 version_append_va(log, format, list);
105                 va_end(list);
106         }
107
108         static void label_set(void *label, const wxChar *format, ...)
109         {
110                 wxStaticText *l = static_cast<wxStaticText *>(label);
111                 wxString str;
112                 va_list list;
113                 
114                 va_start(list, format);
115                 str.PrintfV(format, list);
116                 va_end(list);
117
118                 wxMutexGuiEnter();
119                 l->SetLabel(str);
120                 wxMutexGuiLeave();
121         }
122
123         static void choice_append(void *choice, const wxChar *str)
124         {
125                 wxChoice *c = static_cast<wxChoice *>(choice);
126                 c->Append(wxString(str));
127         }
128
129         static void gauge_init(struct gauge *t)
130         {
131                 t->label_set = label_set;
132                 t->range_set = range_set;
133                 t->value_set = value_set;
134                 t->value_add = value_add;
135         }
136 }
137
138 //---- script execute thread ----
139 class anago_dumper : public wxThread
140 {
141 private:
142         wxWindow *const m_frame;
143         wxTextCtrl *const m_log;
144         const wxSound m_sound_success, m_sound_fail;
145         RomDb *const m_romdb;
146
147         struct dump_config m_config;
148 protected:
149         void *Entry(void)
150         {
151                 try{
152                         bool r = false;
153                         switch(m_config.mode){
154                         case MODE_ROM_DUMP:
155                                 r = script_dump_execute(&m_config);
156                                 break;
157                         case MODE_RAM_READ: case MODE_RAM_WRITE:
158                                 r = script_workram_execute(&m_config);
159                                 break;
160                         default:
161                                 assert(0);
162                                 break;
163                         }
164                         if(r == true && m_sound_success.IsOk() == true){
165                                 m_sound_success.Play();
166                         }
167                 }catch(const wxChar *t){
168                         if(m_sound_fail.IsOk() == true){
169                                 m_sound_fail.Play();
170                         }
171                         *m_log << t;
172                 }
173                 if(m_romdb != NULL){
174                         m_romdb->Search(m_config.crc, m_log);
175                 }
176                 wxMutexGuiEnter();
177                 m_frame->Enable();
178                 wxMutexGuiLeave();
179                 return NULL;
180         }
181         void OnExit()
182         {
183                 delete [] m_config.script;
184                 delete [] m_config.target;
185         }
186 public:
187         anago_dumper(wxWindow *f, const struct dump_config *d, wxTextCtrl *log, wxString sound_success, wxString sound_fail, RomDb *db = NULL) 
188           : wxThread(), m_frame(f), m_log(log), 
189           m_sound_success(sound_success), m_sound_fail(sound_fail),
190           m_romdb(db)
191         {
192                 m_config = *d; //struct data copy
193         }
194 };
195
196 class anago_programmer : public wxThread
197 {
198 private:
199         wxWindow *const m_frame;
200         wxTextCtrl *const m_log;
201         struct program_config m_config;
202         const wxSound m_sound_success, m_sound_fail;
203 protected:
204         void *Entry(void)
205         {
206                 try{
207                         if(script_program_execute(&m_config) == true){
208                                 if(m_sound_success.IsOk() == true){
209                                         m_sound_success.Play();
210                                 }
211                         }
212                 }catch(const wxChar *t){
213                         if(m_sound_fail.IsOk() == true){
214                                 m_sound_fail.Play();
215                         }
216                         *m_log << t;
217                 }
218                 wxMutexGuiEnter();
219                 m_frame->Enable();
220                 wxMutexGuiLeave();
221                 return NULL;
222         }
223
224         void OnExit()
225         {
226                 delete [] m_config.script;
227                 delete [] m_config.target;
228         }
229 public:
230         anago_programmer(wxWindow *f, wxTextCtrl *log, const struct program_config *d, wxString sound_success, wxString sound_fail) 
231           : wxThread(), m_frame(f), m_log(log),
232           m_sound_success(sound_success), m_sound_fail(sound_fail)
233         {
234                 m_config = *d;
235         }
236 };
237
238 static void script_choice_init(wxControlWithItems *c, wxArrayString filespec, wxTextCtrl *log)
239 {
240         wxDir dir(wxGetCwd());
241         wxArrayString ar;
242
243         c->Clear();
244         if ( !dir.IsOpened() ){
245                 return;
246         }
247         for(size_t i = 0; i < filespec.GetCount(); i++){
248                 wxString filename;
249                 bool cont = dir.GetFirst(&filename, filespec[i], wxDIR_FILES);
250                 while ( cont ){
251                         ar.Add(filename);
252                         cont = dir.GetNext(&filename);
253                 }
254         }
255         if(ar.GetCount() == 0){
256                 *log << wxT("warning: ");
257                 for(size_t i = 0; i < filespec.GetCount(); i++){
258                         *log << filespec[i] << wxT(" ");
259                 }
260                 *log << wxT("script not found.\n");
261         }else{
262                 ar.Sort(false);
263                 for(size_t i = 0; i < ar.GetCount(); i++){
264                         c->Append(ar[i]);
265                 }
266                 c->Select(0);
267         }
268 }
269
270 static void increase_init(wxControlWithItems *c)
271 {
272         c->Clear();
273         c->Append(wxT("x1"));
274         c->Append(wxT("x2"));
275         c->Append(wxT("x4"));
276         c->Select(0);
277 }
278
279 static int increase_get(wxControlWithItems *c)
280 {
281         switch(c->GetSelection()){
282         case 0: return 1;
283         case 1: return 2;
284         case 2: return 4;
285         case 3: return INCREASE_AUTO;
286         }
287         return 1;
288 }
289
290 enum anago_status{
291         STATUS_IDLE, STATUS_DUMPPING, STATUS_PROGRAMMING,
292         STATUS_RAM_READ, STATUS_RAM_WRITE
293 };
294
295 class anago_panel_dump : public panel_dump
296 {
297 private:
298         wxThread *m_anago_thread;
299         const struct reader_driver *const m_reader;
300         enum anago_status *const m_status;
301         wxTextCtrl *const m_log;
302         wxString m_sound_success, m_sound_fail;
303         wxString m_database;
304         RomDb *m_romdb;
305
306         void execute(void)
307         {
308                 struct dump_config config;
309                 config.mode = MODE_ROM_DUMP;
310                 config.cpu.gauge.bar = m_cpu_gauge;
311                 config.cpu.gauge.label = m_cpu_value;
312                 c_wrapper::gauge_init(&config.cpu.gauge);
313
314                 config.ppu.gauge.bar = m_ppu_gauge;
315                 config.ppu.gauge.label = m_ppu_value;
316                 c_wrapper::gauge_init(&config.ppu.gauge);
317                 
318                 config.log.object = m_log;
319                 config.log.append = c_wrapper::text_append;
320                 config.log.append_va = c_wrapper::text_append_va;
321                 config.except = c_wrapper::throw_error;
322                 config.cpu.increase = increase_get(m_cpu_increase);
323                 config.ppu.increase = increase_get(m_ppu_increase);
324                 config.progress = true;
325                 config.battery = m_check_battery->GetValue();
326                 {
327                         wxString str_script = m_script_choice->GetStringSelection();
328                         wxChar *t = new wxChar[str_script.Length() + 1];
329                         config.script = t;
330                         STRNCPY(t, str_script.c_str(), str_script.Length() + 1);
331                 }
332
333                 {
334                         wxString str;
335                         config.mappernum = -1;
336                         if(m_check_forcemapper->GetValue() == true){
337                                 str = m_text_forcemapper->GetValue();
338                                 if(str.ToLong(&config.mappernum) == false){
339                                         *m_log << wxT("bad mapper number\n");
340                                         return;
341                                 }
342                         }
343                 }
344
345                 {
346                         wxTextCtrl *text = m_romimage_picker->GetTextCtrl();
347                         wxString str_rom = text->GetValue();
348                         wxChar *t = new wxChar[str_rom.Length() + 1];
349                         if(text->IsEmpty() == true){
350                                 *m_log << wxT("Enter filename to ROM image\n");
351                                 return;
352                         }
353                         config.target = t;
354                         STRNCPY(t, str_rom.c_str(), str_rom.Length() + 1);
355                 }
356
357                 config.control = &m_reader->control;
358                 config.cpu.access = &m_reader->cpu;
359                 config.ppu.access = &m_reader->ppu;
360
361                 this->Disable();
362
363 /*              if(m_anago_thread != NULL){ //???
364                         delete m_anago_thread;
365                 }*/
366                 m_anago_thread = new anago_dumper(this, &config, m_log, m_sound_success, m_sound_fail, m_romdb);
367                 if(m_anago_thread->Create() != wxTHREAD_NO_ERROR){
368                         *m_log << wxT("thread creating error");
369                 }else if(m_anago_thread->Run() != wxTHREAD_NO_ERROR){
370                         *m_log << wxT("thread running error");
371                 }else{
372                         *m_status = STATUS_DUMPPING;
373                 }
374         }
375 protected:
376         void button_click(wxCommandEvent& event)
377         {
378                 switch(*m_status){
379                 case STATUS_IDLE:
380                         this->execute();
381                         break;
382                 case STATUS_DUMPPING:
383                         m_anago_thread->Kill();
384                         this->Enable();
385                         break;
386                 default: //do nothing
387                         break;
388                 }
389         }
390
391         void mapper_change_check(wxCommandEvent& event)
392         {
393                 if(m_check_forcemapper->GetValue() == true){
394                         m_text_forcemapper->Enable();
395                 }else{
396                         m_text_forcemapper->Disable();
397                 }
398         }
399
400 public:
401         anago_panel_dump(wxNotebook *p, const struct reader_driver *r, enum anago_status *status, wxFileConfig *config, wxTextCtrl *log)
402           : panel_dump(p), m_reader(r), m_status(status), m_log(log)
403         {
404                 config->Read(wxT("dump.database"), &m_database, wxT("NesCarts (2011-09-10).xml"));
405                 if(wxFileName::FileExists(m_database) == true){
406                         m_romdb = new RomDb(m_database);
407                         m_romdb->Generate();
408                 }else{
409                         *log << wxT("m_database not found\n");
410                         m_romdb = new RomDb();
411                 }
412
413                 config->Read(wxT("dump.sound.success"), &m_sound_success, wxT("tinkalink2.wav"));
414                 config->Read(wxT("dump.sound.fail"), &m_sound_fail, wxT("doggrowl.wav"));
415
416                 wxArrayString ar;
417                 ar.Add(wxT("*.ad"));
418                 ar.Add(wxT("*.ae"));
419                 ar.Add(wxT("*.af"));
420                 ar.Add(wxT("*.ag"));
421                 script_choice_init(m_script_choice, ar, log);
422                 ::increase_init(m_cpu_increase);
423                 m_cpu_increase->Append(wxT("Auto"));
424                 m_cpu_increase->Select(3);
425                 ::increase_init(m_ppu_increase);
426                 if(DEBUG==1){
427                         m_romimage_picker->GetTextCtrl()->SetLabel(wxT("t.nes"));
428                 }
429         }
430         virtual ~anago_panel_dump(void)
431         {
432                 delete m_romdb;
433         }
434         bool Enable(bool t = true)
435         {
436                 m_script_choice->Enable(t);
437                 m_romimage_picker->Enable(t);
438                 m_check_battery->Enable(t);
439                 m_check_forcemapper->Enable(t);
440                 m_cpu_increase->Enable(t);
441                 m_ppu_increase->Enable(t);
442                 if(t == true){
443                         *m_status = STATUS_IDLE;
444                         m_button->SetLabel(wxT("&dump"));
445                         if(m_check_forcemapper->GetValue() == true){
446                                 m_text_forcemapper->Enable();
447                         }
448                 }else{
449                         m_button->SetLabel(wxT("cancel"));
450                         m_check_forcemapper->Disable();
451                 }
452                 m_button->SetFocus();
453                 return true;
454         }
455         bool Disable(void)
456         {
457                 return this->Enable(false);
458         }
459 };
460
461 class anago_panel_program : public panel_program
462 {
463 private:
464         wxThread *m_anago_thread;
465         const struct reader_driver *const m_reader;
466         wxString m_sound_success, m_sound_fail;
467         enum anago_status *const m_status;
468         wxTextCtrl *const m_log;
469         
470         void padding_init(wxControlWithItems *c)
471         {
472                 c->Clear();
473                 c->Append(wxT("full"));
474                 c->Append(wxT("top"));
475                 c->Append(wxT("bottom"));
476                 c->Append(wxT("empty"));
477                 c->Select(0);
478         }
479         bool rom_set(wxString device, int trans, struct memory *m, struct flash_device *f)
480         {
481                 m->offset = 0;
482                 if(flash_device_get(device, f) == false){
483                         *m_log << wxT("unknown flash memory device ");
484                         *m_log << device << wxT("\n");
485                         return false;
486                 }
487                 switch(trans){
488                 case 0: 
489                         m->transtype = TRANSTYPE_FULL;
490                         break;
491                 case 1: 
492                         m->transtype = TRANSTYPE_TOP;
493                         break;
494                 case 2: 
495                         m->transtype = TRANSTYPE_BOTTOM;
496                         break;
497                 default: 
498                         m->transtype = TRANSTYPE_EMPTY;
499                         break;
500                 }
501                 return true;
502         }
503
504         void execute(void)
505         {
506                 struct program_config f;
507                 
508                 f.cpu.gauge.bar = m_cpu_gauge;
509                 f.cpu.gauge.label = m_cpu_value;
510                 c_wrapper::gauge_init(&f.cpu.gauge);
511
512                 f.ppu.gauge.bar = m_ppu_gauge;
513                 f.ppu.gauge.label = m_ppu_value;
514                 c_wrapper::gauge_init(&f.ppu.gauge);
515                 
516                 f.log.object = m_log;
517                 f.log.append = c_wrapper::text_append;
518                 f.log.append_va = c_wrapper::text_append_va;
519                 f.except = c_wrapper::throw_error;
520                 
521                 {
522                         wxString str_script = m_script_choice->GetStringSelection();
523                         wxChar *t = new wxChar[str_script.Length() + 1];
524                         STRNCPY(t, str_script.c_str(), str_script.Length() + 1);
525                         f.script = t;
526                 }
527
528                 {
529                         wxTextCtrl *text = m_romimage_picker->GetTextCtrl();
530                         wxString str_rom = text->GetValue();
531                         if(text->IsEmpty() == true){
532                                 *m_log << wxT("Enter filename to ROM image\n");
533                                 return;
534                         }
535                         wxChar *t = new wxChar[str_rom.Length() + 1];
536                         STRNCPY(t, str_rom.c_str(), str_rom.Length() + 1);
537                         f.target = t;
538                 }
539                 f.compare = m_compare->GetValue();
540
541                 if(rom_set(
542                         m_cpu_device->GetStringSelection(), 
543                         m_cpu_padding->GetSelection(),
544                         &f.cpu.memory, &f.cpu.flash
545                 ) == false){
546                         return;
547                 }
548                 if(rom_set(
549                         m_ppu_device->GetStringSelection(), 
550                         m_ppu_padding->GetSelection(),
551                         &f.ppu.memory, &f.ppu.flash
552                 ) == false){
553                         return;
554                 }
555
556                 f.control = &m_reader->control;
557                 f.cpu.access = &m_reader->cpu;
558                 f.ppu.access = &m_reader->ppu;
559
560                 this->Disable();
561
562                 m_anago_thread = new anago_programmer(this, m_log, &f, m_sound_success, m_sound_fail);
563                 if(m_anago_thread->Create() != wxTHREAD_NO_ERROR){
564                         *m_log << wxT("thread creating error");
565                 }else if(m_anago_thread->Run() != wxTHREAD_NO_ERROR){
566                         *m_log << wxT("thread running error");
567                 }else{
568                         *m_status = STATUS_PROGRAMMING;
569                 }
570         }
571
572         void device_load(wxControlWithItems *choice, wxFileConfig *c, wxString key)
573         {
574                 wxString device;
575                 int val;
576                 c->Read(key, &device);
577                 val = choice->FindString(device);
578                 if(val == wxNOT_FOUND){
579                         choice->Select(0);
580                 }else{
581                         choice->Select(val);
582                 }
583         }
584 protected:
585         void button_click(wxCommandEvent& event)
586         {
587                 switch(*m_status){
588                 case STATUS_IDLE:
589                         this->execute();
590                         break;
591                 case STATUS_PROGRAMMING:
592                         m_anago_thread->Kill();
593                         this->Enable();
594                         break;
595                 default: //do nothing
596                         break;
597                 }
598         }
599 public:
600         anago_panel_program(wxNotebook *p, const struct reader_driver *r, enum anago_status *status, wxFileConfig *config, wxTextCtrl *log) 
601           : panel_program(p), m_reader(r), m_status(status), m_log(log)
602         {
603                 config->Read(wxT("program.sound.success"), &m_sound_success, wxT("cuckoo.wav"));
604                 config->Read(wxT("program.sound.fail"), &m_sound_fail, wxT("doggrowl.wav"));
605                 {
606                         wxArrayString t;
607                         t.Add(wxT("*.af"));
608                         t.Add(wxT("*.ag"));
609                         script_choice_init(m_script_choice, t, m_log);
610                 }
611                 {
612                         struct flash_listup list;
613                         list.obj_cpu = m_cpu_device;
614                         list.obj_ppu = m_ppu_device;
615                         list.append = c_wrapper::choice_append;
616                         flash_device_listup(&list);
617                 }
618                 if(m_cpu_device->GetCount() == 0){
619                         *m_log << wxT("warning: flash device parameter not found\n");
620                 }else{
621                         device_load(m_cpu_device, config, wxT("program.cpu.device"));
622                         device_load(m_ppu_device, config, wxT("program.ppu.device"));
623                 }
624                 this->padding_init(m_cpu_padding);
625                 this->padding_init(m_ppu_padding);
626                 
627                 m_anago_thread = NULL;
628         }
629         bool Enable(bool t = true)
630         {
631                 m_script_choice->Enable(t);
632                 m_romimage_picker->Enable(t);
633                 m_compare->Enable(t);
634                 m_cpu_padding->Enable(t);
635                 m_cpu_device->Enable(t);
636                 m_ppu_padding->Enable(t);
637                 m_ppu_device->Enable(t);
638                 if(t == true){
639                         *m_status = STATUS_IDLE;
640                         m_button->SetLabel(wxT("&program"));
641                 }else{
642                         m_button->SetLabel(wxT("cancel"));
643                 }
644                 m_button->SetFocus();
645                 return true;
646         }
647         bool Disable(void)
648         {
649                 return this->Enable(false);
650         }
651         void ConfigWrite(wxFileConfig *c)
652         {
653                 c->Write(wxT("program.cpu.device"), m_cpu_device->GetStringSelection());
654                 c->Write(wxT("program.ppu.device"), m_ppu_device->GetStringSelection());
655         }
656 };
657
658 class anago_panel_workram : public panel_workram
659 {
660 private:
661         wxThread *m_anago_thread;
662         const struct reader_driver *const m_reader;
663         enum anago_status *const m_status;
664         wxTextCtrl *const m_log;
665         wxString m_sound_success, m_sound_fail;
666
667         void execute(struct dump_config *c, wxControlWithItems *script, wxFilePickerCtrl *picker, enum anago_status status)
668         {
669                 c->cpu.gauge.label = NULL;
670                 c_wrapper::gauge_init(&c->cpu.gauge);
671                 
672                 c->log.object = m_log;
673                 c->log.append = c_wrapper::text_append;
674                 c->log.append_va = c_wrapper::text_append_va;
675                 c->except = c_wrapper::throw_error;
676                 assert(c->cpu.increase != INCREASE_AUTO);
677                 c->progress = true;
678                 {
679                         wxString str_script = script->GetStringSelection();
680                         wxChar *t = new wxChar[str_script.Length() + 1];
681                         c->script = t;
682                         STRNCPY(t, str_script.c_str(), str_script.Length() + 1);
683                 }
684                 {
685                         wxTextCtrl *text = picker->GetTextCtrl();
686                         wxString str_rom = text->GetValue();
687                         wxChar *t = new wxChar[str_rom.Length() + 1];
688                         if(text->IsEmpty() == true){
689                                 *m_log << wxT("Enter filename to ROM image\n");
690                                 return;
691                         }
692                         c->target = t;
693                         STRNCPY(t, str_rom.c_str(), str_rom.Length() + 1);
694                 }
695                 c->control = &m_reader->control;
696                 c->cpu.access = &m_reader->cpu;
697                 c->ppu.access = &m_reader->ppu;
698                 
699                 m_anago_thread = new anago_dumper(this, c, m_log, m_sound_success, m_sound_fail);
700                 if(m_anago_thread->Create() != wxTHREAD_NO_ERROR){
701                         *m_log << wxT("thread creating error");
702                 }else if(m_anago_thread->Run() != wxTHREAD_NO_ERROR){
703                         *m_log << wxT("thread running error");
704                 }else{
705                         *m_status = status; //先に status を設定すること
706                         this->Disable();
707                 }
708         }
709
710         void read(void)
711         {
712                 struct dump_config config;
713                 config.mode = MODE_RAM_READ;
714                 config.cpu.gauge.bar = m_read_gauge;
715                 config.cpu.increase = ::increase_get(m_read_increase);
716                 this->execute(&config, m_read_script, m_read_picker, STATUS_RAM_READ);
717         }
718         void write(void)
719         {
720                 struct dump_config config;
721                 config.mode = MODE_RAM_WRITE;
722                 config.cpu.gauge.bar = m_write_gauge;
723                 config.cpu.increase = ::increase_get(m_write_increase);
724                 this->execute(&config, m_write_script, m_write_picker, STATUS_RAM_WRITE);
725         }
726 protected:
727         void read_button_click(wxCommandEvent& event)
728         {
729                 switch(*m_status){
730                 case STATUS_IDLE:
731                         read();
732                         break;
733                 case STATUS_RAM_READ:
734                         this->Enable();
735                         break;
736                 default: //do nothing
737                         break;
738                 }
739         }
740
741         void write_button_click(wxCommandEvent& event)
742         {
743                 switch(*m_status){
744                 case STATUS_IDLE:
745                         write();
746                         break;
747                 case STATUS_RAM_WRITE:
748                         this->Enable();
749                         break;
750                 default: //do nothing
751                         break;
752                 }
753         }
754 public:
755         anago_panel_workram(wxWindow *p, const struct reader_driver *r, enum anago_status *status, wxFileConfig *config, wxTextCtrl *log)
756           : panel_workram(p), m_reader(r), m_status(status), m_log(log)
757         {
758                 config->Read(wxT("workram.sound.success"), &m_sound_success, wxT("tinkalink2.wav"));
759                 config->Read(wxT("workram.sound.fail"), &m_sound_fail, wxT("doggrowl.wav"));
760
761                 wxArrayString ar;
762                 ar.Add(wxT("*.ae"));
763                 ar.Add(wxT("*.ag"));
764                 ::script_choice_init(m_read_script, ar, log);
765                 ::script_choice_init(m_write_script, ar, log);
766                 ::increase_init(m_read_increase);
767                 ::increase_init(m_write_increase);
768                 
769                 if(DEBUG == 1){
770                         m_read_picker->GetTextCtrl()->SetLabel(wxT("t.sav"));
771                 }
772         }
773         
774         bool Enable(bool t = true)
775         {
776                 m_read_script->Enable(t);
777                 m_read_picker->Enable(t);
778                 m_write_script->Enable(t);
779                 m_write_picker->Enable(t);
780                 if(t == true){
781                         switch(*m_status){
782                         case STATUS_RAM_READ:
783                                 m_read_button->SetLabel(wxT("&read"));
784                                 m_read_button->SetFocus();
785                                 m_write_button->Enable();
786                                 break;
787                         case STATUS_RAM_WRITE:
788                                 m_write_button->SetLabel(wxT("&write"));
789                                 m_write_button->SetFocus();
790                                 m_read_button->Enable();
791                                 break;
792                         default:
793                                 break;
794                         }
795                         *m_status = STATUS_IDLE;
796                 }else{
797                         switch(*m_status){
798                         case STATUS_RAM_READ:
799                                 m_read_button->SetLabel(wxT("&cancel"));
800                                 m_write_button->Disable();
801                                 break;
802                         case STATUS_RAM_WRITE:
803                                 m_write_button->SetLabel(wxT("&cancel"));
804                                 m_read_button->Disable();
805                                 break;
806                         default:
807                                 break;
808                         }
809                 }
810                 return true;
811         }
812
813         bool Disable(void)
814         {
815                 return this->Enable(false);
816         }
817 };
818
819 class anago_panel_version : public panel_version
820 {
821 public:
822         anago_panel_version(wxWindow *p) : panel_version(p)
823         {
824 //version infomation
825                 {
826                         struct textcontrol detail;
827                         *m_version_detail << wxT("anago build at ") << wxT(__DATE__) << wxT("\n\n");
828                         detail.object = m_version_detail;
829                         detail.append = c_wrapper::version_append;
830                         detail.append_va = c_wrapper::version_append_va;
831                         qr_version_print(&detail);
832                         *m_version_detail << wxVERSION_STRING << wxT(" (c) Julian Smar");
833                 }
834                 
835 #if 0 //def WIN32
836                 #include "okada.xpm"
837                 wxBitmap bitmap_okada(okada);
838                 wxString tooltip(wxT(
839                         "緑区 na6ko 町さん (28歳, 童貞)\n\n"
840
841                         "28年間バカにされっぱなし、ミジメ過ぎた俺の人生が anago,\n"
842                         "kazzo を持つようになった途端、突然ツキがめぐってきた。\n"
843 //                      "競馬をやれば連戦連勝、夢にまでみた万馬券を当て、気がつくと\n"
844 //                      "しんじられない事にギャンブルで稼いだお金が460万円!!\n"
845                         "元手はたった4000円。しかもたった2ヶ月で人生大逆転!!\n"
846                         "女は3P4Pヤリ放題!!"
847 //                      "勤めていた新聞屋も辞めギャンブルで\n"
848 //                      "身を立てていこうと思っています。実は来月の11日にラスベガスに\n"
849 //                      "行き勝負をかけます。結果はまた報告します。宜しく。"
850                 ));
851 #else
852                 #include "slyly.xpm"
853                 wxBitmap bitmap_okada(slyly);
854                 wxString tooltip(wxT("CARP                        ピロ"));
855 #endif
856 //              #include "araki.xpm"
857 //              wxBitmap bitmap_okada(araki);
858                 m_version_photo->SetBitmap(bitmap_okada);
859                 m_version_photo->SetToolTip(tooltip);
860         }
861 };
862
863 //---- main frame class ----
864 class anago_frame : public frame_main
865 {
866 private:
867         enum anago_status m_status; //ここだけ実体, 各パネルはこのポインタ
868         const wxString m_config_file;
869         anago_panel_program *m_panel_program;
870 protected:
871         void menu_log_clean(wxCommandEvent& event)
872         {
873                 m_log->Clear();
874         }
875         
876 public:
877         /** Constructor */
878         anago_frame(wxWindow* parent, const struct reader_driver *r)
879           : frame_main(parent), m_status(STATUS_IDLE),
880 #ifdef WIN32
881           m_config_file(wxGetCwd() + wxT("/anago.cfg"))
882 #else
883           m_config_file(wxT(".anago"))
884 #endif
885         {
886                 wxFileConfig config(wxEmptyString, wxEmptyString, m_config_file);
887 //form config load
888                 wxPoint position;
889                 
890                 config.Read(wxT("position.x"), &position.x, 32);
891                 config.Read(wxT("position.y"), &position.y, 32);
892                 this->SetPosition(position);
893                 
894                 wxSize size;
895                 config.Read(wxT("size.x"), &size.x, 340);
896                 config.Read(wxT("size.y"), &size.y, 460);
897                 this->SetSize(size);
898
899                 m_notebook->AddPage(new anago_panel_dump(m_notebook, r, &m_status, &config, m_log), wxT("dump"), false);
900
901                 m_panel_program = new anago_panel_program(m_notebook, r, &m_status, &config, m_log);
902                 m_notebook->AddPage(m_panel_program, wxT("program"), false);
903
904                 m_notebook->AddPage(new anago_panel_workram(m_notebook, r, &m_status, &config, m_log), wxT("workram"), false);
905                 m_notebook->AddPage(new anago_panel_version(m_notebook), wxT("version"), false);
906
907 #ifdef WIN32
908                 SetIcon(wxIcon(wxT("unagi_blue")));
909 #else
910                 #include "unagi_blue.xpm"
911                 SetIcon(wxIcon(unagi_blue));
912 #endif
913         }
914
915         virtual ~anago_frame(void)
916         {
917                 wxFileConfig config(wxEmptyString, wxEmptyString, m_config_file);
918                 wxPoint position = this->GetPosition();
919                 
920                 config.Write(wxT("position.x"), position.x);
921                 config.Write(wxT("position.y"), position.y);
922
923                 wxSize size = this->GetSize();
924                 config.Write(wxT("size.x"), size.x);
925                 config.Write(wxT("size.y"), size.y);
926                 
927                 m_panel_program->ConfigWrite(&config);
928         }
929 };
930
931 #ifndef WIN32
932 extern "C"{
933   int anago_cui(int c, wxChar **v);
934 }
935 int main(int c, wxChar **v)
936 {
937         if(c < 3){
938                 return wxEntry(c, v);
939         }
940         return anago_cui(c, v);
941 }
942 #endif
943
944 class MyApp : public wxApp
945 {
946 private:
947         anago_frame *m_frame;
948 public: 
949         bool OnInit()
950         {
951                 if(this->argc >= 2){
952                         m_frame = new anago_frame(NULL, &DRIVER_DUMMY);
953                 }else{
954                         m_frame = new anago_frame(NULL, &DRIVER_KAZZO);
955                 }
956                 m_frame->Show();
957                 
958                 return true;
959         }
960 };
961 #ifdef WIN32
962 IMPLEMENT_APP(MyApp)
963 #else
964 IMPLEMENT_APP_NO_MAIN(MyApp)
965 #endif