MemoryPatcher namespace, activate cheats on start

This commit is contained in:
CrazyBloo 2024-08-22 19:54:34 -04:00
parent 957d3e38df
commit 06f6082bc1
6 changed files with 91 additions and 33 deletions

View file

@ -299,6 +299,8 @@ set(COMMON src/common/logging/backend.cpp
src/common/enum.h
src/common/io_file.cpp
src/common/io_file.h
src/common/memory_patcher.cpp
src/common/memory_patcher.h
src/common/error.cpp
src/common/error.h
src/common/scope_exit.h

View file

@ -0,0 +1,44 @@
#include "memory_patcher.h"
#include "common/logging/log.h"
namespace MemoryPatcher
{
uintptr_t g_eboot_address;
std::vector<patchInfo> pending_patches;
void AddPatchToQueue(patchInfo patchToAdd) {
pending_patches.push_back(patchToAdd);
}
void ApplyPendingPatches() {
for (size_t i = 0; i < pending_patches.size(); ++i) {
patchInfo currentPatch = pending_patches[i];
LOG_INFO(Loader, "loading patch {}", i);
PatchMemory(currentPatch.modNameStr, currentPatch.offsetStr, currentPatch.valueStr);
}
pending_patches.clear();
}
void PatchMemory(std::string modNameStr, std::string offsetStr, std::string valueStr) {
// Send a request to modify the process memory.
void* cheatAddress =
reinterpret_cast<void*>(g_eboot_address + std::stoi(offsetStr, 0, 16));
std::vector<unsigned char> bytePatch;
for (size_t i = 0; i < valueStr.length(); i += 2) {
unsigned char byte =
static_cast<unsigned char>(std::strtol(valueStr.substr(i, 2).c_str(), nullptr, 16));
bytePatch.push_back(byte);
}
std::memcpy(cheatAddress, bytePatch.data(), bytePatch.size());
LOG_INFO(Loader, "Applied patch:{}, Offset:{}, Value:{}", modNameStr, (uintptr_t)cheatAddress, valueStr);
}
}

View file

@ -0,0 +1,24 @@
#pragma once
#include <cstring>
#include <vector>
#include <string>
namespace MemoryPatcher
{
extern uintptr_t g_eboot_address;
struct patchInfo {
std::string modNameStr;
std::string offsetStr;
std::string valueStr;
};
extern std::vector<patchInfo> pending_patches;
void AddPatchToQueue(patchInfo patchToAdd);
void ApplyPendingPatches();
void PatchMemory(std::string modNameStr, std::string offsetStr, std::string valueStr);
}

View file

@ -11,6 +11,7 @@
#include "core/loader/dwarf.h"
#include "core/memory.h"
#include "core/module.h"
#include "common/memory_patcher.h"
namespace Core {
@ -19,8 +20,6 @@ using EntryFunc = PS4_SYSV_ABI int (*)(size_t args, const void* argp, void* para
static u64 LoadOffset = CODE_BASE_OFFSET;
static constexpr u64 CODE_BASE_INCR = 0x010000000u;
uintptr_t g_eboot_address;
static u64 GetAlignedSize(const elf_program_header& phdr) {
return (phdr.p_align != 0 ? (phdr.p_memsz + (phdr.p_align - 1)) & ~(phdr.p_align - 1)
: phdr.p_memsz);
@ -92,12 +91,6 @@ void Module::LoadModuleToMemory(u32& max_tls_index) {
LoadOffset += CODE_BASE_INCR * (1 + aligned_base_size / CODE_BASE_INCR);
LOG_INFO(Core_Linker, "Loading module {} to {}", name, fmt::ptr(*out_addr));
if (g_eboot_address == 0) {
if (name == "eboot") {
g_eboot_address = base_virtual_addr;
}
}
// Initialize trampoline generator.
void* trampoline_addr = std::bit_cast<void*>(base_virtual_addr + aligned_base_size);
Xbyak::CodeGenerator c(TrampolineSize, trampoline_addr);
@ -200,6 +193,15 @@ void Module::LoadModuleToMemory(u32& max_tls_index) {
const VAddr entry_addr = base_virtual_addr + elf.GetElfEntry();
LOG_INFO(Core_Linker, "program entry addr ..........: {:#018x}", entry_addr);
if (MemoryPatcher::g_eboot_address == 0) {
if (name == "eboot") {
MemoryPatcher::g_eboot_address = base_virtual_addr;
MemoryPatcher::ApplyPendingPatches();
}
}
}
void Module::LoadDynamicInfo() {

View file

@ -243,6 +243,4 @@ public:
std::vector<u8> rela_bits;
};
extern uintptr_t g_eboot_address;
} // namespace Core

View file

@ -28,6 +28,8 @@
#include "cheats_patches.h"
#include "common/path_util.h"
#include "core/module.h"
#include "common/memory_patcher.h"
using namespace Common::FS;
CheatsPatches::CheatsPatches(const QString& gameName, const QString& gameSerial,
@ -625,16 +627,6 @@ void CheatsPatches::applyCheat(const QString& modName, bool enabled) {
if (!m_cheats.contains(modName))
return;
if (Core::g_eboot_address == 0) {
if (showErrorMessage) {
QMessageBox::warning(this, "Game Not Started",
"Cheat cannot be applied until the game has started.");
showErrorMessage = false;
}
uncheckAllCheatCheckBoxes();
return;
}
Cheat cheat = m_cheats[modName];
for (const MemoryMod& memoryMod : cheat.memoryMods) {
@ -644,21 +636,17 @@ void CheatsPatches::applyCheat(const QString& modName, bool enabled) {
std::string offsetStr = memoryMod.offset.toStdString();
std::string valueStr = value.toStdString();
LOG_INFO(Loader, "Cheat applied:{}, Offset:{}, Value:{}", modNameStr, offsetStr, valueStr);
if (MemoryPatcher::g_eboot_address == 0) {
MemoryPatcher::patchInfo addingPatch;
addingPatch.modNameStr = modNameStr;
addingPatch.offsetStr = offsetStr;
addingPatch.valueStr = valueStr;
// Send a request to modify the process memory.
void* cheatAddress =
reinterpret_cast<void*>(Core::g_eboot_address + std::stoi(offsetStr, 0, 16));
std::vector<unsigned char> bytePatch;
for (size_t i = 0; i < valueStr.length(); i += 2) {
unsigned char byte =
static_cast<unsigned char>(std::strtol(valueStr.substr(i, 2).c_str(), nullptr, 16));
bytePatch.push_back(byte);
MemoryPatcher::AddPatchToQueue(addingPatch);
continue;
}
std::memcpy(cheatAddress, bytePatch.data(), bytePatch.size());
MemoryPatcher::PatchMemory(modNameStr, offsetStr, valueStr);
}
}