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

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