Skip to content

Commit 55cf876

Browse files
committed
fix(core): Patches
1 parent ec234df commit 55cf876

File tree

3 files changed

+134
-0
lines changed

3 files changed

+134
-0
lines changed

src/entrypoint.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
#include "plugins/PluginManager.h"
2828
#include "plugins/core/scripting.h"
2929
#include "signatures/Signatures.h"
30+
#include "signatures/Patches.h"
3031
#include "signatures/Offsets.h"
3132
#include "voicemanager/VoiceManager.h"
3233

@@ -102,6 +103,7 @@ Precacher *g_precacher = nullptr;
102103
DatabaseManager *g_dbManager = nullptr;
103104
MenuManager *g_MenuManager = nullptr;
104105
ResourceMonitor *g_ResourceMonitor = nullptr;
106+
Patches *g_Patches = nullptr;
105107
VoiceManager g_voiceManager;
106108

107109
//////////////////////////////////////////////////////////////
@@ -148,6 +150,7 @@ bool Swiftly::Load(PluginId id, ISmmAPI *ismm, char *error, size_t maxlen, bool
148150
g_conFilter = new ConsoleFilter();
149151
g_Signatures = new Signatures();
150152
g_Offsets = new Offsets();
153+
g_Patches = new Patches();
151154
g_playerManager = new PlayerManager();
152155
g_Logger = new Logger();
153156
g_translations = new Translations();
@@ -165,6 +168,9 @@ bool Swiftly::Load(PluginId id, ISmmAPI *ismm, char *error, size_t maxlen, bool
165168
g_Config->LoadPluginConfigurations();
166169
g_Signatures->LoadSignatures();
167170
g_Offsets->LoadOffsets();
171+
g_Patches->LoadPatches();
172+
g_Patches->PerformPatches();
173+
168174
g_dbManager->LoadDatabases();
169175

170176
g_addons.LoadAddons();

src/signatures/Patches.cpp

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
#include "Patches.h"
2+
#include "Signatures.h"
3+
#include "../common.h"
4+
#include "../utils/plat.h"
5+
#include "../files/Files.h"
6+
#include "../configuration/Configuration.h"
7+
8+
#include <rapidjson/document.h>
9+
#include <rapidjson/error/en.h>
10+
11+
#define HAS_MEMBER(DOCUMENT, MEMBER_NAME, MEMBER_PATH) \
12+
if (!DOCUMENT.HasMember(MEMBER_NAME)) \
13+
{ \
14+
PatchesError(string_format("The field \"%s\" doesn't exists.", MEMBER_PATH)); \
15+
continue; \
16+
}
17+
18+
#define IS_STRING(DOCUMENT, MEMBER_NAME, MEMBER_PATH) \
19+
if (!DOCUMENT[MEMBER_NAME].IsString()) \
20+
{ \
21+
PatchesError(string_format("The field \"%s\" is not a string.", MEMBER_PATH)); \
22+
continue; \
23+
}
24+
25+
byte *HexToByte(const char *src, size_t &length);
26+
27+
void PatchesError(std::string text)
28+
{
29+
if (!g_SMAPI)
30+
return;
31+
32+
PRINTF("Patches", "%s\n", text.c_str());
33+
}
34+
35+
void Patches::LoadPatches()
36+
{
37+
rapidjson::Document patchesFile;
38+
patchesFile.Parse(Files::Read("addons/swiftly/gamedata/patches.json").c_str());
39+
if (patchesFile.HasParseError())
40+
return PatchesError(string_format("A parsing error has been detected.\nError (offset %u): %s\n", (unsigned)patchesFile.GetErrorOffset(), GetParseError_En(patchesFile.GetParseError())));
41+
42+
if (patchesFile.IsArray())
43+
return PatchesError("Patches file cannot be an array.");
44+
45+
for (auto it = patchesFile.MemberBegin(); it != patchesFile.MemberEnd(); ++it)
46+
{
47+
std::string name = it->name.GetString();
48+
49+
HAS_MEMBER(it->value, "signature", string_format("%s.signature", name))
50+
HAS_MEMBER(it->value, "windows", string_format("%s.windows", name))
51+
HAS_MEMBER(it->value, "linux", string_format("%s.linux", name))
52+
53+
IS_STRING(it->value, "signature", string_format("%s.signature", name))
54+
IS_STRING(it->value, "windows", string_format("%s.windows", name))
55+
IS_STRING(it->value, "linux", string_format("%s.linux", name))
56+
57+
std::string signature = it->value["signature"].GetString();
58+
if (!g_Signatures->Exists(signature))
59+
{
60+
PatchesError(string_format("%s: Signature '%s' does not exists in signatures file.\n", name.c_str(), signature.c_str()));
61+
continue;
62+
}
63+
64+
this->patches.insert(std::make_pair(name, std::string(it->value[WIN_LINUX("windows", "linux")].GetString())));
65+
this->signatures.insert(std::make_pair(name, signature));
66+
}
67+
}
68+
69+
void Patches::PerformPatch(std::string patch_name)
70+
{
71+
if (this->patches.find(patch_name) == this->patches.end())
72+
{
73+
PRINTF("Patch", "Invalid patch name: \"%s\".\n", patch_name.c_str());
74+
return;
75+
}
76+
77+
void *patchAddress = g_Signatures->FetchRawSignature(this->signatures.at(patch_name));
78+
79+
size_t iLength = 0;
80+
byte *patch = HexToByte(this->patches.at(patch_name).c_str(), iLength);
81+
82+
Plat_WriteMemory(patchAddress, (byte *)patch, iLength);
83+
PRINTF("Patch", "Patched \"%s\" using signature \"%s\".\n", patch_name.c_str(), this->signatures.at(patch_name).c_str());
84+
}
85+
86+
void Patches::PerformPatches()
87+
{
88+
if (g_Config->HasKey("core.patchesToPerform"))
89+
{
90+
std::vector<std::string> patchesToPerform = explode(g_Config->FetchValue<std::string>("core.patchesToPerform"), " ");
91+
92+
uint32_t patchesPerformed = 0;
93+
for (std::string &patchName : patchesToPerform)
94+
{
95+
if (patchName == "")
96+
continue;
97+
98+
this->PerformPatch(patchName);
99+
++patchesPerformed;
100+
}
101+
102+
PRINTF("Patch", "Patches performed: %02d.\n", patchesPerformed);
103+
patchesToPerform.clear();
104+
}
105+
}

src/signatures/Patches.h

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
#ifndef _patches_h
2+
#define _patches_h
3+
4+
#include <string>
5+
#include <map>
6+
7+
class Patches
8+
{
9+
private:
10+
std::map<std::string, std::string> patches;
11+
std::map<std::string, std::string> signatures;
12+
13+
public:
14+
Patches() {}
15+
16+
void LoadPatches();
17+
void PerformPatch(std::string patch_name);
18+
void PerformPatches();
19+
};
20+
21+
extern Patches *g_Patches;
22+
23+
#endif

0 commit comments

Comments
 (0)