From 63c384b055cccf8942085895ea1ba1aee28d388c Mon Sep 17 00:00:00 2001 From: Anairkoen Schno Date: Sun, 23 Sep 2018 00:27:02 -0500 Subject: [PATCH] Non-destructive permanent patcher now works More tweaking needed before ready for release --- Doorstop | 2 +- IPA.Injector/ConsoleWindow.cs | 9 +++- IPA.Injector/Injector.cs | 81 +++++++++++++++++++++++++++++++++-- IPA/IPA.csproj | 9 +--- IPA/Program.cs | 2 +- 5 files changed, 88 insertions(+), 15 deletions(-) diff --git a/Doorstop b/Doorstop index fb537afc..c5072722 160000 --- a/Doorstop +++ b/Doorstop @@ -1 +1 @@ -Subproject commit fb537afc549420a5e857700d29807dba87ed2b60 +Subproject commit c5072722ea34f4c45a5f1fcabb3d9a46d1bf5eb4 diff --git a/IPA.Injector/ConsoleWindow.cs b/IPA.Injector/ConsoleWindow.cs index 96fb1365..0882f467 100644 --- a/IPA.Injector/ConsoleWindow.cs +++ b/IPA.Injector/ConsoleWindow.cs @@ -22,11 +22,16 @@ namespace IPA.Injector.Windows if (consoleAttached) { - InitializeOutStream(); - InitializeInStream(); + InitializeStreams(); } } + public static void InitializeStreams() + { + InitializeOutStream(); + InitializeInStream(); + } + private static void InitializeOutStream() { var fs = CreateFileStream("CONOUT$", GENERIC_WRITE, FILE_SHARE_WRITE, FileAccess.Write); diff --git a/IPA.Injector/Injector.cs b/IPA.Injector/Injector.cs index f920a78d..fbe8a451 100644 --- a/IPA.Injector/Injector.cs +++ b/IPA.Injector/Injector.cs @@ -1,12 +1,17 @@ using Harmony; using IPA.Loader; using IPA.Logging; +using Mono.Cecil; +using Mono.Cecil.Cil; using System; +using System.Collections.Generic; using System.IO; using System.Reflection; using System.Runtime.InteropServices; using UnityEngine; using static IPA.Logging.Logger; +using Logger = IPA.Logging.Logger; +using MethodAttributes = Mono.Cecil.MethodAttributes; namespace IPA.Injector { @@ -30,7 +35,9 @@ namespace IPA.Injector // it loads Ionic.Zip. SetupLibraryLoading(); - // This will load Harmony and UnityEngine.CoreModule + loader.Debug("Prepping bootstrapper"); + + // // This will load Mono.Cecil InstallBootstrapPatch(); } catch (Exception e) @@ -41,13 +48,79 @@ namespace IPA.Injector private static void InstallBootstrapPatch() { - var harmony = HarmonyInstance.Create("IPA_NonDestructive_Bootstrapper"); - // patch the Application static constructor to create the bootstrapper after being called - harmony.Patch(typeof(Application).TypeInitializer, null, new HarmonyMethod(typeof(Injector).GetMethod(nameof(CreateBootstrapper), BindingFlags.NonPublic | BindingFlags.Static))); + var cAsmName = Assembly.GetExecutingAssembly().GetName(); + + #region Insert patch into UnityEngine.CoreModule.dll + var unityPath = Path.Combine(Environment.CurrentDirectory, "Beat Saber_Data", "Managed", "UnityEngine.CoreModule.dll"); + + var unityAsmDef = AssemblyDefinition.ReadAssembly(unityPath); + var unityModDef = unityAsmDef.MainModule; + + bool modified = false; + foreach (var asmref in unityModDef.AssemblyReferences) + { + if (asmref.Name == cAsmName.Name) + { + if (asmref.Version != cAsmName.Version) + { + asmref.Version = cAsmName.Version; + modified = true; + } + } + } + + var application = unityModDef.GetType("UnityEngine", "Application"); + + MethodDefinition cctor = null; + foreach (var m in application.Methods) + if (m.IsRuntimeSpecialName && m.Name == ".cctor") + cctor = m; + + var cbs = unityModDef.Import(((Action)CreateBootstrapper).Method); + + if (cctor == null) + { + cctor = new MethodDefinition(".cctor", MethodAttributes.RTSpecialName | MethodAttributes.Static | MethodAttributes.SpecialName, unityModDef.TypeSystem.Void); + application.Methods.Add(cctor); + modified = true; + + var ilp = cctor.Body.GetILProcessor(); + ilp.Emit(OpCodes.Call, cbs); + ilp.Emit(OpCodes.Ret); + } + else + { + var ilp = cctor.Body.GetILProcessor(); + for (int i = 0; i < Math.Min(2, cctor.Body.Instructions.Count); i++) + { + var ins = cctor.Body.Instructions[i]; + if (i == 0 && (ins.OpCode != OpCodes.Call || ins.Operand != cbs)) + { + ilp.Replace(ins, ilp.Create(OpCodes.Call, cbs)); + modified = true; + } + if (i == 1 && ins.OpCode != OpCodes.Ret) + { + ilp.Replace(ins, ilp.Create(OpCodes.Ret)); + modified = true; + } + } + } + + if (modified) + unityAsmDef.Write(unityPath); + #endregion } + private static bool bootstrapped = false; private static void CreateBootstrapper() { + if (bootstrapped) return; + bootstrapped = true; + + // need to reinit streams singe Unity seems to redirect stdout + Windows.WinConsole.InitializeStreams(); + var bootstrapper = new GameObject("NonDestructiveBootstrapper").AddComponent(); bootstrapper.Destroyed += Bootstrapper_Destroyed; } diff --git a/IPA/IPA.csproj b/IPA/IPA.csproj index 3e7adaed..8736dcbe 100644 --- a/IPA/IPA.csproj +++ b/IPA/IPA.csproj @@ -28,8 +28,8 @@ false false true - - + + AnyCPU @@ -124,11 +124,6 @@ false - - -