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