mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2026-07-09 17:25:37 -06:00
This reverts commit a52b4c0dae.
This commit is contained in:
parent
a52b4c0dae
commit
221efa40c7
@ -30,34 +30,20 @@ std::string toHex(u64 value, size_t byteSize) {
|
|||||||
return ss.str();
|
return ss.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool isHexSym(const std::string& s) {
|
|
||||||
return (s.size() >= 2 && (s[0] == '$' || s[0] == '#'));
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool isHex0x(const std::string& s) {
|
|
||||||
return (s.size() >= 3 && s[0] == '0' && (s[1] == 'x' || s[1] == 'X'));
|
|
||||||
}
|
|
||||||
|
|
||||||
// possible prefixes == (s == `0x` || s == `#` || s == `$`) will be interpet as hex value, else is
|
|
||||||
// decimal
|
|
||||||
static int convertNumBase(const std::string& s) {
|
|
||||||
return (isHex0x(s) || isHexSym(s)) ? 16 : 10;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string convertValueToHex(const std::string type, const std::string valueStr) {
|
std::string convertValueToHex(const std::string type, const std::string valueStr) {
|
||||||
std::string result;
|
std::string result;
|
||||||
|
|
||||||
if (type == "byte") {
|
if (type == "byte") {
|
||||||
const u32 value = std::stoul(valueStr, nullptr, convertNumBase(valueStr));
|
const u32 value = std::stoul(valueStr, nullptr, 16);
|
||||||
result = toHex(value, 1);
|
result = toHex(value, 1);
|
||||||
} else if (type == "bytes16") {
|
} else if (type == "bytes16") {
|
||||||
const u32 value = std::stoul(valueStr, nullptr, convertNumBase(valueStr));
|
const u32 value = std::stoul(valueStr, nullptr, 16);
|
||||||
result = toHex(value, 2);
|
result = toHex(value, 2);
|
||||||
} else if (type == "bytes32") {
|
} else if (type == "bytes32") {
|
||||||
const u32 value = std::stoul(valueStr, nullptr, convertNumBase(valueStr));
|
const u32 value = std::stoul(valueStr, nullptr, 16);
|
||||||
result = toHex(value, 4);
|
result = toHex(value, 4);
|
||||||
} else if (type == "bytes64") {
|
} else if (type == "bytes64") {
|
||||||
const u64 value = std::stoull(valueStr, nullptr, convertNumBase(valueStr));
|
const u64 value = std::stoull(valueStr, nullptr, 16);
|
||||||
result = toHex(value, 8);
|
result = toHex(value, 8);
|
||||||
} else if (type == "float32") {
|
} else if (type == "float32") {
|
||||||
union {
|
union {
|
||||||
@ -184,18 +170,9 @@ void ApplyPatchesFromXML(std::filesystem::path path) {
|
|||||||
maskOffsetValue = std::stoi(maskOffsetStr, 0, 10);
|
maskOffsetValue = std::stoi(maskOffsetStr, 0, 10);
|
||||||
}
|
}
|
||||||
|
|
||||||
const patchInfo patch = {
|
MemoryPatcher::PatchMemory(currentPatchName, address, patchValue, targetStr,
|
||||||
.gameSerial = "*",
|
sizeStr, false, littleEndian, patchMask,
|
||||||
.modNameStr = currentPatchName,
|
maskOffsetValue);
|
||||||
.offsetStr = address,
|
|
||||||
.valueStr = patchValue,
|
|
||||||
.targetStr = targetStr,
|
|
||||||
.sizeStr = sizeStr,
|
|
||||||
.littleEndian = littleEndian,
|
|
||||||
.patchMask = patchMask,
|
|
||||||
.maskOffset = maskOffsetValue,
|
|
||||||
};
|
|
||||||
MemoryPatcher::PatchMemory(patch);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -237,9 +214,11 @@ void OnGameLoaded() {
|
|||||||
ApplyPendingPatches();
|
ApplyPendingPatches();
|
||||||
}
|
}
|
||||||
|
|
||||||
void AddPatchToQueue(const patchInfo& patchToAdd) {
|
void AddPatchToQueue(patchInfo patchToAdd) {
|
||||||
if (patches_applied) {
|
if (patches_applied) {
|
||||||
PatchMemory(patchToAdd);
|
PatchMemory(patchToAdd.modNameStr, patchToAdd.offsetStr, patchToAdd.valueStr,
|
||||||
|
patchToAdd.targetStr, patchToAdd.sizeStr, patchToAdd.isOffset,
|
||||||
|
patchToAdd.littleEndian, patchToAdd.patchMask, patchToAdd.maskOffset);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
pending_patches.push_back(patchToAdd);
|
pending_patches.push_back(patchToAdd);
|
||||||
@ -253,32 +232,35 @@ void ApplyPendingPatches() {
|
|||||||
if (currentPatch.gameSerial != "*" && currentPatch.gameSerial != g_game_serial)
|
if (currentPatch.gameSerial != "*" && currentPatch.gameSerial != g_game_serial)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
PatchMemory(currentPatch);
|
PatchMemory(currentPatch.modNameStr, currentPatch.offsetStr, currentPatch.valueStr,
|
||||||
|
currentPatch.targetStr, currentPatch.sizeStr, currentPatch.isOffset,
|
||||||
|
currentPatch.littleEndian, currentPatch.patchMask, currentPatch.maskOffset);
|
||||||
}
|
}
|
||||||
|
|
||||||
pending_patches.clear();
|
pending_patches.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void PatchMemory(const patchInfo& patch) {
|
void PatchMemory(std::string modNameStr, std::string offsetStr, std::string valueStr,
|
||||||
|
std::string targetStr, std::string sizeStr, bool isOffset, bool littleEndian,
|
||||||
|
PatchMask patchMask, int maskOffset) {
|
||||||
// Send a request to modify the process memory.
|
// Send a request to modify the process memory.
|
||||||
void* cheatAddress = nullptr;
|
void* cheatAddress = nullptr;
|
||||||
|
|
||||||
if (patch.patchMask == PatchMask::None) {
|
if (patchMask == PatchMask::None) {
|
||||||
if (patch.isOffset) {
|
if (isOffset) {
|
||||||
cheatAddress =
|
cheatAddress = reinterpret_cast<void*>(g_eboot_address + std::stoi(offsetStr, 0, 16));
|
||||||
reinterpret_cast<void*>(g_eboot_address + std::stoi(patch.offsetStr, 0, 16));
|
|
||||||
} else {
|
} else {
|
||||||
cheatAddress = reinterpret_cast<void*>(g_eboot_address +
|
cheatAddress =
|
||||||
(std::stoi(patch.offsetStr, 0, 16) - 0x400000));
|
reinterpret_cast<void*>(g_eboot_address + (std::stoi(offsetStr, 0, 16) - 0x400000));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (patch.patchMask == PatchMask::Mask) {
|
if (patchMask == PatchMask::Mask) {
|
||||||
cheatAddress = reinterpret_cast<void*>(PatternScan(patch.offsetStr) + patch.maskOffset);
|
cheatAddress = reinterpret_cast<void*>(PatternScan(offsetStr) + maskOffset);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (patch.patchMask == PatchMask::Mask_Jump32) {
|
if (patchMask == PatchMask::Mask_Jump32) {
|
||||||
int jumpSize = std::stoi(patch.sizeStr);
|
int jumpSize = std::stoi(sizeStr);
|
||||||
|
|
||||||
constexpr int MAX_PATTERN_LENGTH = 256;
|
constexpr int MAX_PATTERN_LENGTH = 256;
|
||||||
if (jumpSize < 5) {
|
if (jumpSize < 5) {
|
||||||
@ -291,35 +273,35 @@ void PatchMemory(const patchInfo& patch) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Find the base address using "Address"
|
// Find the base address using "Address"
|
||||||
uintptr_t baseAddress = PatternScan(patch.offsetStr);
|
uintptr_t baseAddress = PatternScan(offsetStr);
|
||||||
if (baseAddress == 0) {
|
if (baseAddress == 0) {
|
||||||
LOG_ERROR(Loader, "PatternScan failed for mask_jump32 with pattern: {}",
|
LOG_ERROR(Loader, "PatternScan failed for mask_jump32 with pattern: {}", offsetStr);
|
||||||
patch.offsetStr);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
uintptr_t patchAddress = baseAddress + patch.maskOffset;
|
uintptr_t patchAddress = baseAddress + maskOffset;
|
||||||
|
|
||||||
// Fills the original region (jumpSize bytes) with NOPs
|
// Fills the original region (jumpSize bytes) with NOPs
|
||||||
std::vector<u8> nopBytes(jumpSize, 0x90);
|
std::vector<u8> nopBytes(jumpSize, 0x90);
|
||||||
std::memcpy(reinterpret_cast<void*>(patchAddress), nopBytes.data(), nopBytes.size());
|
std::memcpy(reinterpret_cast<void*>(patchAddress), nopBytes.data(), nopBytes.size());
|
||||||
|
|
||||||
// Use "Target" to locate the start of the code cave
|
// Use "Target" to locate the start of the code cave
|
||||||
uintptr_t jump_target = PatternScan(patch.targetStr);
|
uintptr_t jump_target = PatternScan(targetStr);
|
||||||
if (jump_target == 0) {
|
if (jump_target == 0) {
|
||||||
LOG_ERROR(Loader, "PatternScan failed to Target with pattern: {}", patch.targetStr);
|
LOG_ERROR(Loader, "PatternScan failed to Target with pattern: {}", targetStr);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Converts the Value attribute to a byte array (payload)
|
// Converts the Value attribute to a byte array (payload)
|
||||||
std::vector<u8> payload;
|
std::vector<u8> payload;
|
||||||
for (size_t i = 0; i < patch.valueStr.length(); i += 2) {
|
for (size_t i = 0; i < valueStr.length(); i += 2) {
|
||||||
std::string tempStr = patch.valueStr.substr(i, 2);
|
|
||||||
|
std::string tempStr = valueStr.substr(i, 2);
|
||||||
const char* byteStr = tempStr.c_str();
|
const char* byteStr = tempStr.c_str();
|
||||||
char* endPtr;
|
char* endPtr;
|
||||||
unsigned int byteVal = std::strtoul(byteStr, &endPtr, 16);
|
unsigned int byteVal = std::strtoul(byteStr, &endPtr, 16);
|
||||||
|
|
||||||
if (endPtr != byteStr + 2) {
|
if (endPtr != byteStr + 2) {
|
||||||
LOG_ERROR(Loader, "Invalid byte in Value: {}", patch.valueStr.substr(i, 2));
|
LOG_ERROR(Loader, "Invalid byte in Value: {}", valueStr.substr(i, 2));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
payload.push_back(static_cast<u8>(byteVal));
|
payload.push_back(static_cast<u8>(byteVal));
|
||||||
@ -351,32 +333,32 @@ void PatchMemory(const patchInfo& patch) {
|
|||||||
LOG_INFO(Loader,
|
LOG_INFO(Loader,
|
||||||
"Applied Patch mask_jump32: {}, PatchAddress: {:#x}, JumpTarget: {:#x}, "
|
"Applied Patch mask_jump32: {}, PatchAddress: {:#x}, JumpTarget: {:#x}, "
|
||||||
"CodeCaveEnd: {:#x}, JumpSize: {}",
|
"CodeCaveEnd: {:#x}, JumpSize: {}",
|
||||||
patch.modNameStr, patchAddress, jump_target, code_cave_end, jumpSize);
|
modNameStr, patchAddress, jump_target, code_cave_end, jumpSize);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cheatAddress == nullptr) {
|
if (cheatAddress == nullptr) {
|
||||||
LOG_ERROR(Loader, "Failed to get address for patch {}", patch.modNameStr);
|
LOG_ERROR(Loader, "Failed to get address for patch {}", modNameStr);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<unsigned char> bytePatch;
|
std::vector<unsigned char> bytePatch;
|
||||||
|
|
||||||
for (size_t i = 0; i < patch.valueStr.length(); i += 2) {
|
for (size_t i = 0; i < valueStr.length(); i += 2) {
|
||||||
unsigned char byte = static_cast<unsigned char>(
|
unsigned char byte =
|
||||||
std::strtol(patch.valueStr.substr(i, 2).c_str(), nullptr, 16));
|
static_cast<unsigned char>(std::strtol(valueStr.substr(i, 2).c_str(), nullptr, 16));
|
||||||
|
|
||||||
bytePatch.push_back(byte);
|
bytePatch.push_back(byte);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (patch.littleEndian) {
|
if (littleEndian) {
|
||||||
std::reverse(bytePatch.begin(), bytePatch.end());
|
std::reverse(bytePatch.begin(), bytePatch.end());
|
||||||
}
|
}
|
||||||
|
|
||||||
std::memcpy(cheatAddress, bytePatch.data(), bytePatch.size());
|
std::memcpy(cheatAddress, bytePatch.data(), bytePatch.size());
|
||||||
|
|
||||||
LOG_INFO(Loader, "Applied patch: {}, Offset: {:#x}, Value: {}", patch.modNameStr,
|
LOG_INFO(Loader, "Applied patch: {}, Offset: {}, Value: {}", modNameStr,
|
||||||
(uintptr_t)cheatAddress, patch.valueStr);
|
(uintptr_t)cheatAddress, valueStr);
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::vector<int32_t> PatternToByte(const std::string& pattern) {
|
static std::vector<int32_t> PatternToByte(const std::string& pattern) {
|
||||||
|
|||||||
@ -26,12 +26,12 @@ enum PatchMask : uint8_t {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct patchInfo {
|
struct patchInfo {
|
||||||
const std::string& gameSerial;
|
std::string gameSerial;
|
||||||
const std::string& modNameStr;
|
std::string modNameStr;
|
||||||
const std::string& offsetStr;
|
std::string offsetStr;
|
||||||
const std::string& valueStr;
|
std::string valueStr;
|
||||||
const std::string& targetStr;
|
std::string targetStr;
|
||||||
const std::string& sizeStr;
|
std::string sizeStr;
|
||||||
bool isOffset;
|
bool isOffset;
|
||||||
bool littleEndian;
|
bool littleEndian;
|
||||||
PatchMask patchMask;
|
PatchMask patchMask;
|
||||||
@ -41,9 +41,11 @@ struct patchInfo {
|
|||||||
std::string convertValueToHex(const std::string type, const std::string valueStr);
|
std::string convertValueToHex(const std::string type, const std::string valueStr);
|
||||||
|
|
||||||
void OnGameLoaded();
|
void OnGameLoaded();
|
||||||
void AddPatchToQueue(const patchInfo& patchToAdd);
|
void AddPatchToQueue(patchInfo patchToAdd);
|
||||||
|
|
||||||
void PatchMemory(const patchInfo& patch);
|
void PatchMemory(std::string modNameStr, std::string offsetStr, std::string valueStr,
|
||||||
|
std::string targetStr, std::string sizeStr, bool isOffset, bool littleEndian,
|
||||||
|
PatchMask patchMask = PatchMask::None, int maskOffset = 0);
|
||||||
|
|
||||||
static std::vector<int32_t> PatternToByte(const std::string& pattern);
|
static std::vector<int32_t> PatternToByte(const std::string& pattern);
|
||||||
uintptr_t PatternScan(const std::string& signature);
|
uintptr_t PatternScan(const std::string& signature);
|
||||||
|
|||||||
@ -124,18 +124,17 @@ void IPC::InputLoop() {
|
|||||||
} else if (cmd == "START") {
|
} else if (cmd == "START") {
|
||||||
start_semaphore.release();
|
start_semaphore.release();
|
||||||
} else if (cmd == "PATCH_MEMORY") {
|
} else if (cmd == "PATCH_MEMORY") {
|
||||||
const MemoryPatcher::patchInfo entry = {
|
MemoryPatcher::patchInfo entry;
|
||||||
.gameSerial = "*",
|
entry.gameSerial = "*";
|
||||||
.modNameStr = next_str(),
|
entry.modNameStr = next_str();
|
||||||
.offsetStr = next_str(),
|
entry.offsetStr = next_str();
|
||||||
.valueStr = next_str(),
|
entry.valueStr = next_str();
|
||||||
.targetStr = next_str(),
|
entry.targetStr = next_str();
|
||||||
.sizeStr = next_str(),
|
entry.sizeStr = next_str();
|
||||||
.isOffset = next_u64() != 0,
|
entry.isOffset = next_u64() != 0;
|
||||||
.littleEndian = next_u64() != 0,
|
entry.littleEndian = next_u64() != 0;
|
||||||
.patchMask = static_cast<MemoryPatcher::PatchMask>(next_u64()),
|
entry.patchMask = static_cast<MemoryPatcher::PatchMask>(next_u64());
|
||||||
.maskOffset = static_cast<int>(next_u64()),
|
entry.maskOffset = static_cast<int>(next_u64());
|
||||||
};
|
|
||||||
MemoryPatcher::AddPatchToQueue(entry);
|
MemoryPatcher::AddPatchToQueue(entry);
|
||||||
} else if (cmd == "PAUSE") {
|
} else if (cmd == "PAUSE") {
|
||||||
DebugState.PauseGuestThreads();
|
DebugState.PauseGuestThreads();
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user