1
0
mirror of https://github.com/RPCS3/rpcs3.git synced 2024-11-22 10:42:36 +01:00

Implement runtime PPU executable code modification via Cheat Manager

This commit is contained in:
Eladash 2019-11-14 23:03:58 +02:00 committed by Ivan
parent 93a6e9e4e4
commit 8427af8886
2 changed files with 47 additions and 5 deletions

View File

@ -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<typename T = u64>
@ -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<u32>(reinterpret_cast<std::uintptr_t>(ppu_fallback));
const u32 _break = ::narrow<u32>(reinterpret_cast<std::uintptr_t>(ppu_break));
while (size)
{
if (ppu_ref<u32>(addr) == fallback)
if (ppu_ref<u32>(addr) != _break)
{
ppu_ref(addr) = ppu_cache(addr);
}

View File

@ -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<u32> cheat_engine::search(const T value, const std::vector<u32>& to_
{
for (const auto& off : to_filter)
{
if (vm::check_addr(off))
if (vm::check_addr(off, sizeof(T)))
{
if (*vm::get_super_ptr<T>(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<T>(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<u32>(addr + size, 4) - (addr & -4);
addr &= -4;
}
else if (exec_code_at_end)
{
size -= align<u32>(size - 4096 + (addr & 4095), 4);
addr = align<u32>(addr, 4096);
}
else if (exec_code_at_start)
{
size = align<u32>(4096 - (addr & 4095), 4);
addr &= -4;
}
// Reinitialize executable code
ppu_register_function_at(addr, size, nullptr);
}
return true;
}