6 #include <wx/fileconf.h>
7 #include <wx/filename.h>
11 #include "anago_gui.h"
12 #include "nescartxml.hh"
14 #include "reader_master.h"
15 #include "reader_kazzo.h"
16 #include "reader_dummy.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);
25 #define STRNCPY wcsncpy
27 #define STRNCPY strncpy
29 //---- C++ -> C -> C++ wrapping static functions ----
31 static void throw_error(const wxChar *t)
36 static void value_set(void *gauge, void *label, int value)
38 wxGauge *g = static_cast<wxGauge *>(gauge);
39 wxStaticText *l = static_cast<wxStaticText *>(label);
41 if(g->GetRange() == 1){
44 str.Printf(wxT("0x%06x/0x%06x"), value, g->GetRange());
55 static void value_add(void *gauge, void *label, int value)
57 wxGauge *g = static_cast<wxGauge *>(gauge);
58 value += g->GetValue();
60 value_set(gauge, label, value);
63 static void range_set(void *gauge, int value)
65 wxGauge *g = static_cast<wxGauge *>(gauge);
72 static void text_append_va(void *log, const wxChar *format, va_list list)
74 wxTextCtrl *l = static_cast<wxTextCtrl *>(log);
76 str.PrintfV(format, list);
83 static void text_append(void *log, const wxChar *format, ...)
86 va_start(list, format);
87 text_append_va(log, format, list);
91 static void version_append_va(void *log, const wxChar *format, va_list list)
93 wxTextCtrl *l = static_cast<wxTextCtrl *>(log);
95 str.PrintfV(format, list);
100 static void version_append(void *log, const wxChar *format, ...)
103 va_start(list, format);
104 version_append_va(log, format, list);
108 static void label_set(void *label, const wxChar *format, ...)
110 wxStaticText *l = static_cast<wxStaticText *>(label);
114 va_start(list, format);
115 str.PrintfV(format, list);
123 static void choice_append(void *choice, const wxChar *str)
125 wxChoice *c = static_cast<wxChoice *>(choice);
126 c->Append(wxString(str));
129 static void gauge_init(struct gauge *t)
131 t->label_set = label_set;
132 t->range_set = range_set;
133 t->value_set = value_set;
134 t->value_add = value_add;
138 //---- script execute thread ----
139 class anago_dumper : public wxThread
142 wxWindow *const m_frame;
143 wxTextCtrl *const m_log;
144 const wxSound m_sound_success, m_sound_fail;
145 RomDb *const m_romdb;
147 struct dump_config m_config;
153 switch(m_config.mode){
155 r = script_dump_execute(&m_config);
157 case MODE_RAM_READ: case MODE_RAM_WRITE:
158 r = script_workram_execute(&m_config);
164 if(r == true && m_sound_success.IsOk() == true){
165 m_sound_success.Play();
167 }catch(const wxChar *t){
168 if(m_sound_fail.IsOk() == true){
174 m_romdb->Search(m_config.crc, m_log);
183 delete [] m_config.script;
184 delete [] m_config.target;
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),
192 m_config = *d; //struct data copy
196 class anago_programmer : public wxThread
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;
207 if(script_program_execute(&m_config) == true){
208 if(m_sound_success.IsOk() == true){
209 m_sound_success.Play();
212 }catch(const wxChar *t){
213 if(m_sound_fail.IsOk() == true){
226 delete [] m_config.script;
227 delete [] m_config.target;
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)
238 static void script_choice_init(wxControlWithItems *c, wxArrayString filespec, wxTextCtrl *log)
240 wxDir dir(wxGetCwd());
244 if ( !dir.IsOpened() ){
247 for(size_t i = 0; i < filespec.GetCount(); i++){
249 bool cont = dir.GetFirst(&filename, filespec[i], wxDIR_FILES);
252 cont = dir.GetNext(&filename);
255 if(ar.GetCount() == 0){
256 *log << wxT("warning: ");
257 for(size_t i = 0; i < filespec.GetCount(); i++){
258 *log << filespec[i] << wxT(" ");
260 *log << wxT("script not found.\n");
263 for(size_t i = 0; i < ar.GetCount(); i++){
270 static void increase_init(wxControlWithItems *c)
273 c->Append(wxT("x1"));
274 c->Append(wxT("x2"));
275 c->Append(wxT("x4"));
279 static int increase_get(wxControlWithItems *c)
281 switch(c->GetSelection()){
285 case 3: return INCREASE_AUTO;
291 STATUS_IDLE, STATUS_DUMPPING, STATUS_PROGRAMMING,
292 STATUS_RAM_READ, STATUS_RAM_WRITE
295 class anago_panel_dump : public panel_dump
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;
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);
314 config.ppu.gauge.bar = m_ppu_gauge;
315 config.ppu.gauge.label = m_ppu_value;
316 c_wrapper::gauge_init(&config.ppu.gauge);
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();
327 wxString str_script = m_script_choice->GetStringSelection();
328 wxChar *t = new wxChar[str_script.Length() + 1];
330 STRNCPY(t, str_script.c_str(), str_script.Length() + 1);
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");
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");
354 STRNCPY(t, str_rom.c_str(), str_rom.Length() + 1);
357 config.control = &m_reader->control;
358 config.cpu.access = &m_reader->cpu;
359 config.ppu.access = &m_reader->ppu;
363 /* if(m_anago_thread != NULL){ //???
364 delete m_anago_thread;
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");
372 *m_status = STATUS_DUMPPING;
376 void button_click(wxCommandEvent& event)
382 case STATUS_DUMPPING:
383 m_anago_thread->Kill();
386 default: //do nothing
391 void mapper_change_check(wxCommandEvent& event)
393 if(m_check_forcemapper->GetValue() == true){
394 m_text_forcemapper->Enable();
396 m_text_forcemapper->Disable();
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)
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);
409 *log << wxT("m_database not found\n");
410 m_romdb = new RomDb();
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"));
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);
427 m_romimage_picker->GetTextCtrl()->SetLabel(wxT("t.nes"));
430 virtual ~anago_panel_dump(void)
434 bool Enable(bool t = true)
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);
443 *m_status = STATUS_IDLE;
444 m_button->SetLabel(wxT("&dump"));
445 if(m_check_forcemapper->GetValue() == true){
446 m_text_forcemapper->Enable();
449 m_button->SetLabel(wxT("cancel"));
450 m_check_forcemapper->Disable();
452 m_button->SetFocus();
457 return this->Enable(false);
461 class anago_panel_program : public panel_program
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;
470 void padding_init(wxControlWithItems *c)
473 c->Append(wxT("full"));
474 c->Append(wxT("top"));
475 c->Append(wxT("bottom"));
476 c->Append(wxT("empty"));
479 bool rom_set(wxString device, int trans, struct memory *m, struct flash_device *f)
482 if(flash_device_get(device, f) == false){
483 *m_log << wxT("unknown flash memory device ");
484 *m_log << device << wxT("\n");
489 m->transtype = TRANSTYPE_FULL;
492 m->transtype = TRANSTYPE_TOP;
495 m->transtype = TRANSTYPE_BOTTOM;
498 m->transtype = TRANSTYPE_EMPTY;
506 struct program_config f;
508 f.cpu.gauge.bar = m_cpu_gauge;
509 f.cpu.gauge.label = m_cpu_value;
510 c_wrapper::gauge_init(&f.cpu.gauge);
512 f.ppu.gauge.bar = m_ppu_gauge;
513 f.ppu.gauge.label = m_ppu_value;
514 c_wrapper::gauge_init(&f.ppu.gauge);
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;
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);
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");
535 wxChar *t = new wxChar[str_rom.Length() + 1];
536 STRNCPY(t, str_rom.c_str(), str_rom.Length() + 1);
539 f.compare = m_compare->GetValue();
542 m_cpu_device->GetStringSelection(),
543 m_cpu_padding->GetSelection(),
544 &f.cpu.memory, &f.cpu.flash
549 m_ppu_device->GetStringSelection(),
550 m_ppu_padding->GetSelection(),
551 &f.ppu.memory, &f.ppu.flash
556 f.control = &m_reader->control;
557 f.cpu.access = &m_reader->cpu;
558 f.ppu.access = &m_reader->ppu;
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");
568 *m_status = STATUS_PROGRAMMING;
572 void device_load(wxControlWithItems *choice, wxFileConfig *c, wxString key)
576 c->Read(key, &device);
577 val = choice->FindString(device);
578 if(val == wxNOT_FOUND){
585 void button_click(wxCommandEvent& event)
591 case STATUS_PROGRAMMING:
592 m_anago_thread->Kill();
595 default: //do nothing
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)
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"));
609 script_choice_init(m_script_choice, t, m_log);
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);
618 if(m_cpu_device->GetCount() == 0){
619 *m_log << wxT("warning: flash device parameter not found\n");
621 device_load(m_cpu_device, config, wxT("program.cpu.device"));
622 device_load(m_ppu_device, config, wxT("program.ppu.device"));
624 this->padding_init(m_cpu_padding);
625 this->padding_init(m_ppu_padding);
627 m_anago_thread = NULL;
629 bool Enable(bool t = true)
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);
639 *m_status = STATUS_IDLE;
640 m_button->SetLabel(wxT("&program"));
642 m_button->SetLabel(wxT("cancel"));
644 m_button->SetFocus();
649 return this->Enable(false);
651 void ConfigWrite(wxFileConfig *c)
653 c->Write(wxT("program.cpu.device"), m_cpu_device->GetStringSelection());
654 c->Write(wxT("program.ppu.device"), m_ppu_device->GetStringSelection());
658 class anago_panel_workram : public panel_workram
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;
667 void execute(struct dump_config *c, wxControlWithItems *script, wxFilePickerCtrl *picker, enum anago_status status)
669 c->cpu.gauge.label = NULL;
670 c_wrapper::gauge_init(&c->cpu.gauge);
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);
679 wxString str_script = script->GetStringSelection();
680 wxChar *t = new wxChar[str_script.Length() + 1];
682 STRNCPY(t, str_script.c_str(), str_script.Length() + 1);
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");
693 STRNCPY(t, str_rom.c_str(), str_rom.Length() + 1);
695 c->control = &m_reader->control;
696 c->cpu.access = &m_reader->cpu;
697 c->ppu.access = &m_reader->ppu;
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");
705 *m_status = status; //先に status を設定すること
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);
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);
727 void read_button_click(wxCommandEvent& event)
733 case STATUS_RAM_READ:
736 default: //do nothing
741 void write_button_click(wxCommandEvent& event)
747 case STATUS_RAM_WRITE:
750 default: //do nothing
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)
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"));
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);
770 m_read_picker->GetTextCtrl()->SetLabel(wxT("t.sav"));
774 bool Enable(bool t = true)
776 m_read_script->Enable(t);
777 m_read_picker->Enable(t);
778 m_write_script->Enable(t);
779 m_write_picker->Enable(t);
782 case STATUS_RAM_READ:
783 m_read_button->SetLabel(wxT("&read"));
784 m_read_button->SetFocus();
785 m_write_button->Enable();
787 case STATUS_RAM_WRITE:
788 m_write_button->SetLabel(wxT("&write"));
789 m_write_button->SetFocus();
790 m_read_button->Enable();
795 *m_status = STATUS_IDLE;
798 case STATUS_RAM_READ:
799 m_read_button->SetLabel(wxT("&cancel"));
800 m_write_button->Disable();
802 case STATUS_RAM_WRITE:
803 m_write_button->SetLabel(wxT("&cancel"));
804 m_read_button->Disable();
815 return this->Enable(false);
819 class anago_panel_version : public panel_version
822 anago_panel_version(wxWindow *p) : panel_version(p)
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");
837 wxBitmap bitmap_okada(okada);
838 wxString tooltip(wxT(
839 "緑区 na6ko 町さん (28歳, 童貞)\n\n"
841 "28年間バカにされっぱなし、ミジメ過ぎた俺の人生が anago,\n"
842 "kazzo を持つようになった途端、突然ツキがめぐってきた。\n"
843 // "競馬をやれば連戦連勝、夢にまでみた万馬券を当て、気がつくと\n"
844 // "しんじられない事にギャンブルで稼いだお金が460万円!!\n"
845 "元手はたった4000円。しかもたった2ヶ月で人生大逆転!!\n"
847 // "勤めていた新聞屋も辞めギャンブルで\n"
848 // "身を立てていこうと思っています。実は来月の11日にラスベガスに\n"
849 // "行き勝負をかけます。結果はまた報告します。宜しく。"
853 wxBitmap bitmap_okada(slyly);
854 wxString tooltip(wxT("CARP ピロ"));
856 // #include "araki.xpm"
857 // wxBitmap bitmap_okada(araki);
858 m_version_photo->SetBitmap(bitmap_okada);
859 m_version_photo->SetToolTip(tooltip);
863 //---- main frame class ----
864 class anago_frame : public frame_main
867 enum anago_status m_status; //ここだけ実体, 各パネルはこのポインタ
868 const wxString m_config_file;
869 anago_panel_program *m_panel_program;
871 void menu_log_clean(wxCommandEvent& event)
878 anago_frame(wxWindow* parent, const struct reader_driver *r)
879 : frame_main(parent), m_status(STATUS_IDLE),
881 m_config_file(wxGetCwd() + wxT("/anago.cfg"))
883 m_config_file(wxT(".anago"))
886 wxFileConfig config(wxEmptyString, wxEmptyString, m_config_file);
890 config.Read(wxT("position.x"), &position.x, 32);
891 config.Read(wxT("position.y"), &position.y, 32);
892 this->SetPosition(position);
895 config.Read(wxT("size.x"), &size.x, 340);
896 config.Read(wxT("size.y"), &size.y, 460);
899 m_notebook->AddPage(new anago_panel_dump(m_notebook, r, &m_status, &config, m_log), wxT("dump"), false);
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);
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);
908 SetIcon(wxIcon(wxT("unagi_blue")));
910 #include "unagi_blue.xpm"
911 SetIcon(wxIcon(unagi_blue));
915 virtual ~anago_frame(void)
917 wxFileConfig config(wxEmptyString, wxEmptyString, m_config_file);
918 wxPoint position = this->GetPosition();
920 config.Write(wxT("position.x"), position.x);
921 config.Write(wxT("position.y"), position.y);
923 wxSize size = this->GetSize();
924 config.Write(wxT("size.x"), size.x);
925 config.Write(wxT("size.y"), size.y);
927 m_panel_program->ConfigWrite(&config);
933 int anago_cui(int c, wxChar **v);
935 int main(int c, wxChar **v)
938 return wxEntry(c, v);
940 return anago_cui(c, v);
944 class MyApp : public wxApp
947 anago_frame *m_frame;
952 m_frame = new anago_frame(NULL, &DRIVER_DUMMY);
954 m_frame = new anago_frame(NULL, &DRIVER_KAZZO);
964 IMPLEMENT_APP_NO_MAIN(MyApp)