diff --git a/ARMeilleure/Translation/PTC/Ptc.cs b/ARMeilleure/Translation/PTC/Ptc.cs index ccb3f7054..c6069d887 100644 --- a/ARMeilleure/Translation/PTC/Ptc.cs +++ b/ARMeilleure/Translation/PTC/Ptc.cs @@ -1,6 +1,7 @@ using ARMeilleure.CodeGen; using ARMeilleure.CodeGen.Unwinding; using ARMeilleure.Memory; +using Ryujinx.Common.Configuration; using Ryujinx.Common.Logging; using System; using System.Buffers.Binary; @@ -22,8 +23,6 @@ namespace ARMeilleure.Translation.PTC private const int InternalVersion = 1471; //! To be incremented manually for each change to the ARMeilleure project. - private const string BaseDir = "Ryujinx"; - private const string ActualDir = "0"; private const string BackupDir = "1"; @@ -49,8 +48,6 @@ namespace ARMeilleure.Translation.PTC private static readonly AutoResetEvent _loggerEvent; - private static readonly string _basePath; - private static readonly object _lock; private static bool _disposed; @@ -83,8 +80,6 @@ namespace ARMeilleure.Translation.PTC _loggerEvent = new AutoResetEvent(false); - _basePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), BaseDir); - _lock = new object(); _disposed = false; @@ -130,8 +125,8 @@ namespace ARMeilleure.Translation.PTC if (enabled) { - string workPathActual = Path.Combine(_basePath, "games", TitleIdText, "cache", "cpu", ActualDir); - string workPathBackup = Path.Combine(_basePath, "games", TitleIdText, "cache", "cpu", BackupDir); + string workPathActual = Path.Combine(AppDataManager.GamesDirPath, TitleIdText, "cache", "cpu", ActualDir); + string workPathBackup = Path.Combine(AppDataManager.GamesDirPath, TitleIdText, "cache", "cpu", BackupDir); if (!Directory.Exists(workPathActual)) { diff --git a/Ryujinx.Common/Configuration/AppDataManager.cs b/Ryujinx.Common/Configuration/AppDataManager.cs new file mode 100644 index 000000000..6630026f0 --- /dev/null +++ b/Ryujinx.Common/Configuration/AppDataManager.cs @@ -0,0 +1,69 @@ +using Ryujinx.Common.Logging; +using System; +using System.IO; + +namespace Ryujinx.Common.Configuration +{ + public static class AppDataManager + { + private static readonly string _defaultBaseDirPath; + + private const string DefaultBaseDir = "Ryujinx"; + + // The following 3 are always part of Base Directory + private const string GamesDir = "games"; + private const string ProfilesDir = "profiles"; + private const string KeysDir = "system"; + + public static bool IsCustomBasePath { get; private set; } + public static string BaseDirPath { get; private set; } + public static string GamesDirPath { get; private set; } + public static string ProfilesDirPath { get; private set; } + public static string KeysDirPath { get; private set; } + public static string KeysDirPathAlt { get; } + + public const string DefaultNandDir = "bis"; + public const string DefaultSdcardDir = "sdcard"; + private const string DefaultModsDir = "mods"; + + public static string CustomModsPath { get; set; } + public static string CustomNandPath { get; set; } // TODO: Actually implement this into VFS + public static string CustomSdCardPath { get; set; } // TODO: Actually implement this into VFS + + static AppDataManager() + { + _defaultBaseDirPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), DefaultBaseDir); + KeysDirPathAlt = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".switch"); + } + + public static void Initialize(string baseDirPath) + { + BaseDirPath = _defaultBaseDirPath; + + if (baseDirPath != null && baseDirPath != _defaultBaseDirPath) + { + if (!Directory.Exists(baseDirPath)) + { + Logger.Error?.Print(LogClass.Application, $"Custom Data Directory '{baseDirPath}' does not exist. Using defaults..."); + } + else + { + BaseDirPath = baseDirPath; + IsCustomBasePath = true; + } + } + + SetupBasePaths(); + } + + private static void SetupBasePaths() + { + Directory.CreateDirectory(BaseDirPath); + Directory.CreateDirectory(GamesDirPath = Path.Combine(BaseDirPath, GamesDir)); + Directory.CreateDirectory(ProfilesDirPath = Path.Combine(BaseDirPath, ProfilesDir)); + Directory.CreateDirectory(KeysDirPath = Path.Combine(BaseDirPath, KeysDir)); + } + + public static string GetModsPath() => CustomModsPath ?? Directory.CreateDirectory(Path.Combine(BaseDirPath, DefaultModsDir)).FullName; + } +} \ No newline at end of file diff --git a/Ryujinx.Common/Configuration/ConfigurationState.cs b/Ryujinx.Common/Configuration/ConfigurationState.cs index 489382cde..7f79dd6e1 100644 --- a/Ryujinx.Common/Configuration/ConfigurationState.cs +++ b/Ryujinx.Common/Configuration/ConfigurationState.cs @@ -750,7 +750,7 @@ namespace Ryujinx.Configuration { ToFileFormat().SaveConfig(configurationFilePath); - Common.Logging.Logger.Warning?.Print(LogClass.Application, "Configuration file has been updated!"); + Common.Logging.Logger.Notice.Print(LogClass.Application, $"Configuration file updated to version {ConfigurationFileFormat.CurrentVersion}"); } } diff --git a/Ryujinx.Common/Logging/Logger.cs b/Ryujinx.Common/Logging/Logger.cs index 9246368c4..e41eaf535 100644 --- a/Ryujinx.Common/Logging/Logger.cs +++ b/Ryujinx.Common/Logging/Logger.cs @@ -112,6 +112,11 @@ namespace Ryujinx.Common.Logging AsyncLogTargetOverflowAction.Discard)); Notice = new Log(LogLevel.Notice); + + // Enable important log levels before configuration is loaded + Error = new Log(LogLevel.Error); + Warning = new Log(LogLevel.Warning); + Info = new Log(LogLevel.Info); } public static void RestartTime() diff --git a/Ryujinx.HLE/FileSystem/VirtualFileSystem.cs b/Ryujinx.HLE/FileSystem/VirtualFileSystem.cs index 588909953..a95c9c0f5 100644 --- a/Ryujinx.HLE/FileSystem/VirtualFileSystem.cs +++ b/Ryujinx.HLE/FileSystem/VirtualFileSystem.cs @@ -4,6 +4,7 @@ using LibHac.Fs; using LibHac.FsService; using LibHac.FsSystem; using LibHac.Spl; +using Ryujinx.Common.Configuration; using Ryujinx.HLE.FileSystem.Content; using Ryujinx.HLE.HOS; using System; @@ -13,11 +14,8 @@ namespace Ryujinx.HLE.FileSystem { public class VirtualFileSystem : IDisposable { - public const string BasePath = "Ryujinx"; - public const string NandPath = "bis"; - public const string SdCardPath = "sdcard"; - public const string SystemPath = "system"; - public const string ModsPath = "mods"; + public const string NandPath = AppDataManager.DefaultNandDir; + public const string SdCardPath = AppDataManager.DefaultSdcardDir; public static string SafeNandPath = Path.Combine(NandPath, "safe"); public static string SystemNandPath = Path.Combine(NandPath, "system"); @@ -77,20 +75,10 @@ namespace Ryujinx.HLE.FileSystem return fullPath; } - public string GetBaseModsPath() - { - var baseModsDir = Path.Combine(GetBasePath(), "mods"); - ModLoader.EnsureBaseDirStructure(baseModsDir); - - return baseModsDir; - } - - public string GetSdCardPath() => MakeFullPath(SdCardPath); - + internal string GetBasePath() => AppDataManager.BaseDirPath; + internal string GetSdCardPath() => MakeFullPath(SdCardPath); public string GetNandPath() => MakeFullPath(NandPath); - public string GetSystemPath() => MakeFullPath(SystemPath); - internal string GetSavePath(ServiceCtx context, SaveInfo saveInfo, bool isDirectory = true) { string saveUserPath = ""; @@ -207,13 +195,6 @@ namespace Ryujinx.HLE.FileSystem return new DriveInfo(Path.GetPathRoot(GetBasePath())); } - public string GetBasePath() - { - string appDataPath = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData); - - return Path.Combine(appDataPath, BasePath); - } - public void Reload() { ReloadKeySet(); @@ -245,10 +226,12 @@ namespace Ryujinx.HLE.FileSystem string titleKeyFile = null; string consoleKeyFile = null; - string home = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile); + if (!AppDataManager.IsCustomBasePath) + { + LoadSetAtPath(AppDataManager.KeysDirPathAlt); + } - LoadSetAtPath(Path.Combine(home, ".switch")); - LoadSetAtPath(GetSystemPath()); + LoadSetAtPath(AppDataManager.KeysDirPath); void LoadSetAtPath(string basePath) { diff --git a/Ryujinx.HLE/HOS/ApplicationLoader.cs b/Ryujinx.HLE/HOS/ApplicationLoader.cs index b6e17b7b5..b52678de5 100644 --- a/Ryujinx.HLE/HOS/ApplicationLoader.cs +++ b/Ryujinx.HLE/HOS/ApplicationLoader.cs @@ -69,7 +69,7 @@ namespace Ryujinx.HLE.HOS Npdm metaData = ReadNpdm(codeFs); - _fileSystem.ModLoader.CollectMods(TitleId, _fileSystem.GetBaseModsPath()); + _fileSystem.ModLoader.CollectMods(TitleId, _fileSystem.ModLoader.GetModsBasePath()); if (TitleId != 0) { @@ -224,7 +224,7 @@ namespace Ryujinx.HLE.HOS IFileSystem codeFs = null; // Load Update - string titleUpdateMetadataPath = Path.Combine(_fileSystem.GetBasePath(), "games", mainNca.Header.TitleId.ToString("x16"), "updates.json"); + string titleUpdateMetadataPath = Path.Combine(AppDataManager.GamesDirPath, mainNca.Header.TitleId.ToString("x16"), "updates.json"); if (File.Exists(titleUpdateMetadataPath)) { @@ -261,7 +261,7 @@ namespace Ryujinx.HLE.HOS } // Load Aoc - string titleAocMetadataPath = Path.Combine(_fileSystem.GetBasePath(), "games", mainNca.Header.TitleId.ToString("x16"), "dlc.json"); + string titleAocMetadataPath = Path.Combine(AppDataManager.GamesDirPath, mainNca.Header.TitleId.ToString("x16"), "dlc.json"); if (File.Exists(titleAocMetadataPath)) { @@ -310,7 +310,7 @@ namespace Ryujinx.HLE.HOS Npdm metaData = ReadNpdm(codeFs); - _fileSystem.ModLoader.CollectMods(TitleId, _fileSystem.GetBaseModsPath()); + _fileSystem.ModLoader.CollectMods(TitleId, _fileSystem.ModLoader.GetModsBasePath()); if (controlNca != null) { diff --git a/Ryujinx.HLE/HOS/ModLoader.cs b/Ryujinx.HLE/HOS/ModLoader.cs index 867d120f4..786484aea 100644 --- a/Ryujinx.HLE/HOS/ModLoader.cs +++ b/Ryujinx.HLE/HOS/ModLoader.cs @@ -2,6 +2,7 @@ using LibHac.Common; using LibHac.Fs; using LibHac.FsSystem; using LibHac.FsSystem.RomFs; +using Ryujinx.Common.Configuration; using Ryujinx.Common.Logging; using Ryujinx.HLE.Loaders.Mods; using Ryujinx.HLE.Loaders.Executables; @@ -105,15 +106,18 @@ namespace Ryujinx.HLE.HOS private static bool StrEquals(string s1, string s2) => string.Equals(s1, s2, StringComparison.OrdinalIgnoreCase); - public void EnsureBaseDirStructure(string modsBasePath) + public string GetModsBasePath() => EnsureBaseDirStructure(AppDataManager.GetModsPath()); + + private string EnsureBaseDirStructure(string modsBasePath) { var modsDir = new DirectoryInfo(modsBasePath); - modsDir.Create(); modsDir.CreateSubdirectory(AmsContentsDir); modsDir.CreateSubdirectory(AmsNsoPatchDir); modsDir.CreateSubdirectory(AmsNroPatchDir); // modsDir.CreateSubdirectory(AmsKipPatchDir); // uncomment when KIPs are supported + + return modsDir.FullName; } private static DirectoryInfo FindTitleDir(DirectoryInfo contentsDir, string titleId) diff --git a/Ryujinx/Program.cs b/Ryujinx/Program.cs index 0b55d6f8e..5320a1eb6 100644 --- a/Ryujinx/Program.cs +++ b/Ryujinx/Program.cs @@ -1,5 +1,6 @@ using ARMeilleure.Translation.PTC; using Gtk; +using Ryujinx.Common.Configuration; using Ryujinx.Common.Logging; using Ryujinx.Common.SystemInfo; using Ryujinx.Configuration; @@ -20,6 +21,29 @@ namespace Ryujinx static void Main(string[] args) { + // Parse Arguments + string launchPath = null; + string baseDirPath = null; + for (int i = 0; i < args.Length; ++i) + { + string arg = args[i]; + + if (arg == "-r" || arg == "--root-data-dir") + { + if (i + 1 >= args.Length) + { + Logger.Error?.Print(LogClass.Application, $"Invalid option '{arg}'"); + continue; + } + + baseDirPath = args[++i]; + } + else if (launchPath == null) + { + launchPath = arg; + } + } + Toolkit.Init(new ToolkitOptions { Backend = PlatformBackend.PreferNative, @@ -38,6 +62,9 @@ namespace Ryujinx AppDomain.CurrentDomain.UnhandledException += (object sender, UnhandledExceptionEventArgs e) => ProcessUnhandledException(e.ExceptionObject as Exception, e.IsTerminating); AppDomain.CurrentDomain.ProcessExit += (object sender, EventArgs e) => ProgramExit(); + // Setup base data directory + AppDataManager.Initialize(baseDirPath); + // Initialize the configuration ConfigurationState.Initialize(); @@ -47,9 +74,8 @@ namespace Ryujinx // Initialize Discord integration DiscordIntegrationModule.Initialize(); - string localConfigurationPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Config.json"); - string globalBasePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "Ryujinx"); - string globalConfigurationPath = Path.Combine(globalBasePath, "Config.json"); + string localConfigurationPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Config.json"); + string appDataConfigurationPath = Path.Combine(AppDataManager.BaseDirPath, "Config.json"); // Now load the configuration as the other subsystems are now registered if (File.Exists(localConfigurationPath)) @@ -60,24 +86,21 @@ namespace Ryujinx ConfigurationState.Instance.Load(configurationFileFormat, ConfigurationPath); } - else if (File.Exists(globalConfigurationPath)) + else if (File.Exists(appDataConfigurationPath)) { - ConfigurationPath = globalConfigurationPath; + ConfigurationPath = appDataConfigurationPath; - ConfigurationFileFormat configurationFileFormat = ConfigurationFileFormat.Load(globalConfigurationPath); + ConfigurationFileFormat configurationFileFormat = ConfigurationFileFormat.Load(appDataConfigurationPath); ConfigurationState.Instance.Load(configurationFileFormat, ConfigurationPath); } else { // No configuration, we load the default values and save it on disk - ConfigurationPath = globalConfigurationPath; - - // Make sure to create the Ryujinx directory if needed. - Directory.CreateDirectory(globalBasePath); + ConfigurationPath = appDataConfigurationPath; ConfigurationState.Instance.LoadDefault(); - ConfigurationState.Instance.ToFileFormat().SaveConfig(globalConfigurationPath); + ConfigurationState.Instance.ToFileFormat().SaveConfig(appDataConfigurationPath); } PrintSystemInfo(); @@ -86,9 +109,9 @@ namespace Ryujinx Application.Init(); - string globalProdKeysPath = Path.Combine(globalBasePath, "system", "prod.keys"); - string userProfilePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".switch", "prod.keys"); - if (!File.Exists(globalProdKeysPath) && !File.Exists(userProfilePath) && !Migration.IsMigrationNeeded()) + bool hasGlobalProdKeys = File.Exists(Path.Combine(AppDataManager.KeysDirPath, "prod.keys")); + bool hasAltProdKeys = !AppDataManager.IsCustomBasePath && File.Exists(Path.Combine(AppDataManager.KeysDirPathAlt, "prod.keys")); + if (!hasGlobalProdKeys && !hasAltProdKeys && !Migration.IsMigrationNeeded()) { GtkDialog.CreateWarningDialog("Key file was not found", "Please refer to `KEYS.md` for more info"); } @@ -96,9 +119,9 @@ namespace Ryujinx MainWindow mainWindow = new MainWindow(); mainWindow.Show(); - if (args.Length == 1) + if (launchPath != null) { - mainWindow.LoadApplication(args[0]); + mainWindow.LoadApplication(launchPath); } Application.Run(); @@ -114,6 +137,11 @@ namespace Ryujinx var enabledLogs = Logger.GetEnabledLevels(); Logger.Notice.Print(LogClass.Application, $"Logs Enabled: {(enabledLogs.Count == 0 ? "" : string.Join(", ", enabledLogs))}"); + + if (AppDataManager.IsCustomBasePath) + { + Logger.Notice.Print(LogClass.Application, $"Custom Data Directory: {AppDataManager.BaseDirPath}"); + } } private static void ProcessUnhandledException(Exception e, bool isTerminating) diff --git a/Ryujinx/Ui/ApplicationLibrary.cs b/Ryujinx/Ui/ApplicationLibrary.cs index e20a42920..742dcc073 100644 --- a/Ryujinx/Ui/ApplicationLibrary.cs +++ b/Ryujinx/Ui/ApplicationLibrary.cs @@ -480,7 +480,7 @@ namespace Ryujinx.Ui internal static ApplicationMetadata LoadAndSaveMetaData(string titleId, Action modifyFunction = null) { - string metadataFolder = Path.Combine(_virtualFileSystem.GetBasePath(), "games", titleId, "gui"); + string metadataFolder = Path.Combine(AppDataManager.GamesDirPath, titleId, "gui"); string metadataFile = Path.Combine(metadataFolder, "metadata.json"); ApplicationMetadata appMetadata; @@ -618,7 +618,7 @@ namespace Ryujinx.Ui private static bool IsUpdateApplied(string titleId, out string version) { - string jsonPath = Path.Combine(_virtualFileSystem.GetBasePath(), "games", titleId, "updates.json"); + string jsonPath = Path.Combine(AppDataManager.GamesDirPath, titleId, "updates.json"); if (File.Exists(jsonPath)) { diff --git a/Ryujinx/Ui/ControllerWindow.cs b/Ryujinx/Ui/ControllerWindow.cs index 9518ba98d..1d879eb59 100644 --- a/Ryujinx/Ui/ControllerWindow.cs +++ b/Ryujinx/Ui/ControllerWindow.cs @@ -1,5 +1,6 @@ using Gtk; using OpenTK.Input; +using Ryujinx.Common.Configuration; using Ryujinx.Common.Configuration.Hid; using Ryujinx.Common.Utilities; using Ryujinx.Configuration; @@ -602,7 +603,7 @@ namespace Ryujinx.Ui private string GetProfileBasePath() { - string path = System.IO.Path.Combine(_virtualFileSystem.GetBasePath(), "profiles"); + string path = AppDataManager.ProfilesDirPath; if (_inputDevice.ActiveId.StartsWith("keyboard")) { diff --git a/Ryujinx/Ui/DlcWindow.cs b/Ryujinx/Ui/DlcWindow.cs index 3e57c5790..09ff9afcb 100644 --- a/Ryujinx/Ui/DlcWindow.cs +++ b/Ryujinx/Ui/DlcWindow.cs @@ -38,7 +38,7 @@ namespace Ryujinx.Ui _titleId = titleId; _virtualFileSystem = virtualFileSystem; - _dlcJsonPath = System.IO.Path.Combine(virtualFileSystem.GetBasePath(), "games", _titleId, "dlc.json"); + _dlcJsonPath = System.IO.Path.Combine(AppDataManager.GamesDirPath, _titleId, "dlc.json"); _baseTitleInfoLabel.Text = $"DLC Available for {titleName} [{titleId.ToUpper()}]"; try diff --git a/Ryujinx/Ui/GameTableContextMenu.cs b/Ryujinx/Ui/GameTableContextMenu.cs index afa2182d0..93306b576 100644 --- a/Ryujinx/Ui/GameTableContextMenu.cs +++ b/Ryujinx/Ui/GameTableContextMenu.cs @@ -339,7 +339,7 @@ namespace Ryujinx.Ui return; } - string titleUpdateMetadataPath = System.IO.Path.Combine(_virtualFileSystem.GetBasePath(), "games", mainNca.Header.TitleId.ToString("x16"), "updates.json"); + string titleUpdateMetadataPath = System.IO.Path.Combine(AppDataManager.GamesDirPath, mainNca.Header.TitleId.ToString("x16"), "updates.json"); if (File.Exists(titleUpdateMetadataPath)) { @@ -614,7 +614,7 @@ namespace Ryujinx.Ui { string titleId = _gameTableStore.GetValue(_rowIter, 2).ToString().Split("\n")[1].ToLower(); - var modsBasePath = _virtualFileSystem.GetBaseModsPath(); + var modsBasePath = _virtualFileSystem.ModLoader.GetModsBasePath(); var titleModsPath = _virtualFileSystem.ModLoader.GetTitleDir(modsBasePath, titleId); Process.Start(new ProcessStartInfo @@ -643,7 +643,7 @@ namespace Ryujinx.Ui private void OpenPtcDir_Clicked(object sender, EventArgs args) { string titleId = _gameTableStore.GetValue(_rowIter, 2).ToString().Split("\n")[1].ToLower(); - string ptcDir = System.IO.Path.Combine(_virtualFileSystem.GetBasePath(), "games", titleId, "cache", "cpu"); + string ptcDir = System.IO.Path.Combine(AppDataManager.GamesDirPath, titleId, "cache", "cpu"); string mainPath = System.IO.Path.Combine(ptcDir, "0"); string backupPath = System.IO.Path.Combine(ptcDir, "1"); @@ -668,8 +668,8 @@ namespace Ryujinx.Ui string[] tableEntry = _gameTableStore.GetValue(_rowIter, 2).ToString().Split("\n"); string titleId = tableEntry[1].ToLower(); - DirectoryInfo mainDir = new DirectoryInfo(System.IO.Path.Combine(_virtualFileSystem.GetBasePath(), "games", titleId, "cache", "cpu", "0")); - DirectoryInfo backupDir = new DirectoryInfo(System.IO.Path.Combine(_virtualFileSystem.GetBasePath(), "games", titleId, "cache", "cpu", "1")); + DirectoryInfo mainDir = new DirectoryInfo(System.IO.Path.Combine(AppDataManager.GamesDirPath, titleId, "cache", "cpu", "0")); + DirectoryInfo backupDir = new DirectoryInfo(System.IO.Path.Combine(AppDataManager.GamesDirPath, titleId, "cache", "cpu", "1")); MessageDialog warningDialog = new MessageDialog(null, DialogFlags.Modal, MessageType.Warning, ButtonsType.YesNo, null) { diff --git a/Ryujinx/Ui/MainWindow.cs b/Ryujinx/Ui/MainWindow.cs index d2b303e42..0501b96e5 100644 --- a/Ryujinx/Ui/MainWindow.cs +++ b/Ryujinx/Ui/MainWindow.cs @@ -3,6 +3,7 @@ using Gtk; using LibHac.Common; using LibHac.Ns; using Ryujinx.Audio; +using Ryujinx.Common.Configuration; using Ryujinx.Common.Logging; using Ryujinx.Common.System; using Ryujinx.Configuration; @@ -873,7 +874,7 @@ namespace Ryujinx.Ui { Process.Start(new ProcessStartInfo() { - FileName = _virtualFileSystem.GetBasePath(), + FileName = AppDataManager.BaseDirPath, UseShellExecute = true, Verb = "open" }); @@ -1113,7 +1114,7 @@ namespace Ryujinx.Ui private void Update_Pressed(object sender, EventArgs args) { - string ryuUpdater = System.IO.Path.Combine(_virtualFileSystem.GetBasePath(), "RyuUpdater.exe"); + string ryuUpdater = System.IO.Path.Combine(AppDataManager.BaseDirPath, "RyuUpdater.exe"); try { diff --git a/Ryujinx/Ui/Migration.cs b/Ryujinx/Ui/Migration.cs index 20d810647..a7a49105a 100644 --- a/Ryujinx/Ui/Migration.cs +++ b/Ryujinx/Ui/Migration.cs @@ -1,5 +1,6 @@ using Gtk; using LibHac; +using Ryujinx.Common.Configuration; using Ryujinx.HLE.FileSystem; using System; using System.IO; @@ -175,6 +176,8 @@ namespace Ryujinx.Ui public static bool IsMigrationNeeded() { + if (AppDataManager.IsCustomBasePath) return false; + string appDataPath = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData); string oldBasePath = Path.Combine(appDataPath, "RyuFs"); diff --git a/Ryujinx/Ui/TitleUpdateWindow.cs b/Ryujinx/Ui/TitleUpdateWindow.cs index 538f1d2cf..35fdf8728 100644 --- a/Ryujinx/Ui/TitleUpdateWindow.cs +++ b/Ryujinx/Ui/TitleUpdateWindow.cs @@ -41,7 +41,7 @@ namespace Ryujinx.Ui _titleId = titleId; _virtualFileSystem = virtualFileSystem; - _updateJsonPath = System.IO.Path.Combine(_virtualFileSystem.GetBasePath(), "games", _titleId, "updates.json"); + _updateJsonPath = System.IO.Path.Combine(AppDataManager.GamesDirPath, _titleId, "updates.json"); _radioButtonToPathDictionary = new Dictionary(); try