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