From 2005c89baac943abba6476557b47c77dc87c00ad Mon Sep 17 00:00:00 2001 From: Eladash Date: Thu, 14 Jan 2021 19:54:27 +0200 Subject: [PATCH] memory viewer: Implement RSX mode * Set the ground for RSX modes of register editor and insttruction editor, do not use shared ptrs directly. * Make register editor and instruction editor modeless to allow to copypaste values from thread context etc in the background. --- rpcs3/Emu/RSX/RSXThread.cpp | 7 +- rpcs3/Emu/RSX/RSXThread.h | 2 +- rpcs3/rpcs3qt/debugger_frame.cpp | 189 ++++++++++++++------ rpcs3/rpcs3qt/debugger_frame.h | 8 +- rpcs3/rpcs3qt/instruction_editor_dialog.cpp | 19 +- rpcs3/rpcs3qt/instruction_editor_dialog.h | 6 +- rpcs3/rpcs3qt/kernel_explorer.cpp | 8 +- rpcs3/rpcs3qt/kernel_explorer.h | 4 +- rpcs3/rpcs3qt/main_window.cpp | 6 +- rpcs3/rpcs3qt/memory_viewer_panel.cpp | 133 +++++++++++--- rpcs3/rpcs3qt/memory_viewer_panel.h | 15 +- rpcs3/rpcs3qt/register_editor_dialog.cpp | 39 ++-- rpcs3/rpcs3qt/register_editor_dialog.h | 6 +- 13 files changed, 320 insertions(+), 122 deletions(-) diff --git a/rpcs3/Emu/RSX/RSXThread.cpp b/rpcs3/Emu/RSX/RSXThread.cpp index 8d4b855c9a..d2cc3240c3 100644 --- a/rpcs3/Emu/RSX/RSXThread.cpp +++ b/rpcs3/Emu/RSX/RSXThread.cpp @@ -43,7 +43,7 @@ namespace rsx { std::function g_access_violation_handler; - u32 get_address(u32 offset, u32 location, u32 line, u32 col, const char* file, const char* func) + u32 get_address(u32 offset, u32 location, bool allow_failure, u32 line, u32 col, const char* file, const char* func) { const auto render = get_current_renderer(); std::string_view msg; @@ -150,6 +150,11 @@ namespace rsx } } + if (allow_failure) + { + return 0; + } + fmt::throw_exception("rsx::get_address(offset=0x%x, location=0x%x): %s%s", offset, location, msg, src_loc{line, col, file, func}); } diff --git a/rpcs3/Emu/RSX/RSXThread.h b/rpcs3/Emu/RSX/RSXThread.h index 6600db18d0..69f7bd61a8 100644 --- a/rpcs3/Emu/RSX/RSXThread.h +++ b/rpcs3/Emu/RSX/RSXThread.h @@ -172,7 +172,7 @@ namespace rsx u32 get_vertex_type_size_on_host(vertex_base_type type, u32 size); - u32 get_address(u32 offset, u32 location, + u32 get_address(u32 offset, u32 location, bool allow_failure = false, u32 line = __builtin_LINE(), u32 col = __builtin_COLUMN(), const char* file = __builtin_FILE(), diff --git a/rpcs3/rpcs3qt/debugger_frame.cpp b/rpcs3/rpcs3qt/debugger_frame.cpp index 512505d3b5..ba4984b22b 100644 --- a/rpcs3/rpcs3qt/debugger_frame.cpp +++ b/rpcs3/rpcs3qt/debugger_frame.cpp @@ -313,10 +313,14 @@ void debugger_frame::keyPressEvent(QKeyEvent* event) { case Qt::Key_E: { - if (m_cpu) + if (cpu->id_type() == 1 || cpu->id_type() == 2) { - instruction_editor_dialog* dlg = new instruction_editor_dialog(this, pc, m_cpu, m_disasm.get()); - dlg->show(); + if (!m_inst_editor) + { + m_inst_editor = new instruction_editor_dialog(this, pc, m_disasm.get(), make_check_cpu(cpu)); + connect(m_inst_editor, &QDialog::finished, this, [this]() { m_inst_editor = nullptr; }); + m_inst_editor->show(); + } } return; } @@ -332,10 +336,14 @@ void debugger_frame::keyPressEvent(QKeyEvent* event) } case Qt::Key_R: { - if (m_cpu) + if (cpu->id_type() == 1 || cpu->id_type() == 2) { - register_editor_dialog* dlg = new register_editor_dialog(this, m_cpu, m_disasm.get()); - dlg->show(); + if (!m_reg_editor) + { + m_reg_editor = new register_editor_dialog(this, m_disasm.get(), make_check_cpu(cpu)); + connect(m_reg_editor, &QDialog::finished, this, [this]() { m_reg_editor = nullptr; }); + m_reg_editor->show(); + } } return; } @@ -386,7 +394,7 @@ void debugger_frame::keyPressEvent(QKeyEvent* event) case Qt::Key_M: { // Memory viewer - if (m_cpu) idm::make(this, pc, m_cpu); + idm::make(this, pc, make_check_cpu(cpu)); return; } case Qt::Key_F10: @@ -417,19 +425,63 @@ cpu_thread* debugger_frame::get_cpu() // m_rsx is raw pointer, when emulation is stopped it won't be cleared // Therefore need to do invalidation checks manually + if (m_emu_state == system_state::stopped) + { + m_rsx = nullptr; + return m_rsx; + } + if (g_fxo->get() != m_rsx) { m_rsx = nullptr; + return m_rsx; } if (m_rsx && !m_rsx->ctrl) { m_rsx = nullptr; + return m_rsx; } return m_rsx; } +std::function debugger_frame::make_check_cpu(cpu_thread* cpu) +{ + const u32 id = cpu ? cpu->id : UINT32_MAX; + const u32 type = id >> 24; + + std::shared_ptr shared = type == 1 ? static_cast>(idm::get>(id)) : + type == 2 ? idm::get>(id) : nullptr; + + if (shared.get() != cpu) + { + shared.reset(); + } + + return [&rsx = m_rsx, cpu, type, shared = std::move(shared)]() -> cpu_thread* + { + if (type == 1 || type == 2) + { + // SPU and PPU + if (!shared || (shared->state & cpu_flag::exit && shared->state & cpu_flag::wait)) + { + return nullptr; + } + + return shared.get(); + } + + // RSX + if (rsx == cpu) + { + return cpu; + } + + return nullptr; + }; +} + void debugger_frame::UpdateUI() { UpdateUnitList(); @@ -476,8 +528,9 @@ void debugger_frame::UpdateUI() } } -Q_DECLARE_METATYPE(std::weak_ptr); -Q_DECLARE_METATYPE(::rsx::thread*); +using data_type = std::pair; + +Q_DECLARE_METATYPE(data_type); void debugger_frame::UpdateUnitList() { @@ -500,15 +553,20 @@ void debugger_frame::UpdateUnitList() //const int old_size = m_choice_units->count(); QVariant old_cpu = m_choice_units->currentData(); + bool reselected = false; + const auto on_select = [&](u32 id, cpu_thread& cpu) { if (emu_state == system_state::stopped) return; - QVariant var_cpu = QVariant::fromValue>( - id >> 24 == 1 ? static_cast>(idm::get_unlocked>(id)) : idm::get_unlocked>(id)); + QVariant var_cpu = QVariant::fromValue>(std::make_pair(&cpu, id)); + m_choice_units->addItem(qstr(id >> 24 == 0x55 ? "RSX[0x55555555]" : cpu.get_name()), var_cpu); - m_choice_units->addItem(qstr(cpu.get_name()), var_cpu); - if (old_cpu == var_cpu) m_choice_units->setCurrentIndex(m_choice_units->count() - 1); + if (!reselected && old_cpu == var_cpu) + { + m_choice_units->setCurrentIndex(m_choice_units->count() - 1); + reselected = true; + } }; { @@ -522,12 +580,17 @@ void debugger_frame::UpdateUnitList() if (auto render = g_fxo->get(); emu_state != system_state::stopped && render && render->ctrl) { - QVariant var_cpu = QVariant::fromValue(render); - m_choice_units->addItem("RSX[0x55555555]", var_cpu); - if (old_cpu == var_cpu) m_choice_units->setCurrentIndex(m_choice_units->count() - 1); + on_select(render->id, *render); } } + // Close dialogs which are tied to the specific thread selected + if (!reselected) + { + if (m_reg_editor) m_reg_editor->close(); + if (m_inst_editor) m_inst_editor->close(); + } + OnSelectUnit(); m_choice_units->update(); @@ -535,65 +598,83 @@ void debugger_frame::UpdateUnitList() void debugger_frame::OnSelectUnit() { - if (m_choice_units->count() < 1) - { - m_debugger_list->UpdateCPUData(nullptr, nullptr); - m_breakpoint_list->UpdateCPUData(nullptr, nullptr); - m_disasm.reset(); - m_cpu.reset(); - return; - } - - const auto weak = m_choice_units->currentData().value>(); - const auto render = m_choice_units->currentData().value(); + auto [selected, cpu_id] = m_choice_units->currentData().value>(); if (m_emu_state != system_state::stopped) { - if (!render && !weak.owner_before(m_cpu) && !m_cpu.owner_before(weak)) + if (selected && m_cpu.get() == selected) { // They match, nothing to do. return; } - if (render && render == get_cpu()) + if (selected && m_rsx == selected) { return; } + + if (!selected && !m_rsx && !m_cpu) + { + return; + } + } + else + { + selected = nullptr; } m_disasm.reset(); m_cpu.reset(); m_rsx = nullptr; - if (!weak.expired()) + if (selected) { - if (const auto cpu0 = weak.lock()) + switch (cpu_id >> 24) { - if (cpu0->id_type() == 1) - { - if (cpu0.get() == idm::check>(cpu0->id)) - { - m_cpu = cpu0; - m_disasm = std::make_shared(cpu_disasm_mode::interpreter, vm::g_sudo_addr); - } - } - else if (cpu0->id_type() == 2) - { - if (cpu0.get() == idm::check>(cpu0->id)) - { - m_cpu = cpu0; - m_disasm = std::make_shared(cpu_disasm_mode::interpreter, static_cast(cpu0.get())->ls); - } - } - } - } - else - { - m_rsx = render; + case 1: + { + m_cpu = idm::get>(cpu_id); - if (get_cpu()) + if (selected == m_cpu.get()) + { + m_disasm = std::make_shared(cpu_disasm_mode::interpreter, vm::g_sudo_addr); + } + else + { + m_cpu.reset(); + selected = nullptr; + } + + break; + } + case 2: { - m_disasm = std::make_shared(cpu_disasm_mode::interpreter, vm::g_sudo_addr, m_rsx); + m_cpu = idm::get>(cpu_id); + + if (selected == m_cpu.get()) + { + m_disasm = std::make_shared(cpu_disasm_mode::interpreter, static_cast(m_cpu.get())->ls); + } + else + { + m_cpu.reset(); + selected = nullptr; + } + + break; + } + case 0x55: + { + m_rsx = static_cast(selected); + + if (get_cpu()) + { + m_disasm = std::make_shared(cpu_disasm_mode::interpreter, vm::g_sudo_addr, m_rsx); + } + + break; + } + default: break; } } diff --git a/rpcs3/rpcs3qt/debugger_frame.h b/rpcs3/rpcs3qt/debugger_frame.h index 541c7fbccc..d6faa0b8e9 100644 --- a/rpcs3/rpcs3qt/debugger_frame.h +++ b/rpcs3/rpcs3qt/debugger_frame.h @@ -27,6 +27,9 @@ namespace rsx enum class system_state : u32; +class instruction_editor_dialog; +class register_editor_dialog; + class debugger_frame : public custom_dock_widget { Q_OBJECT @@ -62,12 +65,15 @@ class debugger_frame : public custom_dock_widget breakpoint_list* m_breakpoint_list; breakpoint_handler* m_breakpoint_handler; - call_stack_list* m_call_stack_list; + instruction_editor_dialog* m_inst_editor = nullptr; + register_editor_dialog* m_reg_editor = nullptr; std::shared_ptr xgui_settings; cpu_thread* get_cpu(); + std::function make_check_cpu(cpu_thread* cpu); + public: explicit debugger_frame(std::shared_ptr settings, QWidget *parent = 0); diff --git a/rpcs3/rpcs3qt/instruction_editor_dialog.cpp b/rpcs3/rpcs3qt/instruction_editor_dialog.cpp index 284793aae7..23906934b5 100644 --- a/rpcs3/rpcs3qt/instruction_editor_dialog.cpp +++ b/rpcs3/rpcs3qt/instruction_editor_dialog.cpp @@ -13,17 +13,19 @@ constexpr auto qstr = QString::fromStdString; extern bool ppu_patch(u32 addr, u32 value); -instruction_editor_dialog::instruction_editor_dialog(QWidget *parent, u32 _pc, const std::shared_ptr& _cpu, CPUDisAsm* _disasm) +instruction_editor_dialog::instruction_editor_dialog(QWidget *parent, u32 _pc, CPUDisAsm* _disasm, std::function func) : QDialog(parent) , m_pc(_pc) , m_disasm(_disasm) - , m_cpu(_cpu) + , m_get_cpu(std::move(func)) { setWindowTitle(tr("Edit instruction")); setAttribute(Qt::WA_DeleteOnClose); setMinimumSize(300, sizeHint().height()); - m_cpu_offset = m_cpu->id_type() == 2 ? static_cast(*m_cpu).ls : vm::g_sudo_addr; + const auto cpu = m_get_cpu(); + + m_cpu_offset = cpu && cpu->id_type() == 2 ? static_cast(*cpu).ls : vm::g_sudo_addr; QString instruction = qstr(fmt::format("%08x", *reinterpret_cast*>(m_cpu_offset + m_pc))); QVBoxLayout* vbox_panel(new QVBoxLayout()); @@ -68,11 +70,18 @@ instruction_editor_dialog::instruction_editor_dialog(QWidget *parent, u32 _pc, c vbox_panel->addSpacing(10); vbox_panel->addLayout(hbox_b_panel); setLayout(vbox_panel); - setModal(true); // Events connect(button_ok, &QAbstractButton::clicked, [=, this]() { + const auto cpu = m_get_cpu(); + + if (!cpu) + { + close(); + return; + } + bool ok; ulong opcode = m_instr->text().toULong(&ok, 16); if (!ok || opcode > UINT32_MAX) @@ -80,7 +89,7 @@ instruction_editor_dialog::instruction_editor_dialog(QWidget *parent, u32 _pc, c QMessageBox::critical(this, tr("Error"), tr("Failed to parse PPU instruction.")); return; } - else if (m_cpu->id_type() == 1) + else if (cpu->id_type() == 1) { if (!ppu_patch(m_pc, static_cast(opcode))) { diff --git a/rpcs3/rpcs3qt/instruction_editor_dialog.h b/rpcs3/rpcs3qt/instruction_editor_dialog.h index 044786407e..cb7b2ac327 100644 --- a/rpcs3/rpcs3qt/instruction_editor_dialog.h +++ b/rpcs3/rpcs3qt/instruction_editor_dialog.h @@ -22,10 +22,10 @@ private: QLineEdit* m_instr; QLabel* m_preview; -public: - std::shared_ptr m_cpu; + const std::function m_get_cpu; - instruction_editor_dialog(QWidget *parent, u32 _pc, const std::shared_ptr& _cpu, CPUDisAsm* _disasm); +public: + instruction_editor_dialog(QWidget *parent, u32 _pc, CPUDisAsm* _disasm, std::function func); void updatePreview(); }; diff --git a/rpcs3/rpcs3qt/kernel_explorer.cpp b/rpcs3/rpcs3qt/kernel_explorer.cpp index 0d8d17c457..365036a07a 100644 --- a/rpcs3/rpcs3qt/kernel_explorer.cpp +++ b/rpcs3/rpcs3qt/kernel_explorer.cpp @@ -149,9 +149,8 @@ static QTreeWidgetItem* add_solid_node(QTreeWidget* tree, QTreeWidgetItem *paren return node; } -kernel_explorer::kernel_explorer(QWidget* parent, std::function on_destroy) +kernel_explorer::kernel_explorer(QWidget* parent) : QDialog(parent) - , m_on_destroy(on_destroy) { setWindowTitle(tr("Kernel Explorer")); setObjectName("kernel_explorer"); @@ -182,11 +181,6 @@ kernel_explorer::kernel_explorer(QWidget* parent, std::function on_destr Update(); } -kernel_explorer::~kernel_explorer() -{ - m_on_destroy(); -} - void kernel_explorer::Update() { const auto dct = g_fxo->get(); diff --git a/rpcs3/rpcs3qt/kernel_explorer.h b/rpcs3/rpcs3qt/kernel_explorer.h index bca13c165e..7da464aef0 100644 --- a/rpcs3/rpcs3qt/kernel_explorer.h +++ b/rpcs3/rpcs3qt/kernel_explorer.h @@ -26,12 +26,10 @@ class kernel_explorer : public QDialog }; public: - kernel_explorer(QWidget* parent, std::function on_destroy); - ~kernel_explorer(); + kernel_explorer(QWidget* parent); private: QTreeWidget* m_tree; - std::function m_on_destroy; private Q_SLOTS: void Update(); diff --git a/rpcs3/rpcs3qt/main_window.cpp b/rpcs3/rpcs3qt/main_window.cpp index a1d0a11a27..dde52db6a7 100644 --- a/rpcs3/rpcs3qt/main_window.cpp +++ b/rpcs3/rpcs3qt/main_window.cpp @@ -1827,10 +1827,8 @@ void main_window::CreateConnects() { if (!m_kernel_explorer) { - m_kernel_explorer = new kernel_explorer(this, [this]() - { - m_kernel_explorer = nullptr; - }); + m_kernel_explorer = new kernel_explorer(this); + connect(m_kernel_explorer, &QDialog::finished, this, [this]() { m_kernel_explorer = nullptr; }); } m_kernel_explorer->show(); diff --git a/rpcs3/rpcs3qt/memory_viewer_panel.cpp b/rpcs3/rpcs3qt/memory_viewer_panel.cpp index aa4d8b07c5..76a2d54045 100644 --- a/rpcs3/rpcs3qt/memory_viewer_panel.cpp +++ b/rpcs3/rpcs3qt/memory_viewer_panel.cpp @@ -5,6 +5,8 @@ #include "memory_viewer_panel.h" #include "Emu/Cell/SPUThread.h" +#include "Emu/RSX/RSXThread.h" +#include "Emu/RSX/rsx_utils.h" #include "Emu/IdManager.h" #include #include @@ -20,14 +22,35 @@ constexpr auto qstr = QString::fromStdString; -memory_viewer_panel::memory_viewer_panel(QWidget* parent, u32 addr, const std::shared_ptr& cpu) +memory_viewer_panel::memory_viewer_panel(QWidget* parent, u32 addr, std::function func) : QDialog(parent) , m_addr(addr) - , m_type(!cpu || cpu->id_type() == 1 ? thread_type::ppu : thread_type::spu) - , m_spu_shm(m_type == thread_type::spu ? static_cast(cpu.get())->shm : nullptr) + , m_get_cpu(std::move(func)) + , m_type([&]() + { + const auto cpu = m_get_cpu(); + + if (!cpu) return thread_type::none; + if (cpu->id_type() == 1) return thread_type::ppu; + if (cpu->id_type() == 0x55) return thread_type::rsx; + if (cpu->id_type() == 2) return thread_type::spu; + + fmt::throw_exception("Unknown CPU type (0x%x)", cpu->id_type()); + }()) + , m_rsx(m_type == thread_type::rsx ? static_cast(m_get_cpu()) : nullptr) + , m_spu_shm([&]() + { + const auto cpu = m_get_cpu(); + return cpu && m_type == thread_type::spu ? static_cast(cpu)->shm : nullptr; + }()) , m_addr_mask(m_type == thread_type::spu ? SPU_LS_SIZE - 1 : ~0) { - setWindowTitle(m_type != thread_type::spu ? tr("Memory Viewer") : tr("Memory Viewer Of %0").arg(qstr(cpu->get_name()))); + const auto cpu = m_get_cpu(); + + setWindowTitle( + cpu && m_type == thread_type::spu ? tr("Memory Viewer Of %0").arg(qstr(cpu->get_name())) : + cpu && m_type == thread_type::rsx ? tr("Memory Viewer Of RSX[0x55555555]") : + tr("Memory Viewer")); setObjectName("memory_viewer"); m_colcount = 4; @@ -361,6 +384,83 @@ std::string memory_viewer_panel::getHeaderAtAddr(u32 addr) return {}; } +void* memory_viewer_panel::to_ptr(u32 addr, u32 size) +{ + if (m_type >= thread_type::spu && !m_get_cpu()) + { + return nullptr; + } + + if (!size) + { + return nullptr; + } + + switch (m_type) + { + case thread_type::none: + case thread_type::ppu: + { + if (vm::check_addr(addr, 0, size)) + { + return vm::get_super_ptr(addr); + } + + break; + } + case thread_type::spu: + { + if (size <= SPU_LS_SIZE && SPU_LS_SIZE - size >= (addr % SPU_LS_SIZE)) + { + return m_spu_shm->map_self() + (addr % SPU_LS_SIZE); + } + + break; + } + case thread_type::rsx: + { + u32 final_addr = 0; + + if (size > 0x2000'0000 || rsx::constants::local_mem_base + 0x1000'0000 - size < addr) + { + break; + } + + for (u32 i = addr; i >> 20 <= (addr + size - 1) >> 20; i += 0x100000) + { + const u32 temp = rsx::get_address(i, i < rsx::constants::local_mem_base ? CELL_GCM_LOCATION_MAIN : CELL_GCM_LOCATION_LOCAL, true); + + if (!temp) + { + // Failure + final_addr = 0; + break; + } + else if (!final_addr) + { + // First time, save starting address for later checks + final_addr = temp; + } + else if (final_addr != temp - (i - addr)) + { + // TODO: Non-contiguous memory + final_addr = 0; + break; + } + } + + if (vm::check_addr(final_addr, 0, size)) + { + return vm::get_super_ptr(final_addr); + } + + break; + } + default: break; + } + + return nullptr; +} void memory_viewer_panel::ShowMemory() { QString t_mem_addr_str; @@ -436,9 +536,9 @@ void memory_viewer_panel::ShowMemory() u32 addr = (m_addr + (row - spu_passed) * m_colcount * 4 + col * 4) & m_addr_mask; - if (m_spu_shm || vm::check_addr(addr, 0, 4)) + if (auto ptr = this->to_ptr(addr)) { - const be_t rmem = m_spu_shm ? *reinterpret_cast*>(m_spu_shm->map_self() + addr) : *vm::get_super_ptr(addr); + const be_t rmem = *reinterpret_cast*>(ptr); t_mem_hex_str += qstr(fmt::format("%02x %02x %02x %02x", static_cast(rmem >> 24), static_cast(rmem >> 16), @@ -484,26 +584,17 @@ void memory_viewer_panel::SetPC(const uint pc) void memory_viewer_panel::ShowImage(QWidget* parent, u32 addr, color_format format, u32 width, u32 height, bool flipv) { - const u64 memsize = 4ull * width * height; - - if (!memsize || memsize > m_addr_mask) - { - return; - } + // If exceeds 32-bits it is invalid as well, UINT32_MAX always fails checks + const u32 memsize = static_cast(std::min(4ull * width * height, UINT32_MAX)); std::shared_lock rlock(vm::g_mutex); - if (!m_spu_shm && !vm::check_addr(addr, 0, static_cast(memsize))) - { - return; - } + const auto originalBuffer = static_cast(this->to_ptr(addr, memsize)); + const auto convertedBuffer = new (std::nothrow) u8[memsize]; - const auto originalBuffer = m_spu_shm ? (m_spu_shm->map_self() + addr) : vm::get_super_ptr(addr); - const auto convertedBuffer = new (std::nothrow) u8[static_cast(memsize)]; - - if (!convertedBuffer) + if (!originalBuffer || !convertedBuffer) { - // OOM, give up + // OOM or invalid memory address, give up return; } diff --git a/rpcs3/rpcs3qt/memory_viewer_panel.h b/rpcs3/rpcs3qt/memory_viewer_panel.h index ddb0aca1ae..32b2140b78 100644 --- a/rpcs3/rpcs3qt/memory_viewer_panel.h +++ b/rpcs3/rpcs3qt/memory_viewer_panel.h @@ -17,12 +17,17 @@ namespace utils class shm; } +namespace rsx +{ + class thread; +} + class memory_viewer_panel : public QDialog { Q_OBJECT public: - memory_viewer_panel(QWidget* parent, u32 addr = 0, const std::shared_ptr& cpu = nullptr); + memory_viewer_panel(QWidget* parent, u32 addr = 0, std::function func = []() -> cpu_thread* { return {}; }); ~memory_viewer_panel(); enum class color_format : int @@ -53,17 +58,21 @@ private: enum class thread_type { + none, ppu, spu, - //rsx + rsx, }; + const std::function m_get_cpu; const thread_type m_type; + const std::add_pointer_t m_rsx; const std::shared_ptr m_spu_shm; const u32 m_addr_mask; std::string getHeaderAtAddr(u32 addr); void scroll(s32 steps); + void* to_ptr(u32 addr, u32 size = 1); void SetPC(const uint pc); virtual void ShowMemory(); @@ -84,7 +93,7 @@ struct memory_viewer_handle { } - ~memory_viewer_handle() { m_mvp->deleteLater(); } + ~memory_viewer_handle() { m_mvp->close(); m_mvp->deleteLater(); } private: const std::add_pointer_t m_mvp; diff --git a/rpcs3/rpcs3qt/register_editor_dialog.cpp b/rpcs3/rpcs3qt/register_editor_dialog.cpp index 845ed37229..2656a51840 100644 --- a/rpcs3/rpcs3qt/register_editor_dialog.cpp +++ b/rpcs3/rpcs3qt/register_editor_dialog.cpp @@ -58,10 +58,10 @@ enum registers : int PC, }; -register_editor_dialog::register_editor_dialog(QWidget *parent, const std::shared_ptr& _cpu, CPUDisAsm* _disasm) +register_editor_dialog::register_editor_dialog(QWidget *parent, CPUDisAsm* _disasm, std::function func) : QDialog(parent) , m_disasm(_disasm) - , m_cpu(_cpu) + , m_get_cpu(std::move(func)) { setWindowTitle(tr("Edit registers")); setAttribute(Qt::WA_DeleteOnClose); @@ -95,9 +95,9 @@ register_editor_dialog::register_editor_dialog(QWidget *parent, const std::share hbox_button_panel->addWidget(button_cancel); hbox_button_panel->setAlignment(Qt::AlignCenter); - if (1) + if (const auto cpu = m_get_cpu()) { - if (m_cpu->id_type() == 1) + if (cpu->id_type() == 1) { for (int i = ppu_r0; i <= ppu_r31; i++) m_register_combo->addItem(qstr(fmt::format("r%d", i % 32)), i); for (int i = ppu_f0; i <= ppu_f31; i++) m_register_combo->addItem(qstr(fmt::format("f%d", i % 32)), i); @@ -113,7 +113,7 @@ register_editor_dialog::register_editor_dialog(QWidget *parent, const std::share m_register_combo->addItem("Priority", +PPU_PRIO); //m_register_combo->addItem("Priority 2", +PPU_PRIO2); } - else if (m_cpu->id_type() == 2) + else if (cpu->id_type() == 2) { for (int i = spu_r0; i <= spu_r127; i++) m_register_combo->addItem(qstr(fmt::format("r%d", i % 128)), i); m_register_combo->addItem("MFC Pending Events", +MFC_PEVENTS); @@ -141,7 +141,6 @@ register_editor_dialog::register_editor_dialog(QWidget *parent, const std::share vbox_panel->addSpacing(10); vbox_panel->addLayout(hbox_button_panel); setLayout(vbox_panel); - setModal(true); // Events connect(button_ok, &QAbstractButton::clicked, this, [this](){ OnOkay(); accept(); }); @@ -161,12 +160,14 @@ void register_editor_dialog::updateRegister(int reg) { std::string str = sstr(tr("Error parsing register value!")); - if (!m_cpu) + const auto cpu = m_get_cpu(); + + if (!cpu) { } - else if (m_cpu->id_type() == 1) + else if (cpu->id_type() == 1) { - const auto& ppu = *static_cast(m_cpu.get()); + const auto& ppu = *static_cast(cpu); if (reg >= ppu_r0 && reg <= ppu_v31) { @@ -189,9 +190,9 @@ void register_editor_dialog::updateRegister(int reg) else if (reg == RESERVATION_LOST) str = sstr(ppu.raddr ? tr("Lose reservation on OK") : tr("Reservation is inactive")); else if (reg == PC) str = fmt::format("%08x", ppu.cia); } - else if (m_cpu->id_type() == 2) + else if (cpu->id_type() == 2) { - const auto& spu = *static_cast(m_cpu.get()); + const auto& spu = *static_cast(cpu); if (reg >= spu_r0 && reg <= spu_r127) { @@ -244,12 +245,18 @@ void register_editor_dialog::OnOkay() } } - if (!m_cpu || value.empty()) + const auto cpu = m_get_cpu(); + + if (!cpu || value.empty()) { + if (!cpu) + { + close(); + } } - else if (m_cpu->id_type() == 1) + else if (cpu->id_type() == 1) { - auto& ppu = *static_cast(m_cpu.get()); + auto& ppu = *static_cast(cpu); if (reg >= ppu_r0 && reg <= ppu_v31) { @@ -334,9 +341,9 @@ void register_editor_dialog::OnOkay() return; } } - else if (m_cpu->id_type() == 2) + else if (cpu->id_type() == 2) { - auto& spu = *static_cast(m_cpu.get()); + auto& spu = *static_cast(cpu); if (reg >= spu_r0 && reg <= spu_r127) { diff --git a/rpcs3/rpcs3qt/register_editor_dialog.h b/rpcs3/rpcs3qt/register_editor_dialog.h index f2c0229e1c..542c9551a6 100644 --- a/rpcs3/rpcs3qt/register_editor_dialog.h +++ b/rpcs3/rpcs3qt/register_editor_dialog.h @@ -19,14 +19,14 @@ class register_editor_dialog : public QDialog QComboBox* m_register_combo; QLineEdit* m_value_line; + const std::function m_get_cpu; + public: - register_editor_dialog(QWidget *parent, const std::shared_ptr& _cpu, CPUDisAsm* _disasm); + register_editor_dialog(QWidget *parent, CPUDisAsm* _disasm, std::function func); private: void OnOkay(); - std::shared_ptr m_cpu; - private Q_SLOTS: void updateRegister(int reg); };