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