-
-
Notifications
You must be signed in to change notification settings - Fork 490
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
81043aa
commit f900cce
Showing
9 changed files
with
265 additions
and
41 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,8 +1,15 @@ | ||
using System; | ||
|
||
namespace MelonLoader.Bootstrap | ||
{ | ||
public static unsafe class BootstrapInterop | ||
{ | ||
public static delegate* unmanaged<void*, void*, void*> HookAttach; | ||
public static delegate* unmanaged<void*, void> HookDetach; | ||
public static delegate* unmanaged<void*, void*, void*> NativeHookAttach; | ||
public static delegate* unmanaged<void*, void> NativeHookDetach; | ||
|
||
public static void HookAttach(IntPtr target, IntPtr detour) | ||
=> NativeHookAttach(target.ToPointer(), detour.ToPointer()); | ||
public static void HookDetach(IntPtr target) | ||
=> NativeHookDetach(target.ToPointer()); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
using System; | ||
using System.Runtime.InteropServices; | ||
|
||
namespace MelonLoader.Shared.Utils | ||
{ | ||
public static class MelonExtensions | ||
{ | ||
#region Delegate | ||
|
||
public static IntPtr GetFunctionPointer(this Delegate del) | ||
=> Marshal.GetFunctionPointerForDelegate(del); | ||
|
||
#endregion | ||
|
||
#region IntPtr | ||
|
||
public static void GetDelegate<T>(this IntPtr ptr, out T output) where T : Delegate | ||
=> output = GetDelegate<T>(ptr); | ||
public static T GetDelegate<T>(this IntPtr ptr) where T : Delegate | ||
=> GetDelegate(ptr, typeof(T)) as T; | ||
public static Delegate GetDelegate(this IntPtr ptr, Type type) | ||
{ | ||
if (ptr == IntPtr.Zero) | ||
throw new ArgumentNullException(nameof(ptr)); | ||
Delegate del = Marshal.GetDelegateForFunctionPointer(ptr, type); | ||
if (del == null) | ||
throw new Exception($"Unable to Get Delegate of Type {type.FullName} for Function Pointer!"); | ||
return del; | ||
} | ||
|
||
#endregion | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using System.Text; | ||
using System.Threading.Tasks; | ||
|
||
namespace MelonLoader.Unity | ||
{ | ||
internal static class Il2Cpp | ||
{ | ||
internal static void Startup(string gameAssemblyPath) | ||
{ | ||
|
||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,155 @@ | ||
using System; | ||
using System.IO; | ||
using System.Runtime.InteropServices; | ||
using MelonLoader.Bootstrap; | ||
using MelonLoader.Shared.Utils; | ||
|
||
namespace MelonLoader.Unity | ||
{ | ||
internal static class Mono | ||
{ | ||
internal static unsafe void Startup() | ||
{ | ||
// Scan the Game for Information about the Mono Runtime | ||
RuntimeInfo runtimeInfo = RuntimeInfo.Get(); | ||
|
||
// Check if it found any Mono variant library | ||
if ((runtimeInfo == null) | ||
|| string.IsNullOrEmpty(runtimeInfo.FilePath)) | ||
{ | ||
Assertion.ThrowInternalFailure($"Failed to find Mono or MonoBleedingEdge Library!"); | ||
return; | ||
} | ||
|
||
// Check if there is a Posix Helper included with the Mono variant library | ||
if (!string.IsNullOrEmpty(runtimeInfo.PosixPath)) | ||
{ | ||
// Force-Load the Posix Helper before the actual Mono variant library | ||
// Otherwise can cause crashing in some cases | ||
if (!NativeLibrary.TryLoad(runtimeInfo.PosixPath, out IntPtr monoPosixHandle)) | ||
{ | ||
Assertion.ThrowInternalFailure($"Failed to load {runtimeInfo.FolderVariant} Posix Helper from {runtimeInfo.PosixPath}!"); | ||
return; | ||
} | ||
} | ||
|
||
// Load the Mono variant library | ||
if (!NativeLibrary.TryLoad(runtimeInfo.FilePath, out IntPtr monoHandle)) | ||
{ | ||
Assertion.ThrowInternalFailure($"Failed to load {runtimeInfo.FolderVariant} Library from {runtimeInfo.FilePath}!"); | ||
return; | ||
} | ||
|
||
// Get mono_jit_init_version Export | ||
if (!NativeLibrary.TryGetExport(monoHandle, "mono_jit_init_version", out IntPtr initPtr)) | ||
{ | ||
Assertion.ThrowInternalFailure($"Failed to get mono_jit_init_version Export from {runtimeInfo.FolderVariant} Library!"); | ||
return; | ||
} | ||
|
||
// Get mono_runtime_invoke Export | ||
if (!NativeLibrary.TryGetExport(monoHandle, "mono_runtime_invoke", out IntPtr runtimeInvokePtr)) | ||
{ | ||
Assertion.ThrowInternalFailure($"Failed to get mono_runtime_invoke Export from {runtimeInfo.FolderVariant} Library!"); | ||
return; | ||
} | ||
|
||
// Hook mono_jit_init_version | ||
BootstrapInterop.HookAttach(initPtr, ((d_mono_jit_init_version)mono_jit_init_version).GetFunctionPointer()); | ||
|
||
// Hook mono_runtime_invoke | ||
BootstrapInterop.HookAttach(runtimeInvokePtr, ((d_mono_runtime_invoke)mono_runtime_invoke).GetFunctionPointer()); | ||
} | ||
|
||
private unsafe delegate void* d_mono_jit_init_version(void* name, void* version); | ||
private static unsafe void* mono_jit_init_version(void* name, void* version) | ||
{ | ||
return (void*)0; | ||
} | ||
|
||
private unsafe delegate void* d_mono_runtime_invoke(void* method, void* obj, void** prams, void** exec); | ||
private static unsafe void* mono_runtime_invoke(void* method, void* obj, void** prams, void** exec) | ||
{ | ||
return (void*)0; | ||
} | ||
|
||
private class RuntimeInfo | ||
{ | ||
internal readonly string FilePath; | ||
internal readonly string PosixPath; | ||
internal readonly string FolderVariant; | ||
internal readonly bool IsOldMono; | ||
|
||
private RuntimeInfo(string filePath, string posixPath, string folderVariant, bool isOldMono) | ||
{ | ||
FilePath = filePath; | ||
PosixPath = posixPath; | ||
FolderVariant = folderVariant; | ||
IsOldMono = isOldMono; | ||
} | ||
|
||
internal static RuntimeInfo Get() | ||
{ | ||
// Folders the Mono folders might be located in | ||
string[] directoriesToSearch = new string[] | ||
{ | ||
MelonEnvironment.GameRootDirectory, | ||
Bootstrap.GameDataPath | ||
}; | ||
|
||
// Variants of Mono folders | ||
string[] monoFolderVariants = new string[] | ||
{ | ||
"Mono", | ||
"MonoBleedingEdge" | ||
}; | ||
|
||
// Get Mono variant library file name | ||
string monoFileNameWithoutExt = "mono"; | ||
if (MelonUtils.IsUnix || MelonUtils.IsMac) | ||
monoFileNameWithoutExt = $"lib{monoFileNameWithoutExt}"; | ||
|
||
// Get Mono Posix Helper file name | ||
string monoPosixFileNameWithoutExt = "MonoPosixHelper"; | ||
if (MelonUtils.IsUnix || MelonUtils.IsMac) | ||
monoPosixFileNameWithoutExt = "libmonoposixhelper"; | ||
|
||
// Get Platform Used Extension | ||
string monoFileExt = ".dll"; | ||
if (MelonUtils.IsUnix) | ||
monoFileExt = ".so"; | ||
if (MelonUtils.IsMac) | ||
monoFileExt = ".dylib"; | ||
|
||
bool isOldMono = true; | ||
foreach (var variant in monoFolderVariants) | ||
{ | ||
foreach (var dir in directoriesToSearch) | ||
{ | ||
string dirPath = Path.Combine(Path.Combine(dir, variant), "EmbedRuntime"); | ||
if (!Directory.Exists(dirPath)) | ||
continue; | ||
|
||
string[] foundFiles = Directory.GetFiles(dirPath); | ||
if ((foundFiles == null) | ||
|| (foundFiles.Length <= 0)) | ||
continue; | ||
|
||
string posixPath = Path.Combine(dirPath, $"{monoPosixFileNameWithoutExt}{monoFileExt}"); | ||
foreach (var filePath in foundFiles) | ||
{ | ||
string fileName = Path.GetFileName(filePath); | ||
if (fileName.Equals($"{monoFileNameWithoutExt}{monoFileExt}") | ||
|| (fileName.StartsWith($"{monoFileNameWithoutExt}-") && fileName.EndsWith(monoFileExt))) | ||
return new RuntimeInfo(filePath, posixPath, variant, isOldMono); | ||
} | ||
} | ||
|
||
isOldMono = false; | ||
} | ||
|
||
return null; | ||
} | ||
} | ||
} | ||
} |