From c7cfdaaa9ed7e067d6bfdaa00d818ef9e61e6c8f Mon Sep 17 00:00:00 2001
From: hazre <37149950+hazre@users.noreply.github.com>
Date: Wed, 17 Dec 2025 14:09:27 +0100
Subject: [PATCH 1/2] refactor(BepisLoader): remove Hardware.Info dependency
---
.gitmodules | 4 ----
Hardware.Info | 1 -
Runtimes/NET/BepisLoader/BepisLoader.cs | 9 +++++++++
Runtimes/NET/BepisLoader/BepisLoader.csproj | 10 ----------
4 files changed, 9 insertions(+), 15 deletions(-)
delete mode 160000 Hardware.Info
diff --git a/.gitmodules b/.gitmodules
index 6079211f..362a8e01 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -2,7 +2,3 @@
path = HarmonyX
url = https://github.com/ResoniteModding/HarmonyX.git
branch = patchy
-[submodule "Hardware.Info"]
- path = Hardware.Info
- url = https://github.com/ResoniteModding/Hardware.Info.git
- branch = patchy
diff --git a/Hardware.Info b/Hardware.Info
deleted file mode 160000
index b0e99d8c..00000000
--- a/Hardware.Info
+++ /dev/null
@@ -1 +0,0 @@
-Subproject commit b0e99d8c1eb2a5eb1e55efe144d38f47d52ec1c4
diff --git a/Runtimes/NET/BepisLoader/BepisLoader.cs b/Runtimes/NET/BepisLoader/BepisLoader.cs
index a243b9d7..d0342e24 100644
--- a/Runtimes/NET/BepisLoader/BepisLoader.cs
+++ b/Runtimes/NET/BepisLoader/BepisLoader.cs
@@ -7,6 +7,7 @@ namespace BepisLoader;
public class BepisLoader
{
internal static string resoDir = string.Empty;
+ private static readonly string tfmFolder = "net10.0";
internal static AssemblyLoadContext alc = null!;
static void Main(string[] args)
{
@@ -18,6 +19,14 @@ static void Main(string[] args)
alc = new BepisLoadContext();
+ // Load System.Management explicitly for Windows to avoid PlatformNotSupportedException
+ var systemManagementPath = RuntimeInformation.RuntimeIdentifier.StartsWith("win")
+ ? new FileInfo(Path.Combine(resoDir, "runtimes", "win", "lib", tfmFolder, "System.Management.dll"))
+ : new FileInfo(Path.Combine(resoDir, "System.Management.dll"));
+
+ if (systemManagementPath.Exists)
+ alc.LoadFromAssemblyPath(systemManagementPath.FullName);
+
// TODO: removing this breaks stuff, idk why
AppDomain.CurrentDomain.AssemblyResolve += ResolveGameDll;
diff --git a/Runtimes/NET/BepisLoader/BepisLoader.csproj b/Runtimes/NET/BepisLoader/BepisLoader.csproj
index a2617df8..e5a7da5a 100644
--- a/Runtimes/NET/BepisLoader/BepisLoader.csproj
+++ b/Runtimes/NET/BepisLoader/BepisLoader.csproj
@@ -12,16 +12,6 @@
embedded
-
-
-
-
-
-
-
-
-
-
From 28b61378c0e6191efca019b1555563db497db49e Mon Sep 17 00:00:00 2001
From: hazre <37149950+hazre@users.noreply.github.com>
Date: Wed, 17 Dec 2025 17:00:00 +0100
Subject: [PATCH 2/2] refactor(BepisLoader): simplify assembly resolution using
AssemblyDependencyResolver
Replace custom ResolveInternal method with System.Runtime.Loader's AssemblyDependencyResolver for cleaner dependency resolution.
---
Runtimes/NET/BepisLoader/BepisLoader.cs | 100 +++++++-----------------
1 file changed, 30 insertions(+), 70 deletions(-)
diff --git a/Runtimes/NET/BepisLoader/BepisLoader.cs b/Runtimes/NET/BepisLoader/BepisLoader.cs
index d0342e24..fa1e7698 100644
--- a/Runtimes/NET/BepisLoader/BepisLoader.cs
+++ b/Runtimes/NET/BepisLoader/BepisLoader.cs
@@ -1,5 +1,4 @@
using System.Reflection;
-using System.Runtime.InteropServices;
using System.Runtime.Loader;
namespace BepisLoader;
@@ -7,7 +6,6 @@ namespace BepisLoader;
public class BepisLoader
{
internal static string resoDir = string.Empty;
- private static readonly string tfmFolder = "net10.0";
internal static AssemblyLoadContext alc = null!;
static void Main(string[] args)
{
@@ -19,15 +17,7 @@ static void Main(string[] args)
alc = new BepisLoadContext();
- // Load System.Management explicitly for Windows to avoid PlatformNotSupportedException
- var systemManagementPath = RuntimeInformation.RuntimeIdentifier.StartsWith("win")
- ? new FileInfo(Path.Combine(resoDir, "runtimes", "win", "lib", tfmFolder, "System.Management.dll"))
- : new FileInfo(Path.Combine(resoDir, "System.Management.dll"));
-
- if (systemManagementPath.Exists)
- alc.LoadFromAssemblyPath(systemManagementPath.FullName);
-
- // TODO: removing this breaks stuff, idk why
+ // The game runs in the Default AssemblyLoadContext, not our custom BepisLoadContext. When code in the Default ALC requests a dependency, BepisLoadContext.Load() is never called, only this global AssemblyResolve event fires as a fallback.
AppDomain.CurrentDomain.AssemblyResolve += ResolveGameDll;
var bepinPath = Path.Combine(resoDir, "BepInEx");
@@ -40,8 +30,7 @@ static void Main(string[] args)
var asm = alc.LoadFromAssemblyPath(Path.Combine(bepinPath, "core", "BepInEx.NET.CoreCLR.dll"));
- var resoDllPath = Path.Combine(resoDir, "Renderite.Host.dll");
- if (!File.Exists(resoDllPath)) resoDllPath = Path.Combine(resoDir, "Resonite.dll");
+ var resoDllPath = GetResoDllPath();
var t = asm.GetType("StartupHook");
var m = t.GetMethod("Initialize", BindingFlags.Public | BindingFlags.Static, [typeof(string), typeof(string), typeof(AssemblyLoadContext)]);
@@ -80,8 +69,6 @@ static void Main(string[] args)
return found;
}
- if (assemblyName.Name == "System.Management") return null;
-
var targetPath = Path.Combine(resoDir, assemblyName.Name + ".dll");
if (File.Exists(targetPath))
{
@@ -92,74 +79,47 @@ static void Main(string[] args)
return null;
}
+ private static string GetResoDllPath()
+ {
+ var path = Path.Combine(resoDir, "Renderite.Host.dll");
+ return File.Exists(path) ? path : Path.Combine(resoDir, "Resonite.dll");
+ }
+
private class BepisLoadContext : AssemblyLoadContext
{
+ private readonly AssemblyDependencyResolver? _resolver;
+
+ public BepisLoadContext() : base(isCollectible: false)
+ {
+ var resoDllPath = GetResoDllPath();
+
+ if (File.Exists(resoDllPath))
+ _resolver = new AssemblyDependencyResolver(resoDllPath);
+ }
+
protected override Assembly? Load(AssemblyName assemblyName)
{
- return ResolveInternal(assemblyName);
+ // Check already-loaded assemblies first
+ var found = AppDomain.CurrentDomain.GetAssemblies()
+ .FirstOrDefault(x => x.GetName().Name == assemblyName.Name);
+ if (found != null) return found;
+
+ // Use deps.json resolution
+ string? assemblyPath = _resolver?.ResolveAssemblyToPath(assemblyName);
+ return assemblyPath != null ? LoadFromAssemblyPath(assemblyPath) : null;
}
protected override IntPtr LoadUnmanagedDll(string unmanagedDllName)
{
- var rid = GetRuntimeIdentifier();
-
- var nativeLibs = Path.Join(resoDir, "runtimes", rid, "native");
- IEnumerable potentialPaths = [unmanagedDllName, Path.Combine(nativeLibs, GetUnmanagedLibraryName(unmanagedDllName))];
- if (unmanagedDllName.EndsWith("steam_api64.so")) potentialPaths = ((IEnumerable)["libsteam_api.so"]).Concat(potentialPaths);
-
Log("NativeLib " + unmanagedDllName);
- foreach (var path in potentialPaths)
+ string? libraryPath = _resolver?.ResolveUnmanagedDllToPath(unmanagedDllName);
+ if (libraryPath != null)
{
- Log(" Testing: " + path);
- if (File.Exists(path))
- {
- Log(" Exists! " + path);
- var dll = LoadUnmanagedDllFromPath(path);
- if (dll != IntPtr.Zero)
- {
- Log(" Loaded! " + path);
- return dll;
- }
- }
+ Log(" Resolved: " + libraryPath);
+ return LoadUnmanagedDllFromPath(libraryPath);
}
-
return IntPtr.Zero;
}
-
-
- private static string GetRuntimeIdentifier()
- {
- string os;
- if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
- os = "win";
- else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
- os = "osx";
- else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
- os = "linux";
- else
- throw new PlatformNotSupportedException();
-
- string arch = RuntimeInformation.OSArchitecture switch
- {
- Architecture.X86 => "-x86",
- Architecture.X64 => "-x64",
- Architecture.Arm64 => "-arm64",
- _ => ""
- };
-
- return $"{os}{arch}";
- }
- private static string GetUnmanagedLibraryName(string name)
- {
- if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
- return $"{name}.dll";
- if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
- return $"lib{name}.so";
- if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
- return $"lib{name}.dylib";
-
- throw new PlatformNotSupportedException();
- }
}
#if DEBUG