From 4e55d412c3fe79e62c396e209c509dff3ef3ee3c Mon Sep 17 00:00:00 2001 From: Andrew Opalach Date: Mon, 15 Jun 2026 16:45:45 -0400 Subject: Correctly display Shadow Map Size (aligned to 128) Signed-off-by: Andrew Opalach --- .gitignore | 4 ++ Plugin.cs | 150 ++++++++++++++++++++++++++++++++++++++++--------------------- 2 files changed, 104 insertions(+), 50 deletions(-) diff --git a/.gitignore b/.gitignore index da66154..db4486f 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,6 @@ +**/bin/ +**/obj/ +.vs/ +Archive/ Scripts/cmd_Decompiler.exe Scripts/d3dcompiler_47.dll diff --git a/Plugin.cs b/Plugin.cs index 3c84d50..47dce7e 100755 --- a/Plugin.cs +++ b/Plugin.cs @@ -1,16 +1,18 @@ //#define ENABLE_ASSERTS +//#define OVERSIZED_SHADOW_MAP //#define SHADER_FEATURES using System.Numerics; using System.Globalization; -using System.Runtime.InteropServices; #if ENABLE_ASSERTS using System.Diagnostics; #endif using ImGuiNET; using SharpPluginLoader.Core; +#if SHADER_FEATURES using SharpPluginLoader.Core.Rendering; +#endif //using SharpPluginLoader.Core.Resources; using SharpPluginLoader.Core.Configuration; using SharpPluginLoader.Core.Memory; @@ -111,6 +113,7 @@ namespace WorldTuningTool FLAG, BYTE, INT, + ALIGNED_INT, HEX, COLOR, FLOAT, @@ -323,6 +326,7 @@ namespace WorldTuningTool } break; case ParameterType.INT: + case ParameterType.ALIGNED_INT: case ParameterType.HEX: case ParameterType.COLOR: MemoryUtil.GetRef(lastAddr + offset) = valueInt; @@ -397,8 +401,8 @@ namespace WorldTuningTool { valueV = oValueV; valueInt = oValueInt; - bValue = false; maybeWriteCurrentValue(); + bValue = false; overrideValue = false; } } @@ -480,6 +484,7 @@ namespace WorldTuningTool break; } case ParameterType.INT: + case ParameterType.ALIGNED_INT: case ParameterType.HEX: case ParameterType.COLOR: { @@ -571,6 +576,44 @@ namespace WorldTuningTool } } + public void AdjustValue(ref Vector4 v4, ref int i1) + { + if (Type == ParameterType.SHADOW_RESOLUTION) // Hard limit. + { +#if OVERSIZED_SHADOW_MAP + i1 = Math.Clamp(i1, 1, 6); +#else + i1 = Math.Clamp(i1, 1, 5); +#endif + } + else if (!ignoreMinMax) + { + switch (Type) + { + case ParameterType.BOOL: + case ParameterType.FLAG: + case ParameterType.BYTE: + case ParameterType.INT: + case ParameterType.HEX: + i1 = Math.Clamp(i1, min, max); + break; + case ParameterType.ALIGNED_INT: + i1 = Math.Clamp((i1 + (step - 1))&~(step - 1), min, max); + break; + case ParameterType.FLOAT: + case ParameterType.PATCH_FLOAT: + case ParameterType.VECTOR3: + case ParameterType.VECTOR4: + v4 = new Vector4( + Math.Clamp(v4.X, minf, maxf), + Math.Clamp(v4.Y, minf, maxf), + Math.Clamp(v4.Z, minf, maxf), + Math.Clamp(v4.W, minf, maxf)); + break; + } + } + } + public bool DrawValue(ref Vector4 v4, ref int i1, float width, bool drawLabel) { bool valueChanged = false; @@ -601,6 +644,7 @@ namespace WorldTuningTool break; } case ParameterType.INT: + case ParameterType.ALIGNED_INT: case ParameterType.HEX: case ParameterType.SHADOW_RESOLUTION: { @@ -662,33 +706,7 @@ namespace WorldTuningTool } if (valueChanged) { - if (Type == ParameterType.SHADOW_RESOLUTION) - { - i1 = Math.Clamp(i1, 1, 5); // Hard limit. - } - else if (!ignoreMinMax) - { - switch (Type) - { - case ParameterType.BOOL: - case ParameterType.FLAG: - case ParameterType.BYTE: - case ParameterType.INT: - case ParameterType.HEX: - i1 = Math.Clamp(i1, min, max); - break; - case ParameterType.FLOAT: - case ParameterType.PATCH_FLOAT: - case ParameterType.VECTOR3: - case ParameterType.VECTOR4: - v4 = new Vector4( - Math.Clamp(v4.X, minf, maxf), - Math.Clamp(v4.Y, minf, maxf), - Math.Clamp(v4.Z, minf, maxf), - Math.Clamp(v4.W, minf, maxf)); - break; - } - } + AdjustValue(ref v4, ref i1); } return valueChanged; } @@ -704,6 +722,7 @@ namespace WorldTuningTool break; case ParameterType.BYTE: case ParameterType.INT: + case ParameterType.ALIGNED_INT: case ParameterType.SHADOW_RESOLUTION: ImGui.Text($"({name}: {i1})"); break; @@ -985,6 +1004,7 @@ namespace WorldTuningTool return BooleanToString(sValueInt != 0); case ParameterType.BYTE: case ParameterType.INT: + case ParameterType.ALIGNED_INT: case ParameterType.SHADOW_RESOLUTION: return Int32ToString(sValueInt); case ParameterType.HEX: @@ -1015,6 +1035,7 @@ namespace WorldTuningTool break; case ParameterType.BYTE: case ParameterType.INT: + case ParameterType.ALIGNED_INT: case ParameterType.SHADOW_RESOLUTION: valueInt = StringToInt32(value); break; @@ -1042,6 +1063,7 @@ namespace WorldTuningTool { Log.Warn($"Value of '{Name}' override too large."); } + Param.AdjustValue(ref valueV, ref valueInt); Save(); } } @@ -1053,7 +1075,6 @@ namespace WorldTuningTool private int sValueInt = 0; public Override() { } - public Override(Parameter param, Vector4 v4, int i1) { Param = param; @@ -1101,7 +1122,7 @@ namespace WorldTuningTool ImGui.PushItemFlag(ImGuiItemFlags.Disabled, true); } ImGui.PushItemWidth(width * 0.475f); - if (ImGui.BeginCombo("##Parameters", (Param != null) ? Param.Name : "")) + if (ImGui.BeginCombo("##Parameters", (Param != null) ? Param.Name : "", ImGuiComboFlags.HeightLarge)) { if (currentOverrides != null) { @@ -1180,9 +1201,9 @@ namespace WorldTuningTool } } (Vector4 v4, int i1) = Param.GetValue(); - bool valueDiffers = (v4, i1) != (valueV, valueInt); - // @TODO: Not sValue and valueDiffers should be seperated/more clear. - if ((valueV, valueInt) != (sValueV, sValueInt) || (isSet && valueDiffers && !Param.PendingUpdate())) + bool valueDiffers = (valueV, valueInt) != (v4, i1); + bool valueNotSaved = (valueV, valueInt) != (sValueV, sValueInt); + if ((!Param.PendingUpdate() && valueDiffers && isSet) || valueNotSaved) { ImGui.SameLine(); if (ImGui.Button("⇄")) @@ -1199,6 +1220,11 @@ namespace WorldTuningTool { ImGui.PopStyleVar(); } + if (valueNotSaved) + { + ImGui.SameLine(); + Param.DrawReferenceValue("Saved", sValueV, sValueInt); + } if (Param.PendingUpdate()) { ImGui.SameLine(); @@ -1366,7 +1392,7 @@ namespace WorldTuningTool newFrameParameter("Sunlight Is Primary", 0x1D, ParameterType.BOOL), newFrameParameter("Do Volumetric", 0x1F, ParameterType.BOOL), newFrameParameter("Shadow Cast", 0x23, ParameterType.BOOL), - newFrameParameter("Shadow Map Size", 0x30, ParameterType.INT), // Aligned to 128. + newFrameParameter("Shadow Map Size", 0x30, ParameterType.ALIGNED_INT, pMinStep(0, 128)), // 0 = 64x64 no multiplier @TODO: Verify in the code. newFrameParameter("Shadow Near Clip Distance", 0x28, ParameterType.FLOAT), newFrameParameter("Shadow Cascade Mode", 0x174, ParameterType.INT, pMinMaxStep(0, 3, 1)), newFrameParameter("Shadow Cascade 2Way Bias", 0x17C, ParameterType.FLOAT), @@ -1547,6 +1573,9 @@ namespace WorldTuningTool private static Patch shadowRes1_3x; private static Patch shadowRes1_4x; private static Patch shadowRes1_5x; +#if OVERSIZED_SHADOW_MAP + private static Patch shadowRes1_6x; +#endif private static Patch shadowRes1_1; private static Patch shadowRes1_2; private static Patch shadowRes1_3; @@ -1583,6 +1612,11 @@ namespace WorldTuningTool case 5: shadowRes1_5x.Disable(); break; +#if OVERSIZED_SHADOW_MAP + case 6: + shadowRes1_6x.Disable(); + break; +#endif } switch (multiplier) { @@ -1596,9 +1630,13 @@ namespace WorldTuningTool shadowRes1_4x.Enable(); break; case 5: - case 6: shadowRes1_5x.Enable(); break; +#if OVERSIZED_SHADOW_MAP + case 6: + shadowRes1_6x.Enable(); + break; +#endif } currentShadowResMultiplier = multiplier; setShadowQuality.Invoke(MemoryUtil.Read(sMhScene!.Instance + 0x5530) + 1); @@ -1624,6 +1662,11 @@ namespace WorldTuningTool case 5: shadowRes1_5x.Disable(); break; +#if OVERSIZED_SHADOW_MAP + case 6: + shadowRes1_6x.Disable(); + break; +#endif } shadowRes1_1.Disable(); shadowRes1_2.Disable(); @@ -1720,7 +1763,7 @@ namespace WorldTuningTool newFrameParameter("Min Roughness", 0x58C, ParameterType.FLOAT, pStep(0.0025f)), newParameter("Do Volumetric", 0x590, ParameterType.BOOL), newFlag("Shadow Cast", 0x138, ParameterType.FLAG, (1 << 23)), - newParameter("Shadow Map Size", 0x1B8, ParameterType.INT), // Aligned to 128. + newParameter("Shadow Map Size", 0x1B8, ParameterType.ALIGNED_INT, pMinStep(0, 128)), newParameter("Shadow Near Clip Distance", 0x1B4, ParameterType.FLOAT), newFrameParameter("Shadow Depth Bias", 0x57C, ParameterType.FLOAT, pStep(0.00001f)), newFrameParameter("Shadow Sloped Depth Bias", 0x580, ParameterType.FLOAT, pStep(0.00001f)), @@ -1888,19 +1931,26 @@ namespace WorldTuningTool addr = PatternScanner.FindFirst(Pattern.FromString("48 83 EC 28 F3 0F 10 0D ?? ?? ?? ?? 80 F9 04 75 2F 48 8B 0D ?? ?? ?? ?? E8 D3 8A E4 01 48 8B 0D ?? ?? ?? ?? 33 D2 E8 ?? ?? ?? ??")); Assert(addr == 0x14043FF80); - // @TODO: Allocate our own memory for this? - Assert(MemoryUtil.Read(0x142EE1A90) == 2.0f); - Assert(MemoryUtil.Read(0x142E4FE5C) == 3.0f); - Assert(MemoryUtil.Read(0x142C4A2F0) == 4.0f); - Assert(MemoryUtil.Read(0x142F0F260) == 5.0f); - shadowRes1_2x = new Patch(addr + 0x8, [0x04, 0x1B, 0xAA, 0x02]); // 2.0. - shadowRes1_3x = new Patch(addr + 0x8, [0xD0, 0xFE, 0xA0, 0x02]); // 3.0. - shadowRes1_4x = new Patch(addr + 0x8, [0x64, 0xA3, 0x80, 0x02]); // 4.0. - shadowRes1_5x = new Patch(addr + 0x8, [0xD4, 0xF2, 0xAC, 0x02]); // 5.0. + Assert(MemoryUtil.Read(0x142EE1A90) == 0x40000000); // 2.0. + Assert(MemoryUtil.Read(0x142E4FE5C) == 0x40400000); // 3.0. + Assert(MemoryUtil.Read(0x142F1FD4C) == 0x40800000); // 4.0. + Assert(MemoryUtil.Read(0x142F1FD50) == 0x40a00000); // 5.0. + Assert(MemoryUtil.Read(0x14321222C) == 0x40c00000); // 6.0. + shadowRes1_2x = new Patch(addr + 0x8, [0x04, 0x1B, 0xAA, 0x02]); + shadowRes1_3x = new Patch(addr + 0x8, [0xD0, 0xFE, 0xA0, 0x02]); + shadowRes1_4x = new Patch(addr + 0x8, [0xC0, 0xFD, 0xAD, 0x02]); + shadowRes1_5x = new Patch(addr + 0x8, [0xC4, 0xFD, 0xAD, 0x02]); +#if OVERSIZED_SHADOW_MAP + shadowRes1_6x = new Patch(addr + 0x8, [0xA0, 0x22, 0xDD, 0x02]); +#endif shadowRes1_1 = new Patch(addr + 0x65, [0x17]); // Always set "Value is not 1.0" flag. shadowRes1_2 = new Patch(addr + 0x68, [0x59]); // movss -> mulss. shadowRes1_3 = new Patch(addr + 0x77, [0x59]); // movss -> mulss. +#if OVERSIZED_SHADOW_MAP + shadowRes1_4 = new Patch(new nint(0x142288AAA) + 0x4, [0x7A, 0x97, 0xF8, 0x00]); // Limit 4.0 -> 6.0. +#else shadowRes1_4 = new Patch(new nint(0x142288AAA) + 0x4, [0x9E]); // Limit 4.0 -> 5.0. +#endif // shadowRes2/3 control the detail of the infrequently updated fallback shadows (Broad Area). addr = PatternScanner.FindFirst(Pattern.FromString("83 FA FF 74 06 89 91 1C 55 00 00 8B 91 30 55 00 00 83 FA FF 7F 06 8B 91 1C 55 00 00 85 D2 74 4B 83 EA 01 74 3B 83 EA 01 74 2B 83 EA 01 74 1B 83 FA 01 74 0B C7 81 20 55 00 00 01 00 00 00 C3 C7 81 20 55 00 00 00 10 00 00")); @@ -2585,7 +2635,7 @@ namespace WorldTuningTool if (!superseded) { ovR.Unset(); - if (globalOverrides != null && ovR.Param != null) + if (ovR.Param != null && globalOverrides != null) { setIfOverridesContainsParam(globalOverrides, ovR.Param); } @@ -2630,7 +2680,7 @@ namespace WorldTuningTool ImGui.Text($"Current Stage: {Config.StageToString(currentStage)}"); ImGui.PushItemWidth(width * 0.35f); - if (ImGui.BeginCombo("##Stage", Config.StageToString(selectedStage))) + if (ImGui.BeginCombo("##Stage", Config.StageToString(selectedStage), ImGuiComboFlags.HeightLarge)) { foreach (Stage area in Enum.GetValues(typeof(Stage))) { @@ -3071,7 +3121,7 @@ namespace WorldTuningTool { Light light = ourLights[i]; ImGui.PushID(i); - ImGui.Text($"Type: {light.Type}, Address: {light.Object:X}"); + ImGui.Text($"Type: {light.Type}, Address: 0x{light.Object:X}"); foreach (Parameter param in light.Parameters) { param.Draw(width, true); @@ -3107,7 +3157,7 @@ namespace WorldTuningTool { Light light = sceneLights[i]; ImGui.PushID(i); - ImGui.Text($"Type: {light.Type}, Address: {light.Object:X}"); + ImGui.Text($"Type: {light.Type}, Address: 0x{light.Object:X}"); foreach (Parameter param in light.Parameters) { param.Draw(width); -- cgit v1.2.3-101-g0448