diff --git a/Il2CppInterop.Generator/Utils/RuntimeAssemblyReferences.cs b/Il2CppInterop.Generator/Utils/RuntimeAssemblyReferences.cs index 112c4602..fbdfc204 100644 --- a/Il2CppInterop.Generator/Utils/RuntimeAssemblyReferences.cs +++ b/Il2CppInterop.Generator/Utils/RuntimeAssemblyReferences.cs @@ -30,6 +30,8 @@ public RuntimeAssemblyReferences(ModuleDefinition module, RewriteGlobalContext g public Lazy Il2CppStringArrayctor_size { get; private set; } public Memoize Il2CppStructArrayctor_size { get; private set; } public Lazy Il2CppArrayBase_get_Length { get; private set; } + public Memoize Il2CppArrayBase_get_Item { get; private set; } + public Memoize Il2CppArrayBase_set_Item { get; private set; } public Lazy IL2CPP_Il2CppObjectBaseToPtr { get; private set; } public Lazy IL2CPP_Il2CppObjectBaseToPtrNotNull { get; private set; } public Lazy IL2CPP_Il2CppStringToManaged { get; private set; } @@ -122,6 +124,8 @@ private void InitTypeRefs() var nonGenericIl2CppArrayBase = new TypeReference(Module, assemblyRef, "Il2CppInterop.Runtime.InteropTypes.Arrays", "Il2CppArrayBase").ToTypeSignature(); + var genericIl2CppArrayBase = new TypeReference(Module, assemblyRef, "Il2CppInterop.Runtime.InteropTypes.Arrays", "Il2CppArrayBase`1").ToTypeSignature(); + Il2CppStructArray = new TypeReference(Module, assemblyRef, "Il2CppInterop.Runtime.InteropTypes.Arrays", "Il2CppStructArray`1").ToTypeSignature(); Il2CppReferenceArray = new TypeReference(Module, assemblyRef, "Il2CppInterop.Runtime.InteropTypes.Arrays", "Il2CppReferenceArray`1").ToTypeSignature(); @@ -140,6 +144,7 @@ private void InitTypeRefs() allTypes["Il2CppInterop.Runtime.InteropTypes.Il2CppObjectBase"] = Il2CppObjectBase; allTypes["Il2CppInterop.Runtime.Runtime.Il2CppObjectPool"] = Il2CppObjectPool; allTypes["Il2CppInterop.Runtime.InteropTypes.Arrays.Il2CppArrayBase"] = nonGenericIl2CppArrayBase; + allTypes["Il2CppInterop.Runtime.InteropTypes.Arrays.Il2CppArrayBase"] = genericIl2CppArrayBase; allTypes["Il2CppInterop.Runtime.InteropTypes.Arrays.Il2CppStringArray"] = Il2CppStringArray; allTypes["Il2CppInterop.Runtime.InteropTypes.Arrays.Il2CppReferenceArray"] = Il2CppReferenceArray; allTypes["Il2CppInterop.Runtime.InteropTypes.Arrays.Il2CppStructArray"] = Il2CppStructArray; @@ -211,6 +216,24 @@ private void InitMethodRefs() return mr; }); + Il2CppArrayBase_get_Item = new((param) => + { + var owner = ResolveType("Il2CppInterop.Runtime.InteropTypes.Arrays.Il2CppArrayBase"); + var giOwner = owner.MakeGenericInstanceType(param).ToTypeDefOrRef(); + var mr = ReferenceCreator.CreateInstanceMethodReference("get_Item", new GenericParameterSignature(Module, GenericParameterType.Type, 0), + giOwner, ResolveType("System.Int32")); + return mr; + }); + + Il2CppArrayBase_set_Item = new((param) => + { + var owner = ResolveType("Il2CppInterop.Runtime.InteropTypes.Arrays.Il2CppArrayBase"); + var giOwner = owner.MakeGenericInstanceType(param).ToTypeDefOrRef(); + var mr = ReferenceCreator.CreateInstanceMethodReference("set_Item", Module.Void(), + giOwner, ResolveType("System.Int32"), new GenericParameterSignature(Module, GenericParameterType.Type, 0)); + return mr; + }); + IL2CPP_Il2CppObjectBaseToPtr = new Lazy(() => { var mr = ReferenceCreator.CreateStaticMethodReference("Il2CppObjectBaseToPtr", ResolveType("System.IntPtr"), diff --git a/Il2CppInterop.Generator/Utils/UnstripTranslator.cs b/Il2CppInterop.Generator/Utils/UnstripTranslator.cs index 4688f5df..217e03b7 100644 --- a/Il2CppInterop.Generator/Utils/UnstripTranslator.cs +++ b/Il2CppInterop.Generator/Utils/UnstripTranslator.cs @@ -57,34 +57,69 @@ public static bool TranslateMethod(MethodDefinition original, MethodDefinition t imports.Module.DefaultImporter.ImportMethod(imports.Il2CppArrayBase_get_Length.Value)); break; - case CilCode.Ldelema: - //This is Il2CppArrayBase.Pointer + index * sizeof(T) but the T is not known because the operand is null. + case CilCode.Ldelem_Ref: + //This is Il2CppReferenceArray.get_Item but the T is not known because the operand is null. return false; - case CilCode.Ldelem: - //This is Il2CppArrayBase.set_Item but the T is not known because the operand is null. + case CilCode.Stelem_Ref: + //This is Il2CppReferenceArray.set_Item but the T is not known because the operand is null. return false; - case CilCode.Stelem: - //This is Il2CppArrayBase.set_Item but the T is not known because the operand is null. + case CilCode.Ldelem_I1: + case CilCode.Ldelem_I2: + case CilCode.Ldelem_I4: + case CilCode.Ldelem_U4: + //This is Il2CppArrayBase.get_Item but the T could be either the cooresponding primitive or an enum. return false; - case CilCode.Ldelem_Ref: - //This is Il2CppReferenceArray.get_Item but the T is not known because the operand is null. + case CilCode.Ldelem_U1: + //This is Il2CppArrayBase.get_Item but the T could be either byte, bool, or an enum. return false; - case CilCode.Stelem_Ref: - //This is Il2CppReferenceArray.set_Item but the T is not known because the operand is null. + case CilCode.Ldelem_U2: + //This is Il2CppArrayBase.get_Item but the T could be either ushort, char, or an enum. + return false; + + case CilCode.Ldelem_I8: + //This is Il2CppArrayBase.get_Item but the T could be either signed, unsigned, or an enum. return false; - case >= CilCode.Ldelem_I1 and <= CilCode.Ldelem_R8: - //This is Il2CppStructArray.get_Item + case CilCode.Ldelem_I: + //This is Il2CppArrayBase.get_Item but the T could be either signed, unsigned, or a pointer. return false; - case >= CilCode.Stelem_I and <= CilCode.Stelem_R8: + case CilCode.Ldelem_R4: + { + var getMethod = imports.Il2CppArrayBase_get_Item.Get(imports.Module.CorLibTypeFactory.Single); + newInstruction = targetBuilder.Add(OpCodes.Callvirt, imports.Module.DefaultImporter.ImportMethod(getMethod)); + } + break; + + case CilCode.Ldelem_R8: + { + var getMethod = imports.Il2CppArrayBase_get_Item.Get(imports.Module.CorLibTypeFactory.Double); + newInstruction = targetBuilder.Add(OpCodes.Callvirt, imports.Module.DefaultImporter.ImportMethod(getMethod)); + } + break; + + case >= CilCode.Stelem_I and <= CilCode.Stelem_I8: //This is Il2CppStructArray.set_Item return false; + case CilCode.Stelem_R4: + { + var setMethod = imports.Il2CppArrayBase_set_Item.Get(imports.Module.CorLibTypeFactory.Single); + newInstruction = targetBuilder.Add(OpCodes.Callvirt, imports.Module.DefaultImporter.ImportMethod(setMethod)); + } + break; + + case CilCode.Stelem_R8: + { + var setMethod = imports.Il2CppArrayBase_set_Item.Get(imports.Module.CorLibTypeFactory.Double); + newInstruction = targetBuilder.Add(OpCodes.Callvirt, imports.Module.DefaultImporter.ImportMethod(setMethod)); + } + break; + case >= CilCode.Ldind_I1 and <= CilCode.Ldind_Ref: //This is for by ref parameters goto default; @@ -239,7 +274,7 @@ public static bool TranslateMethod(MethodDefinition original, MethodDefinition t imports.Module.DefaultImporter.ImportMethod(imports.Il2CppObjectBase_TryCast.Value.MakeGenericInstanceMethod(targetType))); instructionMap.Add(bodyInstruction, newInstruction); } - else if (bodyInstruction.OpCode == OpCodes.Newarr && !targetType.IsValueType) + else if (bodyInstruction.OpCode == OpCodes.Newarr) { var newInstruction = targetBuilder.Add(OpCodes.Conv_I8); @@ -260,6 +295,23 @@ public static bool TranslateMethod(MethodDefinition original, MethodDefinition t ReferenceCreator.CreateInstanceMethodReference(".ctor", imports.Module.Void(), il2cppTypeArray, imports.Module.Long()))); instructionMap.Add(bodyInstruction, newInstruction); } + else if (bodyInstruction.OpCode == OpCodes.Ldelema) + { + // Not implemented + return false; + } + else if (bodyInstruction.OpCode == OpCodes.Ldelem) + { + var getMethod = imports.Il2CppArrayBase_get_Item.Get(targetType); + var newInstruction = targetBuilder.Add(OpCodes.Callvirt, imports.Module.DefaultImporter.ImportMethod(getMethod)); + instructionMap.Add(bodyInstruction, newInstruction); + } + else if (bodyInstruction.OpCode == OpCodes.Stelem) + { + var setMethod = imports.Il2CppArrayBase_set_Item.Get(targetType); + var newInstruction = targetBuilder.Add(OpCodes.Callvirt, imports.Module.DefaultImporter.ImportMethod(setMethod)); + instructionMap.Add(bodyInstruction, newInstruction); + } else { var newInstruction = targetBuilder.Add(bodyInstruction.OpCode, targetType.ToTypeDefOrRef());