diff --git a/src/Components/Modules/QuickPatch.cpp b/src/Components/Modules/QuickPatch.cpp index 4672fc79..3038ec76 100644 --- a/src/Components/Modules/QuickPatch.cpp +++ b/src/Components/Modules/QuickPatch.cpp @@ -47,7 +47,7 @@ namespace Components } } - __declspec(naked) void QuickPatch::JavelinResetHookStub() + __declspec(naked) void QuickPatch::JavelinResetHook_Stub() { __asm { @@ -62,7 +62,7 @@ namespace Components } Game::dvar_t* QuickPatch::g_antilag; - __declspec(naked) void QuickPatch::ClientEventsFireWeaponStub() + __declspec(naked) void QuickPatch::ClientEventsFireWeapon_Stub() { __asm { @@ -90,7 +90,7 @@ namespace Components } } - __declspec(naked) void QuickPatch::ClientEventsFireWeaponMeleeStub() + __declspec(naked) void QuickPatch::ClientEventsFireWeaponMelee_Stub() { __asm { @@ -144,7 +144,7 @@ namespace Components Utils::Hook::Set(0x66E1C78, r_customAspectRatio.get()); } - __declspec(naked) void QuickPatch::SetAspectRatioStub() + __declspec(naked) void QuickPatch::SetAspectRatio_Stub() { __asm { @@ -175,7 +175,7 @@ namespace Components } } - BOOL QuickPatch::IsDynClassnameStub(const char* classname) + BOOL QuickPatch::IsDynClassname_Stub(const char* classname) { const auto version = Zones::Version(); @@ -248,10 +248,46 @@ namespace Components } auto workingDir = std::filesystem::current_path().string(); - auto dir = FileSystem::GetAppdataPath() / "data" / "iw4x" / *Game::sys_exitCmdLine; + auto binary = FileSystem::GetAppdataPath() / "data" / "iw4x" / *Game::sys_exitCmdLine; SetEnvironmentVariableA("XLABS_MW2_INSTALL", workingDir.data()); - Utils::Library::LaunchProcess(dir.string(), "-singleplayer", workingDir); + Utils::Library::LaunchProcess(binary.string(), "-singleplayer", workingDir); + } + + __declspec(naked) void QuickPatch::SND_GetAliasOffset_Stub() + { + using namespace Game; + + static const char* msg = "SND_GetAliasOffset: Could not find sound alias '%s'"; + static const DWORD func = 0x4B22D0; // Com_Error + + __asm + { + // Check if snd_alias_t* is null immediately after call to Com_FindSoundAlias_FastFile + test eax, eax + jz error + + // Game code hook skipped + mov ecx, eax + mov edx, dword ptr [ecx + 0x4] + + // Resume function + push 0x437CB2 + ret + + error: + add esp, 0x4 // Com_FindSoundAlias_FastFile takes one argument + + push [esi] // alias->aliasName + push msg + push ERR_DROP + call func // Going to longjmp back to safety + add esp, 0xC + + xor eax, eax + pop esi + ret + } } Game::dvar_t* QuickPatch::Dvar_RegisterConMinicon(const char* dvarName, [[maybe_unused]] bool value, unsigned __int16 flags, const char* description) @@ -267,7 +303,7 @@ namespace Components QuickPatch::QuickPatch() { // Filtering any mapents that is intended for Spec:Ops gamemode (CODO) and prevent them from spawning - Utils::Hook(0x5FBD6E, QuickPatch::IsDynClassnameStub, HOOK_CALL).install()->quick(); + Utils::Hook(0x5FBD6E, QuickPatch::IsDynClassname_Stub, HOOK_CALL).install()->quick(); // Hook escape handling on open console to change behaviour to close the console instead of only canceling autocomplete Utils::Hook(0x4F66A3, CL_KeyEvent_ConsoleEscape_Stub, HOOK_JUMP).install()->quick(); @@ -276,15 +312,15 @@ namespace Components Game::Dvar_RegisterFloat("scr_intermissionTime", 10, 0, 120, Game::DVAR_NONE, "Time in seconds before match server loads the next map"); g_antilag = Game::Dvar_RegisterBool("g_antilag", true, Game::DVAR_CODINFO, "Perform antilag"); - Utils::Hook(0x5D6D56, QuickPatch::ClientEventsFireWeaponStub, HOOK_JUMP).install()->quick(); - Utils::Hook(0x5D6D6A, QuickPatch::ClientEventsFireWeaponMeleeStub, HOOK_JUMP).install()->quick(); + Utils::Hook(0x5D6D56, QuickPatch::ClientEventsFireWeapon_Stub, HOOK_JUMP).install()->quick(); + Utils::Hook(0x5D6D6A, QuickPatch::ClientEventsFireWeaponMelee_Stub, HOOK_JUMP).install()->quick(); // Javelin fix - Utils::Hook(0x578F52, QuickPatch::JavelinResetHookStub, HOOK_JUMP).install()->quick(); + Utils::Hook(0x578F52, QuickPatch::JavelinResetHook_Stub, HOOK_JUMP).install()->quick(); // Add ultrawide support Utils::Hook(0x51B13B, QuickPatch::Dvar_RegisterAspectRatioDvar, HOOK_CALL).install()->quick(); - Utils::Hook(0x5063F3, QuickPatch::SetAspectRatioStub, HOOK_JUMP).install()->quick(); + Utils::Hook(0x5063F3, QuickPatch::SetAspectRatio_Stub, HOOK_JUMP).install()->quick(); Utils::Hook(0x4FA448, QuickPatch::Dvar_RegisterConMinicon, HOOK_CALL).install()->quick(); @@ -293,6 +329,9 @@ namespace Components Utils::Hook::Set(0x41DB8C, "iw4x-sp.exe"); Utils::Hook(0x4D6989, QuickPatch::Sys_SpawnQuitProcess_Hk, HOOK_CALL).install()->quick(); + // Fix crash as nullptr goes unchecked + Utils::Hook(0x437CAD, QuickPatch::SND_GetAliasOffset_Stub, HOOK_JUMP).install()->quick(); + // protocol version (workaround for hacks) Utils::Hook::Set(0x4FB501, PROTOCOL); diff --git a/src/Components/Modules/QuickPatch.hpp b/src/Components/Modules/QuickPatch.hpp index 18de2fa4..64fa0793 100644 --- a/src/Components/Modules/QuickPatch.hpp +++ b/src/Components/Modules/QuickPatch.hpp @@ -12,18 +12,18 @@ namespace Components static void UnlockStats(); private: - static void JavelinResetHookStub(); + static void JavelinResetHook_Stub(); static Dvar::Var r_customAspectRatio; static Game::dvar_t* Dvar_RegisterAspectRatioDvar(const char* dvarName, const char** valueList, int defaultIndex, unsigned __int16 flags, const char* description); - static void SetAspectRatioStub(); + static void SetAspectRatio_Stub(); static void SetAspectRatio(); static Game::dvar_t* g_antilag; - static void ClientEventsFireWeaponStub(); - static void ClientEventsFireWeaponMeleeStub(); + static void ClientEventsFireWeapon_Stub(); + static void ClientEventsFireWeaponMelee_Stub(); - static BOOL IsDynClassnameStub(const char* classname); + static BOOL IsDynClassname_Stub(const char* classname); static void CL_KeyEvent_OnEscape(); static void CL_KeyEvent_ConsoleEscape_Stub(); @@ -32,6 +32,8 @@ namespace Components static void Sys_SpawnQuitProcess_Hk(); + static void SND_GetAliasOffset_Stub(); + static Game::dvar_t* Dvar_RegisterConMinicon(const char* dvarName, bool value, unsigned __int16 flags, const char* description); }; } diff --git a/src/STDInclude.hpp b/src/STDInclude.hpp index 057bd2f5..becd7189 100644 --- a/src/STDInclude.hpp +++ b/src/STDInclude.hpp @@ -107,15 +107,6 @@ using namespace std::literals; static_assert(offsetof(x, y) == (offset), \ #x "::" #y " is not at the right offset. Must be at " #offset) -// Helps the optimizer know code such as default label in a switch statement is unreachable. -// It may generate less assembly (speed increase) if used properly -#define ASSUME(e) ( (assert(0)), __assume(e) ) -#ifdef NDEBUG - #define AssertUnreachable __assume(0) -#else - #define AssertUnreachable ASSUME(0) -#endif - // Protobuf #include "proto/session.pb.h" #include "proto/party.pb.h" diff --git a/src/Utils/Json.cpp b/src/Utils/Json.cpp index 2a0c19f0..6dd8ea9a 100644 --- a/src/Utils/Json.cpp +++ b/src/Utils/Json.cpp @@ -27,7 +27,7 @@ namespace Utils::Json case nlohmann::json::value_t::discarded: return "discarded"; default: - AssertUnreachable; + return "null"; } } }