mirror of
https://github.com/CookiePLMonster/SilentPatch.git
synced 2024-11-21 21:12:29 +01:00
III/VC/SA: Fix credits scaling and timing
This commit is contained in:
parent
2b64e74069
commit
5cb14580b5
@ -99,15 +99,15 @@ static const void* SubtitlesShadowFix_JumpBack;
|
||||
|
||||
auto WorldRemove = reinterpret_cast<void(*)(void*)>(hook::get_pattern("8A 43 50 56 24 07", -5));
|
||||
|
||||
static const float& ResolutionWidthMult = **AddressByVersion<float**>(0x57E956, 0x57ECA6, 0x57EBA6);
|
||||
inline float GetWidthMult()
|
||||
float GetWidthMult()
|
||||
{
|
||||
static const float& ResolutionWidthMult = **AddressByVersion<float**>(0x57E956, 0x57ECA6, 0x57EBA6);
|
||||
return ResolutionWidthMult;
|
||||
}
|
||||
|
||||
static const float& ResolutionHeightMult = **AddressByVersion<float**>(0x57E940, 0x57EC90, 0x57EB90);
|
||||
inline float GetHeightMult()
|
||||
float GetHeightMult()
|
||||
{
|
||||
static const float& ResolutionHeightMult = **AddressByVersion<float**>(0x57E940, 0x57EC90, 0x57EB90);
|
||||
return ResolutionHeightMult;
|
||||
}
|
||||
|
||||
@ -987,6 +987,29 @@ namespace OnscreenCounterBarFixes
|
||||
HOOK_EACH_INIT(YPos, orgYPos, YPos_Recalculated);
|
||||
}
|
||||
|
||||
// ============= Fix credits not scaling to resolution =============
|
||||
namespace CreditsScalingFixes
|
||||
{
|
||||
static const unsigned int FIXED_RES_HEIGHT_SCALE = 448;
|
||||
|
||||
template<std::size_t Index>
|
||||
static void (*orgPrintString)(float,float,const wchar_t*);
|
||||
|
||||
template<std::size_t Index>
|
||||
static void PrintString_ScaleY(float fX, float fY, const wchar_t* pText)
|
||||
{
|
||||
orgPrintString<Index>(fX, fY * GetHeightMult() * RsGlobal->MaximumHeight, pText);
|
||||
}
|
||||
|
||||
static void (*orgSetScale)(float X, float Y);
|
||||
static void SetScale_ScaleToRes(float X, float Y)
|
||||
{
|
||||
orgSetScale(X * GetWidthMult() * RsGlobal->MaximumWidth, Y * GetHeightMult() * RsGlobal->MaximumHeight);
|
||||
}
|
||||
|
||||
HOOK_EACH_INIT(PrintString, orgPrintString, PrintString_ScaleY);
|
||||
}
|
||||
|
||||
namespace ModelIndicesReadyHook
|
||||
{
|
||||
static void (*orgInitialiseObjectData)(const char*);
|
||||
@ -1252,6 +1275,41 @@ void InjectDelayedPatches_III_Common( bool bHasDebugMenu, const wchar_t* wcModul
|
||||
}
|
||||
TXN_CATCH();
|
||||
|
||||
|
||||
// Fix credits not scaling to resolution
|
||||
try
|
||||
{
|
||||
using namespace CreditsScalingFixes;
|
||||
|
||||
std::array<void*, 1> creditPrintString = {
|
||||
get_pattern("D9 1C 24 E8 ? ? ? ? 83 C4 0C 8B 03", 3),
|
||||
};
|
||||
|
||||
auto setScale = get_pattern("E8 ? ? ? ? 8B 44 24 28 59 59");
|
||||
|
||||
// Credits are timed for 640x480, but the PC version scales to 640x448 internally - speed credits up a bit,
|
||||
// especially since ours are longer and even the PS2 version cuts them a bit late.
|
||||
float** creditsSpeed = get_pattern<float*>("D8 0D ? ? ? ? D9 5D E8", 2);
|
||||
|
||||
// As we now scale everything on PrintString time, the resolution height checks need to be unscaled.
|
||||
void* resHeightScales[] = {
|
||||
get_pattern("DF 6C 24 08 DB 05 ? ? ? ? D8 05", 4 + 2),
|
||||
get_pattern("8B 35 ? ? ? ? 03 75 F4", 2),
|
||||
};
|
||||
|
||||
HookEach_PrintString(creditPrintString, InterceptCall);
|
||||
InterceptCall(setScale, orgSetScale, SetScale_ScaleToRes);
|
||||
|
||||
static float newSpeed = **creditsSpeed * (480.0f/448.0f);
|
||||
Patch(creditsSpeed, &newSpeed);
|
||||
|
||||
for (void* addr : resHeightScales)
|
||||
{
|
||||
Patch(addr, &FIXED_RES_HEIGHT_SCALE);
|
||||
}
|
||||
}
|
||||
TXN_CATCH();
|
||||
|
||||
FLAUtils::Init(moduleList);
|
||||
}
|
||||
|
||||
|
@ -322,6 +322,21 @@ struct AlphaObjectInfo
|
||||
{ return a.fCompareValue < b.fCompareValue; }
|
||||
};
|
||||
|
||||
struct PsGlobalType;
|
||||
|
||||
struct RsGlobalType
|
||||
{
|
||||
const char* AppName;
|
||||
signed int MaximumWidth;
|
||||
signed int MaximumHeight;
|
||||
unsigned int frameLimit;
|
||||
BOOL quit;
|
||||
PsGlobalType* ps;
|
||||
void* keyboard;
|
||||
void* mouse;
|
||||
void* pad;
|
||||
};
|
||||
|
||||
// Other wrappers
|
||||
void (*GTAdelete)(void*) = AddressByVersion<void(*)(void*)>(0x82413F, 0x824EFF, 0x85E58C);
|
||||
const char* (*GetFrameNodeName)(RwFrame*) = AddressByVersion<const char*(*)(RwFrame*)>(0x72FB30, 0x730360, 0x769C20);
|
||||
@ -345,6 +360,8 @@ auto WorldRemove = AddressByVersion<void(*)(CEntity*)>(0x563280, 0, 0x57D37
|
||||
// SA variables
|
||||
void** rwengine = *AddressByVersion<void***>(0x58FFC0, 0x53F032, 0x48C194, { "8B 48 20 53 56 57 6A 01", -5 + 1 });
|
||||
|
||||
RsGlobalType* RsGlobal = *AddressByVersion<RsGlobalType**>(0x619602 + 2, { "33 C0 C7 05 ? ? ? ? ? ? ? ? C7 05", 2 + 2 });
|
||||
|
||||
unsigned char& nGameClockDays = **AddressByVersion<unsigned char**>(0x4E841D, 0x4E886D, 0x4F3871);
|
||||
unsigned char& nGameClockMonths = **AddressByVersion<unsigned char**>(0x4E842D, 0x4E887D, 0x4F3861);
|
||||
void*& pUserTracksStuff = **AddressByVersion<void***>(0x4D9B7B, 0x4DA06C, 0x4E4A43);
|
||||
@ -468,6 +485,39 @@ static CAEWaveDecoder* __stdcall CAEWaveDecoderInit(CAEDataStream* pStream)
|
||||
return new CAEWaveDecoder(pStream);
|
||||
}
|
||||
|
||||
namespace ScalingInternals
|
||||
{
|
||||
// 1.0 - fast math uses a scaling multiplier
|
||||
float ScaleX_Multiplier(float val)
|
||||
{
|
||||
static const float& ResolutionWidthMult = **(float**)(0x43CF57 + 2);
|
||||
return val * RsGlobal->MaximumWidth * ResolutionWidthMult;
|
||||
}
|
||||
|
||||
float ScaleY_Multiplier(float val)
|
||||
{
|
||||
static const float& ResolutionHeightMult = **(float**)(0x43CF47 + 2);
|
||||
return val * RsGlobal->MaximumHeight * ResolutionHeightMult;
|
||||
}
|
||||
|
||||
// New binaries - precise math uses a scaling divisor
|
||||
float ScaleX_Divisor(float val)
|
||||
{
|
||||
static const double& ResolutionWidthDiv = **hook::get_pattern<double*>("DC 35 ? ? ? ? DC 0D ? ? ? ? DE E9 D9 5D F0", 2);
|
||||
return static_cast<float>(val * RsGlobal->MaximumWidth / ResolutionWidthDiv);
|
||||
}
|
||||
|
||||
float ScaleY_Divisor(float val)
|
||||
{
|
||||
static const double& ResolutionHeightDiv = **hook::get_pattern<double*>("50 DC 35 ? ? ? ? DC 0D", 1 + 2);
|
||||
return static_cast<float>(val * RsGlobal->MaximumHeight / ResolutionHeightDiv);
|
||||
}
|
||||
}
|
||||
|
||||
// Default to 1.0, update these pointers with a pointer to the new binaries function if needed
|
||||
auto ScaleX = &ScalingInternals::ScaleX_Multiplier;
|
||||
auto ScaleY = &ScalingInternals::ScaleY_Multiplier;
|
||||
|
||||
namespace ScriptFixes
|
||||
{
|
||||
|
||||
@ -2759,6 +2809,38 @@ namespace NewResolutionSelectionDialog
|
||||
}
|
||||
|
||||
|
||||
// ============= Fix credits not scaling to resolution =============
|
||||
// Also makes the shadow scale properly, as they haven't done that either...
|
||||
// But since this seems to be the only place, don't pull in the fix from Vice City,
|
||||
// fix it here instead
|
||||
namespace CreditsScalingFixes
|
||||
{
|
||||
static const unsigned int FIXED_RES_HEIGHT_SCALE = 448;
|
||||
|
||||
template<std::size_t Index>
|
||||
static void (*orgPrintString)(float,float,const wchar_t*);
|
||||
|
||||
template<std::size_t Index>
|
||||
static void PrintString_ScaleY(float fX, float fY, const wchar_t* pText)
|
||||
{
|
||||
if constexpr (Index == 1)
|
||||
{
|
||||
// Fix the shadow X scale - the Y scale will be fixed below
|
||||
fX = fX + 1.0f - ScaleX(1.0f);
|
||||
}
|
||||
orgPrintString<Index>(fX, ScaleY(fY), pText);
|
||||
}
|
||||
|
||||
static void (*orgSetScale)(float X, float Y);
|
||||
static void SetScale_ScaleToRes(float X, float Y)
|
||||
{
|
||||
orgSetScale(ScaleX(X), ScaleY(Y));
|
||||
}
|
||||
|
||||
HOOK_EACH_INIT(PrintString, orgPrintString, PrintString_ScaleY);
|
||||
}
|
||||
|
||||
|
||||
// ============= LS-RP Mode stuff =============
|
||||
namespace LSRPMode
|
||||
{
|
||||
@ -5614,6 +5696,29 @@ void Patch_SA_10(HINSTANCE hInstance)
|
||||
}
|
||||
|
||||
|
||||
// Fix credits not scaling to resolution
|
||||
{
|
||||
using namespace CreditsScalingFixes;
|
||||
|
||||
std::array<uintptr_t, 2> creditPrintString = { 0x5A8707, 0x5A8785 };
|
||||
|
||||
HookEach_PrintString(creditPrintString, InterceptCall);
|
||||
InterceptCall(0x5A86C0, orgSetScale, SetScale_ScaleToRes);
|
||||
|
||||
// Fix the credits cutting off on the bottom early, they don't do that in III
|
||||
// but it regressed in VC and SA
|
||||
static const float topMargin = 1.0f;
|
||||
static const float bottomMargin = -(**(float**)(0x5A869A + 2));
|
||||
|
||||
Patch(0x5A8689 + 2, &topMargin);
|
||||
Patch(0x5A869A + 2, &bottomMargin);
|
||||
|
||||
// As we now scale everything on PrintString time, the resolution height checks need to be unscaled.
|
||||
Patch(0x5A8660 + 2, &FIXED_RES_HEIGHT_SCALE);
|
||||
Patch(0x5AF8C9 + 2, &FIXED_RES_HEIGHT_SCALE);
|
||||
}
|
||||
|
||||
|
||||
#if FULL_PRECISION_D3D
|
||||
// Test - full precision D3D device
|
||||
Patch<uint8_t>( 0x7F672B+1, *(uint8_t*)(0x7F672B+1) | D3DCREATE_FPU_PRESERVE );
|
||||
@ -6374,6 +6479,9 @@ void Patch_SA_NewBinaries_Common(HINSTANCE hInstance)
|
||||
using namespace Memory;
|
||||
using namespace hook::txn;
|
||||
|
||||
ScaleX = &ScalingInternals::ScaleX_Divisor;
|
||||
ScaleY = &ScalingInternals::ScaleY_Divisor;
|
||||
|
||||
try
|
||||
{
|
||||
void* isAlreadyRunning = get_pattern( "85 C0 74 08 33 C0 8B E5 5D C2 10 00", -5 );
|
||||
@ -7635,6 +7743,40 @@ void Patch_SA_NewBinaries_Common(HINSTANCE hInstance)
|
||||
InjectHook(rwEngineGetCurrentSubSystem, RwEngineGetCurrentSubSystem_FromSettings);
|
||||
}
|
||||
TXN_CATCH();
|
||||
|
||||
|
||||
// Fix credits not scaling to resolution
|
||||
{
|
||||
using namespace CreditsScalingFixes;
|
||||
|
||||
std::array<void*, 2> creditPrintString = {
|
||||
get_pattern("E8 ? ? ? ? 83 C4 0C 80 7D 1C 00"),
|
||||
get_pattern("D9 1C 24 E8 ? ? ? ? DD 05 ? ? ? ? 83 C4 0C 5E", 3),
|
||||
};
|
||||
|
||||
auto setScale = get_pattern("D9 1C 24 E8 ? ? ? ? 83 C4 08 68 FF 00 00 00 6A 00 6A 00 6A 00", 3);
|
||||
|
||||
// Fix the credits cutting off on the bottom early, they don't do that in III
|
||||
// but it regressed in VC and SA
|
||||
auto positionOffset = get_pattern("DE C2 D9 45 18 DE EA D9 C9 D9 5D 14 D9 05", 12 + 2);
|
||||
|
||||
// As we now scale everything on PrintString time, the resolution height checks need to be unscaled.
|
||||
void* resHeightScales[] = {
|
||||
get_pattern("DB 05 ? ? ? ? 57 8B 7D 14", 2),
|
||||
get_pattern("A1 ? ? ? ? 03 45 FC 89 45 F4", 1)
|
||||
};
|
||||
|
||||
static const float topMargin = 1.0f;
|
||||
Patch(positionOffset, &topMargin);
|
||||
|
||||
HookEach_PrintString(creditPrintString, InterceptCall);
|
||||
InterceptCall(setScale, orgSetScale, SetScale_ScaleToRes);
|
||||
|
||||
for (void* addr : resHeightScales)
|
||||
{
|
||||
Patch(addr, &FIXED_RES_HEIGHT_SCALE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -72,13 +72,13 @@ void* (*GetModelInfo)(const char*, int*);
|
||||
CVehicleModelInfo**& ms_modelInfoPtrs = *hook::get_pattern<CVehicleModelInfo**>("8B 15 ? ? ? ? 8D 04 24", 2);
|
||||
int32_t& numModelInfos = *hook::get_pattern<int32_t>("81 FD ? ? ? ? 7C B7", 2);
|
||||
|
||||
inline float GetWidthMult()
|
||||
float GetWidthMult()
|
||||
{
|
||||
static const float& ResolutionWidthMult = **AddressByVersion<float**>(0x5FA15E, 0x5FA17E, 0x5F9DBE);
|
||||
return ResolutionWidthMult;
|
||||
}
|
||||
|
||||
inline float GetHeightMult()
|
||||
float GetHeightMult()
|
||||
{
|
||||
static const float& ResolutionHeightMult = **AddressByVersion<float**>(0x5FA148, 0x5FA168, 0x5F9DA8);
|
||||
return ResolutionHeightMult;
|
||||
@ -176,6 +176,21 @@ namespace PrintStringShadows
|
||||
}
|
||||
};
|
||||
|
||||
template<uintptr_t pFltX>
|
||||
struct XMinus
|
||||
{
|
||||
static inline void (*orgPrintString)(float,float,const wchar_t*);
|
||||
static void PrintString(float fX, float fY, const wchar_t* pText)
|
||||
{
|
||||
PrintString_Internal(orgPrintString, fX, fY, -(**margin<pFltX>), 0.0f, pText);
|
||||
}
|
||||
|
||||
static void Hook(uintptr_t addr)
|
||||
{
|
||||
Memory::DynBase::InterceptCall(addr, orgPrintString, PrintString);
|
||||
}
|
||||
};
|
||||
|
||||
template<uintptr_t pFltY>
|
||||
struct Y
|
||||
{
|
||||
@ -384,7 +399,7 @@ namespace RadarTraceOutlineFixes
|
||||
}
|
||||
|
||||
|
||||
// ============= Fix the loading bar outline not scaling to resolution=============
|
||||
// ============= Fix the loading bar outline not scaling to resolution =============
|
||||
namespace LoadingBarOutlineFixes
|
||||
{
|
||||
template<std::size_t Index>
|
||||
@ -429,6 +444,28 @@ namespace LoadingBarOutlineFixes
|
||||
HOOK_EACH_INIT(YPos, orgYPos, YPos_Recalculated);
|
||||
}
|
||||
|
||||
// ============= Fix credits not scaling to resolution =============
|
||||
namespace CreditsScalingFixes
|
||||
{
|
||||
static const unsigned int FIXED_RES_HEIGHT_SCALE = 448;
|
||||
|
||||
template<std::size_t Index>
|
||||
static void (*orgPrintString)(float,float,const wchar_t*);
|
||||
|
||||
template<std::size_t Index>
|
||||
static void PrintString_ScaleY(float fX, float fY, const wchar_t* pText)
|
||||
{
|
||||
orgPrintString<Index>(fX, fY * GetHeightMult() * RsGlobal->MaximumHeight, pText);
|
||||
}
|
||||
|
||||
static void (*orgSetScale)(float X, float Y);
|
||||
static void SetScale_ScaleToRes(float X, float Y)
|
||||
{
|
||||
orgSetScale(X * GetWidthMult() * RsGlobal->MaximumWidth, Y * GetHeightMult() * RsGlobal->MaximumHeight);
|
||||
}
|
||||
|
||||
HOOK_EACH_INIT(PrintString, orgPrintString, PrintString_ScaleY);
|
||||
}
|
||||
|
||||
float FixedRefValue()
|
||||
{
|
||||
@ -1555,6 +1592,42 @@ void InjectDelayedPatches_VC_Common( bool bHasDebugMenu, const wchar_t* wcModule
|
||||
TXN_CATCH();
|
||||
|
||||
|
||||
// Fix credits not scaling to resolution
|
||||
try
|
||||
{
|
||||
using namespace CreditsScalingFixes;
|
||||
|
||||
std::array<void*, 2> creditPrintString = {
|
||||
get_pattern("E8 ? ? ? ? 83 C4 0C 8D 4C 24 14"),
|
||||
get_pattern("E8 ? ? ? ? 83 C4 0C 8B 03"),
|
||||
};
|
||||
|
||||
auto setScale = get_pattern("E8 ? ? ? ? 59 59 8D 4C 24 10");
|
||||
|
||||
// Fix the credits cutting off on the bottom early, they don't do that in III
|
||||
// but it regressed in VC and SA
|
||||
auto positionOffset = pattern("D8 1D ? ? ? ? DF E0 F6 C4 45 0F 85 ? ? ? ? 89 4C 24 08 DB 44 24 08 D8 25").get_one();
|
||||
|
||||
// As we now scale everything on PrintString time, the resolution height checks need to be unscaled.
|
||||
void* resHeightScales[] = {
|
||||
get_pattern("8B 0D ? ? ? ? 8B 03", 2),
|
||||
get_pattern("8B 0D ? ? ? ? C7 44 24 ? ? ? ? ? 03 4C 24 14 ", 2),
|
||||
};
|
||||
|
||||
static const float floatStorage[2] = { 1.0f, -(**positionOffset.get<float*>(0x19 + 2)) };
|
||||
Patch(positionOffset.get<void>(2), &floatStorage[0]);
|
||||
Patch(positionOffset.get<void>(0x19 + 2), &floatStorage[0]);
|
||||
|
||||
HookEach_PrintString(creditPrintString, InterceptCall);
|
||||
InterceptCall(setScale, orgSetScale, SetScale_ScaleToRes);
|
||||
|
||||
for (void* addr : resHeightScales)
|
||||
{
|
||||
Patch(addr, &FIXED_RES_HEIGHT_SCALE);
|
||||
}
|
||||
}
|
||||
TXN_CATCH();
|
||||
|
||||
FLAUtils::Init(moduleList);
|
||||
}
|
||||
|
||||
@ -1600,7 +1673,7 @@ void Patch_VC_10(uint32_t width, uint32_t height)
|
||||
using namespace PrintStringShadows;
|
||||
|
||||
XY<0x5FA1F6, 0x5FA1D5>::Hook(0x5FA1FD);
|
||||
XYMinus<0x544727, 0x544727>::Hook(0x54474D);
|
||||
XMinus<0x544727/*, 0x544727*/>::Hook(0x54474D); // Don't patch Y as we're doing it in the credits scale fix
|
||||
}
|
||||
|
||||
// Mouse fucking fix!
|
||||
@ -1688,7 +1761,7 @@ void Patch_VC_11(uint32_t width, uint32_t height)
|
||||
using namespace PrintStringShadows;
|
||||
|
||||
XY<0x5FA216, 0x5FA1F5>::Hook(0x5FA21D);
|
||||
XYMinus<0x544747, 0x544747>::Hook(0x54476D);
|
||||
XMinus<0x544747/*, 0x544747*/>::Hook(0x54476D); // Don't patch Y as we're doing it in the credits scale fix
|
||||
}
|
||||
|
||||
// Mouse fucking fix!
|
||||
@ -1775,7 +1848,7 @@ void Patch_VC_Steam(uint32_t width, uint32_t height)
|
||||
using namespace PrintStringShadows;
|
||||
|
||||
XY<0x5F9E56, 0x5F9E35>::Hook(0x5F9E5D);
|
||||
XYMinus<0x544617, 0x544617>::Hook(0x54463D);
|
||||
XMinus<0x544617/*, 0x544617*/>::Hook(0x54463D); // Don't patch Y as we're doing it in the credits scale fix
|
||||
}
|
||||
|
||||
// Mouse fucking fix!
|
||||
|
Loading…
Reference in New Issue
Block a user