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); }
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); }
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); } } }
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); } } }
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); } } }
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 }
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)); }
public static void runtime_class_init(IntPtr klass) { if (MelonUtils.IsGameIl2Cpp()) { il2cpp_runtime_class_init(klass); } else { mono_runtime_class_init(klass); } }
public static void gchandle_free(uint gchandle) { if (MelonUtils.IsGameIl2Cpp()) { il2cpp_gchandle_free(gchandle); } else { mono_gchandle_free(gchandle); } }
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)); } }
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; } }
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(); } }
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); } }
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); } }
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); }
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(); }
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); }
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); } }
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);
public static void format_stack_trace(IntPtr ex, void *output, int output_size) { if (MelonUtils.IsGameIl2Cpp()) il2cpp_format_stack_trace(ex, output, output_size); }
public static IntPtr gchandle_get_target(uint gchandle) => MelonUtils.IsGameIl2Cpp() ? il2cpp_gchandle_get_target(gchandle) : mono_gchandle_get_target(gchandle);
public static IntPtr value_box(IntPtr klass, IntPtr val) => MelonUtils.IsGameIl2Cpp() ? il2cpp_value_box(klass, val) : mono_value_box(domain, klass, val);
public static uint gchandle_new(IntPtr obj, bool pinned) => MelonUtils.IsGameIl2Cpp() ? il2cpp_gchandle_new(obj, pinned) : mono_gchandle_new(obj, pinned ? 1 : 0);
public static IntPtr array_new(IntPtr elementTypeInfo, ulong length) => MelonUtils.IsGameIl2Cpp() ? il2cpp_array_new(elementTypeInfo, length) : mono_array_new(domain, elementTypeInfo, length);
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);
public static IntPtr object_new(IntPtr klass) => MelonUtils.IsGameIl2Cpp() ? il2cpp_object_new(klass) : mono_object_new(domain, klass);
public static IntPtr object_unbox(IntPtr obj) => MelonUtils.IsGameIl2Cpp() ? il2cpp_object_unbox(obj) : mono_object_unbox(obj);
public static uint field_get_offset(IntPtr field) => MelonUtils.IsGameIl2Cpp() ? il2cpp_field_get_offset(field) : mono_field_get_offset(field);
public static uint array_length(IntPtr array) => MelonUtils.IsGameIl2Cpp() ? il2cpp_array_length(array) : *(uint *)((long)array + IntPtr.Size * 3);