diff --git a/rpcs3/Emu/Cell/PPUThread.cpp b/rpcs3/Emu/Cell/PPUThread.cpp index 0c60db11fd..3752f5f1f7 100644 --- a/rpcs3/Emu/Cell/PPUThread.cpp +++ b/rpcs3/Emu/Cell/PPUThread.cpp @@ -165,6 +165,7 @@ extern void ppu_initialize(); extern void ppu_initialize(const ppu_module& info); static void ppu_initialize2(class jit_compiler& jit, const ppu_module& module_part, const std::string& cache_path, const std::string& obj_name); extern void ppu_execute_syscall(ppu_thread& ppu, u64 code); +static bool ppu_break(ppu_thread& ppu, ppu_opcode_t op); // Get pointer to executable cache template @@ -308,11 +309,11 @@ extern void ppu_register_function_at(u32 addr, u32 size, ppu_function_t ptr) } // Initialize interpreter cache - const u32 fallback = ::narrow(reinterpret_cast(ppu_fallback)); + const u32 _break = ::narrow(reinterpret_cast(ppu_break)); while (size) { - if (ppu_ref(addr) == fallback) + if (ppu_ref(addr) != _break) { ppu_ref(addr) = ppu_cache(addr); } diff --git a/rpcs3/rpcs3qt/cheat_manager.cpp b/rpcs3/rpcs3qt/cheat_manager.cpp index bcf7204e6d..17626e7ce1 100644 --- a/rpcs3/rpcs3qt/cheat_manager.cpp +++ b/rpcs3/rpcs3qt/cheat_manager.cpp @@ -16,6 +16,7 @@ #include "Emu/IdManager.h" #include "Emu/Cell/PPUAnalyser.h" +#include "Emu/Cell/PPUFunction.h" #include "Utilities/StrUtil.h" @@ -332,7 +333,7 @@ std::vector cheat_engine::search(const T value, const std::vector& to_ { for (const auto& off : to_filter) { - if (vm::check_addr(off)) + if (vm::check_addr(off, sizeof(T))) { if (*vm::get_super_ptr(off) == value_swapped) results.push_back(off); @@ -370,7 +371,7 @@ T cheat_engine::get_value(const u32 offset, bool& success) cpu_thread::suspend_all cpu_lock(nullptr); - if (!vm::check_addr(offset)) + if (!vm::check_addr(offset, sizeof(T))) { success = false; return 0; @@ -391,12 +392,52 @@ bool cheat_engine::set_value(const u32 offset, const T value) cpu_thread::suspend_all cpu_lock(nullptr); - if (!vm::check_addr(offset)) + if (!vm::check_addr(offset, sizeof(T))) { return false; } *vm::get_super_ptr(offset) = value; + + const bool exec_code_at_start = vm::check_addr(offset, 1, vm::page_executable); + const bool exec_code_at_end = [&]() + { + if constexpr (sizeof(T) == 1) + { + return exec_code_at_start; + } + else + { + return vm::check_addr(offset + sizeof(T) - 1, 1, vm::page_executable); + } + }(); + + if (exec_code_at_end || exec_code_at_start) + { + extern void ppu_register_function_at(u32, u32, ppu_function_t); + + u32 addr = offset, size = sizeof(T); + + if (exec_code_at_end && exec_code_at_start) + { + size = align(addr + size, 4) - (addr & -4); + addr &= -4; + } + else if (exec_code_at_end) + { + size -= align(size - 4096 + (addr & 4095), 4); + addr = align(addr, 4096); + } + else if (exec_code_at_start) + { + size = align(4096 - (addr & 4095), 4); + addr &= -4; + } + + // Reinitialize executable code + ppu_register_function_at(addr, size, nullptr); + } + return true; }