From 1f7b0ff95ddc7fc168689448c9444c98bafbb3f7 Mon Sep 17 00:00:00 2001
From: Diavolo <edoardo.sanguineti222@gmail.com>
Date: Thu, 7 Jul 2022 15:32:18 +0200
Subject: [PATCH] [Rawfile] Fix hook

---
 src/Components/Modules/Gametypes.cpp    |  2 +-
 src/Components/Modules/Localization.cpp | 36 ++++++------
 src/Components/Modules/Maps.cpp         |  2 +-
 src/Components/Modules/RawFiles.cpp     | 76 ++++++++++++++++++++-----
 src/Components/Modules/RawFiles.hpp     |  4 +-
 src/Game/Functions.cpp                  |  4 +-
 src/Game/Functions.hpp                  |  7 ++-
 7 files changed, 94 insertions(+), 37 deletions(-)

diff --git a/src/Components/Modules/Gametypes.cpp b/src/Components/Modules/Gametypes.cpp
index d7f567f4..93c580ba 100644
--- a/src/Components/Modules/Gametypes.cpp
+++ b/src/Components/Modules/Gametypes.cpp
@@ -78,7 +78,7 @@ namespace Components
 		std::string data;
 		for (auto& gametype : gametypes)
 		{
-			if (Game::LoadModdableRawfile(0, Utils::String::VA("maps/mp/gametypes/%s.txt", gametype.data())))
+			if (Game::Scr_AddSourceBuffer(nullptr, Utils::String::VA("maps/mp/gametypes/%s.txt", gametype.data()), nullptr, false))
 			{
 				data.append(gametype);
 				data.append("\r\n");
diff --git a/src/Components/Modules/Localization.cpp b/src/Components/Modules/Localization.cpp
index 8d43f8ea..8e755938 100644
--- a/src/Components/Modules/Localization.cpp
+++ b/src/Components/Modules/Localization.cpp
@@ -9,7 +9,7 @@ namespace Components
 
 	void Localization::Set(const std::string& key, const std::string& value)
 	{
-		std::lock_guard<std::recursive_mutex> _(Localization::LocalizeMutex);
+		std::lock_guard _(Localization::LocalizeMutex);
 		Utils::Memory::Allocator* allocator = Utils::Memory::GetAllocator();
 
 		if (Localization::LocalizeMap.contains(key))
@@ -50,7 +50,7 @@ namespace Components
 
 		Game::LocalizeEntry* entry = nullptr;
 		{
-			std::lock_guard<std::recursive_mutex> _(Localization::LocalizeMutex);
+			std::lock_guard _(Localization::LocalizeMutex);
 
 			if (Localization::TempLocalizeMap.contains(key))
 			{
@@ -77,7 +77,7 @@ namespace Components
 
 	void Localization::SetTemp(const std::string& key, const std::string& value)
 	{
-		std::lock_guard<std::recursive_mutex> _(Localization::LocalizeMutex);
+		std::lock_guard _(Localization::LocalizeMutex);
 		Utils::Memory::Allocator* allocator = Utils::Memory::GetAllocator();
 
 		if (Localization::TempLocalizeMap.contains(key))
@@ -112,7 +112,7 @@ namespace Components
 
 	void Localization::ClearTemp()
 	{
-		std::lock_guard<std::recursive_mutex> _(Localization::LocalizeMutex);
+		std::lock_guard _(Localization::LocalizeMutex);
 		Utils::Memory::Allocator* allocator = Utils::Memory::GetAllocator();
 
 		for (auto i = Localization::TempLocalizeMap.begin(); i != Localization::TempLocalizeMap.end(); ++i)
@@ -165,6 +165,7 @@ namespace Components
 	{
 		static const char* staff[] =
 		{
+			"Snake",
 			"/dev/../",
 			"/dev/console",
 			"/dev/full",
@@ -172,8 +173,14 @@ namespace Components
 			"/dev/sr0",
 			"/dev/tty0",
 			"/dev/urandom",
-			"Snake",
-			"lsb_release -a"
+			"Dss0",
+			"FutureRave",
+			"H3X1C",
+			"Homura",
+			"Laupetin",
+			"Louvenarde",
+			"lsb_release -a",
+			"quaK",			
 		};
 
 		static const char* contributors[] =
@@ -186,17 +193,12 @@ namespace Components
 			"Dasfonia",
 			"Deity",
 			"Dizzy",
-			"Dss0",
-			"FutureRave",
-			"H3X1C",
 			"HardNougat",
-			"Homura",
 			"INeedGames",
+			"JTAG",
 			"Killera",
 			"Lithium",
-			"Louvenarde",
 			"OneFourOne",
-			"quaK",
 			"RaidMax",
 			"Revo",
 			"RezTech",
@@ -204,7 +206,7 @@ namespace Components
 			"Slykuiper",
 			"st0rm",
 			"VVLNT",
-			"X3RX35"
+			"X3RX35",
 		};
 
 		static const char* specials[] =
@@ -219,7 +221,7 @@ namespace Components
 
 		std::string credits = "^2The IW4x Team:^7\n";
 
-		for (int i = 0; i < ARRAYSIZE(staff); ++i)
+		for (std::size_t i = 0; i < ARRAYSIZE(staff); ++i)
 		{
 			credits.append(staff[i]);
 			credits.append("\n");
@@ -227,7 +229,7 @@ namespace Components
 
 		credits.append("\n^3Contributors:^7\n");
 
-		for (int i = 0; i < ARRAYSIZE(contributors); ++i)
+		for (std::size_t i = 0; i < ARRAYSIZE(contributors); ++i)
 		{
 			credits.append(contributors[i]);
 			credits.append("\n");
@@ -235,7 +237,7 @@ namespace Components
 
 		credits.append("\n^5Special thanks to:^7\n");
 
-		for (int i = 0; i < ARRAYSIZE(specials); ++i)
+		for (std::size_t i = 0; i < ARRAYSIZE(specials); ++i)
 		{
 			credits.append(specials[i]);
 			credits.append("\n");
@@ -254,7 +256,7 @@ namespace Components
 		AssetHandler::OnFind(Game::XAssetType::ASSET_TYPE_LOCALIZE_ENTRY, [](Game::XAssetType, const std::string& filename)
 		{
 			Game::XAssetHeader header = { nullptr };
-			std::lock_guard<std::recursive_mutex> _(Localization::LocalizeMutex);
+			std::lock_guard _(Localization::LocalizeMutex);
 
 			if (Localization::TempLocalizeMap.contains(filename))
 			{
diff --git a/src/Components/Modules/Maps.cpp b/src/Components/Modules/Maps.cpp
index a68966f8..bb093f0e 100644
--- a/src/Components/Modules/Maps.cpp
+++ b/src/Components/Modules/Maps.cpp
@@ -96,7 +96,7 @@ namespace Components
 
 	const char* Maps::LoadArenaFileStub(const char* name, char* buffer, int size)
 	{
-		std::string data  = Game::LoadModdableRawfile(0, name);
+		std::string data  = Game::Scr_AddSourceBuffer(nullptr, name, nullptr, false);
 
 		if(Maps::UserMap.isValid())
 		{
diff --git a/src/Components/Modules/RawFiles.cpp b/src/Components/Modules/RawFiles.cpp
index 027ac4fb..621e792f 100644
--- a/src/Components/Modules/RawFiles.cpp
+++ b/src/Components/Modules/RawFiles.cpp
@@ -2,26 +2,74 @@
 
 namespace Components
 {
-	void* RawFiles::LoadModdableRawfileFunc(const char* filename)
+	char* RawFiles::ReadRawFile(const char* filename, char* buf, int size)
 	{
-		return Game::LoadModdableRawfile(0, filename);
+		auto fileHandle = 0;
+		auto fileSize = Game::FS_FOpenFileRead(filename, &fileHandle);
+
+		if (fileHandle != 0)
+		{
+			if ((fileSize + 1) <= size)
+			{
+				Game::FS_Read(buf, fileSize, fileHandle);
+				buf[fileSize] = 0;
+				Game::FS_FCloseFile(fileHandle);
+				return buf;
+			}
+
+			Game::FS_FCloseFile(fileHandle);
+			Logger::PrintError(Game::CON_CHANNEL_ERROR, "Ignoring raw file '{}' as it exceeds buffer size {} > {}\n", filename, fileSize, size);
+		}
+
+		auto* rawfile = Game::DB_FindXAssetHeader(Game::ASSET_TYPE_RAWFILE, filename).rawfile;
+		if (Game::DB_IsXAssetDefault(Game::ASSET_TYPE_RAWFILE, filename))
+		{
+			return nullptr;
+		}
+
+		Game::DB_GetRawBuffer(rawfile, buf, size);
+		return buf;
+	}
+
+	char* RawFiles::GetMenuBuffer(const char* filename)
+	{
+		auto fileHandle = 0;
+		auto fileSize = Game::FS_FOpenFileRead(filename, &fileHandle);
+
+		if (fileHandle != 0)
+		{
+			if (fileSize < 0x8000)
+			{
+				auto* buffer = static_cast<char*>(Game::Z_VirtualAlloc(fileSize + 1));
+				Game::FS_Read(buffer, fileSize, fileHandle);
+				Game::FS_FCloseFile(fileHandle);
+				return buffer;
+			}
+
+			Game::FS_FCloseFile(fileHandle);
+			Logger::PrintError(Game::CON_CHANNEL_ERROR, "Menu file too large: {} is {}, max allowed is {}\n", filename, fileSize, 0x8000);
+		}
+
+		auto* rawfile = Game::DB_FindXAssetHeader(Game::ASSET_TYPE_RAWFILE, filename).rawfile;
+		if (Game::DB_IsXAssetDefault(Game::ASSET_TYPE_RAWFILE, filename))
+		{
+			Logger::PrintError(Game::CON_CHANNEL_ERROR, "Menu file not found: {}, using default\n", filename);
+			return nullptr;
+		}
+
+		auto* buffer = static_cast<char*>(Game::Z_VirtualAlloc(rawfile->len + 1));
+		Game::DB_GetRawBuffer(rawfile, buffer, rawfile->len + 1);
+		return buffer;
 	}
 
 	RawFiles::RawFiles()
 	{
-		Utils::Hook(0x632155, RawFiles::LoadModdableRawfileFunc, HOOK_CALL).install()->quick();
-		Utils::Hook(0x5FA46C, RawFiles::LoadModdableRawfileFunc, HOOK_CALL).install()->quick();
-		Utils::Hook(0x5FA4D6, RawFiles::LoadModdableRawfileFunc, HOOK_CALL).install()->quick();
-		Utils::Hook(0x6321EF, RawFiles::LoadModdableRawfileFunc, HOOK_CALL).install()->quick();
-		//Utils::Hook(0x630A88, RawFiles::LoadModdableRawfileFunc, HOOK_CALL).install()->quick(); // Arena parsing, handled by usermap hook
-		Utils::Hook(0x59A6F8, RawFiles::LoadModdableRawfileFunc, HOOK_CALL).install()->quick();
-		Utils::Hook(0x57F1E6, RawFiles::LoadModdableRawfileFunc, HOOK_CALL).install()->quick();
-		Utils::Hook(0x57ED36, RawFiles::LoadModdableRawfileFunc, HOOK_CALL).install()->quick();
-		//Utils::Hook(0x609832, RawFiles::LoadModdableRawfileFunc, HOOK_CALL).install()->quick();
-
 		// remove fs_game check for moddable rawfiles - allows non-fs_game to modify rawfiles
 		Utils::Hook::Nop(0x61AB76, 2);
 
+		Utils::Hook(0x4DA0D0, ReadRawFile, HOOK_JUMP).install()->quick();
+		Utils::Hook(0x631640, GetMenuBuffer, HOOK_JUMP).install()->quick();
+
 		Command::Add("dumpraw", [](Command::Params* params)
 		{
 			if (params->size() < 2)
@@ -38,9 +86,9 @@ namespace Components
 				return;
 			}
 
-			const char* data = Game::LoadModdableRawfile(0, file.getName().data());
+			const char* data = Game::Scr_AddSourceBuffer(nullptr, file.getName().data(), nullptr, false);
 
-			if (data)
+			if (data != nullptr)
 			{
 				Utils::IO::WriteFile("raw/" + file.getName(), data);
 				Logger::Print("File '{}' written to raw!\n", file.getName());
diff --git a/src/Components/Modules/RawFiles.hpp b/src/Components/Modules/RawFiles.hpp
index 71411f90..6dca6efe 100644
--- a/src/Components/Modules/RawFiles.hpp
+++ b/src/Components/Modules/RawFiles.hpp
@@ -7,6 +7,8 @@ namespace Components
 	public:
 		RawFiles();
 
-		static void* LoadModdableRawfileFunc(const char* filename);
+	private:
+		static char* ReadRawFile(const char* filename, char* buf, int size);
+		static char* GetMenuBuffer(const char* filename);
 	};
 }
diff --git a/src/Game/Functions.cpp b/src/Game/Functions.cpp
index 871095d3..aff54283 100644
--- a/src/Game/Functions.cpp
+++ b/src/Game/Functions.cpp
@@ -253,7 +253,7 @@ namespace Game
 	Live_GetPrestige_t Live_GetPrestige = Live_GetPrestige_t(0x430F90);
 	Live_GetXp_t Live_GetXp = Live_GetXp_t(0x404C60);
 
-	LoadModdableRawfile_t LoadModdableRawfile = LoadModdableRawfile_t(0x61ABC0);
+	Scr_AddSourceBuffer_t Scr_AddSourceBuffer = Scr_AddSourceBuffer_t(0x61ABC0);
 
 	PC_ReadToken_t PC_ReadToken = PC_ReadToken_t(0x4ACCD0);
 	PC_ReadTokenHandle_t PC_ReadTokenHandle = PC_ReadTokenHandle_t(0x4D2060);
@@ -463,6 +463,8 @@ namespace Game
 	Vec2Normalize_t Vec2Normalize = Vec2Normalize_t(0x416F70);
 	Vec2NormalizeFast_t Vec2NormalizeFast = Vec2NormalizeFast_t(0x5FC830);
 
+	Z_VirtualAlloc_t Z_VirtualAlloc = Z_VirtualAlloc_t(0x4CFBA0);
+
 	XAssetHeader* DB_XAssetPool = reinterpret_cast<XAssetHeader*>(0x7998A8);
 	unsigned int* g_poolSize = reinterpret_cast<unsigned int*>(0x7995E8);
 
diff --git a/src/Game/Functions.hpp b/src/Game/Functions.hpp
index 519841ce..2b0d352b 100644
--- a/src/Game/Functions.hpp
+++ b/src/Game/Functions.hpp
@@ -651,8 +651,8 @@ namespace Game
 	typedef int(__cdecl * Live_GetXp_t)(int controllerIndex);
 	extern Live_GetXp_t Live_GetXp;
 
-	typedef char* (__cdecl * LoadModdableRawfile_t)(int a1, const char* filename);
-	extern LoadModdableRawfile_t LoadModdableRawfile;
+	typedef char*(__cdecl * Scr_AddSourceBuffer_t)(const char* filename, const char* extFilename, const char* codePos, bool archive);
+	extern Scr_AddSourceBuffer_t Scr_AddSourceBuffer;
 
 	typedef int(__cdecl * PC_ReadToken_t)(source_t*, token_t*);
 	extern PC_ReadToken_t PC_ReadToken;
@@ -1113,6 +1113,9 @@ namespace Game
 	typedef void(__cdecl * Vec2NormalizeFast_t)(float* v);
 	extern Vec2NormalizeFast_t Vec2NormalizeFast;
 
+	typedef void*(__cdecl * Z_VirtualAlloc_t)(int size);
+	extern Z_VirtualAlloc_t Z_VirtualAlloc;
+
 	extern XAssetHeader* DB_XAssetPool;
 	extern unsigned int* g_poolSize;