From 2a5f9f439c1f16d13f6f8674f80e3d2bd7cbcee9 Mon Sep 17 00:00:00 2001 From: Silent Date: Wed, 8 May 2024 23:12:24 +0200 Subject: [PATCH] III: Clean up the pickup object when reusing a temporary slot Fixes #21 --- SilentPatchIII/SilentPatchIII.cpp | 57 +++++++++++++++++++++++++++---- 1 file changed, 51 insertions(+), 6 deletions(-) diff --git a/SilentPatchIII/SilentPatchIII.cpp b/SilentPatchIII/SilentPatchIII.cpp index 9e7b99d..86f2874 100644 --- a/SilentPatchIII/SilentPatchIII.cpp +++ b/SilentPatchIII/SilentPatchIII.cpp @@ -58,14 +58,13 @@ static void (*DrawRect)(const CRect&,const CRGBA&); static int* InstantHitsFiredByPlayer; static const void* HeadlightsFix_JumpBack; - -void (__stdcall *AudioResetTimers)(unsigned int); - static bool* bWantsToDrawHud; static bool* bCamCheck; static RsGlobalType* RsGlobal; static const void* SubtitlesShadowFix_JumpBack; +auto WorldRemove = reinterpret_cast(hook::get_pattern("8A 43 50 56 24 07", -5)); + static const float& ResolutionWidthMult = **AddressByVersion(0x57E956, 0x57ECA6, 0x57EBA6); inline float GetWidthMult() { @@ -728,6 +727,44 @@ namespace VariableResets } +// ============= Clean up the pickup object when reusing a temporary slot ============= +// This has been fixed in VC/SA +namespace GenerateNewPickup_ReuseObjectFix +{ + static void* pPickupObject; + static void (*orgGiveUsAPickUpObject)(int); + + __declspec(naked) void GiveUsAPickUpObject_CleanUpObject() + { + _asm + { + mov eax, [pPickupObject] + add eax, ebp + mov eax, [eax] + test eax, eax + jz NoPickup + push edi + mov edi, eax + + push edi + call [WorldRemove] + add esp, 4 + + // Call dtor + mov ecx, edi + mov eax, [edi] + push 1 + call dword ptr [eax] + + pop edi + + NoPickup: + jmp [orgGiveUsAPickUpObject] + } + } +} + + void InjectDelayedPatches_III_Common( bool bHasDebugMenu, const wchar_t* wcModulePath ) { using namespace Memory; @@ -912,7 +949,6 @@ void Patch_III_10(uint32_t width, uint32_t height) using namespace Memory::DynBase; DrawRect = (void(*)(const CRect&,const CRGBA&))DynBaseAddress(0x51F970); - AudioResetTimers = (void(__stdcall*)(unsigned int))DynBaseAddress(0x57CCD0); InstantHitsFiredByPlayer = *(int**)DynBaseAddress(0x482C8F); bWantsToDrawHud = *(bool**)DynBaseAddress(0x4A5877); @@ -1040,7 +1076,6 @@ void Patch_III_11(uint32_t width, uint32_t height) using namespace Memory::DynBase; DrawRect = (void(*)(const CRect&,const CRGBA&))DynBaseAddress(0x51FBA0); - AudioResetTimers = (void(__stdcall*)(unsigned int))DynBaseAddress(0x57CCC0); InstantHitsFiredByPlayer = *(int**)DynBaseAddress(0x482D5F); bWantsToDrawHud = *(bool**)DynBaseAddress(0x4A5967); @@ -1147,7 +1182,6 @@ void Patch_III_Steam(uint32_t width, uint32_t height) using namespace Memory::DynBase; DrawRect = (void(*)(const CRect&,const CRGBA&))DynBaseAddress(0x51FB30); - AudioResetTimers = (void(__stdcall*)(unsigned int))DynBaseAddress(0x57CF20); InstantHitsFiredByPlayer = *(int**)DynBaseAddress(0x482D5F); bWantsToDrawHud = *(bool**)DynBaseAddress(0x4A58F7); @@ -1590,6 +1624,17 @@ void Patch_III_Common() GameVariablesToReset.emplace_back(*get_pattern("7D 72 A1 ? ? ? ? 05", 2 + 1)); // LastTimeAmbulanceCreated GameVariablesToReset.emplace_back(*get_pattern("74 7F A1 ? ? ? ? 05", 2 + 1)); // LastTimeFireTruckCreated } + + + // Clean up the pickup object when reusing a temporary slot + { + using namespace GenerateNewPickup_ReuseObjectFix; + + auto give_us_a_pick_up_object = pattern("6A FF E8 ? ? ? ? 89 85").get_one(); + + pPickupObject = *give_us_a_pick_up_object.get(7 + 2); + InterceptCall(give_us_a_pick_up_object.get(2), orgGiveUsAPickUpObject, GiveUsAPickUpObject_CleanUpObject); + } } BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)