From 13d2498405289d230dcaace9924e10ff67003448 Mon Sep 17 00:00:00 2001 From: Vova Date: Tue, 22 Oct 2024 20:35:31 +1000 Subject: [PATCH 01/15] test --- src/Ryujinx/Program.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Ryujinx/Program.cs b/src/Ryujinx/Program.cs index 5087d5d820..a79b99d171 100644 --- a/src/Ryujinx/Program.cs +++ b/src/Ryujinx/Program.cs @@ -31,6 +31,7 @@ namespace Ryujinx.Ava { internal partial class Program { + // public static double WindowScaleFactor { get; set; } public static double DesktopScaleFactor { get; set; } = 1.0; public static string Version { get; private set; } From 8074a4dd870a283936c21fad437bbf8b919a38db Mon Sep 17 00:00:00 2001 From: Vova Date: Wed, 30 Oct 2024 22:17:29 +1000 Subject: [PATCH 02/15] Fixed a visual bug in "input settings", when switching between players the settings were reset to default --- src/Ryujinx/UI/ViewModels/Input/InputViewModel.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Ryujinx/UI/ViewModels/Input/InputViewModel.cs b/src/Ryujinx/UI/ViewModels/Input/InputViewModel.cs index c133f25fa8..090ce000f4 100644 --- a/src/Ryujinx/UI/ViewModels/Input/InputViewModel.cs +++ b/src/Ryujinx/UI/ViewModels/Input/InputViewModel.cs @@ -100,6 +100,7 @@ public PlayerIndex PlayerId { _playerId = PlayerIndex.Player1; } + _isLoaded = false; LoadConfiguration(); LoadDevice(); From d83da7d2fbdde2c73cd52e0f3b8b404f69bb2337 Mon Sep 17 00:00:00 2001 From: Vova Date: Sat, 2 Nov 2024 22:42:57 +1000 Subject: [PATCH 03/15] Fixed the logic of saving the input section. Added a new dialog box when changing parameters --- src/Ryujinx/Assets/Locales/en_US.json | 1 + src/Ryujinx/UI/Helpers/ContentDialogHelper.cs | 18 ++++++ .../UI/ViewModels/Input/InputViewModel.cs | 10 ++++ .../Views/Input/ControllerInputView.axaml.cs | 60 ++++++++++++++++++- src/Ryujinx/UI/Views/Input/InputView.axaml | 2 +- src/Ryujinx/UI/Views/Input/InputView.axaml.cs | 34 +++++++++-- 6 files changed, 118 insertions(+), 7 deletions(-) diff --git a/src/Ryujinx/Assets/Locales/en_US.json b/src/Ryujinx/Assets/Locales/en_US.json index 68b48146b0..a826e49f17 100644 --- a/src/Ryujinx/Assets/Locales/en_US.json +++ b/src/Ryujinx/Assets/Locales/en_US.json @@ -407,6 +407,7 @@ "AvatarSetBackgroundColor": "Set Background Color", "AvatarClose": "Close", "ControllerSettingsLoadProfileToolTip": "Load Profile", + "ControllerSettingsViewProfileToolTip": "View Profile", "ControllerSettingsAddProfileToolTip": "Add Profile", "ControllerSettingsRemoveProfileToolTip": "Remove Profile", "ControllerSettingsSaveProfileToolTip": "Save Profile", diff --git a/src/Ryujinx/UI/Helpers/ContentDialogHelper.cs b/src/Ryujinx/UI/Helpers/ContentDialogHelper.cs index 67a3642a9d..bd8c1e3a7b 100644 --- a/src/Ryujinx/UI/Helpers/ContentDialogHelper.cs +++ b/src/Ryujinx/UI/Helpers/ContentDialogHelper.cs @@ -226,6 +226,24 @@ internal static async Task CreateConfirmationDialog( (int)Symbol.Help, primaryButtonResult); + internal static async Task CreateConfirmationDialogExtended( + string primaryText, + string secondaryText, + string acceptButtonText, + string noacceptButtonText, + string cancelButtonText, + string title, + UserResult primaryButtonResult = UserResult.Yes) + => await ShowTextDialog( + string.IsNullOrWhiteSpace(title) ? LocaleManager.Instance[LocaleKeys.DialogConfirmationTitle] : title, + primaryText, + secondaryText, + acceptButtonText, + noacceptButtonText, + cancelButtonText, + (int)Symbol.Help, + primaryButtonResult); + internal static async Task CreateLocalizedConfirmationDialog(string primaryText, string secondaryText) => await CreateConfirmationDialog( primaryText, diff --git a/src/Ryujinx/UI/ViewModels/Input/InputViewModel.cs b/src/Ryujinx/UI/ViewModels/Input/InputViewModel.cs index 090ce000f4..54f278cec6 100644 --- a/src/Ryujinx/UI/ViewModels/Input/InputViewModel.cs +++ b/src/Ryujinx/UI/ViewModels/Input/InputViewModel.cs @@ -44,6 +44,7 @@ public class InputViewModel : BaseModel, IDisposable private readonly MainWindow _mainWindow; private PlayerIndex _playerId; + private PlayerIndex _playerIdChoose; private int _controller; private string _controllerImage; private int _device; @@ -83,6 +84,12 @@ public object ConfigViewModel } } + public PlayerIndex PlayerIdChoose + { + get => _playerIdChoose; + set { } + } + public PlayerIndex PlayerId { get => _playerId; @@ -90,6 +97,8 @@ public PlayerIndex PlayerId { if (IsModified) { + + _playerIdChoose = value; return; } @@ -99,6 +108,7 @@ public PlayerIndex PlayerId if (!Enum.IsDefined(typeof(PlayerIndex), _playerId)) { _playerId = PlayerIndex.Player1; + } _isLoaded = false; diff --git a/src/Ryujinx/UI/Views/Input/ControllerInputView.axaml.cs b/src/Ryujinx/UI/Views/Input/ControllerInputView.axaml.cs index b76648da77..47e6ad53de 100644 --- a/src/Ryujinx/UI/Views/Input/ControllerInputView.axaml.cs +++ b/src/Ryujinx/UI/Views/Input/ControllerInputView.axaml.cs @@ -4,11 +4,14 @@ using Avalonia.Input; using Avalonia.Interactivity; using Avalonia.LogicalTree; +using DiscordRPC; using Ryujinx.Ava.UI.Helpers; using Ryujinx.Ava.UI.ViewModels.Input; using Ryujinx.Common.Configuration.Hid.Controller; +using Ryujinx.Common.Logging; using Ryujinx.Input; using Ryujinx.Input.Assigner; +using System; using StickInputId = Ryujinx.Common.Configuration.Hid.Controller.StickInputId; namespace Ryujinx.Ava.UI.Views.Input @@ -27,6 +30,16 @@ public ControllerInputView() { button.IsCheckedChanged += Button_IsCheckedChanged; } + + if (visual is CheckBox check) + { + check.IsCheckedChanged += CheckBox_IsCheckedChanged; + } + + if (visual is Slider slider) + { + slider.PropertyChanged += Slider_IsCheckedChanged; + } } } @@ -40,9 +53,52 @@ protected override void OnPointerReleased(PointerReleasedEventArgs e) } } + private float _changeSlider = -1.0f; + + private void Slider_IsCheckedChanged(object? sender, AvaloniaPropertyChangedEventArgs e) + { + if (sender is Slider check) + { + if ((bool)check.IsPointerOver && _changeSlider == -1.0f) + { + _changeSlider = (float)check.Value; + + } + else if (!(bool)check.IsPointerOver) + { + _changeSlider = -1.0f; + } + + if (_changeSlider != -1.0f && _changeSlider != (float)check.Value) + { + + var viewModel = (DataContext as ControllerInputViewModel); + viewModel.ParentModel.IsModified = true; + //Logger.Notice.Print(LogClass.Application, $"IsEnabled: {temp}\" \"{check.Value} {check.IsPointerOver}"); + _changeSlider = (float)check.Value; + } + } + } + + private void CheckBox_IsCheckedChanged(object sender, RoutedEventArgs e) + { + if (sender is CheckBox check) + { + if ((bool)check.IsPointerOver) + { + + var viewModel = (DataContext as ControllerInputViewModel); + viewModel.ParentModel.IsModified = true; + _currentAssigner?.Cancel(); + _currentAssigner = null; + } + } + } + + private void Button_IsCheckedChanged(object sender, RoutedEventArgs e) { - if (sender is ToggleButton button) + if (sender is ToggleButton button ) { if ((bool)button.IsChecked) { @@ -149,7 +205,7 @@ private void Button_IsCheckedChanged(object sender, RoutedEventArgs e) } else { - if (_currentAssigner != null) + if (_currentAssigner != null ) { _currentAssigner.Cancel(); _currentAssigner = null; diff --git a/src/Ryujinx/UI/Views/Input/InputView.axaml b/src/Ryujinx/UI/Views/Input/InputView.axaml index 851c9c626f..b5bfa666d8 100644 --- a/src/Ryujinx/UI/Views/Input/InputView.axaml +++ b/src/Ryujinx/UI/Views/Input/InputView.axaml @@ -108,7 +108,7 @@ ToolTip.Tip="{ext:Locale ControllerSettingsLoadProfileToolTip}" Command="{Binding LoadProfile}"> diff --git a/src/Ryujinx/UI/Views/Input/InputView.axaml.cs b/src/Ryujinx/UI/Views/Input/InputView.axaml.cs index 356381a8aa..5fda7ef6ae 100644 --- a/src/Ryujinx/UI/Views/Input/InputView.axaml.cs +++ b/src/Ryujinx/UI/Views/Input/InputView.axaml.cs @@ -25,17 +25,27 @@ public void SaveCurrentProfile() private async void PlayerIndexBox_OnSelectionChanged(object sender, SelectionChangedEventArgs e) { + if (PlayerIndexBox != null) + { + if (PlayerIndexBox.SelectedIndex != (int)ViewModel.PlayerId) + { + PlayerIndexBox.SelectedIndex = (int)ViewModel.PlayerId; + } + } + if (ViewModel.IsModified && !_dialogOpen) { _dialogOpen = true; - var result = await ContentDialogHelper.CreateConfirmationDialog( + var result = await ContentDialogHelper.CreateConfirmationDialogExtended( LocaleManager.Instance[LocaleKeys.DialogControllerSettingsModifiedConfirmMessage], LocaleManager.Instance[LocaleKeys.DialogControllerSettingsModifiedConfirmSubMessage], LocaleManager.Instance[LocaleKeys.InputDialogYes], LocaleManager.Instance[LocaleKeys.InputDialogNo], + LocaleManager.Instance[LocaleKeys.Cancel], LocaleManager.Instance[LocaleKeys.RyujinxConfirm]); + if (result == UserResult.Yes) { ViewModel.Save(); @@ -43,14 +53,30 @@ private async void PlayerIndexBox_OnSelectionChanged(object sender, SelectionCha _dialogOpen = false; + if (result == UserResult.Cancel) + { + + return; + } + ViewModel.IsModified = false; - if (e.AddedItems.Count > 0) + if (result != UserResult.Cancel) + { + ViewModel.PlayerId = ViewModel.PlayerIdChoose; + } + + if (result == UserResult.Cancel) { - var player = (PlayerModel)e.AddedItems[0]; - ViewModel.PlayerId = player.Id; + if (e.AddedItems.Count > 0) + { + ViewModel.IsModified = true; + var player = (PlayerModel)e.AddedItems[0]; + ViewModel.PlayerId = player.Id; + } } } + } public void Dispose() From b9012e291baa69dee2bb7d11c50d2a3e7600a6be Mon Sep 17 00:00:00 2001 From: Vova Date: Sun, 10 Nov 2024 14:32:45 +1000 Subject: [PATCH 04/15] code cleaning --- src/Ryujinx/UI/Views/Input/ControllerInputView.axaml.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/Ryujinx/UI/Views/Input/ControllerInputView.axaml.cs b/src/Ryujinx/UI/Views/Input/ControllerInputView.axaml.cs index 47e6ad53de..c900ea5328 100644 --- a/src/Ryujinx/UI/Views/Input/ControllerInputView.axaml.cs +++ b/src/Ryujinx/UI/Views/Input/ControllerInputView.axaml.cs @@ -55,7 +55,7 @@ protected override void OnPointerReleased(PointerReleasedEventArgs e) private float _changeSlider = -1.0f; - private void Slider_IsCheckedChanged(object? sender, AvaloniaPropertyChangedEventArgs e) + private void Slider_IsCheckedChanged(object sender, AvaloniaPropertyChangedEventArgs e) { if (sender is Slider check) { @@ -74,7 +74,6 @@ private void Slider_IsCheckedChanged(object? sender, AvaloniaPropertyChangedEven var viewModel = (DataContext as ControllerInputViewModel); viewModel.ParentModel.IsModified = true; - //Logger.Notice.Print(LogClass.Application, $"IsEnabled: {temp}\" \"{check.Value} {check.IsPointerOver}"); _changeSlider = (float)check.Value; } } From 37b4dd21337a356eb6ba9792a4bbb0093365cff2 Mon Sep 17 00:00:00 2001 From: Vova Date: Wed, 8 Jan 2025 21:43:18 +1000 Subject: [PATCH 05/15] Added new option "exit by pressing plus and minus buttons" to the input section. --- src/Ryujinx.Input.SDL2/SDL2Gamepad.cs | 38 +++++- src/Ryujinx.Input.SDL2/SDL2Keyboard.cs | 5 + src/Ryujinx.Input.SDL2/SDL2Mouse.cs | 4 + src/Ryujinx.Input/HLE/NpadController.cs | 12 +- src/Ryujinx.Input/HLE/NpadManager.cs | 10 +- src/Ryujinx.Input/IGamepad.cs | 6 + src/Ryujinx/AppHost.cs | 42 +++++- src/Ryujinx/Assets/locales.json | 125 ++++++++++++++++++ src/Ryujinx/Headless/HeadlessRyujinx.cs | 6 +- src/Ryujinx/Headless/Metal/MetalWindow.cs | 5 +- src/Ryujinx/Headless/OpenGL/OpenGLWindow.cs | 5 +- src/Ryujinx/Headless/Options.cs | 9 +- src/Ryujinx/Headless/Vulkan/VulkanWindow.cs | 5 +- src/Ryujinx/Headless/WindowBase.cs | 5 +- src/Ryujinx/Input/AvaloniaKeyboard.cs | 5 + src/Ryujinx/Input/AvaloniaMouse.cs | 5 + .../UI/ViewModels/MainWindowViewModel.cs | 7 + .../UI/ViewModels/SettingsViewModel.cs | 17 +++ .../UI/Views/Settings/SettingsInputView.axaml | 16 ++- src/Ryujinx/UI/Windows/MainWindow.axaml.cs | 11 +- .../Configuration/ConfigurationFileFormat.cs | 7 +- .../ConfigurationState.Migration.cs | 5 + .../Configuration/ConfigurationState.Model.cs | 6 + .../Configuration/ConfigurationState.cs | 2 + 24 files changed, 333 insertions(+), 25 deletions(-) diff --git a/src/Ryujinx.Input.SDL2/SDL2Gamepad.cs b/src/Ryujinx.Input.SDL2/SDL2Gamepad.cs index 12bfab4bb4..26aa496a38 100644 --- a/src/Ryujinx.Input.SDL2/SDL2Gamepad.cs +++ b/src/Ryujinx.Input.SDL2/SDL2Gamepad.cs @@ -253,11 +253,23 @@ public GamepadStateSnapshot GetStateSnapshot() return IGamepad.GetStateSnapshot(this); } + private static bool hotButtonMinus = false; + private static bool HotExit = false; + + public bool spetialExit() + { + if (hotButtonMinus) + { + hotButtonMinus = false; + return HotExit; + } + return HotExit = false; + } + public GamepadStateSnapshot GetMappedStateSnapshot() { GamepadStateSnapshot rawState = GetStateSnapshot(); GamepadStateSnapshot result = default; - lock (_userMappingLock) { if (_buttonsUserMapping.Count == 0) @@ -270,6 +282,28 @@ public GamepadStateSnapshot GetMappedStateSnapshot() if (!entry.IsValid) continue; + if (GamepadButtonInputId.Minus == entry.To) + { + if (rawState.IsPressed(entry.From) && !hotButtonMinus) + { + hotButtonMinus = true; + } + else if (!result.IsPressed(entry.From) && hotButtonMinus) + { + hotButtonMinus = false; + } + } + + if (GamepadButtonInputId.Plus == entry.To) + { + if (rawState.IsPressed(entry.To) && hotButtonMinus) + { + + HotExit = true; + } + + } + // Do not touch state of button already pressed if (!result.IsPressed(entry.To)) { @@ -376,5 +410,7 @@ public bool IsPressed(GamepadButtonInputId inputId) return SDL_GameControllerGetButton(_gamepadHandle, _buttonsDriverMapping[(int)inputId]) == 1; } + + } } diff --git a/src/Ryujinx.Input.SDL2/SDL2Keyboard.cs b/src/Ryujinx.Input.SDL2/SDL2Keyboard.cs index 8d6a30d11a..0fd25a54ea 100644 --- a/src/Ryujinx.Input.SDL2/SDL2Keyboard.cs +++ b/src/Ryujinx.Input.SDL2/SDL2Keyboard.cs @@ -329,6 +329,11 @@ public GamepadStateSnapshot GetMappedStateSnapshot() return result; } + public bool spetialExit() + { + return false; + } + public GamepadStateSnapshot GetStateSnapshot() { throw new NotSupportedException(); diff --git a/src/Ryujinx.Input.SDL2/SDL2Mouse.cs b/src/Ryujinx.Input.SDL2/SDL2Mouse.cs index 37b356b765..d3f64d5ed2 100644 --- a/src/Ryujinx.Input.SDL2/SDL2Mouse.cs +++ b/src/Ryujinx.Input.SDL2/SDL2Mouse.cs @@ -25,6 +25,10 @@ public SDL2Mouse(SDL2MouseDriver driver) { _driver = driver; } + public bool spetialExit() + { + return false; + } public Vector2 GetPosition() { diff --git a/src/Ryujinx.Input/HLE/NpadController.cs b/src/Ryujinx.Input/HLE/NpadController.cs index 3807452838..991311d02e 100644 --- a/src/Ryujinx.Input/HLE/NpadController.cs +++ b/src/Ryujinx.Input/HLE/NpadController.cs @@ -3,6 +3,7 @@ using Ryujinx.Common.Configuration.Hid.Controller; using Ryujinx.Common.Configuration.Hid.Controller.Motion; using Ryujinx.Common.Logging; +using Ryujinx.Graphics.Gpu; using Ryujinx.HLE.HOS.Services.Hid; using System; using System.Collections.Concurrent; @@ -273,15 +274,21 @@ private void UpdateMotionInput(MotionConfigController motionConfig) } } - public void Update() + public bool Update() { + // _gamepad may be altered by other threads var gamepad = _gamepad; - + if (gamepad != null && GamepadDriver != null) { State = gamepad.GetMappedStateSnapshot(); + if (gamepad.spetialExit()) + { + return true; + } + if (_config is StandardControllerInputConfig controllerConfig && controllerConfig.Motion.EnableMotion) { if (controllerConfig.Motion.MotionBackend == MotionInputBackendType.GamepadDriver) @@ -334,6 +341,7 @@ public void Update() State = default; _leftMotionInput = null; } + return false; } public GamepadInput GetHLEInputState() diff --git a/src/Ryujinx.Input/HLE/NpadManager.cs b/src/Ryujinx.Input/HLE/NpadManager.cs index 08f222a918..6955f1d2e7 100644 --- a/src/Ryujinx.Input/HLE/NpadManager.cs +++ b/src/Ryujinx.Input/HLE/NpadManager.cs @@ -200,8 +200,10 @@ public void Initialize(Switch device, List inputConfig, bool enable ReloadConfiguration(inputConfig, enableKeyboard, enableMouse); } - public void Update(float aspectRatio = 1) + public bool Update(float aspectRatio = 1) { + bool spetialExit = false; + lock (_lock) { List hleInputStates = new(); @@ -225,9 +227,9 @@ public void Update(float aspectRatio = 1) DriverConfigurationUpdate(ref controller, inputConfig); controller.UpdateUserConfiguration(inputConfig); - controller.Update(); + spetialExit = controller.Update(); //hotkey press check controller.UpdateRumble(_device.Hid.Npads.GetRumbleQueue(playerIndex)); - + inputState = controller.GetHLEInputState(); inputState.Buttons |= _device.Hid.UpdateStickButtons(inputState.LStick, inputState.RStick); @@ -315,6 +317,8 @@ public void Update(float aspectRatio = 1) _device.TamperMachine.UpdateInput(hleInputStates); } + + return spetialExit; } internal InputConfig GetPlayerInputConfigByIndex(int index) diff --git a/src/Ryujinx.Input/IGamepad.cs b/src/Ryujinx.Input/IGamepad.cs index 3853f28196..8e6a8e33fe 100644 --- a/src/Ryujinx.Input/IGamepad.cs +++ b/src/Ryujinx.Input/IGamepad.cs @@ -79,6 +79,12 @@ public interface IGamepad : IDisposable /// A remapped snaphost of the state of the gamepad. GamepadStateSnapshot GetMappedStateSnapshot(); + /// + /// Gets the state if the minus and plus buttons were pressed on the gamepad. + /// + /// returns true if the buttons were pressed. + bool spetialExit(); + /// /// Get a snaphost of the state of the gamepad. /// diff --git a/src/Ryujinx/AppHost.cs b/src/Ryujinx/AppHost.cs index a35a79e864..c16cd5e119 100644 --- a/src/Ryujinx/AppHost.cs +++ b/src/Ryujinx/AppHost.cs @@ -18,6 +18,7 @@ using Ryujinx.Ava.UI.Models; using Ryujinx.Ava.UI.Renderer; using Ryujinx.Ava.UI.ViewModels; +using Ryujinx.Ava.UI.Views.Main; using Ryujinx.Ava.UI.Windows; using Ryujinx.Ava.Utilities; using Ryujinx.Ava.Utilities.AppLibrary; @@ -70,6 +71,7 @@ internal class AppHost private const float MaxResolutionScale = 4.0f; // Max resolution hotkeys can scale to before wrapping. private const int TargetFps = 60; private const float VolumeDelta = 0.05f; + static bool spetialExit = false; private static readonly Cursor _invisibleCursor = new(StandardCursorType.None); private readonly nint _invisibleCursorWin; @@ -96,6 +98,7 @@ internal class AppHost private bool _isCursorInRenderer = true; private bool _ignoreCursorState = false; + private enum CursorStates { CursorIsHidden, @@ -503,10 +506,15 @@ public void Start() _viewModel.Volume = ConfigurationState.Instance.System.AudioVolume.Value; MainLoop(); - + Exit(); } + public bool IsSpecialExit() + { + return spetialExit; + } + private void UpdateIgnoreMissingServicesState(object sender, ReactiveEventArgs args) { if (Device != null) @@ -589,6 +597,7 @@ private void Exit() _isStopped = true; Stop(); + } public void DisposeContext() @@ -1023,12 +1032,12 @@ private void Window_BoundsChanged(object sender, Size e) } private void MainLoop() - { + { while (UpdateFrame()) { - // Polling becomes expensive if it's not slept. Thread.Sleep(1); } + } private void RenderLoop() @@ -1135,6 +1144,7 @@ public void UpdateStatus() string dockedMode = ConfigurationState.Instance.System.EnableDockedMode ? LocaleManager.Instance[LocaleKeys.Docked] : LocaleManager.Instance[LocaleKeys.Handheld]; string vSyncMode = Device.VSyncMode.ToString(); + UpdateShaderCount(); if (GraphicsConfig.ResScale != 1) @@ -1200,7 +1210,29 @@ private bool UpdateFrame() return false; } - NpadManager.Update(ConfigurationState.Instance.Graphics.AspectRatio.Value.ToFloat()); + if (NpadManager.Update(ConfigurationState.Instance.Graphics.AspectRatio.Value.ToFloat())) + { + if (ConfigurationState.Instance.Hid.SpetialExitEmulator.Value == 1) + { + spetialExit = true; + } + + + _isActive = false; + } + + if (NpadManager.Update(ConfigurationState.Instance.Graphics.AspectRatio.Value.ToFloat())) + { + if (ConfigurationState.Instance.Hid.SpetialExitEmulator.Value == 1) + { + spetialExit = true; // close App + } + if (ConfigurationState.Instance.Hid.SpetialExitEmulator.Value > 0) + { + + _isActive = false; //close game + } + } if (_viewModel.IsActive) { @@ -1335,6 +1367,8 @@ private bool UpdateFrame() Device.Hid.DebugPad.Update(); + + return true; } diff --git a/src/Ryujinx/Assets/locales.json b/src/Ryujinx/Assets/locales.json index 0951ad6325..634cc60eb3 100644 --- a/src/Ryujinx/Assets/locales.json +++ b/src/Ryujinx/Assets/locales.json @@ -147,6 +147,31 @@ "zh_TW": "滑鼠直接存取" } }, + { + "ID": "SettingsExtraCloseApp", + "Translations": { + "ar_SA": "خروج سريع من التطبيق", + "de_DE": "Schneller Ausstieg aus der Anwendung", + "el_GR": "Γρήγορη έξοδος από την εφαρμογή", + "en_US": "Quick Exit from Application", + "es_ES": "Salida rápida de la aplicación", + "fr_FR": "Sortie rapide de l'application", + "he_IL": "יציאה מהירה מהאפליקציה", + "it_IT": "Uscita rapida dall'applicazione", + "ja_JP": "アプリケーションからの迅速な終了", + "ko_KR": "애플리케이션에서 빠른 종료", + "no_NO": "Rask avslutning av applikasjonen", + "pl_PL": "Szybkie wyjście z aplikacji", + "pt_BR": "Saída rápida do aplicativo", + "ru_RU": "Быстрый выход из приложения", + "sv_SE": "Snabb avslutning från applikationen", + "th_TH": "ออกจากแอปพลิเคชันอย่างรวดเร็ว", + "tr_TR": "Uygulamadan Hızlı Çıkış", + "uk_UA": "Швидкий вихід з програми", + "zh_CN": "快速退出应用程序", + "zh_TW": "快速退出應用程式" + } + }, { "ID": "SettingsTabSystemMemoryManagerMode", "Translations": { @@ -11047,6 +11072,81 @@ "zh_TW": "淺色" } }, + { + "ID": "SettingsTabInputDisableExitHotKey", + "Translations": { + "ar_SA": "الخروج السريع معطل", + "de_DE": "Schneller Ausstieg deaktiviert", + "el_GR": "Η γρήγορη έξοδος είναι απενεργοποιημένη", + "en_US": "Quick exit disabled", + "es_ES": "Salida rápida desactivada", + "fr_FR": "Sortie rapide désactivée", + "he_IL": "יציאה מהירה מושבתת", + "it_IT": "Uscita rapida disabilitata", + "ja_JP": "クイック終了が無効です", + "ko_KR": "빠른 종료 비활성화됨", + "no_NO": "Rask avslutning er deaktivert", + "pl_PL": "Szybkie wyjście wyłączone", + "pt_BR": "Saída rápida desativada", + "ru_RU": "Быстрый выход выключен", + "sv_SE": "Snabb avslutning inaktiverad", + "th_TH": "ปิดใช้งานออกอย่างรวดเร็ว", + "tr_TR": "Hızlı çıkış devre dışı bırakıldı", + "uk_UA": "Швидкий вихід вимкнено", + "zh_CN": "快速退出已禁用", + "zh_TW": "快速退出已停用" + } + }, + { + "ID": "SettingsTabInputHotkeyIsCloseApp", + "Translations": { + "ar_SA": "إغلاق التطبيق بالضغط على الزرين '+' و '-'.", + "de_DE": "App schließen mit den '+' und '-' Tasten.", + "el_GR": "Κλείσιμο της εφαρμογής με τα κουμπιά '+' και '-'.", + "en_US": "Close app by '+' and '-' buttons.", + "es_ES": "Cerrar la aplicación pulsando los botones '+' y '-'.", + "fr_FR": "Fermer l'application avec les boutons '+' et '-'.", + "he_IL": "סגור את האפליקציה בלחיצה על '+' ו-'-'.", + "it_IT": "Chiudi l'app premendo i pulsanti '+' e '-'.", + "ja_JP": "「+」と「-」ボタンを押してアプリを終了します。", + "ko_KR": "'+' 및 '-' 버튼을 눌러 앱을 종료합니다.", + "no_NO": "Lukk appen med '+' og '-' knappene.", + "pl_PL": "Zamknij aplikację przyciskiem '+' i '-'.", + "pt_BR": "Fechar o aplicativo pressionando os botões '+' e '-'.", + "ru_RU": "Закрыть приложение нажатием '+' и '-'.", + "sv_SE": "Stäng appen med '+' och '-' knapparna.", + "th_TH": "ปิดแอปโดยกดปุ่ม '+' และ '-'.", + "tr_TR": "'+' ve '-' düğmelerine basarak uygulamayı kapatın.", + "uk_UA": "Закрити додаток натисканням '+' та '-'.", + "zh_CN": "", + "zh_TW": "" + } + }, + { + "ID": "SettingsTabInputHotkeyIsCloseGame", + "Translations": { + "ar_SA": "الخروج من اللعبة بالضغط على الزرين '+' و '-'.", + "de_DE": "Spiel beenden mit den '+' und '-' Tasten.", + "el_GR": "Έξοδος από το παιχνίδι με τα κουμπιά '+' και '-'.", + "en_US": "Exit game by '+' and '-' buttons.", + "es_ES": "Salir del juego pulsando los botones '+' y '-'.", + "fr_FR": "Quitter le jeu avec les boutons '+' et '-'.", + "he_IL": "יציאה מהמשחק בלחיצה על '+' ו-'-'.", + "it_IT": "Esci dal gioco premendo i pulsanti '+' e '-'.", + "ja_JP": "「+」と「-」ボタンを押してゲームを終了します。", + "ko_KR": "'+' 및 '-' 버튼을 눌러 게임을 종료합니다.", + "no_NO": "Avslutt spillet med '+' og '-' knappene.", + "pl_PL": "Wyjście z gry przyciskiem '+' i '-'.", + "pt_BR": "Sair do jogo pressionando os botões '+' e '-'.", + "ru_RU": "Выйти из игры нажатием '+' и '-'.", + "sv_SE": "Avsluta spelet med '+' och '-' knapparna.", + "th_TH": "ออกจากเกมโดยกดปุ่ม '+' และ '-'.", + "tr_TR": "'+' ve '-' düğmelerine basarak oyundan çıkın.", + "uk_UA": "Вийти з гри натисканням '+' та '-'.", + "zh_CN": "", + "zh_TW": "" + } + }, { "ID": "ControllerSettingsConfigureGeneral", "Translations": { @@ -15147,6 +15247,31 @@ "zh_TW": "支援滑鼠直接存取 (HID)。遊戲可將滑鼠作為指向裝置使用。\n\n僅適用於在 Switch 硬體上原生支援滑鼠控制的遊戲,這類遊戲很少。\n\n啟用後,觸控螢幕功能可能無法使用。\n\n如果不確定,請保持關閉狀態。" } }, + { + "ID": "spetialExitTooltip", + "Translations": { + "ar_SA": "يقوم بتفعيل مفاتيح الاختصار 'زائد' و 'ناقص'.\nاضغط على زرّي زائد وناقص في نفس الوقت لتنفيذ إحدى العمليات:\n\n1) إغلاق التطبيق باستخدام مفاتيح الاختصار.\n2) الخروج من اللعبة دون إغلاق التطبيق.\n\nيعمل فقط مع أذرع التحكم.", + "de_DE": "Aktiviert die Hotkeys 'Plus' und 'Minus'.\nDrücken Sie gleichzeitig die Plus- und Minus-Tasten, um eine der folgenden Aktionen auszuführen:\n\n1) Schließt die Anwendung durch Drücken der Hotkeys.\n2) Beendet das Spiel, ohne die Anwendung zu schließen.\n\nFunktioniert nur mit Gamepads.", + "el_GR": "Ενεργοποιεί τα πλήκτρα πρόσβασης 'συν' και 'πλην'.\nΠατήστε ταυτόχρονα τα κουμπιά συν και πλην για μία από τις ενέργειες:\n\n1) Κλείνει την εφαρμογή πατώντας τα πλήκτρα πρόσβασης.\n2) Εξέρχεται από το παιχνίδι χωρίς να κλείσει η εφαρμογή.\n\nΛειτουργεί μόνο με gamepads.", + "en_US": "Activates the hot keys 'plus' and 'minus'.\nPress buttons plus and minus at the same time to get one of the actions:\n\n1) Closes the application by pressing the hot keys.\n2) Exits the game without closing the application.\n\nWorks only with gamepads.", + "es_ES": "Activa las teclas rápidas 'más' y 'menos'.\nPresiona los botones más y menos al mismo tiempo para realizar una de las siguientes acciones:\n\n1) Cierra la aplicación presionando las teclas rápidas.\n2) Salir del juego sin cerrar la aplicación.\n\nFunciona solo con mandos.", + "fr_FR": "Active les raccourcis 'plus' et 'moins'.\nAppuyez simultanément sur les boutons plus et moins pour effectuer l'une des actions suivantes :\n\n1) Ferme l'application en appuyant sur les raccourcis.\n2) Quitte le jeu sans fermer l'application.\n\nFonctionne uniquement avec les manettes.", + "he_IL": "מפעיל את המקשים הקצרים 'פלוס' ו-'מינוס'.\nלחץ על הכפתורים פלוס ומינוס בו זמנית כדי לבצע אחת מהפעולות:\n\n1) סוגר את היישום באמצעות המקשים הקצרים.\n2) יוצא מהמשחק מבלי לסגור את היישום.\n\nפועל רק עם בקרי משחק.", + "it_IT": "Attiva i tasti rapidi 'più' e 'meno'.\nPremere i pulsanti più e meno contemporaneamente per eseguire una delle seguenti azioni:\n\n1) Chiude l'applicazione premendo i tasti rapidi.\n2) Esce dal gioco senza chiudere l'applicazione.\n\nFunziona solo con i gamepad.", + "ja_JP": "ホットキー「プラス」と「マイナス」を有効化します。\nプラスとマイナスのボタンを同時に押して、次のいずれかの操作を実行します:\n\n1) ホットキーを押すことでアプリを閉じます。\n2) アプリを閉じずにゲームを終了します。\n\nゲームパッドでのみ動作します。", + "ko_KR": "'플러스' 및 '마이너스' 단축키를 활성화합니다.\n플러스 및 마이너스 버튼을 동시에 눌러 다음 작업 중 하나를 수행합니다:\n\n1) 단축키를 눌러 애플리케이션을 닫습니다.\n2) 애플리케이션을 닫지 않고 게임을 종료합니다.\n\n게임패드에서만 작동합니다.", + "no_NO": "Aktiverer hurtigtastene 'pluss' og 'minus'.\nTrykk på knappene pluss og minus samtidig for å utføre en av følgende handlinger:\n\n1) Lukker applikasjonen ved å trykke på hurtigtastene.\n2) Avslutter spillet uten å lukke applikasjonen.\n\nFungerer kun med spillkontroller.", + "pl_PL": "Aktywuje klawisze skrótu 'plus' i 'minus'.\nNaciśnij jednocześnie przyciski plus i minus, aby wykonać jedną z akcji:\n\n1) Zamknij aplikację, naciskając klawisze skrótu.\n2) Wyjdź z gry bez zamykania aplikacji.\n\nDziała tylko z gamepadami.", + "pt_BR": "Ativa as teclas de atalho 'mais' e 'menos'.\nPressione os botões mais e menos ao mesmo tempo para realizar uma das ações:\n\n1) Fecha o aplicativo pressionando as teclas de atalho.\n2) Sai do jogo sem fechar o aplicativo.\n\nFunciona apenas com gamepads.", + "ru_RU": "Активирует горячие клавиши 'плюс' и 'минус'.\nНажмите одновременно кнопки плюс и минус чтобы получить одно из действий:\n\n1) Закрывает приложение по нажатию горячих кнопок.\n2) Выходит из игры без закрытия приложения.\n\nРаботает только с геймпадами.", + "sv_SE": "Aktiverar snabbtangenterna 'plus' och 'minus'.\nTryck samtidigt på plus- och minusknapparna för att utföra en av följande åtgärder:\n\n1) Stänger applikationen med snabbtangenterna.\n2) Avslutar spelet utan att stänga applikationen.\n\nFungerar bara med spelkontroller.", + "th_TH": "เปิดใช้งานปุ่มลัด '+' และ '-'.\nกดปุ่ม '+' และ '-' พร้อมกันเพื่อทำการอย่างใดอย่างหนึ่ง:\n\n1) ปิดแอปพลิเคชันด้วยการกดปุ่มลัด\n2) ออกจากเกมโดยไม่ปิดแอปพลิเคชัน\n\nใช้งานได้เฉพาะกับจอยเกม", + "tr_TR": "'Artı' ve 'eksi' kısayol tuşlarını etkinleştirir.\nArtı ve eksi tuşlarına aynı anda basarak aşağıdaki işlemlerden birini gerçekleştirin:\n\n1) Kısayol tuşlarına basarak uygulamayı kapatır.\n2) Uygulamayı kapatmadan oyundan çıkar.\n\nYalnızca gamepad'lerle çalışır.", + "uk_UA": "Активує гарячі клавіші '+' та '-'.\nНатисніть одночасно кнопки плюс та мінус для виконання однієї з дій:\n\n1) Закриває додаток за допомогою гарячих клавіш.\n2) Виходить із гри без закриття додатка.\n\nПрацює лише з геймпадами.", + "zh_CN": "激活快捷键“加号”和“减号”。\n同时按下加号和减号按钮以执行以下操作之一:\n\n1) 按快捷键关闭应用程序。\n2) 退出游戏而不关闭应用程序。\n\n仅适用于游戏手柄。", + "zh_TW": "啟用快捷鍵「加號」和「減號」。\n同時按下加號和減號按鈕以執行以下其中一項操作:\n\n1) 按快捷鍵關閉應用程式。\n2) 離開遊戲而不關閉應用程式。\n\n僅適用於遊戲手柄。" + } + }, { "ID": "RegionTooltip", "Translations": { diff --git a/src/Ryujinx/Headless/HeadlessRyujinx.cs b/src/Ryujinx/Headless/HeadlessRyujinx.cs index 5730254f73..4be23245d1 100644 --- a/src/Ryujinx/Headless/HeadlessRyujinx.cs +++ b/src/Ryujinx/Headless/HeadlessRyujinx.cs @@ -350,11 +350,11 @@ private static WindowBase CreateWindow(Options options) { return options.GraphicsBackend switch { - GraphicsBackend.Vulkan => new VulkanWindow(_inputManager, options.LoggingGraphicsDebugLevel, options.AspectRatio, options.EnableMouse, options.HideCursorMode, options.IgnoreControllerApplet), + GraphicsBackend.Vulkan => new VulkanWindow(_inputManager, options.LoggingGraphicsDebugLevel, options.AspectRatio, options.EnableMouse, options.HideCursorMode, options.IgnoreControllerApplet, options.spetialExit), GraphicsBackend.Metal => OperatingSystem.IsMacOS() ? - new MetalWindow(_inputManager, options.LoggingGraphicsDebugLevel, options.AspectRatio, options.EnableKeyboard, options.HideCursorMode, options.IgnoreControllerApplet) : + new MetalWindow(_inputManager, options.LoggingGraphicsDebugLevel, options.AspectRatio, options.EnableKeyboard, options.HideCursorMode, options.IgnoreControllerApplet, options.spetialExit) : throw new Exception("Attempted to use Metal renderer on non-macOS platform!"), - _ => new OpenGLWindow(_inputManager, options.LoggingGraphicsDebugLevel, options.AspectRatio, options.EnableMouse, options.HideCursorMode, options.IgnoreControllerApplet) + _ => new OpenGLWindow(_inputManager, options.LoggingGraphicsDebugLevel, options.AspectRatio, options.EnableMouse, options.HideCursorMode, options.IgnoreControllerApplet, options.spetialExit) }; } diff --git a/src/Ryujinx/Headless/Metal/MetalWindow.cs b/src/Ryujinx/Headless/Metal/MetalWindow.cs index a2693c69d0..3afe65ae1a 100644 --- a/src/Ryujinx/Headless/Metal/MetalWindow.cs +++ b/src/Ryujinx/Headless/Metal/MetalWindow.cs @@ -23,8 +23,9 @@ public MetalWindow( AspectRatio aspectRatio, bool enableMouse, HideCursorMode hideCursorMode, - bool ignoreControllerApplet) - : base(inputManager, glLogLevel, aspectRatio, enableMouse, hideCursorMode, ignoreControllerApplet) { } + bool ignoreControllerApplet, + int SpetialExitEmulator) + : base(inputManager, glLogLevel, aspectRatio, enableMouse, hideCursorMode, ignoreControllerApplet, SpetialExitEmulator) { } public override SDL_WindowFlags GetWindowFlags() => SDL_WindowFlags.SDL_WINDOW_METAL; diff --git a/src/Ryujinx/Headless/OpenGL/OpenGLWindow.cs b/src/Ryujinx/Headless/OpenGL/OpenGLWindow.cs index c00a0648fd..eedf740172 100644 --- a/src/Ryujinx/Headless/OpenGL/OpenGLWindow.cs +++ b/src/Ryujinx/Headless/OpenGL/OpenGLWindow.cs @@ -118,8 +118,9 @@ public OpenGLWindow( AspectRatio aspectRatio, bool enableMouse, HideCursorMode hideCursorMode, - bool ignoreControllerApplet) - : base(inputManager, glLogLevel, aspectRatio, enableMouse, hideCursorMode, ignoreControllerApplet) + bool ignoreControllerApplet, + int SpetialExitEmulator) + : base(inputManager, glLogLevel, aspectRatio, enableMouse, hideCursorMode, ignoreControllerApplet, SpetialExitEmulator) { _glLogLevel = glLogLevel; } diff --git a/src/Ryujinx/Headless/Options.cs b/src/Ryujinx/Headless/Options.cs index 0d7e462851..c4cedb4e24 100644 --- a/src/Ryujinx/Headless/Options.cs +++ b/src/Ryujinx/Headless/Options.cs @@ -150,7 +150,10 @@ public void InheritMainConfig(string[] originalArgs, ConfigurationState configur if (NeedsOverride(nameof(IgnoreControllerApplet))) IgnoreControllerApplet = configurationState.IgnoreApplet; - + + if (NeedsOverride(nameof(spetialExit))) + spetialExit = configurationState.Hid.SpetialExitEmulator; + return; bool NeedsOverride(string argKey) => originalArgs.None(arg => arg.TrimStart('-').EqualsIgnoreCase(OptionName(argKey))); @@ -274,6 +277,9 @@ private static string OptionName(string propertyName) => [Option("enable-mouse", Required = false, Default = false, HelpText = "Enable or disable mouse support.")] public bool EnableMouse { get; set; } + [Option("enable-press-hotkeys-to-exit", Required = false, Default = 0, HelpText = "press the minus and plus buttons to: 0 -disable, 1 - exit app, 2 - exit game.")] + public int spetialExit { get; set; } + [Option("hide-cursor", Required = false, Default = HideCursorMode.OnIdle, HelpText = "Change when the cursor gets hidden.")] public HideCursorMode HideCursorMode { get; set; } @@ -414,6 +420,7 @@ private static string OptionName(string propertyName) => [Option("ignore-controller-applet", Required = false, Default = false, HelpText = "Enable ignoring the controller applet when your game loses connection to your controller.")] public bool IgnoreControllerApplet { get; set; } + // Values [Value(0, MetaName = "input", HelpText = "Input to load.", Required = true)] diff --git a/src/Ryujinx/Headless/Vulkan/VulkanWindow.cs b/src/Ryujinx/Headless/Vulkan/VulkanWindow.cs index 92caad34e0..d31586718c 100644 --- a/src/Ryujinx/Headless/Vulkan/VulkanWindow.cs +++ b/src/Ryujinx/Headless/Vulkan/VulkanWindow.cs @@ -18,8 +18,9 @@ public VulkanWindow( AspectRatio aspectRatio, bool enableMouse, HideCursorMode hideCursorMode, - bool ignoreControllerApplet) - : base(inputManager, glLogLevel, aspectRatio, enableMouse, hideCursorMode, ignoreControllerApplet) + bool ignoreControllerApplet, + int SpetialExitEmulator) + : base(inputManager, glLogLevel, aspectRatio, enableMouse, hideCursorMode, ignoreControllerApplet, SpetialExitEmulator) { _glLogLevel = glLogLevel; } diff --git a/src/Ryujinx/Headless/WindowBase.cs b/src/Ryujinx/Headless/WindowBase.cs index d89638cc12..f302802574 100644 --- a/src/Ryujinx/Headless/WindowBase.cs +++ b/src/Ryujinx/Headless/WindowBase.cs @@ -88,6 +88,7 @@ public static void QueueMainThreadAction(Action action) private readonly AspectRatio _aspectRatio; private readonly bool _enableMouse; + private readonly int _SpetialExitEmulator; private readonly bool _ignoreControllerApplet; public WindowBase( @@ -96,7 +97,8 @@ public WindowBase( AspectRatio aspectRatio, bool enableMouse, HideCursorMode hideCursorMode, - bool ignoreControllerApplet) + bool ignoreControllerApplet, + int SpetialExitEmulator) { MouseDriver = new SDL2MouseDriver(hideCursorMode); _inputManager = inputManager; @@ -112,6 +114,7 @@ public WindowBase( _gpuDoneEvent = new ManualResetEvent(false); _aspectRatio = aspectRatio; _enableMouse = enableMouse; + _SpetialExitEmulator = SpetialExitEmulator; _ignoreControllerApplet = ignoreControllerApplet; HostUITheme = new HeadlessHostUiTheme(); diff --git a/src/Ryujinx/Input/AvaloniaKeyboard.cs b/src/Ryujinx/Input/AvaloniaKeyboard.cs index 0b63af2d9b..12a4d6f469 100644 --- a/src/Ryujinx/Input/AvaloniaKeyboard.cs +++ b/src/Ryujinx/Input/AvaloniaKeyboard.cs @@ -30,6 +30,11 @@ private class ButtonMappingEntry(GamepadButtonInputId to, Key from) public readonly Key From = from; } + public bool spetialExit() + { + return false; + } + public AvaloniaKeyboard(AvaloniaKeyboardDriver driver, string id, string name) { _buttonsUserMapping = []; diff --git a/src/Ryujinx/Input/AvaloniaMouse.cs b/src/Ryujinx/Input/AvaloniaMouse.cs index 1aa2d586a3..871c16bc74 100644 --- a/src/Ryujinx/Input/AvaloniaMouse.cs +++ b/src/Ryujinx/Input/AvaloniaMouse.cs @@ -13,6 +13,11 @@ internal class AvaloniaMouse : IMouse public string Id => "0"; public string Name => "AvaloniaMouse"; + public bool spetialExit() + { + return false; + } + public bool IsConnected => true; public GamepadFeaturesFlag Features => throw new NotImplementedException(); public bool[] Buttons => _driver.PressedButtons; diff --git a/src/Ryujinx/UI/ViewModels/MainWindowViewModel.cs b/src/Ryujinx/UI/ViewModels/MainWindowViewModel.cs index e11d855a6d..25e1136b84 100644 --- a/src/Ryujinx/UI/ViewModels/MainWindowViewModel.cs +++ b/src/Ryujinx/UI/ViewModels/MainWindowViewModel.cs @@ -1046,6 +1046,7 @@ private void PrepareLoadScreen() private void InitializeGame() { + RendererHostControl.WindowCreated += RendererHost_Created; AppHost.StatusUpdatedEvent += Update_StatusBar; @@ -1055,7 +1056,13 @@ private void InitializeGame() AppHost?.Start(); + if (AppHost?.IsSpecialExit() == true) + { + Window.ForceExit(); + } + AppHost?.DisposeContext(); + } private async Task HandleRelaunch() diff --git a/src/Ryujinx/UI/ViewModels/SettingsViewModel.cs b/src/Ryujinx/UI/ViewModels/SettingsViewModel.cs index 2678bbf983..bda93b83d9 100644 --- a/src/Ryujinx/UI/ViewModels/SettingsViewModel.cs +++ b/src/Ryujinx/UI/ViewModels/SettingsViewModel.cs @@ -128,6 +128,7 @@ public float CustomResolutionScale public bool EnableDockedMode { get; set; } public bool EnableKeyboard { get; set; } public bool EnableMouse { get; set; } + public int EnableSpetialExit { get; set; } public VSyncMode VSyncMode { get => _vSyncMode; @@ -259,6 +260,8 @@ public int ScalingFilterLevel public int OpenglDebugLevel { get; set; } public int MemoryMode { get; set; } public int BaseStyleIndex { get; set; } + + public int GraphicsBackendIndex { get => _graphicsBackendIndex; @@ -511,6 +514,13 @@ public void LoadCurrentConfiguration() EnableDockedMode = config.System.EnableDockedMode; EnableKeyboard = config.Hid.EnableKeyboard; EnableMouse = config.Hid.EnableMouse; + EnableSpetialExit = config.Hid.SpetialExitEmulator.Value switch + { + 0=> 0, //"Hotkey 'Exit' is Disabled" + 1=> 1, //"Close app. by hotkey" + 2=> 2, // "Close game by hotkey" + _ => 0 //"Hotkey 'Exit' is Disabled" + }; // Keyboard Hotkeys KeyboardHotkey = new HotkeyConfig(config.Hid.Hotkeys.Value); @@ -618,6 +628,13 @@ public void SaveSettings() config.System.EnableDockedMode.Value = EnableDockedMode; config.Hid.EnableKeyboard.Value = EnableKeyboard; config.Hid.EnableMouse.Value = EnableMouse; + config.Hid.SpetialExitEmulator.Value = EnableSpetialExit switch + { + 0 => 0, //"Hotkey 'Exit' is Disabled", + 1 => 1, //"Close app. by hotkey", + 2 => 2, //"Close game by hotkey", + _ => 0, //"Hotkey 'Exit' is Disabled" + }; // Keyboard Hotkeys config.Hid.Hotkeys.Value = KeyboardHotkey.GetConfig(); diff --git a/src/Ryujinx/UI/Views/Settings/SettingsInputView.axaml b/src/Ryujinx/UI/Views/Settings/SettingsInputView.axaml index b0edc51a58..1874912330 100644 --- a/src/Ryujinx/UI/Views/Settings/SettingsInputView.axaml +++ b/src/Ryujinx/UI/Views/Settings/SettingsInputView.axaml @@ -1,4 +1,4 @@ - + + + + + + + + + + + diff --git a/src/Ryujinx/UI/Windows/MainWindow.axaml.cs b/src/Ryujinx/UI/Windows/MainWindow.axaml.cs index e5a815b28b..baee0f66fa 100644 --- a/src/Ryujinx/UI/Windows/MainWindow.axaml.cs +++ b/src/Ryujinx/UI/Windows/MainWindow.axaml.cs @@ -45,6 +45,7 @@ public partial class MainWindow : StyleableAppWindow internal readonly AvaHostUIHandler UiHandler; private bool _isLoading; + private bool _isExitWithoutConfirm = false; private bool _applicationsLoadedOnce; private UserChannelPersistence _userChannelPersistence; @@ -574,11 +575,11 @@ private void VolumeStatus_CheckedChanged(object sender, RoutedEventArgs e) protected override void OnClosing(WindowClosingEventArgs e) { - if (!ViewModel.IsClosing && ViewModel.AppHost != null && ConfigurationState.Instance.ShowConfirmExit) + if (!ViewModel.IsClosing && ViewModel.AppHost != null && ConfigurationState.Instance.ShowConfirmExit && !_isExitWithoutConfirm) { e.Cancel = true; - ConfirmExit(); + ConfirmExit(); return; } @@ -619,6 +620,12 @@ protected override void OnClosing(WindowClosingEventArgs e) base.OnClosing(e); } + public void ForceExit() { + + _isExitWithoutConfirm = true; + Close(); + } + private void ConfirmExit() { Dispatcher.UIThread.InvokeAsync(async () => diff --git a/src/Ryujinx/Utilities/Configuration/ConfigurationFileFormat.cs b/src/Ryujinx/Utilities/Configuration/ConfigurationFileFormat.cs index 947dd5c8fd..96d5543ab0 100644 --- a/src/Ryujinx/Utilities/Configuration/ConfigurationFileFormat.cs +++ b/src/Ryujinx/Utilities/Configuration/ConfigurationFileFormat.cs @@ -17,7 +17,7 @@ public class ConfigurationFileFormat /// /// The current version of the file format /// - public const int CurrentVersion = 59; + public const int CurrentVersion = 60; /// /// Version of the configuration file format @@ -366,6 +366,11 @@ public class ConfigurationFileFormat /// public bool EnableMouse { get; set; } + /// + /// Allows you to choose from three options: do nothing, exit the application, exit the emulator + /// + public int SpetialExitEmulator { get; set; } + /// /// Hotkey Keyboard Bindings /// diff --git a/src/Ryujinx/Utilities/Configuration/ConfigurationState.Migration.cs b/src/Ryujinx/Utilities/Configuration/ConfigurationState.Migration.cs index ec66bcaac1..c627fe29af 100644 --- a/src/Ryujinx/Utilities/Configuration/ConfigurationState.Migration.cs +++ b/src/Ryujinx/Utilities/Configuration/ConfigurationState.Migration.cs @@ -136,6 +136,7 @@ in _migrations.OrderBy(x => x.Key)) Hid.EnableKeyboard.Value = cff.EnableKeyboard; Hid.EnableMouse.Value = cff.EnableMouse; + Hid.SpetialExitEmulator.Value = cff.SpetialExitEmulator; Hid.Hotkeys.Value = cff.Hotkeys; Hid.InputConfig.Value = cff.InputConfig ?? []; @@ -414,6 +415,10 @@ in _migrations.OrderBy(x => x.Key)) // This was accidentally enabled by default when it was PRed. That is not what we want, // so as a compromise users who want to use it will simply need to re-enable it once after updating. cff.IgnoreApplet = false; + }), + (60, static cff => + { + cff.SpetialExitEmulator = 1; }) ); } diff --git a/src/Ryujinx/Utilities/Configuration/ConfigurationState.Model.cs b/src/Ryujinx/Utilities/Configuration/ConfigurationState.Model.cs index fe5f2c3ad6..6965c8efc6 100644 --- a/src/Ryujinx/Utilities/Configuration/ConfigurationState.Model.cs +++ b/src/Ryujinx/Utilities/Configuration/ConfigurationState.Model.cs @@ -420,6 +420,11 @@ public class HidSection /// public ReactiveObject EnableMouse { get; private set; } + /// + /// Allows you to choose from three options: do nothing, exit the application, exit the emulator + /// + public ReactiveObject SpetialExitEmulator { get; private set; } + /// /// Hotkey Keyboard Bindings /// @@ -436,6 +441,7 @@ public HidSection() { EnableKeyboard = new ReactiveObject(); EnableMouse = new ReactiveObject(); + SpetialExitEmulator = new ReactiveObject(); Hotkeys = new ReactiveObject(); InputConfig = new ReactiveObject>(); } diff --git a/src/Ryujinx/Utilities/Configuration/ConfigurationState.cs b/src/Ryujinx/Utilities/Configuration/ConfigurationState.cs index 95ec62e838..20c120f7d2 100644 --- a/src/Ryujinx/Utilities/Configuration/ConfigurationState.cs +++ b/src/Ryujinx/Utilities/Configuration/ConfigurationState.cs @@ -128,6 +128,7 @@ public ConfigurationFileFormat ToFileFormat() ShowConsole = UI.ShowConsole, EnableKeyboard = Hid.EnableKeyboard, EnableMouse = Hid.EnableMouse, + SpetialExitEmulator = Hid.SpetialExitEmulator, Hotkeys = Hid.Hotkeys, KeyboardConfig = [], ControllerConfig = [], @@ -241,6 +242,7 @@ public void LoadDefault() UI.WindowStartup.WindowMaximized.Value = false; Hid.EnableKeyboard.Value = false; Hid.EnableMouse.Value = false; + Hid.SpetialExitEmulator.Value = 0; Hid.Hotkeys.Value = new KeyboardHotkeys { ToggleVSyncMode = Key.F1, From b6667a8352fb4fc07728581b1a325e77047dd622 Mon Sep 17 00:00:00 2001 From: Vova Date: Wed, 8 Jan 2025 22:45:33 +1000 Subject: [PATCH 06/15] multiple fixes, variable typo fixes, adherence to a certain style. Fixed initialization of the new function, defaults to 0 --- src/Ryujinx.Input.SDL2/SDL2Gamepad.cs | 10 ++++----- src/Ryujinx.Input.SDL2/SDL2Keyboard.cs | 2 +- src/Ryujinx.Input.SDL2/SDL2Mouse.cs | 2 +- src/Ryujinx.Input/HLE/NpadController.cs | 2 +- src/Ryujinx.Input/HLE/NpadManager.cs | 8 ++++--- src/Ryujinx.Input/IGamepad.cs | 2 +- src/Ryujinx/AppHost.cs | 14 ++++++------ src/Ryujinx/Assets/locales.json | 2 +- src/Ryujinx/Headless/HeadlessRyujinx.cs | 6 ++--- src/Ryujinx/Headless/Metal/MetalWindow.cs | 4 ++-- src/Ryujinx/Headless/OpenGL/OpenGLWindow.cs | 4 ++-- src/Ryujinx/Headless/Options.cs | 6 ++--- src/Ryujinx/Headless/Vulkan/VulkanWindow.cs | 4 ++-- src/Ryujinx/Headless/WindowBase.cs | 6 ++--- src/Ryujinx/Input/AvaloniaKeyboard.cs | 2 +- src/Ryujinx/Input/AvaloniaMouse.cs | 2 +- .../UI/ViewModels/SettingsViewModel.cs | 22 +++++++++---------- .../UI/Views/Settings/SettingsInputView.axaml | 4 ++-- .../Configuration/ConfigurationFileFormat.cs | 2 +- .../ConfigurationState.Migration.cs | 4 ++-- .../Configuration/ConfigurationState.Model.cs | 4 ++-- .../Configuration/ConfigurationState.cs | 4 ++-- 22 files changed, 59 insertions(+), 57 deletions(-) diff --git a/src/Ryujinx.Input.SDL2/SDL2Gamepad.cs b/src/Ryujinx.Input.SDL2/SDL2Gamepad.cs index 26aa496a38..7e8bd4167f 100644 --- a/src/Ryujinx.Input.SDL2/SDL2Gamepad.cs +++ b/src/Ryujinx.Input.SDL2/SDL2Gamepad.cs @@ -254,16 +254,16 @@ public GamepadStateSnapshot GetStateSnapshot() } private static bool hotButtonMinus = false; - private static bool HotExit = false; + private static bool hotExit = false; - public bool spetialExit() + public bool SpecialExit() { if (hotButtonMinus) { hotButtonMinus = false; - return HotExit; + return hotExit; } - return HotExit = false; + return hotExit = false; } public GamepadStateSnapshot GetMappedStateSnapshot() @@ -299,7 +299,7 @@ public GamepadStateSnapshot GetMappedStateSnapshot() if (rawState.IsPressed(entry.To) && hotButtonMinus) { - HotExit = true; + hotExit = true; } } diff --git a/src/Ryujinx.Input.SDL2/SDL2Keyboard.cs b/src/Ryujinx.Input.SDL2/SDL2Keyboard.cs index 0fd25a54ea..ab01a9bbc7 100644 --- a/src/Ryujinx.Input.SDL2/SDL2Keyboard.cs +++ b/src/Ryujinx.Input.SDL2/SDL2Keyboard.cs @@ -329,7 +329,7 @@ public GamepadStateSnapshot GetMappedStateSnapshot() return result; } - public bool spetialExit() + public bool SpecialExit() { return false; } diff --git a/src/Ryujinx.Input.SDL2/SDL2Mouse.cs b/src/Ryujinx.Input.SDL2/SDL2Mouse.cs index d3f64d5ed2..da0622db3e 100644 --- a/src/Ryujinx.Input.SDL2/SDL2Mouse.cs +++ b/src/Ryujinx.Input.SDL2/SDL2Mouse.cs @@ -25,7 +25,7 @@ public SDL2Mouse(SDL2MouseDriver driver) { _driver = driver; } - public bool spetialExit() + public bool SpecialExit() { return false; } diff --git a/src/Ryujinx.Input/HLE/NpadController.cs b/src/Ryujinx.Input/HLE/NpadController.cs index 991311d02e..f41c2af7f1 100644 --- a/src/Ryujinx.Input/HLE/NpadController.cs +++ b/src/Ryujinx.Input/HLE/NpadController.cs @@ -284,7 +284,7 @@ public bool Update() { State = gamepad.GetMappedStateSnapshot(); - if (gamepad.spetialExit()) + if (gamepad.SpecialExit()) { return true; } diff --git a/src/Ryujinx.Input/HLE/NpadManager.cs b/src/Ryujinx.Input/HLE/NpadManager.cs index 6955f1d2e7..9d07d9c22b 100644 --- a/src/Ryujinx.Input/HLE/NpadManager.cs +++ b/src/Ryujinx.Input/HLE/NpadManager.cs @@ -202,7 +202,7 @@ public void Initialize(Switch device, List inputConfig, bool enable public bool Update(float aspectRatio = 1) { - bool spetialExit = false; + bool specialExit = false; lock (_lock) { @@ -227,7 +227,9 @@ public bool Update(float aspectRatio = 1) DriverConfigurationUpdate(ref controller, inputConfig); controller.UpdateUserConfiguration(inputConfig); - spetialExit = controller.Update(); //hotkey press check + + specialExit = controller.Update(); //hotkey press check + controller.UpdateRumble(_device.Hid.Npads.GetRumbleQueue(playerIndex)); inputState = controller.GetHLEInputState(); @@ -318,7 +320,7 @@ public bool Update(float aspectRatio = 1) _device.TamperMachine.UpdateInput(hleInputStates); } - return spetialExit; + return specialExit; } internal InputConfig GetPlayerInputConfigByIndex(int index) diff --git a/src/Ryujinx.Input/IGamepad.cs b/src/Ryujinx.Input/IGamepad.cs index 8e6a8e33fe..f52703e193 100644 --- a/src/Ryujinx.Input/IGamepad.cs +++ b/src/Ryujinx.Input/IGamepad.cs @@ -83,7 +83,7 @@ public interface IGamepad : IDisposable /// Gets the state if the minus and plus buttons were pressed on the gamepad. /// /// returns true if the buttons were pressed. - bool spetialExit(); + bool SpecialExit(); /// /// Get a snaphost of the state of the gamepad. diff --git a/src/Ryujinx/AppHost.cs b/src/Ryujinx/AppHost.cs index c16cd5e119..c98c7c9643 100644 --- a/src/Ryujinx/AppHost.cs +++ b/src/Ryujinx/AppHost.cs @@ -71,7 +71,7 @@ internal class AppHost private const float MaxResolutionScale = 4.0f; // Max resolution hotkeys can scale to before wrapping. private const int TargetFps = 60; private const float VolumeDelta = 0.05f; - static bool spetialExit = false; + static bool SpecialExit = false; private static readonly Cursor _invisibleCursor = new(StandardCursorType.None); private readonly nint _invisibleCursorWin; @@ -512,7 +512,7 @@ public void Start() public bool IsSpecialExit() { - return spetialExit; + return SpecialExit; } private void UpdateIgnoreMissingServicesState(object sender, ReactiveEventArgs args) @@ -1212,9 +1212,9 @@ private bool UpdateFrame() if (NpadManager.Update(ConfigurationState.Instance.Graphics.AspectRatio.Value.ToFloat())) { - if (ConfigurationState.Instance.Hid.SpetialExitEmulator.Value == 1) + if (ConfigurationState.Instance.Hid.specialExitEmulator.Value == 1) { - spetialExit = true; + SpecialExit = true; } @@ -1223,11 +1223,11 @@ private bool UpdateFrame() if (NpadManager.Update(ConfigurationState.Instance.Graphics.AspectRatio.Value.ToFloat())) { - if (ConfigurationState.Instance.Hid.SpetialExitEmulator.Value == 1) + if (ConfigurationState.Instance.Hid.specialExitEmulator.Value == 1) { - spetialExit = true; // close App + SpecialExit = true; // close App } - if (ConfigurationState.Instance.Hid.SpetialExitEmulator.Value > 0) + if (ConfigurationState.Instance.Hid.specialExitEmulator.Value > 0) { _isActive = false; //close game diff --git a/src/Ryujinx/Assets/locales.json b/src/Ryujinx/Assets/locales.json index 634cc60eb3..7c4978f0f9 100644 --- a/src/Ryujinx/Assets/locales.json +++ b/src/Ryujinx/Assets/locales.json @@ -15248,7 +15248,7 @@ } }, { - "ID": "spetialExitTooltip", + "ID": "SpecialExitTooltip", "Translations": { "ar_SA": "يقوم بتفعيل مفاتيح الاختصار 'زائد' و 'ناقص'.\nاضغط على زرّي زائد وناقص في نفس الوقت لتنفيذ إحدى العمليات:\n\n1) إغلاق التطبيق باستخدام مفاتيح الاختصار.\n2) الخروج من اللعبة دون إغلاق التطبيق.\n\nيعمل فقط مع أذرع التحكم.", "de_DE": "Aktiviert die Hotkeys 'Plus' und 'Minus'.\nDrücken Sie gleichzeitig die Plus- und Minus-Tasten, um eine der folgenden Aktionen auszuführen:\n\n1) Schließt die Anwendung durch Drücken der Hotkeys.\n2) Beendet das Spiel, ohne die Anwendung zu schließen.\n\nFunktioniert nur mit Gamepads.", diff --git a/src/Ryujinx/Headless/HeadlessRyujinx.cs b/src/Ryujinx/Headless/HeadlessRyujinx.cs index 4be23245d1..98636d4ffb 100644 --- a/src/Ryujinx/Headless/HeadlessRyujinx.cs +++ b/src/Ryujinx/Headless/HeadlessRyujinx.cs @@ -350,11 +350,11 @@ private static WindowBase CreateWindow(Options options) { return options.GraphicsBackend switch { - GraphicsBackend.Vulkan => new VulkanWindow(_inputManager, options.LoggingGraphicsDebugLevel, options.AspectRatio, options.EnableMouse, options.HideCursorMode, options.IgnoreControllerApplet, options.spetialExit), + GraphicsBackend.Vulkan => new VulkanWindow(_inputManager, options.LoggingGraphicsDebugLevel, options.AspectRatio, options.EnableMouse, options.HideCursorMode, options.IgnoreControllerApplet, options.SpecialExit), GraphicsBackend.Metal => OperatingSystem.IsMacOS() ? - new MetalWindow(_inputManager, options.LoggingGraphicsDebugLevel, options.AspectRatio, options.EnableKeyboard, options.HideCursorMode, options.IgnoreControllerApplet, options.spetialExit) : + new MetalWindow(_inputManager, options.LoggingGraphicsDebugLevel, options.AspectRatio, options.EnableKeyboard, options.HideCursorMode, options.IgnoreControllerApplet, options.SpecialExit) : throw new Exception("Attempted to use Metal renderer on non-macOS platform!"), - _ => new OpenGLWindow(_inputManager, options.LoggingGraphicsDebugLevel, options.AspectRatio, options.EnableMouse, options.HideCursorMode, options.IgnoreControllerApplet, options.spetialExit) + _ => new OpenGLWindow(_inputManager, options.LoggingGraphicsDebugLevel, options.AspectRatio, options.EnableMouse, options.HideCursorMode, options.IgnoreControllerApplet, options.SpecialExit) }; } diff --git a/src/Ryujinx/Headless/Metal/MetalWindow.cs b/src/Ryujinx/Headless/Metal/MetalWindow.cs index 3afe65ae1a..1ae8f5ee45 100644 --- a/src/Ryujinx/Headless/Metal/MetalWindow.cs +++ b/src/Ryujinx/Headless/Metal/MetalWindow.cs @@ -24,8 +24,8 @@ public MetalWindow( bool enableMouse, HideCursorMode hideCursorMode, bool ignoreControllerApplet, - int SpetialExitEmulator) - : base(inputManager, glLogLevel, aspectRatio, enableMouse, hideCursorMode, ignoreControllerApplet, SpetialExitEmulator) { } + int specialExitEmulator) + : base(inputManager, glLogLevel, aspectRatio, enableMouse, hideCursorMode, ignoreControllerApplet, specialExitEmulator) { } public override SDL_WindowFlags GetWindowFlags() => SDL_WindowFlags.SDL_WINDOW_METAL; diff --git a/src/Ryujinx/Headless/OpenGL/OpenGLWindow.cs b/src/Ryujinx/Headless/OpenGL/OpenGLWindow.cs index eedf740172..ca4f488610 100644 --- a/src/Ryujinx/Headless/OpenGL/OpenGLWindow.cs +++ b/src/Ryujinx/Headless/OpenGL/OpenGLWindow.cs @@ -119,8 +119,8 @@ public OpenGLWindow( bool enableMouse, HideCursorMode hideCursorMode, bool ignoreControllerApplet, - int SpetialExitEmulator) - : base(inputManager, glLogLevel, aspectRatio, enableMouse, hideCursorMode, ignoreControllerApplet, SpetialExitEmulator) + int specialExitEmulator) + : base(inputManager, glLogLevel, aspectRatio, enableMouse, hideCursorMode, ignoreControllerApplet, specialExitEmulator) { _glLogLevel = glLogLevel; } diff --git a/src/Ryujinx/Headless/Options.cs b/src/Ryujinx/Headless/Options.cs index c4cedb4e24..62edea4979 100644 --- a/src/Ryujinx/Headless/Options.cs +++ b/src/Ryujinx/Headless/Options.cs @@ -151,8 +151,8 @@ public void InheritMainConfig(string[] originalArgs, ConfigurationState configur if (NeedsOverride(nameof(IgnoreControllerApplet))) IgnoreControllerApplet = configurationState.IgnoreApplet; - if (NeedsOverride(nameof(spetialExit))) - spetialExit = configurationState.Hid.SpetialExitEmulator; + if (NeedsOverride(nameof(SpecialExit))) + SpecialExit = configurationState.Hid.specialExitEmulator; return; @@ -278,7 +278,7 @@ private static string OptionName(string propertyName) => public bool EnableMouse { get; set; } [Option("enable-press-hotkeys-to-exit", Required = false, Default = 0, HelpText = "press the minus and plus buttons to: 0 -disable, 1 - exit app, 2 - exit game.")] - public int spetialExit { get; set; } + public int SpecialExit { get; set; } [Option("hide-cursor", Required = false, Default = HideCursorMode.OnIdle, HelpText = "Change when the cursor gets hidden.")] public HideCursorMode HideCursorMode { get; set; } diff --git a/src/Ryujinx/Headless/Vulkan/VulkanWindow.cs b/src/Ryujinx/Headless/Vulkan/VulkanWindow.cs index d31586718c..9819bbc9b2 100644 --- a/src/Ryujinx/Headless/Vulkan/VulkanWindow.cs +++ b/src/Ryujinx/Headless/Vulkan/VulkanWindow.cs @@ -19,8 +19,8 @@ public VulkanWindow( bool enableMouse, HideCursorMode hideCursorMode, bool ignoreControllerApplet, - int SpetialExitEmulator) - : base(inputManager, glLogLevel, aspectRatio, enableMouse, hideCursorMode, ignoreControllerApplet, SpetialExitEmulator) + int specialExitEmulator) + : base(inputManager, glLogLevel, aspectRatio, enableMouse, hideCursorMode, ignoreControllerApplet, specialExitEmulator) { _glLogLevel = glLogLevel; } diff --git a/src/Ryujinx/Headless/WindowBase.cs b/src/Ryujinx/Headless/WindowBase.cs index f302802574..4e4d5a4d48 100644 --- a/src/Ryujinx/Headless/WindowBase.cs +++ b/src/Ryujinx/Headless/WindowBase.cs @@ -88,7 +88,7 @@ public static void QueueMainThreadAction(Action action) private readonly AspectRatio _aspectRatio; private readonly bool _enableMouse; - private readonly int _SpetialExitEmulator; + private readonly int _specialExitEmulator; private readonly bool _ignoreControllerApplet; public WindowBase( @@ -98,7 +98,7 @@ public WindowBase( bool enableMouse, HideCursorMode hideCursorMode, bool ignoreControllerApplet, - int SpetialExitEmulator) + int specialExitEmulator) { MouseDriver = new SDL2MouseDriver(hideCursorMode); _inputManager = inputManager; @@ -114,7 +114,7 @@ public WindowBase( _gpuDoneEvent = new ManualResetEvent(false); _aspectRatio = aspectRatio; _enableMouse = enableMouse; - _SpetialExitEmulator = SpetialExitEmulator; + _specialExitEmulator = specialExitEmulator; _ignoreControllerApplet = ignoreControllerApplet; HostUITheme = new HeadlessHostUiTheme(); diff --git a/src/Ryujinx/Input/AvaloniaKeyboard.cs b/src/Ryujinx/Input/AvaloniaKeyboard.cs index 12a4d6f469..8936513ca9 100644 --- a/src/Ryujinx/Input/AvaloniaKeyboard.cs +++ b/src/Ryujinx/Input/AvaloniaKeyboard.cs @@ -30,7 +30,7 @@ private class ButtonMappingEntry(GamepadButtonInputId to, Key from) public readonly Key From = from; } - public bool spetialExit() + public bool SpecialExit() { return false; } diff --git a/src/Ryujinx/Input/AvaloniaMouse.cs b/src/Ryujinx/Input/AvaloniaMouse.cs index 871c16bc74..cdcdc2106f 100644 --- a/src/Ryujinx/Input/AvaloniaMouse.cs +++ b/src/Ryujinx/Input/AvaloniaMouse.cs @@ -13,7 +13,7 @@ internal class AvaloniaMouse : IMouse public string Id => "0"; public string Name => "AvaloniaMouse"; - public bool spetialExit() + public bool SpecialExit() { return false; } diff --git a/src/Ryujinx/UI/ViewModels/SettingsViewModel.cs b/src/Ryujinx/UI/ViewModels/SettingsViewModel.cs index bda93b83d9..bbb78e912a 100644 --- a/src/Ryujinx/UI/ViewModels/SettingsViewModel.cs +++ b/src/Ryujinx/UI/ViewModels/SettingsViewModel.cs @@ -128,7 +128,7 @@ public float CustomResolutionScale public bool EnableDockedMode { get; set; } public bool EnableKeyboard { get; set; } public bool EnableMouse { get; set; } - public int EnableSpetialExit { get; set; } + public int EnableSpecialExit { get; set; } public VSyncMode VSyncMode { get => _vSyncMode; @@ -514,12 +514,12 @@ public void LoadCurrentConfiguration() EnableDockedMode = config.System.EnableDockedMode; EnableKeyboard = config.Hid.EnableKeyboard; EnableMouse = config.Hid.EnableMouse; - EnableSpetialExit = config.Hid.SpetialExitEmulator.Value switch + EnableSpecialExit = config.Hid.specialExitEmulator.Value switch { - 0=> 0, //"Hotkey 'Exit' is Disabled" - 1=> 1, //"Close app. by hotkey" - 2=> 2, // "Close game by hotkey" - _ => 0 //"Hotkey 'Exit' is Disabled" + 0=> 0, // "Hotkey 'Exit' is Disabled" + 1=> 1, // "Close app. by hotkey" + 2=> 2, // "Close game by hotkey" + _ => 0 // "Hotkey 'Exit' is Disabled" }; // Keyboard Hotkeys @@ -628,12 +628,12 @@ public void SaveSettings() config.System.EnableDockedMode.Value = EnableDockedMode; config.Hid.EnableKeyboard.Value = EnableKeyboard; config.Hid.EnableMouse.Value = EnableMouse; - config.Hid.SpetialExitEmulator.Value = EnableSpetialExit switch + config.Hid.specialExitEmulator.Value = EnableSpecialExit switch { - 0 => 0, //"Hotkey 'Exit' is Disabled", - 1 => 1, //"Close app. by hotkey", - 2 => 2, //"Close game by hotkey", - _ => 0, //"Hotkey 'Exit' is Disabled" + 0 => 0, // "Hotkey 'Exit' is Disabled", + 1 => 1, // "Close app. by hotkey", + 2 => 2, // "Close game by hotkey", + _ => 0, // "Hotkey 'Exit' is Disabled" }; // Keyboard Hotkeys diff --git a/src/Ryujinx/UI/Views/Settings/SettingsInputView.axaml b/src/Ryujinx/UI/Views/Settings/SettingsInputView.axaml index 1874912330..0333525483 100644 --- a/src/Ryujinx/UI/Views/Settings/SettingsInputView.axaml +++ b/src/Ryujinx/UI/Views/Settings/SettingsInputView.axaml @@ -58,8 +58,8 @@ - diff --git a/src/Ryujinx/Utilities/Configuration/ConfigurationFileFormat.cs b/src/Ryujinx/Utilities/Configuration/ConfigurationFileFormat.cs index 96d5543ab0..9fb2169d93 100644 --- a/src/Ryujinx/Utilities/Configuration/ConfigurationFileFormat.cs +++ b/src/Ryujinx/Utilities/Configuration/ConfigurationFileFormat.cs @@ -369,7 +369,7 @@ public class ConfigurationFileFormat /// /// Allows you to choose from three options: do nothing, exit the application, exit the emulator /// - public int SpetialExitEmulator { get; set; } + public int specialExitEmulator { get; set; } /// /// Hotkey Keyboard Bindings diff --git a/src/Ryujinx/Utilities/Configuration/ConfigurationState.Migration.cs b/src/Ryujinx/Utilities/Configuration/ConfigurationState.Migration.cs index c627fe29af..2308a1508c 100644 --- a/src/Ryujinx/Utilities/Configuration/ConfigurationState.Migration.cs +++ b/src/Ryujinx/Utilities/Configuration/ConfigurationState.Migration.cs @@ -136,7 +136,7 @@ in _migrations.OrderBy(x => x.Key)) Hid.EnableKeyboard.Value = cff.EnableKeyboard; Hid.EnableMouse.Value = cff.EnableMouse; - Hid.SpetialExitEmulator.Value = cff.SpetialExitEmulator; + Hid.specialExitEmulator.Value = cff.specialExitEmulator; Hid.Hotkeys.Value = cff.Hotkeys; Hid.InputConfig.Value = cff.InputConfig ?? []; @@ -418,7 +418,7 @@ in _migrations.OrderBy(x => x.Key)) }), (60, static cff => { - cff.SpetialExitEmulator = 1; + cff.specialExitEmulator = 0; }) ); } diff --git a/src/Ryujinx/Utilities/Configuration/ConfigurationState.Model.cs b/src/Ryujinx/Utilities/Configuration/ConfigurationState.Model.cs index 6965c8efc6..e19b128a69 100644 --- a/src/Ryujinx/Utilities/Configuration/ConfigurationState.Model.cs +++ b/src/Ryujinx/Utilities/Configuration/ConfigurationState.Model.cs @@ -423,7 +423,7 @@ public class HidSection /// /// Allows you to choose from three options: do nothing, exit the application, exit the emulator /// - public ReactiveObject SpetialExitEmulator { get; private set; } + public ReactiveObject specialExitEmulator { get; private set; } /// /// Hotkey Keyboard Bindings @@ -441,7 +441,7 @@ public HidSection() { EnableKeyboard = new ReactiveObject(); EnableMouse = new ReactiveObject(); - SpetialExitEmulator = new ReactiveObject(); + specialExitEmulator = new ReactiveObject(); Hotkeys = new ReactiveObject(); InputConfig = new ReactiveObject>(); } diff --git a/src/Ryujinx/Utilities/Configuration/ConfigurationState.cs b/src/Ryujinx/Utilities/Configuration/ConfigurationState.cs index 20c120f7d2..861dae74b2 100644 --- a/src/Ryujinx/Utilities/Configuration/ConfigurationState.cs +++ b/src/Ryujinx/Utilities/Configuration/ConfigurationState.cs @@ -128,7 +128,7 @@ public ConfigurationFileFormat ToFileFormat() ShowConsole = UI.ShowConsole, EnableKeyboard = Hid.EnableKeyboard, EnableMouse = Hid.EnableMouse, - SpetialExitEmulator = Hid.SpetialExitEmulator, + specialExitEmulator = Hid.specialExitEmulator, Hotkeys = Hid.Hotkeys, KeyboardConfig = [], ControllerConfig = [], @@ -242,7 +242,7 @@ public void LoadDefault() UI.WindowStartup.WindowMaximized.Value = false; Hid.EnableKeyboard.Value = false; Hid.EnableMouse.Value = false; - Hid.SpetialExitEmulator.Value = 0; + Hid.specialExitEmulator.Value = 0; Hid.Hotkeys.Value = new KeyboardHotkeys { ToggleVSyncMode = Key.F1, From c20452be61e6c7ce89ac6d8db885a9950553be41 Mon Sep 17 00:00:00 2001 From: Vova Date: Wed, 8 Jan 2025 23:00:41 +1000 Subject: [PATCH 07/15] Fixed a bug where the emulator would still terminate the game when pressing a hotkey (unnecessary check removed) --- src/Ryujinx/AppHost.cs | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/src/Ryujinx/AppHost.cs b/src/Ryujinx/AppHost.cs index c98c7c9643..910f1213e9 100644 --- a/src/Ryujinx/AppHost.cs +++ b/src/Ryujinx/AppHost.cs @@ -1210,17 +1210,6 @@ private bool UpdateFrame() return false; } - if (NpadManager.Update(ConfigurationState.Instance.Graphics.AspectRatio.Value.ToFloat())) - { - if (ConfigurationState.Instance.Hid.specialExitEmulator.Value == 1) - { - SpecialExit = true; - } - - - _isActive = false; - } - if (NpadManager.Update(ConfigurationState.Instance.Graphics.AspectRatio.Value.ToFloat())) { if (ConfigurationState.Instance.Hid.specialExitEmulator.Value == 1) @@ -1229,7 +1218,6 @@ private bool UpdateFrame() } if (ConfigurationState.Instance.Hid.specialExitEmulator.Value > 0) { - _isActive = false; //close game } } From 1c6390cbfbcbaaec6a977391e4e1ed99814fadbe Mon Sep 17 00:00:00 2001 From: Vova Date: Wed, 8 Jan 2025 23:05:58 +1000 Subject: [PATCH 08/15] minor bugs fixed --- src/Ryujinx.Input/HLE/NpadManager.cs | 1 - src/Ryujinx/UI/ViewModels/SettingsViewModel.cs | 8 ++++---- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/src/Ryujinx.Input/HLE/NpadManager.cs b/src/Ryujinx.Input/HLE/NpadManager.cs index 9d07d9c22b..4ebb8401d9 100644 --- a/src/Ryujinx.Input/HLE/NpadManager.cs +++ b/src/Ryujinx.Input/HLE/NpadManager.cs @@ -229,7 +229,6 @@ public bool Update(float aspectRatio = 1) controller.UpdateUserConfiguration(inputConfig); specialExit = controller.Update(); //hotkey press check - controller.UpdateRumble(_device.Hid.Npads.GetRumbleQueue(playerIndex)); inputState = controller.GetHLEInputState(); diff --git a/src/Ryujinx/UI/ViewModels/SettingsViewModel.cs b/src/Ryujinx/UI/ViewModels/SettingsViewModel.cs index bbb78e912a..0950b3174b 100644 --- a/src/Ryujinx/UI/ViewModels/SettingsViewModel.cs +++ b/src/Ryujinx/UI/ViewModels/SettingsViewModel.cs @@ -516,10 +516,10 @@ public void LoadCurrentConfiguration() EnableMouse = config.Hid.EnableMouse; EnableSpecialExit = config.Hid.specialExitEmulator.Value switch { - 0=> 0, // "Hotkey 'Exit' is Disabled" - 1=> 1, // "Close app. by hotkey" - 2=> 2, // "Close game by hotkey" - _ => 0 // "Hotkey 'Exit' is Disabled" + 0=> 0, // "Hotkey 'Exit' is Disabled" + 1=> 1, // "Close app. by hotkey" + 2=> 2, // "Close game by hotkey" + _=> 0 // "Hotkey 'Exit' is Disabled" }; // Keyboard Hotkeys From 0c503e10aee982ed54fca18a9ad2998225e82643 Mon Sep 17 00:00:00 2001 From: Vladimir Sokolov Date: Wed, 8 Jan 2025 23:09:09 +1000 Subject: [PATCH 09/15] Update SettingsViewModel.cs --- src/Ryujinx/UI/ViewModels/SettingsViewModel.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Ryujinx/UI/ViewModels/SettingsViewModel.cs b/src/Ryujinx/UI/ViewModels/SettingsViewModel.cs index 0950b3174b..462b6c5595 100644 --- a/src/Ryujinx/UI/ViewModels/SettingsViewModel.cs +++ b/src/Ryujinx/UI/ViewModels/SettingsViewModel.cs @@ -516,10 +516,10 @@ public void LoadCurrentConfiguration() EnableMouse = config.Hid.EnableMouse; EnableSpecialExit = config.Hid.specialExitEmulator.Value switch { - 0=> 0, // "Hotkey 'Exit' is Disabled" - 1=> 1, // "Close app. by hotkey" - 2=> 2, // "Close game by hotkey" - _=> 0 // "Hotkey 'Exit' is Disabled" + 0 => 0, // "Hotkey 'Exit' is Disabled" + 1 => 1, // "Close app. by hotkey" + 2 => 2, // "Close game by hotkey" + _ => 0 // "Hotkey 'Exit' is Disabled" }; // Keyboard Hotkeys From 3352d70ea4ef3d07f18e28232d2c6efa102a420c Mon Sep 17 00:00:00 2001 From: Vladimir Sokolov Date: Sat, 11 Jan 2025 10:43:38 +1000 Subject: [PATCH 10/15] Update SettingsViewModel.cs small fix --- src/Ryujinx/UI/ViewModels/SettingsViewModel.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Ryujinx/UI/ViewModels/SettingsViewModel.cs b/src/Ryujinx/UI/ViewModels/SettingsViewModel.cs index 462b6c5595..e99db5d74d 100644 --- a/src/Ryujinx/UI/ViewModels/SettingsViewModel.cs +++ b/src/Ryujinx/UI/ViewModels/SettingsViewModel.cs @@ -519,7 +519,7 @@ public void LoadCurrentConfiguration() 0 => 0, // "Hotkey 'Exit' is Disabled" 1 => 1, // "Close app. by hotkey" 2 => 2, // "Close game by hotkey" - _ => 0 // "Hotkey 'Exit' is Disabled" + _ => 0 }; // Keyboard Hotkeys @@ -633,7 +633,7 @@ public void SaveSettings() 0 => 0, // "Hotkey 'Exit' is Disabled", 1 => 1, // "Close app. by hotkey", 2 => 2, // "Close game by hotkey", - _ => 0, // "Hotkey 'Exit' is Disabled" + _ => 0 }; // Keyboard Hotkeys From 01e22f1c6707220570aab0e9b4adc471ff05b839 Mon Sep 17 00:00:00 2001 From: Evan Husted Date: Fri, 10 Jan 2025 21:13:39 -0600 Subject: [PATCH 11/15] newline brace --- src/Ryujinx/UI/Windows/MainWindow.axaml.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Ryujinx/UI/Windows/MainWindow.axaml.cs b/src/Ryujinx/UI/Windows/MainWindow.axaml.cs index baee0f66fa..f5d23642c2 100644 --- a/src/Ryujinx/UI/Windows/MainWindow.axaml.cs +++ b/src/Ryujinx/UI/Windows/MainWindow.axaml.cs @@ -620,8 +620,8 @@ protected override void OnClosing(WindowClosingEventArgs e) base.OnClosing(e); } - public void ForceExit() { - + public void ForceExit() + { _isExitWithoutConfirm = true; Close(); } From 78e7a3085aa189800c12daf05dd2c9efe11cdcba Mon Sep 17 00:00:00 2001 From: Evan Husted Date: Fri, 10 Jan 2025 21:16:31 -0600 Subject: [PATCH 12/15] add back a comment that was removed for no reason --- src/Ryujinx/AppHost.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Ryujinx/AppHost.cs b/src/Ryujinx/AppHost.cs index 910f1213e9..d5b6cce505 100644 --- a/src/Ryujinx/AppHost.cs +++ b/src/Ryujinx/AppHost.cs @@ -1032,12 +1032,12 @@ private void Window_BoundsChanged(object sender, Size e) } private void MainLoop() - { + { while (UpdateFrame()) { + // Polling becomes expensive if it's not slept. Thread.Sleep(1); } - } private void RenderLoop() From 11f1922a82e870c37a849d6ea8a5d8801a6fe692 Mon Sep 17 00:00:00 2001 From: Vova Date: Sat, 11 Jan 2025 22:20:08 +1000 Subject: [PATCH 13/15] fix specialExitEmulator -> SpecialExitEmulator, Added description to clarify function --- src/Ryujinx/AppHost.cs | 4 ++-- src/Ryujinx/Headless/Options.cs | 2 +- src/Ryujinx/UI/ViewModels/SettingsViewModel.cs | 4 ++-- .../Utilities/Configuration/ConfigurationFileFormat.cs | 2 +- .../Configuration/ConfigurationState.Migration.cs | 2 +- .../Utilities/Configuration/ConfigurationState.Model.cs | 8 +++++--- src/Ryujinx/Utilities/Configuration/ConfigurationState.cs | 4 ++-- 7 files changed, 14 insertions(+), 12 deletions(-) diff --git a/src/Ryujinx/AppHost.cs b/src/Ryujinx/AppHost.cs index d5b6cce505..c94e869d53 100644 --- a/src/Ryujinx/AppHost.cs +++ b/src/Ryujinx/AppHost.cs @@ -1212,11 +1212,11 @@ private bool UpdateFrame() if (NpadManager.Update(ConfigurationState.Instance.Graphics.AspectRatio.Value.ToFloat())) { - if (ConfigurationState.Instance.Hid.specialExitEmulator.Value == 1) + if (ConfigurationState.Instance.Hid.SpecialExitEmulator.Value == 1) { SpecialExit = true; // close App } - if (ConfigurationState.Instance.Hid.specialExitEmulator.Value > 0) + if (ConfigurationState.Instance.Hid.SpecialExitEmulator.Value > 0) { _isActive = false; //close game } diff --git a/src/Ryujinx/Headless/Options.cs b/src/Ryujinx/Headless/Options.cs index 62edea4979..c575416be4 100644 --- a/src/Ryujinx/Headless/Options.cs +++ b/src/Ryujinx/Headless/Options.cs @@ -152,7 +152,7 @@ public void InheritMainConfig(string[] originalArgs, ConfigurationState configur IgnoreControllerApplet = configurationState.IgnoreApplet; if (NeedsOverride(nameof(SpecialExit))) - SpecialExit = configurationState.Hid.specialExitEmulator; + SpecialExit = configurationState.Hid.SpecialExitEmulator; return; diff --git a/src/Ryujinx/UI/ViewModels/SettingsViewModel.cs b/src/Ryujinx/UI/ViewModels/SettingsViewModel.cs index e99db5d74d..ad82b4d620 100644 --- a/src/Ryujinx/UI/ViewModels/SettingsViewModel.cs +++ b/src/Ryujinx/UI/ViewModels/SettingsViewModel.cs @@ -514,7 +514,7 @@ public void LoadCurrentConfiguration() EnableDockedMode = config.System.EnableDockedMode; EnableKeyboard = config.Hid.EnableKeyboard; EnableMouse = config.Hid.EnableMouse; - EnableSpecialExit = config.Hid.specialExitEmulator.Value switch + EnableSpecialExit = config.Hid.SpecialExitEmulator.Value switch { 0 => 0, // "Hotkey 'Exit' is Disabled" 1 => 1, // "Close app. by hotkey" @@ -628,7 +628,7 @@ public void SaveSettings() config.System.EnableDockedMode.Value = EnableDockedMode; config.Hid.EnableKeyboard.Value = EnableKeyboard; config.Hid.EnableMouse.Value = EnableMouse; - config.Hid.specialExitEmulator.Value = EnableSpecialExit switch + config.Hid.SpecialExitEmulator.Value = EnableSpecialExit switch { 0 => 0, // "Hotkey 'Exit' is Disabled", 1 => 1, // "Close app. by hotkey", diff --git a/src/Ryujinx/Utilities/Configuration/ConfigurationFileFormat.cs b/src/Ryujinx/Utilities/Configuration/ConfigurationFileFormat.cs index 9fb2169d93..ab2e36aaed 100644 --- a/src/Ryujinx/Utilities/Configuration/ConfigurationFileFormat.cs +++ b/src/Ryujinx/Utilities/Configuration/ConfigurationFileFormat.cs @@ -369,7 +369,7 @@ public class ConfigurationFileFormat /// /// Allows you to choose from three options: do nothing, exit the application, exit the emulator /// - public int specialExitEmulator { get; set; } + public int SpecialExitEmulator { get; set; } /// /// Hotkey Keyboard Bindings diff --git a/src/Ryujinx/Utilities/Configuration/ConfigurationState.Migration.cs b/src/Ryujinx/Utilities/Configuration/ConfigurationState.Migration.cs index 2308a1508c..4fb189c769 100644 --- a/src/Ryujinx/Utilities/Configuration/ConfigurationState.Migration.cs +++ b/src/Ryujinx/Utilities/Configuration/ConfigurationState.Migration.cs @@ -136,7 +136,7 @@ in _migrations.OrderBy(x => x.Key)) Hid.EnableKeyboard.Value = cff.EnableKeyboard; Hid.EnableMouse.Value = cff.EnableMouse; - Hid.specialExitEmulator.Value = cff.specialExitEmulator; + Hid.SpecialExitEmulator.Value = cff.SpecialExitEmulator; Hid.Hotkeys.Value = cff.Hotkeys; Hid.InputConfig.Value = cff.InputConfig ?? []; diff --git a/src/Ryujinx/Utilities/Configuration/ConfigurationState.Model.cs b/src/Ryujinx/Utilities/Configuration/ConfigurationState.Model.cs index e19b128a69..85bede2d5e 100644 --- a/src/Ryujinx/Utilities/Configuration/ConfigurationState.Model.cs +++ b/src/Ryujinx/Utilities/Configuration/ConfigurationState.Model.cs @@ -421,9 +421,11 @@ public class HidSection public ReactiveObject EnableMouse { get; private set; } /// - /// Allows you to choose from three options: do nothing, exit the application, exit the emulator + /// Allows you to choose one of several behaviors when pressing hotkeys: + /// 0 - Do nothing, 1 - Close the emulator application, 2 - Exit the game. /// - public ReactiveObject specialExitEmulator { get; private set; } + public ReactiveObject SpecialExitEmulator { get; private set; } + /// /// Hotkey Keyboard Bindings @@ -441,7 +443,7 @@ public HidSection() { EnableKeyboard = new ReactiveObject(); EnableMouse = new ReactiveObject(); - specialExitEmulator = new ReactiveObject(); + SpecialExitEmulator = new ReactiveObject(); Hotkeys = new ReactiveObject(); InputConfig = new ReactiveObject>(); } diff --git a/src/Ryujinx/Utilities/Configuration/ConfigurationState.cs b/src/Ryujinx/Utilities/Configuration/ConfigurationState.cs index 861dae74b2..b68f97826e 100644 --- a/src/Ryujinx/Utilities/Configuration/ConfigurationState.cs +++ b/src/Ryujinx/Utilities/Configuration/ConfigurationState.cs @@ -128,7 +128,7 @@ public ConfigurationFileFormat ToFileFormat() ShowConsole = UI.ShowConsole, EnableKeyboard = Hid.EnableKeyboard, EnableMouse = Hid.EnableMouse, - specialExitEmulator = Hid.specialExitEmulator, + SpecialExitEmulator = Hid.SpecialExitEmulator, Hotkeys = Hid.Hotkeys, KeyboardConfig = [], ControllerConfig = [], @@ -242,7 +242,7 @@ public void LoadDefault() UI.WindowStartup.WindowMaximized.Value = false; Hid.EnableKeyboard.Value = false; Hid.EnableMouse.Value = false; - Hid.specialExitEmulator.Value = 0; + Hid.SpecialExitEmulator.Value = 0; Hid.Hotkeys.Value = new KeyboardHotkeys { ToggleVSyncMode = Key.F1, From f75efbea5400075efd22c461977b363cfd6a0e71 Mon Sep 17 00:00:00 2001 From: Vova Date: Sat, 11 Jan 2025 22:27:28 +1000 Subject: [PATCH 14/15] oops, rename to"SpecialExitEmulator" --- .../Utilities/Configuration/ConfigurationState.Migration.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Ryujinx/Utilities/Configuration/ConfigurationState.Migration.cs b/src/Ryujinx/Utilities/Configuration/ConfigurationState.Migration.cs index 4fb189c769..f341c5f154 100644 --- a/src/Ryujinx/Utilities/Configuration/ConfigurationState.Migration.cs +++ b/src/Ryujinx/Utilities/Configuration/ConfigurationState.Migration.cs @@ -418,7 +418,7 @@ in _migrations.OrderBy(x => x.Key)) }), (60, static cff => { - cff.specialExitEmulator = 0; + cff.SpecialExitEmulator = 0; }) ); } From 2ec032c48bcc642f6b654e44460df25c3b121cb6 Mon Sep 17 00:00:00 2001 From: Vova Date: Sat, 11 Jan 2025 22:37:33 +1000 Subject: [PATCH 15/15] Added description in another file --- src/Ryujinx/Utilities/Configuration/ConfigurationFileFormat.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Ryujinx/Utilities/Configuration/ConfigurationFileFormat.cs b/src/Ryujinx/Utilities/Configuration/ConfigurationFileFormat.cs index ab2e36aaed..a0cfaec0cf 100644 --- a/src/Ryujinx/Utilities/Configuration/ConfigurationFileFormat.cs +++ b/src/Ryujinx/Utilities/Configuration/ConfigurationFileFormat.cs @@ -367,7 +367,8 @@ public class ConfigurationFileFormat public bool EnableMouse { get; set; } /// - /// Allows you to choose from three options: do nothing, exit the application, exit the emulator + /// Allows you to choose one of several behaviors when pressing hotkeys: + /// 0 - Do nothing, 1 - Close the emulator application, 2 - Exit the game. /// public int SpecialExitEmulator { get; set; }