mirror of
https://github.com/CookiePLMonster/SilentPatch.git
synced 2024-12-29 15:23:02 +05:00
CdStream fix future proof for new FLA
This commit is contained in:
parent
d6e0f3e74f
commit
d596ec7d1e
3 changed files with 72 additions and 38 deletions
|
@ -7,6 +7,7 @@
|
||||||
|
|
||||||
int32_t (*FLAUtils::GetExtendedID8Func)(const uint8_t* ptr) = FLAUtils::GetExtendedID8_Stock;
|
int32_t (*FLAUtils::GetExtendedID8Func)(const uint8_t* ptr) = FLAUtils::GetExtendedID8_Stock;
|
||||||
int32_t (*FLAUtils::GetExtendedID16Func)(const uint16_t* ptr) = FLAUtils::GetExtendedID16_Stock;
|
int32_t (*FLAUtils::GetExtendedID16Func)(const uint16_t* ptr) = FLAUtils::GetExtendedID16_Stock;
|
||||||
|
void (*FLAUtils::SetCdStreamWakeFunc)(CdStreamWakeFunc func) = nullptr;
|
||||||
|
|
||||||
static HMODULE flaModule = nullptr;
|
static HMODULE flaModule = nullptr;
|
||||||
|
|
||||||
|
@ -26,6 +27,8 @@ void FLAUtils::Init()
|
||||||
{
|
{
|
||||||
GetExtendedID16Func = function16;
|
GetExtendedID16Func = function16;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SetCdStreamWakeFunc = reinterpret_cast<decltype(SetCdStreamWakeFunc)>(GetProcAddress( flaModule, "SetCdStreamReleaseChannelfUsedByTheFLA" ));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -35,9 +35,24 @@ public:
|
||||||
uint16_t value;
|
uint16_t value;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef void(*CdStreamWakeFunc)( struct CdStream* );
|
||||||
|
|
||||||
static void Init();
|
static void Init();
|
||||||
static bool UsesEnhancedIMGs();
|
static bool UsesEnhancedIMGs();
|
||||||
|
|
||||||
|
static void SetCdStreamWakeFunction( CdStreamWakeFunc func )
|
||||||
|
{
|
||||||
|
if ( SetCdStreamWakeFunc != nullptr )
|
||||||
|
{
|
||||||
|
SetCdStreamWakeFunc( func );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool CdStreamRaceConditionAware()
|
||||||
|
{
|
||||||
|
return SetCdStreamWakeFunc != nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static constexpr int32_t MAX_UINT8_ID = 0xFF;
|
static constexpr int32_t MAX_UINT8_ID = 0xFF;
|
||||||
static constexpr int32_t MAX_UINT16_ID = 0xFFFD;
|
static constexpr int32_t MAX_UINT16_ID = 0xFFFD;
|
||||||
|
@ -56,6 +71,7 @@ private:
|
||||||
|
|
||||||
static int32_t (*GetExtendedID8Func)(const uint8_t* ptr);
|
static int32_t (*GetExtendedID8Func)(const uint8_t* ptr);
|
||||||
static int32_t (*GetExtendedID16Func)(const uint16_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(int8) == sizeof(uint8_t) );
|
||||||
static_assert( sizeof(int16) == sizeof(uint16_t) );
|
static_assert( sizeof(int16) == sizeof(uint16_t) );
|
||||||
|
|
|
@ -1412,6 +1412,10 @@ static void CdStreamInitThread()
|
||||||
|
|
||||||
InitializeCriticalSectionAndSpinCount( &CdStreamCritSec, 10 );
|
InitializeCriticalSectionAndSpinCount( &CdStreamCritSec, 10 );
|
||||||
|
|
||||||
|
FLAUtils::SetCdStreamWakeFunction( []( CdStream* pStream ) {
|
||||||
|
CdStreamThreadOnObject( pStream );
|
||||||
|
} );
|
||||||
|
|
||||||
orgCdStreamInitThread();
|
orgCdStreamInitThread();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2916,55 +2920,66 @@ BOOL InjectDelayedPatches_10()
|
||||||
|
|
||||||
// Race condition in CdStream fixed
|
// Race condition in CdStream fixed
|
||||||
// Not taking effect with modloader
|
// Not taking effect with modloader
|
||||||
if ( !ModCompat::ModloaderCdStreamRaceConditionAware( modloaderModule ) && !FLAUtils::UsesEnhancedIMGs() )
|
if ( !ModCompat::ModloaderCdStreamRaceConditionAware( modloaderModule ) )
|
||||||
{
|
{
|
||||||
ReadCall( 0x406C78, CdStreamSync::orgCdStreamInitThread );
|
// Don't patch if old FLA and enhanced IMGs are in place
|
||||||
InjectHook( 0x406C78, CdStreamSync::CdStreamInitThread );
|
// 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;
|
ReadCall( 0x406C78, CdStreamSync::orgCdStreamInitThread );
|
||||||
if ( *(uint8_t*)0x406460 == 0xE9 )
|
InjectHook( 0x406C78, CdStreamSync::CdStreamInitThread );
|
||||||
{
|
|
||||||
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 } );
|
uintptr_t address;
|
||||||
VP::Patch( waitForSingleObject + 3, &CdStreamSync::CdStreamSyncOnObject );
|
if ( *(uint8_t*)0x406460 == 0xE9 )
|
||||||
VP::Patch( waitForSingleObject + 3 + 4, { 0x5E, 0xC3 } );
|
|
||||||
|
|
||||||
{
|
{
|
||||||
const uint8_t orgCode1[] = { 0xFF, 0x15 };
|
ReadCall( 0x406460, address );
|
||||||
const uint8_t orgCode2[] = { 0x48, 0xF7, 0xD8 };
|
}
|
||||||
const uintptr_t getOverlappedResult = address + 0x5F;
|
else
|
||||||
if ( memcmp( orgCode1, (void*)getOverlappedResult, sizeof(orgCode1) ) == 0 &&
|
{
|
||||||
memcmp( orgCode2, (void*)(getOverlappedResult + 6), sizeof(orgCode2) ) == 0 )
|
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 );
|
const uint8_t orgCode1[] = { 0xFF, 0x15 };
|
||||||
VP::Patch( getOverlappedResult + 6, { 0x5E, 0xC3 } ); // pop esi / retn
|
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
|
#ifndef NDEBUG
|
||||||
|
|
Loading…
Reference in a new issue