From 055a5f838f8f6a1d72ee9eb930bffd9fe953f9a6 Mon Sep 17 00:00:00 2001 From: Swift Date: Sun, 7 Jun 2026 18:18:32 -0500 Subject: [PATCH] debugger: add more memory writing options --- src/gui/wxgui/debugger/DumpCtrl.cpp | 215 +++++++++++++++++++++++++--- src/gui/wxgui/debugger/DumpCtrl.h | 17 +++ src/gui/wxgui/helpers/wxHelpers.h | 19 +++ 3 files changed, 229 insertions(+), 22 deletions(-) diff --git a/src/gui/wxgui/debugger/DumpCtrl.cpp b/src/gui/wxgui/debugger/DumpCtrl.cpp index 16167e39..65dcb39d 100644 --- a/src/gui/wxgui/debugger/DumpCtrl.cpp +++ b/src/gui/wxgui/debugger/DumpCtrl.cpp @@ -1,5 +1,6 @@ #include "wxgui/wxgui.h" #include "wxgui/debugger/DumpCtrl.h" +#include "wxgui/helpers/wxHelpers.h" #include "Cafe/OS/RPL/rpl.h" #include "Cafe/OS/RPL/rpl_structs.h" #include "Cafe/HW/Espresso/Debugger/Debugger.h" @@ -28,6 +29,8 @@ DumpCtrl::DumpCtrl(wxWindow* parent, const wxWindowID& id, const wxPoint& pos, c m_memoryRegion.size = 0x1000; Init(); } + + Bind(wxEVT_MENU, &DumpCtrl::OnMenuSelected, this); } void DumpCtrl::Init() @@ -163,32 +166,47 @@ void DumpCtrl::OnMouseMove(const wxPoint& start_position, uint32 line) position.x -= OFFSET_MEMORY; } +uint32 DumpCtrl::PositionToAddress(const wxPoint& position, uint32 line) +{ + wxPoint pos = position; + + if (pos.x <= OFFSET_ADDRESS + OFFSET_ADDRESS_RELATIVE) + return MPTR_NULL; + + pos.x -= OFFSET_ADDRESS + OFFSET_ADDRESS_RELATIVE; + + if (pos.x > OFFSET_MEMORY) + return MPTR_NULL; + + const uint32 byteIndex = (pos.x / m_char_width) / 3; + return LineToOffset(line) + byteIndex; +} + void DumpCtrl::OnMouseDClick(const wxPoint& position, uint32 line) { - wxPoint pos = position; - if (pos.x <= OFFSET_ADDRESS + OFFSET_ADDRESS_RELATIVE) + uint32 address = PositionToAddress(position, line); + + if (address == MPTR_NULL) return; - - pos.x -= OFFSET_ADDRESS + OFFSET_ADDRESS_RELATIVE; - if(pos.x <= OFFSET_MEMORY) + + if (!memory_isAddressRangeAccessible(address, 1)) + return; + + if (WriteNumericDialog(address)) { - const uint32 byte_index = (pos.x / m_char_width) / 3; - const uint32 offset = LineToOffset(line) + byte_index; - if (!memory_isAddressRangeAccessible(offset, 1)) - return; - const uint8 value = memory_readU8(offset); - - wxTextEntryDialog set_value_dialog(this, _("Enter a new value."), wxString::Format(_("Set byte at address %08x"), offset), wxString::Format("%02x", value)); - if (set_value_dialog.ShowModal() == wxID_OK) - { - const uint8 new_value = std::stoul(set_value_dialog.GetValue().ToStdString(), nullptr, 16); - memory_writeU8(offset, new_value); - wxRect update_rect(0, line * m_line_height, GetSize().x, m_line_height); - RefreshControl(&update_rect); - } - - return; + wxRect updateRect(0, line * m_line_height, GetSize().x, m_line_height); + RefreshControl(&updateRect); } + // const uint8 value = memory_readU8(address); + + // wxTextEntryDialog set_value_dialog(this, _("Enter a new value."), wxString::Format(_("Set byte at address %08x"), address), wxString::Format("%02x", value)); + // if (set_value_dialog.ShowModal() == wxID_OK) + // { + // const uint8 new_value = std::stoul(set_value_dialog.GetValue().ToStdString(), nullptr, 16); + // memory_writeU8(address, new_value); + // wxRect update_rect(0, line * m_line_height, GetSize().x, m_line_height); + // RefreshControl(&update_rect); + // } } void DumpCtrl::GoToAddressDialog() @@ -264,7 +282,6 @@ uint32 DumpCtrl::OffsetToLine(uint32 offset) return (offset - m_memoryRegion.baseAddress) / 0x10; } - void DumpCtrl::OnKeyPressed(sint32 key_code, const wxPoint& position) { switch (key_code) @@ -284,3 +301,157 @@ wxSize DumpCtrl::DoGetBestSize() const { return TextList::DoGetBestSize(); } + +void DumpCtrl::OnContextMenu(const wxPoint& position, uint32 line) +{ + wxPoint pos = position; + + if (pos.x <= OFFSET_ADDRESS + OFFSET_ADDRESS_RELATIVE) + return; + + pos.x -= OFFSET_ADDRESS + OFFSET_ADDRESS_RELATIVE; + + if (pos.x > OFFSET_MEMORY) + return; + + const uint32 byteIndex = (pos.x / m_char_width) / 3; + const uint32 address = LineToOffset(line) + byteIndex; + + if (!memory_isAddressRangeAccessible(address, 1)) + return; + + m_writerContextAddress = address; + m_writerContextLine = line; + + wxMenu menu; + + menu.Append(ID_WRITE_U8, "Write Byte"); + menu.Append(ID_WRITE_U16, "Write Int16"); + menu.Append(ID_WRITE_U32, "Write Int32"); + menu.Append(ID_WRITE_FLOAT, "Write Float"); + menu.Append(ID_WRITE_STRING, "Write String"); + + PopupMenu(&menu); +} + +void DumpCtrl::OnMenuSelected(wxCommandEvent& event) +{ + bool update = false; + switch (event.GetId()) + { + case ID_WRITE_U8: + update = WriteNumericDialog(m_writerContextAddress); + break; + case ID_WRITE_U16: + update = WriteNumericDialog(m_writerContextAddress); + break; + case ID_WRITE_U32: + update = WriteNumericDialog(m_writerContextAddress); + break; + case ID_WRITE_FLOAT: + update = WriteNumericDialog(m_writerContextAddress); + break; + case ID_WRITE_STRING: + update = WriteString(m_writerContextAddress); + break; + } + + if (update) + { + wxRect updateRect(0, m_writerContextLine * m_line_height, GetSize().x, m_line_height); + RefreshControl(&updateRect); + } +} + +template +bool DumpCtrl::WriteNumericDialog(uint32 address) +{ + static_assert( + std::is_same::value || + std::is_same::value || + std::is_same::value || + std::is_same::value, + "Unsupported type" + ); + + T value; + const char* dataType; + wxString label; + + if constexpr (std::is_same::value) + { + value = memory_readU8(address); + dataType = "byte"; + label = wxString::Format("0x%02x", value); + } + else if constexpr (std::is_same::value) + { + value = memory_readU16(address); + dataType = "int16"; + label = wxString::Format("0x%04x", value); + } + else if constexpr (std::is_same::value) + { + value = memory_readU32(address); + dataType = "int32"; + label = wxString::Format("0x%08x", value); + } + else if constexpr (std::is_same::value) + { + value = memory_readFloat(address); + dataType = "float"; + label = wxString::Format("%f", value); + } + + wxTextEntryDialog dialog( + this, + _("Enter a new value."), + wxString::Format(_("Write %s at address 0x%08x"), dataType, address), + label + ); + + if (dialog.ShowModal() != wxID_OK) + return false; + + const std::optional opt = parse_numeric(dialog.GetValue()); + + if (!opt.has_value()) + { + wxMessageBox(_("Invalid value."), _("Error"), wxOK | wxICON_ERROR, this); + return false; + } + + if constexpr (std::is_same::value) + memory_writeU8(address, opt.value()); + else if constexpr (std::is_same::value) + memory_writeU16(address, opt.value()); + else if constexpr (std::is_same::value) + memory_writeU32(address, opt.value()); + else if constexpr (std::is_same::value) + memory_writeFloat(address, opt.value()); + + return true; +} + +bool DumpCtrl::WriteString(uint32 address) +{ + wxTextEntryDialog dialog( + this, + _("Enter string"), + wxString::Format(_("Write string at address 0x%08x"), address), + "" + ); + + if (dialog.ShowModal() != wxID_OK) + return false; + + std::string text = dialog.GetValue().ToStdString(); + + for (size_t i = 0; i < text.size(); i++) + memory_writeU8(address + i, static_cast(text[i])); + + // null-terminator + memory_writeU8(address + text.size(), 0); + + return true; +} diff --git a/src/gui/wxgui/debugger/DumpCtrl.h b/src/gui/wxgui/debugger/DumpCtrl.h index eb7fc53b..6e070162 100644 --- a/src/gui/wxgui/debugger/DumpCtrl.h +++ b/src/gui/wxgui/debugger/DumpCtrl.h @@ -2,6 +2,14 @@ #include "wxgui/components/TextList.h" +enum { + ID_WRITE_U8 = wxID_HIGHEST + 1, + ID_WRITE_U16, + ID_WRITE_U32, + ID_WRITE_FLOAT, + ID_WRITE_STRING +}; + class DumpCtrl : public TextList { public: @@ -15,11 +23,18 @@ protected: void CenterOffset(uint32 offset); uint32 LineToOffset(uint32 line); uint32 OffsetToLine(uint32 offset); + uint32 PositionToAddress(const wxPoint& position, uint32 line); void OnDraw(wxDC& dc, sint32 start, sint32 count, const wxPoint& start_position) override; void OnMouseMove(const wxPoint& position, uint32 line) override; void OnMouseDClick(const wxPoint& position, uint32 line) override; void OnKeyPressed(sint32 key_code, const wxPoint& position) override; + void OnContextMenu(const wxPoint& position, uint32 line) override; + void OnMenuSelected(wxCommandEvent& event); + + template + bool WriteNumericDialog(uint32 address); + bool WriteString(uint32 address); private: struct { @@ -27,4 +42,6 @@ private: uint32 size; }m_memoryRegion; uint32 m_lastGotoOffset{0}; + uint32 m_writerContextAddress {0}; + uint32 m_writerContextLine {0}; }; diff --git a/src/gui/wxgui/helpers/wxHelpers.h b/src/gui/wxgui/helpers/wxHelpers.h index fa42338b..bf030803 100644 --- a/src/gui/wxgui/helpers/wxHelpers.h +++ b/src/gui/wxgui/helpers/wxHelpers.h @@ -5,6 +5,8 @@ #include #include +#include + template <> struct fmt::formatter : formatter { @@ -106,3 +108,20 @@ void update_slider_text(wxCommandEvent& event, const wxFormatString& format = "% uint32 fix_raw_keycode(uint32 keycode, uint32 raw_flags); WindowSystem::WindowHandleInfo initHandleContextFromWxWidgetsWindow(wxWindow* wxw); + +template +std::optional parse_numeric(const wxString& text) +{ + try + { + if (std::is_same::value) + return std::stof(text.ToStdString()); + + // it's integral + return static_cast(std::stol(text.ToStdString(), nullptr, 0)); + } + catch (...) + { + return std::nullopt; + } +}