mirror of
https://github.com/cemu-project/Cemu.git
synced 2026-07-11 01:25:15 +02:00
debugger: Tweaks + add context menu to write different value types (#1950)
This commit is contained in:
@@ -12,6 +12,14 @@
|
||||
#define OFFSET_ADDRESS_RELATIVE (90)
|
||||
#define OFFSET_MEMORY (450)
|
||||
|
||||
enum {
|
||||
ID_WRITE_U8 = wxID_HIGHEST + 1,
|
||||
ID_WRITE_U16,
|
||||
ID_WRITE_U32,
|
||||
ID_WRITE_FLOAT,
|
||||
ID_WRITE_STRING
|
||||
};
|
||||
|
||||
DumpCtrl::DumpCtrl(wxWindow* parent, const wxWindowID& id, const wxPoint& pos, const wxSize& size, long style)
|
||||
: TextList(parent, id, pos, size, style)
|
||||
{
|
||||
@@ -28,6 +36,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,31 +173,36 @@ 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<uint8>(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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -264,7 +279,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 +298,144 @@ wxSize DumpCtrl::DoGetBestSize() const
|
||||
{
|
||||
return TextList::DoGetBestSize();
|
||||
}
|
||||
|
||||
void DumpCtrl::OnContextMenu(const wxPoint& position, uint32 line)
|
||||
{
|
||||
const uint32 address = PositionToAddress(position, line);
|
||||
|
||||
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<uint8>(m_writerContextAddress);
|
||||
break;
|
||||
case ID_WRITE_U16:
|
||||
update = WriteNumericDialog<uint16>(m_writerContextAddress);
|
||||
break;
|
||||
case ID_WRITE_U32:
|
||||
update = WriteNumericDialog<uint32>(m_writerContextAddress);
|
||||
break;
|
||||
case ID_WRITE_FLOAT:
|
||||
update = WriteNumericDialog<float>(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 <typename T>
|
||||
bool DumpCtrl::WriteNumericDialog(uint32 address)
|
||||
{
|
||||
static_assert(
|
||||
std::is_same<T, uint8>::value ||
|
||||
std::is_same<T, uint16>::value ||
|
||||
std::is_same<T, uint32>::value ||
|
||||
std::is_same<T, float>::value,
|
||||
"Unsupported type"
|
||||
);
|
||||
|
||||
T value;
|
||||
const char* dataType;
|
||||
wxString label;
|
||||
|
||||
if constexpr (std::is_same<T, uint8>::value)
|
||||
{
|
||||
value = memory_readU8(address);
|
||||
dataType = "byte";
|
||||
label = wxString::Format("0x%02x", value);
|
||||
}
|
||||
else if constexpr (std::is_same<T, uint16>::value)
|
||||
{
|
||||
value = memory_readU16(address);
|
||||
dataType = "int16";
|
||||
label = wxString::Format("0x%04x", value);
|
||||
}
|
||||
else if constexpr (std::is_same<T, uint32>::value)
|
||||
{
|
||||
value = memory_readU32(address);
|
||||
dataType = "int32";
|
||||
label = wxString::Format("0x%08x", value);
|
||||
}
|
||||
else if constexpr (std::is_same<T, float>::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 T newValue = ConvertString<T>(dialog.GetValue().ToStdString());
|
||||
|
||||
if constexpr (std::is_same<T, uint8>::value)
|
||||
memory_writeU8(address, newValue);
|
||||
else if constexpr (std::is_same<T, uint16>::value)
|
||||
memory_writeU16(address, newValue);
|
||||
else if constexpr (std::is_same<T, uint32>::value)
|
||||
memory_writeU32(address, newValue);
|
||||
else if constexpr (std::is_same<T, float>::value)
|
||||
memory_writeFloat(address, newValue);
|
||||
|
||||
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();
|
||||
|
||||
if (text.empty())
|
||||
return false;
|
||||
|
||||
for (size_t i = 0; i < text.size(); i++)
|
||||
memory_writeU8(address + i, static_cast<uint8>(text[i]));
|
||||
|
||||
// null-terminator
|
||||
memory_writeU8(address + text.size(), 0);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
#pragma once
|
||||
#include "wxgui/components/TextList.h"
|
||||
|
||||
|
||||
class DumpCtrl : public TextList
|
||||
{
|
||||
public:
|
||||
@@ -15,11 +14,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 <typename T>
|
||||
bool WriteNumericDialog(uint32 address);
|
||||
bool WriteString(uint32 address);
|
||||
private:
|
||||
struct
|
||||
{
|
||||
@@ -27,4 +33,6 @@ private:
|
||||
uint32 size;
|
||||
}m_memoryRegion;
|
||||
uint32 m_lastGotoOffset{0};
|
||||
uint32 m_writerContextAddress {0};
|
||||
uint32 m_writerContextLine {0};
|
||||
};
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include "Cafe/OS/RPL/rpl.h"
|
||||
#include "Cafe/OS/RPL/rpl_structs.h"
|
||||
#include "Cafe/HW/Espresso/EspressoISA.h"
|
||||
#include "util/helpers/helpers.h"
|
||||
|
||||
enum
|
||||
{
|
||||
@@ -355,15 +356,17 @@ void RegisterWindow::OnMouseDClickEvent(wxMouseEvent& event)
|
||||
{
|
||||
const uint32 register_index = id - kRegisterValueR0;
|
||||
const uint32 register_value = ppcSnapshot.gpr[register_index];
|
||||
wxTextEntryDialog set_value_dialog(this, _("Enter a new value."), wxString::Format(_("Set R%d value"), register_index), wxString::Format("%08x", register_value));
|
||||
wxTextEntryDialog set_value_dialog(this, _("Enter a new value."), wxString::Format(_("Set R%d value"), register_index), wxString::Format("0x%08x", register_value));
|
||||
if (set_value_dialog.ShowModal() == wxID_OK)
|
||||
{
|
||||
const uint32 new_value = std::stoul(set_value_dialog.GetValue().ToStdString(), nullptr, 16);
|
||||
const uint32 value = ConvertString<uint32>(set_value_dialog.GetValue().ToStdString());
|
||||
|
||||
if (debugSession = debugger_lockDebugSession(); debugSession)
|
||||
{
|
||||
debugSession->gpr[register_index] = new_value;
|
||||
debugSession->gpr[register_index] = value;
|
||||
debugger_unlockDebugSession(debugSession);
|
||||
}
|
||||
|
||||
OnUpdateView();
|
||||
}
|
||||
return;
|
||||
@@ -376,12 +379,14 @@ void RegisterWindow::OnMouseDClickEvent(wxMouseEvent& event)
|
||||
wxTextEntryDialog set_value_dialog(this, _("Enter a new value."), wxString::Format(_("Set FP0_%d value"), register_index), wxString::Format("%lf", register_value));
|
||||
if (set_value_dialog.ShowModal() == wxID_OK)
|
||||
{
|
||||
const double new_value = std::stod(set_value_dialog.GetValue().ToStdString());
|
||||
const double value = ConvertString<double>(set_value_dialog.GetValue().ToStdString());
|
||||
|
||||
if (debugSession = debugger_lockDebugSession(); debugSession)
|
||||
{
|
||||
debugSession->fpr[register_index].fp0 = new_value;
|
||||
debugSession->fpr[register_index].fp0 = value;
|
||||
debugger_unlockDebugSession(debugSession);
|
||||
}
|
||||
|
||||
OnUpdateView();
|
||||
}
|
||||
|
||||
@@ -395,12 +400,14 @@ void RegisterWindow::OnMouseDClickEvent(wxMouseEvent& event)
|
||||
wxTextEntryDialog set_value_dialog(this, _("Enter a new value."), wxString::Format(_("Set FP1_%d value"), register_index), wxString::Format("%lf", register_value));
|
||||
if (set_value_dialog.ShowModal() == wxID_OK)
|
||||
{
|
||||
const double new_value = std::stod(set_value_dialog.GetValue().ToStdString());
|
||||
const double value = ConvertString<double>(set_value_dialog.GetValue().ToStdString());
|
||||
|
||||
if (debugSession = debugger_lockDebugSession(); debugSession)
|
||||
{
|
||||
debugSession->fpr[register_index].fp1 = new_value;
|
||||
debugSession->fpr[register_index].fp1 = value;
|
||||
debugger_unlockDebugSession(debugSession);
|
||||
}
|
||||
|
||||
OnUpdateView();
|
||||
}
|
||||
return;
|
||||
|
||||
Reference in New Issue
Block a user