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