--- nono/wx/wxdumpmonitor.cpp 2026/04/29 17:04:30 1.1.1.2 +++ nono/wx/wxdumpmonitor.cpp 2026/04/29 17:04:56 1.1.1.9 @@ -1,13 +1,14 @@ // // nono -// Copyright (C) 2019 isaki@NetBSD.org +// Copyright (C) 2020 nono project +// Licensed under nono-license.txt // -#include "wxheader.h" #include "wxdumpmonitor.h" #include "wxtextscreen.h" -#include "mystring.h" #include "bus.h" +#include "debugger.h" +#include // // メモリダンプウィンドウ @@ -24,54 +25,85 @@ wxBEGIN_EVENT_TABLE(WXMemdumpWindow, inh EVT_TEXT_ENTER(ID_TEXT, WXMemdumpWindow::OnTextEnter) EVT_BUTTON(ID_PREV, WXMemdumpWindow::OnPrev) EVT_BUTTON(ID_NEXT, WXMemdumpWindow::OnNext) - EVT_TIMER(wxID_ANY, WXMemdumpWindow::OnTimer) wxEND_EVENT_TABLE() // コンストラクタ -WXMemdumpWindow::WXMemdumpWindow(wxWindow *parent, wxWindowID id) - : inherited(parent, id, wxT("メモリダンプ")) -{ - col = 76; - row = 16; - // 最初に不一致を起こさせて再描画させるため - last_addr = 0xffffffff; - - wxBoxSizer *vbox = new wxBoxSizer(wxVERTICAL); - - // 上枠 - wxBoxSizer *hbox = new wxBoxSizer(wxHORIZONTAL); - vbox->Add(hbox); +// (タイトルは UpdateAddr() でセットする) +WXMemdumpWindow::WXMemdumpWindow(wxWindow *parent, int idx_) + : inherited(parent, wxID_ANY, wxEmptyString) +{ + idx = idx_; + + // → + // +--+----------------------------+--+ + // | |↓+-----------------------+ | | + // | | | 上枠 (アドレス入力欄) | | | + // | | +-----------------------+ | | + // |左| | 上余白 (padding1) | |右| + // |余| +-----------------------+ |余| + // |白| | TextScreen | |白| + // | | +-----------------------+ | | + // | | | 下余白 (padding2) | | | + // | | +-----------------------+ | | + // +--+----------------------------+--+ + + topsizer = new wxBoxSizer(wxHORIZONTAL); + // 左余白 + topsizer->Add(new WXPaddingPanel(this), 0, wxEXPAND); + + // 中列用の縦 sizer + auto *vbox = new wxBoxSizer(wxVERTICAL); + topsizer->Add(vbox, 0, wxEXPAND); + + // 上枠用の下敷きパネル + WXPaddingPanel *ctrlpanel = new WXPaddingPanel(this); + vbox->Add(ctrlpanel, 0, wxEXPAND); + + // 上枠用の横 sizer + ctrlbox = new wxBoxSizer(wxHORIZONTAL); // アドレスコントロール addrctrl = new wxTextCtrl(this, ID_TEXT, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_PROCESS_ENTER); - hbox->Add(addrctrl); - hbox->AddSpacer(20); + ctrlbox->Add(addrctrl); + ctrlbox->AddSpacer(10); // △ボタン // XXX とりあえずね prev_btn = new wxButton(this, ID_PREV, wxT("△")); next_btn = new wxButton(this, ID_NEXT, wxT("▽")); - hbox->Add(prev_btn); - hbox->Add(next_btn); - - // XXX TODO 初期フォーカスをテキストコントロールに移したい - - // テキストスクリーン - monitor.Init(col, row); - screen = new WXTextScreen(this, col, row, monitor.GetBuf()); - vbox->Add(screen, 0, wxEXPAND); + ctrlbox->Add(prev_btn); + ctrlbox->Add(next_btn); - SetSizer(vbox); + // 上枠の sizer と下敷きを紐付ける + ctrlpanel->SetSizer(ctrlbox); + ctrlbox->SetSizeHints(ctrlpanel); + + // パディングパネル(上下) + // ウィンドウを1行ずつ伸縮させるためには、クライアント領域がフォント高さの + // 整数倍になるようにしないといけない。このウィンドウには大きさ不詳の + // コントロール枠があるので、フォントサイズが確定しないとパディングの + // 高さも確定しない。先にサイズ不定のパネルだけ置いといて、フォントサイズ + // 確定後に大きさを確定させる。DoSize() 参照。 + padding1 = new WXPaddingPanel(this); + padding2 = new WXPaddingPanel(this); + screen = new WXTextScreen(this, debugger_memdump_monitor(idx)); + vbox->Add(padding1, 0, wxEXPAND); + vbox->Add(screen, 1, wxEXPAND); + vbox->Add(padding2, 0, wxEXPAND); + + // 右余白 + topsizer->Add(new WXPaddingPanel(this), 0, wxEXPAND); + + SetSizer(topsizer); + + // 表示を初期化する + screen->SetUserData(sticky_addr[idx]); + UpdateAddr(); - Layout(); - Fit(); - - // メモリが高速で変わるのを目で追う必要もないと思うので - // 30Hz くらいでどうか。 - timer.SetOwner(this); - timer.Start(33); + // ウィンドウサイズを確定させる + DoSize(); } // デストラクタ @@ -79,132 +111,99 @@ WXMemdumpWindow::~WXMemdumpWindow() { } +// フォントサイズが確定したら、それによってウィンドウサイズを再計算する。 +void +WXMemdumpWindow::DoSize() +{ + // コントロールパネルの大きさ + wxSize csize = ctrlbox->ComputeFittingWindowSize(this); + CalcVSize(csize.y); +} + // テキスト入力イベント void WXMemdumpWindow::OnTextEnter(wxCommandEvent& event) { // 入力文字列(16進文字列)を数値に変換 - wxString wstr = event.GetString(); - const char *cstr = (const char *)wstr.mb_str(); - uint32 val = strtoul(cstr, NULL, 16); + const wxString& wstr = event.GetString(); + uint32 val = strtoul((const char *)wstr.mb_str(), NULL, 16); // 16 に整列 val &= ~15; - input_addr = val; + // アドレスを更新 + union64 udata; + udata.q = screen->GetUserData(); + udata.l = val; + screen->SetUserData(udata.q); + UpdateAddr(); } // △(PREV) ボタン押下イベント void WXMemdumpWindow::OnPrev(wxCommandEvent& event) { - input_addr -= 0x100; + union64 udata; + + // 1ページ戻る (横16バイト固定 × 表示行数分) + udata.q = screen->GetUserData(); + udata.l -= screen->GetRow() * 16; + + screen->SetUserData(udata.q); + UpdateAddr(); } // ▽(NEXT) ボタン押下イベント void WXMemdumpWindow::OnNext(wxCommandEvent& event) { - input_addr += 0x100; + union64 udata; + + // 1ページ進む (横16バイト固定 × 表示行数分) + udata.q = screen->GetUserData(); + udata.l += screen->GetRow() * 16; + + screen->SetUserData(udata.q); + UpdateAddr(); } -// タイマーイベント +// アドレス欄の表示を更新する void -WXMemdumpWindow::OnTimer(wxTimerEvent& event) +WXMemdumpWindow::UpdateAddr() { - if (input_addr != last_addr) { - // EVT_TEXT を起こさず変更する - addrctrl->ChangeValue(wxString(string_format("%08x", input_addr))); - last_addr = input_addr; - - // カーソルを末尾に - addrctrl->SetInsertionPointEnd(); - } - - // テキストスクリーンを更新 - Update(); - screen->Refresh(); -} - -// フォントサイズ変更 -void -WXMemdumpWindow::SetFontSize(fontsize_t fontsize) -{ - screen->SetFontSize(fontsize); - - Layout(); - Fit(); -} - -// テキストスクリーンを更新 -void -WXMemdumpWindow::Update() -{ - uint32 laddr; - uint64 paddr; - - monitor.Clear(); - - laddr = input_addr; - paddr = 0; // shut up gcc - for (int y = 0; y < row; y++) { - if (is_logical) { - } else { - // 物理アドレス - paddr = laddr; - } - - // アドレス作成 - std::string addrstr = string_format("%08x", laddr); - if (is_logical == false) { - // 物理アドレス - addrstr += ":"; - } else if ((int64)paddr < 0) { - // MMU 時点でバスエラー - addrstr += ":BusErr"; - } else if (paddr == laddr) { - // PA==VA - addrstr += "=PA"; - } else { - // PA!=VA - addrstr += string_format(":%08x:", (uint32)paddr); - } - monitor.Print(0, y, "%s", addrstr.c_str()); - - // ダンプ作成 - std::string hexstr; - std::string chrstr; - for (int x = 0; x < 8; x++) { - uint64 b1 = m68030_phys_peek_8(paddr); - uint64 b2 = m68030_phys_peek_8(paddr + 1); - - // 偶数バイト目 - if ((int64)b1 < 0) { - hexstr += "--"; - chrstr += " "; - } else { - uint32 c1 = (uint32)b1; - hexstr += string_format("%02x", c1); - chrstr += string_format("%c", - (0x20 <= c1 && c1 <= 0x7e) ? c1 : '.'); - } - // 奇数バイト目 - if ((int64)b2 < 0) { - hexstr += "--"; - chrstr += " "; - } else { - uint32 c2 = (uint32)b2; - hexstr += string_format("%02x", c2); - chrstr += string_format("%c", - (0x20 <= c2 && c2 <= 0x7e) ? c2 : '.'); - } - hexstr += " "; - - laddr += 2; - paddr += 2; - } - - monitor.Print(19, y, "%s", hexstr.c_str()); - monitor.Print(60, y, "%s", chrstr.c_str()); - } + uint32 addr = screen->GetUserData(); + + // 二次情報にコピー。 + sticky_addr[idx] = addr; + + // EVT_TEXT を起こさず変更する + addrctrl->ChangeValue(wxString(string_format("%08x", addr))); + + // カーソルを末尾に + addrctrl->SetInsertionPointEnd(); + + // タイトルを変更 + SetTitle(_("Memory Dump") + string_format(" %d: $%08x", idx, addr)); +} + +// ウィンドウ ID に対応する sticky address を返す +uint32 +WXMemdumpWindow::GetStickyAddr(int id) +{ + int n = id - ID_MONITOR_MEMDUMP0; + assert(n < sticky_addr.size()); + return sticky_addr[n]; +} + +// ウィンドウ ID に対応する sticky address を設定する +void +WXMemdumpWindow::SetStickyAddr(int id, uint32 addr) +{ + int n = id - ID_MONITOR_MEMDUMP0; + assert(n < sticky_addr.size()); + sticky_addr[n] = addr; } + +// アドレス +/*static*/ std::array +WXMemdumpWindow::sticky_addr;