OSDN Git Service

skip 表示を修正, squirrel の呼び出しバグを修正
[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 <cstdarg>
8 #include "type.h"
9 #include "anago_gui.h"
10 #include "widget.h"
11 #include "reader_master.h"
12 #include "reader_kazzo.h"
13 extern "C"{
14   #include "romimage.h"
15   #include "flash_device.h"
16   #include "script_dump.h"
17   #include "script_program.h"
18   void qr_version_print(const struct textcontrol *l);
19 }
20 #if DEBUG==1
21 extern const struct reader_driver DRIVER_DUMMY;
22 #endif
23 #ifdef _UNICODE
24   #define STRNCPY wcsncpy
25 #else
26   #define STRNCPY strncpy
27 #endif
28 //---- C++ -> C -> C++ wrapping functions ----
29 static void throw_error(const wxChar *t)
30 {
31         throw t;
32 }
33
34 static void value_set(void *gauge, void *label, int value)
35 {
36         wxGauge *g = static_cast<wxGauge *>(gauge);
37         wxStaticText *l = static_cast<wxStaticText *>(label);
38         wxString str;
39         if(g->GetRange() == 1){
40                 str = wxT("skip             ");
41         }else{
42                 str.Printf(wxT("0x%06x/0x%06x"), value, g->GetRange());
43         }
44         
45         wxMutexGuiEnter();
46         g->SetValue(value);
47         l->SetLabel(str);
48         wxMutexGuiLeave();
49 }
50
51 static void value_add(void *gauge, void *label, int value)
52 {
53         wxGauge *g = static_cast<wxGauge *>(gauge);
54         value += g->GetValue();
55         
56         value_set(gauge, label, value);
57 }
58
59 static void range_set(void *gauge, int value)
60 {
61         wxGauge *g = static_cast<wxGauge *>(gauge);
62         if(value == 0){
63                 value = 1;
64         }
65         g->SetRange(value);
66 }
67
68 static void text_append_va(void *log, const wxChar *format, va_list list)
69 {
70         wxTextCtrl *l = static_cast<wxTextCtrl *>(log);
71         wxString str;
72         str.PrintfV(format, list);
73
74         wxMutexGuiEnter();
75         *l << str;
76         wxMutexGuiLeave();
77 }
78
79 static void text_append(void *log, const wxChar *format, ...)
80 {
81         va_list list;
82         va_start(list, format);
83         text_append_va(log, format, list);
84         va_end(list);
85 }
86
87 static void version_append_va(void *log, const wxChar *format, va_list list)
88 {
89         wxTextCtrl *l = static_cast<wxTextCtrl *>(log);
90         wxString str;
91         str.PrintfV(format, list);
92
93         *l << str;
94 }
95
96 static void version_append(void *log, const wxChar *format, ...)
97 {
98         va_list list;
99         va_start(list, format);
100         version_append_va(log, format, list);
101         va_end(list);
102 }
103
104 static void label_set(void *label, const wxChar *format, ...)
105 {
106         wxStaticText *l = static_cast<wxStaticText *>(label);
107         wxString str;
108         va_list list;
109         
110         va_start(list, format);
111         str.PrintfV(format, list);
112         va_end(list);
113
114         wxMutexGuiEnter();
115         l->SetLabel(str);
116         wxMutexGuiLeave();
117 }
118
119 void choice_append(void *choice, const wxChar *str)
120 {
121         wxChoice *c = static_cast<wxChoice *>(choice);
122         c->Append(wxString(str));
123 }
124
125 //---- script execute thread ----
126 class anago_frame;
127
128 class anago_dumper : public wxThread
129 {
130 private:
131         anago_frame *m_frame;
132         struct dump_config m_config;
133         const wxSound m_sound_success, m_sound_fail;
134 protected:
135         void *Entry(void);
136         void OnExit()
137         {
138                 delete [] m_config.script;
139                 delete [] m_config.target;
140         }
141 public:
142         anago_dumper(anago_frame *f, const struct dump_config *d, wxString sound_success, wxString sound_fail) 
143           : wxThread(), m_sound_success(sound_success), m_sound_fail(sound_fail)
144         {
145                 m_frame = f;
146                 m_config = *d; //struct data copy
147         }
148 };
149
150 class anago_programmer : public wxThread
151 {
152 private:
153         anago_frame *m_frame;
154         struct program_config m_config;
155         const wxSound m_sound_success, m_sound_fail;
156 protected:
157         void *Entry(void);
158         void OnExit()
159         {
160                 delete [] m_config.script;
161                 delete [] m_config.target;
162         }
163 public:
164         anago_programmer(anago_frame *f, const struct program_config *d, wxString sound_success, wxString sound_fail) 
165           : wxThread(), m_sound_success(sound_success), m_sound_fail(sound_fail)
166         {
167                 m_frame = f;
168                 m_config = *d;
169         }
170 };
171
172 //---- main frame class ----
173 class anago_frame : public frame_main
174 {
175 private:
176         wxThread *m_anago_thread;
177         const wxString m_config_file;
178         const struct reader_driver *m_reader;
179         wxString m_dump_sound_success, m_dump_sound_fail;
180         wxString m_program_sound_success, m_program_sound_fail;
181         enum{
182                 STATUS_IDLE, STATUS_DUMPPING, STATUS_PROGRAMMING
183         }m_status;
184         
185         void gauge_init(struct gauge *t)
186         {
187                 t->label_set = label_set;
188                 t->range_set = range_set;
189                 t->value_set = value_set;
190                 t->value_add = value_add;
191         }
192         void script_choice_init(wxChoice *c, wxString filespec)
193         {
194                 wxDir dir(wxGetCwd());
195                 wxString filename;
196
197                 c->Clear();
198                 if ( !dir.IsOpened() ){
199                         return;
200                 }
201                 bool cont = dir.GetFirst(&filename, filespec, wxDIR_FILES);
202                 while ( cont ){
203                         c->Append(filename);
204                         cont = dir.GetNext(&filename);
205                 }
206                 if(c->GetCount() == 0){
207                         *m_log << wxT("warning: ") << filespec << wxT(" script not found.\n");
208                 }else{
209                         c->Select(0);
210                 }
211         }
212 //---- dump mode functions ----
213         void dump_increase_init(wxChoice *c)
214         {
215                 c->Clear();
216                 c->Append(wxT("x1"));
217                 c->Append(wxT("x2"));
218                 c->Append(wxT("x4"));
219                 c->Select(0);
220         }
221         int dump_increase_get(wxChoice *c)
222         {
223                 switch(c->GetSelection()){
224                 case 0: return 1;
225                 case 1: return 2;
226                 case 2: return 4;
227                 }
228                 return 1;
229         }
230         void dump_execute(void)
231         {
232                 struct dump_config config;
233                 config.cpu.gauge.bar = m_dump_cpu_gauge;
234                 config.cpu.gauge.label = m_dump_cpu_value;
235                 gauge_init(&config.cpu.gauge);
236
237                 config.ppu.gauge.bar = m_dump_ppu_gauge;
238                 config.ppu.gauge.label = m_dump_ppu_value;
239                 gauge_init(&config.ppu.gauge);
240                 
241                 config.log.object = m_log;
242                 config.log.append = text_append;
243                 config.log.append_va = text_append_va;
244                 config.except = throw_error;
245                 config.cpu.increase = dump_increase_get(m_dump_cpu_increase);
246                 config.ppu.increase = dump_increase_get(m_dump_ppu_increase);
247                 config.progress = true;
248                 config.battery = m_dump_check_battery->GetValue();
249                 {
250                         wxString str_script = m_dump_script_choice->GetStringSelection();
251                         wxChar *t = new wxChar[str_script.Length() + 1];
252                         config.script = t;
253                         STRNCPY(t, str_script.fn_str(), str_script.Length() + 1);
254                 }
255
256                 {
257                         wxString str;
258                         config.mappernum = -1;
259                         if(m_dump_check_forcemapper->GetValue() == true){
260                                 str = m_dump_text_forcemapper->GetValue();
261                                 if(str.ToLong(&config.mappernum) == false){
262                                         *m_log << wxT("bad mapper number\n");
263                                         return;
264                                 }
265                         }
266                 }
267
268                 {
269                         wxTextCtrl *text = m_dump_romimage_picker->GetTextCtrl();
270                         wxString str_rom = text->GetValue();
271                         wxChar *t = new wxChar[str_rom.Length() + 1];
272                         if(text->IsEmpty() == true){
273                                 *m_log << wxT("Enter filename to ROM image\n");
274                                 return;
275                         }
276                         config.target = t;
277                         STRNCPY(t, str_rom.fn_str(), str_rom.Length() + 1);
278                 }
279
280                 config.control = &m_reader->control;
281                 config.cpu.access = &m_reader->cpu;
282                 config.ppu.access = &m_reader->ppu;
283
284                 m_dump_script_choice->Disable();
285                 m_dump_romimage_picker->Disable();
286                 m_dump_check_battery->Disable();
287                 m_dump_check_forcemapper->Disable();
288                 m_dump_button->SetLabel(wxT("cancel"));
289                 m_dump_text_forcemapper->Disable();
290                 m_dump_cpu_increase->Disable();
291                 m_dump_ppu_increase->Disable();
292
293 /*              if(m_anago_thread != NULL){ //???
294                         delete m_anago_thread;
295                 }*/
296                 m_anago_thread = new anago_dumper(this, &config, m_dump_sound_success, m_dump_sound_fail);
297                 if(m_anago_thread->Create() != wxTHREAD_NO_ERROR){
298                         *m_log << wxT("thread creating error");
299                 }else if(m_anago_thread->Run() != wxTHREAD_NO_ERROR){
300                         *m_log << wxT("thread running error");
301                 }else{
302                         m_status = STATUS_DUMPPING;
303                 }
304         }
305         
306 //----- program mode functions ----
307         void program_padding_init(wxChoice *c)
308         {
309                 c->Clear();
310                 c->Append(wxT("full"));
311                 c->Append(wxT("top"));
312                 c->Append(wxT("bottom"));
313                 c->Append(wxT("empty"));
314                 c->Select(0);
315         }
316         bool program_rom_set(wxString device, int trans, struct memory *m, struct flash_device *f)
317         {
318                 m->offset = 0;
319                 if(flash_device_get(device, f) == false){
320                         *m_log << wxT("unknown flash memory device ");
321                         *m_log << device << wxT("\n");
322                         return false;
323                 }
324                 switch(trans){
325                 case 0: 
326                         m->transtype = TRANSTYPE_FULL;
327                         break;
328                 case 1: 
329                         m->transtype = TRANSTYPE_TOP;
330                         break;
331                 case 2: 
332                         m->transtype = TRANSTYPE_BOTTOM;
333                         break;
334                 default: 
335                         m->transtype = TRANSTYPE_EMPTY;
336                         break;
337                 }
338                 return true;
339         }
340
341         void program_execute(void)
342         {
343                 struct program_config f;
344                 
345                 f.cpu.gauge.bar = m_program_cpu_gauge;
346                 f.cpu.gauge.label = m_program_cpu_value;
347                 gauge_init(&f.cpu.gauge);
348
349                 f.ppu.gauge.bar = m_program_ppu_gauge;
350                 f.ppu.gauge.label = m_program_ppu_value;
351                 gauge_init(&f.ppu.gauge);
352                 
353                 f.log.object = m_log;
354                 f.log.append = text_append;
355                 f.log.append_va = text_append_va;
356                 f.except = throw_error;
357                 
358                 {
359                         wxString str_script = m_program_script_choice->GetStringSelection();
360                         wxChar *t = new wxChar[str_script.Length() + 1];
361                         STRNCPY(t, str_script.fn_str(), str_script.Length() + 1);
362                         f.script = t;
363                 }
364
365                 {
366                         wxTextCtrl *text = m_program_romimage_picker->GetTextCtrl();
367                         wxString str_rom = text->GetValue();
368                         if(text->IsEmpty() == true){
369                                 *m_log << wxT("Enter filename to ROM image\n");
370                                 return;
371                         }
372                         wxChar *t = new wxChar[str_rom.Length() + 1];
373                         STRNCPY(t, str_rom.fn_str(), str_rom.Length() + 1);
374                         f.target = t;
375                 }
376                 f.compare = m_program_compare->GetValue();
377                 f.testrun = false;
378
379                 if(program_rom_set(
380                         m_program_cpu_device->GetStringSelection(), 
381                         m_program_cpu_padding->GetSelection(),
382                         &f.cpu.memory, &f.cpu.flash
383                 ) == false){
384                         return;
385                 }
386                 if(program_rom_set(
387                         m_program_ppu_device->GetStringSelection(), 
388                         m_program_ppu_padding->GetSelection(),
389                         &f.ppu.memory, &f.ppu.flash
390                 ) == false){
391                         return;
392                 }
393
394                 f.control = &m_reader->control;
395                 f.cpu.access = &m_reader->cpu;
396                 f.ppu.access = &m_reader->ppu;
397
398                 m_program_script_choice->Disable();
399                 m_program_romimage_picker->Disable();
400                 m_program_compare->Disable();
401                 m_program_button->SetLabel(wxT("cancel"));
402                 m_program_cpu_padding->Disable();
403                 m_program_cpu_device->Disable();
404                 m_program_ppu_padding->Disable();
405                 m_program_ppu_device->Disable();
406                 m_program_compare->Disable();
407
408                 m_anago_thread = new anago_programmer(this, &f, m_program_sound_success, m_program_sound_fail);
409                 if(m_anago_thread->Create() != wxTHREAD_NO_ERROR){
410                         *m_log << wxT("thread creating error");
411                 }else if(m_anago_thread->Run() != wxTHREAD_NO_ERROR){
412                         *m_log << wxT("thread running error");
413                 }else{
414                         m_status = STATUS_PROGRAMMING;
415                 }
416         }
417
418 protected:
419         void dump_button_click(wxCommandEvent& event)
420         {
421                 switch(m_status){
422                 case STATUS_IDLE:
423                         this->dump_execute();
424                         break;
425                 case STATUS_DUMPPING:
426                         m_anago_thread->Kill();
427                         this->DumpThreadFinish();
428                         m_status = STATUS_IDLE;
429                         break;
430                 default: //do nothing
431                         break;
432                 }
433         }
434         void program_button_click(wxCommandEvent& event)
435         {
436                 switch(m_status){
437                 case STATUS_IDLE:
438                         this->program_execute();
439                         break;
440                 case STATUS_PROGRAMMING:
441                         m_anago_thread->Kill();
442                         this->ProgramThreadFinish();
443                         m_status = STATUS_IDLE;
444                         break;
445                 default: //do nothing
446                         break;
447                 }
448         }
449         void mapper_change_check(wxCommandEvent& event)
450         {
451                 if(m_dump_check_forcemapper->GetValue() == true){
452                         m_dump_text_forcemapper->Enable();
453                 }else{
454                         m_dump_text_forcemapper->Disable();
455                 }
456         }
457         void menu_log_clean(wxCommandEvent& event)
458         {
459                 m_log->Clear();
460         }
461 public:
462         /** Constructor */
463         anago_frame(wxWindow* parent, const struct reader_driver *r)
464           : frame_main(parent), 
465 #ifdef WIN32
466           m_config_file(wxGetCwd() + wxT("/anago.cfg"))
467 #else
468           m_config_file(wxT(".anago"))
469 #endif
470         {
471                 m_reader = r;
472 //form config load
473                 {
474                         wxFileConfig config(wxEmptyString, wxEmptyString, m_config_file);
475                         wxPoint position;
476                         
477                         config.Read(wxT("position.x"), &position.x, 32);
478                         config.Read(wxT("position.y"), &position.y, 32);
479                         this->SetPosition(position);
480                         
481                         wxSize size;
482                         config.Read(wxT("size.x"), &size.x, 340);
483                         config.Read(wxT("size.y"), &size.y, 460);
484                         this->SetSize(size);
485                         
486                         config.Read(wxT("program.sound.success"), &m_program_sound_success, wxT("cuckoo.wav"));
487                         config.Read(wxT("program.sound.fail"), &m_program_sound_fail, wxT("doggrowl.wav"));
488
489                         config.Read(wxT("dump.sound.success"), &m_dump_sound_success, wxT("tinkalink2.wav"));
490                         config.Read(wxT("dump.sound.fail"), &m_dump_sound_fail, wxT("doggrowl.wav"));
491                 }
492
493 //form item init
494                 this->script_choice_init(m_dump_script_choice, wxT("*.ad"));
495                 this->script_choice_init(m_program_script_choice, wxT("*.af"));
496                 this->dump_increase_init(m_dump_cpu_increase);
497                 this->dump_increase_init(m_dump_ppu_increase);
498
499                 {
500                         struct flash_listup list;
501                         list.obj_cpu = m_program_cpu_device;
502                         list.obj_ppu = m_program_ppu_device;
503                         list.append = choice_append;
504                         flash_device_listup(&list);
505                 }
506                 if(m_program_cpu_device->GetCount() == 0){
507                         *m_log << wxT("warning: flash device parameter not found\n");
508                 }else{
509                         m_program_cpu_device->Select(0);
510                         m_program_ppu_device->Select(0);
511                 }
512                 this->program_padding_init(m_program_cpu_padding);
513                 this->program_padding_init(m_program_ppu_padding);
514                 
515                 m_anago_thread = NULL;
516                 m_status = STATUS_IDLE;
517
518 //version infomation
519                 {
520                         struct textcontrol detail;
521                         *m_version_detail << wxT("anago build at ") << wxT(__DATE__) << wxT("\n\n");
522                         detail.object = m_version_detail;
523                         detail.append = version_append;
524                         detail.append_va = version_append_va;
525                         qr_version_print(&detail);
526                         *m_version_detail << wxVERSION_STRING << wxT(" (c) Julian Smar");
527                 }
528 #ifdef WIN32
529                 #include "okada.xpm"
530                 wxBitmap bitmap_okada(okada);
531                 wxString tooltip(wxT(
532                         "緑区 na6ko 町さん (28歳, 童貞)\n\n"
533
534                         "28年間バカにされっぱなし、ミジメ過ぎた俺の人生が anago,\n"
535                         "kazzo を持つようになった途端、突然ツキがめぐってきた。\n"
536 //                      "競馬をやれば連戦連勝、夢にまでみた万馬券を当て、気がつくと\n"
537 //                      "しんじられない事にギャンブルで稼いだお金が460万円!!\n"
538                         "元手はたった4000円。しかもたった2ヶ月で人生大逆転!!\n"
539                         "女は3P4Pヤリ放題!!"
540 //                      "勤めていた新聞屋も辞めギャンブルで\n"
541 //                      "身を立てていこうと思っています。実は来月の11日にラスベガスに\n"
542 //                      "行き勝負をかけます。結果はまた報告します。宜しく。"
543                 ));
544 #else
545                 #include "taiyo.xpm"
546                 wxBitmap bitmap_okada(taiyo);
547                 wxString tooltip(wxT("たいよ~ほえ~るず♪"));
548 #endif
549 //              #include "araki.xpm"
550 //              wxBitmap bitmap_okada(araki);
551                 m_version_photo->SetBitmap(bitmap_okada);
552                 m_version_photo->SetToolTip(tooltip);
553                 
554                 if(DEBUG==1){
555                         m_dump_romimage_picker->GetTextCtrl()->SetLabel(wxT("t.nes"));
556                 }
557         }
558
559         void DumpThreadFinish(void)
560         {
561                 m_dump_script_choice->Enable();
562                 m_dump_script_choice->SetFocus();
563                 m_dump_romimage_picker->Enable();
564                 m_dump_check_battery->Enable();
565                 m_dump_check_forcemapper->Enable();
566                 m_dump_cpu_increase->Enable();
567                 m_dump_ppu_increase->Enable();
568                 m_dump_button->SetLabel(wxT("&dump"));
569                 if(m_dump_check_forcemapper->GetValue() == true){
570                         m_dump_text_forcemapper->Enable();
571                 }
572                 m_status = STATUS_IDLE;
573         }
574         
575         void ProgramThreadFinish(void)
576         {
577                 m_program_script_choice->Enable();
578                 m_dump_script_choice->SetFocus();
579                 m_program_romimage_picker->Enable();
580                 m_program_compare->Enable();
581                 m_program_button->SetLabel(wxT("&program"));
582                 m_program_cpu_padding->Enable();
583                 m_program_cpu_device->Enable();
584                 m_program_ppu_padding->Enable();
585                 m_program_ppu_device->Enable();
586                 m_status = STATUS_IDLE;
587         }
588         void LogAppend(const wxChar *t)
589         {
590                 *m_log << t;
591         }
592         virtual ~anago_frame(void)
593         {
594                 wxFileConfig config(wxEmptyString, wxEmptyString, m_config_file);
595                 wxPoint position = this->GetPosition();
596                 
597                 config.Write(wxT("position.x"), position.x);
598                 config.Write(wxT("position.y"), position.y);
599
600                 wxSize size = this->GetSize();
601                 config.Write(wxT("size.x"), size.x);
602                 config.Write(wxT("size.y"), size.y);
603         }
604 };
605
606
607 void *anago_dumper::Entry(void)
608 {
609         try{
610                 if(script_dump_execute(&m_config) == true){
611                         if(m_sound_success.IsOk() == true){
612                                 m_sound_success.Play();
613                         }
614                 }
615         }catch(const wxChar *t){
616                 if(m_sound_fail.IsOk() == true){
617                         m_sound_fail.Play();
618                 }
619                 m_frame->LogAppend(t);
620         }
621         m_frame->DumpThreadFinish();
622         return NULL;
623 }
624
625 void *anago_programmer::Entry(void)
626 {
627         try{
628                 if(script_program_execute(&m_config) == true){
629                         if(m_sound_success.IsOk() == true){
630                                 m_sound_success.Play();
631                         }
632                 }
633         }catch(const wxChar *t){
634                 if(m_sound_fail.IsOk() == true){
635                         m_sound_fail.Play();
636                 }
637                 m_frame->LogAppend(t);
638         }
639         m_frame->ProgramThreadFinish();
640         return NULL;
641 }
642
643 #ifndef WIN32
644 extern "C"{
645   int anago_cui(int c, wxChar **v);
646 }
647 int main(int c, wxChar **v)
648 {
649         if(c < 2){
650                 return wxEntry(c, v);
651         }
652         return anago_cui(c, v);
653 }
654 #endif
655
656 class MyApp : public wxApp
657 {
658 private:
659         anago_frame *m_frame;
660 public: 
661         bool OnInit()
662         {
663                 if(DEBUG== 1 && this->argc >= 2){
664                         m_frame = new anago_frame(NULL, &DRIVER_DUMMY);
665                 }else{
666                         m_frame = new anago_frame(NULL, &DRIVER_KAZZO);
667                 }
668                 m_frame->Show();
669                 
670                 return true;
671         }
672 };
673 #ifdef WIN32
674 IMPLEMENT_APP(MyApp)
675 #else
676 IMPLEMENT_APP_NO_MAIN(MyApp)
677 #endif