diff --git a/src/Ryujinx.Ava/UI/ViewModels/MainWindowViewModel.cs b/src/Ryujinx.Ava/UI/ViewModels/MainWindowViewModel.cs
index 4ce4799904..f4556bc3c9 100644
--- a/src/Ryujinx.Ava/UI/ViewModels/MainWindowViewModel.cs
+++ b/src/Ryujinx.Ava/UI/ViewModels/MainWindowViewModel.cs
@@ -1576,8 +1576,8 @@ namespace Ryujinx.Ava.UI.ViewModels
         {
             if (SelectedApplication != null)
             {
-                string modsBasePath  = ModLoader.GetModsBasePath();
-                string titleModsPath = ModLoader.GetTitleDir(modsBasePath, SelectedApplication.TitleId);
+                string modsBasePath  = VirtualFileSystem.ModLoader.GetModsBasePath();
+                string titleModsPath = VirtualFileSystem.ModLoader.GetTitleDir(modsBasePath, SelectedApplication.TitleId);
 
                 OpenHelper.OpenFolder(titleModsPath);
             }
@@ -1587,8 +1587,8 @@ namespace Ryujinx.Ava.UI.ViewModels
         {
             if (SelectedApplication != null)
             {
-                string sdModsBasePath = ModLoader.GetSdModsBasePath();
-                string titleModsPath  = ModLoader.GetTitleDir(sdModsBasePath, SelectedApplication.TitleId);
+                string sdModsBasePath = VirtualFileSystem.ModLoader.GetSdModsBasePath();
+                string titleModsPath  = VirtualFileSystem.ModLoader.GetTitleDir(sdModsBasePath, SelectedApplication.TitleId);
 
                 OpenHelper.OpenFolder(titleModsPath);
             }
diff --git a/src/Ryujinx.Ava/UI/Windows/CheatWindow.axaml.cs b/src/Ryujinx.Ava/UI/Windows/CheatWindow.axaml.cs
index 241a6c346c..cb939763b0 100644
--- a/src/Ryujinx.Ava/UI/Windows/CheatWindow.axaml.cs
+++ b/src/Ryujinx.Ava/UI/Windows/CheatWindow.axaml.cs
@@ -35,8 +35,8 @@ namespace Ryujinx.Ava.UI.Windows
 
             InitializeComponent();
 
-            string modsBasePath = ModLoader.GetModsBasePath();
-            string titleModsPath = ModLoader.GetTitleDir(modsBasePath, titleId);
+            string modsBasePath = virtualFileSystem.ModLoader.GetModsBasePath();
+            string titleModsPath = virtualFileSystem.ModLoader.GetTitleDir(modsBasePath, titleId);
             ulong titleIdValue = ulong.Parse(titleId, System.Globalization.NumberStyles.HexNumber);
 
             _enabledCheatsPath = Path.Combine(titleModsPath, "cheats", "enabled.txt");
diff --git a/src/Ryujinx.HLE/HOS/ModLoader.cs b/src/Ryujinx.HLE/HOS/ModLoader.cs
index a173ac418e..1651254144 100644
--- a/src/Ryujinx.HLE/HOS/ModLoader.cs
+++ b/src/Ryujinx.HLE/HOS/ModLoader.cs
@@ -89,7 +89,7 @@ namespace Ryujinx.HLE.HOS
         }
 
         // Title independent mods
-        private class PatchCache
+        public class PatchCache
         {
             public List<Mod<DirectoryInfo>> NsoPatches { get; }
             public List<Mod<DirectoryInfo>> NroPatches { get; }
@@ -107,14 +107,14 @@ namespace Ryujinx.HLE.HOS
             }
         }
 
-        private readonly Dictionary<ulong, ModCache> _appMods; // key is TitleId
-        private PatchCache _patches;
+        public Dictionary<ulong, ModCache> AppMods; // key is TitleId
+        public PatchCache Patches;
 
-        private static readonly EnumerationOptions DirEnumOptions;
+        private static readonly EnumerationOptions _dirEnumOptions;
 
         static ModLoader()
         {
-            DirEnumOptions = new EnumerationOptions
+            _dirEnumOptions = new EnumerationOptions
             {
                 MatchCasing = MatchCasing.CaseInsensitive,
                 MatchType = MatchType.Simple,
@@ -125,73 +125,37 @@ namespace Ryujinx.HLE.HOS
 
         public ModLoader()
         {
-            _appMods = new Dictionary<ulong, ModCache>();
-            _patches = new PatchCache();
+            AppMods = new Dictionary<ulong, ModCache>();
+            Patches = new PatchCache();
         }
 
-        private void Clear()
+        public void Clear()
         {
-            _appMods.Clear();
-            _patches = new PatchCache();
+            AppMods.Clear();
+            Patches = new PatchCache();
         }
 
         private static bool StrEquals(string s1, string s2) => string.Equals(s1, s2, StringComparison.OrdinalIgnoreCase);
 
-        public static string GetModsBasePath()   => EnsureBaseDirStructure(AppDataManager.GetModsPath());
-        public static string GetSdModsBasePath() => EnsureBaseDirStructure(AppDataManager.GetSdModsPath());
+        public string GetModsBasePath()   => EnsureBaseDirStructure(AppDataManager.GetModsPath());
+        public string GetSdModsBasePath() => EnsureBaseDirStructure(AppDataManager.GetSdModsPath());
 
-        private static string EnsureBaseDirStructure(string modsBasePath)
+        private string EnsureBaseDirStructure(string modsBasePath)
         {
             var modsDir = new DirectoryInfo(modsBasePath);
 
             modsDir.CreateSubdirectory(AmsContentsDir);
             modsDir.CreateSubdirectory(AmsNsoPatchDir);
             modsDir.CreateSubdirectory(AmsNroPatchDir);
-            // TODO: uncomment when KIPs are supported
-            // modsDir.CreateSubdirectory(AmsKipPatchDir);
+            // modsDir.CreateSubdirectory(AmsKipPatchDir); // uncomment when KIPs are supported
 
             return modsDir.FullName;
         }
 
         private static DirectoryInfo FindTitleDir(DirectoryInfo contentsDir, string titleId)
-            => contentsDir.EnumerateDirectories($"{titleId}*", DirEnumOptions).FirstOrDefault();
+            => contentsDir.EnumerateDirectories($"{titleId}*", _dirEnumOptions).FirstOrDefault();
 
-        private static void AddModsFromDirectory(ModCache mods, DirectoryInfo dir, string titleId)
-        {
-            System.Text.StringBuilder types = new();
-
-            foreach (var modDir in dir.EnumerateDirectories())
-            {
-                types.Clear();
-                Mod<DirectoryInfo> mod = new("", null);
-
-                if (StrEquals(RomfsDir, modDir.Name))
-                {
-                    mods.RomfsDirs.Add(mod = new Mod<DirectoryInfo>($"<{titleId} RomFs>", modDir));
-                    types.Append('R');
-                }
-                else if (StrEquals(ExefsDir, modDir.Name))
-                {
-                    mods.ExefsDirs.Add(mod = new Mod<DirectoryInfo>($"<{titleId} ExeFs>", modDir));
-                    types.Append('E');
-                }
-                else if (StrEquals(CheatDir, modDir.Name))
-                {
-                    types.Append('C', QueryCheatsDir(mods, modDir));
-                }
-                else
-                {
-                    AddModsFromDirectory(mods, modDir, titleId);
-                }
-
-                if (types.Length > 0)
-                {
-                    Logger.Info?.Print(LogClass.ModLoader, $"Found mod '{mod.Name}' [{types}]");
-                }
-            }
-        }
-
-        public static string GetTitleDir(string modsBasePath, string titleId)
+        public string GetTitleDir(string modsBasePath, string titleId)
         {
             var contentsDir = new DirectoryInfo(Path.Combine(modsBasePath, AmsContentsDir));
             var titleModsPath = FindTitleDir(contentsDir, titleId);
@@ -206,32 +170,17 @@ namespace Ryujinx.HLE.HOS
         }
 
         // Static Query Methods
-        private static void QueryPatchDirs(PatchCache cache, DirectoryInfo patchDir)
+        public static void QueryPatchDirs(PatchCache cache, DirectoryInfo patchDir)
         {
-            if (cache.Initialized || !patchDir.Exists)
-            {
-                return;
-            }
+            if (cache.Initialized || !patchDir.Exists) return;
 
-            List<Mod<DirectoryInfo>> patches;
-            string type;
+            var patches = cache.KipPatches;
+            string type = null;
 
-            if (StrEquals(AmsNsoPatchDir, patchDir.Name))
-            {
-                patches = cache.NsoPatches; type = "NSO";
-            }
-            else if (StrEquals(AmsNroPatchDir, patchDir.Name))
-            {
-                patches = cache.NroPatches; type = "NRO";
-            }
-            else if (StrEquals(AmsKipPatchDir, patchDir.Name))
-            {
-                patches = cache.KipPatches; type = "KIP";
-            }
-            else
-            {
-                return;
-            }
+            if (StrEquals(AmsNsoPatchDir, patchDir.Name)) { patches = cache.NsoPatches; type = "NSO"; }
+            else if (StrEquals(AmsNroPatchDir, patchDir.Name)) { patches = cache.NroPatches; type = "NRO"; }
+            else if (StrEquals(AmsKipPatchDir, patchDir.Name)) { patches = cache.KipPatches; type = "KIP"; }
+            else return;
 
             foreach (var modDir in patchDir.EnumerateDirectories())
             {
@@ -240,12 +189,9 @@ namespace Ryujinx.HLE.HOS
             }
         }
 
-        private static void QueryTitleDir(ModCache mods, DirectoryInfo titleDir)
+        public static void QueryTitleDir(ModCache mods, DirectoryInfo titleDir)
         {
-            if (!titleDir.Exists)
-            {
-                return;
-            }
+            if (!titleDir.Exists) return;
 
             var fsFile = new FileInfo(Path.Combine(titleDir.FullName, RomfsContainer));
             if (fsFile.Exists)
@@ -259,15 +205,64 @@ namespace Ryujinx.HLE.HOS
                 mods.ExefsContainers.Add(new Mod<FileInfo>($"<{titleDir.Name} ExeFs>", fsFile));
             }
 
-            AddModsFromDirectory(mods, titleDir, titleDir.Name);
+            System.Text.StringBuilder types = new System.Text.StringBuilder(5);
+
+            foreach (var modDir in titleDir.EnumerateDirectories())
+            {
+                types.Clear();
+                Mod<DirectoryInfo> mod = new Mod<DirectoryInfo>("", null);
+
+                if (StrEquals(RomfsDir, modDir.Name))
+                {
+                    mods.RomfsDirs.Add(mod = new Mod<DirectoryInfo>($"<{titleDir.Name} RomFs>", modDir));
+                    types.Append('R');
+                }
+                else if (StrEquals(ExefsDir, modDir.Name))
+                {
+                    mods.ExefsDirs.Add(mod = new Mod<DirectoryInfo>($"<{titleDir.Name} ExeFs>", modDir));
+                    types.Append('E');
+                }
+                else if (StrEquals(CheatDir, modDir.Name))
+                {
+                    for (int i = 0; i < QueryCheatsDir(mods, modDir); i++)
+                    {
+                        types.Append('C');
+                    }
+                }
+                else
+                {
+                    var romfs = new DirectoryInfo(Path.Combine(modDir.FullName, RomfsDir));
+                    var exefs = new DirectoryInfo(Path.Combine(modDir.FullName, ExefsDir));
+                    var cheat = new DirectoryInfo(Path.Combine(modDir.FullName, CheatDir));
+
+                    if (romfs.Exists)
+                    {
+                        mods.RomfsDirs.Add(mod = new Mod<DirectoryInfo>(modDir.Name, romfs));
+                        types.Append('R');
+                    }
+
+                    if (exefs.Exists)
+                    {
+                        mods.ExefsDirs.Add(mod = new Mod<DirectoryInfo>(modDir.Name, exefs));
+                        types.Append('E');
+                    }
+
+                    if (cheat.Exists)
+                    {
+                        for (int i = 0; i < QueryCheatsDir(mods, cheat); i++)
+                        {
+                            types.Append('C');
+                        }
+                    }
+                }
+
+                if (types.Length > 0) Logger.Info?.Print(LogClass.ModLoader, $"Found mod '{mod.Name}' [{types}]");
+            }
         }
 
         public static void QueryContentsDir(ModCache mods, DirectoryInfo contentsDir, ulong titleId)
         {
-            if (!contentsDir.Exists)
-            {
-                return;
-            }
+            if (!contentsDir.Exists) return;
 
             Logger.Info?.Print(LogClass.ModLoader, $"Searching mods for {((titleId & 0x1000) != 0 ? "DLC" : "Title")} {titleId:X16}");
 
@@ -307,16 +302,9 @@ namespace Ryujinx.HLE.HOS
                     continue;
                 }
 
-                int oldCheatsCount = mods.Cheats.Count;
-
                 // A cheat file can contain several cheats for the same executable, so the file must be parsed in
                 // order to properly enumerate them.
                 mods.Cheats.AddRange(GetCheatsInFile(file));
-
-                if (mods.Cheats.Count - oldCheatsCount > 0)
-                {
-                    numMods++;
-                }
             }
 
             return numMods;
@@ -325,54 +313,57 @@ namespace Ryujinx.HLE.HOS
         private static IEnumerable<Cheat> GetCheatsInFile(FileInfo cheatFile)
         {
             string cheatName = DefaultCheatName;
-            List<string> instructions = new();
-            List<Cheat> cheats = new();
+            List<string> instructions = new List<string>();
+            List<Cheat> cheats = new List<Cheat>();
 
-            using StreamReader cheatData = cheatFile.OpenText();
-            while (cheatData.ReadLine() is { } line)
+            using (StreamReader cheatData = cheatFile.OpenText())
             {
-                line = line.Trim();
-
-                if (line.StartsWith('['))
+                string line;
+                while ((line = cheatData.ReadLine()) != null)
                 {
-                    // This line starts a new cheat section.
-                    if (!line.EndsWith(']') || line.Length < 3)
+                    line = line.Trim();
+
+                    if (line.StartsWith('['))
                     {
-                        // Skip the entire file if there's any error while parsing the cheat file.
+                        // This line starts a new cheat section.
+                        if (!line.EndsWith(']') || line.Length < 3)
+                        {
+                            // Skip the entire file if there's any error while parsing the cheat file.
 
-                        Logger.Warning?.Print(LogClass.ModLoader, $"Ignoring cheat '{cheatFile.FullName}' because it is malformed");
+                            Logger.Warning?.Print(LogClass.ModLoader, $"Ignoring cheat '{cheatFile.FullName}' because it is malformed");
 
-                        return Array.Empty<Cheat>();
+                            return new List<Cheat>();
+                        }
+
+                        // Add the previous section to the list.
+                        if (instructions.Count != 0)
+                        {
+                            cheats.Add(new Cheat($"<{cheatName} Cheat>", cheatFile, instructions));
+                        }
+
+                        // Start a new cheat section.
+                        cheatName = line.Substring(1, line.Length - 2);
+                        instructions = new List<string>();
                     }
-
-                    // Add the previous section to the list.
-                    if (instructions.Count > 0)
+                    else if (line.Length > 0)
                     {
-                        cheats.Add(new Cheat($"<{cheatName} Cheat>", cheatFile, instructions));
+                        // The line contains an instruction.
+                        instructions.Add(line);
                     }
-
-                    // Start a new cheat section.
-                    cheatName = line.Substring(1, line.Length - 2);
-                    instructions.Clear();
                 }
-                else if (line.Length > 0)
+
+                // Add the last section being processed.
+                if (instructions.Count != 0)
                 {
-                    // The line contains an instruction.
-                    instructions.Add(line);
+                    cheats.Add(new Cheat($"<{cheatName} Cheat>", cheatFile, instructions));
                 }
             }
 
-            // Add the last section being processed.
-            if (instructions.Count > 0)
-            {
-                cheats.Add(new Cheat($"<{cheatName} Cheat>", cheatFile, instructions));
-            }
-
             return cheats;
         }
 
         // Assumes searchDirPaths don't overlap
-        private static void CollectMods(Dictionary<ulong, ModCache> modCaches, PatchCache patches, params string[] searchDirPaths)
+        public static void CollectMods(Dictionary<ulong, ModCache> modCaches, PatchCache patches, params string[] searchDirPaths)
         {
             static bool IsPatchesDir(string name) => StrEquals(AmsNsoPatchDir, name) ||
                                                      StrEquals(AmsNroPatchDir, name) ||
@@ -384,7 +375,7 @@ namespace Ryujinx.HLE.HOS
             {
                 if (IsContentsDir(searchDir.Name))
                 {
-                    foreach ((ulong titleId, ModCache cache) in modCaches)
+                    foreach (var (titleId, cache) in modCaches)
                     {
                         QueryContentsDir(cache, searchDir, titleId);
                     }
@@ -428,15 +419,15 @@ namespace Ryujinx.HLE.HOS
 
             foreach (ulong titleId in titles)
             {
-                _appMods[titleId] = new ModCache();
+                AppMods[titleId] = new ModCache();
             }
 
-            CollectMods(_appMods, _patches, searchDirPaths);
+            CollectMods(AppMods, Patches, searchDirPaths);
         }
 
         internal IStorage ApplyRomFsMods(ulong titleId, IStorage baseStorage)
         {
-            if (!_appMods.TryGetValue(titleId, out ModCache mods) || mods.RomfsDirs.Count + mods.RomfsContainers.Count == 0)
+            if (!AppMods.TryGetValue(titleId, out ModCache mods) || mods.RomfsDirs.Count + mods.RomfsContainers.Count == 0)
             {
                 return baseStorage;
             }
@@ -496,7 +487,7 @@ namespace Ryujinx.HLE.HOS
             return newStorage;
         }
 
-        private static void AddFiles(IFileSystem fs, string modName, ISet<string> fileSet, RomFsBuilder builder)
+        private static void AddFiles(IFileSystem fs, string modName, HashSet<string> fileSet, RomFsBuilder builder)
         {
             foreach (var entry in fs.EnumerateEntries()
                                     .Where(f => f.Type == DirectoryEntryType.File)
@@ -518,7 +509,7 @@ namespace Ryujinx.HLE.HOS
 
         internal bool ReplaceExefsPartition(ulong titleId, ref IFileSystem exefs)
         {
-            if (!_appMods.TryGetValue(titleId, out ModCache mods) || mods.ExefsContainers.Count == 0)
+            if (!AppMods.TryGetValue(titleId, out ModCache mods) || mods.ExefsContainers.Count == 0)
             {
                 return false;
             }
@@ -546,13 +537,13 @@ namespace Ryujinx.HLE.HOS
 
         internal ModLoadResult ApplyExefsMods(ulong titleId, NsoExecutable[] nsos)
         {
-            ModLoadResult modLoadResult = new()
+            ModLoadResult modLoadResult = new ModLoadResult
             {
                 Stubs = new BitVector32(),
                 Replaces = new BitVector32()
             };
 
-            if (!_appMods.TryGetValue(titleId, out ModCache mods) || mods.ExefsDirs.Count == 0)
+            if (!AppMods.TryGetValue(titleId, out ModCache mods) || mods.ExefsDirs.Count == 0)
             {
                 return modLoadResult;
             }
@@ -570,7 +561,7 @@ namespace Ryujinx.HLE.HOS
                 {
                     var nsoName = ProcessConst.ExeFsPrefixes[i];
 
-                    FileInfo nsoFile = new(Path.Combine(mod.Path.FullName, nsoName));
+                    FileInfo nsoFile = new FileInfo(Path.Combine(mod.Path.FullName, nsoName));
                     if (nsoFile.Exists)
                     {
                         if (modLoadResult.Replaces[1 << i])
@@ -589,7 +580,7 @@ namespace Ryujinx.HLE.HOS
                     modLoadResult.Stubs[1 << i] |= File.Exists(Path.Combine(mod.Path.FullName, nsoName + StubExtension));
                 }
 
-                FileInfo npdmFile = new(Path.Combine(mod.Path.FullName, "main.npdm"));
+                FileInfo npdmFile = new FileInfo(Path.Combine(mod.Path.FullName, "main.npdm"));
                 if (npdmFile.Exists)
                 {
                     if (modLoadResult.Npdm != null)
@@ -620,7 +611,7 @@ namespace Ryujinx.HLE.HOS
 
         internal void ApplyNroPatches(NroExecutable nro)
         {
-            var nroPatches = _patches.NroPatches;
+            var nroPatches = Patches.NroPatches;
 
             if (nroPatches.Count == 0) return;
 
@@ -631,9 +622,9 @@ namespace Ryujinx.HLE.HOS
 
         internal bool ApplyNsoPatches(ulong titleId, params IExecutable[] programs)
         {
-            IEnumerable<Mod<DirectoryInfo>> nsoMods = _patches.NsoPatches;
+            IEnumerable<Mod<DirectoryInfo>> nsoMods = Patches.NsoPatches;
 
-            if (_appMods.TryGetValue(titleId, out ModCache mods))
+            if (AppMods.TryGetValue(titleId, out ModCache mods))
             {
                 nsoMods = nsoMods.Concat(mods.ExefsDirs);
             }
@@ -645,7 +636,7 @@ namespace Ryujinx.HLE.HOS
 
         internal void LoadCheats(ulong titleId, ProcessTamperInfo tamperInfo, TamperMachine tamperMachine)
         {
-            if (tamperInfo?.BuildIds == null || tamperInfo.CodeAddresses == null)
+            if (tamperInfo == null || tamperInfo.BuildIds == null || tamperInfo.CodeAddresses == null)
             {
                 Logger.Error?.Print(LogClass.ModLoader, "Unable to install cheat because the associated process is invalid");
 
@@ -654,14 +645,14 @@ namespace Ryujinx.HLE.HOS
 
             Logger.Info?.Print(LogClass.ModLoader, $"Build ids found for title {titleId:X16}:\n    {String.Join("\n    ", tamperInfo.BuildIds)}");
 
-            if (!_appMods.TryGetValue(titleId, out ModCache mods) || mods.Cheats.Count == 0)
+            if (!AppMods.TryGetValue(titleId, out ModCache mods) || mods.Cheats.Count == 0)
             {
                 return;
             }
 
             var cheats = mods.Cheats;
             var processExes = tamperInfo.BuildIds.Zip(tamperInfo.CodeAddresses, (k, v) => new { k, v })
-                .ToDictionary(x => x.k[..Math.Min(Cheat.CheatIdSize, x.k.Length)], x => x.v);
+                .ToDictionary(x => x.k.Substring(0, Math.Min(Cheat.CheatIdSize, x.k.Length)), x => x.v);
 
             foreach (var cheat in cheats)
             {
@@ -767,4 +758,4 @@ namespace Ryujinx.HLE.HOS
             return count > 0;
         }
     }
-}
\ No newline at end of file
+}
diff --git a/src/Ryujinx.HLE/Loaders/Processes/Extensions/LocalFileSystemExtensions.cs b/src/Ryujinx.HLE/Loaders/Processes/Extensions/LocalFileSystemExtensions.cs
index fb85329d2b..28d9078512 100644
--- a/src/Ryujinx.HLE/Loaders/Processes/Extensions/LocalFileSystemExtensions.cs
+++ b/src/Ryujinx.HLE/Loaders/Processes/Extensions/LocalFileSystemExtensions.cs
@@ -2,7 +2,6 @@
 using LibHac.FsSystem;
 using LibHac.Loader;
 using LibHac.Ns;
-using Ryujinx.HLE.HOS;
 using Ryujinx.HLE.Loaders.Processes.Extensions;
 using ApplicationId = LibHac.Ncm.ApplicationId;
 
@@ -18,8 +17,8 @@ namespace Ryujinx.HLE.Loaders.Processes
 
             device.Configuration.VirtualFileSystem.ModLoader.CollectMods(
                 new[] { programId },
-                ModLoader.GetModsBasePath(),
-                ModLoader.GetSdModsBasePath());
+                device.Configuration.VirtualFileSystem.ModLoader.GetModsBasePath(),
+                device.Configuration.VirtualFileSystem.ModLoader.GetSdModsBasePath());
 
             if (programId != 0)
             {
@@ -37,4 +36,4 @@ namespace Ryujinx.HLE.Loaders.Processes
             return processResult;
         }
     }
-}
\ No newline at end of file
+}
diff --git a/src/Ryujinx.HLE/Loaders/Processes/Extensions/NcaExtensions.cs b/src/Ryujinx.HLE/Loaders/Processes/Extensions/NcaExtensions.cs
index e11b81d7f7..473f374db9 100644
--- a/src/Ryujinx.HLE/Loaders/Processes/Extensions/NcaExtensions.cs
+++ b/src/Ryujinx.HLE/Loaders/Processes/Extensions/NcaExtensions.cs
@@ -8,7 +8,6 @@ using LibHac.Ns;
 using LibHac.Tools.FsSystem;
 using LibHac.Tools.FsSystem.NcaUtils;
 using Ryujinx.Common.Logging;
-using Ryujinx.HLE.HOS;
 using System.IO;
 using System.Linq;
 using ApplicationId = LibHac.Ncm.ApplicationId;
@@ -36,8 +35,8 @@ namespace Ryujinx.HLE.Loaders.Processes.Extensions
             // Collecting mods related to AocTitleIds and ProgramId.
             device.Configuration.VirtualFileSystem.ModLoader.CollectMods(
                 device.Configuration.ContentManager.GetAocTitleIds().Prepend(metaLoader.GetProgramId()),
-                ModLoader.GetModsBasePath(),
-                ModLoader.GetSdModsBasePath());
+                device.Configuration.VirtualFileSystem.ModLoader.GetModsBasePath(),
+                device.Configuration.VirtualFileSystem.ModLoader.GetSdModsBasePath());
 
             // Load Nacp file.
             var nacpData = new BlitStruct<ApplicationControlProperty>(1);
diff --git a/src/Ryujinx/Ui/Widgets/GameTableContextMenu.cs b/src/Ryujinx/Ui/Widgets/GameTableContextMenu.cs
index 6d83316586..558288aab3 100644
--- a/src/Ryujinx/Ui/Widgets/GameTableContextMenu.cs
+++ b/src/Ryujinx/Ui/Widgets/GameTableContextMenu.cs
@@ -460,16 +460,16 @@ namespace Ryujinx.Ui.Widgets
 
         private void OpenTitleModDir_Clicked(object sender, EventArgs args)
         {
-            string modsBasePath  = ModLoader.GetModsBasePath();
-            string titleModsPath = ModLoader.GetTitleDir(modsBasePath, _titleIdText);
+            string modsBasePath  = _virtualFileSystem.ModLoader.GetModsBasePath();
+            string titleModsPath = _virtualFileSystem.ModLoader.GetTitleDir(modsBasePath, _titleIdText);
 
             OpenHelper.OpenFolder(titleModsPath);
         }
 
         private void OpenTitleSdModDir_Clicked(object sender, EventArgs args)
         {
-            string sdModsBasePath  = ModLoader.GetSdModsBasePath();
-            string titleModsPath   = ModLoader.GetTitleDir(sdModsBasePath, _titleIdText);
+            string sdModsBasePath  = _virtualFileSystem.ModLoader.GetSdModsBasePath();
+            string titleModsPath   = _virtualFileSystem.ModLoader.GetTitleDir(sdModsBasePath, _titleIdText);
 
             OpenHelper.OpenFolder(titleModsPath);
         }
diff --git a/src/Ryujinx/Ui/Windows/CheatWindow.cs b/src/Ryujinx/Ui/Windows/CheatWindow.cs
index 7dbea01289..917603b290 100644
--- a/src/Ryujinx/Ui/Windows/CheatWindow.cs
+++ b/src/Ryujinx/Ui/Windows/CheatWindow.cs
@@ -28,8 +28,8 @@ namespace Ryujinx.Ui.Windows
             builder.Autoconnect(this);
             _baseTitleInfoLabel.Text = $"Cheats Available for {titleName} [{titleId:X16}]";
 
-            string modsBasePath  = ModLoader.GetModsBasePath();
-            string titleModsPath = ModLoader.GetTitleDir(modsBasePath, titleId.ToString("X16"));
+            string modsBasePath  = virtualFileSystem.ModLoader.GetModsBasePath();
+            string titleModsPath = virtualFileSystem.ModLoader.GetTitleDir(modsBasePath, titleId.ToString("X16"));
 
             _enabledCheatsPath = System.IO.Path.Combine(titleModsPath, "cheats", "enabled.txt");