--- nono/wx/wxmainframe.cpp 2026/04/29 17:05:23 1.1.1.17 +++ nono/wx/wxmainframe.cpp 2026/04/29 17:05:40 1.1.1.21 @@ -10,6 +10,7 @@ #include "wxmainframe.h" #include "fontmanager.h" +#include "wxaccstatmonitor.h" #include "wxdipswwindow.h" #include "wxdumpmonitor.h" #include "wxlcdwindow.h" @@ -32,7 +33,8 @@ #include "mpu.h" #include "nmi.h" #include "power.h" -#include "spc.h" +#include "scsidev.h" +#include "scsidomain.h" #include "syncer.h" #include @@ -89,6 +91,8 @@ enum { ID_FONTSIZE_24, ID_FONTSIZE_END, + ID_DEVICE_EMPTY, + ID_MONRATE_START, ID_MONRATE_END = ID_MONRATE_START + 4, @@ -222,12 +226,15 @@ WXMainFrame::WXMainFrame(wxWindow *paren wxDEFAULT_FRAME_STYLE & ~wxMAXIMIZE_BOX & ~wxRESIZE_BORDER) { // デバイスを取得 - mpu = GetMPUDevice(); power = GetPowerDevice(); syncer = GetSyncer(); // デバイスを取得。こっちはあるかどうかを調べる keyboard = gMainApp.FindObject(OBJ_KEYBOARD); + // メイン MPU 名を取得。メニューとタイトルによく出てくるので。 + // "88xx0" とか "88200" は別処理。 + mpuname = GetMPUDevice()->GetMPUName(); + // メニュー wxMenuBar *menubar = new wxMenuBar(); // メニュー > VM @@ -291,7 +298,7 @@ WXMainFrame::WXMainFrame(wxWindow *paren menuFontSize->AppendRadioItem(ID_FONTSIZE_24, "2&4"); menuDisplay->AppendSubMenu(menuFontSize, _("&Font Size")); wxMenu *menuMonRate = new wxMenu(); - user_idx = CreateMonRateTable(); + CreateMonRateTable(); for (int i = 0, end = monrates.size(); i < end; i++) { std::string text; switch (monrates[i]) { @@ -327,6 +334,13 @@ WXMainFrame::WXMainFrame(wxWindow *paren menuOper->AppendCheckItem(ID_KEYBOARD_CONNECT, _("Connect &Keyboard")); menuDevice->AppendSubMenu(menuOper, _("&Operation")); } + // アイテムが何もなければ本当はメニューバーのアイテムを無効にしたいが、 + // それは出来ないっぽい。何かアイテムを置かないと変なパネルが出たりする。 + if (menuDevice->GetMenuItems().IsEmpty()) { + // TRANSLATORS: This is "Device > Nothing" in the menubar. + menuDevice->Append(ID_DEVICE_EMPTY, _("Nothing")); + menuDevice->Enable(ID_DEVICE_EMPTY, false); + } menubar->Append(menuDevice, _("&Device")); #define AppendIfSeparator(menu, vmcap_) do { \ @@ -355,15 +369,20 @@ WXMainFrame::WXMainFrame(wxWindow *paren menuMPU->AppendSeparator(); // MEMDUMPn のラベルは UpdateUI で書き直すのでここでは適当に // 埋めておく。(empty だと怒られる) - for (int i = 0; i < MAX_MEMDUMP_MONITOR; i++) { + for (uint i = 0; i < MAX_MEMDUMP_MONITOR; i++) { AppendIf(menuMPU, ID_MONITOR_MEMDUMP(i), "memdump"); } menuMPU->AppendSeparator(); AppendIf(menuMPU, ID_SUBWIN_BRHIST, _("Branch &History")); AppendIf(menuMPU, ID_SUBWIN_EXHIST, _("&Exception History")); AppendIf(menuMPU, ID_SUBWIN_VECTOR, _("&Vector Table")); - menuMonitor->AppendSubMenu(menuMPU, - (gMainApp.Has(VMCap::M68K) ? "&MPU(MC68030)" : "&MPU(MC88xx0)")); + wxString mpulabel; + if (gMainApp.Has(VMCap::M68K)) { + mpulabel = "&MPU(" + mpuname + ")"; + } else { + mpulabel = "&MPU(MC88xx0)"; + } + menuMonitor->AppendSubMenu(menuMPU, mpulabel); if (gMainApp.Has(VMCap::LUNA)) { wxMenu *menuXP = new wxMenu(); @@ -371,7 +390,7 @@ WXMainFrame::WXMainFrame(wxWindow *paren AppendIf(menuXP, ID_MONITOR_XPINTR, _("&Interrupt")); AppendIf(menuXP, ID_MONITOR_XPIO, _("Internal &Devices")); menuXP->AppendSeparator(); - for (int i = 0; i < MAX_XPMEMDUMP_MONITOR; i++) { + for (uint i = 0; i < MAX_XPMEMDUMP_MONITOR; i++) { AppendIf(menuXP, ID_MONITOR_XPMEMDUMP(i), "memdump"); } menuXP->AppendSeparator(); @@ -406,21 +425,23 @@ WXMainFrame::WXMainFrame(wxWindow *paren AppendIf(menuDev, ID_MONITOR_KEYBOARD, _("Keyboard/Mouse")); AppendIf(menuDev, ID_MONITOR_LANCE, "Lance"); AppendIf(menuDev, ID_MONITOR_NEREID, "Nereid"); - for (int i = 0; i < 2; i++) { - int id = ID_MONITOR_RTL8019AS(i); - wxString name = string_format("Nereid(RTL8019AS) #%d", i); + for (uint i = 0; i < 2; i++) { + uint id = ID_MONITOR_RTL8019AS(i); + wxString name = string_format("Nereid(RTL8019AS) #%u", i); AppendIf(menuDev, id, name); } AppendIf(menuDev, ID_MONITOR_SYSPORT, _("System Port")); AppendIf(menuDev, ID_MONITOR_AREASET, _("Areaset")); AppendIf(menuDev, ID_MONITOR_LCD, "LCD"); AppendIf(menuDev, ID_MONITOR_SYSCLK, _("System Clock")); - for (int i = 0; i < 8; i++) { - int id = ID_MONITOR_VIRTIO_BLOCK(i); - wxString name = _("VirtIO Block") + string_format(" #%d", i); + for (uint i = 0; i < 8; i++) { + uint id = ID_MONITOR_VIRTIO_BLOCK(i); + wxString name = _("VirtIO Block") + string_format(" #%u", i); AppendIf(menuDev, id, name); } AppendIf(menuDev, ID_MONITOR_VIRTIO_NET, _("VirtIO Network")); + AppendIf(menuDev, ID_MONITOR_VIRTIO_SCSI, "VirtIO SCSI"); + AppendIf(menuDev, ID_MONITOR_VIRTIO_ENTROPY,_("VirtIO Entropy")); AppendIf(menuDev, ID_MONITOR_CRTC, "CRTC"); AppendIf(menuDev, ID_MONITOR_LUNAVC, _("Video Control")); AppendIf(menuDev, ID_MONITOR_BT45x, "Bt454/458"); @@ -429,6 +450,7 @@ WXMainFrame::WXMainFrame(wxWindow *paren AppendIf(menuDev, ID_MONITOR_RENDERER, _("Renderer")); AppendIf(menuDev, ID_SUBWIN_LUNAFB, _("Bitmap Plane")); AppendIf(menuDev, ID_SUBWIN_TVRAM, _("Text VRAM")); + AppendIf(menuDev, ID_MONITOR_SSG, "SSG"); AppendIf(menuDev, ID_MONITOR_ROMCONS, _("ROM Console (provisional)")); AppendIf(menuDev, ID_SUBWIN_ROM, "ROM"); // LUNA はバスが複数あるので Mainbus Device とする。 @@ -444,9 +466,9 @@ WXMainFrame::WXMainFrame(wxWindow *paren if (gMainApp.IsX68030()) { // X68030 ではネットワークは最大2つあるのでナンバリングが必要。 // あれば表示ではなく、なければ Disable。 - for (int i = 0; i < 2; i++) { - int id = ID_MONITOR_HOSTNET(i); - wxString name = _("Host Network") + string_format(" #%d", i); + for (uint i = 0; i < 2; i++) { + uint id = ID_MONITOR_HOSTNET(i); + wxString name = _("Host Network") + string_format(" #%u", i); menuHost->AppendCheckItem(id, name); if (gMonitorManager->Find(id) == NULL) { menuHost->Enable(id, false); @@ -456,6 +478,7 @@ WXMainFrame::WXMainFrame(wxWindow *paren // それ以外ではネットワークは1つ固定なのでナンバリング不要 AppendIf(menuHost, ID_MONITOR_HOSTNET(0), _("Host Network")); } + AppendIf(menuHost, ID_MONITOR_SLIRP, _("SLIRP Internal States")); AppendIf(menuHost, ID_MONITOR_HOSTCOM, _("Host &Serial Port")); menuMonitor->AppendSubMenu(menuHost, _("&Host")); @@ -483,14 +506,14 @@ WXMainFrame::WXMainFrame(wxWindow *paren SetMenuBar(menubar); - wxString title("nono"); + frame_title = wxString("nono"); const char *vmname = gMainApp.GetVMName(); if (vmname) { - title += '('; - title += wxString(vmname); - title += ')'; + frame_title += '('; + frame_title += wxString(vmname); + frame_title += ')'; } - SetTitle(title); + SetTitle(frame_title); // UpdateUI イベントは Idle 時に時折チェックされるらしいが、 // (メインビューとサブウィンドウを合わせた) タイマーイベントの粒度が @@ -597,10 +620,10 @@ WXMainFrame::CreateRemovableMenu(wxMenu } // CD, MO - auto spc = gMainApp.FindObject(OBJ_SPC); - if (spc) { + auto scsi = gMainApp.FindObject(OBJ_SCSI); + if (scsi) { for (int id = 0; id < 8; id++) { - scsidev[id] = spc->GetTarget(id); + scsidev[id] = scsi->GetTarget(id); if (scsidev[id]) { menu = CreateSCSIRemovableMenu(id); if (menu) { @@ -993,10 +1016,8 @@ WXMainFrame::monrates { 1, }; -// 「表示 > モニタ更新頻度」のメニュー項目作成に必要な monrates を作成し、 -// ユーザ指定値があれば monrates[] 内のインデックスを返す。 -// ユーザ指定値がなければ -1 を返す。 -int +// 「表示 > モニタ更新頻度」のメニュー項目作成に必要な monrates を作成する。 +void WXMainFrame::CreateMonRateTable() { // 設定ファイル monitor-rate で指定された値を追加。 @@ -1010,16 +1031,7 @@ WXMainFrame::CreateMonRateTable() std::sort(monrates.begin(), monrates.end(), [](int a, int b) { return a > b; } ); - - // ユーザ指定の値が何番目かを返す。指定されてなければ -1。 - for (int i = 0, end = monrates.size(); i < end; i++) { - if (monrates[i] == user_rate) { - return i; - } - } - // 見付からないことはないはずだが } - return -1; } // メニューの「表示 > モニタ更新頻度 > *」の共通イベント @@ -1261,11 +1273,12 @@ WXMainFrame::OnMouseMode(wxCommandEvent& // enable ならチェックを付けようとして呼ばれた bool enable = event.IsChecked(); + wxString new_title = frame_title; if (enable) { // メッセージを表示したい - } else { - // メッセージを表示したい + new_title += " (CTRL + F12 to quit mouse mode)"; } + SetTitle(new_title); // マウスモードを設定 wxCommandEvent newev(NONO_EVT_MOUSEMODE, GetId()); @@ -1310,6 +1323,13 @@ WXMainFrame::OnWindow(wxCommandEvent& ev DoWindow(id, event.IsChecked()); } +#define SetMonitor(id, name) do { \ + try { \ + windows[id].reset(new WXMonitorWindow(this, (name), \ + gMonitorManager->Get(id))); \ + } catch (...) { } \ +} while (0) + void WXMainFrame::DoWindow(int id, bool enable) { @@ -1317,15 +1337,16 @@ WXMainFrame::DoWindow(int id, bool enabl // id はモニター ID であると同時に、windows[] 配列の添字、さらにこの // モニタウィンドウの wxWindowID としても使っている // (WXSubWindow::OnClose() 参照)。 -#define SetMonitor(id, name) \ - windows[id].reset(new WXMonitorWindow(this, (name), \ - gMonitorManager->Get(id))) if (enable) { // チェックが入ったのでウィンドウを作成 switch (id) { case ID_MONITOR_ACCSTAT: - SetMonitor(id, _("Access Status")); + // こいつだけモニタ ID を持ちつつ上位互換のサブウィンドウがある。 + try { + windows[id].reset(new + WXAccStatWindow(this, gMonitorManager->Get(id))); + } catch (...) { } break; case ID_MONITOR_AREASET: @@ -1341,8 +1362,8 @@ WXMainFrame::DoWindow(int id, bool enabl case ID_MONITOR_ATC6: case ID_MONITOR_ATC7: { - int n = id - ID_MONITOR_ATC0; - wxString name(string_format("ATC#%d", n)); + uint n = id - ID_MONITOR_ATC0; + wxString name(string_format("ATC#%u", n)); if ((n & 1) == 0) { name += _("(Data)"); } else { @@ -1369,8 +1390,8 @@ WXMainFrame::DoWindow(int id, bool enabl case ID_MONITOR_CMMU6: case ID_MONITOR_CMMU7: { - int n = id - ID_MONITOR_CMMU0; - wxString name(string_format("CMMU#%d", n)); + uint n = id - ID_MONITOR_CMMU0; + wxString name(string_format("CMMU#%u", n)); if ((n & 1) == 0) { name += _("(Data)"); } else { @@ -1401,8 +1422,8 @@ WXMainFrame::DoWindow(int id, bool enabl { wxString name = _("Host Network"); if (gMainApp.IsX68030()) { - int n = id - ID_MONITOR_HOSTNET0; - name += string_format(" #%d", n); + uint n = id - ID_MONITOR_HOSTNET0; + name += string_format(" #%u", n); } SetMonitor(id, name); break; @@ -1430,7 +1451,9 @@ WXMainFrame::DoWindow(int id, bool enabl break; case ID_MONITOR_LCD: - windows[id].reset(new WXLCDMonitor(this)); + try { + windows[id].reset(new WXLCDMonitor(this)); + } catch (...) { } break; case ID_MONITOR_LUNAVC: @@ -1454,7 +1477,9 @@ WXMainFrame::DoWindow(int id, bool enabl case ID_MONITOR_XPMEMDUMP0 ... ID_MONITOR_XPMEMDUMP(MAX_XPMEMDUMP_MONITOR - 1): { - windows[id].reset(new WXMemdumpWindow(this, id)); + try { + windows[id].reset(new WXMemdumpWindow(this, id)); + } catch (...) { } break; } @@ -1513,8 +1538,8 @@ WXMainFrame::DoWindow(int id, bool enabl case ID_MONITOR_RTL8019AS0: case ID_MONITOR_RTL8019AS1: { - int n = id - ID_MONITOR_RTL8019AS0; - wxString name = string_format("Nereid (RTL8019AS) #%d", n); + uint n = id - ID_MONITOR_RTL8019AS0; + wxString name = string_format("Nereid (RTL8019AS) #%u", n); SetMonitor(id, name); break; } @@ -1535,10 +1560,18 @@ WXMainFrame::DoWindow(int id, bool enabl SetMonitor(id, "SIO (uPD7201)"); break; + case ID_MONITOR_SLIRP: + SetMonitor(id, _("SLIRP Internal States")); + break; + case ID_MONITOR_SPC: SetMonitor(id, "SPC (MB89352)"); break; + case ID_MONITOR_SSG: + SetMonitor(id, "SSG (YM2149)"); + break; + case ID_MONITOR_SYSCLK: SetMonitor(id, _("System Clock")); break; @@ -1550,8 +1583,8 @@ WXMainFrame::DoWindow(int id, bool enabl case ID_MONITOR_VIRTIO_BLOCK0 ... ID_MONITOR_VIRTIO_BLOCK7: { - int n = id - ID_MONITOR_VIRTIO_BLOCK0; - wxString name = _("VirtIO Block") + string_format(" #%d", n); + uint n = id - ID_MONITOR_VIRTIO_BLOCK0; + wxString name = _("VirtIO Block") + string_format(" #%u", n); SetMonitor(id, name); break; } @@ -1560,6 +1593,14 @@ WXMainFrame::DoWindow(int id, bool enabl SetMonitor(id, _("VirtIO Network")); break; + case ID_MONITOR_VIRTIO_SCSI: + SetMonitor(id, "VirtIO SCSI"); + break; + + case ID_MONITOR_VIRTIO_ENTROPY: + SetMonitor(id, _("VirtIO Entropy")); + break; + case ID_MONITOR_WXHOSTINFO: SetMonitor(id, _("Host Information")); break; @@ -1579,16 +1620,20 @@ WXMainFrame::DoWindow(int id, bool enabl case ID_SUBWIN_BRHIST: { wxString name = MPUName() + " " + _("Branch History"); - windows[id].reset(new WXScrollMonitorWindow(this, name, - gMonitorManager->Get(id))); + try { + windows[id].reset(new WXScrollMonitorWindow(this, name, + gMonitorManager->Get(id))); + } catch (...) { } break; } case ID_SUBWIN_EXHIST: { wxString name = MPUName() + " " + _("Exception History"); - windows[id].reset(new WXScrollMonitorWindow(this, name, - gMonitorManager->Get(id))); + try { + windows[id].reset(new WXScrollMonitorWindow(this, name, + gMonitorManager->Get(id))); + } catch (...) { } break; } @@ -1601,31 +1646,43 @@ WXMainFrame::DoWindow(int id, bool enabl case ID_SUBWIN_CACHE6: case ID_SUBWIN_CACHE7: { - int n = id - ID_SUBWIN_CACHE0; + uint n = id - ID_SUBWIN_CACHE0; wxString name = _("Cache"); - name += string_format("#%d", n); + name += string_format("#%u", n); if ((n & 1) == 0) { name += _("(Data)"); } else { name += _("(Inst)"); } - windows[id].reset(new WXCacheWindow(this, name, - gMonitorManager->Get(id))); + try { + windows[id].reset(new WXCacheWindow(this, name, + gMonitorManager->Get(id))); + } catch (...) { } break; } case ID_SUBWIN_DIPSW: - windows[id].reset(new WXDipswWindow(this)); + try { + windows[id].reset(new WXDipswWindow(this)); + } catch (...) { } break; case ID_SUBWIN_LCDPANEL: - windows[id].reset(new WXLCDWindow(this)); + try { + windows[id].reset(new WXLCDWindow(this)); + } catch (...) { } break; + case ID_SUBWIN_LOG: - windows[id].reset(new WXLogMonitor(this)); + try { + windows[id].reset(new WXLogMonitor(this)); + } catch (...) { } break; + case ID_SUBWIN_LOGSETTING: - windows[id].reset(new WXLogSettingWindow(this)); + try { + windows[id].reset(new WXLogSettingWindow(this)); + } catch (...) { } break; case ID_SUBWIN_LUNAFB: @@ -1638,17 +1695,19 @@ WXMainFrame::DoWindow(int id, bool enabl } else { name = _("Text VRAM"); } - windows[id].reset(new WXPlaneVRAMWindow(this, name)); + try { + windows[id].reset(new WXPlaneVRAMWindow(this, name)); + } catch (...) { } break; } case ID_SUBWIN_NEWSIO: - { - windows[id].reset(new WXScrollMonitorWindow(this, - _("Device Map (NEWS)"), - gMonitorManager->Get(id))); + try { + windows[id].reset(new WXScrollMonitorWindow(this, + _("Device Map (NEWS)"), + gMonitorManager->Get(id))); + } catch (...) { } break; - } case ID_SUBWIN_PALETTE: case ID_SUBWIN_TEXTPAL: @@ -1660,47 +1719,60 @@ WXMainFrame::DoWindow(int id, bool enabl } else { name = _("Palette Colormap"); } - windows[id].reset(new WXPaletteWindow(this, name)); + try { + windows[id].reset(new WXPaletteWindow(this, name)); + } catch (...) { } break; } case ID_SUBWIN_ROM: - windows[id].reset(new WXROMWindow(this)); + try { + windows[id].reset(new WXROMWindow(this)); + } catch (...) { } break; case ID_SUBWIN_SOFTKEY: - windows[id].reset(new WXSoftKeyWindow(this, gMainApp.GetVMType())); + try { + windows[id].reset(new WXSoftKeyWindow(this, + gMainApp.GetVMType())); + } catch (...) { } break; case ID_SUBWIN_VECTOR: { wxString name = MPUName() + " " + _("Vector Table"); - windows[id].reset(new WXScrollMonitorWindow(this, name, - gMonitorManager->Get(id))); + try { + windows[id].reset(new WXScrollMonitorWindow(this, name, + gMonitorManager->Get(id))); + } catch (...) { } break; } case ID_SUBWIN_X68KIO: - { - windows[id].reset(new WXScrollMonitorWindow(this, - _("Device Map (24bit space)"), - gMonitorManager->Get(id))); + try { + windows[id].reset(new WXScrollMonitorWindow(this, + _("Device Map (24bit space)"), + gMonitorManager->Get(id))); + } catch (...) { } break; - } case ID_SUBWIN_XPBRHIST: { wxString name = "HD647180 " + _("Branch History"); - windows[id].reset(new WXScrollMonitorWindow(this, name, - gMonitorManager->Get(id))); + try { + windows[id].reset(new WXScrollMonitorWindow(this, name, + gMonitorManager->Get(id))); + } catch (...) { } break; } case ID_SUBWIN_XPEXHIST: { wxString name = "HD647180 " + _("Exception History"); - windows[id].reset(new WXScrollMonitorWindow(this, name, - gMonitorManager->Get(id))); + try { + windows[id].reset(new WXScrollMonitorWindow(this, name, + gMonitorManager->Get(id))); + } catch (...) { } break; } @@ -1728,18 +1800,18 @@ WXMainFrame::OnWindowUI(wxUpdateUIEvent& // メニューに現在のアドレスを載せる // (ウィンドウの生存期間外にも呼ばれることに注意) auto mon = gMonitorManager->Get(id); - auto *memdump = dynamic_cast(mon.obj); + auto *memdump = dynamic_cast(mon->obj); assert(memdump); - uint32 addr = memdump->GetAddr(); + uint32 addr = memdump->GetAddr().Addr(); - int n; + uint n; wxString text = _("Memory Dump"); if (IS_MONITOR_XPMEMDUMP(id)) { n = id - ID_MONITOR_XPMEMDUMP0; - text += string_format(" &%d: $%05x", n, addr); + text += string_format(" &%u: $%05x", n, addr); } else { n = id - ID_MONITOR_MEMDUMP0; - text += string_format(" &%d: $%08x", n, addr); + text += string_format(" &%u: $%08x", n, addr); } event.SetText(text); } @@ -1826,14 +1898,6 @@ WXMainFrame::DeleteWindow(wxWindow *win) } } -// メイン MPU 名を返す。メニューとタイトルによく出てくるので。 -// 88xx0 とか 88200 は別処理。 -wxString -WXMainFrame::MPUName() const -{ - return mpu->GetMPUName(); -} - // m680x0 ダブルバスフォールト処理 void WXMainFrame::OnHaltNotify(wxCommandEvent& event)