@@ -89,9 +89,6 @@ public static object InvokeMirror(MethodBase original, object[] args)
8989 internal static void Initialize ( Harmony harmony )
9090 {
9191 MirroredAssemblies . Init ( ) ;
92- MirroredAssemblies . Generator . Init ( ) ;
93- MirroredAssemblies . ManagedAssembly = MirroredAssemblies . LoadMirrorAssembly ( Paths . PublicizedAssemblyPath ) ;
94- MirroredAssemblies . NativeAssembly = typeof ( Actor ) . Assembly ;
9592 harmony . Patch (
9693 AccessTools . Method ( typeof ( HarmonyManipulator ) , nameof ( HarmonyManipulator . Manipulate ) ,
9794 new [ ] { typeof ( MethodBase ) , typeof ( PatchInfo ) , typeof ( ILContext ) } ) ,
@@ -104,14 +101,14 @@ internal static void Initialize(Harmony harmony)
104101
105102 static void ManagedField ( ref Type type )
106103 {
107- if ( type . Assembly . FileName ( ) == " Assembly-CSharp.dll" )
104+ if ( MirroredAssemblies . TryGetNative ( type . Assembly , out Assembly native ) )
108105 {
109- type = MirroredAssemblies . RemapType ( type , MirroredAssemblies . ManagedAssembly ) ;
106+ type = MirroredAssemblies . RemapType ( type , native ) ;
110107 }
111108 }
112109
113110 /// <summary>
114- /// Generates a mirror method for your transpiler and replaces <see cref=" transpiler"/> with the IL2CPP2Managed transpiler or null if already patched
111+ /// Generates a mirror method for your transpiler and replaces the transpiler param with the IL2CPP2Managed transpiler or null if already patched
115112 /// </summary>
116113 /// <param name="original">the method to transpile</param>
117114 /// <param name="transpiler">your transpiler</param>
@@ -236,7 +233,10 @@ private static IEnumerable<CodeInstruction> IL2CPP2Managed(IEnumerable<CodeInstr
236233 return code ;
237234 }
238235}
239-
236+ /// <summary>
237+ /// The Managed mirrored assemblies, all loaded in a separate context. this is where all the mirror methods are stored and generated from.
238+ /// </summary>
239+ /// <remarks> also contains the mapping between IL2CPP and Managed types for field transformation and operand remapping</remarks>
240240public class MirroredAssemblies : AssemblyLoadContext
241241{
242242 internal static Dictionary < MethodBase , MirrorData > Mirrors = new ( ) ;
@@ -258,30 +258,49 @@ public static MirrorData GetMirror(MethodBase Method)
258258 /// the IL2CPP Assembly
259259 /// </summary>
260260 public static Assembly NativeAssembly { get ; internal set ; }
261-
262- private MirroredAssemblies ( ) : base ( "MirrorContext" , isCollectible : true )
261+ static Dictionary < Assembly , Assembly > StubToNativeMap = [ ] ;
262+ public static bool TryGetNative ( Assembly Managed , out Assembly Native )
263+ {
264+ return StubToNativeMap . TryGetValue ( Managed , out Native ) ;
265+ }
266+ private MirroredAssemblies ( ) : base ( "ManagedAssemblies" , isCollectible : false )
263267 {
264268 }
265269
266270 protected override Assembly Load ( AssemblyName assemblyName ) => null ;
267271 private static MirroredAssemblies Instance ;
268-
272+ public static bool IsManaged ( Assembly Assembly )
273+ {
274+ return Assembly != null && ( Assembly == ManagedAssembly || StubToNativeMap . ContainsKey ( Assembly ) ) ;
275+ }
269276 internal static void Init ( )
270277 {
271278 Instance = new MirroredAssemblies ( ) ;
279+ ManagedAssembly = LoadMirrorAssembly ( Paths . PublicizedAssemblyPath ) ;
280+ foreach ( var path in Directory . GetFiles ( Paths . ManagedPath , "*.dll" ) )
281+ {
282+ LogService . LogInfo ( path ) ;
283+ Assembly stub = LoadMirrorAssembly ( path ) ;
284+ string name = stub . GetName ( ) . Name ;
285+ Assembly native = AppDomain . CurrentDomain . GetAssemblies ( ) . FirstOrDefault ( a => a . GetName ( ) . Name == name ) ;
286+ if ( native != null )
287+ {
288+ StubToNativeMap . Add ( stub , native ) ;
289+ }
290+ else
291+ {
292+ LogService . LogWarning ( $ "Failed to find native assembly for { name } ") ;
293+ }
294+ }
295+ NativeAssembly = typeof ( Actor ) . Assembly ;
296+ Generator . Init ( ) ;
272297 }
273298
274299 public static Assembly LoadMirrorAssembly ( string path )
275300 {
276301 return Instance . LoadFromAssemblyPath ( Path . GetFullPath ( path ) ) ;
277302 }
278303
279- public static void Destroy ( )
280- {
281- Instance . Unload ( ) ;
282- Instance = null ;
283- }
284-
285304 public static Type RemapType ( Type type , Assembly targetAssembly , Type nativeDeclaringType = null )
286305 {
287306 if ( type == null )
@@ -290,6 +309,10 @@ public static Type RemapType(Type type, Assembly targetAssembly, Type nativeDecl
290309 if ( type . Assembly == targetAssembly )
291310 return type ;
292311
312+ if ( StubToNativeMap . TryGetValue ( type . Assembly , out Assembly native ) && native != targetAssembly ) {
313+ return RemapType ( type , native , nativeDeclaringType ) ;
314+ }
315+
293316 if ( type . IsByRef )
294317 return RemapType ( type . GetElementType ( ) , targetAssembly , nativeDeclaringType ) . MakeByRefType ( ) ;
295318
@@ -608,14 +631,13 @@ public static bool TransformField(ref OpCode opcode, ref object operand)
608631
609632 return true ;
610633 }
611-
612634 private static object RemapOperand ( object operand )
613635 {
614636 Type nativeDeclType ;
615637 Type RemapOperandType ( Type t ) => RemapType ( t , NativeAssembly , nativeDeclType ) ;
616638 switch ( operand )
617639 {
618- case MethodInfo m when m . DeclaringType ? . Assembly == ManagedAssembly :
640+ case MethodInfo m when IsManaged ( m . DeclaringType ? . Assembly ) :
619641 {
620642 nativeDeclType = RemapType ( m . DeclaringType , NativeAssembly ) ;
621643 // Find method definition (ignore generic args)
@@ -667,7 +689,7 @@ private static object RemapOperand(object operand)
667689
668690 return method ;
669691 }
670- case ConstructorInfo c when c . DeclaringType ? . Assembly == ManagedAssembly :
692+ case ConstructorInfo c when IsManaged ( c . DeclaringType ? . Assembly ) :
671693 {
672694 nativeDeclType = RemapType ( c . DeclaringType , NativeAssembly ) ;
673695 var paramTypes = c . GetParameters ( )
@@ -676,7 +698,7 @@ private static object RemapOperand(object operand)
676698
677699 return AccessTools . Constructor ( nativeDeclType , paramTypes ) ;
678700 }
679- case Type t when t . Assembly == ManagedAssembly :
701+ case Type t when IsManaged ( t . Assembly ) :
680702 return RemapType ( t , NativeAssembly ) ;
681703 default :
682704 return operand ;
0 commit comments