Allow launching with custom data directories (#1505)
* Allow launching with custom data directories Don't load alternate keys when using custom directory * Address gdkchan's comments * Misc fixes to log levels Added more enabled log levels by default Moved successful config updation to Notice as 1. It's not a warning 2. Warnings could've been disabled by the config load and hence message would be lost
This commit is contained in:
parent
f3e12d5b02
commit
b9398f1f3a
15 changed files with 159 additions and 70 deletions
|
@ -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 ? "<None>" : string.Join(", ", enabledLogs))}");
|
||||
|
||||
if (AppDataManager.IsCustomBasePath)
|
||||
{
|
||||
Logger.Notice.Print(LogClass.Application, $"Custom Data Directory: {AppDataManager.BaseDirPath}");
|
||||
}
|
||||
}
|
||||
|
||||
private static void ProcessUnhandledException(Exception e, bool isTerminating)
|
||||
|
|
|
@ -480,7 +480,7 @@ namespace Ryujinx.Ui
|
|||
|
||||
internal static ApplicationMetadata LoadAndSaveMetaData(string titleId, Action<ApplicationMetadata> 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))
|
||||
{
|
||||
|
|
|
@ -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"))
|
||||
{
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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<RadioButton, string>();
|
||||
|
||||
try
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue