From f079ea89ff1587466fb6006829a9811b105f211a Mon Sep 17 00:00:00 2001 From: Trevor Date: Fri, 6 Jun 2025 02:08:41 -0400 Subject: [PATCH 1/8] Add linux-bionic-arm64 support to the Bootstrap --- Directory.Build.props | 12 +- MelonLoader.Bootstrap/BionicNativeAot.targets | 81 + MelonLoader.Bootstrap/Core.cs | 24 +- .../Deps/linux-bionic-arm64/libdobby.a | Bin 0 -> 968846 bytes .../Deps/linux-bionic-arm64/libplthook.a | Bin 0 -> 11176 bytes MelonLoader.Bootstrap/Exports.cs | 32 +- MelonLoader.Bootstrap/LibcNative.cs | 19 + MelonLoader.Bootstrap/Logging/MelonLogger.cs | 24 + .../MelonLoader.Bootstrap.csproj | 14 +- MelonLoader.Bootstrap/PltHook.cs | 5 + .../Proxy/Android/AndroidBootstrap.cs | 228 +++ .../Proxy/Android/AndroidProxy.cs | 85 + .../Proxy/Android/StdRedirect.cs | 73 + .../RuntimeHandlers/Il2Cpp/ClrMonoLib.cs | 65 + .../RuntimeHandlers/Il2Cpp/Dotnet.cs | 12 + .../RuntimeHandlers/Il2Cpp/Il2CppHandler.cs | 88 + .../RuntimeHandlers/Il2Cpp/Il2CppLib.cs | 69 +- .../RuntimeHandlers/Mono/MonoHandler.cs | 2 +- MelonLoader.Bootstrap/SharedDelegates.cs | 5 + MelonLoader.Bootstrap/Utils/WineUtils.cs | 5 +- MelonLoader.Bootstrap/androidexports.def | 17 + MelonLoader/JNI/JArray.cs | 39 + MelonLoader/JNI/JClass.cs | 148 ++ MelonLoader/JNI/JFieldID.cs | 24 + MelonLoader/JNI/JMethodID.cs | 24 + MelonLoader/JNI/JNI.cs | 1447 +++++++++++++++++ MelonLoader/JNI/JNIEnv.cs | 713 ++++++++ MelonLoader/JNI/JNIResultException.cs | 15 + MelonLoader/JNI/JObject.cs | 67 + MelonLoader/JNI/JObjectArray.cs | 35 + MelonLoader/JNI/JString.cs | 10 + MelonLoader/JNI/JThrowable.cs | 12 + MelonLoader/JNI/JThrowableException.cs | 17 + MelonLoader/JNI/JValue.cs | 158 ++ MelonLoader/JNI/JavaVM.cs | 40 + MelonLoader/JNI/ReferenceType.cs | 13 + MelonLoader/JNI/ReleaseMode.cs | 13 + MelonLoader/JNI/Result.cs | 41 + MelonLoader/JNI/TypeSignature.cs | 69 + MelonLoader/JNI/Version.cs | 15 + MelonLoader/LoaderConfig.cs | 2 +- MelonLoader/Utils/APKAssetManager.cs | 288 ++++ README.md | 2 + 43 files changed, 4032 insertions(+), 20 deletions(-) create mode 100644 MelonLoader.Bootstrap/BionicNativeAot.targets create mode 100644 MelonLoader.Bootstrap/Deps/linux-bionic-arm64/libdobby.a create mode 100644 MelonLoader.Bootstrap/Deps/linux-bionic-arm64/libplthook.a create mode 100644 MelonLoader.Bootstrap/Proxy/Android/AndroidBootstrap.cs create mode 100644 MelonLoader.Bootstrap/Proxy/Android/AndroidProxy.cs create mode 100644 MelonLoader.Bootstrap/Proxy/Android/StdRedirect.cs create mode 100644 MelonLoader.Bootstrap/RuntimeHandlers/Il2Cpp/ClrMonoLib.cs create mode 100644 MelonLoader.Bootstrap/androidexports.def create mode 100644 MelonLoader/JNI/JArray.cs create mode 100644 MelonLoader/JNI/JClass.cs create mode 100644 MelonLoader/JNI/JFieldID.cs create mode 100644 MelonLoader/JNI/JMethodID.cs create mode 100644 MelonLoader/JNI/JNI.cs create mode 100644 MelonLoader/JNI/JNIEnv.cs create mode 100644 MelonLoader/JNI/JNIResultException.cs create mode 100644 MelonLoader/JNI/JObject.cs create mode 100644 MelonLoader/JNI/JObjectArray.cs create mode 100644 MelonLoader/JNI/JString.cs create mode 100644 MelonLoader/JNI/JThrowable.cs create mode 100644 MelonLoader/JNI/JThrowableException.cs create mode 100644 MelonLoader/JNI/JValue.cs create mode 100644 MelonLoader/JNI/JavaVM.cs create mode 100644 MelonLoader/JNI/ReferenceType.cs create mode 100644 MelonLoader/JNI/ReleaseMode.cs create mode 100644 MelonLoader/JNI/Result.cs create mode 100644 MelonLoader/JNI/TypeSignature.cs create mode 100644 MelonLoader/JNI/Version.cs create mode 100644 MelonLoader/Utils/APKAssetManager.cs diff --git a/Directory.Build.props b/Directory.Build.props index 3cc075207..4a8186bde 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -24,6 +24,15 @@ .a + + linux-bionic-arm64 + linux-bionic-arm64 + arm64 + $(DefineConstants);ANDROID + lib + .a + + osx-x64 @@ -34,7 +43,8 @@ .a - + + win-x64;win-x86 win-$(Platform) $(DefineConstants);WINDOWS diff --git a/MelonLoader.Bootstrap/BionicNativeAot.targets b/MelonLoader.Bootstrap/BionicNativeAot.targets new file mode 100644 index 000000000..5c3e856ab --- /dev/null +++ b/MelonLoader.Bootstrap/BionicNativeAot.targets @@ -0,0 +1,81 @@ + + + + + $(RuntimeIdentifier.ToLower().StartsWith('android')) + $(RuntimeIdentifier.ToLower().StartsWith('linux-bionic')) + $([MSBuild]::IsOSPlatform('Windows')) + $([MSBuild]::IsOSPlatform('Linux')) + $([MSBuild]::IsOSPlatform('OSX')) + true + + + + + $(ANDROID_NDK_ROOT)\source.properties + windows-x86_64 + linux-x86_64 + darwin-x86_64 + $(ANDROID_NDK_ROOT)/toolchains/llvm/prebuilt/$(NdkHost)/sysroot + + $([System.IO.File]::ReadAllText('$(NdkPropertiesFile)')) + $([System.Text.RegularExpressions.Regex]::Match('$(BaseRevision)', 'Pkg.Revision\s*=\s*(\S+)').Groups[1].Value.Split('.')[0]) + 0 + + + + + $(ANDROID_NDK_ROOT)/toolchains/llvm/prebuilt/$(NdkHost)/bin/clang + $(ANDROID_NDK_ROOT)/toolchains/llvm/prebuilt/$(NdkHost)/bin/llvm-objcopy + + android_clang.cmd + android_llvm-objcopy.cmd + + + + + + + + + + + + + + + $([System.Int32]::Parse($([System.String]::Copy('$(NdkVersion)').Split('.')[0]))) + + + + + + + + + + $(ANDROID_NDK_ROOT)\toolchains\llvm\prebuilt\$(NdkHost)\bin\ + $(ANDROID_NDK_ROOT)/toolchains/llvm/prebuilt/$(NdkHost)/bin/ + + + + + + + + + + + + + + + + + + true + + + + diff --git a/MelonLoader.Bootstrap/Core.cs b/MelonLoader.Bootstrap/Core.cs index d72f36680..b367b6885 100644 --- a/MelonLoader.Bootstrap/Core.cs +++ b/MelonLoader.Bootstrap/Core.cs @@ -12,7 +12,7 @@ namespace MelonLoader.Bootstrap; public static class Core { -#if LINUX || OSX +#if LINUX || OSX || ANDROID [UnmanagedFunctionPointer(CallingConvention.Cdecl, CharSet = CharSet.Ansi)] private delegate nint DlsymFn(nint handle, string symbol); private static readonly DlsymFn HookDlsymDelegate = HookDlsym; @@ -40,10 +40,20 @@ public static void Init(nint moduleHandle) var exePath = Environment.ProcessPath!; GameDir = Path.GetDirectoryName(exePath)!; -#if !OSX - DataDir = Path.Combine(GameDir, Path.GetFileNameWithoutExtension(exePath) + "_Data"); -#else +#if ANDROID + DataDir = Proxy.Android.AndroidBootstrap.GetDataDir(); + if (!Proxy.Android.AndroidBootstrap.EnsurePerms()) + throw new Exception("Permissions not granted! MelonLoader cannot continue without permissions."); + + MelonLoader.Utils.APKAssetManager.Initialize(); + Proxy.Android.AndroidProxy.Log("JNI initialized!"); + + Proxy.Android.AndroidBootstrap.CopyMelonLoaderData(Proxy.Android.AndroidBootstrap.GetApkModificationDate()); + Proxy.Android.AndroidProxy.Log("APK assets copied!"); +#elif OSX DataDir = Path.Combine(Path.GetDirectoryName(GameDir)!, "Resources", "Data"); +#else + DataDir = Path.Combine(GameDir, Path.GetFileNameWithoutExtension(exePath) + "_Data"); #endif if (!Directory.Exists(DataDir)) return; @@ -55,7 +65,7 @@ public static void Init(nint moduleHandle) MelonLogger.Init(); -#if LINUX || OSX +#if LINUX || OSX || ANDROID PltHook.InstallHooks ([ ("dlsym", Marshal.GetFunctionPointerForDelegate(HookDlsymDelegate)) @@ -99,7 +109,7 @@ private static nint RedirectSymbol(nint handle, string symbolName, nint original return redirect.detourPtr; } -#if LINUX || OSX +#if LINUX || OSX || ANDROID private static nint HookDlsym(nint handle, string symbol) { nint originalSymbolAddress = LibcNative.Dlsym(handle, symbol); @@ -124,6 +134,8 @@ private static void InitConfig() Path.GetDirectoryName( Path.GetDirectoryName( Path.GetDirectoryName(Process.GetCurrentProcess().MainModule!.FileName)!))!)!; +#elif ANDROID + DataDir; // Android doesn't work with the GetCurrentProcess system so we use the cached DataDir #else Path.GetDirectoryName(Process.GetCurrentProcess().MainModule!.FileName)!; #endif diff --git a/MelonLoader.Bootstrap/Deps/linux-bionic-arm64/libdobby.a b/MelonLoader.Bootstrap/Deps/linux-bionic-arm64/libdobby.a new file mode 100644 index 0000000000000000000000000000000000000000..ad084b2e6267d4b616b137baa20d6bf205bcb9ce GIT binary patch literal 968846 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�FHj6>~b&bJ~}7th*L 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�hu%A($PqOE3wARd2$y+3k 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

r}f{exSj=47d4T>rW~ZuGKBn5qX&c| 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®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 literal 0 HcmV?d00001 diff --git a/MelonLoader.Bootstrap/Deps/linux-bionic-arm64/libplthook.a b/MelonLoader.Bootstrap/Deps/linux-bionic-arm64/libplthook.a new file mode 100644 index 0000000000000000000000000000000000000000..e676d82b65a72798545cb20806f40532d6df71fe GIT binary patch literal 11176 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 literal 0 HcmV?d00001 diff --git a/MelonLoader.Bootstrap/Exports.cs b/MelonLoader.Bootstrap/Exports.cs index 968c6bb3b..2acf6bb82 100644 --- a/MelonLoader.Bootstrap/Exports.cs +++ b/MelonLoader.Bootstrap/Exports.cs @@ -212,7 +212,7 @@ public static unsafe void LogMsg(ColorARGB* msgColor, char* msg, int msgLength, return; } - var mMsg = new ReadOnlySpan(msg, msgLength); + var mMsg = PointerToSpan(msg, msgLength); if (sectionColor == null || section == null) { @@ -220,13 +220,15 @@ public static unsafe void LogMsg(ColorARGB* msgColor, char* msg, int msgLength, return; } - MelonLogger.Log(*msgColor, mMsg, *sectionColor, new(section, sectionLength)); + var mSect = PointerToSpan(section, sectionLength); + + MelonLogger.Log(*msgColor, mMsg, *sectionColor, mSect); } [UnmanagedCallersOnly(EntryPoint = "LogError")] public static unsafe void LogError(char* msg, int msgLength, char* section, int sectionLength, bool warning) { - var mMsg = new ReadOnlySpan(msg, msgLength); + var mMsg = PointerToSpan(msg, msgLength); if (section == null) { if (warning) @@ -237,10 +239,22 @@ public static unsafe void LogError(char* msg, int msgLength, char* section, int return; } + var mSect = PointerToSpan(section, sectionLength); + if (warning) - MelonLogger.LogWarning(mMsg, new(section, sectionLength)); + MelonLogger.LogWarning(mMsg, mSect); else - MelonLogger.LogError(mMsg, new(section, sectionLength)); + MelonLogger.LogError(mMsg, mSect); + } + + private static unsafe ReadOnlySpan PointerToSpan(char* c, int length) + { +#if !ANDROID + return new(c, length); +#else + // Required to prevent strings from being mangled when logged on Android. + return System.Text.Encoding.UTF8.GetString(new ReadOnlySpan(c, length)).TrimEnd('\0', '\n', '\r'); +#endif } [UnmanagedCallersOnly(EntryPoint = "LogMelonInfo")] @@ -279,4 +293,12 @@ public static unsafe void GetLoaderConfig(nint* pConfig) { Marshal.StructureToPtr(LoaderConfig.Current, *pConfig, false); } + +#if ANDROID + [UnmanagedCallersOnly(EntryPoint = "GetJavaVM")] + public static unsafe IntPtr GetJavaVM() + { + return (IntPtr)MelonLoader.Java.JNI.VM; + } +#endif } diff --git a/MelonLoader.Bootstrap/LibcNative.cs b/MelonLoader.Bootstrap/LibcNative.cs index 1ffff1df2..16d198fd7 100644 --- a/MelonLoader.Bootstrap/LibcNative.cs +++ b/MelonLoader.Bootstrap/LibcNative.cs @@ -72,4 +72,23 @@ public static unsafe partial int LibCStartMain( [UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])] public static partial int FClose(nint stream); } +#endif + +#if ANDROID +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +namespace MelonLoader.Bootstrap; + +internal partial class LibcNative +{ + internal const int Stdout = 1; + internal const int Stderr = 2; + + internal const int SeekEnd = 2; + + [LibraryImport("libdl", EntryPoint = "dlsym", StringMarshalling = StringMarshalling.Utf8)] + [UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])] + public static partial nint Dlsym(nint handle, string symbol); +} #endif \ No newline at end of file diff --git a/MelonLoader.Bootstrap/Logging/MelonLogger.cs b/MelonLoader.Bootstrap/Logging/MelonLogger.cs index 54cb31e8e..07031bf94 100644 --- a/MelonLoader.Bootstrap/Logging/MelonLogger.cs +++ b/MelonLoader.Bootstrap/Logging/MelonLogger.cs @@ -163,7 +163,11 @@ public static void Log(ColorARGB msgColor, ReadOnlySpan msg) return; } +#if !ANDROID Console.WriteLine($"[{time.Pastel(timeColor)}] {msg.Pastel(msgColor)}"); +#else + Proxy.Android.AndroidProxy.Log($"[{time.Pastel(timeColor)}] {msg.Pastel(msgColor)}"); +#endif } public static void Log(ColorARGB msgColor, ReadOnlySpan msg, ColorARGB sectionColor, ReadOnlySpan sectionName) @@ -198,7 +202,11 @@ public static void Log(ColorARGB msgColor, ReadOnlySpan msg, ColorARGB sec return; } +#if !ANDROID Console.WriteLine($"[{time.Pastel(timeColor)}] [{sectionName.Pastel(sectionColor)}] {msg.Pastel(msgColor)}"); +#else + Proxy.Android.AndroidProxy.Log($"[{time.Pastel(timeColor)}] [{sectionName.Pastel(sectionColor)}] {msg.Pastel(msgColor)}"); +#endif } public static void LogWarning(ReadOnlySpan msg) @@ -244,7 +252,11 @@ public static void LogError(ReadOnlySpan msg) return; } +#if !ANDROID Console.WriteLine($"[{time}] {msg}".Pastel(ColorARGB.IndianRed)); +#else + Proxy.Android.AndroidProxy.Log($"[{time}] {msg}".Pastel(ColorARGB.IndianRed)); +#endif } public static void LogError(ReadOnlySpan msg, ReadOnlySpan sectionName) @@ -264,7 +276,11 @@ public static void LogError(ReadOnlySpan msg, ReadOnlySpan sectionNa return; } +#if !ANDROID Console.WriteLine($"[{time}] [{sectionName}] {msg}".Pastel(ColorARGB.IndianRed)); +#else + Proxy.Android.AndroidProxy.Log($"[{time}] [{sectionName}] {msg}".Pastel(ColorARGB.IndianRed)); +#endif } public static void LogMelonInfo(ColorARGB nameColor, ReadOnlySpan name, ReadOnlySpan info) @@ -297,7 +313,11 @@ public static void LogMelonInfo(ColorARGB nameColor, ReadOnlySpan name, Re return; } +#if !ANDROID Console.WriteLine($"[{time.Pastel(timeColor)}] {name.Pastel(nameColor)} {info}"); +#else + Proxy.Android.AndroidProxy.Log($"[{time.Pastel(timeColor)}] {name.Pastel(nameColor)} {info}"); +#endif } public static void LogSpacer() @@ -307,6 +327,10 @@ public static void LogSpacer() if (!ConsoleHandler.IsOpen) return; +#if !ANDROID Console.WriteLine(); +#else + Proxy.Android.AndroidProxy.Log(""); +#endif } } diff --git a/MelonLoader.Bootstrap/MelonLoader.Bootstrap.csproj b/MelonLoader.Bootstrap/MelonLoader.Bootstrap.csproj index fe86d2ad1..238afb12c 100644 --- a/MelonLoader.Bootstrap/MelonLoader.Bootstrap.csproj +++ b/MelonLoader.Bootstrap/MelonLoader.Bootstrap.csproj @@ -12,6 +12,8 @@ true + + linuxexports.def true @@ -21,6 +23,10 @@ Deps/$(RuntimeIdentifier)/osxentry.o true + + androidexports.def + true + @@ -62,6 +68,8 @@ + + @@ -84,9 +92,13 @@ Overwrite="true"/> - + + + + + diff --git a/MelonLoader.Bootstrap/PltHook.cs b/MelonLoader.Bootstrap/PltHook.cs index 9e7a75e32..5ec9a0500 100644 --- a/MelonLoader.Bootstrap/PltHook.cs +++ b/MelonLoader.Bootstrap/PltHook.cs @@ -35,8 +35,13 @@ internal static partial class PltHook [UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])] private static partial nint PlthookError(); +#if !ANDROID private static readonly string? PlayerFileName = Process.GetCurrentProcess().Modules.OfType() .FirstOrDefault(x => x.FileName.Contains("UnityPlayer"))?.FileName; +#else + private static readonly string? PlayerFileName = Process.GetCurrentProcess().Modules.OfType() + .FirstOrDefault(x => x.FileName.Contains("libunity.so"))?.FileName; +#endif internal static void InstallHooks(List<(string functionName, nint hookFunctionPtr)> hooks) { diff --git a/MelonLoader.Bootstrap/Proxy/Android/AndroidBootstrap.cs b/MelonLoader.Bootstrap/Proxy/Android/AndroidBootstrap.cs new file mode 100644 index 000000000..9d8de29e1 --- /dev/null +++ b/MelonLoader.Bootstrap/Proxy/Android/AndroidBootstrap.cs @@ -0,0 +1,228 @@ +#if ANDROID +using System.Diagnostics.CodeAnalysis; +using System.Runtime.InteropServices; +using System.Text; +using MelonLoader.Java; +using MelonLoader.Utils; + +namespace MelonLoader.Bootstrap.Proxy.Android; + +public static class AndroidBootstrap +{ + public static string? PackageName { get; private set; } + public static string? DotnetDir { get; private set; } + public static int ApiLevel { get; private set; } = 0; + + [RequiresDynamicCode("Calls Init then InitConfig ")] + public static unsafe int LoadBootstrap() + { + // linux-bionic .NET logs everything to stdout/err, this allows us to see these logs in logcat with our logs + StdRedirect.RedirectStdOut(); + StdRedirect.RedirectStdErr(); + + Core.Init(NativeLibrary.Load("libmain.so")); + return 1; + } + + public static void CopyMelonLoaderData(DateTimeOffset date) + { + var baseDataDir = Core.DataDir; + var melonloaderFolder = Path.Combine(Core.DataDir, "MelonLoader"); + var baseInternalFolder = $"/data/data/{PackageName}/"; + var dotnetFolder = $"/data/data/{PackageName}/dotnet"; + + // TODO: put up toasts as initial copy can take awhile + + if (Directory.Exists(melonloaderFolder)) + { + var fileModTime = Directory.GetLastWriteTimeUtc(melonloaderFolder); + if (fileModTime > date) + AndroidProxy.Log("MelonLoader folder is already up-to-date"); + else + APKAssetManager.SaveItemToDirectory("MelonLoader", baseDataDir, true); + } + else + APKAssetManager.SaveItemToDirectory("MelonLoader", baseDataDir, true); + + if (Directory.Exists(dotnetFolder)) + { + var fileModTime = Directory.GetLastWriteTimeUtc(dotnetFolder); + if (fileModTime > date) + AndroidProxy.Log("Dotnet folder is already up-to-date"); + else + APKAssetManager.SaveItemToDirectory("dotnet", baseInternalFolder, true); + } + else + APKAssetManager.SaveItemToDirectory("dotnet", baseInternalFolder, true); + + DotnetDir = Path.Combine(dotnetFolder); + } + + public static string GetDataDir() + { + JClass unityPlayer = JNI.FindClass("com/unity3d/player/UnityPlayer"); + JFieldID activityFieldId = JNI.GetStaticFieldID(unityPlayer, "currentActivity", "Landroid/app/Activity;"); + using JObject currentActivityObj = JNI.GetStaticObjectField(unityPlayer, activityFieldId); + using JString callObjectMethod = JNI.CallObjectMethod(currentActivityObj, JNI.GetMethodID(JNI.GetObjectClass(currentActivityObj), "getPackageName", "()Ljava/lang/String;")); + PackageName = callObjectMethod.GetString(); + + JClass environment = JNI.FindClass("android/os/Environment"); + using JObject getExtDir = JNI.CallStaticObjectMethod(environment, JNI.GetStaticMethodID(environment, "getExternalStorageDirectory", "()Ljava/io/File;")); + + JMethodID jMethodId = JNI.GetMethodID(JNI.GetObjectClass(getExtDir), "toString", "()Ljava/lang/String;"); + using JString objectMethod = JNI.CallObjectMethod(getExtDir, jMethodId); + + return Path.Combine(objectMethod.GetString(), "MelonLoader", PackageName); + } + + // TODO: test multiple android versions + public static bool EnsurePerms() + { + JClass versionClass = JNI.FindClass("android/os/Build$VERSION"); + JFieldID sdkIntField = JNI.GetStaticFieldID(versionClass, "SDK_INT", "I"); + ApiLevel = JNI.GetStaticField(versionClass, sdkIntField); + AndroidProxy.Log($"Android API Level: {ApiLevel}"); + + JClass threadClass = JNI.FindClass("android/app/ActivityThread"); + JMethodID currentActivityThreadId = JNI.GetStaticMethodID(threadClass, "currentActivityThread", "()Landroid/app/ActivityThread;"); + using JObject currentActivityThread = JNI.CallStaticObjectMethod(threadClass, currentActivityThreadId); + + JMethodID getApplicationMethodId = JNI.GetMethodID(JNI.GetObjectClass(currentActivityThread), "getApplication", "()Landroid/app/Application;"); + using JObject currentActivityObj = JNI.CallObjectMethod(currentActivityThread, getApplicationMethodId); + + if (!CheckManageAllFilesPermission(currentActivityObj)) + { + AndroidProxy.Log("Failed to get MANAGE_ALL_FILES permission."); + return false; + } + + if (!EnsurePermsWithUnity(currentActivityObj)) + { + AndroidProxy.Log("Failed to ensure permissions with Unity."); + return false; + } + + return true; + } + + private static bool CheckManageAllFilesPermission(JObject currentActivityObj) + { + if (ApiLevel < 30) + return true; // This part of the API does not exist on Android versions below 11 (API level 30) + + const int MAX_WAIT = 30000; // in milliseconds + + JClass environment = JNI.FindClass("android/os/Environment"); + JClass uri = JNI.FindClass("android/net/Uri"); + JClass intent = JNI.FindClass("android/content/Intent"); + + JMethodID isExternalStorageManagerMethodId = JNI.GetStaticMethodID(environment, "isExternalStorageManager", "()Z"); + bool isExternalStorageManager = JNI.CallStaticMethod(environment, isExternalStorageManagerMethodId); + if (JNI.ExceptionCheck()) + return false; + + if (isExternalStorageManager) + return true; + + using JString actionName = JNI.NewString("android.settings.MANAGE_APP_ALL_FILES_ACCESS_PERMISSION"); + + using JString packageName = JNI.NewString($"package:{PackageName}"); + + using JObject callStaticObjectMethod = JNI.CallStaticObjectMethod(uri, JNI.GetStaticMethodID(uri, "parse", "(Ljava/lang/String;)Landroid/net/Uri;"), packageName); + + JMethodID intentConstructor = JNI.GetMethodID(intent, "", "(Ljava/lang/String;Landroid/net/Uri;)V"); + using JObject initialIntent = JNI.NewObject(intent, intentConstructor, actionName, callStaticObjectMethod); + + JMethodID addFlagsMethodId = JNI.GetMethodID(intent, "addFlags", "(I)Landroid/content/Intent;"); + int flag = 0x10000000; // FLAG_ACTIVITY_NEW_TASK + using JObject flaggedIntent = JNI.CallObjectMethod(initialIntent, addFlagsMethodId, new JValue(flag)); + + JClass activityClass = JNI.GetObjectClass(currentActivityObj); + JMethodID startActivityMethod = JNI.GetMethodID(activityClass, "startActivity", "(Landroid/content/Intent;)V"); + JNI.CallVoidMethod(currentActivityObj, startActivityMethod, new JValue(flaggedIntent)); + + JNI.CheckExceptionAndThrow(); + + // TODO: this shouldn't sleep in the main thread; not sure if there is a better method + int totalWaitTime = 0; + while (totalWaitTime < MAX_WAIT) { + isExternalStorageManager = JNI.CallStaticMethod(environment, isExternalStorageManagerMethodId); + if (JNI.ExceptionCheck()) + return false; + + if (isExternalStorageManager) + return true; + + System.Threading.Thread.Sleep(250); + totalWaitTime += 250; + } + + AndroidProxy.Log("Timed out waiting for MANAGE_ALL_FILES permission, final check..."); + isExternalStorageManager = JNI.CallStaticMethod(environment, isExternalStorageManagerMethodId); + if (JNI.ExceptionCheck()) + return false; + + if (isExternalStorageManager) + return true; + + AndroidProxy.Log("Failed to get MANAGE_ALL_FILES permission after waiting."); + return false; + } + + private static bool EnsurePermsWithUnity(JObject currentActivityObj) { + if (ApiLevel >= 30) + return true; // Not necessary on Android 11+ as you need MANAGE_ALL_FILES_ACCESS_PERMISSION instead. + + string[] permissions = new string[] + { + "android.permission.WRITE_EXTERNAL_STORAGE", + "android.permission.READ_EXTERNAL_STORAGE", + "android.permission.MANAGE_EXTERNAL_STORAGE" + }; + + JClass unityPermissions = JNI.FindClass("com/unity3d/player/UnityPermissions"); + JClass unityWaitPermissionsClass = JNI.FindClass("com/unity3d/player/UnityPermissions$ModalWaitForPermissionResponse"); + + using JObject waitPermission = JNI.NewObject(unityWaitPermissionsClass, JNI.GetMethodID(unityWaitPermissionsClass, "", "()V")); + + using JArray permissionArray = new JArray(permissions.Length); + for (int i = 0; i < permissions.Length; i++) + { + permissionArray[i] = JNI.NewString(permissions[i]); + } + + JMethodID requestUserPermissionsId = JNI.GetStaticMethodID(unityPermissions, "requestUserPermissions", "(Landroid/app/Activity;[Ljava/lang/String;Lcom/unity3d/player/IPermissionRequestCallbacks;)V"); + JNI.CallStaticVoidMethod(unityPermissions, requestUserPermissionsId, new JValue(currentActivityObj), new JValue(permissionArray), new JValue(waitPermission)); + + if (JNI.ExceptionCheck()) + { + AndroidProxy.Log("Failed to request permissions."); + return false; + } + + JMethodID waitForResponseId = JNI.GetMethodID(JNI.GetObjectClass(waitPermission), "waitForResponse", "()Z"); + JNI.CallVoidMethod(waitPermission, waitForResponseId); + + if (JNI.ExceptionCheck()) + { + AndroidProxy.Log("Failed to wait for permission response."); + return false; + } + + return true; + } + + public static DateTimeOffset GetApkModificationDate() + { + var assetBytes = APKAssetManager.GetAssetBytes("lemon_patch_date.txt"); + string assetContent = Encoding.UTF8.GetString(assetBytes); + + // Now parse the string content into an RFC 3339 DateTime + // RFC 3339 is essentially ISO 8601, so DateTime.Parse can handle it. + if (DateTimeOffset.TryParse(assetContent, out DateTimeOffset date)) + return date; + + return default; + } +} +#endif \ No newline at end of file diff --git a/MelonLoader.Bootstrap/Proxy/Android/AndroidProxy.cs b/MelonLoader.Bootstrap/Proxy/Android/AndroidProxy.cs new file mode 100644 index 000000000..51012f959 --- /dev/null +++ b/MelonLoader.Bootstrap/Proxy/Android/AndroidProxy.cs @@ -0,0 +1,85 @@ +#if ANDROID +using System.Diagnostics.CodeAnalysis; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.InteropServices.Marshalling; +using MelonLoader.Java; +using MelonLoader.Bootstrap.Utils; + +namespace MelonLoader.Bootstrap.Proxy.Android; + +public static class AndroidProxy +{ + [DllImport("liblog", EntryPoint = "__android_log_print")] + private static extern int LogInternal(int prio, string tag, string text); + + public static void Log(string text) => LogInternal(4, "MelonLoader", text); + + [UnmanagedCallersOnly(CallConvs = [typeof(CallConvCdecl)])] + [RequiresDynamicCode("Calls MelonLoader.Bootstrap.Proxy.Android.AndroidBootstrap.LoadBootstrap()")] + private static unsafe byte Load(void* env, void* jobject, void* str) + { + LoadUnity(); + AndroidBootstrap.LoadBootstrap(); + return 1; + } + + public static unsafe void LoadUnity() + { + if (!NativeLibrary.TryLoad("libunity.so", out var libUnity)) + { + Log("Failed to load libunity.so"); + return; + } + + if (!NativeFunc.GetExport(libUnity, "JNI_OnLoad", out var jniOnLoad)) + { + Log("Can't load Export via JNI_OnLoad"); + return; + } + + jniOnLoad((IntPtr)JNI.VM, IntPtr.Zero); + } + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public delegate nint JNI_OnLoadFunc(IntPtr vm, IntPtr reserved); + + [UnmanagedCallersOnly(CallConvs = [typeof(CallConvCdecl)])] + private static unsafe byte Unload(void* vm, void* reserved) + { + Log("Unload called"); + return 1; + } + + [UnmanagedCallersOnly(EntryPoint = "JNI_OnLoad")] + public static unsafe JNI.Version JNI_OnLoad(IntPtr vm, void* reserved) + { + JNI.Initialize(vm); + JClass nativeLoader = JNI.FindClass("com/unity3d/player/NativeLoader"); + if (!nativeLoader.Valid()) + { + Log("Cannot find NativeLoader class"); + return JNI.Version.V1_6; + } + + var methods = (JNINativeMethod*)NativeMemory.Alloc((nuint)(sizeof(JNINativeMethod) * 2)); + + methods[0] = new JNINativeMethod { Name = Utf8StringMarshaller.ConvertToUnmanaged("load"), Signature = Utf8StringMarshaller.ConvertToUnmanaged("(Ljava/lang/String;)Z"), FnPtr = (delegate* unmanaged[Cdecl])&Load }; + methods[1] = new JNINativeMethod { Name = Utf8StringMarshaller.ConvertToUnmanaged("unload"), Signature = Utf8StringMarshaller.ConvertToUnmanaged("()Z"), FnPtr = (delegate* unmanaged[Cdecl])&Unload }; + + var registerNatives = JNI.Env->Functions->RegisterNatives(JNI.Env, nativeLoader.Handle, (IntPtr)methods, 2); + if (registerNatives != 0) + { + Log("Failed to register native methods"); + } + return JNI.Version.V1_6; + } + + private unsafe struct JNINativeMethod + { + public byte* Name; + public byte* Signature; + public void* FnPtr; + } +} +#endif \ No newline at end of file diff --git a/MelonLoader.Bootstrap/Proxy/Android/StdRedirect.cs b/MelonLoader.Bootstrap/Proxy/Android/StdRedirect.cs new file mode 100644 index 000000000..ea956fb0e --- /dev/null +++ b/MelonLoader.Bootstrap/Proxy/Android/StdRedirect.cs @@ -0,0 +1,73 @@ +#if ANDROID +using System.Runtime.InteropServices; +using System.Text; + +namespace MelonLoader.Bootstrap.Proxy.Android; + +internal static class StdRedirect +{ + private const int STDERR_FILENO = 2; + private const int STDOUT_FILENO = 1; + + [DllImport("libc.so", SetLastError = true)] + private static extern int pipe(int[] pipefd); + + [DllImport("libc.so", SetLastError = true)] + private static extern int dup2(int oldfd, int newfd); + + [DllImport("libc.so", SetLastError = true)] + private static extern IntPtr fdopen(int fd, string mode); + + [DllImport("libc.so", SetLastError = true)] + private static extern IntPtr fgets(byte[] buffer, int size, IntPtr stream); + + [DllImport("liblog.so", SetLastError = true)] + private static extern int __android_log_write(int prio, string tag, string text); + + public static void RedirectStdErr() + { + Environment.SetEnvironmentVariable("COREHOST_TRACE", "1"); + Environment.SetEnvironmentVariable("COREHOST_TRACE_VERBOSITY", "3"); + + RedirectStream(STDERR_FILENO, "MelonLoader"); + } + + public static void RedirectStdOut() + { + Environment.SetEnvironmentVariable("COREHOST_TRACE", "1"); + Environment.SetEnvironmentVariable("COREHOST_TRACE_VERBOSITY", "3"); + + RedirectStream(STDOUT_FILENO, "MelonLoader"); + } + + private static void RedirectStream(int fileno, string tag) + { + int[] pipes = new int[2]; + if (pipe(pipes) != 0) + { + Console.WriteLine("Failed to create pipe"); + return; + } + + dup2(pipes[1], fileno); + IntPtr inputFile = fdopen(pipes[0], "r"); + + Thread logThread = new Thread(() => + { + byte[] buffer = new byte[512]; + while (true) + { + IntPtr result = fgets(buffer, buffer.Length, inputFile); + if (result == IntPtr.Zero) + break; + + string logMsg = Encoding.UTF8.GetString(buffer).TrimEnd('\0', '\n', '\r'); + __android_log_write(3, tag, logMsg); // debug + } + }); + + logThread.IsBackground = true; + logThread.Start(); + } +} +#endif diff --git a/MelonLoader.Bootstrap/RuntimeHandlers/Il2Cpp/ClrMonoLib.cs b/MelonLoader.Bootstrap/RuntimeHandlers/Il2Cpp/ClrMonoLib.cs new file mode 100644 index 000000000..bcdac663e --- /dev/null +++ b/MelonLoader.Bootstrap/RuntimeHandlers/Il2Cpp/ClrMonoLib.cs @@ -0,0 +1,65 @@ +#if ANDROID +using MelonLoader.Bootstrap.Proxy.Android; +using MelonLoader.Bootstrap.Utils; +using System.Runtime.InteropServices; + +namespace MelonLoader.Bootstrap.RuntimeHandlers.Il2Cpp; + +// NOTE: parts of this are specific to a LemonLoader fork of dotnet/runtime +internal class ClrMonoLib +{ + public required nint Handle { get; init; } + + public required SetThreadCheckerDelegate SetThreadChecker { get; init; } + public required ThreadSuspendReloadDelegate ThreadSuspendReload { get; init; } + public required InstallUnhandledExceptionHookDelegate InstallUnhandledExceptionHook { get; init; } + public required PrintUnhandledExceptionDelegate PrintUnhandledException { get; init; } + public required SetStringDelegate SetLevelString { get; init; } + public required SetStringDelegate SetMaskString { get; init; } + + public static ClrMonoLib? TryLoad() + { + MelonDebug.Log("Loading CoreCLR Mono exports"); + + if (string.IsNullOrEmpty(AndroidBootstrap.DotnetDir)) + { + MelonDebug.Log("DotnetDir is not set, cannot load CoreCLR Mono exports."); + return null; + } + + if (!NativeLibrary.TryLoad(Path.Combine(AndroidBootstrap.DotnetDir, "shared", "Microsoft.NETCore.App", "8.0.6", "libcoreclr.so"), out var hRuntime) + || !NativeFunc.GetExport(hRuntime, "mono_melonloader_set_thread_checker", out var setThreadChecker) + || !NativeFunc.GetExport(hRuntime, "mono_melonloader_thread_suspend_reload", out var threadSuspendReload) + || !NativeFunc.GetExport(hRuntime, "mono_install_unhandled_exception_hook", out var installUnhandledExceptionHook) + || !NativeFunc.GetExport(hRuntime, "mono_print_unhandled_exception", out var printUnhandledException) + || !NativeFunc.GetExport(hRuntime, "mono_trace_set_level_string", out var setLevelString) + || !NativeFunc.GetExport(hRuntime, "mono_trace_set_mask_string", out var setMaskString)) + return null; + + return new() + { + Handle = hRuntime, + SetThreadChecker = setThreadChecker, + ThreadSuspendReload = threadSuspendReload, + InstallUnhandledExceptionHook = installUnhandledExceptionHook, + PrintUnhandledException = printUnhandledException, + SetLevelString = setLevelString, + SetMaskString = setMaskString + }; + } + + public delegate bool CheckThreadDelegate(ulong threadId); + public delegate void MonoUnhandledExceptionDelegate(IntPtr exc, IntPtr userData); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public delegate void SetThreadCheckerDelegate(CheckThreadDelegate checker); + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public delegate void ThreadSuspendReloadDelegate(); + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public delegate void InstallUnhandledExceptionHookDelegate(MonoUnhandledExceptionDelegate callback, IntPtr userData); + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public delegate void PrintUnhandledExceptionDelegate(IntPtr exc); + [UnmanagedFunctionPointer(CallingConvention.Cdecl, CharSet = CharSet.Ansi)] + public delegate void SetStringDelegate(string str); +} +#endif \ No newline at end of file diff --git a/MelonLoader.Bootstrap/RuntimeHandlers/Il2Cpp/Dotnet.cs b/MelonLoader.Bootstrap/RuntimeHandlers/Il2Cpp/Dotnet.cs index b3bbe1010..846c8bebb 100644 --- a/MelonLoader.Bootstrap/RuntimeHandlers/Il2Cpp/Dotnet.cs +++ b/MelonLoader.Bootstrap/RuntimeHandlers/Il2Cpp/Dotnet.cs @@ -18,6 +18,8 @@ internal static partial class Dotnet StringMarshalling.Utf8; #endif + private const string ANDROID_DOTNET_VERSION = "8.0.6"; + public static bool LoadHostfxr() { var path = GetHostfxrPath(); @@ -26,10 +28,20 @@ public static bool LoadHostfxr() private static string? GetHostfxrPath() { +#if ANDROID + if (string.IsNullOrEmpty(MelonLoader.Bootstrap.Proxy.Android.AndroidBootstrap.DotnetDir)) + { + MelonDebug.Log("DotnetDir is not set, cannot find hostfxr."); + return null; + } + + return Path.Combine(MelonLoader.Bootstrap.Proxy.Android.AndroidBootstrap.DotnetDir, "host", "fxr", ANDROID_DOTNET_VERSION, "libhostfxr.so"); +#else var buffer = new StringBuilder(1024); var bufferSize = (nint)buffer.Capacity; var result = get_hostfxr_path(buffer, ref bufferSize, 0); return result != 0 ? null : buffer.ToString(); +#endif } public static bool InitializeForRuntimeConfig(string runtimeConfigPath, out nint context) diff --git a/MelonLoader.Bootstrap/RuntimeHandlers/Il2Cpp/Il2CppHandler.cs b/MelonLoader.Bootstrap/RuntimeHandlers/Il2Cpp/Il2CppHandler.cs index 1cf310c33..8fa20ce4d 100644 --- a/MelonLoader.Bootstrap/RuntimeHandlers/Il2Cpp/Il2CppHandler.cs +++ b/MelonLoader.Bootstrap/RuntimeHandlers/Il2Cpp/Il2CppHandler.cs @@ -8,6 +8,9 @@ internal static class Il2CppHandler private static Action? startFunc; // Prevent GC private static Il2CppLib il2cpp = null!; +#if ANDROID + private static ClrMonoLib mono = null!; +#endif private static bool il2cppInitDone; private static bool invokeStarted; @@ -21,6 +24,16 @@ public static void Initialize(nint handle) } il2cpp = il2cppLib; + +#if ANDROID + var monoLib = ClrMonoLib.TryLoad(); + if (monoLib is null) + { + Core.Logger.Error("Could not load CoreCLR Mono"); + return; + } + mono = monoLib; +#endif } internal static nint InitDetour(nint a) @@ -57,6 +70,16 @@ private static void InitializeManaged() return; } +#if ANDROID + // Workaround so that we can use .NET 8 on Android without upgrading MelonLoader's .NET version + string runtimeConfig = File.ReadAllText(runtimeConfigPath); + if (runtimeConfig.Contains("net6")) + { + runtimeConfig = runtimeConfig.Replace("6.0", "8.0"); + File.WriteAllText(runtimeConfigPath, runtimeConfig); + } +#endif + MelonDebug.Log("Attempting to load hostfxr"); if (!Dotnet.LoadHostfxr()) { @@ -87,6 +110,10 @@ private static void InitializeManaged() return; } +#if ANDROID + ApplyMonoPatches(); +#endif + var startFuncPtr = Core.LibraryHandle; MelonDebug.Log("Invoking NativeHost entry"); @@ -115,6 +142,11 @@ internal static nint InvokeDetour(nint method, nint obj, nint args, nint exc) invokeStarted = true; MelonDebug.Log("Invoke hijacked"); +#if ANDROID + mono.ThreadSuspendReload(); + MelonDebug.Log("Mono thread reset"); +#endif + Start(); return result; @@ -135,6 +167,62 @@ private static unsafe void NativeHookDetachImpl(nint* target, nint detour) Dobby.HookDetach(*target); } +#if ANDROID + private static void ApplyMonoPatches() + { + MelonDebug.Log("Applying Mono runtime patches"); + + mono.SetLevelString("warning"); + mono.SetMaskString("all"); + + MelonDebug.Log("Enabled Mono logging"); + + mono.InstallUnhandledExceptionHook(MonoUnhandledExceptionHandler, IntPtr.Zero); + + MelonDebug.Log("Installed unhandled exception hook"); + + mono.SetThreadChecker(MonoCheckThread); + + MelonDebug.Log("Installed thread checker"); + } + + private static void MonoUnhandledExceptionHandler(IntPtr exc, IntPtr userData) + { + if (exc == IntPtr.Zero) + return; + + mono.PrintUnhandledException(exc); + } + + private static bool MonoCheckThread(ulong threadId) + { + UIntPtr size = 0; + + IntPtr threads = il2cpp.GetAllAttachedThreads(ref size); + IntPtr[] threadsSlice = new IntPtr[(int)size]; + Marshal.Copy(threads, threadsSlice, 0, threadsSlice.Length); + + for (int i = 0; i < threadsSlice.Length; i++) + { + Il2CppThread thread = Marshal.PtrToStructure(threadsSlice[i]); + IntPtr internalThreadPtr = thread.internal_thread; + + if (internalThreadPtr != IntPtr.Zero) + { + Il2CppInternalThread internalThread = Marshal.PtrToStructure(internalThreadPtr); + + if (internalThread.tid == threadId) + { + MelonDebug.Log($"Attached IL2CPP thread {internalThread.tid:X}"); + return false; + } + } + } + + return true; + } +#endif + // Requires the bootstrap handle to be passed first private delegate void InitializeFn(ref nint startFunc); } diff --git a/MelonLoader.Bootstrap/RuntimeHandlers/Il2Cpp/Il2CppLib.cs b/MelonLoader.Bootstrap/RuntimeHandlers/Il2Cpp/Il2CppLib.cs index b91ab1c2f..88b48f94a 100644 --- a/MelonLoader.Bootstrap/RuntimeHandlers/Il2Cpp/Il2CppLib.cs +++ b/MelonLoader.Bootstrap/RuntimeHandlers/Il2Cpp/Il2CppLib.cs @@ -9,19 +9,22 @@ internal class Il2CppLib(Il2CppLib.MethodGetNameFn methodGetName) public required InitFn Init { get; init; } public required RuntimeInvokeFn RuntimeInvoke { get; init; } + public required GetAllAttachedThreadsDelegate GetAllAttachedThreads { get; init; } public static Il2CppLib? TryLoad(nint hRuntime) { if (!NativeFunc.GetExport(hRuntime, "il2cpp_init", out var init) || !NativeFunc.GetExport(hRuntime, "il2cpp_runtime_invoke", out var runtimeInvoke) - || !NativeFunc.GetExport(hRuntime, "il2cpp_method_get_name", out var methodGetName)) + || !NativeFunc.GetExport(hRuntime, "il2cpp_method_get_name", out var methodGetName) + || !NativeFunc.GetExport(hRuntime, "il2cpp_thread_get_all_attached_threads", out var getAllAttached)) return null; return new(methodGetName) { Handle = hRuntime, Init = init, - RuntimeInvoke = runtimeInvoke + RuntimeInvoke = runtimeInvoke, + GetAllAttachedThreads = getAllAttached }; } @@ -36,4 +39,66 @@ internal class Il2CppLib(Il2CppLib.MethodGetNameFn methodGetName) public delegate nint RuntimeInvokeFn(nint method, nint obj, nint args, nint exc); [UnmanagedFunctionPointer(CallingConvention.Cdecl)] public delegate nint MethodGetNameFn(nint method); + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public delegate IntPtr GetAllAttachedThreadsDelegate(ref UIntPtr size); } + +[StructLayout(LayoutKind.Sequential)] +public struct Il2CppObject +{ + private IntPtr data; + private IntPtr monitor; +} + +[StructLayout(LayoutKind.Sequential)] +public struct Il2CppInternalThread +{ + public Il2CppObject obj; + public int lock_thread_id; + public IntPtr handle; + public IntPtr native_handle; + public IntPtr cached_culture_info; + public IntPtr name; + public int name_len; + public uint state; + public IntPtr abort_exc; + public int abort_state_handle; + public ulong tid; + public IntPtr debugger_thread; + public IntPtr static_data; + public IntPtr runtime_thread_info; + public IntPtr current_appcontext; + public IntPtr root_domain_thread; + public IntPtr _serialized_principal; + public int _serialized_principal_version; + public IntPtr appdomain_refs; + public int interruption_requested; + public IntPtr synch_cs; + public byte threadpool_thread; + public byte thread_interrupt_requested; + public int stack_size; + public byte apartment_state; + public int critical_region_level; + public int managed_id; + public uint small_id; + public IntPtr manage_callback; + public IntPtr interrupt_on_stop; + public IntPtr flags; + public IntPtr thread_pinning_ref; + public IntPtr abort_protected_block_count; + public int priority; + public IntPtr owned_mutexes; + public IntPtr suspended; + public int self_suspended; + public ulong thread_state; + public ulong unused2; + public IntPtr last; +} + +[StructLayout(LayoutKind.Sequential)] +public struct Il2CppThread +{ + // Truncated just for the things needed + public Il2CppObject obj; + public IntPtr internal_thread; +} \ No newline at end of file diff --git a/MelonLoader.Bootstrap/RuntimeHandlers/Mono/MonoHandler.cs b/MelonLoader.Bootstrap/RuntimeHandlers/Mono/MonoHandler.cs index 11da90e9c..9092fee77 100644 --- a/MelonLoader.Bootstrap/RuntimeHandlers/Mono/MonoHandler.cs +++ b/MelonLoader.Bootstrap/RuntimeHandlers/Mono/MonoHandler.cs @@ -15,7 +15,7 @@ internal static class MonoHandler private const char MonoPathSeparator = #if WINDOWS ';'; -#elif LINUX || OSX +#elif LINUX || OSX || ANDROID ':'; #endif diff --git a/MelonLoader.Bootstrap/SharedDelegates.cs b/MelonLoader.Bootstrap/SharedDelegates.cs index b5060ef52..dbf999d98 100644 --- a/MelonLoader.Bootstrap/SharedDelegates.cs +++ b/MelonLoader.Bootstrap/SharedDelegates.cs @@ -30,3 +30,8 @@ namespace MelonLoader.Bootstrap; [UnmanagedFunctionPointer(CallingConvention.StdCall)] internal delegate void GetLoaderConfigFn(ref LoaderConfig config); + +#if ANDROID +[UnmanagedFunctionPointer(CallingConvention.StdCall)] +internal delegate System.IntPtr GetJavaVM(); +#endif \ No newline at end of file diff --git a/MelonLoader.Bootstrap/Utils/WineUtils.cs b/MelonLoader.Bootstrap/Utils/WineUtils.cs index b82a7dac7..e005efa2e 100644 --- a/MelonLoader.Bootstrap/Utils/WineUtils.cs +++ b/MelonLoader.Bootstrap/Utils/WineUtils.cs @@ -13,9 +13,8 @@ static WineUtils() #if WINDOWS if (NativeLibrary.TryLoad("ntdll.dll", out var ntdll) && NativeLibrary.TryGetExport(ntdll, "wine_get_version", out _)) IsWine = true; -#endif -#if LINUX - IsWine = false; +#else + IsWine = false; #endif } } diff --git a/MelonLoader.Bootstrap/androidexports.def b/MelonLoader.Bootstrap/androidexports.def new file mode 100644 index 000000000..2e3310eb2 --- /dev/null +++ b/MelonLoader.Bootstrap/androidexports.def @@ -0,0 +1,17 @@ +{ + global: + DotNetRuntimeDebugHeader; + NativeHookAttach; + NativeHookDetach; + LogMsg; + LogError; + LogMelonInfo; + MonoInstallHooks; + MonoGetDomainPtr; + MonoGetRuntimeHandle; + IsConsoleOpen; + GetLoaderConfig; + GetJavaVM; + JNI_OnLoad; + local: *; +}; diff --git a/MelonLoader/JNI/JArray.cs b/MelonLoader/JNI/JArray.cs new file mode 100644 index 000000000..94f677ad3 --- /dev/null +++ b/MelonLoader/JNI/JArray.cs @@ -0,0 +1,39 @@ +#if ANDROID +namespace MelonLoader.Java; + +using System.Collections; +using System.Collections.Generic; + +public class JArray : JObject, IEnumerable +{ + public JArray() : base() { } + + public JArray(int size) => JNI.NewArray(size); + + public int Length => JNI.GetArrayLength(this); + + public T this[int index] + { + get => JNI.GetArrayElement(this, index); + set => JNI.SetArrayElement(this, index, value); + } + + public T[] GetElements() + { + return JNI.GetArrayElements(this); + } + + public IEnumerator GetEnumerator() + { + for (int i = 0; i < this.Length; i++) + { + yield return JNI.GetArrayElement(this, i); + } + } + + IEnumerator IEnumerable.GetEnumerator() + { + return this.GetEnumerator(); + } +} +#endif diff --git a/MelonLoader/JNI/JClass.cs b/MelonLoader/JNI/JClass.cs new file mode 100644 index 000000000..a55b08430 --- /dev/null +++ b/MelonLoader/JNI/JClass.cs @@ -0,0 +1,148 @@ +#if ANDROID +using System.Collections.Generic; + +namespace MelonLoader.Java; + +public class JClass : JObject +{ + private Dictionary<(string, string), JFieldID> FieldCache { get; set; } = new(); + + private Dictionary<(string, string), JMethodID> MethodCache { get; set; } = new(); + + public JClass() : base() { } + + public JFieldID GetFieldID(string name, string sig) + { + (string, string) key = new(name, sig); + + if (this.FieldCache.TryGetValue(key, out JFieldID found)) + { + return found; + } + else + { + JFieldID id = JNI.GetFieldID(this, name, sig); + this.FieldCache.Add(key, id); + return id; + } + } + + public JFieldID GetStaticFieldID(string name, string sig) + { + (string, string) key = new(name, sig); + + if (this.FieldCache.TryGetValue(key, out JFieldID found)) + { + return found; + } + else + { + JFieldID id = JNI.GetStaticFieldID(this, name, sig); + this.FieldCache.Add(key, id); + return id; + } + } + + public JMethodID GetMethodID(string name, string sig) + { + (string, string) key = new(name, sig); + + if (this.MethodCache.TryGetValue(key, out JMethodID found)) + { + return found; + } + else + { + JMethodID id = JNI.GetMethodID(this, name, sig); + this.MethodCache.Add(key, id); + return id; + } + } + + public JMethodID GetStaticMethodID(string name, string sig) + { + (string, string) key = new(name, sig); + + if (this.MethodCache.TryGetValue(key, out JMethodID found)) + { + return found; + } + else + { + JMethodID id = JNI.GetStaticMethodID(this, name, sig); + this.MethodCache.Add(key, id); + return id; + } + } + + public T GetStaticObjectField(string name, string sig) where T : JObject, new() + { + return JNI.GetStaticObjectField(this, this.GetStaticFieldID(name, sig)); + } + + public T GetStaticField(string name) + { + return JNI.GetStaticField(this, this.GetStaticFieldID(name, JNI.GetTypeSignature())); + } + + public void SetStaticField(string name, T value) + { + JNI.SetStaticField(this, this.GetStaticFieldID(name, JNI.GetTypeSignature()), value); + } + + public T GetObjectField(JObject obj, string name, string sig) where T : JObject, new() + { + return JNI.GetObjectField(obj, this.GetFieldID(name, sig)); + } + + public T GetField(JObject obj, string name) + { + return JNI.GetField(obj, this.GetFieldID(name, JNI.GetTypeSignature())); + } + + public void SetObjectField(JObject obj, string name, string sig, JObject value) + { + JNI.SetObjectField(obj, this.GetFieldID(name, sig), value); + } + + public void SetField(JObject obj, string name, T value) + { + JNI.SetField(obj, this.GetFieldID(name, JNI.GetTypeSignature()), value); + } + + public T CallStaticObjectMethod(string name, string sig, params JValue[] args) where T : JObject, new() + { + return JNI.CallStaticObjectMethod(this, this.GetStaticMethodID(name, sig), args); + } + + public T CallStaticMethod(string name, string sig, params JValue[] args) + { + return JNI.CallStaticMethod(this, this.GetStaticMethodID(name, sig), args); + } + + public void CallStaticVoidMethod(string name, string sig, params JValue[] args) + { + JNI.CallStaticVoidMethod(this, this.GetMethodID(name, sig), args); + } + + public T CallObjectMethod(JObject obj, string name, string sig, params JValue[] args) where T : JObject, new() + { + return JNI.CallObjectMethod(obj, this.GetMethodID(name, sig), args); + } + + public T CallMethod(JObject obj, string name, string sig, params JValue[] args) + { + return JNI.CallMethod(obj, this.GetMethodID(name, sig), args); + } + + public void CallVoidMethod(JObject obj, string name, string sig, params JValue[] args) + { + JNI.CallVoidMethod(obj, this.GetMethodID(name, sig), args); + } + + public T NewObject(string name, string sig, params JValue[] args) where T : JObject, new() + { + return JNI.NewObject(this, this.GetMethodID(name, sig), args); + } +} +#endif diff --git a/MelonLoader/JNI/JFieldID.cs b/MelonLoader/JNI/JFieldID.cs new file mode 100644 index 000000000..ab63fd778 --- /dev/null +++ b/MelonLoader/JNI/JFieldID.cs @@ -0,0 +1,24 @@ +#if ANDROID +using System; + +namespace MelonLoader.Java; + +public readonly struct JFieldID : IEquatable +{ + public readonly IntPtr Handle { get; } + + internal JFieldID(IntPtr handle) + { + this.Handle = handle; + } + + public static implicit operator IntPtr(JFieldID fieldID) => fieldID.Handle; + + public static implicit operator JFieldID(IntPtr pointer) => new(pointer); + + public bool Equals(JFieldID other) + { + return this.Handle == other.Handle; + } +} +#endif diff --git a/MelonLoader/JNI/JMethodID.cs b/MelonLoader/JNI/JMethodID.cs new file mode 100644 index 000000000..31fac16fa --- /dev/null +++ b/MelonLoader/JNI/JMethodID.cs @@ -0,0 +1,24 @@ +#if ANDROID +using System; + +namespace MelonLoader.Java; + +public readonly struct JMethodID : IEquatable +{ + public readonly IntPtr Handle { get; } + + internal JMethodID(IntPtr handle) + { + this.Handle = handle; + } + + public static implicit operator IntPtr(JMethodID methodID) => methodID.Handle; + + public static implicit operator JMethodID(IntPtr pointer) => new(pointer); + + public bool Equals(JMethodID other) + { + return this.Handle == other.Handle; + } +} +#endif diff --git a/MelonLoader/JNI/JNI.cs b/MelonLoader/JNI/JNI.cs new file mode 100644 index 000000000..5be72a5d7 --- /dev/null +++ b/MelonLoader/JNI/JNI.cs @@ -0,0 +1,1447 @@ +#pragma warning disable CS8600 // Converting null literal or possible null value to non-nullable type +#pragma warning disable CS8605 // Unboxing a possibly null value. +#pragma warning disable CS8632 // The annotation for nullable reference types... +#pragma warning disable CS8602 // Dereference of a possibly null reference + +#if ANDROID +namespace MelonLoader.Java; + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.InteropServices; + +///

+/// Represents the Java Native Interface +/// +public unsafe static partial class JNI +{ + internal static JavaVM* VM; + + [ThreadStatic] + private static JNIEnv* _env; + internal static JNIEnv* Env + { + get + { + if (_env == null) + { + if (VM == null) + throw new InvalidOperationException("JNI not initialized. Call JNI.Initialize() first."); + + Initialize(IntPtr.Zero); + } + + return _env; + } + } + + internal static Dictionary ClassCache { get; set; } = new(); + + public static void Initialize(IntPtr vmPtr) + { + if (VM == null && vmPtr != IntPtr.Zero) + VM = (JavaVM*)vmPtr; + else if (VM == null) + throw new InvalidOperationException("JavaVM not initialized. Call JNI.Initialize() with a VM pointer first."); + + unsafe + { + JavaVMAttachArgs args = new() + { + version = (int)Version.V1_6, + name = IntPtr.Zero, + group = IntPtr.Zero + }; + + IntPtr argsPtr = +#if NET35 + Marshal.AllocHGlobal(Marshal.SizeOf(typeof(JavaVMAttachArgs))); +#else + Marshal.AllocHGlobal(Marshal.SizeOf()); +#endif + + try + { + Marshal.StructureToPtr(args, argsPtr, false); + + // TODO: threads need detached at some point, not sure how this should be handled for things like the finalizer thread + Result res = VM->Functions->AttachCurrentThread(VM, out JNIEnv* localEnv, argsPtr); + _env = localEnv; + + if (res != Result.Ok) + throw new InvalidOperationException($"Failed to attach current thread to JVM. Result: {res}"); + } + finally + { + Marshal.FreeHGlobal(argsPtr); + } + } + } + + [StructLayout(LayoutKind.Sequential)] + struct JavaVMAttachArgs + { + public int version; + public IntPtr name; + public IntPtr group; + } + + public static int GetVersion() + { + unsafe + { + return Env->Functions->GetVersion(Env); + } + } + + public static JClass DefineClass(string name, JObject loader, sbyte[] bytes) + { + unsafe + { + IntPtr bytesPtr = Marshal.UnsafeAddrOfPinnedArrayElement(bytes, 0); + IntPtr nameAnsi = Marshal.StringToHGlobalAnsi(name); + + IntPtr res = Env->Functions->DefineClass(Env, nameAnsi, loader.Handle, bytesPtr, bytes.Length); + + Marshal.FreeHGlobal(nameAnsi); + + using JClass local = new() { Handle = res, ReferenceType = JNI.ReferenceType.Local }; + return NewGlobalRef(local); + } + } + + public static JClass FindClass(string name) + { + unsafe + { + if (ClassCache.TryGetValue(name, out JClass? found)) + { + return found; + } + else + { + IntPtr nameAnsi = Marshal.StringToHGlobalAnsi(name); + IntPtr res = Env->Functions->FindClass(Env, nameAnsi); + + Marshal.FreeHGlobal(nameAnsi); + + using JClass local = new() { Handle = res, ReferenceType = JNI.ReferenceType.Local }; + JClass global = NewGlobalRef(local); + ClassCache.Add(name, global); + return global; + } + } + } + + public static JMethodID FromReflectedMethod(JObject method) + { + unsafe + { + return Env->Functions->FromReflectedMethod(Env, method.Handle); + } + } + + public static JFieldID FromReflectedField(JObject field) + { + unsafe + { + return Env->Functions->FromReflectedField(Env, field.Handle); + } + } + + public static JObject ToReflectedMethod(JClass cls, JMethodID methodID, bool isStatic) + { + unsafe + { + IntPtr res = Env->Functions->ToReflectedMethod(Env, cls.Handle, methodID, Convert.ToByte(isStatic)); + + using JObject local = new() { Handle = res, ReferenceType = ReferenceType.Local }; + return NewGlobalRef(local); + } + } + + public static JClass GetSuperClass(JClass sub) + { + unsafe + { + IntPtr res = Env->Functions->GetSuperClass(Env, sub.Handle); + + using JClass local = new() { Handle = res, ReferenceType = JNI.ReferenceType.Local }; + return NewGlobalRef(local); + } + } + + public static bool IsAssignableFrom(JClass sub, JClass sup) + { + unsafe + { + return Convert.ToBoolean(Env->Functions->IsAssignableFrom(Env, sub.Handle, sup.Handle)); + } + } + + public static JObject ToReflectedField(JClass cls, JFieldID fieldID, bool isStatic) + { + throw new NotImplementedException(); + } + + public static void Throw(JThrowable throwable) + { + unsafe + { + int res = Env->Functions->Throw(Env, throwable.Handle); + } + } + + public static void ThrowNew(JClass cls, string message) + { + unsafe + { + IntPtr messageAnsi = Marshal.StringToHGlobalAnsi(message); + int res = Env->Functions->Throw(Env, messageAnsi); + Marshal.FreeHGlobal(messageAnsi); + } + } + + public static JThrowable ExceptionOccurred() + { + unsafe + { + IntPtr res = Env->Functions->ExceptionOccurred(Env); + + using JThrowable local = new() { Handle = res, ReferenceType = JNI.ReferenceType.Local }; + return NewGlobalRef(local); + } + } + + public static void ExceptionDescribe() + { + unsafe + { + Env->Functions->ExceptionDescribe(Env); + } + } + + public static void ExceptionClear() + { + unsafe + { + Env->Functions->ExceptionClear(Env); + } + } + + public static void FatalError(string message) + { + throw new NotImplementedException(); + } + + public static int PushLocalFrame(int capacity) + { + throw new NotImplementedException(); + } + + public static JObject PopLocalFrame(JObject result) + { + throw new NotImplementedException(); + } + + public static T NewGlobalRef(JObject lobj) where T : JObject, new() + { + unsafe + { + IntPtr res = Env->Functions->NewGlobalRef(Env, lobj.Handle); + return new T() { Handle = res, ReferenceType = JNI.ReferenceType.Global }; + } + } + + public static void DeleteGlobalRef(JObject gref) + { + unsafe + { + if (gref == null) + return; + + if (!gref.Valid()) + return; + + Env->Functions->DeleteGlobalRef(Env, gref.Handle); + } + } + + public static void CheckExceptionAndThrow() + { + if (ExceptionCheck()) + { + JThrowable throwable = ExceptionOccurred(); + ExceptionClear(); + throw new JThrowableException(throwable); + } + } + + public static void DeleteLocalRef(JObject lref) + { + unsafe + { + if (lref == null) + return; + + if (!lref.Valid()) + return; + + Env->Functions->DeleteLocalRef(Env, lref.Handle); + } + } + + public static bool IsSameObject(JObject obj1, JObject obj2) + { + unsafe + { + return Convert.ToBoolean(Env->Functions->IsSameObject(Env, obj1.Handle, obj2.Handle)); + } + } + + public static T NewLocalRef(JObject obj) where T : JObject, new() + { + unsafe + { + IntPtr res = Env->Functions->NewLocalRef(Env, obj.Handle); + return new T() { Handle = res, ReferenceType = JNI.ReferenceType.Local }; + } + } + + public static int EnsureLocalCapacity(int capacity) + { + unsafe + { + return Env->Functions->EnsureLocalCapacity(Env, capacity); + } + } + + public static T AllocObject(JClass cls) where T : JObject, new() + { + unsafe + { + IntPtr res = Env->Functions->AllocObject(Env, cls.Handle); + + using JObject local = new() { Handle = res, ReferenceType = JNI.ReferenceType.Local }; + return NewGlobalRef(local); + } + } + + public static T NewObject(JClass cls, JMethodID methodID, params JValue[] args) where T : JObject, new() + { + unsafe + { + IntPtr argsPtr = Marshal.UnsafeAddrOfPinnedArrayElement(args, 0); + IntPtr res = Env->Functions->NewObjectA(Env, cls.Handle, methodID, argsPtr); + JObject local = new() { Handle = res, ReferenceType = JNI.ReferenceType.Local }; + return NewGlobalRef(local); + } + } + + public static JClass GetObjectClass(JObject obj) + { + unsafe + { + IntPtr res = Env->Functions->GetObjectClass(Env, obj.Handle); + + using JClass local = new() { Handle = res, ReferenceType = JNI.ReferenceType.Local }; + return NewGlobalRef(local); + } + } + + public static bool IsInstanceOf(JObject obj, JClass cls) + { + unsafe + { + return Convert.ToBoolean(Env->Functions->IsInstanceOf(Env, obj.Handle, cls.Handle)); + } + } + + public static JMethodID GetMethodID(JClass cls, string name, string sig) + { + unsafe + { + IntPtr nameAnsi = Marshal.StringToHGlobalAnsi(name); + IntPtr sigAnsi = Marshal.StringToHGlobalAnsi(sig); + + JMethodID id = Env->Functions->GetMethodID(Env, cls.Handle, nameAnsi, sigAnsi); + + Marshal.FreeHGlobal(nameAnsi); + Marshal.FreeHGlobal(sigAnsi); + return id; + } + } + + public static T CallObjectMethod(JObject obj, JMethodID methodID, params JValue[] args) where T : JObject, new() + { + unsafe + { + IntPtr argsPtr = Marshal.UnsafeAddrOfPinnedArrayElement(args, 0); + + fixed (JValue* v = args) + { + IntPtr res = Env->Functions->CallObjectMethodA(Env, obj.Handle, methodID, argsPtr); + using JObject local = new() { Handle = res, ReferenceType = JNI.ReferenceType.Local }; + return NewGlobalRef(local); + } + } + } + + public static T CallMethod(JObject obj, JMethodID methodID, params JValue[] args) + { + unsafe + { + Type t = typeof(T); + IntPtr argsPtr = Marshal.UnsafeAddrOfPinnedArrayElement(args, 0); + + if (t == typeof(bool)) + { + return (T)(object)Convert.ToBoolean(Env->Functions->CallBooleanMethodA(Env, obj.Handle, methodID, argsPtr)); + } + else if (t == typeof(sbyte)) + { + return (T)(object)Env->Functions->CallByteMethodA(Env, obj.Handle, methodID, argsPtr); + } + else if (t == typeof(char)) + { + return (T)(object)Env->Functions->CallCharMethodA(Env, obj.Handle, methodID, argsPtr); + } + else if (t == typeof(short)) + { + return (T)(object)Env->Functions->CallShortMethodA(Env, obj.Handle, methodID, argsPtr); + } + else if (t == typeof(int)) + { + return (T)(object)Env->Functions->CallIntMethodA(Env, obj.Handle, methodID, argsPtr); + } + else if (t == typeof(long)) + { + return (T)(object)Env->Functions->CallLongMethodA(Env, obj.Handle, methodID, argsPtr); + } + else if (t == typeof(float)) + { + return (T)(object)Env->Functions->CallFloatMethodA(Env, obj.Handle, methodID, argsPtr); + } + else if (t == typeof(double)) + { + return (T)(object)Env->Functions->CallDoubleMethodA(Env, obj.Handle, methodID, argsPtr); + } + else + { + throw new ArgumentException($"CallMethod Type {t} not supported."); + } + } + } + + public static void CallVoidMethod(JObject obj, JMethodID methodID, params JValue[] args) + { + unsafe + { + IntPtr argsPtr = Marshal.UnsafeAddrOfPinnedArrayElement(args, 0); + Env->Functions->CallVoidMethodA(Env, obj.Handle, methodID, argsPtr); + } + } + + public static T CallNonvirtualObjectMethod(JObject obj, JClass cls, JMethodID methodID, params JValue[] args) where T : JObject, new() + { + unsafe + { + IntPtr argsPtr = Marshal.UnsafeAddrOfPinnedArrayElement(args, 0); + IntPtr res = Env->Functions->CallNonvirtualObjectMethodA(Env, obj.Handle, cls.Handle, methodID, argsPtr); + + using JObject local = new() { Handle = res, ReferenceType = JNI.ReferenceType.Local }; + return NewGlobalRef(local); + } + } + + public static T CallNonvirtualMethod(JObject obj, JClass cls, JMethodID methodID, params JValue[] args) + { + unsafe + { + Type t = typeof(T); + IntPtr argsPtr = Marshal.UnsafeAddrOfPinnedArrayElement(args, 0); + + if (t == typeof(bool)) + { + return (T)(object)Convert.ToBoolean(Env->Functions->CallNonvirtualBooleanMethodA(Env, obj.Handle, cls.Handle, methodID, argsPtr)); + } + else if (t == typeof(sbyte)) + { + return (T)(object)Env->Functions->CallNonvirtualByteMethodA(Env, obj.Handle, cls.Handle, methodID, argsPtr); + } + else if (t == typeof(char)) + { + return (T)(object)Env->Functions->CallNonvirtualCharMethodA(Env, obj.Handle, cls.Handle, methodID, argsPtr); + } + else if (t == typeof(short)) + { + return (T)(object)Env->Functions->CallNonvirtualShortMethodA(Env, obj.Handle, cls.Handle, methodID, argsPtr); + } + else if (t == typeof(int)) + { + return (T)(object)Env->Functions->CallNonvirtualIntMethodA(Env, obj.Handle, cls.Handle, methodID, argsPtr); + } + else if (t == typeof(long)) + { + return (T)(object)Env->Functions->CallNonvirtualLongMethodA(Env, obj.Handle, cls.Handle, methodID, argsPtr); + } + else if (t == typeof(float)) + { + return (T)(object)Env->Functions->CallNonvirtualFloatMethodA(Env, obj.Handle, cls.Handle, methodID, argsPtr); + } + else if (t == typeof(double)) + { + return (T)(object)Env->Functions->CallNonvirtualDoubleMethodA(Env, obj.Handle, cls.Handle, methodID, argsPtr); + } + else + { + throw new ArgumentException($"CallNonvirtualMethod Type {t} not supported."); + } + } + } + + public static void CallNonvirtualVoidMethod(JObject obj, JClass cls, JMethodID methodID, params JValue[] args) + { + unsafe + { + IntPtr argsPtr = Marshal.UnsafeAddrOfPinnedArrayElement(args, 0); + Env->Functions->CallNonvirtualVoidMethodA(Env, obj.Handle, cls.Handle, methodID, argsPtr); + } + } + + public static JFieldID GetFieldID(JClass cls, string name, string sig) + { + unsafe + { + IntPtr nameAnsi = Marshal.StringToHGlobalAnsi(name); + IntPtr sigAnsi = Marshal.StringToHGlobalAnsi(sig); + + JFieldID id = Env->Functions->GetFieldID(Env, cls.Handle, nameAnsi, sigAnsi); + + Marshal.FreeHGlobal(nameAnsi); + Marshal.FreeHGlobal(sigAnsi); + return id; + } + } + + public static T GetObjectField(JObject obj, JFieldID fieldID) where T : JObject, new() + { + unsafe + { + IntPtr res = Env->Functions->GetObjectField(Env, obj.Handle, fieldID); + using JObject local = new() { Handle = res, ReferenceType = JNI.ReferenceType.Local }; + return NewGlobalRef(local); + } + } + + public static T GetField(JObject obj, JFieldID fieldID) + { + unsafe + { + Type t = typeof(T); + + if (t == typeof(bool)) + { + return (T)(object)Convert.ToBoolean(Env->Functions->GetBooleanField(Env, obj.Handle, fieldID)); + } + else if (t == typeof(sbyte)) + { + return (T)(object)Env->Functions->GetByteField(Env, obj.Handle, fieldID); + } + else if (t == typeof(char)) + { + return (T)(object)Env->Functions->GetCharField(Env, obj.Handle, fieldID); + } + else if (t == typeof(short)) + { + return (T)(object)Env->Functions->GetShortField(Env, obj.Handle, fieldID); + } + else if (t == typeof(int)) + { + return (T)(object)Env->Functions->GetIntField(Env, obj.Handle, fieldID); + } + else if (t == typeof(long)) + { + return (T)(object)Env->Functions->GetLongField(Env, obj.Handle, fieldID); + } + else if (t == typeof(float)) + { + return (T)(object)Env->Functions->GetFloatField(Env, obj.Handle, fieldID); + } + else if (t == typeof(double)) + { + return (T)(object)Env->Functions->GetDoubleField(Env, obj.Handle, fieldID); + } + else + { + throw new ArgumentException($"GetField Type {t} not supported."); + } + } + } + + public static void SetObjectField(JObject obj, JFieldID fieldID, JObject val) + { + unsafe + { + Env->Functions->SetObjectField(Env, obj.Handle, fieldID, val.Handle); + } + } + + public static void SetField(JObject obj, JFieldID fieldID, T value) + { + unsafe + { + switch (value) + { + case bool b: + Env->Functions->SetBooleanField(Env, obj.Handle, fieldID, Convert.ToByte(b)); + break; + + case sbyte b: + Env->Functions->SetByteField(Env, obj.Handle, fieldID, b); + break; + + case char c: + Env->Functions->SetCharField(Env, obj.Handle, fieldID, c); + break; + + case short s: + Env->Functions->SetShortField(Env, obj.Handle, fieldID, s); + break; + + case int i: + Env->Functions->SetIntField(Env, obj.Handle, fieldID, i); + break; + + case float f: + Env->Functions->SetFloatField(Env, obj.Handle, fieldID, f); + break; + + case double d: + Env->Functions->SetDoubleField(Env, obj.Handle, fieldID, d); + break; + + default: + throw new ArgumentException($"SetField Type {value?.GetType()} not supported."); + } + } + } + + public static JMethodID GetStaticMethodID(JClass cls, string name, string sig) + { + unsafe + { + IntPtr nameAnsi = Marshal.StringToHGlobalAnsi(name); + IntPtr sigAnsi = Marshal.StringToHGlobalAnsi(sig); + JMethodID id = Env->Functions->GetStaticMethodID(Env, cls.Handle, nameAnsi, sigAnsi); + return id; + } + } + + public static T CallStaticObjectMethod(JClass cls, JMethodID methodID, params JValue[] args) where T : JObject, new() + { + unsafe + { + IntPtr argsPtr = Marshal.UnsafeAddrOfPinnedArrayElement(args, 0); + IntPtr res = Env->Functions->CallStaticObjectMethodA(Env, cls.Handle, methodID.Handle, argsPtr); + using JObject local = new() { Handle = res, ReferenceType = JNI.ReferenceType.Local }; + return NewGlobalRef(local); + } + } + + public static T CallStaticMethod(JClass cls, JMethodID methodID, params JValue[] args) + { + Type t = typeof(T); + IntPtr argsPtr = Marshal.UnsafeAddrOfPinnedArrayElement(args, 0); + + if (t == typeof(bool)) + { + return (T)(object)Convert.ToBoolean(Env->Functions->CallStaticBooleanMethodA(Env, cls.Handle, methodID, argsPtr)); + } + else if (t == typeof(sbyte)) + { + return (T)(object)Env->Functions->CallStaticByteMethodA(Env, cls.Handle, methodID, argsPtr); + } + else if (t == typeof(char)) + { + return (T)(object)Env->Functions->CallStaticCharMethodA(Env, cls.Handle, methodID, argsPtr); + } + else if (t == typeof(short)) + { + return (T)(object)Env->Functions->CallStaticShortMethodA(Env, cls.Handle, methodID, argsPtr); + } + else if (t == typeof(int)) + { + return (T)(object)Env->Functions->CallStaticIntMethodA(Env, cls.Handle, methodID, argsPtr); + } + else if (t == typeof(long)) + { + return (T)(object)Env->Functions->CallStaticLongMethodA(Env, cls.Handle, methodID, argsPtr); + } + else if (t == typeof(float)) + { + return (T)(object)Env->Functions->CallStaticFloatMethodA(Env, cls.Handle, methodID, argsPtr); + } + else if (t == typeof(double)) + { + return (T)(object)Env->Functions->CallStaticDoubleMethodA(Env, cls.Handle, methodID, argsPtr); + } + else + { + throw new ArgumentException($"CallStaticMethod Type {t} not supported."); + } + } + + public static void CallStaticVoidMethod(JClass cls, JMethodID methodID, params JValue[] args) + { + unsafe + { + IntPtr argsPtr = Marshal.UnsafeAddrOfPinnedArrayElement(args, 0); + Env->Functions->CallStaticVoidMethodA(Env, cls.Handle, methodID, argsPtr); + } + } + + public static JFieldID GetStaticFieldID(JClass cls, string name, string sig) + { + unsafe + { + IntPtr nameAnsi = Marshal.StringToHGlobalAnsi(name); + IntPtr sigAnsi = Marshal.StringToHGlobalAnsi(sig); + + JFieldID id = Env->Functions->GetStaticFieldID(Env, cls.Handle, nameAnsi, sigAnsi); + + Marshal.FreeHGlobal(nameAnsi); + Marshal.FreeHGlobal(sigAnsi); + return id; + } + } + + public static T GetStaticObjectField(JClass cls, JFieldID fieldID) where T : JObject, new() + { + unsafe + { + IntPtr res = Env->Functions->GetStaticObjectField(Env, cls.Handle, fieldID); + + using JObject local = new() { Handle = res, ReferenceType = JNI.ReferenceType.Local }; + return NewGlobalRef(local); + } + } + + public static T GetStaticField(JClass cls, JFieldID fieldID) + { + unsafe + { + Type t = typeof(T); + + if (t == typeof(bool)) + { + return (T)(object)Convert.ToBoolean(Env->Functions->GetStaticBooleanField(Env, cls.Handle, fieldID)); + } + else if (t == typeof(sbyte)) + { + return (T)(object)Env->Functions->GetStaticByteField(Env, cls.Handle, fieldID); + } + else if (t == typeof(char)) + { + return (T)(object)Env->Functions->GetStaticCharField(Env, cls.Handle, fieldID); + } + else if (t == typeof(short)) + { + return (T)(object)Env->Functions->GetStaticShortField(Env, cls.Handle, fieldID); + } + else if (t == typeof(int)) + { + return (T)(object)Env->Functions->GetStaticIntField(Env, cls.Handle, fieldID); + } + else if (t == typeof(long)) + { + return (T)(object)Env->Functions->GetStaticLongField(Env, cls.Handle, fieldID); + } + else if (t == typeof(float)) + { + return (T)(object)Env->Functions->GetStaticFloatField(Env, cls.Handle, fieldID); + } + else if (t == typeof(double)) + { + return (T)(object)Env->Functions->GetStaticDoubleField(Env, cls.Handle, fieldID); + } + else + { + throw new ArgumentException($"GetStaticField Type {t} not supported."); + } + } + } + + public static void SetStaticObjectField(JClass cls, JFieldID fieldID, T value) where T : JObject, new() + { + unsafe + { + Env->Functions->SetStaticObjectField(Env, cls.Handle, fieldID, value.Handle); + } + } + + public static void SetStaticField(JClass cls, JFieldID fieldID, T value) + { + unsafe + { + switch (value) + { + case bool b: + Env->Functions->SetStaticBooleanField(Env, cls.Handle, fieldID, Convert.ToByte(b)); + break; + + case sbyte b: + Env->Functions->SetStaticByteField(Env, cls.Handle, fieldID, b); + break; + + case char c: + Env->Functions->SetStaticCharField(Env, cls.Handle, fieldID, c); + break; + + case short s: + Env->Functions->SetStaticShortField(Env, cls.Handle, fieldID, s); + break; + + case int i: + Env->Functions->SetStaticIntField(Env, cls.Handle, fieldID, i); + break; + + case float f: + Env->Functions->SetStaticFloatField(Env, cls.Handle, fieldID, f); + break; + + case double d: + Env->Functions->SetStaticDoubleField(Env, cls.Handle, fieldID, d); + break; + + default: + throw new ArgumentException($"SetField Type {value.GetType()} not supported."); + } + } + } + + public static JString NewString(string str) + { + unsafe + { + IntPtr strUni = Marshal.StringToHGlobalUni(str); + + IntPtr res = Env->Functions->NewString(Env, strUni, str.Length); + + Marshal.FreeHGlobal(strUni); + + using JObject local = new() { Handle = res, ReferenceType = JNI.ReferenceType.Local }; + return NewGlobalRef(local); + } + } + + public static int GetStringLength(JString str) + { + unsafe + { + return Env->Functions->GetStringLength(Env, str.Handle); + } + } + + public static string GetJStringString(JString str) + { + unsafe + { + if (!str.Valid()) + return ""; + + IntPtr res = Env->Functions->GetStringUTFChars(Env, str.Handle, out byte isCopy); + string? resultString = Marshal.PtrToStringAuto(res); + Env->Functions->ReleaseStringChars(Env, str.Handle, res); + return resultString ?? ""; + } + } + + private static void ReleaseStringChars(JString str, IntPtr chars) + { + Env->Functions->ReleaseStringChars(Env, str.Handle, chars); + } + + public static int GetArrayLength(JArray jarray) + { + unsafe + { + return Env->Functions->GetArrayLength(Env, jarray.Handle); + } + } + + public static int GetArrayLength(JObjectArray jarray) where T : JObject, new() + { + unsafe + { + return Env->Functions->GetArrayLength(Env, jarray.Handle); + } + } + + public static T GetObjectArrayElement(JObjectArray array, int index) where T : JObject, new() + { + unsafe + { + IntPtr res = Env->Functions->GetObjectArrayElement(Env, array.Handle, index); + + using JObject local = new() { Handle = res, ReferenceType = JNI.ReferenceType.Local }; + return NewGlobalRef(local); + } + } + + public static void SetObjectArrayElement(JObjectArray array, int index, T value) where T : JObject, new() + { + unsafe + { + Env->Functions->SetObjectArrayElement(Env, array.Handle, index, value.Handle); + } + } + + public static JArray NewArray(int length) + { + unsafe + { + Type t = typeof(T); + IntPtr res; + + if (t == typeof(bool)) + { + res = Env->Functions->NewBooleanArray(Env, length); + } + else if (t == typeof(sbyte)) + { + res = Env->Functions->NewByteArray(Env, length); + } + else if (t == typeof(char)) + { + res = Env->Functions->NewCharArray(Env, length); + } + else if (t == typeof(short)) + { + res = Env->Functions->NewShortArray(Env, length); + } + else if (t == typeof(int)) + { + res = Env->Functions->NewIntArray(Env, length); + } + else if (t == typeof(long)) + { + res = Env->Functions->NewBooleanArray(Env, length); + } + else if (t == typeof(float)) + { + res = Env->Functions->NewBooleanArray(Env, length); + } + else if (t == typeof(double)) + { + res = Env->Functions->NewBooleanArray(Env, length); + } + else + { + throw new ArgumentException($"CallStaticMethod Type {t} not supported."); + } + + using JObject local = new() { Handle = res, ReferenceType = JNI.ReferenceType.Local }; + return NewGlobalRef>(local); + } + } + + public static T[] GetArrayElements(JArray array) + { + unsafe + { + Type t = typeof(T); + int length = GetArrayLength(array); + + if (t == typeof(bool)) + { + byte* arr = Env->Functions->GetBooleanArrayElements(Env, array.Handle, out byte isCopy); + + bool[] buf = new bool[length]; + + for (int i = 0; i < length; i++) + buf[i] = Convert.ToBoolean(arr[i]); + + Env->Functions->ReleaseBooleanArrayElements(Env, array.Handle, arr, (int)JNI.ReleaseMode.Abort); + return (T[])(object)buf; + } + else if (t == typeof(sbyte)) + { + sbyte* arr = Env->Functions->GetByteArrayElements(Env, array.Handle, out byte isCopy); + + sbyte[] buf = new sbyte[length]; + + for (int i = 0; i < length; i++) + buf[i] = arr[i]; + + Env->Functions->ReleaseByteArrayElements(Env, array.Handle, arr, (int)JNI.ReleaseMode.Abort); + return (T[])(object)buf; + } + else if (t == typeof(char)) + { + char* arr = Env->Functions->GetCharArrayElements(Env, array.Handle, out byte isCopy); + + char[] buf = new char[length]; + + for (int i = 0; i < length; i++) + buf[i] = arr[i]; + + Env->Functions->ReleaseCharArrayElements(Env, array.Handle, arr, (int)JNI.ReleaseMode.Abort); + return (T[])(object)buf; + } + else if (t == typeof(short)) + { + short* arr = Env->Functions->GetShortArrayElements(Env, array.Handle, out byte isCopy); + + short[] buf = new short[length]; + + for (int i = 0; i < length; i++) + buf[i] = arr[i]; + + Env->Functions->ReleaseShortArrayElements(Env, array.Handle, arr, (int)JNI.ReleaseMode.Abort); + return (T[])(object)buf; + } + else if (t == typeof(int)) + { + int* arr = Env->Functions->GetIntArrayElements(Env, array.Handle, out byte isCopy); + + int[] buf = new int[length]; + + for (int i = 0; i < length; i++) + buf[i] = arr[i]; + + Env->Functions->ReleaseIntArrayElements(Env, array.Handle, arr, (int)JNI.ReleaseMode.Abort); + return (T[])(object)buf; + } + else if (t == typeof(long)) + { + long* arr = Env->Functions->GetLongArrayElements(Env, array.Handle, out byte isCopy); + + long[] buf = new long[length]; + + for (int i = 0; i < length; i++) + buf[i] = arr[i]; + + Env->Functions->ReleaseLongArrayElements(Env, array.Handle, arr, (int)JNI.ReleaseMode.Abort); + return (T[])(object)buf; + } + else if (t == typeof(float)) + { + float* arr = Env->Functions->GetFloatArrayElements(Env, array.Handle, out byte isCopy); + + float[] buf = new float[length]; + + for (int i = 0; i < length; i++) + buf[i] = arr[i]; + + Env->Functions->ReleaseFloatArrayElements(Env, array.Handle, arr, (int)JNI.ReleaseMode.Abort); + return (T[])(object)buf; + } + else if (t == typeof(double)) + { + double* arr = Env->Functions->GetDoubleArrayElements(Env, array.Handle, out byte isCopy); + + double[] buf = new double[length]; + + for (int i = 0; i < length; i++) + buf[i] = arr[i]; + + Env->Functions->ReleaseDoubleArrayElements(Env, array.Handle, arr, (int)JNI.ReleaseMode.Abort); + return (T[])(object)buf; + } + else + { + throw new ArgumentException($"GetArrayElements Type {t} not supported."); + } + } + } + + public static T[] GetArrayRegion(JArray array, int start, int len) + { + unsafe + { + Type t = typeof(T); + + if (t == typeof(bool)) + { + fixed (byte* buf = new byte[len]) + { + Env->Functions->GetBooleanArrayRegion(Env, array.Handle, start, len, buf); + + bool[] res = new bool[len]; + for (int i = 0; i < len; i++) + { + res[i] = Convert.ToBoolean(buf[i]); + } + return (T[])(object)res; + } + } + else if (t == typeof(sbyte)) + { + sbyte[] buf = new sbyte[len]; + + fixed (sbyte* b = buf) + { + Env->Functions->GetByteArrayRegion(Env, array.Handle, start, len, b); + return (T[])(object)buf; + } + } + else if (t == typeof(char)) + { + char[] buf = new char[len]; + + fixed (char* b = buf) + { + Env->Functions->GetCharArrayRegion(Env, array.Handle, start, len, b); + return (T[])(object)buf; + } + } + else if (t == typeof(short)) + { + short[] buf = new short[len]; + + fixed (short* b = buf) + { + Env->Functions->GetShortArrayRegion(Env, array.Handle, start, len, b); + return (T[])(object)buf; + } + } + else if (t == typeof(int)) + { + int[] buf = new int[len]; + + fixed (int* b = buf) + { + Env->Functions->GetIntArrayRegion(Env, array.Handle, start, len, b); + return (T[])(object)buf; + } + } + else if (t == typeof(long)) + { + long[] buf = new long[len]; + + fixed (long* b = buf) + { + Env->Functions->GetLongArrayRegion(Env, array.Handle, start, len, b); + return (T[])(object)buf; + } + } + else if (t == typeof(float)) + { + float[] buf = new float[len]; + + fixed (float* b = buf) + { + Env->Functions->GetFloatArrayRegion(Env, array.Handle, start, len, b); + return (T[])(object)buf; + } + } + else if (t == typeof(double)) + { + double[] buf = new double[len]; + + fixed (double* b = buf) + { + Env->Functions->GetDoubleArrayRegion(Env, array.Handle, start, len, b); + return (T[])(object)buf; + } + } + else + { + throw new ArgumentException($"GetArrayRegion Type {t} not supported."); + } + } + } + + public static T GetArrayElement(JArray array, int index) + { + Type t = typeof(T); + + if (t == typeof(bool)) + { + byte b; + Env->Functions->GetBooleanArrayRegion(Env, array.Handle, index, 1, &b); + return (T)(object)Convert.ToBoolean(b); + } + else if (t == typeof(sbyte)) + { + sbyte b; + Env->Functions->GetByteArrayRegion(Env, array.Handle, index, 1, &b); + return (T)(object)b; + } + else if (t == typeof(char)) + { + char c; + Env->Functions->GetCharArrayRegion(Env, array.Handle, index, 1, &c); + return (T)(object)c; + } + else if (t == typeof(short)) + { + short s; + Env->Functions->GetShortArrayRegion(Env, array.Handle, index, 1, &s); + return (T)(object)s; + } + else if (t == typeof(int)) + { + int i; + Env->Functions->GetIntArrayRegion(Env, array.Handle, index, 1, &i); + return (T)(object)i; + } + else if (t == typeof(long)) + { + long l; + Env->Functions->GetLongArrayRegion(Env, array.Handle, index, 1, &l); + return (T)(object)l; + } + else if (t == typeof(float)) + { + float f; + Env->Functions->GetFloatArrayRegion(Env, array.Handle, index, 1, &f); + return (T)(object)f; + } + else if (t == typeof(double)) + { + double d; + Env->Functions->GetDoubleArrayRegion(Env, array.Handle, index, 1, &d); + return (T)(object)d; + } + else + { + throw new ArgumentException($"GetArrayElement Type {t} not supported."); + } + } + + public static void SetArrayRegion(JArray array, int start, int len, T[] elems) + { + unsafe + { + Type t = typeof(T); + + if (t == typeof(bool)) + { + fixed (byte* buf = elems.Select(b => Convert.ToByte(b)).ToArray()) + { + Env->Functions->SetBooleanArrayRegion(Env, array.Handle, start, len, null); + } + } + else if (t == typeof(sbyte)) + { + fixed (sbyte* buf = (sbyte[])(object)elems) + { + Env->Functions->SetByteArrayRegion(Env, array.Handle, start, len, buf); + } + } + else if (t == typeof(char)) + { + fixed (char* buf = (char[])(object)elems) + { + Env->Functions->SetCharArrayRegion(Env, array.Handle, start, len, buf); + } + } + else if (t == typeof(short)) + { + fixed (short* buf = (short[])(object)elems) + { + Env->Functions->SetShortArrayRegion(Env, array.Handle, start, len, buf); + } + } + else if (t == typeof(int)) + { + fixed (int* buf = (int[])(object)elems) + { + Env->Functions->SetIntArrayRegion(Env, array.Handle, start, len, buf); + } + } + else if (t == typeof(long)) + { + fixed (long* buf = (long[])(object)elems) + { + Env->Functions->SetLongArrayRegion(Env, array.Handle, start, len, buf); + } + } + else if (t == typeof(float)) + { + fixed (float* buf = (float[])(object)elems) + { + Env->Functions->SetFloatArrayRegion(Env, array.Handle, start, len, buf); + } + } + else if (t == typeof(double)) + { + fixed (double* buf = (double[])(object)elems) + { + Env->Functions->SetDoubleArrayRegion(Env, array.Handle, start, len, buf); + } + } + else + { + throw new ArgumentException($"SetArrayRegion Type {t} not supported."); + } + } + } + + public static void SetArrayElement(JArray array, int index, T value) + { + Type t = typeof(T); + + if (t == typeof(bool)) + { + byte b = Convert.ToByte(value); + Env->Functions->SetBooleanArrayRegion(Env, array.Handle, index, 1, &b); + } + else if (t == typeof(sbyte)) + { + sbyte b = (sbyte)(object)value; + Env->Functions->SetByteArrayRegion(Env, array.Handle, index, 1, &b); + } + else if (t == typeof(char)) + { + char c = (char)(object)value; + Env->Functions->SetCharArrayRegion(Env, array.Handle, index, 1, &c); + } + else if (t == typeof(short)) + { + short s = (short)(object)value; + Env->Functions->SetShortArrayRegion(Env, array.Handle, index, 1, &s); + } + else if (t == typeof(int)) + { + int c = (int)(object)value; + Env->Functions->SetIntArrayRegion(Env, array.Handle, index, 1, &c); + } + else if (t == typeof(long)) + { + long l = (long)(object)value; + Env->Functions->SetLongArrayRegion(Env, array.Handle, index, 1, &l); + } + else if (t == typeof(float)) + { + float f = (float)(object)value; + Env->Functions->SetFloatArrayRegion(Env, array.Handle, index, 1, &f); + } + else if (t == typeof(double)) + { + double d = (double)(object)value; + Env->Functions->SetDoubleArrayRegion(Env, array.Handle, index, 1, &d); + } + else + { + throw new ArgumentException($"SetArrayElement Type {t} not supported."); + } + } + + private static int RegisterNatives(JClass cls, IntPtr methods, int nmethods) + { + throw new NotImplementedException(); + } + + private static int UnregisterNatives(JClass cls) + { + throw new NotImplementedException(); + } + + public static int MonitorEnter(JObject obj) + { + unsafe + { + return Env->Functions->MonitorEnter(Env, obj.Handle); + } + } + + public static int MonitorExit(JObject obj) + { + unsafe + { + return Env->Functions->MonitorExit(Env, obj.Handle); + } + } + + private static JavaVM* GetJavaVM() + { + throw new NotImplementedException(); + } + + public static string? GetStringRegion(JString str, int start, int len) + { + unsafe + { + //Probably need to allocate space? + IntPtr buf = IntPtr.Zero; + Env->Functions->GetStringRegion(Env, str.Handle, start, len, buf); + + if (buf != IntPtr.Zero) + { + return Marshal.PtrToStringUni(buf); + } + + return null; + } + } + + private static IntPtr GetPrimitiveArrayCritical(JArray array) + { + throw new NotImplementedException(); + } + + private static void ReleasePrimitiveArrayCritical(JArray array, IntPtr carray, int mode) + { + throw new NotImplementedException(); + } + + private static string GetStringCritical(JString str) + { + throw new NotImplementedException(); + } + + private static void ReleaseStringCritical(JString str) + { + throw new NotImplementedException(); + } + + public static T NewWeakGlobalRef(JObject obj) where T : JObject, new() + { + unsafe + { + IntPtr res = Env->Functions->NewWeakGlobalRef(Env, obj.Handle); + return new T() { Handle = res, ReferenceType = JNI.ReferenceType.WeakGlobal }; + } + } + + public static void DeleteWeakGlobalRef(JObject obj) + { + unsafe + { + Env->Functions->DeleteWeakGlobalRef(Env, obj.Handle); + } + } + + public static bool ExceptionCheck() + { + unsafe + { + return Convert.ToBoolean(Env->Functions->ExceptionCheck(Env)); + } + } + + private static JObject NewDirectByteBuffer(IntPtr address, int capacity) + { + throw new NotImplementedException(); + } + + private static IntPtr GetDirectBufferAddress(JObject buf) + { + throw new NotImplementedException(); + } + + private static int GetDirectBufferCapacity(JObject obj) + { + throw new NotImplementedException(); + } +} +#endif + +#pragma warning restore CS8600 +#pragma warning restore CS8605 +#pragma warning restore CS8632 +#pragma warning restore CS8602 \ No newline at end of file diff --git a/MelonLoader/JNI/JNIEnv.cs b/MelonLoader/JNI/JNIEnv.cs new file mode 100644 index 000000000..85a93cc1c --- /dev/null +++ b/MelonLoader/JNI/JNIEnv.cs @@ -0,0 +1,713 @@ +#if ANDROID +namespace MelonLoader.Java; + +using System; +using System.Runtime.InteropServices; + +/// +/// Represents a JNIEnv C struct, the FunctionTable contains +/// all the JNI functions. +/// +[StructLayout(LayoutKind.Sequential)] +internal readonly unsafe struct JNIEnv +{ + [StructLayout(LayoutKind.Sequential)] + internal readonly unsafe struct FunctionTable + { + internal readonly IntPtr Reserved0; + + internal readonly IntPtr Reserved1; + + internal readonly IntPtr Reserved2; + + internal readonly IntPtr Reserved3; + + // jint (JNICALL *GetVersion)(JNIEnv *env); + internal readonly delegate* unmanaged[Stdcall] GetVersion; + + // jclass (JNICALL *DefineClass) (JNIEnv* env, const char* name, jobject loader, const jbyte* buf, jsize len); + internal readonly delegate* unmanaged[Stdcall] DefineClass; + + // jclass (JNICALL *FindClass) (JNIEnv* env, const char* name); + internal readonly delegate* unmanaged[Stdcall] FindClass; + + // jmethodID (JNICALL *FromReflectedMethod) (JNIEnv* env, jobject method); + internal readonly delegate* unmanaged[Stdcall] FromReflectedMethod; + + // jfieldID (JNICALL *FromReflectedField) (JNIEnv* env, jobject field); + internal readonly delegate* unmanaged[Stdcall] FromReflectedField; + + // jobject (JNICALL *ToReflectedMethod) (JNIEnv* env, jclass cls, jmethodID methodID, jboolean isStatic); + internal readonly delegate* unmanaged[Stdcall] ToReflectedMethod; + + // jclass (JNICALL *GetSuperclass) (JNIEnv* env, jclass sub); + internal readonly delegate* unmanaged[Stdcall] GetSuperClass; + + // jboolean (JNICALL *IsAssignableFrom) (JNIEnv* env, jclass sub, jclass sup); + internal readonly delegate* unmanaged[Stdcall] IsAssignableFrom; + + // jobject (JNICALL *ToReflectedField) (JNIEnv* env, jclass cls, jfieldID fieldID, jboolean isStatic); + internal readonly delegate* unmanaged[Stdcall] ToReflectedField; + + // jint (JNICALL *Throw) (JNIEnv* env, jthrowable obj); + internal readonly delegate* unmanaged[Stdcall] Throw; + + // jint (JNICALL *ThrowNew) (JNIEnv* env, jclass clazz, const char* msg); + internal readonly delegate* unmanaged[Stdcall] ThrowNew; + + // jthrowable (JNICALL *ExceptionOccurred) (JNIEnv* env); + internal readonly delegate* unmanaged[Stdcall] ExceptionOccurred; + + // void (JNICALL *ExceptionDescribe) (JNIEnv* env); + internal readonly delegate* unmanaged[Stdcall] ExceptionDescribe; + + // void (JNICALL *ExceptionClear) (JNIEnv* env); + internal readonly delegate* unmanaged[Stdcall] ExceptionClear; + + // void (JNICALL *FatalError) (JNIEnv* env, const char* msg); + internal readonly delegate* unmanaged[Stdcall] FatalError; + + // jint (JNICALL *PushLocalFrame) (JNIEnv* env, jint capacity); + internal readonly delegate* unmanaged[Stdcall] PushLocalFrame; + + // jobject (JNICALL *PopLocalFrame) (JNIEnv* env, jobject result); + internal readonly delegate* unmanaged[Stdcall] PopLocalFrame; + + // jobject (JNICALL *NewGlobalRef) (JNIEnv* env, jobject lobj); + internal readonly delegate* unmanaged[Stdcall] NewGlobalRef; + + // void (JNICALL *DeleteGlobalRef) (JNIEnv* env, jobject gref); + internal readonly delegate* unmanaged[Stdcall] DeleteGlobalRef; + + // void (JNICALL *DeleteLocalRef) (JNIEnv* env, jobject obj); + internal readonly delegate* unmanaged[Stdcall] DeleteLocalRef; + + // jboolean (JNICALL *IsSameObject) (JNIEnv* env, jobject obj1, jobject obj2); + internal readonly delegate* unmanaged[Stdcall] IsSameObject; + + // jobject (JNICALL *NewLocalRef) (JNIEnv* env, jobject ref); + internal readonly delegate* unmanaged[Stdcall] NewLocalRef; + + // jint (JNICALL *EnsureLocalCapacity) (JNIEnv* env, jint capacity); + internal readonly delegate* unmanaged[Stdcall] EnsureLocalCapacity; + + // jobject (JNICALL *AllocObject) (JNIEnv* env, jclass clazz); + internal readonly delegate* unmanaged[Stdcall] AllocObject; + + // jobject (JNICALL *NewObject) (JNIEnv* env, jclass clazz, jmethodID methodID, ...); + internal readonly IntPtr NewObject; + + // jobject (JNICALL *NewObjectV) (JNIEnv* env, jclass clazz, jmethodID methodID, va_list args); + internal readonly IntPtr NewObjectV; + + // jobject (JNICALL *NewObjectA) (JNIEnv* env, jclass clazz, jmethodID methodID, const jvalue* args); + internal readonly delegate* unmanaged[Stdcall] NewObjectA; + + // jclass (JNICALL *GetObjectClass) (JNIEnv* env, jobject obj); + internal readonly delegate* unmanaged[Stdcall] GetObjectClass; + + // jboolean (JNICALL *IsInstanceOf) (JNIEnv* env, jobject obj, jclass clazz); + internal readonly delegate* unmanaged[Stdcall] IsInstanceOf; + + // jmethodID (JNICALL *GetMethodID) (JNIEnv* env, jclass clazz, const char* name, const char* sig); + internal readonly delegate* unmanaged[Stdcall] GetMethodID; + + // jobject (JNICALL *CallObjectMethod) (JNIEnv* env, jobject obj, jmethodID methodID, ...); + internal readonly IntPtr CallObjectMethod; + + // jobject (JNICALL *CallObjectMethodV) (JNIEnv* env, jobject obj, jmethodID methodID, va_list args); + internal readonly IntPtr CallObjectMethodV; + + // jobject (JNICALL *CallObjectMethodA) (JNIEnv* env, jobject obj, jmethodID methodID, const jvalue* args); + internal readonly delegate* unmanaged[Stdcall] CallObjectMethodA; + + // jboolean (JNICALL *CallBooleanMethod) (JNIEnv* env, jobject obj, jmethodID methodID, ...); + internal readonly IntPtr CallBooleanMethod; + + // jboolean (JNICALL *CallBooleanMethodV) (JNIEnv* env, jobject obj, jmethodID methodID, va_list args); + internal readonly IntPtr CallBooleanMethodV; + + // jboolean (JNICALL *CallBooleanMethodA) (JNIEnv* env, jobject obj, jmethodID methodID, const jvalue* args); + internal readonly delegate* unmanaged[Stdcall] CallBooleanMethodA; + + // jbyte (JNICALL *CallByteMethod) (JNIEnv* env, jobject obj, jmethodID methodID, ...); + internal readonly IntPtr CallByteMethod; + + // jbyte (JNICALL *CallByteMethodV) (JNIEnv* env, jobject obj, jmethodID methodID, va_list args); + internal readonly IntPtr CallByteMethodV; + + // jbyte (JNICALL *CallByteMethodA) (JNIEnv* env, jobject obj, jmethodID methodID, const jvalue* args); + internal readonly delegate* unmanaged[Stdcall] CallByteMethodA; + + // jchar (JNICALL *CallCharMethod) (JNIEnv* env, jobject obj, jmethodID methodID, ...); + internal readonly IntPtr CallCharMethod; + + // jchar (JNICALL *CallCharMethodV) (JNIEnv* env, jobject obj, jmethodID methodID, va_list args); + internal readonly IntPtr CallCharMethodV; + + // jchar (JNICALL *CallCharMethodA) (JNIEnv* env, jobject obj, jmethodID methodID, const jvalue* args); + internal readonly delegate* unmanaged[Stdcall] CallCharMethodA; + + // jshort (JNICALL *CallShortMethod) (JNIEnv* env, jobject obj, jmethodID methodID, ...); + internal readonly IntPtr CallShortMethod; + + // jshort (JNICALL *CallShortMethodV) (JNIEnv* env, jobject obj, jmethodID methodID, va_list args); + internal readonly IntPtr CallShortMethodV; + + // jshort (JNICALL *CallShortMethodA) (JNIEnv* env, jobject obj, jmethodID methodID, const jvalue* args); + internal readonly delegate* unmanaged[Stdcall] CallShortMethodA; + + // jint (JNICALL *CallIntMethod) (JNIEnv* env, jobject obj, jmethodID methodID, ...); + internal readonly IntPtr CallIntMethod; + + // jshort (JNICALL *CallShortMethodV) (JNIEnv* env, jobject obj, jmethodID methodID, va_list args); + internal readonly IntPtr CallIntMethodV; + + // jint (JNICALL *CallIntMethodA) (JNIEnv* env, jobject obj, jmethodID methodID, const jvalue* args); + internal readonly delegate* unmanaged[Stdcall] CallIntMethodA; + + // jlong (JNICALL *CallLongMethod) (JNIEnv* env, jobject obj, jmethodID methodID, ...); + internal readonly IntPtr CallLongMethod; + + // jlong (JNICALL *CallLongMethodV) (JNIEnv* env, jobject obj, jmethodID methodID, va_list args); + internal readonly IntPtr CallLongMethodV; + + // jlong (JNICALL *CallLongMethodA) (JNIEnv* env, jobject obj, jmethodID methodID, const jvalue* args); + internal readonly delegate* unmanaged[Stdcall] CallLongMethodA; + + // jfloat (JNICALL *CallFloatMethod) (JNIEnv* env, jobject obj, jmethodID methodID, ...); + internal readonly IntPtr CallFloatMethod; + + // jfloat (JNICALL *CallFloatMethodV) (JNIEnv* env, jobject obj, jmethodID methodID, va_list args); + internal readonly IntPtr CallFloatMethodV; + + // jfloat (JNICALL *CallFloatMethodA) (JNIEnv* env, jobject obj, jmethodID methodID, const jvalue* args); + internal readonly delegate* unmanaged[Stdcall] CallFloatMethodA; + + // jdouble (JNICALL *CallDoubleMethod) (JNIEnv* env, jobject obj, jmethodID methodID, ...); + internal readonly IntPtr CallDoubleMethod; + + // jdouble (JNICALL *CallDoubleMethodV) (JNIEnv* env, jobject obj, jmethodID methodID, va_list args); + internal readonly IntPtr CallDoubleMethodV; + + // jdouble (JNICALL *CallDoubleMethodA) (JNIEnv* env, jobject obj, jmethodID methodID, const jvalue* args); + internal readonly delegate* unmanaged[Stdcall] CallDoubleMethodA; + + // void (JNICALL *CallVoidMethod) (JNIEnv* env, jobject obj, jmethodID methodID, ...); + internal readonly IntPtr CallVoidMethod; + + // void (JNICALL *CallVoidMethodV) (JNIEnv* env, jobject obj, jmethodID methodID, va_list args); + internal readonly IntPtr CallVoidMethodV; + + // void (JNICALL *CallVoidMethodA) (JNIEnv* env, jobject obj, jmethodID methodID, const jvalue* args); + internal readonly delegate* unmanaged[Stdcall] CallVoidMethodA; + + // jobject (JNICALL *CallNonvirtualObjectMethod) (JNIEnv* env, jobject obj, jclass clazz, jmethodID methodID, ...); + internal readonly IntPtr CallNonvirtualObjectMethod; + + // jobject (JNICALL *CallNonvirtualObjectMethodV) (JNIEnv* env, jobject obj, jclass clazz, jmethodID methodID, va_list args); + internal readonly IntPtr CallNonvirtualObjectMethodV; + + // jobject (JNICALL *CallNonvirtualObjectMethodA) (JNIEnv* env, jobject obj, jclass clazz, jmethodID methodID, const jvalue* args); + internal readonly delegate* unmanaged[Stdcall] CallNonvirtualObjectMethodA; + + // jboolean (JNICALL *CallNonvirtualBooleanMethod) (JNIEnv* env, jobject obj, jclass clazz, jmethodID methodID, ...); + internal readonly IntPtr CallNonvirtualBooleanMethod; + + // jboolean (JNICALL *CallNonvirtualBooleanMethodV) (JNIEnv* env, jobject obj, jclass clazz, jmethodID methodID, va_list args); + internal readonly IntPtr CallNonvirtualBooleanMethodV; + + // jboolean (JNICALL *CallNonvirtualBooleanMethodA) (JNIEnv* env, jobject obj, jclass clazz, jmethodID methodID, const jvalue* args); + internal readonly delegate* unmanaged[Stdcall] CallNonvirtualBooleanMethodA; + + // jbyte (JNICALL *CallNonvirtualByteMethod) (JNIEnv* env, jobject obj, jclass clazz, jmethodID methodID, ...); + internal readonly IntPtr CallNonvirtualByteMethod; + + // jbyte (JNICALL *CallNonvirtualByteMethodV) (JNIEnv* env, jobject obj, jclass clazz, jmethodID methodID, va_list args); + internal readonly IntPtr CallNonvirtualByteMethodV; + + // jbyte (JNICALL *CallNonvirtualByteMethodA) (JNIEnv* env, jobject obj, jclass clazz, jmethodID methodID, const jvalue* args); + internal readonly delegate* unmanaged[Stdcall] CallNonvirtualByteMethodA; + + // jchar (JNICALL *CallNonvirtualCharMethod) (JNIEnv* env, jobject obj, jclass clazz, jmethodID methodID, ...); + internal readonly IntPtr CallNonvirtualCharMethod; + + // jchar (JNICALL *CallNonvirtualCharMethodV) (JNIEnv* env, jobject obj, jclass clazz, jmethodID methodID, va_list args); + internal readonly IntPtr CallNonvirtualCharMethodV; + + // jchar (JNICALL *CallNonvirtualCharMethodA) (JNIEnv* env, jobject obj, jclass clazz, jmethodID methodID, const jvalue* args); + internal readonly delegate* unmanaged[Stdcall] CallNonvirtualCharMethodA; + + // jshort (JNICALL *CallNonvirtualShortMethod) (JNIEnv* env, jobject obj, jclass clazz, jmethodID methodID, ...); + internal readonly IntPtr CallNonvirtualShortMethod; + + // jshort (JNICALL *CallNonvirtualShortMethodV) (JNIEnv* env, jobject obj, jclass clazz, jmethodID methodID, va_list args); + internal readonly IntPtr CallNonvirtualShortMethodV; + + // jshort (JNICALL *CallNonvirtualShortMethodA) (JNIEnv* env, jobject obj, jclass clazz, jmethodID methodID, const jvalue* args); + internal readonly delegate* unmanaged[Stdcall] CallNonvirtualShortMethodA; + + // jint (JNICALL *CallNonvirtualIntMethod) (JNIEnv* env, jobject obj, jclass clazz, jmethodID methodID, ...); + internal readonly IntPtr CallNonvirtualIntMethod; + + // jint (JNICALL *CallNonvirtualIntMethodV) (JNIEnv* env, jobject obj, jclass clazz, jmethodID methodID, va_list args); + internal readonly IntPtr CallNonvirtualIntMethodV; + + // jint (JNICALL *CallNonvirtualIntMethodA) (JNIEnv* env, jobject obj, jclass clazz, jmethodID methodID, const jvalue* args); + internal readonly delegate* unmanaged[Stdcall] CallNonvirtualIntMethodA; + + // jlong (JNICALL *CallNonvirtualLongMethod) (JNIEnv* env, jobject obj, jclass clazz, jmethodID methodID, ...); + internal readonly IntPtr CallNonvirtualLongMethod; + + // jlong (JNICALL *CallNonvirtualLongMethodV)(JNIEnv* env, jobject obj, jclass clazz, jmethodID methodID, va_list args); + internal readonly IntPtr CallNonvirtualLongMethodV; + + // jlong (JNICALL *CallNonvirtualLongMethodA) (JNIEnv* env, jobject obj, jclass clazz, jmethodID methodID, const jvalue* args); + internal readonly delegate* unmanaged[Stdcall] CallNonvirtualLongMethodA; + + // jfloat (JNICALL *CallNonvirtualFloatMethod) (JNIEnv* env, jobject obj, jclass clazz, jmethodID methodID, ...); + internal readonly IntPtr CallNonvirtualFloatMethod; + + // jfloat (JNICALL *CallNonvirtualFloatMethodV) (JNIEnv* env, jobject obj, jclass clazz, jmethodID methodID, va_list args); + internal readonly IntPtr CallNonvirtualFloatMethodV; + + // jfloat (JNICALL *CallNonvirtualFloatMethodA) (JNIEnv* env, jobject obj, jclass clazz, jmethodID methodID, const jvalue* args); + internal readonly delegate* unmanaged[Stdcall] CallNonvirtualFloatMethodA; + + // jdouble (JNICALL *CallNonvirtualDoubleMethod) (JNIEnv* env, jobject obj, jclass clazz, jmethodID methodID, ...); + internal readonly IntPtr CallNonvirtualDoubleMethod; + + // jdouble (JNICALL *CallNonvirtualDoubleMethodV) (JNIEnv* env, jobject obj, jclass clazz, jmethodID methodID, va_list args); + internal readonly IntPtr CallNonvirtualDoubleMethodV; + + // jdouble (JNICALL *CallNonvirtualDoubleMethodA) (JNIEnv* env, jobject obj, jclass clazz, jmethodID methodID, const jvalue* args); + internal readonly delegate* unmanaged[Stdcall] CallNonvirtualDoubleMethodA; + + // void (JNICALL *CallNonvirtualVoidMethod) (JNIEnv* env, jobject obj, jclass clazz, jmethodID methodID, ...); + internal readonly IntPtr CallNonvirtualVoidMethod; + + // void (JNICALL *CallNonvirtualVoidMethodV) (JNIEnv* env, jobject obj, jclass clazz, jmethodID methodID, va_list args); + internal readonly IntPtr CallNonvirtualVoidMethodV; + + // void (JNICALL *CallNonvirtualVoidMethodA) (JNIEnv* env, jobject obj, jclass clazz, jmethodID methodID, const jvalue* args); + internal readonly delegate* unmanaged[Stdcall] CallNonvirtualVoidMethodA; + + // jfieldID (JNICALL *GetFieldID) (JNIEnv* env, jclass clazz, const char* name, const char* sig); + internal readonly delegate* unmanaged[Stdcall] GetFieldID; + + // jobject (JNICALL *GetObjectField) (JNIEnv* env, jobject obj, jfieldID fieldID); + internal readonly delegate* unmanaged[Stdcall] GetObjectField; + + // jboolean (JNICALL *GetBooleanField) (JNIEnv* env, jobject obj, jfieldID fieldID); + internal readonly delegate* unmanaged[Stdcall] GetBooleanField; + + // jbyte (JNICALL *GetByteField) (JNIEnv* env, jobject obj, jfieldID fieldID); + internal readonly delegate* unmanaged[Stdcall] GetByteField; + + // jchar (JNICALL *GetCharField) (JNIEnv* env, jobject obj, jfieldID fieldID); + internal readonly delegate* unmanaged[Stdcall] GetCharField; + + // jshort (JNICALL *GetShortField) (JNIEnv* env, jobject obj, jfieldID fieldID); + internal readonly delegate* unmanaged[Stdcall] GetShortField; + + // jint (JNICALL *GetIntField) (JNIEnv* env, jobject obj, jfieldID fieldID); + internal readonly delegate* unmanaged[Stdcall] GetIntField; + + // jlong (JNICALL *GetLongField) (JNIEnv* env, jobject obj, jfieldID fieldID); + internal readonly delegate* unmanaged[Stdcall] GetLongField; + + // jfloat (JNICALL *GetFloatField) (JNIEnv* env, jobject obj, jfieldID fieldID); + internal readonly delegate* unmanaged[Stdcall] GetFloatField; + + // jdouble (JNICALL *GetDoubleField) (JNIEnv* env, jobject obj, jfieldID fieldID); + internal readonly delegate* unmanaged[Stdcall] GetDoubleField; + + // void (JNICALL *SetObjectField) (JNIEnv* env, jobject obj, jfieldID fieldID, jobject val); + internal readonly delegate* unmanaged[Stdcall] SetObjectField; + + // void (JNICALL *SetBooleanField) (JNIEnv* env, jobject obj, jfieldID fieldID, jboolean val); + internal readonly delegate* unmanaged[Stdcall] SetBooleanField; + + // void (JNICALL *SetByteField) (JNIEnv* env, jobject obj, jfieldID fieldID, jbyte val); + internal readonly delegate* unmanaged[Stdcall] SetByteField; + + // void (JNICALL *SetCharField) (JNIEnv* env, jobject obj, jfieldID fieldID, jchar val); + internal readonly delegate* unmanaged[Stdcall] SetCharField; + + // void (JNICALL *SetShortField) (JNIEnv* env, jobject obj, jfieldID fieldID, jshort val); + internal readonly delegate* unmanaged[Stdcall] SetShortField; + + // void (JNICALL *SetIntField) (JNIEnv* env, jobject obj, jfieldID fieldID, jint val); + internal readonly delegate* unmanaged[Stdcall] SetIntField; + + // void (JNICALL *SetLongField) (JNIEnv* env, jobject obj, jfieldID fieldID, jlong val); + internal readonly delegate* unmanaged[Stdcall] SetLongField; + + // void (JNICALL *SetFloatField) (JNIEnv* env, jobject obj, jfieldID fieldID, jfloat val); + internal readonly delegate* unmanaged[Stdcall] SetFloatField; + + // void (JNICALL *SetDoubleField) (JNIEnv* env, jobject obj, jfieldID fieldID, jdouble val); + internal readonly delegate* unmanaged[Stdcall] SetDoubleField; + + // jmethodID (JNICALL *GetStaticMethodID) (JNIEnv* env, jclass clazz, const char* name, const char* sig); + internal readonly delegate* unmanaged[Stdcall] GetStaticMethodID; + + // jobject (JNICALL *CallStaticObjectMethod) (JNIEnv* env, jclass clazz, jmethodID methodID, ...); + internal readonly IntPtr CallStaticObjectMethod; + + // jobject (JNICALL *CallStaticObjectMethodV) (JNIEnv* env, jclass clazz, jmethodID methodID, va_list args); + internal readonly IntPtr CallStaticObjectMethodV; + + // jobject (JNICALL *CallStaticObjectMethodA) (JNIEnv* env, jclass clazz, jmethodID methodID, const jvalue* args); + internal readonly delegate* unmanaged[Stdcall] CallStaticObjectMethodA; + + // jboolean (JNICALL *CallStaticBooleanMethod) (JNIEnv* env, jclass clazz, jmethodID methodID, ...); + internal readonly IntPtr CallStaticBooleanMethod; + + // jboolean (JNICALL *CallStaticBooleanMethodV) (JNIEnv* env, jclass clazz, jmethodID methodID, va_list args); + internal readonly IntPtr CallStaticBooleanMethodV; + + // jboolean (JNICALL *CallStaticBooleanMethodA) (JNIEnv* env, jclass clazz, jmethodID methodID, const jvalue* args); + internal readonly delegate* unmanaged[Stdcall] CallStaticBooleanMethodA; + + // jbyte (JNICALL *CallStaticByteMethod)(JNIEnv* env, jclass clazz, jmethodID methodID, ...); + internal readonly IntPtr CallStaticByteMethod; + + // jbyte (JNICALL *CallStaticByteMethodV) (JNIEnv* env, jclass clazz, jmethodID methodID, va_list args); + internal readonly IntPtr CallStaticByteMethodV; + + // jbyte (JNICALL *CallStaticByteMethodA) (JNIEnv* env, jclass clazz, jmethodID methodID, const jvalue* args); + internal readonly delegate* unmanaged[Stdcall] CallStaticByteMethodA; + + // jchar (JNICALL *CallStaticCharMethod) (JNIEnv* env, jclass clazz, jmethodID methodID, ...); + internal readonly IntPtr CallStaticCharMethod; + + // jchar (JNICALL *CallStaticCharMethodV) (JNIEnv* env, jclass clazz, jmethodID methodID, va_list args); + internal readonly IntPtr CallStaticCharMethodV; + + // jchar (JNICALL *CallStaticCharMethodA) (JNIEnv* env, jclass clazz, jmethodID methodID, const jvalue* args); + internal readonly delegate* unmanaged[Stdcall] CallStaticCharMethodA; + + // jshort (JNICALL *CallStaticShortMethod) (JNIEnv* env, jclass clazz, jmethodID methodID, ...); + internal readonly IntPtr CallStaticShortMethod; + + // jshort (JNICALL *CallStaticShortMethodV) (JNIEnv* env, jclass clazz, jmethodID methodID, va_list args); + internal readonly IntPtr CallStaticShortMethodV; + + // jshort (JNICALL *CallStaticShortMethodA) (JNIEnv* env, jclass clazz, jmethodID methodID, const jvalue* args); + internal readonly delegate* unmanaged[Stdcall] CallStaticShortMethodA; + + // jint (JNICALL *CallStaticIntMethod) (JNIEnv* env, jclass clazz, jmethodID methodID, ...); + internal readonly IntPtr CallStaticIntMethod; + + // jint (JNICALL *CallStaticIntMethodV) (JNIEnv* env, jclass clazz, jmethodID methodID, va_list args); + internal readonly IntPtr CallStaticIntMethodV; + + // jint (JNICALL *CallStaticIntMethodA) (JNIEnv* env, jclass clazz, jmethodID methodID, const jvalue* args); + internal readonly delegate* unmanaged[Stdcall] CallStaticIntMethodA; + + // jlong (JNICALL *CallStaticLongMethod) (JNIEnv* env, jclass clazz, jmethodID methodID, ...); + internal readonly IntPtr CallStaticLongMethod; + + // jlong (JNICALL *CallStaticLongMethodV) (JNIEnv* env, jclass clazz, jmethodID methodID, va_list args); + internal readonly IntPtr CallStaticLongMethodV; + + // jlong (JNICALL *CallStaticLongMethodA) (JNIEnv* env, jclass clazz, jmethodID methodID, const jvalue* args); + internal readonly delegate* unmanaged[Stdcall] CallStaticLongMethodA; + + // jfloat (JNICALL *CallStaticFloatMethod) (JNIEnv* env, jclass clazz, jmethodID methodID, ...); + internal readonly IntPtr CallStaticFloatMethod; + + // jfloat (JNICALL *CallStaticFloatMethodV) (JNIEnv* env, jclass clazz, jmethodID methodID, va_list args); + internal readonly IntPtr CallStaticFloatMethodV; + + // jfloat (JNICALL *CallStaticFloatMethodA) (JNIEnv* env, jclass clazz, jmethodID methodID, const jvalue* args); + internal readonly delegate* unmanaged[Stdcall] CallStaticFloatMethodA; + + // jdouble (JNICALL *CallStaticDoubleMethod) (JNIEnv* env, jclass clazz, jmethodID methodID, ...); + internal readonly IntPtr CallStaticDoubleMethod; + + // jdouble (JNICALL *CallStaticDoubleMethodV) (JNIEnv* env, jclass clazz, jmethodID methodID, va_list args); + internal readonly IntPtr CallStaticDoubleMethodV; + + // jdouble (JNICALL *CallStaticDoubleMethodA) (JNIEnv* env, jclass clazz, jmethodID methodID, const jvalue* args); + internal readonly delegate* unmanaged[Stdcall] CallStaticDoubleMethodA; + + // void (JNICALL *CallStaticVoidMethod) (JNIEnv* env, jclass cls, jmethodID methodID, ...); + internal readonly IntPtr CallStaticVoidMethod; + + // void (JNICALL *CallStaticVoidMethodV) (JNIEnv* env, jclass cls, jmethodID methodID, va_list args); + internal readonly IntPtr CallStaticVoidMethodV; + + // void (JNICALL *CallStaticVoidMethodA) (JNIEnv* env, jclass cls, jmethodID methodID, const jvalue* args); + internal readonly delegate* unmanaged[Stdcall] CallStaticVoidMethodA; + + // jfieldID (JNICALL *GetStaticFieldID) (JNIEnv* env, jclass clazz, const char* name, const char* sig); + internal readonly delegate* unmanaged[Stdcall] GetStaticFieldID; + + // jobject (JNICALL *GetStaticObjectField) (JNIEnv* env, jclass clazz, jfieldID fieldID); + internal readonly delegate* unmanaged[Stdcall] GetStaticObjectField; + + // jboolean (JNICALL *GetStaticBooleanField) (JNIEnv* env, jclass clazz, jfieldID fieldID); + internal readonly delegate* unmanaged[Stdcall] GetStaticBooleanField; + + // jbyte (JNICALL *GetStaticByteField) (JNIEnv* env, jclass clazz, jfieldID fieldID); + internal readonly delegate* unmanaged[Stdcall] GetStaticByteField; + + // jchar (JNICALL *GetStaticCharField) (JNIEnv* env, jclass clazz, jfieldID fieldID); + internal readonly delegate* unmanaged[Stdcall] GetStaticCharField; + + // jshort (JNICALL *GetStaticShortField) (JNIEnv* env, jclass clazz, jfieldID fieldID); + internal readonly delegate* unmanaged[Stdcall] GetStaticShortField; + + // jint (JNICALL *GetStaticIntField) (JNIEnv* env, jclass clazz, jfieldID fieldID); + internal readonly delegate* unmanaged[Stdcall] GetStaticIntField; + + // jlong (JNICALL *GetStaticLongField) (JNIEnv* env, jclass clazz, jfieldID fieldID); + internal readonly delegate* unmanaged[Stdcall] GetStaticLongField; + + // jfloat (JNICALL *GetStaticFloatField) (JNIEnv* env, jclass clazz, jfieldID fieldID); + internal readonly delegate* unmanaged[Stdcall] GetStaticFloatField; + + // jdouble (JNICALL *GetStaticDoubleField) (JNIEnv* env, jclass clazz, jfieldID fieldID); + internal readonly delegate* unmanaged[Stdcall] GetStaticDoubleField; + + // void (JNICALL *SetStaticObjectField) (JNIEnv* env, jclass clazz, jfieldID fieldID, jobject value); + internal readonly delegate* unmanaged[Stdcall] SetStaticObjectField; + + // void (JNICALL *SetStaticBooleanField) (JNIEnv* env, jclass clazz, jfieldID fieldID, jboolean value); + internal readonly delegate* unmanaged[Stdcall] SetStaticBooleanField; + + // void (JNICALL *SetStaticByteField) (JNIEnv* env, jclass clazz, jfieldID fieldID, jbyte value); + internal readonly delegate* unmanaged[Stdcall] SetStaticByteField; + + // void (JNICALL *SetStaticCharField) (JNIEnv* env, jclass clazz, jfieldID fieldID, jchar value); + internal readonly delegate* unmanaged[Stdcall] SetStaticCharField; + + // void (JNICALL *SetStaticShortField) (JNIEnv* env, jclass clazz, jfieldID fieldID, jshort value); + internal readonly delegate* unmanaged[Stdcall] SetStaticShortField; + + // void (JNICALL *SetStaticIntField) (JNIEnv* env, jclass clazz, jfieldID fieldID, jint value); + internal readonly delegate* unmanaged[Stdcall] SetStaticIntField; + + // void (JNICALL *SetStaticLongField) (JNIEnv* env, jclass clazz, jfieldID fieldID, jlong value); + internal readonly delegate* unmanaged[Stdcall] SetStaticLongField; + + // void (JNICALL *SetStaticFloatField) (JNIEnv* env, jclass clazz, jfieldID fieldID, jfloat value); + internal readonly delegate* unmanaged[Stdcall] SetStaticFloatField; + + // void (JNICALL *SetStaticDoubleField) (JNIEnv* env, jclass clazz, jfieldID fieldID, jdouble value); + internal readonly delegate* unmanaged[Stdcall] SetStaticDoubleField; + + // jstring (JNICALL *NewString) (JNIEnv* env, const jchar* unicode, jsize len); + internal readonly delegate* unmanaged[Stdcall] NewString; + + // jsize (JNICALL *GetStringLength) (JNIEnv* env, jstring str); + internal readonly delegate* unmanaged[Stdcall] GetStringLength; + + // const jchar *(JNICALL *GetStringChars) (JNIEnv* env, jstring str, jboolean* isCopy); + internal readonly delegate* unmanaged[Stdcall] GetStringChars; + + // void (JNICALL *ReleaseStringChars) (JNIEnv* env, jstring str, const jchar* chars); + internal readonly delegate* unmanaged[Stdcall] ReleaseStringChars; + + // jstring (JNICALL *NewStringUTF) (JNIEnv* env, const char* utf); + internal readonly delegate* unmanaged[Stdcall] NewStringUTF; + + // jsize (JNICALL *GetStringUTFLength) (JNIEnv* env, jstring str); + internal readonly delegate* unmanaged[Stdcall] GetStringUTFLength; + + // const char* (JNICALL *GetStringUTFChars) (JNIEnv* env, jstring str, jboolean* isCopy); + internal readonly delegate* unmanaged[Stdcall] GetStringUTFChars; + + // void (JNICALL *ReleaseStringUTFChars) (JNIEnv* env, jstring str, const char* chars); + internal readonly delegate* unmanaged[Stdcall] ReleaseStringUTFChars; + + // jsize (JNICALL *GetArrayLength) (JNIEnv* env, jarray array); + internal readonly delegate* unmanaged[Stdcall] GetArrayLength; + + // jobjectArray (JNICALL *NewObjectArray) (JNIEnv* env, jsize len, jclass clazz, jobject init); + internal readonly delegate* unmanaged[Stdcall] NewObjectArray; + + // jobject (JNICALL *GetObjectArrayElement) (JNIEnv* env, jobjectArray array, jsize index); + internal readonly delegate* unmanaged[Stdcall] GetObjectArrayElement; + + // void (JNICALL *SetObjectArrayElement) (JNIEnv* env, jobjectArray array, jsize index, jobject val); + internal readonly delegate* unmanaged[Stdcall] SetObjectArrayElement; + + // jbooleanArray (JNICALL *NewBooleanArray) (JNIEnv* env, jsize len); + internal readonly delegate* unmanaged[Stdcall] NewBooleanArray; + + // jbyteArray (JNICALL *NewByteArray) (JNIEnv* env, jsize len); + internal readonly delegate* unmanaged[Stdcall] NewByteArray; + + // jcharArray (JNICALL *NewCharArray) (JNIEnv* env, jsize len); + internal readonly delegate* unmanaged[Stdcall] NewCharArray; + + // jshortArray (JNICALL *NewShortArray) (JNIEnv* env, jsize len); + internal readonly delegate* unmanaged[Stdcall] NewShortArray; + + // jintArray (JNICALL *NewIntArray) (JNIEnv* env, jsize len); + internal readonly delegate* unmanaged[Stdcall] NewIntArray; + + // jlongArray (JNICALL *NewLongArray) (JNIEnv* env, jsize len); + internal readonly delegate* unmanaged[Stdcall] NewLongArray; + + // jfloatArray (JNICALL *NewFloatArray) (JNIEnv* env, jsize len); + internal readonly delegate* unmanaged[Stdcall] NewFloatArray; + + // jdoubleArray (JNICALL *NewDoubleArray) (JNIEnv* env, jsize len); + internal readonly delegate* unmanaged[Stdcall] NewDoubleArray; + + // jboolean * (JNICALL *GetBooleanArrayElements) (JNIEnv* env, jbooleanArray array, jboolean* isCopy); + internal readonly delegate* unmanaged[Stdcall] GetBooleanArrayElements; + + // jbyte * (JNICALL *GetByteArrayElements) (JNIEnv* env, jbyteArray array, jboolean* isCopy); + internal readonly delegate* unmanaged[Stdcall] GetByteArrayElements; + + // jchar * (JNICALL *GetCharArrayElements) (JNIEnv* env, jcharArray array, jboolean* isCopy); + internal readonly delegate* unmanaged[Stdcall] GetCharArrayElements; + + // jshort * (JNICALL *GetShortArrayElements) (JNIEnv* env, jshortArray array, jboolean* isCopy); + internal readonly delegate* unmanaged[Stdcall] GetShortArrayElements; + + // jint * (JNICALL *GetIntArrayElements) (JNIEnv* env, jintArray array, jboolean* isCopy); + internal readonly delegate* unmanaged[Stdcall] GetIntArrayElements; + + // jlong * (JNICALL *GetLongArrayElements) (JNIEnv* env, jlongArray array, jboolean* isCopy); + internal readonly delegate* unmanaged[Stdcall] GetLongArrayElements; + + // jfloat * (JNICALL *GetFloatArrayElements) (JNIEnv* env, jfloatArray array, jboolean* isCopy); + internal readonly delegate* unmanaged[Stdcall] GetFloatArrayElements; + + // jdouble * (JNICALL *GetDoubleArrayElements) (JNIEnv* env, jdoubleArray array, jboolean* isCopy); + internal readonly delegate* unmanaged[Stdcall] GetDoubleArrayElements; + + // void (JNICALL *ReleaseBooleanArrayElements) (JNIEnv* env, jbooleanArray array, jboolean* elems, jint mode); + internal readonly delegate* unmanaged[Stdcall] ReleaseBooleanArrayElements; + + // void (JNICALL *ReleaseByteArrayElements) (JNIEnv* env, jbyteArray array, jbyte* elems, jint mode); + internal readonly delegate* unmanaged[Stdcall] ReleaseByteArrayElements; + + // void (JNICALL *ReleaseCharArrayElements) (JNIEnv* env, jcharArray array, jchar* elems, jint mode); + internal readonly delegate* unmanaged[Stdcall] ReleaseCharArrayElements; + + // void (JNICALL *ReleaseShortArrayElements) (JNIEnv* env, jshortArray array, jshort* elems, jint mode); + internal readonly delegate* unmanaged[Stdcall] ReleaseShortArrayElements; + + // void (JNICALL *ReleaseIntArrayElements) (JNIEnv* env, jintArray array, jint* elems, jint mode); + internal readonly delegate* unmanaged[Stdcall] ReleaseIntArrayElements; + + // void (JNICALL *ReleaseLongArrayElements) (JNIEnv* env, jlongArray array, jlong* elems, jint mode); + internal readonly delegate* unmanaged[Stdcall] ReleaseLongArrayElements; + + // void (JNICALL *ReleaseFloatArrayElements) (JNIEnv* env, jfloatArray array, jfloat* elems, jint mode); + internal readonly delegate* unmanaged[Stdcall] ReleaseFloatArrayElements; + + // void (JNICALL *ReleaseDoubleArrayElements) (JNIEnv* env, jdoubleArray array, jdouble* elems, jint mode); + internal readonly delegate* unmanaged[Stdcall] ReleaseDoubleArrayElements; + + // void (JNICALL *GetBooleanArrayRegion) (JNIEnv* env, jbooleanArray array, jsize start, jsize l, jboolean* buf); + internal readonly delegate* unmanaged[Stdcall] GetBooleanArrayRegion; + + // void (JNICALL *GetByteArrayRegion) (JNIEnv* env, jbyteArray array, jsize start, jsize len, jbyte* buf); + internal readonly delegate* unmanaged[Stdcall] GetByteArrayRegion; + + // void (JNICALL *GetCharArrayRegion) (JNIEnv* env, jcharArray array, jsize start, jsize len, jchar* buf); + internal readonly delegate* unmanaged[Stdcall] GetCharArrayRegion; + + // void (JNICALL *GetShortArrayRegion) (JNIEnv* env, jshortArray array, jsize start, jsize len, jshort* buf); + internal readonly delegate* unmanaged[Stdcall] GetShortArrayRegion; + + // void (JNICALL *GetIntArrayRegion) (JNIEnv* env, jintArray array, jsize start, jsize len, jint* buf); + internal readonly delegate* unmanaged[Stdcall] GetIntArrayRegion; + + // void (JNICALL *GetLongArrayRegion) (JNIEnv* env, jlongArray array, jsize start, jsize len, jlong* buf); + internal readonly delegate* unmanaged[Stdcall] GetLongArrayRegion; + + // void (JNICALL *GetFloatArrayRegion) (JNIEnv* env, jfloatArray array, jsize start, jsize len, jfloat* buf); + internal readonly delegate* unmanaged[Stdcall] GetFloatArrayRegion; + + // void (JNICALL *GetDoubleArrayRegion) (JNIEnv* env, jdoubleArray array, jsize start, jsize len, jdouble* buf); + internal readonly delegate* unmanaged[Stdcall] GetDoubleArrayRegion; + + // void (JNICALL *SetBooleanArrayRegion) (JNIEnv* env, jbooleanArray array, jsize start, jsize l, const jboolean* buf); + internal readonly delegate* unmanaged[Stdcall] SetBooleanArrayRegion; + + // void (JNICALL *SetByteArrayRegion) (JNIEnv* env, jbyteArray array, jsize start, jsize len, const jbyte* buf); + internal readonly delegate* unmanaged[Stdcall] SetByteArrayRegion; + + // void (JNICALL *SetCharArrayRegion) (JNIEnv* env, jcharArray array, jsize start, jsize len, const jchar* buf); + internal readonly delegate* unmanaged[Stdcall] SetCharArrayRegion; + + // void (JNICALL *SetShortArrayRegion) (JNIEnv* env, jshortArray array, jsize start, jsize len, const jshort* buf); + internal readonly delegate* unmanaged[Stdcall] SetShortArrayRegion; + + // void (JNICALL *SetIntArrayRegion) (JNIEnv* env, jintArray array, jsize start, jsize len, const jint* buf); + internal readonly delegate* unmanaged[Stdcall] SetIntArrayRegion; + + // void (JNICALL *SetLongArrayRegion) (JNIEnv* env, jlongArray array, jsize start, jsize len, const jlong* buf); + internal readonly delegate* unmanaged[Stdcall] SetLongArrayRegion; + + // void (JNICALL *SetFloatArrayRegion) (JNIEnv* env, jfloatArray array, jsize start, jsize len, const jfloat* buf); + internal readonly delegate* unmanaged[Stdcall] SetFloatArrayRegion; + + // void (JNICALL *SetDoubleArrayRegion) (JNIEnv* env, jdoubleArray array, jsize start, jsize len, const jdouble* buf); + internal readonly delegate* unmanaged[Stdcall] SetDoubleArrayRegion; + +// jint (JNICALL *RegisterNatives) (JNIEnv* env, jclass clazz, const JNINativeMethod* methods, jint nMethods); + // internal readonly delegate* unmanaged[Stdcall] RegisterNatives; + internal readonly delegate* unmanaged[Stdcall] RegisterNatives; + + // jint (JNICALL *UnregisterNatives) (JNIEnv* env, jclass clazz); + internal readonly delegate* unmanaged[Stdcall] UnregisterNatives; + + // jint (JNICALL *MonitorEnter) (JNIEnv* env, jobject obj); + internal readonly delegate* unmanaged[Stdcall] MonitorEnter; + + // jint (JNICALL *MonitorExit) (JNIEnv* env, jobject obj); + internal readonly delegate* unmanaged[Stdcall] MonitorExit; + + // jint (JNICALL *GetJavaVM) (JNIEnv* env, JavaVM** vm); + internal readonly delegate* unmanaged[Stdcall] GetJavaVM; + + // void (JNICALL *GetStringRegion) (JNIEnv* env, jstring str, jsize start, jsize len, jchar* buf); + internal readonly delegate* unmanaged[Stdcall] GetStringRegion; + + // void (JNICALL *GetStringUTFRegion) (JNIEnv* env, jstring str, jsize start, jsize len, char* buf); + internal readonly delegate* unmanaged[Stdcall] GetStringUTFRegion; + + // void * (JNICALL *GetPrimitiveArrayCritical) (JNIEnv* env, jarray array, jboolean* isCopy); + internal readonly delegate* unmanaged[Stdcall] GetPrimitiveArrayCritical; + + // void (JNICALL *ReleasePrimitiveArrayCritical) (JNIEnv* env, jarray array, void* carray, jint mode); + internal readonly delegate* unmanaged[Stdcall] ReleasePrimitiveArrayCritical; + + // const jchar * (JNICALL *GetStringCritical) (JNIEnv* env, jstring string, jboolean* isCopy); + internal readonly delegate* unmanaged[Stdcall] GetStringCritical; + + // void (JNICALL *ReleaseStringCritical) (JNIEnv* env, jstring string, const jchar* cstring); + internal readonly delegate* unmanaged[Stdcall] ReleaseStringCritical; + + // jweak (JNICALL *NewWeakGlobalRef) (JNIEnv* env, jobject obj); + internal readonly delegate* unmanaged[Stdcall] NewWeakGlobalRef; + + // void (JNICALL *DeleteWeakGlobalRef) (JNIEnv* env, jweak ref); + internal readonly delegate* unmanaged[Stdcall] DeleteWeakGlobalRef; + + // jboolean (JNICALL *ExceptionCheck) (JNIEnv* env); + internal readonly delegate* unmanaged[Stdcall] ExceptionCheck; + + // jobject (JNICALL *NewDirectByteBuffer) (JNIEnv* env, void* address, jlong capacity); + internal readonly delegate* unmanaged[Stdcall] NewDirectByteBuffer; + + // void* (JNICALL *GetDirectBufferAddress) (JNIEnv* env, jobject buf); + internal readonly delegate* unmanaged[Stdcall] GetDirectBufferAddress; + + // jlong (JNICALL *GetDirectBufferCapacity) (JNIEnv* env, jobject buf); + internal readonly delegate* unmanaged[Stdcall] GetDirectBufferCapacity; + } + + internal readonly FunctionTable* Functions; +} +#endif diff --git a/MelonLoader/JNI/JNIResultException.cs b/MelonLoader/JNI/JNIResultException.cs new file mode 100644 index 000000000..948d840b6 --- /dev/null +++ b/MelonLoader/JNI/JNIResultException.cs @@ -0,0 +1,15 @@ +#if ANDROID +using System; + +namespace MelonLoader.Java; + +public class JNIResultException : Exception +{ + public JNI.Result Result { get; set;} + + public JNIResultException(JNI.Result result) : base($"JNI error occurred: {result}") + { + this.Result = result; + } +} +#endif diff --git a/MelonLoader/JNI/JObject.cs b/MelonLoader/JNI/JObject.cs new file mode 100644 index 000000000..6d8a07a49 --- /dev/null +++ b/MelonLoader/JNI/JObject.cs @@ -0,0 +1,67 @@ +#if ANDROID +using System; + +namespace MelonLoader.Java; + +public class JObject : IDisposable +{ + private bool Disposed { get; set; } + + public IntPtr Handle { get; set;} + + internal JNI.ReferenceType ReferenceType { get; set;} + + public JObject() { } + + public JObject(IntPtr handle, JNI.ReferenceType referenceType) + { + this.Handle = handle; + this.ReferenceType = referenceType; + } + + public JObject(JObject obj) : this(obj.Handle, obj.ReferenceType) + { + this.Disposed = obj.Disposed; + obj.Disposed = true; + } + + protected virtual void Dispose(bool disposing) + { + if (Disposed || this.Handle == IntPtr.Zero) + return; + + switch (this.ReferenceType) + { + case JNI.ReferenceType.Local: + JNI.DeleteLocalRef(this); + break; + + case JNI.ReferenceType.Global: + JNI.DeleteGlobalRef(this); + break; + + case JNI.ReferenceType.WeakGlobal: + JNI.DeleteWeakGlobalRef(this); + break; + } + + Disposed = true; + } + + public bool Valid() + { + return this.Handle != IntPtr.Zero; + } + + ~JObject() + { + Dispose(disposing: false); + } + + public void Dispose() + { + Dispose(disposing: true); + GC.SuppressFinalize(this); + } +} +#endif diff --git a/MelonLoader/JNI/JObjectArray.cs b/MelonLoader/JNI/JObjectArray.cs new file mode 100644 index 000000000..f1506cb51 --- /dev/null +++ b/MelonLoader/JNI/JObjectArray.cs @@ -0,0 +1,35 @@ +#if ANDROID +namespace MelonLoader.Java; + +using System.Collections; +using System.Collections.Generic; + +public class JObjectArray : JObject, IEnumerable where T : JObject, new() +{ + public int Length => JNI.GetArrayLength(this); + + public T this[int index] + { + get => JNI.GetObjectArrayElement(this, index); + set => JNI.SetObjectArrayElement(this, index, value); + } + + public void SetElement(T value, int index) + { + JNI.SetObjectArrayElement(this, index, value); + } + + public IEnumerator GetEnumerator() + { + for (int i = 0; i < this.Length; i++) + { + yield return JNI.GetObjectArrayElement(this, i); + } + } + + IEnumerator IEnumerable.GetEnumerator() + { + return this.GetEnumerator(); + } +} +#endif diff --git a/MelonLoader/JNI/JString.cs b/MelonLoader/JNI/JString.cs new file mode 100644 index 000000000..064f0ce06 --- /dev/null +++ b/MelonLoader/JNI/JString.cs @@ -0,0 +1,10 @@ +#if ANDROID +namespace MelonLoader.Java; + +public class JString : JObject +{ + public JString() : base() { } + + public string GetString() => JNI.GetJStringString(this); +} +#endif diff --git a/MelonLoader/JNI/JThrowable.cs b/MelonLoader/JNI/JThrowable.cs new file mode 100644 index 000000000..3413cb445 --- /dev/null +++ b/MelonLoader/JNI/JThrowable.cs @@ -0,0 +1,12 @@ +#if ANDROID +namespace MelonLoader.Java; + +public class JThrowable : JObject +{ + public JThrowable() { } + + public string GetMessage() => JNI.FindClass("java/lang/Throwable").CallObjectMethod(this, "getMessage", "()Ljava/lang/String;").GetString(); + + public override string ToString() => JNI.FindClass("java/lang/Throwable").CallObjectMethod(this, "toString", "()Ljava/lang/String;").GetString(); +} +#endif diff --git a/MelonLoader/JNI/JThrowableException.cs b/MelonLoader/JNI/JThrowableException.cs new file mode 100644 index 000000000..a013495ef --- /dev/null +++ b/MelonLoader/JNI/JThrowableException.cs @@ -0,0 +1,17 @@ +#if ANDROID +using System; + +namespace MelonLoader.Java; + +public class JThrowableException : Exception +{ + public JThrowable? Throwable { get; set;} + + public JThrowableException() { } + + public JThrowableException(JThrowable throwable) : base() + { + this.Throwable = throwable; + } +} +#endif diff --git a/MelonLoader/JNI/JValue.cs b/MelonLoader/JNI/JValue.cs new file mode 100644 index 000000000..2928fd8d6 --- /dev/null +++ b/MelonLoader/JNI/JValue.cs @@ -0,0 +1,158 @@ +#if ANDROID +namespace MelonLoader.Java; + +using System; +using System.Runtime.InteropServices; + +[StructLayout(LayoutKind.Explicit, Size = 8)] +public readonly struct JValue +{ + [FieldOffset(0)] + public readonly byte Z; + + [FieldOffset(0)] + public readonly sbyte B; + + [FieldOffset(0)] + public readonly char C; + + [FieldOffset(0)] + public readonly short S; + + [FieldOffset(0)] + public readonly int I; + + [FieldOffset(0)] + public readonly long J; + + [FieldOffset(0)] + public readonly float F; + + [FieldOffset(0)] + public readonly double D; + + [FieldOffset(0)] + public readonly IntPtr L; + + public JValue(bool value) + { + this = new JValue(); + Z = Convert.ToByte(value); + } + + public JValue(sbyte value) + { + this = new JValue(); + B = value; + } + + public JValue(char value) + { + this = new JValue(); + C = value; + } + + public JValue(short value) + { + this = new JValue(); + S = value; + } + + public JValue(int value) + { + this = new JValue(); + I = value; + } + + public JValue(long value) + { + this = new JValue(); + J = value; + } + + public JValue(float value) + { + this = new JValue(); + F = value; + } + + public JValue(double value) + { + this = new JValue(); + D = value; + } + + public JValue(IntPtr value) + { + this = new JValue(); + L = value; + } + + public JValue(JObject obj) + { + this = new JValue(); + this.L = obj.Handle; + } + + public JValue(object value) + { + this = new JValue(); + switch (value) + { + case bool z: + this.Z = Convert.ToByte(z); + break; + + case sbyte b: + this.B = b; + break; + + case char c: + this.C = c; + break; + + case short s: + this.S = s; + break; + + case int i: + this.I = i; + break; + + case long j: + this.J = j; + break; + + case float f: + this.F = f; + break; + + case double d: + this.D = d; + break; + + case JObject obj: + this.L = obj.Handle; + break; + } + } + + public static implicit operator JValue(bool b) => new JValue(b); + + public static implicit operator JValue(sbyte b) => new JValue(b); + + public static implicit operator JValue(char c) => new JValue(c); + + public static implicit operator JValue(short s) => new JValue(s); + + public static implicit operator JValue(int i) => new JValue(i); + + public static implicit operator JValue(long j) => new JValue(j); + + public static implicit operator JValue(float f) => new JValue(f); + + public static implicit operator JValue(double d) => new JValue(d); + + public static implicit operator JValue(JObject obj) => new JValue(obj); +} +#endif diff --git a/MelonLoader/JNI/JavaVM.cs b/MelonLoader/JNI/JavaVM.cs new file mode 100644 index 000000000..d3ec83119 --- /dev/null +++ b/MelonLoader/JNI/JavaVM.cs @@ -0,0 +1,40 @@ +#if ANDROID +namespace MelonLoader.Java; + +using System; +using System.Runtime.InteropServices; + +/// +/// Represents a JavaVM C struct. +/// +[StructLayout(LayoutKind.Sequential)] +internal readonly unsafe struct JavaVM +{ + [StructLayout(LayoutKind.Sequential)] + internal readonly unsafe struct FunctionTable + { + internal readonly IntPtr Reserved0; + + internal readonly IntPtr Reserved1; + + internal readonly IntPtr Reserved2; + + // jint (JNICALL *DestroyJavaVM)(JavaVM *vm); + internal readonly delegate* unmanaged[Stdcall] DestroyJavaVM; + + // jint (JNICALL *AttachCurrentThread)(JavaVM *vm, void **penv, void *args); + internal readonly delegate* unmanaged[Stdcall] AttachCurrentThread; + + // jint (JNICALL *DetachCurrentThread)(JavaVM *vm); + internal readonly delegate* unmanaged[Stdcall] DetachCurrentThread; + + // jint (JNICALL *GetEnv)(JavaVM *vm, void **penv, jint version); + internal readonly delegate* unmanaged[Stdcall] GetEnv; + + // jint (JNICALL *AttachCurrentThreadAsDaemon)(JavaVM *vm, void **penv, void *args); + internal readonly delegate* unmanaged[Stdcall] AttachCurrentThreadAsDaemon; + } + + internal readonly FunctionTable* Functions; +} +#endif diff --git a/MelonLoader/JNI/ReferenceType.cs b/MelonLoader/JNI/ReferenceType.cs new file mode 100644 index 000000000..2df597e9e --- /dev/null +++ b/MelonLoader/JNI/ReferenceType.cs @@ -0,0 +1,13 @@ +#if ANDROID +namespace MelonLoader.Java; + +public static partial class JNI +{ + public enum ReferenceType + { + Local = 0, + Global = 1, + WeakGlobal = 2 + } +} +#endif diff --git a/MelonLoader/JNI/ReleaseMode.cs b/MelonLoader/JNI/ReleaseMode.cs new file mode 100644 index 000000000..09c47a813 --- /dev/null +++ b/MelonLoader/JNI/ReleaseMode.cs @@ -0,0 +1,13 @@ +#if ANDROID +namespace MelonLoader.Java; + +public static partial class JNI +{ + public enum ReleaseMode + { + Default = 0, + Commit = 1, + Abort = 2 + } +} +#endif diff --git a/MelonLoader/JNI/Result.cs b/MelonLoader/JNI/Result.cs new file mode 100644 index 000000000..47dba5747 --- /dev/null +++ b/MelonLoader/JNI/Result.cs @@ -0,0 +1,41 @@ +#if ANDROID +namespace MelonLoader.Java; + +public static partial class JNI +{ + /// + /// Represents a JNI error. + /// + public enum Result + { + /// + /// Success. + /// + Ok = 0, + /// + /// Unknown error occured. + /// + Unknown = -1, + /// + /// Thread detached from the JVM. + /// + Detached = -2, + /// + /// Version unsupported. + /// + Version = -3, + /// + /// JVM out of memory. + /// + OutOfMemory = -4, + /// + /// JVM already exists. + /// + AlreadyExists = -5, + /// + /// Invalid arguments passed. + /// + InvalidArguments = -6 + } +} +#endif diff --git a/MelonLoader/JNI/TypeSignature.cs b/MelonLoader/JNI/TypeSignature.cs new file mode 100644 index 000000000..d1f7cac08 --- /dev/null +++ b/MelonLoader/JNI/TypeSignature.cs @@ -0,0 +1,69 @@ +#if ANDROID +using System; + +namespace MelonLoader.Java; + +public static partial class JNI +{ + public static class TypeSignature + { + public const string Bool = "Z"; + + public const string Byte = "B"; + + public const string Char = "C"; + + public const string Short = "S"; + + public const string Int = "I"; + + public const string Long = "J"; + + public const string Float = "F"; + + public const string Double = "D"; + } + + public static string GetTypeSignature() + { + Type t = typeof(T); + + if (t == typeof(bool)) + { + return TypeSignature.Bool; + } + else if (t == typeof(sbyte)) + { + return TypeSignature.Byte; + } + else if (t == typeof(char)) + { + return TypeSignature.Char; + } + else if (t == typeof(short)) + { + return TypeSignature.Short; + } + else if (t == typeof(int)) + { + return TypeSignature.Int; + } + else if (t == typeof(long)) + { + return TypeSignature.Long; + } + else if (t == typeof(float)) + { + return TypeSignature.Float; + } + else if (t == typeof(double)) + { + return TypeSignature.Double; + } + else + { + throw new ArgumentException($"GetTypeSignature Type {t} not supported."); + } + } +} +#endif diff --git a/MelonLoader/JNI/Version.cs b/MelonLoader/JNI/Version.cs new file mode 100644 index 000000000..0d53a7f03 --- /dev/null +++ b/MelonLoader/JNI/Version.cs @@ -0,0 +1,15 @@ +#if ANDROID +namespace MelonLoader.Java; + +public static partial class JNI +{ + public enum Version + { + V1_1 = 0x00010001, + V1_2 = 0x00010001, + V1_4 = 0x00010004, + V1_6 = 0x00010006, + V1_8 = 0x00010008 + } +} +#endif diff --git a/MelonLoader/LoaderConfig.cs b/MelonLoader/LoaderConfig.cs index 36dc73b6f..082fe74c2 100644 --- a/MelonLoader/LoaderConfig.cs +++ b/MelonLoader/LoaderConfig.cs @@ -136,7 +136,7 @@ public class UnityEngineConfig private const string MonoPathSeparatorDescription = #if WINDOWS "semicolon (;)"; -#elif LINUX || OSX +#elif LINUX || OSX || ANDROID "colon (:)"; #endif diff --git a/MelonLoader/Utils/APKAssetManager.cs b/MelonLoader/Utils/APKAssetManager.cs new file mode 100644 index 000000000..eb377c594 --- /dev/null +++ b/MelonLoader/Utils/APKAssetManager.cs @@ -0,0 +1,288 @@ +#nullable enable + +#if ANDROID +using MelonLoader.Java; +using System; +using System.IO; +using System.Linq; + +namespace MelonLoader.Utils; + +public static class APKAssetManager +{ + private static JObject? assetManager; + + public static void Initialize() + { + GetAndroidAssetManager(); + } + + public static void SaveItemToDirectory(string itemPath, string copyBase, bool includeInitial = true) + { + if (assetManager == null || !assetManager.Valid()) + { + GetAndroidAssetManager(); + if (assetManager == null || !assetManager.Valid()) + throw new Exception("[APKAssetManager] Asset manager is not initialized."); + } + + string[] contents = GetDirectoryContents(itemPath); + if (contents.Length == 0) + { + string path = includeInitial ? itemPath : itemPath[(itemPath.IndexOf('/') + 1)..]; + if (string.IsNullOrEmpty(path)) + return; + + string outPath = Path.Combine(copyBase, path); + string outDir = Path.GetDirectoryName(outPath)!; + + if (!Directory.Exists(outDir)) + Directory.CreateDirectory(outDir); + + using FileStream fileStream = File.Open(outPath, FileMode.Create); + using Stream? assetStream = GetAssetStream(itemPath); + if (assetStream == null) + throw new Exception("[APKAssetManager] Failed to get asset stream: " + itemPath); + + byte[] buffer = new byte[81920]; + int bytesRead; + while ((bytesRead = assetStream.Read(buffer, 0, buffer.Length)) > 0) + fileStream.Write(buffer, 0, bytesRead); + + return; + } + + foreach (string item in contents) + { + SaveItemToDirectory(Path.Combine(itemPath, item), copyBase, includeInitial); + } + } + + public static byte[] GetAssetBytes(string path) + { + if (assetManager == null || !assetManager.Valid()) + { + GetAndroidAssetManager(); + if (assetManager == null || !assetManager.Valid()) + throw new Exception("[APKAssetManager] Asset manager is not initialized."); + } + + using JString pathString = JNI.NewString(path); + JClass assetManagerClass = JNI.GetObjectClass(assetManager); + using JObject asset = JNI.CallObjectMethod(assetManager, JNI.GetMethodID(assetManagerClass, "open", "(Ljava/lang/String;)Ljava/io/InputStream;"), new JValue(pathString)); + if (asset == null || !asset.Valid()) + return []; + + using MemoryStream outputStream = new(); + + using JArray buffer = JNI.NewArray(1024); + JMethodID readMethodID = JNI.GetMethodID(JNI.GetObjectClass(asset), "read", "([B)I"); + + int bytesRead = 0; + while ((bytesRead = JNI.CallMethod(asset, readMethodID, new JValue(buffer))) > 0) + { + byte[] managedBuffer = (byte[])(Array)buffer.GetElements(); + outputStream.Write(managedBuffer, 0, bytesRead); + } + + JClass assetClass = JNI.GetObjectClass(asset); + JMethodID closeMethodID = JNI.GetMethodID(assetClass, "close", "()V"); + JNI.CallVoidMethod(asset, closeMethodID); + + HandleException(); + + return outputStream.ToArray(); + } + + public static Stream? GetAssetStream(string path) + { + if (assetManager == null || !assetManager.Valid()) + { + GetAndroidAssetManager(); + if (assetManager == null || !assetManager.Valid()) + throw new Exception("[APKAssetManager] Asset manager is not initialized."); + } + + using JString pathString = JNI.NewString(path); + JClass assetManagerClass = JNI.GetObjectClass(assetManager); + JObject asset = JNI.CallObjectMethod(assetManager, JNI.GetMethodID(assetManagerClass, "open", "(Ljava/lang/String;)Ljava/io/InputStream;"), new JValue(pathString)); + if (asset == null || !asset.Valid()) + return null; + + HandleException(); + + return new APKAssetStream(asset); + } + + public static string[] GetDirectoryContents(string directory) + { + if (assetManager == null || !assetManager.Valid()) + { + GetAndroidAssetManager(); + if (assetManager == null || !assetManager.Valid()) + throw new Exception("[APKAssetManager] Asset manager is not initialized."); + } + + using JString pathString = JNI.NewString(directory); + JClass assetManagerClass = JNI.GetObjectClass(assetManager); + using JObjectArray assets = JNI.CallObjectMethod>(assetManager, JNI.GetMethodID(assetManagerClass, "list", "(Ljava/lang/String;)[Ljava/lang/String;"), new JValue(pathString)); + + string[] cleanAssets = [.. assets.Select(a => a.GetString())]; + HandleException(); + + return cleanAssets; + } + + public static bool DoesAssetExist(string path) + { + if (assetManager == null || !assetManager.Valid()) + { + GetAndroidAssetManager(); + if (assetManager == null || !assetManager.Valid()) + throw new Exception("[APKAssetManager] Asset manager is not initialized."); + } + + // using `list` isn't as fast as just calling open, but this allows the function to not crash on debuggable builds of apps + string containingDir = path[..path.LastIndexOf('/')]; + using JString pathString = JNI.NewString(containingDir); + JClass assetManagerClass = JNI.GetObjectClass(assetManager); + using JObjectArray assets = JNI.CallObjectMethod>(assetManager, JNI.GetMethodID(assetManagerClass, "list", "(Ljava/lang/String;)[Ljava/lang/String;"), new JValue(pathString)); + + bool exists = assets.Any(js => + { + string asset = JNI.GetJStringString(js); + return path.EndsWith(asset); + }); + + HandleException(); + + return exists; + } + + private static void HandleException() + { + if (JNI.ExceptionCheck()) + JNI.ExceptionClear(); + } + + private static void GetAndroidAssetManager() + { + if (assetManager?.Valid() ?? false) + return; + + JClass unityClass = JNI.FindClass("com/unity3d/player/UnityPlayer"); + JFieldID activityFieldId = JNI.GetStaticFieldID(unityClass, "currentActivity", "Landroid/app/Activity;"); + using JObject currentActivityObj = JNI.GetStaticObjectField(unityClass, activityFieldId); + JClass activityClass = JNI.GetObjectClass(currentActivityObj); + JObject assetManagerObj = JNI.CallObjectMethod(currentActivityObj, JNI.GetMethodID(activityClass, "getAssets", "()Landroid/content/res/AssetManager;")); + + HandleException(); + + assetManager = assetManagerObj; + } + + public class APKAssetStream : Stream, IDisposable + { + private readonly JMethodID _availableJmid; + private readonly JMethodID _markSupportedJmid; + private readonly JMethodID _skipJmid; + private readonly JMethodID _resetJmid; + private readonly JMethodID _readJmid; + private readonly JMethodID _closeJmid; + + private readonly JObject _streamObject; + + private long _pos = 0; + private bool _disposed = false; + + public APKAssetStream(JObject obj) + { + _streamObject = obj; + + JClass streamClass = JNI.GetObjectClass(_streamObject); + + _availableJmid = JNI.GetMethodID(streamClass, "available", "()I"); + _readJmid = JNI.GetMethodID(streamClass, "read", "([BII)I"); + _markSupportedJmid = JNI.GetMethodID(streamClass, "markSupported", "()Z"); + _skipJmid = JNI.GetMethodID(streamClass, "skip", "(J)J"); + _resetJmid = JNI.GetMethodID(streamClass, "reset", "()V"); + _closeJmid = JNI.GetMethodID(streamClass, "close", "()V"); + } + + public override bool CanRead => true; + + public override bool CanSeek => false; + + public override bool CanWrite => false; + + public override long Length + { + get + { + int length = JNI.CallMethod(_streamObject, _availableJmid); + HandleException(); + return length; + } + } + + public override long Position + { + get => _pos; + set + { + bool canMark = JNI.CallMethod(_streamObject, _markSupportedJmid); + if (!canMark) + throw new NotImplementedException(); + + JNI.CallVoidMethod(_streamObject, _resetJmid); + if (value > 0) + { + long val = JNI.CallMethod(_streamObject, _skipJmid, new JValue(value)); + _pos = val; + } + + HandleException(); + } + } + + public override int Read(byte[] buffer, int offset, int count) + { + using JArray javaBuffer = JNI.NewArray(count); + + int read = JNI.CallMethod(_streamObject, _readJmid, new JValue(javaBuffer), new JValue(offset), new JValue(count)); + HandleException(); + + if (read == -1) + return 0; + + for (int i = 0; i < read; i++) + { + buffer[i] = (byte)javaBuffer[i]; + } + + _pos += read; + return read; + } + + public override void Write(byte[] buffer, int offset, int count) => throw new NotImplementedException(); + public override long Seek(long offset, SeekOrigin origin) => throw new NotImplementedException(); + public override void SetLength(long value) => throw new NotImplementedException(); + public override void Flush() { } + + protected override void Dispose(bool disposing) + { + if (!_disposed) + { + if (disposing) + { + JNI.CallVoidMethod(_streamObject, _closeJmid); + _streamObject.Dispose(); + HandleException(); + } + _disposed = true; + } + base.Dispose(disposing); + } + } +} +#endif \ No newline at end of file diff --git a/README.md b/README.md index 58894c950..4701fb140 100644 --- a/README.md +++ b/README.md @@ -294,6 +294,8 @@ Third-party Libraries used as Source Code and/or bundled in Binary Form: - [WebSocketDotNet](https://github.com/SamboyCoding/WebSocketDotNet) is licensed under the MIT License. See [LICENSE](https://github.com/SamboyCoding/WebSocketDotNet/blob/master/LICENSE) for the full License. - [Pastel](https://github.com/silkfire/Pastel) is licensed under the MIT License. See [LICENSE](https://github.com/silkfire/Pastel/blob/master/LICENSE) for the full License. - [Il2CppInterop](https://github.com/BepInEx/Il2CppInterop) is licensed under the LGPLv3 License. See [LICENSE](https://github.com/BepInEx/Il2CppInterop/blob/master/LICENSE) for the full License. +- [JNISharp](https://github.com/WarrenUlrich/JNISharp) is licensed under the MIT License. See [LICENSE](https://github.com/WarrenUlrich/JNISharp/blob/master/LICENSE) for the full License. +- [NativeAOT-AndroidHelloJniLib](https://github.com/josephmoresena/NativeAOT-AndroidHelloJniLib) is licensed under the MIT License. See [LICENSE](https://github.com/josephmoresena/NativeAOT-AndroidHelloJniLib/blob/main/LICENSE) for the full License. External Libraries and Tools that are downloaded and used at Runtime: - [Cpp2IL](https://github.com/SamboyCoding/Cpp2IL) is licensed under the MIT License. See [LICENSE](https://github.com/SamboyCoding/Cpp2IL/blob/master/LICENSE) for the full License. From 37629e3692a06bf1d3285e1ec3535f99bf8b2e19 Mon Sep 17 00:00:00 2001 From: Trevor Date: Fri, 6 Jun 2025 19:43:57 -0400 Subject: [PATCH 2/8] Add Android support in Core --- MelonLoader/Core.cs | 7 +++ MelonLoader/Fixes/Il2CppInteropFixes.cs | 2 + MelonLoader/InternalUtils/BootstrapLibrary.cs | 1 + .../InternalUtils/UnityInformationHandler.cs | 58 ++++++++++++++++--- MelonLoader/MelonUtils.cs | 36 +++++++++++- MelonLoader/Utils/MelonEnvironment.cs | 20 ++++++- MelonLoader/Utils/NativeLibrary.cs | 52 ++++++++++++++++- 7 files changed, 163 insertions(+), 13 deletions(-) diff --git a/MelonLoader/Core.cs b/MelonLoader/Core.cs index 80e9b30e4..9cf24a5e5 100644 --- a/MelonLoader/Core.cs +++ b/MelonLoader/Core.cs @@ -91,6 +91,11 @@ private static void Entrypoint() internal static int Initialize() { +#if ANDROID + Java.JNI.Initialize(BootstrapInterop.Library.GetJavaVM()); + APKAssetManager.Initialize(); +#endif + // The config should be set before running anything else due to static constructors depending on it // Don't ask me how this works, because I don't know either. -slxdy var config = new LoaderConfig(); @@ -189,7 +194,9 @@ internal static int Initialize() // if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) // NativeStackWalk.LogNativeStackTrace(); +#if !ANDROID Fixes.DotnetAssemblyLoadContextFix.Install(); +#endif Fixes.DotnetModHandlerRedirectionFix.Install(); #endif diff --git a/MelonLoader/Fixes/Il2CppInteropFixes.cs b/MelonLoader/Fixes/Il2CppInteropFixes.cs index 4c8d8189a..e4821530a 100644 --- a/MelonLoader/Fixes/Il2CppInteropFixes.cs +++ b/MelonLoader/Fixes/Il2CppInteropFixes.cs @@ -192,11 +192,13 @@ internal static void Install() null, new HarmonyMethod(_systemTypeFromIl2CppType_Transpiler)); +#if !ANDROID // On Android this patch causes MissingMethodExceptions for an unknown reason LogDebugMsg("Patching Il2CppInterop ClassInjector.RegisterTypeInIl2Cpp..."); Core.HarmonyInstance.Patch(_registerTypeInIl2Cpp, null, null, new HarmonyMethod(_registerTypeInIl2Cpp_Transpiler)); +#endif LogDebugMsg("Patching Il2CppInterop ClassInjector.IsTypeSupported..."); Core.HarmonyInstance.Patch(_isTypeSupported, diff --git a/MelonLoader/InternalUtils/BootstrapLibrary.cs b/MelonLoader/InternalUtils/BootstrapLibrary.cs index d7256bbfa..833b0f07d 100644 --- a/MelonLoader/InternalUtils/BootstrapLibrary.cs +++ b/MelonLoader/InternalUtils/BootstrapLibrary.cs @@ -14,4 +14,5 @@ internal class BootstrapLibrary internal PtrRetFn MonoGetRuntimeHandle { get; private set; } internal BoolRetFn IsConsoleOpen { get; private set; } internal GetLoaderConfigFn GetLoaderConfig { get; private set; } + internal GetJavaVM GetJavaVM { get; private set; } } diff --git a/MelonLoader/InternalUtils/UnityInformationHandler.cs b/MelonLoader/InternalUtils/UnityInformationHandler.cs index 5250cae11..9f24a0ace 100644 --- a/MelonLoader/InternalUtils/UnityInformationHandler.cs +++ b/MelonLoader/InternalUtils/UnityInformationHandler.cs @@ -49,9 +49,11 @@ internal static void Setup() ReadGameInfo(assetsManager, gameDataPath); assetsManager.UnloadAll(); +#if !ANDROID // app.info doesn't exist on Android if (string.IsNullOrEmpty(GameDeveloper) || string.IsNullOrEmpty(GameName)) ReadGameInfoFallback(); +#endif if (EngineVersion == UnityVersion.MinVersion) EngineVersion = ReadVersionFallback(gameDataPath); @@ -78,20 +80,33 @@ private static void ReadGameInfo(AssetsManager assetsManager, string gameDataPat try { string bundlePath = Path.Combine(gameDataPath, "globalgamemanagers"); - if (!File.Exists(bundlePath)) + if (!FileExists(bundlePath)) bundlePath = Path.Combine(gameDataPath, "mainData"); - if (!File.Exists(bundlePath)) + if (!FileExists(bundlePath)) { bundlePath = Path.Combine(gameDataPath, "data.unity3d"); - if (!File.Exists(bundlePath)) + if (!FileExists(bundlePath)) return; +#if !ANDROID BundleFileInstance bundleFile = assetsManager.LoadBundleFile(bundlePath); +#else + Stream bundleStream = APKAssetManager.GetAssetStream(bundlePath); + BundleFileInstance bundleFile = assetsManager.LoadBundleFile(bundleStream, bundlePath); +#endif instance = assetsManager.LoadAssetsFileFromBundle(bundleFile, "globalgamemanagers"); } else + { +#if !ANDROID instance = assetsManager.LoadAssetsFile(bundlePath, true); +#else + Stream bundleStream = APKAssetManager.GetAssetStream(bundlePath); + instance = assetsManager.LoadAssetsFile(bundleStream, bundlePath, true); +#endif + } + if (instance == null) return; @@ -165,6 +180,7 @@ private static void ReadGameInfoFallback() private static UnityVersion ReadVersionFallback(string gameDataPath) { +#if !ANDROID string unityPlayerPath = MelonEnvironment.UnityPlayerPath; if (!File.Exists(unityPlayerPath)) unityPlayerPath = MelonEnvironment.GameExecutablePath; @@ -174,12 +190,13 @@ private static UnityVersion ReadVersionFallback(string gameDataPath) var unityVer = FileVersionInfo.GetVersionInfo(unityPlayerPath); return TryParse(unityVer.FileVersion); } +#endif try { var globalgamemanagersPath = Path.Combine(gameDataPath, "globalgamemanagers"); - if (File.Exists(globalgamemanagersPath)) - return GetVersionFromGlobalGameManagers(File.ReadAllBytes(globalgamemanagersPath)); + if (FileExists(globalgamemanagersPath)) + return GetVersionFromGlobalGameManagers(FileReadAllBytes(globalgamemanagersPath)); } catch (Exception ex) { @@ -190,8 +207,8 @@ private static UnityVersion ReadVersionFallback(string gameDataPath) try { var dataPath = Path.Combine(gameDataPath, "data.unity3d"); - if (File.Exists(dataPath)) - return GetVersionFromDataUnity3D(File.OpenRead(dataPath)); + if (FileExists(dataPath)) + return GetVersionFromDataUnity3D(FileOpenRead(dataPath)); } catch (Exception ex) { @@ -252,5 +269,32 @@ private static UnityVersion GetVersionFromDataUnity3D(Stream fileStream) return TryParse(verString.ToString().Trim()); } + + private static bool FileExists(string path) + { +#if !ANDROID + return File.Exists(path); +#else + return APKAssetManager.DoesAssetExist(path); +#endif + } + + private static byte[] FileReadAllBytes(string path) + { +#if !ANDROID + return File.ReadAllBytes(path); +#else + return APKAssetManager.GetAssetBytes(path); +#endif + } + + private static Stream FileOpenRead(string path) + { +#if !ANDROID + return File.OpenRead(path); +#else + return APKAssetManager.GetAssetStream(path); +#endif + } } } diff --git a/MelonLoader/MelonUtils.cs b/MelonLoader/MelonUtils.cs index 434a12830..2b8ed6998 100644 --- a/MelonLoader/MelonUtils.cs +++ b/MelonLoader/MelonUtils.cs @@ -111,6 +111,12 @@ internal static void Setup(AppDomain domain) public static bool IsUnix => GetPlatform is PlatformID.Unix; public static bool IsWindows => GetPlatform is PlatformID.Win32NT or PlatformID.Win32S or PlatformID.Win32Windows or PlatformID.WinCE; public static bool IsMac => GetPlatform is PlatformID.MacOSX; + public static bool IsAndroid => +#if ANDROID // This is what .NET does internally for OperatingSystem.IsAndroid, this just prevents errors on net35 + true; +#else + false; +#endif #if NET6_0_OR_GREATER private static PlatformID GetPlatformFromRuntimeInformation() @@ -515,14 +521,19 @@ public static ClassPackageFile LoadIncludedClassPackage(this AssetsManager asset public static unsafe bool IsGame32Bit() => -#if X64 +#if X64 || ANDROID // NOTE: This will need to be refactored if other arches are ever supported on Android false; #else true; #endif - public static bool IsGameIl2Cpp() => Directory.Exists(MelonEnvironment.Il2CppDataDirectory); + public static bool IsGameIl2Cpp() => +#if !ANDROID + Directory.Exists(MelonEnvironment.Il2CppDataDirectory); +#else + APKAssetManager.DoesAssetExist(Path.Combine(Path.Combine(MelonEnvironment.Il2CppDataDirectory, "Metadata"), "global-metadata.dat")); +#endif public static bool IsOldMono() { @@ -532,7 +543,9 @@ public static bool IsOldMono() return libs.Select(Path.GetFileName).Contains("libmono.0.dylib"); #else return File.Exists(MelonEnvironment.UnityGameDataDirectory + "\\Mono\\mono.dll") || - File.Exists(MelonEnvironment.UnityGameDataDirectory + "\\Mono\\libmono.so"); + File.Exists(MelonEnvironment.UnityGameDataDirectory + "\\Mono\\libmono.so") || + Process.GetCurrentProcess().Modules.OfType() // Android support + .Any(x => x.FileName.Contains("libmono.so")); #endif } @@ -619,6 +632,23 @@ internal struct OsVersionInfo internal static string GetOSVersion() { + if (IsAndroid) + { + StringBuilder sb = new(); + sb.Append("Android "); + int apiLevel = Environment.OSVersion.Version.Major; + // https://apilevels.com/ + string androidVersion = apiLevel switch + { + 27 => "8.1", 28 => "9", 29 => "10", + 30 => "11", 31 => "12", 32 => "12L", 33 => "13", 34 => "14", 35 => "15", 36 => "16", + _ => $"API Level {apiLevel}" + }; + sb.Append(androidVersion); + + return sb.ToString(); + } + if (IsUnix || IsMac) return Environment.OSVersion.VersionString; diff --git a/MelonLoader/Utils/MelonEnvironment.cs b/MelonLoader/Utils/MelonEnvironment.cs index d5e0f50be..77f490e0c 100644 --- a/MelonLoader/Utils/MelonEnvironment.cs +++ b/MelonLoader/Utils/MelonEnvironment.cs @@ -24,7 +24,14 @@ public static class MelonEnvironment Process.GetCurrentProcess().MainModule.FileName; #endif public static string MelonLoaderDirectory { get; } = Path.Combine(MelonBaseDirectory, "MelonLoader"); +#if !ANDROID public static string GameRootDirectory { get; } = Path.GetDirectoryName(GameExecutablePath); +#else + public static string GameRootDirectory { get; } = MelonBaseDirectory; + + // MelonBaseDirectory is named after the current package by the Bootstrap + public static string PackageName { get; } = Path.GetFileName(MelonBaseDirectory); +#endif public static string DependenciesDirectory { get; } = Path.Combine(MelonLoaderDirectory, "Dependencies"); @@ -39,14 +46,23 @@ public static class MelonEnvironment public static string OurRuntimeDirectory { get; } = Path.Combine(MelonLoaderDirectory, OurRuntimeName); public static string GameExecutableName { get; } = Path.GetFileNameWithoutExtension(GameExecutablePath); - public static string UnityGameDataDirectory { get; } = + public static string UnityGameDataDirectory { get; } = #if OSX Path.Combine(GameExecutablePath!, "Contents/Resources/Data"); +#elif ANDROID + // inside the APK's assets directory; we're interacting with it via the AssetManager API so this makes sense even if it looks weird + "bin/Data/"; #else Path.Combine(GameRootDirectory, GameExecutableName + "_Data"); #endif public static string UnityGameManagedDirectory { get; } = Path.Combine(UnityGameDataDirectory, "Managed"); - public static string Il2CppDataDirectory { get; } = Path.Combine(UnityGameDataDirectory, "il2cpp_data"); + public static string Il2CppDataDirectory { get; } = +#if !ANDROID + Path.Combine(UnityGameDataDirectory, "il2cpp_data"); +#else + // Managed on Android, when built with IL2CPP, is the same as il2cpp_data + Path.Combine(UnityGameDataDirectory, "Managed"); +#endif public static string UnityPlayerPath { get; } = Path.Combine(GameRootDirectory, "UnityPlayer.dll"); public static string MelonManagedDirectory { get; } = Path.Combine(DependenciesDirectory, "Mono"); diff --git a/MelonLoader/Utils/NativeLibrary.cs b/MelonLoader/Utils/NativeLibrary.cs index 5ec51fa37..eff6ae9c9 100644 --- a/MelonLoader/Utils/NativeLibrary.cs +++ b/MelonLoader/Utils/NativeLibrary.cs @@ -1,3 +1,4 @@ +using MelonLoader.Utils; using System; using System.IO; using System.Reflection; @@ -27,8 +28,16 @@ public static IntPtr LoadLib(string filepath) if (string.IsNullOrEmpty(filepath)) throw new ArgumentNullException(nameof(filepath)); IntPtr ptr = AgnosticLoadLibrary(filepath); +#if !ANDROID if (ptr == IntPtr.Zero) throw new Exception($"Unable to Load Native Library {filepath}!"); +#else + if (ptr == IntPtr.Zero) + { + var error = Marshal.PtrToStringAnsi(dlerror()); + throw new DlErrorException($"Unable to Load Native Library {filepath}!\ndlerror: {error}"); + } +#endif return ptr; } @@ -68,6 +77,27 @@ public static IntPtr AgnosticLoadLibrary(string name) name += ".dylib"; return dlopen(name, RTLD_NOW); +#elif ANDROID + // Workaround that allows us to bypass Android's security that prevents libraries from being loaded from outside APKs + string path = name; + if (File.Exists(path)) + { + string fileName = Path.GetFileName(path); + path = Path.Combine("/data/data/", MelonEnvironment.PackageName); + path = Path.Combine(path, fileName); + + FileInfo newLib = new(name); + FileInfo copiedLib = new(path); + if (copiedLib.Exists && newLib.LastWriteTime > copiedLib.LastWriteTime) + { + copiedLib.Delete(); + File.Copy(name, path); + } + else if (!copiedLib.Exists) + File.Copy(name, path); + } + + return dlopen(path, RTLD_NOW); #endif } @@ -75,7 +105,7 @@ public static IntPtr AgnosticGetProcAddress(IntPtr hModule, string lpProcName) { #if WINDOWS return GetProcAddress(hModule, lpProcName); -#elif LINUX || OSX +#elif LINUX || OSX || ANDROID return dlsym(hModule, lpProcName); #endif } @@ -95,6 +125,17 @@ public static IntPtr AgnosticGetProcAddress(IntPtr hModule, string lpProcName) protected static extern IntPtr dlsym(IntPtr handle, string symbol); const int RTLD_NOW = 2; // for dlopen's flags +#elif ANDROID + [DllImport("libdl.so")] + protected static extern IntPtr dlopen(string filename, int flags); + + [DllImport("libdl.so")] + protected static extern IntPtr dlsym(IntPtr handle, string symbol); + + [DllImport("libdl.so")] + protected static extern IntPtr dlerror(); + + const int RTLD_NOW = 2; // for dlopen's flags #elif OSX [DllImport("libSystem.B.dylib")] protected static extern IntPtr dlopen(string filename, int flags); @@ -147,4 +188,13 @@ public NativeLibrary(IntPtr ptr) : base(ptr) } } } + +#if ANDROID + public class DlErrorException : Exception + { + public DlErrorException() { } + public DlErrorException(string message) : base(message) { } + public DlErrorException(string message, Exception inner) : base(message, inner) { } + } +#endif } From 475534a47cc271e8ac0be150cf05362b2eaf11cc Mon Sep 17 00:00:00 2001 From: Trevor Date: Fri, 6 Jun 2025 19:48:25 -0400 Subject: [PATCH 3/8] Fix BootstrapLibrary for non-Android targets; add license OpenSSL is required by linux-bionic .NET runtime and is included with Lemon. --- MelonLoader/InternalUtils/BootstrapLibrary.cs | 2 ++ README.md | 1 + 2 files changed, 3 insertions(+) diff --git a/MelonLoader/InternalUtils/BootstrapLibrary.cs b/MelonLoader/InternalUtils/BootstrapLibrary.cs index 833b0f07d..52e4d2469 100644 --- a/MelonLoader/InternalUtils/BootstrapLibrary.cs +++ b/MelonLoader/InternalUtils/BootstrapLibrary.cs @@ -14,5 +14,7 @@ internal class BootstrapLibrary internal PtrRetFn MonoGetRuntimeHandle { get; private set; } internal BoolRetFn IsConsoleOpen { get; private set; } internal GetLoaderConfigFn GetLoaderConfig { get; private set; } +#if ANDROID internal GetJavaVM GetJavaVM { get; private set; } +#endif } diff --git a/README.md b/README.md index 4701fb140..cf7214f90 100644 --- a/README.md +++ b/README.md @@ -295,6 +295,7 @@ Third-party Libraries used as Source Code and/or bundled in Binary Form: - [Pastel](https://github.com/silkfire/Pastel) is licensed under the MIT License. See [LICENSE](https://github.com/silkfire/Pastel/blob/master/LICENSE) for the full License. - [Il2CppInterop](https://github.com/BepInEx/Il2CppInterop) is licensed under the LGPLv3 License. See [LICENSE](https://github.com/BepInEx/Il2CppInterop/blob/master/LICENSE) for the full License. - [JNISharp](https://github.com/WarrenUlrich/JNISharp) is licensed under the MIT License. See [LICENSE](https://github.com/WarrenUlrich/JNISharp/blob/master/LICENSE) for the full License. +- [OpenSSL](https://github.com/openssl/openssl) is licensed under the Apache License, Version 2.0. See [LICENSE](https://github.com/openssl/openssl/blob/master/LICENSE.txt) for the full License. - [NativeAOT-AndroidHelloJniLib](https://github.com/josephmoresena/NativeAOT-AndroidHelloJniLib) is licensed under the MIT License. See [LICENSE](https://github.com/josephmoresena/NativeAOT-AndroidHelloJniLib/blob/main/LICENSE) for the full License. External Libraries and Tools that are downloaded and used at Runtime: From 3f8068df9e034ec45347b862f1649a29b29ab7cc Mon Sep 17 00:00:00 2001 From: Trevor Date: Sat, 16 Aug 2025 14:44:12 -0400 Subject: [PATCH 4/8] Improve LibcNative and data copying I believe the changes in APKAssetManager fixed some GC weirdness, hopefully it stays that way. --- MelonLoader.Bootstrap/LibcNative.cs | 58 ++++++++---------- .../Proxy/Android/AndroidBootstrap.cs | 54 +++++++++------- MelonLoader/Utils/APKAssetManager.cs | 61 ++++++++----------- 3 files changed, 80 insertions(+), 93 deletions(-) diff --git a/MelonLoader.Bootstrap/LibcNative.cs b/MelonLoader.Bootstrap/LibcNative.cs index 16d198fd7..2edd251f4 100644 --- a/MelonLoader.Bootstrap/LibcNative.cs +++ b/MelonLoader.Bootstrap/LibcNative.cs @@ -1,4 +1,4 @@ -#if LINUX || OSX +#if LINUX || OSX || ANDROID using System.Runtime.CompilerServices; using System.Runtime.InteropServices; @@ -13,8 +13,17 @@ internal partial class LibcNative internal const int RtldLazy = 0x1; internal const int RtldNoLoad = 0x10; - - [LibraryImport("libc", EntryPoint = "__libc_start_main")] + + const string DL_LIB = +#if !ANDROID + "libc"; +#else + "libdl"; +#endif + + const string C_LIB = "libc"; + + [LibraryImport(C_LIB, EntryPoint = "__libc_start_main")] public static unsafe partial int LibCStartMain( delegate* unmanaged[Cdecl] main, int argc, @@ -24,71 +33,52 @@ public static unsafe partial int LibCStartMain( nint rtLdFini, nint stackEnd); - [LibraryImport("libc", EntryPoint = "dlopen", StringMarshalling = StringMarshalling.Utf8)] + [LibraryImport(DL_LIB, EntryPoint = "dlopen", StringMarshalling = StringMarshalling.Utf8)] [UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])] public static partial nint Dlopen(string handle, int flags); - [LibraryImport("libc", EntryPoint = "dlsym", StringMarshalling = StringMarshalling.Utf8)] + [LibraryImport(DL_LIB, EntryPoint = "dlsym", StringMarshalling = StringMarshalling.Utf8)] [UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])] public static partial nint Dlsym(nint handle, string symbol); - [LibraryImport("libc", EntryPoint = "setenv", StringMarshalling = StringMarshalling.Utf8)] + [LibraryImport(C_LIB, EntryPoint = "setenv", StringMarshalling = StringMarshalling.Utf8)] [UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])] public static partial int Setenv(string name, string value,[MarshalAs(UnmanagedType.Bool)] bool overwrite); - [LibraryImport("libc", EntryPoint = "dup2")] + [LibraryImport(C_LIB, EntryPoint = "dup2")] [UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])] public static partial int Dup2(int oldFd, int newFd); #if OSX - [LibraryImport("libc", EntryPoint = "fopen", StringMarshalling = StringMarshalling.Utf8)] + [LibraryImport(C_LIB, EntryPoint = "fopen", StringMarshalling = StringMarshalling.Utf8)] #else - [LibraryImport("libc", EntryPoint = "fopen64", StringMarshalling = StringMarshalling.Utf8)] + [LibraryImport(C_LIB, EntryPoint = "fopen64", StringMarshalling = StringMarshalling.Utf8)] #endif [UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])] public static partial nint Fopen64(string pathName, string modes); - [LibraryImport("libc", EntryPoint = "vfprintf", StringMarshalling = StringMarshalling.Utf8)] + [LibraryImport(C_LIB, EntryPoint = "vfprintf", StringMarshalling = StringMarshalling.Utf8)] [UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])] public static partial int Vfprintf(nint stream, string format, nint vList); - [LibraryImport("libc", EntryPoint = "vsnprintf", StringMarshalling = StringMarshalling.Utf8)] + [LibraryImport(C_LIB, EntryPoint = "vsnprintf", StringMarshalling = StringMarshalling.Utf8)] [UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])] public static unsafe partial int Vsnprintf(byte* s, int maxLen, string format, nint arg); - [LibraryImport("libc", EntryPoint = "fseek", StringMarshalling = StringMarshalling.Utf8)] + [LibraryImport(C_LIB, EntryPoint = "fseek", StringMarshalling = StringMarshalling.Utf8)] [UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])] public static partial int Fseek(nint stream, long offset, int whence); - [LibraryImport("libc", EntryPoint = "fwrite", StringMarshalling = StringMarshalling.Utf8)] + [LibraryImport(C_LIB, EntryPoint = "fwrite", StringMarshalling = StringMarshalling.Utf8)] [UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])] public static unsafe partial int Fwrite(byte* ptr, int size, int nItems, nint stream); - [LibraryImport("libc", EntryPoint = "fileno")] + [LibraryImport(C_LIB, EntryPoint = "fileno")] [UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])] public static partial int Fileno(nint stream); - [LibraryImport("libc", EntryPoint = "fclose")] + [LibraryImport(C_LIB, EntryPoint = "fclose")] [UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])] public static partial int FClose(nint stream); } -#endif - -#if ANDROID -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -namespace MelonLoader.Bootstrap; - -internal partial class LibcNative -{ - internal const int Stdout = 1; - internal const int Stderr = 2; - - internal const int SeekEnd = 2; - - [LibraryImport("libdl", EntryPoint = "dlsym", StringMarshalling = StringMarshalling.Utf8)] - [UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])] - public static partial nint Dlsym(nint handle, string symbol); -} #endif \ No newline at end of file diff --git a/MelonLoader.Bootstrap/Proxy/Android/AndroidBootstrap.cs b/MelonLoader.Bootstrap/Proxy/Android/AndroidBootstrap.cs index 9d8de29e1..39b6e03bd 100644 --- a/MelonLoader.Bootstrap/Proxy/Android/AndroidBootstrap.cs +++ b/MelonLoader.Bootstrap/Proxy/Android/AndroidBootstrap.cs @@ -26,36 +26,44 @@ public static unsafe int LoadBootstrap() public static void CopyMelonLoaderData(DateTimeOffset date) { - var baseDataDir = Core.DataDir; - var melonloaderFolder = Path.Combine(Core.DataDir, "MelonLoader"); - var baseInternalFolder = $"/data/data/{PackageName}/"; - var dotnetFolder = $"/data/data/{PackageName}/dotnet"; + CopyAssetFolder("MelonLoader", Core.DataDir, Core.DataDir, date); + CopyAssetFolder("dotnet", $"/data/data/{PackageName}/", $"/data/data/{PackageName}/", date); - // TODO: put up toasts as initial copy can take awhile + DotnetDir = Path.Combine($"/data/data/{PackageName}/dotnet"); + } + + private static void CopyAssetFolder(string assetName, string copyBase, string targetBase, DateTimeOffset cutoffDate) + { + string targetFolder = Path.Combine(targetBase, assetName); + string markerFile = Path.Combine(targetFolder, ".copy_complete"); + + bool needsCopy = true; - if (Directory.Exists(melonloaderFolder)) + if (Directory.Exists(targetFolder)) { - var fileModTime = Directory.GetLastWriteTimeUtc(melonloaderFolder); - if (fileModTime > date) - AndroidProxy.Log("MelonLoader folder is already up-to-date"); - else - APKAssetManager.SaveItemToDirectory("MelonLoader", baseDataDir, true); + if (File.Exists(markerFile)) + { + DateTime lastComplete = File.GetLastWriteTimeUtc(markerFile); + if (lastComplete > cutoffDate) + { + AndroidProxy.Log($"{assetName} folder is already up-to-date"); + needsCopy = false; + } + } } - else - APKAssetManager.SaveItemToDirectory("MelonLoader", baseDataDir, true); - if (Directory.Exists(dotnetFolder)) + if (needsCopy) { - var fileModTime = Directory.GetLastWriteTimeUtc(dotnetFolder); - if (fileModTime > date) - AndroidProxy.Log("Dotnet folder is already up-to-date"); - else - APKAssetManager.SaveItemToDirectory("dotnet", baseInternalFolder, true); + // TODO: put up toasts as initial copy can take awhile + AndroidProxy.Log($"Copying {assetName} assets..."); + if (Directory.Exists(targetFolder)) + Directory.Delete(targetFolder, true); + + APKAssetManager.SaveItemToDirectory(assetName, copyBase, includeInitial: true); + + Directory.CreateDirectory(targetFolder); + File.WriteAllText(markerFile, $"Copied at {DateTime.UtcNow:o}"); } - else - APKAssetManager.SaveItemToDirectory("dotnet", baseInternalFolder, true); - - DotnetDir = Path.Combine(dotnetFolder); } public static string GetDataDir() diff --git a/MelonLoader/Utils/APKAssetManager.cs b/MelonLoader/Utils/APKAssetManager.cs index eb377c594..3287a62af 100644 --- a/MelonLoader/Utils/APKAssetManager.cs +++ b/MelonLoader/Utils/APKAssetManager.cs @@ -17,14 +17,18 @@ public static void Initialize() GetAndroidAssetManager(); } - public static void SaveItemToDirectory(string itemPath, string copyBase, bool includeInitial = true) + private static void EnsureInitialized() { if (assetManager == null || !assetManager.Valid()) - { GetAndroidAssetManager(); - if (assetManager == null || !assetManager.Valid()) - throw new Exception("[APKAssetManager] Asset manager is not initialized."); - } + + if (assetManager == null || !assetManager.Valid()) + throw new InvalidOperationException("[APKAssetManager] Asset manager is not initialized."); + } + + public static void SaveItemToDirectory(string itemPath, string copyBase, bool includeInitial = true) + { + EnsureInitialized(); string[] contents = GetDirectoryContents(itemPath); if (contents.Length == 0) @@ -60,16 +64,11 @@ public static void SaveItemToDirectory(string itemPath, string copyBase, bool in public static byte[] GetAssetBytes(string path) { - if (assetManager == null || !assetManager.Valid()) - { - GetAndroidAssetManager(); - if (assetManager == null || !assetManager.Valid()) - throw new Exception("[APKAssetManager] Asset manager is not initialized."); - } - + EnsureInitialized(); + using JString pathString = JNI.NewString(path); - JClass assetManagerClass = JNI.GetObjectClass(assetManager); - using JObject asset = JNI.CallObjectMethod(assetManager, JNI.GetMethodID(assetManagerClass, "open", "(Ljava/lang/String;)Ljava/io/InputStream;"), new JValue(pathString)); + JClass assetManagerClass = JNI.GetObjectClass(assetManager!); + using JObject asset = JNI.CallObjectMethod(assetManager!, JNI.GetMethodID(assetManagerClass, "open", "(Ljava/lang/String;)Ljava/io/InputStream;"), new JValue(pathString)); if (asset == null || !asset.Valid()) return []; @@ -96,12 +95,7 @@ public static byte[] GetAssetBytes(string path) public static Stream? GetAssetStream(string path) { - if (assetManager == null || !assetManager.Valid()) - { - GetAndroidAssetManager(); - if (assetManager == null || !assetManager.Valid()) - throw new Exception("[APKAssetManager] Asset manager is not initialized."); - } + EnsureInitialized(); using JString pathString = JNI.NewString(path); JClass assetManagerClass = JNI.GetObjectClass(assetManager); @@ -116,12 +110,7 @@ public static byte[] GetAssetBytes(string path) public static string[] GetDirectoryContents(string directory) { - if (assetManager == null || !assetManager.Valid()) - { - GetAndroidAssetManager(); - if (assetManager == null || !assetManager.Valid()) - throw new Exception("[APKAssetManager] Asset manager is not initialized."); - } + EnsureInitialized(); using JString pathString = JNI.NewString(directory); JClass assetManagerClass = JNI.GetObjectClass(assetManager); @@ -135,13 +124,8 @@ public static string[] GetDirectoryContents(string directory) public static bool DoesAssetExist(string path) { - if (assetManager == null || !assetManager.Valid()) - { - GetAndroidAssetManager(); - if (assetManager == null || !assetManager.Valid()) - throw new Exception("[APKAssetManager] Asset manager is not initialized."); - } - + EnsureInitialized(); + // using `list` isn't as fast as just calling open, but this allows the function to not crash on debuggable builds of apps string containingDir = path[..path.LastIndexOf('/')]; using JString pathString = JNI.NewString(containingDir); @@ -173,12 +157,17 @@ private static void GetAndroidAssetManager() JClass unityClass = JNI.FindClass("com/unity3d/player/UnityPlayer"); JFieldID activityFieldId = JNI.GetStaticFieldID(unityClass, "currentActivity", "Landroid/app/Activity;"); using JObject currentActivityObj = JNI.GetStaticObjectField(unityClass, activityFieldId); + JClass activityClass = JNI.GetObjectClass(currentActivityObj); - JObject assetManagerObj = JNI.CallObjectMethod(currentActivityObj, JNI.GetMethodID(activityClass, "getAssets", "()Landroid/content/res/AssetManager;")); + JObject localAssetManager = JNI.CallObjectMethod( + currentActivityObj, + JNI.GetMethodID(activityClass, "getAssets", "()Landroid/content/res/AssetManager;") + ); - HandleException(); + // promote to global ref so GC can't kill it + assetManager = JNI.NewGlobalRef(localAssetManager); - assetManager = assetManagerObj; + HandleException(); } public class APKAssetStream : Stream, IDisposable From b4ee2ef7f21a5b0af0bdc426b7d3f4f6fd581a0d Mon Sep 17 00:00:00 2001 From: Trevor Date: Sat, 16 Aug 2025 14:45:00 -0400 Subject: [PATCH 5/8] Fix LoaderConfig with alpha-dev changes I don't think this is the best way to handle this so it may get changed later. --- MelonLoader.Bootstrap/Core.cs | 4 ++++ MelonLoader/LoaderConfig.cs | 4 ++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/MelonLoader.Bootstrap/Core.cs b/MelonLoader.Bootstrap/Core.cs index 04f654044..76d8a9986 100644 --- a/MelonLoader.Bootstrap/Core.cs +++ b/MelonLoader.Bootstrap/Core.cs @@ -58,7 +58,11 @@ public static void Init(nint moduleHandle) if (!Directory.Exists(DataDir)) return; +#if !ANDROID LoaderConfig.Initialize(); +#else + LoaderConfig.Initialize(DataDir); // Android doesn't work with the GetCurrentProcess system so we use the cached DataDir +#endif if (LoaderConfig.Current.Loader.Disable) return; diff --git a/MelonLoader/LoaderConfig.cs b/MelonLoader/LoaderConfig.cs index 0c1bc5ee9..878dc9cad 100644 --- a/MelonLoader/LoaderConfig.cs +++ b/MelonLoader/LoaderConfig.cs @@ -25,10 +25,10 @@ private static string GetParentDirectory(string path, int level) #endif [RequiresDynamicCode("Dynamically accesses LoaderConfig properties")] - internal static void Initialize() + internal static void Initialize(string? baseDir = null) { var customBaseDir = ArgParser.GetValue("melonloader.basedir"); - var baseDir = Path.GetDirectoryName(Environment.ProcessPath)!; + baseDir ??= Path.GetDirectoryName(Environment.ProcessPath)!; #if OSX baseDir = GetParentDirectory(baseDir, 3); From 86787d60f6799db2f8394d4e58b699b6c9564154 Mon Sep 17 00:00:00 2001 From: Trevor Date: Sat, 16 Aug 2025 18:31:28 -0400 Subject: [PATCH 6/8] Fix tuple usage on net35 --- MelonLoader/JNI/JClass.cs | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/MelonLoader/JNI/JClass.cs b/MelonLoader/JNI/JClass.cs index a55b08430..4e4481425 100644 --- a/MelonLoader/JNI/JClass.cs +++ b/MelonLoader/JNI/JClass.cs @@ -5,15 +5,15 @@ namespace MelonLoader.Java; public class JClass : JObject { - private Dictionary<(string, string), JFieldID> FieldCache { get; set; } = new(); + private Dictionary FieldCache { get; set; } = new(); - private Dictionary<(string, string), JMethodID> MethodCache { get; set; } = new(); + private Dictionary MethodCache { get; set; } = new(); public JClass() : base() { } public JFieldID GetFieldID(string name, string sig) { - (string, string) key = new(name, sig); + CacheItem key = new(name, sig); if (this.FieldCache.TryGetValue(key, out JFieldID found)) { @@ -29,7 +29,7 @@ public JFieldID GetFieldID(string name, string sig) public JFieldID GetStaticFieldID(string name, string sig) { - (string, string) key = new(name, sig); + CacheItem key = new(name, sig); if (this.FieldCache.TryGetValue(key, out JFieldID found)) { @@ -45,7 +45,7 @@ public JFieldID GetStaticFieldID(string name, string sig) public JMethodID GetMethodID(string name, string sig) { - (string, string) key = new(name, sig); + CacheItem key = new(name, sig); if (this.MethodCache.TryGetValue(key, out JMethodID found)) { @@ -61,7 +61,7 @@ public JMethodID GetMethodID(string name, string sig) public JMethodID GetStaticMethodID(string name, string sig) { - (string, string) key = new(name, sig); + CacheItem key = new(name, sig); if (this.MethodCache.TryGetValue(key, out JMethodID found)) { @@ -144,5 +144,11 @@ public void CallVoidMethod(JObject obj, string name, string sig, params JValue[] { return JNI.NewObject(this, this.GetMethodID(name, sig), args); } + + private class CacheItem(string name, string value) + { + public string Name { get; private set; } = name; + public string Value { get; private set; } = value; + } } -#endif +#endif \ No newline at end of file From ef188b6fe12422a1d259d3d68c26f918104a9b9e Mon Sep 17 00:00:00 2001 From: Trevor Date: Sat, 16 Aug 2025 19:51:34 -0400 Subject: [PATCH 7/8] Implement Cpp2IL in Il2CppAssemblyGenerator --- Dependencies/Il2CppAssemblyGenerator/Core.cs | 70 ++++++++- .../Il2CppAssemblyGenerator.csproj | 7 +- .../Packages/Cpp2IL_Android.cs | 137 ++++++++++++++++++ Directory.Build.props | 3 + MelonLoader/Resolver/MelonAssemblyResolver.cs | 3 + 5 files changed, 214 insertions(+), 6 deletions(-) create mode 100644 Dependencies/Il2CppAssemblyGenerator/Packages/Cpp2IL_Android.cs diff --git a/Dependencies/Il2CppAssemblyGenerator/Core.cs b/Dependencies/Il2CppAssemblyGenerator/Core.cs index 88e940aee..f71fa8b2d 100644 --- a/Dependencies/Il2CppAssemblyGenerator/Core.cs +++ b/Dependencies/Il2CppAssemblyGenerator/Core.cs @@ -1,9 +1,13 @@ -using System.IO; -using System.Net.Http; -using MelonLoader.Il2CppAssemblyGenerator.Packages; +using MelonLoader.Il2CppAssemblyGenerator.Packages; using MelonLoader.Il2CppAssemblyGenerator.Packages.Models; using MelonLoader.Modules; using MelonLoader.Utils; +using System.IO; +using System.Linq; +using System.Net.Http; +#if ANDROID +using MelonLoader.Java; +#endif namespace MelonLoader.Il2CppAssemblyGenerator { @@ -31,7 +35,18 @@ public override void OnInitialize() { Logger = LoggerInstance; +#if ANDROID + // Android has problems with SSL, which prevents any connections. This is the workaround. + HttpClientHandler handler = new() + { + ClientCertificateOptions = ClientCertificateOption.Manual, + ServerCertificateCustomValidationCallback = (_, _, _, _) => true + }; + + webClient = new(handler); +#else webClient = new(); +#endif webClient.DefaultRequestHeaders.Add("User-Agent", $"{Properties.BuildInfo.Name} v{Properties.BuildInfo.Version}"); AssemblyGenerationNeeded = LoaderConfig.Current.UnityEngine.ForceRegeneration; @@ -46,6 +61,8 @@ public override void OnInitialize() #if OSX GameAssemblyPath = Path.Combine(MelonEnvironment.GameExecutablePath, "Contents", "Frameworks", gameAssemblyName); +#elif ANDROID + GameAssemblyPath = GetLibIl2CppPath(); #else GameAssemblyPath = Path.Combine(MelonEnvironment.GameRootDirectory, gameAssemblyName); #endif @@ -60,12 +77,17 @@ private static int Run() if (!LoaderConfig.Current.UnityEngine.ForceOfflineGeneration) RemoteAPI.Contact(); - Cpp2IL cpp2IL_netcore = new Cpp2IL(); + Packages.Cpp2IL cpp2IL_netcore = new(); if (MelonUtils.IsWindows - && (cpp2IL_netcore.VersionSem < Cpp2IL.NetCoreMinVersion)) + && (cpp2IL_netcore.VersionSem < Packages.Cpp2IL.NetCoreMinVersion)) cpp2il = new Cpp2IL_NetFramework(); else cpp2il = cpp2IL_netcore; + +#if ANDROID + cpp2il = new Cpp2IL_Android(); +#endif + cpp2il_scrs = new Cpp2IL_StrippedCodeRegSupport(cpp2il); il2cppinterop = new Packages.Il2CppInterop(); @@ -133,6 +155,44 @@ private static int Run() return 0; } +#if ANDROID + private string GetLibIl2CppPath() + { + // get player activity + using JClass unityClass = JNI.FindClass("com/unity3d/player/UnityPlayer"); + JFieldID activityFieldId = JNI.GetStaticFieldID(unityClass, "currentActivity", "Landroid/app/Activity;"); + using JObject currentActivityObj = JNI.GetStaticObjectField(unityClass, activityFieldId); + + // get applicationinfo + using JClass activityType = JNI.GetObjectClass(currentActivityObj); + JMethodID getAppInfoId = JNI.GetMethodID(activityType, "getApplicationInfo", "()Landroid/content/pm/ApplicationInfo;"); + using JObject applicationInfoObj = JNI.CallObjectMethod(currentActivityObj, getAppInfoId); + + // get nativelibrarydir + JFieldID filesFieldId = JNI.GetFieldID(JNI.GetObjectClass(applicationInfoObj), "nativeLibraryDir", "Ljava/lang/String;"); + using JString pathJString = JNI.GetObjectField(applicationInfoObj, filesFieldId); + + if (pathJString == null || !pathJString.Valid()) + { + MelonLogger.Msg("Unable to get libil2cpp path."); + if (JNI.ExceptionCheck()) + { + var ex = JNI.ExceptionOccurred(); + JNI.ExceptionClear(); + MelonLogger.Msg(ex.GetMessage()); + } + + return ""; + } + + string nativePath = JNI.GetJStringString(pathJString); + string[] directoryLibs = Directory.GetFiles(nativePath, "*.so"); + + string libil2Path = directoryLibs.FirstOrDefault(s => s.EndsWith("libil2cpp.so")); + return libil2Path; + } +#endif + private static void OldFiles_Cleanup() { if (Config.Values.OldFiles.Count <= 0) diff --git a/Dependencies/Il2CppAssemblyGenerator/Il2CppAssemblyGenerator.csproj b/Dependencies/Il2CppAssemblyGenerator/Il2CppAssemblyGenerator.csproj index b117f5027..ba88dc43d 100644 --- a/Dependencies/Il2CppAssemblyGenerator/Il2CppAssemblyGenerator.csproj +++ b/Dependencies/Il2CppAssemblyGenerator/Il2CppAssemblyGenerator.csproj @@ -9,14 +9,19 @@ embedded false false + https://nuget.samboy.dev/v3/index.json;$(RestoreSources)
- + + + + + \ No newline at end of file diff --git a/Dependencies/Il2CppAssemblyGenerator/Packages/Cpp2IL_Android.cs b/Dependencies/Il2CppAssemblyGenerator/Packages/Cpp2IL_Android.cs new file mode 100644 index 000000000..5553127bb --- /dev/null +++ b/Dependencies/Il2CppAssemblyGenerator/Packages/Cpp2IL_Android.cs @@ -0,0 +1,137 @@ +#if ANDROID + +using AssetRipper.Primitives; +using Cpp2IL.Core; +using Cpp2IL.Core.Api; +using Cpp2IL.Core.Extensions; +using Cpp2IL.Core.Logging; +using LibCpp2IL.Wasm; +using MelonLoader.InternalUtils; +using MelonLoader.Utils; +using System; +using System.IO; + +namespace MelonLoader.Il2CppAssemblyGenerator.Packages +{ + // Using a direct implementation of Cpp2IL as there isn't any good way of running the executable to my knowledge + internal class Cpp2IL_Android : Models.ExecutablePackage + { + internal Cpp2IL_Android() + { + Version = "2022.1.0-pre-release.20"; + + Name = nameof(Cpp2IL_Android); + Destination = Path.Combine(Core.BasePath, Name); + OutputFolder = Path.Combine(Destination, "cpp2il_out"); + } + + internal override bool ShouldSetup() + => string.IsNullOrEmpty(Config.Values.DumperVersion) + || !Config.Values.DumperVersion.Equals(Version); + + internal override void Cleanup() { } + + internal override void Save() + => Save(ref Config.Values.DumperVersion); + + internal override bool Execute() + { + Logger.InfoLog += (l, s) => Core.Logger.Msg($"[{s}] {l.TrimEnd('\n')}"); + Logger.WarningLog += (l, s) => Core.Logger.Warning($"[{s}] {l.TrimEnd('\n')}"); + Logger.ErrorLog += (l, s) => Core.Logger.Error($"[{s}] {l.TrimEnd('\n')}"); + Logger.VerboseLog += (l, s) => Core.Logger.Msg($"[{s}] {l.TrimEnd('\n')}"); + + byte[] mdData = APKAssetManager.GetAssetBytes("bin/Data/Managed/Metadata/global-metadata.dat"); + string mdPath = Path.Combine(Core.BasePath, "global-metadata.dat"); + File.WriteAllBytes(mdPath, mdData); + + Cpp2IlApi.Init(); + Cpp2IlApi.ConfigureLib(false); + var result = new Cpp2IlRuntimeArgs() + { + PathToAssembly = Core.GameAssemblyPath, + PathToMetadata = mdPath, + UnityVersion = UnityVersion.Parse(UnityInformationHandler.EngineVersion.ToString()), // they use different versions of the same library but under different names, thanks ds5678 + Valid = true, + OutputRootDirectory = OutputFolder, + OutputFormat = OutputFormatRegistry.GetFormat("dummydll"), + ProcessingLayersToRun = [ProcessingLayerRegistry.GetById("attributeinjector")], + }; + + return RunCpp2IL(result); + } + + // mostly copied from https://github.com/SamboyCoding/Cpp2IL/blob/development/Cpp2IL/Program.cs + private bool RunCpp2IL(Cpp2IlRuntimeArgs runtimeArgs) + { + var executionStart = DateTime.Now; + + runtimeArgs.OutputFormat?.OnOutputFormatSelected(); + + WasmFile.RemappedDynCallFunctions = null; + + Cpp2IlApi.InitializeLibCpp2Il(runtimeArgs.PathToAssembly, runtimeArgs.PathToMetadata, runtimeArgs.UnityVersion); + + foreach (var (key, value) in runtimeArgs.ProcessingLayerConfigurationOptions) + Cpp2IlApi.CurrentAppContext.PutExtraData(key, value); + + //Pre-process processing layers, allowing them to stop others from running + Core.Logger.Msg("Pre-processing processing layers..."); + var layers = runtimeArgs.ProcessingLayersToRun.Clone(); + RunProcessingLayers(runtimeArgs, processingLayer => processingLayer.PreProcess(Cpp2IlApi.CurrentAppContext, layers)); + runtimeArgs.ProcessingLayersToRun = layers; + + //Run processing layers + Core.Logger.Msg("Invoking processing layers..."); + RunProcessingLayers(runtimeArgs, processingLayer => processingLayer.Process(Cpp2IlApi.CurrentAppContext)); + + var outputStart = DateTime.Now; + + if (runtimeArgs.OutputFormat != null) + { + Core.Logger.Msg($"Outputting as {runtimeArgs.OutputFormat.OutputFormatName} to {runtimeArgs.OutputRootDirectory}..."); + runtimeArgs.OutputFormat.DoOutput(Cpp2IlApi.CurrentAppContext, runtimeArgs.OutputRootDirectory); + Core.Logger.Msg($"Finished outputting in {(DateTime.Now - outputStart).TotalMilliseconds}ms"); + } + else + { + Core.Logger.Warning("No output format requested, so not outputting anything. The il2cpp game loaded properly though! (Hint: You probably want to specify an output format, try --output-as)"); + } + + Cpp2IlPluginManager.CallOnFinish(); + + File.Delete(runtimeArgs.PathToMetadata); // because we extracted it from the apk's assets folder; only purpose was this + + Core.Logger.Msg($"Done. Total execution time: {(DateTime.Now - executionStart).TotalMilliseconds}ms"); + return true; + } + + private static void RunProcessingLayers(Cpp2IlRuntimeArgs runtimeArgs, Action run) + { + foreach (var processingLayer in runtimeArgs.ProcessingLayersToRun) + { + var processorStart = DateTime.Now; + + Core.Logger.Msg($" {processingLayer.Name}..."); + +#if !DEBUG + try + { +#endif + run(processingLayer); +#if !DEBUG + } + catch (Exception e) + { + Logger.Error($"Processing layer {processingLayer.Id} threw an exception: {e}"); + Environment.Exit(1); + } +#endif + + Core.Logger.Msg($" {processingLayer.Name} finished in {(DateTime.Now - processorStart).TotalMilliseconds}ms"); + } + } + } +} + +#endif \ No newline at end of file diff --git a/Directory.Build.props b/Directory.Build.props index adb2761d5..199e14519 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -13,6 +13,9 @@ x86;x64 false false + + + $(ForcedRID)
diff --git a/MelonLoader/Resolver/MelonAssemblyResolver.cs b/MelonLoader/Resolver/MelonAssemblyResolver.cs index 5624ad228..239a31e56 100644 --- a/MelonLoader/Resolver/MelonAssemblyResolver.cs +++ b/MelonLoader/Resolver/MelonAssemblyResolver.cs @@ -20,6 +20,9 @@ internal static void Setup() // Setup Search Directories AddSearchDirectory(MelonEnvironment.OurRuntimeDirectory); +#if ANDROID // Needed for loading Cpp2IL and deps + AddSearchDirectory(Path.Combine(MelonEnvironment.DependenciesDirectory, "Il2CppAssemblyGenerator")); +#endif // Setup Redirections OverrideBaseAssembly(); From d01ba293d330e548bc683d15b3012d663fe454d1 Mon Sep 17 00:00:00 2001 From: Trevor Date: Sun, 17 Aug 2025 22:59:54 -0400 Subject: [PATCH 8/8] Add Android Interop + minor fixes Interop is very primitive currently, but updating it just takes changing the version number --- .../Il2CppAssemblyGenerator/Il2CppAssemblyGenerator.csproj | 1 - .../Il2CppAssemblyGenerator/Packages/Cpp2IL_Android.cs | 2 +- Dependencies/SupportModules/Il2Cpp/Il2Cpp.csproj | 1 - Directory.Build.props | 4 ++++ MelonLoader/Core.cs | 2 ++ NuGet.config | 2 ++ 6 files changed, 9 insertions(+), 3 deletions(-) diff --git a/Dependencies/Il2CppAssemblyGenerator/Il2CppAssemblyGenerator.csproj b/Dependencies/Il2CppAssemblyGenerator/Il2CppAssemblyGenerator.csproj index ba88dc43d..b6f113551 100644 --- a/Dependencies/Il2CppAssemblyGenerator/Il2CppAssemblyGenerator.csproj +++ b/Dependencies/Il2CppAssemblyGenerator/Il2CppAssemblyGenerator.csproj @@ -9,7 +9,6 @@ embedded false false - https://nuget.samboy.dev/v3/index.json;$(RestoreSources) diff --git a/Dependencies/Il2CppAssemblyGenerator/Packages/Cpp2IL_Android.cs b/Dependencies/Il2CppAssemblyGenerator/Packages/Cpp2IL_Android.cs index 5553127bb..d28581c4b 100644 --- a/Dependencies/Il2CppAssemblyGenerator/Packages/Cpp2IL_Android.cs +++ b/Dependencies/Il2CppAssemblyGenerator/Packages/Cpp2IL_Android.cs @@ -20,7 +20,7 @@ internal Cpp2IL_Android() { Version = "2022.1.0-pre-release.20"; - Name = nameof(Cpp2IL_Android); + Name = nameof(Cpp2IL); Destination = Path.Combine(Core.BasePath, Name); OutputFolder = Path.Combine(Destination, "cpp2il_out"); } diff --git a/Dependencies/SupportModules/Il2Cpp/Il2Cpp.csproj b/Dependencies/SupportModules/Il2Cpp/Il2Cpp.csproj index 6f713e514..67db03c03 100644 --- a/Dependencies/SupportModules/Il2Cpp/Il2Cpp.csproj +++ b/Dependencies/SupportModules/Il2Cpp/Il2Cpp.csproj @@ -8,7 +8,6 @@ embedded SM_Il2Cpp true - https://nuget.bepinex.dev/v3/index.json false diff --git a/Directory.Build.props b/Directory.Build.props index 199e14519..de8c39bcc 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -2,6 +2,7 @@ 0.7.2 1.5.0-ci.625 + 1.5.0-ci.5-arm64 Lava Gang discord.gg/2Wn3N2P @@ -34,6 +35,9 @@ $(DefineConstants);ANDROID lib .a + + + $(Il2CppInteropAndroidVersion) diff --git a/MelonLoader/Core.cs b/MelonLoader/Core.cs index 1eee365d4..350f68e78 100644 --- a/MelonLoader/Core.cs +++ b/MelonLoader/Core.cs @@ -153,7 +153,9 @@ internal static int Initialize() #endif Fixes.Il2CppInterop.Il2CppInteropFixes.Install(); +#if !ANDROID Fixes.Il2CppInterop.Il2CppInteropGetFieldDefaultValueFix.Install(); +#endif Fixes.Il2CppInterop.Il2CppICallInjector.Install(); diff --git a/NuGet.config b/NuGet.config index 063fa5b3a..06cfe7781 100644 --- a/NuGet.config +++ b/NuGet.config @@ -4,6 +4,8 @@ + +