mirror of
https://github.com/ryujinx-mirror/ryujinx.git
synced 2024-11-25 11:35:12 +00:00
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,6 +1,7 @@
|
||||||
using ARMeilleure.CodeGen;
|
using ARMeilleure.CodeGen;
|
||||||
using ARMeilleure.CodeGen.Unwinding;
|
using ARMeilleure.CodeGen.Unwinding;
|
||||||
using ARMeilleure.Memory;
|
using ARMeilleure.Memory;
|
||||||
|
using Ryujinx.Common.Configuration;
|
||||||
using Ryujinx.Common.Logging;
|
using Ryujinx.Common.Logging;
|
||||||
using System;
|
using System;
|
||||||
using System.Buffers.Binary;
|
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 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 ActualDir = "0";
|
||||||
private const string BackupDir = "1";
|
private const string BackupDir = "1";
|
||||||
|
|
||||||
|
@ -49,8 +48,6 @@ namespace ARMeilleure.Translation.PTC
|
||||||
|
|
||||||
private static readonly AutoResetEvent _loggerEvent;
|
private static readonly AutoResetEvent _loggerEvent;
|
||||||
|
|
||||||
private static readonly string _basePath;
|
|
||||||
|
|
||||||
private static readonly object _lock;
|
private static readonly object _lock;
|
||||||
|
|
||||||
private static bool _disposed;
|
private static bool _disposed;
|
||||||
|
@ -83,8 +80,6 @@ namespace ARMeilleure.Translation.PTC
|
||||||
|
|
||||||
_loggerEvent = new AutoResetEvent(false);
|
_loggerEvent = new AutoResetEvent(false);
|
||||||
|
|
||||||
_basePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), BaseDir);
|
|
||||||
|
|
||||||
_lock = new object();
|
_lock = new object();
|
||||||
|
|
||||||
_disposed = false;
|
_disposed = false;
|
||||||
|
@ -130,8 +125,8 @@ namespace ARMeilleure.Translation.PTC
|
||||||
|
|
||||||
if (enabled)
|
if (enabled)
|
||||||
{
|
{
|
||||||
string workPathActual = Path.Combine(_basePath, "games", TitleIdText, "cache", "cpu", ActualDir);
|
string workPathActual = Path.Combine(AppDataManager.GamesDirPath, TitleIdText, "cache", "cpu", ActualDir);
|
||||||
string workPathBackup = Path.Combine(_basePath, "games", TitleIdText, "cache", "cpu", BackupDir);
|
string workPathBackup = Path.Combine(AppDataManager.GamesDirPath, TitleIdText, "cache", "cpu", BackupDir);
|
||||||
|
|
||||||
if (!Directory.Exists(workPathActual))
|
if (!Directory.Exists(workPathActual))
|
||||||
{
|
{
|
||||||
|
|
69
Ryujinx.Common/Configuration/AppDataManager.cs
Normal file
69
Ryujinx.Common/Configuration/AppDataManager.cs
Normal file
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -750,7 +750,7 @@ namespace Ryujinx.Configuration
|
||||||
{
|
{
|
||||||
ToFileFormat().SaveConfig(configurationFilePath);
|
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}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -112,6 +112,11 @@ namespace Ryujinx.Common.Logging
|
||||||
AsyncLogTargetOverflowAction.Discard));
|
AsyncLogTargetOverflowAction.Discard));
|
||||||
|
|
||||||
Notice = new Log(LogLevel.Notice);
|
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()
|
public static void RestartTime()
|
||||||
|
|
|
@ -4,6 +4,7 @@ using LibHac.Fs;
|
||||||
using LibHac.FsService;
|
using LibHac.FsService;
|
||||||
using LibHac.FsSystem;
|
using LibHac.FsSystem;
|
||||||
using LibHac.Spl;
|
using LibHac.Spl;
|
||||||
|
using Ryujinx.Common.Configuration;
|
||||||
using Ryujinx.HLE.FileSystem.Content;
|
using Ryujinx.HLE.FileSystem.Content;
|
||||||
using Ryujinx.HLE.HOS;
|
using Ryujinx.HLE.HOS;
|
||||||
using System;
|
using System;
|
||||||
|
@ -13,11 +14,8 @@ namespace Ryujinx.HLE.FileSystem
|
||||||
{
|
{
|
||||||
public class VirtualFileSystem : IDisposable
|
public class VirtualFileSystem : IDisposable
|
||||||
{
|
{
|
||||||
public const string BasePath = "Ryujinx";
|
public const string NandPath = AppDataManager.DefaultNandDir;
|
||||||
public const string NandPath = "bis";
|
public const string SdCardPath = AppDataManager.DefaultSdcardDir;
|
||||||
public const string SdCardPath = "sdcard";
|
|
||||||
public const string SystemPath = "system";
|
|
||||||
public const string ModsPath = "mods";
|
|
||||||
|
|
||||||
public static string SafeNandPath = Path.Combine(NandPath, "safe");
|
public static string SafeNandPath = Path.Combine(NandPath, "safe");
|
||||||
public static string SystemNandPath = Path.Combine(NandPath, "system");
|
public static string SystemNandPath = Path.Combine(NandPath, "system");
|
||||||
|
@ -77,20 +75,10 @@ namespace Ryujinx.HLE.FileSystem
|
||||||
return fullPath;
|
return fullPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
public string GetBaseModsPath()
|
internal string GetBasePath() => AppDataManager.BaseDirPath;
|
||||||
{
|
internal string GetSdCardPath() => MakeFullPath(SdCardPath);
|
||||||
var baseModsDir = Path.Combine(GetBasePath(), "mods");
|
|
||||||
ModLoader.EnsureBaseDirStructure(baseModsDir);
|
|
||||||
|
|
||||||
return baseModsDir;
|
|
||||||
}
|
|
||||||
|
|
||||||
public string GetSdCardPath() => MakeFullPath(SdCardPath);
|
|
||||||
|
|
||||||
public string GetNandPath() => MakeFullPath(NandPath);
|
public string GetNandPath() => MakeFullPath(NandPath);
|
||||||
|
|
||||||
public string GetSystemPath() => MakeFullPath(SystemPath);
|
|
||||||
|
|
||||||
internal string GetSavePath(ServiceCtx context, SaveInfo saveInfo, bool isDirectory = true)
|
internal string GetSavePath(ServiceCtx context, SaveInfo saveInfo, bool isDirectory = true)
|
||||||
{
|
{
|
||||||
string saveUserPath = "";
|
string saveUserPath = "";
|
||||||
|
@ -207,13 +195,6 @@ namespace Ryujinx.HLE.FileSystem
|
||||||
return new DriveInfo(Path.GetPathRoot(GetBasePath()));
|
return new DriveInfo(Path.GetPathRoot(GetBasePath()));
|
||||||
}
|
}
|
||||||
|
|
||||||
public string GetBasePath()
|
|
||||||
{
|
|
||||||
string appDataPath = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
|
|
||||||
|
|
||||||
return Path.Combine(appDataPath, BasePath);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Reload()
|
public void Reload()
|
||||||
{
|
{
|
||||||
ReloadKeySet();
|
ReloadKeySet();
|
||||||
|
@ -245,10 +226,12 @@ namespace Ryujinx.HLE.FileSystem
|
||||||
string titleKeyFile = null;
|
string titleKeyFile = null;
|
||||||
string consoleKeyFile = null;
|
string consoleKeyFile = null;
|
||||||
|
|
||||||
string home = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile);
|
if (!AppDataManager.IsCustomBasePath)
|
||||||
|
{
|
||||||
|
LoadSetAtPath(AppDataManager.KeysDirPathAlt);
|
||||||
|
}
|
||||||
|
|
||||||
LoadSetAtPath(Path.Combine(home, ".switch"));
|
LoadSetAtPath(AppDataManager.KeysDirPath);
|
||||||
LoadSetAtPath(GetSystemPath());
|
|
||||||
|
|
||||||
void LoadSetAtPath(string basePath)
|
void LoadSetAtPath(string basePath)
|
||||||
{
|
{
|
||||||
|
|
|
@ -69,7 +69,7 @@ namespace Ryujinx.HLE.HOS
|
||||||
|
|
||||||
Npdm metaData = ReadNpdm(codeFs);
|
Npdm metaData = ReadNpdm(codeFs);
|
||||||
|
|
||||||
_fileSystem.ModLoader.CollectMods(TitleId, _fileSystem.GetBaseModsPath());
|
_fileSystem.ModLoader.CollectMods(TitleId, _fileSystem.ModLoader.GetModsBasePath());
|
||||||
|
|
||||||
if (TitleId != 0)
|
if (TitleId != 0)
|
||||||
{
|
{
|
||||||
|
@ -224,7 +224,7 @@ namespace Ryujinx.HLE.HOS
|
||||||
IFileSystem codeFs = null;
|
IFileSystem codeFs = null;
|
||||||
|
|
||||||
// Load Update
|
// 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))
|
if (File.Exists(titleUpdateMetadataPath))
|
||||||
{
|
{
|
||||||
|
@ -261,7 +261,7 @@ namespace Ryujinx.HLE.HOS
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load Aoc
|
// 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))
|
if (File.Exists(titleAocMetadataPath))
|
||||||
{
|
{
|
||||||
|
@ -310,7 +310,7 @@ namespace Ryujinx.HLE.HOS
|
||||||
|
|
||||||
Npdm metaData = ReadNpdm(codeFs);
|
Npdm metaData = ReadNpdm(codeFs);
|
||||||
|
|
||||||
_fileSystem.ModLoader.CollectMods(TitleId, _fileSystem.GetBaseModsPath());
|
_fileSystem.ModLoader.CollectMods(TitleId, _fileSystem.ModLoader.GetModsBasePath());
|
||||||
|
|
||||||
if (controlNca != null)
|
if (controlNca != null)
|
||||||
{
|
{
|
||||||
|
|
|
@ -2,6 +2,7 @@ using LibHac.Common;
|
||||||
using LibHac.Fs;
|
using LibHac.Fs;
|
||||||
using LibHac.FsSystem;
|
using LibHac.FsSystem;
|
||||||
using LibHac.FsSystem.RomFs;
|
using LibHac.FsSystem.RomFs;
|
||||||
|
using Ryujinx.Common.Configuration;
|
||||||
using Ryujinx.Common.Logging;
|
using Ryujinx.Common.Logging;
|
||||||
using Ryujinx.HLE.Loaders.Mods;
|
using Ryujinx.HLE.Loaders.Mods;
|
||||||
using Ryujinx.HLE.Loaders.Executables;
|
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);
|
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);
|
var modsDir = new DirectoryInfo(modsBasePath);
|
||||||
modsDir.Create();
|
|
||||||
|
|
||||||
modsDir.CreateSubdirectory(AmsContentsDir);
|
modsDir.CreateSubdirectory(AmsContentsDir);
|
||||||
modsDir.CreateSubdirectory(AmsNsoPatchDir);
|
modsDir.CreateSubdirectory(AmsNsoPatchDir);
|
||||||
modsDir.CreateSubdirectory(AmsNroPatchDir);
|
modsDir.CreateSubdirectory(AmsNroPatchDir);
|
||||||
// modsDir.CreateSubdirectory(AmsKipPatchDir); // uncomment when KIPs are supported
|
// modsDir.CreateSubdirectory(AmsKipPatchDir); // uncomment when KIPs are supported
|
||||||
|
|
||||||
|
return modsDir.FullName;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static DirectoryInfo FindTitleDir(DirectoryInfo contentsDir, string titleId)
|
private static DirectoryInfo FindTitleDir(DirectoryInfo contentsDir, string titleId)
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
using ARMeilleure.Translation.PTC;
|
using ARMeilleure.Translation.PTC;
|
||||||
using Gtk;
|
using Gtk;
|
||||||
|
using Ryujinx.Common.Configuration;
|
||||||
using Ryujinx.Common.Logging;
|
using Ryujinx.Common.Logging;
|
||||||
using Ryujinx.Common.SystemInfo;
|
using Ryujinx.Common.SystemInfo;
|
||||||
using Ryujinx.Configuration;
|
using Ryujinx.Configuration;
|
||||||
|
@ -20,6 +21,29 @@ namespace Ryujinx
|
||||||
|
|
||||||
static void Main(string[] args)
|
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
|
Toolkit.Init(new ToolkitOptions
|
||||||
{
|
{
|
||||||
Backend = PlatformBackend.PreferNative,
|
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.UnhandledException += (object sender, UnhandledExceptionEventArgs e) => ProcessUnhandledException(e.ExceptionObject as Exception, e.IsTerminating);
|
||||||
AppDomain.CurrentDomain.ProcessExit += (object sender, EventArgs e) => ProgramExit();
|
AppDomain.CurrentDomain.ProcessExit += (object sender, EventArgs e) => ProgramExit();
|
||||||
|
|
||||||
|
// Setup base data directory
|
||||||
|
AppDataManager.Initialize(baseDirPath);
|
||||||
|
|
||||||
// Initialize the configuration
|
// Initialize the configuration
|
||||||
ConfigurationState.Initialize();
|
ConfigurationState.Initialize();
|
||||||
|
|
||||||
|
@ -47,9 +74,8 @@ namespace Ryujinx
|
||||||
// Initialize Discord integration
|
// Initialize Discord integration
|
||||||
DiscordIntegrationModule.Initialize();
|
DiscordIntegrationModule.Initialize();
|
||||||
|
|
||||||
string localConfigurationPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Config.json");
|
string localConfigurationPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Config.json");
|
||||||
string globalBasePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "Ryujinx");
|
string appDataConfigurationPath = Path.Combine(AppDataManager.BaseDirPath, "Config.json");
|
||||||
string globalConfigurationPath = Path.Combine(globalBasePath, "Config.json");
|
|
||||||
|
|
||||||
// Now load the configuration as the other subsystems are now registered
|
// Now load the configuration as the other subsystems are now registered
|
||||||
if (File.Exists(localConfigurationPath))
|
if (File.Exists(localConfigurationPath))
|
||||||
|
@ -60,24 +86,21 @@ namespace Ryujinx
|
||||||
|
|
||||||
ConfigurationState.Instance.Load(configurationFileFormat, ConfigurationPath);
|
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);
|
ConfigurationState.Instance.Load(configurationFileFormat, ConfigurationPath);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// No configuration, we load the default values and save it on disk
|
// No configuration, we load the default values and save it on disk
|
||||||
ConfigurationPath = globalConfigurationPath;
|
ConfigurationPath = appDataConfigurationPath;
|
||||||
|
|
||||||
// Make sure to create the Ryujinx directory if needed.
|
|
||||||
Directory.CreateDirectory(globalBasePath);
|
|
||||||
|
|
||||||
ConfigurationState.Instance.LoadDefault();
|
ConfigurationState.Instance.LoadDefault();
|
||||||
ConfigurationState.Instance.ToFileFormat().SaveConfig(globalConfigurationPath);
|
ConfigurationState.Instance.ToFileFormat().SaveConfig(appDataConfigurationPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
PrintSystemInfo();
|
PrintSystemInfo();
|
||||||
|
@ -86,9 +109,9 @@ namespace Ryujinx
|
||||||
|
|
||||||
Application.Init();
|
Application.Init();
|
||||||
|
|
||||||
string globalProdKeysPath = Path.Combine(globalBasePath, "system", "prod.keys");
|
bool hasGlobalProdKeys = File.Exists(Path.Combine(AppDataManager.KeysDirPath, "prod.keys"));
|
||||||
string userProfilePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".switch", "prod.keys");
|
bool hasAltProdKeys = !AppDataManager.IsCustomBasePath && File.Exists(Path.Combine(AppDataManager.KeysDirPathAlt, "prod.keys"));
|
||||||
if (!File.Exists(globalProdKeysPath) && !File.Exists(userProfilePath) && !Migration.IsMigrationNeeded())
|
if (!hasGlobalProdKeys && !hasAltProdKeys && !Migration.IsMigrationNeeded())
|
||||||
{
|
{
|
||||||
GtkDialog.CreateWarningDialog("Key file was not found", "Please refer to `KEYS.md` for more info");
|
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 mainWindow = new MainWindow();
|
||||||
mainWindow.Show();
|
mainWindow.Show();
|
||||||
|
|
||||||
if (args.Length == 1)
|
if (launchPath != null)
|
||||||
{
|
{
|
||||||
mainWindow.LoadApplication(args[0]);
|
mainWindow.LoadApplication(launchPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
Application.Run();
|
Application.Run();
|
||||||
|
@ -114,6 +137,11 @@ namespace Ryujinx
|
||||||
|
|
||||||
var enabledLogs = Logger.GetEnabledLevels();
|
var enabledLogs = Logger.GetEnabledLevels();
|
||||||
Logger.Notice.Print(LogClass.Application, $"Logs Enabled: {(enabledLogs.Count == 0 ? "<None>" : string.Join(", ", enabledLogs))}");
|
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)
|
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)
|
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");
|
string metadataFile = Path.Combine(metadataFolder, "metadata.json");
|
||||||
|
|
||||||
ApplicationMetadata appMetadata;
|
ApplicationMetadata appMetadata;
|
||||||
|
@ -618,7 +618,7 @@ namespace Ryujinx.Ui
|
||||||
|
|
||||||
private static bool IsUpdateApplied(string titleId, out string version)
|
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))
|
if (File.Exists(jsonPath))
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
using Gtk;
|
using Gtk;
|
||||||
using OpenTK.Input;
|
using OpenTK.Input;
|
||||||
|
using Ryujinx.Common.Configuration;
|
||||||
using Ryujinx.Common.Configuration.Hid;
|
using Ryujinx.Common.Configuration.Hid;
|
||||||
using Ryujinx.Common.Utilities;
|
using Ryujinx.Common.Utilities;
|
||||||
using Ryujinx.Configuration;
|
using Ryujinx.Configuration;
|
||||||
|
@ -602,7 +603,7 @@ namespace Ryujinx.Ui
|
||||||
|
|
||||||
private string GetProfileBasePath()
|
private string GetProfileBasePath()
|
||||||
{
|
{
|
||||||
string path = System.IO.Path.Combine(_virtualFileSystem.GetBasePath(), "profiles");
|
string path = AppDataManager.ProfilesDirPath;
|
||||||
|
|
||||||
if (_inputDevice.ActiveId.StartsWith("keyboard"))
|
if (_inputDevice.ActiveId.StartsWith("keyboard"))
|
||||||
{
|
{
|
||||||
|
|
|
@ -38,7 +38,7 @@ namespace Ryujinx.Ui
|
||||||
|
|
||||||
_titleId = titleId;
|
_titleId = titleId;
|
||||||
_virtualFileSystem = virtualFileSystem;
|
_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()}]";
|
_baseTitleInfoLabel.Text = $"DLC Available for {titleName} [{titleId.ToUpper()}]";
|
||||||
|
|
||||||
try
|
try
|
||||||
|
|
|
@ -339,7 +339,7 @@ namespace Ryujinx.Ui
|
||||||
return;
|
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))
|
if (File.Exists(titleUpdateMetadataPath))
|
||||||
{
|
{
|
||||||
|
@ -614,7 +614,7 @@ namespace Ryujinx.Ui
|
||||||
{
|
{
|
||||||
string titleId = _gameTableStore.GetValue(_rowIter, 2).ToString().Split("\n")[1].ToLower();
|
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);
|
var titleModsPath = _virtualFileSystem.ModLoader.GetTitleDir(modsBasePath, titleId);
|
||||||
|
|
||||||
Process.Start(new ProcessStartInfo
|
Process.Start(new ProcessStartInfo
|
||||||
|
@ -643,7 +643,7 @@ namespace Ryujinx.Ui
|
||||||
private void OpenPtcDir_Clicked(object sender, EventArgs args)
|
private void OpenPtcDir_Clicked(object sender, EventArgs args)
|
||||||
{
|
{
|
||||||
string titleId = _gameTableStore.GetValue(_rowIter, 2).ToString().Split("\n")[1].ToLower();
|
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 mainPath = System.IO.Path.Combine(ptcDir, "0");
|
||||||
string backupPath = System.IO.Path.Combine(ptcDir, "1");
|
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[] tableEntry = _gameTableStore.GetValue(_rowIter, 2).ToString().Split("\n");
|
||||||
string titleId = tableEntry[1].ToLower();
|
string titleId = tableEntry[1].ToLower();
|
||||||
|
|
||||||
DirectoryInfo mainDir = new DirectoryInfo(System.IO.Path.Combine(_virtualFileSystem.GetBasePath(), "games", titleId, "cache", "cpu", "0"));
|
DirectoryInfo mainDir = new DirectoryInfo(System.IO.Path.Combine(AppDataManager.GamesDirPath, titleId, "cache", "cpu", "0"));
|
||||||
DirectoryInfo backupDir = new DirectoryInfo(System.IO.Path.Combine(_virtualFileSystem.GetBasePath(), "games", titleId, "cache", "cpu", "1"));
|
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)
|
MessageDialog warningDialog = new MessageDialog(null, DialogFlags.Modal, MessageType.Warning, ButtonsType.YesNo, null)
|
||||||
{
|
{
|
||||||
|
|
|
@ -3,6 +3,7 @@ using Gtk;
|
||||||
using LibHac.Common;
|
using LibHac.Common;
|
||||||
using LibHac.Ns;
|
using LibHac.Ns;
|
||||||
using Ryujinx.Audio;
|
using Ryujinx.Audio;
|
||||||
|
using Ryujinx.Common.Configuration;
|
||||||
using Ryujinx.Common.Logging;
|
using Ryujinx.Common.Logging;
|
||||||
using Ryujinx.Common.System;
|
using Ryujinx.Common.System;
|
||||||
using Ryujinx.Configuration;
|
using Ryujinx.Configuration;
|
||||||
|
@ -873,7 +874,7 @@ namespace Ryujinx.Ui
|
||||||
{
|
{
|
||||||
Process.Start(new ProcessStartInfo()
|
Process.Start(new ProcessStartInfo()
|
||||||
{
|
{
|
||||||
FileName = _virtualFileSystem.GetBasePath(),
|
FileName = AppDataManager.BaseDirPath,
|
||||||
UseShellExecute = true,
|
UseShellExecute = true,
|
||||||
Verb = "open"
|
Verb = "open"
|
||||||
});
|
});
|
||||||
|
@ -1113,7 +1114,7 @@ namespace Ryujinx.Ui
|
||||||
|
|
||||||
private void Update_Pressed(object sender, EventArgs args)
|
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
|
try
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
using Gtk;
|
using Gtk;
|
||||||
using LibHac;
|
using LibHac;
|
||||||
|
using Ryujinx.Common.Configuration;
|
||||||
using Ryujinx.HLE.FileSystem;
|
using Ryujinx.HLE.FileSystem;
|
||||||
using System;
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
@ -175,6 +176,8 @@ namespace Ryujinx.Ui
|
||||||
|
|
||||||
public static bool IsMigrationNeeded()
|
public static bool IsMigrationNeeded()
|
||||||
{
|
{
|
||||||
|
if (AppDataManager.IsCustomBasePath) return false;
|
||||||
|
|
||||||
string appDataPath = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
|
string appDataPath = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
|
||||||
|
|
||||||
string oldBasePath = Path.Combine(appDataPath, "RyuFs");
|
string oldBasePath = Path.Combine(appDataPath, "RyuFs");
|
||||||
|
|
|
@ -41,7 +41,7 @@ namespace Ryujinx.Ui
|
||||||
|
|
||||||
_titleId = titleId;
|
_titleId = titleId;
|
||||||
_virtualFileSystem = virtualFileSystem;
|
_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>();
|
_radioButtonToPathDictionary = new Dictionary<RadioButton, string>();
|
||||||
|
|
||||||
try
|
try
|
||||||
|
|
Loading…
Reference in a new issue