diff --git a/Runtimes/Unity/BepInEx.Unity.IL2CPP/BepInEx.Unity.IL2CPP.csproj b/Runtimes/Unity/BepInEx.Unity.IL2CPP/BepInEx.Unity.IL2CPP.csproj index 9dca287..333ab54 100644 --- a/Runtimes/Unity/BepInEx.Unity.IL2CPP/BepInEx.Unity.IL2CPP.csproj +++ b/Runtimes/Unity/BepInEx.Unity.IL2CPP/BepInEx.Unity.IL2CPP.csproj @@ -14,7 +14,7 @@ - + @@ -22,7 +22,7 @@ - + diff --git a/Runtimes/Unity/BepInEx.Unity.IL2CPP/Il2CppInteropManager.AsmToCecilConverter.cs b/Runtimes/Unity/BepInEx.Unity.IL2CPP/Il2CppInteropManager.AsmToCecilConverter.cs new file mode 100644 index 0000000..05855bb --- /dev/null +++ b/Runtimes/Unity/BepInEx.Unity.IL2CPP/Il2CppInteropManager.AsmToCecilConverter.cs @@ -0,0 +1,63 @@ +using System.Collections.Generic; +using System.IO; +using System.Linq; +using Mono.Cecil; + +namespace BepInEx.Unity.IL2CPP; + +internal static partial class Il2CppInteropManager +{ + private sealed class AsmToCecilConverter : IAssemblyResolver + { + private readonly Dictionary asmResolverDictionary; + private readonly Dictionary cecilDictionary = new(); + private readonly Dictionary asmToCecil = new(); + public AsmToCecilConverter(List list) + { + asmResolverDictionary = list.ToDictionary(a => a.Name?.ToString(), a => a); + } + + public void Dispose() { } + public AssemblyDefinition Resolve(AssemblyNameReference name) => Resolve(name, new() { AssemblyResolver = this }); + public AssemblyDefinition Resolve(AssemblyNameReference name, ReaderParameters parameters) + { + var assemblyName = name.Name; + if (!cecilDictionary.TryGetValue(assemblyName, out var cecilAssembly) && asmResolverDictionary.TryGetValue(assemblyName, out var asmAssembly)) + { + cecilAssembly = Convert(asmAssembly, parameters); + } + return cecilAssembly; + } + + public List ConvertAll() + { + List cecilAssemblies = new(asmResolverDictionary.Count); + foreach (var asmResolverAssembly in asmResolverDictionary.Values) + { + var cecilAssembly = Convert(asmResolverAssembly); + cecilAssemblies.Add(cecilAssembly); + } + return cecilAssemblies; + } + + private AssemblyDefinition Convert(AsmResolver.DotNet.AssemblyDefinition asmResolverAssembly) + { + return Convert(asmResolverAssembly, new ReaderParameters() { AssemblyResolver = this }); + } + + private AssemblyDefinition Convert(AsmResolver.DotNet.AssemblyDefinition asmResolverAssembly, ReaderParameters readerParameters) + { + if (asmToCecil.TryGetValue(asmResolverAssembly, out var cecilAssembly)) + { + return cecilAssembly; + } + MemoryStream stream = new(); + asmResolverAssembly.WriteManifest(stream); + stream.Position = 0; + cecilAssembly = AssemblyDefinition.ReadAssembly(stream, readerParameters); + cecilDictionary.Add(cecilAssembly.Name.Name, cecilAssembly); + asmToCecil.Add(asmResolverAssembly, cecilAssembly); + return cecilAssembly; + } + } +} diff --git a/Runtimes/Unity/BepInEx.Unity.IL2CPP/Il2CppInteropManager.cs b/Runtimes/Unity/BepInEx.Unity.IL2CPP/Il2CppInteropManager.cs index 4c900f4..d6f41b6 100644 --- a/Runtimes/Unity/BepInEx.Unity.IL2CPP/Il2CppInteropManager.cs +++ b/Runtimes/Unity/BepInEx.Unity.IL2CPP/Il2CppInteropManager.cs @@ -14,6 +14,10 @@ using BepInEx.Unity.Common; using BepInEx.Unity.IL2CPP.Hook; using BepInEx.Unity.IL2CPP.Logging; using Cpp2IL.Core; +using Cpp2IL.Core.Api; +using Cpp2IL.Core.InstructionSets; +using Cpp2IL.Core.OutputFormats; +using Cpp2IL.Core.ProcessingLayers; using HarmonyLib; using Il2CppInterop.Common; using Il2CppInterop.Generator; @@ -29,8 +33,15 @@ using MSLoggerFactory = Microsoft.Extensions.Logging.LoggerFactory; namespace BepInEx.Unity.IL2CPP; -internal static class Il2CppInteropManager +internal static partial class Il2CppInteropManager { + static Il2CppInteropManager() + { + InstructionSetRegistry.RegisterInstructionSet(DefaultInstructionSets.X86_32); + InstructionSetRegistry.RegisterInstructionSet(DefaultInstructionSets.X86_64); + LibCpp2IlBinaryRegistry.RegisterBuiltInBinarySupport(); + } + private static readonly ConfigEntry UpdateInteropAssemblies = ConfigFile.CoreConfig.Bind("IL2CPP", "UpdateInteropAssemblies", @@ -199,17 +210,18 @@ internal static class Il2CppInteropManager AppDomain.CurrentDomain.AddCecilPlatformAssemblies(UnityBaseLibsDirectory); DownloadUnityAssemblies(); - var dummyAssemblies = RunCpp2Il(); + var asmResolverAssemblies = RunCpp2Il(); + var cecilAssemblies = new AsmToCecilConverter(asmResolverAssemblies).ConvertAll(); if (DumpDummyAssemblies.Value) { var dummyPath = Path.Combine(Paths.BepInExRootPath, "dummy"); Directory.CreateDirectory(dummyPath); - foreach (var assemblyDefinition in dummyAssemblies) + foreach (var assemblyDefinition in cecilAssemblies) assemblyDefinition.Write(Path.Combine(dummyPath, $"{assemblyDefinition.Name.Name}.dll")); } - RunIl2CppInteropGenerator(dummyAssemblies); + RunIl2CppInteropGenerator(cecilAssemblies); File.WriteAllText(HashPath, ComputeHash()); } @@ -242,7 +254,7 @@ internal static class Il2CppInteropManager } } - private static List RunCpp2Il() + private static List RunCpp2Il() { Logger.LogMessage("Running Cpp2IL to generate dummy assemblies"); @@ -252,40 +264,44 @@ internal static class Il2CppInteropManager "Metadata", "global-metadata.dat"); - List sourceAssemblies; - var stopwatch = new Stopwatch(); stopwatch.Start(); var cpp2IlLogger = BepInEx.Logging.Logger.CreateLogSource("Cpp2IL"); - Cpp2IL.Core.Logger.VerboseLog += (message, s) => + Cpp2IL.Core.Logging.Logger.VerboseLog += (message, s) => cpp2IlLogger.LogDebug($"[{s}] {message.Trim()}"); - Cpp2IL.Core.Logger.InfoLog += (message, s) => + Cpp2IL.Core.Logging.Logger.InfoLog += (message, s) => cpp2IlLogger.LogInfo($"[{s}] {message.Trim()}"); - Cpp2IL.Core.Logger.WarningLog += (message, s) => + Cpp2IL.Core.Logging.Logger.WarningLog += (message, s) => cpp2IlLogger.LogWarning($"[{s}] {message.Trim()}"); - Cpp2IL.Core.Logger.ErrorLog += (message, s) => + Cpp2IL.Core.Logging.Logger.ErrorLog += (message, s) => cpp2IlLogger.LogError($"[{s}] {message.Trim()}"); var unityVersion = UnityInfo.Version; - Cpp2IlApi.InitializeLibCpp2Il(GameAssemblyPath, metadataPath, new int[] + Cpp2IlApi.InitializeLibCpp2Il(GameAssemblyPath, metadataPath, unityVersion, false); + + List processingLayers = new() { new AttributeInjectorProcessingLayer(), }; + + foreach (var cpp2IlProcessingLayer in processingLayers) { - unityVersion.Major, - unityVersion.Minor, - unityVersion.Build, - }, false); - sourceAssemblies = Cpp2IlApi.MakeDummyDLLs(); - Cpp2IlApi.RunAttributeRestorationForAllAssemblies(null, - LibCpp2IlMain.MetadataVersion >= 29 || - LibCpp2IlMain.Binary!.InstructionSet is InstructionSet.X86_32 - or InstructionSet.X86_64); - Cpp2IlApi.DisposeAndCleanupAll(); + cpp2IlProcessingLayer.PreProcess(Cpp2IlApi.CurrentAppContext, processingLayers); + } + + foreach (var cpp2IlProcessingLayer in processingLayers) + { + cpp2IlProcessingLayer.Process(Cpp2IlApi.CurrentAppContext); + } + + var assemblies = new AsmResolverDummyDllOutputFormat().BuildAssemblies(Cpp2IlApi.CurrentAppContext); + + LibCpp2IlMain.Reset(); + Cpp2IlApi.CurrentAppContext = null; stopwatch.Stop(); Logger.LogInfo($"Cpp2IL finished in {stopwatch.Elapsed}"); - return sourceAssemblies; + return assemblies; } private static void RunIl2CppInteropGenerator(List sourceAssemblies) diff --git a/nuget.config b/nuget.config index 1864ded..5e67f2a 100644 --- a/nuget.config +++ b/nuget.config @@ -2,5 +2,6 @@ + - \ No newline at end of file +