Migrate to transactional patterns

This commit is contained in:
Silent 2024-05-16 23:43:48 +02:00
parent 6ee676400b
commit d4374df50a
No known key found for this signature in database
GPG key ID: AE53149BB0C45AF1
9 changed files with 706 additions and 439 deletions

View file

@ -75,7 +75,6 @@
<SDLCheck>true</SDLCheck> <SDLCheck>true</SDLCheck>
<AdditionalIncludeDirectories>..\SilentPatch;..\DDraw;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>..\SilentPatch;..\DDraw;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>_HAS_EXCEPTIONS=0;%(PreprocessorDefinitions)</PreprocessorDefinitions> <PreprocessorDefinitions>_HAS_EXCEPTIONS=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ExceptionHandling>false</ExceptionHandling>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary> <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<EnableEnhancedInstructionSet>NoExtensions</EnableEnhancedInstructionSet> <EnableEnhancedInstructionSet>NoExtensions</EnableEnhancedInstructionSet>
<EnforceTypeConversionRules>true</EnforceTypeConversionRules> <EnforceTypeConversionRules>true</EnforceTypeConversionRules>
@ -107,7 +106,6 @@ copy /y "$(TargetPath)" "D:\Steam\steamapps\common\Grand Theft Auto Vice City\dd
<AdditionalIncludeDirectories>..\SilentPatch;..\DDraw;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>..\SilentPatch;..\DDraw;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>_HAS_EXCEPTIONS=0;%(PreprocessorDefinitions)</PreprocessorDefinitions> <PreprocessorDefinitions>_HAS_EXCEPTIONS=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<StringPooling>true</StringPooling> <StringPooling>true</StringPooling>
<ExceptionHandling>false</ExceptionHandling>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary> <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<EnableEnhancedInstructionSet>NoExtensions</EnableEnhancedInstructionSet> <EnableEnhancedInstructionSet>NoExtensions</EnableEnhancedInstructionSet>
<EnforceTypeConversionRules>true</EnforceTypeConversionRules> <EnforceTypeConversionRules>true</EnforceTypeConversionRules>
@ -141,7 +139,6 @@ copy /y "$(TargetPath)" "D:\Steam\steamapps\common\Grand Theft Auto Vice City\dd
<AdditionalIncludeDirectories>..\SilentPatch;..\DDraw;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>..\SilentPatch;..\DDraw;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>_HAS_EXCEPTIONS=0;NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions> <PreprocessorDefinitions>_HAS_EXCEPTIONS=0;NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<StringPooling>true</StringPooling> <StringPooling>true</StringPooling>
<ExceptionHandling>false</ExceptionHandling>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary> <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<EnableEnhancedInstructionSet>NoExtensions</EnableEnhancedInstructionSet> <EnableEnhancedInstructionSet>NoExtensions</EnableEnhancedInstructionSet>
<EnforceTypeConversionRules>true</EnforceTypeConversionRules> <EnforceTypeConversionRules>true</EnforceTypeConversionRules>

View file

@ -208,30 +208,38 @@ namespace Common {
void III_VC_Common() void III_VC_Common()
{ {
using namespace Memory; using namespace Memory;
using namespace hook; using namespace hook::txn;
// Delayed patching // Delayed patching
try
{ {
using namespace DelayedPatches; using namespace DelayedPatches;
auto addr_mssHook = get_pattern( "6A 00 6A 02 6A 10 68 00 7D 00 00", -6 + 2 ); 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<decltype(OldSetPreference)*>(addr_mssHook); OldSetPreference = *static_cast<decltype(OldSetPreference)*>(addr_mssHook);
Patch( addr_mssHook, &pInjectMSS ); Patch( addr_mssHook, &pInjectMSS );
auto addr_ualHook = get_pattern( "FF 15 ? ? ? ? 6A 00 6A 18", 0xA );
ReadCall( addr_ualHook, RsEventHandler ); ReadCall( addr_ualHook, RsEventHandler );
InjectHook( addr_ualHook, Inject_UAL ); InjectHook( addr_ualHook, Inject_UAL );
} }
TXN_CATCH();
// Fixed bomb ownership/bombs saving for bikes // Fixed bomb ownership/bombs saving for bikes
try
{ {
auto addr = get_pattern( "83 3C 33 00 74 19 89 F9 E8", 8 ); auto addr = get_pattern( "83 3C 33 00 74 19 89 F9 E8", 8 );
ReadCall( addr, CStoredCar::orgRestoreCar ); ReadCall( addr, CStoredCar::orgRestoreCar );
InjectHook( addr, &CStoredCar::RestoreCar_SilentPatch ); InjectHook( addr, &CStoredCar::RestoreCar_SilentPatch );
} }
TXN_CATCH();
// Fixed handling.cfg name matching (names don't need unique prefixes anymore) // Fixed handling.cfg name matching (names don't need unique prefixes anymore)
try
{ {
using namespace HandlingNameLoadFix; using namespace HandlingNameLoadFix;
@ -240,9 +248,11 @@ namespace Common {
InjectHook( findExactWord.get<void>( -5 ), strncpy_Fix ); InjectHook( findExactWord.get<void>( -5 ), strncpy_Fix );
InjectHook( findExactWord.get<void>( 0xD ), strncmp_Fix ); InjectHook( findExactWord.get<void>( 0xD ), strncmp_Fix );
} }
TXN_CATCH();
// Fixed corona lines rendering on non-nvidia cards // Fixed corona lines rendering on non-nvidia cards
try
{ {
using namespace CoronaLinesFix; using namespace CoronaLinesFix;
@ -250,9 +260,11 @@ namespace Common {
InterceptCall(renderLine, orgRwIm2DRenderLine, RenderLine_SetRecipZ); InterceptCall(renderLine, orgRwIm2DRenderLine, RenderLine_SetRecipZ);
} }
TXN_CATCH();
// Fixed static shadows not rendering under fire and pickups // Fixed static shadows not rendering under fire and pickups
try
{ {
using namespace StaticShadowAlphaFix; using namespace StaticShadowAlphaFix;
@ -281,9 +293,11 @@ namespace Common {
HookEach_StoreAlphaTest(disableAlphaTestAndSetState, InterceptCall); HookEach_StoreAlphaTest(disableAlphaTestAndSetState, InterceptCall);
HookEach_RestoreAlphaTest(setStateAndReenableAlphaTest, InterceptCall); HookEach_RestoreAlphaTest(setStateAndReenableAlphaTest, InterceptCall);
} }
TXN_CATCH();
// Reset requested extras if created vehicle has no extras // Reset requested extras if created vehicle has no extras
try
{ {
using namespace CompsToUseFix; using namespace CompsToUseFix;
@ -291,10 +305,12 @@ namespace Common {
InjectHook( resetComps.get<void>( -14 ), ResetCompsForNoExtras, HookType::Call ); InjectHook( resetComps.get<void>( -14 ), ResetCompsForNoExtras, HookType::Call );
Nop( resetComps.get<void>( -9 ), 9 ); Nop( resetComps.get<void>( -9 ), 9 );
} }
TXN_CATCH();
// Rescale light switching randomness in CAutomobile::PreRender/CBike::PreRender for PC the randomness range // 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 // 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 // GTA III expects 2 matches, VC expects 4 due to the addition of CBike::PreRender
#if _GTA_III #if _GTA_III
@ -310,9 +326,11 @@ namespace Common {
Patch<const void*>(match.get<void>(2), &LightStatusRandomnessThreshold); Patch<const void*>(match.get<void>(2), &LightStatusRandomnessThreshold);
}); });
} }
TXN_CATCH();
// Make script randomness 16-bit, like on PS2 // Make script randomness 16-bit, like on PS2
try
{ {
using namespace Rand16bit; using namespace Rand16bit;
@ -323,6 +341,7 @@ namespace Common {
HookEach_Rand(rands, InterceptCall); HookEach_Rand(rands, InterceptCall);
} }
TXN_CATCH();
} }
void III_VC_SetDelayedPatchesFunc( void(*func)() ) void III_VC_SetDelayedPatchesFunc( void(*func)() )
@ -333,24 +352,21 @@ namespace Common {
void III_VC_DelayedCommon( bool /*hasDebugMenu*/, const wchar_t* wcModulePath ) void III_VC_DelayedCommon( bool /*hasDebugMenu*/, const wchar_t* wcModulePath )
{ {
using namespace Memory; using namespace Memory;
using namespace hook; using namespace hook::txn;
ExtraCompSpecularity::ReadExtraCompSpecularityExceptions(wcModulePath); ExtraCompSpecularity::ReadExtraCompSpecularityExceptions(wcModulePath);
// Corrected taxi light placement for Taxi // 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; 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 ) Patch<uint8_t>( getTaxiLightPos.get<void>( -15 ), 0x55 ); // push eax -> push ebp
{ InjectHook( getTaxiLightPos.get<void>(), GetTransformedCoronaPos );
auto match = getTaxiLightPos.get_one();
Patch<uint8_t>( match.get<void>( -15 ), 0x55 ); // push eax -> push ebp
InjectHook( match.get<void>(), GetTransformedCoronaPos );
}
} }
TXN_CATCH();
} }
} }
} }

View file

@ -39,25 +39,37 @@ namespace Common {
namespace Patches { 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" ); // _rwcseg can be placed far after the code section, and the default pattern heuristics currently break with it
auto end = pattern( "9B D9 3D ? ? ? ? 81 25 ? ? ? ? FF FC FF FF 83 0D ? ? ? ? 3F" ); // (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<uintptr_t>(GetModuleHandle(nullptr));
PIMAGE_DOS_HEADER dosHeader = reinterpret_cast<PIMAGE_DOS_HEADER>(module);
PIMAGE_NT_HEADERS ntHeader = reinterpret_cast<PIMAGE_NT_HEADERS>(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<void>();
auto end = make_range_pattern(moduleBegin, moduleEnd, "9B D9 3D ? ? ? ? 81 25 ? ? ? ? FF FC FF FF 83 0D ? ? ? ? 3F").get_first<void>(31);
const ptrdiff_t size = reinterpret_cast<uintptr_t>(end) - reinterpret_cast<uintptr_t>(begin);
if ( size > 0 )
{ {
const ptrdiff_t size = (intptr_t)end.get_first( 24 ) - (intptr_t)begin.get_first(); DWORD dwProtect;
if ( size > 0 ) VirtualProtect( begin, size, PAGE_EXECUTE_READ, &dwProtect );
{ return true;
DWORD dwProtect;
VirtualProtect( begin.get_first(), size, PAGE_EXECUTE_READ, &dwProtect );
return true;
}
} }
return false; return false;
} }
catch (const hook::txn_exception&)
{
return false;
}
// ================= III ================= // ================= III =================
void DDraw_III_10( uint32_t width, uint32_t height, const char* desktopText ) void DDraw_III_10( uint32_t width, uint32_t height, const char* desktopText )
@ -207,38 +219,34 @@ namespace Common {
void DDraw_Common() void DDraw_Common()
{ {
using namespace Memory; using namespace Memory;
using namespace hook; using namespace hook::txn;
// Remove FILE_FLAG_NO_BUFFERING from CdStreams // Remove FILE_FLAG_NO_BUFFERING from CdStreams
try
{ {
auto mem = pattern( "81 7C 24 04 00 08 00 00" ).count_hint(1); auto mem = get_pattern("81 7C 24 04 00 08 00 00", 0x12);
if ( mem.size() == 1 ) Patch<uint8_t>( mem, 0xEB );
{
Patch<uint8_t>( mem.get_first( 0x12 ), 0xEB );
}
} }
TXN_CATCH();
// No censorships // No censorships
try
{ {
auto addr = pattern( "83 FB 07 74 0A 83 FD 07 74 05 83 FE 07 75 15" ).count_hint(1); auto addr = get_pattern( "83 FB 07 74 0A 83 FD 07 74 05 83 FE 07 75 15" );
if ( addr.size() == 1 ) Patch( addr, { 0xEB, 0x5E } );
{
Patch( addr.get_first(), { 0xEB, 0x5E } );
}
} }
TXN_CATCH();
// unnamed CdStream semaphore // unnamed CdStream semaphore
try
{ {
auto mem = pattern( "8D 04 85 00 00 00 00 50 6A 40 FF 15" ).count_hint(1); auto mem = pattern( "8D 04 85 00 00 00 00 50 6A 40 FF 15" ).get_one();
if ( mem.size() == 1 )
{
Patch( mem.get_first( 0x25 ), { 0x6A, 0x00 } ); // push 0 \ nop
Nop( mem.get_first( 0x25 + 2 ), 3 );
}
Patch( mem.get<void>( 0x25 ), { 0x6A, 0x00 } ); // push 0 \ nop
Nop( mem.get<void>( 0x25 + 2 ), 3 );
} }
TXN_CATCH();
} }
} }
} }

View file

@ -842,7 +842,7 @@ namespace SitInBoat
void InjectDelayedPatches_III_Common( bool bHasDebugMenu, const wchar_t* wcModulePath ) void InjectDelayedPatches_III_Common( bool bHasDebugMenu, const wchar_t* wcModulePath )
{ {
using namespace Memory; using namespace Memory;
using namespace hook; using namespace hook::txn;
const ModuleList moduleList; 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 // 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 // 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); auto canPickBlista = get_pattern("83 FA 66 74", 2);
if ( canPickBlista.size() == 1 ) Patch<int8_t>( canPickBlista, 127 ); // coach
{
Patch<int8_t>( canPickBlista.get_first<void>( 2 ), 127 ); // coach
}
} }
TXN_CATCH();
// Corrected siren corona placement for emergency vehicles // Corrected siren corona placement for emergency vehicles
if ( GetPrivateProfileIntW(L"SilentPatch", L"EnableVehicleCoronaFixes", -1, wcModulePath) == 1 ) 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 // 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 firetruckX1 = get_pattern("C7 84 24 9C 05 00 00 CD CC 8C 3F", 7);
auto firetruckY1 = pattern( "C7 84 24 A4 05 00 00 9A 99 D9 3F" ); auto firetruckY1 = get_pattern("C7 84 24 A4 05 00 00 9A 99 D9 3F", 7);
auto firetruckZ1 = pattern( "C7 84 24 A8 05 00 00 00 00 00 40" ); 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 firetruckX2 = get_pattern("C7 84 24 A8 05 00 00 CD CC 8C BF", 7);
auto firetruckY2 = pattern( "C7 84 24 B0 05 00 00 9A 99 D9 3F" ); auto firetruckY2 = get_pattern("C7 84 24 B0 05 00 00 9A 99 D9 3F", 7);
auto firetruckZ2 = pattern( "C7 84 24 B4 05 00 00 00 00 00 40" ); 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 && constexpr CVector FIRETRUCK_SIREN_POS(0.95f, 3.2f, 1.4f);
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);
Patch<float>( firetruckX1.get_first( 7 ), FIRETRUCK_SIREN_POS.x ); Patch<float>( firetruckX1, FIRETRUCK_SIREN_POS.x );
Patch<float>( firetruckY1.get_first( 7 ), FIRETRUCK_SIREN_POS.y ); Patch<float>( firetruckY1, FIRETRUCK_SIREN_POS.y );
Patch<float>( firetruckZ1.get_first( 7 ), FIRETRUCK_SIREN_POS.z ); Patch<float>( firetruckZ1, FIRETRUCK_SIREN_POS.z );
Patch<float>( firetruckX2.get_first( 7 ), -FIRETRUCK_SIREN_POS.x ); Patch<float>( firetruckX2, -FIRETRUCK_SIREN_POS.x );
Patch<float>( firetruckY2.get_first( 7 ), FIRETRUCK_SIREN_POS.y ); Patch<float>( firetruckY2, FIRETRUCK_SIREN_POS.y );
Patch<float>( firetruckZ2.get_first( 7 ), FIRETRUCK_SIREN_POS.z ); Patch<float>( firetruckZ2, FIRETRUCK_SIREN_POS.z );
}
} }
TXN_CATCH();
try
{ {
auto ambulanceX1 = pattern( "C7 84 24 84 05 00 00 CD CC 8C 3F" ); auto ambulanceX1 = get_pattern("C7 84 24 84 05 00 00 CD CC 8C 3F", 7);
auto ambulanceY1 = pattern( "C7 84 24 8C 05 00 00 66 66 66 3F" ); auto ambulanceY1 = get_pattern("C7 84 24 8C 05 00 00 66 66 66 3F", 7);
auto ambulanceZ1 = pattern( "C7 84 24 90 05 00 00 CD CC CC 3F" ); 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 ambulanceX2 = get_pattern("C7 84 24 90 05 00 00 CD CC 8C BF", 7);
auto ambulanceY2 = pattern( "C7 84 24 98 05 00 00 66 66 66 3F" ); auto ambulanceY2 = get_pattern("C7 84 24 98 05 00 00 66 66 66 3F", 7);
auto ambulanceZ2 = pattern( "C7 84 24 9C 05 00 00 CD CC CC 3F" ); 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 && constexpr CVector AMBULANCE_SIREN_POS(0.7f, 0.65f, 1.55f);
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);
Patch<float>( ambulanceX1.get_first( 7 ), AMBULANCE_SIREN_POS.x ); Patch<float>( ambulanceX1, AMBULANCE_SIREN_POS.x );
Patch<float>( ambulanceY1.get_first( 7 ), AMBULANCE_SIREN_POS.y ); Patch<float>( ambulanceY1, AMBULANCE_SIREN_POS.y );
Patch<float>( ambulanceZ1.get_first( 7 ), AMBULANCE_SIREN_POS.z ); Patch<float>( ambulanceZ1, AMBULANCE_SIREN_POS.z );
Patch<float>( ambulanceX2.get_first( 7 ), -AMBULANCE_SIREN_POS.x ); Patch<float>( ambulanceX2, -AMBULANCE_SIREN_POS.x );
Patch<float>( ambulanceY2.get_first( 7 ), AMBULANCE_SIREN_POS.y ); Patch<float>( ambulanceY2, AMBULANCE_SIREN_POS.y );
Patch<float>( ambulanceZ2.get_first( 7 ), AMBULANCE_SIREN_POS.z ); Patch<float>( ambulanceZ2, AMBULANCE_SIREN_POS.z );
}
} }
TXN_CATCH();
try
{ {
auto enforcerX1 = pattern( "C7 84 24 6C 05 00 00 CD CC 8C 3F" ); auto enforcerX1 = get_pattern("C7 84 24 6C 05 00 00 CD CC 8C 3F", 7);
auto enforcerY1 = pattern( "C7 84 24 74 05 00 00 CD CC 4C 3F" ); auto enforcerY1 = get_pattern("C7 84 24 74 05 00 00 CD CC 4C 3F", 7);
auto enforcerZ1 = pattern( "C7 84 24 78 05 00 00 9A 99 99 3F" ); 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 enforcerX2 = get_pattern("C7 84 24 78 05 00 00 CD CC 8C BF", 7);
auto enforcerY2 = pattern( "C7 84 24 80 05 00 00 CD CC 4C 3F" ); auto enforcerY2 = get_pattern("C7 84 24 80 05 00 00 CD CC 4C 3F", 7);
auto enforcerZ2 = pattern( "C7 84 24 84 05 00 00 9A 99 99 3F" ); 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 && constexpr CVector ENFORCER_SIREN_POS(0.6f, 1.05f, 1.4f);
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);
Patch<float>( enforcerX1.get_first( 7 ), ENFORCER_SIREN_POS.x ); Patch<float>( enforcerX1, ENFORCER_SIREN_POS.x );
Patch<float>( enforcerY1.get_first( 7 ), ENFORCER_SIREN_POS.y ); Patch<float>( enforcerY1, ENFORCER_SIREN_POS.y );
Patch<float>( enforcerZ1.get_first( 7 ), ENFORCER_SIREN_POS.z ); Patch<float>( enforcerZ1, ENFORCER_SIREN_POS.z );
Patch<float>( enforcerX2.get_first( 7 ), -ENFORCER_SIREN_POS.x ); Patch<float>( enforcerX2, -ENFORCER_SIREN_POS.x );
Patch<float>( enforcerY2.get_first( 7 ), ENFORCER_SIREN_POS.y ); Patch<float>( enforcerY2, ENFORCER_SIREN_POS.y );
Patch<float>( enforcerZ2.get_first( 7 ), ENFORCER_SIREN_POS.z ); Patch<float>( 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( chopper1.get<float>( 4 ), CHOPPER_SEARCH_LIGHT_POS.y );
Patch( chopper1.get<float>( 9 + 4 ), CHOPPER_SEARCH_LIGHT_POS.z );
Patch( match.get<float>( 4 ), CHOPPER_SEARCH_LIGHT_POS.y );
Patch( match.get<float>( 9 + 4 ), CHOPPER_SEARCH_LIGHT_POS.z );
}
} }
TXN_CATCH();
} }
// Corrected FBI Car secondary siren sound // Corrected FBI Car secondary siren sound
try
{ {
using namespace SirenSwitchingFix; using namespace SirenSwitchingFix;
// Other mods might be touching it, so only patch specific vehicles if their code has not been touched at all // 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); auto usesSirenSwitching = pattern("E8 ? ? ? ? 84 C0 74 12 83 C4 08").get_one();
if ( usesSirenSwitching.size() == 1 )
{ InterceptCall(usesSirenSwitching.get<void>(), orgUsesSirenSwitching, UsesSirenSwitching_FbiCar);
auto match = usesSirenSwitching.get_one();
ReadCall( match.get<void>(), orgUsesSirenSwitching );
InjectHook( match.get<void>(), UsesSirenSwitching_FbiCar );
}
} }
TXN_CATCH();
// Corrected CSimpleModelInfo::SetupBigBuilding minimum draw distance for big buildings without a matching model // Corrected CSimpleModelInfo::SetupBigBuilding minimum draw distance for big buildings without a matching model
// Fixes cranes in Portland and bright windows in the city // Fixes cranes in Portland and bright windows in the city
// By aap // By aap
try
{ {
auto setupMinDist = pattern( "C7 43 44 00 00 C8 42" ).count_hint(1); auto setupMinDist = pattern("C7 43 44 00 00 C8 42").get_one();
if ( setupMinDist.size() == 1 ) // In case of another mod or second instance of SP changing it
{
auto match = setupMinDist.get_one();
// mov ecx, ebx // mov ecx, ebx
// call CSimpleModelInfo::SetNearDistanceForLOD // call CSimpleModelInfo::SetNearDistanceForLOD
Patch( match.get<void>(), { 0x89, 0xD9 } ); Patch( setupMinDist.get<void>(), { 0x89, 0xD9 } );
InjectHook( match.get<void>( 2 ), &CSimpleModelInfo::SetNearDistanceForLOD_SilentPatch, HookType::Call ); InjectHook( setupMinDist.get<void>( 2 ), &CSimpleModelInfo::SetNearDistanceForLOD_SilentPatch, HookType::Call );
}
} }
TXN_CATCH();
FLAUtils::Init(moduleList); FLAUtils::Init(moduleList);
} }
@ -1346,10 +1335,11 @@ void Patch_III_Steam(uint32_t width, uint32_t height)
void Patch_III_Common() void Patch_III_Common()
{ {
using namespace Memory; using namespace Memory;
using namespace hook; using namespace hook::txn;
// New timers fix // 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 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" ); auto jmpPoint = get_pattern( "DD D8 E9 37 FF FF FF DD D8" );
@ -1357,8 +1347,11 @@ void Patch_III_Common()
InjectHook( hookPoint.get<void>( 0x21 ), CTimer::Update_SilentPatch, HookType::Call ); InjectHook( hookPoint.get<void>( 0x21 ), CTimer::Update_SilentPatch, HookType::Call );
InjectHook( hookPoint.get<void>( 0x21 + 5 ), jmpPoint, HookType::Jump ); InjectHook( hookPoint.get<void>( 0x21 + 5 ), jmpPoint, HookType::Jump );
} }
TXN_CATCH();
// Alt+F4 // Alt+F4
try
{ {
auto addr = pattern( "59 59 31 C0 83 C4 48 5D 5F 5E 5B C2 10 00" ).count(2); 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" ); auto dest = get_pattern( "53 55 56 FF 74 24 68 FF 15" );
@ -1367,8 +1360,11 @@ void Patch_III_Common()
InjectHook( match.get<void>( 2 ), dest, HookType::Jump ); InjectHook( match.get<void>( 2 ), dest, HookType::Jump );
}); });
} }
TXN_CATCH();
// Proper panels damage // Proper panels damage
try
{ {
auto addr = pattern( "C6 43 09 03 C6 43 0A 03 C6 43 0B 03" ).get_one(); 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<uint8_t>( addr.get<void>( 0x23 + 1 ), 6 ); Patch<uint8_t>( addr.get<void>( 0x23 + 1 ), 6 );
Nop( addr.get<void>( 0x3F ), 7 ); Nop( addr.get<void>( 0x3F ), 7 );
} }
TXN_CATCH();
// Proper metric-imperial conversion constants // Proper metric-imperial conversion constants
try
{ {
static const float METERS_TO_MILES = 0.0006213711922f; static const float METERS_TO_MILES = 0.0006213711922f;
static const float METERS_TO_FEET = 3.280839895f; static const float METERS_TO_FEET = 3.280839895f;
@ -1389,8 +1388,11 @@ void Patch_III_Common()
Patch<const void*>( addr.get(2).get<void>( 2 ), &METERS_TO_FEET ); Patch<const void*>( addr.get(2).get<void>( 2 ), &METERS_TO_FEET );
Patch<const void*>( addr.get(3).get<void>( 2 ), &METERS_TO_FEET ); Patch<const void*>( addr.get(3).get<void>( 2 ), &METERS_TO_FEET );
} }
TXN_CATCH();
// Improved pathfinding in PickNextNodeAccordingStrategy - PickNextNodeToChaseCar with XYZ coords // Improved pathfinding in PickNextNodeAccordingStrategy - PickNextNodeToChaseCar with XYZ coords
try
{ {
auto addr = pattern( "E8 ? ? ? ? 50 8D 44 24 10 50 E8" ).get_one(); auto addr = pattern( "E8 ? ? ? ? 50 8D 44 24 10 50 E8" ).get_one();
ReadCall( addr.get<void>( 0x25 ), orgPickNextNodeToChaseCar ); ReadCall( addr.get<void>( 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) // Uncomment this to get rid of "treadable hack" in CCarCtrl::PickNextNodeToChaseCar (to mirror VC behaviour)
InjectHook( funcAddr + 0x2A, funcAddr + 0x182, HookType::Jump ); InjectHook( funcAddr + 0x2A, funcAddr + 0x182, HookType::Jump );
} }
TXN_CATCH();
// No censorships // No censorships
try
{ {
auto addr = get_pattern( "8B 15 ? ? ? ? C6 05 ? ? ? ? 00 89 D0" ); auto addr = get_pattern( "8B 15 ? ? ? ? C6 05 ? ? ? ? 00 89 D0" );
Patch( addr, { 0x83, 0xC4, 0x08, 0xC3 } ); // add esp, 8 \ retn Patch( addr, { 0x83, 0xC4, 0x08, 0xC3 } ); // add esp, 8 \ retn
} }
TXN_CATCH();
// 014C cargen counter fix (by spaceeinstein) // 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(); auto do_processing = pattern( "0F B7 45 28 83 F8 FF 7D 04 66 FF 4D 28" ).get_one();
Patch<uint8_t>( do_processing.get<uint8_t*>(1), 0xBF ); // movzx eax, word ptr [ebx+28h] -> movsx eax, word ptr [ebx+28h] Patch<uint8_t>( do_processing.get<uint8_t*>(1), 0xBF ); // movzx eax, word ptr [ebx+28h] -> movsx eax, word ptr [ebx+28h]
Patch<uint8_t>( do_processing.get<uint8_t*>(7), 0x74 ); // jge -> jz Patch<uint8_t>( do_processing.get<uint8_t*>(7), 0x74 ); // jge -> jz
} }
TXN_CATCH();
// Fixed ammo from SCM // Fixed ammo from SCM
try
{ {
using namespace ZeroAmmoFix; using namespace ZeroAmmoFix;
@ -1449,9 +1457,11 @@ void Patch_III_Common()
}; };
HookEach_GiveWeapon(give_weapon, InterceptCall); HookEach_GiveWeapon(give_weapon, InterceptCall);
} }
TXN_CATCH();
// Credits =) // 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(); 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<void>( -5 ), Credits::PrintCreditText_Hooked ); ReadCall( renderCredits.get<void>( -5 ), Credits::PrintCreditText_Hooked );
InjectHook( renderCredits.get<void>( -5 ), Credits::PrintSPCredits ); InjectHook( renderCredits.get<void>( -5 ), Credits::PrintSPCredits );
} }
TXN_CATCH();
// Decreased keyboard input latency // Decreased keyboard input latency
try
{ {
using namespace KeyboardInputFix; using namespace KeyboardInputFix;
@ -1477,20 +1489,20 @@ void Patch_III_Common()
InjectHook( simButtonCheckers, ClearSimButtonPressCheckers ); InjectHook( simButtonCheckers, ClearSimButtonPressCheckers );
InjectHook( updatePads.get<void>( 10 ), jmpDest, HookType::Jump ); InjectHook( updatePads.get<void>( 10 ), jmpDest, HookType::Jump );
} }
TXN_CATCH();
// Locale based metric/imperial system // Locale based metric/imperial system
try
{ {
using namespace Localization; using namespace Localization;
void* updateCompareFlag = get_pattern( "89 E9 6A 00 E8 ? ? ? ? 30 C0 83 C4 70 5D 5E 5B C2 04 00", 4 ); 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 ); ReadCall( updateCompareFlag, orgUpdateCompareFlag_IsMetric );
InjectHook( updateCompareFlag, UpdateCompareFlag_IsMetric ); InjectHook( updateCompareFlag, UpdateCompareFlag_IsMetric );
// Stats
auto constructStatLine = pattern( "FF 24 9D ? ? ? ? 39 D0" ).get_one();
// push eax // push eax
// push edx // push edx
// call IsMetric_LocaleBased // call IsMetric_LocaleBased
@ -1503,25 +1515,29 @@ void Patch_III_Common()
Patch( constructStatLine.get<void>( -0xF + 7 ), { 0x0F, 0xB6, 0xD8, 0x5A, 0x58 } ); Patch( constructStatLine.get<void>( -0xF + 7 ), { 0x0F, 0xB6, 0xD8, 0x5A, 0x58 } );
Nop( constructStatLine.get<void>( -0xF + 12 ), 3 ); Nop( constructStatLine.get<void>( -0xF + 12 ), 3 );
} }
TXN_CATCH();
// Add cDMAudio::IsAudioInitialised checks before constructing cAudioScriptObject, like in VC // Add cDMAudio::IsAudioInitialised checks before constructing cAudioScriptObject, like in VC
try
{ {
using namespace AudioInitializedFix; using namespace AudioInitializedFix;
auto processCommands300 = pattern( "E8 ? ? ? ? 85 C0 59 74 ? 89 C1 E8 ? ? ? ? D9 05" ).get_one(); 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<uintptr_t*>( "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<void>( 0 ), operatorNew ); ReadCall( processCommands300.get<void>( 0 ), operatorNew );
InjectHook( processCommands300.get<void>( 0 ), operatorNew_InitializedCheck ); InjectHook( processCommands300.get<void>( 0 ), operatorNew_InitializedCheck );
Patch<int8_t>( processCommands300.get<void>( 8 + 1 ), 0x440B62 - 0x440B24 ); Patch<int8_t>( processCommands300.get<void>( 8 + 1 ), 0x440B62 - 0x440B24 );
auto processCommands300_2 = pattern( "6A 14 E8 ? ? ? ? 89 C3 59 85 DB 74" ).get_one();
InjectHook( processCommands300_2.get<void>( 2 ), operatorNew_InitializedCheck ); InjectHook( processCommands300_2.get<void>( 2 ), operatorNew_InitializedCheck );
Patch<int8_t>( processCommands300_2.get<void>( 0xC + 1 ), 0x440BD7 - 0x440B8B ); Patch<int8_t>( processCommands300_2.get<void>( 0xC + 1 ), 0x440BD7 - 0x440B8B );
// We need to patch switch cases 0, 3, 4 // We need to patch switch cases 0, 3, 4
auto bulletInfoUpdate_Switch = *get_pattern<uintptr_t*>( "FF 24 85 ? ? ? ? 6A 14", 3 );
const uintptr_t bulletInfoUpdate_0 = bulletInfoUpdate_Switch[0]; const uintptr_t bulletInfoUpdate_0 = bulletInfoUpdate_Switch[0];
const uintptr_t bulletInfoUpdate_3 = bulletInfoUpdate_Switch[3]; const uintptr_t bulletInfoUpdate_3 = bulletInfoUpdate_Switch[3];
const uintptr_t bulletInfoUpdate_4 = bulletInfoUpdate_Switch[4]; const uintptr_t bulletInfoUpdate_4 = bulletInfoUpdate_Switch[4];
@ -1535,32 +1551,31 @@ void Patch_III_Common()
InjectHook( bulletInfoUpdate_4 + 2, operatorNew_InitializedCheck ); InjectHook( bulletInfoUpdate_4 + 2, operatorNew_InitializedCheck );
Patch<int8_t>( bulletInfoUpdate_4 + 0xA + 1, 0x558C19 - 0x558BE3 ); Patch<int8_t>( 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<void>( 2 ), operatorNew_InitializedCheck ); InjectHook( playlayOneShotScriptObject.get<void>( 2 ), operatorNew_InitializedCheck );
Patch<int8_t>( playlayOneShotScriptObject.get<void>( 0xA + 1 ), 0x57C633 - 0x57C601 ); Patch<int8_t>( playlayOneShotScriptObject.get<void>( 0xA + 1 ), 0x57C633 - 0x57C601 );
auto loadAllAudioScriptObjects = get_pattern( "FF B5 78 FF FF FF E8 ? ? ? ? 59 59 8B 45 C8", 6 );
ReadCall( loadAllAudioScriptObjects, orgLoadAllAudioScriptObjects ); ReadCall( loadAllAudioScriptObjects, orgLoadAllAudioScriptObjects );
InjectHook( loadAllAudioScriptObjects, LoadAllAudioScriptObjects_InitializedCheck ); InjectHook( loadAllAudioScriptObjects, LoadAllAudioScriptObjects_InitializedCheck );
} }
TXN_CATCH();
// Give chopper/escape a properly sized collision bounding box instead of using ped's // 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); auto initHelis = pattern( "C6 40 2C 00 A1" ).get_one();
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 = initHelisPattern.get_one(); static constexpr CColModel colModelChopper( CColSphere( 8.5f, CVector(0.0f, -1.75f, 0.73f), 0, 0 ),
Patch( initHelis.get<void>( -7 + 3 ), &colModelChopper ); CColBox( CVector(-2.18f, -8.52f, -0.67f), CVector(-2.18f, 4.58f, 2.125f), 0, 0 ) );
Patch( initHelis.get<void>( 9 + 3 ), &colModelChopper );
} Patch( initHelis.get<void>( -7 + 3 ), &colModelChopper );
Patch( initHelis.get<void>( 9 + 3 ), &colModelChopper );
} }
TXN_CATCH();
// Fixed vehicles exploding twice if the driver leaves the car while it's exploding // Fixed vehicles exploding twice if the driver leaves the car while it's exploding
try
{ {
using namespace RemoveDriverStatusFix; using namespace RemoveDriverStatusFix;
@ -1581,35 +1596,43 @@ void Patch_III_Common()
Nop(processCommands4, 3); Nop(processCommands4, 3);
Nop(pedSetOutCar, 3); Nop(pedSetOutCar, 3);
} }
TXN_CATCH();
// Fixed an inverted condition in CCarCtrl::PickNextNodeRandomly // Fixed an inverted condition in CCarCtrl::PickNextNodeRandomly
// leading to cars being unable to turn right from one way roads // leading to cars being unable to turn right from one way roads
// By Nick007J // By Nick007J
try
{ {
auto pickNodeRandomly = get_pattern("3B 44 24 24 74 09", 4); auto pickNodeRandomly = get_pattern("3B 44 24 24 74 09", 4);
Patch<uint8_t>(pickNodeRandomly, 0x75); Patch<uint8_t>(pickNodeRandomly, 0x75);
} }
TXN_CATCH();
// Apply bilinear filtering on the player skin // Apply bilinear filtering on the player skin
try
{ {
using namespace SkinTextureFilter; using namespace SkinTextureFilter;
auto getSkinTexture = get_pattern("E8 ? ? ? ? 89 C3 59 55"); auto getSkinTexture = get_pattern("E8 ? ? ? ? 89 C3 59 55");
InterceptCall(getSkinTexture, orgRwTextureCreate, RwTextureCreate_SetLinearFilter); InterceptCall(getSkinTexture, orgRwTextureCreate, RwTextureCreate_SetLinearFilter);
} }
TXN_CATCH();
// Apply the environment mapping on extra components // Apply the environment mapping on extra components
try
{ {
auto setEnvironmentMap = get_pattern("C7 83 D8 01 00 00 00 00 00 00 E8", 10); auto setEnvironmentMap = get_pattern("C7 83 D8 01 00 00 00 00 00 00 E8", 10);
InterceptCall(setEnvironmentMap, CVehicleModelInfo::orgSetEnvironmentMap, &CVehicleModelInfo::SetEnvironmentMap_ExtraComps); InterceptCall(setEnvironmentMap, CVehicleModelInfo::orgSetEnvironmentMap, &CVehicleModelInfo::SetEnvironmentMap_ExtraComps);
} }
TXN_CATCH();
// Fix the evasive dive miscalculating the angle, resulting in peds diving towards the vehicle // Fix the evasive dive miscalculating the angle, resulting in peds diving towards the vehicle
try
{ {
using namespace EvasiveDiveFix; using namespace EvasiveDiveFix;
@ -1618,9 +1641,11 @@ void Patch_III_Common()
Nop(setEvasiveDive.get<void>(), 1); Nop(setEvasiveDive.get<void>(), 1);
InjectHook(setEvasiveDive.get<void>(1), &CalculateAngle_Hook, HookType::Call); InjectHook(setEvasiveDive.get<void>(1), &CalculateAngle_Hook, HookType::Call);
} }
TXN_CATCH();
// Fix probabilities in CVehicle::InflictDamage incorrectly assuming a random range from 0 to 100.000 // 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_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); auto probability_flee = get_pattern("0F B7 46 5A 3D ? ? ? ? 0F 8E", 4 + 1);
@ -1628,9 +1653,11 @@ void Patch_III_Common()
Patch<uint16_t>(probability_do_nothing, 35000u * 32767u / 100000u); Patch<uint16_t>(probability_do_nothing, 35000u * 32767u / 100000u);
Patch<uint32_t>(probability_flee, 75000u * 32767u / 100000u); Patch<uint32_t>(probability_flee, 75000u * 32767u / 100000u);
} }
TXN_CATCH();
// Null terminate read lines in CPlane::LoadPath and CTrain::ReadAndInterpretTrackFile // Null terminate read lines in CPlane::LoadPath and CTrain::ReadAndInterpretTrackFile
try
{ {
using namespace NullTerminatedLines; using namespace NullTerminatedLines;
@ -1648,25 +1675,26 @@ void Patch_III_Common()
Nop(readTrackFile2.get<void>(), 2); Nop(readTrackFile2.get<void>(), 2);
InjectHook(readTrackFile2.get<void>(2), ReadTrackFile_Terminate, HookType::Call); InjectHook(readTrackFile2.get<void>(2), ReadTrackFile_Terminate, HookType::Call);
} }
TXN_CATCH();
// Backport 1.1 Stats menu font fix to 1.0 // Backport 1.1 Stats menu font fix to 1.0
try
{ {
using namespace StatsMenuFont; using namespace StatsMenuFont;
// This pattern fails by design on 1.1/Steam // This pattern fails by design on 1.1/Steam
auto constructStatLine = pattern("E8 ? ? ? ? D9 05 ? ? ? ? DC 0D ? ? ? ? 89 C7").count_hint(1); auto constructStatLine = pattern("E8 ? ? ? ? D9 05 ? ? ? ? DC 0D ? ? ? ? 89 C7").get_one();
if (constructStatLine.size() == 1) auto setFontStyle = get_pattern("6A 00 E8 ? ? ? ? 83 3D ? ? ? ? ? 59 0F 84", 2);
{
auto setFontStyle = get_pattern("6A 00 E8 ? ? ? ? 83 3D ? ? ? ? ? 59 0F 84", 2);
ReadCall(setFontStyle, orgSetFontStyle); ReadCall(setFontStyle, orgSetFontStyle);
InterceptCall(constructStatLine.get_first<void>(), orgConstructStatLine, ConstructStatLine_SetFontStyle); InterceptCall(constructStatLine.get<void>(), orgConstructStatLine, ConstructStatLine_SetFontStyle);
}
} }
TXN_CATCH();
// Enable Dodo keyboard controls for all cars when the flying cars cheat is enabled // Enable Dodo keyboard controls for all cars when the flying cars cheat is enabled
try
{ {
using namespace DodoKeyboardControls; using namespace DodoKeyboardControls;
@ -1676,9 +1704,11 @@ void Patch_III_Common()
bAllDodosCheat = allDodosCheat; bAllDodosCheat = allDodosCheat;
InterceptCall(findPlayerVehicle, orgFindPlayerVehicle, FindPlayerVehicle_DodoCheck); InterceptCall(findPlayerVehicle, orgFindPlayerVehicle, FindPlayerVehicle_DodoCheck);
} }
TXN_CATCH();
// Reset variables on New Game // Reset variables on New Game
try
{ {
using namespace VariableResets; using namespace VariableResets;
@ -1696,9 +1726,11 @@ void Patch_III_Common()
GameVariablesToReset.emplace_back(*get_pattern<int*>("7D 72 A1 ? ? ? ? 05", 2 + 1)); // LastTimeAmbulanceCreated GameVariablesToReset.emplace_back(*get_pattern<int*>("7D 72 A1 ? ? ? ? 05", 2 + 1)); // LastTimeAmbulanceCreated
GameVariablesToReset.emplace_back(*get_pattern<int*>("74 7F A1 ? ? ? ? 05", 2 + 1)); // LastTimeFireTruckCreated GameVariablesToReset.emplace_back(*get_pattern<int*>("74 7F A1 ? ? ? ? 05", 2 + 1)); // LastTimeFireTruckCreated
} }
TXN_CATCH();
// Clean up the pickup object when reusing a temporary slot // Clean up the pickup object when reusing a temporary slot
try
{ {
using namespace GenerateNewPickup_ReuseObjectFix; using namespace GenerateNewPickup_ReuseObjectFix;
@ -1707,10 +1739,12 @@ void Patch_III_Common()
pPickupObject = *give_us_a_pick_up_object.get<void*>(7 + 2); pPickupObject = *give_us_a_pick_up_object.get<void*>(7 + 2);
InterceptCall(give_us_a_pick_up_object.get<void>(2), orgGiveUsAPickUpObject, GiveUsAPickUpObject_CleanUpObject); InterceptCall(give_us_a_pick_up_object.get<void>(2), orgGiveUsAPickUpObject, GiveUsAPickUpObject_CleanUpObject);
} }
TXN_CATCH();
// Sitting in boat (Speeder), implemented as a special vehicle feature // Sitting in boat (Speeder), implemented as a special vehicle feature
// Based off SitInBoat from Fire_Head, with extra improvements // Based off SitInBoat from Fire_Head, with extra improvements
try
{ {
using namespace SitInBoat; 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! // This is intended - we don't actually need the original SetFinishCallback, only its parameters!
InjectHook(finish_callback, FinishCallback_CallImmediately); InjectHook(finish_callback, FinishCallback_CallImmediately);
} }
TXN_CATCH();
// Copy the atomic render CB in CloneAtomicToFrameCB instead of overriding it // Copy the atomic render CB in CloneAtomicToFrameCB instead of overriding it
// Fixes detached limbs rendering the normal and LOD atomics together // Fixes detached limbs rendering the normal and LOD atomics together
try
{ {
auto set_render_cb = get_pattern("55 E8 ? ? ? ? 89 D8 59", 1); auto set_render_cb = get_pattern("55 E8 ? ? ? ? 89 D8 59", 1);
Nop(set_render_cb, 5); Nop(set_render_cb, 5);
} }
TXN_CATCH();
// Fix dark car reflections in the Steam EXE // Fix dark car reflections in the Steam EXE
// Based off Sergenaur's fix // Based off Sergenaur's fix
try
{ {
auto reflection = pattern("A1 ? ? ? ? 85 C0 74 34"); // This will only pass on the Steam EXE, and if Sergenaur's standalone fix isn't present
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 reflection = pattern("A1 ? ? ? ? 85 C0 74 34").get_one();
{
auto match = reflection.get_one();
// xor eax, eax \ nop // xor eax, eax \ nop
Patch(match.get<void>(), { 0x31, 0xC0 }); Patch(reflection.get<void>(), { 0x31, 0xC0 });
Nop(match.get<void>(2), 3); Nop(reflection.get<void>(2), 3);
}
} }
TXN_CATCH();
// Don't override the color of the FBI car // Don't override the color of the FBI car
try
{ {
auto spawn_one_car = get_pattern("83 7C 24 ? ? 75 0E C6 85", 5); auto spawn_one_car = get_pattern("83 7C 24 ? ? 75 0E C6 85", 5);
Patch<uint8_t>(spawn_one_car, 0xEB); Patch<uint8_t>(spawn_one_car, 0xEB);
} }
TXN_CATCH();
} }
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)

View file

@ -152,7 +152,6 @@
<LanguageStandard>stdcpp17</LanguageStandard> <LanguageStandard>stdcpp17</LanguageStandard>
<EnforceTypeConversionRules>true</EnforceTypeConversionRules> <EnforceTypeConversionRules>true</EnforceTypeConversionRules>
<RuntimeTypeInfo>false</RuntimeTypeInfo> <RuntimeTypeInfo>false</RuntimeTypeInfo>
<ExceptionHandling>false</ExceptionHandling>
</ClCompile> </ClCompile>
<Link> <Link>
<SubSystem>Windows</SubSystem> <SubSystem>Windows</SubSystem>
@ -186,7 +185,6 @@
<LanguageStandard>stdcpp17</LanguageStandard> <LanguageStandard>stdcpp17</LanguageStandard>
<EnforceTypeConversionRules>true</EnforceTypeConversionRules> <EnforceTypeConversionRules>true</EnforceTypeConversionRules>
<RuntimeTypeInfo>false</RuntimeTypeInfo> <RuntimeTypeInfo>false</RuntimeTypeInfo>
<ExceptionHandling>false</ExceptionHandling>
</ClCompile> </ClCompile>
<Link> <Link>
<EnableCOMDATFolding>true</EnableCOMDATFolding> <EnableCOMDATFolding>true</EnableCOMDATFolding>
@ -222,7 +220,6 @@
<LanguageStandard>stdcpp17</LanguageStandard> <LanguageStandard>stdcpp17</LanguageStandard>
<EnforceTypeConversionRules>true</EnforceTypeConversionRules> <EnforceTypeConversionRules>true</EnforceTypeConversionRules>
<RuntimeTypeInfo>false</RuntimeTypeInfo> <RuntimeTypeInfo>false</RuntimeTypeInfo>
<ExceptionHandling>false</ExceptionHandling>
</ClCompile> </ClCompile>
<Link> <Link>
<EnableCOMDATFolding>true</EnableCOMDATFolding> <EnableCOMDATFolding>true</EnableCOMDATFolding>

File diff suppressed because it is too large Load diff

View file

@ -97,7 +97,6 @@
<EnforceTypeConversionRules>true</EnforceTypeConversionRules> <EnforceTypeConversionRules>true</EnforceTypeConversionRules>
<RuntimeTypeInfo>false</RuntimeTypeInfo> <RuntimeTypeInfo>false</RuntimeTypeInfo>
<LanguageStandard>stdcpp17</LanguageStandard> <LanguageStandard>stdcpp17</LanguageStandard>
<ExceptionHandling>false</ExceptionHandling>
</ClCompile> </ClCompile>
<Link> <Link>
<SubSystem>Windows</SubSystem> <SubSystem>Windows</SubSystem>
@ -137,7 +136,6 @@ copy /y "$(TargetPath)" "H:\Rockstar Games\Grand Theft Auto San Andreas\SilentPa
<EnforceTypeConversionRules>true</EnforceTypeConversionRules> <EnforceTypeConversionRules>true</EnforceTypeConversionRules>
<RuntimeTypeInfo>false</RuntimeTypeInfo> <RuntimeTypeInfo>false</RuntimeTypeInfo>
<LanguageStandard>stdcpp17</LanguageStandard> <LanguageStandard>stdcpp17</LanguageStandard>
<ExceptionHandling>false</ExceptionHandling>
</ClCompile> </ClCompile>
<Link> <Link>
<EnableCOMDATFolding>true</EnableCOMDATFolding> <EnableCOMDATFolding>true</EnableCOMDATFolding>
@ -179,7 +177,6 @@ copy /y "$(TargetPath)" "H:\Rockstar Games\Grand Theft Auto San Andreas\SilentPa
<EnforceTypeConversionRules>true</EnforceTypeConversionRules> <EnforceTypeConversionRules>true</EnforceTypeConversionRules>
<RuntimeTypeInfo>false</RuntimeTypeInfo> <RuntimeTypeInfo>false</RuntimeTypeInfo>
<LanguageStandard>stdcpp17</LanguageStandard> <LanguageStandard>stdcpp17</LanguageStandard>
<ExceptionHandling>false</ExceptionHandling>
</ClCompile> </ClCompile>
<Link> <Link>
<EnableCOMDATFolding>true</EnableCOMDATFolding> <EnableCOMDATFolding>true</EnableCOMDATFolding>

View file

@ -717,7 +717,7 @@ namespace VariableResets
void InjectDelayedPatches_VC_Common( bool bHasDebugMenu, const wchar_t* wcModulePath ) void InjectDelayedPatches_VC_Common( bool bHasDebugMenu, const wchar_t* wcModulePath )
{ {
using namespace Memory; using namespace Memory;
using namespace hook; using namespace hook::txn;
const ModuleList moduleList; const ModuleList moduleList;
@ -749,139 +749,124 @@ void InjectDelayedPatches_VC_Common( bool bHasDebugMenu, const wchar_t* wcModule
if ( GetPrivateProfileIntW(L"SilentPatch", L"EnableVehicleCoronaFixes", -1, wcModulePath) == 1 ) 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 // Other mods might be touching it, so only patch specific vehicles if their code has not been touched at all
try
{ {
auto firetruck1 = pattern( "8D 8C 24 24 09 00 00 FF 35 ? ? ? ? FF 35 ? ? ? ? FF 35" ); auto firetruck1 = pattern("8D 8C 24 24 09 00 00 FF 35 ? ? ? ? FF 35 ? ? ? ? FF 35").get_one();
auto firetruck2 = pattern( "8D 8C 24 30 09 00 00 FF 35 ? ? ? ? FF 35 ? ? ? ? FF 35" ); auto firetruck2 = pattern("8D 8C 24 30 09 00 00 FF 35 ? ? ? ? FF 35 ? ? ? ? FF 35").get_one();
if ( firetruck1.count_hint(1).size() == 1 && firetruck2.count_hint(1).size() == 1 ) static const CVector FIRETRUCK_SIREN_POS(0.95f, 3.2f, 1.4f);
{ static const float FIRETRUCK_SIREN_MINUS_X = -FIRETRUCK_SIREN_POS.x;
static const CVector FIRETRUCK_SIREN_POS(0.95f, 3.2f, 1.4f);
static const float FIRETRUCK_SIREN_MINUS_X = -FIRETRUCK_SIREN_POS.x;
auto match1 = firetruck1.get_one(); Patch( firetruck1.get<float*>( 7 + 2 ), &FIRETRUCK_SIREN_POS.z );
auto match2 = firetruck2.get_one(); Patch( firetruck1.get<float*>( 7 + 2 + (6*1) ), &FIRETRUCK_SIREN_POS.y );
Patch( firetruck1.get<float*>( 7 + 2 + (6*2) ), &FIRETRUCK_SIREN_POS.x );
Patch( match1.get<float*>( 7 + 2 ), &FIRETRUCK_SIREN_POS.z ); Patch( firetruck2.get<float*>( 7 + 2 ), &FIRETRUCK_SIREN_POS.z );
Patch( match1.get<float*>( 7 + 2 + (6*1) ), &FIRETRUCK_SIREN_POS.y ); Patch( firetruck2.get<float*>( 7 + 2 + (6*1) ), &FIRETRUCK_SIREN_POS.y );
Patch( match1.get<float*>( 7 + 2 + (6*2) ), &FIRETRUCK_SIREN_POS.x ); Patch( firetruck2.get<float*>( 7 + 2 + (6*2) ), &FIRETRUCK_SIREN_MINUS_X );
Patch( match2.get<float*>( 7 + 2 ), &FIRETRUCK_SIREN_POS.z );
Patch( match2.get<float*>( 7 + 2 + (6*1) ), &FIRETRUCK_SIREN_POS.y );
Patch( match2.get<float*>( 7 + 2 + (6*2) ), &FIRETRUCK_SIREN_MINUS_X );
}
} }
TXN_CATCH();
try
{ {
auto ambulan1 = pattern( "8D 8C 24 0C 09 00 00 FF 35 ? ? ? ? FF 35 ? ? ? ? FF 35" ); auto ambulan1 = pattern("8D 8C 24 0C 09 00 00 FF 35 ? ? ? ? FF 35 ? ? ? ? FF 35").get_one();
auto ambulan2 = pattern( "8D 8C 24 18 09 00 00 FF 35 ? ? ? ? FF 35 ? ? ? ? FF 35" ); auto ambulan2 = pattern("8D 8C 24 18 09 00 00 FF 35 ? ? ? ? FF 35 ? ? ? ? FF 35").get_one();
if ( ambulan1.count_hint(1).size() == 1 && ambulan2.count_hint(1).size() == 1 ) static const CVector AMBULANCE_SIREN_POS(0.7f, 0.65f, 1.55f);
{ static const float AMBULANCE_SIREN_MINUS_X = -AMBULANCE_SIREN_POS.x;
static const CVector AMBULANCE_SIREN_POS(0.7f, 0.65f, 1.55f);
static const float AMBULANCE_SIREN_MINUS_X = -AMBULANCE_SIREN_POS.x;
auto match1 = ambulan1.get_one(); Patch( ambulan1.get<float*>( 7 + 2 ), &AMBULANCE_SIREN_POS.z );
auto match2 = ambulan2.get_one(); Patch( ambulan1.get<float*>( 7 + 2 + (6*1) ), &AMBULANCE_SIREN_POS.y );
Patch( ambulan1.get<float*>( 7 + 2 + (6*2) ), &AMBULANCE_SIREN_POS.x );
Patch( match1.get<float*>( 7 + 2 ), &AMBULANCE_SIREN_POS.z ); Patch( ambulan2.get<float*>( 7 + 2 ), &AMBULANCE_SIREN_POS.z );
Patch( match1.get<float*>( 7 + 2 + (6*1) ), &AMBULANCE_SIREN_POS.y ); Patch( ambulan2.get<float*>( 7 + 2 + (6*1) ), &AMBULANCE_SIREN_POS.y );
Patch( match1.get<float*>( 7 + 2 + (6*2) ), &AMBULANCE_SIREN_POS.x ); Patch( ambulan2.get<float*>( 7 + 2 + (6*2) ), &AMBULANCE_SIREN_MINUS_X );
Patch( match2.get<float*>( 7 + 2 ), &AMBULANCE_SIREN_POS.z );
Patch( match2.get<float*>( 7 + 2 + (6*1) ), &AMBULANCE_SIREN_POS.y );
Patch( match2.get<float*>( 7 + 2 + (6*2) ), &AMBULANCE_SIREN_MINUS_X );
}
} }
TXN_CATCH();
try
{ {
auto police1 = pattern( "8D 8C 24 DC 08 00 00 FF 35 ? ? ? ? FF 35 ? ? ? ? FF 35" ); auto police1 = pattern("8D 8C 24 DC 08 00 00 FF 35 ? ? ? ? FF 35 ? ? ? ? FF 35").get_one();
auto police2 = pattern( "8D 8C 24 E8 08 00 00 FF 35 ? ? ? ? FF 35 ? ? ? ? FF 35" ); auto police2 = pattern("8D 8C 24 E8 08 00 00 FF 35 ? ? ? ? FF 35 ? ? ? ? FF 35").get_one();
if ( police1.count_hint(1).size() == 1 && police2.count_hint(1).size() == 1 ) static const CVector POLICE_SIREN_POS(0.55f, -0.4f, 0.95f);
{ static const float POLICE_SIREN_MINUS_X = -POLICE_SIREN_POS.x;
static const CVector POLICE_SIREN_POS(0.55f, -0.4f, 0.95f);
static const float POLICE_SIREN_MINUS_X = -POLICE_SIREN_POS.x;
auto match1 = police1.get_one(); Patch( police1.get<float*>( 7 + 2 ), &POLICE_SIREN_POS.z );
auto match2 = police2.get_one(); Patch( police1.get<float*>( 7 + 2 + (6*1) ), &POLICE_SIREN_POS.y );
Patch( police1.get<float*>( 7 + 2 + (6*2) ), &POLICE_SIREN_POS.x );
Patch( match1.get<float*>( 7 + 2 ), &POLICE_SIREN_POS.z ); Patch( police2.get<float*>( 7 + 2 ), &POLICE_SIREN_POS.z );
Patch( match1.get<float*>( 7 + 2 + (6*1) ), &POLICE_SIREN_POS.y ); Patch( police2.get<float*>( 7 + 2 + (6*1) ), &POLICE_SIREN_POS.y );
Patch( match1.get<float*>( 7 + 2 + (6*2) ), &POLICE_SIREN_POS.x ); Patch( police2.get<float*>( 7 + 2 + (6*2) ), &POLICE_SIREN_MINUS_X );
Patch( match2.get<float*>( 7 + 2 ), &POLICE_SIREN_POS.z );
Patch( match2.get<float*>( 7 + 2 + (6*1) ), &POLICE_SIREN_POS.y );
Patch( match2.get<float*>( 7 + 2 + (6*2) ), &POLICE_SIREN_MINUS_X );
}
} }
TXN_CATCH();
try
{ {
auto enforcer1 = pattern( "8D 8C 24 F4 08 00 00 FF 35 ? ? ? ? FF 35 ? ? ? ? FF 35" ); auto enforcer1 = pattern("8D 8C 24 F4 08 00 00 FF 35 ? ? ? ? FF 35 ? ? ? ? FF 35").get_one();
auto enforcer2 = pattern( "8D 8C 24 00 09 00 00 FF 35 ? ? ? ? FF 35 ? ? ? ? FF 35" ); auto enforcer2 = pattern("8D 8C 24 00 09 00 00 FF 35 ? ? ? ? FF 35 ? ? ? ? FF 35").get_one();
if ( enforcer1.count_hint(1).size() == 1 && enforcer2.count_hint(1).size() == 1 ) static const CVector ENFORCER_SIREN_POS(0.6f, 1.05f, 1.4f);
{ static const float ENFORCER_SIREN_MINUS_X = -ENFORCER_SIREN_POS.x;
static const CVector ENFORCER_SIREN_POS(0.6f, 1.05f, 1.4f);
static const float ENFORCER_SIREN_MINUS_X = -ENFORCER_SIREN_POS.x;
auto match1 = enforcer1.get_one(); Patch( enforcer1.get<float*>( 7 + 2 ), &ENFORCER_SIREN_POS.z );
auto match2 = enforcer2.get_one(); Patch( enforcer1.get<float*>( 7 + 2 + (6*1) ), &ENFORCER_SIREN_POS.y );
Patch( enforcer1.get<float*>( 7 + 2 + (6*2) ), &ENFORCER_SIREN_POS.x );
Patch( match1.get<float*>( 7 + 2 ), &ENFORCER_SIREN_POS.z ); Patch( enforcer2.get<float*>( 7 + 2 ), &ENFORCER_SIREN_POS.z );
Patch( match1.get<float*>( 7 + 2 + (6*1) ), &ENFORCER_SIREN_POS.y ); Patch( enforcer2.get<float*>( 7 + 2 + (6*1) ), &ENFORCER_SIREN_POS.y );
Patch( match1.get<float*>( 7 + 2 + (6*2) ), &ENFORCER_SIREN_POS.x ); Patch( enforcer2.get<float*>( 7 + 2 + (6*2) ), &ENFORCER_SIREN_MINUS_X );
Patch( match2.get<float*>( 7 + 2 ), &ENFORCER_SIREN_POS.z );
Patch( match2.get<float*>( 7 + 2 + (6*1) ), &ENFORCER_SIREN_POS.y );
Patch( match2.get<float*>( 7 + 2 + (6*2) ), &ENFORCER_SIREN_MINUS_X );
}
} }
{ TXN_CATCH();
auto chopper1 = pattern( "C7 44 24 44 00 00 E0 40 50 C7 44 24 4C 00 00 00 00" ); // Front light
auto chopper2 = pattern( "C7 44 24 6C 00 00 10 C1 8D 44 24 5C C7 44 24 70 00 00 00 00" ); // Tail light
if ( chopper1.count_hint(1).size() == 1 ) {
try
{ {
auto chopper1 = pattern("C7 44 24 44 00 00 E0 40 50 C7 44 24 4C 00 00 00 00").get_one(); // Front light
constexpr CVector CHOPPER_SEARCH_LIGHT_POS(0.0f, 3.0f, -1.0f); // Same as in III Aircraft (not implemented there yet!) constexpr CVector CHOPPER_SEARCH_LIGHT_POS(0.0f, 3.0f, -1.0f); // Same as in III Aircraft (not implemented there yet!)
auto match = chopper1.get_one(); Patch( chopper1.get<float>( 4 ), CHOPPER_SEARCH_LIGHT_POS.y );
Patch( chopper1.get<float>( 9 + 4 ), CHOPPER_SEARCH_LIGHT_POS.z );
Patch( match.get<float>( 4 ), CHOPPER_SEARCH_LIGHT_POS.y );
Patch( match.get<float>( 9 + 4 ), CHOPPER_SEARCH_LIGHT_POS.z );
} }
TXN_CATCH();
if ( chopper2.count_hint(1).size() == 1 ) try
{ {
auto chopper2 = pattern("C7 44 24 6C 00 00 10 C1 8D 44 24 5C C7 44 24 70 00 00 00 00").get_one(); // Tail light
constexpr CVector CHOPPER_RED_LIGHT_POS(0.0f, -7.5f, 2.5f); // Same as in III Aircraft constexpr CVector CHOPPER_RED_LIGHT_POS(0.0f, -7.5f, 2.5f); // Same as in III Aircraft
auto match = chopper2.get_one(); Patch( chopper2.get<float>( 4 ), CHOPPER_RED_LIGHT_POS.y );
Patch( chopper2.get<float>( 12 + 4 ), CHOPPER_RED_LIGHT_POS.z );
Patch( match.get<float>( 4 ), CHOPPER_RED_LIGHT_POS.y );
Patch( match.get<float>( 12 + 4 ), CHOPPER_RED_LIGHT_POS.z );
} }
TXN_CATCH();
} }
try
{ {
using namespace FBISirenCoronaFix; using namespace FBISirenCoronaFix;
auto hasFBISiren = pattern( "83 E9 04 0F 84 87 0A 00 00 83 E9 10" ); // Predicate for showing FBI/Vice Squad siren auto viceCheetah = pattern("8D 8C 24 CC 09 00 00 FF 35 ? ? ? ? FF 35 ? ? ? ? FF 35 ? ? ? ? E8").get_one(); // Siren pos
auto viceCheetah = pattern( "8D 8C 24 CC 09 00 00 FF 35 ? ? ? ? FF 35 ? ? ? ? FF 35 ? ? ? ? E8" ); // Siren pos
if ( viceCheetah.count_hint(1).size() == 1 ) try
{ {
auto match = viceCheetah.get_one(); auto hasFBISiren = pattern("83 E9 04 0F 84 87 0A 00 00 83 E9 10").get_one(); // Predicate for showing FBI/Vice Squad siren
if ( hasFBISiren.count_hint(1).size() == 1 ) Patch<uint8_t>( hasFBISiren.get<void>(), 0x55 ); // push ebp
{ InjectHook( hasFBISiren.get<void>( 1 ), SetUpFBISiren, HookType::Call );
auto matchSiren = hasFBISiren.get_one(); Patch( hasFBISiren.get<void>( 1 + 5 ), { 0x83, 0xC4, 0x04, 0x84, 0xC0, 0x90 } ); // add esp, 4 / test al, al / nop
Patch<uint8_t>( matchSiren.get<void>(), 0x55 ); // push ebp InjectHook( viceCheetah.get<void>( 0x19 ), SetUpVector );
InjectHook( matchSiren.get<void>( 1 ), SetUpFBISiren, HookType::Call );
Patch( matchSiren.get<void>( 1 + 5 ), { 0x83, 0xC4, 0x04, 0x84, 0xC0, 0x90 } ); // add esp, 4 / test al, al / nop
InjectHook( match.get<void>( 0x19 ), SetUpVector );
}
static const float VICE_CHEETAH_SIREN_POS_Z = 0.25f;
Patch( match.get<float*>( 7 + 2 ), &VICE_CHEETAH_SIREN_POS_Z );
} }
TXN_CATCH();
static const float VICE_CHEETAH_SIREN_POS_Z = 0.25f;
Patch( viceCheetah.get<float*>( 7 + 2 ), &VICE_CHEETAH_SIREN_POS_Z );
} }
TXN_CATCH();
} }
FLAUtils::Init(moduleList); FLAUtils::Init(moduleList);
@ -1180,9 +1165,10 @@ void Patch_VC_JP()
void Patch_VC_Common() void Patch_VC_Common()
{ {
using namespace Memory; using namespace Memory;
using namespace hook; using namespace hook::txn;
// New timers fix // 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 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 31 FF FF FF" ); auto jmpPoint = get_pattern( "DD D8 E9 31 FF FF FF" );
@ -1190,8 +1176,11 @@ void Patch_VC_Common()
InjectHook( hookPoint.get<void>( 0x21 ), CTimer::Update_SilentPatch, HookType::Call ); InjectHook( hookPoint.get<void>( 0x21 ), CTimer::Update_SilentPatch, HookType::Call );
InjectHook( hookPoint.get<void>( 0x21 + 5 ), jmpPoint, HookType::Jump ); InjectHook( hookPoint.get<void>( 0x21 + 5 ), jmpPoint, HookType::Jump );
} }
TXN_CATCH();
// Alt+F4 // Alt+F4
try
{ {
auto addr = pattern( "59 59 31 C0 83 C4 70 5D 5F 5E 5B C2 10 00" ).count(2); auto addr = pattern( "59 59 31 C0 83 C4 70 5D 5F 5E 5B C2 10 00" ).count(2);
auto dest = get_pattern( "53 55 56 FF B4 24 90 00 00 00 FF 15" ); auto dest = get_pattern( "53 55 56 FF B4 24 90 00 00 00 FF 15" );
@ -1200,8 +1189,11 @@ void Patch_VC_Common()
InjectHook( match.get<void>( 2 ), dest, HookType::Jump ); InjectHook( match.get<void>( 2 ), dest, HookType::Jump );
}); });
} }
TXN_CATCH();
// Proper panels damage // Proper panels damage
try
{ {
auto addr = pattern( "C6 41 09 03 C6 41 0A 03 C6 41 0B 03" ).get_one(); auto addr = pattern( "C6 41 09 03 C6 41 0A 03 C6 41 0B 03" ).get_one();
@ -1212,20 +1204,27 @@ void Patch_VC_Common()
Nop( addr.get<void>( 0x33 ), 7 ); Nop( addr.get<void>( 0x33 ), 7 );
} }
TXN_CATCH();
// Proper metric-imperial conversion constants // Proper metric-imperial conversion constants
try
{ {
static const float METERS_TO_MILES = 0.0006213711922f; static const float METERS_TO_MILES = 0.0006213711922f;
auto addr = pattern( "75 ? D9 05 ? ? ? ? D8 0D ? ? ? ? 6A 00 6A 00 D9 9C 24" ).count(6); auto addr = pattern( "75 ? D9 05 ? ? ? ? D8 0D ? ? ? ? 6A 00 6A 00 D9 9C 24" ).count(6);
auto sum = get_pattern( "D9 9C 24 A8 00 00 00 8D 84 24 A8 00 00 00 50", -6 + 2 );
addr.for_each_result( [&]( pattern_match match ) { addr.for_each_result( [&]( pattern_match match ) {
Patch<const void*>( match.get<void>( 0x8 + 2 ), &METERS_TO_MILES ); Patch<const void*>( match.get<void>( 0x8 + 2 ), &METERS_TO_MILES );
}); });
auto sum = get_pattern( "D9 9C 24 A8 00 00 00 8D 84 24 A8 00 00 00 50", -6 + 2 );
Patch<const void*>( sum, &METERS_TO_MILES ); Patch<const void*>( sum, &METERS_TO_MILES );
} }
TXN_CATCH();
// Improved pathfinding in PickNextNodeAccordingStrategy - PickNextNodeToChaseCar with XYZ coords // Improved pathfinding in PickNextNodeAccordingStrategy - PickNextNodeToChaseCar with XYZ coords
try
{ {
auto addr = pattern( "E8 ? ? ? ? 50 8D 44 24 10 50 E8" ).get_one(); auto addr = pattern( "E8 ? ? ? ? 50 8D 44 24 10 50 E8" ).get_one();
ReadCall( addr.get<void>( 0x25 ), orgPickNextNodeToChaseCar ); ReadCall( addr.get<void>( 0x25 ), orgPickNextNodeToChaseCar );
@ -1258,25 +1257,31 @@ void Patch_VC_Common()
InjectHook( addr.get<void>( 0x46 ), PickNextNodeToChaseCarXYZ ); InjectHook( addr.get<void>( 0x46 ), PickNextNodeToChaseCarXYZ );
Patch<uint8_t>( addr.get<void>( 0x4B + 2 ), 0xC ); Patch<uint8_t>( addr.get<void>( 0x4B + 2 ), 0xC );
} }
TXN_CATCH();
// No censorships // No censorships
try
{ {
auto addr = get_pattern( "8B 43 50 85 C0 8B 53 50 74 2B 83 E8 01" ); auto addr = get_pattern( "8B 43 50 85 C0 8B 53 50 74 2B 83 E8 01" );
Patch( addr, { 0x83, 0xC4, 0x08, 0x5B, 0xC3 } ); // add esp, 8 \ pop ebx \ retn Patch( addr, { 0x83, 0xC4, 0x08, 0x5B, 0xC3 } ); // add esp, 8 \ pop ebx \ retn
} }
TXN_CATCH();
// 014C cargen counter fix (by spaceeinstein) // 014C cargen counter fix (by spaceeinstein)
try
{ {
auto do_processing = pattern( "0F B7 43 28 83 F8 FF 7D 04 66 FF 4B 28" ).get_one(); auto do_processing = pattern( "0F B7 43 28 83 F8 FF 7D 04 66 FF 4B 28" ).get_one();
Patch<uint8_t>( do_processing.get<uint8_t*>(1), 0xBF ); // movzx eax, word ptr [ebx+28h] -> movsx eax, word ptr [ebx+28h] Patch<uint8_t>( do_processing.get<uint8_t*>(1), 0xBF ); // movzx eax, word ptr [ebx+28h] -> movsx eax, word ptr [ebx+28h]
Patch<uint8_t>( do_processing.get<uint8_t*>(7), 0x74 ); // jge -> jz Patch<uint8_t>( do_processing.get<uint8_t*>(7), 0x74 ); // jge -> jz
} }
TXN_CATCH();
// Fixed ammo from SCM // Fixed ammo from SCM
try
{ {
using namespace ZeroAmmoFix; using namespace ZeroAmmoFix;
@ -1286,16 +1291,20 @@ void Patch_VC_Common()
}; };
HookEach_GiveWeapon(give_weapon, InterceptCall); HookEach_GiveWeapon(give_weapon, InterceptCall);
} }
TXN_CATCH();
// Extras working correctly on bikes // Extras working correctly on bikes
try
{ {
auto createInstance = get_pattern( "89 C1 8B 41 04" ); auto createInstance = get_pattern( "89 C1 8B 41 04" );
InjectHook( createInstance, CreateInstance_BikeFix, HookType::Call ); InjectHook( createInstance, CreateInstance_BikeFix, HookType::Call );
} }
TXN_CATCH();
// Credits =) // Credits =)
try
{ {
auto renderCredits = pattern( "8D 44 24 28 83 C4 14 50 FF 35 ? ? ? ? E8 ? ? ? ? 8D 44 24 1C 59 59 50 FF 35 ? ? ? ? E8 ? ? ? ? 59 59" ).get_one(); auto renderCredits = pattern( "8D 44 24 28 83 C4 14 50 FF 35 ? ? ? ? E8 ? ? ? ? 8D 44 24 1C 59 59 50 FF 35 ? ? ? ? E8 ? ? ? ? 59 59" ).get_one();
@ -1303,9 +1312,11 @@ void Patch_VC_Common()
ReadCall( renderCredits.get<void>( -5 ), Credits::PrintCreditText_Hooked ); ReadCall( renderCredits.get<void>( -5 ), Credits::PrintCreditText_Hooked );
InjectHook( renderCredits.get<void>( -5 ), Credits::PrintSPCredits ); InjectHook( renderCredits.get<void>( -5 ), Credits::PrintSPCredits );
} }
TXN_CATCH();
// Decreased keyboard input latency // Decreased keyboard input latency
try
{ {
using namespace KeyboardInputFix; using namespace KeyboardInputFix;
@ -1321,42 +1332,44 @@ void Patch_VC_Common()
InjectHook( simButtonCheckers, ClearSimButtonPressCheckers ); InjectHook( simButtonCheckers, ClearSimButtonPressCheckers );
InjectHook( updatePads.get<void>( 9 ), jmpDest, HookType::Jump ); InjectHook( updatePads.get<void>( 9 ), jmpDest, HookType::Jump );
} }
TXN_CATCH();
// Locale based metric/imperial system // Locale based metric/imperial system
try
{ {
using namespace Localization; using namespace Localization;
void* updateCompareFlag = get_pattern( "89 D9 6A 00 E8 ? ? ? ? 30 C0 83 C4 70 5D 5F 5E 5B C2 04 00", 4 ); void* updateCompareFlag = get_pattern( "89 D9 6A 00 E8 ? ? ? ? 30 C0 83 C4 70 5D 5F 5E 5B C2 04 00", 4 );
auto constructStatLine = pattern( "85 C0 74 11 83 E8 01 83 F8 03" ).get_one();
ReadCall( updateCompareFlag, orgUpdateCompareFlag_IsMetric ); ReadCall( updateCompareFlag, orgUpdateCompareFlag_IsMetric );
InjectHook( updateCompareFlag, UpdateCompareFlag_IsMetric ); InjectHook( updateCompareFlag, UpdateCompareFlag_IsMetric );
// Stats // Stats
auto constructStatLine = pattern( "85 C0 74 11 83 E8 01 83 F8 03" ).get_one();
Nop( constructStatLine.get<void>( -11 ), 1 ); Nop( constructStatLine.get<void>( -11 ), 1 );
InjectHook( constructStatLine.get<void>( -11 + 1 ), PrefsLanguage_IsMetric, HookType::Call ); InjectHook( constructStatLine.get<void>( -11 + 1 ), PrefsLanguage_IsMetric, HookType::Call );
Nop( constructStatLine.get<void>( -2 ), 2 ); Nop( constructStatLine.get<void>( -2 ), 2 );
} }
TXN_CATCH();
// Corrected FBI Washington sirens sound // Corrected FBI Washington sirens sound
// Primary siren lower pitched like in FBI Rancher and secondary siren higher pitched // Primary siren lower pitched like in FBI Rancher and secondary siren higher pitched
try
{ {
using namespace SirenSwitchingFix; using namespace SirenSwitchingFix;
// Other mods might be touching it, so only patch specific vehicles if their code has not been touched at all // Other mods might be touching it, so only patch specific vehicles if their code has not been touched at all
auto sirenPitch = pattern( "83 F8 17 74 32" ).count_hint(1); auto sirenPitch = pattern( "83 F8 17 74 32" ).get_one();
if ( sirenPitch.size() == 1 )
InjectHook( sirenPitch.get<void>( 5 ), IsFBIRanchOrFBICar, HookType::Call );
Patch( sirenPitch.get<void>( 5 + 5 ), { 0x84, 0xC0 } ); // test al, al
Nop( sirenPitch.get<void>( 5 + 5 + 2 ), 4 );
// Pitch shift FBI Washington primary siren
try
{ {
auto match = sirenPitch.get_one();
InjectHook( match.get<void>( 5 ), IsFBIRanchOrFBICar, HookType::Call );
Patch( match.get<void>( 5 + 5 ), { 0x84, 0xC0 } ); // test al, al
Nop( match.get<void>( 5 + 5 + 2 ), 4 );
// Pitch shift FBI Washington primary siren
struct tVehicleSampleData { struct tVehicleSampleData {
int m_nAccelerationSampleIndex; int m_nAccelerationSampleIndex;
char m_bEngineSoundType; char m_bEngineSoundType;
@ -1375,20 +1388,25 @@ void Patch_VC_Common()
dataTable[17].m_nSirenOrAlarmFrequency = dataTable[90].m_nSirenOrAlarmFrequency; dataTable[17].m_nSirenOrAlarmFrequency = dataTable[90].m_nSirenOrAlarmFrequency;
} }
} }
TXN_CATCH();
} }
TXN_CATCH();
// Allow extra6 to be picked with component rule 4 (any) // Allow extra6 to be picked with component rule 4 (any)
try
{ {
void* extraMult6 = get_pattern( "D8 0D ? ? ? ? D9 7C 24 04 8B 44 24 04 80 4C 24 05 0C D9 6C 24 04 89 44 24 04 DB 5C 24 08 D9 6C 24 04 8B 44 24 08 83 C4 10 5D", 2 ); void* extraMult6 = get_pattern( "D8 0D ? ? ? ? D9 7C 24 04 8B 44 24 04 80 4C 24 05 0C D9 6C 24 04 89 44 24 04 DB 5C 24 08 D9 6C 24 04 8B 44 24 08 83 C4 10 5D", 2 );
static const float MULT_6 = 6.0f; static const float MULT_6 = 6.0f;
Patch( extraMult6, &MULT_6 ); Patch( extraMult6, &MULT_6 );
} }
TXN_CATCH();
// Make drive-by one shot sounds owned by the driver instead of the car // Make drive-by one shot sounds owned by the driver instead of the car
// Fixes incorrect weapon sound being used for drive-by // Fixes incorrect weapon sound being used for drive-by
try
{ {
auto getDriverOneShot = pattern( "FF 35 ? ? ? ? 6A 37 50 E8 ? ? ? ? 83 7E 08 00" ).get_one(); auto getDriverOneShot = pattern( "FF 35 ? ? ? ? 6A 37 50 E8 ? ? ? ? 83 7E 08 00" ).get_one();
@ -1398,9 +1416,11 @@ void Patch_VC_Common()
Patch( getDriverOneShot.get<void>( -8 ), { 0x90, 0x89, 0xD9 } ); Patch( getDriverOneShot.get<void>( -8 ), { 0x90, 0x89, 0xD9 } );
InjectHook( getDriverOneShot.get<void>( -5 ), &CVehicle::GetOneShotOwnerID_SilentPatch, HookType::Call ); InjectHook( getDriverOneShot.get<void>( -5 ), &CVehicle::GetOneShotOwnerID_SilentPatch, HookType::Call );
} }
TXN_CATCH();
// Fixed vehicles exploding twice if the driver leaves the car while it's exploding // Fixed vehicles exploding twice if the driver leaves the car while it's exploding
try
{ {
using namespace RemoveDriverStatusFix; using namespace RemoveDriverStatusFix;
@ -1419,9 +1439,11 @@ void Patch_VC_Common()
Nop(removeThisPed, 3); Nop(removeThisPed, 3);
Nop(pedSetOutCar, 3); Nop(pedSetOutCar, 3);
} }
TXN_CATCH();
// Apply the environment mapping on extra components // Apply the environment mapping on extra components
try
{ {
using namespace EnvMapsOnExtras; using namespace EnvMapsOnExtras;
@ -1431,17 +1453,21 @@ void Patch_VC_Common()
Patch<uint8_t>(forAllAtomics.get<void>(), 0x53); Patch<uint8_t>(forAllAtomics.get<void>(), 0x53);
InterceptCall(forAllAtomics.get<void>(1), orgRpClumpForAllAtomics, RpClumpForAllAtomics_ExtraComps); InterceptCall(forAllAtomics.get<void>(1), orgRpClumpForAllAtomics, RpClumpForAllAtomics_ExtraComps);
} }
TXN_CATCH();
// Fix probabilities in CVehicle::InflictDamage incorrectly assuming a random range from 0 to 100.000 // Fix probabilities in CVehicle::InflictDamage incorrectly assuming a random range from 0 to 100.000
try
{ {
auto probability = get_pattern("66 81 7B 5A ? ? 73 50", 4); auto probability = get_pattern("66 81 7B 5A ? ? 73 50", 4);
Patch<uint16_t>(probability, 35000u / 2u); Patch<uint16_t>(probability, 35000u / 2u);
} }
TXN_CATCH();
// Null terminate read lines in CPlane::LoadPath // Null terminate read lines in CPlane::LoadPath
try
{ {
using namespace NullTerminatedLines; using namespace NullTerminatedLines;
@ -1449,9 +1475,11 @@ void Patch_VC_Common()
InterceptCall(loadPath, orgSscanf_LoadPath, sscanf1_LoadPath_Terminate); InterceptCall(loadPath, orgSscanf_LoadPath, sscanf1_LoadPath_Terminate);
} }
TXN_CATCH();
// Don't reset mouse sensitivity on New Game // Don't reset mouse sensitivity on New Game
try
{ {
using namespace MouseSensNewGame; using namespace MouseSensNewGame;
@ -1464,9 +1492,11 @@ void Patch_VC_Common()
Nop(cameraInit.get<void>(20), 10); Nop(cameraInit.get<void>(20), 10);
InterceptCall(setDirMyDocuments, orgSetDirMyDocuments, SetDirMyDocuments_ResetMouse); InterceptCall(setDirMyDocuments, orgSetDirMyDocuments, SetDirMyDocuments_ResetMouse);
} }
TXN_CATCH();
// Fixed pickup effects // Fixed pickup effects
try
{ {
using namespace PickupEffectsFixes; using namespace PickupEffectsFixes;
@ -1479,22 +1509,24 @@ void Patch_VC_Common()
// Don't spawn the grenade together with the detonator in the pickup // Don't spawn the grenade together with the detonator in the pickup
// FLA might be altering this due to the usage of 16-bit IDs? Just in case allow for graceful failure // FLA might be altering this due to the usage of 16-bit IDs? Just in case allow for graceful failure
auto pickupExtraObject = pattern("75 04 66 8B 70 58").count_hint(1); try
if (pickupExtraObject.size() == 1)
{ {
auto match = pickupExtraObject.get_one(); auto pickupExtraObject = pattern("75 04 66 8B 70 58").get_one();
Nop(match.get<void>(), 1); Nop(pickupExtraObject.get<void>(), 1);
InjectHook(match.get<void>(1), &PickUpEffects_GiveUsAnObject, HookType::Call); InjectHook(pickupExtraObject.get<void>(1), &PickUpEffects_GiveUsAnObject, HookType::Call);
} }
TXN_CATCH();
InjectHook(bigDollarColor, &PickUpEffects_BigDollarColor, HookType::Call); InjectHook(bigDollarColor, &PickUpEffects_BigDollarColor, HookType::Call);
InjectHook(minigun2Glow, &PickUpEffects_Minigun2Glow, HookType::Call); InjectHook(minigun2Glow, &PickUpEffects_Minigun2Glow, HookType::Call);
} }
TXN_CATCH();
// Fixed the muzzle flash facing the wrong direction // Fixed the muzzle flash facing the wrong direction
// By Wesser // By Wesser
try
{ {
auto fireInstantHit = pattern("D9 44 24 50 D8 44 24 44").get_one(); auto fireInstantHit = pattern("D9 44 24 50 D8 44 24 44").get_one();
@ -1503,11 +1535,13 @@ void Patch_VC_Common()
Patch(fireInstantHit.get<void>(15), { 0xD9, 0xEE, 0x90, 0x90 }); Patch(fireInstantHit.get<void>(15), { 0xD9, 0xEE, 0x90, 0x90 });
Patch(fireInstantHit.get<void>(30), { 0xD9, 0xEE, 0x90, 0x90 }); Patch(fireInstantHit.get<void>(30), { 0xD9, 0xEE, 0x90, 0x90 });
} }
TXN_CATCH();
// Fixed IS_PLAYER_TARGETTING_CHAR incorrectly detecting targetting in Classic controls // Fixed IS_PLAYER_TARGETTING_CHAR incorrectly detecting targetting in Classic controls
// when the player is not aiming // when the player is not aiming
// By Wesser // By Wesser
try
{ {
using namespace IsPlayerTargettingCharFix; using namespace IsPlayerTargettingCharFix;
@ -1525,17 +1559,21 @@ void Patch_VC_Common()
memmove(isPlayerTargettingChar.get<void>(), isPlayerTargettingChar.get<void>(5), 5); memmove(isPlayerTargettingChar.get<void>(), isPlayerTargettingChar.get<void>(5), 5);
InjectHook(isPlayerTargettingChar.get<void>(5), IsPlayerTargettingChar_ExtraChecks, HookType::Call); InjectHook(isPlayerTargettingChar.get<void>(5), IsPlayerTargettingChar_ExtraChecks, HookType::Call);
} }
TXN_CATCH();
// Use PS2 randomness for Rosenberg audio to hopefully bring the odds closer to PS2 // Use PS2 randomness for Rosenberg audio to hopefully bring the odds closer to PS2
// The functionality was never broken on PC - but the random distribution seemingly made it looks as if it was // The functionality was never broken on PC - but the random distribution seemingly made it looks as if it was
try
{ {
auto busted_audio_rand = get_pattern("80 BB 48 01 00 00 00 0F 85 ? ? ? ? E8 ? ? ? ? 25 FF FF 00 00", 13); auto busted_audio_rand = get_pattern("80 BB 48 01 00 00 00 0F 85 ? ? ? ? E8 ? ? ? ? 25 FF FF 00 00", 13);
InjectHook(busted_audio_rand, rand15_ps2); InjectHook(busted_audio_rand, rand15_ps2);
} }
TXN_CATCH();
// Reset variables on New Game // Reset variables on New Game
try
{ {
using namespace VariableResets; using namespace VariableResets;
@ -1553,30 +1591,28 @@ void Patch_VC_Common()
GameVariablesToReset.emplace_back(*get_pattern<int*>("7D 78 A1 ? ? ? ? 05", 2 + 1)); // LastTimeAmbulanceCreated GameVariablesToReset.emplace_back(*get_pattern<int*>("7D 78 A1 ? ? ? ? 05", 2 + 1)); // LastTimeAmbulanceCreated
GameVariablesToReset.emplace_back(*get_pattern<int*>("A1 ? ? ? ? 05 ? ? ? ? 39 05 ? ? ? ? 0F 86 ? ? ? ? 8B 15", 1)); // LastTimeFireTruckCreated GameVariablesToReset.emplace_back(*get_pattern<int*>("A1 ? ? ? ? 05 ? ? ? ? 39 05 ? ? ? ? 0F 86 ? ? ? ? 8B 15", 1)); // LastTimeFireTruckCreated
} }
TXN_CATCH();
// Ped speech fix // Ped speech fix
// Based off Sergenaur's fix // Based off Sergenaur's fix
try
{ {
// Remove the artificial 6s delay between any ped speech samples // Remove the artificial 6s delay between any ped speech samples
auto delay_check = pattern("80 BE ? ? ? ? ? 0F 85 ? ? ? ? B9"); auto delay_check = get_pattern("80 BE ? ? ? ? ? 0F 85 ? ? ? ? B9", 7);
auto comment_delay_id1 = pattern("0F B7 C2 DD D8 C1 E0 04"); auto comment_delay_id1 = get_pattern("0F B7 C2 DD D8 C1 E0 04");
auto comment_delay_id2 = pattern("0F B7 95 DA 05 00 00 D9 6C 24 04"); auto comment_delay_id2 = pattern("0F B7 95 DA 05 00 00 D9 6C 24 04").get_one();
// Make sure we don't conflict with Sergenaur's fix Nop(delay_check, 6);
if (delay_check.count_hint(1).size() == 1 && comment_delay_id1.count_hint(1).size() == 1 && comment_delay_id2.count_hint(1).size() == 1)
{
Nop(delay_check.get_first<void>(7), 6);
// movzx eax, dx -> movzx eax, bx // movzx eax, dx -> movzx eax, bx
Patch(comment_delay_id1.get_first<void>(), { 0x0F, 0xB7, 0xC3 }); Patch(comment_delay_id1, { 0x0F, 0xB7, 0xC3 });
// movzx edx, word ptr [ebp+5DAh] -> movzx edx, bx \ nop // movzx edx, word ptr [ebp+5DAh] -> movzx edx, bx \ nop
auto delay_id2 = comment_delay_id2.get_one(); Patch(comment_delay_id2.get<void>(), { 0x0F, 0xB7, 0xD3 });
Patch(delay_id2.get<void>(), { 0x0F, 0xB7, 0xD3 }); Nop(comment_delay_id2.get<void>(3), 4);
Nop(delay_id2.get<void>(3), 4);
}
} }
TXN_CATCH();
} }
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)

View file

@ -82,7 +82,6 @@
<EnableEnhancedInstructionSet>NoExtensions</EnableEnhancedInstructionSet> <EnableEnhancedInstructionSet>NoExtensions</EnableEnhancedInstructionSet>
<AdditionalOptions>/Zc:threadSafeInit- /Zc:strictStrings %(AdditionalOptions)</AdditionalOptions> <AdditionalOptions>/Zc:threadSafeInit- /Zc:strictStrings %(AdditionalOptions)</AdditionalOptions>
<SDLCheck>true</SDLCheck> <SDLCheck>true</SDLCheck>
<ExceptionHandling>false</ExceptionHandling>
<EnforceTypeConversionRules>true</EnforceTypeConversionRules> <EnforceTypeConversionRules>true</EnforceTypeConversionRules>
<RuntimeTypeInfo>false</RuntimeTypeInfo> <RuntimeTypeInfo>false</RuntimeTypeInfo>
<LanguageStandard>stdcpp17</LanguageStandard> <LanguageStandard>stdcpp17</LanguageStandard>
@ -114,7 +113,6 @@
<EnableEnhancedInstructionSet>NoExtensions</EnableEnhancedInstructionSet> <EnableEnhancedInstructionSet>NoExtensions</EnableEnhancedInstructionSet>
<AdditionalOptions>/Zc:threadSafeInit- /Zc:strictStrings %(AdditionalOptions)</AdditionalOptions> <AdditionalOptions>/Zc:threadSafeInit- /Zc:strictStrings %(AdditionalOptions)</AdditionalOptions>
<SDLCheck>true</SDLCheck> <SDLCheck>true</SDLCheck>
<ExceptionHandling>false</ExceptionHandling>
<EnforceTypeConversionRules>true</EnforceTypeConversionRules> <EnforceTypeConversionRules>true</EnforceTypeConversionRules>
<RuntimeTypeInfo>false</RuntimeTypeInfo> <RuntimeTypeInfo>false</RuntimeTypeInfo>
<LanguageStandard>stdcpp17</LanguageStandard> <LanguageStandard>stdcpp17</LanguageStandard>
@ -148,7 +146,6 @@
<EnableEnhancedInstructionSet>NoExtensions</EnableEnhancedInstructionSet> <EnableEnhancedInstructionSet>NoExtensions</EnableEnhancedInstructionSet>
<AdditionalOptions>/Zc:threadSafeInit- /Zc:strictStrings %(AdditionalOptions)</AdditionalOptions> <AdditionalOptions>/Zc:threadSafeInit- /Zc:strictStrings %(AdditionalOptions)</AdditionalOptions>
<SDLCheck>true</SDLCheck> <SDLCheck>true</SDLCheck>
<ExceptionHandling>false</ExceptionHandling>
<EnforceTypeConversionRules>true</EnforceTypeConversionRules> <EnforceTypeConversionRules>true</EnforceTypeConversionRules>
<RuntimeTypeInfo>false</RuntimeTypeInfo> <RuntimeTypeInfo>false</RuntimeTypeInfo>
<LanguageStandard>stdcpp17</LanguageStandard> <LanguageStandard>stdcpp17</LanguageStandard>