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