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