diff --git a/.gitignore b/.gitignore index 7eacf06..aa7b409 100644 --- a/.gitignore +++ b/.gitignore @@ -11,6 +11,7 @@ *.sln.docstates *.lnk .obsidian/* +mgs2_live_dump.bin # User-specific files (MonoDevelop/Xamarin Studio) *.userprefs @@ -362,4 +363,4 @@ MigrationBackup/ .ionide/ # Fody - auto-generated XML schema -FodyWeavers.xsd \ No newline at end of file +FodyWeavers.xsd diff --git a/ConfigTool/tab_data.cpp b/ConfigTool/tab_data.cpp index c6b4ef8..26ce435 100644 --- a/ConfigTool/tab_data.cpp +++ b/ConfigTool/tab_data.cpp @@ -224,6 +224,12 @@ std::nullopt, false, Field::Int, 100, 1, 100}, { ConfigKeys::FixOpticalCamo_Section, ConfigKeys::FixOpticalCamo_Setting, ConfigKeys::FixOpticalCamo_Help, ConfigKeys::FixOpticalCamo_Tooltip, std::nullopt, false, Field::Bool, true }, + { ConfigKeys::FixMGS2DepthOfField_Section, ConfigKeys::FixMGS2DepthOfField_Setting, ConfigKeys::FixMGS2DepthOfField_Help, ConfigKeys::FixMGS2DepthOfField_Tooltip, + std::nullopt, false, Field::Bool, true }, + + { ConfigKeys::MGS2DepthOfFieldBlurUvMultiplier_Section, ConfigKeys::MGS2DepthOfFieldBlurUvMultiplier_Setting, ConfigKeys::MGS2DepthOfFieldBlurUvMultiplier_Help, ConfigKeys::MGS2DepthOfFieldBlurUvMultiplier_Tooltip, + std::make_pair(ConfigKeys::FixMGS2DepthOfField_Section, ConfigKeys::FixMGS2DepthOfField_Setting), false, Field::Float, 0, 0, 0, "", {}, 6.0, 0.0, 20.0 }, + { ConfigKeys::RestoreDogtagNames_Section, ConfigKeys::RestoreDogtagNames_Setting, ConfigKeys::RestoreDogtagNames_Help, ConfigKeys::RestoreDogtagNames_Tooltip, std::nullopt, false, Field::Bool, true }, diff --git a/src/dllmain.cpp b/src/dllmain.cpp index 84a7f45..dc1d990 100644 --- a/src/dllmain.cpp +++ b/src/dllmain.cpp @@ -501,6 +501,7 @@ static void InitializeSubsystems() INITIALIZE(MGS2_Kirari_Sun2Fix::ApplyFix()); INITIALIZE(MGS2_RestoreDogtagViewer::Restore()); INITIALIZE(MGS3FixCameraOffset::Activate()); + INITIALIZE(g_DepthOfFieldFixes.Initialize()); #if !defined(RELEASE_BUILD) //todo category @@ -508,7 +509,6 @@ static void InitializeSubsystems() INITIALIZE(CutscenePausing::Setup()); //todo: Make ultrawide & 4:3 reposition HUD elements correctly instead of stretching them - //INITIALIZE(g_DepthOfFieldFixes.Initialize()); //INITIALIZE(MGS2ColorFilterFix::Initialize()); //INITIALIZE(GammaCorrection::Initialize()); //INITIALIZE(MGS3FixHolster::Initialize()); diff --git a/src/features/custom_resolution_and_borderless.cpp b/src/features/custom_resolution_and_borderless.cpp index 1f9a066..a1bfd53 100644 --- a/src/features/custom_resolution_and_borderless.cpp +++ b/src/features/custom_resolution_and_borderless.cpp @@ -1030,19 +1030,14 @@ namespace CustomResolutionAndBorderless spdlog::error("MGS 2: Codec Portraits: Pattern scan failed."); } - // MGS 2: Disable motion blur. - uint8_t* MGS2_MotionBlurScanResult = Memory::PatternScanSilent(baseModule, "F3 48 ?? ?? ?? ?? 48 ?? ?? ?? 48 ?? ?? ?? F3 0F ?? ?? ?? ?? ?? ?? 0F ?? ??"); - if (MGS2_MotionBlurScanResult) + if (fAspectRatio > fNativeAspect) { - spdlog::info("MGS 2: Motion Blur: Address is {:s}+{:X}", sExeName.c_str(), (uintptr_t)MGS2_MotionBlurScanResult - (uintptr_t)baseModule); - - Memory::PatchBytes((uintptr_t)MGS2_MotionBlurScanResult, "\x48\x31\xDB\x90\x90\x90", 6); - spdlog::info("MGS 2: Motion Blur: Patched instruction."); - } - else if (!MGS2_MotionBlurScanResult) - { - spdlog::error("MGS 2: Motion Blur: Pattern scan failed."); + if (uint8_t* MGS2_MotionBlurScanResult = Memory::PatternScanSilent(baseModule, "F3 48 ?? ?? ?? ?? 48 ?? ?? ?? 48 ?? ?? ?? F3 0F ?? ?? ?? ?? ?? ?? 0F ?? ??")) + { + Memory::PatchBytes((uintptr_t)MGS2_MotionBlurScanResult, "\x48\x31\xDB\x90\x90\x90", 6); + } } + } else if (eGameType & MGS3 && bHUDFix || eGameType & MG && fAspectRatio != fNativeAspect) { diff --git a/src/fixes/depth_of_field.cpp b/src/fixes/depth_of_field.cpp index 3fff32c..d57a3d6 100644 --- a/src/fixes/depth_of_field.cpp +++ b/src/fixes/depth_of_field.cpp @@ -1,167 +1,237 @@ #include "stdafx.h" -#include "depth_of_field.hpp" #include "common.hpp" +#include "features/custom_resolution_and_borderless.hpp" +#include "depth_of_field.hpp" +#include "helper.hpp" #include "logging.hpp" -#include "custom_resolution_and_borderless.hpp" +namespace +{ + constexpr int kRegUvOffset0 = 96; + constexpr int kRegUvOffset3 = 99; + constexpr int kFarFocusMaxPlaneCount = 16; + constexpr float kFarFocusBlurWeight0 = 4.0f; + constexpr float kFarFocusBlurWeight12 = 0.2f; + constexpr float kFarFocusBlurWeight34 = 0.03125f; + constexpr float kFarFocusBlurWeight56 = 0.00625f; + + SafetyHookInline SetVertexRegistersHook {}; + SafetyHookMid FarFocusBlurBeginHook {}; + SafetyHookMid FarFocusBlurEndHook {}; + thread_local bool gInsideFarFocusBlur = false; + + bool IsUltrawide() + { + if (CustomResolutionAndBorderless::iInternalResX <= 0 || CustomResolutionAndBorderless::iInternalResY <= 0) + { + return false; + } + constexpr float nativeAspect = 16.0f / 9.0f; + const float aspect = static_cast(CustomResolutionAndBorderless::iInternalResX) / static_cast(CustomResolutionAndBorderless::iInternalResY); + return aspect > nativeAspect; + } + bool LooksLikeBlurUvOffset(const float* regs) + { + if (!regs) + { + return false; + } + float maxAbs = 0.0f; + for (int i = 0; i < 4; ++i) + { + if (!std::isfinite(regs[i])) + { + return false; + } + maxAbs = std::max(maxAbs, std::abs(regs[i])); + } + return maxAbs > 0.000001f && maxAbs <= 0.08f; + } + void ScaleActiveBlurAxis(float* regs) + { + const float multiplier = g_DepthOfFieldFixes.fBlurUvMultiplier; + const bool horizontalPass = (std::abs(regs[0]) > std::abs(regs[1])) || (std::abs(regs[2]) > std::abs(regs[3])); + const bool verticalPass = (std::abs(regs[1]) > std::abs(regs[0])) || (std::abs(regs[3]) > std::abs(regs[2])); + if (horizontalPass && !verticalPass) + { + regs[0] *= multiplier; + regs[2] *= multiplier; + return; + } -void DepthOfFieldFixes::Initialize() -{ - if (!(eGameType & MGS2)) - { - return; + if (verticalPass && !horizontalPass) + { + regs[1] *= multiplier; + regs[3] *= multiplier; + return; + } + + for (int i = 0; i < 4; ++i) + { + regs[i] *= multiplier; + } } - /* - MAKE_HOOK_MID(baseModule, - "F3 44 0F 11 44 24 ?? E8 ?? ?? ?? ?? 48 8B 0D", - "MGS2: FarFocus DOF blur scale", - { - constexpr float kReferenceWidth = 512.0f; - constexpr float kReferenceHeight = 448.0f; - - const float scaleX = - static_cast(CustomResolutionAndBorderless::iInternalResX) / kReferenceWidth; - - const float scaleY = - static_cast(CustomResolutionAndBorderless::iInternalResY) / kReferenceHeight; - - const float scale = std::max(scaleX, scaleY); - - if (scale > 1.0f) - { - auto* srcRectX2 = reinterpret_cast(ctx.rsp + 0x78); - auto* srcRectY2 = reinterpret_cast(ctx.rsp + 0x7C); - - *srcRectX2 = std::max( - 1, - static_cast(std::round(static_cast(*srcRectX2) / scale))); - - *srcRectY2 = std::max( - 1, - static_cast(std::round(static_cast(*srcRectY2) / scale))); - } - }); - - MAKE_HOOK_MID(baseModule, - "C7 44 24 ?? ?? ?? ?? ?? F3 0F 58 C2 F3 0F 58 CB 48 8D 4F ?? F3 0F 11 44 24 ?? F3 0F 11 4C 24 ?? 0F 28 CF F3 44 0F 11 6C 24 ?? F3 44 0F 11 74 24 ?? F3 0F 11 54 24 ?? 0F 28 D7 E8 ?? ?? ?? ?? 48 81 C7", - "MGS2: NearFocus UV scale", - { - constexpr float kReferenceWidth = 512.0f; - constexpr float kReferenceHeight = 448.0f; - - const float scaleX = static_cast(CustomResolutionAndBorderless::iInternalResX) / kReferenceWidth; - const float scaleY = static_cast(CustomResolutionAndBorderless::iInternalResY) / kReferenceHeight; - - const float shiftU = scaleX / kReferenceWidth; - const float shiftV = scaleY / kReferenceHeight; - - if ((ctx.rbx & 1) != 0) - { - ctx.xmm3.f32[0] = shiftU; - ctx.xmm1.f32[0] = 1.0f + shiftU; - } - - if ((ctx.rbx & 2) != 0) - { - ctx.xmm2.f32[0] = shiftV; - ctx.xmm0.f32[0] = 1.0f + shiftV; - } - }); - - /* - if (!CustomResolutionAndBorderless::bOutputResolution) //remove if you fix a vanilla bug. + void __fastcall SetVertexRegisters_Hook(void* backend, int startRegister, int numVectors, const float* regs) { - return; + thread_local float scaledRegs[4]; + static bool loggedFirstHit = false; + + if (gInsideFarFocusBlur && + startRegister > kRegUvOffset0 && + startRegister <= kRegUvOffset3 && + numVectors == 1 && + LooksLikeBlurUvOffset(regs)) + { + std::copy(regs, regs + 4, scaledRegs); + ScaleActiveBlurAxis(scaledRegs); + + if (!loggedFirstHit) + { + loggedFirstHit = true; + spdlog::info("MGS 2: Depth of Field: far-focus blur UV register upload intercepted. reg={}, in=({}, {}, {}, {}), out=({}, {}, {}, {}).", + startRegister, + regs[0], regs[1], regs[2], regs[3], + scaledRegs[0], scaledRegs[1], scaledRegs[2], scaledRegs[3]); + } + + SetVertexRegistersHook.fastcall(backend, startRegister, numVectors, scaledRegs); + return; + } + + SetVertexRegistersHook.fastcall(backend, startRegister, numVectors, regs); } - MAKE_HOOK_MID(baseModule, "E8 ?? ?? ?? ?? F6 C3 ?? 74 ?? 41 0F 28 D9 41 0F 28 CA EB ?? 0F 28 DF 41 0F 28 C8 F6 C3 ?? 74 ?? 41 0F 28 D3 41 0F 28 C4 EB ?? 0F 28 D7 41 0F 28 C0 C7 44 24 ?? ?? ?? ?? ?? F3 0F 58 C2 F3 0F 58 CB 48 8D 4F ?? F3 0F 11 44 24 ?? F3 0F 11 4C 24 ?? 0F 28 CF F3 44 0F 11 6C 24 ?? F3 44 0F 11 74 24 ?? F3 0F 11 54 24 ?? 0F 28 D7 E8 ?? ?? ?? ?? 48 81 C7", "dof test near", { - spdlog::info("ctx.xmm1.f32[0] before = {:.6g}", ctx.xmm1.f32[0]); - ctx.xmm1.f32[0] *= (float)CustomResolutionAndBorderless::iInternalResY / 448.0f; - spdlog::info("ctx.xmm1.f32[0] after = {:.6g}", ctx.xmm1.f32[0]); - }) - - MAKE_HOOK_MID(baseModule, "E8 ?? ?? ?? ?? F6 C3 ?? 74 ?? 41 0F 28 D9 41 0F 28 CA EB ?? 0F 28 DF 41 0F 28 C8 F6 C3 ?? 74 ?? 41 0F 28 D3 41 0F 28 C4 EB ?? 0F 28 D7 41 0F 28 C0 C7 44 24 ?? ?? ?? ?? ?? F3 0F 58 C2 F3 0F 58 CB 48 8D 4F ?? F3 0F 11 44 24 ?? F3 0F 11 4C 24 ?? 0F 28 CF F3 44 0F 11 6C 24 ?? F3 44 0F 11 74 24 ?? F3 0F 11 54 24 ?? 0F 28 D7 E8 ?? ?? ?? ?? 48 83 C7", "dof test far", { - ctx.xmm1.f32[0] *= (float)CustomResolutionAndBorderless::iInternalResY / 448.0f; - }) - - /* uintptr_t testXres = Memory::GetRelativeOffset(Memory::PatternScan(baseModule, "F3 0F 10 35 ?? ?? ?? ?? 0F 57 D2 F3 0F 10 3D ?? ?? ?? ?? 0F 28 DE C1 E3", "MGS 2: GameVars: 1280 resolution") + 4); - Memory::PatchBytes(testXres, "\x00\x00\x70\x45", sizeof(float)); - uintptr_t testYrex = Memory::GetRelativeOffset(Memory::PatternScan(baseModule, "F3 0F 10 3D ?? ?? ?? ?? 0F 28 DE C1 E3", "MGS 2: GameVars: 720 resolution") + 4); - Memory::PatchBytes(testYrex, "\x00\x00\x07\x45", sizeof(float)); - spdlog::info("testXres = {}", *reinterpret_cast(testXres)); - spdlog::info("testYrex = {}", *reinterpret_cast(testYrex));*/ - - /* - MAKE_HOOK_MID(baseModule, "66 0F 1F 84 00 ?? ?? ?? ?? 8B 4E ?? 41 0F 28 F0 F3 0F 10 5E ?? 66 0F 6E C3 F3 0F 5C 5E ?? 8D 41 ?? 66 0F 6E C8 0F 5B C0 0F 5B C9 F3 0F 59 D8 0F 28 C7 F3 0F 5E D9 F3 0F 58 5E ?? F3 0F 5F C3 F3 0F 5D F0 3B D9 0F 8D ?? ?? ?? ?? 41 0F 2E F0 7A ?? 0F 84 ?? ?? ?? ?? 0F 2E F7 7A ?? 0F 84 ?? ?? ?? ?? BA", "dof test near", { - ctx.xmm9.f32[0] = 1.0f / static_cast(iInternalResX); - //ctx.xmm10.f32[0] = 1.0f + (1.0f / static_cast(iInternalResX)); - ctx.xmm11.f32[0] = 1.0f / static_cast(iInternalResY); - //ctx.xmm12.f32[0] = 1.0f + (1.0f / static_cast(iInternalResY)); - //ctx.xmm13.f32[0] = static_cast(iInternalResY); - //ctx.xmm14.f32[0] = static_cast(iInternalResX); - }) - - MAKE_HOOK_MID(baseModule, "66 0F 1F 84 00 ?? ?? ?? ?? 8B 4E ?? 41 0F 28 F0 F3 0F 10 5E ?? 66 0F 6E C3 F3 0F 5C 5E ?? 8D 41 ?? 66 0F 6E C8 0F 5B C0 0F 5B C9 F3 0F 59 D8 0F 28 C7 F3 0F 5E D9 F3 0F 58 5E ?? F3 0F 5F C3 F3 0F 5D F0 3B D9 0F 8D ?? ?? ?? ?? 41 0F 2E F0 7A ?? 0F 84 ?? ?? ?? ?? 0F 2E F7 7A ?? 0F 84 ?? ?? ?? ?? 48 8D 4F", "dof test far", { - ctx.xmm9.f32[0] = 1.0f / static_cast(iInternalResX); - //ctx.xmm10.f32[0] = 1.0f + (1.0f / static_cast(iInternalResX)); - ctx.xmm11.f32[0] = 1.0f / static_cast(iInternalResY); - //ctx.xmm12.f32[0] = 1.0f + (1.0f / static_cast(iInternalResY)); - //ctx.xmm13.f32[0] = static_cast(iInternalResY); - //ctx.xmm14.f32[0] = static_cast(iInternalResX); - }) - /* - MAKE_HOOK_MID(baseModule, "E8 ?? ?? ?? ?? 48 83 C7 ?? FF C3", "MGS2: Depth of Field loc 1", { - spdlog::info("dof loc 1"); - ctx.xmm14.f32[0] = 3840.0f; // 3840.0f - ctx.xmm13.f32[0] = 2160.0f; // 2160.0f - }); - MAKE_HOOK_MID(baseModule, "E8 ?? ?? ?? ?? 48 81 C7 ?? ?? ?? ?? FF C3 83 FB", "MGS2: Depth of Field loc 2", { - spdlog::info("dof loc 2"); - ctx.xmm14.f32[0] = 3840.0f; // 3840.0f - ctx.xmm13.f32[0] = 2160.0f; // 2160.0f + void InstallFarFocusBlurScopeHooks() + { + uint8_t* farFocusBlurCallSetup = Memory::PatternScan( + baseModule, + "F3 44 0F 11 44 24 ?? E8 ?? ?? ?? ?? 48 8B 0D", + "MGS 2: Depth of Field: far focus blur scope"); + + if (!farFocusBlurCallSetup) + { + return; + } + + FarFocusBlurBeginHook = safetyhook::create_mid(farFocusBlurCallSetup, [](SafetyHookContext&) { + gInsideFarFocusBlur = true; }); + LOG_HOOK(FarFocusBlurBeginHook, "MGS 2: Depth of Field: far focus blur scope begin") - MAKE_HOOK_MID(baseModule, "E8 ?? ?? ?? ?? BA ?? ?? ?? ?? 48 8B C8 E8 ?? ?? ?? ?? 48 8B C8", "MGS2: blur 1", { - //spdlog::info("blur 1"); - ctx.xmm6.f32[0] = 3840.0f; // 3840.0f - ctx.xmm7.f32[0] = 2160.0f; // 2160.0f + FarFocusBlurEndHook = safetyhook::create_mid(farFocusBlurCallSetup + 0x0C, [](SafetyHookContext&) { + gInsideFarFocusBlur = false; }); + LOG_HOOK(FarFocusBlurEndHook, "MGS 2: Depth of Field: far focus blur scope end") + } + void ForceFarFocusBlurEnabled() + { + uint8_t* blurGate = Memory::PatternScan( + baseModule, + "83 3D ?? ?? ?? ?? 00 0F 84 ?? ?? ?? ?? F3 0F 10 15 ?? ?? ?? ?? 45 0F 28 D4", + "MGS 2: Depth of Field: far focus blur enable gate"); - MAKE_HOOK_MID(baseModule, "76 ?? 89 93 ?? ?? ?? ?? EB ?? 0F 2F F0", "MGS2: MGS2_Resolution_Conversion", { - spdlog::info("MGS2_Resolution_Conversion"); - Util::DumpContext(ctx); - }); - */ - /* - MAKE_HOOK_MID(baseModule, "66 41 89 42 ?? F3 0F 2C 44 24 ?? F3 0F 59 DA 66 41 89 42 ?? F3 0F 59 CA F3 0F 2C C3 66 41 89 42 ?? F3 0F 2C C0 F3 0F 10 44 24 ?? 66 41 89 42 ?? F3 0F 2C C1 F3 0F 59 C2 66 41 89 42 ?? F3 0F 2C C0 66 41 89 42 ?? 49 8D 42 ?? C3 CC 8B 44 24 ?? 4C 8B D1 F3 0F 10 44 24 ?? 8B D0 C1 EA", "MGS3: Depth of Field loc 1", { - // spdlog::info("x axis {}", ctx.rax); - if (ctx.rax == 512)// || ctx.rax == 1280) + if (!blurGate) { - ctx.rax = iInternalResX; - spdlog::info("MGS3: Depth of Field - X axis set to {}", iInternalResX); + return; } - }); - MAKE_HOOK_MID(baseModule, "66 41 89 42 ?? F3 0F 59 CA F3 0F 2C C3 66 41 89 42 ?? F3 0F 2C C0 F3 0F 10 44 24 ?? 66 41 89 42 ?? F3 0F 2C C1 F3 0F 59 C2 66 41 89 42 ?? F3 0F 2C C0 66 41 89 42 ?? 49 8D 42 ?? C3 CC 8B 44 24 ?? 4C 8B D1 F3 0F 10 44 24 ?? 8B D0 C1 EA", "MGS3: Depth of Field loc 1", { - if (ctx.rax == 448)// || ctx.rax == 720) + uintptr_t blurEnableAddress = Memory::GetRipRelativeAddress(blurGate, 0x02, 0x07); + Memory::Write(blurEnableAddress, 1); + + spdlog::info("MGS 2: Depth of Field: far focus blur enabled at {:s}+{:X}.", + sExeName.c_str(), + blurEnableAddress - reinterpret_cast(baseModule)); + } + + void ForceFarFocusMaxPlaneCount() + { + uint8_t* maxPlaneClamp = Memory::PatternScan( + baseModule, + "39 1D ?? ?? ?? ?? 48 8B 0D ?? ?? ?? ?? 0F 4C 1D ?? ?? ?? ?? 89 9D", + "MGS 2: Depth of Field: far focus max plane count"); + + if (!maxPlaneClamp) { - ctx.rax = iInternalResY; - spdlog::info("MGS3: Depth of Field - Y axis set to {}", iInternalResY); + return; } - }); - */ + uintptr_t maxPlaneCountAddress = Memory::GetRipRelativeAddress(maxPlaneClamp, 0x02, 0x06); + Memory::Write(maxPlaneCountAddress, kFarFocusMaxPlaneCount); + Memory::Write(maxPlaneCountAddress + 0x04, kFarFocusBlurWeight0); + Memory::Write(maxPlaneCountAddress + 0x08, kFarFocusBlurWeight12); + Memory::Write(maxPlaneCountAddress + 0x0C, kFarFocusBlurWeight34); + Memory::Write(maxPlaneCountAddress + 0x10, kFarFocusBlurWeight56); + + spdlog::info("MGS 2: Depth of Field: far focus max plane count set to {} at {:s}+{:X}.", + kFarFocusMaxPlaneCount, + sExeName.c_str(), + maxPlaneCountAddress - reinterpret_cast(baseModule)); + spdlog::info("MGS 2: Depth of Field: far focus blur weights set to {}, {}, {}, {}.", + kFarFocusBlurWeight0, + kFarFocusBlurWeight12, + kFarFocusBlurWeight34, + kFarFocusBlurWeight56); + } + + void InstallBlurUvScaleHook() + { + uint8_t* blurUvRegisterUpload = Memory::PatternScan( + baseModule, + "48 8B 0D ?? ?? ?? ?? 4C 8D 4D ?? 8D 57 60 44 8D 47 01 E8 ?? ?? ?? ?? 48 8B 0D ?? ?? ?? ?? 4C 8D 4C 24 ?? 8D 57 61 44 8D 47 01 E8", + "MGS 2: Depth of Field: blur UV register upload"); + + if (!blurUvRegisterUpload) + { + return; + } + + uint8_t* setVertexRegistersCall = blurUvRegisterUpload + 0x12; + if (*setVertexRegistersCall != 0xE8) + { + spdlog::error("MGS 2: Depth of Field: expected SetVertexRegisters call was not found; blur UV scale disabled."); + return; + } + + const uintptr_t setVertexRegisters = Memory::GetRelativeOffset(setVertexRegistersCall + 1); + SetVertexRegistersHook = safetyhook::create_inline(reinterpret_cast(setVertexRegisters), reinterpret_cast(SetVertexRegisters_Hook)); + LOG_HOOK(SetVertexRegistersHook, "MGS 2: Depth of Field: blur UV register scale") + } } +void DepthOfFieldFixes::Initialize() +{ + if (!(eGameType & MGS2)) + { + return; + } + if (!bEnabled) + { + spdlog::info("MGS 2: Depth of Field: disabled by config."); + return; + } + + if (IsUltrawide()) + { + spdlog::info("MGS 2: Depth of Field: disabled for ultrawide aspect ratio."); + return; + } + fBlurUvMultiplier = std::clamp(fBlurUvMultiplier, 0.0f, 20.0f); + spdlog::info("MGS 2: Depth of Field: blur UV multiplier set to {}.", fBlurUvMultiplier); + + ForceFarFocusBlurEnabled(); + ForceFarFocusMaxPlaneCount(); + InstallFarFocusBlurScopeHooks(); + InstallBlurUvScaleHook(); +} diff --git a/src/fixes/depth_of_field.hpp b/src/fixes/depth_of_field.hpp index 165c8ae..19f83e3 100644 --- a/src/fixes/depth_of_field.hpp +++ b/src/fixes/depth_of_field.hpp @@ -3,7 +3,10 @@ class DepthOfFieldFixes final { public: - static void Initialize(); + bool bEnabled = true; + float fBlurUvMultiplier = 6.0f; + + void Initialize(); }; inline DepthOfFieldFixes g_DepthOfFieldFixes; diff --git a/src/resources/config.cpp b/src/resources/config.cpp index 73d514c..3794f17 100644 --- a/src/resources/config.cpp +++ b/src/resources/config.cpp @@ -22,6 +22,7 @@ #include "check_gamesave_folder.hpp" #include "cpu_core_limit.hpp" #include "distance_culling.hpp" +#include "depth_of_field.hpp" #include "version_checking.hpp" #include "stat_persistence.hpp" #include "keep_aiming_after_firing.hpp" @@ -605,6 +606,12 @@ void Config::Read() { ConfigHelper::getValue(ini, ConfigKeys::FixOpticalCamo_Section, ConfigKeys::FixOpticalCamo_Setting, g_OpticalCamoFix.bEnabled); LOG_CONFIG(ConfigKeys::FixOpticalCamo_Section, ConfigKeys::FixOpticalCamo_Setting, g_OpticalCamoFix.bEnabled); + + ConfigHelper::getValue(ini, ConfigKeys::FixMGS2DepthOfField_Section, ConfigKeys::FixMGS2DepthOfField_Setting, g_DepthOfFieldFixes.bEnabled); + ConfigHelper::getValue(ini, ConfigKeys::MGS2DepthOfFieldBlurUvMultiplier_Section, ConfigKeys::MGS2DepthOfFieldBlurUvMultiplier_Setting, g_DepthOfFieldFixes.fBlurUvMultiplier); + + LOG_CONFIG(ConfigKeys::FixMGS2DepthOfField_Section, ConfigKeys::FixMGS2DepthOfField_Setting, g_DepthOfFieldFixes.bEnabled); + LOG_CONFIG(ConfigKeys::MGS2DepthOfFieldBlurUvMultiplier_Section, ConfigKeys::MGS2DepthOfFieldBlurUvMultiplier_Setting, g_DepthOfFieldFixes.fBlurUvMultiplier); } if (g_VectorScalingFix.bFixRain || g_VectorScalingFix.bFixUI) diff --git a/src/resources/config_keys.hpp b/src/resources/config_keys.hpp index e3ccb19..843b1ba 100644 --- a/src/resources/config_keys.hpp +++ b/src/resources/config_keys.hpp @@ -201,6 +201,18 @@ namespace ConfigKeys constexpr const char* FixOpticalCamo_Help = ""; constexpr const char* FixOpticalCamo_Tooltip = "Improves MGS2 optical camouflage refraction and camo-failure visibility at higher resolutions."; + constexpr const char* FixMGS2DepthOfField_Section = "Bugfixes"; + constexpr const char* FixMGS2DepthOfField_Setting = "MGS2 - Fix Depth of Field"; + constexpr const char* FixMGS2DepthOfField_Help = ""; + constexpr const char* FixMGS2DepthOfField_Tooltip = "Restores stronger MGS2 far-focus depth of field blur at higher resolutions."; + + constexpr const char* MGS2DepthOfFieldBlurUvMultiplier_Section = "Bugfixes"; + constexpr const char* MGS2DepthOfFieldBlurUvMultiplier_Setting = "MGS2 - Depth of Field Blur UV Multiplier"; + constexpr const char* MGS2DepthOfFieldBlurUvMultiplier_Help = "(6.0 recommended for 1440p)"; + constexpr const char* MGS2DepthOfFieldBlurUvMultiplier_Tooltip = "Scales the UV radius used by MGS2's far-focus depth of field blur.\n" + "\n" + "Higher values increase blur radius but can expose sampling artifacts."; + constexpr const char* FixVectorUI_Section = "Bugfixes"; constexpr const char* FixVectorUI_Setting = "Fix UI Width"; constexpr const char* FixVectorUI_Help = ""; @@ -838,5 +850,3 @@ constexpr int k3rdPersonMinCameraDistance = 100; constexpr int k3rdPersonFreecamDefaultMaxCameraDistance = 4000; constexpr float k3rdPersonFreecamDefaultHorizontalSensitivity = 0.6f; constexpr float k3rdPersonFreecamDefaultVerticalSensitivity = 0.4f; - -