|
|
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.13 root 7: //
8: // メインウィンドウ
9: //
10:
1.1.1.4 root 11: #include "wxmainframe.h"
1.1.1.13 root 12: #include "fontmanager.h"
1.1.1.15! root 13: #include "wxdipswwindow.h"
1.1.1.4 root 14: #include "wxdumpmonitor.h"
1.1.1.5 root 15: #include "wxlcdwindow.h"
1.1.1.4 root 16: #include "wxlogmonitor.h"
1.1.1.13 root 17: #include "wxlogsetting.h"
1.1.1.4 root 18: #include "wxmainview.h"
19: #include "wxmonitor.h"
20: #include "wxmpumonitor.h"
1.1.1.15! root 21: #include "wxpalettemonitor.h"
1.1.1.14 root 22: #include "wxplanemonitor.h"
23: #include "wxromwindow.h"
1.1.1.4 root 24: #include "wxsoftkey.h"
1.1.1.9 root 25: #include "wxstatuspanel.h"
1.1.1.11 root 26: #include "wxuimessage.h"
1.1.1.4 root 27: #include "wxversion.h"
1.1.1.13 root 28: #include "config.h"
1.1.1.14 root 29: #include "fdc.h"
30: #include "fdd.h"
1.1.1.3 root 31: #include "mainapp.h"
1.1.1.13 root 32: #include "nmi.h"
33: #include "power.h"
1.1.1.11 root 34: #include "spc.h"
1.1.1.15! root 35: #include "syncer.h"
1.1.1.4 root 36: #include "vm.h"
1.1.1.15! root 37: #include <algorithm>
1.1 root 38:
1.1.1.13 root 39: // ID は 0 から (wxID_LOWEST = 5000 未満まで) 使えるっぽい。
40: // メニュー ID のうちウィンドウのオープン状態を維持する必要があるものは
41: // (ID が 0 から使えるのなら) 0 から割り当てて配列で管理してしまうのが
42: // 手っ取り早い。
43: // ウィンドウに割り当てるウィンドウ ID とメニューイベントで飛んでくる
44: // メニュー ID は互いに干渉しないはずなので、同じ値を使うことでメニューと
45: // ウィンドウの紐付けをする。
46: //
47: // ウィンドウ(サブウィンドウ)は細かくは以下のように4つに分類できるが、
48: // 処理上区別が必要なのは A. (デバッガの show コマンドとも共用できる
49: // サブウィンドウ) とそれ以外のサブウィンドウだけ。
50: //
51: // -----------+------------+----
52: // モニター | テキスト | A. 単純なテキストモニタウィンドウ
53: // ウィンドウ | モニター | (SPC, MFP などのデバイスのモニター)
54: // | ウィンドウ +----
55: // | | B. それ以外のテキストモニターウィンドウ
56: // | | (ログ、メモリのように表示位置があるもの、
57: // | | CMMU のように構造があるもの)
58: // +------------+----
59: // | それ以外の | C. ビデオモニターウィンドウなど
60: // | モニター | (ビットマッププレーン、TVRAM など)
61: // | ウィンドウ |
62: // -----------+------------+----
63: // それ以外のウィンドウ | D. ソフトウェアキーボードウィンドウなど
64: // ------------------------+----
65: enum {
66: ID_SUBWIN_END_DUMMY = ID_SUBWIN_END,
67:
68: // ここから (ウィンドウでない)メニュー ID
1.1.1.15! root 69: ID_EXIT,
1.1.1.13 root 70: ID_RESTART_VM,
71: ID_FULL_SPEED,
72:
73: ID_INPUT_START,
74: ID_INPUT_CHAR,
75: ID_INPUT_JP,
76: ID_INPUT_END,
77:
78: ID_SCALE_START,
1.1.1.15! root 79: ID_SCALE_END = ID_SCALE_START + 6,
1.1.1.13 root 80:
81: ID_FONTSIZE_START, // START 以降は fontsize_t と同じ順に並べること
82: ID_FONTSIZE_12,
83: ID_FONTSIZE_16,
1.1.1.15! root 84: ID_FONTSIZE_24,
1.1.1.13 root 85: ID_FONTSIZE_END,
86:
87: ID_MONRATE_START,
1.1.1.15! root 88: ID_MONRATE_END = ID_MONRATE_START + 4,
1.1.1.13 root 89:
90: ID_SHOW_STATPANEL,
91:
1.1.1.14 root 92: // FD
93: ID_FD_INSERT_0,
94: ID_FD_INSERT_1,
95: ID_FD_INSERT_2,
96: ID_FD_INSERT_3,
97: ID_FD_MISINSERT_0,
98: ID_FD_MISINSERT_1,
99: ID_FD_MISINSERT_2,
100: ID_FD_MISINSERT_3,
101: ID_FD_EJECT_0,
102: ID_FD_EJECT_1,
103: ID_FD_EJECT_2,
104: ID_FD_EJECT_3,
105: ID_FD_FORCE_0,
106: ID_FD_FORCE_1,
107: ID_FD_FORCE_2,
108: ID_FD_FORCE_3,
109:
1.1.1.13 root 110: // CD/MO (リムーバブルデバイス)
111: ID_CD_INSERT_0,
112: ID_CD_INSERT_1,
113: ID_CD_INSERT_2,
114: ID_CD_INSERT_3,
115: ID_CD_INSERT_4,
116: ID_CD_INSERT_5,
117: ID_CD_INSERT_6,
118: ID_CD_INSERT_7,
119: ID_CD_EJECT_0,
120: ID_CD_EJECT_1,
121: ID_CD_EJECT_2,
122: ID_CD_EJECT_3,
123: ID_CD_EJECT_4,
124: ID_CD_EJECT_5,
125: ID_CD_EJECT_6,
126: ID_CD_EJECT_7,
127: ID_CD_FORCE_0,
128: ID_CD_FORCE_1,
129: ID_CD_FORCE_2,
130: ID_CD_FORCE_3,
131: ID_CD_FORCE_4,
132: ID_CD_FORCE_5,
133: ID_CD_FORCE_6,
134: ID_CD_FORCE_7,
135:
136: ID_MOUSEMODE,
1.1.1.14 root 137: ID_POWER_BUTTON,
1.1.1.13 root 138: ID_RESET_BUTTON,
139: ID_NMI_BUTTON,
140: ID_KEYBOARD_CONNECT,
141:
142: ID_local_end, // 最後に置く (チェック用)
143: };
1.1.1.14 root 144: static_assert(ID_local_end - 1 <= (int)IDGROUP_MAINFRAME_END, "ID exceeded");
1.1.1.13 root 145:
1.1.1.14 root 146: #define ID_FD_INSERT(id) (ID_FD_INSERT_0 + (id))
147: #define ID_FD_MISINSERT(id) (ID_FD_MISINSERT_0 + (id))
148: #define ID_FD_EJECT(id) (ID_FD_EJECT_0 + (id))
149: #define ID_FD_FORCE(id) (ID_FD_FORCE_0 + (id))
1.1.1.13 root 150: #define ID_CD_INSERT(id) (ID_CD_INSERT_0 + (id))
151: #define ID_CD_EJECT(id) (ID_CD_EJECT_0 + (id))
152: #define ID_CD_FORCE(id) (ID_CD_FORCE_0 + (id))
153:
1.1 root 154: wxBEGIN_EVENT_TABLE(WXMainFrame, inherited)
1.1.1.3 root 155: EVT_CLOSE(WXMainFrame::OnClose)
1.1.1.15! root 156: EVT_MENU(ID_EXIT, WXMainFrame::OnExit)
1.1 root 157:
1.1.1.12 root 158: EVT_MENU(ID_RESTART_VM, WXMainFrame::OnRestartVM)
1.1 root 159: EVT_MENU(ID_FULL_SPEED, WXMainFrame::OnFullSpeed)
160: EVT_UPDATE_UI(ID_FULL_SPEED, WXMainFrame::OnFullSpeedUI)
1.1.1.12 root 161: EVT_MENU_RANGE(ID_INPUT_START + 1, ID_INPUT_END - 1,
162: WXMainFrame::OnMenuInput)
163: EVT_UPDATE_UI_RANGE(ID_INPUT_START + 1, ID_INPUT_END -1,
164: WXMainFrame::OnMenuInputUI)
1.1.1.15! root 165: EVT_MENU_RANGE(ID_SCALE_START, ID_SCALE_END,
1.1 root 166: WXMainFrame::OnMenuScale)
1.1.1.15! root 167: EVT_UPDATE_UI_RANGE(ID_SCALE_START, ID_SCALE_END,
1.1 root 168: WXMainFrame::OnMenuScaleUI)
169: EVT_MENU_RANGE(ID_FONTSIZE_START + 1, ID_FONTSIZE_END - 1,
170: WXMainFrame::OnMenuFontSize)
171: EVT_UPDATE_UI_RANGE(ID_FONTSIZE_START + 1, ID_FONTSIZE_END - 1,
172: WXMainFrame::OnMenuFontSizeUI)
1.1.1.15! root 173: EVT_MENU_RANGE(ID_MONRATE_START, ID_MONRATE_END,
1.1.1.5 root 174: WXMainFrame::OnMenuMonRate)
1.1.1.15! root 175: EVT_UPDATE_UI_RANGE(ID_MONRATE_START, ID_MONRATE_END,
1.1.1.5 root 176: WXMainFrame::OnMenuMonRateUI)
1.1.1.9 root 177: EVT_MENU(ID_SHOW_STATPANEL, WXMainFrame::OnShowStatusPanel)
178: EVT_UPDATE_UI(ID_SHOW_STATPANEL, WXMainFrame::OnShowStatusPanelUI)
1.1.1.14 root 179: EVT_MENU_RANGE(ID_FD_INSERT_0, ID_FD_INSERT_3,
180: WXMainFrame::OnFDInsert)
181: EVT_UPDATE_UI_RANGE(ID_FD_INSERT_0, ID_FD_INSERT_3,
182: WXMainFrame::OnFDInsertUI)
183: EVT_MENU_RANGE(ID_FD_EJECT_0, ID_FD_EJECT_3,
184: WXMainFrame::OnFDEject)
185: EVT_UPDATE_UI_RANGE(ID_FD_EJECT_0, ID_FD_EJECT_3,
186: WXMainFrame::OnFDEjectUI)
187: EVT_MENU_RANGE(ID_FD_FORCE_0, ID_FD_FORCE_3,
188: WXMainFrame::OnFDForce)
189: EVT_UPDATE_UI_RANGE(ID_FD_FORCE_0, ID_FD_FORCE_3,
190: WXMainFrame::OnFDForceUI)
1.1.1.11 root 191: EVT_MENU_RANGE(ID_CD_INSERT_0, ID_CD_INSERT_7,
192: WXMainFrame::OnCDInsert)
193: EVT_UPDATE_UI_RANGE(ID_CD_INSERT_0, ID_CD_INSERT_7,
194: WXMainFrame::OnCDInsertUI)
195: EVT_MENU_RANGE(ID_CD_EJECT_0, ID_CD_EJECT_7,
196: WXMainFrame::OnCDEject)
197: EVT_UPDATE_UI_RANGE(ID_CD_EJECT_0, ID_CD_EJECT_7,
198: WXMainFrame::OnCDEjectUI)
199: EVT_MENU_RANGE(ID_CD_FORCE_0, ID_CD_FORCE_7,
200: WXMainFrame::OnCDForce)
201: EVT_UPDATE_UI_RANGE(ID_CD_FORCE_0, ID_CD_FORCE_7,
202: WXMainFrame::OnCDForceUI)
1.1.1.2 root 203: EVT_MENU(ID_MOUSEMODE, WXMainFrame::OnMouseMode)
204: EVT_UPDATE_UI(ID_MOUSEMODE, WXMainFrame::OnMouseModeUI)
1.1.1.14 root 205: EVT_MENU(ID_POWER_BUTTON, WXMainFrame::OnPowerButton)
206: EVT_UPDATE_UI(ID_POWER_BUTTON, WXMainFrame::OnPowerButtonUI)
1.1.1.9 root 207: EVT_MENU(ID_RESET_BUTTON, WXMainFrame::OnResetButton)
1.1.1.13 root 208: EVT_MENU(ID_NMI_BUTTON, WXMainFrame::OnNMIButton)
209: EVT_MENU(ID_KEYBOARD_CONNECT, WXMainFrame::OnKeyboardConnect)
210: EVT_UPDATE_UI(ID_KEYBOARD_CONNECT, WXMainFrame::OnKeyboardConnectUI)
1.1.1.10 root 211: EVT_MENU_RANGE(0, ID_SUBWIN_END, WXMainFrame::OnWindow)
212: EVT_UPDATE_UI_RANGE(0, ID_SUBWIN_END, WXMainFrame::OnWindowUI)
1.1.1.4 root 213: EVT_MENU(wxID_ABOUT, WXMainFrame::OnAbout)
1.1 root 214: wxEND_EVENT_TABLE()
215:
216: WXMainFrame::WXMainFrame(wxWindow *parent)
1.1.1.10 root 217: : inherited(parent, wxID_ANY, "nono", wxDefaultPosition, wxDefaultSize,
1.1.1.6 root 218: wxDEFAULT_FRAME_STYLE & ~wxMAXIMIZE_BOX & ~wxRESIZE_BORDER)
1.1 root 219: {
1.1.1.14 root 220: VMType vmtype;
1.1.1.3 root 221: vmtype = gMainApp.GetVMType();
1.1 root 222:
1.1.1.15! root 223: // デバイスを取得
! 224: power = GetPowerDevice();
! 225: syncer = GetSyncer();
! 226: // デバイスを取得。こっちはあるかどうかを調べる
! 227: keyboard = gMainApp.FindObject<Keyboard>(OBJ_KEYBOARD);
! 228:
1.1.1.12 root 229: // メニュー
1.1 root 230: wxMenuBar *menubar = new wxMenuBar();
1.1.1.12 root 231: // メニュー > ファイル
1.1 root 232: wxMenu *menuFile = new wxMenu();
1.1.1.9 root 233: menuFile->Append(ID_RESTART_VM, _("&Restart VM"), "");
1.1.1.15! root 234: menuFile->Append(ID_EXIT, _("E&xit"));
1.1.1.4 root 235: menubar->Append(menuFile, _("&File"));
1.1 root 236:
1.1.1.12 root 237: // メニュー > 設定
238: wxMenu *menuSet = new wxMenu();
239: menuSet->Append(ID_FULL_SPEED, _("Full &Speed Mode"), "", wxITEM_CHECK);
1.1.1.15! root 240: if (keyboard) {
! 241: wxMenu *menuSetInput = new wxMenu();
! 242: menuSetInput->AppendRadioItem(ID_INPUT_CHAR, _("By &Character"));
! 243: menuSetInput->AppendRadioItem(ID_INPUT_JP, _("&JP Keyboard"));
! 244: menuSet->AppendSubMenu(menuSetInput, _("&Key Input"));
! 245: }
1.1.1.12 root 246: menubar->Append(menuSet, _("&Setting"));
247:
248: // メニュー > 表示
1.1 root 249: wxMenu *menuDisplay = new wxMenu();
250: wxMenu *menuViewScale = new wxMenu();
1.1.1.15! root 251: int user_idx = CreateMainviewScaleTable();
! 252: for (int i = 0, end = view_scales.size(); i < end; i++) {
! 253: std::string text;
! 254: if (i == user_idx) {
! 255: // ユーザ指定値は極力指定されたまま表示。
! 256: text = string_format("x%g", view_scales[i]);
! 257: } else {
! 258: // プリセットの数値は "0.5", "0.75", "1.0" と都合よく整形したい。
! 259: text = string_format("x%.2f", view_scales[i]);
! 260: if (text.size() == 5 && text[4] == '0') {
! 261: text.pop_back();
! 262: }
! 263: }
! 264: menuViewScale->AppendRadioItem(ID_SCALE_START + i, text);
! 265: }
1.1.1.4 root 266: menuDisplay->AppendSubMenu(menuViewScale, _("&Scale"));
1.1 root 267: wxMenu *menuFontSize = new wxMenu();
1.1.1.4 root 268: menuFontSize->AppendRadioItem(ID_FONTSIZE_12, "1&2");
269: menuFontSize->AppendRadioItem(ID_FONTSIZE_16, "1&6");
1.1.1.15! root 270: menuFontSize->AppendRadioItem(ID_FONTSIZE_24, "2&4");
1.1.1.4 root 271: menuDisplay->AppendSubMenu(menuFontSize, _("&Font Size"));
1.1.1.5 root 272: wxMenu *menuMonRate = new wxMenu();
1.1.1.15! root 273: user_idx = CreateMonRateTable();
! 274: for (int i = 0, end = monrates.size(); i < end; i++) {
! 275: std::string text;
! 276: switch (monrates[i]) {
! 277: case 20: text = _("High (&20Hz)"); break;
! 278: case 5: text = _("Middle (&5Hz)"); break;
! 279: case 1: text = _("Low (&1Hz)"); break;
! 280: default:
! 281: text = _("User specified") + string_format(" (%dHz)", monrates[i]);
! 282: break;
! 283: }
! 284: menuMonRate->AppendRadioItem(ID_MONRATE_START + i, text);
! 285: }
1.1.1.5 root 286: menuDisplay->AppendSubMenu(menuMonRate, _("&Monitor Speed"));
1.1.1.9 root 287: menuDisplay->Append(ID_SHOW_STATPANEL, _("Show Status &Panel"), "",
288: wxITEM_CHECK);
1.1.1.4 root 289: menubar->Append(menuDisplay, _("&View"));
1.1 root 290:
1.1.1.12 root 291: // メニュー > デバイス
1.1 root 292: wxMenu *menuDevice = new wxMenu();
1.1.1.11 root 293: CreateRemovableMenu(menuDevice);
1.1.1.15! root 294: if (keyboard) {
! 295: menuDevice->Append(ID_SUBWIN_SOFTKEY, _("Software &Keyboard"),
! 296: "", wxITEM_CHECK);
! 297: menuDevice->Append(ID_MOUSEMODE, _("&Mouse Mode\tCTRL+F12"),
! 298: "", wxITEM_CHECK);
! 299: }
1.1.1.14 root 300: if (gMainApp.Has(VMCap::LUNA)) {
1.1.1.10 root 301: menuDevice->Append(ID_SUBWIN_LCDPANEL, _("Front &LCD"),
1.1.1.5 root 302: "", wxITEM_CHECK);
303: }
1.1.1.15! root 304: if (gMainApp.Has(VMCap::LUNA | VMCap::NEWS)) {
! 305: menuDevice->Append(ID_SUBWIN_DIPSW, "&DIPSW", "", wxITEM_CHECK);
! 306: }
1.1.1.9 root 307: menuDevice->AppendSeparator();
1.1.1.10 root 308: wxMenu *menuOper = new wxMenu();
1.1.1.14 root 309: wxItemKind power_button_kind;
310: if (gMainApp.Has(VMCap::LUNA)) {
311: power_button_kind = wxITEM_NORMAL;
312: } else {
313: power_button_kind = wxITEM_CHECK;
314: }
315: menuOper->Append(ID_POWER_BUTTON, _("Push &Power button"),
316: "", power_button_kind);
1.1.1.10 root 317: menuOper->Append(ID_RESET_BUTTON, _("Push &Reset button"));
1.1.1.14 root 318: if (gMainApp.Has(VMCap::LUNA)) {
1.1.1.13 root 319: menuOper->Append(ID_NMI_BUTTON, _("Push &ABORT button"));
1.1.1.15! root 320: } else if (gMainApp.Has(VMCap::X68030)) {
1.1.1.13 root 321: menuOper->Append(ID_NMI_BUTTON, _("Push &Interrupt button"));
322: }
1.1.1.15! root 323: // これ以降があればここにセパレータがほしい
! 324: bool sep = false;
! 325: if (keyboard) {
! 326: if (sep == false) {
! 327: menuOper->AppendSeparator();
! 328: sep = true;
! 329: }
! 330: menuOper->Append(ID_KEYBOARD_CONNECT, _("Connect &Keyboard"),
! 331: "", wxITEM_CHECK);
! 332: }
! 333: menuDevice->AppendSubMenu(menuOper, _("&Operation"));
1.1.1.4 root 334: menubar->Append(menuDevice, _("&Device"));
335:
336: // 機種によってモニタウィンドウを追加する
337: #define AppendIf(menu, id, label) do { \
1.1.1.14 root 338: VMCap vmcap_ = gMonitorManager->GetVMCap(id); \
339: if (gMainApp.Has(vmcap_)) { \
1.1.1.10 root 340: (menu)->Append((id), (label), "", wxITEM_CHECK); \
341: } \
342: } while (0)
1.1.1.14 root 343: #define AppendIfSeparator(menu, vmcap_) do { \
344: if (gMainApp.Has(vmcap_)) { \
1.1.1.10 root 345: (menu)->AppendSeparator(); \
1.1.1.4 root 346: } \
347: } while (0)
1.1 root 348:
1.1.1.12 root 349: // メニュー > モニター
1.1 root 350: wxMenu *menuMonitor = new wxMenu();
1.1.1.10 root 351: AppendIf(menuMonitor, ID_MONITOR_SCHEDULER, _("&Scheduler"));
1.1.1.5 root 352:
1.1.1.4 root 353: wxMenu *menuMPU = new wxMenu();
1.1.1.10 root 354: AppendIf(menuMPU, ID_MONITOR_MPUREG, _("&Register"));
355: AppendIf(menuMPU, ID_MONITOR_MPUATC, "&ATC");
1.1.1.15! root 356: AppendIf(menuMPU, ID_MONITOR_INTERRUPT, _("&Interrupt"));
1.1.1.14 root 357: AppendIfSeparator(menuMPU, VMCap::M88K);
1.1.1.13 root 358: AppendIf(menuMPU, ID_MONITOR_CMMU7, "CMMU#7" + _("(Inst)"));
1.1.1.10 root 359: AppendIf(menuMPU, ID_MONITOR_ATC7, "ATC#7");
360: AppendIf(menuMPU, ID_SUBWIN_CACHE7, _("Cache") + "#7");
1.1.1.14 root 361: AppendIfSeparator(menuMPU, VMCap::M88K);
1.1.1.10 root 362: AppendIf(menuMPU, ID_MONITOR_CMMU6, "CMMU#6" + _("(Data)"));
363: AppendIf(menuMPU, ID_MONITOR_ATC6, "ATC#6");
364: AppendIf(menuMPU, ID_SUBWIN_CACHE6, _("Cache") + "#6");
1.1.1.15! root 365: menuMPU->AppendSeparator();
! 366: // MEMDUMPn のラベルは UpdateUI で書き直すのでここでは適当に
! 367: // 埋めておく。(empty だと怒られる)
! 368: for (int i = 0; i < MAX_MEMDUMP_MONITOR; i++) {
! 369: AppendIf(menuMPU, ID_MONITOR_MEMDUMP(i), "memdump");
! 370: }
! 371: menuMPU->AppendSeparator();
! 372: AppendIf(menuMPU, ID_SUBWIN_BRHIST, _("Branch &History"));
! 373: AppendIf(menuMPU, ID_SUBWIN_EXHIST, _("&Exception History"));
! 374: AppendIf(menuMPU, ID_SUBWIN_VECTOR, _("&Vector Table"));
! 375: menuMonitor->AppendSubMenu(menuMPU,
! 376: (gMainApp.Has(VMCap::M68K) ? "&MPU(MC68030)" : "&MPU(MC88xx0)"));
! 377:
! 378: if (gMainApp.Has(VMCap::LUNA)) {
! 379: wxMenu *menuXP = new wxMenu();
! 380: AppendIf(menuXP, ID_MONITOR_XPREG, _("&Register"));
! 381: AppendIf(menuXP, ID_MONITOR_XPINTR, _("&Interrupt"));
! 382: AppendIf(menuXP, ID_MONITOR_XPIO, _("Internal &Devices"));
! 383: menuXP->AppendSeparator();
! 384: for (int i = 0; i < MAX_XPMEMDUMP_MONITOR; i++) {
! 385: AppendIf(menuXP, ID_MONITOR_XPMEMDUMP(i), "memdump");
! 386: }
! 387: menuXP->AppendSeparator();
! 388: AppendIf(menuXP, ID_SUBWIN_XPBRHIST, _("Branch &History"));
! 389: AppendIf(menuXP, ID_SUBWIN_XPEXHIST, _("&Exception History"));
! 390: menuMonitor->AppendSubMenu(menuXP, "XP(HD647180)");
! 391: }
1.1.1.10 root 392:
393: // MONITOR_RTC は X68k の RTC、LUNA では MONITOR_MK48T02 だが今の所
394: // NVRAM 側のことは表示してないのでラベルも RTC にしてある。
1.1.1.15! root 395: wxMenu *menuDev = new wxMenu();
! 396: AppendIf(menuDev, ID_MONITOR_SPC, "SPC");
! 397: AppendIf(menuDev, ID_MONITOR_SCSIDEVS, _("SCSI Devices"));
! 398: AppendIf(menuDev, ID_MONITOR_RTC, "RTC");
! 399: AppendIf(menuDev, ID_MONITOR_MK48T02, "RTC");
! 400: AppendIf(menuDev, ID_MONITOR_DMAC, "DMAC");
! 401: AppendIf(menuDev, ID_MONITOR_MFP, "MFP");
! 402: AppendIf(menuDev, ID_MONITOR_FDC, "FDC");
! 403: AppendIf(menuDev, ID_MONITOR_SCC, "SCC");
! 404: AppendIf(menuDev, ID_MONITOR_SIO, "SIO");
! 405: AppendIf(menuDev, ID_MONITOR_PIO, "PIO0/PIO1");
! 406: AppendIf(menuDev, ID_MONITOR_KEYBOARD, _("Keyboard/Mouse"));
! 407: AppendIf(menuDev, ID_MONITOR_LANCE, "Lance");
! 408: AppendIf(menuDev, ID_MONITOR_LCD, "LCD");
! 409: AppendIf(menuDev, ID_MONITOR_SYSCLK, _("System Clock"));
! 410: AppendIf(menuDev, ID_MONITOR_CRTC, "CRTC");
! 411: AppendIf(menuDev, ID_MONITOR_LUNAVC, _("Video Control"));
! 412: AppendIf(menuDev, ID_MONITOR_BT45x, "Bt454/458");
! 413: AppendIf(menuDev, ID_SUBWIN_PALETTE, _("Palette Colormap"));
! 414: AppendIf(menuDev, ID_SUBWIN_TEXTPAL, _("Text Palette Colormap"));
! 415: AppendIf(menuDev, ID_MONITOR_RENDERER, _("Renderer"));
! 416: AppendIf(menuDev, ID_SUBWIN_LUNAFB, _("Bitmap Plane"));
! 417: AppendIf(menuDev, ID_SUBWIN_TVRAM, _("Text VRAM"));
! 418: AppendIf(menuDev, ID_MONITOR_ROMCONS, _("ROM Console (provisional)"));
! 419: AppendIf(menuDev, ID_SUBWIN_ROM, "ROM");
! 420: menuMonitor->AppendSubMenu(menuDev, _("De&vice"));
1.1.1.5 root 421:
422: wxMenu *menuHost = new wxMenu();
1.1.1.10 root 423: AppendIf(menuHost, ID_MONITOR_WXHOSTINFO, _("Host &Information"));
424: AppendIf(menuHost, ID_MONITOR_HOSTNET, _("Host &Network"));
1.1.1.13 root 425: AppendIf(menuHost, ID_MONITOR_HOSTCOM, _("Host &Serial Port"));
1.1.1.5 root 426: menuMonitor->AppendSubMenu(menuHost, _("&Host"));
427:
1.1.1.15! root 428: wxMenu *menuDebug = new wxMenu();
! 429: AppendIf(menuDebug, ID_SUBWIN_LOG, _("&Log"));
! 430: AppendIf(menuDebug, ID_MONITOR_BREAKPOINT, _("&Breakpoint"));
! 431: menuDebug->AppendSeparator();
! 432: AppendIf(menuDebug, ID_SUBWIN_LOGSETTING, _("Log Level &Setting"));
! 433: menuMonitor->AppendSubMenu(menuDebug, _("&Debug"));
! 434:
1.1.1.4 root 435: menubar->Append(menuMonitor, _("&Monitor"));
436:
1.1.1.12 root 437: // メニュー > ヘルプ
1.1.1.4 root 438: #if defined(__WXOSX__)
439: // OSX では wxID_ABOUT はリンゴメニューに入れるしきたりになっている。
440: // Append() すると Quit より下に来てしまうので、Prepend() で上に追加。
441: // 今のところヘルプメニューから About ダイアログを抜くとメニューが空に
442: // なってしまうので、ヘルプメニューの追加ごと抑制する。
443: menubar->OSXGetAppleMenu()->Prepend(wxID_ABOUT, _("About nono"));
444: #else
445: wxMenu *menuHelp = new wxMenu();
446: menuHelp->Append(wxID_ABOUT, _("About nono"));
447: menubar->Append(menuHelp, _("&Help"));
448: #endif
449:
1.1 root 450: SetMenuBar(menubar);
451:
452: wxString title("nono");
453: switch (vmtype) {
1.1.1.14 root 454: case VMType::X68030:
1.1.1.3 root 455: title += "(X68030)";
456: break;
1.1.1.14 root 457: case VMType::LUNA1:
1.1 root 458: title += "(LUNA-I)";
459: break;
1.1.1.14 root 460: case VMType::LUNA88K:
1.1.1.15! root 461: title += "(LUNA-88K)";
! 462: break;
! 463: case VMType::NEWS:
! 464: title += "(NWS-1750)";
1.1.1.3 root 465: break;
466: default:
1.1 root 467: break;
468: }
469: SetTitle(title);
470:
471: // UpdateUI イベントは Idle 時に時折チェックされるらしいが、
472: // (メインビューとサブウィンドウを合わせた) タイマーイベントの粒度が
473: // 小さいためか、秒間120回とかいうレベルで UpdateUIEvent が飛んでくる
474: // っぽい (全タイマーをとめたら治る模様)。
475: // さすがにそんなに来られても気持ち悪いのと、どうせメニュー開いた瞬間
476: // 表示しようとする前には一度飛んでくるのだから、アイドル時のチェックは
477: // いらない気がする。間隔広げておいても、ぱっと見副作用はなさそうだけど
478: // 念のため事象が分かりやすいように 10秒くらいにしておく。
479: wxUpdateUIEvent::SetUpdateInterval(10000);
480:
1.1.1.15! root 481: // WXStatusPanel コンストラクタが mainview を参照するので
! 482: // mainview のほうを先に作成すること。
! 483: mainview = new WXMainView(this);
! 484: statuspanel = new WXStatusPanel(this);
1.1 root 485:
1.1.1.9 root 486: // SHOW イベントを最初にも一度起こしたいため
487: // ステータスパネルを一旦非表示にする (これで SHOW(false) イベントが飛ぶ)
1.1.1.15! root 488: statuspanel->Hide();
1.1.1.9 root 489: const ConfigItem& item_show = gConfig->Find("show-statuspanel");
490: if (item_show.AsInt() != 0) {
491: // 必要なら改めて表示 (これで SHOW(true) イベントが飛ぶ)
1.1.1.15! root 492: statuspanel->Show();
1.1.1.9 root 493: }
494:
1.1.1.13 root 495: // Sizer 使わず自前でレイアウトする。
496: SetAutoLayout(true);
1.1 root 497:
1.1.1.4 root 498: // Activate イベントは、このトップレベルウィンドウにウィンドウフォーカスが
499: // 来た or 外れたことを示すので、wxFrame (というかたぶん wxTopLevelWindow)
500: // を継承している WXMainFrameに飛んでくるのだが、処理の都合上 WXMainView で
501: // 扱いたいので、そちらに回す。
502: Connect(wxEVT_ACTIVATE, wxActivateEventHandler(WXMainView::OnActivate),
1.1.1.15! root 503: NULL, mainview);
1.1.1.4 root 504:
1.1.1.11 root 505: // ウィンドウ表示後に続きの処理をするための単発アイドルイベント。
506: Connect(wxEVT_IDLE, wxIdleEventHandler(WXMainFrame::OnIdle));
507:
508: // VM からの通知を接続
1.1.1.13 root 509: WXUIMessage::Connect(UIMessage::APPEXIT, this,
1.1.1.11 root 510: wxCommandEventHandler(WXMainFrame::OnExit));
511: WXUIMessage::Connect(UIMessage::SCSI_MEDIA_FAILED, this,
1.1.1.14 root 512: wxCommandEventHandler(WXMainFrame::OnInsertFailed));
513: WXUIMessage::Connect(UIMessage::FDD_MEDIA_FAILED, this,
514: wxCommandEventHandler(WXMainFrame::OnInsertFailed));
1.1.1.15! root 515: if (gMainApp.Has(VMCap::M68K)) {
1.1.1.11 root 516: WXUIMessage::Connect(UIMessage::HALT, this,
517: wxCommandEventHandler(WXMainFrame::OnHaltNotify));
518: }
1.1 root 519: }
520:
521: WXMainFrame::~WXMainFrame()
522: {
1.1.1.15! root 523: WXUIMessage::Disconnect(UIMessage::APPEXIT, this,
1.1.1.13 root 524: wxCommandEventHandler(WXMainFrame::OnExit));
1.1.1.15! root 525: WXUIMessage::Disconnect(UIMessage::SCSI_MEDIA_FAILED, this,
1.1.1.14 root 526: wxCommandEventHandler(WXMainFrame::OnInsertFailed));
1.1.1.15! root 527: WXUIMessage::Disconnect(UIMessage::FDD_MEDIA_FAILED, this,
1.1.1.14 root 528: wxCommandEventHandler(WXMainFrame::OnInsertFailed));
1.1.1.15! root 529: if (gMainApp.Has(VMCap::M68K)) {
! 530: WXUIMessage::Disconnect(UIMessage::HALT, this,
1.1.1.13 root 531: wxCommandEventHandler(WXMainFrame::OnHaltNotify));
532: }
1.1 root 533: }
534:
1.1.1.11 root 535: // リムーバブルデバイス用のメニューを作成して menuDevice に追加する
536: void
537: WXMainFrame::CreateRemovableMenu(wxMenu *menuDevice)
538: {
539: wxMenu *menu;
540: bool added = false;
541:
542: // FD
1.1.1.15! root 543: for (int unit = 0; unit < FDCDevice::MAX_DRIVE; unit++) {
! 544: fdd_array[unit] = gMainApp.FindObject<FDDDevice>(OBJ_FDD(unit));
! 545: if (fdd_array[unit]) {
1.1.1.14 root 546: menu = CreateFDMenu(unit);
547: std::string label = string_format("FD%d", unit);
548: menuDevice->AppendSubMenu(menu, label);
549: added = true;
550: }
551: }
1.1.1.11 root 552:
553: // CD, MO
1.1.1.15! root 554: auto spc = gMainApp.FindObject<SPCDevice>(OBJ_SPC);
! 555: if (spc) {
! 556: for (int id = 0; id < 8; id++) {
! 557: scsidev[id] = spc->GetTarget(id);
! 558: if (scsidev[id]) {
! 559: menu = CreateSCSIRemovableMenu(id);
! 560: if (menu) {
! 561: std::string label = string_format("%s (ID%d)",
! 562: SCSI::GetDevTypeName(scsidev[id]->GetDevType()), id);
! 563: menuDevice->AppendSubMenu(menu, label);
! 564: added = true;
! 565: }
1.1.1.11 root 566: }
567: }
568: }
569:
570: // 1つでも追加したらセパレータ
571: if (added) {
572: menuDevice->AppendSeparator();
573: }
574: }
575:
1.1.1.14 root 576: // FD 用のメニューを作成して返す。
577: wxMenu *
578: WXMainFrame::CreateFDMenu(int unit) const
579: {
580: wxMenu *menu = new wxMenu();
581: // Insert の実際のラベルは UpdateUI でセットする。
582: // ただし何か入れておかないといけないので適当にセット。
583: menu->Append(ID_FD_INSERT(unit), "Insert", "");
584: // XXX 未実装
585: //menu->Append(ID_FD_MISINSERT(unit), _("Insert incorrectly"), "");
586: menu->Append(ID_FD_EJECT(unit), _("&Eject"), "");
587: menu->Append(ID_FD_FORCE(unit), _("&Force Eject"), "");
588: return menu;
589: }
590:
1.1.1.11 root 591: // SCSI リムーバブルデバイス用のメニューを作成して返す。
592: // id はデバイスが接続されていること (リムーバブルデバイスであるかは問わない)。
593: // リムーバブルデバイスでなければ NULL を返す。
594: // メニューバーとポップアップメニュー共通。
595: wxMenu *
596: WXMainFrame::CreateSCSIRemovableMenu(uint id) const
597: {
598: const auto *dev = scsidev[id];
599: assert(dev);
600:
601: switch (dev->GetDevType()) {
602: case SCSI::DevType::CD:
603: case SCSI::DevType::MO:
604: {
605: wxMenu *menu = new wxMenu();
606: // Insert の実際のラベルは UpdateUI でセットする。
607: // ただし何か入れておかないといけないので適当にセット。
608: menu->Append(ID_CD_INSERT(id), "Insert", "");
609: menu->Append(ID_CD_EJECT(id), _("&Eject"), "");
610: menu->Append(ID_CD_FORCE(id), _("&Force Eject"), "");
611: return menu;
612: }
613: default:
614: return NULL;
615: }
616: }
617:
1.1.1.12 root 618: // (設定反映などの) 初期化。
619: // 成功すれば true、失敗すれば false を返す。
620: bool
621: WXMainFrame::Init()
622: {
1.1.1.15! root 623: if (!mainview->Init()) {
1.1.1.12 root 624: return false;
625: }
626:
627: return true;
628: }
629:
1.1.1.13 root 630: bool
631: WXMainFrame::Layout()
632: {
633: if (inherited::Layout() == false) {
634: return false;
635: }
636:
1.1.1.15! root 637: wxSize msize = statuspanel->GetMinClientSize();
! 638: wxSize ssize = statuspanel->GetClientSize();
! 639: wxSize vsize = mainview->GetClientSize();
1.1.1.13 root 640:
1.1.1.15! root 641: if (statuspanel->IsShown()) {
1.1.1.13 root 642: ssize.y = msize.y;
643: } else {
644: ssize.y = 0;
645: }
646:
647: wxSize size;
648: size.x = std::max(msize.x, vsize.x);
649: size.y = ssize.y + vsize.y;
650:
651: if (ssize.y != 0) {
1.1.1.15! root 652: statuspanel->SetSize(0, 0, size.x, ssize.y);
1.1.1.13 root 653: }
1.1.1.15! root 654: mainview->SetSize(0, ssize.y, size.x, vsize.y);
1.1.1.13 root 655: SetClientSize(size);
656:
657: return true;
658: }
659:
1.1.1.11 root 660: // ウィンドウ作成イベント (を実現するためここではアイドルイベントを使う)
1.1.1.10 root 661: //
1.1.1.11 root 662: // 初期化(っぽい)もののうちコンストラクタでは早すぎるものは、コンストラクタ
663: // 直後に起こすこのイベント内で処理する。使えそうなイベントはいくつかあり、
664: // 自前の Create (今はもうない) -> WindowCreate -> Idle -> Paint の順で
665: // 起きるようだ。
666: // 自前の Create 時点では早すぎて、ここでサブウィンドウを作成するとサイズが 0
667: // みたいなウィンドウが一瞬出来てしまい GTK のワーニングが出る (その後サイズを
668: // 矯正すれば表示自体は出来る)。
1.1.1.10 root 669: // WindowCreate 時点ではその問題は起きないが、ここはまだメインウィンドウ表示
670: // 前なので、ここでサブウィンドウを表示した後メインウィンドウを表示すると
671: // (ウィンドウマネージャにもよるかもだが)、メインウィンドウがサブウィンドウを
672: // 隠してしまう。
1.1.1.11 root 673: // Idle イベント時点まで来ると上の2つの問題は回避できるようだ。
674: // Paint イベントの時点でもタイミング的には問題ないが、環境によっては(?)
675: // このイベント自体が飛んで来ないことがあるようだ。WXMainFrame の再描画は
1.1.1.13 root 676: // 子コントロールが行っており、そのため WXMainFrame 自身が再描画しなければ
677: // ならない領域は存在しないからかも知れないが詳細未調査。
1.1.1.11 root 678: void
679: WXMainFrame::OnIdle(wxIdleEvent& ev)
1.1 root 680: {
1.1.1.11 root 681: // UIMessage の処理を開始する。
682: // 少なくとも WXMainFrame のコンストラクタが完了した後のほうがいいはず。
683: UIMessage::Attach(&WXUIMessage::Process);
684:
1.1 root 685: // ウィンドウを表示
1.1.1.10 root 686: for (int i = 0; i < subwindow_start.size(); i++) {
687: if (subwindow_start[i]) {
1.1 root 688: DoWindow(i, true);
689: }
690: }
691:
1.1.1.9 root 692: // 電源投入
1.1.1.15! root 693: power->PowerButton();
1.1.1.10 root 694:
695: // 一度処理したら、このイベントを外す
1.1.1.11 root 696: Disconnect(wxEVT_IDLE, wxIdleEventHandler(WXMainFrame::OnIdle));
1.1 root 697: }
698:
1.1.1.3 root 699: // ウィンドウクローズイベント
700: void
701: WXMainFrame::OnClose(wxCloseEvent& event)
702: {
1.1.1.9 root 703: // ステータスパネルの更新を停止
1.1.1.15! root 704: statuspanel->Close();
1.1.1.13 root 705: // メインビューの描画を停止
1.1.1.15! root 706: mainview->Close();
1.1.1.9 root 707:
1.1.1.3 root 708: // サブウィンドウを全部閉じる
1.1.1.10 root 709: for (int i = 0; i < ID_SUBWIN_MAX; i++) {
1.1.1.4 root 710: if ((bool)windows[i]) {
1.1.1.3 root 711: windows[i]->Close();
712: }
713: }
714:
715: // VM を解放
1.1.1.4 root 716: gVM->Dispose();
1.1.1.3 root 717:
718: // 後はデフォルト処理
719: event.Skip();
720: }
721:
1.1.1.12 root 722: // メニューの「Restart VM」イベント
723: void
724: WXMainFrame::OnRestartVM(wxCommandEvent& event)
725: {
1.1.1.15! root 726: power->MakeRestart();
1.1.1.12 root 727: }
728:
729: // メニューの「終了」イベント
730: void
731: WXMainFrame::OnExit(wxCommandEvent& event)
732: {
733: // ウィンドウを閉じる
734: Close();
735: }
736:
1.1 root 737: // メニューの「高速モード」イベント
738: void
739: WXMainFrame::OnFullSpeed(wxCommandEvent& event)
740: {
741: if (event.IsChecked()) {
742: // チェックが入ったので、高速モードにする
1.1.1.15! root 743: syncer->RequestFullSpeed(true);
1.1 root 744: } else {
745: // チェックが消えたので、通常モードにする
1.1.1.15! root 746: syncer->RequestFullSpeed(false);
1.1 root 747: }
748: }
749:
750: // メニューの「高速モード」UI
751: void
752: WXMainFrame::OnFullSpeedUI(wxUpdateUIEvent& event)
753: {
1.1.1.15! root 754: bool is_fullspeed = syncer->GetFullSpeed();
1.1 root 755: event.Check(is_fullspeed);
756: }
757:
1.1.1.12 root 758: // メニューの「設定 > 入力 > *」の共通イベント
1.1.1.6 root 759: void
1.1.1.12 root 760: WXMainFrame::OnMenuInput(wxCommandEvent& event)
1.1.1.6 root 761: {
1.1.1.12 root 762: bool char_mode = (event.GetId() == ID_INPUT_CHAR);
763:
1.1.1.15! root 764: mainview->SetCharInputMode(char_mode);
1.1.1.6 root 765: }
766:
1.1.1.12 root 767: // メニューの「設定 > 入力 > *」の共通 UI
1.1 root 768: void
1.1.1.12 root 769: WXMainFrame::OnMenuInputUI(wxUpdateUIEvent& event)
1.1 root 770: {
1.1.1.15! root 771: bool char_mode = mainview->GetCharInputMode();
1.1.1.12 root 772:
773: if (char_mode) {
774: event.Check(event.GetId() == ID_INPUT_CHAR);
775: } else {
776: event.Check(event.GetId() == ID_INPUT_JP);
777: }
1.1 root 778: }
779:
1.1.1.15! root 780: // スケール一覧
! 781: /*static*/ std::vector<double>
! 782: WXMainFrame::view_scales {
! 783: 0.50,
! 784: 0.75,
! 785: 1.00,
! 786: 1.50,
! 787: 2.00,
! 788: };
! 789:
! 790: #define contains(v, key) (std::find(v.begin(), v.end(), key) != v.end())
! 791:
! 792: // 「表示 > スケール」のメニュー項目作成に必要な view_scale を作成し、
! 793: // ユーザ指定値があれば view_scales[] 内でのインデックスを返す。
! 794: // ユーザ指定値がなければ -1 を返す。
! 795: int
! 796: WXMainFrame::CreateMainviewScaleTable()
! 797: {
! 798: // 設定ファイル mainview-scale で指定されたサイズを追加。
! 799: // 値はこの時点で WXMainView::screen_scale にセットされている。
! 800: double user_scale = WXMainView::screen_scale;
! 801: if (contains(view_scales, user_scale)) {
! 802: // プリセットと同じなら、このままでよい。
! 803: } else {
! 804: // 追加したらソート。
! 805: view_scales.push_back(user_scale);
! 806: std::sort(view_scales.begin(), view_scales.end());
! 807:
! 808: // ユーザ指定の値が何番目かを返す。指定されてなければ -1。
! 809: for (int i = 0, end = view_scales.size(); i < end; i++) {
! 810: if (view_scales[i] == user_scale) {
! 811: return i;
! 812: }
! 813: }
! 814: // 見付からないことはないはずだが
! 815: }
! 816: return -1;
! 817: }
! 818:
1.1 root 819: // メニューの「表示 > スケール > *」の共通イベント
820: void
821: WXMainFrame::OnMenuScale(wxCommandEvent& event)
822: {
1.1.1.15! root 823: int idx = event.GetId() - ID_SCALE_START;
! 824: mainview->DoResize(view_scales[idx]);
1.1 root 825: // 再レイアウト
1.1.1.13 root 826: Layout();
1.1 root 827: }
828:
829: // メニューの「表示 > スケール > *」の共通 UI
830: void
831: WXMainFrame::OnMenuScaleUI(wxUpdateUIEvent& event)
832: {
1.1.1.15! root 833: int idx = event.GetId() - ID_SCALE_START;
! 834: double current_scale = mainview->GetScale();
1.1 root 835:
1.1.1.15! root 836: event.Check(view_scales[idx] == current_scale);
1.1 root 837: }
838:
839: // メニューの「表示 > フォントサイズ > *」の共通イベント
840: void
841: WXMainFrame::OnMenuFontSize(wxCommandEvent& event)
842: {
1.1.1.5 root 843: FontId fontid;
1.1 root 844:
1.1.1.3 root 845: assertmsg(
1.1.1.15! root 846: ID_FONTSIZE_12 <= event.GetId() && event.GetId() <= ID_FONTSIZE_24,
1.1.1.3 root 847: "event.GetId()=%d", event.GetId());
1.1 root 848: switch (event.GetId()) {
849: case ID_FONTSIZE_12:
1.1.1.5 root 850: fontid = FontId::_6x12;
1.1 root 851: break;
852: case ID_FONTSIZE_16:
1.1.1.5 root 853: fontid = FontId::_8x16;
1.1 root 854: break;
1.1.1.15! root 855: case ID_FONTSIZE_24:
! 856: fontid = FontId::_12x24;
! 857: break;
1.1 root 858: default:
859: __unreachable();
860: break;
861: }
862:
1.1.1.13 root 863: if (fontid != gFontManager->GetFontId()) {
864: gFontManager->SetFont(fontid);
1.1 root 865:
1.1.1.13 root 866: // アクティブなサブウィンドウ全員にフォント変更通知
1.1.1.10 root 867: for (int i = 0; i < ID_SUBWIN_MAX; i++) {
1.1.1.4 root 868: if ((bool)windows[i]) {
869: WXSubWindow *subwin =
870: dynamic_cast<WXSubWindow *>(windows[i].get());
1.1.1.13 root 871: subwin->FontChanged();
1.1 root 872: }
873: }
1.1.1.13 root 874: // メインウィンドウはここで直接ステータスパネルに通知
1.1.1.15! root 875: statuspanel->FontChanged();
1.1.1.9 root 876:
877: // ステータスパネルの大きさが変わるので再レイアウト
1.1.1.13 root 878: Layout();
1.1 root 879: }
880: }
881:
882: // メニューの「表示 > フォントサイズ > *」共通 UI
883: void
884: WXMainFrame::OnMenuFontSizeUI(wxUpdateUIEvent& event)
885: {
1.1.1.13 root 886: FontId current_size = gFontManager->GetFontId();
1.1.1.5 root 887: FontId event_size = (FontId)(event.GetId() - (ID_FONTSIZE_START+1));
1.1 root 888:
889: event.Check(current_size == event_size);
890: }
891:
1.1.1.15! root 892: // 更新頻度一覧
! 893: /*static*/ std::vector<int>
! 894: WXMainFrame::monrates {
! 895: 20,
! 896: 5,
! 897: 1,
1.1.1.5 root 898: };
899:
1.1.1.15! root 900: // 「表示 > モニタ更新頻度」のメニュー項目作成に必要な monrates を作成し、
! 901: // ユーザ指定値があれば monrates[] 内のインデックスを返す。
! 902: // ユーザ指定値がなければ -1 を返す。
! 903: int
! 904: WXMainFrame::CreateMonRateTable()
! 905: {
! 906: // 設定ファイル monitor-rate で指定された値を追加。
! 907: // 値はこの時点で monitor_rate にセットされている。
! 908: int user_rate = monitor_rate;
! 909: if (contains(monrates, user_rate)) {
! 910: // プリセットと同じなら、このままでよい。
! 911: } else {
! 912: // 追加したら降順にソート。
! 913: monrates.push_back(user_rate);
! 914: std::sort(monrates.begin(), monrates.end(),
! 915: [](int a, int b) { return a > b; }
! 916: );
! 917:
! 918: // ユーザ指定の値が何番目かを返す。指定されてなければ -1。
! 919: for (int i = 0, end = monrates.size(); i < end; i++) {
! 920: if (monrates[i] == user_rate) {
! 921: return i;
! 922: }
! 923: }
! 924: // 見付からないことはないはずだが
! 925: }
! 926: return -1;
! 927: }
! 928:
1.1.1.5 root 929: // メニューの「表示 > モニタ更新頻度 > *」の共通イベント
930: void
931: WXMainFrame::OnMenuMonRate(wxCommandEvent& event)
932: {
1.1.1.15! root 933: int idx = event.GetId() - ID_MONRATE_START;
! 934: monitor_rate = monrates[idx];
1.1.1.5 root 935:
936: // アクティブなサブウィンドウのテキストパネル全員に通知
1.1.1.10 root 937: for (int i = 0; i < ID_SUBWIN_MAX; i++) {
1.1.1.5 root 938: if ((bool)windows[i]) {
939: auto *subwin = dynamic_cast<WXSubWindow *>(windows[i].get());
940: for (wxWindow *child : subwin->GetChildren()) {
1.1.1.14 root 941: auto *panel = dynamic_cast<WXMonitorPanel*>(child);
1.1.1.5 root 942: if (panel) {
943: panel->SetRate(monitor_rate);
944: }
945: }
946: }
947: }
948: }
949:
950: // メニューの「表示 > モニタ更新頻度 > *」共通 UI
951: void
952: WXMainFrame::OnMenuMonRateUI(wxUpdateUIEvent& event)
953: {
1.1.1.15! root 954: int idx = event.GetId() - ID_MONRATE_START;
1.1.1.5 root 955:
1.1.1.15! root 956: event.Check(monrates[idx] == monitor_rate);
1.1.1.5 root 957: }
958:
1.1.1.9 root 959: // メニューの「表示 > ステータスパネルを表示」
960: void
961: WXMainFrame::OnShowStatusPanel(wxCommandEvent& event)
962: {
963: // enable ならチェックを付けようとして呼ばれた
964: bool enable = event.IsChecked();
965:
1.1.1.15! root 966: statuspanel->Show(enable);
1.1.1.9 root 967:
968: // 再レイアウト
1.1.1.13 root 969: Layout();
1.1.1.9 root 970: }
971:
972: // メニューの「表示 > ステータスパネルを表示」UI
973: void
974: WXMainFrame::OnShowStatusPanelUI(wxUpdateUIEvent& event)
975: {
1.1.1.15! root 976: event.Check(statuspanel->IsShown());
1.1.1.9 root 977: }
978:
1.1.1.14 root 979: // メニューの「デバイス > FD > 挿入」
980: void
981: WXMainFrame::OnFDInsert(wxCommandEvent& event)
982: {
983: int unit = event.GetId() - ID_FD_INSERT_0;
984: const auto *fdd = fdd_array[unit];
985: assert(fdd);
986:
987: std::string title(_("Open a FD image"));
988: std::string wildcard("FD images (*.xdf;*.img;*.fs)"
989: "|*.xdf;*.XDF;*.img;*.IMG;*.fs;*.FS"
990: "|All files (*.*)|*.*");
991:
992: // ディレクトリは、まだ一度も使ってなければ VM ディレクトリにする
993: if (current_dir.empty()) {
994: current_dir = gMainApp.GetVMDir();
995: }
996:
997: wxFileDialog dialog(this, title, current_dir, "", wildcard,
998: wxFD_OPEN | wxFD_FILE_MUST_EXIST);
999: if (dialog.ShowModal() == wxID_CANCEL) {
1000: return;
1001: }
1002: auto path = std::string(dialog.GetPath());
1003: InsertFD(unit, path);
1004: }
1005:
1006: // メニューの「デバイス > FD > 挿入」UI
1007: void
1008: WXMainFrame::OnFDInsertUI(wxUpdateUIEvent& event)
1009: {
1010: int unit = event.GetId() - ID_FD_INSERT_0;
1011: const auto *fdd = fdd_array[unit];
1012: assert(fdd);
1013:
1014: if (fdd->IsMediumLoaded()) {
1015: event.SetText(_("Ex&change"));
1016: } else {
1017: event.SetText(_("&Insert"));
1018: }
1019: }
1020:
1021: // メニューの「デバイス > FD > 取り出し」
1022: void
1023: WXMainFrame::OnFDEject(wxCommandEvent& event)
1024: {
1025: int unit = event.GetId() - ID_FD_EJECT_0;
1026:
1027: EjectFD(unit, false);
1028: }
1029:
1030: // メニューの「デバイス > FD > 取り出し」UI
1031: void
1032: WXMainFrame::OnFDEjectUI(wxUpdateUIEvent& event)
1033: {
1034: int unit = event.GetId() - ID_FD_EJECT_0;
1035: FDDDevice *fdd = fdd_array[unit];
1036: assert(fdd);
1037:
1038: // 挿入されてて取り出し可能な時のみ有効
1039: event.Enable(fdd->IsMediumLoaded() && fdd->IsEjectEnable());
1040: }
1041:
1042: // メニューの「デバイス > FD > 強制取り出し」
1043: void
1044: WXMainFrame::OnFDForce(wxCommandEvent& event)
1045: {
1046: int unit = event.GetId() - ID_FD_FORCE_0;
1047:
1048: EjectFD(unit, true);
1049: }
1050:
1051: // メニューの「デバイス > FD > 強制取り出し」UI
1052: void
1053: WXMainFrame::OnFDForceUI(wxUpdateUIEvent& event)
1054: {
1055: int unit = event.GetId() - ID_FD_FORCE_0;
1056: FDDDevice *fdd = fdd_array[unit];
1057: assert(fdd);
1058:
1059: // 挿入されてて取り出し禁止の時のみ有効
1060: event.Enable(fdd->IsMediumLoaded() && fdd->IsEjectEnable() == false);
1061: }
1062:
1.1.1.11 root 1063: // メニューの「デバイス > CD/MO > 挿入」
1064: void
1065: WXMainFrame::OnCDInsert(wxCommandEvent& event)
1066: {
1067: std::string title;
1068: std::string wildcard;
1069:
1070: int id = event.GetId() - ID_CD_INSERT_0;
1071: const auto *dev = scsidev[id];
1072: assert(dev);
1073:
1074: switch (dev->GetDevType()) {
1075: case SCSI::DevType::CD:
1076: title = _("Open a CD image");
1077: wildcard = "ISO images (*.iso;*.img)|*.iso;*.img;*.ISO;*.IMG";
1078: break;
1079: case SCSI::DevType::MO:
1080: title = _("Open an MO image");
1081: wildcard = "MO images (*.img;*.mos)|*.img;*.mos;*.IMG;*.MOS";
1082: break;
1083: default:
1.1.1.15! root 1084: break;
1.1.1.11 root 1085: }
1086: wildcard += "|All files (*.*)|*.*";
1087:
1088: // ディレクトリは、まだ一度も使ってなければ VM ディレクトリにする
1089: if (current_dir.empty()) {
1090: current_dir = gMainApp.GetVMDir();
1091: }
1092:
1093: wxFileDialog dialog(this, title, current_dir, "", wildcard,
1094: wxFD_OPEN | wxFD_FILE_MUST_EXIST);
1095: if (dialog.ShowModal() == wxID_CANCEL) {
1096: return;
1097: }
1098: auto path = std::string(dialog.GetPath());
1099: InsertCD(id, path);
1100: }
1101:
1102: // メニューの「デバイス > CD/MO > 挿入」UI
1103: void
1104: WXMainFrame::OnCDInsertUI(wxUpdateUIEvent& event)
1105: {
1106: int id = event.GetId() - ID_CD_INSERT_0;
1107: SCSIDisk *disk = dynamic_cast<SCSIDisk *>(scsidev[id]);
1108: assert(disk);
1109:
1110: if (disk->IsMediumLoaded()) {
1111: event.SetText(_("Ex&change"));
1112: } else {
1113: event.SetText(_("&Insert"));
1114: }
1115: }
1116:
1117: // メニューの「デバイス > CD/MO > 取り出し」
1118: void
1119: WXMainFrame::OnCDEject(wxCommandEvent& event)
1120: {
1121: int id = event.GetId() - ID_CD_EJECT_0;
1122:
1123: EjectCD(id, false);
1124: }
1125:
1126: // メニューの「デバイス > CD/MO > 取り出し」UI
1127: void
1128: WXMainFrame::OnCDEjectUI(wxUpdateUIEvent& event)
1129: {
1130: int id = event.GetId() - ID_CD_EJECT_0;
1131: SCSIDisk *disk = dynamic_cast<SCSIDisk *>(scsidev[id]);
1132: assert(disk);
1133:
1134: // 挿入されてて取り出し可能な時のみ有効
1135: event.Enable(disk->IsMediumLoaded() &&
1136: disk->IsMediumRemovalAllowed());
1137: }
1138:
1139: // メニューの「デバイス > CD/MO > 強制取り出し」
1140: void
1141: WXMainFrame::OnCDForce(wxCommandEvent& event)
1142: {
1143: int id = event.GetId() - ID_CD_FORCE_0;
1144:
1145: EjectCD(id, true);
1146: }
1147:
1148: // メニューの「デバイス > CD/MO > 強制取り出し」UI
1149: void
1150: WXMainFrame::OnCDForceUI(wxUpdateUIEvent& event)
1151: {
1152: int id = event.GetId() - ID_CD_FORCE_0;
1153: SCSIDisk *disk = dynamic_cast<SCSIDisk *>(scsidev[id]);
1154: assert(disk);
1155:
1156: // 挿入されてて取り出し禁止の時のみ有効
1157: event.Enable(disk->IsMediumLoaded() &&
1158: disk->IsMediumRemovalPrevented());
1159: }
1160:
1.1.1.2 root 1161: // メニューの「デバイス > マウスモード」
1162: void
1163: WXMainFrame::OnMouseMode(wxCommandEvent& event)
1164: {
1165: // enable ならチェックを付けようとして呼ばれた
1166: bool enable = event.IsChecked();
1167:
1168: if (enable) {
1169: // メッセージを表示したい
1170: } else {
1171: // メッセージを表示したい
1172: }
1173:
1174: // マウスモードを設定
1.1.1.15! root 1175: wxCommandEvent newev(NONO_EVT_MOUSEMODE, GetId());
! 1176: newev.SetEventObject(this);
! 1177: newev.SetInt(enable);
! 1178: ::wxPostEvent(mainview, newev);
1.1.1.2 root 1179: }
1180:
1181: // メニューの「デバイス > マウスモード」UI
1182: void
1183: WXMainFrame::OnMouseModeUI(wxUpdateUIEvent& event)
1184: {
1.1.1.15! root 1185: event.Check(mainview->GetMouseMode());
1.1.1.2 root 1186: }
1187:
1.1.1.14 root 1188: // メニューの「デバイス > Push Power Button」イベント
1189: void
1190: WXMainFrame::OnPowerButton(wxCommandEvent& event)
1191: {
1192: // LUNA はモーメンタリ動作、X68030 はオルタネート動作のスイッチ。
1193: // この違いは VM 側で吸収するのでここはボタンを押したという動作だけ
1194: // 通知する。
1.1.1.15! root 1195: power->PowerButton();
1.1.1.14 root 1196: }
1197:
1198: // メニューの「デバイス > Push Power Button」UI
1199: void
1200: WXMainFrame::OnPowerButtonUI(wxUpdateUIEvent& event)
1201: {
1.1.1.15! root 1202: if (gMainApp.Has(VMCap::X68030)) {
! 1203: // X68030 の電源ボタンはオルタネート動作なので、
! 1204: // チェックで状態を表す。
! 1205: event.Check(power->IsPowerPressed());
! 1206: } else {
1.1.1.14 root 1207: // LUNA の電源ボタンはモーメンタリ動作で、電源オフ->オンの機能しかなく
1208: // さらに今の所電源オフ状態はないので、実質無効。
1209: event.Enable(false);
1210: }
1211: }
1212:
1.1.1.9 root 1213: // メニューの「デバイス > Push Reset Button」イベント
1214: // こっちは本体リセットボタンによるリセット
1215: void
1216: WXMainFrame::OnResetButton(wxCommandEvent& event)
1217: {
1.1.1.15! root 1218: power->MakeResetHard();
1.1.1.13 root 1219: }
1220:
1221: // メニューの「デバイス > Push ABORT(Interrupt) Button」イベント
1222: void
1223: WXMainFrame::OnNMIButton(wxCommandEvent& event)
1224: {
1.1.1.15! root 1225: auto nmi = GetNMIDevice();
! 1226: nmi->PressNMI();
1.1.1.13 root 1227: }
1228:
1229: // メニューの「デバイス > Operation > Keyboard Connect」イベント
1230: void
1231: WXMainFrame::OnKeyboardConnect(wxCommandEvent& event)
1232: {
1233: // enable ならチェックを付けようとして呼ばれた
1234: bool enable = event.IsChecked();
1235:
1236: // キーボード接続を設定
1.1.1.15! root 1237: keyboard->Connect(enable);
1.1.1.13 root 1238: }
1239:
1240: // メニューの「デバイス > Operation > Keyboard Connect」UI
1241: void
1242: WXMainFrame::OnKeyboardConnectUI(wxUpdateUIEvent& event)
1243: {
1.1.1.15! root 1244: event.Check(keyboard->IsConnected());
1.1.1.9 root 1245: }
1246:
1.1 root 1247: // メニューのウィンドウ ID 共通イベント
1248: // チェックが入る方なら、ウィンドウを作成して表示。
1249: // チェックが消える方なら、ウィンドウを削除。
1250: void
1251: WXMainFrame::OnWindow(wxCommandEvent& event)
1252: {
1253: int id = event.GetId();
1254:
1255: DoWindow(id, event.IsChecked());
1256: }
1257:
1258: void
1259: WXMainFrame::DoWindow(int id, bool enable)
1260: {
1.1.1.10 root 1261: // モニタウィンドウを作成する共通部分。
1262: // id はモニター ID であると同時に、windows[] 配列の添字、さらにこの
1263: // モニタウィンドウの wxWindowID としても使っている
1264: // (WXSubWindow::OnClose() 参照)。
1265: #define SetMonitor(id, name) \
1266: windows[id].reset(new WXMonitorWindow(this, (name), \
1.1.1.13 root 1267: gMonitorManager->Get(id)))
1.1.1.4 root 1268:
1.1 root 1269: if (enable) {
1270: // チェックが入ったのでウィンドウを作成
1271: switch (id) {
1.1.1.10 root 1272: case ID_MONITOR_ATC0:
1273: case ID_MONITOR_ATC1:
1274: case ID_MONITOR_ATC2:
1275: case ID_MONITOR_ATC3:
1276: case ID_MONITOR_ATC4:
1277: case ID_MONITOR_ATC5:
1278: case ID_MONITOR_ATC6:
1279: case ID_MONITOR_ATC7:
1280: {
1281: int n = id - ID_MONITOR_ATC0;
1282: wxString name(string_format("ATC#%d", n));
1283: if ((n & 1) == 0) {
1284: name += _("(Data)");
1285: } else {
1286: name += _("(Inst)");
1287: }
1288: SetMonitor(id, name);
1.1.1.4 root 1289: break;
1.1.1.10 root 1290: }
1291:
1292: case ID_MONITOR_BREAKPOINT:
1293: SetMonitor(id, _("Breakpoint"));
1.1.1.5 root 1294: break;
1.1.1.10 root 1295:
1.1.1.15! root 1296: case ID_MONITOR_BT45x:
! 1297: SetMonitor(id, "Bt454/458");
! 1298: break;
! 1299:
1.1.1.10 root 1300: case ID_MONITOR_CMMU0:
1301: case ID_MONITOR_CMMU1:
1302: case ID_MONITOR_CMMU2:
1303: case ID_MONITOR_CMMU3:
1304: case ID_MONITOR_CMMU4:
1305: case ID_MONITOR_CMMU5:
1306: case ID_MONITOR_CMMU6:
1307: case ID_MONITOR_CMMU7:
1308: {
1309: int n = id - ID_MONITOR_CMMU0;
1310: wxString name(string_format("CMMU#%d", n));
1311: if ((n & 1) == 0) {
1312: name += _("(Data)");
1313: } else {
1314: name += _("(Inst)");
1315: }
1316: SetMonitor(id, name);
1.1.1.4 root 1317: break;
1.1.1.10 root 1318: }
1319:
1.1.1.13 root 1320: case ID_MONITOR_CRTC:
1321: SetMonitor(id, "CRTC");
1322: break;
1323:
1.1.1.10 root 1324: case ID_MONITOR_DMAC:
1.1.1.15! root 1325: SetMonitor(id, "DMAC (HD63450)");
1.1.1.5 root 1326: break;
1.1.1.10 root 1327:
1.1.1.14 root 1328: case ID_MONITOR_FDC:
1.1.1.15! root 1329: SetMonitor(id, "FDC (uPD72065B)");
1.1.1.14 root 1330: break;
1331:
1.1.1.13 root 1332: case ID_MONITOR_HOSTCOM:
1333: SetMonitor(id, _("Host Serial Port"));
1334: break;
1335:
1336: case ID_MONITOR_HOSTNET:
1337: SetMonitor(id, _("Host Network"));
1338: break;
1339:
1.1.1.10 root 1340: case ID_MONITOR_INTERRUPT:
1.1.1.15! root 1341: {
! 1342: wxString name;
! 1343: if (gMainApp.Has(VMCap::M88K)) {
! 1344: // 実際はほぼシステムコントローラなのでややこしい。
! 1345: name = "MPU " + _("Interrupt");
! 1346: } else {
! 1347: name = MPUName() + " " + _("Interrupt");
! 1348: }
! 1349: SetMonitor(id, name);
1.1.1.5 root 1350: break;
1.1.1.15! root 1351: }
1.1.1.10 root 1352:
1353: case ID_MONITOR_KEYBOARD:
1354: SetMonitor(id, _("Keyboard/Mouse"));
1.1.1.4 root 1355: break;
1.1.1.10 root 1356:
1357: case ID_MONITOR_LANCE:
1.1.1.15! root 1358: SetMonitor(id, "LANCE (AM7990)");
1.1 root 1359: break;
1.1.1.10 root 1360:
1361: case ID_MONITOR_LCD:
1362: windows[id].reset(new WXLCDMonitor(this));
1.1.1.4 root 1363: break;
1.1.1.10 root 1364:
1.1.1.13 root 1365: case ID_MONITOR_LUNAVC:
1366: SetMonitor(id, _("Video Control"));
1.1.1.4 root 1367: break;
1.1.1.10 root 1368:
1369: case ID_MONITOR_MEMDUMP0 ...
1.1.1.15! root 1370: ID_MONITOR_MEMDUMP(MAX_MEMDUMP_MONITOR - 1):
! 1371: case ID_MONITOR_XPMEMDUMP0 ...
! 1372: ID_MONITOR_XPMEMDUMP(MAX_XPMEMDUMP_MONITOR - 1):
1.1.1.10 root 1373: {
1.1.1.15! root 1374: windows[id].reset(new WXMemdumpWindow(this, id));
1.1.1.4 root 1375: break;
1.1.1.10 root 1376: }
1377:
1378: case ID_MONITOR_MFP:
1.1.1.15! root 1379: SetMonitor(id, "MFP (MC68901)");
1.1.1.4 root 1380: break;
1.1.1.10 root 1381:
1382: case ID_MONITOR_MK48T02:
1.1.1.15! root 1383: SetMonitor(id, "RTC (MK48T02)");
1.1 root 1384: break;
1.1.1.10 root 1385:
1386: case ID_MONITOR_MPUATC:
1.1.1.15! root 1387: SetMonitor(id, "MC68030 ATC");
1.1 root 1388: break;
1.1.1.10 root 1389:
1390: case ID_MONITOR_MPUREG:
1.1.1.15! root 1391: {
! 1392: wxString name = MPUName() + " " + _("Register");
! 1393: SetMonitor(id, name);
! 1394: break;
! 1395: }
! 1396:
! 1397: case ID_MONITOR_ROMCONS:
! 1398: SetMonitor(id, _("ROM Console (provisional)"));
1.1.1.7 root 1399: break;
1.1.1.10 root 1400:
1.1.1.15! root 1401: case ID_MONITOR_PIO:
! 1402: SetMonitor(id, "PIO0/PIO1");
1.1.1.3 root 1403: break;
1.1.1.10 root 1404:
1.1.1.13 root 1405: case ID_MONITOR_RENDERER:
1406: SetMonitor(id, _("Renderer"));
1407: break;
1408:
1.1.1.10 root 1409: case ID_MONITOR_RTC:
1.1.1.15! root 1410: SetMonitor(id, "RTC (RP5C15)");
1.1.1.3 root 1411: break;
1.1.1.10 root 1412:
1413: case ID_MONITOR_SCC:
1.1.1.15! root 1414: SetMonitor(id, "SCC (Z8530)");
1.1.1.3 root 1415: break;
1.1.1.10 root 1416:
1417: case ID_MONITOR_SCHEDULER:
1418: SetMonitor(id, _("Scheduler"));
1.1 root 1419: break;
1.1.1.10 root 1420:
1.1.1.11 root 1421: case ID_MONITOR_SCSIDEVS:
1422: SetMonitor(id, _("SCSI Devices"));
1423: break;
1424:
1.1.1.10 root 1425: case ID_MONITOR_SIO:
1.1.1.15! root 1426: SetMonitor(id, "SIO (uPD7201)");
1.1.1.4 root 1427: break;
1.1.1.10 root 1428:
1429: case ID_MONITOR_SPC:
1.1.1.15! root 1430: SetMonitor(id, "SPC (MB89352)");
1.1.1.2 root 1431: break;
1.1.1.10 root 1432:
1433: case ID_MONITOR_SYSCLK:
1434: SetMonitor(id, _("System Clock"));
1.1 root 1435: break;
1.1.1.10 root 1436:
1437: case ID_MONITOR_WXHOSTINFO:
1438: SetMonitor(id, _("Host Information"));
1.1 root 1439: break;
1.1.1.10 root 1440:
1.1.1.15! root 1441: case ID_MONITOR_XPREG:
! 1442: SetMonitor(id, "HD647180 " + _("Register"));
! 1443: break;
! 1444:
! 1445: case ID_MONITOR_XPINTR:
! 1446: SetMonitor(id, "HD647180 " + _("Interrupt"));
! 1447: break;
! 1448:
! 1449: case ID_MONITOR_XPIO:
! 1450: SetMonitor(id, _("HD647180 Internal Devices"));
! 1451: break;
! 1452:
1.1.1.10 root 1453: case ID_SUBWIN_BRHIST:
1.1.1.15! root 1454: {
! 1455: wxString name = MPUName() + " " + _("Branch History");
! 1456: windows[id].reset(new WXScrollMonitorWindow(this, name,
! 1457: gMonitorManager->Get(id)));
1.1.1.4 root 1458: break;
1.1.1.15! root 1459: }
1.1.1.10 root 1460:
1461: case ID_SUBWIN_EXHIST:
1.1.1.15! root 1462: {
! 1463: wxString name = MPUName() + " " + _("Exception History");
! 1464: windows[id].reset(new WXScrollMonitorWindow(this, name,
! 1465: gMonitorManager->Get(id)));
1.1.1.5 root 1466: break;
1.1.1.15! root 1467: }
1.1.1.10 root 1468:
1469: case ID_SUBWIN_CACHE0:
1470: case ID_SUBWIN_CACHE1:
1471: case ID_SUBWIN_CACHE2:
1472: case ID_SUBWIN_CACHE3:
1473: case ID_SUBWIN_CACHE4:
1474: case ID_SUBWIN_CACHE5:
1475: case ID_SUBWIN_CACHE6:
1476: case ID_SUBWIN_CACHE7:
1477: {
1478: int n = id - ID_SUBWIN_CACHE0;
1479: wxString name = _("Cache");
1480: name += string_format("#%d", n);
1481: if ((n & 1) == 0) {
1482: name += _("(Data)");
1483: } else {
1484: name += _("(Inst)");
1485: }
1486: windows[id].reset(new WXCacheWindow(this, name,
1.1.1.13 root 1487: gMonitorManager->Get(id)));
1.1 root 1488: break;
1.1.1.10 root 1489: }
1490:
1.1.1.15! root 1491: case ID_SUBWIN_DIPSW:
! 1492: windows[id].reset(new WXDipswWindow(this));
! 1493: break;
! 1494:
1.1.1.10 root 1495: case ID_SUBWIN_LCDPANEL:
1496: windows[id].reset(new WXLCDWindow(this));
1.1 root 1497: break;
1.1.1.10 root 1498: case ID_SUBWIN_LOG:
1499: windows[id].reset(new WXLogMonitor(this));
1.1 root 1500: break;
1.1.1.13 root 1501: case ID_SUBWIN_LOGSETTING:
1502: windows[id].reset(new WXLogSettingWindow(this));
1503: break;
1.1.1.14 root 1504:
1.1.1.13 root 1505: case ID_SUBWIN_LUNAFB:
1.1.1.14 root 1506: case ID_SUBWIN_TVRAM:
1507: {
1508: // 呼び方が違うので名前と ID が違う
1509: wxString name;
1510: if (id == ID_SUBWIN_LUNAFB) {
1511: name = _("Bitmap Plane");
1512: } else {
1513: name = _("Text VRAM");
1514: }
1515: windows[id].reset(new WXPlaneVRAMWindow(this, name));
1516: break;
1517: }
1518:
1.1.1.15! root 1519: case ID_SUBWIN_PALETTE:
! 1520: case ID_SUBWIN_TEXTPAL:
! 1521: {
! 1522: // 呼び方が違うので名前と ID が違う
! 1523: wxString name;
! 1524: if (id == ID_SUBWIN_TEXTPAL) {
! 1525: name = _("Text Palette Colormap");
! 1526: } else {
! 1527: name = _("Palette Colormap");
! 1528: }
! 1529: windows[id].reset(new WXPaletteWindow(this, name));
! 1530: break;
! 1531: }
! 1532:
1.1.1.14 root 1533: case ID_SUBWIN_ROM:
1534: windows[id].reset(new WXROMWindow(this));
1.1 root 1535: break;
1.1.1.10 root 1536:
1537: case ID_SUBWIN_SOFTKEY:
1538: windows[id].reset(new WXSoftKeyWindow(this, gMainApp.GetVMType()));
1.1.1.5 root 1539: break;
1.1.1.10 root 1540:
1.1.1.13 root 1541: case ID_SUBWIN_VECTOR:
1.1.1.15! root 1542: {
! 1543: wxString name = MPUName() + " " + _("Vector Table");
! 1544: windows[id].reset(new WXScrollMonitorWindow(this, name,
! 1545: gMonitorManager->Get(id)));
1.1.1.13 root 1546: break;
1.1.1.15! root 1547: }
! 1548:
! 1549: case ID_SUBWIN_XPBRHIST:
! 1550: {
! 1551: wxString name = "HD647180 " + _("Branch History");
! 1552: windows[id].reset(new WXScrollMonitorWindow(this, name,
! 1553: gMonitorManager->Get(id)));
! 1554: break;
! 1555: }
! 1556:
! 1557: case ID_SUBWIN_XPEXHIST:
! 1558: {
! 1559: wxString name = "HD647180 " + _("Exception History");
! 1560: windows[id].reset(new WXScrollMonitorWindow(this, name,
! 1561: gMonitorManager->Get(id)));
! 1562: break;
! 1563: }
1.1.1.13 root 1564:
1.1.1.10 root 1565: default:
1.1.1.15! root 1566: PANIC("'%s' not listed", Monitor::GetIdText(id));
1.1 root 1567: }
1568: windows[id]->Show();
1569: } else {
1570: // チェックが消えたのでウィンドウを終了
1571: windows[id]->Close();
1572: // (削除自体はこの少し下の DeleteWindow() で行なっている)
1573: }
1574: }
1575:
1576: // Update UI イベント
1577: void
1578: WXMainFrame::OnWindowUI(wxUpdateUIEvent& event)
1579: {
1580: int id = event.GetId();
1581:
1582: // ウィンドウが存在していればチェックを表示
1.1.1.4 root 1583: event.Check((bool)windows[id]);
1.1.1.10 root 1584:
1.1.1.15! root 1585: if (IS_MONITOR_MEMDUMP(id) || IS_MONITOR_XPMEMDUMP(id)) {
1.1.1.10 root 1586: // メニューに現在のアドレスを載せる
1.1.1.15! root 1587: // (ウィンドウの生存期間外にも呼ばれることに注意)
! 1588: auto mon = gMonitorManager->Get(id);
! 1589: auto *memdump = dynamic_cast<Memdump *>(mon.obj);
! 1590: assert(memdump);
! 1591: uint32 addr = memdump->GetAddr();
! 1592:
! 1593: int n;
! 1594: wxString text = _("Memory Dump");
! 1595: if (IS_MONITOR_XPMEMDUMP(id)) {
! 1596: n = id - ID_MONITOR_XPMEMDUMP0;
! 1597: text += string_format(" &%d: $%05x", n, addr);
! 1598: } else {
! 1599: n = id - ID_MONITOR_MEMDUMP0;
! 1600: text += string_format(" &%d: $%08x", n, addr);
! 1601: }
! 1602: event.SetText(text);
1.1.1.10 root 1603: }
1.1.1.4 root 1604: }
1605:
1606: // バージョンダイアログ
1607: void
1608: WXMainFrame::OnAbout(wxCommandEvent& event)
1609: {
1610: WXVersionDlg dlg(this);
1611: dlg.ShowModal();
1.1 root 1612: }
1613:
1.1.1.14 root 1614: // FD を挿入する。
1615: void
1616: WXMainFrame::InsertFD(int unit, const std::string& path)
1617: {
1618: FDDDevice *fdd = fdd_array[unit];
1619: assert(fdd);
1620:
1621: // VM に依頼
1622: // (エラーが起きれば別途 UI メッセージが飛んでくる)
1623: fdd->LoadDiskUI(path);
1624:
1625: // 次回以降のダイアログのカレントディレクトリをここに更新
1626: auto pos = path.rfind('/');
1627: current_dir = path.substr(0, pos);
1628: }
1629:
1630: // FD をイジェクトする。
1631: void
1632: WXMainFrame::EjectFD(int unit, bool force)
1633: {
1634: FDDDevice *fdd = fdd_array[unit];
1635: assert(fdd);
1636:
1637: fdd->UnloadDiskUI(force);
1638: }
1639:
1.1.1.11 root 1640: // CD/MO を挿入する。
1.1 root 1641: void
1.1.1.11 root 1642: WXMainFrame::InsertCD(int id, const std::string& path)
1.1 root 1643: {
1.1.1.11 root 1644: SCSIDisk *scsidisk = dynamic_cast<SCSIDisk*>(scsidev[id]);
1645: assert(scsidisk);
1.1 root 1646:
1.1.1.11 root 1647: // VM に依頼
1648: // (エラーが起きれば別途 UI メッセージが飛んでくる)
1649: scsidisk->LoadDiskUI(path);
1650:
1651: // 次回以降のダイアログのカレントディレクトリをここに更新
1652: auto pos = path.rfind('/');
1653: current_dir = path.substr(0, pos);
1.1 root 1654: }
1655:
1.1.1.11 root 1656: // CD/MO をイジェクトする。
1.1 root 1657: void
1.1.1.11 root 1658: WXMainFrame::EjectCD(int id, bool force)
1.1 root 1659: {
1.1.1.11 root 1660: SCSIDisk *scsidisk = dynamic_cast<SCSIDisk*>(scsidev[id]);
1661: assert(scsidisk);
1662:
1.1.1.13 root 1663: scsidisk->UnloadDiskUI(force);
1.1 root 1664: }
1665:
1.1.1.14 root 1666: // CD/MO/FD の挿入失敗メッセージ。
1667: // CD/MO と FD でメッセージが同じなので共用する。
1.1.1.4 root 1668: void
1.1.1.14 root 1669: WXMainFrame::OnInsertFailed(wxCommandEvent& event)
1.1.1.4 root 1670: {
1.1.1.11 root 1671: ::wxMessageBox(_("Cannot load the image file"));
1.1.1.4 root 1672: }
1673:
1.1.1.11 root 1674: // ウィンドウをリストから削除する
1675: // (ウィンドウの Close() から呼ばれる)
1.1.1.4 root 1676: void
1.1.1.11 root 1677: WXMainFrame::DeleteWindow(wxWindow *win)
1.1.1.4 root 1678: {
1.1.1.11 root 1679: for (int id = 0; id < ID_SUBWIN_MAX; id++) {
1680: if (windows[id].get() == win) {
1681: windows[id].reset();
1682: break;
1683: }
1684: }
1.1.1.4 root 1685: }
1686:
1.1.1.15! root 1687: // メイン MPU 名を返す。メニューとタイトルによく出てくるので。
! 1688: // 88xx0 とか 88200 は別処理。
! 1689: wxString
! 1690: WXMainFrame::MPUName() const
! 1691: {
! 1692: if (gMainApp.Has(VMCap::M88K)) {
! 1693: return "MC88100";
! 1694: } else {
! 1695: return "MC68030";
! 1696: }
! 1697: }
! 1698:
1.1.1.4 root 1699: // m680x0 ダブルバスフォールト処理
1700: void
1701: WXMainFrame::OnHaltNotify(wxCommandEvent& event)
1702: {
1703: ::wxMessageBox(_("Double bus fault has occurred in VM"),
1704: wxEmptyString,
1705: wxICON_EXCLAMATION);
1706: }
1707:
1.1.1.10 root 1708: // 起動時にオープンするサブウィンドウ (-M オプション)
1709: /*static*/ std::array<bool, ID_SUBWIN_MAX> WXMainFrame::subwindow_start;
1.1.1.15! root 1710:
! 1711: // モニタの更新頻度
! 1712: /*static*/ int WXMainFrame::monitor_rate;
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.