Skip to content

Commit

Permalink
Start of Mono Runtime Support
Browse files Browse the repository at this point in the history
  • Loading branch information
HerpDerpinstine committed Feb 4, 2025
1 parent 24f65a6 commit 1a13d80
Show file tree
Hide file tree
Showing 9 changed files with 239 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,10 @@ private static void ReadGameInfo(AssetsManager assetsManager, string gameDataPat
GameName = productName.AsString;
}
}
else
{
MelonLogger.Warning("Unable to find PlayerSettings in globalgamemanagers. Possible out-dated classdata.tpk present. Using fallback method.");
}
}
catch(Exception ex)
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
using MelonLoader.NativeUtils;
using System;
using System;
using System.Runtime.InteropServices;

namespace MelonLoader.Il2Cpp
namespace MelonLoader.Runtime.Il2Cpp
{
public class Il2CppLibrary
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
using System;
using System.Collections.Generic;
using MelonLoader.Il2Cpp;
using MelonLoader.Modules;
using MelonLoader.NativeUtils;
#pragma warning disable 0649
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
using System;
using System.Runtime.InteropServices;

namespace MelonLoader.Runtime.Mono
{
public class MonoLibrary
{
#region Mono Method

[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public unsafe delegate IntPtr d_mono_method_get_name(IntPtr method);
public d_mono_method_get_name mono_method_get_name;

[UnmanagedFunctionPointer(CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
public unsafe delegate IntPtr d_mono_runtime_invoke(IntPtr method, IntPtr obj, void** param, ref IntPtr exc);
public d_mono_runtime_invoke mono_runtime_invoke;

#endregion
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<RootNamespace>MelonLoader.Runtime.Mono</RootNamespace>
<TargetFrameworks>net35;net6</TargetFrameworks>
<LangVersion>Latest</LangVersion>
<AppendTargetFrameworkToOutputPath>true</AppendTargetFrameworkToOutputPath>
<OutputPath>$(MLOutDir)/MelonLoader/Dependencies/Runtimes/Mono/</OutputPath>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<DebugType>embedded</DebugType>
<AssemblyName>MelonLoader.Runtime.Mono.Shared</AssemblyName>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="$(SolutionDir)\MelonLoader\MelonLoader.csproj" ExcludeAssets="all" Private="False">
<CopyLocalSatelliteAssemblies>False</CopyLocalSatelliteAssemblies>
</ProjectReference>
</ItemGroup>
</Project>
125 changes: 125 additions & 0 deletions Dependencies/Modules/Runtimes/Mono/Runtime.Mono/MonoLoader.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
using System;
using System.Collections.Generic;
using MelonLoader.Modules;
using MelonLoader.NativeUtils;
#pragma warning disable 0649

namespace MelonLoader.Runtime.Mono
{
public unsafe static class MonoLoader
{
#region Private Members

private static MonoLibrary _lib;

private static MelonNativeDetour<MonoLibrary.d_mono_runtime_invoke> mono_runtime_invoke_detour;

#endregion

#region Public Members

public static MelonEngineModule EngineModule { get; private set; }
public static MonoRuntimeInfo RuntimeInfo { get; private set; }

#endregion

#region Loader

public static void Initialize(MelonEngineModule engineModule,
MonoRuntimeInfo runtimeInfo)
{
// Apply the information
EngineModule = engineModule;
RuntimeInfo = runtimeInfo;

// Check if it found any Mono variant library
if (RuntimeInfo == null
|| string.IsNullOrEmpty(RuntimeInfo.LibPath))
{
MelonLogger.ThrowInternalFailure("Failed to find Mono Library!");
return;
}

// Load Library
if (!LoadLib())
return;

// Check Exports
if (!CheckExports())
return;

// Create mono_runtime_invoke Detour
mono_runtime_invoke_detour = new(_lib.mono_runtime_invoke, h_mono_runtime_invoke, false);

// Attach mono_runtime_invoke Detour
MelonDebug.Msg($"Attaching mono_runtime_invoke Detour...");
mono_runtime_invoke_detour.Attach();
}

private static bool LoadLib()
{
// Load the Mono variant library
MelonDebug.Msg($"Loading Mono Library...");
_lib = new MelonNativeLibrary<MonoLibrary>(MelonNativeLibrary.LoadLib(RuntimeInfo.LibPath)).Instance;

// Check for Failure
if (_lib == null)
{
MelonLogger.ThrowInternalFailure($"Failed to load Il2Cpp Library from {RuntimeInfo.LibPath}!");
return false;
}

return true;
}

private static bool CheckExports()
{
Dictionary<string, Delegate> listOfExports = new();

listOfExports[nameof(_lib.mono_method_get_name)] = _lib.mono_method_get_name;
listOfExports[nameof(_lib.mono_runtime_invoke)] = _lib.mono_runtime_invoke;

foreach (var exportPair in listOfExports)
{
if (exportPair.Value != null)
continue;

MelonLogger.ThrowInternalFailure($"Failed to find {exportPair.Key} Export in Il2Cpp Library!");
return false;
}

return true;
}

#endregion

#region Hooks

private static IntPtr h_mono_runtime_invoke(IntPtr method, IntPtr obj, void** param, ref IntPtr exc)
{
// Get Method Name
string methodName = _lib.mono_method_get_name(method).ToAnsiString();

// Check for Trigger Method
foreach (string triggerMethod in RuntimeInfo.TriggerMethods)
{
if (!methodName.Contains(triggerMethod))
continue;

// Detach mono_runtime_invoke Detour
mono_runtime_invoke_detour.Detach();

// Initiate Stage2
EngineModule.Stage2();

// Return original Invoke without Trampoline
return _lib.mono_runtime_invoke(method, obj, param, ref exc);
}

// Return original Invoke
return mono_runtime_invoke_detour.Trampoline(method, obj, param, ref exc);
}

#endregion
}
}
25 changes: 25 additions & 0 deletions Dependencies/Modules/Runtimes/Mono/Runtime.Mono/MonoRuntimeInfo.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
using MelonLoader.Modules;

namespace MelonLoader.Runtime.Mono
{
public class MonoRuntimeInfo : MelonRuntimeInfo
{
#region Public Members

public string[] TriggerMethods { get; private set; }

#endregion

#region Constructors

public MonoRuntimeInfo(
string libPath,
string[] triggerMethods)
{
LibPath = libPath;
TriggerMethods = triggerMethods;
}

#endregion
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<RootNamespace>MelonLoader.Runtime.Mono</RootNamespace>
<TargetFramework>net6</TargetFramework>
<LangVersion>Latest</LangVersion>
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
<OutputPath>$(MLOutDir)/MelonLoader/Dependencies/Runtimes/Mono/</OutputPath>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<DebugType>embedded</DebugType>
<AssemblyName>MelonLoader.Runtime.Mono</AssemblyName>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="$(SolutionDir)\MelonLoader\MelonLoader.csproj" Private="false" ExcludeAssets="all">
<CopyLocalSatelliteAssemblies>False</CopyLocalSatelliteAssemblies>
</ProjectReference>
<ProjectReference Include="..\Runtime.Mono.Shared\Runtime.Mono.Shared.csproj" Private="false" ExcludeAssets="all">
<CopyLocalSatelliteAssemblies>False</CopyLocalSatelliteAssemblies>
</ProjectReference>
</ItemGroup>
</Project>
26 changes: 26 additions & 0 deletions MelonLoader.sln
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,18 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Unity.Il2Cpp.Shared", "Depe
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Unity.Il2Cpp.AssemblyGenerator", "Dependencies\Modules\Engines\Unity\Il2Cpp\Unity.Il2Cpp.AssemblyGenerator\Unity.Il2Cpp.AssemblyGenerator.csproj", "{51405AB6-110B-4279-8D73-177B7B74537C}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Mono", "Mono", "{5B41B0FE-3B90-4F82-B1B0-061E39C27EBB}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Mono", "Mono", "{3B132718-3D60-44B5-AAF8-BDA2E8BBEDBE}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "CoreCLR", "CoreCLR", "{3A54C1B8-344B-4079-971C-7CF7BF1F7295}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Godot", "Godot", "{AEB11019-A160-4A8C-AB56-06E890AF1BA4}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Runtime.Mono", "Dependencies\Modules\Runtimes\Mono\Runtime.Mono\Runtime.Mono.csproj", "{CF071430-B106-4D7E-9AC5-D3E892479BD2}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Runtime.Mono.Shared", "Dependencies\Modules\Runtimes\Mono\Runtime.Mono.Shared\Runtime.Mono.Shared.csproj", "{AF553B0E-A74D-4F1F-857C-18741FB255E8}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -86,6 +98,14 @@ Global
{51405AB6-110B-4279-8D73-177B7B74537C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{51405AB6-110B-4279-8D73-177B7B74537C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{51405AB6-110B-4279-8D73-177B7B74537C}.Release|Any CPU.Build.0 = Release|Any CPU
{CF071430-B106-4D7E-9AC5-D3E892479BD2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{CF071430-B106-4D7E-9AC5-D3E892479BD2}.Debug|Any CPU.Build.0 = Debug|Any CPU
{CF071430-B106-4D7E-9AC5-D3E892479BD2}.Release|Any CPU.ActiveCfg = Release|Any CPU
{CF071430-B106-4D7E-9AC5-D3E892479BD2}.Release|Any CPU.Build.0 = Release|Any CPU
{AF553B0E-A74D-4F1F-857C-18741FB255E8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{AF553B0E-A74D-4F1F-857C-18741FB255E8}.Debug|Any CPU.Build.0 = Debug|Any CPU
{AF553B0E-A74D-4F1F-857C-18741FB255E8}.Release|Any CPU.ActiveCfg = Release|Any CPU
{AF553B0E-A74D-4F1F-857C-18741FB255E8}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand All @@ -101,6 +121,12 @@ Global
{927F019C-35EE-4942-9CAB-75AE3C043D4C} = {1A31A1FE-5F97-4D02-B622-8D62F971EB67}
{EE6B689E-011A-4FEA-933F-325B0150AEDB} = {1A31A1FE-5F97-4D02-B622-8D62F971EB67}
{51405AB6-110B-4279-8D73-177B7B74537C} = {1A31A1FE-5F97-4D02-B622-8D62F971EB67}
{5B41B0FE-3B90-4F82-B1B0-061E39C27EBB} = {339D0985-0570-4C26-B09F-40E6460646EB}
{3B132718-3D60-44B5-AAF8-BDA2E8BBEDBE} = {5939AA02-721D-4011-9B89-358446C3C818}
{3A54C1B8-344B-4079-971C-7CF7BF1F7295} = {339D0985-0570-4C26-B09F-40E6460646EB}
{AEB11019-A160-4A8C-AB56-06E890AF1BA4} = {EFD62F17-3C48-4D77-8F19-1D4BCD62CEFB}
{CF071430-B106-4D7E-9AC5-D3E892479BD2} = {5B41B0FE-3B90-4F82-B1B0-061E39C27EBB}
{AF553B0E-A74D-4F1F-857C-18741FB255E8} = {5B41B0FE-3B90-4F82-B1B0-061E39C27EBB}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {4AB93B1D-1C52-4A80-809D-C28770140E0A}
Expand Down

0 comments on commit 1a13d80

Please sign in to comment.