diff options
| author | booto <remornicus@gmail.com> | 2019-04-11 01:50:52 -0400 |
|---|---|---|
| committer | booto <remornicus@gmail.com> | 2019-05-02 21:14:30 -0400 |
| commit | 2ff0486335b615af5f2d90ae29f5494ee84d2c00 (patch) | |
| tree | ef8d3d0db2c52e0a40861593c9bad7404e28f76d /Source/Core/DolphinQt | |
| parent | 3b16d2261a7fe6c4e2d10bbf388ee6fabc0c0ba0 (diff) | |
Debugger/Memory: Add support for address spaces
Different address spaces can be chosen in the memory view panel.
* Effective (or virtual): Probably the view people mostly want. Address
translation goes through MMU.
* Auxiliary: ARAM address space. Does not display anything in Wii mode.
* Physical: Physical address space. Only supports mem1 and mem2 (wii
mode) so far.
Diffstat (limited to 'Source/Core/DolphinQt')
| -rw-r--r-- | Source/Core/DolphinQt/Debugger/MemoryViewWidget.cpp | 103 | ||||
| -rw-r--r-- | Source/Core/DolphinQt/Debugger/MemoryViewWidget.h | 4 | ||||
| -rw-r--r-- | Source/Core/DolphinQt/Debugger/MemoryWidget.cpp | 158 | ||||
| -rw-r--r-- | Source/Core/DolphinQt/Debugger/MemoryWidget.h | 9 |
4 files changed, 173 insertions, 101 deletions
diff --git a/Source/Core/DolphinQt/Debugger/MemoryViewWidget.cpp b/Source/Core/DolphinQt/Debugger/MemoryViewWidget.cpp index d9041aaceb..4284f60bc9 100644 --- a/Source/Core/DolphinQt/Debugger/MemoryViewWidget.cpp +++ b/Source/Core/DolphinQt/Debugger/MemoryViewWidget.cpp @@ -16,9 +16,7 @@ #include "Core/Core.h" #include "Core/PowerPC/BreakPoints.h" -#include "Core/PowerPC/MMU.h" #include "Core/PowerPC/PowerPC.h" - #include "DolphinQt/Resources.h" #include "DolphinQt/Settings.h" @@ -74,6 +72,8 @@ void MemoryViewWidget::Update() setRowHeight(0, 24); + const AddressSpace::Accessors* accessors = AddressSpace::GetAccessors(m_address_space); + // Calculate (roughly) how many rows will fit in our table int rows = std::round((height() / static_cast<float>(rowHeight(0))) - 0.25); @@ -101,7 +101,7 @@ void MemoryViewWidget::Update() if (addr == m_address) addr_item->setSelected(true); - if (Core::GetState() != Core::State::Paused || !PowerPC::HostIsRAMAddress(addr)) + if (Core::GetState() != Core::State::Paused || !accessors->IsValidAddress(addr)) { for (int c = 2; c < columnCount(); c++) { @@ -115,14 +115,16 @@ void MemoryViewWidget::Update() continue; } - auto* description_item = - new QTableWidgetItem(QString::fromStdString(PowerPC::debug_interface.GetDescription(addr))); - - description_item->setForeground(Qt::blue); - description_item->setFlags(Qt::ItemIsEnabled); + if (m_address_space == AddressSpace::Type::Effective) + { + auto* description_item = new QTableWidgetItem( + QString::fromStdString(PowerPC::debug_interface.GetDescription(addr))); - setItem(i, columnCount() - 1, description_item); + description_item->setForeground(Qt::blue); + description_item->setFlags(Qt::ItemIsEnabled); + setItem(i, columnCount() - 1, description_item); + } bool row_breakpoint = true; auto update_values = [&](auto value_to_string) { @@ -132,14 +134,18 @@ void MemoryViewWidget::Update() hex_item->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable); const u32 address = addr + c * (16 / GetColumnCount(m_type)); - if (PowerPC::memchecks.OverlapsMemcheck(address, 16 / GetColumnCount(m_type))) + if (m_address_space == AddressSpace::Type::Effective && + PowerPC::memchecks.OverlapsMemcheck(address, 16 / GetColumnCount(m_type))) + { hex_item->setBackground(Qt::red); + } else + { row_breakpoint = false; - + } setItem(i, 2 + c, hex_item); - if (PowerPC::HostIsRAMAddress(address)) + if (accessors->IsValidAddress(address)) { hex_item->setText(value_to_string(address)); hex_item->setData(Qt::UserRole, address); @@ -151,35 +157,35 @@ void MemoryViewWidget::Update() } } }; - switch (m_type) { case Type::U8: - update_values([](u32 address) { - const u8 value = PowerPC::HostRead_U8(address); + update_values([&accessors](u32 address) { + const u8 value = accessors->ReadU8(address); return QStringLiteral("%1").arg(value, 2, 16, QLatin1Char('0')); }); break; case Type::ASCII: - update_values([](u32 address) { - const char value = PowerPC::HostRead_U8(address); + update_values([&accessors](u32 address) { + const char value = accessors->ReadU8(address); return std::isprint(value) ? QString{QChar::fromLatin1(value)} : QStringLiteral("."); }); break; case Type::U16: - update_values([](u32 address) { - const u16 value = PowerPC::HostRead_U16(address); + update_values([&accessors](u32 address) { + const u16 value = accessors->ReadU16(address); return QStringLiteral("%1").arg(value, 4, 16, QLatin1Char('0')); }); break; case Type::U32: - update_values([](u32 address) { - const u32 value = PowerPC::HostRead_U32(address); + update_values([&accessors](u32 address) { + const u32 value = accessors->ReadU32(address); return QStringLiteral("%1").arg(value, 8, 16, QLatin1Char('0')); }); break; case Type::Float32: - update_values([](u32 address) { return QString::number(PowerPC::HostRead_F32(address)); }); + update_values( + [&accessors](u32 address) { return QString::number(accessors->ReadF32(address)); }); break; } @@ -202,6 +208,22 @@ void MemoryViewWidget::Update() update(); } +void MemoryViewWidget::SetAddressSpace(AddressSpace::Type address_space) +{ + if (m_address_space == address_space) + { + return; + } + + m_address_space = address_space; + Update(); +} + +AddressSpace::Type MemoryViewWidget::GetAddressSpace() const +{ + return m_address_space; +} + void MemoryViewWidget::SetType(Type type) { if (m_type == type) @@ -273,21 +295,24 @@ void MemoryViewWidget::ToggleRowBreakpoint(bool row) const u32 addr = row ? GetContextAddress() & 0xFFFFFFF0 : GetContextAddress(); const auto length = row ? 16 : (16 / GetColumnCount(m_type)); - if (!PowerPC::memchecks.OverlapsMemcheck(addr, length)) + if (m_address_space == AddressSpace::Type::Effective) { - check.start_address = addr; - check.end_address = check.start_address + length - 1; - check.is_ranged = length > 0; - check.is_break_on_read = (m_bp_type == BPType::ReadOnly || m_bp_type == BPType::ReadWrite); - check.is_break_on_write = (m_bp_type == BPType::WriteOnly || m_bp_type == BPType::ReadWrite); - check.log_on_hit = m_do_log; - check.break_on_hit = true; - - PowerPC::memchecks.Add(check); - } - else - { - PowerPC::memchecks.Remove(addr); + if (!PowerPC::memchecks.OverlapsMemcheck(addr, length)) + { + check.start_address = addr; + check.end_address = check.start_address + length - 1; + check.is_ranged = length > 0; + check.is_break_on_read = (m_bp_type == BPType::ReadOnly || m_bp_type == BPType::ReadWrite); + check.is_break_on_write = (m_bp_type == BPType::WriteOnly || m_bp_type == BPType::ReadWrite); + check.log_on_hit = m_do_log; + check.break_on_hit = true; + + PowerPC::memchecks.Add(check); + } + else + { + PowerPC::memchecks.Remove(addr); + } } emit BreakpointsChanged(); @@ -348,7 +373,8 @@ void MemoryViewWidget::OnCopyHex() const auto length = 16 / GetColumnCount(m_type); - u64 value = PowerPC::HostRead_U64(addr); + const AddressSpace::Accessors* accessors = AddressSpace::GetAccessors(m_address_space); + u64 value = accessors->ReadU64(addr); QApplication::clipboard()->setText( QStringLiteral("%1").arg(value, length * 2, 16, QLatin1Char('0')).left(length * 2)); @@ -362,8 +388,9 @@ void MemoryViewWidget::OnContextMenu() auto* copy_hex = menu->addAction(tr("Copy Hex"), this, &MemoryViewWidget::OnCopyHex); + const AddressSpace::Accessors* accessors = AddressSpace::GetAccessors(m_address_space); copy_hex->setEnabled(Core::GetState() != Core::State::Uninitialized && - PowerPC::HostIsRAMAddress(GetContextAddress())); + accessors->IsValidAddress(GetContextAddress())); menu->addSeparator(); diff --git a/Source/Core/DolphinQt/Debugger/MemoryViewWidget.h b/Source/Core/DolphinQt/Debugger/MemoryViewWidget.h index 4b2b6958ea..5537139f37 100644 --- a/Source/Core/DolphinQt/Debugger/MemoryViewWidget.h +++ b/Source/Core/DolphinQt/Debugger/MemoryViewWidget.h @@ -7,6 +7,7 @@ #include <QTableWidget> #include "Common/CommonTypes.h" +#include "Core/HW/AddressSpace.h" class MemoryViewWidget : public QTableWidget { @@ -34,6 +35,8 @@ public: void ToggleBreakpoint(); void ToggleRowBreakpoint(bool row); + void SetAddressSpace(AddressSpace::Type address_space); + AddressSpace::Type GetAddressSpace() const; void SetType(Type type); void SetBPType(BPType type); void SetAddress(u32 address); @@ -56,6 +59,7 @@ private: void OnCopyAddress(); void OnCopyHex(); + AddressSpace::Type m_address_space = AddressSpace::Type::Effective; Type m_type = Type::U8; BPType m_bp_type = BPType::ReadWrite; bool m_do_log = true; diff --git a/Source/Core/DolphinQt/Debugger/MemoryWidget.cpp b/Source/Core/DolphinQt/Debugger/MemoryWidget.cpp index ec3f3ebf57..5030a8f98e 100644 --- a/Source/Core/DolphinQt/Debugger/MemoryWidget.cpp +++ b/Source/Core/DolphinQt/Debugger/MemoryWidget.cpp @@ -4,6 +4,7 @@ #include "DolphinQt/Debugger/MemoryWidget.h" +#include <optional> #include <string> #include <QCheckBox> @@ -22,9 +23,6 @@ #include "Common/File.h" #include "Common/FileUtil.h" #include "Core/ConfigManager.h" -#include "Core/HW/DSP.h" -#include "Core/HW/Memmap.h" -#include "Core/PowerPC/PowerPC.h" #include "DolphinQt/Debugger/MemoryViewWidget.h" #include "DolphinQt/QtUtils/ModalMessageBox.h" #include "DolphinQt/Settings.h" @@ -60,6 +58,7 @@ MemoryWidget::MemoryWidget(QWidget* parent) : QDockWidget(parent) ConnectWidgets(); Update(); + OnAddressSpaceChanged(); OnTypeChanged(); } @@ -94,6 +93,7 @@ void MemoryWidget::CreateWidgets() // Dump m_dump_mram = new QPushButton(tr("Dump &MRAM")); m_dump_exram = new QPushButton(tr("Dump &ExRAM")); + m_dump_aram = new QPushButton(tr("Dump &ARAM")); m_dump_fake_vmem = new QPushButton(tr("Dump &FakeVMEM")); // Search Options @@ -112,6 +112,25 @@ void MemoryWidget::CreateWidgets() search_layout->addWidget(m_result_label); search_layout->setSpacing(1); + // Address Space + auto* address_space_group = new QGroupBox(tr("Address Space")); + auto* address_space_layout = new QVBoxLayout; + address_space_group->setLayout(address_space_layout); + + // i18n: "Effective" addresses are the addresses used directly by the CPU and may be subject to + // translation via the MMU to physical addresses. + m_address_space_effective = new QRadioButton(tr("Effective")); + // i18n: The "Auxiliary" address space is the address space of ARAM (Auxiliary RAM). + m_address_space_auxiliary = new QRadioButton(tr("Auxiliary")); + // i18n: The "Physical" address space is the address space that reflects how devices (e.g. RAM) is + // physically wired up. + m_address_space_physical = new QRadioButton(tr("Physical")); + + address_space_layout->addWidget(m_address_space_effective); + address_space_layout->addWidget(m_address_space_auxiliary); + address_space_layout->addWidget(m_address_space_physical); + address_space_layout->setSpacing(1); + // Data Type auto* datatype_group = new QGroupBox(tr("Data Type")); auto* datatype_layout = new QVBoxLayout; @@ -170,8 +189,10 @@ void MemoryWidget::CreateWidgets() sidebar_layout->addItem(new QSpacerItem(1, 32)); sidebar_layout->addWidget(m_dump_mram); sidebar_layout->addWidget(m_dump_exram); + sidebar_layout->addWidget(m_dump_aram); sidebar_layout->addWidget(m_dump_fake_vmem); sidebar_layout->addWidget(search_group); + sidebar_layout->addWidget(address_space_group); sidebar_layout->addWidget(datatype_group); sidebar_layout->addWidget(bp_group); sidebar_layout->addItem(new QSpacerItem(0, 0, QSizePolicy::Expanding, QSizePolicy::Expanding)); @@ -208,11 +229,18 @@ void MemoryWidget::ConnectWidgets() connect(m_dump_mram, &QPushButton::pressed, this, &MemoryWidget::OnDumpMRAM); connect(m_dump_exram, &QPushButton::pressed, this, &MemoryWidget::OnDumpExRAM); + connect(m_dump_aram, &QPushButton::pressed, this, &MemoryWidget::OnDumpARAM); connect(m_dump_fake_vmem, &QPushButton::pressed, this, &MemoryWidget::OnDumpFakeVMEM); connect(m_find_next, &QPushButton::pressed, this, &MemoryWidget::OnFindNextValue); connect(m_find_previous, &QPushButton::pressed, this, &MemoryWidget::OnFindPreviousValue); + for (auto* radio : + {m_address_space_effective, m_address_space_auxiliary, m_address_space_physical}) + { + connect(radio, &QRadioButton::toggled, this, &MemoryWidget::OnAddressSpaceChanged); + } + for (auto* radio : {m_type_u8, m_type_u16, m_type_u32, m_type_ascii, m_type_float}) connect(radio, &QRadioButton::toggled, this, &MemoryWidget::OnTypeChanged); @@ -247,6 +275,17 @@ void MemoryWidget::LoadSettings() m_find_ascii->setChecked(search_ascii); m_find_hex->setChecked(search_hex); + const bool address_space_effective = + settings.value(QStringLiteral("memorywidget/addrspace_effective"), true).toBool(); + const bool address_space_auxiliary = + settings.value(QStringLiteral("memorywidget/addrspace_auxiliary"), false).toBool(); + const bool address_space_physical = + settings.value(QStringLiteral("memorywidget/addrspace_physical"), false).toBool(); + + m_address_space_effective->setChecked(address_space_effective); + m_address_space_auxiliary->setChecked(address_space_auxiliary); + m_address_space_physical->setChecked(address_space_physical); + const bool type_u8 = settings.value(QStringLiteral("memorywidget/typeu8"), true).toBool(); const bool type_u16 = settings.value(QStringLiteral("memorywidget/typeu16"), false).toBool(); const bool type_u32 = settings.value(QStringLiteral("memorywidget/typeu32"), false).toBool(); @@ -284,6 +323,13 @@ void MemoryWidget::SaveSettings() settings.setValue(QStringLiteral("memorywidget/searchascii"), m_find_ascii->isChecked()); settings.setValue(QStringLiteral("memorywidget/searchhex"), m_find_hex->isChecked()); + settings.setValue(QStringLiteral("memorywidget/addrspace_effective"), + m_address_space_effective->isChecked()); + settings.setValue(QStringLiteral("memorywidget/addrspace_auxiliary"), + m_address_space_auxiliary->isChecked()); + settings.setValue(QStringLiteral("memorywidget/addrspace_physical"), + m_address_space_physical->isChecked()); + settings.setValue(QStringLiteral("memorywidget/typeu8"), m_type_u8->isChecked()); settings.setValue(QStringLiteral("memorywidget/typeu16"), m_type_u16->isChecked()); settings.setValue(QStringLiteral("memorywidget/typeu32"), m_type_u32->isChecked()); @@ -296,6 +342,22 @@ void MemoryWidget::SaveSettings() settings.setValue(QStringLiteral("memorywidget/bplog"), m_bp_log_check->isChecked()); } +void MemoryWidget::OnAddressSpaceChanged() +{ + AddressSpace::Type space; + + if (m_address_space_effective->isChecked()) + space = AddressSpace::Type::Effective; + else if (m_address_space_auxiliary->isChecked()) + space = AddressSpace::Type::Auxiliary; + else + space = AddressSpace::Type::Physical; + + m_memory_view->SetAddressSpace(space); + + SaveSettings(); +} + void MemoryWidget::OnTypeChanged() { MemoryViewWidget::Type type; @@ -411,12 +473,14 @@ void MemoryWidget::OnSetValue() return; } + AddressSpace::Accessors* accessors = AddressSpace::GetAccessors(m_memory_view->GetAddressSpace()); + if (m_find_ascii->isChecked()) { const QByteArray bytes = m_data_edit->text().toUtf8(); for (char c : bytes) - PowerPC::HostWrite_U8(static_cast<u8>(c), addr++); + accessors->WriteU8(static_cast<u8>(c), addr++); } else { @@ -431,18 +495,18 @@ void MemoryWidget::OnSetValue() if (value == static_cast<u8>(value)) { - PowerPC::HostWrite_U8(static_cast<u8>(value), addr); + accessors->WriteU8(static_cast<u8>(value), addr); } else if (value == static_cast<u16>(value)) { - PowerPC::HostWrite_U16(static_cast<u16>(value), addr); + accessors->WriteU16(static_cast<u16>(value), addr); } else if (value == static_cast<u32>(value)) { - PowerPC::HostWrite_U32(static_cast<u32>(value), addr); + accessors->WriteU32(static_cast<u32>(value), addr); } else - PowerPC::HostWrite_U64(value, addr); + accessors->WriteU64(value, addr); } Update(); @@ -473,24 +537,30 @@ static void DumpArray(const std::string& filename, const u8* data, size_t length void MemoryWidget::OnDumpMRAM() { - DumpArray(File::GetUserPath(F_RAMDUMP_IDX), Memory::m_pRAM, Memory::REALRAM_SIZE); + AddressSpace::Accessors* accessors = AddressSpace::GetAccessors(AddressSpace::Type::Mem1); + DumpArray(File::GetUserPath(F_MEM1DUMP_IDX), accessors->begin(), + std::distance(accessors->begin(), accessors->end())); } void MemoryWidget::OnDumpExRAM() { - if (SConfig::GetInstance().bWii) - { - DumpArray(File::GetUserPath(F_ARAMDUMP_IDX), Memory::m_pEXRAM, Memory::EXRAM_SIZE); - } - else - { - DumpArray(File::GetUserPath(F_ARAMDUMP_IDX), DSP::GetARAMPtr(), DSP::ARAM_SIZE); - } + AddressSpace::Accessors* accessors = AddressSpace::GetAccessors(AddressSpace::Type::Mem2); + DumpArray(File::GetUserPath(F_MEM2DUMP_IDX), accessors->begin(), + std::distance(accessors->begin(), accessors->end())); +} + +void MemoryWidget::OnDumpARAM() +{ + AddressSpace::Accessors* accessors = AddressSpace::GetAccessors(AddressSpace::Type::Auxiliary); + DumpArray(File::GetUserPath(F_ARAMDUMP_IDX), accessors->begin(), + std::distance(accessors->begin(), accessors->end())); } void MemoryWidget::OnDumpFakeVMEM() { - DumpArray(File::GetUserPath(F_FAKEVMEMDUMP_IDX), Memory::m_pFakeVMEM, Memory::FAKEVMEM_SIZE); + AddressSpace::Accessors* accessors = AddressSpace::GetAccessors(AddressSpace::Type::Fake); + DumpArray(File::GetUserPath(F_FAKEVMEMDUMP_IDX), accessors->begin(), + std::distance(accessors->begin(), accessors->end())); } std::vector<u8> MemoryWidget::GetValueData() const @@ -537,62 +607,24 @@ void MemoryWidget::FindValue(bool next) m_result_label->setText(tr("No Value Given")); return; } - - const u8* ram_ptr = nullptr; - std::size_t ram_size = 0; - u32 base_address = 0; - - if (m_type_u16->isChecked()) - { - ram_ptr = DSP::GetARAMPtr(); - ram_size = DSP::ARAM_SIZE; - base_address = 0x0c005000; - } - else if (Memory::m_pRAM) - { - ram_ptr = Memory::m_pRAM; - ram_size = Memory::REALRAM_SIZE; - base_address = 0x80000000; - } - else - { - m_result_label->setText(tr("Memory Not Ready")); - return; - } - u32 addr = 0; if (!m_search_address->text().isEmpty()) - addr = m_search_address->text().toUInt(nullptr, 16) + 1; - - if (addr >= base_address) - addr -= base_address; - - if (addr >= ram_size - search_for.size()) { - m_result_label->setText(tr("Address Out of Range")); - return; + // skip the quoted address so we don't potentially refind the last result + addr = m_search_address->text().toUInt(nullptr, 16) + (next ? 1 : -1); } - const u8* ptr; - const u8* end; + AddressSpace::Accessors* accessors = AddressSpace::GetAccessors(m_memory_view->GetAddressSpace()); - if (next) - { - end = &ram_ptr[ram_size - search_for.size() + 1]; - ptr = std::search(&ram_ptr[addr], end, search_for.begin(), search_for.end()); - } - else - { - end = &ram_ptr[addr + search_for.size() - 1]; - ptr = std::find_end(ram_ptr, end, search_for.begin(), search_for.end()); - } + auto found_addr = + accessors->Search(addr, search_for.data(), static_cast<u32>(search_for.size()), next); - if (ptr != end) + if (found_addr.has_value()) { m_result_label->setText(tr("Match Found")); - u32 offset = static_cast<u32>(ptr - ram_ptr) + base_address; + u32 offset = *found_addr; m_search_address->setText(QStringLiteral("%1").arg(offset, 8, 16, QLatin1Char('0'))); diff --git a/Source/Core/DolphinQt/Debugger/MemoryWidget.h b/Source/Core/DolphinQt/Debugger/MemoryWidget.h index 5d4cb0b603..77c10b88e7 100644 --- a/Source/Core/DolphinQt/Debugger/MemoryWidget.h +++ b/Source/Core/DolphinQt/Debugger/MemoryWidget.h @@ -9,6 +9,7 @@ #include <QDockWidget> #include "Common/CommonTypes.h" +#include "Core/HW/AddressSpace.h" class MemoryViewWidget; class QCheckBox; @@ -38,6 +39,7 @@ private: void LoadSettings(); void SaveSettings(); + void OnAddressSpaceChanged(); void OnTypeChanged(); void OnBPLogChanged(); void OnBPTypeChanged(); @@ -51,6 +53,7 @@ private: void OnDumpMRAM(); void OnDumpExRAM(); + void OnDumpARAM(); void OnDumpFakeVMEM(); std::vector<u8> GetValueData() const; @@ -66,6 +69,7 @@ private: QPushButton* m_set_value; QPushButton* m_dump_mram; QPushButton* m_dump_exram; + QPushButton* m_dump_aram; QPushButton* m_dump_fake_vmem; // Search @@ -75,6 +79,11 @@ private: QRadioButton* m_find_hex; QLabel* m_result_label; + // Address Spaces + QRadioButton* m_address_space_physical; + QRadioButton* m_address_space_effective; + QRadioButton* m_address_space_auxiliary; + // Datatypes QRadioButton* m_type_u8; QRadioButton* m_type_u16; |
