Annotation of nono/wx/wxmainframe.cpp, revision 1.1.1.14

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.