diff --git a/Client/game_sa/CHudSA.cpp b/Client/game_sa/CHudSA.cpp index 2f5c49e3660..e6889c3c3a3 100644 --- a/Client/game_sa/CHudSA.cpp +++ b/Client/game_sa/CHudSA.cpp @@ -1,6 +1,6 @@ /***************************************************************************** * - * PROJECT: Multi Theft Auto v1.0 + * PROJECT: Multi Theft Auto * LICENSE: See LICENSE in the top level directory * FILE: game_sa/CHudSA.cpp * PURPOSE: HUD display @@ -19,8 +19,8 @@ extern CGameSA* pGame; -char szVehicleName[50] = {'\0'}; -char szZoneName[50] = {'\0'}; +static float radarAltimeterFix = 0.0014625f; // Changes altimeter width (and maybe x pos) +static constexpr float aspectRatioMultiplicatorUntouched = 0.0015625f; // (1 / 640) static ComponentProperties componentProperties; @@ -56,23 +56,18 @@ CHudSA::CHudSA() { InitComponentList(); - // Set the default values - m_fSniperCrosshairScale = 210.0f; + m_pfAspectRatioMultiplicatorX = reinterpret_cast(VAR_AspectRatioMultX); + m_pfAspectRatioMultiplicatorY = reinterpret_cast(VAR_AspectRatioMult); - m_pfCameraCrosshairScale = (float*)VAR_CameraCrosshairScale; - MemPut(m_pfCameraCrosshairScale, 192.0f); - m_pfAspectRatioMultiplicator = (float*)VAR_AspectRatioMult; - MemPut(m_pfAspectRatioMultiplicator, 0.002232143f); + MemPut(0x866C84, 640.0f / ((4.0f / 3.0f) * 448.0f)); // 0x866C84: Weapon sprite x position + MemPut(m_pfAspectRatioMultiplicatorX, 0.0015625f); // (1 / 640) + MemPut(m_pfAspectRatioMultiplicatorY, 0.002232143f); // (1 / 448) - UpdateStreetchCalculations(); + MemPut(0x58B141, &aspectRatioMultiplicatorUntouched); // Vehicle name x pos + MemPut(0x58AE4C, &aspectRatioMultiplicatorUntouched); // Area name x pos + MemPut(0x58A6E0, &radarAltimeterFix); // Fix radar altimeter - // Patch xrefs to 0x863B34, because this variable seems to be shared (2 other functions without any context access to it; probably a compiler optimization) - MemPut(0x58E7D4 + 2, (DWORD)&m_fSniperCrosshairScale); - MemPut(0x58E7EA + 2, (DWORD)&m_fSniperCrosshairScale); - MemPut(0x53E3ED + 2, (DWORD)&m_fSniperCrosshairScale); - MemPut(0x53E41A + 2, (DWORD)&m_fSniperCrosshairScale); - MemPut(0x53E488 + 2, (DWORD)&m_fSniperCrosshairScale); - MemPut(0x53E4BF + 2, (DWORD)&m_fSniperCrosshairScale); + UpdateStreetchCalculations(); // Initalize default data componentProperties.hpBar = MapGet(defaultComponentProperties, HUD_HEALTH); @@ -198,8 +193,8 @@ bool CHudSA::IsComponentVisible(eHudComponent component) void CHudSA::UpdateStreetchCalculations() { - calcStreetchX = rsGlobal->maximumWidth * (*reinterpret_cast(VAR_AspectRatioMultX)); - calcStreetchY = rsGlobal->maximumHeight * (*m_pfAspectRatioMultiplicator); + calcStreetchX = rsGlobal->maximumWidth * (*m_pfAspectRatioMultiplicatorX); + calcStreetchY = rsGlobal->maximumHeight * (*m_pfAspectRatioMultiplicatorY); SComponentPlacement& hpPlacement = componentProperties.hpBar.placement; hpPlacement.height = calcStreetchY * 9.0f; @@ -265,14 +260,13 @@ void CHudSA::AdjustComponents(float fAspectRatio) // Fix for #7400 (HUD elements do not scale correctly for widescreen) // 0x859524: GTA multiplies all HUD and menu transformation variables by this floating point value. It is equal to 1/448, so just translate it to 16/10 / // 16/9 - MemPut(m_pfAspectRatioMultiplicator, 0.002232143f / (4.0f / 3.0f) * fAspectRatio); - - // Set the sniper crosshair scale (fix for #7659) - m_fSniperCrosshairScale = 210.0f * (4.0f / 3.0f) / fAspectRatio; - - // Set the camera crosshair scale (same display flaw as in #7659) - MemPut(m_pfCameraCrosshairScale, 192.0f * (4.0f / 3.0f) / fAspectRatio); + const float ratio = (640.0f / (fAspectRatio * 448.0f)); + radarAltimeterFix = ratio * 0.00147f; + MemPut(m_pfAspectRatioMultiplicatorX, ratio * 0.0015625f); + MemPut(m_pfAspectRatioMultiplicatorY, ratio * 0.002232143f); + MemPut(0x866C84, ratio * 0.17343046f); // 0x866C84: Weapon sprite x position + UpdateStreetchCalculations(); } @@ -282,9 +276,10 @@ void CHudSA::AdjustComponents(float fAspectRatio) void CHudSA::ResetComponentAdjustment() { // Restore default values (4:3 aspect ratio) - MemPut(m_pfAspectRatioMultiplicator, 0.002232143f); - MemPut(m_pfCameraCrosshairScale, 192.0f); - m_fSniperCrosshairScale = 210.0f; + radarAltimeterFix = 0.0014625f; + MemPut(m_pfAspectRatioMultiplicatorX, 0.0015625f); // (1 / 640) + MemPut(m_pfAspectRatioMultiplicatorY, 0.002232143f); // (1 / 448) + MemPut(0x866C84, 0.17343046f); // 0x866C84: Weapon sprite x position UpdateStreetchCalculations(); } diff --git a/Client/game_sa/CHudSA.h b/Client/game_sa/CHudSA.h index 134f69757a4..39e89918c4a 100644 --- a/Client/game_sa/CHudSA.h +++ b/Client/game_sa/CHudSA.h @@ -273,7 +273,8 @@ class CHudSA : public CHud private: std::map m_HudComponentMap; - float* m_pfAspectRatioMultiplicator; + float* m_pfAspectRatioMultiplicatorX; + float* m_pfAspectRatioMultiplicatorY; float* m_pfCameraCrosshairScale; float m_fSniperCrosshairScale; diff --git a/Client/game_sa/CSettingsSA.cpp b/Client/game_sa/CSettingsSA.cpp index 95b66d40dfe..037ad4c94f1 100644 --- a/Client/game_sa/CSettingsSA.cpp +++ b/Client/game_sa/CSettingsSA.cpp @@ -51,7 +51,7 @@ CSettingsSA::CSettingsSA() HookInstall(HOOKPOS_StoreShadowForVehicle, (DWORD)HOOK_StoreShadowForVehicle, 9); m_iDesktopWidth = 0; m_iDesktopHeight = 0; - MemPut(0x6FF420, 0xC3); // Truncate CalculateAspectRatio + MemPut(0x6FF420, 0xC3); MemPut(0x732926, &ms_fVehicleLODDistance); MemPut(0x732940, &ms_fTrainPlaneLODDistance); diff --git a/Client/multiplayer_sa/CMultiplayerSA.cpp b/Client/multiplayer_sa/CMultiplayerSA.cpp index f0cd5661336..d8a37f25b13 100644 --- a/Client/multiplayer_sa/CMultiplayerSA.cpp +++ b/Client/multiplayer_sa/CMultiplayerSA.cpp @@ -1587,6 +1587,7 @@ void CMultiplayerSA::InitHooks() InitHooks_Streaming(); InitHooks_FrameRateFixes(); + InitHooks_WidescreenFix(); InitHooks_ProjectileCollisionFix(); InitHooks_ObjectStreamerOptimization(); diff --git a/Client/multiplayer_sa/CMultiplayerSA.h b/Client/multiplayer_sa/CMultiplayerSA.h index b4339fae47f..c7a680bb8de 100644 --- a/Client/multiplayer_sa/CMultiplayerSA.h +++ b/Client/multiplayer_sa/CMultiplayerSA.h @@ -77,6 +77,7 @@ class CMultiplayerSA : public CMultiplayer void InitHooks_FixLineOfSightArgs(); void InitHooks_Streaming(); void InitHooks_FrameRateFixes(); + void InitHooks_WidescreenFix(); void InitHooks_ProjectileCollisionFix(); void InitHooks_ObjectStreamerOptimization(); void InitHooks_Postprocess(); diff --git a/Client/multiplayer_sa/CMultiplayerSA_WidescreenFix.cpp b/Client/multiplayer_sa/CMultiplayerSA_WidescreenFix.cpp new file mode 100644 index 00000000000..80dc8bbf8bb --- /dev/null +++ b/Client/multiplayer_sa/CMultiplayerSA_WidescreenFix.cpp @@ -0,0 +1,88 @@ +/***************************************************************************** + * + * PROJECT: Multi Theft Auto + * LICENSE: See LICENSE in the top level directory + * FILE: multiplayer_sa/CMultiplayerSA_WidescreenFix.cpp + * + * Multi Theft Auto is available from https://www.multitheftauto.com/ + * + *****************************************************************************/ + +// NOTE: This code is based on ThirteenAG's fix, which is licensed under the MIT license. +#include "StdInc.h" + +#ifndef M_PI + #define M_PI 3.14159265358979323846 +#endif + +static constexpr float CameraWidth = 0.01403292f; +static constexpr float SkyMultiFix = 10.0f; + +static float* ScreenAspectRatio = reinterpret_cast(0xC3EFA4); +static float* ScreenFieldOfView = reinterpret_cast(0x8D5038); + +static float AdjustFOV(float factor, float aspectRatio) noexcept +{ + return std::round((2.0f * std::atan(((aspectRatio) / (4.0f / 3.0f)) * + std::tan(factor / 2.0f * ((float)M_PI / 180.0f)))) * + (180.0f / (float)M_PI) * 100.0f) / 100.0f; +} + +static void SetFOV(float factor) +{ + *ScreenFieldOfView = AdjustFOV(factor, *ScreenAspectRatio); +} + +static constexpr std::uintptr_t RETURN_CCamera_Find3rdPersonCamTargetVector = 0x5149A6; +static void __declspec(naked) CalculateAimingPoint() +{ + _asm + { + fstp st + mov edx, [ScreenAspectRatio] + fmul [edx] + mov edi, [esp + 1Ch + 14h] + mov edx, edi + jmp RETURN_CCamera_Find3rdPersonCamTargetVector + } +} + +static void InstallAspectRatioFixes() +{ + // Disables jump instructions in GetVideoModeList + MemSet((void*)0x745BD1, 0x90, 2); + MemSet((void*)0x745BD9, 0x90, 2); + + // Proportional coronas, skips multiplication by ScreenY in CCoronas::Render + MemSet((void*)0x6FB2C9, 0x90, 4); + + // Load ScreenY value from the stack + MemPut(0x6FB2BD, 0x6C); // CCoronas::Render + MemPut(0x6FB2DC, 0x78); // CCoronas::Render + MemPut(0x713BE5, 0x20); // CClouds::Render + MemPut(0x713B6D, 0x38); // CClouds::Render + MemPut(0x713CFB, 0x38); // CClouds::Render + MemPut(0x713EFC, 0x30); // CClouds::Render + MemPut(0x714004, 0x38); // CClouds::Render +} + +static void InstallFieldOfViewFixes() +{ + // Fix sky blurring white in ultrawide screens + MemPut(0x714843, &SkyMultiFix); + MemPut(0x714860, &SkyMultiFix); + + HookInstall(0x6FF410, reinterpret_cast(SetFOV), 9); + HookInstall(0x51499E, reinterpret_cast(CalculateAimingPoint), 6); + + // Skips division by CDraw::ms_fAspectRatio + MemSet((void*)0x50AD79, 0x90, 6); + MemPut(0x50AD5B, &CameraWidth); // CCamera::Find3rdPersonQuickAimPitch + MemPut(0x51498F, &CameraWidth); // CCamera::Find3rdPersonCamTargetVector +} + +void CMultiplayerSA::InitHooks_WidescreenFix() +{ + InstallAspectRatioFixes(); + InstallFieldOfViewFixes(); +} diff --git a/Client/sdk/game/CSettings.h b/Client/sdk/game/CSettings.h index 6ce85f2c2e6..b6f33ea8d95 100644 --- a/Client/sdk/game/CSettings.h +++ b/Client/sdk/game/CSettings.h @@ -145,7 +145,7 @@ class CGameSettings virtual float GetAspectRatioValue() = 0; virtual eAspectRatio GetAspectRatio() = 0; - virtual void SetAspectRatio(eAspectRatio aspectRatio, bool bAdjustmentEnabled = true) = 0; + virtual void SetAspectRatio(eAspectRatio aspectRatio, bool isAdjustmentEnabled) = 0; virtual bool IsGrassEnabled() = 0; virtual void SetGrassEnabled(bool bEnable) = 0;