From 06f6082bc18340b01e8592eed3e0e3c87db70726 Mon Sep 17 00:00:00 2001 From: CrazyBloo Date: Thu, 22 Aug 2024 19:54:34 -0400 Subject: [PATCH] MemoryPatcher namespace, activate cheats on start --- CMakeLists.txt | 2 ++ src/common/memory_patcher.cpp | 44 +++++++++++++++++++++++++++++++++++ src/common/memory_patcher.h | 24 +++++++++++++++++++ src/core/module.cpp | 18 +++++++------- src/core/module.h | 2 -- src/qt_gui/cheats_patches.cpp | 34 +++++++++------------------ 6 files changed, 91 insertions(+), 33 deletions(-) create mode 100644 src/common/memory_patcher.cpp create mode 100644 src/common/memory_patcher.h diff --git a/CMakeLists.txt b/CMakeLists.txt index b2b2ceaad..6495cb665 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -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 diff --git a/src/common/memory_patcher.cpp b/src/common/memory_patcher.cpp new file mode 100644 index 000000000..fb6ef7542 --- /dev/null +++ b/src/common/memory_patcher.cpp @@ -0,0 +1,44 @@ +#include "memory_patcher.h" +#include "common/logging/log.h" + +namespace MemoryPatcher +{ + +uintptr_t g_eboot_address; + +std::vector 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(g_eboot_address + std::stoi(offsetStr, 0, 16)); + + std::vector bytePatch; + + for (size_t i = 0; i < valueStr.length(); i += 2) { + unsigned char byte = + static_cast(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); +} + +} \ No newline at end of file diff --git a/src/common/memory_patcher.h b/src/common/memory_patcher.h new file mode 100644 index 000000000..f06e547ec --- /dev/null +++ b/src/common/memory_patcher.h @@ -0,0 +1,24 @@ +#pragma once +#include +#include +#include + +namespace MemoryPatcher +{ + extern uintptr_t g_eboot_address; + + struct patchInfo { + std::string modNameStr; + std::string offsetStr; + std::string valueStr; + }; + + extern std::vector pending_patches; + + void AddPatchToQueue(patchInfo patchToAdd); + void ApplyPendingPatches(); + + void PatchMemory(std::string modNameStr, std::string offsetStr, std::string valueStr); + + +} \ No newline at end of file diff --git a/src/core/module.cpp b/src/core/module.cpp index 369931ff5..338025475 100644 --- a/src/core/module.cpp +++ b/src/core/module.cpp @@ -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(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() { diff --git a/src/core/module.h b/src/core/module.h index c00488550..007501f08 100644 --- a/src/core/module.h +++ b/src/core/module.h @@ -243,6 +243,4 @@ public: std::vector rela_bits; }; -extern uintptr_t g_eboot_address; - } // namespace Core diff --git a/src/qt_gui/cheats_patches.cpp b/src/qt_gui/cheats_patches.cpp index bc1b0c840..a58a07e72 100644 --- a/src/qt_gui/cheats_patches.cpp +++ b/src/qt_gui/cheats_patches.cpp @@ -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(Core::g_eboot_address + std::stoi(offsetStr, 0, 16)); - - std::vector bytePatch; - - for (size_t i = 0; i < valueStr.length(); i += 2) { - unsigned char byte = - static_cast(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); } }