|
|
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"
18: #include "wxversion.h"
19: #include "wxvideomonitor.h"
1.1.1.5 root 20: #include "debugger.h"
1.1.1.3 root 21: #include "mainapp.h"
1.1.1.4 root 22: #include "mpu680x0.h"
23: #include "mpu88xx0.h"
1.1 root 24: #include "netdriver.h"
25: #include "scheduler.h"
1.1.1.4 root 26: #include "vm.h"
1.1 root 27:
28: WXMainFrame *gMainFrame;
29:
30: wxBEGIN_EVENT_TABLE(WXMainFrame, inherited)
1.1.1.3 root 31: EVT_CLOSE(WXMainFrame::OnClose)
1.1 root 32: EVT_MENU(wxID_EXIT, WXMainFrame::OnExit)
33:
34: EVT_MENU(ID_FULL_SPEED, WXMainFrame::OnFullSpeed)
35: EVT_UPDATE_UI(ID_FULL_SPEED, WXMainFrame::OnFullSpeedUI)
1.1.1.9 root 36: EVT_MENU(ID_RESTART_VM, WXMainFrame::OnRestartVM)
1.1 root 37: EVT_MENU_RANGE(ID_SCALE_START + 1, ID_SCALE_END - 1,
38: WXMainFrame::OnMenuScale)
39: EVT_UPDATE_UI_RANGE(ID_SCALE_START + 1, ID_SCALE_END - 1,
40: WXMainFrame::OnMenuScaleUI)
41: EVT_MENU_RANGE(ID_FONTSIZE_START + 1, ID_FONTSIZE_END - 1,
42: WXMainFrame::OnMenuFontSize)
43: EVT_UPDATE_UI_RANGE(ID_FONTSIZE_START + 1, ID_FONTSIZE_END - 1,
44: WXMainFrame::OnMenuFontSizeUI)
1.1.1.5 root 45: EVT_MENU_RANGE(ID_MONRATE_START + 1, ID_MONRATE_END - 1,
46: WXMainFrame::OnMenuMonRate)
47: EVT_UPDATE_UI_RANGE(ID_MONRATE_START + 1, ID_MONRATE_END - 1,
48: WXMainFrame::OnMenuMonRateUI)
1.1.1.9 root 49: EVT_MENU(ID_SHOW_STATPANEL, WXMainFrame::OnShowStatusPanel)
50: EVT_UPDATE_UI(ID_SHOW_STATPANEL, WXMainFrame::OnShowStatusPanelUI)
1.1.1.2 root 51: EVT_MENU(ID_MOUSEMODE, WXMainFrame::OnMouseMode)
52: EVT_UPDATE_UI(ID_MOUSEMODE, WXMainFrame::OnMouseModeUI)
1.1.1.9 root 53: EVT_MENU(ID_RESET_BUTTON, WXMainFrame::OnResetButton)
1.1.1.10! root 54: EVT_MENU_RANGE(0, ID_SUBWIN_END, WXMainFrame::OnWindow)
! 55: EVT_UPDATE_UI_RANGE(0, ID_SUBWIN_END, WXMainFrame::OnWindowUI)
1.1.1.4 root 56: EVT_MENU(wxID_ABOUT, WXMainFrame::OnAbout)
57:
58: EVT_COMMAND(wxID_ANY, WXW_EVT_HALT_NOTIFY, WXMainFrame::OnHaltNotify)
1.1 root 59: wxEND_EVENT_TABLE()
60:
61: WXMainFrame::WXMainFrame(wxWindow *parent)
1.1.1.10! root 62: : inherited(parent, wxID_ANY, "nono", wxDefaultPosition, wxDefaultSize,
1.1.1.6 root 63: wxDEFAULT_FRAME_STYLE & ~wxMAXIMIZE_BOX & ~wxRESIZE_BORDER)
1.1 root 64: {
1.1.1.3 root 65: vmtype_t vmtype;
66: vmtype = gMainApp.GetVMType();
1.1 root 67:
68: // とりあえずメニュー
69: // XXX すぐにメニューファクトリーになる
70: wxMenuBar *menubar = new wxMenuBar();
71: wxMenu *menuFile = new wxMenu();
72: // XXX とりあえず適当なところにおいとく
1.1.1.4 root 73: menuFile->Append(ID_FULL_SPEED, _("Full &Speed Mode"), "", wxITEM_CHECK);
1.1.1.9 root 74: menuFile->AppendSeparator();
75: menuFile->Append(ID_RESTART_VM, _("&Restart VM"), "");
1.1.1.4 root 76: menuFile->Append(wxID_EXIT, _("E&xit"));
77: menubar->Append(menuFile, _("&File"));
1.1 root 78:
79: wxMenu *menuDisplay = new wxMenu();
80: wxMenu *menuViewScale = new wxMenu();
1.1.1.4 root 81: menuViewScale->Append(ID_SCALE_1_00, _("x1.&0"), "", wxITEM_CHECK);
82: menuViewScale->Append(ID_SCALE_0_75, _("x0.&75"), "", wxITEM_CHECK);
83: menuViewScale->Append(ID_SCALE_0_50, _("x0.&5"), "", wxITEM_CHECK);
84: menuDisplay->AppendSubMenu(menuViewScale, _("&Scale"));
1.1 root 85: wxMenu *menuFontSize = new wxMenu();
1.1.1.4 root 86: menuFontSize->AppendRadioItem(ID_FONTSIZE_12, "1&2");
87: menuFontSize->AppendRadioItem(ID_FONTSIZE_16, "1&6");
88: menuDisplay->AppendSubMenu(menuFontSize, _("&Font Size"));
1.1.1.5 root 89: wxMenu *menuMonRate = new wxMenu();
90: menuMonRate->AppendRadioItem(ID_MONRATE_20, _("High (&20Hz)"));
91: menuMonRate->AppendRadioItem(ID_MONRATE_5, _("Middle (&5Hz)"));
92: menuMonRate->AppendRadioItem(ID_MONRATE_1, _("Low (&1Hz)"));
93: menuDisplay->AppendSubMenu(menuMonRate, _("&Monitor Speed"));
1.1.1.9 root 94: menuDisplay->Append(ID_SHOW_STATPANEL, _("Show Status &Panel"), "",
95: wxITEM_CHECK);
1.1.1.4 root 96: menubar->Append(menuDisplay, _("&View"));
1.1 root 97:
98: wxMenu *menuDevice = new wxMenu();
1.1.1.10! root 99: menuDevice->Append(ID_SUBWIN_SOFTKEY, _("Software &Keyboard"),
1.1.1.2 root 100: "", wxITEM_CHECK);
1.1.1.4 root 101: menuDevice->Append(ID_MOUSEMODE, _("&Mouse Mode\tCTRL+F12"),
1.1.1.2 root 102: "", wxITEM_CHECK);
1.1.1.5 root 103: if (gMainApp.HasVMFeature(VMF_LUNA)) {
1.1.1.10! root 104: menuDevice->Append(ID_SUBWIN_LCDPANEL, _("Front &LCD"),
1.1.1.5 root 105: "", wxITEM_CHECK);
106: }
1.1.1.9 root 107: menuDevice->AppendSeparator();
1.1.1.10! root 108: wxMenu *menuOper = new wxMenu();
! 109: menuOper->Append(ID_RESET_BUTTON, _("Push &Reset button"));
! 110: menuDevice->AppendSubMenu(menuOper, _("Operation"));
1.1.1.4 root 111: menubar->Append(menuDevice, _("&Device"));
112:
113: // 機種によってモニタウィンドウを追加する
114: #define AppendIf(menu, id, label) do { \
1.1.1.10! root 115: vmf_t feature_ = gMonitorManager.GetFeature(id); \
! 116: if (gMainApp.HasVMFeature(feature_)) { \
! 117: (menu)->Append((id), (label), "", wxITEM_CHECK); \
! 118: } \
! 119: } while (0)
! 120: #define AppendIfSeparator(menu, feature_) do { \
! 121: if (gMainApp.HasVMFeature(feature_)) { \
! 122: (menu)->AppendSeparator(); \
1.1.1.4 root 123: } \
124: } while (0)
1.1 root 125:
126: wxMenu *menuMonitor = new wxMenu();
1.1.1.10! root 127: AppendIf(menuMonitor, ID_MONITOR_SCHEDULER, _("&Scheduler"));
! 128: AppendIf(menuMonitor, ID_SUBWIN_LOG, _("&Log"));
1.1.1.4 root 129:
1.1.1.5 root 130: wxMenu *menuDebug = new wxMenu();
1.1.1.10! root 131: AppendIf(menuDebug, ID_MONITOR_BREAKPOINT, _("&Breakpoint"));
! 132: AppendIf(menuDebug, ID_SUBWIN_BRHIST, _("Branch &History"));
! 133: AppendIf(menuDebug, ID_SUBWIN_EXHIST, _("&Exception History"));
1.1.1.5 root 134: menuMonitor->AppendSubMenu(menuDebug, _("&Debug"));
135:
1.1.1.4 root 136: wxMenu *menuMPU = new wxMenu();
1.1.1.10! root 137: AppendIf(menuMPU, ID_MONITOR_MPUREG, _("&Register"));
! 138: AppendIf(menuMPU, ID_MONITOR_MPUATC, "&ATC");
! 139: AppendIfSeparator(menuMPU, VMF_M88K);
! 140: AppendIf(menuMPU, ID_MONITOR_CMMU7, "CMMU#7" + _("(Inst)"));
! 141: AppendIf(menuMPU, ID_MONITOR_ATC7, "ATC#7");
! 142: AppendIf(menuMPU, ID_SUBWIN_CACHE7, _("Cache") + "#7");
! 143: AppendIfSeparator(menuMPU, VMF_M88K);
! 144: AppendIf(menuMPU, ID_MONITOR_CMMU6, "CMMU#6" + _("(Data)"));
! 145: AppendIf(menuMPU, ID_MONITOR_ATC6, "ATC#6");
! 146: AppendIf(menuMPU, ID_SUBWIN_CACHE6, _("Cache") + "#6");
! 147: menuMonitor->AppendSubMenu(menuMPU, "MP&U");
! 148:
! 149: wxMenu *menuMemdump = new wxMenu();
! 150: // MEMDUMPn のラベルは UpdateUI で書き直すのでここでは適当に埋めておく。
! 151: // (empty だと怒られる)
! 152: // MONITOR_RTC は X68k の RTC、LUNA では MONITOR_MK48T02 だが今の所
! 153: // NVRAM 側のことは表示してないのでラベルも RTC にしてある。
! 154: for (int i = 0; i < MAX_MEMDUMP_MONITOR; i++) {
! 155: AppendIf(menuMemdump, ID_MONITOR_MEMDUMP0 + i, "memdump");
! 156: }
! 157: menuMonitor->AppendSubMenu(menuMemdump, _("&Memory Dump"));
! 158: AppendIf(menuMonitor, ID_MONITOR_INTERRUPT, _("&Interrupt"));
! 159: AppendIf(menuMonitor, ID_MONITOR_SPC, "S&PC");
! 160: AppendIf(menuMonitor, ID_MONITOR_RTC, "&RTC");
! 161: AppendIf(menuMonitor, ID_MONITOR_MK48T02, "&RTC");
! 162: AppendIf(menuMonitor, ID_MONITOR_DMAC, "DM&AC");
! 163: AppendIf(menuMonitor, ID_MONITOR_MFP, "M&FP");
! 164: AppendIf(menuMonitor, ID_MONITOR_SCC, "SCC(&Z)");
! 165: AppendIf(menuMonitor, ID_MONITOR_SIO, "SIO(&U)");
! 166: AppendIf(menuMonitor, ID_MONITOR_PIO0, "PIO0");
! 167: AppendIf(menuMonitor, ID_MONITOR_KEYBOARD, _("&Keyboard/Mouse"));
! 168: AppendIf(menuMonitor, ID_MONITOR_LANCE, "Lance(&E)");
! 169: AppendIf(menuMonitor, ID_MONITOR_LCD, "LCD(&J)");
! 170: AppendIf(menuMonitor, ID_MONITOR_SYSCLK, _("S&ystem Clock"));
! 171: AppendIf(menuMonitor, ID_MONITOR_LUNAFB, _("&Bitmap Control"));
! 172: AppendIf(menuMonitor, ID_SUBWIN_LUNAFB0, _("Bitmap #&0"));
1.1.1.5 root 173:
174: wxMenu *menuHost = new wxMenu();
1.1.1.10! root 175: AppendIf(menuHost, ID_MONITOR_WXHOSTINFO, _("Host &Information"));
! 176: AppendIf(menuHost, ID_MONITOR_HOSTNET, _("Host &Network"));
1.1.1.5 root 177: menuMonitor->AppendSubMenu(menuHost, _("&Host"));
178:
1.1.1.4 root 179: menubar->Append(menuMonitor, _("&Monitor"));
180:
181: #if defined(__WXOSX__)
182: // OSX では wxID_ABOUT はリンゴメニューに入れるしきたりになっている。
183: // Append() すると Quit より下に来てしまうので、Prepend() で上に追加。
184: // 今のところヘルプメニューから About ダイアログを抜くとメニューが空に
185: // なってしまうので、ヘルプメニューの追加ごと抑制する。
186: menubar->OSXGetAppleMenu()->Prepend(wxID_ABOUT, _("About nono"));
187: #else
188: wxMenu *menuHelp = new wxMenu();
189: menuHelp->Append(wxID_ABOUT, _("About nono"));
190: menubar->Append(menuHelp, _("&Help"));
191: #endif
192:
1.1 root 193: SetMenuBar(menubar);
194:
195: wxString title("nono");
196: switch (vmtype) {
1.1.1.3 root 197: case VMTYPE_X68030:
198: title += "(X68030)";
199: break;
1.1.1.4 root 200: case VMTYPE_LUNA1:
1.1 root 201: title += "(LUNA-I)";
202: break;
1.1.1.3 root 203: case VMTYPE_LUNA88K:
204: title += "(LUNA88K)";
205: break;
206: default:
1.1 root 207: break;
208: }
209: SetTitle(title);
210:
211: // UpdateUI イベントは Idle 時に時折チェックされるらしいが、
212: // (メインビューとサブウィンドウを合わせた) タイマーイベントの粒度が
213: // 小さいためか、秒間120回とかいうレベルで UpdateUIEvent が飛んでくる
214: // っぽい (全タイマーをとめたら治る模様)。
215: // さすがにそんなに来られても気持ち悪いのと、どうせメニュー開いた瞬間
216: // 表示しようとする前には一度飛んでくるのだから、アイドル時のチェックは
217: // いらない気がする。間隔広げておいても、ぱっと見副作用はなさそうだけど
218: // 念のため事象が分かりやすいように 10秒くらいにしておく。
219: wxUpdateUIEvent::SetUpdateInterval(10000);
220:
221: wxBoxSizer *vbox = new wxBoxSizer(wxVERTICAL);
222:
1.1.1.10! root 223: // WXStatusPanel コンストラクタが gMainView を参照するので
! 224: // gMainView のほうを先に作成すること。
! 225: gMainView = new WXMainView(this);
1.1.1.9 root 226: gStatusPanel = new WXStatusPanel(this);
227: vbox->Add(gStatusPanel, 0, wxEXPAND);
1.1 root 228: vbox->Add(gMainView, 1, wxEXPAND | wxFIXED_MINSIZE);
229:
1.1.1.9 root 230: // SHOW イベントを最初にも一度起こしたいため
231: // ステータスパネルを一旦非表示にする (これで SHOW(false) イベントが飛ぶ)
232: gStatusPanel->Hide();
233: const ConfigItem& item_show = gConfig->Find("show-statuspanel");
234: if (item_show.AsInt() != 0) {
235: // 必要なら改めて表示 (これで SHOW(true) イベントが飛ぶ)
236: gStatusPanel->Show();
237: }
238:
1.1 root 239: SetSizer(vbox);
240:
241: Fit();
242:
1.1.1.5 root 243: // モニタの更新頻度は初期値だけ設定から読んで、あとはここで管理する。
244: // 不正値ならデフォルトの 15Hz にしておくか
1.1.1.9 root 245: const ConfigItem& item_rate = gConfig->Find("monitor-rate");
246: monitor_rate = item_rate.AsInt();
1.1.1.5 root 247: if (monitor_rate < 1 || monitor_rate > 60) {
248: monitor_rate = 15;
249: }
250:
1.1.1.4 root 251: // Activate イベントは、このトップレベルウィンドウにウィンドウフォーカスが
252: // 来た or 外れたことを示すので、wxFrame (というかたぶん wxTopLevelWindow)
253: // を継承している WXMainFrameに飛んでくるのだが、処理の都合上 WXMainView で
254: // 扱いたいので、そちらに回す。
255: Connect(wxEVT_ACTIVATE, wxActivateEventHandler(WXMainView::OnActivate),
256: NULL, gMainView);
257:
1.1.1.10! root 258: // ウィンドウ表示後にサブウィンドウを表示するための Paint イベント。
! 259: Connect(wxEVT_PAINT, wxPaintEventHandler(WXMainFrame::OnPaint));
1.1 root 260: }
261:
262: WXMainFrame::~WXMainFrame()
263: {
264: }
265:
1.1.1.10! root 266: // ウィンドウ作成イベント (を実現するためここでは再描画イベントを使う)
! 267: //
! 268: // 初期化(っぽい)もののうちコンストラクタでは早すぎる処理のため。
! 269: // 似たようなイベントは WindowCreate イベントと自前の Create イベント
! 270: // (今はもうない)があり、Create -> WindowCreate -> Paint の順で発生する
! 271: // ようだ (Ubuntu 20.04 で確認、他でも同様だと思いたい)。
! 272: // Create 時点では早すぎて、ここでサブウィンドウを作成するとサイズが 0 みたい
! 273: // なウィンドウが一瞬出来てしまい GTK のワーニングが出る (その後サイズを矯正
! 274: // すれば表示自体は出来る)。
! 275: // WindowCreate 時点ではその問題は起きないが、ここはまだメインウィンドウ表示
! 276: // 前なので、ここでサブウィンドウを表示した後メインウィンドウを表示すると
! 277: // (ウィンドウマネージャにもよるかもだが)、メインウィンドウがサブウィンドウを
! 278: // 隠してしまう。
! 279: // Paint イベント時点まで来るとこの2つの問題が回避できるようだ。
! 280: // なおこの Paint イベントは通常の再描画の用途では使わないため、一度処理した
! 281: // 後はこのイベントを外す。
! 282: void WXMainFrame::OnPaint(wxPaintEvent& ev)
1.1 root 283: {
284: // ウィンドウを表示
1.1.1.10! root 285: for (int i = 0; i < subwindow_start.size(); i++) {
! 286: if (subwindow_start[i]) {
1.1 root 287: DoWindow(i, true);
288: }
289: }
290:
1.1.1.9 root 291: // 電源投入
1.1 root 292: gVM->PowerButton();
1.1.1.10! root 293:
! 294: // 一度処理したら、このイベントを外す
! 295: Disconnect(wxEVT_PAINT, wxPaintEventHandler(WXMainFrame::OnPaint));
1.1 root 296: }
297:
1.1.1.3 root 298: // ウィンドウクローズイベント
299: void
300: WXMainFrame::OnClose(wxCloseEvent& event)
301: {
1.1.1.9 root 302: // ステータスパネルの更新を停止
303: gStatusPanel->Close();
304:
1.1.1.3 root 305: // サブウィンドウを全部閉じる
1.1.1.10! root 306: for (int i = 0; i < ID_SUBWIN_MAX; i++) {
1.1.1.4 root 307: if ((bool)windows[i]) {
1.1.1.3 root 308: windows[i]->Close();
309: }
310: }
311:
312: // VM を解放
1.1.1.4 root 313: gVM->Dispose();
1.1.1.3 root 314: gVM.reset();
315:
316: // 後はデフォルト処理
317: event.Skip();
318: }
319:
1.1 root 320: // メニューの「高速モード」イベント
321: void
322: WXMainFrame::OnFullSpeed(wxCommandEvent& event)
323: {
324: if (event.IsChecked()) {
325: // チェックが入ったので、高速モードにする
326: gScheduler->SetFullSpeed(true);
327: } else {
328: // チェックが消えたので、通常モードにする
329: gScheduler->SetFullSpeed(false);
330: }
331: }
332:
333: // メニューの「高速モード」UI
334: void
335: WXMainFrame::OnFullSpeedUI(wxUpdateUIEvent& event)
336: {
337: bool is_fullspeed = gScheduler->GetFullSpeed();
338: event.Check(is_fullspeed);
339: }
340:
1.1.1.9 root 341: // メニューの「Restart VM」イベント
1.1.1.6 root 342: void
1.1.1.9 root 343: WXMainFrame::OnRestartVM(wxCommandEvent& event)
1.1.1.6 root 344: {
1.1.1.9 root 345: gScheduler->RequestRestartVM();
1.1.1.6 root 346: }
347:
1.1 root 348: // メニューの「終了」イベント
349: void
350: WXMainFrame::OnExit(wxCommandEvent& event)
351: {
352: // ウィンドウを閉じる
353: Close();
354: }
355:
356: // メニューの「表示 > スケール > *」の共通イベント
357: void
358: WXMainFrame::OnMenuScale(wxCommandEvent& event)
359: {
360: double scale;
361:
362: switch (event.GetId()) {
363: default:
364: case ID_SCALE_1_00:
365: scale = 1.0;
366: break;
367: case ID_SCALE_0_75:
368: scale = 0.75;
369: break;
370: case ID_SCALE_0_50:
371: scale = 0.5;
372: break;
373: }
374: gMainView->DoResize(scale);
375:
376: // 再レイアウト
377: Fit();
378: }
379:
380: // メニューの「表示 > スケール > *」の共通 UI
381: void
382: WXMainFrame::OnMenuScaleUI(wxUpdateUIEvent& event)
383: {
384: double current_scale = gMainView->GetScale();
385:
1.1.1.2 root 386: if (current_scale == 1.0) {
387: event.Check(event.GetId() == ID_SCALE_1_00);
388: } else if (current_scale == 0.75) {
389: event.Check(event.GetId() == ID_SCALE_0_75);
390: } else if (current_scale == 0.5) {
391: event.Check(event.GetId() == ID_SCALE_0_50);
1.1 root 392: }
393: }
394:
395: // メニューの「表示 > フォントサイズ > *」の共通イベント
396: void
397: WXMainFrame::OnMenuFontSize(wxCommandEvent& event)
398: {
1.1.1.5 root 399: FontId fontid;
1.1 root 400:
1.1.1.3 root 401: assertmsg(
1.1.1.4 root 402: ID_FONTSIZE_12 <= event.GetId() && event.GetId() <= ID_FONTSIZE_16,
1.1.1.3 root 403: "event.GetId()=%d", event.GetId());
1.1 root 404: switch (event.GetId()) {
405: case ID_FONTSIZE_12:
1.1.1.5 root 406: fontid = FontId::_6x12;
1.1 root 407: break;
408: case ID_FONTSIZE_16:
1.1.1.5 root 409: fontid = FontId::_8x16;
1.1 root 410: break;
411: default:
412: __unreachable();
413: break;
414: }
415:
1.1.1.5 root 416: if (fontid != WXTextPanel::global_fontid) {
417: WXTextPanel::global_fontid = fontid;
1.1 root 418:
419: // アクティブなサブウィンドウ全員に通知
1.1.1.10! root 420: for (int i = 0; i < ID_SUBWIN_MAX; i++) {
1.1.1.4 root 421: if ((bool)windows[i]) {
422: WXSubWindow *subwin =
423: dynamic_cast<WXSubWindow *>(windows[i].get());
1.1.1.5 root 424: subwin->SetFontSize(fontid);
1.1 root 425: }
426: }
1.1.1.9 root 427:
428: // ステータスパネルに通知
429: gStatusPanel->SetFontSize(fontid);
430:
431: // ステータスパネルの大きさが変わるので再レイアウト
432: Fit();
1.1 root 433: }
434: }
435:
436: // メニューの「表示 > フォントサイズ > *」共通 UI
437: void
438: WXMainFrame::OnMenuFontSizeUI(wxUpdateUIEvent& event)
439: {
1.1.1.5 root 440: FontId current_size = WXTextPanel::global_fontid;
441: FontId event_size = (FontId)(event.GetId() - (ID_FONTSIZE_START+1));
1.1 root 442:
443: event.Check(current_size == event_size);
444: }
445:
1.1.1.5 root 446: // 更新頻度 ID -> 数値 (メニューのテキスト、ID と一致させること)
447: /*static*/ const int
448: WXMainFrame::IDtoMonRate[] = {
449: 20, // ID_MONRATE_20
450: 5, // ID_MONRATE_5
451: 1, // ID_MONRATE_1
452: };
453:
454: // メニューの「表示 > モニタ更新頻度 > *」の共通イベント
455: void
456: WXMainFrame::OnMenuMonRate(wxCommandEvent& event)
457: {
458: int id = event.GetId();
459: assert(ID_MONRATE_START < id && id < ID_MONRATE_END);
460: monitor_rate = IDtoMonRate[id - (ID_MONRATE_START + 1)];
461:
462: // アクティブなサブウィンドウのテキストパネル全員に通知
1.1.1.10! root 463: for (int i = 0; i < ID_SUBWIN_MAX; i++) {
1.1.1.5 root 464: if ((bool)windows[i]) {
465: auto *subwin = dynamic_cast<WXSubWindow *>(windows[i].get());
466: for (wxWindow *child : subwin->GetChildren()) {
467: auto *panel = dynamic_cast<WXTextScreen*>(child);
468: if (panel) {
469: panel->SetRate(monitor_rate);
470: }
471: }
472: }
473: }
474: }
475:
476: // メニューの「表示 > モニタ更新頻度 > *」共通 UI
477: void
478: WXMainFrame::OnMenuMonRateUI(wxUpdateUIEvent& event)
479: {
480: int id = event.GetId();
481: assert(ID_MONRATE_START < id && id < ID_MONRATE_END);
482: int event_rate = IDtoMonRate[id - (ID_MONRATE_START + 1)];
483:
484: event.Check(monitor_rate == event_rate);
485: }
486:
1.1.1.9 root 487: // メニューの「表示 > ステータスパネルを表示」
488: void
489: WXMainFrame::OnShowStatusPanel(wxCommandEvent& event)
490: {
491: // enable ならチェックを付けようとして呼ばれた
492: bool enable = event.IsChecked();
493:
494: gStatusPanel->Show(enable);
495:
496: // 再レイアウト
497: Fit();
498: }
499:
500: // メニューの「表示 > ステータスパネルを表示」UI
501: void
502: WXMainFrame::OnShowStatusPanelUI(wxUpdateUIEvent& event)
503: {
504: event.Check(gStatusPanel->IsShown());
505: }
506:
1.1.1.2 root 507: // メニューの「デバイス > マウスモード」
508: void
509: WXMainFrame::OnMouseMode(wxCommandEvent& event)
510: {
511: // enable ならチェックを付けようとして呼ばれた
512: bool enable = event.IsChecked();
513:
514: if (enable) {
515: // メッセージを表示したい
516: } else {
517: // メッセージを表示したい
518: }
519:
520: // マウスモードを設定
521: gMainView->SetMouseMode(enable);
522: }
523:
524: // メニューの「デバイス > マウスモード」UI
525: void
526: WXMainFrame::OnMouseModeUI(wxUpdateUIEvent& event)
527: {
528: event.Check(gMainView->GetMouseMode());
529: }
530:
1.1.1.9 root 531: // メニューの「デバイス > Push Reset Button」イベント
532: // こっちは本体リセットボタンによるリセット
533: void
534: WXMainFrame::OnResetButton(wxCommandEvent& event)
535: {
536: gScheduler->RequestResetHard();
537: }
538:
1.1 root 539: // メニューのウィンドウ ID 共通イベント
540: // チェックが入る方なら、ウィンドウを作成して表示。
541: // チェックが消える方なら、ウィンドウを削除。
542: void
543: WXMainFrame::OnWindow(wxCommandEvent& event)
544: {
545: int id = event.GetId();
546:
547: DoWindow(id, event.IsChecked());
548: }
549:
550: void
551: WXMainFrame::DoWindow(int id, bool enable)
552: {
1.1.1.10! root 553: // モニタウィンドウを作成する共通部分。
! 554: // id はモニター ID であると同時に、windows[] 配列の添字、さらにこの
! 555: // モニタウィンドウの wxWindowID としても使っている
! 556: // (WXSubWindow::OnClose() 参照)。
! 557: #define SetMonitor(id, name) \
! 558: windows[id].reset(new WXMonitorWindow(this, (name), \
! 559: gMonitorManager.Get(id)))
1.1.1.4 root 560:
1.1 root 561: if (enable) {
562: // チェックが入ったのでウィンドウを作成
563: switch (id) {
1.1.1.10! root 564: case ID_MONITOR_ATC0:
! 565: case ID_MONITOR_ATC1:
! 566: case ID_MONITOR_ATC2:
! 567: case ID_MONITOR_ATC3:
! 568: case ID_MONITOR_ATC4:
! 569: case ID_MONITOR_ATC5:
! 570: case ID_MONITOR_ATC6:
! 571: case ID_MONITOR_ATC7:
! 572: {
! 573: int n = id - ID_MONITOR_ATC0;
! 574: wxString name(string_format("ATC#%d", n));
! 575: if ((n & 1) == 0) {
! 576: name += _("(Data)");
! 577: } else {
! 578: name += _("(Inst)");
! 579: }
! 580: SetMonitor(id, name);
1.1.1.4 root 581: break;
1.1.1.10! root 582: }
! 583:
! 584: case ID_MONITOR_BREAKPOINT:
! 585: SetMonitor(id, _("Breakpoint"));
1.1.1.5 root 586: break;
1.1.1.10! root 587:
! 588: case ID_MONITOR_CMMU0:
! 589: case ID_MONITOR_CMMU1:
! 590: case ID_MONITOR_CMMU2:
! 591: case ID_MONITOR_CMMU3:
! 592: case ID_MONITOR_CMMU4:
! 593: case ID_MONITOR_CMMU5:
! 594: case ID_MONITOR_CMMU6:
! 595: case ID_MONITOR_CMMU7:
! 596: {
! 597: int n = id - ID_MONITOR_CMMU0;
! 598: wxString name(string_format("CMMU#%d", n));
! 599: if ((n & 1) == 0) {
! 600: name += _("(Data)");
! 601: } else {
! 602: name += _("(Inst)");
! 603: }
! 604: SetMonitor(id, name);
1.1.1.4 root 605: break;
1.1.1.10! root 606: }
! 607:
! 608: case ID_MONITOR_DMAC:
! 609: SetMonitor(id, "DMAC");
1.1.1.5 root 610: break;
1.1.1.10! root 611:
! 612: case ID_MONITOR_INTERRUPT:
! 613: SetMonitor(id, _("Interrupt"));
1.1.1.5 root 614: break;
1.1.1.10! root 615:
! 616: case ID_MONITOR_KEYBOARD:
! 617: SetMonitor(id, _("Keyboard/Mouse"));
1.1.1.4 root 618: break;
1.1.1.10! root 619:
! 620: case ID_MONITOR_LANCE:
! 621: SetMonitor(id, "LANCE");
1.1 root 622: break;
1.1.1.10! root 623:
! 624: case ID_MONITOR_LCD:
! 625: windows[id].reset(new WXLCDMonitor(this));
1.1.1.4 root 626: break;
1.1.1.10! root 627:
! 628: case ID_MONITOR_LUNAFB:
! 629: SetMonitor(id, _("Bitmap Control"));
1.1.1.4 root 630: break;
1.1.1.10! root 631:
! 632: case ID_MONITOR_MEMDUMP0 ...
! 633: (ID_MONITOR_MEMDUMP0 + MAX_MEMDUMP_MONITOR - 1):
! 634: {
! 635: int n = id - ID_MONITOR_MEMDUMP0;
! 636: windows[id].reset(new WXMemdumpWindow(this, n));
1.1.1.4 root 637: break;
1.1.1.10! root 638: }
! 639:
! 640: case ID_MONITOR_MFP:
! 641: SetMonitor(id, "MFP");
1.1.1.4 root 642: break;
1.1.1.10! root 643:
! 644: case ID_MONITOR_MK48T02:
! 645: SetMonitor(id, "MK48T02");
1.1 root 646: break;
1.1.1.10! root 647:
! 648: case ID_MONITOR_MPUATC:
! 649: SetMonitor(id, _("MPU (ATC)"));
1.1 root 650: break;
1.1.1.10! root 651:
! 652: case ID_MONITOR_MPUREG:
! 653: SetMonitor(id, _("MPU (Register)"));
1.1.1.7 root 654: break;
1.1.1.10! root 655:
! 656: case ID_MONITOR_HOSTNET:
! 657: SetMonitor(id, _("Host Network"));
1.1 root 658: break;
1.1.1.10! root 659:
! 660: case ID_MONITOR_PIO0:
! 661: SetMonitor(id, "PIO");
1.1.1.3 root 662: break;
1.1.1.10! root 663:
! 664: case ID_MONITOR_RTC:
! 665: SetMonitor(id, "RTC");
1.1.1.3 root 666: break;
1.1.1.10! root 667:
! 668: case ID_MONITOR_SCC:
! 669: SetMonitor(id, "SCC");
1.1.1.3 root 670: break;
1.1.1.10! root 671:
! 672: case ID_MONITOR_SCHEDULER:
! 673: SetMonitor(id, _("Scheduler"));
1.1 root 674: break;
1.1.1.10! root 675:
! 676: case ID_MONITOR_SIO:
! 677: SetMonitor(id, "SIO");
1.1.1.4 root 678: break;
1.1.1.10! root 679:
! 680: case ID_MONITOR_SPC:
! 681: SetMonitor(id, "SPC");
1.1.1.2 root 682: break;
1.1.1.10! root 683:
! 684: case ID_MONITOR_SYSCLK:
! 685: SetMonitor(id, _("System Clock"));
1.1 root 686: break;
1.1.1.10! root 687:
! 688: case ID_MONITOR_WXHOSTINFO:
! 689: SetMonitor(id, _("Host Information"));
1.1 root 690: break;
1.1.1.10! root 691:
! 692: case ID_SUBWIN_BRHIST:
! 693: windows[id].reset(new WXBranchHistoryMonitor(this,
! 694: gMonitorManager.Get(id)));
1.1.1.4 root 695: break;
1.1.1.10! root 696:
! 697: case ID_SUBWIN_EXHIST:
! 698: windows[id].reset(new WXExceptionHistoryMonitor(this,
! 699: gMonitorManager.Get(id)));
1.1.1.5 root 700: break;
1.1.1.10! root 701:
! 702: case ID_SUBWIN_CACHE0:
! 703: case ID_SUBWIN_CACHE1:
! 704: case ID_SUBWIN_CACHE2:
! 705: case ID_SUBWIN_CACHE3:
! 706: case ID_SUBWIN_CACHE4:
! 707: case ID_SUBWIN_CACHE5:
! 708: case ID_SUBWIN_CACHE6:
! 709: case ID_SUBWIN_CACHE7:
! 710: {
! 711: int n = id - ID_SUBWIN_CACHE0;
! 712: wxString name = _("Cache");
! 713: name += string_format("#%d", n);
! 714: if ((n & 1) == 0) {
! 715: name += _("(Data)");
! 716: } else {
! 717: name += _("(Inst)");
! 718: }
! 719: windows[id].reset(new WXCacheWindow(this, name,
! 720: gMonitorManager.Get(id)));
1.1 root 721: break;
1.1.1.10! root 722: }
! 723:
! 724: case ID_SUBWIN_LCDPANEL:
! 725: windows[id].reset(new WXLCDWindow(this));
1.1 root 726: break;
1.1.1.10! root 727: case ID_SUBWIN_LOG:
! 728: windows[id].reset(new WXLogMonitor(this));
1.1 root 729: break;
1.1.1.10! root 730: case ID_SUBWIN_LUNAFB0:
! 731: windows[id].reset(new WXLunaBitmapWindow(this, _("Bitmap #0")));
1.1 root 732: break;
1.1.1.10! root 733:
! 734: case ID_SUBWIN_SOFTKEY:
! 735: windows[id].reset(new WXSoftKeyWindow(this, gMainApp.GetVMType()));
1.1.1.5 root 736: break;
1.1.1.10! root 737:
! 738: default:
! 739: assert(false);
1.1 root 740: }
741: windows[id]->Show();
742: } else {
743: // チェックが消えたのでウィンドウを終了
744: windows[id]->Close();
745: // (削除自体はこの少し下の DeleteWindow() で行なっている)
746: }
747: }
748:
749: // Update UI イベント
750: void
751: WXMainFrame::OnWindowUI(wxUpdateUIEvent& event)
752: {
753: int id = event.GetId();
754:
755: // ウィンドウが存在していればチェックを表示
1.1.1.4 root 756: event.Check((bool)windows[id]);
1.1.1.10! root 757:
! 758: if (IS_MONITOR_MEMDUMP(id)) {
! 759: // メニューに現在のアドレスを載せる
! 760: int n = id - ID_MONITOR_MEMDUMP0;
! 761: event.SetText(string_format("%d: $%08x", n,
! 762: WXMemdumpWindow::GetStickyAddr(id)));
! 763: }
1.1.1.4 root 764: }
765:
766: // バージョンダイアログ
767: void
768: WXMainFrame::OnAbout(wxCommandEvent& event)
769: {
770: WXVersionDlg dlg(this);
771: dlg.ShowModal();
1.1 root 772: }
773:
774: // ウィンドウをリストから削除する
775: // (ウィンドウの Close() から呼ばれる)
776: void
1.1.1.10! root 777: WXMainFrame::DeleteWindow(wxWindow *win)
1.1 root 778: {
1.1.1.10! root 779: for (int id = 0; id < ID_SUBWIN_MAX; id++) {
! 780: if (windows[id].get() == win) {
! 781: windows[id].reset();
! 782: break;
! 783: }
! 784: }
1.1 root 785: }
786:
787: // VM 電源オフ時に呼ばれるコールバック。
788: // (VM スレッドからアプリケーションを終了するため)
789: void
790: wxmainframe_poweroff_callback()
791: {
792: gMainFrame->PowerOffCallback();
793: }
794:
795: // VM からの電源オフ処理
796: void
797: WXMainFrame::PowerOffCallback()
798: {
799: wxCommandEvent *ev = new wxCommandEvent(wxEVT_MENU, wxID_EXIT);
800: QueueEvent(ev);
801: }
802:
1.1.1.4 root 803: // m680x0 ダブルバスフォールト時に呼ばれるコールバック。
804: // step1. グローバル関数で受けて、クラスメンバ関数を呼ぶだけ。
805: void
806: wxmainframe_halt_callback(void *arg)
807: {
808: ((WXMainFrame *)arg)->HaltCallback();
809: }
810:
811: // m680x0 ダブルバスフォールト処理。
812: // step2. クラス内だが VM スレッドなので、ここではイベントをポストするだけ。
813: void
814: WXMainFrame::HaltCallback()
815: {
816: wxCommandEvent *ev = new wxCommandEvent(WXW_EVT_HALT_NOTIFY);
817: QueueEvent(ev);
818: }
819:
820: // m680x0 ダブルバスフォールト処理
821: // step3. ここが本題。でもダイアログを出すだけ。
822: void
823: WXMainFrame::OnHaltNotify(wxCommandEvent& event)
824: {
825: ::wxMessageBox(_("Double bus fault has occurred in VM"),
826: wxEmptyString,
827: wxICON_EXCLAMATION);
828: }
829:
1.1.1.10! root 830: // 起動時にオープンするサブウィンドウ (-M オプション)
! 831: /*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.