OSDN Git Service

DB ファイル名を変更
[unagi/old-svn-converted.git] / client / trunk / anago / anago_frame.cpp
index a1b99a7..bb4b51c 100644 (file)
 #include <wx/wx.h>
-#include <wx/log.h>
-#include <wx/dir.h>
-#include <wx/thread.h>
 #include <wx/app.h>
-#include <cstring>
+#include <wx/thread.h>
+#include <wx/dir.h>
+#include <wx/sound.h>
+#include <wx/fileconf.h>
+#include <wx/filename.h>
+#include <cassert>
 #include <cstdarg>
+#include "type.h"
 #include "anago_gui.h"
+#include "nescartxml.hh"
 #include "widget.h"
 #include "reader_master.h"
-//#include "reader_kazzo.h"
-extern const struct reader_driver DRIVER_KAZZO;
+#include "reader_kazzo.h"
+#include "reader_dummy.h"
 extern "C"{
-#include "header.h"
-#include "flash_device.h"
-#include "script_dump.h"
-#include "script_program.h"
-void qr_version_print(const struct textcontrol *l);
+  #include "romimage.h"
+  #include "flash_device.h"
+  #include "script_dump.h"
+  #include "script_program.h"
+  void qr_version_print(const struct textcontrol *l);
 }
+#ifdef _UNICODE
+  #define STRNCPY wcsncpy
+#else
+  #define STRNCPY strncpy
+#endif
+//---- C++ -> C -> C++ wrapping static functions ----
+namespace c_wrapper{
+       static void throw_error(const wxChar *t)
+       {
+               throw t;
+       }
 
-//---- C++ -> C -> C++ wrapping functions ----
-static void value_set(void *gauge, void *label, int value)
-{
-       wxGauge *g = static_cast<wxGauge *>(gauge);
-       wxStaticText *l = static_cast<wxStaticText *>(label);
-       wxString str;
-       str.Printf(wxT("0x%06x/0x%06x"), value, g->GetRange());
-       
-       wxMutexGuiEnter();
-       g->SetValue(value);
-       l->SetLabel(str);
-       wxMutexGuiLeave();
-}
+       static void value_set(void *gauge, void *label, int value)
+       {
+               wxGauge *g = static_cast<wxGauge *>(gauge);
+               wxStaticText *l = static_cast<wxStaticText *>(label);
+               wxString str;
+               if(g->GetRange() == 1){
+                       str = wxT("skip             ");
+               }else{
+                       str.Printf(wxT("0x%06x/0x%06x"), value, g->GetRange());
+               }
+               
+               wxMutexGuiEnter();
+               g->SetValue(value);
+               if(label != NULL){
+                       l->SetLabel(str);
+               }
+               wxMutexGuiLeave();
+       }
 
-static void value_add(void *gauge, void *label, int value)
-{
-       wxGauge *g = static_cast<wxGauge *>(gauge);
-       value += g->GetValue();
-       
-       value_set(gauge, label, value);
-}
+       static void value_add(void *gauge, void *label, int value)
+       {
+               wxGauge *g = static_cast<wxGauge *>(gauge);
+               value += g->GetValue();
+               
+               value_set(gauge, label, value);
+       }
 
-static void range_set(void *gauge, int value)
-{
-       wxGauge *g = static_cast<wxGauge *>(gauge);
-       if(value == 0){
-               value = 1;
+       static void range_set(void *gauge, int value)
+       {
+               wxGauge *g = static_cast<wxGauge *>(gauge);
+               if(value == 0){
+                       value = 1;
+               }
+               g->SetRange(value);
        }
-       g->SetRange(value);
-}
 
-static void text_append_va(void *log, const char *format, va_list list)
-{
-       wxTextCtrl *l = static_cast<wxTextCtrl *>(log);
-       wxString str;
-       str.PrintfV(format, list);
+       static void text_append_va(void *log, const wxChar *format, va_list list)
+       {
+               wxTextCtrl *l = static_cast<wxTextCtrl *>(log);
+               wxString str;
+               str.PrintfV(format, list);
 
-       wxMutexGuiEnter();
-       *l << str;
-       wxMutexGuiLeave();
-}
+               wxMutexGuiEnter();
+               *l << str;
+               wxMutexGuiLeave();
+       }
 
-static void text_append(void *log, const char *format, ...)
-{
-       va_list list;
-       va_start(list, format);
-       text_append_va(log, format, list);
-       va_end(list);
-}
+       static void text_append(void *log, const wxChar *format, ...)
+       {
+               va_list list;
+               va_start(list, format);
+               text_append_va(log, format, list);
+               va_end(list);
+       }
 
-static void version_append_va(void *log, const char *format, va_list list)
-{
-       wxTextCtrl *l = static_cast<wxTextCtrl *>(log);
-       wxString str;
-       str.PrintfV(format, list);
+       static void version_append_va(void *log, const wxChar *format, va_list list)
+       {
+               wxTextCtrl *l = static_cast<wxTextCtrl *>(log);
+               wxString str;
+               str.PrintfV(format, list);
 
-       *l << str;
-}
+               *l << str;
+       }
 
-static void version_append(void *log, const char *format, ...)
-{
-       va_list list;
-       va_start(list, format);
-       version_append_va(log, format, list);
-       va_end(list);
-}
+       static void version_append(void *log, const wxChar *format, ...)
+       {
+               va_list list;
+               va_start(list, format);
+               version_append_va(log, format, list);
+               va_end(list);
+       }
 
-static void label_set(void *label, const char *format, ...)
-{
-       wxStaticText *l = static_cast<wxStaticText *>(label);
-       wxString str;
-       va_list list;
-       
-       va_start(list, format);
-       str.PrintfV(format, list);
-       va_end(list);
+       static void label_set(void *label, const wxChar *format, ...)
+       {
+               wxStaticText *l = static_cast<wxStaticText *>(label);
+               wxString str;
+               va_list list;
+               
+               va_start(list, format);
+               str.PrintfV(format, list);
+               va_end(list);
 
-       wxMutexGuiEnter();
-       l->SetLabel(str);
-       wxMutexGuiLeave();
-}
+               wxMutexGuiEnter();
+               l->SetLabel(str);
+               wxMutexGuiLeave();
+       }
 
-void choice_append(void *choice, const char *str)
-{
-       wxChoice *c = static_cast<wxChoice *>(choice);
-       c->Append(wxString(str));
+       static void choice_append(void *choice, const wxChar *str)
+       {
+               wxChoice *c = static_cast<wxChoice *>(choice);
+               c->Append(wxString(str));
+       }
+
+       static void gauge_init(struct gauge *t)
+       {
+               t->label_set = label_set;
+               t->range_set = range_set;
+               t->value_set = value_set;
+               t->value_add = value_add;
+       }
 }
 
 //---- script execute thread ----
-class anago_frame;
 class anago_dumper : public wxThread
 {
 private:
-       anago_frame *m_frame;
+       wxWindow *const m_frame;
+       wxTextCtrl *const m_log;
+       const wxSound m_sound_success, m_sound_fail;
+       RomDb *const m_romdb;
+
        struct dump_config m_config;
 protected:
-       void *Entry(void);
+       void *Entry(void)
+       {
+               try{
+                       bool r = false;
+                       switch(m_config.mode){
+                       case MODE_ROM_DUMP:
+                               r = script_dump_execute(&m_config);
+                               break;
+                       case MODE_RAM_READ: case MODE_RAM_WRITE:
+                               r = script_workram_execute(&m_config);
+                               break;
+                       default:
+                               assert(0);
+                               break;
+                       }
+                       if(r == true && m_sound_success.IsOk() == true){
+                               m_sound_success.Play();
+                       }
+               }catch(const wxChar *t){
+                       if(m_sound_fail.IsOk() == true){
+                               m_sound_fail.Play();
+                       }
+                       *m_log << t;
+               }
+               if(m_romdb != NULL){
+                       m_romdb->Search(m_config.crc, m_log);
+               }
+               wxMutexGuiEnter();
+               m_frame->Enable();
+               wxMutexGuiLeave();
+               return NULL;
+       }
        void OnExit()
        {
                delete [] m_config.script;
                delete [] m_config.target;
        }
 public:
-       anago_dumper(anago_frame *f, const struct dump_config *d) : wxThread()
+       anago_dumper(wxWindow *f, const struct dump_config *d, wxTextCtrl *log, wxString sound_success, wxString sound_fail, RomDb *db = NULL) 
+         : wxThread(), m_frame(f), m_log(log), 
+         m_sound_success(sound_success), m_sound_fail(sound_fail),
+         m_romdb(db)
        {
-               m_frame = f;
-               memcpy(&m_config, d, sizeof(struct dump_config));
+               m_config = *d; //struct data copy
        }
 };
 
 class anago_programmer : public wxThread
 {
 private:
-       anago_frame *m_frame;
+       wxWindow *const m_frame;
+       wxTextCtrl *const m_log;
        struct program_config m_config;
+       const wxSound m_sound_success, m_sound_fail;
 protected:
-       void *Entry(void);
+       void *Entry(void)
+       {
+               try{
+                       if(script_program_execute(&m_config) == true){
+                               if(m_sound_success.IsOk() == true){
+                                       m_sound_success.Play();
+                               }
+                       }
+               }catch(const wxChar *t){
+                       if(m_sound_fail.IsOk() == true){
+                               m_sound_fail.Play();
+                       }
+                       *m_log << t;
+               }
+               wxMutexGuiEnter();
+               m_frame->Enable();
+               wxMutexGuiLeave();
+               return NULL;
+       }
+
        void OnExit()
        {
                delete [] m_config.script;
                delete [] m_config.target;
        }
 public:
-       anago_programmer(anago_frame *f, const struct program_config *d) : wxThread()
+       anago_programmer(wxWindow *f, wxTextCtrl *log, const struct program_config *d, wxString sound_success, wxString sound_fail) 
+         : wxThread(), m_frame(f), m_log(log),
+         m_sound_success(sound_success), m_sound_fail(sound_fail)
        {
-               m_frame = f;
-               memcpy(&m_config, d, sizeof(struct program_config));
+               m_config = *d;
        }
 };
 
-//---- main frame class ----
-class anago_frame : public frame_main
+static void script_choice_init(wxControlWithItems *c, wxArrayString filespec, wxTextCtrl *log)
 {
-private:
-       wxThread *m_anago_thread;
-       enum{
-               STATUS_IDLE, STATUS_DUMPPING, STATUS_PROGRAMMING
-       }m_status;
-       void gauge_init(struct gauge *t)
-       {
-               t->label_set = label_set;
-               t->range_set = range_set;
-               t->value_set = value_set;
-               t->value_add = value_add;
+       wxDir dir(wxGetCwd());
+       wxArrayString ar;
+
+       c->Clear();
+       if ( !dir.IsOpened() ){
+               return;
        }
-       void script_choice_init(wxChoice *c, wxString filespec)
-       {
-               wxDir dir(wxGetCwd());
+       for(size_t i = 0; i < filespec.GetCount(); i++){
                wxString filename;
-
-               c->Clear();
-               if ( !dir.IsOpened() ){
-                       return;
-               }
-               bool cont = dir.GetFirst(&filename, filespec, wxDIR_FILES);
+               bool cont = dir.GetFirst(&filename, filespec[i], wxDIR_FILES);
                while ( cont ){
-                       c->Append(filename);
+                       ar.Add(filename);
                        cont = dir.GetNext(&filename);
                }
-               if(c->GetCount() == 0){
-                       *m_log << wxT("warning: ") << filespec << wxT(" script not found.\n");
-               }else{
-                       c->Select(0);
-               }
        }
-//---- dump mode functions ----
-       void dump_increase_init(wxChoice *c)
-       {
-               c->Clear();
-               c->Append(wxT("x1"));
-               c->Append(wxT("x2"));
-               c->Append(wxT("x4"));
+       if(ar.GetCount() == 0){
+               *log << wxT("warning: ");
+               for(size_t i = 0; i < filespec.GetCount(); i++){
+                       *log << filespec[i] << wxT(" ");
+               }
+               *log << wxT("script not found.\n");
+       }else{
+               ar.Sort(false);
+               for(size_t i = 0; i < ar.GetCount(); i++){
+                       c->Append(ar[i]);
+               }
                c->Select(0);
        }
-       int dump_increase_get(wxChoice *c)
-       {
-               switch(c->GetSelection()){
-               case 0: return 1;
-               case 1: return 2;
-               case 2: return 4;
-               }
-               return 1;
+}
+
+static void increase_init(wxControlWithItems *c)
+{
+       c->Clear();
+       c->Append(wxT("x1"));
+       c->Append(wxT("x2"));
+       c->Append(wxT("x4"));
+       c->Select(0);
+}
+
+static int increase_get(wxControlWithItems *c)
+{
+       switch(c->GetSelection()){
+       case 0: return 1;
+       case 1: return 2;
+       case 2: return 4;
+       case 3: return INCREASE_AUTO;
        }
-       void dump_execute(void)
+       return 1;
+}
+
+enum anago_status{
+       STATUS_IDLE, STATUS_DUMPPING, STATUS_PROGRAMMING,
+       STATUS_RAM_READ, STATUS_RAM_WRITE
+};
+
+class anago_panel_dump : public panel_dump
+{
+private:
+       wxThread *m_anago_thread;
+       const struct reader_driver *const m_reader;
+       enum anago_status *const m_status;
+       wxTextCtrl *const m_log;
+       wxString m_sound_success, m_sound_fail;
+       wxString m_database;
+       RomDb *m_romdb;
+
+       void execute(void)
        {
                struct dump_config config;
-               config.cpu.gauge.bar = m_dump_cpu_gauge;
-               config.cpu.gauge.label = m_dump_cpu_value;
-               gauge_init(&config.cpu.gauge);
-
-               config.ppu.gauge.bar = m_dump_ppu_gauge;
-               config.ppu.gauge.label = m_dump_ppu_value;
-               gauge_init(&config.ppu.gauge);
+               config.mode = MODE_ROM_DUMP;
+               config.cpu.gauge.bar = m_cpu_gauge;
+               config.cpu.gauge.label = m_cpu_value;
+               c_wrapper::gauge_init(&config.cpu.gauge);
+
+               config.ppu.gauge.bar = m_ppu_gauge;
+               config.ppu.gauge.label = m_ppu_value;
+               c_wrapper::gauge_init(&config.ppu.gauge);
                
                config.log.object = m_log;
-               config.log.append = text_append;
-               config.log.append_va = text_append_va;
-               config.cpu.increase = dump_increase_get(m_dump_cpu_increase);
-               config.ppu.increase = dump_increase_get(m_dump_ppu_increase);
+               config.log.append = c_wrapper::text_append;
+               config.log.append_va = c_wrapper::text_append_va;
+               config.except = c_wrapper::throw_error;
+               config.cpu.increase = increase_get(m_cpu_increase);
+               config.ppu.increase = increase_get(m_ppu_increase);
                config.progress = true;
-               config.battery = m_dump_check_battery->GetValue();
+               config.battery = m_check_battery->GetValue();
                {
-                       wxString str_script = m_dump_script_choice->GetStringSelection();
-                       char *t = new char[str_script.Length() + 1];
+                       wxString str_script = m_script_choice->GetStringSelection();
+                       wxChar *t = new wxChar[str_script.Length() + 1];
                        config.script = t;
-                       strncpy(t, str_script.fn_str(), str_script.Length() + 1);
+                       STRNCPY(t, str_script.c_str(), str_script.Length() + 1);
                }
 
                {
                        wxString str;
                        config.mappernum = -1;
-                       if(m_dump_check_forcemapper->GetValue() == true){
-                               str = m_dump_text_forcemapper->GetValue();
+                       if(m_check_forcemapper->GetValue() == true){
+                               str = m_text_forcemapper->GetValue();
                                if(str.ToLong(&config.mappernum) == false){
                                        *m_log << wxT("bad mapper number\n");
                                        return;
@@ -239,45 +343,131 @@ private:
                }
 
                {
-                       wxTextCtrl *text = m_dump_romimage_picker->GetTextCtrl();
+                       wxTextCtrl *text = m_romimage_picker->GetTextCtrl();
                        wxString str_rom = text->GetValue();
-                       char *t = new char[str_rom.Length() + 1];
+                       wxChar *t = new wxChar[str_rom.Length() + 1];
                        if(text->IsEmpty() == true){
                                *m_log << wxT("Enter filename to ROM image\n");
                                return;
                        }
                        config.target = t;
-                       strncpy(t, str_rom.fn_str(), str_rom.Length() + 1);
+                       STRNCPY(t, str_rom.c_str(), str_rom.Length() + 1);
                }
 
-               config.control = &DRIVER_KAZZO.control;
-               config.cpu.access = &DRIVER_KAZZO.cpu;
-               config.ppu.access = &DRIVER_KAZZO.ppu;
+               config.control = &m_reader->control;
+               config.cpu.access = &m_reader->cpu;
+               config.ppu.access = &m_reader->ppu;
 
-               m_dump_script_choice->Disable();
-               m_dump_romimage_picker->Disable();
-               m_dump_check_battery->Disable();
-               m_dump_check_forcemapper->Disable();
-               m_dump_button->SetLabel(wxT("cancel"));
-               m_dump_text_forcemapper->Disable();
-               m_dump_cpu_increase->Disable();
-               m_dump_ppu_increase->Disable();
+               this->Disable();
 
 /*             if(m_anago_thread != NULL){ //???
                        delete m_anago_thread;
                }*/
-               m_anago_thread = new anago_dumper(this, &config);
+               m_anago_thread = new anago_dumper(this, &config, m_log, m_sound_success, m_sound_fail, m_romdb);
                if(m_anago_thread->Create() != wxTHREAD_NO_ERROR){
                        *m_log << wxT("thread creating error");
                }else if(m_anago_thread->Run() != wxTHREAD_NO_ERROR){
                        *m_log << wxT("thread running error");
                }else{
-                       m_status = STATUS_DUMPPING;
+                       *m_status = STATUS_DUMPPING;
+               }
+       }
+protected:
+       void button_click(wxCommandEvent& event)
+       {
+               switch(*m_status){
+               case STATUS_IDLE:
+                       this->execute();
+                       break;
+               case STATUS_DUMPPING:
+                       m_anago_thread->Kill();
+                       this->Enable();
+                       break;
+               default: //do nothing
+                       break;
+               }
+       }
+
+       void mapper_change_check(wxCommandEvent& event)
+       {
+               if(m_check_forcemapper->GetValue() == true){
+                       m_text_forcemapper->Enable();
+               }else{
+                       m_text_forcemapper->Disable();
+               }
+       }
+
+public:
+       anago_panel_dump(wxNotebook *p, const struct reader_driver *r, enum anago_status *status, wxFileConfig *config, wxTextCtrl *log)
+         : panel_dump(p), m_reader(r), m_status(status), m_log(log)
+       {
+               config->Read(wxT("dump.database"), &m_database, wxT("NesCarts (2011-09-10).xml"));
+               if(wxFileName::FileExists(m_database) == true){
+                       m_romdb = new RomDb(m_database);
+                       m_romdb->Generate();
+               }else{
+                       *log << wxT("m_database not found\n");
+                       m_romdb = new RomDb();
+               }
+
+               config->Read(wxT("dump.sound.success"), &m_sound_success, wxT("tinkalink2.wav"));
+               config->Read(wxT("dump.sound.fail"), &m_sound_fail, wxT("doggrowl.wav"));
+
+               wxArrayString ar;
+               ar.Add(wxT("*.ad"));
+               ar.Add(wxT("*.ae"));
+               ar.Add(wxT("*.af"));
+               ar.Add(wxT("*.ag"));
+               script_choice_init(m_script_choice, ar, log);
+               ::increase_init(m_cpu_increase);
+               m_cpu_increase->Append(wxT("Auto"));
+               m_cpu_increase->Select(3);
+               ::increase_init(m_ppu_increase);
+               if(DEBUG==1){
+                       m_romimage_picker->GetTextCtrl()->SetLabel(wxT("t.nes"));
+               }
+       }
+       virtual ~anago_panel_dump(void)
+       {
+               delete m_romdb;
+       }
+       bool Enable(bool t = true)
+       {
+               m_script_choice->Enable(t);
+               m_romimage_picker->Enable(t);
+               m_check_battery->Enable(t);
+               m_check_forcemapper->Enable(t);
+               m_cpu_increase->Enable(t);
+               m_ppu_increase->Enable(t);
+               if(t == true){
+                       *m_status = STATUS_IDLE;
+                       m_button->SetLabel(wxT("&dump"));
+                       if(m_check_forcemapper->GetValue() == true){
+                               m_text_forcemapper->Enable();
+                       }
+               }else{
+                       m_button->SetLabel(wxT("cancel"));
+                       m_check_forcemapper->Disable();
                }
+               m_button->SetFocus();
+               return true;
+       }
+       bool Disable(void)
+       {
+               return this->Enable(false);
        }
+};
+
+class anago_panel_program : public panel_program
+{
+private:
+       wxThread *m_anago_thread;
+       const struct reader_driver *const m_reader;
+       wxString m_sound_success, m_sound_fail;
+       enum anago_status *const m_status;
+       wxTextCtrl *const m_log;
        
-//----- program mode functions ----
-       void program_padding_init(wxChoice *c)
+       void padding_init(wxControlWithItems *c)
        {
                c->Clear();
                c->Append(wxT("full"));
@@ -286,7 +476,7 @@ private:
                c->Append(wxT("empty"));
                c->Select(0);
        }
-       bool program_rom_set(wxString device, int trans, struct memory *m, struct flash_device *f)
+       bool rom_set(wxString device, int trans, struct memory *m, struct flash_device *f)
        {
                m->offset = 0;
                if(flash_device_get(device, f) == false){
@@ -311,161 +501,338 @@ private:
                return true;
        }
 
-       void program_execute(void)
+       void execute(void)
        {
                struct program_config f;
                
-               f.cpu.gauge.bar = m_program_cpu_gauge;
-               f.cpu.gauge.label = m_program_cpu_value;
-               gauge_init(&f.cpu.gauge);
+               f.cpu.gauge.bar = m_cpu_gauge;
+               f.cpu.gauge.label = m_cpu_value;
+               c_wrapper::gauge_init(&f.cpu.gauge);
 
-               f.ppu.gauge.bar = m_program_ppu_gauge;
-               f.ppu.gauge.label = m_program_ppu_value;
-               gauge_init(&f.ppu.gauge);
+               f.ppu.gauge.bar = m_ppu_gauge;
+               f.ppu.gauge.label = m_ppu_value;
+               c_wrapper::gauge_init(&f.ppu.gauge);
                
                f.log.object = m_log;
-               f.log.append = text_append;
-               f.log.append_va = text_append_va;
+               f.log.append = c_wrapper::text_append;
+               f.log.append_va = c_wrapper::text_append_va;
+               f.except = c_wrapper::throw_error;
                
                {
-                       wxString str_script = m_program_script_choice->GetStringSelection();
-                       char *t = new char[str_script.Length() + 1];
-                       strncpy(t, str_script.fn_str(), str_script.Length() + 1);
+                       wxString str_script = m_script_choice->GetStringSelection();
+                       wxChar *t = new wxChar[str_script.Length() + 1];
+                       STRNCPY(t, str_script.c_str(), str_script.Length() + 1);
                        f.script = t;
                }
 
                {
-                       wxTextCtrl *text = m_program_romimage_picker->GetTextCtrl();
+                       wxTextCtrl *text = m_romimage_picker->GetTextCtrl();
                        wxString str_rom = text->GetValue();
                        if(text->IsEmpty() == true){
                                *m_log << wxT("Enter filename to ROM image\n");
                                return;
                        }
-                       char *t = new char[str_rom.Length() + 1];
-                       strncpy(t, str_rom.fn_str(), str_rom.Length() + 1);
+                       wxChar *t = new wxChar[str_rom.Length() + 1];
+                       STRNCPY(t, str_rom.c_str(), str_rom.Length() + 1);
                        f.target = t;
                }
-               f.compare = m_program_compare->GetValue();
-               f.testrun = false;
+               f.compare = m_compare->GetValue();
 
-               if(program_rom_set(
-                       m_program_cpu_device->GetStringSelection(), 
-                       m_program_cpu_padding->GetSelection(),
+               if(rom_set(
+                       m_cpu_device->GetStringSelection(), 
+                       m_cpu_padding->GetSelection(),
                        &f.cpu.memory, &f.cpu.flash
                ) == false){
                        return;
                }
-               if(program_rom_set(
-                       m_program_ppu_device->GetStringSelection(), 
-                       m_program_ppu_padding->GetSelection(),
+               if(rom_set(
+                       m_ppu_device->GetStringSelection(), 
+                       m_ppu_padding->GetSelection(),
                        &f.ppu.memory, &f.ppu.flash
                ) == false){
                        return;
                }
 
-               f.control = &DRIVER_KAZZO.control;
-               f.cpu.access = &DRIVER_KAZZO.cpu;
-               f.ppu.access = &DRIVER_KAZZO.ppu;
+               f.control = &m_reader->control;
+               f.cpu.access = &m_reader->cpu;
+               f.ppu.access = &m_reader->ppu;
 
-               m_program_script_choice->Disable();
-               m_program_romimage_picker->Disable();
-               m_program_compare->Disable();
-               m_program_button->SetLabel(wxT("cancel"));
-               m_program_cpu_padding->Disable();
-               m_program_cpu_device->Disable();
-               m_program_ppu_padding->Disable();
-               m_program_ppu_device->Disable();
-               m_program_compare->Disable();
+               this->Disable();
 
-               m_anago_thread = new anago_programmer(this, &f);
+               m_anago_thread = new anago_programmer(this, m_log, &f, m_sound_success, m_sound_fail);
                if(m_anago_thread->Create() != wxTHREAD_NO_ERROR){
                        *m_log << wxT("thread creating error");
                }else if(m_anago_thread->Run() != wxTHREAD_NO_ERROR){
                        *m_log << wxT("thread running error");
                }else{
-                       m_status = STATUS_PROGRAMMING;
+                       *m_status = STATUS_PROGRAMMING;
                }
        }
 
+       void device_load(wxControlWithItems *choice, wxFileConfig *c, wxString key)
+       {
+               wxString device;
+               int val;
+               c->Read(key, &device);
+               val = choice->FindString(device);
+               if(val == wxNOT_FOUND){
+                       choice->Select(0);
+               }else{
+                       choice->Select(val);
+               }
+       }
 protected:
-       void dump_button_click(wxCommandEvent& event)
+       void button_click(wxCommandEvent& event)
        {
-               switch(m_status){
+               switch(*m_status){
                case STATUS_IDLE:
-                       this->dump_execute();
+                       this->execute();
                        break;
-               case STATUS_DUMPPING:
+               case STATUS_PROGRAMMING:
                        m_anago_thread->Kill();
-                       this->DumpThreadFinish();
-                       m_status = STATUS_IDLE;
+                       this->Enable();
                        break;
                default: //do nothing
                        break;
                }
        }
-       void program_button_click(wxCommandEvent& event)
+public:
+       anago_panel_program(wxNotebook *p, const struct reader_driver *r, enum anago_status *status, wxFileConfig *config, wxTextCtrl *log) 
+         : panel_program(p), m_reader(r), m_status(status), m_log(log)
        {
-               switch(m_status){
+               config->Read(wxT("program.sound.success"), &m_sound_success, wxT("cuckoo.wav"));
+               config->Read(wxT("program.sound.fail"), &m_sound_fail, wxT("doggrowl.wav"));
+               {
+                       wxArrayString t;
+                       t.Add(wxT("*.af"));
+                       t.Add(wxT("*.ag"));
+                       script_choice_init(m_script_choice, t, m_log);
+               }
+               {
+                       struct flash_listup list;
+                       list.obj_cpu = m_cpu_device;
+                       list.obj_ppu = m_ppu_device;
+                       list.append = c_wrapper::choice_append;
+                       flash_device_listup(&list);
+               }
+               if(m_cpu_device->GetCount() == 0){
+                       *m_log << wxT("warning: flash device parameter not found\n");
+               }else{
+                       device_load(m_cpu_device, config, wxT("program.cpu.device"));
+                       device_load(m_ppu_device, config, wxT("program.ppu.device"));
+               }
+               this->padding_init(m_cpu_padding);
+               this->padding_init(m_ppu_padding);
+               
+               m_anago_thread = NULL;
+       }
+       bool Enable(bool t = true)
+       {
+               m_script_choice->Enable(t);
+               m_romimage_picker->Enable(t);
+               m_compare->Enable(t);
+               m_cpu_padding->Enable(t);
+               m_cpu_device->Enable(t);
+               m_ppu_padding->Enable(t);
+               m_ppu_device->Enable(t);
+               if(t == true){
+                       *m_status = STATUS_IDLE;
+                       m_button->SetLabel(wxT("&program"));
+               }else{
+                       m_button->SetLabel(wxT("cancel"));
+               }
+               m_button->SetFocus();
+               return true;
+       }
+       bool Disable(void)
+       {
+               return this->Enable(false);
+       }
+       void ConfigWrite(wxFileConfig *c)
+       {
+               c->Write(wxT("program.cpu.device"), m_cpu_device->GetStringSelection());
+               c->Write(wxT("program.ppu.device"), m_ppu_device->GetStringSelection());
+       }
+};
+
+class anago_panel_workram : public panel_workram
+{
+private:
+       wxThread *m_anago_thread;
+       const struct reader_driver *const m_reader;
+       enum anago_status *const m_status;
+       wxTextCtrl *const m_log;
+       wxString m_sound_success, m_sound_fail;
+
+       void execute(struct dump_config *c, wxControlWithItems *script, wxFilePickerCtrl *picker, enum anago_status status)
+       {
+               c->cpu.gauge.label = NULL;
+               c_wrapper::gauge_init(&c->cpu.gauge);
+               
+               c->log.object = m_log;
+               c->log.append = c_wrapper::text_append;
+               c->log.append_va = c_wrapper::text_append_va;
+               c->except = c_wrapper::throw_error;
+               assert(c->cpu.increase != INCREASE_AUTO);
+               c->progress = true;
+               {
+                       wxString str_script = script->GetStringSelection();
+                       wxChar *t = new wxChar[str_script.Length() + 1];
+                       c->script = t;
+                       STRNCPY(t, str_script.c_str(), str_script.Length() + 1);
+               }
+               {
+                       wxTextCtrl *text = picker->GetTextCtrl();
+                       wxString str_rom = text->GetValue();
+                       wxChar *t = new wxChar[str_rom.Length() + 1];
+                       if(text->IsEmpty() == true){
+                               *m_log << wxT("Enter filename to ROM image\n");
+                               return;
+                       }
+                       c->target = t;
+                       STRNCPY(t, str_rom.c_str(), str_rom.Length() + 1);
+               }
+               c->control = &m_reader->control;
+               c->cpu.access = &m_reader->cpu;
+               c->ppu.access = &m_reader->ppu;
+               
+               m_anago_thread = new anago_dumper(this, c, m_log, m_sound_success, m_sound_fail);
+               if(m_anago_thread->Create() != wxTHREAD_NO_ERROR){
+                       *m_log << wxT("thread creating error");
+               }else if(m_anago_thread->Run() != wxTHREAD_NO_ERROR){
+                       *m_log << wxT("thread running error");
+               }else{
+                       *m_status = status; //先に status を設定すること
+                       this->Disable();
+               }
+       }
+
+       void read(void)
+       {
+               struct dump_config config;
+               config.mode = MODE_RAM_READ;
+               config.cpu.gauge.bar = m_read_gauge;
+               config.cpu.increase = ::increase_get(m_read_increase);
+               this->execute(&config, m_read_script, m_read_picker, STATUS_RAM_READ);
+       }
+       void write(void)
+       {
+               struct dump_config config;
+               config.mode = MODE_RAM_WRITE;
+               config.cpu.gauge.bar = m_write_gauge;
+               config.cpu.increase = ::increase_get(m_write_increase);
+               this->execute(&config, m_write_script, m_write_picker, STATUS_RAM_WRITE);
+       }
+protected:
+       void read_button_click(wxCommandEvent& event)
+       {
+               switch(*m_status){
                case STATUS_IDLE:
-                       this->program_execute();
+                       read();
                        break;
-               case STATUS_PROGRAMMING:
-                       m_anago_thread->Kill();
-                       this->ProgramThreadFinish();
-                       m_status = STATUS_IDLE;
+               case STATUS_RAM_READ:
+                       this->Enable();
                        break;
                default: //do nothing
                        break;
                }
        }
-       void mapper_change_check(wxCommandEvent& event)
+
+       void write_button_click(wxCommandEvent& event)
        {
-               if(m_dump_check_forcemapper->GetValue() == true){
-                       m_dump_text_forcemapper->Enable();
-               }else{
-                       m_dump_text_forcemapper->Disable();
+               switch(*m_status){
+               case STATUS_IDLE:
+                       write();
+                       break;
+               case STATUS_RAM_WRITE:
+                       this->Enable();
+                       break;
+               default: //do nothing
+                       break;
                }
        }
-       void menu_log_clean(wxCommandEvent& event)
+public:
+       anago_panel_workram(wxWindow *p, const struct reader_driver *r, enum anago_status *status, wxFileConfig *config, wxTextCtrl *log)
+         : panel_workram(p), m_reader(r), m_status(status), m_log(log)
        {
-               m_log->Clear();
+               config->Read(wxT("workram.sound.success"), &m_sound_success, wxT("tinkalink2.wav"));
+               config->Read(wxT("workram.sound.fail"), &m_sound_fail, wxT("doggrowl.wav"));
+
+               wxArrayString ar;
+               ar.Add(wxT("*.ae"));
+               ar.Add(wxT("*.ag"));
+               ::script_choice_init(m_read_script, ar, log);
+               ::script_choice_init(m_write_script, ar, log);
+               ::increase_init(m_read_increase);
+               ::increase_init(m_write_increase);
+               
+               if(DEBUG == 1){
+                       m_read_picker->GetTextCtrl()->SetLabel(wxT("t.sav"));
+               }
        }
-public:
-       /** Constructor */
-       anago_frame( wxWindow* parent ) : frame_main(parent)
-       {
-               this->script_choice_init(m_dump_script_choice, wxT("*.ad"));
-               this->script_choice_init(m_program_script_choice, wxT("*.af"));
-               this->dump_increase_init(m_dump_cpu_increase);
-               this->dump_increase_init(m_dump_ppu_increase);
-
-               struct flash_listup list;
-               list.obj_cpu = m_program_cpu_device;
-               list.obj_ppu = m_program_ppu_device;
-               list.append = choice_append;
-               flash_device_listup(&list);
-               if(m_program_cpu_device->GetCount() == 0){
-                       *m_log << wxT("warning: flash device parameter not found\n");
+       
+       bool Enable(bool t = true)
+       {
+               m_read_script->Enable(t);
+               m_read_picker->Enable(t);
+               m_write_script->Enable(t);
+               m_write_picker->Enable(t);
+               if(t == true){
+                       switch(*m_status){
+                       case STATUS_RAM_READ:
+                               m_read_button->SetLabel(wxT("&read"));
+                               m_read_button->SetFocus();
+                               m_write_button->Enable();
+                               break;
+                       case STATUS_RAM_WRITE:
+                               m_write_button->SetLabel(wxT("&write"));
+                               m_write_button->SetFocus();
+                               m_read_button->Enable();
+                               break;
+                       default:
+                               break;
+                       }
+                       *m_status = STATUS_IDLE;
                }else{
-                       m_program_cpu_device->Select(0);
-                       m_program_ppu_device->Select(0);
+                       switch(*m_status){
+                       case STATUS_RAM_READ:
+                               m_read_button->SetLabel(wxT("&cancel"));
+                               m_write_button->Disable();
+                               break;
+                       case STATUS_RAM_WRITE:
+                               m_write_button->SetLabel(wxT("&cancel"));
+                               m_read_button->Disable();
+                               break;
+                       default:
+                               break;
+                       }
                }
-               this->program_padding_init(m_program_cpu_padding);
-               this->program_padding_init(m_program_ppu_padding);
-               
-               m_anago_thread = NULL;
-               m_status = STATUS_IDLE;
+               return true;
+       }
 
+       bool Disable(void)
+       {
+               return this->Enable(false);
+       }
+};
+
+class anago_panel_version : public panel_version
+{
+public:
+       anago_panel_version(wxWindow *p) : panel_version(p)
+       {
 //version infomation
-               struct textcontrol detail;
-               *m_version_detail << wxT("anago build at ") << __DATE__ << wxT("\n\n");
-               detail.object = m_version_detail;
-               detail.append = version_append;
-               detail.append_va = version_append_va;
-               qr_version_print(&detail);
-               *m_version_detail << wxVERSION_STRING << wxT(" (c) Julian Smar");
+               {
+                       struct textcontrol detail;
+                       *m_version_detail << wxT("anago build at ") << wxT(__DATE__) << wxT("\n\n");
+                       detail.object = m_version_detail;
+                       detail.append = c_wrapper::version_append;
+                       detail.append_va = c_wrapper::version_append_va;
+                       qr_version_print(&detail);
+                       *m_version_detail << wxVERSION_STRING << wxT(" (c) Julian Smar");
+               }
                
-#ifdef WIN32
+#if 0 //def WIN32
                #include "okada.xpm"
                wxBitmap bitmap_okada(okada);
                wxString tooltip(wxT(
@@ -482,67 +849,92 @@ public:
 //                     "行き勝負をかけます。結果はまた報告します。宜しく。"
                ));
 #else
-               #include "taiyo.xpm"
-               wxBitmap bitmap_okada(taiyo);
-               wxString tooltip(wxT("たいよ~ほえ~るず♪"));
+               #include "slyly.xpm"
+               wxBitmap bitmap_okada(slyly);
+               wxString tooltip(wxT("CARP                        ピロ"));
 #endif
 //             #include "araki.xpm"
 //             wxBitmap bitmap_okada(araki);
                m_version_photo->SetBitmap(bitmap_okada);
                m_version_photo->SetToolTip(tooltip);
        }
+};
 
-       void DumpThreadFinish(void)
+//---- main frame class ----
+class anago_frame : public frame_main
+{
+private:
+       enum anago_status m_status; //ここだけ実体, 各パネルはこのポインタ
+       const wxString m_config_file;
+       anago_panel_program *m_panel_program;
+protected:
+       void menu_log_clean(wxCommandEvent& event)
        {
-               m_dump_script_choice->Enable();
-               m_dump_romimage_picker->Enable();
-               m_dump_check_battery->Enable();
-               m_dump_check_forcemapper->Enable();
-               m_dump_cpu_increase->Enable();
-               m_dump_ppu_increase->Enable();
-               m_dump_button->SetLabel(wxT("&dump"));
-               if(m_dump_check_forcemapper->GetValue() == true){
-                       m_dump_text_forcemapper->Enable();
-               }
-               m_status = STATUS_IDLE;
+               m_log->Clear();
        }
        
-       void ProgramThreadFinish(void)
-       {
-               m_program_script_choice->Enable();
-               m_program_romimage_picker->Enable();
-               m_program_compare->Enable();
-               m_program_button->SetLabel(wxT("&program"));
-               m_program_cpu_padding->Enable();
-               m_program_cpu_device->Enable();
-               m_program_ppu_padding->Enable();
-               m_program_ppu_device->Enable();
-               m_status = STATUS_IDLE;
-       }
-};
+public:
+       /** Constructor */
+       anago_frame(wxWindow* parent, const struct reader_driver *r)
+         : frame_main(parent), m_status(STATUS_IDLE),
+#ifdef WIN32
+         m_config_file(wxGetCwd() + wxT("/anago.cfg"))
+#else
+         m_config_file(wxT(".anago"))
+#endif
+       {
+               wxFileConfig config(wxEmptyString, wxEmptyString, m_config_file);
+//form config load
+               wxPoint position;
+               
+               config.Read(wxT("position.x"), &position.x, 32);
+               config.Read(wxT("position.y"), &position.y, 32);
+               this->SetPosition(position);
+               
+               wxSize size;
+               config.Read(wxT("size.x"), &size.x, 340);
+               config.Read(wxT("size.y"), &size.y, 460);
+               this->SetSize(size);
 
+               m_notebook->AddPage(new anago_panel_dump(m_notebook, r, &m_status, &config, m_log), wxT("dump"), false);
 
-void *anago_dumper::Entry(void)
-{
-       script_dump_execute(&m_config);
-       m_frame->DumpThreadFinish();
-       return NULL;
-}
+               m_panel_program = new anago_panel_program(m_notebook, r, &m_status, &config, m_log);
+               m_notebook->AddPage(m_panel_program, wxT("program"), false);
 
-void *anago_programmer::Entry(void)
-{
-       script_program_execute(&m_config);
-       m_frame->ProgramThreadFinish();
-       return NULL;
-}
+               m_notebook->AddPage(new anago_panel_workram(m_notebook, r, &m_status, &config, m_log), wxT("workram"), false);
+               m_notebook->AddPage(new anago_panel_version(m_notebook), wxT("version"), false);
+
+#ifdef WIN32
+               SetIcon(wxIcon(wxT("unagi_blue")));
+#else
+               #include "unagi_blue.xpm"
+               SetIcon(wxIcon(unagi_blue));
+#endif
+       }
+
+       virtual ~anago_frame(void)
+       {
+               wxFileConfig config(wxEmptyString, wxEmptyString, m_config_file);
+               wxPoint position = this->GetPosition();
+               
+               config.Write(wxT("position.x"), position.x);
+               config.Write(wxT("position.y"), position.y);
+
+               wxSize size = this->GetSize();
+               config.Write(wxT("size.x"), size.x);
+               config.Write(wxT("size.y"), size.y);
+               
+               m_panel_program->ConfigWrite(&config);
+       }
+};
 
 #ifndef WIN32
 extern "C"{
-       int anago_cui(int c, char **v);
+  int anago_cui(int c, wxChar **v);
 }
-int main(int c, char **v)
+int main(int c, wxChar **v)
 {
-       if(c < 2){
+       if(c < 3){
                return wxEntry(c, v);
        }
        return anago_cui(c, v);
@@ -556,11 +948,18 @@ private:
 public: 
        bool OnInit()
        {
-               m_frame = new anago_frame(NULL);
+               if(this->argc >= 2){
+                       m_frame = new anago_frame(NULL, &DRIVER_DUMMY);
+               }else{
+                       m_frame = new anago_frame(NULL, &DRIVER_KAZZO);
+               }
                m_frame->Show();
                
                return true;
        }
 };
+#ifdef WIN32
 IMPLEMENT_APP(MyApp)
-
+#else
+IMPLEMENT_APP_NO_MAIN(MyApp)
+#endif