Skip to content

Commit 1172895

Browse files
tuff
1 parent f09cef7 commit 1172895

File tree

3 files changed

+54
-26
lines changed

3 files changed

+54
-26
lines changed

android_compatibility_module/IL2CPP/TranspilerSupport.cs

Lines changed: 42 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -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>
240240
public 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;

constants/Paths.cs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,14 +44,17 @@ public static class Paths
4444
public static readonly string NativeModsPath = Combine(StreamingAssetsPath, Others.IsAndroid ? "mods" : "Mods");
4545

4646
/// <summary>
47-
/// Path to game native Managed folder, or IL2CPP assemblies if on android
47+
/// Path to game native Managed folder,if on android these are STUB DLLS! DO NOT USE THEM!
4848
/// </summary>
4949
public static readonly string ManagedPath = !Others.IsAndroid
5050
? Others.is_editor
5151
? Combine(StreamingAssetsPath, "..", ".Managed")
5252
: Combine(StreamingAssetsPath, "..", "Managed")
53-
: Combine(MelonPath, "MelonLoader", "Il2CppAssemblies");
54-
53+
: Combine(MelonPath, "MelonLoader", "ManagedAssemblies");
54+
/// <summary>
55+
/// the Il2cpp Assemblies. on android
56+
/// </summary>
57+
public static readonly string Il2CppAssemblies = Combine(MelonPath, "MelonLoader", "Il2CppAssemblies");
5558
/// <summary>
5659
/// Path to folder contains NML's cache
5760
/// </summary>

services/ModCompileLoadService.cs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -269,11 +269,15 @@ public static void prepareCompile(List<ModDependencyNode> pModNodes)
269269
}
270270

271271
var default_ref_path_list = new List<string>();
272-
default_ref_path_list.AddRange(Directory.GetFiles(Paths.ManagedPath, "*.dll"));
273272
default_ref_path_list.AddRange(Directory.GetFiles(Paths.NMLAssembliesPath, "*.dll"));
274273
if (Config.isAndroid)
275274
{
276275
default_ref_path_list.AddRange(Directory.GetFiles(Paths.MelonAssemblies, "*.dll"));
276+
default_ref_path_list.AddRange(Directory.GetFiles(Paths.Il2CppAssemblies, "*.dll"));
277+
}
278+
else
279+
{
280+
default_ref_path_list.AddRange(Directory.GetFiles(Paths.ManagedPath, "*.dll"));
277281
}
278282
default_ref_path_list.Add(Paths.NMLModPath);
279283
_default_ref_path = default_ref_path_list.ToArray();
@@ -291,10 +295,9 @@ public static void prepareCompile(List<ModDependencyNode> pModNodes)
291295
LogService.LogError($"Error when load default reference {_default_ref_path[i]}: {e.Message}");
292296
}
293297
}
294-
295298
if (Config.isAndroid)
296299
{
297-
_default_ref = _default_ref.AddRangeToArray(LoadDotNetReferencesFromApk(Paths.DotnetAPKPath).ToArray());
300+
_default_ref = _default_ref.AddRangeToArray([..LoadDotNetReferencesFromApk(Paths.DotnetAPKPath)]);
298301
}
299302
_publicized_assembly_ref = MetadataReference.CreateFromFile(Paths.PublicizedAssemblyPath);
300303
}

0 commit comments

Comments
 (0)