--- nono/wx/wxmainframe.cpp 2026/04/29 17:05:48 1.1.1.23 +++ nono/wx/wxmainframe.cpp 2026/04/29 17:05:58 1.1.1.25 @@ -20,10 +20,12 @@ #include "wxmainview.h" #include "wxmonitor.h" #include "wxmpumonitor.h" +#include "wxpagetablemonitor.h" #include "wxpalettemonitor.h" #include "wxromwindow.h" #include "wxsoftkey.h" #include "wxstatuspanel.h" +#include "wxthreadmonitor.h" #include "wxtvrammonitor.h" #include "wxuimessage.h" #include "wxversion.h" @@ -32,6 +34,7 @@ #include "fdd.h" #include "hostcom.h" #include "hostnet.h" +#include "hostsound.h" #include "mainapp.h" #include "mpu.h" #include "netdriver_slirp.h" @@ -124,6 +127,13 @@ enum { ID_HOSTCOM_DBG_CONSOLE, // 存在しないけど HOSTCOMn と揃える必要がある。 ID_HOSTCOM_DBG_NONE, // 最後に置くこと。 + ID_HOSTSOUND_START, + ID_HOSTSOUND_NETBSD, + ID_HOSTSOUND_SNDIO, + ID_HOSTSOUND_ALSA, + ID_HOSTSOUND_WAV, + ID_HOSTSOUND_NONE, // 最後に置くこと + ID_SCALE_START, ID_SCALE_END = ID_SCALE_START + 6, @@ -225,6 +235,10 @@ wxBEGIN_EVENT_TABLE(WXMainFrame, inherit WXMainFrame::OnMenuHostCom) EVT_UPDATE_UI_RANGE(ID_HOSTCOM0_START + 1, ID_HOSTCOM2_NONE, WXMainFrame::OnMenuHostComUI) + EVT_MENU_RANGE(ID_HOSTSOUND_START + 1, ID_HOSTSOUND_NONE, + WXMainFrame::OnMenuHostSound) + EVT_UPDATE_UI_RANGE(ID_HOSTSOUND_START + 1, ID_HOSTSOUND_NONE, + WXMainFrame::OnMenuHostSoundUI) EVT_MENU_RANGE(ID_SCALE_START, ID_SCALE_END, WXMainFrame::OnMenuScale) @@ -295,6 +309,7 @@ WXMainFrame::WXMainFrame(wxWindow *paren hostcom[i] = gMainApp.FindObject(OBJ_HOSTCOM(i)); } hostcom_dbg = gMainApp.FindObject(OBJ_HOSTCOM_DBG); + hostsound = gMainApp.FindObject(OBJ_HOSTSOUND); // メイン MPU 名を取得。メニューとタイトルによく出てくるので。 // "88xx0" とか "88200" は別処理。 @@ -342,6 +357,7 @@ WXMainFrame::WXMainFrame(wxWindow *paren for (uint i = 0; i < hostcom.size(); i++) { CreateHostComMenu(menuSet, i); } + CreateHostSoundMenu(menuSet); menubar->Append(menuSet, _("&Setting")); // メニュー > 表示 @@ -427,6 +443,7 @@ WXMainFrame::WXMainFrame(wxWindow *paren wxMenu *menuMPU = new wxMenu(); AppendIf(menuMPU, ID_MONITOR_MPUREG, _("&Registers")); AppendIf(menuMPU, ID_MONITOR_MPUATC, "&ATC"); + AppendIf(menuMPU, ID_SUBWIN_MPUPT, _("&Page Table")); AppendIf(menuMPU, ID_MONITOR_MPUCACHE, _("&Caches")); AppendIf(menuMPU, ID_MONITOR_INTERRUPT, _("&Interrupts")); AppendIfSeparator(menuMPU, VMCap::M88K); @@ -526,7 +543,9 @@ WXMainFrame::WXMainFrame(wxWindow *paren AppendIf(menuDev, ID_SUBWIN_LUNAFB, _("Bitmap Plane")); AppendIf(menuDev, ID_SUBWIN_TVRAM, _("Text Screen")); AppendIf(menuDev, ID_SUBWIN_GVRAM, _("Graphic Screen")); + AppendIf(menuDev, ID_MONITOR_SOUND, _("Sound")); AppendIf(menuDev, ID_MONITOR_SSG, "SSG"); + AppendIf(menuDev, ID_MONITOR_ADPCM, "ADPCM"); AppendIf(menuDev, ID_MONITOR_ROMCONS, _("ROM Console (provisional)")); AppendIf(menuDev, ID_SUBWIN_ROM, "ROM"); // LUNA はバスが複数あるので Mainbus Device とする。 @@ -539,6 +558,7 @@ WXMainFrame::WXMainFrame(wxWindow *paren wxMenu *menuHost = new wxMenu(); AppendIf(menuHost, ID_MONITOR_WXHOSTINFO, _("Host &Information")); + AppendIf(menuHost, ID_SUBWIN_THREADS, _("Thread Status")); for (uint i = 0; i < hostnet.size(); i++) { uint id = ID_MONITOR_HOSTNET(i); if (gMonitorManager->Find(id)) { @@ -552,6 +572,7 @@ WXMainFrame::WXMainFrame(wxWindow *paren menuHost->AppendCheckItem(id, GetHostComLabel(i)); } } + AppendIf(menuHost, ID_MONITOR_HOSTSOUND, _("Host Sound")); menuMonitor->AppendSubMenu(menuHost, _("&Host")); wxMenu *menuDebug = new wxMenu(); @@ -616,8 +637,7 @@ WXMainFrame::WXMainFrame(wxWindow *paren // SHOW イベントを最初にも一度起こしたいため // ステータスパネルを一旦非表示にする (これで SHOW(false) イベントが飛ぶ) statuspanel->Hide(); - const ConfigItem& item_show = gConfig->Find("show-statuspanel"); - if (item_show.AsInt() != 0) { + if (gConfig->Find("show-statuspanel").AsBool()) { // 必要なら改めて表示 (これで SHOW(true) イベントが飛ぶ) statuspanel->Show(); } @@ -628,10 +648,10 @@ WXMainFrame::WXMainFrame(wxWindow *paren // 来た or 外れたことを示すので、wxFrame (というかたぶん wxTopLevelWindow) // を継承している WXMainFrameに飛んでくるのだが、処理の都合上 WXMainView で // 扱いたいので、そちらに回す。 - Connect(wxEVT_ACTIVATE, wxActivateEventHandler(WXMainView::OnActivate), - NULL, mainview); + Bind(wxEVT_ACTIVATE, &WXMainView::OnActivate, mainview); // ウィンドウ表示後に続きの処理をするための単発アイドルイベント。 + // こっちは Disconnect() するので Bind() は使えない。 Connect(wxEVT_IDLE, wxIdleEventHandler(WXMainFrame::OnIdle)); // VM からの通知を接続 @@ -645,6 +665,8 @@ WXMainFrame::WXMainFrame(wxWindow *paren wxCommandEventHandler(WXMainFrame::OnHostNetFailed)); WXUIMessage::Connect(UIMessage::HOSTCOM_FAILED, this, wxCommandEventHandler(WXMainFrame::OnHostComFailed)); + WXUIMessage::Connect(UIMessage::HOSTSOUND_FAILED, this, + wxCommandEventHandler(WXMainFrame::OnHostSoundFailed)); if (gMainApp.Has(VMCap::M68K)) { WXUIMessage::Connect(UIMessage::HALT, this, wxCommandEventHandler(WXMainFrame::OnHaltNotify)); @@ -663,6 +685,8 @@ WXMainFrame::~WXMainFrame() wxCommandEventHandler(WXMainFrame::OnHostNetFailed)); WXUIMessage::Disconnect(UIMessage::HOSTCOM_FAILED, this, wxCommandEventHandler(WXMainFrame::OnHostComFailed)); + WXUIMessage::Disconnect(UIMessage::HOSTSOUND_FAILED, this, + wxCommandEventHandler(WXMainFrame::OnHostSoundFailed)); if (gMainApp.Has(VMCap::M68K)) { WXUIMessage::Disconnect(UIMessage::HALT, this, wxCommandEventHandler(WXMainFrame::OnHaltNotify)); @@ -768,6 +792,29 @@ WXMainFrame::CreateHostComMenu(wxMenu *m menuSet->AppendSubMenu(menu, name); } +// HostSound 用のメニューを作成して menuSet に追加する。 +void +WXMainFrame::CreateHostSoundMenu(wxMenu *menuSet) +{ + if (hostsound == NULL) { + return; + } + + wxMenu *menu = new wxMenu(); +#if defined(HAVE_HOSTSOUND_NETBSD) + menu->AppendRadioItem(ID_HOSTSOUND_NETBSD, "&netbsd"); +#endif +#if defined(HAVE_HOSTSOUND_SNDIO) + menu->AppendRadioItem(ID_HOSTSOUND_SNDIO, "&sndio"); +#endif +#if defined(HAVE_HOSTSOUND_ALSA) + menu->AppendRadioItem(ID_HOSTSOUND_ALSA, "&alsa"); +#endif + menu->AppendRadioItem(ID_HOSTSOUND_WAV, "&wav"); + menu->AppendRadioItem(ID_HOSTSOUND_NONE, "&none"); + menuSet->AppendSubMenu(menu, "HostSound"); +} + // リムーバブルデバイス用のメニューを作成して menuDevice に追加する void WXMainFrame::CreateRemovableMenu(wxMenu *menuDevice) @@ -1043,10 +1090,10 @@ WXMainFrame::OnFullSpeed(wxCommandEvent& { if (event.IsChecked()) { // チェックが入ったので、高速モードにする - syncer->RequestFullSpeed(true); + syncer->NotifyFullSpeed(true); } else { // チェックが消えたので、通常モードにする - syncer->RequestFullSpeed(false); + syncer->NotifyFullSpeed(false); } } @@ -1222,6 +1269,49 @@ WXMainFrame::OnMenuHostComUI(wxUpdateUIE event.Check((id == selected)); } +// メニューの「設定 > HostSound > *」の選択肢イベント +void +WXMainFrame::OnMenuHostSound(wxCommandEvent& event) +{ + // 設定を更新。 + std::string line = "hostsound-driver="; + switch (event.GetId()) { + case ID_HOSTSOUND_NETBSD: line += "netbsd"; break; + case ID_HOSTSOUND_SNDIO: line += "sndio"; break; + case ID_HOSTSOUND_ALSA: line += "alsa"; break; + case ID_HOSTSOUND_WAV: line += "wav"; break; + case ID_HOSTSOUND_NONE: line += "none"; break; + default: + assert(false); + } + gConfig->UpdateRunning(line); + + // ホストスレッドに通知。 + hostsound->NotifyReselectDriver(); +} + +// メニューの「設定 > HostSound > *」の UI +void +WXMainFrame::OnMenuHostSoundUI(wxUpdateUIEvent& event) +{ + int id = event.GetId(); + const std::string driver = hostsound->GetDriverName(); + int selected; + if (driver == "netbsd") { + selected = ID_HOSTSOUND_NETBSD; + } else if (driver == "sndio") { + selected = ID_HOSTSOUND_SNDIO; + } else if (driver == "alsa") { + selected = ID_HOSTSOUND_ALSA; + } else if (driver == "wav") { + selected = ID_HOSTSOUND_WAV; + } else { + selected = ID_HOSTSOUND_NONE; + } + + event.Check((id == selected)); +} + // hostnet ドライバ起動失敗のメッセージ。 void WXMainFrame::OnHostNetFailed(wxCommandEvent& event) @@ -1235,6 +1325,7 @@ WXMainFrame::OnHostNetFailed(wxCommandEv HostDriverFailed(hostdev, errmsg); } +// hostcom ドライバ起動失敗のメッセージ。 void WXMainFrame::OnHostComFailed(wxCommandEvent& event) { @@ -1252,6 +1343,16 @@ WXMainFrame::OnHostComFailed(wxCommandEv HostDriverFailed(hostdev, errmsg); } +// hostsound ドライバ起動失敗のメッセージ +void +WXMainFrame::OnHostSoundFailed(wxCommandEvent& event) +{ + wxString errmsg; + + errmsg = hostsound->GetErrmsg(); + HostDriverFailed("hostsound", errmsg); +} + // ホストドライバ起動失敗のメッセージ。 void WXMainFrame::HostDriverFailed(const wxString& hostdev, const wxString& errmsg) @@ -1717,6 +1818,10 @@ WXMainFrame::DoWindow(int id, bool enabl } catch (...) { } break; + case ID_MONITOR_ADPCM: + SetMonitor(id, "ADPCM"); + break; + case ID_MONITOR_AREASET: SetMonitor(id, _("Areaset")); break; @@ -1800,6 +1905,10 @@ WXMainFrame::DoWindow(int id, bool enabl break; } + case ID_MONITOR_HOSTSOUND: + SetMonitor(id, _("Host Sound")); + break; + case ID_MONITOR_INTERRUPT: { wxString name; @@ -1941,6 +2050,10 @@ WXMainFrame::DoWindow(int id, bool enabl SetMonitor(id, _("SLIRP Internal States")); break; + case ID_MONITOR_SOUND: + SetMonitor(id, _("Sound")); + break; + case ID_MONITOR_SPC: SetMonitor(id, "SPC (MB89352)"); break; @@ -2082,6 +2195,23 @@ WXMainFrame::DoWindow(int id, bool enabl break; } + case ID_SUBWIN_MPUPT: + { + wxString name = MPUName() + " " + _("Page Table"); + if (MPUName() == "MC68030") { + try { + windows[id].reset(new WXPageTable68030Window(this, name)); + } catch (...) { } + } else if (MPUName() == "MC68040") { + try { + windows[id].reset(new WXPageTable68040Window(this, name)); + } catch (...) { } + } else { + // not supported + } + break; + } + case ID_SUBWIN_NEWSIO: try { windows[id].reset(new WXScrollMonitorWindow(this, @@ -2110,6 +2240,12 @@ WXMainFrame::DoWindow(int id, bool enabl } catch (...) { } break; + case ID_SUBWIN_THREADS: + try { + windows[id].reset(new WXThreadMonitorWindow(this)); + } catch (...) { } + break; + case ID_SUBWIN_VECTOR: { wxString name = MPUName() + " " + _("Vector Table");