public override DynamicMethodDefinition CopyOriginal()
        {
            DynamicMethodDefinition method = Original.ToNewDynamicMethodDefinition();

            method.Definition.Name += "_wrapper";
            ILContext      ilcontext          = new ILContext(method.Definition);
            ILCursor       ilcursor           = new ILCursor(ilcontext);
            FieldReference tempfieldreference = null;

            if (ilcursor.TryGotoNext(x => x.MatchLdsfld(out tempfieldreference), x => x.MatchCall(UnhollowerSupport.IL2CPPType, "il2cpp_object_get_virtual_method")))
            {
                // Virtual method: Replace the sequence
                // - ldarg.0
                // - call native int[UnhollowerBaseLib] UnhollowerBaseLib.IL2CPP::Il2CppObjectBaseToPtr(class [UnhollowerBaseLib] UnhollowerBaseLib.Il2CppObjectBase)
                // - ldsfld native int SomeClass::NativeMethodInfoPtr_Etc
                // - call native int[UnhollowerBaseLib] UnhollowerBaseLib.IL2CPP::il2cpp_object_get_virtual_method(native int, native int)

                ilcursor.Index -= 2;
                ilcursor.RemoveRange(4);
            }
            else if (ilcursor.TryGotoNext(x => x.MatchLdsfld(UnhollowerSupport.MethodBaseToIl2CppFieldInfo(Original))))
            {
                ilcursor.Remove();
            }
            else
            {
                MelonLogger.Error("Harmony Patcher could not rewrite Il2Cpp Unhollowed Method. Expect a stack overflow.");
                return(method);
            }
            ilcursor.Emit(Mono.Cecil.Cil.OpCodes.Ldc_I8, copiedMethodInfoPointer.ToInt64());
            ilcursor.Emit(Mono.Cecil.Cil.OpCodes.Conv_I);
            return(method);
        }
        public static void RegisterAssembly(Assembly asm)
        {
            if (!MelonUtils.IsGameIl2Cpp())
            {
                return;
            }
            IEnumerable <Type> typeTbl = asm.GetValidTypes();

            if ((typeTbl == null) || (typeTbl.Count() <= 0))
            {
                return;
            }
            foreach (Type type in typeTbl)
            {
                object[] attTbl = type.GetCustomAttributes(typeof(RegisterTypeInIl2Cpp), false);
                if ((attTbl == null) || (attTbl.Length <= 0))
                {
                    continue;
                }
                RegisterTypeInIl2Cpp att = (RegisterTypeInIl2Cpp)attTbl[0];
                if (att == null)
                {
                    continue;
                }
                UnhollowerSupport.RegisterTypeInIl2CppDomain(type, att.LogSuccess);
            }
        }
 internal static void TryResolve(object sender, PatchManager.PatcherResolverEventArgs args)
 {
     if (UnhollowerSupport.IsGeneratedAssemblyType(args.Original.DeclaringType))
     {
         args.MethodPatcher = new HarmonyIl2CppMethodPatcher(args.Original);
     }
 }
Example #4
0
        private static void OnApplicationStart()
        {
            if (Imports.IsIl2CppGame())
            {
                Assembly_CSharp = Assembly.Load("Assembly-CSharp");
                UnhollowerSupport.Initialize();
            }
            SupportModule.Initialize();

            MelonModLogger.Log("------------------------------");
            MelonModLogger.Log("Unity " + UnityVersion);
            MelonModLogger.Log("------------------------------");
            MelonModLogger.Log("Name: " + CurrentGameAttribute.GameName);
            MelonModLogger.Log("Developer: " + CurrentGameAttribute.Developer);
            MelonModLogger.Log("Type: " + (Imports.IsIl2CppGame() ? "Il2Cpp" : (Imports.IsOldMono() ? "Mono" : "MonoBleedingEdge")));
            MelonModLogger.Log("------------------------------");
            MelonModLogger.Log("Using v" + BuildInfo.Version + " Open-Beta");
            MelonModLogger.Log("------------------------------");

            LoadMods();
            if (Mods.Count > 0)
            {
                for (int i = 0; i < Mods.Count; i++)
                {
                    MelonMod mod = Mods[i];
                    if (mod != null)
                    {
                        MelonModLogger.Log(mod.InfoAttribute.Name
                                           + (!string.IsNullOrEmpty(mod.InfoAttribute.Version)
                            ? (" v" + mod.InfoAttribute.Version) : "")
                                           + (!string.IsNullOrEmpty(mod.InfoAttribute.Author)
                            ? (" by " + mod.InfoAttribute.Author) : "")
                                           + (!string.IsNullOrEmpty(mod.InfoAttribute.DownloadLink)
                            ? (" (" + mod.InfoAttribute.DownloadLink + ")")
                            : "")
                                           );
                        if (Imports.IsDebugMode())
                        {
                            MelonModLogger.Log("Preload: " + mod.IsPreload.ToString());
                        }
                        MelonModLogger.LogModStatus((mod.GameAttributes.Any()) ? (mod.IsUniversal ? 0 : 1) : 2);
                        MelonModLogger.Log("------------------------------");
                    }
                }
                for (int i = 0; i < Mods.Count; i++)
                {
                    MelonMod mod = Mods[i];
                    if (mod != null)
                    {
                        try { mod.OnApplicationStart(); } catch (Exception ex) { MelonModLogger.LogModError(ex.ToString(), mod.InfoAttribute.Name); }
                    }
                }
            }
            else
            {
                MelonModLogger.Log("No Mods Loaded!");
                MelonModLogger.Log("------------------------------");
            }
        }
 private static void ConvertTypeToIl2Cpp(ILGenerator il, Type returnType)
 {
     if (returnType == typeof(string))
     {
         il.Emit(OpCodes.Call, UnhollowerSupport.ManagedStringToIl2CppMethod);
     }
     else if (!returnType.IsValueType && UnhollowerSupport.IsGeneratedAssemblyType(returnType))
     {
         il.Emit(OpCodes.Call, UnhollowerSupport.Il2CppObjectBaseToPtrMethod);
     }
 }
        private void WarnIfOriginalMethodIsInlined(string melonName)
        {
            int callerCount = UnhollowerSupport.GetIl2CppMethodCallerCount(Original) ?? -1;

            if ((callerCount > 0) ||
                UnityMagicMethods.IsUnityMagicMethod(Original))
            {
                return;
            }
            MelonLogger.ManualWarning(melonName, $"Harmony: Method {Original.FullDescription()} does not appear to get called directly from anywhere, " +
                                      "suggesting it may have been inlined and your patch may not be called.");
        }
 private static Type Il2CppTypeForPatchType(Type type)
 {
     if (type.IsByRef)
     {
         Type element = type.GetElementType();
         if (element == typeof(string) || UnhollowerSupport.IsGeneratedAssemblyType(element))
         {
             return(typeof(IntPtr *));
         }
     }
     else if (type == typeof(string) || UnhollowerSupport.IsGeneratedAssemblyType(type))
     {
         return(typeof(IntPtr));
     }
     return(type);
 }
Example #8
0
        private static void OnApplicationStart()
        {
            if (!HasGeneratedAssembly)
            {
                return;
            }

            if (Imports.IsIl2CppGame())
            {
                if (IsVRChat)
                {
                    Assembly_CSharp = Assembly.Load("Assembly-CSharp");
                }
                UnhollowerSupport.Initialize();
            }
            SupportModule.Initialize();

            MelonModLogger.Log("------------------------------");
            MelonModLogger.Log("Unity " + UnityVersion);
            MelonModLogger.Log("------------------------------");
            MelonModLogger.Log("Name: " + CurrentGameAttribute.GameName);
            MelonModLogger.Log("Developer: " + CurrentGameAttribute.Developer);
            MelonModLogger.Log("Type: " + (Imports.IsIl2CppGame() ? "Il2Cpp" : (Imports.IsOldMono() ? "Mono" : "MonoBleedingEdge")));
            MelonModLogger.Log("------------------------------");
            MelonModLogger.Log("Using v" + BuildInfo.Version + " Open-Beta");
            MelonModLogger.Log("------------------------------");

            LoadDLLs();
            if (Plugins.Count > 0)
            {
                for (int i = 0; i < Plugins.Count; i++)
                {
                    MelonPlugin plugin = Plugins[i];
                    if (plugin != null)
                    {
                        MelonModLogger.Log(plugin.InfoAttribute.Name
                                           + (!string.IsNullOrEmpty(plugin.InfoAttribute.Version)
                            ? (" v" + plugin.InfoAttribute.Version) : "")
                                           + (!string.IsNullOrEmpty(plugin.InfoAttribute.Author)
                            ? (" by " + plugin.InfoAttribute.Author) : "")
                                           + (!string.IsNullOrEmpty(plugin.InfoAttribute.DownloadLink)
                            ? (" (" + plugin.InfoAttribute.DownloadLink + ")")
                            : "")
                                           );
                        MelonModLogger.LogDLLStatus(plugin.Compatibility);
                        MelonModLogger.Log("------------------------------");
                    }
                }
                Plugins = TempPlugins;
            }
            if (Plugins.Count <= 0)
            {
                MelonModLogger.Log("No Plugins Loaded!");
                MelonModLogger.Log("------------------------------");
            }

            if (Mods.Count > 0)
            {
                for (int i = 0; i < Mods.Count; i++)
                {
                    MelonMod mod = Mods[i];
                    if (mod != null)
                    {
                        MelonModLogger.Log(mod.InfoAttribute.Name
                                           + (!string.IsNullOrEmpty(mod.InfoAttribute.Version)
                            ? (" v" + mod.InfoAttribute.Version) : "")
                                           + (!string.IsNullOrEmpty(mod.InfoAttribute.Author)
                            ? (" by " + mod.InfoAttribute.Author) : "")
                                           + (!string.IsNullOrEmpty(mod.InfoAttribute.DownloadLink)
                            ? (" (" + mod.InfoAttribute.DownloadLink + ")")
                            : "")
                                           );
                        MelonModLogger.LogDLLStatus(mod.Compatibility);
                        MelonModLogger.Log("------------------------------");
                    }
                }
                Mods.RemoveAll((MelonMod mod) => (mod.Compatibility >= MelonBase.MelonCompatibility.INCOMPATIBLE));
                DependencyGraph <MelonMod> .TopologicalSort(Mods, mod => mod.InfoAttribute.Name);
            }
            if (Mods.Count <= 0)
            {
                MelonModLogger.Log("No Mods Loaded!");
                MelonModLogger.Log("------------------------------");
            }

            if ((Plugins.Count > 0) || (Mods.Count > 0))
            {
                AddUnityDebugLog();
            }

            if (Plugins.Count > 0)
            {
                HashSet <MelonPlugin> failedPlugins = new HashSet <MelonPlugin>();
                for (int i = 0; i < Plugins.Count; i++)
                {
                    MelonPlugin plugin = Plugins[i];
                    if (plugin != null)
                    {
                        try { InitializeModOrPlugin(plugin); } catch (Exception ex) { MelonModLogger.LogDLLError(ex.ToString(), plugin.InfoAttribute.Name); failedPlugins.Add(plugin); }
                    }
                }
                Plugins.RemoveAll(plugin => failedPlugins.Contains(plugin));
            }

            if (Mods.Count > 0)
            {
                HashSet <MelonMod> failedMods = new HashSet <MelonMod>();
                for (int i = 0; i < Mods.Count; i++)
                {
                    MelonMod mod = Mods[i];
                    if (mod != null)
                    {
                        try { InitializeModOrPlugin(mod); } catch (Exception ex) { MelonModLogger.LogDLLError(ex.ToString(), mod.InfoAttribute.Name); failedMods.Add(mod); }
                    }
                }
                Mods.RemoveAll(mod => failedMods.Contains(mod));
            }

            if ((Plugins.Count <= 0) && (Mods.Count <= 0))
            {
                SupportModule.Destroy();
            }
        }
 private HarmonyIl2CppMethodPatcher(MethodBase original) : base(original)
 {
     originalMethodInfoPointer = UnhollowerSupport.MethodBaseToIl2CppMethodInfoPointer(Original);
     copiedMethodInfoPointer   = (IntPtr)UnhollowerSupport.CopyMethodInfoStructMethod.Invoke(null, new object[] { originalMethodInfoPointer });
 }
        private static void ConvertArgument(ILGenerator il, Type paramType, ref LocalBuilder byRefLocal)
        {
            if (paramType.IsValueType)
            {
                return;
            }

            Type currentType = paramType;
            bool byRef       = paramType.IsByRef;

            if (byRef)
            {
                currentType = paramType.GetElementType();
            }

            if (currentType == typeof(string))
            {
                // return Il2CppStringToManaged(ptr);

                // byRefLocal = Il2CppStringToManaged(*ptr);
                // return ref byRefLocal;

                if (byRef)
                {
                    byRefLocal = il.DeclareLocal(currentType);
                    il.Emit(OpCodes.Ldind_I);
                }

                il.Emit(OpCodes.Call, UnhollowerSupport.Il2CppStringToManagedMethod);

                if (byRef)
                {
                    il.Emit(OpCodes.Stloc, byRefLocal);
                    il.Emit(OpCodes.Ldloca, byRefLocal);
                }
            }
            else if (UnhollowerSupport.IsGeneratedAssemblyType(currentType))
            {
                // return ptr == 0 ? null : new SomeType(ptr);

                // byRefLocal = *ptr == 0 ? null : new SomeType(*ptr);
                // return ref byRefLocal;

                Label ptrNonZero = il.DefineLabel();
                Label done       = il.DefineLabel();

                if (byRef)
                {
                    byRefLocal = il.DeclareLocal(currentType);
                    il.Emit(OpCodes.Ldind_I);
                }

                il.Emit(OpCodes.Dup);
                il.Emit(OpCodes.Brtrue_S, ptrNonZero);
                il.Emit(OpCodes.Pop);

                if (!byRef)
                {
                    il.Emit(OpCodes.Ldnull);
                }

                il.Emit(OpCodes.Br_S, done);
                il.MarkLabel(ptrNonZero);
                il.Emit(OpCodes.Newobj, Il2CppConstuctor(currentType));

                if (byRef)
                {
                    il.Emit(OpCodes.Stloc, byRefLocal);
                }

                il.MarkLabel(done);

                if (byRef)
                {
                    il.Emit(OpCodes.Ldloca, byRefLocal);
                }
            }
        }