From da7f3e619ec736cdd90da00fd814f39bf7b3377b Mon Sep 17 00:00:00 2001 From: momo5502 Date: Wed, 23 Dec 2015 22:21:03 +0100 Subject: [PATCH] Smooth asset handler --- iw4/Components/AssetHandler.cpp | 85 ++++++++++++++++++++++++++++++++ iw4/Components/AssetHandler.hpp | 22 +++++++++ iw4/Components/Command.cpp | 2 +- iw4/Components/Command.hpp | 2 +- iw4/Components/Loader.cpp | 8 ++- iw4/Components/Loader.hpp | 4 ++ iw4/Components/Logger.cpp | 57 +++++++++++++++++++++ iw4/Components/Logger.hpp | 14 ++++++ iw4/Components/Menus.cpp | 26 ++++++++++ iw4/Components/Menus.hpp | 9 ++++ iw4/Components/MusicalTalent.cpp | 43 ++++++++++++++++ iw4/Components/MusicalTalent.hpp | 15 ++++++ iw4/Components/QuickPatch.cpp | 10 ++++ iw4/Game/Functions.cpp | 5 ++ iw4/Game/Functions.hpp | 12 +++++ iw4/Game/Structs.hpp | 24 +++++++++ iw4/iw4.vcxproj | 8 +++ iw4/iw4.vcxproj.filters | 24 +++++++++ 18 files changed, 366 insertions(+), 4 deletions(-) create mode 100644 iw4/Components/AssetHandler.cpp create mode 100644 iw4/Components/AssetHandler.hpp create mode 100644 iw4/Components/Logger.cpp create mode 100644 iw4/Components/Logger.hpp create mode 100644 iw4/Components/Menus.cpp create mode 100644 iw4/Components/Menus.hpp create mode 100644 iw4/Components/MusicalTalent.cpp create mode 100644 iw4/Components/MusicalTalent.hpp diff --git a/iw4/Components/AssetHandler.cpp b/iw4/Components/AssetHandler.cpp new file mode 100644 index 00000000..1403b8f4 --- /dev/null +++ b/iw4/Components/AssetHandler.cpp @@ -0,0 +1,85 @@ +#include "..\STDInclude.hpp" + +namespace Components +{ + bool AssetHandler::BypassState = false; + std::map AssetHandler::TypeCallbacks; + + Game::XAssetHeader AssetHandler::FindAsset(Game::XAssetType type, const char* filename) + { + Game::XAssetHeader header = nullptr; + + AssetHandler::BypassState = true; + + if (AssetHandler::TypeCallbacks.find(type) != AssetHandler::TypeCallbacks.end()) + { + header = AssetHandler::TypeCallbacks[type](type, filename); + } + + AssetHandler::BypassState = false; + + return header; + } + + void __declspec(naked) AssetHandler::FindAssetStub() + { + __asm + { + push ecx + push ebx + push ebp + push esi + push edi + + // Check if custom handler should be bypassed + xor eax, eax + mov al, AssetHandler::BypassState + + test al, al + jnz finishOriginal + + mov ecx, [esp + 18h] // Asset type + mov ebx, [esp + 1Ch] // Filename + + push ebx + push ecx + + call AssetHandler::FindAsset + + add esp, 8h + + test eax, eax + jnz finishFound + + finishOriginal: + // Asset not found using custom handlers, redirect to DB_FindXAssetHeader + mov ebx, ds:6D7190h // InterlockedDecrement + mov eax, 40793Bh + jmp eax + + finishFound: + + pop edi + pop esi + pop ebp + pop ebx + pop ecx + retn + } + } + + void AssetHandler::On(Game::XAssetType type, AssetHandler::Callback callback) + { + AssetHandler::TypeCallbacks[type] = callback; + } + + AssetHandler::AssetHandler() + { + Utils::Hook(Game::DB_FindXAssetHeader, AssetHandler::FindAssetStub).Install()->Quick(); + } + + AssetHandler::~AssetHandler() + { + AssetHandler::TypeCallbacks.clear(); + } +} diff --git a/iw4/Components/AssetHandler.hpp b/iw4/Components/AssetHandler.hpp new file mode 100644 index 00000000..6848b60c --- /dev/null +++ b/iw4/Components/AssetHandler.hpp @@ -0,0 +1,22 @@ +namespace Components +{ + class AssetHandler : public Component + { + public: + typedef Game::XAssetHeader(*Callback)(Game::XAssetType, const char*); + + AssetHandler(); + ~AssetHandler(); + const char* GetName() { return "AssetHandler"; }; + + static void On(Game::XAssetType type, Callback callback); + + private: + static bool BypassState; + + static Game::XAssetHeader FindAsset(Game::XAssetType type, const char* filename); + static void FindAssetStub(); + + static std::map TypeCallbacks; + }; +} diff --git a/iw4/Components/Command.cpp b/iw4/Components/Command.cpp index 2beb85b4..18e05658 100644 --- a/iw4/Components/Command.cpp +++ b/iw4/Components/Command.cpp @@ -5,7 +5,7 @@ namespace Components std::vector Command::Functions; std::map Command::FunctionMap; - const char* Command::Params::operator[](size_t index) + char* Command::Params::operator[](size_t index) { if (index >= this->Length()) { diff --git a/iw4/Components/Command.hpp b/iw4/Components/Command.hpp index 2059da3c..f1d7c625 100644 --- a/iw4/Components/Command.hpp +++ b/iw4/Components/Command.hpp @@ -9,7 +9,7 @@ namespace Components Params(DWORD id) : CommandId(id) {}; Params(const Params &obj) { this->CommandId = obj.CommandId; }; - const char* operator[](size_t index); + char* operator[](size_t index); size_t Length(); private: diff --git a/iw4/Components/Loader.cpp b/iw4/Components/Loader.cpp index 5b8af67a..c9c5fe54 100644 --- a/iw4/Components/Loader.cpp +++ b/iw4/Components/Loader.cpp @@ -7,7 +7,9 @@ namespace Components void Loader::Initialize() { Loader::Register(new Dvar()); + Loader::Register(new Menus()); Loader::Register(new Colors()); + Loader::Register(new Logger()); Loader::Register(new Window()); Loader::Register(new Command()); Loader::Register(new Console()); @@ -15,13 +17,15 @@ namespace Components Loader::Register(new Renderer()); Loader::Register(new Materials()); Loader::Register(new QuickPatch()); + Loader::Register(new AssetHandler()); + Loader::Register(new MusicalTalent()); } void Loader::Uninitialize() { for (auto component : Loader::Components) { - OutputDebugStringA(Utils::VA("Unregistering component: %s", component->GetName())); + Logger::Print("Unregistering component: %s", component->GetName()); delete component; } @@ -32,7 +36,7 @@ namespace Components { if (component) { - OutputDebugStringA(Utils::VA("Component registered: %s", component->GetName())); + Logger::Print("Component registered: %s", component->GetName()); Loader::Components.push_back(component); } } diff --git a/iw4/Components/Loader.hpp b/iw4/Components/Loader.hpp index f986ae71..c5770462 100644 --- a/iw4/Components/Loader.hpp +++ b/iw4/Components/Loader.hpp @@ -21,7 +21,9 @@ namespace Components } #include "Dvar.hpp" +#include "Menus.hpp" #include "Colors.hpp" +#include "Logger.hpp" #include "Window.hpp" #include "Command.hpp" #include "Console.hpp" @@ -29,3 +31,5 @@ namespace Components #include "Renderer.hpp" #include "Materials.hpp" #include "QuickPatch.hpp" +#include "AssetHandler.hpp" +#include "MusicalTalent.hpp" diff --git a/iw4/Components/Logger.cpp b/iw4/Components/Logger.cpp new file mode 100644 index 00000000..6b2178b2 --- /dev/null +++ b/iw4/Components/Logger.cpp @@ -0,0 +1,57 @@ +#include "..\STDInclude.hpp" + +namespace Components +{ + bool Logger::IsConsoleReady() + { + return (IsWindow(*(HWND*)0x64A3288) != FALSE); + } + + void Logger::Print(const char* message, ...) + { + char buffer[0x1000] = { 0 }; + + va_list ap; + va_start(ap, message); + vsprintf_s(buffer, message, ap); + va_end(ap); + + if (Logger::IsConsoleReady()) + { + Game::Com_Printf(0, "%s", buffer); + } + else + { + OutputDebugStringA(buffer); + } + } + + void Logger::Error(const char* message, ...) + { + char buffer[0x1000] = { 0 }; + + va_list ap; + va_start(ap, message); + vsprintf_s(buffer, message, ap); + va_end(ap); + + Game::Com_Error(0, "%s", buffer); + } + + void Logger::SoftError(const char* message, ...) + { + char buffer[0x1000] = { 0 }; + + va_list ap; + va_start(ap, message); + vsprintf_s(buffer, message, ap); + va_end(ap); + + Game::Com_Error(2, "%s", buffer); + } + + Logger::Logger() + { + + } +} diff --git a/iw4/Components/Logger.hpp b/iw4/Components/Logger.hpp new file mode 100644 index 00000000..81204dab --- /dev/null +++ b/iw4/Components/Logger.hpp @@ -0,0 +1,14 @@ +namespace Components +{ + class Logger : public Component + { + public: + Logger(); + const char* GetName() { return "Logger"; }; + + static void Print(const char* message, ...); + static void Error(const char* message, ...); + static void SoftError(const char* message, ...); + static bool IsConsoleReady(); + }; +} diff --git a/iw4/Components/Menus.cpp b/iw4/Components/Menus.cpp new file mode 100644 index 00000000..7d99f06e --- /dev/null +++ b/iw4/Components/Menus.cpp @@ -0,0 +1,26 @@ +#include "..\STDInclude.hpp" + +namespace Components +{ + Menus::Menus() + { + Command::Add("openmenu", [] (Command::Params params) + { + if (params.Length() != 2) + { + Logger::Print("USAGE: openmenu \n"); + return; + } + + char* menu = params[1]; + + __asm + { + push menu + push 62E2858h + mov eax, 4CCE60h + call eax + } + }); + } +} diff --git a/iw4/Components/Menus.hpp b/iw4/Components/Menus.hpp new file mode 100644 index 00000000..b54472d9 --- /dev/null +++ b/iw4/Components/Menus.hpp @@ -0,0 +1,9 @@ +namespace Components +{ + class Menus : public Component + { + public: + Menus(); + const char* GetName() { return "Menus"; }; + }; +} diff --git a/iw4/Components/MusicalTalent.cpp b/iw4/Components/MusicalTalent.cpp new file mode 100644 index 00000000..4af85982 --- /dev/null +++ b/iw4/Components/MusicalTalent.cpp @@ -0,0 +1,43 @@ +#include "..\STDInclude.hpp" + +namespace Components +{ + std::map MusicalTalent::SoundAliasList; + + void MusicalTalent::Replace(std::string sound, const char* file) + { + MusicalTalent::SoundAliasList[Utils::StrToLower(sound)] = file; + } + + Game::XAssetHeader MusicalTalent::ManipulateAliases(Game::XAssetType type, const char* filename) + { + if (MusicalTalent::SoundAliasList.find(Utils::StrToLower(filename)) != MusicalTalent::SoundAliasList.end()) + { + Game::snd_alias_list_t* aliases = (Game::snd_alias_list_t*)Game::DB_FindXAssetHeader(type, filename); + + if (aliases) + { + if (aliases->aliases->stream->type == 2) + { + aliases->aliases->stream->file = MusicalTalent::SoundAliasList[Utils::StrToLower(filename)]; + } + + return aliases; + } + } + + return NULL; + } + + MusicalTalent::MusicalTalent() + { + AssetHandler::On(Game::XAssetType::ASSET_TYPE_SOUND, MusicalTalent::ManipulateAliases); + + MusicalTalent::Replace("music_mainmenu_mp", "hz_boneyard_intro_LR_1.mp3"); + } + + MusicalTalent::~MusicalTalent() + { + MusicalTalent::SoundAliasList.clear(); + } +} diff --git a/iw4/Components/MusicalTalent.hpp b/iw4/Components/MusicalTalent.hpp new file mode 100644 index 00000000..aece4968 --- /dev/null +++ b/iw4/Components/MusicalTalent.hpp @@ -0,0 +1,15 @@ +namespace Components +{ + class MusicalTalent : public Component + { + public: + MusicalTalent(); + ~MusicalTalent(); + + static void Replace(std::string sound, const char* file); + + private: + static std::map SoundAliasList; + static Game::XAssetHeader ManipulateAliases(Game::XAssetType type, const char* filename); + }; +} diff --git a/iw4/Components/QuickPatch.cpp b/iw4/Components/QuickPatch.cpp index 9f384c36..50d40c96 100644 --- a/iw4/Components/QuickPatch.cpp +++ b/iw4/Components/QuickPatch.cpp @@ -38,6 +38,16 @@ namespace Components // fs_basegame Utils::Hook::Set(0x6431D1, "data"); + // Disable UPNP + Utils::Hook::Nop(0x60BE24, 5); + + // disable the IWNet IP detection (default 'got ipdetect' flag to 1) + Utils::Hook::Set(0x649D6F0, 1); + + // Fix stats sleeping + Utils::Hook::Set(0x6832BA, 0xEB); + Utils::Hook::Set(0x4BD190, 0xC3); + // Why? Game::ReallocateAssetPool(Game::XAssetType::ASSET_TYPE_WEAPON, 2400); } diff --git a/iw4/Game/Functions.cpp b/iw4/Game/Functions.cpp index 26ef3831..44415e90 100644 --- a/iw4/Game/Functions.cpp +++ b/iw4/Game/Functions.cpp @@ -4,6 +4,11 @@ namespace Game { Cmd_AddCommand_t Cmd_AddCommand = (Cmd_AddCommand_t)0x470090; + Com_Error_t Com_Error = (Com_Error_t)0x4B22D0; + Com_Printf_t Com_Printf = (Com_Printf_t)0x402500; + Com_Milliseconds_t Com_Milliseconds = (Com_Milliseconds_t)0x42A660; + + DB_FindXAssetHeader_t DB_FindXAssetHeader = (DB_FindXAssetHeader_t)0x407930; DB_GetXAssetSizeHandler_t* DB_GetXAssetSizeHandlers = (DB_GetXAssetSizeHandler_t*)0x799488; Dvar_RegisterBool_t Dvar_RegisterBool = (Dvar_RegisterBool_t)0x4CE1A0; diff --git a/iw4/Game/Functions.hpp b/iw4/Game/Functions.hpp index 0945c039..1ca8f247 100644 --- a/iw4/Game/Functions.hpp +++ b/iw4/Game/Functions.hpp @@ -3,6 +3,18 @@ namespace Game typedef void(__cdecl * Cmd_AddCommand_t)(const char* name, void(*callback), cmd_function_t* data, char); extern Cmd_AddCommand_t Cmd_AddCommand; + typedef void(__cdecl * Com_Error_t)(int type, char* message, ...); + extern Com_Error_t Com_Error; + + typedef void(__cdecl * Com_Printf_t)(int, const char*, ...); + extern Com_Printf_t Com_Printf; + + typedef int(__cdecl * Com_Milliseconds_t)(void); + extern Com_Milliseconds_t Com_Milliseconds; + + typedef XAssetHeader (__cdecl * DB_FindXAssetHeader_t)(XAssetType type, const char* filename); + extern DB_FindXAssetHeader_t DB_FindXAssetHeader; + typedef int(__cdecl * DB_GetXAssetSizeHandler_t)(); extern DB_GetXAssetSizeHandler_t* DB_GetXAssetSizeHandlers; diff --git a/iw4/Game/Structs.hpp b/iw4/Game/Structs.hpp index 0d246868..e6b995b8 100644 --- a/iw4/Game/Structs.hpp +++ b/iw4/Game/Structs.hpp @@ -48,6 +48,8 @@ namespace Game ASSET_TYPE_MAX = 43 } XAssetType; + typedef void *XAssetHeader; // Temporary + typedef enum { DVAR_FLAG_NONE = 0x0, //no flags @@ -120,4 +122,26 @@ namespace Game { char pad[24]; } cmd_function_t; + + typedef struct + { + char type; + char pad[3]; + const char* folder; + const char* file; + } StreamFile; + + typedef struct + { + char pad[20]; + StreamFile* stream; + char pad2[76]; + } snd_alias_t; + + typedef struct + { + const char* name; + snd_alias_t* aliases; + int numAliases; + } snd_alias_list_t; } diff --git a/iw4/iw4.vcxproj b/iw4/iw4.vcxproj index b6b056ae..8de06f3f 100644 --- a/iw4/iw4.vcxproj +++ b/iw4/iw4.vcxproj @@ -51,12 +51,16 @@ + + + + @@ -77,12 +81,16 @@ + + + + diff --git a/iw4/iw4.vcxproj.filters b/iw4/iw4.vcxproj.filters index 3052697c..b22b9700 100644 --- a/iw4/iw4.vcxproj.filters +++ b/iw4/iw4.vcxproj.filters @@ -98,6 +98,18 @@ Source\Components\Modules + + Source\Components\Modules + + + Source\Components\Modules + + + Source\Components\Modules + + + Source\Components\Modules + @@ -172,5 +184,17 @@ Source\Components\Modules + + Source\Components\Modules + + + Source\Components\Modules + + + Source\Components\Modules + + + Source\Components\Modules + \ No newline at end of file