diff --git a/src/Ryujinx.Common/Configuration/Hid/KeyboardHotkeys.cs b/src/Ryujinx.Common/Configuration/Hid/KeyboardHotkeys.cs index 0cb49ca8ce..3ef6ee4911 100644 --- a/src/Ryujinx.Common/Configuration/Hid/KeyboardHotkeys.cs +++ b/src/Ryujinx.Common/Configuration/Hid/KeyboardHotkeys.cs @@ -11,5 +11,7 @@ namespace Ryujinx.Common.Configuration.Hid public Key ResScaleDown { get; set; } public Key VolumeUp { get; set; } public Key VolumeDown { get; set; } + public Key ToggleTurbo { get; set; } + public bool TurboWhileHeld { get; set; } } } diff --git a/src/Ryujinx.Cpu/ITickSource.cs b/src/Ryujinx.Cpu/ITickSource.cs index e65e99e265..d598719ca3 100644 --- a/src/Ryujinx.Cpu/ITickSource.cs +++ b/src/Ryujinx.Cpu/ITickSource.cs @@ -13,6 +13,11 @@ namespace Ryujinx.Cpu /// TimeSpan ElapsedTime { get; } + /// + /// Clock tick multiplier, in percent points (100 = 1.0). + /// + long TickMultiplier { get; set; } + /// /// Time elapsed since the counter was created, in seconds. /// diff --git a/src/Ryujinx.Cpu/TickSource.cs b/src/Ryujinx.Cpu/TickSource.cs index eee83fc62b..7467a080c6 100644 --- a/src/Ryujinx.Cpu/TickSource.cs +++ b/src/Ryujinx.Cpu/TickSource.cs @@ -15,11 +15,25 @@ namespace Ryujinx.Cpu /// public ulong Counter => (ulong)(ElapsedSeconds * Frequency); - /// - public TimeSpan ElapsedTime => _tickCounter.Elapsed; + public long TickMultiplier { get; set; } = 100; + private static long AcumElapsedTicks = 0; + private static long LastElapsedTicks = 0; + private long Elapsedticks + { + get + { + long elapsedTicks = _tickCounter.ElapsedTicks; + AcumElapsedTicks += (elapsedTicks - LastElapsedTicks) * TickMultiplier / 100; + LastElapsedTicks = elapsedTicks; + return AcumElapsedTicks; + } + } /// - public double ElapsedSeconds => _tickCounter.ElapsedTicks * _hostTickFreq; + public TimeSpan ElapsedTime => Stopwatch.GetElapsedTime(0, Elapsedticks); + + /// + public double ElapsedSeconds => Elapsedticks * _hostTickFreq; public TickSource(ulong frequency) { diff --git a/src/Ryujinx.Gtk3/UI/MainWindow.cs b/src/Ryujinx.Gtk3/UI/MainWindow.cs index b10dfe3f9e..d86beed6ff 100644 --- a/src/Ryujinx.Gtk3/UI/MainWindow.cs +++ b/src/Ryujinx.Gtk3/UI/MainWindow.cs @@ -677,7 +677,8 @@ namespace Ryujinx.UI ConfigurationState.Instance.System.AudioVolume, ConfigurationState.Instance.System.UseHypervisor, ConfigurationState.Instance.Multiplayer.LanInterfaceId.Value, - ConfigurationState.Instance.Multiplayer.Mode); + ConfigurationState.Instance.Multiplayer.Mode, + ConfigurationState.Instance.System.TurboMultiplier); _emulationContext = new HLE.Switch(configuration); } diff --git a/src/Ryujinx.Gtk3/UI/RendererWidgetBase.cs b/src/Ryujinx.Gtk3/UI/RendererWidgetBase.cs index 12139e87d9..bb30ba9c22 100644 --- a/src/Ryujinx.Gtk3/UI/RendererWidgetBase.cs +++ b/src/Ryujinx.Gtk3/UI/RendererWidgetBase.cs @@ -502,7 +502,8 @@ namespace Ryujinx.UI _gpuBackendName, dockedMode, ConfigurationState.Instance.Graphics.AspectRatio.Value.ToText(), - $"Game: {Device.Statistics.GetGameFrameRate():00.00} FPS ({Device.Statistics.GetGameFrameTime():00.00} ms)", + $"Game: {Device.Statistics.GetGameFrameRate():00.00} FPS ({Device.Statistics.GetGameFrameTime():00.00} ms)" + + (Device.TurboMode ? $" Turbo ({Device.Configuration.TurboMultiplier}%)" : ""), $"FIFO: {Device.Statistics.GetFifoPercent():0.00} %", $"GPU: {_gpuDriverName}")); diff --git a/src/Ryujinx.HLE/HLEConfiguration.cs b/src/Ryujinx.HLE/HLEConfiguration.cs index 955fee4b5f..73eb2b3e71 100644 --- a/src/Ryujinx.HLE/HLEConfiguration.cs +++ b/src/Ryujinx.HLE/HLEConfiguration.cs @@ -83,6 +83,11 @@ namespace Ryujinx.HLE /// This cannot be changed after instantiation. internal readonly RegionCode Region; + /// + /// Turbo mode speed multiplier + /// + public long TurboMultiplier; + /// /// Control the initial state of the vertical sync in the SurfaceFlinger service. /// @@ -194,7 +199,8 @@ namespace Ryujinx.HLE float audioVolume, bool useHypervisor, string multiplayerLanInterfaceId, - MultiplayerMode multiplayerMode) + MultiplayerMode multiplayerMode, + long turboMultiplier) { VirtualFileSystem = virtualFileSystem; LibHacHorizonManager = libHacHorizonManager; @@ -207,6 +213,7 @@ namespace Ryujinx.HLE HostUIHandler = hostUIHandler; SystemLanguage = systemLanguage; Region = region; + TurboMultiplier = turboMultiplier; EnableVsync = enableVsync; EnableDockedMode = enableDockedMode; EnablePtc = enablePtc; diff --git a/src/Ryujinx.HLE/HOS/Services/SurfaceFlinger/SurfaceFlinger.cs b/src/Ryujinx.HLE/HOS/Services/SurfaceFlinger/SurfaceFlinger.cs index 4c17e7aedc..ed6264fd72 100644 --- a/src/Ryujinx.HLE/HOS/Services/SurfaceFlinger/SurfaceFlinger.cs +++ b/src/Ryujinx.HLE/HOS/Services/SurfaceFlinger/SurfaceFlinger.cs @@ -2,6 +2,7 @@ using Ryujinx.Common; using Ryujinx.Common.Configuration; using Ryujinx.Common.Logging; using Ryujinx.Common.PreciseSleep; +using Ryujinx.Cpu; using Ryujinx.Graphics.GAL; using Ryujinx.Graphics.Gpu; using Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvMap; @@ -88,7 +89,7 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger } else { - _ticksPerFrame = Stopwatch.Frequency / TargetFps; + _ticksPerFrame = (Stopwatch.Frequency / TargetFps * 100) / (_device.System?.TickSource?.TickMultiplier ?? 100); } } diff --git a/src/Ryujinx.HLE/Switch.cs b/src/Ryujinx.HLE/Switch.cs index 9dfc698923..892e05abe7 100644 --- a/src/Ryujinx.HLE/Switch.cs +++ b/src/Ryujinx.HLE/Switch.cs @@ -28,6 +28,7 @@ namespace Ryujinx.HLE public IHostUIHandler UIHandler { get; } public bool EnableDeviceVsync { get; set; } = true; + public bool TurboMode { get; set; } = false; public bool IsFrameAvailable => Gpu.Window.IsFrameAvailable; @@ -125,6 +126,18 @@ namespace Ryujinx.HLE return AudioDeviceDriver.Volume; } + public void SetTickSourceMultiplier(long tickMultiplier) + { + System.TickSource.TickMultiplier = tickMultiplier; + } + + public void ToggleTurbo() + { + TurboMode = !TurboMode; + long turboMultiplier = TurboMode ? Configuration.TurboMultiplier : 100; + SetTickSourceMultiplier(turboMultiplier); + } + public void EnableCheats() { ModLoader.EnableCheats(Processes.ActiveApplication.ProgramId, TamperMachine); diff --git a/src/Ryujinx.Headless.SDL2/Options.cs b/src/Ryujinx.Headless.SDL2/Options.cs index ef8849eeaa..c18fc6ba5b 100644 --- a/src/Ryujinx.Headless.SDL2/Options.cs +++ b/src/Ryujinx.Headless.SDL2/Options.cs @@ -114,6 +114,9 @@ namespace Ryujinx.Headless.SDL2 [Option("fs-global-access-log-mode", Required = false, Default = 0, HelpText = "Enables FS access log output to the console.")] public int FsGlobalAccessLogMode { get; set; } + [Option("turbo-multiplier", Required = false, Default = 200, HelpText = "The Turbo mode clock speed multiplier.")] + public long TurboMultiplier { get; set; } + [Option("disable-vsync", Required = false, HelpText = "Disables Vertical Sync.")] public bool DisableVSync { get; set; } diff --git a/src/Ryujinx.Headless.SDL2/Program.cs b/src/Ryujinx.Headless.SDL2/Program.cs index 4ee2712037..bff59f2c11 100644 --- a/src/Ryujinx.Headless.SDL2/Program.cs +++ b/src/Ryujinx.Headless.SDL2/Program.cs @@ -580,7 +580,8 @@ namespace Ryujinx.Headless.SDL2 options.AudioVolume, options.UseHypervisor ?? true, options.MultiplayerLanInterfaceId, - Common.Configuration.Multiplayer.MultiplayerMode.Disabled); + Common.Configuration.Multiplayer.MultiplayerMode.Disabled, + options.TurboMultiplier); return new Switch(configuration); } diff --git a/src/Ryujinx.Headless.SDL2/WindowBase.cs b/src/Ryujinx.Headless.SDL2/WindowBase.cs index 8768913f5a..3d40a04521 100644 --- a/src/Ryujinx.Headless.SDL2/WindowBase.cs +++ b/src/Ryujinx.Headless.SDL2/WindowBase.cs @@ -312,7 +312,8 @@ namespace Ryujinx.Headless.SDL2 Device.EnableDeviceVsync, dockedMode, Device.Configuration.AspectRatio.ToText(), - $"Game: {Device.Statistics.GetGameFrameRate():00.00} FPS ({Device.Statistics.GetGameFrameTime():00.00} ms)", + $"Game: {Device.Statistics.GetGameFrameRate():00.00} FPS ({Device.Statistics.GetGameFrameTime():00.00} ms)" + + (Device.TurboMode ? $" Turbo ({Device.Configuration.TurboMultiplier}%)" : ""), $"FIFO: {Device.Statistics.GetFifoPercent():0.00} %", $"GPU: {_gpuDriverName}")); diff --git a/src/Ryujinx.UI.Common/Configuration/ConfigurationFileFormat.cs b/src/Ryujinx.UI.Common/Configuration/ConfigurationFileFormat.cs index 8a0be40283..88fac29250 100644 --- a/src/Ryujinx.UI.Common/Configuration/ConfigurationFileFormat.cs +++ b/src/Ryujinx.UI.Common/Configuration/ConfigurationFileFormat.cs @@ -15,7 +15,7 @@ namespace Ryujinx.UI.Common.Configuration /// /// The current version of the file format /// - public const int CurrentVersion = 51; + public const int CurrentVersion = 52; /// /// Version of the configuration file format @@ -177,6 +177,11 @@ namespace Ryujinx.UI.Common.Configuration /// public HideCursorMode HideCursor { get; set; } + /// + /// Clock speed multiplier for Turbo mode + /// + public long TurboMultiplier { get; set; } + /// /// Enables or disables Vertical Sync /// diff --git a/src/Ryujinx.UI.Common/Configuration/ConfigurationState.cs b/src/Ryujinx.UI.Common/Configuration/ConfigurationState.cs index 8420dc5d98..6f6e769e01 100644 --- a/src/Ryujinx.UI.Common/Configuration/ConfigurationState.cs +++ b/src/Ryujinx.UI.Common/Configuration/ConfigurationState.cs @@ -366,6 +366,11 @@ namespace Ryujinx.UI.Common.Configuration /// public ReactiveObject UseHypervisor { get; private set; } + /// + /// Turbo mode clock speed multiplier + /// + public ReactiveObject TurboMultiplier { get; private set; } + public SystemSection() { Language = new ReactiveObject(); @@ -394,6 +399,8 @@ namespace Ryujinx.UI.Common.Configuration AudioVolume.Event += static (sender, e) => LogValueChange(e, nameof(AudioVolume)); UseHypervisor = new ReactiveObject(); UseHypervisor.Event += static (sender, e) => LogValueChange(e, nameof(UseHypervisor)); + TurboMultiplier = new ReactiveObject(); + TurboMultiplier.Event += static (sender, e) => LogValueChange(e, nameof(TurboMultiplier)); } } @@ -688,6 +695,7 @@ namespace Ryujinx.UI.Common.Configuration SystemTimeZone = System.TimeZone, SystemTimeOffset = System.SystemTimeOffset, DockedMode = System.EnableDockedMode, + TurboMultiplier = System.TurboMultiplier, EnableDiscordIntegration = EnableDiscordIntegration, CheckUpdatesOnStart = CheckUpdatesOnStart, ShowConfirmExit = ShowConfirmExit, @@ -797,6 +805,7 @@ namespace Ryujinx.UI.Common.Configuration System.TimeZone.Value = "UTC"; System.SystemTimeOffset.Value = 0; System.EnableDockedMode.Value = true; + System.TurboMultiplier.Value = 200; EnableDiscordIntegration.Value = true; CheckUpdatesOnStart.Value = true; ShowConfirmExit.Value = true; @@ -871,6 +880,8 @@ namespace Ryujinx.UI.Common.Configuration ResScaleDown = Key.Unbound, VolumeUp = Key.Unbound, VolumeDown = Key.Unbound, + ToggleTurbo = Key.Unbound, + TurboWhileHeld = false, }; Hid.InputConfig.Value = new List { @@ -1477,6 +1488,30 @@ namespace Ryujinx.UI.Common.Configuration configurationFileUpdated = true; } + if (configurationFileFormat.Version < 52) + { + Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 52."); + + configurationFileFormat.TurboMultiplier = 200; + + configurationFileFormat.Hotkeys = new KeyboardHotkeys + { + ToggleTurbo = Key.Unbound, + TurboWhileHeld = false, + Screenshot = configurationFileFormat.Hotkeys.Screenshot, + ShowUI = configurationFileFormat.Hotkeys.ShowUI, + Pause = configurationFileFormat.Hotkeys.Pause, + ToggleMute = configurationFileFormat.Hotkeys.ToggleMute, + ResScaleUp = configurationFileFormat.Hotkeys.ResScaleUp, + ResScaleDown = configurationFileFormat.Hotkeys.ResScaleDown, + VolumeUp = configurationFileFormat.Hotkeys.VolumeUp, + VolumeDown = configurationFileFormat.Hotkeys.VolumeDown, + ToggleVsync = configurationFileFormat.Hotkeys.ToggleVsync, + }; + + configurationFileUpdated = true; + } + Logger.EnableFileLog.Value = configurationFileFormat.EnableFileLog; Graphics.ResScale.Value = configurationFileFormat.ResScale; Graphics.ResScaleCustom.Value = configurationFileFormat.ResScaleCustom; @@ -1504,6 +1539,7 @@ namespace Ryujinx.UI.Common.Configuration System.TimeZone.Value = configurationFileFormat.SystemTimeZone; System.SystemTimeOffset.Value = configurationFileFormat.SystemTimeOffset; System.EnableDockedMode.Value = configurationFileFormat.DockedMode; + System.TurboMultiplier.Value = configurationFileFormat.TurboMultiplier; EnableDiscordIntegration.Value = configurationFileFormat.EnableDiscordIntegration; CheckUpdatesOnStart.Value = configurationFileFormat.CheckUpdatesOnStart; ShowConfirmExit.Value = configurationFileFormat.ShowConfirmExit; diff --git a/src/Ryujinx/AppHost.cs b/src/Ryujinx/AppHost.cs index f4bfd1169e..7b594434b0 100644 --- a/src/Ryujinx/AppHost.cs +++ b/src/Ryujinx/AppHost.cs @@ -23,6 +23,7 @@ using Ryujinx.Common.Configuration.Multiplayer; using Ryujinx.Common.Logging; using Ryujinx.Common.SystemInterop; using Ryujinx.Common.Utilities; +using Ryujinx.Cpu; using Ryujinx.Graphics.GAL; using Ryujinx.Graphics.GAL.Multithreading; using Ryujinx.Graphics.Gpu; @@ -872,7 +873,8 @@ namespace Ryujinx.Ava ConfigurationState.Instance.System.AudioVolume, ConfigurationState.Instance.System.UseHypervisor, ConfigurationState.Instance.Multiplayer.LanInterfaceId.Value, - ConfigurationState.Instance.Multiplayer.Mode); + ConfigurationState.Instance.Multiplayer.Mode, + ConfigurationState.Instance.System.TurboMultiplier); Device = new Switch(configuration); } @@ -1069,7 +1071,8 @@ namespace Ryujinx.Ava LocaleManager.Instance[LocaleKeys.VolumeShort] + $": {(int)(Device.GetVolume() * 100)}%", dockedMode, ConfigurationState.Instance.Graphics.AspectRatio.Value.ToText(), - LocaleManager.Instance[LocaleKeys.Game] + $": {Device.Statistics.GetGameFrameRate():00.00} FPS ({Device.Statistics.GetGameFrameTime():00.00} ms)", + LocaleManager.Instance[LocaleKeys.Game] + $": {Device.Statistics.GetGameFrameRate():00.00} FPS ({Device.Statistics.GetGameFrameTime():00.00} ms)" + + (Device.TurboMode ? $" Turbo ({Device.Configuration.TurboMultiplier}%)" : ""), $"FIFO: {Device.Statistics.GetFifoPercent():00.00} %")); } @@ -1147,6 +1150,11 @@ namespace Ryujinx.Ava if (currentHotkeyState != _prevHotkeyState) { + if (ConfigurationState.Instance.Hid.Hotkeys.Value.TurboWhileHeld && + _keyboardInterface.IsPressed((Key)ConfigurationState.Instance.Hid.Hotkeys.Value.ToggleTurbo) != Device.TurboMode) + { + Device.ToggleTurbo(); + } switch (currentHotkeyState) { case KeyboardHotkeyState.ToggleVSync: @@ -1158,6 +1166,12 @@ namespace Ryujinx.Ava case KeyboardHotkeyState.ShowUI: _viewModel.ShowMenuAndStatusBar = !_viewModel.ShowMenuAndStatusBar; break; + case KeyboardHotkeyState.ToggleTurbo: + if (!ConfigurationState.Instance.Hid.Hotkeys.Value.TurboWhileHeld) + { + Device.ToggleTurbo(); + } + break; case KeyboardHotkeyState.Pause: if (_viewModel.IsPaused) { @@ -1273,6 +1287,10 @@ namespace Ryujinx.Ava { state = KeyboardHotkeyState.VolumeDown; } + else if (_keyboardInterface.IsPressed((Key)ConfigurationState.Instance.Hid.Hotkeys.Value.ToggleTurbo)) + { + state = KeyboardHotkeyState.ToggleTurbo; + } return state; } diff --git a/src/Ryujinx/Assets/Locales/en_US.json b/src/Ryujinx/Assets/Locales/en_US.json index b3cab7f5f6..48ab192d05 100644 --- a/src/Ryujinx/Assets/Locales/en_US.json +++ b/src/Ryujinx/Assets/Locales/en_US.json @@ -135,6 +135,9 @@ "SettingsTabSystemSystemLanguageTraditionalChinese": "Traditional Chinese", "SettingsTabSystemSystemTimeZone": "System TimeZone:", "SettingsTabSystemSystemTime": "System Time:", + "SettingsTabSystemTurboMultiplierValue": "Turbo multiplier:", + "SettingsTabSystemTurboMultiplierSliderTooltip": "The Turbo mode multiplier target value.", + "SettingsTabSystemTurboMultiplierValueTooltip": "The Turbo mode multiplier, as a percentage of the normal Switch clock speed.", "SettingsTabSystemEnableVsync": "VSync", "SettingsTabSystemEnablePptc": "PPTC (Profiled Persistent Translation Cache)", "SettingsTabSystemEnableFsIntegrityChecks": "FS Integrity Checks", @@ -628,6 +631,7 @@ "SettingsTabNetworkConnection": "Network Connection", "SettingsTabCpuCache": "CPU Cache", "SettingsTabCpuMemory": "CPU Mode", + "SettingsTabCpuHacks": "Hacks", "DialogUpdaterFlatpakNotSupportedMessage": "Please update Ryujinx via FlatHub.", "UpdaterDisabledWarningTitle": "Updater Disabled!", "ControllerSettingsRotate90": "Rotate 90° Clockwise", @@ -738,6 +742,9 @@ "RyujinxUpdaterMessage": "Do you want to update Ryujinx to the latest version?", "SettingsTabHotkeysVolumeUpHotkey": "Increase Volume:", "SettingsTabHotkeysVolumeDownHotkey": "Decrease Volume:", + "SettingsTabHotkeysToggleTurboHotkey": "Toggle turbo mode:", + "SettingsTabHotkeysToggleTurboToggleTooltip": "Makes the turbo hotkey enable turbo while held instead of toggling it.", + "SettingsTabHotkeysToggleTurboToggle": "Enable turbo while held:", "SettingsEnableMacroHLE": "Enable Macro HLE", "SettingsEnableMacroHLETooltip": "High-level emulation of GPU Macro code.\n\nImproves performance, but may cause graphical glitches in some games.\n\nLeave ON if unsure.", "SettingsEnableColorSpacePassthrough": "Color Space Passthrough", diff --git a/src/Ryujinx/Common/KeyboardHotkeyState.cs b/src/Ryujinx/Common/KeyboardHotkeyState.cs index 6e49209887..ea86f6a368 100644 --- a/src/Ryujinx/Common/KeyboardHotkeyState.cs +++ b/src/Ryujinx/Common/KeyboardHotkeyState.cs @@ -12,5 +12,6 @@ namespace Ryujinx.Ava.Common ResScaleDown, VolumeUp, VolumeDown, + ToggleTurbo, } } diff --git a/src/Ryujinx/UI/Models/Input/HotkeyConfig.cs b/src/Ryujinx/UI/Models/Input/HotkeyConfig.cs index b5f53508bd..6b233a2dcd 100644 --- a/src/Ryujinx/UI/Models/Input/HotkeyConfig.cs +++ b/src/Ryujinx/UI/Models/Input/HotkeyConfig.cs @@ -104,6 +104,28 @@ namespace Ryujinx.Ava.UI.Models.Input } } + private Key _toggleTurbo; + public Key ToggleTurbo + { + get => _toggleTurbo; + set + { + _toggleTurbo = value; + OnPropertyChanged(); + } + } + + private bool _turboWhileHeld; + public bool TurboWhileHeld + { + get => _turboWhileHeld; + set + { + _turboWhileHeld = value; + OnPropertyChanged(); + } + } + public HotkeyConfig(KeyboardHotkeys config) { if (config != null) @@ -117,6 +139,8 @@ namespace Ryujinx.Ava.UI.Models.Input ResScaleDown = config.ResScaleDown; VolumeUp = config.VolumeUp; VolumeDown = config.VolumeDown; + ToggleTurbo = config.ToggleTurbo; + TurboWhileHeld = config.TurboWhileHeld; } } @@ -133,6 +157,8 @@ namespace Ryujinx.Ava.UI.Models.Input ResScaleDown = ResScaleDown, VolumeUp = VolumeUp, VolumeDown = VolumeDown, + ToggleTurbo = ToggleTurbo, + TurboWhileHeld = TurboWhileHeld, }; return config; diff --git a/src/Ryujinx/UI/ViewModels/SettingsViewModel.cs b/src/Ryujinx/UI/ViewModels/SettingsViewModel.cs index 70e5fa5c74..50a6fa99c0 100644 --- a/src/Ryujinx/UI/ViewModels/SettingsViewModel.cs +++ b/src/Ryujinx/UI/ViewModels/SettingsViewModel.cs @@ -13,6 +13,7 @@ using Ryujinx.Common.Configuration; using Ryujinx.Common.Configuration.Multiplayer; using Ryujinx.Common.GraphicsDriver; using Ryujinx.Common.Logging; +using Ryujinx.Cpu; using Ryujinx.Graphics.Vulkan; using Ryujinx.HLE.FileSystem; using Ryujinx.HLE.HOS.Services.Time.TimeZone; @@ -49,6 +50,7 @@ namespace Ryujinx.Ava.UI.ViewModels private int _graphicsBackendIndex; private int _scalingFilter; private int _scalingFilterLevel; + private long _turboModeMultiplier; public event Action CloseWindow; public event Action SaveSettingsEvent; @@ -135,6 +137,26 @@ namespace Ryujinx.Ava.UI.ViewModels public int HideCursor { get; set; } public bool EnableDockedMode { get; set; } public bool EnableKeyboard { get; set; } + public long TurboMultiplier + { + get => _turboModeMultiplier; + set + { + if (_turboModeMultiplier != value) + { + _turboModeMultiplier = value; + OnPropertyChanged(); + OnPropertyChanged((nameof(TurboMultiplierPercentageText))); + } + } + } + public string TurboMultiplierPercentageText + { + get + { + return TurboMultiplier.ToString() + "%"; + } + } public bool EnableMouse { get; set; } public bool EnableVsync { get; set; } public bool EnablePptc { get; set; } @@ -433,6 +455,7 @@ namespace Ryujinx.Ava.UI.ViewModels EnablePptc = config.System.EnablePtc; MemoryMode = (int)config.System.MemoryManagerMode.Value; UseHypervisor = config.System.UseHypervisor; + _turboModeMultiplier = config.System.TurboMultiplier; // Graphics GraphicsBackendIndex = (int)config.Graphics.GraphicsBackend.Value; @@ -518,6 +541,7 @@ namespace Ryujinx.Ava.UI.ViewModels } config.System.SystemTimeOffset.Value = Convert.ToInt64((CurrentDate.ToUnixTimeSeconds() + CurrentTime.TotalSeconds) - DateTimeOffset.Now.ToUnixTimeSeconds()); + config.System.TurboMultiplier.Value = TurboMultiplier; config.Graphics.EnableVsync.Value = EnableVsync; config.System.EnableFsIntegrityChecks.Value = EnableFsIntegrityChecks; config.System.ExpandRam.Value = ExpandDramSize; @@ -584,6 +608,7 @@ namespace Ryujinx.Ava.UI.ViewModels config.ToFileFormat().SaveConfig(Program.ConfigurationPath); MainWindow.UpdateGraphicsConfig(); + MainWindow.UpdateTurboConfig(TurboMultiplier); SaveSettingsEvent?.Invoke(); diff --git a/src/Ryujinx/UI/Views/Settings/SettingsCPUView.axaml b/src/Ryujinx/UI/Views/Settings/SettingsCPUView.axaml index c74d3dd579..caf3a0c10c 100644 --- a/src/Ryujinx/UI/Views/Settings/SettingsCPUView.axaml +++ b/src/Ryujinx/UI/Views/Settings/SettingsCPUView.axaml @@ -1,10 +1,11 @@ - @@ -71,6 +72,48 @@ ToolTip.Tip="{locale:Locale UseHypervisorTooltip}" /> + + + + + + + + + + + diff --git a/src/Ryujinx/UI/Views/Settings/SettingsHotkeysView.axaml b/src/Ryujinx/UI/Views/Settings/SettingsHotkeysView.axaml index bffcada055..d0479ee192 100644 --- a/src/Ryujinx/UI/Views/Settings/SettingsHotkeysView.axaml +++ b/src/Ryujinx/UI/Views/Settings/SettingsHotkeysView.axaml @@ -1,4 +1,4 @@ - + + + + + + + + + + diff --git a/src/Ryujinx/UI/Views/Settings/SettingsHotkeysView.axaml.cs b/src/Ryujinx/UI/Views/Settings/SettingsHotkeysView.axaml.cs index fb0fe2bb12..0974f0eeea 100644 --- a/src/Ryujinx/UI/Views/Settings/SettingsHotkeysView.axaml.cs +++ b/src/Ryujinx/UI/Views/Settings/SettingsHotkeysView.axaml.cs @@ -109,6 +109,9 @@ namespace Ryujinx.Ava.UI.Views.Settings case "VolumeDown": viewModel.KeyboardHotkey.VolumeDown = buttonValue.AsHidType(); break; + case "ToggleTurbo": + viewModel.KeyboardHotkey.ToggleTurbo = buttonValue.AsHidType(); + break; } } }; diff --git a/src/Ryujinx/UI/Views/Settings/SettingsSystemView.axaml b/src/Ryujinx/UI/Views/Settings/SettingsSystemView.axaml index e6f7c6e463..e8cab19f4f 100644 --- a/src/Ryujinx/UI/Views/Settings/SettingsSystemView.axaml +++ b/src/Ryujinx/UI/Views/Settings/SettingsSystemView.axaml @@ -1,4 +1,4 @@ - - \ No newline at end of file + diff --git a/src/Ryujinx/UI/Windows/MainWindow.axaml.cs b/src/Ryujinx/UI/Windows/MainWindow.axaml.cs index 348412e78c..4b39557718 100644 --- a/src/Ryujinx/UI/Windows/MainWindow.axaml.cs +++ b/src/Ryujinx/UI/Windows/MainWindow.axaml.cs @@ -503,6 +503,18 @@ namespace Ryujinx.Ava.UI.Windows } } + public static void UpdateTurboConfig(long turboMultiplier) + { + if (MainWindow.MainWindowViewModel.IsGameRunning) + { + MainWindow.MainWindowViewModel.AppHost.Device.Configuration.TurboMultiplier = turboMultiplier; + if (MainWindow.MainWindowViewModel.AppHost.Device.TurboMode) + { + MainWindow.MainWindowViewModel.AppHost.Device.SetTickSourceMultiplier(turboMultiplier); + } + } + } + public static void UpdateGraphicsConfig() { #pragma warning disable IDE0055 // Disable formatting