Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of SuperSampling DSR v0.1.3
BepInEx/plugins/ValheimSupersampling/ValheimSupersampling.dll
Decompiled 3 days agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Text; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using HarmonyLib; using Microsoft.CodeAnalysis; using UnityEngine; using UnityEngine.EventSystems; using UnityEngine.Experimental.Rendering; using UnityEngine.Rendering; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyTitle("SuperSampling (DSR)")] [assembly: AssemblyDescription("Client-side world supersampling and optional system DSR resolution selection.")] [assembly: AssemblyProduct("SuperSampling (DSR)")] [assembly: AssemblyFileVersion("0.1.3.0")] [assembly: AssemblyInformationalVersion("0.1.3")] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyVersion("0.1.3.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace ValheimSupersampling { public enum SamplingMode { Off, InGame, SystemDSR } [Serializable] public sealed class DisplayMode { public int Width; public int Height; public int Fullscreen; public uint RateNumerator; public uint RateDenominator; public double Hz { get { if (RateDenominator != 0) { return (double)RateNumerator / (double)RateDenominator; } return 0.0; } } public bool Valid { get { if (Width >= 320 && Height >= 240 && Width <= 16384 && Height <= 16384 && Fullscreen >= 0) { return Fullscreen <= 3; } return false; } } public string Key => Width + "x" + Height + "@" + RateNumerator + "/" + RateDenominator; public bool SameSizeAndMode(DisplayMode other) { if (other != null && Width == other.Width && Height == other.Height) { return Fullscreen == other.Fullscreen; } return false; } public override string ToString() { return Width + " x " + Height + " @ " + Hz.ToString("0.###", CultureInfo.InvariantCulture) + " Hz"; } } public static class RenderMath { public const long MaxPixels = 67108864L; public static bool TrySize(int width, int height, float percent, int maxDimension, out int rw, out int rh, out string error) { rw = (rh = 0); error = ""; if (width < 8 || height < 8 || float.IsNaN(percent) || float.IsInfinity(percent) || percent < 100f || percent > 300f) { error = "Use a render scale from 100% to 300%."; return false; } rw = (int)Math.Round((double)width * (double)percent / 100.0, MidpointRounding.AwayFromZero); rh = (int)Math.Round((double)height * (double)percent / 100.0, MidpointRounding.AwayFromZero); if (rw > maxDimension || rh > maxDimension || (long)rw * (long)rh > 67108864) { error = "That resolution exceeds the texture size limit. Choose a lower scale."; return false; } return true; } public static bool IsHigher(DisplayMode mode, int nativeWidth, int nativeHeight) { if (mode == null || nativeWidth < 1 || nativeHeight < 1 || !mode.Valid) { return false; } double num = Math.Abs((double)mode.Width / (double)mode.Height / ((double)nativeWidth / (double)nativeHeight) - 1.0); if (mode.Width > nativeWidth && mode.Height > nativeHeight) { return num < 0.015; } return false; } public static List<DisplayMode> HigherModes(IEnumerable<DisplayMode> modes, int width, int height) { return (from x in modes where IsHigher(x, width, height) group x by x.Key into x select x.First() into x orderby (long)x.Width * (long)x.Height, x.Hz descending select x).ToList(); } public static float UiRatio(int outputHeight, int nativeHeight, float adjustment) { if (nativeHeight <= 0 || outputHeight <= 0) { return 1f; } return (float)((double)outputHeight / (double)nativeHeight) * adjustment; } } public interface IDisplayHost { DisplayMode Capture(); void Set(DisplayMode mode); void SaveRecovery(DisplayMode original); void ClearRecovery(); } public enum SwitchPhase { Idle, Applying, Confirming, Active, Restoring, Failed } public sealed class DisplayTransaction { private readonly IDisplayHost host; private DisplayMode original; private DisplayMode rollback; private DisplayMode target; private bool previouslyActive; private bool restoreToActive; private int matchingFrames; private double deadline; public SwitchPhase Phase { get; private set; } public string Notice { get; private set; } = ""; public bool InDsr { get { if (Phase != SwitchPhase.Applying && Phase != SwitchPhase.Confirming && Phase != SwitchPhase.Active) { if (Phase == SwitchPhase.Restoring) { return restoreToActive; } return false; } return true; } } public bool Busy { get { if (Phase != SwitchPhase.Applying && Phase != SwitchPhase.Confirming) { return Phase == SwitchPhase.Restoring; } return true; } } public bool NeedsConfirmation { get { if (Phase != SwitchPhase.Applying) { return Phase == SwitchPhase.Confirming; } return true; } } public DisplayMode Original => original; public DisplayMode Target => target; public double SecondsLeft(double now) { return Math.Max(0.0, deadline - now); } public DisplayTransaction(IDisplayHost host) { this.host = host; } public void Begin(DisplayMode requested, double now) { if (requested == null || !requested.Valid) { throw new ArgumentException("Invalid display mode."); } if (Busy) { throw new InvalidOperationException("Wait for the current display change."); } if (Phase == SwitchPhase.Failed) { throw new InvalidOperationException("Display recovery has not been verified. Restart Valheim before another DSR switch."); } rollback = host.Capture(); previouslyActive = Phase == SwitchPhase.Active; if (!previouslyActive) { original = rollback; } host.SaveRecovery(original); target = requested; Phase = SwitchPhase.Applying; matchingFrames = 0; deadline = now + 20.0; Notice = "Switching resolution..."; host.Set(target); } public bool Keep() { if (Phase != SwitchPhase.Confirming || !target.SameSizeAndMode(host.Capture())) { return false; } Phase = SwitchPhase.Active; Notice = "DSR resolution confirmed."; return true; } public void Cancel(double now) { if (NeedsConfirmation) { Restore(rollback, previouslyActive, now, "Display change reverted."); } } public void Exit(double now) { if (original != null && Phase != SwitchPhase.Idle) { Restore(original, activeAfter: false, now, "Previous resolution restored."); } } public void Recover(DisplayMode saved, double now) { if (saved == null || !saved.Valid) { throw new ArgumentException("Invalid recovery resolution."); } original = saved; Restore(saved, activeAfter: false, now, "Recovered the display settings from the previous session."); } private void Restore(DisplayMode value, bool activeAfter, double now, string notice) { target = value; restoreToActive = activeAfter; Phase = SwitchPhase.Restoring; matchingFrames = 0; deadline = now + 15.0; Notice = notice; host.Set(target); } public void Tick(double now) { if (!Busy) { return; } if (Phase == SwitchPhase.Confirming) { if (now >= deadline) { Cancel(now); } return; } matchingFrames = (target.SameSizeAndMode(host.Capture()) ? (matchingFrames + 1) : 0); if (matchingFrames >= 3) { if (Phase == SwitchPhase.Applying) { Phase = SwitchPhase.Confirming; deadline = now + 15.0; Notice = "Keep this resolution?"; return; } Phase = (restoreToActive ? SwitchPhase.Active : SwitchPhase.Idle); if (!restoreToActive) { host.ClearRecovery(); original = null; } } else if (now >= deadline) { if (Phase == SwitchPhase.Applying) { Cancel(now); return; } Phase = SwitchPhase.Failed; Notice = "The game did not confirm display restoration. Recovery is saved for the next launch."; } } } internal sealed class ApiMember { public readonly string Owner; public readonly string Name; public readonly string ValueType; public readonly bool IsField; public readonly bool IsStatic; public readonly string[] Parameters; public ApiMember(string owner, string name, string valueType, bool isField = false, bool isStatic = false, params string[] parameters) { Owner = owner; Name = name; ValueType = valueType; IsField = isField; IsStatic = isStatic; Parameters = parameters; } public MemberInfo Resolve(Func<string, Type> findType) { Type type = findType(Owner) ?? throw new TypeLoadException("Missing game type: " + Owner); if (IsField) { FieldInfo field = type.GetField(Name, BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); if (field != null && field.IsStatic == IsStatic && TypeName(field.FieldType) == ValueType) { return field; } } else { MethodInfo[] array = (from m in type.GetMethods(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic) where m.Name == Name && !m.IsGenericMethod && m.IsStatic == IsStatic && TypeName(m.ReturnType) == ValueType && (from p in m.GetParameters() select TypeName(p.ParameterType)).SequenceEqual(Parameters) select m).ToArray(); if (array.Length == 1) { return array[0]; } } throw new MissingMemberException("Incompatible game API: " + this); } private static string TypeName(Type type) { if (!type.IsGenericType) { return type.FullName; } string fullName = type.GetGenericTypeDefinition().FullName; return fullName.Substring(0, fullName.IndexOf('`')) + "<" + string.Join(",", type.GetGenericArguments().Select(TypeName)) + ">"; } public override string ToString() { return (IsStatic ? "static " : "instance ") + Owner + "." + Name + (IsField ? "" : ("(" + string.Join(", ", Parameters) + ")")) + " : " + ValueType; } } internal static class GameApiContract { public const string ReferenceGame = "1.0.12"; public const string ReferenceUnity = "6000.0.75f1"; public const string RequiredBepInExPack = "5.4.2350"; public static readonly ApiMember WorldCamera = new ApiMember("UpscaledFrameBuffer", "m_camera", "UnityEngine.Camera", true, false); public static readonly ApiMember WorldTexture = new ApiMember("UpscaledFrameBuffer", "m_renderTexture", "UnityEngine.RenderTexture", true, false); public static readonly ApiMember ClearCamera = new ApiMember("UpscaledFrameBuffer", "m_clearCamera", "UnityEngine.Camera", true, false); public static readonly ApiMember IsScaled = new ApiMember("UpscaledFrameBuffer", "m_isUsingScaledRendering", "System.Boolean", true, false); public static readonly ApiMember Subscribers = new ApiMember("UpscaledFrameBuffer", "m_subscribers", "System.Collections.Generic.List<FrameBufferScaler>", true, false); public static readonly ApiMember UpdateTarget = new ApiMember("UpscaledFrameBuffer", "UpdateCameraTarget", "System.Void", false, false); public static readonly ApiMember ReleaseTexture = new ApiMember("UpscaledFrameBuffer", "ReleaseTextureIfExists", "System.Void", false, false); public static readonly ApiMember CreateClearCamera = new ApiMember("UpscaledFrameBuffer", "CreateClearCamera", "System.Void", false, false); public static readonly ApiMember DestroyBuffer = new ApiMember("UpscaledFrameBuffer", "OnDestroy", "System.Void", false, false); public static readonly ApiMember BufferCreated = new ApiMember("FrameBufferScaler", "OnBufferCreated", "System.Void", false, false, "UpscaledFrameBuffer", "UnityEngine.RenderTexture"); public static readonly ApiMember UiSize = new ApiMember("GuiScaler", "GetScreenSizeFactor", "System.Single", false, false); public static readonly ApiMember MenuVisible = new ApiMember("Menu", "IsVisible", "System.Boolean", false, true); public static readonly ApiMember TakeInput = new ApiMember("PlayerController", "TakeInput", "System.Boolean", false, false, "System.Boolean"); public static readonly ApiMember MouseCapture = new ApiMember("GameCamera", "UpdateMouseCapture", "System.Void", false, false); public static readonly ApiMember UpdateCamera = new ApiMember("GameCamera", "UpdateCamera", "System.Void", false, false, "System.Single"); public static readonly ApiMember[] All = new ApiMember[15] { WorldCamera, WorldTexture, ClearCamera, IsScaled, Subscribers, UpdateTarget, ReleaseTexture, CreateClearCamera, DestroyBuffer, BufferCreated, UiSize, MenuVisible, TakeInput, MouseCapture, UpdateCamera }; } internal sealed class NativeRenderer { private readonly Plugin plugin; private readonly Dictionary<Component, RenderTexture> owned = new Dictionary<Component, RenderTexture>(); private Type bufferType; private FieldInfo cameraField; private FieldInfo textureField; private FieldInfo clearCameraField; private FieldInfo scaledField; private FieldInfo subscribersField; private MethodInfo updateMethod; private MethodInfo destroyMethod; private MethodInfo releaseMethod; private MethodInfo createClearMethod; private MethodInfo bufferCreated; public bool Supported { get; private set; } public string Detail { get; private set; } = "Not initialized."; public int Width { get; private set; } public int Height { get; private set; } public int Count => owned.Count((KeyValuePair<Component, RenderTexture> x) => Object.op_Implicit((Object)(object)x.Key) && Object.op_Implicit((Object)(object)x.Value)); public NativeRenderer(Plugin plugin) { this.plugin = plugin; } public void Install(Harmony harmony) { //IL_022a: Unknown result type (might be due to invalid IL or missing references) //IL_022f: Unknown result type (might be due to invalid IL or missing references) //IL_023f: Expected O, but got Unknown //IL_0257: Unknown result type (might be due to invalid IL or missing references) //IL_0265: Expected O, but got Unknown try { cameraField = (FieldInfo)GameApiContract.WorldCamera.Resolve((Func<string, Type>)AccessTools.TypeByName); bufferType = cameraField.DeclaringType; if (!typeof(Component).IsAssignableFrom(bufferType)) { throw new NotSupportedException("The world framebuffer is no longer a Unity component."); } textureField = (FieldInfo)GameApiContract.WorldTexture.Resolve((Func<string, Type>)AccessTools.TypeByName); clearCameraField = (FieldInfo)GameApiContract.ClearCamera.Resolve((Func<string, Type>)AccessTools.TypeByName); scaledField = (FieldInfo)GameApiContract.IsScaled.Resolve((Func<string, Type>)AccessTools.TypeByName); subscribersField = (FieldInfo)GameApiContract.Subscribers.Resolve((Func<string, Type>)AccessTools.TypeByName); updateMethod = (MethodInfo)GameApiContract.UpdateTarget.Resolve((Func<string, Type>)AccessTools.TypeByName); releaseMethod = (MethodInfo)GameApiContract.ReleaseTexture.Resolve((Func<string, Type>)AccessTools.TypeByName); createClearMethod = (MethodInfo)GameApiContract.CreateClearCamera.Resolve((Func<string, Type>)AccessTools.TypeByName); destroyMethod = (MethodInfo)GameApiContract.DestroyBuffer.Resolve((Func<string, Type>)AccessTools.TypeByName); bufferCreated = (MethodInfo)GameApiContract.BufferCreated.Resolve((Func<string, Type>)AccessTools.TypeByName); harmony.Patch((MethodBase)updateMethod, new HarmonyMethod(typeof(NativeRenderer), "UpdatePrefix", (Type[])null) { priority = 0 }, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); harmony.Patch((MethodBase)destroyMethod, new HarmonyMethod(typeof(NativeRenderer), "DestroyPrefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); Supported = true; Detail = "Valheim world framebuffer adapter ready."; } catch (Exception ex) { Supported = false; plugin.RemoveOwnPatches(updateMethod, destroyMethod); Detail = "Unsupported framebuffer API: " + ex.GetBaseException().Message; plugin.LogWarning(Detail); } } private static bool UpdatePrefix(Component __instance) { Plugin instance = Plugin.Instance; if ((Object)(object)instance == (Object)null || instance.Renderer == null || !instance.Renderer.Supported || instance.RuntimeMode == SamplingMode.Off) { return true; } try { return instance.Renderer.Update(__instance); } catch (Exception ex) { try { instance.Renderer.Release(__instance); } catch (Exception ex2) { instance.LogWarning(ex2.GetBaseException().Message); } instance.RenderingFailed(ex.GetBaseException().Message); return true; } } private static void DestroyPrefix(Component __instance) { NativeRenderer nativeRenderer = Plugin.Instance?.Renderer; if (nativeRenderer == null || !nativeRenderer.owned.ContainsKey(__instance)) { return; } try { nativeRenderer.Release(__instance); } catch (Exception ex) { Plugin.Instance?.LogWarning("Framebuffer cleanup: " + ex.GetBaseException().Message); } } private bool Update(Component instance) { //IL_01f1: Unknown result type (might be due to invalid IL or missing references) //IL_01f6: Unknown result type (might be due to invalid IL or missing references) //IL_0201: Unknown result type (might be due to invalid IL or missing references) //IL_0209: Unknown result type (might be due to invalid IL or missing references) //IL_0210: Unknown result type (might be due to invalid IL or missing references) //IL_0218: Unknown result type (might be due to invalid IL or missing references) //IL_0220: Unknown result type (might be due to invalid IL or missing references) //IL_022e: Unknown result type (might be due to invalid IL or missing references) //IL_0235: Unknown result type (might be due to invalid IL or missing references) //IL_023c: Unknown result type (might be due to invalid IL or missing references) //IL_0249: Expected O, but got Unknown if (!Object.op_Implicit((Object)(object)instance)) { return true; } if (Screen.width < 8 || Screen.height < 8) { return false; } if ((Object)(object)GraphicsSettings.currentRenderPipeline != (Object)null) { throw new NotSupportedException("This build requires Valheim's built-in render pipeline."); } object? value = cameraField.GetValue(instance); Camera val = (Camera)((value is Camera) ? value : null); if (!Object.op_Implicit((Object)(object)val)) { val = instance.GetComponent<Camera>(); cameraField.SetValue(instance, val); } if (!Object.op_Implicit((Object)(object)val)) { return true; } if (val.stereoEnabled) { throw new NotSupportedException("Stereo/VR rendering is not supported."); } object? value2 = textureField.GetValue(instance); RenderTexture val2 = (RenderTexture)((value2 is RenderTexture) ? value2 : null); if (Object.op_Implicit((Object)(object)val.targetTexture) && (Object)(object)val.targetTexture != (Object)(object)val2) { throw new InvalidOperationException("Another renderer owns this camera. Supersampling was disabled."); } IList list = (IList)subscribersField.GetValue(instance); if (plugin.RuntimeMode == SamplingMode.SystemDSR || plugin.RenderScale <= 100f || list.Count == 0) { if (Object.op_Implicit((Object)(object)val2) || (bool)scaledField.GetValue(instance)) { ReleaseNative(instance); } owned[instance] = null; Width = Screen.width; Height = Screen.height; Detail = ((list.Count == 0 && plugin.RuntimeMode == SamplingMode.InGame) ? "Waiting for the world display surface." : "World renders at the current output resolution."); return false; } if (!RenderMath.TrySize(Screen.width, Screen.height, plugin.RenderScale, SystemInfo.maxTextureSize, out var rw, out var rh, out var error)) { throw new NotSupportedException(error); } bool mipmapped = plugin.Mipmapped; if (!owned.TryGetValue(instance, out var value3) || !Object.op_Implicit((Object)(object)value3) || (Object)(object)value3 != (Object)(object)val2 || ((Texture)value3).width != rw || ((Texture)value3).height != rh || value3.useMipMap != mipmapped || !value3.IsCreated()) { RenderTexture val3 = new RenderTexture(rw, rh, 24, (DefaultFormat)0) { name = "Valheim Supersampling World", hideFlags = (HideFlags)52, antiAliasing = 1, useMipMap = mipmapped, autoGenerateMips = mipmapped, filterMode = (FilterMode)((!mipmapped) ? 1 : 2), wrapMode = (TextureWrapMode)1, anisoLevel = 0, mipMapBias = 0f }; try { if (!val3.Create()) { throw new NotSupportedException("The GPU rejected the world render texture. Try a lower scale."); } ReleaseNative(instance); createClearMethod.Invoke(instance, null); textureField.SetValue(instance, val3); val.targetTexture = val3; scaledField.SetValue(instance, true); owned[instance] = val3; for (int i = 0; i < list.Count; i++) { object? obj = list[i]; Component val4 = (Component)((obj is Component) ? obj : null); if (val4 != null && Object.op_Implicit((Object)(object)val4)) { bufferCreated.Invoke(val4, new object[2] { instance, val3 }); } } } catch { if (Object.op_Implicit((Object)(object)val3) && (Object)(object)val3 != (Object)/*isinst with value type is only supported in some contexts*/) { val3.Release(); Object.Destroy((Object)(object)val3); } throw; } plugin.LogInfo("World " + rw + "x" + rh + " -> output/UI " + Screen.width + "x" + Screen.height + (mipmapped ? "; trilinear mipmaps." : "; bilinear.")); } Width = rw; Height = rh; Detail = "World " + rw + " x " + rh + " | UI " + Screen.width + " x " + Screen.height; return false; } private void ReleaseNative(Component instance) { if (!Object.op_Implicit((Object)(object)instance)) { return; } object? value = textureField.GetValue(instance); RenderTexture val = (RenderTexture)((value is RenderTexture) ? value : null); object? value2 = cameraField.GetValue(instance); Camera val2 = (Camera)((value2 is Camera) ? value2 : null); RenderTexture val3 = ((Object.op_Implicit((Object)(object)val2) && Object.op_Implicit((Object)(object)val2.targetTexture) && (Object)(object)val2.targetTexture != (Object)(object)val) ? val2.targetTexture : null); try { releaseMethod.Invoke(instance, null); } finally { if (Object.op_Implicit((Object)(object)val2) && Object.op_Implicit((Object)(object)val3)) { val2.targetTexture = val3; } textureField.SetValue(instance, null); if (Object.op_Implicit((Object)(object)val)) { val.Release(); Object.Destroy((Object)(object)val); } object? value3 = clearCameraField.GetValue(instance); Camera val4 = (Camera)((value3 is Camera) ? value3 : null); if (Object.op_Implicit((Object)(object)val4)) { ((Behaviour)val4).enabled = false; Object.Destroy((Object)(object)((Component)val4).gameObject); } clearCameraField.SetValue(instance, null); scaledField.SetValue(instance, false); if (owned.TryGetValue(instance, out var value4) && Object.op_Implicit((Object)(object)value4) && (Object)(object)value4 != (Object)(object)val) { value4.Release(); Object.Destroy((Object)(object)value4); } owned.Remove(instance); } } private void Release(Component instance) { ReleaseNative(instance); owned.Remove(instance); } public void ReleaseAll() { KeyValuePair<Component, RenderTexture>[] array = owned.ToArray(); int i; for (i = 0; i < array.Length; i++) { KeyValuePair<Component, RenderTexture> keyValuePair = array[i]; try { if (Object.op_Implicit((Object)(object)keyValuePair.Key)) { Release(keyValuePair.Key); } else if (Object.op_Implicit((Object)(object)keyValuePair.Value)) { keyValuePair.Value.Release(); Object.Destroy((Object)(object)keyValuePair.Value); } } catch (Exception ex) { plugin.LogWarning("Framebuffer restore: " + ex.GetBaseException().Message); } } owned.Clear(); i = (Height = 0); Width = i; Detail = (Supported ? "Supersampling off." : Detail); } } [BepInPlugin("mods.valheim.supersampling", "SuperSampling (DSR)", "0.1.3")] [BepInProcess("valheim.exe")] [BepInProcess("valheim.x86_64")] public sealed class Plugin : BaseUnityPlugin { public const string Id = "mods.valheim.supersampling"; public const string Name = "SuperSampling (DSR)"; public const string Version = "0.1.3"; internal static Plugin Instance; internal NativeRenderer Renderer; internal UiCompensation Ui; private ConfigEntry<SamplingMode> modeEntry; private ConfigEntry<float> scaleEntry; private ConfigEntry<float> uiAdjustmentEntry; private ConfigEntry<bool> keepUiEntry; private ConfigEntry<bool> mipEntry; private ConfigEntry<int> nativeWidthEntry; private ConfigEntry<int> nativeHeightEntry; private ConfigEntry<string> resolutionEntry; private ConfigEntry<KeyboardShortcut> menuKey; private ConfigEntry<KeyboardShortcut> resetKey; private Harmony harmony; private DisplayTransaction display; private UnityDisplayHost displayHost; private bool initialized; private bool shutdown; private bool renderFailed; private string notice = "Starting..."; private SamplingMode returnMode; private SamplingMode afterRestoreMode; private bool windowOpen; private CursorLockMode previousCursorLock; private bool previousCursorVisible; private readonly HashSet<EventSystem> blockedEvents = new HashSet<EventSystem>(); private SamplingMode draftMode; private string scaleText = "150"; private string nativeWidthText = "1920"; private string nativeHeightText = "1080"; private bool draftKeepUi = true; private bool draftMipmaps = true; private bool showReference; private float draftUiAdjustment = 1f; private List<DisplayMode> resolutions = new List<DisplayMode>(); private int selectedResolution = -1; private Vector2 scroll; private Vector2 resolutionScroll; private Rect windowRect; private int lastWidth; private int lastHeight; private GUIStyle textStyle; private GUIStyle titleStyle; private GUIStyle buttonStyle; private GUIStyle boxStyle; private GUIStyle toggleStyle; private GUIStyle fieldStyle; internal SamplingMode RuntimeMode { get; private set; } internal float RenderScale => scaleEntry.Value; internal bool Mipmapped => mipEntry.Value; internal int NativeWidth { get { if (nativeWidthEntry.Value <= 0) { return Screen.width; } return nativeWidthEntry.Value; } } internal int NativeHeight { get { if (nativeHeightEntry.Value <= 0) { return Screen.height; } return nativeHeightEntry.Value; } } internal float UiAdjustment => uiAdjustmentEntry.Value; internal bool CompensateUi { get { if (RuntimeMode == SamplingMode.SystemDSR && keepUiEntry.Value) { return Ui.Supported; } return false; } } internal static double Now => (double)Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency; internal void LogInfo(string text) { ((BaseUnityPlugin)this).Logger.LogInfo((object)text); } internal void LogWarning(string text) { ((BaseUnityPlugin)this).Logger.LogWarning((object)text); } private void Awake() { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Invalid comparison between Unknown and I4 //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Expected O, but got Unknown //IL_00ed: Unknown result type (might be due to invalid IL or missing references) //IL_00f7: Expected O, but got Unknown //IL_017e: Unknown result type (might be due to invalid IL or missing references) //IL_01b6: Unknown result type (might be due to invalid IL or missing references) //IL_01e7: Unknown result type (might be due to invalid IL or missing references) //IL_01f1: Expected O, but got Unknown //IL_027b: Unknown result type (might be due to invalid IL or missing references) //IL_0280: Unknown result type (might be due to invalid IL or missing references) //IL_02c5: Unknown result type (might be due to invalid IL or missing references) //IL_02ca: Unknown result type (might be due to invalid IL or missing references) //IL_02e9: Unknown result type (might be due to invalid IL or missing references) //IL_02ee: Unknown result type (might be due to invalid IL or missing references) Instance = this; if (Application.isBatchMode || (int)SystemInfo.graphicsDeviceType == 4) { ((Behaviour)this).enabled = false; return; } modeEntry = ((BaseUnityPlugin)this).Config.Bind<SamplingMode>("General", "Mode", SamplingMode.Off, "Off or InGame can resume on launch. SystemDSR is applied manually with F8 each session."); scaleEntry = ((BaseUnityPlugin)this).Config.Bind<float>("In-game", "RenderScale", 150f, new ConfigDescription("Percentage of output width AND height. 200% renders four times the pixels.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(100f, 300f), Array.Empty<object>())); mipEntry = ((BaseUnityPlugin)this).Config.Bind<bool>("In-game", "MipmappedDownsampling", true, "Trilinear mipmapped downsampling. Disable for a sharper basic bilinear filter."); keepUiEntry = ((BaseUnityPlugin)this).Config.Bind<bool>("System DSR", "KeepUiAtNativeSize", true, "Compensate Valheim's GuiScaler to preserve native apparent UI size. InGame always keeps normal UI rendering."); uiAdjustmentEntry = ((BaseUnityPlugin)this).Config.Bind<float>("System DSR", "UiSizeAdjustment", 1f, new ConfigDescription("Extra UI size adjustment. 1 = automatic compensation only.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 2f), Array.Empty<object>())); resolutionEntry = ((BaseUnityPlugin)this).Config.Bind<string>("System DSR", "Resolution", "", "Previously selected system mode; does not enable DSR in the driver."); nativeWidthEntry = ((BaseUnityPlugin)this).Config.Bind<int>("Display reference", "NativeWidth", 0, "Monitor native width. 0 captures the desktop/output size at startup; verify in F8."); nativeHeightEntry = ((BaseUnityPlugin)this).Config.Bind<int>("Display reference", "NativeHeight", 0, "Monitor native height. 0 captures the desktop/output size at startup; verify in F8."); menuKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Keys", "Settings", new KeyboardShortcut((KeyCode)289, Array.Empty<KeyCode>()), "Open settings."); resetKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Keys", "EmergencyOff", new KeyboardShortcut((KeyCode)289, (KeyCode[])(object)new KeyCode[1] { (KeyCode)306 }), "Disable supersampling and restore the pre-DSR resolution."); Renderer = new NativeRenderer(this); Ui = new UiCompensation(); harmony = new Harmony("mods.valheim.supersampling"); Renderer.Install(harmony); Ui.Install(harmony, this); InstallInputHooks(); displayHost = new UnityDisplayHost(Path.Combine(Paths.ConfigPath, "mods.valheim.supersampling.recovery.json")); display = new DisplayTransaction(displayHost); ((BaseUnityPlugin)this).Logger.LogInfo((object)("SuperSampling (DSR) 0.1.3; Unity " + Application.unityVersion + "; " + SystemInfo.graphicsDeviceName + "; " + ((object)SystemInfo.graphicsDeviceType/*cast due to .constrained prefix*/).ToString())); ((BaseUnityPlugin)this).Logger.LogInfo((object)"Reference target: Valheim 1.0.12; Unity 6000.0.75f1; BepInExPack 5.4.2350. Runtime hooks are checked separately."); ((BaseUnityPlugin)this).Logger.LogInfo((object)("Press " + ((object)menuKey.Value/*cast due to .constrained prefix*/).ToString() + " for settings; " + ((object)resetKey.Value/*cast due to .constrained prefix*/).ToString() + " for emergency Off.")); } private IEnumerator Start() { if (!((Behaviour)this).enabled || display == null) { yield break; } yield return (object)new WaitForSecondsRealtime(2f); try { DisplayMode displayMode = displayHost.ReadRecovery(); if (nativeWidthEntry.Value < 320 || nativeHeightEntry.Value < 240) { Resolution currentResolution = Screen.currentResolution; nativeWidthEntry.Value = displayMode?.Width ?? Math.Max(Screen.width, ((Resolution)(ref currentResolution)).width); nativeHeightEntry.Value = displayMode?.Height ?? Math.Max(Screen.height, ((Resolution)(ref currentResolution)).height); } initialized = true; if (displayMode != null) { modeEntry.Value = SamplingMode.Off; afterRestoreMode = SamplingMode.Off; display.Recover(displayMode, Now); notice = "Restoring display settings from the previous session."; } else if (modeEntry.Value == SamplingMode.InGame && Renderer.Supported) { RuntimeMode = SamplingMode.InGame; notice = "In-game supersampling enabled."; } else { modeEntry.Value = SamplingMode.Off; notice = "Press " + ((object)menuKey.Value/*cast due to .constrained prefix*/).ToString() + " to choose supersampling."; } ((BaseUnityPlugin)this).Config.Save(); } catch (Exception ex) { initialized = true; notice = "Startup recovery: " + ex.GetBaseException().Message; LogWarning(notice); } } private void Update() { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) if (!initialized || shutdown) { return; } KeyboardShortcut value = resetKey.Value; if (((KeyboardShortcut)(ref value)).IsDown()) { TurnOff(); SetWindow(open: false); } else { value = menuKey.Value; if (((KeyboardShortcut)(ref value)).IsDown()) { SetWindow(!windowOpen); } } if (renderFailed) { renderFailed = false; TurnOff(replaceNotice: false); SetWindow(open: true); } try { SwitchPhase phase = display.Phase; display.Tick(Now); if (phase != display.Phase) { notice = display.Notice; if (display.Phase == SwitchPhase.Idle) { RuntimeMode = afterRestoreMode; modeEntry.Value = afterRestoreMode; ((BaseUnityPlugin)this).Config.Save(); LoadDraft(); } else if (display.Phase == SwitchPhase.Restoring || display.Phase == SwitchPhase.Failed) { RuntimeMode = (display.InDsr ? SamplingMode.SystemDSR : SamplingMode.Off); Renderer.ReleaseAll(); } else if (display.Phase == SwitchPhase.Active) { RuntimeMode = SamplingMode.SystemDSR; } } } catch (Exception ex) { notice = "Display switch: " + ex.GetBaseException().Message; LogWarning(notice); TurnOff(replaceNotice: false); } if (windowOpen) { EventSystem current = EventSystem.current; if (Object.op_Implicit((Object)(object)current) && ((Behaviour)current).enabled) { ((Behaviour)current).enabled = false; blockedEvents.Add(current); } } } private void LateUpdate() { if (windowOpen) { Cursor.lockState = (CursorLockMode)0; Cursor.visible = true; } } internal void RenderingFailed(string error) { if (!renderFailed) { notice = "Supersampling disabled: " + error; LogWarning(notice); renderFailed = true; RuntimeMode = SamplingMode.Off; } } private void SetWindow(bool open) { //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) if (open == windowOpen) { return; } if (!open && display != null && display.NeedsConfirmation) { CancelDisplay(); } windowOpen = open; if (open) { previousCursorLock = Cursor.lockState; previousCursorVisible = Cursor.visible; Cursor.lockState = (CursorLockMode)0; Cursor.visible = true; LoadDraft(); return; } foreach (EventSystem blockedEvent in blockedEvents) { if (Object.op_Implicit((Object)(object)blockedEvent)) { ((Behaviour)blockedEvent).enabled = true; } } blockedEvents.Clear(); Cursor.lockState = previousCursorLock; Cursor.visible = previousCursorVisible; } private void TurnOff(bool replaceNotice = true) { RuntimeMode = SamplingMode.Off; afterRestoreMode = SamplingMode.Off; Renderer?.ReleaseAll(); if (modeEntry != null) { modeEntry.Value = SamplingMode.Off; ((BaseUnityPlugin)this).Config.Save(); } try { if (display != null && display.Phase != SwitchPhase.Idle && (display.Phase != SwitchPhase.Restoring || display.InDsr)) { display.Exit(Now); } } catch (Exception ex) { LogWarning("Restore request failed: " + ex.GetBaseException().Message); } if (replaceNotice) { notice = "Supersampling off. Restoring the previous display mode if needed."; } if (windowOpen) { LoadDraft(); } } private void CancelDisplay() { afterRestoreMode = returnMode; display.Cancel(Now); RuntimeMode = (display.InDsr ? SamplingMode.SystemDSR : SamplingMode.Off); Renderer.ReleaseAll(); notice = display.Notice; } private void ApplySettings() { //IL_01bc: Unknown result type (might be due to invalid IL or missing references) //IL_01c2: Invalid comparison between Unknown and I4 if (display.Busy) { notice = "Finish the current display change first."; return; } if (draftMode == SamplingMode.Off) { TurnOff(); return; } if (!Renderer.Supported) { notice = Renderer.Detail; return; } if (!float.TryParse(scaleText, NumberStyles.Float, CultureInfo.InvariantCulture, out var result)) { notice = "Enter a render scale such as 150 or 162.5."; return; } int width = ((display.InDsr && display.Original != null) ? display.Original.Width : Screen.width); int height = ((display.InDsr && display.Original != null) ? display.Original.Height : Screen.height); if (!RenderMath.TrySize(width, height, (draftMode == SamplingMode.InGame) ? result : 100f, SystemInfo.maxTextureSize, out var _, out var _, out var error)) { notice = error; return; } if (result < 100f || result > 300f || float.IsNaN(result) || float.IsInfinity(result)) { notice = "Use a render scale from 100% to 300%."; return; } if (!int.TryParse(nativeWidthText, out var result2) || !int.TryParse(nativeHeightText, out var result3) || result2 < 320 || result3 < 240 || result2 > 16384 || result3 > 16384) { notice = "Enter the monitor's native width and height."; return; } if (display.InDsr && (result2 != NativeWidth || result3 != NativeHeight)) { notice = "Turn DSR off before changing the native display reference."; return; } DisplayMode selected = null; if (draftMode == SamplingMode.SystemDSR) { if ((int)Application.platform != 2) { notice = "System DSR switching requires Windows. Use In-Game on this platform."; return; } if (draftKeepUi && !Ui.Supported) { notice = Ui.Detail; return; } if (selectedResolution < 0 || selectedResolution >= resolutions.Count) { notice = "No higher system resolution is selected. Enable DSR/DLDSR in the driver, then refresh."; return; } selected = resolutions[selectedResolution]; if (!RenderMath.IsHigher(selected, result2, result3)) { notice = "Choose a resolution above the native reference."; return; } if (!UnityDisplayHost.Available().Any((DisplayMode x) => x.Key == selected.Key)) { notice = "That display mode is no longer available. Refresh the list."; return; } } scaleEntry.Value = result; keepUiEntry.Value = draftKeepUi; mipEntry.Value = draftMipmaps; uiAdjustmentEntry.Value = draftUiAdjustment; nativeWidthEntry.Value = result2; nativeHeightEntry.Value = result3; Renderer.ReleaseAll(); if (draftMode == SamplingMode.SystemDSR) { if (!display.InDsr) { returnMode = RuntimeMode; } afterRestoreMode = returnMode; resolutionEntry.Value = selected.Key; modeEntry.Value = SamplingMode.Off; ((BaseUnityPlugin)this).Config.Save(); RuntimeMode = SamplingMode.SystemDSR; try { display.Begin(selected, Now); notice = display.Notice; return; } catch (Exception ex) { RuntimeMode = (display.InDsr ? SamplingMode.SystemDSR : returnMode); notice = "Could not switch display: " + ex.GetBaseException().Message; LogWarning(notice); try { if (display.NeedsConfirmation) { CancelDisplay(); } } catch (Exception ex2) { LogWarning(ex2.GetBaseException().Message); } modeEntry.Value = ((RuntimeMode != SamplingMode.SystemDSR) ? RuntimeMode : SamplingMode.Off); ((BaseUnityPlugin)this).Config.Save(); return; } } if (display.InDsr) { afterRestoreMode = SamplingMode.InGame; RuntimeMode = SamplingMode.Off; modeEntry.Value = SamplingMode.InGame; ((BaseUnityPlugin)this).Config.Save(); display.Exit(Now); notice = "Restoring the previous display resolution before enabling In-Game."; } else { RuntimeMode = SamplingMode.InGame; modeEntry.Value = SamplingMode.InGame; ((BaseUnityPlugin)this).Config.Save(); notice = "In-game supersampling enabled. HUD and menus keep their normal resolution."; } } private void InstallInputHooks() { PatchIfPresent(GameApiContract.MenuVisible, "MenuVisible", prefix: false); PatchIfPresent(GameApiContract.TakeInput, "TakeInput", prefix: false); PatchIfPresent(GameApiContract.MouseCapture, "MouseCapture", prefix: true); PatchIfPresent(GameApiContract.UpdateCamera, "CameraUpdate", prefix: true); } private void PatchIfPresent(ApiMember target, string patch, bool prefix) { //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Expected O, but got Unknown MethodInfo methodInfo = null; try { methodInfo = (MethodInfo)target.Resolve((Func<string, Type>)AccessTools.TypeByName); HarmonyMethod val = new HarmonyMethod(typeof(Plugin), patch, (Type[])null); harmony.Patch((MethodBase)methodInfo, prefix ? val : null, prefix ? null : val, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } catch (Exception ex) { RemoveOwnPatches(methodInfo); LogWarning("Optional settings input hook unavailable: " + target?.ToString() + "; " + ex.GetBaseException().Message); } } internal void RemoveOwnPatches(params MethodBase[] methods) { foreach (MethodBase methodBase in methods) { if (!(methodBase == null)) { try { harmony.Unpatch(methodBase, (HarmonyPatchType)0, "mods.valheim.supersampling"); } catch (Exception ex) { LogWarning("Patch rollback: " + ex.GetBaseException().Message); } } } } private static void MenuVisible(ref bool __result) { if ((Object)(object)Instance != (Object)null && Instance.windowOpen) { __result = true; } } private static void TakeInput(ref bool __result) { if ((Object)(object)Instance != (Object)null && Instance.windowOpen) { __result = false; } } private static bool MouseCapture() { if ((Object)(object)Instance == (Object)null || !Instance.windowOpen) { return true; } Cursor.lockState = (CursorLockMode)0; Cursor.visible = true; return false; } private static bool CameraUpdate() { if (!((Object)(object)Instance == (Object)null)) { return !Instance.windowOpen; } return true; } private void OnApplicationQuit() { Shutdown(); } private void OnDestroy() { Shutdown(); } private void OnDisable() { if (initialized && !shutdown) { Shutdown(); } } private void Shutdown() { if (shutdown) { return; } shutdown = true; SetWindow(open: false); RuntimeMode = SamplingMode.Off; Renderer?.ReleaseAll(); try { if (display?.Original != null) { displayHost.Set(display.Original); } } catch (Exception ex) { LogWarning("Display restoration is saved for next launch: " + ex.GetBaseException().Message); } Harmony obj = harmony; if (obj != null) { obj.UnpatchSelf(); } if ((Object)(object)Instance == (Object)(object)this) { Instance = null; } } private void LoadDraft() { if (scaleEntry != null) { draftMode = ((RuntimeMode != SamplingMode.Off) ? RuntimeMode : modeEntry.Value); scaleText = RenderScale.ToString("0.####", CultureInfo.InvariantCulture); draftKeepUi = keepUiEntry.Value; draftMipmaps = Mipmapped; draftUiAdjustment = UiAdjustment; nativeWidthText = NativeWidth.ToString(); nativeHeightText = NativeHeight.ToString(); RefreshModes(); } } private void RefreshModes() { int result; int width = (int.TryParse(nativeWidthText, out result) ? result : NativeWidth); int result2; int height = (int.TryParse(nativeHeightText, out result2) ? result2 : NativeHeight); try { resolutions = RenderMath.HigherModes(UnityDisplayHost.Available(), width, height); selectedResolution = resolutions.FindIndex((DisplayMode x) => x.Key == resolutionEntry.Value); if (selectedResolution < 0 && resolutions.Count > 0) { selectedResolution = 0; } } catch (Exception ex) { resolutions.Clear(); selectedResolution = -1; notice = "Display mode list unavailable: " + ex.GetBaseException().Message; } } private void OnGUI() { //IL_025d: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Invalid comparison between Unknown and I4 //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Invalid comparison between Unknown and I4 //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Expected O, but got Unknown //IL_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: Unknown result type (might be due to invalid IL or missing references) //IL_00da: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Expected O, but got Unknown //IL_00f1: Unknown result type (might be due to invalid IL or missing references) //IL_00f6: Unknown result type (might be due to invalid IL or missing references) //IL_00fe: Unknown result type (might be due to invalid IL or missing references) //IL_0105: Unknown result type (might be due to invalid IL or missing references) //IL_010f: Expected O, but got Unknown //IL_010f: Unknown result type (might be due to invalid IL or missing references) //IL_011b: Expected O, but got Unknown //IL_0126: Unknown result type (might be due to invalid IL or missing references) //IL_012b: Unknown result type (might be due to invalid IL or missing references) //IL_0134: Unknown result type (might be due to invalid IL or missing references) //IL_013e: Expected O, but got Unknown //IL_0143: Expected O, but got Unknown //IL_014e: Unknown result type (might be due to invalid IL or missing references) //IL_0153: Unknown result type (might be due to invalid IL or missing references) //IL_015b: Unknown result type (might be due to invalid IL or missing references) //IL_0167: Expected O, but got Unknown //IL_0172: Unknown result type (might be due to invalid IL or missing references) //IL_0177: Unknown result type (might be due to invalid IL or missing references) //IL_017f: Unknown result type (might be due to invalid IL or missing references) //IL_0184: Unknown result type (might be due to invalid IL or missing references) //IL_018e: Expected O, but got Unknown //IL_0193: Expected O, but got Unknown //IL_021b: Unknown result type (might be due to invalid IL or missing references) //IL_0220: Unknown result type (might be due to invalid IL or missing references) //IL_022c: Unknown result type (might be due to invalid IL or missing references) //IL_0238: Unknown result type (might be due to invalid IL or missing references) //IL_0256: Expected O, but got Unknown //IL_0251: Unknown result type (might be due to invalid IL or missing references) //IL_0256: Unknown result type (might be due to invalid IL or missing references) if (!initialized || !windowOpen || shutdown) { return; } if ((int)Event.current.type == 4 && (int)Event.current.keyCode == 27) { Event.current.Use(); SetWindow(open: false); return; } Matrix4x4 matrix = GUI.matrix; int depth = GUI.depth; try { float num = Mathf.Clamp((float)Screen.height / 1080f, 0.65f, 8f); GUI.matrix = Matrix4x4.TRS(Vector3.zero, Quaternion.identity, Vector3.one * num); GUI.depth = -10000; if (textStyle == null) { textStyle = new GUIStyle(GUI.skin.label) { fontSize = 16, wordWrap = true }; titleStyle = new GUIStyle(textStyle) { fontSize = 20, fontStyle = (FontStyle)1 }; buttonStyle = new GUIStyle(GUI.skin.button) { fontSize = 16, padding = new RectOffset(12, 12, 8, 8), wordWrap = true }; boxStyle = new GUIStyle(GUI.skin.box) { padding = new RectOffset(16, 16, 12, 12) }; toggleStyle = new GUIStyle(GUI.skin.toggle) { fontSize = 16, wordWrap = true }; fieldStyle = new GUIStyle(GUI.skin.textField) { fontSize = 16, padding = new RectOffset(8, 8, 6, 6) }; } if (lastWidth != Screen.width || lastHeight != Screen.height) { lastWidth = Screen.width; lastHeight = Screen.height; float num2 = Mathf.Min(780f, (float)Screen.width / num - 24f); float num3 = Mathf.Min(870f, (float)Screen.height / num - 24f); windowRect = new Rect(((float)Screen.width / num - num2) / 2f, ((float)Screen.height / num - num3) / 2f, num2, num3); } windowRect = GUILayout.Window(1446204243, windowRect, new WindowFunction(DrawWindow), "SuperSampling (DSR) | 0.1.3", GUI.skin.window, Array.Empty<GUILayoutOption>()); } finally { GUI.matrix = matrix; GUI.depth = depth; } } private void Label(string value) { GUILayout.Label(value, textStyle, Array.Empty<GUILayoutOption>()); } private bool Button(string value, params GUILayoutOption[] options) { return GUILayout.Button(value, buttonStyle, options); } private void DrawWindow(int id) { //IL_0149: Unknown result type (might be due to invalid IL or missing references) //IL_0153: Unknown result type (might be due to invalid IL or missing references) //IL_0158: Unknown result type (might be due to invalid IL or missing references) //IL_0884: Unknown result type (might be due to invalid IL or missing references) //IL_0889: Unknown result type (might be due to invalid IL or missing references) //IL_08a3: Unknown result type (might be due to invalid IL or missing references) //IL_08a8: Unknown result type (might be due to invalid IL or missing references) //IL_08e0: Unknown result type (might be due to invalid IL or missing references) //IL_04f4: Unknown result type (might be due to invalid IL or missing references) //IL_050c: Unknown result type (might be due to invalid IL or missing references) //IL_0511: Unknown result type (might be due to invalid IL or missing references) GUILayout.Space(8f); GUILayout.Label("Sharper world. Readable UI.", titleStyle, Array.Empty<GUILayoutOption>()); Label("Active: " + ModeLabel(RuntimeMode) + " | Output: " + displayHost.Capture()); if (display.NeedsConfirmation) { GUILayout.BeginVertical(boxStyle, Array.Empty<GUILayoutOption>()); GUILayout.Label((display.Phase == SwitchPhase.Applying) ? "Testing display mode..." : "Keep this resolution?", titleStyle, Array.Empty<GUILayoutOption>()); Label("Automatic revert in " + Math.Ceiling(display.SecondsLeft(Now)) + " seconds."); GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); GUI.enabled = display.Phase == SwitchPhase.Confirming; if (Button("Keep") && display.Keep()) { notice = display.Notice; } GUI.enabled = true; if (Button("Revert")) { CancelDisplay(); } GUILayout.EndHorizontal(); GUILayout.EndVertical(); } scroll = GUILayout.BeginScrollView(scroll, Array.Empty<GUILayoutOption>()); GUI.enabled = !display.Busy; draftMode = (SamplingMode)GUILayout.Toolbar((int)draftMode, new string[3] { "Off", "In-Game", "System DSR" }, buttonStyle, Array.Empty<GUILayoutOption>()); GUILayout.Space(12f); if (draftMode == SamplingMode.InGame) { Label("Renders the 3D world above the current output resolution, then downsamples it. HUD and menus remain at normal resolution and size."); GUILayout.Space(8f); GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); int[] array = new int[4] { 125, 150, 175, 200 }; for (int i = 0; i < array.Length; i++) { int num = array[i]; if (Button(num + "%")) { scaleText = num.ToString(); } } GUILayout.EndHorizontal(); float.TryParse(scaleText, NumberStyles.Float, CultureInfo.InvariantCulture, out var result); float num2 = ((float.IsNaN(result) || float.IsInfinity(result)) ? 100f : Mathf.Clamp(result, 100f, 300f)); float num3 = GUILayout.HorizontalSlider(num2, 100f, 300f, Array.Empty<GUILayoutOption>()); if (Math.Abs(num3 - num2) > 0.01f) { scaleText = Mathf.RoundToInt(num3).ToString(); } GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); Label("Render scale (%)"); scaleText = GUILayout.TextField(scaleText, 8, fieldStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(115f) }); GUILayout.EndHorizontal(); int num4 = ((display.InDsr && display.Original != null) ? display.Original.Width : Screen.width); int num5 = ((display.InDsr && display.Original != null) ? display.Original.Height : Screen.height); if (RenderMath.TrySize(num4, num5, result, SystemInfo.maxTextureSize, out var rw, out var rh, out var error)) { Label(rw + " x " + rh + " world -> " + num4 + " x " + num5 + " output\n" + ((double)rw * (double)rh / ((double)num4 * (double)num5)).ToString("0.####", CultureInfo.InvariantCulture) + "x as many world pixels. Higher scales use more GPU time and VRAM."); } else { Label(error); } draftMipmaps = GUILayout.Toggle(draftMipmaps, "Prefilter downsampling (smoother edges)", toggleStyle, Array.Empty<GUILayoutOption>()); Label(draftMipmaps ? "Trilinear mipmaps; 200% provides a 2 x 2 downsampling footprint." : "Basic bilinear filter; can look sharper at fractional scales."); bool enabled = GUI.enabled; GUI.enabled = false; GUILayout.Toggle(true, "Keep UI at native size (automatic in this mode)", toggleStyle, Array.Empty<GUILayoutOption>()); GUI.enabled = enabled; } else if (draftMode == SamplingMode.SystemDSR) { Label("NVIDIA DSR / DLDSR or other higher system resolutions. Enable the desired factors in your driver first. This mode uses exclusive fullscreen and restores your previous window/fullscreen mode when you leave it."); Label("Unity lists available modes, but cannot label them as DSR versus DLDSR. Driver settings choose the downsampling method."); GUILayout.Space(8f); Label("Native reference: " + nativeWidthText + " x " + nativeHeightText); if (Button("Refresh available resolutions")) { RefreshModes(); } if (resolutions.Count == 0) { Label("No higher modes found. Check the native reference below, enable DSR/DLDSR in the driver, then restart Valheim if needed."); } else { resolutionScroll = GUILayout.BeginScrollView(resolutionScroll, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(145f) }); selectedResolution = GUILayout.SelectionGrid(selectedResolution, resolutions.Select((DisplayMode x) => x.ToString()).ToArray(), 1, buttonStyle, Array.Empty<GUILayoutOption>()); GUILayout.EndScrollView(); } draftKeepUi = GUILayout.Toggle(draftKeepUi, "Keep UI at native size", toggleStyle, Array.Empty<GUILayoutOption>()); Label("DSR UI size adjustment: " + (draftUiAdjustment * 100f).ToString("0", CultureInfo.InvariantCulture) + "%"); draftUiAdjustment = Mathf.Round(GUILayout.HorizontalSlider(draftUiAdjustment, 0.5f, 2f, Array.Empty<GUILayoutOption>()) * 100f) / 100f; Label("100% preserves the normal apparent size. Raise it for larger text and HUD elements."); if (!Ui.Supported) { Label(Ui.Detail); } } else { Label("Valheim uses its own graphics settings. Turning this off also restores the resolution used before System DSR."); } GUILayout.Space(10f); showReference = GUILayout.Toggle(showReference, "Display reference and diagnostics", toggleStyle, Array.Empty<GUILayoutOption>()); if (showReference) { Label("Set these to the monitor's native resolution. The first-run estimate can be wrong if the desktop already uses DSR or you change monitors."); GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); Label("Width"); nativeWidthText = GUILayout.TextField(nativeWidthText, 5, fieldStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(100f) }); Label("Height"); nativeHeightText = GUILayout.TextField(nativeHeightText, 5, fieldStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(100f) }); GUILayout.EndHorizontal(); if (!display.InDsr && Button("Use current game output as native reference")) { nativeWidthText = Screen.width.ToString(); nativeHeightText = Screen.height.ToString(); RefreshModes(); } Label(Renderer.Detail); Label(Ui.Detail); if (Button("Write diagnostic report")) { WriteDiagnosticReport(); } if (Button("Reload configuration file")) { try { ((BaseUnityPlugin)this).Config.Reload(); LoadDraft(); notice = "Configuration loaded. Select a mode and Apply."; } catch (Exception ex) { notice = ex.Message; } } } GUI.enabled = true; GUILayout.EndScrollView(); GUILayout.Space(8f); GUILayout.BeginVertical(boxStyle, Array.Empty<GUILayoutOption>()); Label(notice); GUILayout.EndVertical(); GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); GUI.enabled = !display.Busy; if (Button("Apply")) { try { ApplySettings(); } catch (Exception ex2) { notice = "Could not apply: " + ex2.GetBaseException().Message; LogWarning(notice); } } GUI.enabled = true; if (Button("Off / restore")) { TurnOff(); } if (Button("Close")) { SetWindow(open: false); } GUILayout.EndHorizontal(); Label(((object)menuKey.Value/*cast due to .constrained prefix*/).ToString() + ": settings | " + ((object)resetKey.Value/*cast due to .constrained prefix*/).ToString() + ": emergency Off"); GUI.DragWindow(new Rect(0f, 0f, ((Rect)(ref windowRect)).width, 24f)); } private static string ModeLabel(SamplingMode mode) { return mode switch { SamplingMode.SystemDSR => "System DSR", SamplingMode.InGame => "In-Game", _ => "Off", }; } private void WriteDiagnosticReport() { //IL_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_010f: Unknown result type (might be due to invalid IL or missing references) //IL_0114: Unknown result type (might be due to invalid IL or missing references) //IL_0134: Unknown result type (might be due to invalid IL or missing references) //IL_0139: Unknown result type (might be due to invalid IL or missing references) //IL_033f: Unknown result type (might be due to invalid IL or missing references) //IL_0344: Unknown result type (might be due to invalid IL or missing references) try { StringBuilder stringBuilder = new StringBuilder(); stringBuilder.AppendLine("SuperSampling (DSR) 0.1.3"); stringBuilder.AppendLine("UTC: " + DateTime.UtcNow.ToString("O")); stringBuilder.AppendLine("Unity: " + Application.unityVersion + "; game: " + Application.version); stringBuilder.AppendLine("Reference target: Valheim 1.0.12; Unity 6000.0.75f1; BepInExPack 5.4.2350"); stringBuilder.AppendLine("Loaded BepInEx: " + typeof(BaseUnityPlugin).Assembly.GetName().Version); stringBuilder.AppendLine("GPU: " + SystemInfo.graphicsDeviceName + "; VRAM MiB: " + SystemInfo.graphicsMemorySize); stringBuilder.AppendLine("Graphics: " + ((object)SystemInfo.graphicsDeviceType/*cast due to .constrained prefix*/).ToString() + "; " + SystemInfo.graphicsDeviceVersion); stringBuilder.AppendLine("Output: " + displayHost.Capture()?.ToString() + "; fullscreen: " + ((object)Screen.fullScreenMode/*cast due to .constrained prefix*/).ToString()); stringBuilder.AppendLine("Desktop/current display: " + ((object)Screen.currentResolution/*cast due to .constrained prefix*/).ToString()); stringBuilder.AppendLine("Native reference: " + NativeWidth + "x" + NativeHeight); stringBuilder.AppendLine("Mode: " + RuntimeMode.ToString() + "; scale: " + RenderScale + "; mipmaps: " + Mipmapped + "; UI compensation: " + CompensateUi); stringBuilder.AppendLine("Framebuffer: " + Renderer.Detail + "; owned targets: " + Renderer.Count); stringBuilder.AppendLine("UI: " + Ui.Detail); stringBuilder.AppendLine("Display transaction: " + display.Phase.ToString() + "; " + notice); stringBuilder.AppendLine("Cameras:"); Camera[] allCameras = Camera.allCameras; foreach (Camera val in allCameras) { stringBuilder.AppendLine(" " + ((Object)val).name + "; depth " + val.depth + "; target " + (Object.op_Implicit((Object)(object)val.targetTexture) ? (((Texture)val.targetTexture).width + "x" + ((Texture)val.targetTexture).height) : "screen") + "; " + ((object)val.actualRenderingPath/*cast due to .constrained prefix*/).ToString()); } stringBuilder.AppendLine("BepInEx plugins:"); foreach (PluginInfo value in Chainloader.PluginInfos.Values) { stringBuilder.AppendLine(" " + value.Metadata.GUID + " " + value.Metadata.Version); } stringBuilder.AppendLine("Available higher display modes:"); foreach (DisplayMode item in RenderMath.HigherModes(UnityDisplayHost.Available(), NativeWidth, NativeHeight)) { stringBuilder.AppendLine(" " + item?.ToString() + " [" + item.Key + "]"); } File.WriteAllText(Path.Combine(Paths.ConfigPath, "mods.valheim.supersampling.diagnostics.txt"), stringBuilder.ToString()); notice = "Saved BepInEx/config/mods.valheim.supersampling.diagnostics.txt"; } catch (Exception ex) { notice = "Could not save diagnostics: " + ex.Message; } } } internal sealed class UnityDisplayHost : IDisplayHost { private readonly string path; public UnityDisplayHost(string path) { this.path = path; } public DisplayMode Capture() { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Expected I4, but got Unknown //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) Resolution currentResolution = Screen.currentResolution; RefreshRate refreshRateRatio = ((Resolution)(ref currentResolution)).refreshRateRatio; return new DisplayMode { Width = Screen.width, Height = Screen.height, Fullscreen = (int)Screen.fullScreenMode, RateNumerator = refreshRateRatio.numerator, RateDenominator = refreshRateRatio.denominator }; } public void Set(DisplayMode mode) { //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) if (mode == null || !mode.Valid) { throw new ArgumentException("Invalid resolution."); } Screen.SetResolution(mode.Width, mode.Height, (FullScreenMode)mode.Fullscreen, new RefreshRate { numerator = mode.RateNumerator, denominator = ((mode.RateDenominator == 0) ? 1u : mode.RateDenominator) }); } public void SaveRecovery(DisplayMode original) { if (original == null || !original.Valid) { throw new ArgumentException("Current display settings could not be captured."); } Directory.CreateDirectory(Path.GetDirectoryName(path)); File.WriteAllText(path, JsonUtility.ToJson((object)original, true)); } public void ClearRecovery() { if (File.Exists(path)) { File.Delete(path); } } public DisplayMode ReadRecovery() { if (!File.Exists(path)) { return null; } DisplayMode displayMode = JsonUtility.FromJson<DisplayMode>(File.ReadAllText(path)); if (displayMode == null || !displayMode.Valid) { throw new InvalidDataException("Saved display recovery data is invalid; automatic switching was skipped."); } return displayMode; } public static List<DisplayMode> Available() { return Screen.resolutions.Select((Resolution x) => new DisplayMode { Width = ((Resolution)(ref x)).width, Height = ((Resolution)(ref x)).height, Fullscreen = 0, RateNumerator = ((Resolution)(ref x)).refreshRateRatio.numerator, RateDenominator = ((Resolution)(ref x)).refreshRateRatio.denominator }).ToList(); } } internal sealed class UiCompensation { public bool Supported { get; private set; } public string Detail { get; private set; } = "UI adapter unavailable."; private static bool Active { get { if ((Object)(object)Plugin.Instance != (Object)null) { return Plugin.Instance.CompensateUi; } return false; } } public void Install(Harmony harmony, Plugin plugin) { //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Expected O, but got Unknown //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Expected O, but got Unknown MethodInfo methodInfo = null; try { methodInfo = (MethodInfo)GameApiContract.UiSize.Resolve((Func<string, Type>)AccessTools.TypeByName); MethodInfo methodInfo2 = methodInfo; HarmonyMethod val = new HarmonyMethod(typeof(UiCompensation), "UseReferenceSize", (Type[])null); harmony.Patch((MethodBase)methodInfo2, (HarmonyMethod)null, new HarmonyMethod(typeof(UiCompensation), "ScaleResult", (Type[])null), val, (HarmonyMethod)null, (HarmonyMethod)null); Supported = true; Detail = "Native UI size compensation ready."; } catch (Exception ex) { Supported = false; plugin.RemoveOwnPatches(methodInfo); Detail = "UI compensation unavailable: " + ex.GetBaseException().Message; plugin.LogWarning(Detail); } } public static int ReferenceWidth() { if (!Active) { return Screen.width; } return Plugin.Instance.NativeWidth; } public static int ReferenceHeight() { if (!Active) { return Screen.height; } return Plugin.Instance.NativeHeight; } private static IEnumerable<CodeInstruction> UseReferenceSize(IEnumerable<CodeInstruction> instructions) { List<CodeInstruction> list = instructions.ToList(); MethodInfo methodInfo = AccessTools.PropertyGetter(typeof(Screen), "width"); MethodInfo methodInfo2 = AccessTools.PropertyGetter(typeof(Screen), "height"); int num = 0; int num2 = 0; foreach (CodeInstruction item in list) { if (CodeInstructionExtensions.Calls(item, methodInfo)) { item.opcode = OpCodes.Call; item.operand = AccessTools.Method(typeof(UiCompensation), "ReferenceWidth", (Type[])null, (Type[])null); num++; } else if (CodeInstructionExtensions.Calls(item, methodInfo2)) { item.opcode = OpCodes.Call; item.operand = AccessTools.Method(typeof(UiCompensation), "ReferenceHeight", (Type[])null, (Type[])null); num2++; } } if (num == 0 || num2 == 0) { throw new NotSupportedException("The game's UI sizing method has changed."); } return list; } private static void ScaleResult(ref float __result) { if (Active) { __result *= RenderMath.UiRatio(Screen.height, Plugin.Instance.NativeHeight, Plugin.Instance.UiAdjustment); } } } }