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

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.11  root      144:        // ウィンドウサイズを確定させる
1.1.1.13  root      145:        FontChanged();
1.1.1.11  root      146: 
1.1.1.13  root      147:        // パネルに来るマウスイベントをこっちに回す
                    148:        screen->Connect(wxEVT_MOUSEWHEEL,
                    149:                wxMouseEventHandler(WXMemdumpWindow::OnMouseWheel), NULL, this);
                    150:        screen->Connect(wxEVT_LEFT_DCLICK,
                    151:                wxMouseEventHandler(WXMemdumpWindow::OnDClick), NULL, this);
                    152: 
                    153:        // メモリダンプオブジェクトを取得
                    154:        auto mon = screen->GetMonitor();
1.1.1.15  root      155:        memdump = dynamic_cast<MemdumpMonitor *>(mon->obj);
1.1.1.13  root      156:        assert(memdump);
                    157: 
                    158:        // 初期値をコントロールに設定
                    159:        auto fmt = memdump->GetFormat();
                    160:        fmtctrl->SetSelection(Format2Selection(fmt));
                    161:        DoFormat(fmt);
1.1.1.9   root      162:        UpdateAddr();
1.1       root      163: }
                    164: 
                    165: // デストラクタ
                    166: WXMemdumpWindow::~WXMemdumpWindow()
                    167: {
                    168: }
                    169: 
1.1.1.13  root      170: void
                    171: WXMemdumpWindow::FontChanged()
                    172: {
                    173:        for (auto *btn : buttons) {
1.1.1.16! root      174:                // ボタンサイズを先に一旦リセット。
        !           175:                btn->SetMinSize(wxSize(1, 1));
        !           176:                btn->SetSize(wxSize(1, 1));
        !           177: 
        !           178:                // 各ボタンコントロールに伝搬。
1.1.1.13  root      179:                btn->FontChanged();
1.1.1.16! root      180: 
        !           181:                // ボタンを正方形に固定する (テキストは1文字か2文字と知っている)。
        !           182:                // 押しやすくするため、最小 24x24 にしてみる。
        !           183:                wxSize size = btn->GetSize();
        !           184:                if (size.y < 24) {
        !           185:                        size.y = 24;
        !           186:                }
        !           187:                size.x = size.y;
        !           188: 
        !           189:                // 勝手にベストサイズに戻らないように最小サイズごと固定する。
        !           190:                btn->SetSize(size);
        !           191:                btn->SetMinSize(size);
1.1.1.13  root      192:        }
1.1.1.16! root      193: 
        !           194:        screen->FontChanged();
        !           195: 
        !           196:        Fit();
        !           197: }
        !           198: 
        !           199: void
        !           200: WXMemdumpWindow::Fit()
        !           201: {
        !           202:        // inherited::Fit() は呼ばずに自力で行う。
        !           203: 
        !           204:        wxSize newsize = DoSizeHints();
        !           205:        SetClientSize(newsize);
        !           206: }
        !           207: 
        !           208: bool
        !           209: WXMemdumpWindow::Layout()
        !           210: {
        !           211:        // wxmonitor.cpp の WXScrollMonitorWindow::Layout() のコメント参照。
        !           212:        wxSize client = GetClientSize();
        !           213:        const wxSize win = GetSize();
        !           214:        const wxSize margin = win - client;
        !           215:        const wxSize ctrlsize = ctrlbox->GetSize();
        !           216:        const wxSize monsize = screen->GetSize();
        !           217: 
        !           218:        if (oldmargin != margin) {
        !           219:                layout_pass2 = true;
        !           220:                oldmargin = margin;
        !           221:                CallAfter([this]() {
        !           222:                        DoSizeHints();
        !           223:                });
        !           224:                return true;
        !           225:        } else if (layout_pass2) {
        !           226:                layout_pass2 = false;
        !           227:                client.y = ctrlsize.y + monsize.y;
        !           228:                SetClientSize(client);
        !           229:                Hide();
        !           230:                Show();
        !           231:                return true;
        !           232:        }
        !           233: 
        !           234:        // Sizer 使ってるのでその処理は任せる。
        !           235:        return inherited::Layout();
        !           236: }
        !           237: 
        !           238: // クライアントサイズと最大/最小サイズを計算する。
        !           239: // SetSizeHints() を実行し、設定すべきクライアントサイズを返す。
        !           240: wxSize
        !           241: WXMemdumpWindow::DoSizeHints()
        !           242: {
        !           243:        // この後の Fit() でリサイズに使われる大きさを取得。
        !           244:        wxSize fitsize = GetSizer()->ComputeFittingClientSize(this);
        !           245:        wxSize ctrlsize = ctrlbox->ComputeFittingClientSize(this);
        !           246: 
        !           247:        // 高さの最小は (コントロールパネル分と) TextScreen 1行分にしておく。
        !           248:        int min_y = ctrlsize.y + screen->GetScreenHeight(1);
        !           249:        int new_y = ctrlsize.y + screen->GetSize().y;
        !           250:        wxSize minsize(fitsize.x, min_y);
        !           251:        wxSize maxsize(fitsize.x, GetMaxClientSize().y);
        !           252:        wxSize incsize(0, screen->GetFontHeight());
        !           253:        SetSizeHints(ClientToWindowSize(minsize), ClientToWindowSize(maxsize),
        !           254:                incsize);
        !           255: 
        !           256:        return wxSize(fitsize.x, new_y);
1.1.1.13  root      257: }
                    258: 
1.1       root      259: // テキスト入力イベント
                    260: void
                    261: WXMemdumpWindow::OnTextEnter(wxCommandEvent& event)
                    262: {
                    263:        // 入力文字列(16進文字列)を数値に変換
1.1.1.5   root      264:        const wxString& wstr = event.GetString();
1.1.1.6   root      265:        uint32 val = strtoul((const char *)wstr.mb_str(), NULL, 16);
1.1       root      266: 
1.1.1.9   root      267:        // アドレスを更新
1.1.1.13  root      268:        memdump->SetAddr(val);
1.1.1.9   root      269:        UpdateAddr();
1.1       root      270: }
                    271: 
1.1.1.13  root      272: // "<"(前行) ボタン押下イベント
1.1       root      273: void
1.1.1.13  root      274: WXMemdumpWindow::OnPrevLine(wxCommandEvent& event)
1.1       root      275: {
1.1.1.13  root      276:        // 1行戻る
                    277:        memdump->Offset(memdump->GetLineOffset(-1));
1.1.1.9   root      278: 
1.1.1.13  root      279:        UpdateAddr();
                    280: }
                    281: 
                    282: // "<<"(前ページ) ボタン押下イベント
                    283: void
                    284: WXMemdumpWindow::OnPrevPage(wxCommandEvent& event)
                    285: {
                    286:        // 1ページ戻る
                    287:        memdump->Offset(memdump->GetPageOffset(-1));
1.1.1.9   root      288: 
                    289:        UpdateAddr();
1.1       root      290: }
                    291: 
1.1.1.13  root      292: // ">"(次行) ボタン押下イベント
1.1       root      293: void
1.1.1.13  root      294: WXMemdumpWindow::OnNextLine(wxCommandEvent& event)
1.1       root      295: {
1.1.1.13  root      296:        // 1行進む
                    297:        memdump->Offset(memdump->GetLineOffset(1));
                    298: 
                    299:        UpdateAddr();
                    300: }
1.1.1.9   root      301: 
1.1.1.13  root      302: // ">>"(次ページ) ボタン押下イベント
                    303: void
                    304: WXMemdumpWindow::OnNextPage(wxCommandEvent& event)
                    305: {
                    306:        // 1ページ進む
                    307:        memdump->Offset(memdump->GetPageOffset(1));
1.1.1.9   root      308: 
                    309:        UpdateAddr();
1.1       root      310: }
                    311: 
1.1.1.9   root      312: // アドレス欄の表示を更新する
                    313: void
                    314: WXMemdumpWindow::UpdateAddr()
                    315: {
1.1.1.13  root      316:        int width;
                    317:        std::string title;
                    318:        if (IS_MONITOR_XPMEMDUMP(monid)) {
                    319:                width = 5;
                    320:                title = _("XP Memory Dump");
                    321:        } else {
                    322:                width = 8;
                    323:                title = _("Main Memory Dump");
                    324:        }
1.1.1.9   root      325: 
1.1.1.14  root      326:        uint32 addr = memdump->GetAddr().Addr();
1.1.1.13  root      327:        std::string addrstr = strhex(addr, width);
1.1.1.9   root      328: 
                    329:        // EVT_TEXT を起こさず変更する
1.1.1.13  root      330:        addrctrl->ChangeValue(addrstr);
1.1.1.9   root      331: 
                    332:        // カーソルを末尾に
                    333:        addrctrl->SetInsertionPointEnd();
                    334: 
                    335:        // タイトルを変更
1.1.1.13  root      336:        title += string_format(" %d: $", myidx);
                    337:        title += addrstr;
                    338:        SetTitle(title);
                    339: 
                    340:        // 即更新
                    341:        Refresh();
1.1.1.9   root      342: }
                    343: 
1.1.1.13  root      344: // 表示フォーマット変更イベント
                    345: void
                    346: WXMemdumpWindow::OnFormat(wxCommandEvent& event)
1.1.1.9   root      347: {
1.1.1.13  root      348:        int idx = event.GetSelection();
                    349:        DoFormat(Selection2Format(idx));
1.1       root      350: }
1.1.1.9   root      351: 
1.1.1.13  root      352: // 表示フォーマット変更処理
1.1.1.9   root      353: void
1.1.1.13  root      354: WXMemdumpWindow::DoFormat(Memdump::Format fmt)
1.1.1.9   root      355: {
1.1.1.13  root      356:        memdump->SetFormat(fmt);
                    357: 
                    358:        // SetFormat() によってアドレスが切り捨てられる場合があるので
                    359:        // アドレス欄の表示ごと更新。
                    360:        UpdateAddr();
                    361: }
                    362: 
                    363: // マウスホイールイベント
                    364: void
                    365: WXMemdumpWindow::OnMouseWheel(wxMouseEvent& event)
                    366: {
                    367:        int delta = event.GetWheelRotation();
                    368: 
                    369:        // 1回の変化で +/-120 が来る。
                    370:        // たいていのアプリケーションで3行ずつの移動に換算することが多いようだが
                    371:        // ここはメモリダンプなので 4行ずつにする。
                    372: 
                    373:        if (delta != 0) {
                    374:                memdump->Offset(memdump->GetLineOffset(-delta / 30));
                    375:                UpdateAddr();
                    376:        }
                    377: }
                    378: 
                    379: // ダブルクリックイベント
                    380: void
                    381: WXMemdumpWindow::OnDClick(wxMouseEvent& event)
                    382: {
                    383:        event.Skip();
                    384: 
                    385:        auto fmt = memdump->GetFormat();
                    386: 
                    387:        // テキストの桁数、行数にする
                    388:        wxPoint tpos = screen->GetTextPosition(event.GetPosition());
                    389:        int x = tpos.x;
                    390:        int y = tpos.y;
                    391: 
                    392:        // ウィンドウサイズを変えた時に出来る下の空き地にはヒットさせない
                    393:        if (y >= screen->GetRow()) {
                    394:                return;
                    395:        }
                    396: 
                    397:        // アドレス部分は常に除外でいいか
                    398:        if (x < 19) {
                    399:                return;
                    400:        }
                    401: 
                    402:        // 現在のフォーマットでのクリック位置のアドレスを求める
                    403:        int len = 0;
                    404:        uint64 addr = -1;
                    405:        switch (fmt) {
                    406:         case Memdump::Byte:
                    407:                len = 1;
                    408:                addr = GetAddrAtHexdump(x, y, len);
                    409:                break;
                    410:         case Memdump::Word:
                    411:                len = 2;
                    412:                addr = GetAddrAtHexdump(x, y, len);
                    413:                break;
                    414:         case Memdump::Long:
                    415:                len = 4;
                    416:                addr = GetAddrAtHexdump(x, y, len);
                    417:                break;
                    418:         case Memdump::M68030PageShort:
                    419:         case Memdump::M88200Page:
                    420:                len = 4;
                    421:                addr = GetAddrAtPageShort(x, y);
                    422:                break;
                    423: 
                    424:         case Memdump::M68030PageLong:
                    425:                PANIC("not supported");
                    426:                break;
                    427: 
1.1.1.15  root      428:         case Memdump::M680x0Disasm:
1.1.1.13  root      429:                len = 2;
                    430:                addr = GetAddrAtDisasm(x, y, len);
                    431:                break;
                    432: 
                    433:         case Memdump::M88100Disasm:
                    434:                len = 4;
                    435:                addr = GetAddrAtDisasm(x, y, len);
                    436:                break;
                    437: 
                    438:         case Memdump::HD64180Disasm:
                    439:                len = 1;
                    440:                addr = GetAddrAtDisasm(x, y, len);
                    441:                break;
                    442: 
                    443:         default:
                    444:                break;
                    445:        }
                    446:        if ((int64)addr < 0) {
                    447:                return;
                    448:        }
                    449:        addr &= ~(len - 1);
                    450: 
                    451:        // このアドレスが編集可能 (≒メモリ) か?
                    452:        if (memdump->CanPoke(addr) == false) {
                    453:                ::wxMessageBox(_("Can not edit here"), _("Memory Edit"),
                    454:                        wxICON_EXCLAMATION | wxOK | wxOK_DEFAULT, this);
                    455:                return;
                    456:        }
                    457: 
                    458:        // 出来ればここをハイライトとかしたい
                    459: 
                    460:        // 現在値を(再)取得。
                    461:        uint32 val = memdump->Peek(addr, len);
                    462: 
                    463:        // sizestr は表示形式ではなく単なるサイズ。(DescShort なら Long)
                    464:        std::string sizestr;
                    465:        switch (len) {
                    466:         case 1:
                    467:                sizestr = Format2String(Memdump::Byte);
                    468:                break;
                    469:         case 2:
                    470:                sizestr = Format2String(Memdump::Word);
                    471:                break;
                    472:         case 4:
                    473:                sizestr = Format2String(Memdump::Long);
                    474:                break;
                    475:         default:
                    476:                PANIC("corrupted len=%d", len);
                    477:        }
                    478: 
                    479:        // 編集
                    480:        auto dlg = new MemEditDialog(this, addr, val, len, sizestr);
                    481:        if (dlg->ShowModal() == wxID_OK) {
                    482:                uint32 data = dlg->GetData();
                    483: 
                    484:                // 更新
1.1.1.14  root      485:                if (memdump->Poke(addr, data, len) == false) {
1.1.1.13  root      486:                        ::wxMessageBox(_("Could not edit"), _("Memory Edit"),
                    487:                                wxICON_EXCLAMATION | wxOK | wxOK_DEFAULT, this);
                    488:                }
                    489:        }
                    490: }
                    491: 
                    492: // 16進ダンプ画面のテキスト座標 (x, y) に対応するアドレスを返す。
                    493: // 対応するアドレスがない場合は (uint64)-1 を返す。
                    494: uint64
                    495: WXMemdumpWindow::GetAddrAtHexdump(int x, int y, int len)
                    496: {
                    497:        if (x < 68) {
                    498:                // 16進ダンプ部分
                    499: 
                    500:                // 空白部分なら除外
                    501:                x -= 19;
                    502:                if (x % (len * 2 + 1) == len * 2) {
                    503:                        return (uint64)-1;
                    504:                }
                    505:                x = (x / (len * 2 + 1)) * len;
                    506:        } else {
                    507:                // 文字ダンプ部分
                    508:                x -= 68;
                    509:        }
                    510: 
                    511:        if (x > 15) {
                    512:                return (uint64)-1;
                    513:        }
                    514: 
1.1.1.14  root      515:        return memdump->GetAddr().Addr() + (y * memdump->GetStride()) + x;
1.1.1.9   root      516: }
                    517: 
1.1.1.13  root      518: // 32bit ページテーブル画面のテキスト座標 (x, y) に対応するアドレスを返す。
                    519: // 対応するアドレスがない場合は (uint64)-1 を返す。
                    520: uint64
                    521: WXMemdumpWindow::GetAddrAtPageShort(int x, int y)
                    522: {
                    523:        // 32bit ページテーブルなら1行で1ロングワード。
                    524:        // 16進の場合との親和性のため、ダンプ値のところだけ反応。
                    525:        if (x >= 19 + 8) {
                    526:                return (uint64)-1;
                    527:        }
1.1.1.14  root      528:        return memdump->GetAddr().Addr() + y * 4;
1.1.1.13  root      529: }
                    530: 
                    531: // 逆アセンブル画面のテキスト座標 (x, y) に対応するアドレスを返す。
                    532: // minlen は命令の最小バイト数。
                    533: // 対応するアドレスがない場合は (uint64)-1 を返す。
                    534: uint64
                    535: WXMemdumpWindow::GetAddrAtDisasm(int x, int y, int minlen)
                    536: {
                    537:        // 先頭から y 行目のアドレス
                    538:        uint32 yaddr = memdump->GetLineOffset(y);
                    539: 
                    540:        // y 行目の命令のバイト数
                    541:        uint32 y1addr = memdump->GetLineOffset(y + 1);
                    542:        uint32 bytes = y1addr - yaddr;
                    543: 
                    544:        // 空白部分なら除外
                    545:        x -= 19;
                    546: 
                    547:        if (x % (minlen * 2 + 1) == minlen * 2) {
                    548:                return (uint64)-1;
                    549:        }
                    550:        x = (x / (minlen * 2 + 1)) * minlen;
                    551: 
                    552:        if (x >= bytes) {
                    553:                return (uint64)-1;
                    554:        }
                    555: 
1.1.1.14  root      556:        return memdump->GetAddr().Addr() + yaddr + x;
1.1.1.13  root      557: }
                    558: 
                    559: // セレクション番号からフォーマット番号への変換
                    560: Memdump::Format
                    561: WXMemdumpWindow::Selection2Format(int idx)
                    562: {
                    563:        assert(idx < fmts.size());
                    564:        return fmts[idx].first;
                    565: }
                    566: 
                    567: // フォーマット番号からセレクション番号への変換
                    568: int
                    569: WXMemdumpWindow::Format2Selection(Memdump::Format fmt_)
                    570: {
                    571:        for (int idx = 0, end = fmts.size(); idx < end; idx++) {
                    572:                auto p = fmts[idx];
                    573:                if (fmt_ == p.first) {
                    574:                        return idx;
                    575:                }
                    576:        }
                    577:        // ?
                    578:        return 0;
                    579: }
                    580: 
                    581: // フォーマット番号から文字列への変換
                    582: wxString
                    583: WXMemdumpWindow::Format2String(Memdump::Format fmt_)
                    584: {
                    585:        for (int idx = 0, end = fmts.size(); idx < end; idx++) {
                    586:                auto p = fmts[idx];
                    587:                if (fmt_ == p.first) {
                    588:                        return p.second;
                    589:                }
                    590:        }
                    591:        // ?
                    592:        return wxEmptyString;
                    593: }
                    594: 
                    595: 
                    596: //
                    597: // 編集ダイアログ
                    598: //
                    599: 
                    600: wxBEGIN_EVENT_TABLE(MemEditDialog, inherited)
                    601:        EVT_TEXT_ENTER(ID_EDIT, MemEditDialog::OnTextEnter)
                    602: wxEND_EVENT_TABLE()
                    603: 
                    604: // コンストラクタ
                    605: MemEditDialog::MemEditDialog(wxWindow *parent, uint32 addr, uint32 oldval,
                    606:        int len, const std::string& sizestr)
                    607:        : inherited(parent, wxID_ANY, _("Edit memory"))
                    608: {
                    609:        auto topsizer = new wxBoxSizer(wxVERTICAL);
                    610: 
                    611:        auto gridsizer = new wxFlexGridSizer(2);
                    612:        topsizer->Add(gridsizer, 0, wxEXPAND | wxALL, 3);
                    613: 
                    614:        gridsizer->Add(new wxStaticText(this, wxID_ANY, _("Address:")),
                    615:                0, wxEXPAND);
                    616: 
                    617:        std::string addrstr = "$";
                    618:        addrstr += strhex(addr);
                    619:        auto addrctrl = new wxStaticText(this, wxID_ANY, addrstr,
                    620:                wxDefaultPosition, wxDefaultSize, wxBORDER_SUNKEN);
                    621:        gridsizer->Add(addrctrl, 0, wxEXPAND);
                    622: 
                    623:        gridsizer->Add(new wxStaticText(this, wxID_ANY, _("Size:")),
                    624:                0, wxEXPAND);
                    625:        gridsizer->Add(new wxStaticText(this, wxID_ANY, sizestr),
                    626:                0, wxEXPAND);
                    627: 
                    628:        gridsizer->Add(new wxStaticText(this, wxID_ANY, _("Data:")),
                    629:                0, wxEXPAND);
                    630: 
                    631:        std::string oldstr = strhex(oldval, len * 2);
                    632:        datactrl = new wxTextCtrl(this, ID_EDIT, oldstr,
                    633:                wxDefaultPosition, wxDefaultSize, wxTE_PROCESS_ENTER);
                    634:        gridsizer->Add(datactrl, 0, wxEXPAND);
                    635: 
                    636:        topsizer->Add(CreateStdDialogButtonSizer(wxOK | wxCANCEL | wxNO_DEFAULT),
                    637:                0, wxEXPAND | wxALL, 3);
                    638: 
                    639:        SetSizer(topsizer);
                    640:        wxSize sz = topsizer->Fit(this);
                    641:        SetClientSize(sz);
                    642:        SetMinClientSize(sz);
                    643: }
                    644: 
                    645: // デストラクタ
                    646: MemEditDialog::~MemEditDialog()
                    647: {
                    648: }
                    649: 
                    650: // テキスト入力
                    651: void
                    652: MemEditDialog::OnTextEnter(wxCommandEvent& event)
                    653: {
                    654:        EndModal(wxID_OK);
                    655: }
                    656: 
                    657: // テキストコントロールの値を返す。
                    658: // 変換できなければ (uint64)-1 を返す。
                    659: uint64
                    660: MemEditDialog::GetData() const
                    661: {
                    662:        unsigned long int ul;
                    663:        char *end;
                    664: 
                    665:        // wxString だと地味にめんどい
                    666:        wxString wtext = datactrl->GetValue();
                    667:        std::string text((const char *)wtext.mb_str());
                    668: 
                    669:        errno = 0;
                    670:        ul = strtoul(&text[0], &end, 16);
                    671:        if (end == &text[0] || *end != '\0' || errno != 0) {
                    672:                return (uint64)-1;
                    673:        }
                    674:        return (uint32)ul;
                    675: }

unix.superglobalmegacorp.com

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