using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Security; using System.Security.Permissions; using AssetRipper.Primitives; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Core.Logging.Interpolation; using BepInEx.Logging; using BepInEx.Preloader.Core; using BepInEx.Preloader.Core.Logging; using BepInEx.Preloader.Core.Patching; using BepInEx.Preloader.RuntimeFixes; using BepInEx.Unity.Common; using BepInEx.Unity.Mono.Preloader.RuntimeFixes; using BepInEx.Unity.Mono.Preloader.Utils; using HarmonyLib; using Microsoft.CodeAnalysis; using Mono.Cecil; using Mono.Cecil.Cil; using MonoMod.RuntimeDetour; using MonoMod.RuntimeDetour.Platforms; using MonoMod.Utils; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyCompany("BepInEx")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyCopyright("Copyright © 2022 BepInEx Team")] [assembly: AssemblyDescription("BepInEx preloader module for UnityMono games")] [assembly: AssemblyFileVersion("6.0.0.0")] [assembly: AssemblyInformationalVersion("6.0.0-be.697+53625800b86f6c68751445248260edf0b27a71c2")] [assembly: AssemblyProduct("BepInEx.Unity.Mono.Preloader")] [assembly: AssemblyTitle("BepInEx.Unity.Mono.Preloader")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("6.0.0.0")] [module: UnverifiableCode] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NativeIntegerAttribute : Attribute { public readonly bool[] TransformFlags; public NativeIntegerAttribute() { TransformFlags = new bool[1] { true }; } public NativeIntegerAttribute(bool[] P_0) { TransformFlags = P_0; } } } namespace BepInEx.Unity.Mono.Preloader { [PatcherPluginInfo("io.bepinex.entrypointpatcher", "BepInEx Entrypoint", "1.0")] internal class EntrypointPatcher : BasePatcher { private static readonly ConfigEntry ConfigEntrypointAssembly = ConfigFile.CoreConfig.Bind("Preloader.Entrypoint", "Assembly", DefaultEntrypointAssembly, "The local filename of the assembly to target."); private static readonly ConfigEntry ConfigEntrypointType = ConfigFile.CoreConfig.Bind("Preloader.Entrypoint", "Type", DefaultEntrypointType, "The name of the type in the entrypoint assembly to search for the entrypoint method."); private static readonly ConfigEntry ConfigEntrypointMethod = ConfigFile.CoreConfig.Bind("Preloader.Entrypoint", "Method", ".cctor", "The name of the method in the specified entrypoint assembly and type to hook and load Chainloader from."); private static string DefaultEntrypointAssembly { get { //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) UnityVersion version = UnityInfo.Version; if (!((UnityVersion)(ref version)).LessThan((ushort)2017)) { return "UnityEngine.CoreModule.dll"; } return "UnityEngine.dll"; } } private static string DefaultEntrypointType { get { //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) UnityVersion version = UnityInfo.Version; if (!((UnityVersion)(ref version)).LessThan((ushort)5)) { return "Application"; } return "MonoBehaviour"; } } private bool HasLoaded { get; set; } [TargetAssembly("_all")] public bool PatchEntrypoint(ref AssemblyDefinition assembly, string filename) { //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Expected O, but got Unknown //IL_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_0136: Unknown result type (might be due to invalid IL or missing references) //IL_013b: Unknown result type (might be due to invalid IL or missing references) //IL_0147: Expected O, but got Unknown //IL_0217: Unknown result type (might be due to invalid IL or missing references) //IL_021e: Expected O, but got Unknown //IL_0238: Unknown result type (might be due to invalid IL or missing references) //IL_02bb: Unknown result type (might be due to invalid IL or missing references) //IL_02d0: Unknown result type (might be due to invalid IL or missing references) if (HasLoaded || filename != ConfigEntrypointAssembly.Value) { return false; } if (((IEnumerable)assembly.MainModule.AssemblyReferences).Any((AssemblyNameReference x) => x.Name.Contains("BepInEx"))) { throw new Exception("BepInEx has been detected to be patched! Please unpatch before using a patchless variant!"); } string entrypointType = ConfigEntrypointType.Value; string entrypointMethod = ConfigEntrypointMethod.Value; ManualLogSource log = ((BasePatcher)this).Log; LogLevel val = (LogLevel)32; LogLevel val2 = val; bool flag = default(bool); BepInExLogInterpolatedStringHandler val3 = new BepInExLogInterpolatedStringHandler(27, 2, val, ref flag); if (flag) { val3.AppendLiteral("Hooking chainloader into "); val3.AppendFormatted(entrypointType); val3.AppendLiteral("::"); val3.AppendFormatted(entrypointMethod); } log.Log(val2, val3); bool flag2 = Utility.IsNullOrWhiteSpace(entrypointMethod) || entrypointMethod == ".cctor"; TypeDefinition val4 = ((IEnumerable)assembly.MainModule.Types).FirstOrDefault((Func)((TypeDefinition x) => ((MemberReference)x).Name == entrypointType)); if (val4 == null) { throw new Exception("The entrypoint type is invalid! Please check your config/BepInEx.cfg file"); } string text = Path.Combine(Paths.BepInExAssemblyDirectory, "BepInEx.Unity.Mono.dll"); ReaderParameters val5 = new ReaderParameters { AssemblyResolver = (IAssemblyResolver)(object)TypeLoader.CecilResolver }; AssemblyDefinition val6 = AssemblyDefinition.ReadAssembly(text, val5); try { MethodDefinition val7 = Utility.EnumerateAllMethods(((IEnumerable)val6.MainModule.Types).First((TypeDefinition x) => ((MemberReference)x).Name == "UnityChainloader")).First((MethodDefinition x) => ((MemberReference)x).Name == "StaticStart"); MethodReference val8 = assembly.MainModule.ImportReference((MethodReference)(object)val7); List list = new List(); if (flag2) { MethodDefinition val9 = ((IEnumerable)val4.Methods).FirstOrDefault((Func)((MethodDefinition m) => m.IsConstructor && m.IsStatic)); if (val9 == null) { val9 = new MethodDefinition(".cctor", (MethodAttributes)6289, assembly.MainModule.ImportReference(typeof(void))); val4.Methods.Add(val9); ILProcessor iLProcessor = val9.Body.GetILProcessor(); iLProcessor.Append(iLProcessor.Create(OpCodes.Ret)); } list.Add(val9); } else { list.AddRange(((IEnumerable)val4.Methods).Where((MethodDefinition x) => ((MemberReference)x).Name == entrypointMethod)); } if (!list.Any()) { throw new Exception("The entrypoint method is invalid! Please check your config.ini"); } foreach (MethodDefinition item in list) { ILProcessor iLProcessor2 = item.Body.GetILProcessor(); Instruction val10 = ((IEnumerable)iLProcessor2.Body.Instructions).First(); iLProcessor2.InsertBefore(val10, iLProcessor2.Create(OpCodes.Ldnull)); iLProcessor2.InsertBefore(val10, iLProcessor2.Create(OpCodes.Call, val8)); } } finally { ((IDisposable)val6)?.Dispose(); } HasLoaded = true; return true; } public override void Finalizer() { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Expected O, but got Unknown //IL_004a: Unknown result type (might be due to invalid IL or missing references) if (!HasLoaded) { ManualLogSource log = ((BasePatcher)this).Log; LogLevel val = (LogLevel)1; LogLevel val2 = val; bool flag = default(bool); BepInExLogInterpolatedStringHandler val3 = new BepInExLogInterpolatedStringHandler(128, 1, val, ref flag); if (flag) { val3.AppendLiteral("Failed to patch BepInEx chainloader into assembly '"); val3.AppendFormatted(ConfigEntrypointAssembly.Value); val3.AppendLiteral("', either due to error or not being able to find it. Is it spelled correctly?"); } log.Log(val2, val3); } } } internal static class UnityPreloader { internal static readonly ConfigEntry ConfigApplyRuntimePatches = ConfigFile.CoreConfig.Bind("Preloader", "ApplyRuntimePatches", true, "Enables or disables runtime patches.\nThis should always be true, unless you cannot start the game due to a Harmony related issue (such as running .NET Standard runtime) or you know what you're doing."); private static PreloaderConsoleListener PreloaderLog { get; set; } private static ManualLogSource Log => PreloaderLogger.Log; public static void Run() { //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Expected O, but got Unknown //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Expected O, but got Unknown //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Expected O, but got Unknown //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_00d5: Expected O, but got Unknown //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: Unknown result type (might be due to invalid IL or missing references) //IL_00fd: 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_00ff: Unknown result type (might be due to invalid IL or missing references) //IL_0103: Unknown result type (might be due to invalid IL or missing references) //IL_0106: Unknown result type (might be due to invalid IL or missing references) //IL_010c: Expected O, but got Unknown //IL_0126: 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_0135: Unknown result type (might be due to invalid IL or missing references) //IL_0136: Unknown result type (might be due to invalid IL or missing references) //IL_013a: Unknown result type (might be due to invalid IL or missing references) //IL_013d: Unknown result type (might be due to invalid IL or missing references) //IL_0143: Expected O, but got Unknown //IL_015d: Unknown result type (might be due to invalid IL or missing references) //IL_016b: Unknown result type (might be due to invalid IL or missing references) //IL_016c: Unknown result type (might be due to invalid IL or missing references) //IL_016d: Unknown result type (might be due to invalid IL or missing references) //IL_0171: Unknown result type (might be due to invalid IL or missing references) //IL_0174: Unknown result type (might be due to invalid IL or missing references) //IL_017a: Expected O, but got Unknown //IL_0194: Unknown result type (might be due to invalid IL or missing references) //IL_01a2: Unknown result type (might be due to invalid IL or missing references) //IL_01a3: Unknown result type (might be due to invalid IL or missing references) //IL_01a4: Unknown result type (might be due to invalid IL or missing references) //IL_01a8: Unknown result type (might be due to invalid IL or missing references) //IL_01ab: Unknown result type (might be due to invalid IL or missing references) //IL_01b1: Expected O, but got Unknown //IL_01cb: Unknown result type (might be due to invalid IL or missing references) //IL_0237: Unknown result type (might be due to invalid IL or missing references) //IL_023e: Expected O, but got Unknown //IL_01db: Unknown result type (might be due to invalid IL or missing references) //IL_01dc: Unknown result type (might be due to invalid IL or missing references) //IL_01dd: Unknown result type (might be due to invalid IL or missing references) //IL_01e1: Unknown result type (might be due to invalid IL or missing references) //IL_01e4: Unknown result type (might be due to invalid IL or missing references) //IL_01ea: Expected O, but got Unknown //IL_025d: Unknown result type (might be due to invalid IL or missing references) //IL_025e: Unknown result type (might be due to invalid IL or missing references) //IL_025f: Unknown result type (might be due to invalid IL or missing references) //IL_0263: Unknown result type (might be due to invalid IL or missing references) //IL_0266: Unknown result type (might be due to invalid IL or missing references) //IL_026c: Expected O, but got Unknown //IL_0205: Unknown result type (might be due to invalid IL or missing references) //IL_02c3: Unknown result type (might be due to invalid IL or missing references) //IL_02dd: Unknown result type (might be due to invalid IL or missing references) //IL_02de: Unknown result type (might be due to invalid IL or missing references) //IL_02df: Unknown result type (might be due to invalid IL or missing references) //IL_02e3: Unknown result type (might be due to invalid IL or missing references) //IL_02e6: Unknown result type (might be due to invalid IL or missing references) //IL_02ec: Expected O, but got Unknown //IL_0312: Unknown result type (might be due to invalid IL or missing references) try { HarmonyBackendFix.Initialize(); UnityInfo.Initialize(Paths.ExecutablePath, Paths.GameDataPath); ConsoleManager.Initialize(false, false); AllocateConsole(); Exception ex = default(Exception); Utility.TryDo((Action)delegate { if (ConfigApplyRuntimePatches.Value) { UnityPatches.Apply(); } }, ref ex); Logger.Sources.Add((ILogSource)new HarmonyLogSource()); Logger.Sources.Add(TraceLogSource.CreateSource()); PreloaderLog = new PreloaderConsoleListener(); Logger.Listeners.Add((ILogListener)(object)PreloaderLog); ChainloaderLogHelper.PrintLogInfo(Log); ManualLogSource log = Log; LogLevel val = (LogLevel)16; LogLevel val2 = val; bool flag = default(bool); BepInExLogInterpolatedStringHandler val3 = new BepInExLogInterpolatedStringHandler(20, 1, val, ref flag); if (flag) { val3.AppendLiteral("Running under Unity "); val3.AppendFormatted(UnityInfo.Version); } log.Log(val2, val3); ManualLogSource log2 = Log; val2 = (LogLevel)16; val = val2; val3 = new BepInExLogInterpolatedStringHandler(21, 1, val2, ref flag); if (flag) { val3.AppendLiteral("CLR runtime version: "); val3.AppendFormatted(Environment.Version); } log2.Log(val, val3); ManualLogSource log3 = Log; val = (LogLevel)16; val2 = val; val3 = new BepInExLogInterpolatedStringHandler(14, 1, val, ref flag); if (flag) { val3.AppendLiteral("Supports SRE: "); val3.AppendFormatted(Utility.CLRSupportsDynamicAssemblies); } log3.Log(val2, val3); ManualLogSource log4 = Log; val2 = (LogLevel)32; val = val2; val3 = new BepInExLogInterpolatedStringHandler(22, 1, val2, ref flag); if (flag) { val3.AppendLiteral("Game executable path: "); val3.AppendFormatted(Paths.ExecutablePath); } log4.Log(val, val3); ManualLogSource log5 = Log; val = (LogLevel)32; val2 = val; val3 = new BepInExLogInterpolatedStringHandler(25, 1, val, ref flag); if (flag) { val3.AppendLiteral("Unity Managed directory: "); val3.AppendFormatted(Paths.ManagedPath); } log5.Log(val2, val3); ManualLogSource log6 = Log; val2 = (LogLevel)32; val = val2; val3 = new BepInExLogInterpolatedStringHandler(19, 1, val2, ref flag); if (flag) { val3.AppendLiteral("BepInEx root path: "); val3.AppendFormatted(Paths.BepInExRootPath); } log6.Log(val, val3); if (ex != null) { ManualLogSource log7 = Log; val = (LogLevel)4; val2 = val; val3 = new BepInExLogInterpolatedStringHandler(90, 1, val, ref flag); if (flag) { val3.AppendLiteral("Failed to apply runtime patches for Mono. See more info in the output log. Error message: "); val3.AppendFormatted(ex.Message); } log7.Log(val2, val3); } Log.Log((LogLevel)8, (object)"Preloader started"); TypeLoader.SearchDirectories.UnionWith(Paths.DllSearchPaths); AssemblyPatcher val4 = new AssemblyPatcher((Func)MonoAssemblyHelper.LoadFromMemory); try { val4.AddPatchersFromDirectory(Paths.BepInExAssemblyDirectory); val4.AddPatchersFromDirectory(Paths.PatcherPluginPath); ManualLogSource log8 = Log; val2 = (LogLevel)16; val = val2; val3 = new BepInExLogInterpolatedStringHandler(22, 2, val2, ref flag); if (flag) { val3.AppendFormatted(val4.PatcherContext.PatcherPlugins.Count); val3.AppendLiteral(" patcher plugin"); val3.AppendFormatted((val4.PatcherContext.PatcherPlugins.Count == 1) ? "" : "s"); val3.AppendLiteral(" loaded"); } log8.Log(val, val3); val4.LoadAssemblyDirectories(Paths.DllSearchPaths); ManualLogSource log9 = Log; val = (LogLevel)16; val2 = val; val3 = new BepInExLogInterpolatedStringHandler(22, 1, val, ref flag); if (flag) { val3.AppendFormatted(val4.PatcherContext.AvailableAssemblies.Count); val3.AppendLiteral(" assemblies discovered"); } log9.Log(val2, val3); val4.PatchAndLoad(); } finally { ((IDisposable)val4)?.Dispose(); } Log.Log((LogLevel)8, (object)"Preloader finished"); Logger.Listeners.Remove((ILogListener)(object)PreloaderLog); PreloaderLog.Dispose(); } catch (Exception ex2) { try { Log.Log((LogLevel)1, (object)"Could not run preloader!"); Log.Log((LogLevel)1, (object)ex2); if (!ConsoleManager.ConsoleActive) { AllocateConsole(); Console.Write(PreloaderLog); } } catch { } string text = string.Empty; try { text = string.Join("\r\n", PreloaderConsoleListener.LogEvents.Select((LogEventArgs x) => ((object)x).ToString()).ToArray()); text += "\r\n"; PreloaderConsoleListener preloaderLog = PreloaderLog; if (preloaderLog != null) { preloaderLog.Dispose(); } PreloaderLog = null; } catch { } File.WriteAllText(Path.Combine(Paths.GameRootPath, $"preloader_{DateTime.Now:yyyyMMdd_HHmmss_fff}.log"), text + ex2); } } public static void AllocateConsole() { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Expected O, but got Unknown if (!ConsoleManager.ConsoleEnabled) { return; } try { ConsoleManager.CreateConsole(); Logger.Listeners.Add((ILogListener)new ConsoleLogListener()); } catch (Exception ex) { Log.LogError((object)"Failed to allocate console!"); Log.LogError((object)ex); } } } internal static class UnityPreloaderRunner { private static readonly string[] CriticalAssemblies = new string[4] { "Mono.Cecil.dll", "Mono.Cecil.Mdb.dll", "Mono.Cecil.Pdb.dll", "Mono.Cecil.Rocks.dll" }; private static void LoadCriticalAssemblies() { string[] criticalAssemblies = CriticalAssemblies; foreach (string path in criticalAssemblies) { try { MonoAssemblyHelper.Load(Path.Combine(Paths.BepInExAssemblyDirectory, path)); } catch (Exception) { } } } public static void PreloaderPreMain() { PlatformUtils.SetPlatform(); string text = Utility.ParentDirectory(Path.GetFullPath(EnvVars.DOORSTOP_INVOKE_DLL_PATH), 2); Paths.SetExecutablePath(EnvVars.DOORSTOP_PROCESS_PATH, text, EnvVars.DOORSTOP_MANAGED_FOLDER_DIR, true, EnvVars.DOORSTOP_DLL_SEARCH_DIRS); LoadCriticalAssemblies(); AppDomain.CurrentDomain.AssemblyResolve += LocalResolve; PreloaderMain(); } private static void PreloaderMain() { if (UnityPreloader.ConfigApplyRuntimePatches.Value) { XTermFix.Apply(); ConsoleSetOutFix.Apply(); } UnityPreloader.Run(); } private static Assembly LocalResolve(object sender, ResolveEventArgs args) { AssemblyName assemblyName = default(AssemblyName); if (!Utility.TryParseAssemblyName(args.Name, ref assemblyName)) { return null; } AssemblyName assemblyName2 = default(AssemblyName); var source = (from a in AppDomain.CurrentDomain.GetAssemblies() select new { assembly = a, name = (Utility.TryParseAssemblyName(a.FullName, ref assemblyName2) ? assemblyName2 : null) } into a where a.name != null && a.name.Name == assemblyName.Name orderby a.name.Version descending select a).ToList(); Assembly assembly = (source.FirstOrDefault(a => a.name.Version == assemblyName.Version) ?? source.FirstOrDefault())?.assembly; if ((object)assembly != null) { return assembly; } if (MonoAssemblyHelper.TryResolveDllAssembly(assemblyName, Paths.BepInExAssemblyDirectory, out assembly) || MonoAssemblyHelper.TryResolveDllAssembly(assemblyName, Paths.PatcherPluginPath, out assembly) || MonoAssemblyHelper.TryResolveDllAssembly(assemblyName, Paths.PluginPath, out assembly)) { return assembly; } return null; } } } namespace BepInEx.Unity.Mono.Preloader.Utils { internal static class MonoAssemblyHelper { [UnmanagedFunctionPointer(CallingConvention.Cdecl)] private delegate nint ImageOpenDelegate(nint data, uint dataLength, bool needCopy, out MonoImageOpenStatus status, bool refOnly, [MarshalAs(UnmanagedType.LPStr)] string name); [UnmanagedFunctionPointer(CallingConvention.Cdecl)] private delegate nint AssemblyLoadDelegate(nint image, [MarshalAs(UnmanagedType.LPStr)] string fileName, out MonoImageOpenStatus status, bool refOnly); private enum MonoImageOpenStatus { MONO_IMAGE_OK, MONO_IMAGE_ERROR_ERRNO, MONO_IMAGE_MISSING_ASSEMBLYREF, MONO_IMAGE_IMAGE_INVALID } private class ReadAssemblyResult { public byte[] AssemblyData; public string AssemblyName; public unsafe Assembly Load(string fullPath) { Assembly assemblyByName = GetAssemblyByName(AssemblyName); if ((object)assemblyByName != null) { return assemblyByName; } fixed (byte* data = &AssemblyData[0]) { MonoImageOpenStatus status; nint image = imageOpen((nint)data, (uint)AssemblyData.Length, needCopy: true, out status, refOnly: false, fullPath); if (status != MonoImageOpenStatus.MONO_IMAGE_OK) { throw new BadImageFormatException($"Failed to load image {fullPath}: {status}"); } assemblyLoad(image, fullPath, out status, refOnly: false); if (status != MonoImageOpenStatus.MONO_IMAGE_OK) { throw new BadImageFormatException($"Failed to load assembly {fullPath}: {status}"); } return GetAssemblyByName(AssemblyName); } } } [DynDllImport("mono", new string[] { "mono_image_open_from_data_with_name" })] private static ImageOpenDelegate imageOpen; [DynDllImport("mono", new string[] { "mono_assembly_load_from_full" })] private static AssemblyLoadDelegate assemblyLoad; static MonoAssemblyHelper() { DynDll.ResolveDynDllImports(typeof(MonoAssemblyHelper), new Dictionary> { ["mono"] = new List { DynDllMapping.op_Implicit(EnvVars.DOORSTOP_MONO_LIB_PATH) } }); } private static ReadAssemblyResult ReadAssemblyData(string filePath) { return ReadAssemblyData(File.ReadAllBytes(filePath)); } private static ReadAssemblyResult ReadAssemblyData(byte[] assemblyData) { using MemoryStream memoryStream = new MemoryStream(assemblyData); AssemblyDefinition val = AssemblyDefinition.ReadAssembly((Stream)memoryStream); try { return new ReadAssemblyResult { AssemblyName = ((AssemblyNameReference)val.Name).Name, AssemblyData = assemblyData }; } finally { ((IDisposable)val)?.Dispose(); } } private static Assembly GetAssemblyByName(string assemblyName) { AssemblyName assemblyName2 = default(AssemblyName); return AppDomain.CurrentDomain.GetAssemblies().FirstOrDefault((Assembly a) => Utility.TryParseAssemblyName(a.FullName, ref assemblyName2) && assemblyName2.Name == assemblyName); } public static bool TryResolveDllAssembly(AssemblyName assemblyName, string directory, out Assembly assembly) { return Utility.TryResolveDllAssembly(assemblyName, directory, (Func)Load, ref assembly); } public static Assembly LoadFromMemory(byte[] data, string filePath) { string fullPath = Path.GetFullPath(filePath); return ReadAssemblyData(data).Load(fullPath); } public static Assembly Load(string filePath) { string fullPath = Path.GetFullPath(filePath); return ReadAssemblyData(fullPath).Load(fullPath); } } } namespace BepInEx.Unity.Mono.Preloader.RuntimeFixes { internal static class TraceFix { private static Type TraceImplType; private static object ListenersSyncRoot; private static TraceListenerCollection Listeners; private static PropertyInfo prop_AutoFlush; private static bool AutoFlush => (bool)prop_AutoFlush.GetValue(null, null); public static void ApplyFix() { //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00e9: Unknown result type (might be due to invalid IL or missing references) //IL_00f7: Expected O, but got Unknown TraceImplType = AppDomain.CurrentDomain.GetAssemblies().First((Assembly x) => x.GetName().Name == "System").GetTypes() .FirstOrDefault((Type x) => x.Name == "TraceImpl"); if ((object)TraceImplType != null) { ListenersSyncRoot = AccessTools.Property(TraceImplType, "ListenersSyncRoot").GetValue(null, null); Listeners = (TraceListenerCollection)AccessTools.Property(TraceImplType, "Listeners").GetValue(null, null); prop_AutoFlush = AccessTools.Property(TraceImplType, "AutoFlush"); new Harmony("com.bepis.bepinex.tracefix").Patch((MethodBase)typeof(Trace).GetMethod("DoTrace", BindingFlags.Static | BindingFlags.NonPublic), new HarmonyMethod(typeof(TraceFix).GetMethod("DoTraceReplacement", BindingFlags.Static | BindingFlags.NonPublic)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } } private static bool DoTraceReplacement(string kind, Assembly report, string message) { string source = string.Empty; try { source = report.GetName().Name; } catch (MethodAccessException) { } TraceEventType eventType = (TraceEventType)Enum.Parse(typeof(TraceEventType), kind); lock (ListenersSyncRoot) { foreach (TraceListener listener in Listeners) { listener.TraceEvent(new TraceEventCache(), source, eventType, 0, message); if (AutoFlush) { listener.Flush(); } } } return false; } } internal static class UnityPatches { private static Harmony HarmonyInstance { get; set; } public static void Apply() { HarmonyInstance = Harmony.CreateAndPatchAll(typeof(UnityPatches), (string)null); try { TraceFix.ApplyFix(); } catch { } } [HarmonyPrefix] [HarmonyPatch(typeof(Assembly), "LoadFile", new Type[] { typeof(string) })] [HarmonyPatch(typeof(Assembly), "LoadFrom", new Type[] { typeof(string) })] public static bool LoadFilePrefix(string __0, ref Assembly __result) { if (!File.Exists(__0)) { throw new FileNotFoundException(__0); } __result = MonoAssemblyHelper.Load(__0); return false; } } internal static class XTermFix { public static int intOffset; public static void Apply() { //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Expected O, but got Unknown //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Expected O, but got Unknown //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Expected O, but got Unknown //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Expected O, but got Unknown //IL_00e5: Unknown result type (might be due to invalid IL or missing references) //IL_00f1: Expected O, but got Unknown //IL_0123: Unknown result type (might be due to invalid IL or missing references) //IL_012f: Expected O, but got Unknown if (!PlatformHelper.Is((Platform)37) && (object)typeof(Console).Assembly.GetType("System.ConsoleDriver") != null && (object)AccessTools.Method("System.TermInfoReader:DetermineVersion", (Type[])null, (Type[])null) == null) { DetourHelper.Native = (IDetourNativePlatform)new DetourNativeX86Platform(); Harmony val = new Harmony("com.bepinex.xtermfix"); val.Patch((MethodBase)AccessTools.Method("System.TermInfoReader:ReadHeader", (Type[])null, (Type[])null), new HarmonyMethod(typeof(XTermFix), "ReadHeaderPrefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); val.Patch((MethodBase)AccessTools.Method("System.TermInfoReader:Get", new Type[1] { AccessTools.TypeByName("System.TermInfoNumbers") }, (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(typeof(XTermFix), "GetTermInfoNumbersTranspiler", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null); val.Patch((MethodBase)AccessTools.Method("System.TermInfoReader:Get", new Type[1] { AccessTools.TypeByName("System.TermInfoStrings") }, (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(typeof(XTermFix), "GetTermInfoStringsTranspiler", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null); val.Patch((MethodBase)AccessTools.Method("System.TermInfoReader:GetStringBytes", new Type[1] { AccessTools.TypeByName("System.TermInfoStrings") }, (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(typeof(XTermFix), "GetTermInfoStringsTranspiler", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null); DetourHelper.Native = null; } } public static int GetInt32(byte[] buffer, int offset) { byte num = buffer[offset]; int num2 = buffer[offset + 1]; int num3 = buffer[offset + 2]; int num4 = buffer[offset + 3]; return num | (num2 << 8) | (num3 << 16) | (num4 << 24); } public static short GetInt16(byte[] buffer, int offset) { byte num = buffer[offset]; int num2 = buffer[offset + 1]; return (short)(num | (num2 << 8)); } public static int GetInteger(byte[] buffer, int offset) { if (intOffset != 2) { return GetInt32(buffer, offset); } return GetInt16(buffer, offset); } public static void DetermineVersion(short magic) { switch (magic) { case 282: intOffset = 2; break; case 542: intOffset = 4; break; default: throw new Exception($"Unknown xterm header format: {magic}"); } } public static bool ReadHeaderPrefix(byte[] buffer, ref int position, ref short ___boolSize, ref short ___numSize, ref short ___strOffsets) { short @int = GetInt16(buffer, position); position += 2; DetermineVersion(@int); position += 2; ___boolSize = GetInt16(buffer, position); position += 2; ___numSize = GetInt16(buffer, position); position += 2; ___strOffsets = GetInt16(buffer, position); position += 2; position += 2; return false; } public static IEnumerable GetTermInfoNumbersTranspiler(IEnumerable instructions) { //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Expected O, but got Unknown //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Expected O, but got Unknown //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Expected O, but got Unknown List list = instructions.ToList(); list[31] = new CodeInstruction(OpCodes.Ldsfld, (object)AccessTools.Field(typeof(XTermFix), "intOffset")); list[36] = new CodeInstruction(OpCodes.Nop, (object)null); list[39] = new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(XTermFix), "GetInteger", (Type[])null, (Type[])null)); return list; } public static IEnumerable GetTermInfoStringsTranspiler(IEnumerable instructions) { //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Expected O, but got Unknown List list = instructions.ToList(); list[32] = new CodeInstruction(OpCodes.Ldsfld, (object)AccessTools.Field(typeof(XTermFix), "intOffset")); return list; } } } namespace Doorstop { internal static class Entrypoint { public static void Start() { string text = $"preloader_{DateTime.Now:yyyyMMdd_HHmmss_fff}.log"; try { EnvVars.LoadVars(); text = Path.Combine(Path.GetDirectoryName(EnvVars.DOORSTOP_PROCESS_PATH) ?? ".", text); typeof(Entrypoint).Assembly.GetType("BepInEx.Unity.Mono.Preloader.UnityPreloaderRunner")?.GetMethod("PreloaderPreMain")?.Invoke(null, null); } catch (Exception ex) { File.WriteAllText(text, ex.ToString()); } } } }