diff --git a/DDraw/DDraw.vcxproj b/DDraw/DDraw.vcxproj
index 8acacba..9b253a6 100644
--- a/DDraw/DDraw.vcxproj
+++ b/DDraw/DDraw.vcxproj
@@ -75,7 +75,6 @@
true
..\SilentPatch;..\DDraw;%(AdditionalIncludeDirectories)
_HAS_EXCEPTIONS=0;%(PreprocessorDefinitions)
- false
MultiThreadedDebug
NoExtensions
true
@@ -107,7 +106,6 @@ copy /y "$(TargetPath)" "D:\Steam\steamapps\common\Grand Theft Auto Vice City\dd
..\SilentPatch;..\DDraw;%(AdditionalIncludeDirectories)
_HAS_EXCEPTIONS=0;%(PreprocessorDefinitions)
true
- false
MultiThreaded
NoExtensions
true
@@ -141,7 +139,6 @@ copy /y "$(TargetPath)" "D:\Steam\steamapps\common\Grand Theft Auto Vice City\dd
..\SilentPatch;..\DDraw;%(AdditionalIncludeDirectories)
_HAS_EXCEPTIONS=0;NDEBUG;%(PreprocessorDefinitions)
true
- false
MultiThreaded
NoExtensions
true
diff --git a/SilentPatch/Common.cpp b/SilentPatch/Common.cpp
index f1741ee..0dc0307 100644
--- a/SilentPatch/Common.cpp
+++ b/SilentPatch/Common.cpp
@@ -208,30 +208,38 @@ namespace Common {
void III_VC_Common()
{
using namespace Memory;
- using namespace hook;
+ using namespace hook::txn;
// Delayed patching
+ try
{
using namespace DelayedPatches;
auto addr_mssHook = get_pattern( "6A 00 6A 02 6A 10 68 00 7D 00 00", -6 + 2 );
+ auto addr_ualHook = get_pattern( "FF 15 ? ? ? ? 6A 00 6A 18", 0xA );
+
OldSetPreference = *static_cast(addr_mssHook);
Patch( addr_mssHook, &pInjectMSS );
- auto addr_ualHook = get_pattern( "FF 15 ? ? ? ? 6A 00 6A 18", 0xA );
ReadCall( addr_ualHook, RsEventHandler );
InjectHook( addr_ualHook, Inject_UAL );
}
+ TXN_CATCH();
+
// Fixed bomb ownership/bombs saving for bikes
+ try
{
auto addr = get_pattern( "83 3C 33 00 74 19 89 F9 E8", 8 );
ReadCall( addr, CStoredCar::orgRestoreCar );
InjectHook( addr, &CStoredCar::RestoreCar_SilentPatch );
}
+ TXN_CATCH();
+
// Fixed handling.cfg name matching (names don't need unique prefixes anymore)
+ try
{
using namespace HandlingNameLoadFix;
@@ -240,9 +248,11 @@ namespace Common {
InjectHook( findExactWord.get( -5 ), strncpy_Fix );
InjectHook( findExactWord.get( 0xD ), strncmp_Fix );
}
+ TXN_CATCH();
// Fixed corona lines rendering on non-nvidia cards
+ try
{
using namespace CoronaLinesFix;
@@ -250,9 +260,11 @@ namespace Common {
InterceptCall(renderLine, orgRwIm2DRenderLine, RenderLine_SetRecipZ);
}
+ TXN_CATCH();
// Fixed static shadows not rendering under fire and pickups
+ try
{
using namespace StaticShadowAlphaFix;
@@ -281,9 +293,11 @@ namespace Common {
HookEach_StoreAlphaTest(disableAlphaTestAndSetState, InterceptCall);
HookEach_RestoreAlphaTest(setStateAndReenableAlphaTest, InterceptCall);
}
+ TXN_CATCH();
// Reset requested extras if created vehicle has no extras
+ try
{
using namespace CompsToUseFix;
@@ -291,10 +305,12 @@ namespace Common {
InjectHook( resetComps.get( -14 ), ResetCompsForNoExtras, HookType::Call );
Nop( resetComps.get( -9 ), 9 );
}
+ TXN_CATCH();
// Rescale light switching randomness in CAutomobile::PreRender/CBike::PreRender for PC the randomness range
// The original randomness was 50000 out of 65535, which is impossible to hit with PC's 32767 range
+ try
{
// GTA III expects 2 matches, VC expects 4 due to the addition of CBike::PreRender
#if _GTA_III
@@ -310,9 +326,11 @@ namespace Common {
Patch(match.get(2), &LightStatusRandomnessThreshold);
});
}
+ TXN_CATCH();
// Make script randomness 16-bit, like on PS2
+ try
{
using namespace Rand16bit;
@@ -323,6 +341,7 @@ namespace Common {
HookEach_Rand(rands, InterceptCall);
}
+ TXN_CATCH();
}
void III_VC_SetDelayedPatchesFunc( void(*func)() )
@@ -333,24 +352,21 @@ namespace Common {
void III_VC_DelayedCommon( bool /*hasDebugMenu*/, const wchar_t* wcModulePath )
{
using namespace Memory;
- using namespace hook;
+ using namespace hook::txn;
ExtraCompSpecularity::ReadExtraCompSpecularityExceptions(wcModulePath);
// Corrected taxi light placement for Taxi
- if ( GetPrivateProfileIntW(L"SilentPatch", L"EnableVehicleCoronaFixes", -1, wcModulePath) == 1 )
+ if ( GetPrivateProfileIntW(L"SilentPatch", L"EnableVehicleCoronaFixes", -1, wcModulePath) == 1 ) try
{
using namespace TaxiCoronaFix;
- auto getTaxiLightPos = pattern( "E8 ? ? ? ? D9 84 24 ? ? ? ? D8 84 24 ? ? ? ? 83 C4 0C FF 35" );
+ auto getTaxiLightPos = pattern( "E8 ? ? ? ? D9 84 24 ? ? ? ? D8 84 24 ? ? ? ? 83 C4 0C FF 35" ).get_one();
- if ( getTaxiLightPos.count_hint(1).size() == 1 )
- {
- auto match = getTaxiLightPos.get_one();
- Patch( match.get( -15 ), 0x55 ); // push eax -> push ebp
- InjectHook( match.get(), GetTransformedCoronaPos );
- }
+ Patch( getTaxiLightPos.get( -15 ), 0x55 ); // push eax -> push ebp
+ InjectHook( getTaxiLightPos.get(), GetTransformedCoronaPos );
}
+ TXN_CATCH();
}
}
}
\ No newline at end of file
diff --git a/SilentPatch/Common_ddraw.cpp b/SilentPatch/Common_ddraw.cpp
index 652ab72..62e1240 100644
--- a/SilentPatch/Common_ddraw.cpp
+++ b/SilentPatch/Common_ddraw.cpp
@@ -39,25 +39,37 @@ namespace Common {
namespace Patches {
- bool FixRwcseg_Patterns()
+ bool FixRwcseg_Patterns() try
{
- using namespace hook;
+ using namespace hook::txn;
- auto begin = pattern( "55 8B EC 50 53 51 52 8B 5D 14 8B 4D 10 8B 45 0C 8B 55 08" );
- auto end = pattern( "9B D9 3D ? ? ? ? 81 25 ? ? ? ? FF FC FF FF 83 0D ? ? ? ? 3F" );
+ // _rwcseg can be placed far after the code section, and the default pattern heuristics currently break with it
+ // (it's only using SizeOfCode instead of scanning all code sections).
+ // To fix this, explicitly scan the entire module
+ const uintptr_t module = reinterpret_cast(GetModuleHandle(nullptr));
+ PIMAGE_DOS_HEADER dosHeader = reinterpret_cast(module);
+ PIMAGE_NT_HEADERS ntHeader = reinterpret_cast(module + dosHeader->e_lfanew);
- if ( begin.count_hint(1).size() == 1 && end.count_hint(1).size() == 1 )
+ const uintptr_t sizeOfHeaders = ntHeader->OptionalHeader.SizeOfHeaders;
+ const uintptr_t moduleBegin = module + sizeOfHeaders;
+ const uintptr_t moduleEnd = module + (ntHeader->OptionalHeader.SizeOfImage - sizeOfHeaders);
+
+ auto begin = make_range_pattern(moduleBegin, moduleEnd, "55 8B EC 50 53 51 52 8B 5D 14 8B 4D 10 8B 45 0C 8B 55 08").get_first();
+ auto end = make_range_pattern(moduleBegin, moduleEnd, "9B D9 3D ? ? ? ? 81 25 ? ? ? ? FF FC FF FF 83 0D ? ? ? ? 3F").get_first(31);
+
+ const ptrdiff_t size = reinterpret_cast(end) - reinterpret_cast(begin);
+ if ( size > 0 )
{
- const ptrdiff_t size = (intptr_t)end.get_first( 24 ) - (intptr_t)begin.get_first();
- if ( size > 0 )
- {
- DWORD dwProtect;
- VirtualProtect( begin.get_first(), size, PAGE_EXECUTE_READ, &dwProtect );
- return true;
- }
+ DWORD dwProtect;
+ VirtualProtect( begin, size, PAGE_EXECUTE_READ, &dwProtect );
+ return true;
}
return false;
}
+ catch (const hook::txn_exception&)
+ {
+ return false;
+ }
// ================= III =================
void DDraw_III_10( uint32_t width, uint32_t height, const char* desktopText )
@@ -207,38 +219,34 @@ namespace Common {
void DDraw_Common()
{
using namespace Memory;
- using namespace hook;
+ using namespace hook::txn;
// Remove FILE_FLAG_NO_BUFFERING from CdStreams
+ try
{
- auto mem = pattern( "81 7C 24 04 00 08 00 00" ).count_hint(1);
- if ( mem.size() == 1 )
- {
- Patch( mem.get_first( 0x12 ), 0xEB );
- }
+ auto mem = get_pattern("81 7C 24 04 00 08 00 00", 0x12);
+ Patch( mem, 0xEB );
}
+ TXN_CATCH();
// No censorships
+ try
{
- auto addr = pattern( "83 FB 07 74 0A 83 FD 07 74 05 83 FE 07 75 15" ).count_hint(1);
- if ( addr.size() == 1 )
- {
- Patch( addr.get_first(), { 0xEB, 0x5E } );
- }
-
+ auto addr = get_pattern( "83 FB 07 74 0A 83 FD 07 74 05 83 FE 07 75 15" );
+ Patch( addr, { 0xEB, 0x5E } );
}
+ TXN_CATCH();
// unnamed CdStream semaphore
+ try
{
- auto mem = pattern( "8D 04 85 00 00 00 00 50 6A 40 FF 15" ).count_hint(1);
- if ( mem.size() == 1 )
- {
- Patch( mem.get_first( 0x25 ), { 0x6A, 0x00 } ); // push 0 \ nop
- Nop( mem.get_first( 0x25 + 2 ), 3 );
- }
-
+ auto mem = pattern( "8D 04 85 00 00 00 00 50 6A 40 FF 15" ).get_one();
+
+ Patch( mem.get( 0x25 ), { 0x6A, 0x00 } ); // push 0 \ nop
+ Nop( mem.get( 0x25 + 2 ), 3 );
}
+ TXN_CATCH();
}
}
}
\ No newline at end of file
diff --git a/SilentPatchIII/SilentPatchIII.cpp b/SilentPatchIII/SilentPatchIII.cpp
index 308be88..56fc348 100644
--- a/SilentPatchIII/SilentPatchIII.cpp
+++ b/SilentPatchIII/SilentPatchIII.cpp
@@ -842,7 +842,7 @@ namespace SitInBoat
void InjectDelayedPatches_III_Common( bool bHasDebugMenu, const wchar_t* wcModulePath )
{
using namespace Memory;
- using namespace hook;
+ using namespace hook::txn;
const ModuleList moduleList;
@@ -876,135 +876,124 @@ void InjectDelayedPatches_III_Common( bool bHasDebugMenu, const wchar_t* wcModul
}
// Make crane be unable to lift Coach instead of Blista
+ try
{
// There is a possible incompatibility with limit adjusters, so patch it in a delayed hook point and gracefully handle failure
- auto canPickBlista = pattern( "83 FA 66 74" ).count_hint(1);
- if ( canPickBlista.size() == 1 )
- {
- Patch( canPickBlista.get_first( 2 ), 127 ); // coach
- }
+ auto canPickBlista = get_pattern("83 FA 66 74", 2);
+ Patch( canPickBlista, 127 ); // coach
}
+ TXN_CATCH();
// Corrected siren corona placement for emergency vehicles
if ( GetPrivateProfileIntW(L"SilentPatch", L"EnableVehicleCoronaFixes", -1, wcModulePath) == 1 )
{
// Other mods might be touching it, so only patch specific vehicles if their code has not been touched at all
+ try
{
- auto firetruckX1 = pattern( "C7 84 24 9C 05 00 00 CD CC 8C 3F" );
- auto firetruckY1 = pattern( "C7 84 24 A4 05 00 00 9A 99 D9 3F" );
- auto firetruckZ1 = pattern( "C7 84 24 A8 05 00 00 00 00 00 40" );
+ auto firetruckX1 = get_pattern("C7 84 24 9C 05 00 00 CD CC 8C 3F", 7);
+ auto firetruckY1 = get_pattern("C7 84 24 A4 05 00 00 9A 99 D9 3F", 7);
+ auto firetruckZ1 = get_pattern("C7 84 24 A8 05 00 00 00 00 00 40", 7);
- auto firetruckX2 = pattern( "C7 84 24 A8 05 00 00 CD CC 8C BF" );
- auto firetruckY2 = pattern( "C7 84 24 B0 05 00 00 9A 99 D9 3F" );
- auto firetruckZ2 = pattern( "C7 84 24 B4 05 00 00 00 00 00 40" );
+ auto firetruckX2 = get_pattern("C7 84 24 A8 05 00 00 CD CC 8C BF", 7);
+ auto firetruckY2 = get_pattern("C7 84 24 B0 05 00 00 9A 99 D9 3F", 7);
+ auto firetruckZ2 = get_pattern("C7 84 24 B4 05 00 00 00 00 00 40", 7);
- if ( firetruckX1.count_hint(1).size() == 1 && firetruckY1.count_hint(1).size() == 1 && firetruckZ1.count_hint(1).size() == 1 &&
- firetruckX2.count_hint(1).size() == 1 && firetruckY2.count_hint(1).size() == 1 && firetruckZ2.count_hint(1).size() == 1 )
- {
- constexpr CVector FIRETRUCK_SIREN_POS(0.95f, 3.2f, 1.4f);
+ constexpr CVector FIRETRUCK_SIREN_POS(0.95f, 3.2f, 1.4f);
- Patch( firetruckX1.get_first( 7 ), FIRETRUCK_SIREN_POS.x );
- Patch( firetruckY1.get_first( 7 ), FIRETRUCK_SIREN_POS.y );
- Patch( firetruckZ1.get_first( 7 ), FIRETRUCK_SIREN_POS.z );
+ Patch( firetruckX1, FIRETRUCK_SIREN_POS.x );
+ Patch( firetruckY1, FIRETRUCK_SIREN_POS.y );
+ Patch( firetruckZ1, FIRETRUCK_SIREN_POS.z );
- Patch( firetruckX2.get_first( 7 ), -FIRETRUCK_SIREN_POS.x );
- Patch( firetruckY2.get_first( 7 ), FIRETRUCK_SIREN_POS.y );
- Patch( firetruckZ2.get_first( 7 ), FIRETRUCK_SIREN_POS.z );
- }
+ Patch( firetruckX2, -FIRETRUCK_SIREN_POS.x );
+ Patch( firetruckY2, FIRETRUCK_SIREN_POS.y );
+ Patch( firetruckZ2, FIRETRUCK_SIREN_POS.z );
}
+ TXN_CATCH();
+
+ try
{
- auto ambulanceX1 = pattern( "C7 84 24 84 05 00 00 CD CC 8C 3F" );
- auto ambulanceY1 = pattern( "C7 84 24 8C 05 00 00 66 66 66 3F" );
- auto ambulanceZ1 = pattern( "C7 84 24 90 05 00 00 CD CC CC 3F" );
+ auto ambulanceX1 = get_pattern("C7 84 24 84 05 00 00 CD CC 8C 3F", 7);
+ auto ambulanceY1 = get_pattern("C7 84 24 8C 05 00 00 66 66 66 3F", 7);
+ auto ambulanceZ1 = get_pattern("C7 84 24 90 05 00 00 CD CC CC 3F", 7);
- auto ambulanceX2 = pattern( "C7 84 24 90 05 00 00 CD CC 8C BF" );
- auto ambulanceY2 = pattern( "C7 84 24 98 05 00 00 66 66 66 3F" );
- auto ambulanceZ2 = pattern( "C7 84 24 9C 05 00 00 CD CC CC 3F" );
+ auto ambulanceX2 = get_pattern("C7 84 24 90 05 00 00 CD CC 8C BF", 7);
+ auto ambulanceY2 = get_pattern("C7 84 24 98 05 00 00 66 66 66 3F", 7);
+ auto ambulanceZ2 = get_pattern("C7 84 24 9C 05 00 00 CD CC CC 3F", 7);
- if ( ambulanceX1.count_hint(1).size() == 1 && ambulanceY1.count_hint(1).size() == 1 && ambulanceZ1.count_hint(1).size() == 1 &&
- ambulanceX2.count_hint(1).size() == 1 && ambulanceY2.count_hint(1).size() == 1 && ambulanceZ2.count_hint(1).size() == 1 )
- {
- constexpr CVector AMBULANCE_SIREN_POS(0.7f, 0.65f, 1.55f);
+ constexpr CVector AMBULANCE_SIREN_POS(0.7f, 0.65f, 1.55f);
- Patch( ambulanceX1.get_first( 7 ), AMBULANCE_SIREN_POS.x );
- Patch( ambulanceY1.get_first( 7 ), AMBULANCE_SIREN_POS.y );
- Patch( ambulanceZ1.get_first( 7 ), AMBULANCE_SIREN_POS.z );
+ Patch( ambulanceX1, AMBULANCE_SIREN_POS.x );
+ Patch( ambulanceY1, AMBULANCE_SIREN_POS.y );
+ Patch( ambulanceZ1, AMBULANCE_SIREN_POS.z );
- Patch( ambulanceX2.get_first( 7 ), -AMBULANCE_SIREN_POS.x );
- Patch( ambulanceY2.get_first( 7 ), AMBULANCE_SIREN_POS.y );
- Patch( ambulanceZ2.get_first( 7 ), AMBULANCE_SIREN_POS.z );
- }
+ Patch( ambulanceX2, -AMBULANCE_SIREN_POS.x );
+ Patch( ambulanceY2, AMBULANCE_SIREN_POS.y );
+ Patch( ambulanceZ2, AMBULANCE_SIREN_POS.z );
}
+ TXN_CATCH();
+
+ try
{
- auto enforcerX1 = pattern( "C7 84 24 6C 05 00 00 CD CC 8C 3F" );
- auto enforcerY1 = pattern( "C7 84 24 74 05 00 00 CD CC 4C 3F" );
- auto enforcerZ1 = pattern( "C7 84 24 78 05 00 00 9A 99 99 3F" );
+ auto enforcerX1 = get_pattern("C7 84 24 6C 05 00 00 CD CC 8C 3F", 7);
+ auto enforcerY1 = get_pattern("C7 84 24 74 05 00 00 CD CC 4C 3F", 7);
+ auto enforcerZ1 = get_pattern("C7 84 24 78 05 00 00 9A 99 99 3F", 7);
- auto enforcerX2 = pattern( "C7 84 24 78 05 00 00 CD CC 8C BF" );
- auto enforcerY2 = pattern( "C7 84 24 80 05 00 00 CD CC 4C 3F" );
- auto enforcerZ2 = pattern( "C7 84 24 84 05 00 00 9A 99 99 3F" );
+ auto enforcerX2 = get_pattern("C7 84 24 78 05 00 00 CD CC 8C BF", 7);
+ auto enforcerY2 = get_pattern("C7 84 24 80 05 00 00 CD CC 4C 3F", 7);
+ auto enforcerZ2 = get_pattern("C7 84 24 84 05 00 00 9A 99 99 3F", 7);
- if ( enforcerX1.count_hint(1).size() == 1 && enforcerY1.count_hint(1).size() == 1 && enforcerZ1.count_hint(1).size() == 1 &&
- enforcerX2.count_hint(1).size() == 1 && enforcerY2.count_hint(1).size() == 1 && enforcerZ2.count_hint(1).size() == 1 )
- {
- constexpr CVector ENFORCER_SIREN_POS(0.6f, 1.05f, 1.4f);
+ constexpr CVector ENFORCER_SIREN_POS(0.6f, 1.05f, 1.4f);
- Patch( enforcerX1.get_first( 7 ), ENFORCER_SIREN_POS.x );
- Patch( enforcerY1.get_first( 7 ), ENFORCER_SIREN_POS.y );
- Patch( enforcerZ1.get_first( 7 ), ENFORCER_SIREN_POS.z );
+ Patch( enforcerX1, ENFORCER_SIREN_POS.x );
+ Patch( enforcerY1, ENFORCER_SIREN_POS.y );
+ Patch( enforcerZ1, ENFORCER_SIREN_POS.z );
- Patch( enforcerX2.get_first( 7 ), -ENFORCER_SIREN_POS.x );
- Patch( enforcerY2.get_first( 7 ), ENFORCER_SIREN_POS.y );
- Patch( enforcerZ2.get_first( 7 ), ENFORCER_SIREN_POS.z );
- }
+ Patch( enforcerX2, -ENFORCER_SIREN_POS.x );
+ Patch( enforcerY2, ENFORCER_SIREN_POS.y );
+ Patch( enforcerZ2, ENFORCER_SIREN_POS.z );
}
+ TXN_CATCH();
+
+ try
{
- auto chopper1 = pattern( "C7 44 24 44 00 00 E0 40 50 C7 44 24 4C 00 00 00 00" ); // Front light
+ auto chopper1 = pattern("C7 44 24 44 00 00 E0 40 50 C7 44 24 4C 00 00 00 00").get_one(); // Front light
- if ( chopper1.count_hint(1).size() == 1 )
- {
- constexpr CVector CHOPPER_SEARCH_LIGHT_POS(0.0f, 3.0f, -1.25f);
+ constexpr CVector CHOPPER_SEARCH_LIGHT_POS(0.0f, 3.0f, -1.25f);
- auto match = chopper1.get_one();
-
- Patch( match.get( 4 ), CHOPPER_SEARCH_LIGHT_POS.y );
- Patch( match.get( 9 + 4 ), CHOPPER_SEARCH_LIGHT_POS.z );
- }
+ Patch( chopper1.get( 4 ), CHOPPER_SEARCH_LIGHT_POS.y );
+ Patch( chopper1.get( 9 + 4 ), CHOPPER_SEARCH_LIGHT_POS.z );
}
+ TXN_CATCH();
}
// Corrected FBI Car secondary siren sound
+ try
{
using namespace SirenSwitchingFix;
// Other mods might be touching it, so only patch specific vehicles if their code has not been touched at all
- auto usesSirenSwitching = pattern( "E8 ? ? ? ? 84 C0 74 12 83 C4 08" ).count_hint(1);
- if ( usesSirenSwitching.size() == 1 )
- {
- auto match = usesSirenSwitching.get_one();
- ReadCall( match.get(), orgUsesSirenSwitching );
- InjectHook( match.get(), UsesSirenSwitching_FbiCar );
- }
+ auto usesSirenSwitching = pattern("E8 ? ? ? ? 84 C0 74 12 83 C4 08").get_one();
+
+ InterceptCall(usesSirenSwitching.get(), orgUsesSirenSwitching, UsesSirenSwitching_FbiCar);
}
+ TXN_CATCH();
// Corrected CSimpleModelInfo::SetupBigBuilding minimum draw distance for big buildings without a matching model
// Fixes cranes in Portland and bright windows in the city
// By aap
+ try
{
- auto setupMinDist = pattern( "C7 43 44 00 00 C8 42" ).count_hint(1);
- if ( setupMinDist.size() == 1 ) // In case of another mod or second instance of SP changing it
- {
- auto match = setupMinDist.get_one();
+ auto setupMinDist = pattern("C7 43 44 00 00 C8 42").get_one();
- // mov ecx, ebx
- // call CSimpleModelInfo::SetNearDistanceForLOD
- Patch( match.get(), { 0x89, 0xD9 } );
- InjectHook( match.get( 2 ), &CSimpleModelInfo::SetNearDistanceForLOD_SilentPatch, HookType::Call );
- }
+ // mov ecx, ebx
+ // call CSimpleModelInfo::SetNearDistanceForLOD
+ Patch( setupMinDist.get(), { 0x89, 0xD9 } );
+ InjectHook( setupMinDist.get( 2 ), &CSimpleModelInfo::SetNearDistanceForLOD_SilentPatch, HookType::Call );
}
+ TXN_CATCH();
FLAUtils::Init(moduleList);
}
@@ -1346,10 +1335,11 @@ void Patch_III_Steam(uint32_t width, uint32_t height)
void Patch_III_Common()
{
using namespace Memory;
- using namespace hook;
+ using namespace hook::txn;
// New timers fix
+ try
{
auto hookPoint = pattern( "83 E4 F8 89 44 24 08 C7 44 24 0C 00 00 00 00 DF 6C 24 08" ).get_one();
auto jmpPoint = get_pattern( "DD D8 E9 37 FF FF FF DD D8" );
@@ -1357,8 +1347,11 @@ void Patch_III_Common()
InjectHook( hookPoint.get( 0x21 ), CTimer::Update_SilentPatch, HookType::Call );
InjectHook( hookPoint.get( 0x21 + 5 ), jmpPoint, HookType::Jump );
}
+ TXN_CATCH();
+
// Alt+F4
+ try
{
auto addr = pattern( "59 59 31 C0 83 C4 48 5D 5F 5E 5B C2 10 00" ).count(2);
auto dest = get_pattern( "53 55 56 FF 74 24 68 FF 15" );
@@ -1367,8 +1360,11 @@ void Patch_III_Common()
InjectHook( match.get( 2 ), dest, HookType::Jump );
});
}
+ TXN_CATCH();
+
// Proper panels damage
+ try
{
auto addr = pattern( "C6 43 09 03 C6 43 0A 03 C6 43 0B 03" ).get_one();
@@ -1376,8 +1372,11 @@ void Patch_III_Common()
Patch( addr.get( 0x23 + 1 ), 6 );
Nop( addr.get( 0x3F ), 7 );
}
+ TXN_CATCH();
+
// Proper metric-imperial conversion constants
+ try
{
static const float METERS_TO_MILES = 0.0006213711922f;
static const float METERS_TO_FEET = 3.280839895f;
@@ -1389,8 +1388,11 @@ void Patch_III_Common()
Patch( addr.get(2).get( 2 ), &METERS_TO_FEET );
Patch( addr.get(3).get( 2 ), &METERS_TO_FEET );
}
+ TXN_CATCH();
+
// Improved pathfinding in PickNextNodeAccordingStrategy - PickNextNodeToChaseCar with XYZ coords
+ try
{
auto addr = pattern( "E8 ? ? ? ? 50 8D 44 24 10 50 E8" ).get_one();
ReadCall( addr.get( 0x25 ), orgPickNextNodeToChaseCar );
@@ -1421,25 +1423,31 @@ void Patch_III_Common()
// Uncomment this to get rid of "treadable hack" in CCarCtrl::PickNextNodeToChaseCar (to mirror VC behaviour)
InjectHook( funcAddr + 0x2A, funcAddr + 0x182, HookType::Jump );
}
+ TXN_CATCH();
// No censorships
+ try
{
auto addr = get_pattern( "8B 15 ? ? ? ? C6 05 ? ? ? ? 00 89 D0" );
Patch( addr, { 0x83, 0xC4, 0x08, 0xC3 } ); // add esp, 8 \ retn
}
+ TXN_CATCH();
// 014C cargen counter fix (by spaceeinstein)
+ try
{
auto do_processing = pattern( "0F B7 45 28 83 F8 FF 7D 04 66 FF 4D 28" ).get_one();
Patch( do_processing.get(1), 0xBF ); // movzx eax, word ptr [ebx+28h] -> movsx eax, word ptr [ebx+28h]
Patch( do_processing.get(7), 0x74 ); // jge -> jz
}
+ TXN_CATCH();
// Fixed ammo from SCM
+ try
{
using namespace ZeroAmmoFix;
@@ -1449,9 +1457,11 @@ void Patch_III_Common()
};
HookEach_GiveWeapon(give_weapon, InterceptCall);
}
+ TXN_CATCH();
// Credits =)
+ try
{
auto renderCredits = pattern( "83 C4 14 8D 45 F4 50 FF 35 ? ? ? ? E8 ? ? ? ? 59 59 8D 45 F4 50 FF 35 ? ? ? ? E8 ? ? ? ? 59 59 E8" ).get_one();
@@ -1459,9 +1469,11 @@ void Patch_III_Common()
ReadCall( renderCredits.get( -5 ), Credits::PrintCreditText_Hooked );
InjectHook( renderCredits.get( -5 ), Credits::PrintSPCredits );
}
+ TXN_CATCH();
// Decreased keyboard input latency
+ try
{
using namespace KeyboardInputFix;
@@ -1477,20 +1489,20 @@ void Patch_III_Common()
InjectHook( simButtonCheckers, ClearSimButtonPressCheckers );
InjectHook( updatePads.get( 10 ), jmpDest, HookType::Jump );
}
+ TXN_CATCH();
// Locale based metric/imperial system
+ try
{
using namespace Localization;
void* updateCompareFlag = get_pattern( "89 E9 6A 00 E8 ? ? ? ? 30 C0 83 C4 70 5D 5E 5B C2 04 00", 4 );
+ auto constructStatLine = pattern( "FF 24 9D ? ? ? ? 39 D0" ).get_one();
ReadCall( updateCompareFlag, orgUpdateCompareFlag_IsMetric );
InjectHook( updateCompareFlag, UpdateCompareFlag_IsMetric );
- // Stats
- auto constructStatLine = pattern( "FF 24 9D ? ? ? ? 39 D0" ).get_one();
-
// push eax
// push edx
// call IsMetric_LocaleBased
@@ -1503,25 +1515,29 @@ void Patch_III_Common()
Patch( constructStatLine.get( -0xF + 7 ), { 0x0F, 0xB6, 0xD8, 0x5A, 0x58 } );
Nop( constructStatLine.get( -0xF + 12 ), 3 );
}
+ TXN_CATCH();
// Add cDMAudio::IsAudioInitialised checks before constructing cAudioScriptObject, like in VC
+ try
{
using namespace AudioInitializedFix;
auto processCommands300 = pattern( "E8 ? ? ? ? 85 C0 59 74 ? 89 C1 E8 ? ? ? ? D9 05" ).get_one();
+ auto processCommands300_2 = pattern( "6A 14 E8 ? ? ? ? 89 C3 59 85 DB 74" ).get_one();
+ auto bulletInfoUpdate_Switch = *get_pattern( "FF 24 85 ? ? ? ? 6A 14", 3 );
+ auto playlayOneShotScriptObject = pattern( "6A 14 E8 ? ? ? ? 85 C0 59 74 ? 89 C1 E8 ? ? ? ? D9 03 D9 58 04" ).get_one();
+ auto loadAllAudioScriptObjects = get_pattern( "FF B5 78 FF FF FF E8 ? ? ? ? 59 59 8B 45 C8", 6 );
+
ReadCall( processCommands300.get( 0 ), operatorNew );
InjectHook( processCommands300.get( 0 ), operatorNew_InitializedCheck );
Patch( processCommands300.get( 8 + 1 ), 0x440B62 - 0x440B24 );
- auto processCommands300_2 = pattern( "6A 14 E8 ? ? ? ? 89 C3 59 85 DB 74" ).get_one();
InjectHook( processCommands300_2.get( 2 ), operatorNew_InitializedCheck );
Patch( processCommands300_2.get( 0xC + 1 ), 0x440BD7 - 0x440B8B );
// We need to patch switch cases 0, 3, 4
- auto bulletInfoUpdate_Switch = *get_pattern( "FF 24 85 ? ? ? ? 6A 14", 3 );
-
const uintptr_t bulletInfoUpdate_0 = bulletInfoUpdate_Switch[0];
const uintptr_t bulletInfoUpdate_3 = bulletInfoUpdate_Switch[3];
const uintptr_t bulletInfoUpdate_4 = bulletInfoUpdate_Switch[4];
@@ -1535,32 +1551,31 @@ void Patch_III_Common()
InjectHook( bulletInfoUpdate_4 + 2, operatorNew_InitializedCheck );
Patch( bulletInfoUpdate_4 + 0xA + 1, 0x558C19 - 0x558BE3 );
- auto playlayOneShotScriptObject = pattern( "6A 14 E8 ? ? ? ? 85 C0 59 74 ? 89 C1 E8 ? ? ? ? D9 03 D9 58 04" ).get_one();
InjectHook( playlayOneShotScriptObject.get( 2 ), operatorNew_InitializedCheck );
Patch( playlayOneShotScriptObject.get( 0xA + 1 ), 0x57C633 - 0x57C601 );
- auto loadAllAudioScriptObjects = get_pattern( "FF B5 78 FF FF FF E8 ? ? ? ? 59 59 8B 45 C8", 6 );
ReadCall( loadAllAudioScriptObjects, orgLoadAllAudioScriptObjects );
InjectHook( loadAllAudioScriptObjects, LoadAllAudioScriptObjects_InitializedCheck );
}
+ TXN_CATCH();
// Give chopper/escape a properly sized collision bounding box instead of using ped's
+ try
{
- auto initHelisPattern = pattern( "C6 40 2C 00 A1" ).count_hint(1);
- if ( initHelisPattern.size() == 1 )
- {
- static constexpr CColModel colModelChopper( CColSphere( 8.5f, CVector(0.0f, -1.75f, 0.73f), 0, 0 ),
- CColBox( CVector(-2.18f, -8.52f, -0.67f), CVector(-2.18f, 4.58f, 2.125f), 0, 0 ) );
+ auto initHelis = pattern( "C6 40 2C 00 A1" ).get_one();
- auto initHelis = initHelisPattern.get_one();
- Patch( initHelis.get( -7 + 3 ), &colModelChopper );
- Patch( initHelis.get( 9 + 3 ), &colModelChopper );
- }
+ static constexpr CColModel colModelChopper( CColSphere( 8.5f, CVector(0.0f, -1.75f, 0.73f), 0, 0 ),
+ CColBox( CVector(-2.18f, -8.52f, -0.67f), CVector(-2.18f, 4.58f, 2.125f), 0, 0 ) );
+
+ Patch( initHelis.get( -7 + 3 ), &colModelChopper );
+ Patch( initHelis.get( 9 + 3 ), &colModelChopper );
}
+ TXN_CATCH();
// Fixed vehicles exploding twice if the driver leaves the car while it's exploding
+ try
{
using namespace RemoveDriverStatusFix;
@@ -1581,35 +1596,43 @@ void Patch_III_Common()
Nop(processCommands4, 3);
Nop(pedSetOutCar, 3);
}
+ TXN_CATCH();
// Fixed an inverted condition in CCarCtrl::PickNextNodeRandomly
// leading to cars being unable to turn right from one way roads
// By Nick007J
+ try
{
auto pickNodeRandomly = get_pattern("3B 44 24 24 74 09", 4);
Patch(pickNodeRandomly, 0x75);
}
+ TXN_CATCH();
// Apply bilinear filtering on the player skin
+ try
{
using namespace SkinTextureFilter;
auto getSkinTexture = get_pattern("E8 ? ? ? ? 89 C3 59 55");
InterceptCall(getSkinTexture, orgRwTextureCreate, RwTextureCreate_SetLinearFilter);
}
+ TXN_CATCH();
// Apply the environment mapping on extra components
+ try
{
auto setEnvironmentMap = get_pattern("C7 83 D8 01 00 00 00 00 00 00 E8", 10);
InterceptCall(setEnvironmentMap, CVehicleModelInfo::orgSetEnvironmentMap, &CVehicleModelInfo::SetEnvironmentMap_ExtraComps);
}
+ TXN_CATCH();
// Fix the evasive dive miscalculating the angle, resulting in peds diving towards the vehicle
+ try
{
using namespace EvasiveDiveFix;
@@ -1618,9 +1641,11 @@ void Patch_III_Common()
Nop(setEvasiveDive.get(), 1);
InjectHook(setEvasiveDive.get(1), &CalculateAngle_Hook, HookType::Call);
}
+ TXN_CATCH();
// Fix probabilities in CVehicle::InflictDamage incorrectly assuming a random range from 0 to 100.000
+ try
{
auto probability_do_nothing = get_pattern("66 81 7E 5A ? ? 73 50", 4);
auto probability_flee = get_pattern("0F B7 46 5A 3D ? ? ? ? 0F 8E", 4 + 1);
@@ -1628,9 +1653,11 @@ void Patch_III_Common()
Patch(probability_do_nothing, 35000u * 32767u / 100000u);
Patch(probability_flee, 75000u * 32767u / 100000u);
}
+ TXN_CATCH();
// Null terminate read lines in CPlane::LoadPath and CTrain::ReadAndInterpretTrackFile
+ try
{
using namespace NullTerminatedLines;
@@ -1648,25 +1675,26 @@ void Patch_III_Common()
Nop(readTrackFile2.get(), 2);
InjectHook(readTrackFile2.get(2), ReadTrackFile_Terminate, HookType::Call);
}
+ TXN_CATCH();
// Backport 1.1 Stats menu font fix to 1.0
+ try
{
using namespace StatsMenuFont;
// This pattern fails by design on 1.1/Steam
- auto constructStatLine = pattern("E8 ? ? ? ? D9 05 ? ? ? ? DC 0D ? ? ? ? 89 C7").count_hint(1);
- if (constructStatLine.size() == 1)
- {
- auto setFontStyle = get_pattern("6A 00 E8 ? ? ? ? 83 3D ? ? ? ? ? 59 0F 84", 2);
+ auto constructStatLine = pattern("E8 ? ? ? ? D9 05 ? ? ? ? DC 0D ? ? ? ? 89 C7").get_one();
+ auto setFontStyle = get_pattern("6A 00 E8 ? ? ? ? 83 3D ? ? ? ? ? 59 0F 84", 2);
- ReadCall(setFontStyle, orgSetFontStyle);
- InterceptCall(constructStatLine.get_first(), orgConstructStatLine, ConstructStatLine_SetFontStyle);
- }
+ ReadCall(setFontStyle, orgSetFontStyle);
+ InterceptCall(constructStatLine.get(), orgConstructStatLine, ConstructStatLine_SetFontStyle);
}
+ TXN_CATCH();
// Enable Dodo keyboard controls for all cars when the flying cars cheat is enabled
+ try
{
using namespace DodoKeyboardControls;
@@ -1676,9 +1704,11 @@ void Patch_III_Common()
bAllDodosCheat = allDodosCheat;
InterceptCall(findPlayerVehicle, orgFindPlayerVehicle, FindPlayerVehicle_DodoCheck);
}
+ TXN_CATCH();
// Reset variables on New Game
+ try
{
using namespace VariableResets;
@@ -1696,9 +1726,11 @@ 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
}
+ TXN_CATCH();
// Clean up the pickup object when reusing a temporary slot
+ try
{
using namespace GenerateNewPickup_ReuseObjectFix;
@@ -1707,10 +1739,12 @@ void Patch_III_Common()
pPickupObject = *give_us_a_pick_up_object.get(7 + 2);
InterceptCall(give_us_a_pick_up_object.get(2), orgGiveUsAPickUpObject, GiveUsAPickUpObject_CleanUpObject);
}
+ TXN_CATCH();
// Sitting in boat (Speeder), implemented as a special vehicle feature
// Based off SitInBoat from Fire_Head, with extra improvements
+ try
{
using namespace SitInBoat;
@@ -1730,36 +1764,40 @@ void Patch_III_Common()
// This is intended - we don't actually need the original SetFinishCallback, only its parameters!
InjectHook(finish_callback, FinishCallback_CallImmediately);
}
+ TXN_CATCH();
// Copy the atomic render CB in CloneAtomicToFrameCB instead of overriding it
// Fixes detached limbs rendering the normal and LOD atomics together
+ try
{
auto set_render_cb = get_pattern("55 E8 ? ? ? ? 89 D8 59", 1);
Nop(set_render_cb, 5);
}
+ TXN_CATCH();
// Fix dark car reflections in the Steam EXE
// Based off Sergenaur's fix
+ try
{
- auto reflection = pattern("A1 ? ? ? ? 85 C0 74 34");
- if (reflection.count_hint(1).size() == 1) // This will only pass on the Steam EXE, and if Sergenaur's standalone fix isn't present
- {
- auto match = reflection.get_one();
+ // This will only pass on the Steam EXE, and if Sergenaur's standalone fix isn't present
+ auto reflection = pattern("A1 ? ? ? ? 85 C0 74 34").get_one();
- // xor eax, eax \ nop
- Patch(match.get(), { 0x31, 0xC0 });
- Nop(match.get(2), 3);
- }
+ // xor eax, eax \ nop
+ Patch(reflection.get(), { 0x31, 0xC0 });
+ Nop(reflection.get(2), 3);
}
+ TXN_CATCH();
// Don't override the color of the FBI car
+ try
{
auto spawn_one_car = get_pattern("83 7C 24 ? ? 75 0E C6 85", 5);
Patch(spawn_one_car, 0xEB);
}
+ TXN_CATCH();
}
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
diff --git a/SilentPatchIII/SilentPatchIII.vcxproj b/SilentPatchIII/SilentPatchIII.vcxproj
index 0c4d665..8f4ccc7 100644
--- a/SilentPatchIII/SilentPatchIII.vcxproj
+++ b/SilentPatchIII/SilentPatchIII.vcxproj
@@ -152,7 +152,6 @@
stdcpp17
true
false
- false
Windows
@@ -186,7 +185,6 @@
stdcpp17
true
false
- false
true
@@ -222,7 +220,6 @@
stdcpp17
true
false
- false
true
diff --git a/SilentPatchSA/SilentPatchSA.cpp b/SilentPatchSA/SilentPatchSA.cpp
index f5219e2..f0e51ea 100644
--- a/SilentPatchSA/SilentPatchSA.cpp
+++ b/SilentPatchSA/SilentPatchSA.cpp
@@ -4261,7 +4261,7 @@ BOOL InjectDelayedPatches_Newsteam()
if ( !IsAlreadyRunning() )
{
using namespace Memory;
- using namespace hook;
+ using namespace hook::txn;
const HINSTANCE hInstance = GetModuleHandle( nullptr );
std::unique_ptr Protect = ScopedUnprotect::UnprotectSectionOrFullModule( hInstance, ".text" );
@@ -4276,15 +4276,16 @@ BOOL InjectDelayedPatches_Newsteam()
constexpr bool flaBugAware = false;
constexpr bool usesEnhancedImages = false;
- if constexpr ( !usesEnhancedImages || flaBugAware )
+ if constexpr ( !usesEnhancedImages || flaBugAware ) try
{
void* initThread = get_pattern( "74 14 81 25 ? ? ? ? ? ? ? ? C7 05", 0x16 );
+ auto cdStreamSync = pattern( "8B 0D ? ? ? ? 8D 04 40 03 C0" ).get_one(); // 0x4064E6
+ auto cdStreamInitThread = pattern( "6A 00 6A 02 6A 00 6A 00 FF D3" ).get_one();
+ auto cdStreamShutdown = pattern( "8B 4C 07 14" ).get_one();
ReadCall( initThread, CdStreamSync::orgCdStreamInitThread );
InjectHook( initThread, CdStreamSync::CdStreamInitThread );
- auto cdStreamSync = pattern( "8B 0D ? ? ? ? 8D 04 40 03 C0" ).get_one(); // 0x4064E6
-
Patch( cdStreamSync.get( 0x18 ), { 0x56, 0xFF, 0x15 } );
Patch( cdStreamSync.get( 0x18 + 3 ), &CdStreamSync::CdStreamSyncOnObject );
Patch( cdStreamSync.get( 0x18 + 3 + 4 ), { 0x5E, 0x5D, 0xC3 } ); // pop ebp / retn
@@ -4292,7 +4293,7 @@ BOOL InjectDelayedPatches_Newsteam()
Patch( cdStreamSync.get( 0x5E + 2 ), &CdStreamSync::pGetOverlappedResult );
Patch( cdStreamSync.get( 0x5E + 6 ), { 0x5E, 0x5D, 0xC3 } ); // pop esi / pop ebp / retn
- if constexpr ( !usesEnhancedImages )
+ if constexpr ( !usesEnhancedImages ) try
{
auto cdStreamThread = pattern( "C7 46 04 00 00 00 00 8A 4E 0D" ).get_one();
@@ -4300,17 +4301,17 @@ BOOL InjectDelayedPatches_Newsteam()
Patch( cdStreamThread.get( 3 ), &CdStreamSync::CdStreamThreadOnObject );
Patch( cdStreamThread.get( 3 + 4 ), { 0xEB, 0x17 } );
}
+ TXN_CATCH();
- auto cdStreamInitThread = pattern( "6A 00 6A 02 6A 00 6A 00 FF D3" ).get_one();
Patch( cdStreamInitThread.get(), { 0xFF, 0x15 } );
Patch( cdStreamInitThread.get( 2 ), &CdStreamSync::CdStreamInitializeSyncObject );
Nop( cdStreamInitThread.get( 6 ), 4 );
Nop( cdStreamInitThread.get( 0x16 ), 2 );
- auto cdStreamShutdown = pattern( "8B 4C 07 14" ).get_one();
Patch( cdStreamShutdown.get(), { 0x56, 0x50 } );
InjectHook( cdStreamShutdown.get( 2 ), CdStreamSync::CdStreamShutdownSyncObject_Stub, HookType::Call );
}
+ TXN_CATCH();
}
@@ -6093,15 +6094,19 @@ void Patch_SA_Steam()
void Patch_SA_NewBinaries_Common(HINSTANCE hInstance)
{
using namespace Memory;
- using namespace hook;
+ using namespace hook::txn;
+ try
{
void* isAlreadyRunning = get_pattern( "85 C0 74 08 33 C0 8B E5 5D C2 10 00", -5 );
ReadCall( isAlreadyRunning, IsAlreadyRunning );
InjectHook(isAlreadyRunning, InjectDelayedPatches_Newsteam);
}
+ TXN_CATCH();
+
// (Hopefully) more precise frame limiter
+ try
{
void* rsEventHandler = get_pattern( "83 C4 08 39 3D ? ? ? ? 75 23", -5 );
void* getTimeSinceLastFrame = get_pattern( "EB 7F E8 ? ? ? ? 89 45 08", 2 );
@@ -6110,53 +6115,54 @@ void Patch_SA_NewBinaries_Common(HINSTANCE hInstance)
InjectHook( rsEventHandler, NewFrameRender );
InjectHook( getTimeSinceLastFrame, GetTimeSinceLastFrame );
}
+ TXN_CATCH();
+
// No framedelay
+ try
{
- // TODO: Simplify with transactional patching
- auto framedelay_jmpSrc = pattern( "83 EC 08 E8 ? ? ? ? E8" ).count(1);
- auto framedelay_jmpDest = pattern( "33 D2 8B C6 F7 F1 A3" ).count(1);
- auto popEsi = pattern( "83 C4 04 83 7D 08 00 5E" ).count(1);
+ auto framedelay_jmpSrc = get_pattern("83 EC 08 E8 ? ? ? ? E8", 3);
+ auto framedelay_jmpDest = get_pattern("33 D2 8B C6 F7 F1 A3", 11);
+ auto popEsi = pattern("83 C4 04 83 7D 08 00 5E").get_one();
- if ( framedelay_jmpSrc.size() == 1 && framedelay_jmpDest.size() == 1 && popEsi.size() == 1 )
- {
- // TODO: Let this place long or short jump, whatever it prefers
- InjectHook( framedelay_jmpSrc.get_first( 3 ), framedelay_jmpDest.get_first( 11 ), HookType::Jump );
+ InjectHook( framedelay_jmpSrc, framedelay_jmpDest, HookType::Jump );
- auto popEsiMatch = popEsi.get_one();
- Patch( popEsiMatch.get( 3 + 2 ), 0x4);
- Nop( popEsiMatch.get( 3 + 4 ), 1 );
- }
+ Patch( popEsi.get( 3 + 2 ), 0x4);
+ Nop( popEsi.get( 3 + 4 ), 1 );
}
+ TXN_CATCH();
+
// Unlock 1.0/1.01 saves loading
+ try
{
- auto sizeCheck = pattern( "0F 84 ? ? ? ? 8D 45 FC" ).count(1);
- if ( sizeCheck.size() == 1 )
- {
- Patch( sizeCheck.get_first(), { 0x90, 0xE9 } ); // nop / jmp
- }
+ auto sizeCheck = get_pattern( "0F 84 ? ? ? ? 8D 45 FC" );
+ Patch( sizeCheck, { 0x90, 0xE9 } ); // nop / jmp
}
+ TXN_CATCH();
+
// Old .set files working again
+ try
{
void* setFileSave = get_pattern( "C6 45 FD 5F", 0xE + 1 );
- auto setCheckVersion1 = pattern( "83 7D F8 07" ).count(1);
- auto setCheckVersion2 = pattern( "83 C4 18 83 7D FC 07" ).count(1);
+ auto setCheckVersion1 = get_pattern( "83 7D F8 07", 3);
+ auto setCheckVersion2 = get_pattern( "83 C4 18 83 7D FC 07", 3 + 3);
- if ( setCheckVersion1.size() == 1 && setCheckVersion2.size() == 1 )
- {
- static const DWORD dwSetVersion = 6;
- Patch( setFileSave, &dwSetVersion );
- Patch( setCheckVersion1.get_first( 3 ), dwSetVersion );
- Patch( setCheckVersion2.get_first( 3 + 3 ), dwSetVersion );
- }
+ static const DWORD dwSetVersion = 6;
+ Patch( setFileSave, &dwSetVersion );
+ Patch( setCheckVersion1, dwSetVersion );
+ Patch( setCheckVersion2, dwSetVersion );
}
+ TXN_CATCH();
+
// Disable re-initialization of DirectInput mouse device by the game
+ try
{
void* reinitMouse1 = get_pattern( "84 C0 ? 0F E8 ? ? ? ? 6A 01 E8", 2 );
auto reinitMouse2 = pattern( "84 C0 ? 0E E8 ? ? ? ? 53 E8" ).count(2);
+ void* diInitMouse = get_pattern( "6A 00 83 C1 1C", -3 );
Patch( reinitMouse1, 0xEB );
@@ -6164,72 +6170,71 @@ void Patch_SA_NewBinaries_Common(HINSTANCE hInstance)
Patch( match.get( 2 ), 0xEB );
});
- void* diInitMouse = get_pattern( "6A 00 83 C1 1C", -3 );
-
// Make sure DirectInput mouse device is set non-exclusive (may not be needed?)
// nop / mov al, 1
Patch( diInitMouse, { 0x90, 0xB0, 0x01 } );
}
+ TXN_CATCH();
+
// Unlocked widescreen resolutions
{
// Assume anybody could have changed those, so bail out if ANYTHING goes wrong
// However, all those patches are independent so try one by one
- auto wsRes_jmpSrc = pattern( "81 F9 E0 01 00 00 7C").count(1);
- auto wsRes1_jmpDest = pattern( "8B 45 EC 0F AF C2" ).count(1);
- auto wsRes2 = pattern( "0F 8C ? ? ? ? 81 7D ? ? ? ? ? 0F 8C" ).count(1);
- auto wsRes3 = pattern( "7A 4D EB 02" ).count(1);
-
- if ( wsRes_jmpSrc.size() == 1 && wsRes1_jmpDest.size() == 1 )
+ try
{
- auto wsRes_jmpSrcMatch = wsRes_jmpSrc.get_one();
- auto wsRes1_jmpDestMatch = wsRes1_jmpDest.get_one();
+ auto wsRes_jmpSrc = pattern( "81 F9 E0 01 00 00 7C").get_one();
+ auto wsRes1_jmpDest = pattern( "8B 45 EC 0F AF C2" ).get_one();
- const uintptr_t jumpSource = reinterpret_cast(wsRes_jmpSrcMatch.get( 6 + 2 ));
- const uintptr_t jumpDestination = reinterpret_cast(wsRes1_jmpDestMatch.get() );
+ const uintptr_t jumpSource = reinterpret_cast(wsRes_jmpSrc.get( 6 + 2 ));
+ const uintptr_t jumpDestination = reinterpret_cast(wsRes1_jmpDest.get() );
const ptrdiff_t dist = jumpDestination - jumpSource;
// Can only do a short jump
if ( INT8_MIN <= dist && dist <= INT8_MAX )
{
// jnl 00B19C33
- Patch( wsRes_jmpSrcMatch.get( 6 ), { 0x7D, static_cast(dist) } );
+ Patch( wsRes_jmpSrc.get( 6 ), { 0x7D, static_cast(dist) } );
}
}
+ TXN_CATCH();
- if ( wsRes2.size() == 1 )
+ try
{
- auto wsRes2Match = wsRes2.get_one();
- Nop( wsRes2Match.get(), 4 );
- Patch( wsRes2Match.get( 4 ), { 0x7D, 0xD } );
- }
+ auto wsRes2 = pattern( "0F 8C ? ? ? ? 81 7D ? ? ? ? ? 0F 8C" ).get_one();
- if ( wsRes3.size() == 1 )
- {
- Nop( wsRes3.get_first(), 2 );
+ Nop( wsRes2.get(), 4 );
+ Patch( wsRes2.get( 4 ), { 0x7D, 0xD } );
}
+ TXN_CATCH();
+
+ try
+ {
+ auto wsRes3 = get_pattern( "7A 4D EB 02" );
+ Nop( wsRes3, 2 );
+ }
+ TXN_CATCH();
}
+
// Default resolution to native resolution
+ try
{
- auto resolution = pattern( "BB 20 03 00 00" ).count(1); // Another instance could overwrite it so check first
+ auto resolution = pattern( "BB 20 03 00 00" ).get_one();
+ void* cannotFindResMessage = get_pattern( "6A 00 68 ? ? ? ? 68 ? ? ? ? 6A 00", 7 + 1 );
- if ( resolution.size() == 1 )
- {
- void* cannotFindResMessage = get_pattern( "6A 00 68 ? ? ? ? 68 ? ? ? ? 6A 00", 7 + 1 );
+ RECT desktop;
+ GetWindowRect(GetDesktopWindow(), &desktop);
+ sprintf_s(aNoDesktopMode, "Cannot find %dx%dx32 video mode", desktop.right, desktop.bottom);
- RECT desktop;
- GetWindowRect(GetDesktopWindow(), &desktop);
- sprintf_s(aNoDesktopMode, "Cannot find %dx%dx32 video mode", desktop.right, desktop.bottom);
-
- auto resolutionMatch = resolution.get_one();
-
- Patch( resolutionMatch.get( 1 ), desktop.right );
- Patch( resolutionMatch.get( 5 + 1 ), desktop.bottom );
- Patch( cannotFindResMessage, aNoDesktopMode );
- }
+ Patch( resolution.get( 1 ), desktop.right );
+ Patch( resolution.get( 5 + 1 ), desktop.bottom );
+ Patch( cannotFindResMessage, aNoDesktopMode );
}
+ TXN_CATCH();
+
// No DirectPlay dependency
+ try
{
auto getDXversion = pattern( "50 68 ? ? ? ? A3" ).get_one();
@@ -6237,38 +6242,55 @@ void Patch_SA_NewBinaries_Common(HINSTANCE hInstance)
Patch( getDXversion.get( -5 ), 0xB8 );
Patch( getDXversion.get( -5 + 1 ), 0x900 );
}
+ TXN_CATCH();
+
// SHGetFolderPath on User Files
+ try
{
void* getDocumentsPath = get_pattern( "8D 45 FC 50 68 19 00 02 00", -6 );
InjectHook( getDocumentsPath, GetMyDocumentsPathSA, HookType::Jump );
}
+ TXN_CATCH();
+
// Fixed muzzleflash not showing from last bullet
+ try
{
auto weaponStateCheck = pattern("83 BC 8E A4 05 00 00 01").get_one();
Nop(weaponStateCheck.get(-16), 22);
Patch(weaponStateCheck.get(6), { 0x84, 0xC0, 0x74 });
}
+ TXN_CATCH();
+
// Proper randomizations
+ try
{
- pattern( "C1 F8 06 99" ).count(2).for_each_result( []( pattern_match match ) {
+ auto pedsRand = pattern( "C1 F8 06 99" ).count(2);
+ void* prostitutesRand = get_pattern( "8B F8 32 C0", -5 );
+
+ pedsRand.for_each_result( []( pattern_match match ) {
InjectHook( match.get( -5 ), Int32Rand ); // Missing ped paths
});
- void* prostitutesRand = get_pattern( "8B F8 32 C0", -5 );
InjectHook( prostitutesRand, Int32Rand ); // Prostitutes
}
+ TXN_CATCH();
+
// Help boxes showing with big message
// Game seems to assume they can show together
+ try
{
void* showingBigMessage = get_pattern( "38 1D ? ? ? ? 0F 85 ? ? ? ? 38 1D ? ? ? ? 0F 85 ? ? ? ? 38 1D", 6 );
Nop( showingBigMessage, 6 );
}
+ TXN_CATCH();
+
// Fixed lens flare
+ try
{
auto coronasRenderEpilogue = pattern( "83 C7 3C FF 4D BC" ).get_one();
auto flushLensSwitchZ = pattern( "6A 01 6A 06 FF D0 83 C4 08" ).get_one();
@@ -6295,8 +6317,11 @@ void Patch_SA_NewBinaries_Common(HINSTANCE hInstance)
Patch( initBufferSwitchZ.get( -8 + 3 ), 0xB9 );
Patch( initBufferSwitchZ.get( -8 + 4 ), &InitBufferSwitchZ );
}
+ TXN_CATCH();
+
// Y axis sensitivity fix
+ try
{
auto horizontalSens = pattern( "D9 05 ? ? ? ? D8 4D 0C D8 C9" ).get_one();
float* sens = *horizontalSens.get( 2 );
@@ -6308,15 +6333,20 @@ void Patch_SA_NewBinaries_Common(HINSTANCE hInstance)
float* vertSens = *horizontalSens.get( 0xE + 2 );
memcpy( bytes + 2, &vertSens, sizeof(vertSens) );
- pattern( {bytes, _countof(bytes)}, {mask, _countof(mask)} ).count(4).for_each_result( [sens]( pattern_match match ) {
+ auto mulVerticalSens1 = pattern( {bytes, _countof(bytes)}, {mask, _countof(mask)} ).count(4);
+ void* mulVerticalSens2 = get_pattern( "D8 0D ? ? ? ? D8 C9 D9 5D F4", 2 );
+
+ mulVerticalSens1.for_each_result( [sens]( pattern_match match ) {
Patch( match.get( 2 ), sens );
} );
- void* mulVerticalSens = get_pattern( "D8 0D ? ? ? ? D8 C9 D9 5D F4", 2 );
- Patch( mulVerticalSens, sens );
+ Patch( mulVerticalSens2, sens );
}
+ TXN_CATCH();
+
// Don't lock mouse Y axis during fadeins
+ try
{
void* followPedWithMouse = get_pattern( "D9 5D 08 A0", -7 );
void* followPedWithMouse2 = get_pattern( "66 83 3D ? ? ? ? ? 0F 85 ? ? ? ? 80 3D", -6 );
@@ -6329,29 +6359,42 @@ void Patch_SA_NewBinaries_Common(HINSTANCE hInstance)
Patch( followPedWithMouse2, { 0x90, 0xE9 } );
InjectHook( followPedSA, folowPedSA_dest, HookType::Jump );
}
+ TXN_CATCH();
+
// Fixed mirrors crash
+ try
{
// TODO: Change when short jumps are supported
void* beforeMainRender = get_pattern( "8B 15 ? ? ? ? 83 C4 0C 52", 0xF );
Patch( beforeMainRender, { 0x85, 0xC0, 0x74, 0x34, 0x83, 0xC4, 0x04 } );
}
+ TXN_CATCH();
+
// Mirrors depth fix & bumped quality
+ try
{
void* createBuffers = get_pattern( "7B 0A C7 05 ? ? ? ? 01 00 00 00", 0xC );
InjectHook( createBuffers, CreateMirrorBuffers );
}
+ TXN_CATCH();
+
// Fixed MSAA options
+ try
{
using namespace MSAAFixes;
- // TODO: Remove wildcards in patterns once transactional patching is implemented
- auto func1 = pattern( "83 BE C8 00 00 00 04 ? ? E8" ).get_one();
- void* func2 = get_pattern( "05 A3 ? ? ? ? 59", -1 );
- void* func3 = get_pattern( "05 A3 ? ? ? ? 8B C7", -1 );
- void* func4 = get_pattern( "0F 8C ? ? ? ? 8B 44 24 0C", 0x18 );
+ auto func1 = pattern("83 BE C8 00 00 00 04 7F 11 E8").get_one();
+ void* func2 = get_pattern("76 05 A3 ? ? ? ? 59");
+ void* func3 = get_pattern("76 05 A3 ? ? ? ? 8B C7");
+ void* func4 = get_pattern("0F 8C ? ? ? ? 8B 44 24 0C", 0x18);
+
+ auto getMaxMultisamplingLevels = pattern( "5F 89 86 C8 00 00 00 8A 45 FF" ).get_one();
+ void* changeMultiSamplingLevels = get_pattern( "8B 8E D0 00 00 00 51", -5 );
+ void* changeMultiSamplingLevels2 = get_pattern( "8B 96 D0 00 00 00 52", -5 );
+ void* setMultiSamplingLevels = get_pattern( "83 C4 04 8B C7 5F 5E 5B 8B E5 5D C3 BB", -5 );
Patch( func1.get( 0x4A ), 0xEB ); // jmp
Nop( func1.get( 7 ), 2 ); // nop a jmp
@@ -6360,11 +6403,6 @@ void Patch_SA_NewBinaries_Common(HINSTANCE hInstance)
Patch(func3, 0xEB); // jmp
Patch(func4, { 0x90, 0xE9 }); // jmp
- auto getMaxMultisamplingLevels = pattern( "5F 89 86 C8 00 00 00 8A 45 FF" ).get_one();
- void* changeMultiSamplingLevels = get_pattern( "8B 8E D0 00 00 00 51", -5 );
- void* changeMultiSamplingLevels2 = get_pattern( "8B 96 D0 00 00 00 52", -5 );
- void* setMultiSamplingLevels = get_pattern( "83 C4 04 8B C7 5F 5E 5B 8B E5 5D C3 BB", -5 );
-
std::array getMaxMultiSamplingLevels = {
getMaxMultisamplingLevels.get( -5 ),
func1.get( 7 + 2 ),
@@ -6379,27 +6417,34 @@ void Patch_SA_NewBinaries_Common(HINSTANCE hInstance)
};
HookEach_SetOrChangeMultiSamplingLevels(setOrChangeMultiSamplingLevels, InterceptCall);
- auto msaaText = pattern( "48 50 68 ? ? ? ? 53" ).count(1); // Only so newsteam r1 doesn't crash
- if ( msaaText.size() == 1 ) // transactional patching will obsolete this
+ // Only so newsteam r1 doesn't crash
+ try
{
- auto msaaTextMatch = msaaText.get_one();
+ auto msaaText = pattern( "48 50 68 ? ? ? ? 53" ).get_one();
// nop / mov edx, offset MSAAText
- Patch( msaaTextMatch.get( -6 ), { 0x90, 0xBA } );
- Patch( msaaTextMatch.get( -6 + 2 ), MSAAText );
+ Patch( msaaText.get( -6 ), { 0x90, 0xBA } );
+ Patch( msaaText.get( -6 + 2 ), MSAAText );
}
+ TXN_CATCH();
}
+ TXN_CATCH();
+
// Fixed car collisions - car you're hitting gets proper damage now
+ try
{
auto fixedCarDamage = pattern( "8B 7D 10 0F B6 47 21" ).get_one();
Nop( fixedCarDamage.get(), 2 );
InjectHook( fixedCarDamage.get( 2 ), FixedCarDamage_Newsteam, HookType::Call );
}
+ TXN_CATCH();
+
// Car explosion crash with multimonitor
// Unitialized collision data breaking stencil shadows
+ try
{
using namespace UnitializedCollisionDataFix;
@@ -6412,12 +6457,15 @@ void Patch_SA_NewBinaries_Common(HINSTANCE hInstance)
InterceptCall(memMgrAlloc, orgMemMgrMalloc, CollisionData_MallocAndInit);
HookEach_CollisionDataNew(newAlloc, InterceptCall);
}
+ TXN_CATCH();
+
// Crash when entering advanced display options on a dual monitor machine after:
// - starting game on primary monitor in maximum resolution, exiting,
// starting again in maximum resolution on secondary monitor.
// Secondary monitor maximum resolution had to be greater than maximum resolution of primary monitor.
// Not in 1.01
+ try
{
void* storeVideoModes = get_pattern( "6A 00 8B F8 6A 04", -5 );
void* retrieveVideoModes = get_pattern( "57 E8 ? ? ? ? 83 3D", 1 );
@@ -6426,61 +6474,61 @@ void Patch_SA_NewBinaries_Common(HINSTANCE hInstance)
InjectHook( storeVideoModes, GetNumVideoModes_Store );
InjectHook( retrieveVideoModes, GetNumVideoModes_Retrieve );
}
+ TXN_CATCH();
+
// Fixed escalators crash
+ try
{
orgEscalatorsUpdate = static_cast(get_pattern( "80 3D ? ? ? ? ? 74 23 56" ));
- // TODO: Simplify when transactional patching is implemented
- auto updateEscalators = pattern( "80 3D ? ? ? ? ? 74 22 56" ).count(1);
- auto removeEscalatorsForEntity = pattern( "80 7E F5 00 74 56" ).count(1);
+ auto updateEscalators = get_pattern("80 3D ? ? ? ? ? 74 22 56");
+ auto removeEscalatorsForEntity = pattern( "80 7E F5 00 74 56" ).get_one();
- if ( updateEscalators.size() == 1 && removeEscalatorsForEntity.size() == 1 )
- {
- InjectHook( updateEscalators.get_first(), UpdateEscalators, HookType::Jump );
+ InjectHook( updateEscalators, UpdateEscalators, HookType::Jump );
- // lea ecx, [esi-84] / call CEscalator::SwitchOffNoRemove / jmp loc_734C0A
- auto removeEscalatorsMatch = removeEscalatorsForEntity.get_one();
-
- // TODO: Change when short jmps are supported
- Patch( removeEscalatorsMatch.get(), { 0x8D, 0x8E } );
- Patch( removeEscalatorsMatch.get( 2 ), -0x84 );
- InjectHook( removeEscalatorsMatch.get( 6 ), &CEscalator::SwitchOffNoRemove, HookType::Call );
- Patch( removeEscalatorsMatch.get( 6 + 5 ), { 0xEB, 0x4F } );
- }
+ // lea ecx, [esi-84] / call CEscalator::SwitchOffNoRemove / jmp loc_734C0A
+ // TODO: Change when short jmps are supported
+ Patch( removeEscalatorsForEntity.get(), { 0x8D, 0x8E } );
+ Patch( removeEscalatorsForEntity.get( 2 ), -0x84 );
+ InjectHook( removeEscalatorsForEntity.get( 6 ), &CEscalator::SwitchOffNoRemove, HookType::Call );
+ Patch( removeEscalatorsForEntity.get( 6 + 5 ), { 0xEB, 0x4F } );
}
+ TXN_CATCH();
+
// Don't allocate constant memory for stencil shadows every frame
+ try
{
- // TODO: Simplify when transactional patching is implemented
- auto shadowAlloc = pattern( "83 C4 08 6A 00 68 00 60 00 00" ).count(1);
- auto shadowFree = pattern( "A2 ? ? ? ? A1 ? ? ? ? 50 E8" ).count(1);
- if ( shadowAlloc.size() == 1 && shadowFree.size() == 1 )
- {
- auto allocMatch = shadowAlloc.get_one();
+ auto shadowAlloc = pattern("83 C4 08 6A 00 68 00 60 00 00").get_one();
+ auto shadowFree = get_pattern( "A2 ? ? ? ? A1 ? ? ? ? 50 E8", 5);
- InjectHook( allocMatch.get( 3 ), StencilShadowAlloc, HookType::Call) ;
- Patch( allocMatch.get( 3 + 5 ), { 0xEB, 0x2C } );
- Nop( allocMatch.get( 0x3B ), 3 );
- Patch( shadowFree.get_first( 5 ), { 0x5F, 0x5E, 0x5B, 0x5D, 0xC3 } ); // pop edi, pop esi, pop ebx, pop ebp, retn
- }
+ InjectHook( shadowAlloc.get( 3 ), StencilShadowAlloc, HookType::Call) ;
+ Patch( shadowAlloc.get( 3 + 5 ), { 0xEB, 0x2C } );
+ Nop( shadowAlloc.get( 0x3B ), 3 );
+ Patch( shadowFree, { 0x5F, 0x5E, 0x5B, 0x5D, 0xC3 } ); // pop edi, pop esi, pop ebx, pop ebp, retn
}
+ TXN_CATCH();
+
// "Streaming memory bug" fix
+ try
{
void* animInterpolator = get_pattern( "83 C4 1C C7 03 00 30 00 00 5B", -5 );
InjectHook(animInterpolator, GTARtAnimInterpolatorSetCurrentAnim);
}
+ TXN_CATCH();
+
// Fixed ammo for melee weapons in cheats
+ try
{
- // TODO: Remove wildcards in patterns once transactional patching is implemented
- void* knifeAmmo1 = get_pattern( "6A ? 6A 04 6A FF", 1 );
- void* knifeAmmo2 = get_pattern( "6A 01 6A ? 6A 04 6A 01", 2 + 1 );
- void* chainsawAmmo1 = get_pattern( "6A ? 6A 09 6A FF", 1 );
- void* chainsawAmmo2 = get_pattern( "6A ? 6A 09 6A 01", 1 );
- void* parachuteAmmo = get_pattern( "6A ? 6A 2E 6A FF", 1 );
- void* katanaAmmo = get_pattern( "83 C4 0C ? ? ? 6A 08 6A FF", 3 );
+ void* knifeAmmo1 = get_pattern( "6A 00 6A 04 6A FF", 1 );
+ void* knifeAmmo2 = get_pattern( "6A 01 6A 00 6A 04 6A 01", 2 + 1 );
+ void* chainsawAmmo1 = get_pattern( "6A 00 6A 09 6A FF", 1 );
+ void* chainsawAmmo2 = get_pattern( "6A 00 6A 09 6A 01", 1 );
+ void* parachuteAmmo = get_pattern( "6A 00 6A 2E 6A FF", 1 );
+ void* katanaAmmo = get_pattern( "83 C4 0C 6A 01 53 6A 08 6A FF", 3 );
Patch(knifeAmmo1, 1); // knife
Patch(knifeAmmo2, 1); // knife
@@ -6491,8 +6539,11 @@ void Patch_SA_NewBinaries_Common(HINSTANCE hInstance)
// push ebx / push 1
Patch( katanaAmmo, { 0x53, 0x6A, 0x01 } ); // katana
}
+ TXN_CATCH();
+
// Proper aspect ratios
+ try
{
auto calculateAr = pattern( "74 13 D9 05 ? ? ? ? D9 1D" ).get_one(); // 0x734247; has two matches but both from the same function
@@ -6501,6 +6552,8 @@ void Patch_SA_NewBinaries_Common(HINSTANCE hInstance)
Patch(calculateAr.get( 0x1E + 2 ), &f54);
Patch(calculateAr.get( 0x31 + 2 ), &f43);
}
+ TXN_CATCH();
+
// 6 extra directionals on Medium and higher
// push dword ptr [CGame::currArea]
@@ -6508,6 +6561,7 @@ void Patch_SA_NewBinaries_Common(HINSTANCE hInstance)
// add esp, 4
// mov ebx, eax
// nop
+ try
{
auto maxdirs_addr = pattern( "83 3D ? ? ? ? 00 8D 5E 05 74 05 BB 06 00 00 00" ).get_one();
@@ -6516,15 +6570,21 @@ void Patch_SA_NewBinaries_Common(HINSTANCE hInstance)
Patch( maxdirs_addr.get(11), { 0x83, 0xC4, 0x04, 0x8B, 0xD8 } );
Nop( maxdirs_addr.get(16), 1 );
}
+ TXN_CATCH();
+
// AI accuracy issue
+ try
{
auto match = pattern( "8B 82 8C 05 00 00 85 C0 74 09" ).get_one(); // 0x76DEA7 in newsteam r1
Nop(match.get(0), 1);
InjectHook( match.get(1), WeaponRangeMult_VehicleCheck, HookType::Call );
}
+ TXN_CATCH();
+
// Don't catch WM_SYSKEYDOWN and WM_SYSKEYUP (fixes Alt+F4)
+ try
{
auto patternie = pattern( "8B 75 10 8B ? 14 56" ).count(2); // 0x77C588 and 0x77C5CC in newsteam r2
auto defproc = get_pattern( "8B ? 14 8B ? 10 8B ? 08 ? ? 56" );
@@ -6539,12 +6599,26 @@ void Patch_SA_NewBinaries_Common(HINSTANCE hInstance)
Patch( match.get(0x2B + 2), -8 ); // use stack space for new lParam
} );
}
+ TXN_CATCH();
// Reset variables on New Game
+ try
{
using namespace VariableResets;
+ // Variables to reset
+ {
+ auto timers_init = pattern( "89 45 FC DB 45 FC C6 05 ? ? ? ? 01" ).get_one();
+
+ GameVariablesToReset.emplace_back( *timers_init.get(-17 + 2) );
+ GameVariablesToReset.emplace_back( *timers_init.get(-11 + 2) );
+ GameVariablesToReset.emplace_back( *timers_init.get*>(0x41 + 2) );
+ }
+
+ GameVariablesToReset.emplace_back( *get_pattern( "A2 ? ? ? ? E9 ? ? ? ? 6A 01 8B CE", 1 ) ); // CGameLogic::bPenaltyForDeathApplies
+ GameVariablesToReset.emplace_back( *get_pattern( "88 0D ? ? ? ? E9 ? ? ? ? 6A 05", 2 ) ); // CGameLogic::bPenaltyForArrestApplies
+
{
auto loadPickup = get_pattern("E8 ? ? ? ? EB 1B 6A 00");
auto loadCarGenerator = get_pattern("E8 ? ? ? ? 83 C4 08 EB 11");
@@ -6560,40 +6634,38 @@ void Patch_SA_NewBinaries_Common(HINSTANCE hInstance)
InterceptCall(loadCarGenerator, orgLoadCarGenerator, LoadCarGenerator_SaveLine);
InterceptCall(loadStuntJump, orgLoadStuntJump, LoadStuntJump_SaveLine);
}
-
- // Variables to reset
- {
- auto timers_init = pattern( "89 45 FC DB 45 FC C6 05 ? ? ? ? 01" ).get_one();
-
- GameVariablesToReset.emplace_back( *timers_init.get(-17 + 2) );
- GameVariablesToReset.emplace_back( *timers_init.get(-11 + 2) );
- GameVariablesToReset.emplace_back( *timers_init.get*>(0x41 + 2) );
- }
-
- GameVariablesToReset.emplace_back( *get_pattern( "A2 ? ? ? ? E9 ? ? ? ? 6A 01 8B CE", 1 ) ); // CGameLogic::bPenaltyForDeathApplies
- GameVariablesToReset.emplace_back( *get_pattern( "88 0D ? ? ? ? E9 ? ? ? ? 6A 05", 2 ) ); // CGameLogic::bPenaltyForArrestApplies
}
+ TXN_CATCH();
+
// FuckCarCompletely not fixing panels
+ try
{
void* panel_addr = get_pattern( "C6 46 04 FA 5E 5B", -3 );
Nop(panel_addr, 3);
}
+ TXN_CATCH();
+
// 014C cargen counter fix (by spaceeinstein)
+ try
{
auto do_processing = pattern( "B8 C3 2E 57 06 F7 EE C1 FA 06" ).get_one();
Patch( do_processing.get