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

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

unix.superglobalmegacorp.com

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