Annotation of nono/wx/wxdumpmonitor.cpp, revision 1.1.1.18

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.11  root        7: //
                      8: // メモリダンプウィンドウ
                      9: //
                     10: 
1.1       root       11: #include "wxdumpmonitor.h"
1.1.1.13  root       12: #include "mainapp.h"
                     13: #include "mainbus.h"
1.1.1.15  root       14: #include "monitor.h"
                     15: #include "mpu680x0.h"
1.1       root       16: 
                     17: enum {
1.1.1.11  root       18:        ID_TEXT = IDGROUP_MEMDUMP,
1.1.1.13  root       19:        ID_PREVLINE,
                     20:        ID_PREVPAGE,
                     21:        ID_NEXTLINE,
                     22:        ID_NEXTPAGE,
                     23:        ID_FORMAT,
                     24: 
                     25:        ID_EDIT,
1.1.1.11  root       26: 
                     27:        ID_local_end,   // 最後に置く (チェック用)
1.1       root       28: };
1.1.1.12  root       29: static_assert(ID_local_end - 1 <= (int)IDGROUP_MEMDUMP_END, "ID exceeded");
1.1       root       30: 
                     31: // イベントテーブル
                     32: wxBEGIN_EVENT_TABLE(WXMemdumpWindow, inherited)
                     33:        EVT_TEXT_ENTER(ID_TEXT, WXMemdumpWindow::OnTextEnter)
1.1.1.13  root       34:        EVT_COMMAND(ID_PREVLINE, NONO_EVT_BUTTON, WXMemdumpWindow::OnPrevLine)
                     35:        EVT_COMMAND(ID_PREVPAGE, NONO_EVT_BUTTON, WXMemdumpWindow::OnPrevPage)
                     36:        EVT_COMMAND(ID_NEXTLINE, NONO_EVT_BUTTON, WXMemdumpWindow::OnNextLine)
                     37:        EVT_COMMAND(ID_NEXTPAGE, NONO_EVT_BUTTON, WXMemdumpWindow::OnNextPage)
                     38:        EVT_CHOICE(ID_FORMAT, WXMemdumpWindow::OnFormat)
1.1       root       39: wxEND_EVENT_TABLE()
                     40: 
                     41: // コンストラクタ
1.1.1.9   root       42: // (タイトルは UpdateAddr() でセットする)
1.1.1.13  root       43: WXMemdumpWindow::WXMemdumpWindow(wxWindow *parent, int monid_)
1.1.1.12  root       44:        : inherited(parent, wxID_ANY, wxEmptyString,
                     45:                DEFAULT_STYLE | wxRESIZE_BORDER)
1.1       root       46: {
1.1.1.13  root       47:        monid = monid_;
                     48:        if (IS_MONITOR_XPMEMDUMP(monid)) {
                     49:                myidx = monid - ID_MONITOR_XPMEMDUMP0;
                     50:        } else {
                     51:                myidx = monid - ID_MONITOR_MEMDUMP0;
                     52:        }
                     53: 
                     54:        // ↓ topsizer
                     55:        //   +--------------------------------------------+
                     56:        //   |上枠 →                                     |
                     57:        //   |+-----+------+-----+----------+-----+------+|
                     58:        //   ||余白 | "<<" | "<" | アドレス | ">" | ">>" ||
                     59:        //   |+-----+------+-----+----------+-----+------+|
                     60:        //   +--------------------------------------------+
                     61:        //   | TextScreen                                 |
                     62:        //   +--------------------------------------------+
1.1.1.11  root       63: 
                     64:        auto *topsizer = new wxBoxSizer(wxVERTICAL);
1.1.1.5   root       65: 
1.1.1.9   root       66:        // 上枠用の下敷きパネル
1.1.1.13  root       67:        auto *ctrlpanel = new wxPanel(this);
1.1.1.15  root       68:        ctrlpanel->SetName("WXMemdumpWindow.CtrlPanel");
1.1.1.11  root       69:        topsizer->Add(ctrlpanel, 0, wxEXPAND);
1.1.1.9   root       70: 
1.1.1.5   root       71:        // 上枠用の横 sizer
                     72:        ctrlbox = new wxBoxSizer(wxHORIZONTAL);
1.1       root       73: 
                     74:        // アドレスコントロール
1.1.1.13  root       75:        addrctrl = new wxTextCtrl(ctrlpanel, ID_TEXT,
1.1       root       76:                wxEmptyString, wxDefaultPosition, wxDefaultSize,
                     77:                wxTE_PROCESS_ENTER);
1.1.1.13  root       78:        buttons[0] = new WXButton(ctrlpanel, ID_PREVPAGE, wxDefaultSize, "<<");
                     79:        buttons[1] = new WXButton(ctrlpanel, ID_PREVLINE, wxDefaultSize, "<");
                     80:        buttons[2] = new WXButton(ctrlpanel, ID_NEXTLINE, wxDefaultSize, ">");
                     81:        buttons[3] = new WXButton(ctrlpanel, ID_NEXTPAGE, wxDefaultSize, ">>");
                     82: 
                     83:        ctrlbox->AddSpacer(3);
                     84:        ctrlbox->Add(buttons[0], 0, wxALIGN_CENTER);
                     85:        ctrlbox->Add(buttons[1], 0, wxALIGN_CENTER);
                     86:        ctrlbox->AddSpacer(3);
                     87:        ctrlbox->Add(addrctrl, 0, wxALIGN_CENTER);
                     88:        ctrlbox->AddSpacer(3);
                     89:        ctrlbox->Add(buttons[2], 0, wxALIGN_CENTER);
                     90:        ctrlbox->Add(buttons[3], 0, wxALIGN_CENTER);
                     91:        ctrlbox->AddSpacer(3);
                     92: 
                     93:        // 表示形式 (機種によって選択肢と名前が異なる)
                     94:        if (gMainApp.Has(VMCap::M68K)) {
1.1.1.15  root       95:                auto mpu680x0 = GetMPU680x0Device(GetMPUDevice());
1.1.1.13  root       96:                fmts.emplace_back(Memdump::Byte, _("Byte"));
                     97:                fmts.emplace_back(Memdump::Word, _("Word"));
                     98:                fmts.emplace_back(Memdump::Long, _("Long Word"));
1.1.1.15  root       99:                switch (mpu680x0->GetMPUType()) {
                    100:                 case m680x0MPUType::M68030:
                    101:                        fmts.emplace_back(Memdump::M68030PageShort,
                    102:                                _("MMU Descriptor (Short Format)"));
                    103:                        break;
                    104:                 case m680x0MPUType::M68040:
                    105:                        fmts.emplace_back(Memdump::M68040TableDesc,
                    106:                                _("MMU Table Descriptor"));
                    107:                        fmts.emplace_back(Memdump::M68040PageDesc,
                    108:                                _("MMU Page Descriptor"));
                    109:                        break;
                    110:                 default:
                    111:                        break;
                    112:                }
                    113:                fmts.emplace_back(Memdump::M680x0Disasm, _("680x0 Disassemble"));
1.1.1.13  root      114:        } else {
                    115:                fmts.emplace_back(Memdump::Byte, _("Byte"));
                    116:                fmts.emplace_back(Memdump::Word, _("Half Word"));
                    117:                fmts.emplace_back(Memdump::Long, _("Word"));
                    118:                fmts.emplace_back(Memdump::M88200Page, _("88200 Descriptor"));
                    119:                fmts.emplace_back(Memdump::M88100Disasm, _("88100 Disassemble"));
                    120:        }
                    121:        if (gMainApp.Has(VMCap::LUNA)) {
                    122:                fmts.emplace_back(Memdump::HD64180Disasm, _("HD64180 Disassemble"));
                    123:        }
                    124: 
                    125:        // fmts から名前だけの配列を作る
                    126:        std::vector<wxString> fmt_choice;
                    127:        for (auto p : fmts) {
                    128:                fmt_choice.push_back(p.second);
                    129:        }
                    130:        fmtctrl = new wxChoice(ctrlpanel, ID_FORMAT,
                    131:                wxDefaultPosition, wxDefaultSize,
                    132:                fmt_choice.size(), &fmt_choice[0]);
                    133:        ctrlbox->Add(fmtctrl, 0, wxALIGN_CENTER);
1.1       root      134: 
1.1.1.9   root      135:        // 上枠の sizer と下敷きを紐付ける
                    136:        ctrlpanel->SetSizer(ctrlbox);
                    137:        ctrlbox->SetSizeHints(ctrlpanel);
                    138: 
1.1.1.13  root      139:        screen = new WXMonitorPanel(this, gMonitorManager->Get(monid));
1.1.1.11  root      140:        topsizer->Add(screen, 1, wxEXPAND);
1.1       root      141: 
1.1.1.4   root      142:        SetSizer(topsizer);
1.1       root      143: 
1.1.1.17  root      144:        // 自前レイアウト。
                    145:        SetMyLayout();
                    146: 
1.1.1.11  root      147:        // ウィンドウサイズを確定させる
1.1.1.13  root      148:        FontChanged();
1.1.1.11  root      149: 
1.1.1.13  root      150:        // パネルに来るマウスイベントをこっちに回す
1.1.1.18! root      151:        screen->Bind(wxEVT_MOUSEWHEEL, &WXMemdumpWindow::OnMouseWheel, this);
        !           152:        screen->Bind(wxEVT_LEFT_DCLICK, &WXMemdumpWindow::OnDClick, this);
1.1.1.13  root      153: 
                    154:        // メモリダンプオブジェクトを取得
                    155:        auto mon = screen->GetMonitor();
1.1.1.15  root      156:        memdump = dynamic_cast<MemdumpMonitor *>(mon->obj);
1.1.1.13  root      157:        assert(memdump);
                    158: 
                    159:        // 初期値をコントロールに設定
                    160:        auto fmt = memdump->GetFormat();
                    161:        fmtctrl->SetSelection(Format2Selection(fmt));
                    162:        DoFormat(fmt);
1.1.1.9   root      163:        UpdateAddr();
1.1       root      164: }
                    165: 
                    166: // デストラクタ
                    167: WXMemdumpWindow::~WXMemdumpWindow()
                    168: {
                    169: }
                    170: 
1.1.1.13  root      171: void
                    172: WXMemdumpWindow::FontChanged()
                    173: {
                    174:        for (auto *btn : buttons) {
1.1.1.16  root      175:                // ボタンサイズを先に一旦リセット。
                    176:                btn->SetMinSize(wxSize(1, 1));
                    177:                btn->SetSize(wxSize(1, 1));
                    178: 
                    179:                // 各ボタンコントロールに伝搬。
1.1.1.13  root      180:                btn->FontChanged();
1.1.1.16  root      181: 
                    182:                // ボタンを正方形に固定する (テキストは1文字か2文字と知っている)。
                    183:                // 押しやすくするため、最小 24x24 にしてみる。
                    184:                wxSize size = btn->GetSize();
                    185:                if (size.y < 24) {
                    186:                        size.y = 24;
                    187:                }
                    188:                size.x = size.y;
                    189: 
                    190:                // 勝手にベストサイズに戻らないように最小サイズごと固定する。
                    191:                btn->SetSize(size);
                    192:                btn->SetMinSize(size);
1.1.1.13  root      193:        }
1.1.1.16  root      194: 
                    195:        screen->FontChanged();
                    196: 
                    197:        Fit();
                    198: }
                    199: 
                    200: bool
1.1.1.17  root      201: WXMemdumpWindow::GetMySizeHints(wxSize *newp, wxSize *minp, wxSize *maxp,
                    202:        wxSize *incp)
1.1.1.16  root      203: {
                    204:        // この後の Fit() でリサイズに使われる大きさを取得。
                    205:        wxSize fitsize = GetSizer()->ComputeFittingClientSize(this);
                    206:        wxSize ctrlsize = ctrlbox->ComputeFittingClientSize(this);
                    207: 
                    208:        // 高さの最小は (コントロールパネル分と) TextScreen 1行分にしておく。
                    209:        int min_y = ctrlsize.y + screen->GetScreenHeight(1);
                    210:        int new_y = ctrlsize.y + screen->GetSize().y;
1.1.1.17  root      211:        wxSize newsize(fitsize.x, new_y);
1.1.1.16  root      212:        wxSize minsize(fitsize.x, min_y);
                    213:        wxSize maxsize(fitsize.x, GetMaxClientSize().y);
                    214:        wxSize incsize(0, screen->GetFontHeight());
                    215: 
1.1.1.17  root      216:        if (newp) *newp = newsize;
                    217:        if (minp) *minp = minsize;
                    218:        if (maxp) *maxp = maxsize;
                    219:        if (incp) *incp = incsize;
                    220:        return true;
                    221: }
                    222: 
                    223: bool
                    224: WXMemdumpWindow::Layout()
                    225: {
                    226:        if (MyLayout() == false) {
                    227:                // Sizer 使ってるのでその処理は(さらに親に)任せる。
                    228:                BaseLayout();
                    229:        }
                    230:        return true;
1.1.1.13  root      231: }
                    232: 
1.1       root      233: // テキスト入力イベント
                    234: void
                    235: WXMemdumpWindow::OnTextEnter(wxCommandEvent& event)
                    236: {
                    237:        // 入力文字列(16進文字列)を数値に変換
1.1.1.5   root      238:        const wxString& wstr = event.GetString();
1.1.1.6   root      239:        uint32 val = strtoul((const char *)wstr.mb_str(), NULL, 16);
1.1       root      240: 
1.1.1.9   root      241:        // アドレスを更新
1.1.1.13  root      242:        memdump->SetAddr(val);
1.1.1.9   root      243:        UpdateAddr();
1.1       root      244: }
                    245: 
1.1.1.13  root      246: // "<"(前行) ボタン押下イベント
1.1       root      247: void
1.1.1.13  root      248: WXMemdumpWindow::OnPrevLine(wxCommandEvent& event)
1.1       root      249: {
1.1.1.13  root      250:        // 1行戻る
                    251:        memdump->Offset(memdump->GetLineOffset(-1));
1.1.1.9   root      252: 
1.1.1.13  root      253:        UpdateAddr();
                    254: }
                    255: 
                    256: // "<<"(前ページ) ボタン押下イベント
                    257: void
                    258: WXMemdumpWindow::OnPrevPage(wxCommandEvent& event)
                    259: {
                    260:        // 1ページ戻る
                    261:        memdump->Offset(memdump->GetPageOffset(-1));
1.1.1.9   root      262: 
                    263:        UpdateAddr();
1.1       root      264: }
                    265: 
1.1.1.13  root      266: // ">"(次行) ボタン押下イベント
1.1       root      267: void
1.1.1.13  root      268: WXMemdumpWindow::OnNextLine(wxCommandEvent& event)
1.1       root      269: {
1.1.1.13  root      270:        // 1行進む
                    271:        memdump->Offset(memdump->GetLineOffset(1));
                    272: 
                    273:        UpdateAddr();
                    274: }
1.1.1.9   root      275: 
1.1.1.13  root      276: // ">>"(次ページ) ボタン押下イベント
                    277: void
                    278: WXMemdumpWindow::OnNextPage(wxCommandEvent& event)
                    279: {
                    280:        // 1ページ進む
                    281:        memdump->Offset(memdump->GetPageOffset(1));
1.1.1.9   root      282: 
                    283:        UpdateAddr();
1.1       root      284: }
                    285: 
1.1.1.9   root      286: // アドレス欄の表示を更新する
                    287: void
                    288: WXMemdumpWindow::UpdateAddr()
                    289: {
1.1.1.13  root      290:        int width;
                    291:        std::string title;
                    292:        if (IS_MONITOR_XPMEMDUMP(monid)) {
                    293:                width = 5;
                    294:                title = _("XP Memory Dump");
                    295:        } else {
                    296:                width = 8;
                    297:                title = _("Main Memory Dump");
                    298:        }
1.1.1.9   root      299: 
1.1.1.14  root      300:        uint32 addr = memdump->GetAddr().Addr();
1.1.1.13  root      301:        std::string addrstr = strhex(addr, width);
1.1.1.9   root      302: 
                    303:        // EVT_TEXT を起こさず変更する
1.1.1.13  root      304:        addrctrl->ChangeValue(addrstr);
1.1.1.9   root      305: 
                    306:        // カーソルを末尾に
                    307:        addrctrl->SetInsertionPointEnd();
                    308: 
                    309:        // タイトルを変更
1.1.1.13  root      310:        title += string_format(" %d: $", myidx);
                    311:        title += addrstr;
                    312:        SetTitle(title);
                    313: 
                    314:        // 即更新
                    315:        Refresh();
1.1.1.9   root      316: }
                    317: 
1.1.1.13  root      318: // 表示フォーマット変更イベント
                    319: void
                    320: WXMemdumpWindow::OnFormat(wxCommandEvent& event)
1.1.1.9   root      321: {
1.1.1.13  root      322:        int idx = event.GetSelection();
                    323:        DoFormat(Selection2Format(idx));
1.1       root      324: }
1.1.1.9   root      325: 
1.1.1.13  root      326: // 表示フォーマット変更処理
1.1.1.9   root      327: void
1.1.1.13  root      328: WXMemdumpWindow::DoFormat(Memdump::Format fmt)
1.1.1.9   root      329: {
1.1.1.13  root      330:        memdump->SetFormat(fmt);
                    331: 
                    332:        // SetFormat() によってアドレスが切り捨てられる場合があるので
                    333:        // アドレス欄の表示ごと更新。
                    334:        UpdateAddr();
                    335: }
                    336: 
                    337: // マウスホイールイベント
                    338: void
                    339: WXMemdumpWindow::OnMouseWheel(wxMouseEvent& event)
                    340: {
                    341:        int delta = event.GetWheelRotation();
                    342: 
                    343:        // 1回の変化で +/-120 が来る。
                    344:        // たいていのアプリケーションで3行ずつの移動に換算することが多いようだが
                    345:        // ここはメモリダンプなので 4行ずつにする。
                    346: 
                    347:        if (delta != 0) {
                    348:                memdump->Offset(memdump->GetLineOffset(-delta / 30));
                    349:                UpdateAddr();
                    350:        }
                    351: }
                    352: 
                    353: // ダブルクリックイベント
                    354: void
                    355: WXMemdumpWindow::OnDClick(wxMouseEvent& event)
                    356: {
                    357:        event.Skip();
                    358: 
                    359:        auto fmt = memdump->GetFormat();
                    360: 
                    361:        // テキストの桁数、行数にする
                    362:        wxPoint tpos = screen->GetTextPosition(event.GetPosition());
                    363:        int x = tpos.x;
                    364:        int y = tpos.y;
                    365: 
                    366:        // ウィンドウサイズを変えた時に出来る下の空き地にはヒットさせない
                    367:        if (y >= screen->GetRow()) {
                    368:                return;
                    369:        }
                    370: 
                    371:        // アドレス部分は常に除外でいいか
                    372:        if (x < 19) {
                    373:                return;
                    374:        }
                    375: 
                    376:        // 現在のフォーマットでのクリック位置のアドレスを求める
                    377:        int len = 0;
                    378:        uint64 addr = -1;
                    379:        switch (fmt) {
                    380:         case Memdump::Byte:
                    381:                len = 1;
                    382:                addr = GetAddrAtHexdump(x, y, len);
                    383:                break;
                    384:         case Memdump::Word:
                    385:                len = 2;
                    386:                addr = GetAddrAtHexdump(x, y, len);
                    387:                break;
                    388:         case Memdump::Long:
                    389:                len = 4;
                    390:                addr = GetAddrAtHexdump(x, y, len);
                    391:                break;
                    392:         case Memdump::M68030PageShort:
                    393:         case Memdump::M88200Page:
                    394:                len = 4;
                    395:                addr = GetAddrAtPageShort(x, y);
                    396:                break;
                    397: 
                    398:         case Memdump::M68030PageLong:
                    399:                PANIC("not supported");
                    400:                break;
                    401: 
1.1.1.15  root      402:         case Memdump::M680x0Disasm:
1.1.1.13  root      403:                len = 2;
                    404:                addr = GetAddrAtDisasm(x, y, len);
                    405:                break;
                    406: 
                    407:         case Memdump::M88100Disasm:
                    408:                len = 4;
                    409:                addr = GetAddrAtDisasm(x, y, len);
                    410:                break;
                    411: 
                    412:         case Memdump::HD64180Disasm:
                    413:                len = 1;
                    414:                addr = GetAddrAtDisasm(x, y, len);
                    415:                break;
                    416: 
                    417:         default:
                    418:                break;
                    419:        }
                    420:        if ((int64)addr < 0) {
                    421:                return;
                    422:        }
                    423:        addr &= ~(len - 1);
                    424: 
                    425:        // このアドレスが編集可能 (≒メモリ) か?
                    426:        if (memdump->CanPoke(addr) == false) {
                    427:                ::wxMessageBox(_("Can not edit here"), _("Memory Edit"),
                    428:                        wxICON_EXCLAMATION | wxOK | wxOK_DEFAULT, this);
                    429:                return;
                    430:        }
                    431: 
                    432:        // 出来ればここをハイライトとかしたい
                    433: 
                    434:        // 現在値を(再)取得。
                    435:        uint32 val = memdump->Peek(addr, len);
                    436: 
                    437:        // sizestr は表示形式ではなく単なるサイズ。(DescShort なら Long)
                    438:        std::string sizestr;
                    439:        switch (len) {
                    440:         case 1:
                    441:                sizestr = Format2String(Memdump::Byte);
                    442:                break;
                    443:         case 2:
                    444:                sizestr = Format2String(Memdump::Word);
                    445:                break;
                    446:         case 4:
                    447:                sizestr = Format2String(Memdump::Long);
                    448:                break;
                    449:         default:
                    450:                PANIC("corrupted len=%d", len);
                    451:        }
                    452: 
                    453:        // 編集
                    454:        auto dlg = new MemEditDialog(this, addr, val, len, sizestr);
                    455:        if (dlg->ShowModal() == wxID_OK) {
                    456:                uint32 data = dlg->GetData();
                    457: 
                    458:                // 更新
1.1.1.14  root      459:                if (memdump->Poke(addr, data, len) == false) {
1.1.1.13  root      460:                        ::wxMessageBox(_("Could not edit"), _("Memory Edit"),
                    461:                                wxICON_EXCLAMATION | wxOK | wxOK_DEFAULT, this);
                    462:                }
                    463:        }
                    464: }
                    465: 
                    466: // 16進ダンプ画面のテキスト座標 (x, y) に対応するアドレスを返す。
                    467: // 対応するアドレスがない場合は (uint64)-1 を返す。
                    468: uint64
                    469: WXMemdumpWindow::GetAddrAtHexdump(int x, int y, int len)
                    470: {
                    471:        if (x < 68) {
                    472:                // 16進ダンプ部分
                    473: 
                    474:                // 空白部分なら除外
                    475:                x -= 19;
                    476:                if (x % (len * 2 + 1) == len * 2) {
                    477:                        return (uint64)-1;
                    478:                }
                    479:                x = (x / (len * 2 + 1)) * len;
                    480:        } else {
                    481:                // 文字ダンプ部分
                    482:                x -= 68;
                    483:        }
                    484: 
                    485:        if (x > 15) {
                    486:                return (uint64)-1;
                    487:        }
                    488: 
1.1.1.14  root      489:        return memdump->GetAddr().Addr() + (y * memdump->GetStride()) + x;
1.1.1.9   root      490: }
                    491: 
1.1.1.13  root      492: // 32bit ページテーブル画面のテキスト座標 (x, y) に対応するアドレスを返す。
                    493: // 対応するアドレスがない場合は (uint64)-1 を返す。
                    494: uint64
                    495: WXMemdumpWindow::GetAddrAtPageShort(int x, int y)
                    496: {
                    497:        // 32bit ページテーブルなら1行で1ロングワード。
                    498:        // 16進の場合との親和性のため、ダンプ値のところだけ反応。
                    499:        if (x >= 19 + 8) {
                    500:                return (uint64)-1;
                    501:        }
1.1.1.14  root      502:        return memdump->GetAddr().Addr() + y * 4;
1.1.1.13  root      503: }
                    504: 
                    505: // 逆アセンブル画面のテキスト座標 (x, y) に対応するアドレスを返す。
                    506: // minlen は命令の最小バイト数。
                    507: // 対応するアドレスがない場合は (uint64)-1 を返す。
                    508: uint64
                    509: WXMemdumpWindow::GetAddrAtDisasm(int x, int y, int minlen)
                    510: {
                    511:        // 先頭から y 行目のアドレス
                    512:        uint32 yaddr = memdump->GetLineOffset(y);
                    513: 
                    514:        // y 行目の命令のバイト数
                    515:        uint32 y1addr = memdump->GetLineOffset(y + 1);
                    516:        uint32 bytes = y1addr - yaddr;
                    517: 
                    518:        // 空白部分なら除外
                    519:        x -= 19;
                    520: 
                    521:        if (x % (minlen * 2 + 1) == minlen * 2) {
                    522:                return (uint64)-1;
                    523:        }
                    524:        x = (x / (minlen * 2 + 1)) * minlen;
                    525: 
                    526:        if (x >= bytes) {
                    527:                return (uint64)-1;
                    528:        }
                    529: 
1.1.1.14  root      530:        return memdump->GetAddr().Addr() + yaddr + x;
1.1.1.13  root      531: }
                    532: 
                    533: // セレクション番号からフォーマット番号への変換
                    534: Memdump::Format
                    535: WXMemdumpWindow::Selection2Format(int idx)
                    536: {
                    537:        assert(idx < fmts.size());
                    538:        return fmts[idx].first;
                    539: }
                    540: 
                    541: // フォーマット番号からセレクション番号への変換
                    542: int
                    543: WXMemdumpWindow::Format2Selection(Memdump::Format fmt_)
                    544: {
                    545:        for (int idx = 0, end = fmts.size(); idx < end; idx++) {
                    546:                auto p = fmts[idx];
                    547:                if (fmt_ == p.first) {
                    548:                        return idx;
                    549:                }
                    550:        }
                    551:        // ?
                    552:        return 0;
                    553: }
                    554: 
                    555: // フォーマット番号から文字列への変換
                    556: wxString
                    557: WXMemdumpWindow::Format2String(Memdump::Format fmt_)
                    558: {
                    559:        for (int idx = 0, end = fmts.size(); idx < end; idx++) {
                    560:                auto p = fmts[idx];
                    561:                if (fmt_ == p.first) {
                    562:                        return p.second;
                    563:                }
                    564:        }
                    565:        // ?
                    566:        return wxEmptyString;
                    567: }
                    568: 
                    569: 
                    570: //
                    571: // 編集ダイアログ
                    572: //
                    573: 
                    574: wxBEGIN_EVENT_TABLE(MemEditDialog, inherited)
                    575:        EVT_TEXT_ENTER(ID_EDIT, MemEditDialog::OnTextEnter)
                    576: wxEND_EVENT_TABLE()
                    577: 
                    578: // コンストラクタ
                    579: MemEditDialog::MemEditDialog(wxWindow *parent, uint32 addr, uint32 oldval,
                    580:        int len, const std::string& sizestr)
                    581:        : inherited(parent, wxID_ANY, _("Edit memory"))
                    582: {
                    583:        auto topsizer = new wxBoxSizer(wxVERTICAL);
                    584: 
                    585:        auto gridsizer = new wxFlexGridSizer(2);
                    586:        topsizer->Add(gridsizer, 0, wxEXPAND | wxALL, 3);
                    587: 
                    588:        gridsizer->Add(new wxStaticText(this, wxID_ANY, _("Address:")),
                    589:                0, wxEXPAND);
                    590: 
                    591:        std::string addrstr = "$";
                    592:        addrstr += strhex(addr);
                    593:        auto addrctrl = new wxStaticText(this, wxID_ANY, addrstr,
                    594:                wxDefaultPosition, wxDefaultSize, wxBORDER_SUNKEN);
                    595:        gridsizer->Add(addrctrl, 0, wxEXPAND);
                    596: 
                    597:        gridsizer->Add(new wxStaticText(this, wxID_ANY, _("Size:")),
                    598:                0, wxEXPAND);
                    599:        gridsizer->Add(new wxStaticText(this, wxID_ANY, sizestr),
                    600:                0, wxEXPAND);
                    601: 
                    602:        gridsizer->Add(new wxStaticText(this, wxID_ANY, _("Data:")),
                    603:                0, wxEXPAND);
                    604: 
                    605:        std::string oldstr = strhex(oldval, len * 2);
                    606:        datactrl = new wxTextCtrl(this, ID_EDIT, oldstr,
                    607:                wxDefaultPosition, wxDefaultSize, wxTE_PROCESS_ENTER);
                    608:        gridsizer->Add(datactrl, 0, wxEXPAND);
                    609: 
                    610:        topsizer->Add(CreateStdDialogButtonSizer(wxOK | wxCANCEL | wxNO_DEFAULT),
                    611:                0, wxEXPAND | wxALL, 3);
                    612: 
                    613:        SetSizer(topsizer);
                    614:        wxSize sz = topsizer->Fit(this);
                    615:        SetClientSize(sz);
                    616:        SetMinClientSize(sz);
                    617: }
                    618: 
                    619: // デストラクタ
                    620: MemEditDialog::~MemEditDialog()
                    621: {
                    622: }
                    623: 
                    624: // テキスト入力
                    625: void
                    626: MemEditDialog::OnTextEnter(wxCommandEvent& event)
                    627: {
                    628:        EndModal(wxID_OK);
                    629: }
                    630: 
                    631: // テキストコントロールの値を返す。
                    632: // 変換できなければ (uint64)-1 を返す。
                    633: uint64
                    634: MemEditDialog::GetData() const
                    635: {
                    636:        unsigned long int ul;
                    637:        char *end;
                    638: 
                    639:        // wxString だと地味にめんどい
                    640:        wxString wtext = datactrl->GetValue();
                    641:        std::string text((const char *)wtext.mb_str());
                    642: 
                    643:        errno = 0;
                    644:        ul = strtoul(&text[0], &end, 16);
                    645:        if (end == &text[0] || *end != '\0' || errno != 0) {
                    646:                return (uint64)-1;
                    647:        }
                    648:        return (uint32)ul;
                    649: }

unix.superglobalmegacorp.com

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