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

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

unix.superglobalmegacorp.com

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