--- nono/wx/wxmainframe.cpp 2026/04/29 17:04:30 1.1.1.2 +++ nono/wx/wxmainframe.cpp 2026/04/29 17:04:51 1.1.1.8 @@ -1,41 +1,55 @@ // // nono -// Copyright (C) 2018 isaki@NetBSD.org +// Copyright (C) 2020 nono project +// Licensed under nono-license.txt // -#include "vm.h" +#include "wxmainframe.h" +#include "wxdumpmonitor.h" +#include "wxhistmonitor.h" +#include "wxlcdwindow.h" +#include "wxlogmonitor.h" +#include "wxmainview.h" +#include "wxmonitor.h" +#include "wxmpumonitor.h" +#include "wxsoftkey.h" +#include "wxtextpanel.h" +#include "wxversion.h" +#include "wxvideomonitor.h" #include "bitmap.h" #include "bt454.h" +#include "debugger.h" +#include "dmac.h" +#include "interrupt.h" #include "keyboard.h" #include "lance.h" #include "lcd.h" +#include "mainapp.h" #include "mfp.h" -#include "mpu.h" +#include "mpu680x0.h" +#include "mpu88xx0.h" #include "netdriver.h" +#include "pio.h" #include "rtc.h" +#include "scc.h" #include "scheduler.h" #include "sio.h" #include "spc.h" -#include "wxheader.h" -#include "wxdumpmonitor.h" -#include "wxlogmonitor.h" -#include "wxmainframe.h" -#include "wxmainview.h" -#include "wxmonitor.h" -#include "wxsoftkey.h" -#include "wxtextpanel.h" -#include "wxvideomonitor.h" +#include "vm.h" static void wxmainframe_poweroff_callback(); +static void wxmainframe_halt_callback(void *); WXMainFrame *gMainFrame; wxBEGIN_EVENT_TABLE(WXMainFrame, inherited) EVT_CREATE(WXMainFrame::OnCreate) + EVT_CLOSE(WXMainFrame::OnClose) EVT_MENU(wxID_EXIT, WXMainFrame::OnExit) EVT_MENU(ID_FULL_SPEED, WXMainFrame::OnFullSpeed) EVT_UPDATE_UI(ID_FULL_SPEED, WXMainFrame::OnFullSpeedUI) + EVT_MENU(ID_RESET_VM, WXMainFrame::OnResetVM) EVT_MENU_RANGE(ID_SCALE_START + 1, ID_SCALE_END - 1, WXMainFrame::OnMenuScale) EVT_UPDATE_UI_RANGE(ID_SCALE_START + 1, ID_SCALE_END - 1, @@ -44,90 +58,145 @@ wxBEGIN_EVENT_TABLE(WXMainFrame, inherit WXMainFrame::OnMenuFontSize) EVT_UPDATE_UI_RANGE(ID_FONTSIZE_START + 1, ID_FONTSIZE_END - 1, WXMainFrame::OnMenuFontSizeUI) + EVT_MENU_RANGE(ID_MONRATE_START + 1, ID_MONRATE_END - 1, + WXMainFrame::OnMenuMonRate) + EVT_UPDATE_UI_RANGE(ID_MONRATE_START + 1, ID_MONRATE_END - 1, + WXMainFrame::OnMenuMonRateUI) EVT_MENU(ID_MOUSEMODE, WXMainFrame::OnMouseMode) EVT_UPDATE_UI(ID_MOUSEMODE, WXMainFrame::OnMouseModeUI) EVT_MENU_RANGE(WinID_Start, WinID_MAX - 1, WXMainFrame::OnWindow) EVT_UPDATE_UI_RANGE(WinID_Start, WinID_MAX - 1, WXMainFrame::OnWindowUI) + EVT_MENU(wxID_ABOUT, WXMainFrame::OnAbout) + + EVT_COMMAND(wxID_ANY, WXW_EVT_HALT_NOTIFY, WXMainFrame::OnHaltNotify) wxEND_EVENT_TABLE() WXMainFrame::WXMainFrame(wxWindow *parent) - : wxFrame(parent, wxID_ANY, wxT("nono")) + : wxFrame(parent, wxID_ANY, "nono", wxDefaultPosition, wxDefaultSize, + wxDEFAULT_FRAME_STYLE & ~wxMAXIMIZE_BOX & ~wxRESIZE_BORDER) { - int vmtype; + vmtype_t vmtype; - vmtype = gVM->GetType(); + vmtype = gMainApp.GetVMType(); // とりあえずメニュー // XXX すぐにメニューファクトリーになる wxMenuBar *menubar = new wxMenuBar(); wxMenu *menuFile = new wxMenu(); // XXX とりあえず適当なところにおいとく - menuFile->Append(ID_FULL_SPEED, wxT("高速モード(&S)"), "", wxITEM_CHECK); - menuFile->Append(wxID_EXIT, wxT("終了(&X)")); - menubar->Append(menuFile, wxT("ファイル(&F)")); + menuFile->Append(ID_FULL_SPEED, _("Full &Speed Mode"), "", wxITEM_CHECK); + menuFile->Append(ID_RESET_VM, _("&Reset VM"), ""); + menuFile->Append(wxID_EXIT, _("E&xit")); + menubar->Append(menuFile, _("&File")); wxMenu *menuDisplay = new wxMenu(); wxMenu *menuViewScale = new wxMenu(); - menuViewScale->Append(ID_SCALE_1_00, wxT("x1.&0"), "", wxITEM_CHECK); - menuViewScale->Append(ID_SCALE_0_75, wxT("x0.&75"), "", wxITEM_CHECK); - menuViewScale->Append(ID_SCALE_0_50, wxT("x0.&5"), "", wxITEM_CHECK); - menuDisplay->AppendSubMenu(menuViewScale, wxT("スケール(&S)")); + menuViewScale->Append(ID_SCALE_1_00, _("x1.&0"), "", wxITEM_CHECK); + menuViewScale->Append(ID_SCALE_0_75, _("x0.&75"), "", wxITEM_CHECK); + menuViewScale->Append(ID_SCALE_0_50, _("x0.&5"), "", wxITEM_CHECK); + menuDisplay->AppendSubMenu(menuViewScale, _("&Scale")); wxMenu *menuFontSize = new wxMenu(); - menuFontSize->AppendRadioItem(ID_FONTSIZE_12, wxT("1&2")); - menuFontSize->AppendRadioItem(ID_FONTSIZE_16, wxT("1&6")); - menuFontSize->AppendRadioItem(ID_FONTSIZE_24, wxT("2&4")); - menuDisplay->AppendSubMenu(menuFontSize, wxT("フォントサイズ(&F)")); - menubar->Append(menuDisplay, wxT("表示(&V)")); + menuFontSize->AppendRadioItem(ID_FONTSIZE_12, "1&2"); + menuFontSize->AppendRadioItem(ID_FONTSIZE_16, "1&6"); + menuDisplay->AppendSubMenu(menuFontSize, _("&Font Size")); + wxMenu *menuMonRate = new wxMenu(); + menuMonRate->AppendRadioItem(ID_MONRATE_20, _("High (&20Hz)")); + menuMonRate->AppendRadioItem(ID_MONRATE_5, _("Middle (&5Hz)")); + menuMonRate->AppendRadioItem(ID_MONRATE_1, _("Low (&1Hz)")); + menuDisplay->AppendSubMenu(menuMonRate, _("&Monitor Speed")); + menubar->Append(menuDisplay, _("&View")); wxMenu *menuDevice = new wxMenu(); - menuDevice->Append(WinID_SOFTKEY, wxT("ソフトウェアキーボード(&K)"), - "", wxITEM_CHECK); - menuDevice->Append(ID_MOUSEMODE, wxT("マウスモード(&M)\tCTRL+F12"), - "", wxITEM_CHECK); - menubar->Append(menuDevice, wxT("デバイス(&D)")); - - wxMenu *menuMonitor = new wxMenu(); - menuMonitor->Append(WinID_MONITOR_SCHEDULER, wxT("スケジューラ(&S)"), - "", wxITEM_CHECK); - menuMonitor->Append(WinID_MONITOR_LOG, wxT("ログ(&L)"), "", wxITEM_CHECK); - menuMonitor->Append(WinID_MONITOR_MPUREG, wxT("MPU レジスタ(&R)"), - "", wxITEM_CHECK); - menuMonitor->Append(WinID_MONITOR_MPUATC, wxT("MPU(&ATC)"), - "", wxITEM_CHECK); - menuMonitor->Append(WinID_MONITOR_MPUBRHIST, wxT("MPU(ブランチ履歴)(&H)"), + menuDevice->Append(WinID_SOFTKEY, _("Software &Keyboard"), "", wxITEM_CHECK); - menuMonitor->Append(WinID_MONITOR_MEMDUMP, wxT("メモリダンプ(&D)"), + menuDevice->Append(ID_MOUSEMODE, _("&Mouse Mode\tCTRL+F12"), "", wxITEM_CHECK); - if (vmtype == VM::TYPE_X68030) { - menuMonitor->Append(WinID_MONITOR_MFP, wxT("&MFP"), "", wxITEM_CHECK); - } - menuMonitor->Append(WinID_MONITOR_SPC, wxT("S&PC"), "", wxITEM_CHECK); - menuMonitor->Append(WinID_MONITOR_RTC, wxT("&RTC"), "", wxITEM_CHECK); - if (vmtype == VM::TYPE_LUNA) { - menuMonitor->Append(WinID_MONITOR_SIO, wxT("S&IO"), "", wxITEM_CHECK); - menuMonitor->Append(WinID_MONITOR_LUNAKEYBOARD, - wxT("キーボード/マウス(&K)"), "", wxITEM_CHECK); - menuMonitor->Append(WinID_MONITOR_LCD, wxT("LCD(&J)"), - "", wxITEM_CHECK); - menuMonitor->Append(WinID_MONITOR_LANCE, wxT("Lance(&E)"), - "", wxITEM_CHECK); - menuMonitor->Append(WinID_MONITOR_BITMAP, wxT("ビットマップ制御(&B)"), - "", wxITEM_CHECK); - menuMonitor->Append(WinID_MONITOR_BITMAP0, wxT("ビットマップ#&0"), + if (gMainApp.HasVMFeature(VMF_LUNA)) { + menuDevice->Append(WinID_LCD, _("Front &LCD"), "", wxITEM_CHECK); } - menuMonitor->Append(WinID_MONITOR_NETDRIVER, wxT("ホストネットワーク(&N)"), - "", wxITEM_CHECK); - menubar->Append(menuMonitor, wxT("モニター(&M)")); + menubar->Append(menuDevice, _("&Device")); + + // 機種によってモニタウィンドウを追加する +#define AppendIf(menu, id, label) do { \ + int id_ = __CONCAT(WinID_MONITOR_,id); \ + const auto& info_ = monitor_info[(id_)]; \ + if (gMainApp.HasVMFeature(info_.feature)) { \ + (menu)->Append((id_), (label), "", wxITEM_CHECK); \ + } \ +} while (0) + + wxMenu *menuMonitor = new wxMenu(); + AppendIf(menuMonitor, SCHEDULER, _("&Scheduler")); + AppendIf(menuMonitor, LOG, _("&Log")); + + wxMenu *menuDebug = new wxMenu(); + AppendIf(menuDebug, BPOINT, _("&Breakpoint")); + AppendIf(menuDebug, BRHIST68K, _("Branch &History")); + AppendIf(menuDebug, BRHIST88K, _("Branch &History")); + AppendIf(menuDebug, EXHIST68K, _("&Exception History")); + AppendIf(menuDebug, EXHIST88K, _("&Exception History")); + menuMonitor->AppendSubMenu(menuDebug, _("&Debug")); + + wxMenu *menuMPU = new wxMenu(); + AppendIf(menuMPU, MPUREG, _("&Register")); + AppendIf(menuMPU, MPUATC, "&ATC"); + AppendIf(menuMPU, CMMU7, "CMMU#7" + _("(Inst)")); + AppendIf(menuMPU, ATC7, "ATC#7"); + AppendIf(menuMPU, CACHE7, _("Cache#7")); + AppendIf(menuMPU, CMMU6, "CMMU#6" + _("(Data)")); + AppendIf(menuMPU, ATC6, "ATC#6"); + AppendIf(menuMPU, CACHE6, _("Cache#6")); + menuMonitor->AppendSubMenu(menuMPU, "MP&U"); + + AppendIf(menuMonitor, MEMDUMP, _("&Memory Dump")); + AppendIf(menuMonitor, INTERRUPT, _("&Interrupt")); + AppendIf(menuMonitor, SPC, "S&PC"); + AppendIf(menuMonitor, RTC, "&RTC"); + AppendIf(menuMonitor, DMAC, "DM&AC"); + AppendIf(menuMonitor, MFP, "M&FP"); + AppendIf(menuMonitor, SCC, "SCC(&Z)"); + AppendIf(menuMonitor, SIO, "SIO(&U)"); + AppendIf(menuMonitor, PIO0, "PIO0"); + AppendIf(menuMonitor, LUNAKEYBOARD, _("&Keyboard/Mouse")); + AppendIf(menuMonitor, LANCE, "Lance(&E)"); + AppendIf(menuMonitor, LCD, "LCD(&J)"); + AppendIf(menuMonitor, BITMAP, _("&Bitmap Control")); + AppendIf(menuMonitor, BITMAP0, _("Bitmap #&0")); + + wxMenu *menuHost = new wxMenu(); + AppendIf(menuHost, HOSTINFO, _("Host &Information")); + AppendIf(menuHost, NETDRIVER, _("Host &Network")); + menuMonitor->AppendSubMenu(menuHost, _("&Host")); + + menubar->Append(menuMonitor, _("&Monitor")); + +#if defined(__WXOSX__) + // OSX では wxID_ABOUT はリンゴメニューに入れるしきたりになっている。 + // Append() すると Quit より下に来てしまうので、Prepend() で上に追加。 + // 今のところヘルプメニューから About ダイアログを抜くとメニューが空に + // なってしまうので、ヘルプメニューの追加ごと抑制する。 + menubar->OSXGetAppleMenu()->Prepend(wxID_ABOUT, _("About nono")); +#else + wxMenu *menuHelp = new wxMenu(); + menuHelp->Append(wxID_ABOUT, _("About nono")); + menubar->Append(menuHelp, _("&Help")); +#endif + SetMenuBar(menubar); wxString title("nono"); switch (vmtype) { - case VM::TYPE_LUNA: + case VMTYPE_X68030: + title += "(X68030)"; + break; + case VMTYPE_LUNA1: title += "(LUNA-I)"; break; - case VM::TYPE_X68030: - title += "(X68030)"; + case VMTYPE_LUNA88K: + title += "(LUNA88K)"; + break; + default: break; } SetTitle(title); @@ -152,6 +221,21 @@ WXMainFrame::WXMainFrame(wxWindow *paren Layout(); Fit(); + // モニタの更新頻度は初期値だけ設定から読んで、あとはここで管理する。 + // 不正値ならデフォルトの 15Hz にしておくか + const ConfigItem& item = gConfig->Find("monitor-rate"); + monitor_rate = item.AsInt(); + if (monitor_rate < 1 || monitor_rate > 60) { + monitor_rate = 15; + } + + // Activate イベントは、このトップレベルウィンドウにウィンドウフォーカスが + // 来た or 外れたことを示すので、wxFrame (というかたぶん wxTopLevelWindow) + // を継承している WXMainFrameに飛んでくるのだが、処理の都合上 WXMainView で + // 扱いたいので、そちらに回す。 + Connect(wxEVT_ACTIVATE, wxActivateEventHandler(WXMainView::OnActivate), + NULL, gMainView); + POST_CREATE(); } @@ -170,15 +254,35 @@ WXMainFrame::OnCreate(wxCommandEvent& ev } } - // 時刻開始? - // なるべく VM が開始する直前にしたい。 - gRTC->InitRTC(); + // VM にコールバックを登録 + gVM->SetPowerOffCallback(wxmainframe_poweroff_callback); + if (gMPU680x0) { + gMPU680x0->SetHaltCallback(wxmainframe_halt_callback, this); + } // VM 実行開始 - gVM->SetPowerOffCallback(wxmainframe_poweroff_callback); gVM->PowerButton(); } +// ウィンドウクローズイベント +void +WXMainFrame::OnClose(wxCloseEvent& event) +{ + // サブウィンドウを全部閉じる + for (int i = 0; i < WinID_MAX; i++) { + if ((bool)windows[i]) { + windows[i]->Close(); + } + } + + // VM を解放 + gVM->Dispose(); + gVM.reset(); + + // 後はデフォルト処理 + event.Skip(); +} + // メニューの「高速モード」イベント void WXMainFrame::OnFullSpeed(wxCommandEvent& event) @@ -200,6 +304,13 @@ WXMainFrame::OnFullSpeedUI(wxUpdateUIEve event.Check(is_fullspeed); } +// メニューの「Reset VM」イベント +void +WXMainFrame::OnResetVM(wxCommandEvent& event) +{ + gScheduler->RequestResetHard(); +} + // メニューの「終了」イベント void WXMainFrame::OnExit(wxCommandEvent& event) @@ -252,32 +363,32 @@ WXMainFrame::OnMenuScaleUI(wxUpdateUIEve void WXMainFrame::OnMenuFontSize(wxCommandEvent& event) { - fontsize_t fontsize; + FontId fontid; - assert(ID_FONTSIZE_12 <= event.GetId() && event.GetId() <= ID_FONTSIZE_24); + assertmsg( + ID_FONTSIZE_12 <= event.GetId() && event.GetId() <= ID_FONTSIZE_16, + "event.GetId()=%d", event.GetId()); switch (event.GetId()) { case ID_FONTSIZE_12: - fontsize = FONT_6x12; + fontid = FontId::_6x12; break; case ID_FONTSIZE_16: - fontsize = FONT_8x16; - break; - case ID_FONTSIZE_24: - fontsize = FONT_12x24; + fontid = FontId::_8x16; break; default: __unreachable(); break; } - if (fontsize != WXTextPanel::global_fontsize) { - WXTextPanel::global_fontsize = fontsize; + if (fontid != WXTextPanel::global_fontid) { + WXTextPanel::global_fontid = fontid; // アクティブなサブウィンドウ全員に通知 for (int i = 0; i < WinID_MAX; i++) { - if (windows[i] != NULL) { - WXSubWindow *subwin = dynamic_cast(windows[i]); - subwin->SetFontSize(fontsize); + if ((bool)windows[i]) { + WXSubWindow *subwin = + dynamic_cast(windows[i].get()); + subwin->SetFontSize(fontid); } } } @@ -287,12 +398,53 @@ WXMainFrame::OnMenuFontSize(wxCommandEve void WXMainFrame::OnMenuFontSizeUI(wxUpdateUIEvent& event) { - fontsize_t current_size = WXTextPanel::global_fontsize; - fontsize_t event_size = (fontsize_t)(event.GetId() - (ID_FONTSIZE_START+1)); + FontId current_size = WXTextPanel::global_fontid; + FontId event_size = (FontId)(event.GetId() - (ID_FONTSIZE_START+1)); event.Check(current_size == event_size); } +// 更新頻度 ID -> 数値 (メニューのテキスト、ID と一致させること) +/*static*/ const int +WXMainFrame::IDtoMonRate[] = { + 20, // ID_MONRATE_20 + 5, // ID_MONRATE_5 + 1, // ID_MONRATE_1 +}; + +// メニューの「表示 > モニタ更新頻度 > *」の共通イベント +void +WXMainFrame::OnMenuMonRate(wxCommandEvent& event) +{ + int id = event.GetId(); + assert(ID_MONRATE_START < id && id < ID_MONRATE_END); + monitor_rate = IDtoMonRate[id - (ID_MONRATE_START + 1)]; + + // アクティブなサブウィンドウのテキストパネル全員に通知 + for (int i = 0; i < WinID_MAX; i++) { + if ((bool)windows[i]) { + auto *subwin = dynamic_cast(windows[i].get()); + for (wxWindow *child : subwin->GetChildren()) { + auto *panel = dynamic_cast(child); + if (panel) { + panel->SetRate(monitor_rate); + } + } + } + } +} + +// メニューの「表示 > モニタ更新頻度 > *」共通 UI +void +WXMainFrame::OnMenuMonRateUI(wxUpdateUIEvent& event) +{ + int id = event.GetId(); + assert(ID_MONRATE_START < id && id < ID_MONRATE_END); + int event_rate = IDtoMonRate[id - (ID_MONRATE_START + 1)]; + + event.Check(monitor_rate == event_rate); +} + // メニューの「デバイス > マウスモード」 void WXMainFrame::OnMouseMode(wxCommandEvent& event) @@ -331,68 +483,123 @@ WXMainFrame::OnWindow(wxCommandEvent& ev void WXMainFrame::DoWindow(int id, bool enable) { + // モニタウィンドウを作成する共通部分 +#define SetMonitor(name, obj) \ + windows[id].reset(new WXMonitorWindow(this, id, (name), *(obj))) + if (enable) { // チェックが入ったのでウィンドウを作成 switch (id) { case WinID_MONITOR_LOG: - windows[id] = new WXLogMonitor(this, id); + windows[id].reset(new WXLogMonitor(this, id)); break; case WinID_MONITOR_SCHEDULER: - windows[id] = new WXMonitorWindow(this, id, wxT("スケジューラ"), - gScheduler); + SetMonitor(_("Scheduler"), gScheduler.get()); break; case WinID_MONITOR_MPUREG: - windows[id] = new WXMonitorWindow(this, id, wxT("MPU レジスタ"), - gMPU); + SetMonitor(_("MPU (Register)"), gMPU.get()); break; case WinID_MONITOR_MPUATC: - windows[id] = new WXMonitorWindow(this, id, wxT("MPU (ATC)"), - gMPUATC); + SetMonitor(_("MPU (ATC)"), gMPUATC.get()); + break; + case WinID_MONITOR_BPOINT: + SetMonitor(_("Breakpoint"), gBreakpointMonitor); + break; + case WinID_MONITOR_BRHIST68K: + windows[id].reset(new WXBranchHistoryMonitor(this, id, + gMPU680x0->GetCPU()->brhist)); + break; + case WinID_MONITOR_BRHIST88K: + windows[id].reset(new WXBranchHistoryMonitor(this, id, + gMPU88xx0->GetCPU()->brhist)); + break; + case WinID_MONITOR_EXHIST68K: + windows[id].reset(new WXExceptionHistoryMonitor(this, id, + gMPU680x0->GetCPU()->exhist)); + break; + case WinID_MONITOR_EXHIST88K: + windows[id].reset(new WXExceptionHistoryMonitor(this, id, + gMPU88xx0->GetCPU()->exhist)); + break; + case WinID_MONITOR_CMMU7: + SetMonitor("CMMU#7" + _("(Inst)"), + &gMPU88xx0->GetCPU()->cmmu[0]); + break; + case WinID_MONITOR_CMMU6: + SetMonitor("CMMU#6" + _("(Data)"), + &gMPU88xx0->GetCPU()->cmmu[1]); + break; + case WinID_MONITOR_ATC7: + SetMonitor("ATC#7" + _("(Inst)"), gMPU88200ATC[0].get()); break; - case WinID_MONITOR_MPUBRHIST: - windows[id] = new WXMonitorWindow(this, id, - wxT("MPU (ブランチ履歴)"), gMPUBrHist); + case WinID_MONITOR_ATC6: + SetMonitor("ATC#6" + _("(Data)"), gMPU88200ATC[1].get()); + break; + case WinID_MONITOR_CACHE7: + windows[id].reset(new WXCacheWindow(this, id, + _("Cache#7") + _("(Inst)"), &gMPU88xx0->GetCPU()->cmmu[0])); + break; + case WinID_MONITOR_CACHE6: + windows[id].reset(new WXCacheWindow(this, id, + _("Cache#6") + _("(Inst)"), &gMPU88xx0->GetCPU()->cmmu[1])); break; case WinID_MONITOR_MEMDUMP: - windows[id] = new WXMemdumpWindow(this, id); + windows[id].reset(new WXMemdumpWindow(this, id)); break; - case WinID_MONITOR_MFP: - windows[id] = new WXMonitorWindow(this, id, wxT("MFP"), gMFP); + case WinID_MONITOR_INTERRUPT: + SetMonitor(_("Interrupt"), gInterrupt.get()); break; case WinID_MONITOR_SPC: - windows[id] = new WXMonitorWindow(this, id, wxT("SPC"), gSPC); + SetMonitor("SPC", gSPC.get()); break; case WinID_MONITOR_RTC: - windows[id] = new WXMonitorWindow(this, id, wxT("RTC"), gRTC); + SetMonitor("RTC", gRTC.get()); + break; + case WinID_MONITOR_DMAC: + SetMonitor("DMAC", gDMAC.get()); + break; + case WinID_MONITOR_MFP: + SetMonitor("MFP", gMFP.get()); + break; + case WinID_MONITOR_SCC: + SetMonitor("SCC", gSCC.get()); break; case WinID_MONITOR_SIO: - windows[id] = new WXMonitorWindow(this, id, wxT("SIO"), gSIO); + SetMonitor("SIO", gSIO.get()); + break; + case WinID_MONITOR_PIO0: + SetMonitor("PIO0", gPIO0.get()); break; case WinID_MONITOR_LUNAKEYBOARD: - windows[id] = new WXMonitorWindow(this, id, - wxT("キーボード/マウス"), gKeyboard); + SetMonitor(_("Keyboard/Mouse"), gKeyboard.get()); break; case WinID_MONITOR_LCD: - windows[id] = new WXMonitorWindow(this, id, wxT("LCD"), gLCD); + windows[id].reset(new WXLCDMonitor(this, id)); break; case WinID_MONITOR_LANCE: - windows[id] = new WXMonitorWindow(this, id, wxT("Lance"), - dynamic_cast(gEthernet)); + SetMonitor("Lance", dynamic_cast(gEthernet.get())); + break; + case WinID_MONITOR_HOSTINFO: + SetMonitor(_("Host Information"), gHostInfo.get()); break; case WinID_MONITOR_NETDRIVER: - windows[id] = new WXMonitorWindow(this, id, - wxT("ホストネットワーク"), gNetDriver); + SetMonitor(_("Host Network"), gNetDriver.get()); break; case WinID_MONITOR_BITMAP: - windows[id] = new WXMonitorWindow(this, id, wxT("ビットマップ制御"), - gBitmap); + SetMonitor(_("Bitmap Control"), gBitmap.get()); break; case WinID_MONITOR_BITMAP0: - windows[id] = new WXLunaBitmapWindow(this, id, - wxT("ビットマップ#0")); + windows[id].reset(new WXLunaBitmapWindow(this, id, _("Bitmap #0"))); break; case WinID_SOFTKEY: - windows[id] = new WXLunaSoftKeyWindow(this, id); + if (gMainApp.GetVMType() == VMTYPE_X68030) { + windows[id].reset(new WXX68kSoftKeyWindow(this, id)); + } else { + windows[id].reset(new WXLunaSoftKeyWindow(this, id)); + } + break; + case WinID_LCD: + windows[id].reset(new WXLCDWindow(this, id)); break; } windows[id]->Show(); @@ -410,7 +617,15 @@ WXMainFrame::OnWindowUI(wxUpdateUIEvent& int id = event.GetId(); // ウィンドウが存在していればチェックを表示 - event.Check((windows[id] != NULL)); + event.Check((bool)windows[id]); +} + +// バージョンダイアログ +void +WXMainFrame::OnAbout(wxCommandEvent& event) +{ + WXVersionDlg dlg(this); + dlg.ShowModal(); } // ウィンドウをリストから削除する @@ -418,8 +633,7 @@ WXMainFrame::OnWindowUI(wxUpdateUIEvent& void WXMainFrame::DeleteWindow(wxWindowID id) { - delete windows[id]; - windows[id] = NULL; + windows[id].reset(); } // VM 電源オフ時に呼ばれるコールバック。 @@ -438,26 +652,71 @@ WXMainFrame::PowerOffCallback() QueueEvent(ev); } +// m680x0 ダブルバスフォールト時に呼ばれるコールバック。 +// step1. グローバル関数で受けて、クラスメンバ関数を呼ぶだけ。 +void +wxmainframe_halt_callback(void *arg) +{ + ((WXMainFrame *)arg)->HaltCallback(); +} + +// m680x0 ダブルバスフォールト処理。 +// step2. クラス内だが VM スレッドなので、ここではイベントをポストするだけ。 +void +WXMainFrame::HaltCallback() +{ + wxCommandEvent *ev = new wxCommandEvent(WXW_EVT_HALT_NOTIFY); + QueueEvent(ev); +} + +// m680x0 ダブルバスフォールト処理 +// step3. ここが本題。でもダイアログを出すだけ。 +void +WXMainFrame::OnHaltNotify(wxCommandEvent& event) +{ + ::wxMessageBox(_("Double bus fault has occurred in VM"), + wxEmptyString, + wxICON_EXCLAMATION); +} + // モニタウィンドウ識別名一覧 -/*static*/ const char * -WXMainFrame::monitor_names[WinID_MAX] = { - "log", // LOG - "scheduler", // SCHEDULER - "mpureg", // MPUREG - "mpuatc", // MPUATC - "mpuhist", // MPUBRHIST - "memdump", // MEMDUMP - "mfp", // MFP - "spc", // SPC - "rtc", // RTC - "sio", // SIO - "keyboard", // LunaKeyboard - "lcd", // LCD - "lance", // LANCE - "bitmap", // BITMAP - "bitmap0", // BITMAP0 - "netdriver", // NETDRIVER - "softkey", // SOFTKEY +// wxmainframe.h の識別子定義と順序を一致させること。 +// brhist は同じ名前だがフラグが異なるので共存できる。 +/*static*/ struct WXMainFrame::monitor_info +WXMainFrame::monitor_info[WinID_MAX] = { + { "log", VMF_ALL }, // LOG + { "scheduler", VMF_ALL }, // SCHEDULER + { "mpureg", VMF_ALL }, // MPUREG + { "mpuatc", VMF_M68K }, // MPUATC + { "breakpoint", VMF_ALL }, // BPOINT + { "brhist", VMF_M68K }, // BRHIST68K + { "brhist", VMF_M88K }, // BRHIST88K + { "exhist", VMF_M68K }, // EXHIST68K + { "exhist", VMF_M88K }, // EXHIST88K + { "cmmu7", VMF_M88K }, // CMMU#7 + { "cmmu6", VMF_M88K }, // CMMU#6 + { "atc7", VMF_M88K }, // ATC#7 + { "atc6", VMF_M88K }, // ATC#6 + { "cache7", VMF_M88K }, // Cache#7 + { "cache6", VMF_M88K }, // Cache#6 + { "memdump", VMF_ALL }, // MEMDUMP + { "interrupt", VMF_ALL }, // INTERRUPT + { "spc", VMF_ALL }, // SPC + { "rtc", VMF_ALL }, // RTC + { "dmac", VMF_X68K }, // DMAC + { "mfp", VMF_X68K }, // MFP + { "scc", VMF_X68K }, // SCC + { "sio", VMF_LUNA }, // SIO + { "pio0", VMF_LUNA }, // PIO0 + { "keyboard", VMF_LUNA }, // LunaKeyboard + { "lcd", VMF_LUNA }, // LCD (Monitor) + { "lance", VMF_LUNA }, // LANCE + { "bitmap", VMF_LUNA }, // BITMAP + { "bitmap0", VMF_LUNA }, // BITMAP0 + { "hostinfo", VMF_ALL }, // HOSTINFO + { "netdriver", VMF_LUNA }, // NETDRIVER + { "softkey", VMF_ALL }, // SOFTKEY + { "lcdpanel", VMF_LUNA }, // LCD (Panel) }; // 起動時にオープンするモニタウィンドウ (-M オプション)