Example #1
0
 internal static string GetName(this ModdingAPI.ModInformation info)
 {
     if (MelonUtils.IsGameIl2Cpp())
     {
         if (name_get_method == null)
         {
             name_get_method = AccessTools.Property(typeof(ModdingAPI.ModInformation), "name").GetGetMethod();
         }
         if (name_get_method != null)
         {
             return((string)name_get_method.Invoke(info, new object[0]));
         }
     }
     else
     {
         if (name_field == null)
         {
             name_field = AccessTools.Field(typeof(ModdingAPI.ModInformation), "name");
         }
         if (name_field != null)
         {
             return((string)name_field.GetValue(info));
         }
     }
     return(null);
 }
Example #2
0
        public static IntPtr ResolveICall(string signature)
        {
            MelonDebug.Msg("Resolving ICall " + signature);
            IntPtr icallPtr;

            if (MelonUtils.IsGameIl2Cpp())
            {
                icallPtr = il2cpp_resolve_icall(signature);
            }
            else
            {
                // We generate a fake MonoMethod + MonoMethodSignature + MonoClass struct to exploit the lookup code and force resolve our icall without the class/method being registered
                // (Slaynash: Yes this is illegal)
                MonoMethod *monoMethod = IcallToFakeMonoMethod(signature);
                icallPtr = mono_lookup_internal_call((IntPtr)monoMethod);
                DestroyFakeMonoMethod(monoMethod);
            }

            if (icallPtr == IntPtr.Zero)
            {
                //MelonLogger.Error($"ICall {signature} not resolved");
                //return IntPtr.Zero;
                throw new Exception($"ICall {signature} not resolved");
            }
            MelonDebug.Msg($" > 0x{(long)icallPtr:X}");

            return(icallPtr);
        }
Example #3
0
 internal static void SetAuthor(this ModdingAPI.ModInformation info, string author)
 {
     if (MelonUtils.IsGameIl2Cpp())
     {
         if (author_method == null)
         {
             author_method = AccessTools.Property(typeof(ModdingAPI.ModInformation), "author").GetSetMethod();
         }
         if (author_method != null)
         {
             author_method.Invoke(info, new object[] { author });
         }
     }
     else
     {
         if (author_field == null)
         {
             author_field = AccessTools.Field(typeof(ModdingAPI.ModInformation), "author");
         }
         if (author_field != null)
         {
             author_field.SetValue(info, author);
         }
     }
 }
Example #4
0
 internal static void SetVersion(this ModdingAPI.ModInformation info, string version)
 {
     if (MelonUtils.IsGameIl2Cpp())
     {
         if (version_method == null)
         {
             version_method = AccessTools.Property(typeof(ModdingAPI.ModInformation), "version").GetSetMethod();
         }
         if (version_method != null)
         {
             version_method.Invoke(info, new object[] { version });
         }
     }
     else
     {
         if (version_field == null)
         {
             version_field = AccessTools.Field(typeof(ModdingAPI.ModInformation), "version");
         }
         if (version_field != null)
         {
             version_field.SetValue(info, version);
         }
     }
 }
Example #5
0
 internal static void SetName(this ModdingAPI.ModInformation info, string name)
 {
     if (MelonUtils.IsGameIl2Cpp())
     {
         if (name_set_method == null)
         {
             name_set_method = AccessTools.Property(typeof(ModdingAPI.ModInformation), "name").GetSetMethod();
         }
         if (name_set_method != null)
         {
             name_set_method.Invoke(info, new object[] { name });
         }
     }
     else
     {
         if (name_field == null)
         {
             name_field = AccessTools.Field(typeof(ModdingAPI.ModInformation), "name");
         }
         if (name_field != null)
         {
             name_field.SetValue(info, name);
         }
     }
 }
Example #6
0
 public static void format_exception(IntPtr ex, void *message, int message_size)
 {
     if (MelonUtils.IsGameIl2Cpp())
     {
         il2cpp_format_exception(ex, message, message_size);
     }
     // TODO Mono mono_format_exception
 }
Example #7
0
        public static IntPtr ManagedStringToInternal(string str)
        {
            if (str == null)
            {
                return(IntPtr.Zero);

                fixed(char *chars = str)
                return(MelonUtils.IsGameIl2Cpp() ? il2cpp_string_new_utf16(chars, str.Length) : mono_string_new_utf16(domain, chars, str.Length));
        }
Example #8
0
 public static void runtime_class_init(IntPtr klass)
 {
     if (MelonUtils.IsGameIl2Cpp())
     {
         il2cpp_runtime_class_init(klass);
     }
     else
     {
         mono_runtime_class_init(klass);
     }
 }
Example #9
0
 public static void gchandle_free(uint gchandle)
 {
     if (MelonUtils.IsGameIl2Cpp())
     {
         il2cpp_gchandle_free(gchandle);
     }
     else
     {
         mono_gchandle_free(gchandle);
     }
 }
Example #10
0
 public InternalAssembly(IntPtr ptr)
 {
     this.ptr = ptr;
     if (MelonUtils.IsGameIl2Cpp())
     {
         name = Marshal.PtrToStringAnsi(il2cpp_image_get_filename(this.ptr));
     }
     else
     {
         name = Marshal.PtrToStringAnsi(mono_image_get_filename(this.ptr));
     }
 }
Example #11
0
 public InternalClass(IntPtr ptr, string name, string name_space)
 {
     if (MelonUtils.IsGameIl2Cpp())
     {
         throw new NotImplementedException();
     }
     else
     {
         this.ptr        = ptr;
         this.name       = name;
         this.name_space = name_space;
     }
 }
Example #12
0
 public InternalClass(IntPtr ptr)
 {
     this.ptr = ptr;
     if (MelonUtils.IsGameIl2Cpp())
     {
         name       = Marshal.PtrToStringAnsi(il2cpp_class_get_name(ptr));
         name_space = Marshal.PtrToStringAnsi(il2cpp_class_get_namespace(ptr));
     }
     else
     {
         throw new NotImplementedException();
     }
 }
Example #13
0
        public static void runtime_class_init(IntPtr klass)
        {
            if (klass == IntPtr.Zero)
            {
                throw new ArgumentException("Class to init is null");
            }

            if (MelonUtils.IsGameIl2Cpp())
            {
                il2cpp_runtime_class_init(klass);
            }
            else
            {
                mono_runtime_class_init(klass);
            }
        }
Example #14
0
        unsafe static UnityInternals()
        {
            if (MelonUtils.IsGameIl2Cpp())
            {
                domain = il2cpp_domain_get();

                uint    assemblyCount = 0;
                IntPtr *assemblyArray = il2cpp_domain_get_assemblies(domain, ref assemblyCount);
                for (int i = 0; i < assemblyCount; ++i)
                {
                    assemblies.Add(new InternalAssembly(il2cpp_assembly_get_image(*(assemblyArray + i))));
                }
            }
            else
            {
                domain = mono_domain_get();

                string unityVersion = MelonUtils.GetUnityVersion();

                MonoClass *testclass = (MonoClass *)Marshal.AllocHGlobal(sizeof(MonoClass));
                testclass->applyZeroes();
                testclass->nested_in_0x04 = (IntPtr)0x1234;
                testclass->nested_in_0x08 = (IntPtr)0x5678;
                testclass->nested_in_0x0C = (IntPtr)0x9012;
                long returnedName = (long)mono_class_get_name((IntPtr)testclass);
                MelonDebug.Msg($"returnedName {returnedName:X}");
                Marshal.FreeHGlobal((IntPtr)testclass);
                if (returnedName == 0x1234)
                {
                    monoClassOffset = 0;
                }
                else if (returnedName == 0x5678)
                {
                    monoClassOffset = (uint)IntPtr.Size * 1;
                }
                else if (returnedName == 0x9012)
                {
                    monoClassOffset = (uint)IntPtr.Size * 2;
                }
                else
                {
                    throw new Exception("Failed to find MonoClass name offset");
                }

                MelonDebug.Msg("monoClassOffset? " + monoClassOffset);
            }
        }
Example #15
0
        public static IntPtr GetField(IntPtr clazz, string fieldName)
        {
            MelonDebug.Msg($"GetField {fieldName}");
            if (clazz == IntPtr.Zero)
            {
                return(IntPtr.Zero);
            }

            var field = MelonUtils.IsGameIl2Cpp() ? il2cpp_class_get_field_from_name(clazz, fieldName) : mono_class_get_field_from_name(clazz, fieldName);

            if (field == IntPtr.Zero)
            {
                throw new Exception($"Field {fieldName} was not found on class {Marshal.PtrToStringAnsi(MelonUtils.IsGameIl2Cpp() ? il2cpp_class_get_name(clazz) : mono_class_get_name(clazz))}");
            }
            MelonDebug.Msg($" > 0x{(long)field:X}");
            return(field);
        }
        private bool CheckPlatformDomainAttribute()
        {
            MelonPlatformDomainAttribute platformDomainAttribute = MelonUtils.PullAttributeFromAssembly <MelonPlatformDomainAttribute>(Assembly);

            if ((platformDomainAttribute == null) ||
                (platformDomainAttribute.Domain == MelonPlatformDomainAttribute.CompatibleDomains.UNIVERSAL))
            {
                return(true);
            }
            bool is_il2cpp_expected_mono = (MelonUtils.IsGameIl2Cpp() && (platformDomainAttribute.Domain == MelonPlatformDomainAttribute.CompatibleDomains.MONO));
            bool is_mono_expected_il2cpp = (!MelonUtils.IsGameIl2Cpp() && (platformDomainAttribute.Domain == MelonPlatformDomainAttribute.CompatibleDomains.IL2CPP));

            if (is_il2cpp_expected_mono || is_mono_expected_il2cpp)
            {
                MelonLogger.Error($"Incompatible Platform Domain for {(is_plugin ? "Plugin" : "Mod")}: {FilePath}");
                return(false);
            }
            return(true);
        }
Example #17
0
        public override void Setup()
        {
            HarmonyLib.Harmony harmony = new HarmonyLib.Harmony("DemeoIntegration");

            harmony.Patch(typeof(GameStateMachine).GetMethod("GetConnectionString", BindingFlags.Public | BindingFlags.Static),
                          typeof(Demeo_Module).GetMethod("GetConnectionString", BindingFlags.NonPublic | BindingFlags.Static).ToNewHarmonyMethod());

            if (MelonUtils.IsGameIl2Cpp())
            {
                Il2Cpp.Patch(harmony);
            }
            else
            {
                Mono.Patch(harmony);
            }

            MelonCompatibilityLayer.AddRefreshPluginsEvent(Refresh);
            MelonCompatibilityLayer.AddRefreshModsEvent(Refresh);
            Refresh();
        }
Example #18
0
        private bool CheckPlatformDomainAttribute()
        {
            MelonPlatformDomainAttribute platformDomainAttribute = MelonUtils.PullAttributeFromAssembly <MelonPlatformDomainAttribute>(Assembly);

            if ((platformDomainAttribute == null) ||
                (platformDomainAttribute.Domain == MelonPlatformDomainAttribute.CompatibleDomains.UNIVERSAL))
            {
                return(true);
            }

            bool is_acceptable = MelonUtils.IsGameIl2Cpp()
                ? (platformDomainAttribute.Domain == MelonPlatformDomainAttribute.CompatibleDomains.IL2CPP)
                : (platformDomainAttribute.Domain == MelonPlatformDomainAttribute.CompatibleDomains.MONO);

            if (!is_acceptable)
            {
                MelonLogger.Error($"Incompatible Platform Domain for {(is_plugin ? "Plugin" : "Mod")}: {FilePath}");
                return(false);
            }

            return(true);
        }
Example #19
0
        internal static IntPtr GetClass(string assemblyname, string name_space, string classname)
        {
            MelonDebug.Msg($"GetClass {assemblyname} {name_space} {classname}");
            if (MelonUtils.IsGameIl2Cpp())
            {
                InternalAssembly assembly = assemblies.FirstOrDefault(a => a.name == assemblyname);
                if (assembly == null)
                {
                    throw new Exception("Unable to find assembly " + assemblyname + " in il2cpp domain");
                }

                IntPtr clazz = il2cpp_class_from_name(assembly.ptr, name_space, classname);
                if (clazz == null)
                {
                    throw new Exception("Unable to find class " + name_space + "." + classname + " in assembly " + assemblyname);
                }

                MelonDebug.Msg($" > 0x{(long)clazz:X}");
                return(clazz);
            }
            else
            {
                string   fullname = string.IsNullOrEmpty(name_space) ? "" : (name_space + ".") + classname;
                Assembly ass      = AppDomain.CurrentDomain.GetAssemblies().FirstOrDefault(a => a.GetName().Name + ".dll" == assemblyname);
                if (ass == null)
                {
                    throw new Exception("Unable to find assembly " + assemblyname + " in mono domain");
                }

                Type t = ass.GetType(fullname);
                if (t == null)
                {
                    throw new Exception("Unable to find class " + fullname + " in assembly " + assemblyname);
                }
                MelonDebug.Msg($" > 0x{(long)(*(IntPtr*)t.TypeHandle.Value):X}");
                return(*(IntPtr *)t.TypeHandle.Value);
            }
        }
Example #20
0
 public static IntPtr runtime_invoke(IntPtr method, IntPtr obj, void **param, ref IntPtr exc) =>
 MelonUtils.IsGameIl2Cpp() ? il2cpp_runtime_invoke(method, obj, param, ref exc) : mono_runtime_invoke(method, obj, param, ref exc);
Example #21
0
 public static void format_stack_trace(IntPtr ex, void *output, int output_size)
 {
     if (MelonUtils.IsGameIl2Cpp())
         il2cpp_format_stack_trace(ex, output, output_size); }
Example #22
0
 public static IntPtr gchandle_get_target(uint gchandle) =>
 MelonUtils.IsGameIl2Cpp() ? il2cpp_gchandle_get_target(gchandle) : mono_gchandle_get_target(gchandle);
Example #23
0
 public static IntPtr value_box(IntPtr klass, IntPtr val) =>
 MelonUtils.IsGameIl2Cpp() ? il2cpp_value_box(klass, val) : mono_value_box(domain, klass, val);
Example #24
0
 public static uint gchandle_new(IntPtr obj, bool pinned) =>
 MelonUtils.IsGameIl2Cpp() ? il2cpp_gchandle_new(obj, pinned) : mono_gchandle_new(obj, pinned ? 1 : 0);
Example #25
0
 public static IntPtr array_new(IntPtr elementTypeInfo, ulong length) =>
 MelonUtils.IsGameIl2Cpp() ? il2cpp_array_new(elementTypeInfo, length) : mono_array_new(domain, elementTypeInfo, length);
Example #26
0
 public static int class_value_size(IntPtr klass, ref uint align) =>
 MelonUtils.IsGameIl2Cpp() ? il2cpp_class_value_size(klass, ref align) : mono_class_value_size(klass, ref align);
Example #27
0
 public static IntPtr object_new(IntPtr klass) =>
 MelonUtils.IsGameIl2Cpp() ? il2cpp_object_new(klass) : mono_object_new(domain, klass);
Example #28
0
 public static IntPtr object_unbox(IntPtr obj) =>
 MelonUtils.IsGameIl2Cpp() ? il2cpp_object_unbox(obj) : mono_object_unbox(obj);
Example #29
0
 public static uint field_get_offset(IntPtr field) =>
 MelonUtils.IsGameIl2Cpp() ? il2cpp_field_get_offset(field) : mono_field_get_offset(field);
Example #30
0
 public static uint array_length(IntPtr array) =>
 MelonUtils.IsGameIl2Cpp() ? il2cpp_array_length(array) : *(uint *)((long)array + IntPtr.Size * 3);