|
|
1.1 root 1: //
2: // nono
1.1.1.4 root 3: // Copyright (C) 2020 nono project
4: // Licensed under nono-license.txt
1.1 root 5: //
6:
1.1.1.4 root 7: #include "wxmainframe.h"
8: #include "wxdumpmonitor.h"
1.1.1.5 root 9: #include "wxhistmonitor.h"
10: #include "wxlcdwindow.h"
1.1.1.4 root 11: #include "wxlogmonitor.h"
12: #include "wxmainview.h"
13: #include "wxmonitor.h"
14: #include "wxmpumonitor.h"
15: #include "wxsoftkey.h"
1.1.1.9 root 16: #include "wxstatuspanel.h"
1.1.1.4 root 17: #include "wxtextpanel.h"
1.1.1.11! root 18: #include "wxuimessage.h"
1.1.1.4 root 19: #include "wxversion.h"
20: #include "wxvideomonitor.h"
1.1.1.5 root 21: #include "debugger.h"
1.1.1.3 root 22: #include "mainapp.h"
1.1.1.4 root 23: #include "mpu680x0.h"
24: #include "mpu88xx0.h"
1.1 root 25: #include "netdriver.h"
26: #include "scheduler.h"
1.1.1.11! root 27: #include "spc.h"
1.1.1.4 root 28: #include "vm.h"
1.1 root 29:
30: WXMainFrame *gMainFrame;
31:
32: wxBEGIN_EVENT_TABLE(WXMainFrame, inherited)
1.1.1.3 root 33: EVT_CLOSE(WXMainFrame::OnClose)
1.1 root 34: EVT_MENU(wxID_EXIT, WXMainFrame::OnExit)
35:
36: EVT_MENU(ID_FULL_SPEED, WXMainFrame::OnFullSpeed)
37: EVT_UPDATE_UI(ID_FULL_SPEED, WXMainFrame::OnFullSpeedUI)
1.1.1.9 root 38: EVT_MENU(ID_RESTART_VM, WXMainFrame::OnRestartVM)
1.1 root 39: EVT_MENU_RANGE(ID_SCALE_START + 1, ID_SCALE_END - 1,
40: WXMainFrame::OnMenuScale)
41: EVT_UPDATE_UI_RANGE(ID_SCALE_START + 1, ID_SCALE_END - 1,
42: WXMainFrame::OnMenuScaleUI)
43: EVT_MENU_RANGE(ID_FONTSIZE_START + 1, ID_FONTSIZE_END - 1,
44: WXMainFrame::OnMenuFontSize)
45: EVT_UPDATE_UI_RANGE(ID_FONTSIZE_START + 1, ID_FONTSIZE_END - 1,
46: WXMainFrame::OnMenuFontSizeUI)
1.1.1.5 root 47: EVT_MENU_RANGE(ID_MONRATE_START + 1, ID_MONRATE_END - 1,
48: WXMainFrame::OnMenuMonRate)
49: EVT_UPDATE_UI_RANGE(ID_MONRATE_START + 1, ID_MONRATE_END - 1,
50: WXMainFrame::OnMenuMonRateUI)
1.1.1.9 root 51: EVT_MENU(ID_SHOW_STATPANEL, WXMainFrame::OnShowStatusPanel)
52: EVT_UPDATE_UI(ID_SHOW_STATPANEL, WXMainFrame::OnShowStatusPanelUI)
1.1.1.11! root 53: EVT_MENU_RANGE(ID_CD_INSERT_0, ID_CD_INSERT_7,
! 54: WXMainFrame::OnCDInsert)
! 55: EVT_UPDATE_UI_RANGE(ID_CD_INSERT_0, ID_CD_INSERT_7,
! 56: WXMainFrame::OnCDInsertUI)
! 57: EVT_MENU_RANGE(ID_CD_EJECT_0, ID_CD_EJECT_7,
! 58: WXMainFrame::OnCDEject)
! 59: EVT_UPDATE_UI_RANGE(ID_CD_EJECT_0, ID_CD_EJECT_7,
! 60: WXMainFrame::OnCDEjectUI)
! 61: EVT_MENU_RANGE(ID_CD_FORCE_0, ID_CD_FORCE_7,
! 62: WXMainFrame::OnCDForce)
! 63: EVT_UPDATE_UI_RANGE(ID_CD_FORCE_0, ID_CD_FORCE_7,
! 64: WXMainFrame::OnCDForceUI)
1.1.1.2 root 65: EVT_MENU(ID_MOUSEMODE, WXMainFrame::OnMouseMode)
66: EVT_UPDATE_UI(ID_MOUSEMODE, WXMainFrame::OnMouseModeUI)
1.1.1.9 root 67: EVT_MENU(ID_RESET_BUTTON, WXMainFrame::OnResetButton)
1.1.1.10 root 68: EVT_MENU_RANGE(0, ID_SUBWIN_END, WXMainFrame::OnWindow)
69: EVT_UPDATE_UI_RANGE(0, ID_SUBWIN_END, WXMainFrame::OnWindowUI)
1.1.1.4 root 70: EVT_MENU(wxID_ABOUT, WXMainFrame::OnAbout)
1.1 root 71: wxEND_EVENT_TABLE()
72:
73: WXMainFrame::WXMainFrame(wxWindow *parent)
1.1.1.10 root 74: : inherited(parent, wxID_ANY, "nono", wxDefaultPosition, wxDefaultSize,
1.1.1.6 root 75: wxDEFAULT_FRAME_STYLE & ~wxMAXIMIZE_BOX & ~wxRESIZE_BORDER)
1.1 root 76: {
1.1.1.3 root 77: vmtype_t vmtype;
78: vmtype = gMainApp.GetVMType();
1.1 root 79:
80: // とりあえずメニュー
81: // XXX すぐにメニューファクトリーになる
82: wxMenuBar *menubar = new wxMenuBar();
83: wxMenu *menuFile = new wxMenu();
84: // XXX とりあえず適当なところにおいとく
1.1.1.4 root 85: menuFile->Append(ID_FULL_SPEED, _("Full &Speed Mode"), "", wxITEM_CHECK);
1.1.1.9 root 86: menuFile->AppendSeparator();
87: menuFile->Append(ID_RESTART_VM, _("&Restart VM"), "");
1.1.1.4 root 88: menuFile->Append(wxID_EXIT, _("E&xit"));
89: menubar->Append(menuFile, _("&File"));
1.1 root 90:
91: wxMenu *menuDisplay = new wxMenu();
92: wxMenu *menuViewScale = new wxMenu();
1.1.1.4 root 93: menuViewScale->Append(ID_SCALE_1_00, _("x1.&0"), "", wxITEM_CHECK);
94: menuViewScale->Append(ID_SCALE_0_75, _("x0.&75"), "", wxITEM_CHECK);
95: menuViewScale->Append(ID_SCALE_0_50, _("x0.&5"), "", wxITEM_CHECK);
96: menuDisplay->AppendSubMenu(menuViewScale, _("&Scale"));
1.1 root 97: wxMenu *menuFontSize = new wxMenu();
1.1.1.4 root 98: menuFontSize->AppendRadioItem(ID_FONTSIZE_12, "1&2");
99: menuFontSize->AppendRadioItem(ID_FONTSIZE_16, "1&6");
100: menuDisplay->AppendSubMenu(menuFontSize, _("&Font Size"));
1.1.1.5 root 101: wxMenu *menuMonRate = new wxMenu();
102: menuMonRate->AppendRadioItem(ID_MONRATE_20, _("High (&20Hz)"));
103: menuMonRate->AppendRadioItem(ID_MONRATE_5, _("Middle (&5Hz)"));
104: menuMonRate->AppendRadioItem(ID_MONRATE_1, _("Low (&1Hz)"));
105: menuDisplay->AppendSubMenu(menuMonRate, _("&Monitor Speed"));
1.1.1.9 root 106: menuDisplay->Append(ID_SHOW_STATPANEL, _("Show Status &Panel"), "",
107: wxITEM_CHECK);
1.1.1.4 root 108: menubar->Append(menuDisplay, _("&View"));
1.1 root 109:
110: wxMenu *menuDevice = new wxMenu();
1.1.1.11! root 111: CreateRemovableMenu(menuDevice);
1.1.1.10 root 112: menuDevice->Append(ID_SUBWIN_SOFTKEY, _("Software &Keyboard"),
1.1.1.2 root 113: "", wxITEM_CHECK);
1.1.1.4 root 114: menuDevice->Append(ID_MOUSEMODE, _("&Mouse Mode\tCTRL+F12"),
1.1.1.2 root 115: "", wxITEM_CHECK);
1.1.1.5 root 116: if (gMainApp.HasVMFeature(VMF_LUNA)) {
1.1.1.10 root 117: menuDevice->Append(ID_SUBWIN_LCDPANEL, _("Front &LCD"),
1.1.1.5 root 118: "", wxITEM_CHECK);
119: }
1.1.1.9 root 120: menuDevice->AppendSeparator();
1.1.1.10 root 121: wxMenu *menuOper = new wxMenu();
122: menuOper->Append(ID_RESET_BUTTON, _("Push &Reset button"));
123: menuDevice->AppendSubMenu(menuOper, _("Operation"));
1.1.1.4 root 124: menubar->Append(menuDevice, _("&Device"));
125:
126: // 機種によってモニタウィンドウを追加する
127: #define AppendIf(menu, id, label) do { \
1.1.1.10 root 128: vmf_t feature_ = gMonitorManager.GetFeature(id); \
129: if (gMainApp.HasVMFeature(feature_)) { \
130: (menu)->Append((id), (label), "", wxITEM_CHECK); \
131: } \
132: } while (0)
133: #define AppendIfSeparator(menu, feature_) do { \
134: if (gMainApp.HasVMFeature(feature_)) { \
135: (menu)->AppendSeparator(); \
1.1.1.4 root 136: } \
137: } while (0)
1.1 root 138:
139: wxMenu *menuMonitor = new wxMenu();
1.1.1.10 root 140: AppendIf(menuMonitor, ID_MONITOR_SCHEDULER, _("&Scheduler"));
141: AppendIf(menuMonitor, ID_SUBWIN_LOG, _("&Log"));
1.1.1.4 root 142:
1.1.1.5 root 143: wxMenu *menuDebug = new wxMenu();
1.1.1.10 root 144: AppendIf(menuDebug, ID_MONITOR_BREAKPOINT, _("&Breakpoint"));
145: AppendIf(menuDebug, ID_SUBWIN_BRHIST, _("Branch &History"));
146: AppendIf(menuDebug, ID_SUBWIN_EXHIST, _("&Exception History"));
1.1.1.5 root 147: menuMonitor->AppendSubMenu(menuDebug, _("&Debug"));
148:
1.1.1.4 root 149: wxMenu *menuMPU = new wxMenu();
1.1.1.10 root 150: AppendIf(menuMPU, ID_MONITOR_MPUREG, _("&Register"));
151: AppendIf(menuMPU, ID_MONITOR_MPUATC, "&ATC");
152: AppendIfSeparator(menuMPU, VMF_M88K);
153: AppendIf(menuMPU, ID_MONITOR_CMMU7, "CMMU#7" + _("(Inst)"));
154: AppendIf(menuMPU, ID_MONITOR_ATC7, "ATC#7");
155: AppendIf(menuMPU, ID_SUBWIN_CACHE7, _("Cache") + "#7");
156: AppendIfSeparator(menuMPU, VMF_M88K);
157: AppendIf(menuMPU, ID_MONITOR_CMMU6, "CMMU#6" + _("(Data)"));
158: AppendIf(menuMPU, ID_MONITOR_ATC6, "ATC#6");
159: AppendIf(menuMPU, ID_SUBWIN_CACHE6, _("Cache") + "#6");
160: menuMonitor->AppendSubMenu(menuMPU, "MP&U");
161:
162: wxMenu *menuMemdump = new wxMenu();
163: // MEMDUMPn のラベルは UpdateUI で書き直すのでここでは適当に埋めておく。
164: // (empty だと怒られる)
165: // MONITOR_RTC は X68k の RTC、LUNA では MONITOR_MK48T02 だが今の所
166: // NVRAM 側のことは表示してないのでラベルも RTC にしてある。
167: for (int i = 0; i < MAX_MEMDUMP_MONITOR; i++) {
168: AppendIf(menuMemdump, ID_MONITOR_MEMDUMP0 + i, "memdump");
169: }
170: menuMonitor->AppendSubMenu(menuMemdump, _("&Memory Dump"));
171: AppendIf(menuMonitor, ID_MONITOR_INTERRUPT, _("&Interrupt"));
172: AppendIf(menuMonitor, ID_MONITOR_SPC, "S&PC");
1.1.1.11! root 173: AppendIf(menuMonitor, ID_MONITOR_SCSIDEVS, _("SCSI Devices"));
1.1.1.10 root 174: AppendIf(menuMonitor, ID_MONITOR_RTC, "&RTC");
175: AppendIf(menuMonitor, ID_MONITOR_MK48T02, "&RTC");
176: AppendIf(menuMonitor, ID_MONITOR_DMAC, "DM&AC");
177: AppendIf(menuMonitor, ID_MONITOR_MFP, "M&FP");
178: AppendIf(menuMonitor, ID_MONITOR_SCC, "SCC(&Z)");
179: AppendIf(menuMonitor, ID_MONITOR_SIO, "SIO(&U)");
180: AppendIf(menuMonitor, ID_MONITOR_PIO0, "PIO0");
181: AppendIf(menuMonitor, ID_MONITOR_KEYBOARD, _("&Keyboard/Mouse"));
182: AppendIf(menuMonitor, ID_MONITOR_LANCE, "Lance(&E)");
183: AppendIf(menuMonitor, ID_MONITOR_LCD, "LCD(&J)");
184: AppendIf(menuMonitor, ID_MONITOR_SYSCLK, _("S&ystem Clock"));
185: AppendIf(menuMonitor, ID_MONITOR_LUNAFB, _("&Bitmap Control"));
186: AppendIf(menuMonitor, ID_SUBWIN_LUNAFB0, _("Bitmap #&0"));
1.1.1.5 root 187:
188: wxMenu *menuHost = new wxMenu();
1.1.1.10 root 189: AppendIf(menuHost, ID_MONITOR_WXHOSTINFO, _("Host &Information"));
190: AppendIf(menuHost, ID_MONITOR_HOSTNET, _("Host &Network"));
1.1.1.5 root 191: menuMonitor->AppendSubMenu(menuHost, _("&Host"));
192:
1.1.1.4 root 193: menubar->Append(menuMonitor, _("&Monitor"));
194:
195: #if defined(__WXOSX__)
196: // OSX では wxID_ABOUT はリンゴメニューに入れるしきたりになっている。
197: // Append() すると Quit より下に来てしまうので、Prepend() で上に追加。
198: // 今のところヘルプメニューから About ダイアログを抜くとメニューが空に
199: // なってしまうので、ヘルプメニューの追加ごと抑制する。
200: menubar->OSXGetAppleMenu()->Prepend(wxID_ABOUT, _("About nono"));
201: #else
202: wxMenu *menuHelp = new wxMenu();
203: menuHelp->Append(wxID_ABOUT, _("About nono"));
204: menubar->Append(menuHelp, _("&Help"));
205: #endif
206:
1.1 root 207: SetMenuBar(menubar);
208:
209: wxString title("nono");
210: switch (vmtype) {
1.1.1.3 root 211: case VMTYPE_X68030:
212: title += "(X68030)";
213: break;
1.1.1.4 root 214: case VMTYPE_LUNA1:
1.1 root 215: title += "(LUNA-I)";
216: break;
1.1.1.3 root 217: case VMTYPE_LUNA88K:
218: title += "(LUNA88K)";
219: break;
220: default:
1.1 root 221: break;
222: }
223: SetTitle(title);
224:
225: // UpdateUI イベントは Idle 時に時折チェックされるらしいが、
226: // (メインビューとサブウィンドウを合わせた) タイマーイベントの粒度が
227: // 小さいためか、秒間120回とかいうレベルで UpdateUIEvent が飛んでくる
228: // っぽい (全タイマーをとめたら治る模様)。
229: // さすがにそんなに来られても気持ち悪いのと、どうせメニュー開いた瞬間
230: // 表示しようとする前には一度飛んでくるのだから、アイドル時のチェックは
231: // いらない気がする。間隔広げておいても、ぱっと見副作用はなさそうだけど
232: // 念のため事象が分かりやすいように 10秒くらいにしておく。
233: wxUpdateUIEvent::SetUpdateInterval(10000);
234:
235: wxBoxSizer *vbox = new wxBoxSizer(wxVERTICAL);
236:
1.1.1.10 root 237: // WXStatusPanel コンストラクタが gMainView を参照するので
238: // gMainView のほうを先に作成すること。
239: gMainView = new WXMainView(this);
1.1.1.9 root 240: gStatusPanel = new WXStatusPanel(this);
241: vbox->Add(gStatusPanel, 0, wxEXPAND);
1.1 root 242: vbox->Add(gMainView, 1, wxEXPAND | wxFIXED_MINSIZE);
243:
1.1.1.9 root 244: // SHOW イベントを最初にも一度起こしたいため
245: // ステータスパネルを一旦非表示にする (これで SHOW(false) イベントが飛ぶ)
246: gStatusPanel->Hide();
247: const ConfigItem& item_show = gConfig->Find("show-statuspanel");
248: if (item_show.AsInt() != 0) {
249: // 必要なら改めて表示 (これで SHOW(true) イベントが飛ぶ)
250: gStatusPanel->Show();
251: }
252:
1.1 root 253: SetSizer(vbox);
254:
255: Fit();
256:
1.1.1.5 root 257: // モニタの更新頻度は初期値だけ設定から読んで、あとはここで管理する。
258: // 不正値ならデフォルトの 15Hz にしておくか
1.1.1.9 root 259: const ConfigItem& item_rate = gConfig->Find("monitor-rate");
260: monitor_rate = item_rate.AsInt();
1.1.1.5 root 261: if (monitor_rate < 1 || monitor_rate > 60) {
262: monitor_rate = 15;
263: }
264:
1.1.1.4 root 265: // Activate イベントは、このトップレベルウィンドウにウィンドウフォーカスが
266: // 来た or 外れたことを示すので、wxFrame (というかたぶん wxTopLevelWindow)
267: // を継承している WXMainFrameに飛んでくるのだが、処理の都合上 WXMainView で
268: // 扱いたいので、そちらに回す。
269: Connect(wxEVT_ACTIVATE, wxActivateEventHandler(WXMainView::OnActivate),
270: NULL, gMainView);
271:
1.1.1.11! root 272: // ウィンドウ表示後に続きの処理をするための単発アイドルイベント。
! 273: Connect(wxEVT_IDLE, wxIdleEventHandler(WXMainFrame::OnIdle));
! 274:
! 275: // VM からの通知を接続
! 276: WXUIMessage::Connect(UIMessage::POWEROFF, this,
! 277: wxCommandEventHandler(WXMainFrame::OnExit));
! 278: WXUIMessage::Connect(UIMessage::SCSI_MEDIA_FAILED, this,
! 279: wxCommandEventHandler(WXMainFrame::OnInsertCDFailed));
! 280: if (gMPU680x0) {
! 281: WXUIMessage::Connect(UIMessage::HALT, this,
! 282: wxCommandEventHandler(WXMainFrame::OnHaltNotify));
! 283: }
1.1 root 284: }
285:
286: WXMainFrame::~WXMainFrame()
287: {
288: }
289:
1.1.1.11! root 290: // リムーバブルデバイス用のメニューを作成して menuDevice に追加する
! 291: void
! 292: WXMainFrame::CreateRemovableMenu(wxMenu *menuDevice)
! 293: {
! 294: wxMenu *menu;
! 295: bool added = false;
! 296:
! 297: // FD
! 298:
! 299: // CD, MO
! 300: for (int id = 0; id < 8; id++) {
! 301: scsidev[id] = gSPC->GetTarget(id);
! 302: if (scsidev[id]) {
! 303: menu = CreateSCSIRemovableMenu(id);
! 304: if (menu) {
! 305: std::string label = string_format("%s (ID%d)",
! 306: SCSI::GetDevTypeName(scsidev[id]->GetDevType()), id);
! 307: menuDevice->AppendSubMenu(menu, label);
! 308: added = true;
! 309: }
! 310: }
! 311: }
! 312:
! 313: // 1つでも追加したらセパレータ
! 314: if (added) {
! 315: menuDevice->AppendSeparator();
! 316: }
! 317: }
! 318:
! 319: // SCSI リムーバブルデバイス用のメニューを作成して返す。
! 320: // id はデバイスが接続されていること (リムーバブルデバイスであるかは問わない)。
! 321: // リムーバブルデバイスでなければ NULL を返す。
! 322: // メニューバーとポップアップメニュー共通。
! 323: wxMenu *
! 324: WXMainFrame::CreateSCSIRemovableMenu(uint id) const
! 325: {
! 326: const auto *dev = scsidev[id];
! 327: assert(dev);
! 328:
! 329: switch (dev->GetDevType()) {
! 330: case SCSI::DevType::CD:
! 331: case SCSI::DevType::MO:
! 332: {
! 333: wxMenu *menu = new wxMenu();
! 334: // Insert の実際のラベルは UpdateUI でセットする。
! 335: // ただし何か入れておかないといけないので適当にセット。
! 336: menu->Append(ID_CD_INSERT(id), "Insert", "");
! 337: menu->Append(ID_CD_EJECT(id), _("&Eject"), "");
! 338: menu->Append(ID_CD_FORCE(id), _("&Force Eject"), "");
! 339: return menu;
! 340: }
! 341: default:
! 342: return NULL;
! 343: }
! 344: }
! 345:
! 346: // ウィンドウ作成イベント (を実現するためここではアイドルイベントを使う)
1.1.1.10 root 347: //
1.1.1.11! root 348: // 初期化(っぽい)もののうちコンストラクタでは早すぎるものは、コンストラクタ
! 349: // 直後に起こすこのイベント内で処理する。使えそうなイベントはいくつかあり、
! 350: // 自前の Create (今はもうない) -> WindowCreate -> Idle -> Paint の順で
! 351: // 起きるようだ。
! 352: // 自前の Create 時点では早すぎて、ここでサブウィンドウを作成するとサイズが 0
! 353: // みたいなウィンドウが一瞬出来てしまい GTK のワーニングが出る (その後サイズを
! 354: // 矯正すれば表示自体は出来る)。
1.1.1.10 root 355: // WindowCreate 時点ではその問題は起きないが、ここはまだメインウィンドウ表示
356: // 前なので、ここでサブウィンドウを表示した後メインウィンドウを表示すると
357: // (ウィンドウマネージャにもよるかもだが)、メインウィンドウがサブウィンドウを
358: // 隠してしまう。
1.1.1.11! root 359: // Idle イベント時点まで来ると上の2つの問題は回避できるようだ。
! 360: // Paint イベントの時点でもタイミング的には問題ないが、環境によっては(?)
! 361: // このイベント自体が飛んで来ないことがあるようだ。WXMainFrame の再描画は
! 362: // Sizer の子コントロールが行っており、そのため WXMainFrame 自身が再描画
! 363: // しなければならない領域は存在しないからかも知れないが詳細未調査。
! 364: void
! 365: WXMainFrame::OnIdle(wxIdleEvent& ev)
1.1 root 366: {
1.1.1.11! root 367: Fit();
! 368:
! 369: // UIMessage の処理を開始する。
! 370: // 少なくとも WXMainFrame のコンストラクタが完了した後のほうがいいはず。
! 371: UIMessage::Attach(&WXUIMessage::Process);
! 372:
1.1 root 373: // ウィンドウを表示
1.1.1.10 root 374: for (int i = 0; i < subwindow_start.size(); i++) {
375: if (subwindow_start[i]) {
1.1 root 376: DoWindow(i, true);
377: }
378: }
379:
1.1.1.9 root 380: // 電源投入
1.1 root 381: gVM->PowerButton();
1.1.1.10 root 382:
383: // 一度処理したら、このイベントを外す
1.1.1.11! root 384: Disconnect(wxEVT_IDLE, wxIdleEventHandler(WXMainFrame::OnIdle));
1.1 root 385: }
386:
1.1.1.3 root 387: // ウィンドウクローズイベント
388: void
389: WXMainFrame::OnClose(wxCloseEvent& event)
390: {
1.1.1.9 root 391: // ステータスパネルの更新を停止
392: gStatusPanel->Close();
393:
1.1.1.3 root 394: // サブウィンドウを全部閉じる
1.1.1.10 root 395: for (int i = 0; i < ID_SUBWIN_MAX; i++) {
1.1.1.4 root 396: if ((bool)windows[i]) {
1.1.1.3 root 397: windows[i]->Close();
398: }
399: }
400:
401: // VM を解放
1.1.1.4 root 402: gVM->Dispose();
1.1.1.3 root 403: gVM.reset();
404:
405: // 後はデフォルト処理
406: event.Skip();
407: }
408:
1.1 root 409: // メニューの「高速モード」イベント
410: void
411: WXMainFrame::OnFullSpeed(wxCommandEvent& event)
412: {
413: if (event.IsChecked()) {
414: // チェックが入ったので、高速モードにする
415: gScheduler->SetFullSpeed(true);
416: } else {
417: // チェックが消えたので、通常モードにする
418: gScheduler->SetFullSpeed(false);
419: }
420: }
421:
422: // メニューの「高速モード」UI
423: void
424: WXMainFrame::OnFullSpeedUI(wxUpdateUIEvent& event)
425: {
426: bool is_fullspeed = gScheduler->GetFullSpeed();
427: event.Check(is_fullspeed);
428: }
429:
1.1.1.9 root 430: // メニューの「Restart VM」イベント
1.1.1.6 root 431: void
1.1.1.9 root 432: WXMainFrame::OnRestartVM(wxCommandEvent& event)
1.1.1.6 root 433: {
1.1.1.9 root 434: gScheduler->RequestRestartVM();
1.1.1.6 root 435: }
436:
1.1 root 437: // メニューの「終了」イベント
438: void
439: WXMainFrame::OnExit(wxCommandEvent& event)
440: {
441: // ウィンドウを閉じる
442: Close();
443: }
444:
445: // メニューの「表示 > スケール > *」の共通イベント
446: void
447: WXMainFrame::OnMenuScale(wxCommandEvent& event)
448: {
449: double scale;
450:
451: switch (event.GetId()) {
452: default:
453: case ID_SCALE_1_00:
454: scale = 1.0;
455: break;
456: case ID_SCALE_0_75:
457: scale = 0.75;
458: break;
459: case ID_SCALE_0_50:
460: scale = 0.5;
461: break;
462: }
463: gMainView->DoResize(scale);
464:
465: // 再レイアウト
466: Fit();
467: }
468:
469: // メニューの「表示 > スケール > *」の共通 UI
470: void
471: WXMainFrame::OnMenuScaleUI(wxUpdateUIEvent& event)
472: {
473: double current_scale = gMainView->GetScale();
474:
1.1.1.2 root 475: if (current_scale == 1.0) {
476: event.Check(event.GetId() == ID_SCALE_1_00);
477: } else if (current_scale == 0.75) {
478: event.Check(event.GetId() == ID_SCALE_0_75);
479: } else if (current_scale == 0.5) {
480: event.Check(event.GetId() == ID_SCALE_0_50);
1.1 root 481: }
482: }
483:
484: // メニューの「表示 > フォントサイズ > *」の共通イベント
485: void
486: WXMainFrame::OnMenuFontSize(wxCommandEvent& event)
487: {
1.1.1.5 root 488: FontId fontid;
1.1 root 489:
1.1.1.3 root 490: assertmsg(
1.1.1.4 root 491: ID_FONTSIZE_12 <= event.GetId() && event.GetId() <= ID_FONTSIZE_16,
1.1.1.3 root 492: "event.GetId()=%d", event.GetId());
1.1 root 493: switch (event.GetId()) {
494: case ID_FONTSIZE_12:
1.1.1.5 root 495: fontid = FontId::_6x12;
1.1 root 496: break;
497: case ID_FONTSIZE_16:
1.1.1.5 root 498: fontid = FontId::_8x16;
1.1 root 499: break;
500: default:
501: __unreachable();
502: break;
503: }
504:
1.1.1.5 root 505: if (fontid != WXTextPanel::global_fontid) {
506: WXTextPanel::global_fontid = fontid;
1.1 root 507:
508: // アクティブなサブウィンドウ全員に通知
1.1.1.10 root 509: for (int i = 0; i < ID_SUBWIN_MAX; i++) {
1.1.1.4 root 510: if ((bool)windows[i]) {
511: WXSubWindow *subwin =
512: dynamic_cast<WXSubWindow *>(windows[i].get());
1.1.1.5 root 513: subwin->SetFontSize(fontid);
1.1 root 514: }
515: }
1.1.1.9 root 516:
517: // ステータスパネルに通知
518: gStatusPanel->SetFontSize(fontid);
519:
520: // ステータスパネルの大きさが変わるので再レイアウト
521: Fit();
1.1 root 522: }
523: }
524:
525: // メニューの「表示 > フォントサイズ > *」共通 UI
526: void
527: WXMainFrame::OnMenuFontSizeUI(wxUpdateUIEvent& event)
528: {
1.1.1.5 root 529: FontId current_size = WXTextPanel::global_fontid;
530: FontId event_size = (FontId)(event.GetId() - (ID_FONTSIZE_START+1));
1.1 root 531:
532: event.Check(current_size == event_size);
533: }
534:
1.1.1.5 root 535: // 更新頻度 ID -> 数値 (メニューのテキスト、ID と一致させること)
536: /*static*/ const int
537: WXMainFrame::IDtoMonRate[] = {
538: 20, // ID_MONRATE_20
539: 5, // ID_MONRATE_5
540: 1, // ID_MONRATE_1
541: };
542:
543: // メニューの「表示 > モニタ更新頻度 > *」の共通イベント
544: void
545: WXMainFrame::OnMenuMonRate(wxCommandEvent& event)
546: {
547: int id = event.GetId();
548: assert(ID_MONRATE_START < id && id < ID_MONRATE_END);
549: monitor_rate = IDtoMonRate[id - (ID_MONRATE_START + 1)];
550:
551: // アクティブなサブウィンドウのテキストパネル全員に通知
1.1.1.10 root 552: for (int i = 0; i < ID_SUBWIN_MAX; i++) {
1.1.1.5 root 553: if ((bool)windows[i]) {
554: auto *subwin = dynamic_cast<WXSubWindow *>(windows[i].get());
555: for (wxWindow *child : subwin->GetChildren()) {
556: auto *panel = dynamic_cast<WXTextScreen*>(child);
557: if (panel) {
558: panel->SetRate(monitor_rate);
559: }
560: }
561: }
562: }
563: }
564:
565: // メニューの「表示 > モニタ更新頻度 > *」共通 UI
566: void
567: WXMainFrame::OnMenuMonRateUI(wxUpdateUIEvent& event)
568: {
569: int id = event.GetId();
570: assert(ID_MONRATE_START < id && id < ID_MONRATE_END);
571: int event_rate = IDtoMonRate[id - (ID_MONRATE_START + 1)];
572:
573: event.Check(monitor_rate == event_rate);
574: }
575:
1.1.1.9 root 576: // メニューの「表示 > ステータスパネルを表示」
577: void
578: WXMainFrame::OnShowStatusPanel(wxCommandEvent& event)
579: {
580: // enable ならチェックを付けようとして呼ばれた
581: bool enable = event.IsChecked();
582:
583: gStatusPanel->Show(enable);
584:
585: // 再レイアウト
586: Fit();
587: }
588:
589: // メニューの「表示 > ステータスパネルを表示」UI
590: void
591: WXMainFrame::OnShowStatusPanelUI(wxUpdateUIEvent& event)
592: {
593: event.Check(gStatusPanel->IsShown());
594: }
595:
1.1.1.11! root 596: // メニューの「デバイス > CD/MO > 挿入」
! 597: void
! 598: WXMainFrame::OnCDInsert(wxCommandEvent& event)
! 599: {
! 600: std::string title;
! 601: std::string wildcard;
! 602:
! 603: int id = event.GetId() - ID_CD_INSERT_0;
! 604: const auto *dev = scsidev[id];
! 605: assert(dev);
! 606:
! 607: switch (dev->GetDevType()) {
! 608: case SCSI::DevType::CD:
! 609: title = _("Open a CD image");
! 610: wildcard = "ISO images (*.iso;*.img)|*.iso;*.img;*.ISO;*.IMG";
! 611: break;
! 612: case SCSI::DevType::MO:
! 613: title = _("Open an MO image");
! 614: wildcard = "MO images (*.img;*.mos)|*.img;*.mos;*.IMG;*.MOS";
! 615: break;
! 616: default:
! 617: __unreachable();
! 618: }
! 619: wildcard += "|All files (*.*)|*.*";
! 620:
! 621: // ディレクトリは、まだ一度も使ってなければ VM ディレクトリにする
! 622: if (current_dir.empty()) {
! 623: current_dir = gMainApp.GetVMDir();
! 624: }
! 625:
! 626: wxFileDialog dialog(this, title, current_dir, "", wildcard,
! 627: wxFD_OPEN | wxFD_FILE_MUST_EXIST);
! 628: if (dialog.ShowModal() == wxID_CANCEL) {
! 629: return;
! 630: }
! 631: auto path = std::string(dialog.GetPath());
! 632: InsertCD(id, path);
! 633: }
! 634:
! 635: // メニューの「デバイス > CD/MO > 挿入」UI
! 636: void
! 637: WXMainFrame::OnCDInsertUI(wxUpdateUIEvent& event)
! 638: {
! 639: int id = event.GetId() - ID_CD_INSERT_0;
! 640: SCSIDisk *disk = dynamic_cast<SCSIDisk *>(scsidev[id]);
! 641: assert(disk);
! 642:
! 643: if (disk->IsMediumLoaded()) {
! 644: event.SetText(_("Ex&change"));
! 645: } else {
! 646: event.SetText(_("&Insert"));
! 647: }
! 648: }
! 649:
! 650: // メニューの「デバイス > CD/MO > 取り出し」
! 651: void
! 652: WXMainFrame::OnCDEject(wxCommandEvent& event)
! 653: {
! 654: int id = event.GetId() - ID_CD_EJECT_0;
! 655:
! 656: EjectCD(id, false);
! 657: }
! 658:
! 659: // メニューの「デバイス > CD/MO > 取り出し」UI
! 660: void
! 661: WXMainFrame::OnCDEjectUI(wxUpdateUIEvent& event)
! 662: {
! 663: int id = event.GetId() - ID_CD_EJECT_0;
! 664: SCSIDisk *disk = dynamic_cast<SCSIDisk *>(scsidev[id]);
! 665: assert(disk);
! 666:
! 667: // 挿入されてて取り出し可能な時のみ有効
! 668: event.Enable(disk->IsMediumLoaded() &&
! 669: disk->IsMediumRemovalAllowed());
! 670: }
! 671:
! 672: // メニューの「デバイス > CD/MO > 強制取り出し」
! 673: void
! 674: WXMainFrame::OnCDForce(wxCommandEvent& event)
! 675: {
! 676: int id = event.GetId() - ID_CD_FORCE_0;
! 677:
! 678: EjectCD(id, true);
! 679: }
! 680:
! 681: // メニューの「デバイス > CD/MO > 強制取り出し」UI
! 682: void
! 683: WXMainFrame::OnCDForceUI(wxUpdateUIEvent& event)
! 684: {
! 685: int id = event.GetId() - ID_CD_FORCE_0;
! 686: SCSIDisk *disk = dynamic_cast<SCSIDisk *>(scsidev[id]);
! 687: assert(disk);
! 688:
! 689: // 挿入されてて取り出し禁止の時のみ有効
! 690: event.Enable(disk->IsMediumLoaded() &&
! 691: disk->IsMediumRemovalPrevented());
! 692: }
! 693:
1.1.1.2 root 694: // メニューの「デバイス > マウスモード」
695: void
696: WXMainFrame::OnMouseMode(wxCommandEvent& event)
697: {
698: // enable ならチェックを付けようとして呼ばれた
699: bool enable = event.IsChecked();
700:
701: if (enable) {
702: // メッセージを表示したい
703: } else {
704: // メッセージを表示したい
705: }
706:
707: // マウスモードを設定
708: gMainView->SetMouseMode(enable);
709: }
710:
711: // メニューの「デバイス > マウスモード」UI
712: void
713: WXMainFrame::OnMouseModeUI(wxUpdateUIEvent& event)
714: {
715: event.Check(gMainView->GetMouseMode());
716: }
717:
1.1.1.9 root 718: // メニューの「デバイス > Push Reset Button」イベント
719: // こっちは本体リセットボタンによるリセット
720: void
721: WXMainFrame::OnResetButton(wxCommandEvent& event)
722: {
723: gScheduler->RequestResetHard();
724: }
725:
1.1 root 726: // メニューのウィンドウ ID 共通イベント
727: // チェックが入る方なら、ウィンドウを作成して表示。
728: // チェックが消える方なら、ウィンドウを削除。
729: void
730: WXMainFrame::OnWindow(wxCommandEvent& event)
731: {
732: int id = event.GetId();
733:
734: DoWindow(id, event.IsChecked());
735: }
736:
737: void
738: WXMainFrame::DoWindow(int id, bool enable)
739: {
1.1.1.10 root 740: // モニタウィンドウを作成する共通部分。
741: // id はモニター ID であると同時に、windows[] 配列の添字、さらにこの
742: // モニタウィンドウの wxWindowID としても使っている
743: // (WXSubWindow::OnClose() 参照)。
744: #define SetMonitor(id, name) \
745: windows[id].reset(new WXMonitorWindow(this, (name), \
746: gMonitorManager.Get(id)))
1.1.1.4 root 747:
1.1 root 748: if (enable) {
749: // チェックが入ったのでウィンドウを作成
750: switch (id) {
1.1.1.10 root 751: case ID_MONITOR_ATC0:
752: case ID_MONITOR_ATC1:
753: case ID_MONITOR_ATC2:
754: case ID_MONITOR_ATC3:
755: case ID_MONITOR_ATC4:
756: case ID_MONITOR_ATC5:
757: case ID_MONITOR_ATC6:
758: case ID_MONITOR_ATC7:
759: {
760: int n = id - ID_MONITOR_ATC0;
761: wxString name(string_format("ATC#%d", n));
762: if ((n & 1) == 0) {
763: name += _("(Data)");
764: } else {
765: name += _("(Inst)");
766: }
767: SetMonitor(id, name);
1.1.1.4 root 768: break;
1.1.1.10 root 769: }
770:
771: case ID_MONITOR_BREAKPOINT:
772: SetMonitor(id, _("Breakpoint"));
1.1.1.5 root 773: break;
1.1.1.10 root 774:
775: case ID_MONITOR_CMMU0:
776: case ID_MONITOR_CMMU1:
777: case ID_MONITOR_CMMU2:
778: case ID_MONITOR_CMMU3:
779: case ID_MONITOR_CMMU4:
780: case ID_MONITOR_CMMU5:
781: case ID_MONITOR_CMMU6:
782: case ID_MONITOR_CMMU7:
783: {
784: int n = id - ID_MONITOR_CMMU0;
785: wxString name(string_format("CMMU#%d", n));
786: if ((n & 1) == 0) {
787: name += _("(Data)");
788: } else {
789: name += _("(Inst)");
790: }
791: SetMonitor(id, name);
1.1.1.4 root 792: break;
1.1.1.10 root 793: }
794:
795: case ID_MONITOR_DMAC:
796: SetMonitor(id, "DMAC");
1.1.1.5 root 797: break;
1.1.1.10 root 798:
799: case ID_MONITOR_INTERRUPT:
800: SetMonitor(id, _("Interrupt"));
1.1.1.5 root 801: break;
1.1.1.10 root 802:
803: case ID_MONITOR_KEYBOARD:
804: SetMonitor(id, _("Keyboard/Mouse"));
1.1.1.4 root 805: break;
1.1.1.10 root 806:
807: case ID_MONITOR_LANCE:
808: SetMonitor(id, "LANCE");
1.1 root 809: break;
1.1.1.10 root 810:
811: case ID_MONITOR_LCD:
812: windows[id].reset(new WXLCDMonitor(this));
1.1.1.4 root 813: break;
1.1.1.10 root 814:
815: case ID_MONITOR_LUNAFB:
816: SetMonitor(id, _("Bitmap Control"));
1.1.1.4 root 817: break;
1.1.1.10 root 818:
819: case ID_MONITOR_MEMDUMP0 ...
820: (ID_MONITOR_MEMDUMP0 + MAX_MEMDUMP_MONITOR - 1):
821: {
822: int n = id - ID_MONITOR_MEMDUMP0;
823: windows[id].reset(new WXMemdumpWindow(this, n));
1.1.1.4 root 824: break;
1.1.1.10 root 825: }
826:
827: case ID_MONITOR_MFP:
828: SetMonitor(id, "MFP");
1.1.1.4 root 829: break;
1.1.1.10 root 830:
831: case ID_MONITOR_MK48T02:
832: SetMonitor(id, "MK48T02");
1.1 root 833: break;
1.1.1.10 root 834:
835: case ID_MONITOR_MPUATC:
836: SetMonitor(id, _("MPU (ATC)"));
1.1 root 837: break;
1.1.1.10 root 838:
839: case ID_MONITOR_MPUREG:
840: SetMonitor(id, _("MPU (Register)"));
1.1.1.7 root 841: break;
1.1.1.10 root 842:
843: case ID_MONITOR_HOSTNET:
844: SetMonitor(id, _("Host Network"));
1.1 root 845: break;
1.1.1.10 root 846:
847: case ID_MONITOR_PIO0:
848: SetMonitor(id, "PIO");
1.1.1.3 root 849: break;
1.1.1.10 root 850:
851: case ID_MONITOR_RTC:
852: SetMonitor(id, "RTC");
1.1.1.3 root 853: break;
1.1.1.10 root 854:
855: case ID_MONITOR_SCC:
856: SetMonitor(id, "SCC");
1.1.1.3 root 857: break;
1.1.1.10 root 858:
859: case ID_MONITOR_SCHEDULER:
860: SetMonitor(id, _("Scheduler"));
1.1 root 861: break;
1.1.1.10 root 862:
1.1.1.11! root 863: case ID_MONITOR_SCSIDEVS:
! 864: SetMonitor(id, _("SCSI Devices"));
! 865: break;
! 866:
1.1.1.10 root 867: case ID_MONITOR_SIO:
868: SetMonitor(id, "SIO");
1.1.1.4 root 869: break;
1.1.1.10 root 870:
871: case ID_MONITOR_SPC:
872: SetMonitor(id, "SPC");
1.1.1.2 root 873: break;
1.1.1.10 root 874:
875: case ID_MONITOR_SYSCLK:
876: SetMonitor(id, _("System Clock"));
1.1 root 877: break;
1.1.1.10 root 878:
879: case ID_MONITOR_WXHOSTINFO:
880: SetMonitor(id, _("Host Information"));
1.1 root 881: break;
1.1.1.10 root 882:
883: case ID_SUBWIN_BRHIST:
884: windows[id].reset(new WXBranchHistoryMonitor(this,
885: gMonitorManager.Get(id)));
1.1.1.4 root 886: break;
1.1.1.10 root 887:
888: case ID_SUBWIN_EXHIST:
889: windows[id].reset(new WXExceptionHistoryMonitor(this,
890: gMonitorManager.Get(id)));
1.1.1.5 root 891: break;
1.1.1.10 root 892:
893: case ID_SUBWIN_CACHE0:
894: case ID_SUBWIN_CACHE1:
895: case ID_SUBWIN_CACHE2:
896: case ID_SUBWIN_CACHE3:
897: case ID_SUBWIN_CACHE4:
898: case ID_SUBWIN_CACHE5:
899: case ID_SUBWIN_CACHE6:
900: case ID_SUBWIN_CACHE7:
901: {
902: int n = id - ID_SUBWIN_CACHE0;
903: wxString name = _("Cache");
904: name += string_format("#%d", n);
905: if ((n & 1) == 0) {
906: name += _("(Data)");
907: } else {
908: name += _("(Inst)");
909: }
910: windows[id].reset(new WXCacheWindow(this, name,
911: gMonitorManager.Get(id)));
1.1 root 912: break;
1.1.1.10 root 913: }
914:
915: case ID_SUBWIN_LCDPANEL:
916: windows[id].reset(new WXLCDWindow(this));
1.1 root 917: break;
1.1.1.10 root 918: case ID_SUBWIN_LOG:
919: windows[id].reset(new WXLogMonitor(this));
1.1 root 920: break;
1.1.1.10 root 921: case ID_SUBWIN_LUNAFB0:
922: windows[id].reset(new WXLunaBitmapWindow(this, _("Bitmap #0")));
1.1 root 923: break;
1.1.1.10 root 924:
925: case ID_SUBWIN_SOFTKEY:
926: windows[id].reset(new WXSoftKeyWindow(this, gMainApp.GetVMType()));
1.1.1.5 root 927: break;
1.1.1.10 root 928:
929: default:
930: assert(false);
1.1 root 931: }
932: windows[id]->Show();
933: } else {
934: // チェックが消えたのでウィンドウを終了
935: windows[id]->Close();
936: // (削除自体はこの少し下の DeleteWindow() で行なっている)
937: }
938: }
939:
940: // Update UI イベント
941: void
942: WXMainFrame::OnWindowUI(wxUpdateUIEvent& event)
943: {
944: int id = event.GetId();
945:
946: // ウィンドウが存在していればチェックを表示
1.1.1.4 root 947: event.Check((bool)windows[id]);
1.1.1.10 root 948:
949: if (IS_MONITOR_MEMDUMP(id)) {
950: // メニューに現在のアドレスを載せる
951: int n = id - ID_MONITOR_MEMDUMP0;
952: event.SetText(string_format("%d: $%08x", n,
953: WXMemdumpWindow::GetStickyAddr(id)));
954: }
1.1.1.4 root 955: }
956:
957: // バージョンダイアログ
958: void
959: WXMainFrame::OnAbout(wxCommandEvent& event)
960: {
961: WXVersionDlg dlg(this);
962: dlg.ShowModal();
1.1 root 963: }
964:
1.1.1.11! root 965: // CD/MO を挿入する。
1.1 root 966: void
1.1.1.11! root 967: WXMainFrame::InsertCD(int id, const std::string& path)
1.1 root 968: {
1.1.1.11! root 969: SCSIDisk *scsidisk = dynamic_cast<SCSIDisk*>(scsidev[id]);
! 970: assert(scsidisk);
1.1 root 971:
1.1.1.11! root 972: // VM に依頼
! 973: // (エラーが起きれば別途 UI メッセージが飛んでくる)
! 974: scsidisk->LoadDiskUI(path);
! 975:
! 976: // 次回以降のダイアログのカレントディレクトリをここに更新
! 977: auto pos = path.rfind('/');
! 978: current_dir = path.substr(0, pos);
1.1 root 979: }
980:
1.1.1.11! root 981: // CD/MO をイジェクトする。
1.1 root 982: void
1.1.1.11! root 983: WXMainFrame::EjectCD(int id, bool force)
1.1 root 984: {
1.1.1.11! root 985: SCSIDisk *scsidisk = dynamic_cast<SCSIDisk*>(scsidev[id]);
! 986: assert(scsidisk);
! 987:
! 988: scsidisk->UnloadDisk(force);
1.1 root 989: }
990:
1.1.1.11! root 991: // CD/MO の挿入失敗メッセージ
1.1.1.4 root 992: void
1.1.1.11! root 993: WXMainFrame::OnInsertCDFailed(wxCommandEvent& event)
1.1.1.4 root 994: {
1.1.1.11! root 995: ::wxMessageBox(_("Cannot load the image file"));
1.1.1.4 root 996: }
997:
1.1.1.11! root 998: // ウィンドウをリストから削除する
! 999: // (ウィンドウの Close() から呼ばれる)
1.1.1.4 root 1000: void
1.1.1.11! root 1001: WXMainFrame::DeleteWindow(wxWindow *win)
1.1.1.4 root 1002: {
1.1.1.11! root 1003: for (int id = 0; id < ID_SUBWIN_MAX; id++) {
! 1004: if (windows[id].get() == win) {
! 1005: windows[id].reset();
! 1006: break;
! 1007: }
! 1008: }
1.1.1.4 root 1009: }
1010:
1011: // m680x0 ダブルバスフォールト処理
1012: void
1013: WXMainFrame::OnHaltNotify(wxCommandEvent& event)
1014: {
1015: ::wxMessageBox(_("Double bus fault has occurred in VM"),
1016: wxEmptyString,
1017: wxICON_EXCLAMATION);
1018: }
1019:
1.1.1.10 root 1020: // 起動時にオープンするサブウィンドウ (-M オプション)
1021: /*static*/ std::array<bool, ID_SUBWIN_MAX> WXMainFrame::subwindow_start;
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.