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)