diff --git a/BepInEx.Preloader/Entrypoint.cs b/BepInEx.Preloader/Entrypoint.cs
index e8461d9..ebc2270 100644
--- a/BepInEx.Preloader/Entrypoint.cs
+++ b/BepInEx.Preloader/Entrypoint.cs
@@ -1,5 +1,4 @@
using System;
-using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
@@ -11,7 +10,7 @@ namespace BepInEx.Preloader
{
public static void PreloaderPreMain(string[] args)
{
- string bepinPath = Path.GetDirectoryName(Path.GetDirectoryName(Path.GetFullPath(EnvVars.DOORSTOP_INVOKE_DLL_PATH)));
+ string bepinPath = Utility.ParentDirectory(Path.GetFullPath(EnvVars.DOORSTOP_INVOKE_DLL_PATH), 2);
Paths.SetExecutablePath(args[0], bepinPath, EnvVars.DOORSTOP_MANAGED_FOLDER_DIR);
AppDomain.CurrentDomain.AssemblyResolve += LocalResolve;
diff --git a/BepInEx/Paths.cs b/BepInEx/Paths.cs
index b53616c..8d53073 100644
--- a/BepInEx/Paths.cs
+++ b/BepInEx/Paths.cs
@@ -1,5 +1,6 @@
using System.IO;
using System.Reflection;
+using MonoMod.Utils;
namespace BepInEx
{
@@ -12,7 +13,11 @@ namespace BepInEx
{
ExecutablePath = executablePath;
ProcessName = Path.GetFileNameWithoutExtension(executablePath);
- GameRootPath = Path.GetDirectoryName(executablePath);
+
+ GameRootPath = Utility.CurrentOs == Platform.MacOS
+ ? Utility.ParentDirectory(executablePath, 4)
+ : Path.GetDirectoryName(executablePath);
+
ManagedPath = managedPath ?? Utility.CombinePaths(GameRootPath, $"{ProcessName}_Data", "Managed");
BepInExRootPath = bepinRootPath ?? Path.Combine(GameRootPath, "BepInEx");
ConfigPath = Path.Combine(BepInExRootPath, "config");
@@ -58,6 +63,7 @@ namespace BepInEx
///
/// The directory that the currently executing process resides in.
+ /// On OSX however, this is the parent directory of the game.app folder.
///
public static string GameRootPath { get; private set; }
diff --git a/BepInEx/Utility.cs b/BepInEx/Utility.cs
index 09430f1..86990cc 100644
--- a/BepInEx/Utility.cs
+++ b/BepInEx/Utility.cs
@@ -67,6 +67,20 @@ namespace BepInEx
/// A combined path.
public static string CombinePaths(params string[] parts) => parts.Aggregate(Path.Combine);
+ ///
+ /// Returns the parent directory of a path, optionally specifying the amount of levels.
+ ///
+ /// The path to get the parent directory of.
+ /// The amount of levels to traverse. Defaults to 1
+ /// The parent directory.
+ public static string ParentDirectory(string path, int levels = 1)
+ {
+ for (int i = 0; i < levels; i++)
+ path = Path.GetDirectoryName(path);
+
+ return path;
+ }
+
///
/// Tries to parse a bool, with a default value if unable to parse.
///