diff --git a/.gitignore b/.gitignore index 2ade1b38..257a3f4b 100644 --- a/.gitignore +++ b/.gitignore @@ -335,8 +335,8 @@ data/update/common/shaders/**/*.fxc source/**/*.cso !source/dxsdk/** -data/update/common/shaders/db/gta_trees_new.sps -data/update/common/shaders/dcl/gta_trees_new.dcl +data/update/common/shaders/db/gta_trees_extended.sps +data/update/common/shaders/dcl/gta_trees_extended.dcl data/update/common/shaders/db/gta_wire.sps data/update/common/shaders/preload.list data/update/pc/textures/*.wtd diff --git a/data/update/GTAIV.EFLC.FusionFix/GTAIV.EFLC.FusionFix/blista.wft b/data/update/GTAIV.EFLC.FusionFix/GTAIV.EFLC.FusionFix/blista.wft index 50b057b9..3ec36b86 100644 Binary files a/data/update/GTAIV.EFLC.FusionFix/GTAIV.EFLC.FusionFix/blista.wft and b/data/update/GTAIV.EFLC.FusionFix/GTAIV.EFLC.FusionFix/blista.wft differ diff --git a/data/update/GTAIV.EFLC.FusionFix/GTAIV.EFLC.FusionFix/burrito2.wft b/data/update/GTAIV.EFLC.FusionFix/GTAIV.EFLC.FusionFix/burrito2.wft index b528b936..7bfbea16 100644 Binary files a/data/update/GTAIV.EFLC.FusionFix/GTAIV.EFLC.FusionFix/burrito2.wft and b/data/update/GTAIV.EFLC.FusionFix/GTAIV.EFLC.FusionFix/burrito2.wft differ diff --git a/data/update/GTAIV.EFLC.FusionFix/GTAIV.EFLC.FusionFix/bus.wft b/data/update/GTAIV.EFLC.FusionFix/GTAIV.EFLC.FusionFix/bus.wft new file mode 100644 index 00000000..a09eccb5 Binary files /dev/null and b/data/update/GTAIV.EFLC.FusionFix/GTAIV.EFLC.FusionFix/bus.wft differ diff --git a/data/update/GTAIV.EFLC.FusionFix/GTAIV.EFLC.FusionFix/e109.wft b/data/update/GTAIV.EFLC.FusionFix/GTAIV.EFLC.FusionFix/e109.wft new file mode 100644 index 00000000..f24ff462 Binary files /dev/null and b/data/update/GTAIV.EFLC.FusionFix/GTAIV.EFLC.FusionFix/e109.wft differ diff --git a/data/update/GTAIV.EFLC.FusionFix/GTAIV.EFLC.FusionFix/feltzer.wft b/data/update/GTAIV.EFLC.FusionFix/GTAIV.EFLC.FusionFix/feltzer.wft new file mode 100644 index 00000000..06f7b145 Binary files /dev/null and b/data/update/GTAIV.EFLC.FusionFix/GTAIV.EFLC.FusionFix/feltzer.wft differ diff --git a/data/update/GTAIV.EFLC.FusionFix/GTAIV.EFLC.FusionFix/fxt.wft b/data/update/GTAIV.EFLC.FusionFix/GTAIV.EFLC.FusionFix/fxt.wft new file mode 100644 index 00000000..329bd3c1 Binary files /dev/null and b/data/update/GTAIV.EFLC.FusionFix/GTAIV.EFLC.FusionFix/fxt.wft differ diff --git a/data/update/GTAIV.EFLC.FusionFix/GTAIV.EFLC.FusionFix/habanero.wft b/data/update/GTAIV.EFLC.FusionFix/GTAIV.EFLC.FusionFix/habanero.wft index 2822fa1b..db087d4d 100644 Binary files a/data/update/GTAIV.EFLC.FusionFix/GTAIV.EFLC.FusionFix/habanero.wft and b/data/update/GTAIV.EFLC.FusionFix/GTAIV.EFLC.FusionFix/habanero.wft differ diff --git a/data/update/GTAIV.EFLC.FusionFix/GTAIV.EFLC.FusionFix/pmp600.wft b/data/update/GTAIV.EFLC.FusionFix/GTAIV.EFLC.FusionFix/pmp600.wft new file mode 100644 index 00000000..4afd7be0 Binary files /dev/null and b/data/update/GTAIV.EFLC.FusionFix/GTAIV.EFLC.FusionFix/pmp600.wft differ diff --git a/data/update/GTAIV.EFLC.FusionFix/GTAIV.EFLC.FusionFix/willard.wft b/data/update/GTAIV.EFLC.FusionFix/GTAIV.EFLC.FusionFix/willard.wft index a3925c17..aa9fe238 100644 Binary files a/data/update/GTAIV.EFLC.FusionFix/GTAIV.EFLC.FusionFix/willard.wft and b/data/update/GTAIV.EFLC.FusionFix/GTAIV.EFLC.FusionFix/willard.wft differ diff --git a/source/fixes.ixx b/source/fixes.ixx index 1593e1bd..a296ff7f 100644 --- a/source/fixes.ixx +++ b/source/fixes.ixx @@ -95,9 +95,6 @@ public: bool bDefaultCameraAngleInTLAD = iniReader.ReadInteger("MISC", "DefaultCameraAngleInTLAD", 0) != 0; bool bPedDeathAnimFixFromTBOGT = iniReader.ReadInteger("MISC", "PedDeathAnimFixFromTBOGT", 1) != 0; - //[SHADOWS] - bool bHighResolutionShadows = iniReader.ReadInteger("SHADOWS", "HighResolutionShadows", 0) != 0; - //fix for zoom flag in tbogt if (nAimingZoomFix) { @@ -401,70 +398,6 @@ public: injector::WriteMemory(pattern.get_first(1), &veh_glass_amber[0], true); } - // Fix Cascaded Shadow Map Resolution - { - // Clamp night shadow resolution to 512x512 @ Very High (was 1024x1024) - auto pattern = hook::pattern("83 3D ? ? ? ? ? 7E 12 B8 ? ? ? ? D3 E0 B9 ? ? ? ? 3B C1 0F 4F C1 C3"); - if (!pattern.empty()) - injector::WriteMemory(pattern.get_first(17), 0x200, true); - else - { - pattern = hook::pattern("3D ? ? ? ? 7E 05 B8 ? ? ? ? C3"); - injector::WriteMemory(pattern.count(2).get(0).get(1), 0x200, true); - injector::WriteMemory(pattern.count(2).get(0).get(8), 0x200, true); - } - - // Force water surface rendertarget resolution to always be 256x256. This matches the water tiling on the console version. - static uint32_t dwWaterQuality = 1; - pattern = find_pattern("8B 0D ? ? ? ? 53 BB ? ? ? ? D3 E3 85 D2 0F 85", "8B 0D ? ? ? ? BF ? ? ? ? D3 E7 85 C0 0F 85"); - if (!pattern.empty()) - { - injector::WriteMemory(pattern.get_first(2), &dwWaterQuality, true); - pattern = find_pattern("8B 0D ? ? ? ? F3 0F 10 0D ? ? ? ? B8 ? ? ? ? D3 E0 8B 0D", "8B 0D ? ? ? ? F3 0F 10 05 ? ? ? ? 6A 02 6A 01 BA"); - injector::WriteMemory(pattern.get_first(2), &dwWaterQuality, true); - pattern = find_pattern("8B 0D ? ? ? ? BE ? ? ? ? D3 E6 83 3D", "8B 0D ? ? ? ? F3 0F 11 0D ? ? ? ? F3 0F 10 0D"); - injector::WriteMemory(pattern.get_first(2), &dwWaterQuality, true); - } - - // Switch texture formats - // CASCADE_ATLAS - constexpr auto NewCascadeAtlasFormat = D3DFMT_R32F; - - pattern = find_pattern("C7 05 ? ? ? ? ? ? ? ? C7 05 ? ? ? ? ? ? ? ? 8B 08 50 FF 51 08 5E 59 C3 8B 44 24 04 6A 72", "C7 05 ? ? ? ? ? ? ? ? C7 05 ? ? ? ? ? ? ? ? 8B 08"); - injector::WriteMemory(pattern.get_first(6), rage::getEngineTextureFormat(NewCascadeAtlasFormat), true); - - // _DEFERRED_GBUFFER_0_ / _DEFERRED_GBUFFER_1_ / _DEFERRED_GBUFFER_2_ - pattern = find_pattern("BA ? ? ? ? 84 C0 0F 45 CA 8B 15", "40 05 00 00 00 8B 0D ? ? ? ? 8B 11 8B 52 38 8D 74 24 14 56 50 A1"); - injector::WriteMemory(pattern.get_first(1), rage::getEngineTextureFormat(D3DFMT_A8R8G8B8), true); - - if (bHighResolutionShadows) - { - auto pattern = find_pattern("8D 7D 40 8B 01 57 FF 75 10 FF 75 24 FF 75 0C FF 75 20 FF 75 18"); - if (!pattern.empty()) - { - static auto FixCascadedShadowMapResolution = safetyhook::create_mid(pattern.get_first(0), [](SafetyHookContext& regs) - { - auto& Width = *(uint32_t*)(regs.ebp + 0x14); - auto& Height = *(uint32_t*)(regs.ebp + 0x18); - auto& Levels = *(uint32_t*)(regs.ebp + 0x20); - auto& Format = *(uint32_t*)(regs.ebp + 0x24); - - if (D3DFORMAT(Format) == NewCascadeAtlasFormat && Height >= 256 && Width == Height * 4 && Levels == 1) - { - Width *= 2; - Height *= 2; - } - }); - } - } - else - { - // Remove code that doubled shadow cascade resolution. - pattern = find_pattern("03 F6 E8 ? ? ? ? 8B 0D ? ? ? ? 8D 54 24 0C", "03 F6 E8 ? ? ? ? 8B 0D ? ? ? ? 8D 44 24 0C"); - injector::MakeNOP(pattern.get_first(0), 2, true); - } - } - // P90 Selector Fix (Prev Weapon key) { auto pattern = hook::pattern("E8 ? ? ? ? 8B F0 3B 37 75 88"); diff --git a/source/framelimit.ixx b/source/framelimit.ixx index 9848f904..d59ae7b2 100644 --- a/source/framelimit.ixx +++ b/source/framelimit.ixx @@ -253,6 +253,15 @@ public: auto pattern = hook::pattern("E8 ? ? ? ? 83 C4 0C C7 04 B5 ? ? ? ? ? ? ? ? 4E"); if (!pattern.empty()) hbsub_C64CB0.fun = injector::MakeCALL(pattern.get_first(0), sub_C64CB0).get(); + + pattern = hook::pattern("83 EC 28 83 3D ? ? ? ? ? 56 8B F1"); + if (!pattern.empty()) + { + static auto InfiniteLoadingWorkaround2 = safetyhook::create_mid(pattern.get_first(), [](SafetyHookContext& regs) + { + LoadingFpsLimiter.Sync(); + }); + } }; FusionFix::onShutdownEvent() += []() diff --git a/source/shadows.ixx b/source/shadows.ixx index 83c07440..c00a5ff7 100644 --- a/source/shadows.ixx +++ b/source/shadows.ixx @@ -77,6 +77,28 @@ void __cdecl CBaseModelInfo__setFlagsHook(void* pModel, int dwFlags, int a3) return injector::cstd::call(CBaseModelInfo__setFlags, pModel, dwFlags, a3); } +int GetNightShadowQuality() +{ + switch (FusionFixSettings.Get("PREF_SHADOW_DENSITY")) + { + case 0: //MO_OFF + return 0; + break; + case 1: //MO_MED + return 256; + break; + case 2: //MO_HIGH + return 512; + break; + case 3: //MO_VHIGH + return 1024; + break; + default: + return 0; + break; + } +} + class Shadows { public: @@ -90,6 +112,7 @@ public: bExtraDynamicShadows = iniReader.ReadInteger("SHADOWS", "ExtraDynamicShadows", 1); bDynamicShadowForTrees = iniReader.ReadInteger("SHADOWS", "DynamicShadowForTrees", 1) != 0; bool bOverrideCascadeRanges = iniReader.ReadInteger("SHADOWS", "OverrideCascadeRanges", 1) != 0; + bool bHighResolutionShadows = iniReader.ReadInteger("SHADOWS", "HighResolutionShadows", 0) != 0; if (bExtraDynamicShadows || bDynamicShadowForTrees) { @@ -146,6 +169,80 @@ public: pCascadeRange2[i].CascadeRange4 = 256.0f; } } + + // Fix Cascaded Shadow Map Resolution + { + // Force water surface rendertarget resolution to always be 256x256. This matches the water tiling on the console version. + static uint32_t dwWaterQuality = 1; + auto pattern = find_pattern("8B 0D ? ? ? ? 53 BB ? ? ? ? D3 E3 85 D2 0F 85", "8B 0D ? ? ? ? BF ? ? ? ? D3 E7 85 C0 0F 85"); + if (!pattern.empty()) + { + injector::WriteMemory(pattern.get_first(2), &dwWaterQuality, true); + pattern = find_pattern("8B 0D ? ? ? ? F3 0F 10 0D ? ? ? ? B8 ? ? ? ? D3 E0 8B 0D", "8B 0D ? ? ? ? F3 0F 10 05 ? ? ? ? 6A 02 6A 01 BA"); + injector::WriteMemory(pattern.get_first(2), &dwWaterQuality, true); + pattern = find_pattern("8B 0D ? ? ? ? BE ? ? ? ? D3 E6 83 3D", "8B 0D ? ? ? ? F3 0F 11 0D ? ? ? ? F3 0F 10 0D"); + injector::WriteMemory(pattern.get_first(2), &dwWaterQuality, true); + } + + // Switch texture formats + // CASCADE_ATLAS + static constexpr auto NewCascadeAtlasFormat = D3DFMT_R32F; + + pattern = find_pattern("C7 05 ? ? ? ? ? ? ? ? C7 05 ? ? ? ? ? ? ? ? 8B 08 50 FF 51 08 5E 59 C3 8B 44 24 04 6A 72", "C7 05 ? ? ? ? ? ? ? ? C7 05 ? ? ? ? ? ? ? ? 8B 08"); + injector::WriteMemory(pattern.get_first(6), rage::getEngineTextureFormat(NewCascadeAtlasFormat), true); + + // _DEFERRED_GBUFFER_0_ / _DEFERRED_GBUFFER_1_ / _DEFERRED_GBUFFER_2_ + pattern = find_pattern("BA ? ? ? ? 84 C0 0F 45 CA 8B 15", "40 05 00 00 00 8B 0D ? ? ? ? 8B 11 8B 52 38 8D 74 24 14 56 50 A1"); + injector::WriteMemory(pattern.get_first(1), rage::getEngineTextureFormat(D3DFMT_A8R8G8B8), true); + + if (bHighResolutionShadows) + { + auto pattern = hook::pattern("8D 7D 40 8B 01 57 FF 75 10 FF 75 24 FF 75 0C FF 75 20 FF 75 18"); + if (!pattern.empty()) + { + static auto FixCascadedShadowMapResolution = safetyhook::create_mid(pattern.get_first(0), [](SafetyHookContext& regs) + { + auto& Width = *(uint32_t*)(regs.ebp + 0x14); + auto& Height = *(uint32_t*)(regs.ebp + 0x18); + auto& Levels = *(uint32_t*)(regs.ebp + 0x20); + auto& Format = *(uint32_t*)(regs.ebp + 0x24); + + if (D3DFORMAT(Format) == NewCascadeAtlasFormat && Height >= 256 && Width == Height * 4 && Levels == 1) + { + Width *= 2; + Height *= 2; + } + }); + } + else + { + pattern = hook::pattern("8D 4F 40 51 89 4C 24 24 8B 4F 10 51 8B 4F 24 51 8B 4F 0C 51 8B 4F 20 E9"); + static auto FixCascadedShadowMapResolution = safetyhook::create_mid(pattern.get_first(0), [](SafetyHookContext& regs) + { + auto& Width = *(uint32_t*)(regs.edi + 0x14); + auto& Height = *(uint32_t*)(regs.edi + 0x18); + auto& Levels = *(uint32_t*)(regs.edi + 0x20); + auto& Format = *(uint32_t*)(regs.edi + 0x24); + + if (D3DFORMAT(Format) == NewCascadeAtlasFormat && Height >= 256 && Width == Height * 4 && Levels == 1) + { + Width *= 2; + Height *= 2; + } + }); + } + } + else + { + // Remove code that doubled shadow cascade resolution. + pattern = find_pattern("03 F6 E8 ? ? ? ? 8B 0D ? ? ? ? 8D 54 24 0C", "03 F6 E8 ? ? ? ? 8B 0D ? ? ? ? 8D 44 24 0C"); + injector::MakeNOP(pattern.get_first(0), 2, true); + } + + // Fix night shadow resolution + pattern = find_pattern("8B 0D ? ? ? ? 85 C9 7E 1B", "8B 0D ? ? ? ? 33 C0 85 C9 7E 1B"); + static auto shsub_925E70 = safetyhook::create_inline(pattern.get_first(0), GetNightShadowQuality); + } }; } } Shadows; \ No newline at end of file