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