diff --git a/src/duckstation-qt/debuggerwindow.cpp b/src/duckstation-qt/debuggerwindow.cpp index 1f6115bb7..329ebdda3 100644 --- a/src/duckstation-qt/debuggerwindow.cpp +++ b/src/duckstation-qt/debuggerwindow.cpp @@ -6,9 +6,12 @@ #include "qthost.h" #include "qtutils.h" -#include "common/assert.h" +#include "core/bus.h" +#include "core/cpu_code_cache.h" #include "core/cpu_core_private.h" +#include "common/assert.h" + #include #include #include @@ -568,10 +571,27 @@ void DebuggerWindow::setMemoryViewRegion(Bus::MemoryRegion region) m_active_memory_region = region; + static constexpr auto edit_ram_callback = [](size_t offset, size_t count) { + // shouldn't happen + if (offset > Bus::g_ram_size) + return; + + const u32 start_page = static_cast(offset) / HOST_PAGE_SIZE; + const u32 end_page = static_cast(offset + count - 1) / HOST_PAGE_SIZE; + for (u32 i = start_page; i <= end_page; i++) + { + if (Bus::g_ram_code_bits[i]) + CPU::CodeCache::InvalidateBlocksWithPageIndex(i); + } + }; + const PhysicalMemoryAddress start = Bus::GetMemoryRegionStart(region); const PhysicalMemoryAddress end = Bus::GetMemoryRegionEnd(region); - m_ui.memoryView->setData(start, Bus::GetMemoryRegionPointer(region), end - start, - Bus::IsMemoryRegionWritable(region)); + void* const mem_ptr = Bus::GetMemoryRegionPointer(region); + const bool mem_writable = Bus::IsMemoryRegionWritable(region); + const MemoryViewWidget::EditCallback edit_callback = + ((region == Bus::MemoryRegion::RAM) ? edit_ram_callback : nullptr); + m_ui.memoryView->setData(start, mem_ptr, end - start, mem_writable, edit_callback); #define SET_REGION_RADIO_BUTTON(name, rb_region) \ do \ diff --git a/src/duckstation-qt/memoryviewwidget.cpp b/src/duckstation-qt/memoryviewwidget.cpp index 5b4d5cbb1..90e857eed 100644 --- a/src/duckstation-qt/memoryviewwidget.cpp +++ b/src/duckstation-qt/memoryviewwidget.cpp @@ -8,7 +8,7 @@ MemoryViewWidget::MemoryViewWidget(QWidget* parent /* = nullptr */, size_t address_offset /* = 0 */, void* data_ptr /* = nullptr */, size_t data_size /* = 0 */, - bool data_editable /* = false */) + bool data_editable /* = false */, EditCallback edit_callback /* = nullptr */) : QAbstractScrollArea(parent) { m_bytes_per_line = 16; @@ -19,7 +19,7 @@ MemoryViewWidget::MemoryViewWidget(QWidget* parent /* = nullptr */, size_t addre connect(horizontalScrollBar(), &QScrollBar::valueChanged, this, &MemoryViewWidget::adjustContent); if (data_ptr) - setData(address_offset, data_ptr, data_size, data_editable); + setData(address_offset, data_ptr, data_size, data_editable, edit_callback); } MemoryViewWidget::~MemoryViewWidget() = default; @@ -46,13 +46,15 @@ void MemoryViewWidget::updateMetrics() m_char_height = fm.height(); } -void MemoryViewWidget::setData(size_t address_offset, void* data_ptr, size_t data_size, bool data_editable) +void MemoryViewWidget::setData(size_t address_offset, void* data_ptr, size_t data_size, bool data_editable, + EditCallback edit_callback) { m_data = data_ptr; m_data_size = data_size; m_data_editable = data_editable; m_address_offset = address_offset; m_selected_address = INVALID_SELECTED_ADDRESS; + m_edit_callback = edit_callback; m_last_data_start_offset = 0; m_last_data.clear(); adjustContent(); @@ -137,7 +139,15 @@ void MemoryViewWidget::keyPressEvent(QKeyEvent* event) if (m_selection_was_ascii) { expandCurrentDataToInclude(m_selected_address); - std::memcpy(static_cast(m_data) + m_selected_address, &ch, sizeof(unsigned char)); + + unsigned char* pdata = static_cast(m_data) + m_selected_address; + if (static_cast(ch) != *pdata) + { + *pdata = static_cast(ch); + if (m_edit_callback) + m_edit_callback(m_selected_address, 1); + } + m_selected_address = std::min(m_selected_address + 1, m_data_size - 1); forceRefresh(); } @@ -157,7 +167,14 @@ void MemoryViewWidget::keyPressEvent(QKeyEvent* event) expandCurrentDataToInclude(m_selected_address); unsigned char* pdata = static_cast(m_data) + m_selected_address; - *pdata = (*pdata & ~(0xf0 >> (m_editing_nibble * 4))) | (nibble << ((1 - m_editing_nibble) * 4)); + const unsigned char new_value = + (*pdata & ~(0xf0 >> (m_editing_nibble * 4))) | (nibble << ((1 - m_editing_nibble) * 4)); + if (*pdata != new_value) + { + *pdata = new_value; + if (m_edit_callback) + m_edit_callback(m_selected_address, 1); + } if (m_editing_nibble == 1) { diff --git a/src/duckstation-qt/memoryviewwidget.h b/src/duckstation-qt/memoryviewwidget.h index 2f6209bf6..313b04e7c 100644 --- a/src/duckstation-qt/memoryviewwidget.h +++ b/src/duckstation-qt/memoryviewwidget.h @@ -9,16 +9,18 @@ class MemoryViewWidget : public QAbstractScrollArea { -public: Q_OBJECT + public: + using EditCallback = void (*)(size_t offset, size_t bytes); + MemoryViewWidget(QWidget* parent = nullptr, size_t address_offset = 0, void* data_ptr = nullptr, size_t data_size = 0, - bool data_editable = false); + bool data_editable = false, EditCallback edit_callback = nullptr); ~MemoryViewWidget(); size_t addressOffset() const { return m_address_offset; } - void setData(size_t address_offset, void* data_ptr, size_t data_size, bool data_editable); + void setData(size_t address_offset, void* data_ptr, size_t data_size, bool data_editable, EditCallback edit_callback); void setHighlightRange(size_t start, size_t end); void clearHighlightRange(); void scrolltoOffset(size_t offset); @@ -71,6 +73,7 @@ private: int m_rows_visible; + EditCallback m_edit_callback = nullptr; std::vector m_last_data; size_t m_last_data_start_offset = 0; }; \ No newline at end of file