OSDN Git Service

RAM access mode support, CUI only
[unagi/old-svn-converted.git] / client / trunk / anago / anago_frame.cpp
index bf2b06f..c90d71e 100644 (file)
@@ -1,29 +1,61 @@
 #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 <cstdarg>
+#include "type.h"
 #include "anago_gui.h"
 #include "widget.h"
 #include "reader_master.h"
-//#include "reader_kazzo.h"
-extern const struct reader_driver DRIVER_KAZZO;
+#include "reader_kazzo.h"
 extern "C"{
-#include "header.h"
-#include "flash_device.h"
-#include "script_dump.h"
-#include "script_flash.h"
+  #include "romimage.h"
+  #include "flash_device.h"
+  #include "script_dump.h"
+  #include "script_program.h"
+  void qr_version_print(const struct textcontrol *l);
+}
+#if DEBUG==1
+extern const struct reader_driver DRIVER_DUMMY;
+#endif
+#ifdef _UNICODE
+  #define STRNCPY wcsncpy
+#else
+  #define STRNCPY strncpy
+#endif
+//---- C++ -> C -> C++ wrapping functions ----
+static void throw_error(const wxChar *t)
+{
+       throw t;
 }
 
-static void value_set(void *gauge, int value)
+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);
+       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 range_set(void *gauge, int value)
 {
        wxGauge *g = static_cast<wxGauge *>(gauge);
@@ -33,41 +65,85 @@ static void range_set(void *gauge, int value)
        g->SetRange(value);
 }
 
-static void text_append(void *log, const char *str)
+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();
 }
 
-static void label_set(void *label, const char *str)
+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 wxChar *format, va_list list)
+{
+       wxTextCtrl *l = static_cast<wxTextCtrl *>(log);
+       wxString str;
+       str.PrintfV(format, list);
+
+       *l << str;
+}
+
+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 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();
 }
 
-void choice_append(void *choice, const char *str)
+static void choice_append(void *choice, const wxChar *str)
 {
        wxChoice *c = static_cast<wxChoice *>(choice);
        c->Append(wxString(str));
 }
 
+//---- script execute thread ----
 class anago_frame;
+
 class anago_dumper : public wxThread
 {
 private:
        anago_frame *m_frame;
-       struct config_dump m_config;
+       struct dump_config m_config;
+       const wxSound m_sound_success, m_sound_fail;
 protected:
-       virtual void *Entry(void);
+       void *Entry(void);
+       void OnExit()
+       {
+               delete [] m_config.script;
+               delete [] m_config.target;
+       }
 public:
-       anago_dumper(anago_frame *f, struct config_dump *d) : wxThread()
+       anago_dumper(anago_frame *f, const struct dump_config *d, wxString sound_success, wxString sound_fail) 
+         : wxThread(), m_sound_success(sound_success), m_sound_fail(sound_fail)
        {
                m_frame = f;
-               memcpy(&m_config, d, sizeof(config_dump));
+               m_config = *d; //struct data copy
        }
 };
 
@@ -75,34 +151,49 @@ class anago_programmer : public wxThread
 {
 private:
        anago_frame *m_frame;
-       struct config_flash m_config;
+       struct program_config m_config;
+       const wxSound m_sound_success, m_sound_fail;
 protected:
-       virtual void *Entry(void);
+       void *Entry(void);
+       void OnExit()
+       {
+               delete [] m_config.script;
+               delete [] m_config.target;
+       }
 public:
-       anago_programmer(anago_frame *f, struct config_flash *d) : wxThread()
+       anago_programmer(anago_frame *f, const struct program_config *d, wxString sound_success, wxString sound_fail) 
+         : wxThread(), m_sound_success(sound_success), m_sound_fail(sound_fail)
        {
                m_frame = f;
-               memcpy(&m_config, d, sizeof(config_flash));
+               m_config = *d;
        }
 };
 
+//---- main frame class ----
 class anago_frame : public frame_main
 {
 private:
        wxThread *m_anago_thread;
+       const wxString m_config_file;
+       const struct reader_driver *m_reader;
+       wxString m_dump_sound_success, m_dump_sound_fail;
+       wxString m_program_sound_success, m_program_sound_fail;
        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;
        }
-       void script_choice_init(wxChoice *c, wxString filespec)
+       void script_choice_init(wxControlWithItems *c, wxString filespec)
        {
                wxDir dir(wxGetCwd());
                wxString filename;
+               wxArrayString ar;
 
                c->Clear();
                if ( !dir.IsOpened() ){
@@ -110,42 +201,62 @@ private:
                }
                bool cont = dir.GetFirst(&filename, filespec, wxDIR_FILES);
                while ( cont ){
-                       c->Append(filename);
+                       ar.Add(filename);
                        cont = dir.GetNext(&filename);
                }
-               if(c->GetCount() == 0){
-                       *m_log << "warning: " << filespec << " script not found.\n";
+               if(ar.GetCount() == 0){
+                       *m_log << wxT("warning: ") << filespec << 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);
                }
        }
 //---- dump mode functions ----
-       void dump_increase_init(wxChoice *c)
+       void dump_increase_init(wxControlWithItems *c)
        {
                c->Clear();
-               c->Append(wxString("x1"));
-               c->Append(wxString("x2"));
-               c->Append(wxString("x4"));
+               c->Append(wxT("x1"));
+               c->Append(wxT("x2"));
+               c->Append(wxT("x4"));
                c->Select(0);
        }
+       int dump_increase_get(wxControlWithItems *c)
+       {
+               switch(c->GetSelection()){
+               case 0: return 1;
+               case 1: return 2;
+               case 2: return 4;
+               }
+               return 1;
+       }
        void dump_execute(void)
        {
-               struct config_dump config;
-               config.gauge_cpu.bar = m_dump_cpu_gauge;
-               config.gauge_cpu.label = m_dump_cpu_label;
-               gauge_init(&config.gauge_cpu);
-
-               config.gauge_ppu.bar = m_dump_ppu_gauge;
-               config.gauge_ppu.label = m_dump_ppu_label;
-               gauge_init(&config.gauge_ppu);
+               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.log.object = m_log;
                config.log.append = text_append;
-               config.increase.cpu = 1;
-               config.increase.ppu = 1;
+               config.log.append_va = text_append_va;
+               config.except = throw_error;
+               config.cpu.increase = dump_increase_get(m_dump_cpu_increase);
+               config.ppu.increase = dump_increase_get(m_dump_ppu_increase);
                config.progress = true;
-               wxString str_script = m_dump_script_choice->GetStringSelection();
-               strncpy(config.script, str_script.fn_str(), DUMP_SCRIPT_STR_LENGTH);
+               config.battery = m_dump_check_battery->GetValue();
+               {
+                       wxString str_script = m_dump_script_choice->GetStringSelection();
+                       wxChar *t = new wxChar[str_script.Length() + 1];
+                       config.script = t;
+                       STRNCPY(t, str_script.fn_str(), str_script.Length() + 1);
+               }
 
                {
                        wxString str;
@@ -153,64 +264,66 @@ private:
                        if(m_dump_check_forcemapper->GetValue() == true){
                                str = m_dump_text_forcemapper->GetValue();
                                if(str.ToLong(&config.mappernum) == false){
-                                       *m_log << "bad mapper number\n";
+                                       *m_log << wxT("bad mapper number\n");
                                        return;
                                }
                        }
                }
 
-               wxTextCtrl *text = m_dump_romimage_picker->GetTextCtrl();
-               wxString str_rom = text->GetValue();
-               if(text->IsEmpty() == true){
-                       *m_log << "Enter filename to ROM image\n";
-                       return;
+               {
+                       wxTextCtrl *text = m_dump_romimage_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;
+                       }
+                       config.target = t;
+                       STRNCPY(t, str_rom.fn_str(), str_rom.Length() + 1);
                }
-               strncpy(config.target, str_rom.fn_str(), DUMP_TARGET_STR_LENGTH);
 
-               config.reader = &DRIVER_KAZZO;
-               if(config.reader->open_or_close(READER_OPEN) == NG){
-                       *m_log << "reader open error\n";
-                       return;
-               }
+               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(wxString("cancel"));
+               m_dump_button->SetLabel(wxT("cancel"));
                m_dump_text_forcemapper->Disable();
                m_dump_cpu_increase->Disable();
                m_dump_ppu_increase->Disable();
 
-               config.reader->init();
 /*             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_dump_sound_success, m_dump_sound_fail);
                if(m_anago_thread->Create() != wxTHREAD_NO_ERROR){
-                       *m_log << "thread creating error";
+                       *m_log << wxT("thread creating error");
                }else if(m_anago_thread->Run() != wxTHREAD_NO_ERROR){
-                       *m_log << "thread running error";
+                       *m_log << wxT("thread running error");
                }else{
                        m_status = STATUS_DUMPPING;
                }
        }
        
 //----- program mode functions ----
-       void program_padding_init(wxChoice *c)
+       void program_padding_init(wxControlWithItems *c)
        {
                c->Clear();
-               c->Append(wxString("full"));
-               c->Append(wxString("top"));
-               c->Append(wxString("bottom"));
-               c->Append(wxString("empty"));
+               c->Append(wxT("full"));
+               c->Append(wxT("top"));
+               c->Append(wxT("bottom"));
+               c->Append(wxT("empty"));
                c->Select(0);
        }
-       bool program_rom_set(const char *area, wxString device, int trans, struct memory *m, struct flash_device *f)
+       bool program_rom_set(wxString device, int trans, struct memory *m, struct flash_device *f)
        {
                m->offset = 0;
                if(flash_device_get(device, f) == false){
-                       *m_log << "unknown flash memory device ";
-                       *m_log << device << "\n";
+                       *m_log << wxT("unknown flash memory device ");
+                       *m_log << device << wxT("\n");
                        return false;
                }
                switch(trans){
@@ -227,91 +340,86 @@ private:
                        m->transtype = TRANSTYPE_EMPTY;
                        break;
                }
-               if(m->size == 0){
-                       m->transtype = TRANSTYPE_EMPTY;
-               }
-               if(f->capacity < m->size){
-                       *m_log << area << "area ROM image size is larger than target device";
-                       return false;
-               }
                return true;
        }
+
        void program_execute(void)
        {
-               struct config_flash f;
+               struct program_config f;
                
-               f.gauge_cpu.bar = m_program_cpu_gauge;
-               f.gauge_cpu.label = m_program_cpu_label;
-               gauge_init(&f.gauge_cpu);
+               f.cpu.gauge.bar = m_program_cpu_gauge;
+               f.cpu.gauge.label = m_program_cpu_value;
+               gauge_init(&f.cpu.gauge);
 
-               f.gauge_ppu.bar = m_program_ppu_gauge;
-               f.gauge_ppu.label = m_program_ppu_label;
-               gauge_init(&f.gauge_ppu);
+               f.ppu.gauge.bar = m_program_ppu_gauge;
+               f.ppu.gauge.label = m_program_ppu_value;
+               gauge_init(&f.ppu.gauge);
                
                f.log.object = m_log;
                f.log.append = text_append;
+               f.log.append_va = text_append_va;
+               f.except = throw_error;
                
-               wxString str_script = m_program_script_choice->GetStringSelection();
-               strncpy(f.script, str_script.fn_str(), PROGRAM_SCRIPT_STR_LENGTH);
+               {
+                       wxString str_script = m_program_script_choice->GetStringSelection();
+                       wxChar *t = new wxChar[str_script.Length() + 1];
+                       STRNCPY(t, str_script.fn_str(), str_script.Length() + 1);
+                       f.script = t;
+               }
 
-               wxTextCtrl *text = m_program_romimage_picker->GetTextCtrl();
-               wxString str_rom = text->GetValue();
-               if(text->IsEmpty() == true){
-                       *m_log << "Enter filename to ROM image\n";
-                       return;
+               {
+                       wxTextCtrl *text = m_program_romimage_picker->GetTextCtrl();
+                       wxString str_rom = text->GetValue();
+                       if(text->IsEmpty() == true){
+                               *m_log << wxT("Enter filename to ROM image\n");
+                               return;
+                       }
+                       wxChar *t = new wxChar[str_rom.Length() + 1];
+                       STRNCPY(t, str_rom.fn_str(), str_rom.Length() + 1);
+                       f.target = t;
                }
-               strncpy(f.target, str_rom.fn_str(), PROGRAM_TARGET_STR_LENGTH);
-               f.compare = false;
+               f.compare = m_program_compare->GetValue();
                f.testrun = false;
-//あとで struct config_flash の構造を見直す
-//             if(nesfile_load(__FUNCTION__, f.target, &f.rom) == false){
-               if(nesfile_load(__FUNCTION__, str_rom.fn_str(), &f.rom) == false){
-                       *m_log << str_rom << " open error\n";
-                       return;
-               }
+
                if(program_rom_set(
-                       "CPU", m_program_cpu_device->GetStringSelection(), 
+                       m_program_cpu_device->GetStringSelection(), 
                        m_program_cpu_padding->GetSelection(),
-                       &f.rom.cpu_rom, &f.flash_cpu
+                       &f.cpu.memory, &f.cpu.flash
                ) == false){
                        return;
                }
                if(program_rom_set(
-                       "PPU", m_program_ppu_device->GetStringSelection(), 
+                       m_program_ppu_device->GetStringSelection(), 
                        m_program_ppu_padding->GetSelection(),
-                       &f.rom.ppu_rom, &f.flash_ppu
+                       &f.ppu.memory, &f.ppu.flash
                ) == false){
                        return;
                }
 
-               f.reader = &DRIVER_KAZZO;
-               if(f.reader->open_or_close(READER_OPEN) == NG){
-                       *m_log << "reader open error\n";
-                       return;
-               }
+               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(wxString("cancel"));
+               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();
-               f.reader->init();
-/*             if(m_anago_thread != NULL){
-                       delete m_anago_thread;
-               }*/
-               m_anago_thread = new anago_programmer(this, &f);
+
+               m_anago_thread = new anago_programmer(this, &f, m_program_sound_success, m_program_sound_fail);
                if(m_anago_thread->Create() != wxTHREAD_NO_ERROR){
-                       *m_log << "thread creating error";
+                       *m_log << wxT("thread creating error");
                }else if(m_anago_thread->Run() != wxTHREAD_NO_ERROR){
-                       *m_log << "thread running error";
+                       *m_log << wxT("thread running error");
                }else{
                        m_status = STATUS_PROGRAMMING;
                }
        }
+
 protected:
        void dump_button_click(wxCommandEvent& event)
        {
@@ -355,40 +463,129 @@ protected:
        {
                m_log->Clear();
        }
+       
+private:
+       void program_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);
+               }
+       }
+       
 public:
        /** Constructor */
-       anago_frame( wxWindow* parent ) : frame_main(parent)
+       anago_frame(wxWindow* parent, const struct reader_driver *r)
+         : frame_main(parent), 
+#ifdef WIN32
+         m_config_file(wxGetCwd() + wxT("/anago.cfg"))
+#else
+         m_config_file(wxT(".anago"))
+#endif
        {
-               this->script_choice_init(m_dump_script_choice, wxString("*.ad"));
-               this->script_choice_init(m_program_script_choice, wxString("*.af"));
+               wxFileConfig config(wxEmptyString, wxEmptyString, m_config_file);
+               m_reader = r;
+//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);
+                       
+                       config.Read(wxT("program.sound.success"), &m_program_sound_success, wxT("cuckoo.wav"));
+                       config.Read(wxT("program.sound.fail"), &m_program_sound_fail, wxT("doggrowl.wav"));
+
+                       config.Read(wxT("dump.sound.success"), &m_dump_sound_success, wxT("tinkalink2.wav"));
+                       config.Read(wxT("dump.sound.fail"), &m_dump_sound_fail, wxT("doggrowl.wav"));
+               }
+
+//form item init
+               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);
+               {
+                       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 << "warning: flash device parameter not found\n";
+                       *m_log << wxT("warning: flash device parameter not found\n");
                }else{
-                       m_program_cpu_device->Select(0);
-                       m_program_ppu_device->Select(0);
+                       program_device_load(m_program_cpu_device, &config, wxT("program.cpu.device"));
+                       program_device_load(m_program_ppu_device, &config, wxT("program.ppu.device"));
                }
                this->program_padding_init(m_program_cpu_padding);
                this->program_padding_init(m_program_ppu_padding);
                
                m_anago_thread = NULL;
                m_status = STATUS_IDLE;
+
+//version infomation
+               {
+                       struct textcontrol detail;
+                       *m_version_detail << wxT("anago build at ") << wxT(__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");
+               }
+#ifdef WIN32
+               #include "okada.xpm"
+               wxBitmap bitmap_okada(okada);
+               wxString tooltip(wxT(
+                       "緑区 na6ko 町さん (28歳, 童貞)\n\n"
+
+                       "28年間バカにされっぱなし、ミジメ過ぎた俺の人生が anago,\n"
+                       "kazzo を持つようになった途端、突然ツキがめぐってきた。\n"
+//                     "競馬をやれば連戦連勝、夢にまでみた万馬券を当て、気がつくと\n"
+//                     "しんじられない事にギャンブルで稼いだお金が460万円!!\n"
+                       "元手はたった4000円。しかもたった2ヶ月で人生大逆転!!\n"
+                       "女は3P4Pヤリ放題!!"
+//                     "勤めていた新聞屋も辞めギャンブルで\n"
+//                     "身を立てていこうと思っています。実は来月の11日にラスベガスに\n"
+//                     "行き勝負をかけます。結果はまた報告します。宜しく。"
+               ));
+#else
+               #include "taiyo.xpm"
+               wxBitmap bitmap_okada(taiyo);
+               wxString tooltip(wxT("たいよ~ほえ~るず♪"));
+#endif
+//             #include "araki.xpm"
+//             wxBitmap bitmap_okada(araki);
+               m_version_photo->SetBitmap(bitmap_okada);
+               m_version_photo->SetToolTip(tooltip);
+               
+               if(DEBUG==1){
+                       m_dump_romimage_picker->GetTextCtrl()->SetLabel(wxT("t.nes"));
+               }
        }
 
        void DumpThreadFinish(void)
        {
                m_dump_script_choice->Enable();
+               m_dump_script_choice->SetFocus();
                m_dump_romimage_picker->Enable();
                m_dump_check_battery->Enable();
                m_dump_check_forcemapper->Enable();
-               m_dump_button->SetLabel(wxString("&dump"));
+               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();
                }
@@ -398,35 +595,86 @@ public:
        void ProgramThreadFinish(void)
        {
                m_program_script_choice->Enable();
+               m_dump_script_choice->SetFocus();
                m_program_romimage_picker->Enable();
                m_program_compare->Enable();
-               m_program_button->SetLabel(wxString("&program"));
+               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;
        }
+       void LogAppend(const wxChar *t)
+       {
+               *m_log << t;
+       }
+       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);
+               
+               config.Write(wxT("program.cpu.device"), m_program_cpu_device->GetStringSelection());
+               config.Write(wxT("program.ppu.device"), m_program_ppu_device->GetStringSelection());
+       }
 };
 
 
 void *anago_dumper::Entry(void)
 {
-       script_dump_execute(&m_config);
-       m_config.reader->open_or_close(READER_CLOSE);
+       try{
+               if(script_dump_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_frame->LogAppend(t);
+       }
        m_frame->DumpThreadFinish();
        return NULL;
 }
 
 void *anago_programmer::Entry(void)
 {
-       script_flash_execute(&m_config);
-       m_config.reader->open_or_close(READER_CLOSE);
-       nesbuffer_free(&m_config.rom, 0);
+       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_frame->LogAppend(t);
+       }
        m_frame->ProgramThreadFinish();
        return NULL;
 }
 
+#ifndef WIN32
+extern "C"{
+  int anago_cui(int c, wxChar **v);
+}
+int main(int c, wxChar **v)
+{
+       if(c < 3){
+               return wxEntry(c, v);
+       }
+       return anago_cui(c, v);
+}
+#endif
 
 class MyApp : public wxApp
 {
@@ -435,10 +683,18 @@ private:
 public: 
        bool OnInit()
        {
-               m_frame = new anago_frame(NULL);
+               if(DEBUG== 1 && 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