From 68ab62057be28c07d836231a269847cfb7d89fcf Mon Sep 17 00:00:00 2001 From: Anairkoen Schno Date: Sun, 23 Sep 2018 13:56:38 -0500 Subject: [PATCH] Completely moved virtualization to the loader --- Doorstop | 2 +- IPA.Injector/IPA.Injector.csproj | 1 + IPA.Injector/Injector.cs | 9 +++ IPA.Injector/Virtualizer.cs | 118 +++++++++++++++++++++++++++++++ IPA/Program.cs | 2 +- 5 files changed, 130 insertions(+), 2 deletions(-) create mode 100644 IPA.Injector/Virtualizer.cs diff --git a/Doorstop b/Doorstop index c5072722..52dae348 160000 --- a/Doorstop +++ b/Doorstop @@ -1 +1 @@ -Subproject commit c5072722ea34f4c45a5f1fcabb3d9a46d1bf5eb4 +Subproject commit 52dae348cf4355cf9687a32aa90e5bcdfc102b11 diff --git a/IPA.Injector/IPA.Injector.csproj b/IPA.Injector/IPA.Injector.csproj index 2bd2e7a5..1d6aa1f2 100644 --- a/IPA.Injector/IPA.Injector.csproj +++ b/IPA.Injector/IPA.Injector.csproj @@ -56,6 +56,7 @@ + diff --git a/IPA.Injector/Injector.cs b/IPA.Injector/Injector.cs index fbe8a451..c6ae0eb3 100644 --- a/IPA.Injector/Injector.cs +++ b/IPA.Injector/Injector.cs @@ -50,6 +50,7 @@ namespace IPA.Injector { var cAsmName = Assembly.GetExecutingAssembly().GetName(); + loader.Debug("Ensuring patch on UnityEngine.CoreModule exists"); #region Insert patch into UnityEngine.CoreModule.dll var unityPath = Path.Combine(Environment.CurrentDirectory, "Beat Saber_Data", "Managed", "UnityEngine.CoreModule.dll"); @@ -110,6 +111,14 @@ namespace IPA.Injector if (modified) unityAsmDef.Write(unityPath); #endregion + + loader.Debug("Ensuring Assembly-CSharp is virtualized"); + #region Virtualize Assembly-CSharp.dll + var ascPath = Path.Combine(Environment.CurrentDirectory, "Beat Saber_Data", "Managed", "Assembly-CSharp.dll"); + + var ascModule = VirtualizedModule.Load(ascPath); + ascModule.Virtualize(cAsmName); + #endregion } private static bool bootstrapped = false; diff --git a/IPA.Injector/Virtualizer.cs b/IPA.Injector/Virtualizer.cs new file mode 100644 index 00000000..d80c65dc --- /dev/null +++ b/IPA.Injector/Virtualizer.cs @@ -0,0 +1,118 @@ +using Mono.Cecil; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Reflection; +using System.Text; + +namespace IPA.Injector +{ + internal class VirtualizedModule + { + private const string ENTRY_TYPE = "Display"; + + public FileInfo file; + public ModuleDefinition module; + + public static VirtualizedModule Load(string engineFile) + { + return new VirtualizedModule(engineFile); + } + + private VirtualizedModule(string assemblyFile) + { + file = new FileInfo(assemblyFile); + + LoadModules(); + } + + private void LoadModules() + { + module = ModuleDefinition.ReadModule(file.FullName); + } + + /// + /// + /// + /// + public void Virtualize(AssemblyName selfName) + { + bool changed = false; + bool virtualize = true; + foreach (var r in module.AssemblyReferences) + { + if (r.Name == selfName.Name) + { + virtualize = false; + if (r.Version != selfName.Version) + { + r.Version = selfName.Version; + changed = true; + } + } + } + + if (virtualize) + { + changed = true; + module.AssemblyReferences.Add(new AssemblyNameReference(selfName.Name, selfName.Version)); + + foreach (var type in module.Types) + { + VirtualizeType(type); + } + } + + if (changed) + module.Write(file.FullName); + } + + private void VirtualizeType(TypeDefinition type) + { + if(type.IsSealed) + { + // Unseal + type.IsSealed = false; + } + + if (type.IsInterface) return; + if (type.IsAbstract) return; + + // These two don't seem to work. + if (type.Name == "SceneControl" || type.Name == "ConfigUI") return; + + // Take care of sub types + foreach (var subType in type.NestedTypes) + { + VirtualizeType(subType); + } + + foreach (var method in type.Methods) + { + if (method.IsManaged + && method.IsIL + && !method.IsStatic + && !method.IsVirtual + && !method.IsAbstract + && !method.IsAddOn + && !method.IsConstructor + && !method.IsSpecialName + && !method.IsGenericInstance + && !method.HasOverrides) + { + method.IsVirtual = true; + method.IsPublic = true; + method.IsPrivate = false; + method.IsNewSlot = true; + method.IsHideBySig = true; + } + } + + foreach (var field in type.Fields) + { + if (field.IsPrivate) field.IsFamily = true; + } + } + } +} diff --git a/IPA/Program.cs b/IPA/Program.cs index 6175b757..415c0511 100644 --- a/IPA/Program.cs +++ b/IPA/Program.cs @@ -270,7 +270,7 @@ namespace IPA #region Virtualizing - if (File.Exists(context.AssemblyFile)) + if (ArgDestructive && File.Exists(context.AssemblyFile)) { var virtualizedModule = VirtualizedModule.Load(context.AssemblyFile); if (!virtualizedModule.IsVirtualized)