diff --git a/src/Ryujinx.Common/ReleaseInformation.cs b/src/Ryujinx.Common/ReleaseInformation.cs index cbf93013f5..c009651163 100644 --- a/src/Ryujinx.Common/ReleaseInformation.cs +++ b/src/Ryujinx.Common/ReleaseInformation.cs @@ -13,12 +13,14 @@ public static class ReleaseInformation public const string BuildGitHash = "%%RYUJINX_BUILD_GIT_HASH%%"; private const string ReleaseChannelName = "%%RYUJINX_TARGET_RELEASE_CHANNEL_NAME%%"; private const string ConfigFileName = "%%RYUJINX_CONFIG_FILE_NAME%%"; + private const string ConfigFileNameOverride = "%%RYUJINX_CONFIG_FILE_NAME_OVERRIDE%%"; public const string ReleaseChannelOwner = "%%RYUJINX_TARGET_RELEASE_CHANNEL_OWNER%%"; public const string ReleaseChannelSourceRepo = "%%RYUJINX_TARGET_RELEASE_CHANNEL_SOURCE_REPO%%"; public const string ReleaseChannelRepo = "%%RYUJINX_TARGET_RELEASE_CHANNEL_REPO%%"; public static string ConfigName => !ConfigFileName.StartsWith("%%") ? ConfigFileName : "Config.json"; + public static string CustomConfigNameOverride => !ConfigFileNameOverride.StartsWith("%%") ? ConfigFileNameOverride : "CustomConfigOverride.json"; public static bool IsValid => !BuildGitHash.StartsWith("%%") && @@ -26,7 +28,8 @@ public static class ReleaseInformation !ReleaseChannelOwner.StartsWith("%%") && !ReleaseChannelSourceRepo.StartsWith("%%") && !ReleaseChannelRepo.StartsWith("%%") && - !ConfigFileName.StartsWith("%%"); + !ConfigFileName.StartsWith("%%") && + !ConfigFileNameOverride.StartsWith("%%"); public static bool IsCanaryBuild => IsValid && ReleaseChannelName.Equals(CanaryChannel); diff --git a/src/Ryujinx/Program.cs b/src/Ryujinx/Program.cs index 831e4294cd..6c953703f6 100644 --- a/src/Ryujinx/Program.cs +++ b/src/Ryujinx/Program.cs @@ -160,6 +160,28 @@ public static void ReloadConfig() string localConfigurationPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, ReleaseInformation.ConfigName); string appDataConfigurationPath = Path.Combine(AppDataManager.BaseDirPath, ReleaseInformation.ConfigName); + string overrideLocalConfigurationPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, ReleaseInformation.CustomConfigNameOverride); + string overrideAppDataConfigurationPath = Path.Combine(AppDataManager.BaseDirPath, ReleaseInformation.CustomConfigNameOverride); + + // Copies and reloads the configuration file if the game was loaded with arguments + // based on global configuration + if (CommandLineState.CountArguments > 0) + { + if (File.Exists(localConfigurationPath)) + { + File.Copy(localConfigurationPath, overrideLocalConfigurationPath, overwrite: true); + } + + localConfigurationPath = overrideLocalConfigurationPath; + + if (File.Exists(appDataConfigurationPath)) + { + File.Copy(appDataConfigurationPath, overrideAppDataConfigurationPath, overwrite: true); + } + + appDataConfigurationPath = overrideAppDataConfigurationPath; + } + // Now load the configuration as the other subsystems are now registered if (File.Exists(localConfigurationPath)) { @@ -232,8 +254,35 @@ public static void ReloadConfig() _ => ConfigurationState.Instance.HideCursor, }; + // Check if memoryManagerMode was overridden. + if (CommandLineState.OverrideMemoryManagerMode is not null) + if (Enum.TryParse(CommandLineState.OverrideMemoryManagerMode, true, out MemoryManagerMode result)) + { + ConfigurationState.Instance.System.MemoryManagerMode.Value = result; + } + + // Check if PPTC was overridden. + if (CommandLineState.OverridePPTC is not null) + if (Enum.TryParse(CommandLineState.OverridePPTC, true, out bool result)) + { + ConfigurationState.Instance.System.EnablePtc.Value = result; + } + + // Check if region was overridden. + if (CommandLineState.OverrideSystemRegion is not null) + if (Enum.TryParse(CommandLineState.OverrideSystemRegion, true, out Ryujinx.HLE.HOS.SystemState.RegionCode result)) + { + ConfigurationState.Instance.System.Region.Value = (Utilities.Configuration.System.Region)result; + } + + //Check if language was overridden. + if (CommandLineState.OverrideSystemLanguage is not null) + if (Enum.TryParse(CommandLineState.OverrideSystemLanguage, true, out Ryujinx.HLE.HOS.SystemState.SystemLanguage result)) + { + ConfigurationState.Instance.System.Language.Value = (Utilities.Configuration.System.Language)result; + } - // Check if hardware-acceleration was overridden. + // Check if hardware-acceleration was overridden. MemoryManagerMode ( outdated! ) if (CommandLineState.OverrideHardwareAcceleration != null) UseHardwareAcceleration = CommandLineState.OverrideHardwareAcceleration.Value; } diff --git a/src/Ryujinx/UI/Controls/ApplicationContextMenu.axaml.cs b/src/Ryujinx/UI/Controls/ApplicationContextMenu.axaml.cs index e55e744551..b4a944752a 100644 --- a/src/Ryujinx/UI/Controls/ApplicationContextMenu.axaml.cs +++ b/src/Ryujinx/UI/Controls/ApplicationContextMenu.axaml.cs @@ -376,15 +376,11 @@ public async void ExtractApplicationLogo_Click(object sender, RoutedEventArgs ar png.SaveTo(fileStream); } - public void CreateApplicationShortcut_Click(object sender, RoutedEventArgs args) + public async void CreateApplicationShortcut_Click(object sender, RoutedEventArgs args) { if (sender is MenuItem { DataContext: MainWindowViewModel { SelectedApplication: not null } viewModel }) - ShortcutHelper.CreateAppShortcut( - viewModel.SelectedApplication.Path, - viewModel.SelectedApplication.Name, - viewModel.SelectedApplication.IdString, - viewModel.SelectedApplication.Icon - ); + await new ArgumentsConfigWindows(viewModel).ShowDialog((Window)viewModel.TopLevel); + } public async void OpenApplicationCompatibility_Click(object sender, RoutedEventArgs args) diff --git a/src/Ryujinx/UI/ViewModels/SettingsViewModel.cs b/src/Ryujinx/UI/ViewModels/SettingsViewModel.cs index d54313e768..1c9d69405f 100644 --- a/src/Ryujinx/UI/ViewModels/SettingsViewModel.cs +++ b/src/Ryujinx/UI/ViewModels/SettingsViewModel.cs @@ -1,8 +1,10 @@ using Avalonia.Collections; using Avalonia.Controls; +using Avalonia.Media.Imaging; using Avalonia.Threading; using CommunityToolkit.Mvvm.ComponentModel; using Gommon; +using LibHac.Tools.Fs; using LibHac.Tools.FsSystem; using Ryujinx.Audio.Backends.OpenAL; using Ryujinx.Audio.Backends.SDL2; @@ -26,6 +28,7 @@ using System; using System.Collections.Generic; using System.Collections.ObjectModel; +using System.IO; using System.Linq; using System.Net.NetworkInformation; using System.Runtime.InteropServices; @@ -63,12 +66,56 @@ public partial class SettingsViewModel : BaseModel public event Action CloseWindow; public event Action SaveSettingsEvent; + public event Action CompareSettingsEvent; private int _networkInterfaceIndex; private int _multiplayerModeIndex; private string _ldnPassphrase; [ObservableProperty] private string _ldnServer; public SettingsHacksViewModel DirtyHacks { get; } + public string GamePath { get; } + public string GameName { get; } + + private Bitmap _gameIcon; + + private string _gameTitle; + private string _gameId; + public Bitmap GameIcon + { + get => _gameIcon; + set + { + if (_gameIcon != value) + { + _gameIcon = value; + } + } + } + + public string GameTitle + { + get => _gameTitle; + set + { + if (_gameTitle != value) + { + _gameTitle = value; + } + } + } + + public string GameId + { + get => _gameId; + set + { + if (_gameId != value) + { + _gameId = value; + } + } + } + public int ResolutionScale { @@ -344,6 +391,30 @@ public SettingsViewModel(VirtualFileSystem virtualFileSystem, ContentManager con } } + public SettingsViewModel(VirtualFileSystem virtualFileSystem, ContentManager contentManager, string gamePath, string gameName, string gameId, byte[] gameIconData) : this() + { + _virtualFileSystem = virtualFileSystem; + _contentManager = contentManager; + + if (gameIconData != null && gameIconData.Length > 0) + { + using (var ms = new MemoryStream(gameIconData)) + { + GameIcon = new Bitmap(ms); + } + } + + GameTitle = gameName; + GameId = gameId; + + if (Program.PreviewerDetached) + { + Task.Run(LoadTimeZones); + + DirtyHacks = new SettingsHacksViewModel(this); + } + } + public SettingsViewModel() { GameDirectories = []; @@ -716,6 +787,11 @@ public void ApplyButton() SaveSettings(); } + public void CreateShortcut() + { + CompareSettingsEvent?.Invoke(); //raises an event to create a shortcut with arguments + } + public void OkButton() { SaveSettings(); diff --git a/src/Ryujinx/UI/Views/Settings/SettingsApplyOverride.axaml b/src/Ryujinx/UI/Views/Settings/SettingsApplyOverride.axaml new file mode 100644 index 0000000000..e508000751 --- /dev/null +++ b/src/Ryujinx/UI/Views/Settings/SettingsApplyOverride.axaml @@ -0,0 +1,237 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Ryujinx/UI/Views/Settings/SettingsApplyOverride.axaml.cs b/src/Ryujinx/UI/Views/Settings/SettingsApplyOverride.axaml.cs new file mode 100644 index 0000000000..d852fdc16d --- /dev/null +++ b/src/Ryujinx/UI/Views/Settings/SettingsApplyOverride.axaml.cs @@ -0,0 +1,12 @@ +using Avalonia.Controls; + +namespace Ryujinx.Ava.UI.Views.Settings +{ + public partial class SettingsApplyOverride : UserControl + { + public SettingsApplyOverride() + { + InitializeComponent(); + } + } +} diff --git a/src/Ryujinx/UI/Windows/ArgumentsConfigWindows.axaml b/src/Ryujinx/UI/Windows/ArgumentsConfigWindows.axaml new file mode 100644 index 0000000000..b0953f77c2 --- /dev/null +++ b/src/Ryujinx/UI/Windows/ArgumentsConfigWindows.axaml @@ -0,0 +1,105 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +