From 70fcba39de34fc211d09da12783898161724b0dc Mon Sep 17 00:00:00 2001 From: TSRBerry <20988865+TSRBerry@users.noreply.github.com> Date: Mon, 29 Jan 2024 19:58:18 +0100 Subject: [PATCH] Make config filename changable for releases & Log to Ryujinx directory if application directory is not writable (#4707) * Remove GetBaseApplicationDirectory() & Move logs directory to user base path We should assume the application directory might be write-protected. * Use Ryujinx.sh in Ryujinx.desktop This desktop file isn't really used right now, so this changes effectively nothing. * Use properties in ReleaseInformation.cs and add ConfigName property * Configure config filename in Github workflows * Add a separate config step for macOS Because they use BSD sed instead of GNU sed * Keep log directory at the old location for dev environments * Add FileSystemUtils since Directory.Move() doesn't work across filesystems Steal CopyDirectory code from https://learn.microsoft.com/en-us/dotnet/standard/io/how-to-copy-directories * Fix "Open Logs folder" button pointing to the wrong directory * Add execute permissions to Ryujinx.sh * Fix missing newlines * AppDataManager: Use FileSystemUtils.MoveDirectory() * Make dotnet format happy * Add a fallback for the logging directory --- .github/workflows/build.yml | 17 +++++- .github/workflows/release.yml | 2 + distribution/linux/Ryujinx.desktop | 2 +- distribution/linux/Ryujinx.sh | 2 +- src/Ryujinx.Ava/Modules/Updater/Updater.cs | 4 +- src/Ryujinx.Ava/Program.cs | 6 +- .../UI/ViewModels/MainWindowViewModel.cs | 9 ++- .../Configuration/AppDataManager.cs | 38 ++---------- .../Logging/Targets/FileLogTarget.cs | 60 +++++++++++++++---- src/Ryujinx.Common/ReleaseInformation.cs | 55 +++++------------ .../Utilities/FileSystemUtils.cs | 48 +++++++++++++++ src/Ryujinx.Headless.SDL2/Program.cs | 27 +++++++-- src/Ryujinx.SDL2.Common/SDL2Driver.cs | 5 +- .../App/ApplicationLibrary.cs | 3 +- .../Configuration/LoggerModule.cs | 19 +++++- .../Helper/FileAssociationHelper.cs | 4 +- src/Ryujinx/Modules/Updater/UpdateDialog.cs | 3 +- src/Ryujinx/Modules/Updater/Updater.cs | 4 +- src/Ryujinx/Program.cs | 6 +- src/Ryujinx/Ui/Helper/ThemeHelper.cs | 3 +- src/Ryujinx/Ui/MainWindow.cs | 7 ++- .../Ui/Widgets/GameTableContextMenu.cs | 2 +- 22 files changed, 209 insertions(+), 117 deletions(-) mode change 100644 => 100755 distribution/linux/Ryujinx.sh create mode 100644 src/Ryujinx.Common/Utilities/FileSystemUtils.cs diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index cf4fdf05..6124ae51 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -40,7 +40,7 @@ jobs: - uses: actions/setup-dotnet@v4 with: global-json-file: global.json - + - name: Overwrite csc problem matcher run: echo "::add-matcher::.github/csc.json" @@ -49,6 +49,16 @@ jobs: run: echo "result=$(git rev-parse --short "${{ github.sha }}")" >> $GITHUB_OUTPUT shell: bash + - name: Change config filename + run: sed -r --in-place 's/\%\%RYUJINX_CONFIG_FILE_NAME\%\%/PRConfig\.json/g;' src/Ryujinx.Common/ReleaseInformation.cs + shell: bash + if: github.event_name == 'pull_request' && matrix.os != 'macOS-latest' + + - name: Change config filename for macOS + run: sed -r -i '' 's/\%\%RYUJINX_CONFIG_FILE_NAME\%\%/PRConfig\.json/g;' src/Ryujinx.Common/ReleaseInformation.cs + shell: bash + if: github.event_name == 'pull_request' && matrix.os == 'macOS-latest' + - name: Build run: dotnet build -c "${{ matrix.configuration }}" -p:Version="${{ env.RYUJINX_BASE_VERSION }}" -p:SourceRevisionId="${{ steps.git_short_hash.outputs.result }}" -p:ExtraDefineConstants=DISABLE_UPDATER @@ -135,6 +145,11 @@ jobs: id: git_short_hash run: echo "result=$(git rev-parse --short "${{ github.sha }}")" >> $GITHUB_OUTPUT + - name: Change config filename + run: sed -r --in-place 's/\%\%RYUJINX_CONFIG_FILE_NAME\%\%/PRConfig\.json/g;' src/Ryujinx.Common/ReleaseInformation.cs + shell: bash + if: github.event_name == 'pull_request' + - name: Publish macOS Ryujinx.Ava run: | ./distribution/macos/create_macos_build_ava.sh . publish_tmp_ava publish_ava ./distribution/macos/entitlements.xml "${{ env.RYUJINX_BASE_VERSION }}" "${{ steps.git_short_hash.outputs.result }}" "${{ matrix.configuration }}" "-p:ExtraDefineConstants=DISABLE_UPDATER" diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 1fb0acdc..d6bcd3fa 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -85,6 +85,7 @@ jobs: sed -r --in-place 's/\%\%RYUJINX_TARGET_RELEASE_CHANNEL_NAME\%\%/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_NAME }}/g;' src/Ryujinx.Common/ReleaseInformation.cs sed -r --in-place 's/\%\%RYUJINX_TARGET_RELEASE_CHANNEL_OWNER\%\%/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/g;' src/Ryujinx.Common/ReleaseInformation.cs sed -r --in-place 's/\%\%RYUJINX_TARGET_RELEASE_CHANNEL_REPO\%\%/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/g;' src/Ryujinx.Common/ReleaseInformation.cs + sed -r --in-place 's/\%\%RYUJINX_CONFIG_FILE_NAME\%\%/Config\.json/g;' src/Ryujinx.Common/ReleaseInformation.cs shell: bash - name: Create output dir @@ -186,6 +187,7 @@ jobs: sed -r --in-place 's/\%\%RYUJINX_TARGET_RELEASE_CHANNEL_NAME\%\%/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_NAME }}/g;' src/Ryujinx.Common/ReleaseInformation.cs sed -r --in-place 's/\%\%RYUJINX_TARGET_RELEASE_CHANNEL_OWNER\%\%/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/g;' src/Ryujinx.Common/ReleaseInformation.cs sed -r --in-place 's/\%\%RYUJINX_TARGET_RELEASE_CHANNEL_REPO\%\%/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/g;' src/Ryujinx.Common/ReleaseInformation.cs + sed -r --in-place 's/\%\%RYUJINX_CONFIG_FILE_NAME\%\%/Config\.json/g;' src/Ryujinx.Common/ReleaseInformation.cs shell: bash - name: Publish macOS Ryujinx.Ava diff --git a/distribution/linux/Ryujinx.desktop b/distribution/linux/Ryujinx.desktop index a4550d10..44f05bf3 100644 --- a/distribution/linux/Ryujinx.desktop +++ b/distribution/linux/Ryujinx.desktop @@ -4,7 +4,7 @@ Name=Ryujinx Type=Application Icon=Ryujinx Exec=Ryujinx.sh %f -Comment=Plays Nintendo Switch applications +Comment=A Nintendo Switch Emulator GenericName=Nintendo Switch Emulator Terminal=false Categories=Game;Emulator; diff --git a/distribution/linux/Ryujinx.sh b/distribution/linux/Ryujinx.sh old mode 100644 new mode 100755 index f356cad0..a80cdcae --- a/distribution/linux/Ryujinx.sh +++ b/distribution/linux/Ryujinx.sh @@ -17,4 +17,4 @@ if command -v gamemoderun > /dev/null 2>&1; then COMMAND="$COMMAND gamemoderun" fi -$COMMAND "$SCRIPT_DIR/$RYUJINX_BIN" "$@" \ No newline at end of file +$COMMAND "$SCRIPT_DIR/$RYUJINX_BIN" "$@" diff --git a/src/Ryujinx.Ava/Modules/Updater/Updater.cs b/src/Ryujinx.Ava/Modules/Updater/Updater.cs index af7608d3..ad33b101 100644 --- a/src/Ryujinx.Ava/Modules/Updater/Updater.cs +++ b/src/Ryujinx.Ava/Modules/Updater/Updater.cs @@ -665,7 +665,7 @@ namespace Ryujinx.Modules return false; } - if (Program.Version.Contains("dirty") || !ReleaseInformation.IsValid()) + if (Program.Version.Contains("dirty") || !ReleaseInformation.IsValid) { if (showWarnings) { @@ -683,7 +683,7 @@ namespace Ryujinx.Modules #else if (showWarnings) { - if (ReleaseInformation.IsFlatHubBuild()) + if (ReleaseInformation.IsFlatHubBuild) { Dispatcher.UIThread.InvokeAsync(() => ContentDialogHelper.CreateWarningDialog( diff --git a/src/Ryujinx.Ava/Program.cs b/src/Ryujinx.Ava/Program.cs index cc062a25..d85749ef 100644 --- a/src/Ryujinx.Ava/Program.cs +++ b/src/Ryujinx.Ava/Program.cs @@ -35,7 +35,7 @@ namespace Ryujinx.Ava public static void Main(string[] args) { - Version = ReleaseInformation.GetVersion(); + Version = ReleaseInformation.Version; if (OperatingSystem.IsWindows() && !OperatingSystem.IsWindowsVersionAtLeast(10, 0, 17134)) { @@ -125,8 +125,8 @@ namespace Ryujinx.Ava public static void ReloadConfig() { - string localConfigurationPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Config.json"); - string appDataConfigurationPath = Path.Combine(AppDataManager.BaseDirPath, "Config.json"); + string localConfigurationPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, ReleaseInformation.ConfigName); + string appDataConfigurationPath = Path.Combine(AppDataManager.BaseDirPath, ReleaseInformation.ConfigName); // Now load the configuration as the other subsystems are now registered if (File.Exists(localConfigurationPath)) diff --git a/src/Ryujinx.Ava/UI/ViewModels/MainWindowViewModel.cs b/src/Ryujinx.Ava/UI/ViewModels/MainWindowViewModel.cs index 7146dfd7..dff5b59b 100644 --- a/src/Ryujinx.Ava/UI/ViewModels/MainWindowViewModel.cs +++ b/src/Ryujinx.Ava/UI/ViewModels/MainWindowViewModel.cs @@ -357,7 +357,7 @@ namespace Ryujinx.Ava.UI.ViewModels public bool OpenBcatSaveDirectoryEnabled => !SelectedApplication.ControlHolder.ByteSpan.IsZeros() && SelectedApplication.ControlHolder.Value.BcatDeliveryCacheStorageSize > 0; - public bool CreateShortcutEnabled => !ReleaseInformation.IsFlatHubBuild(); + public bool CreateShortcutEnabled => !ReleaseInformation.IsFlatHubBuild; public string LoadHeading { @@ -1350,7 +1350,12 @@ namespace Ryujinx.Ava.UI.ViewModels public void OpenLogsFolder() { - string logPath = Path.Combine(ReleaseInformation.GetBaseApplicationDirectory(), "Logs"); + string logPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Logs"); + + if (ReleaseInformation.IsValid) + { + logPath = Path.Combine(AppDataManager.BaseDirPath, "Logs"); + } new DirectoryInfo(logPath).Create(); diff --git a/src/Ryujinx.Common/Configuration/AppDataManager.cs b/src/Ryujinx.Common/Configuration/AppDataManager.cs index 8a226d9a..35aea3c2 100644 --- a/src/Ryujinx.Common/Configuration/AppDataManager.cs +++ b/src/Ryujinx.Common/Configuration/AppDataManager.cs @@ -1,4 +1,5 @@ using Ryujinx.Common.Logging; +using Ryujinx.Common.Utilities; using System; using System.IO; @@ -6,8 +7,8 @@ namespace Ryujinx.Common.Configuration { public static class AppDataManager { - public const string DefaultBaseDir = "Ryujinx"; - public const string DefaultPortableDir = "portable"; + private const string DefaultBaseDir = "Ryujinx"; + private const string DefaultPortableDir = "portable"; // The following 3 are always part of Base Directory private const string GamesDir = "games"; @@ -109,8 +110,7 @@ namespace Ryujinx.Common.Configuration string oldConfigPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), DefaultBaseDir); if (Path.Exists(oldConfigPath) && !IsPathSymlink(oldConfigPath) && !Path.Exists(BaseDirPath)) { - CopyDirectory(oldConfigPath, BaseDirPath); - Directory.Delete(oldConfigPath, true); + FileSystemUtils.MoveDirectory(oldConfigPath, BaseDirPath); Directory.CreateSymbolicLink(oldConfigPath, BaseDirPath); } } @@ -127,41 +127,13 @@ namespace Ryujinx.Common.Configuration } // Check if existing old baseDirPath is a symlink, to prevent possible errors. - // Should be removed, when the existance of the old directory isn't checked anymore. + // Should be removed, when the existence of the old directory isn't checked anymore. private static bool IsPathSymlink(string path) { FileAttributes attributes = File.GetAttributes(path); return (attributes & FileAttributes.ReparsePoint) == FileAttributes.ReparsePoint; } - private static void CopyDirectory(string sourceDir, string destinationDir) - { - var dir = new DirectoryInfo(sourceDir); - - if (!dir.Exists) - { - throw new DirectoryNotFoundException($"Source directory not found: {dir.FullName}"); - } - - DirectoryInfo[] subDirs = dir.GetDirectories(); - Directory.CreateDirectory(destinationDir); - - foreach (FileInfo file in dir.GetFiles()) - { - if (file.Name == ".DS_Store") - { - continue; - } - - file.CopyTo(Path.Combine(destinationDir, file.Name)); - } - - foreach (DirectoryInfo subDir in subDirs) - { - CopyDirectory(subDir.FullName, Path.Combine(destinationDir, subDir.Name)); - } - } - public static string GetModsPath() => CustomModsPath ?? Directory.CreateDirectory(Path.Combine(BaseDirPath, DefaultModsDir)).FullName; public static string GetSdModsPath() => CustomSdModsPath ?? Directory.CreateDirectory(Path.Combine(BaseDirPath, DefaultSdcardDir, "atmosphere")).FullName; } diff --git a/src/Ryujinx.Common/Logging/Targets/FileLogTarget.cs b/src/Ryujinx.Common/Logging/Targets/FileLogTarget.cs index 8aa2a26b..c40c3abe 100644 --- a/src/Ryujinx.Common/Logging/Targets/FileLogTarget.cs +++ b/src/Ryujinx.Common/Logging/Targets/FileLogTarget.cs @@ -13,31 +13,71 @@ namespace Ryujinx.Common.Logging.Targets string ILogTarget.Name { get => _name; } - public FileLogTarget(string path, string name) - : this(path, name, FileShare.Read, FileMode.Append) - { } + public FileLogTarget(string name, FileStream fileStream) + { + _name = name; + _logWriter = new StreamWriter(fileStream); + _formatter = new DefaultLogFormatter(); + } - public FileLogTarget(string path, string name, FileShare fileShare, FileMode fileMode) + public static FileStream PrepareLogFile(string path) { // Ensure directory is present DirectoryInfo logDir = new(Path.Combine(path, "Logs")); - logDir.Create(); + try + { + logDir.Create(); + } + catch (IOException exception) + { + Logger.Warning?.Print(LogClass.Application, $"Logging directory could not be created '{logDir}': {exception}"); + + return null; + } // Clean up old logs, should only keep 3 FileInfo[] files = logDir.GetFiles("*.log").OrderBy((info => info.CreationTime)).ToArray(); for (int i = 0; i < files.Length - 2; i++) { - files[i].Delete(); + try + { + files[i].Delete(); + } + catch (UnauthorizedAccessException exception) + { + Logger.Warning?.Print(LogClass.Application, $"Old log file could not be deleted '{files[i].FullName}': {exception}"); + + return null; + } + catch (IOException exception) + { + Logger.Warning?.Print(LogClass.Application, $"Old log file could not be deleted '{files[i].FullName}': {exception}"); + + return null; + } } - string version = ReleaseInformation.GetVersion(); + string version = ReleaseInformation.Version; // Get path for the current time path = Path.Combine(logDir.FullName, $"Ryujinx_{version}_{DateTime.Now:yyyy-MM-dd_HH-mm-ss}.log"); - _name = name; - _logWriter = new StreamWriter(File.Open(path, fileMode, FileAccess.Write, fileShare)); - _formatter = new DefaultLogFormatter(); + try + { + return File.Open(path, FileMode.Append, FileAccess.Write, FileShare.Read); + } + catch (UnauthorizedAccessException exception) + { + Logger.Warning?.Print(LogClass.Application, $"Log file could not be created '{path}': {exception}"); + + return null; + } + catch (IOException exception) + { + Logger.Warning?.Print(LogClass.Application, $"Log file could not be created '{path}': {exception}"); + + return null; + } } public void Log(object sender, LogEventArgs args) diff --git a/src/Ryujinx.Common/ReleaseInformation.cs b/src/Ryujinx.Common/ReleaseInformation.cs index ab65a98f..774ae012 100644 --- a/src/Ryujinx.Common/ReleaseInformation.cs +++ b/src/Ryujinx.Common/ReleaseInformation.cs @@ -1,5 +1,3 @@ -using Ryujinx.Common.Configuration; -using System; using System.Reflection; namespace Ryujinx.Common @@ -9,50 +7,25 @@ namespace Ryujinx.Common { private const string FlatHubChannelOwner = "flathub"; - public const string BuildVersion = "%%RYUJINX_BUILD_VERSION%%"; - public const string BuildGitHash = "%%RYUJINX_BUILD_GIT_HASH%%"; - public const string ReleaseChannelName = "%%RYUJINX_TARGET_RELEASE_CHANNEL_NAME%%"; + private const string BuildVersion = "%%RYUJINX_BUILD_VERSION%%"; + private const string BuildGitHash = "%%RYUJINX_BUILD_GIT_HASH%%"; + private const string ReleaseChannelName = "%%RYUJINX_TARGET_RELEASE_CHANNEL_NAME%%"; + private const string ConfigFileName = "%%RYUJINX_CONFIG_FILE_NAME%%"; + public const string ReleaseChannelOwner = "%%RYUJINX_TARGET_RELEASE_CHANNEL_OWNER%%"; public const string ReleaseChannelRepo = "%%RYUJINX_TARGET_RELEASE_CHANNEL_REPO%%"; - public static bool IsValid() - { - return !BuildGitHash.StartsWith("%%") && - !ReleaseChannelName.StartsWith("%%") && - !ReleaseChannelOwner.StartsWith("%%") && - !ReleaseChannelRepo.StartsWith("%%"); - } + public static string ConfigName => !ConfigFileName.StartsWith("%%") ? ConfigFileName : "Config.json"; - public static bool IsFlatHubBuild() - { - return IsValid() && ReleaseChannelOwner.Equals(FlatHubChannelOwner); - } + public static bool IsValid => + !BuildGitHash.StartsWith("%%") && + !ReleaseChannelName.StartsWith("%%") && + !ReleaseChannelOwner.StartsWith("%%") && + !ReleaseChannelRepo.StartsWith("%%") && + !ConfigFileName.StartsWith("%%"); - public static string GetVersion() - { - if (IsValid()) - { - return BuildVersion; - } + public static bool IsFlatHubBuild => IsValid && ReleaseChannelOwner.Equals(FlatHubChannelOwner); - return Assembly.GetEntryAssembly().GetCustomAttribute().InformationalVersion; - } - -#if FORCE_EXTERNAL_BASE_DIR - public static string GetBaseApplicationDirectory() - { - return AppDataManager.BaseDirPath; - } -#else - public static string GetBaseApplicationDirectory() - { - if (IsFlatHubBuild() || OperatingSystem.IsMacOS()) - { - return AppDataManager.BaseDirPath; - } - - return AppDomain.CurrentDomain.BaseDirectory; - } -#endif + public static string Version => IsValid ? BuildVersion : Assembly.GetEntryAssembly()!.GetCustomAttribute()?.InformationalVersion; } } diff --git a/src/Ryujinx.Common/Utilities/FileSystemUtils.cs b/src/Ryujinx.Common/Utilities/FileSystemUtils.cs new file mode 100644 index 00000000..e76c2b60 --- /dev/null +++ b/src/Ryujinx.Common/Utilities/FileSystemUtils.cs @@ -0,0 +1,48 @@ +using System.IO; + +namespace Ryujinx.Common.Utilities +{ + public static class FileSystemUtils + { + public static void CopyDirectory(string sourceDir, string destinationDir, bool recursive) + { + // Get information about the source directory + var dir = new DirectoryInfo(sourceDir); + + // Check if the source directory exists + if (!dir.Exists) + { + throw new DirectoryNotFoundException($"Source directory not found: {dir.FullName}"); + } + + // Cache directories before we start copying + DirectoryInfo[] dirs = dir.GetDirectories(); + + // Create the destination directory + Directory.CreateDirectory(destinationDir); + + // Get the files in the source directory and copy to the destination directory + foreach (FileInfo file in dir.GetFiles()) + { + string targetFilePath = Path.Combine(destinationDir, file.Name); + file.CopyTo(targetFilePath); + } + + // If recursive and copying subdirectories, recursively call this method + if (recursive) + { + foreach (DirectoryInfo subDir in dirs) + { + string newDestinationDir = Path.Combine(destinationDir, subDir.Name); + CopyDirectory(subDir.FullName, newDestinationDir, true); + } + } + } + + public static void MoveDirectory(string sourceDir, string destinationDir) + { + CopyDirectory(sourceDir, destinationDir, true); + Directory.Delete(sourceDir, true); + } + } +} diff --git a/src/Ryujinx.Headless.SDL2/Program.cs b/src/Ryujinx.Headless.SDL2/Program.cs index e545079b..6eaa1b86 100644 --- a/src/Ryujinx.Headless.SDL2/Program.cs +++ b/src/Ryujinx.Headless.SDL2/Program.cs @@ -61,7 +61,7 @@ namespace Ryujinx.Headless.SDL2 static void Main(string[] args) { - Version = ReleaseInformation.GetVersion(); + Version = ReleaseInformation.Version; // Make process DPI aware for proper window sizing on high-res screens. ForceDpiAware.Windows(); @@ -427,11 +427,26 @@ namespace Ryujinx.Headless.SDL2 if (!option.DisableFileLog) { - Logger.AddTarget(new AsyncLogTargetWrapper( - new FileLogTarget(ReleaseInformation.GetBaseApplicationDirectory(), "file"), - 1000, - AsyncLogTargetOverflowAction.Block - )); + FileStream logFile = FileLogTarget.PrepareLogFile(AppDomain.CurrentDomain.BaseDirectory); + + if (logFile == null) + { + logFile = FileLogTarget.PrepareLogFile(AppDataManager.BaseDirPath); + + if (logFile == null) + { + Logger.Error?.Print(LogClass.Application, "No writable log directory available. Make sure either the application directory or the Ryujinx directory is writable."); + } + } + + if (logFile != null) + { + Logger.AddTarget(new AsyncLogTargetWrapper( + new FileLogTarget("file", logFile), + 1000, + AsyncLogTargetOverflowAction.Block + )); + } } // Setup graphics configuration diff --git a/src/Ryujinx.SDL2.Common/SDL2Driver.cs b/src/Ryujinx.SDL2.Common/SDL2Driver.cs index db1a85e3..552deafd 100644 --- a/src/Ryujinx.SDL2.Common/SDL2Driver.cs +++ b/src/Ryujinx.SDL2.Common/SDL2Driver.cs @@ -1,4 +1,3 @@ -using Ryujinx.Common; using Ryujinx.Common.Logging; using System; using System.Collections.Concurrent; @@ -13,8 +12,6 @@ namespace Ryujinx.SDL2.Common { private static SDL2Driver _instance; - public static bool IsInitialized => _instance != null; - public static SDL2Driver Instance { get @@ -96,7 +93,7 @@ namespace Ryujinx.SDL2.Common SDL_EventState(SDL_EventType.SDL_CONTROLLERSENSORUPDATE, SDL_DISABLE); - string gamepadDbPath = Path.Combine(ReleaseInformation.GetBaseApplicationDirectory(), "SDL_GameControllerDB.txt"); + string gamepadDbPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "SDL_GameControllerDB.txt"); if (File.Exists(gamepadDbPath)) { diff --git a/src/Ryujinx.Ui.Common/App/ApplicationLibrary.cs b/src/Ryujinx.Ui.Common/App/ApplicationLibrary.cs index 950eb55b..3b35ff27 100644 --- a/src/Ryujinx.Ui.Common/App/ApplicationLibrary.cs +++ b/src/Ryujinx.Ui.Common/App/ApplicationLibrary.cs @@ -8,6 +8,7 @@ using LibHac.Ns; using LibHac.Tools.Fs; using LibHac.Tools.FsSystem; using LibHac.Tools.FsSystem.NcaUtils; +using Ryujinx.Common; using Ryujinx.Common.Configuration; using Ryujinx.Common.Logging; using Ryujinx.Common.Utilities; @@ -105,7 +106,7 @@ namespace Ryujinx.Ui.App.Common if (!Directory.Exists(appDir)) { - Logger.Warning?.Print(LogClass.Application, $"The \"game_dirs\" section in \"Config.json\" contains an invalid directory: \"{appDir}\""); + Logger.Warning?.Print(LogClass.Application, $"The \"game_dirs\" section in \"{ReleaseInformation.ConfigName}\" contains an invalid directory: \"{appDir}\""); continue; } diff --git a/src/Ryujinx.Ui.Common/Configuration/LoggerModule.cs b/src/Ryujinx.Ui.Common/Configuration/LoggerModule.cs index 54ad20dd..6cd63272 100644 --- a/src/Ryujinx.Ui.Common/Configuration/LoggerModule.cs +++ b/src/Ryujinx.Ui.Common/Configuration/LoggerModule.cs @@ -1,7 +1,9 @@ using Ryujinx.Common; +using Ryujinx.Common.Configuration; using Ryujinx.Common.Logging; using Ryujinx.Common.Logging.Targets; using System; +using System.IO; namespace Ryujinx.Ui.Common.Configuration { @@ -80,8 +82,23 @@ namespace Ryujinx.Ui.Common.Configuration { if (e.NewValue) { + FileStream logFile = FileLogTarget.PrepareLogFile(AppDomain.CurrentDomain.BaseDirectory); + + if (logFile == null) + { + logFile = FileLogTarget.PrepareLogFile(AppDataManager.BaseDirPath); + + if (logFile == null) + { + Logger.Error?.Print(LogClass.Application, "No writable log directory available. Make sure either the application directory or the Ryujinx directory is writable."); + Logger.RemoveTarget("file"); + + return; + } + } + Logger.AddTarget(new AsyncLogTargetWrapper( - new FileLogTarget(ReleaseInformation.GetBaseApplicationDirectory(), "file"), + new FileLogTarget("file", logFile), 1000, AsyncLogTargetOverflowAction.Block )); diff --git a/src/Ryujinx.Ui.Common/Helper/FileAssociationHelper.cs b/src/Ryujinx.Ui.Common/Helper/FileAssociationHelper.cs index 570fb91e..daa59d25 100644 --- a/src/Ryujinx.Ui.Common/Helper/FileAssociationHelper.cs +++ b/src/Ryujinx.Ui.Common/Helper/FileAssociationHelper.cs @@ -22,7 +22,7 @@ namespace Ryujinx.Ui.Common.Helper [LibraryImport("shell32.dll", SetLastError = true)] public static partial void SHChangeNotify(uint wEventId, uint uFlags, IntPtr dwItem1, IntPtr dwItem2); - public static bool IsTypeAssociationSupported => (OperatingSystem.IsLinux() || OperatingSystem.IsWindows()) && !ReleaseInformation.IsFlatHubBuild(); + public static bool IsTypeAssociationSupported => (OperatingSystem.IsLinux() || OperatingSystem.IsWindows()) && !ReleaseInformation.IsFlatHubBuild; [SupportedOSPlatform("linux")] private static bool AreMimeTypesRegisteredLinux() => File.Exists(Path.Combine(_mimeDbPath, "packages", "Ryujinx.xml")); @@ -34,7 +34,7 @@ namespace Ryujinx.Ui.Common.Helper if ((uninstall && AreMimeTypesRegisteredLinux()) || (!uninstall && !AreMimeTypesRegisteredLinux())) { - string mimeTypesFile = Path.Combine(ReleaseInformation.GetBaseApplicationDirectory(), "mime", "Ryujinx.xml"); + string mimeTypesFile = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "mime", "Ryujinx.xml"); string additionalArgs = !uninstall ? "--novendor" : ""; using Process mimeProcess = new(); diff --git a/src/Ryujinx/Modules/Updater/UpdateDialog.cs b/src/Ryujinx/Modules/Updater/UpdateDialog.cs index 69563437..0057761b 100644 --- a/src/Ryujinx/Modules/Updater/UpdateDialog.cs +++ b/src/Ryujinx/Modules/Updater/UpdateDialog.cs @@ -1,6 +1,7 @@ using Gdk; using Gtk; using Ryujinx.Common; +using Ryujinx.Common.Configuration; using Ryujinx.Ui; using Ryujinx.Ui.Common.Configuration; using Ryujinx.Ui.Common.Helper; @@ -52,7 +53,7 @@ namespace Ryujinx.Modules ProcessStartInfo processStart = new(ryuName) { UseShellExecute = true, - WorkingDirectory = ReleaseInformation.GetBaseApplicationDirectory(), + WorkingDirectory = AppDomain.CurrentDomain.BaseDirectory }; foreach (string argument in CommandLineState.Arguments) diff --git a/src/Ryujinx/Modules/Updater/Updater.cs b/src/Ryujinx/Modules/Updater/Updater.cs index f8ce4c0b..2fed4362 100644 --- a/src/Ryujinx/Modules/Updater/Updater.cs +++ b/src/Ryujinx/Modules/Updater/Updater.cs @@ -532,7 +532,7 @@ namespace Ryujinx.Modules return false; } - if (Program.Version.Contains("dirty") || !ReleaseInformation.IsValid()) + if (Program.Version.Contains("dirty") || !ReleaseInformation.IsValid) { if (showWarnings) { @@ -546,7 +546,7 @@ namespace Ryujinx.Modules #else if (showWarnings) { - if (ReleaseInformation.IsFlatHubBuild()) + if (ReleaseInformation.IsFlatHubBuild) { GtkDialog.CreateWarningDialog("Updater Disabled!", "Please update Ryujinx via FlatHub."); } diff --git a/src/Ryujinx/Program.cs b/src/Ryujinx/Program.cs index 597d00f3..3b5cd770 100644 --- a/src/Ryujinx/Program.cs +++ b/src/Ryujinx/Program.cs @@ -71,7 +71,7 @@ namespace Ryujinx static void Main(string[] args) { - Version = ReleaseInformation.GetVersion(); + Version = ReleaseInformation.Version; if (OperatingSystem.IsWindows() && !OperatingSystem.IsWindowsVersionAtLeast(10, 0, 17134)) { @@ -167,8 +167,8 @@ namespace Ryujinx Quality = 100, }); - string localConfigurationPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Config.json"); - string appDataConfigurationPath = Path.Combine(AppDataManager.BaseDirPath, "Config.json"); + string localConfigurationPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, ReleaseInformation.ConfigName); + string appDataConfigurationPath = Path.Combine(AppDataManager.BaseDirPath, ReleaseInformation.ConfigName); // Now load the configuration as the other subsystems are now registered ConfigurationPath = File.Exists(localConfigurationPath) diff --git a/src/Ryujinx/Ui/Helper/ThemeHelper.cs b/src/Ryujinx/Ui/Helper/ThemeHelper.cs index 67962cb6..5cd9ad52 100644 --- a/src/Ryujinx/Ui/Helper/ThemeHelper.cs +++ b/src/Ryujinx/Ui/Helper/ThemeHelper.cs @@ -1,4 +1,5 @@ using Gtk; +using Ryujinx.Common; using Ryujinx.Common.Logging; using Ryujinx.Ui.Common.Configuration; using System.IO; @@ -24,7 +25,7 @@ namespace Ryujinx.Ui.Helper } else { - Logger.Warning?.Print(LogClass.Application, $"The \"custom_theme_path\" section in \"Config.json\" contains an invalid path: \"{ConfigurationState.Instance.Ui.CustomThemePath}\"."); + Logger.Warning?.Print(LogClass.Application, $"The \"custom_theme_path\" section in \"{ReleaseInformation.ConfigName}\" contains an invalid path: \"{ConfigurationState.Instance.Ui.CustomThemePath}\"."); ConfigurationState.Instance.Ui.CustomThemePath.Value = ""; ConfigurationState.Instance.Ui.EnableCustomTheme.Value = false; diff --git a/src/Ryujinx/Ui/MainWindow.cs b/src/Ryujinx/Ui/MainWindow.cs index 6cce034b..3cd2b0eb 100644 --- a/src/Ryujinx/Ui/MainWindow.cs +++ b/src/Ryujinx/Ui/MainWindow.cs @@ -1376,7 +1376,12 @@ namespace Ryujinx.Ui private void OpenLogsFolder_Pressed(object sender, EventArgs args) { - string logPath = System.IO.Path.Combine(ReleaseInformation.GetBaseApplicationDirectory(), "Logs"); + string logPath = System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Logs"); + + if (ReleaseInformation.IsValid) + { + logPath = System.IO.Path.Combine(AppDataManager.BaseDirPath, "Logs"); + } new DirectoryInfo(logPath).Create(); diff --git a/src/Ryujinx/Ui/Widgets/GameTableContextMenu.cs b/src/Ryujinx/Ui/Widgets/GameTableContextMenu.cs index 6bf43842..eb9f52d7 100644 --- a/src/Ryujinx/Ui/Widgets/GameTableContextMenu.cs +++ b/src/Ryujinx/Ui/Widgets/GameTableContextMenu.cs @@ -78,7 +78,7 @@ namespace Ryujinx.Ui.Widgets _extractExeFsMenuItem.Sensitive = hasNca; _extractLogoMenuItem.Sensitive = hasNca; - _createShortcutMenuItem.Sensitive = !ReleaseInformation.IsFlatHubBuild(); + _createShortcutMenuItem.Sensitive = !ReleaseInformation.IsFlatHubBuild; PopupAtPointer(null); }