From d596ec7d1e71898fa97cfc07e0b25bcf4dd09580 Mon Sep 17 00:00:00 2001 From: Silent Date: Tue, 26 Sep 2017 18:03:13 +0200 Subject: [PATCH] CdStream fix future proof for new FLA --- SilentPatch/TheFLAUtils.cpp | 3 ++ SilentPatch/TheFLAUtils.h | 16 ++++++ SilentPatchSA/SilentPatchSA.cpp | 91 +++++++++++++++++++-------------- 3 files changed, 72 insertions(+), 38 deletions(-) diff --git a/SilentPatch/TheFLAUtils.cpp b/SilentPatch/TheFLAUtils.cpp index d51a0af..630f52e 100644 --- a/SilentPatch/TheFLAUtils.cpp +++ b/SilentPatch/TheFLAUtils.cpp @@ -7,6 +7,7 @@ int32_t (*FLAUtils::GetExtendedID8Func)(const uint8_t* ptr) = FLAUtils::GetExtendedID8_Stock; int32_t (*FLAUtils::GetExtendedID16Func)(const uint16_t* ptr) = FLAUtils::GetExtendedID16_Stock; +void (*FLAUtils::SetCdStreamWakeFunc)(CdStreamWakeFunc func) = nullptr; static HMODULE flaModule = nullptr; @@ -26,6 +27,8 @@ void FLAUtils::Init() { GetExtendedID16Func = function16; } + + SetCdStreamWakeFunc = reinterpret_cast(GetProcAddress( flaModule, "SetCdStreamReleaseChannelfUsedByTheFLA" )); } } diff --git a/SilentPatch/TheFLAUtils.h b/SilentPatch/TheFLAUtils.h index 8bd8d3e..7962c9a 100644 --- a/SilentPatch/TheFLAUtils.h +++ b/SilentPatch/TheFLAUtils.h @@ -35,9 +35,24 @@ public: uint16_t value; }; + typedef void(*CdStreamWakeFunc)( struct CdStream* ); + static void Init(); static bool UsesEnhancedIMGs(); + static void SetCdStreamWakeFunction( CdStreamWakeFunc func ) + { + if ( SetCdStreamWakeFunc != nullptr ) + { + SetCdStreamWakeFunc( func ); + } + } + + static bool CdStreamRaceConditionAware() + { + return SetCdStreamWakeFunc != nullptr; + } + private: static constexpr int32_t MAX_UINT8_ID = 0xFF; static constexpr int32_t MAX_UINT16_ID = 0xFFFD; @@ -56,6 +71,7 @@ private: static int32_t (*GetExtendedID8Func)(const uint8_t* ptr); static int32_t (*GetExtendedID16Func)(const uint16_t* ptr); + static void (*SetCdStreamWakeFunc)(CdStreamWakeFunc func); static_assert( sizeof(int8) == sizeof(uint8_t) ); static_assert( sizeof(int16) == sizeof(uint16_t) ); diff --git a/SilentPatchSA/SilentPatchSA.cpp b/SilentPatchSA/SilentPatchSA.cpp index 5d13dff..546c084 100644 --- a/SilentPatchSA/SilentPatchSA.cpp +++ b/SilentPatchSA/SilentPatchSA.cpp @@ -1412,6 +1412,10 @@ static void CdStreamInitThread() InitializeCriticalSectionAndSpinCount( &CdStreamCritSec, 10 ); + FLAUtils::SetCdStreamWakeFunction( []( CdStream* pStream ) { + CdStreamThreadOnObject( pStream ); + } ); + orgCdStreamInitThread(); } @@ -2916,55 +2920,66 @@ BOOL InjectDelayedPatches_10() // Race condition in CdStream fixed // Not taking effect with modloader - if ( !ModCompat::ModloaderCdStreamRaceConditionAware( modloaderModule ) && !FLAUtils::UsesEnhancedIMGs() ) + if ( !ModCompat::ModloaderCdStreamRaceConditionAware( modloaderModule ) ) { - ReadCall( 0x406C78, CdStreamSync::orgCdStreamInitThread ); - InjectHook( 0x406C78, CdStreamSync::CdStreamInitThread ); + // Don't patch if old FLA and enhanced IMGs are in place + // For new FLA, we patch everything except CdStreamThread and then interop with FLA + const bool flaBugAware = FLAUtils::CdStreamRaceConditionAware(); + const bool usesEnhancedImages = FLAUtils::UsesEnhancedIMGs(); + if ( !usesEnhancedImages || flaBugAware ) { - uintptr_t address; - if ( *(uint8_t*)0x406460 == 0xE9 ) - { - ReadCall( 0x406460, address ); - } - else - { - address = 0x406460; - } + ReadCall( 0x406C78, CdStreamSync::orgCdStreamInitThread ); + InjectHook( 0x406C78, CdStreamSync::CdStreamInitThread ); - const uintptr_t waitForSingleObject = address + 0x1D; - const uint8_t orgCode[] = { 0x8B, 0x46, 0x04, 0x85, 0xC0, 0x74, 0x10, 0xC6, 0x46, 0x0D, 0x01 }; - if ( memcmp( orgCode, (void*)waitForSingleObject, sizeof(orgCode) ) == 0 ) { - VP::Patch( waitForSingleObject, { 0x56, 0xFF, 0x15 } ); - VP::Patch( waitForSingleObject + 3, &CdStreamSync::CdStreamSyncOnObject ); - VP::Patch( waitForSingleObject + 3 + 4, { 0x5E, 0xC3 } ); - + uintptr_t address; + if ( *(uint8_t*)0x406460 == 0xE9 ) { - const uint8_t orgCode1[] = { 0xFF, 0x15 }; - const uint8_t orgCode2[] = { 0x48, 0xF7, 0xD8 }; - const uintptr_t getOverlappedResult = address + 0x5F; - if ( memcmp( orgCode1, (void*)getOverlappedResult, sizeof(orgCode1) ) == 0 && - memcmp( orgCode2, (void*)(getOverlappedResult + 6), sizeof(orgCode2) ) == 0 ) + ReadCall( 0x406460, address ); + } + else + { + address = 0x406460; + } + + const uintptr_t waitForSingleObject = address + 0x1D; + const uint8_t orgCode[] = { 0x8B, 0x46, 0x04, 0x85, 0xC0, 0x74, 0x10, 0xC6, 0x46, 0x0D, 0x01 }; + if ( memcmp( orgCode, (void*)waitForSingleObject, sizeof(orgCode) ) == 0 ) + { + VP::Patch( waitForSingleObject, { 0x56, 0xFF, 0x15 } ); + VP::Patch( waitForSingleObject + 3, &CdStreamSync::CdStreamSyncOnObject ); + VP::Patch( waitForSingleObject + 3 + 4, { 0x5E, 0xC3 } ); + { - VP::Patch( getOverlappedResult + 2, &CdStreamSync::pGetOverlappedResult ); - VP::Patch( getOverlappedResult + 6, { 0x5E, 0xC3 } ); // pop esi / retn + const uint8_t orgCode1[] = { 0xFF, 0x15 }; + const uint8_t orgCode2[] = { 0x48, 0xF7, 0xD8 }; + const uintptr_t getOverlappedResult = address + 0x5F; + if ( memcmp( orgCode1, (void*)getOverlappedResult, sizeof(orgCode1) ) == 0 && + memcmp( orgCode2, (void*)(getOverlappedResult + 6), sizeof(orgCode2) ) == 0 ) + { + VP::Patch( getOverlappedResult + 2, &CdStreamSync::pGetOverlappedResult ); + VP::Patch( getOverlappedResult + 6, { 0x5E, 0xC3 } ); // pop esi / retn + } } } } + + if ( !usesEnhancedImages ) + { + Patch( 0x406669, { 0x56, 0xFF, 0x15 } ); + Patch( 0x406669 + 3, &CdStreamSync::CdStreamThreadOnObject ); + Patch( 0x406669 + 3 + 4, { 0xEB, 0x0F } ); + } + + Patch( 0x406910, { 0xFF, 0x15 } ); + Patch( 0x406910 + 2, &CdStreamSync::CdStreamInitializeSyncObject ); + Nop( 0x406910 + 6, 4 ); + Nop( 0x406910 + 0x16, 2 ); + + Patch( 0x4063B5, { 0x56, 0x50 } ); + InjectHook( 0x4063B5 + 2, CdStreamSync::CdStreamShutdownSyncObject_Stub, PATCH_CALL ); } - - Patch( 0x406669, { 0x56, 0xFF, 0x15 } ); - Patch( 0x406669 + 3, &CdStreamSync::CdStreamThreadOnObject ); - Patch( 0x406669 + 3 + 4, { 0xEB, 0x0F } ); - - Patch( 0x406910, { 0xFF, 0x15 } ); - Patch( 0x406910 + 2, &CdStreamSync::CdStreamInitializeSyncObject ); - Nop( 0x406910 + 6, 4 ); - Nop( 0x406910 + 0x16, 2 ); - - Patch( 0x4063B5, { 0x56, 0x50 } ); - InjectHook( 0x4063B5 + 2, CdStreamSync::CdStreamShutdownSyncObject_Stub, PATCH_CALL ); } #ifndef NDEBUG