diff --git a/IPA.Injector/Injector.cs b/IPA.Injector/Injector.cs index 70b8ec3f..fe614f55 100644 --- a/IPA.Injector/Injector.cs +++ b/IPA.Injector/Injector.cs @@ -142,7 +142,7 @@ namespace IPA.Injector loader.Debug("Ensuring patch on UnityEngine.CoreModule exists"); -#region Insert patch into UnityEngine.CoreModule.dll + #region Insert patch into UnityEngine.CoreModule.dll { var unityPath = Path.Combine(managedPath, @@ -234,65 +234,63 @@ namespace IPA.Injector CriticalSection.ExitExecuteSection(); } -#endregion Insert patch into UnityEngine.CoreModule.dll + #endregion Insert patch into UnityEngine.CoreModule.dll - loader.Debug("Ensuring Assembly-CSharp is virtualized"); - + loader.Debug("Ensuring game assemblies are virtualized"); + + #region Virtualize game assemblies + bool isFirst = true; + foreach(var name in SelfConfig.GameAssemblies_) { - var ascPath = Path.Combine(managedPath, - "MainAssembly.dll"); // TODO: change to config option for other games + var ascPath = Path.Combine(managedPath, name); -#region Virtualize Assembly-CSharp.dll + CriticalSection.EnterExecuteSection(); + try { - CriticalSection.EnterExecuteSection(); + loader.Debug($"Virtualizing {name}"); + using var ascModule = VirtualizedModule.Load(ascPath); + ascModule.Virtualize(cAsmName, () => bkp?.Add(ascPath)); + } + catch (Exception e) + { + loader.Error($"Could not virtualize {ascPath}"); + if (SelfConfig.Debug_.ShowHandledErrorStackTraces_) + loader.Error(e); + } + if (isFirst) + { try { - var ascModule = VirtualizedModule.Load(ascPath); - ascModule.Virtualize(cAsmName, () => bkp?.Add(ascPath)); - } - catch (Exception e) - { - loader.Error($"Could not virtualize {ascPath}"); - loader.Error(e); - } - - CriticalSection.ExitExecuteSection(); - } + loader.Debug("Applying anti-yeet patch"); -#endregion Virtualize Assembly-CSharp.dll + var ascAsmDef = AssemblyDefinition.ReadAssembly(ascPath, new ReaderParameters + { + ReadWrite = false, + InMemory = true, + ReadingMode = ReadingMode.Immediate + }); + var ascModDef = ascAsmDef.MainModule; -#region Anti-Yeet + var deleter = ascModDef.GetType("IPAPluginsDirDeleter"); + deleter.Methods.Clear(); // delete all methods - CriticalSection.EnterExecuteSection(); + ascAsmDef.Write(ascPath); - try - { - loader.Debug("Applying anti-yeet patch"); - - var ascAsmDef = AssemblyDefinition.ReadAssembly(ascPath, new ReaderParameters + isFirst = false; + } + catch (Exception e) { - ReadWrite = false, - InMemory = true, - ReadingMode = ReadingMode.Immediate - }); - var ascModDef = ascAsmDef.MainModule; - - var deleter = ascModDef.GetType("IPAPluginsDirDeleter"); - deleter.Methods.Clear(); // delete all methods - - ascAsmDef.Write(ascPath); - } - catch (Exception) - { - // ignore + loader.Warn($"Could not apply anti-yeet patch to {ascPath}"); + if (SelfConfig.Debug_.ShowHandledErrorStackTraces_) + loader.Warn(e); + } } CriticalSection.ExitExecuteSection(); - -#endregion } + #endregion } private static bool bootstrapped; diff --git a/IPA.Injector/Virtualizer.cs b/IPA.Injector/Virtualizer.cs index 9afa0686..61e9aeac 100644 --- a/IPA.Injector/Virtualizer.cs +++ b/IPA.Injector/Virtualizer.cs @@ -5,7 +5,7 @@ using System.Reflection; namespace IPA.Injector { - internal class VirtualizedModule + internal class VirtualizedModule : IDisposable { private readonly FileInfo file; private ModuleDefinition module; @@ -31,15 +31,7 @@ namespace IPA.Injector ReadingMode = ReadingMode.Immediate }); } - - ~VirtualizedModule() - { - module?.Dispose(); - } - /// - /// - /// public void Virtualize(AssemblyName selfName, Action beforeChangeCallback = null) { var changed = false; @@ -121,5 +113,36 @@ namespace IPA.Injector if (field.IsPrivate) field.IsFamily = true; } } + + #region IDisposable Support + private bool disposedValue = false; // To detect redundant calls + + protected virtual void Dispose(bool disposing) + { + if (!disposedValue) + { + if (disposing) + { + module.Dispose(); + } + + disposedValue = true; + } + } + + ~VirtualizedModule() + { + // Do not change this code. Put cleanup code in Dispose(bool disposing) above. + Dispose(false); + } + + // This code added to correctly implement the disposable pattern. + public void Dispose() + { + // Do not change this code. Put cleanup code in Dispose(bool disposing) above. + Dispose(true); + GC.SuppressFinalize(this); + } + #endregion } } diff --git a/IPA.Loader/Config/SelfConfig.cs b/IPA.Loader/Config/SelfConfig.cs index dc27155b..8dbf320b 100644 --- a/IPA.Loader/Config/SelfConfig.cs +++ b/IPA.Loader/Config/SelfConfig.cs @@ -3,8 +3,10 @@ using IPA.Logging; using IPA.Utilities; using IPA.Config.Stores; using IPA.Config.Stores.Attributes; +using IPA.Config.Stores.Converters; // END: section ignore using Newtonsoft.Json; +using System.Collections.Generic; namespace IPA.Config { @@ -136,6 +138,21 @@ namespace IPA.Config public static bool YeetMods_ => (Instance?.YeetMods ?? true) && CommandLineValues.YeetMods; + // LINE: ignore + [NonNullable, UseConverter(typeof(CollectionConverter>))] + [JsonProperty(Required = Required.DisallowNull)] + public virtual HashSet GameAssemblies { get; set; } = new HashSet + { + // LINE: ignore 5 +#if BeatSaber // provide these defaults only for Beat Saber builds + "MainAssembly.dll", "HMLib.dll", "HMUI.dll", "VRUI.dll" +#else // otherwise specify Assembly-CSharp.dll + "Assembly-CSharp.dll" +#endif + }; + // LINE: ignore + public static HashSet GameAssemblies_ => Instance?.GameAssemblies ?? new HashSet { "Assembly-CSharp.dll" }; + public virtual string LastGameVersion { get; set; } = null; // LINE: ignore public static string LastGameVersion_ => Instance?.LastGameVersion; diff --git a/IPA.Loader/IPA.Loader.csproj b/IPA.Loader/IPA.Loader.csproj index a4dec5e0..49179841 100644 --- a/IPA.Loader/IPA.Loader.csproj +++ b/IPA.Loader/IPA.Loader.csproj @@ -4,6 +4,7 @@ Debug Net4 + true {5AD344F0-01A0-4CA8-92E5-9D095737744D} Library Properties @@ -44,6 +45,9 @@ v3.5 $(DefineConstants);NET3 + + $(DefineConstants);BeatSaber + $(OutputPath)IPA.Loader.xml diff --git a/appveyor.yml b/appveyor.yml index dcab5753..dd65b620 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -6,6 +6,7 @@ environment: secure: E42gl/yepETuoLSwbJZ1GmEIPK6cCJu6zkd59NA21XiICtEV6COOLW7aehi1tcVU do_deploy: true + BuildForBeatSaber: 'false' matrix: - BUILD_DOC: 'no' - BUILD_DOC: 'yes' @@ -53,6 +54,12 @@ before_build: echo $env:Configuration $env:Platform $env:BuildingInsideVisualStudio for: +- + matrix: + only: + - platform: x64-Net4 + environment: + BuildForBeatSaber: 'true' - matrix: except: