diff --git a/rpcs3/Emu/Cell/PPUThread.cpp b/rpcs3/Emu/Cell/PPUThread.cpp index 41640cf2e5..7cb5159d0f 100644 --- a/rpcs3/Emu/Cell/PPUThread.cpp +++ b/rpcs3/Emu/Cell/PPUThread.cpp @@ -329,6 +329,43 @@ extern void ppu_remove_breakpoint(u32 addr) } } +extern bool ppu_patch(u32 addr, u32 value) +{ + // TODO: check executable flag + if (vm::check_addr(addr, sizeof(u32))) + { + if (g_cfg.core.ppu_decoder == ppu_decoder_type::llvm && Emu.GetStatus() != system_state::ready) + { + // TODO + return false; + } + + if (!vm::check_addr(addr, sizeof(u32), vm::page_writable)) + { + utils::memory_protect(vm::g_base_addr + addr, sizeof(u32), utils::protection::rw); + } + + vm::write32(addr, value); + + const u32 _break = ::narrow(reinterpret_cast(&ppu_break)); + const u32 fallback = ::narrow(reinterpret_cast(&ppu_fallback)); + + if (ppu_ref(addr) != _break && ppu_ref(addr) != fallback) + { + ppu_ref(addr) = ppu_cache(addr); + } + + if (!vm::check_addr(addr, sizeof(u32), vm::page_writable)) + { + utils::memory_protect(vm::g_base_addr + addr, sizeof(u32), utils::protection::ro); + } + + return true; + } + + return false; +} + std::string ppu_thread::get_name() const { return fmt::format("PPU[0x%x] Thread (%s)", id, m_name); diff --git a/rpcs3/rpcs3qt/debugger_frame.cpp b/rpcs3/rpcs3qt/debugger_frame.cpp index 5900ad7634..92da29f6e0 100644 --- a/rpcs3/rpcs3qt/debugger_frame.cpp +++ b/rpcs3/rpcs3qt/debugger_frame.cpp @@ -586,14 +586,12 @@ void debugger_list::keyPressEvent(QKeyEvent* event) { instruction_editor_dialog* dlg = new instruction_editor_dialog(this, pc, cpu, m_debugFrame->m_disasm.get()); dlg->show(); - m_debugFrame->DoUpdate(); return; } case Qt::Key_R: { register_editor_dialog* dlg = new register_editor_dialog(this, pc, cpu, m_debugFrame->m_disasm.get()); dlg->show(); - m_debugFrame->DoUpdate(); return; } } diff --git a/rpcs3/rpcs3qt/instruction_editor_dialog.cpp b/rpcs3/rpcs3qt/instruction_editor_dialog.cpp index 401d7e0bb3..34d0411fb1 100644 --- a/rpcs3/rpcs3qt/instruction_editor_dialog.cpp +++ b/rpcs3/rpcs3qt/instruction_editor_dialog.cpp @@ -4,6 +4,8 @@ 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) : QDialog(parent) , m_pc(_pc) @@ -67,13 +69,26 @@ instruction_editor_dialog::instruction_editor_dialog(QWidget *parent, u32 _pc, c { bool ok; ulong opcode = m_instr->text().toULong(&ok, 16); - if (!ok) + if (!ok || opcode > UINT32_MAX) { - QMessageBox::critical(this, tr("Error"), tr("This instruction could not be parsed.\nNo changes were made.")); + QMessageBox::critical(this, tr("Error"), tr("Failed to parse PPU instruction.")); + return; + } + else if (g_system == system_type::ps3 && cpu->id_type() == 1) + { + if (!ppu_patch(m_cpu_offset + m_pc, static_cast(opcode))) + { + QMessageBox::critical(this, tr("Error"), tr("Failed to patch PPU instruction.")); + return; + } + } + else if (g_system == system_type::ps3) + { + vm::ps3::write32(m_cpu_offset + m_pc, static_cast(opcode)); } else { - vm::ps3::write32(m_cpu_offset + m_pc, (u32)opcode); + vm::psv::write32(m_cpu_offset + m_pc, static_cast(opcode)); } accept(); });