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