fix patches - Different AppVer (#3344)

* fix patches

* fix linux?

* + mask, mask_jump32 |  - insideMetadata
This commit is contained in:
DanielSvoboda 2025-07-29 04:37:03 -03:00 committed by GitHub
parent 26a92d97fa
commit 35132d9fdc
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 76 additions and 52 deletions

View File

@ -17,8 +17,10 @@
#include <QString> #include <QString>
#include <QXmlStreamReader> #include <QXmlStreamReader>
#endif #endif
#include "common/elf_info.h"
#include "common/logging/log.h" #include "common/logging/log.h"
#include "common/path_util.h" #include "common/path_util.h"
#include "core/file_format/psf.h"
#include "memory_patcher.h" #include "memory_patcher.h"
namespace MemoryPatcher { namespace MemoryPatcher {
@ -127,6 +129,9 @@ void OnGameLoaded() {
pugi::xml_document doc; pugi::xml_document doc;
pugi::xml_parse_result result = doc.load_file(filePath.c_str()); pugi::xml_parse_result result = doc.load_file(filePath.c_str());
auto* param_sfo = Common::Singleton<PSF>::Instance();
auto app_version = param_sfo->GetString("APP_VER").value_or("Unknown version");
if (result) { if (result) {
auto patchXML = doc.child("Patch"); auto patchXML = doc.child("Patch");
for (pugi::xml_node_iterator it = patchXML.children().begin(); for (pugi::xml_node_iterator it = patchXML.children().begin();
@ -134,55 +139,71 @@ void OnGameLoaded() {
if (std::string(it->name()) == "Metadata") { if (std::string(it->name()) == "Metadata") {
if (std::string(it->attribute("isEnabled").value()) == "true") { if (std::string(it->attribute("isEnabled").value()) == "true") {
auto patchList = it->first_child();
std::string currentPatchName = it->attribute("Name").value(); std::string currentPatchName = it->attribute("Name").value();
std::string metadataAppVer = it->attribute("AppVer").value();
bool versionMatches = metadataAppVer == app_version;
auto patchList = it->first_child();
for (pugi::xml_node_iterator patchLineIt = patchList.children().begin(); for (pugi::xml_node_iterator patchLineIt = patchList.children().begin();
patchLineIt != patchList.children().end(); ++patchLineIt) { patchLineIt != patchList.children().end(); ++patchLineIt) {
std::string type = patchLineIt->attribute("Type").value(); std::string type = patchLineIt->attribute("Type").value();
std::string address = patchLineIt->attribute("Address").value(); if (!versionMatches && type != "mask" && type != "mask_jump32")
std::string patchValue = patchLineIt->attribute("Value").value(); continue;
std::string maskOffsetStr = patchLineIt->attribute("Offset").value();
std::string targetStr = ""; std::string currentPatchName = it->attribute("Name").value();
std::string sizeStr = "";
if (type == "mask_jump32") { for (pugi::xml_node_iterator patchLineIt = patchList.children().begin();
targetStr = patchLineIt->attribute("Target").value(); patchLineIt != patchList.children().end(); ++patchLineIt) {
sizeStr = patchLineIt->attribute("Size").value();
} else { std::string type = patchLineIt->attribute("Type").value();
patchValue = convertValueToHex(type, patchValue); std::string address = patchLineIt->attribute("Address").value();
std::string patchValue = patchLineIt->attribute("Value").value();
std::string maskOffsetStr =
patchLineIt->attribute("Offset").value();
std::string targetStr = "";
std::string sizeStr = "";
if (type == "mask_jump32") {
targetStr = patchLineIt->attribute("Target").value();
sizeStr = patchLineIt->attribute("Size").value();
} else {
patchValue = convertValueToHex(type, patchValue);
}
bool littleEndian = false;
if (type == "bytes16" || type == "bytes32" || type == "bytes64") {
littleEndian = true;
}
MemoryPatcher::PatchMask patchMask = MemoryPatcher::PatchMask::None;
int maskOffsetValue = 0;
if (type == "mask")
patchMask = MemoryPatcher::PatchMask::Mask;
if (type == "mask_jump32")
patchMask = MemoryPatcher::PatchMask::Mask_Jump32;
if ((type == "mask" || type == "mask_jump32") &&
!maskOffsetStr.empty()) {
maskOffsetValue = std::stoi(maskOffsetStr, 0, 10);
}
MemoryPatcher::PatchMemory(currentPatchName, address, patchValue,
targetStr, sizeStr, false, littleEndian,
patchMask, maskOffsetValue);
} }
bool littleEndian = false;
if (type == "bytes16" || type == "bytes32" || type == "bytes64") {
littleEndian = true;
}
MemoryPatcher::PatchMask patchMask = MemoryPatcher::PatchMask::None;
int maskOffsetValue = 0;
if (type == "mask")
patchMask = MemoryPatcher::PatchMask::Mask;
if (type == "mask_jump32")
patchMask = MemoryPatcher::PatchMask::Mask_Jump32;
if ((type == "mask" || type == "mask_jump32") &&
!maskOffsetStr.empty()) {
maskOffsetValue = std::stoi(maskOffsetStr, 0, 10);
}
MemoryPatcher::PatchMemory(currentPatchName, address, patchValue,
targetStr, sizeStr, false, littleEndian,
patchMask, maskOffsetValue);
} }
} }
} }
} }
} else
ApplyPendingPatches();
return;
} else {
LOG_ERROR(Loader, "couldnt patch parse xml : {}", result.description()); LOG_ERROR(Loader, "couldnt patch parse xml : {}", result.description());
}
ApplyPendingPatches(); ApplyPendingPatches();
return; return;
@ -243,30 +264,33 @@ void OnGameLoaded() {
QString newXmlData; QString newXmlData;
QXmlStreamReader xmlReader(xmlData); QXmlStreamReader xmlReader(xmlData);
bool insideMetadata = false;
bool isEnabled = false; bool isEnabled = false;
std::string currentPatchName; std::string currentPatchName;
auto* param_sfo = Common::Singleton<PSF>::Instance();
auto app_version = param_sfo->GetString("APP_VER").value_or("Unknown version");
bool versionMatches = true;
while (!xmlReader.atEnd()) { while (!xmlReader.atEnd()) {
xmlReader.readNext(); xmlReader.readNext();
if (xmlReader.isStartElement()) { if (xmlReader.isStartElement()) {
QJsonArray patchLines; QJsonArray patchLines;
if (xmlReader.name() == QStringLiteral("Metadata")) { if (xmlReader.name() == QStringLiteral("Metadata")) {
insideMetadata = true;
QString name = xmlReader.attributes().value("Name").toString(); QString name = xmlReader.attributes().value("Name").toString();
currentPatchName = name.toStdString(); currentPatchName = name.toStdString();
QString appVer = xmlReader.attributes().value("AppVer").toString();
// Check and update the isEnabled attribute // Check and update the isEnabled attribute
for (const QXmlStreamAttribute& attr : xmlReader.attributes()) { for (const QXmlStreamAttribute& attr : xmlReader.attributes()) {
if (attr.name() == QStringLiteral("isEnabled")) { if (attr.name() == QStringLiteral("isEnabled")) {
if (attr.value().toString() == "true") { isEnabled = (attr.value().toString() == "true");
isEnabled = true;
} else
isEnabled = false;
} }
} }
versionMatches = (appVer.toStdString() == app_version);
} else if (xmlReader.name() == QStringLiteral("PatchList")) { } else if (xmlReader.name() == QStringLiteral("PatchList")) {
QJsonArray linesArray; QJsonArray linesArray;
while (!xmlReader.atEnd() && while (!xmlReader.atEnd() &&
@ -294,12 +318,17 @@ void OnGameLoaded() {
foreach (const QJsonValue& value, patchLines) { foreach (const QJsonValue& value, patchLines) {
QJsonObject lineObject = value.toObject(); QJsonObject lineObject = value.toObject();
QString type = lineObject["Type"].toString(); QString type = lineObject["Type"].toString();
if ((type != "mask" && type != "mask_jump32") && !versionMatches)
continue;
QString address = lineObject["Address"].toString(); QString address = lineObject["Address"].toString();
QString patchValue = lineObject["Value"].toString(); QString patchValue = lineObject["Value"].toString();
QString maskOffsetStr = lineObject["Offset"].toString(); QString maskOffsetStr = lineObject["Offset"].toString();
QString targetStr; QString targetStr;
QString sizeStr; QString sizeStr;
if (type == "mask_jump32") { if (type == "mask_jump32") {
targetStr = lineObject["Target"].toString(); targetStr = lineObject["Target"].toString();
sizeStr = lineObject["Size"].toString(); sizeStr = lineObject["Size"].toString();
@ -322,8 +351,8 @@ void OnGameLoaded() {
if (type == "mask_jump32") if (type == "mask_jump32")
patchMask = MemoryPatcher::PatchMask::Mask_Jump32; patchMask = MemoryPatcher::PatchMask::Mask_Jump32;
if (type == "mask" || if ((type == "mask" || type == "mask_jump32") &&
type == "mask_jump32" && !maskOffsetStr.toStdString().empty()) { !maskOffsetStr.toStdString().empty()) {
maskOffsetValue = std::stoi(maskOffsetStr.toStdString(), 0, 10); maskOffsetValue = std::stoi(maskOffsetStr.toStdString(), 0, 10);
} }
@ -340,7 +369,7 @@ void OnGameLoaded() {
if (xmlReader.hasError()) { if (xmlReader.hasError()) {
LOG_ERROR(Loader, "Failed to parse XML for {}", g_game_serial); LOG_ERROR(Loader, "Failed to parse XML for {}", g_game_serial);
} else { } else {
LOG_INFO(Loader, "Patches loaded successfully"); LOG_INFO(Loader, "Patches loaded successfully, repository: {}", folder.toStdString());
} }
ApplyPendingPatches(); ApplyPendingPatches();
} }

View File

@ -378,14 +378,12 @@ void CheatsPatches::onSaveButtonClicked() {
xmlWriter.writeStartDocument(); xmlWriter.writeStartDocument();
QXmlStreamReader xmlReader(xmlData); QXmlStreamReader xmlReader(xmlData);
bool insideMetadata = false;
while (!xmlReader.atEnd()) { while (!xmlReader.atEnd()) {
xmlReader.readNext(); xmlReader.readNext();
if (xmlReader.isStartElement()) { if (xmlReader.isStartElement()) {
if (xmlReader.name() == QStringLiteral("Metadata")) { if (xmlReader.name() == QStringLiteral("Metadata")) {
insideMetadata = true;
xmlWriter.writeStartElement(xmlReader.name().toString()); xmlWriter.writeStartElement(xmlReader.name().toString());
QString name = xmlReader.attributes().value("Name").toString(); QString name = xmlReader.attributes().value("Name").toString();
@ -432,9 +430,6 @@ void CheatsPatches::onSaveButtonClicked() {
} }
} }
} else if (xmlReader.isEndElement()) { } else if (xmlReader.isEndElement()) {
if (xmlReader.name() == QStringLiteral("Metadata")) {
insideMetadata = false;
}
xmlWriter.writeEndElement(); xmlWriter.writeEndElement();
} else if (xmlReader.isCharacters() && !xmlReader.isWhitespace()) { } else if (xmlReader.isCharacters() && !xmlReader.isWhitespace()) {
xmlWriter.writeCharacters(xmlReader.text().toString()); xmlWriter.writeCharacters(xmlReader.text().toString());