From bec67dbef7a505fb5c4a1734be1517f67474fb4d Mon Sep 17 00:00:00 2001 From: Mary Date: Sun, 16 May 2021 17:12:14 +0200 Subject: misc: Move configuration management to the Ryujinx project (#2269) * Decouple configuration from Ryujinx.HLE and Ryujinx.Input * Move Configuration to the Ryujinx project --- Ryujinx.Common/Configuration/AudioBackend.cs | 10 - .../Configuration/ConfigurationFileFormat.cs | 276 ------- Ryujinx.Common/Configuration/ConfigurationState.cs | 893 --------------------- Ryujinx.Common/Configuration/LoggerModule.cs | 89 -- Ryujinx.Common/Configuration/System/Language.cs | 23 - Ryujinx.Common/Configuration/System/Region.cs | 13 - Ryujinx.Common/Configuration/Ui/ColumnSort.cs | 8 - Ryujinx.Common/Configuration/Ui/GuiColumns.cs | 16 - Ryujinx.HLE/FileSystem/Content/ContentManager.cs | 28 +- Ryujinx.HLE/HLEConfiguration.cs | 179 +++++ Ryujinx.HLE/HOS/ApplicationLoader.cs | 67 +- Ryujinx.HLE/HOS/Horizon.cs | 27 +- .../ApplicationProxy/IApplicationFunctions.cs | 8 +- Ryujinx.HLE/HOS/Services/Fs/IFileSystemProxy.cs | 2 +- Ryujinx.HLE/HOS/Services/Hid/Hid.cs | 7 +- Ryujinx.HLE/HOS/Services/IpcService.cs | 4 +- Ryujinx.HLE/HOS/Services/ServiceConfiguration.cs | 7 - Ryujinx.HLE/HOS/Services/Sm/IUserInterface.cs | 2 +- .../HOS/Services/SurfaceFlinger/SurfaceFlinger.cs | 3 +- .../Time/TimeZone/TimeZoneContentManager.cs | 9 +- Ryujinx.HLE/Switch.cs | 106 +-- Ryujinx.Input/HLE/NpadManager.cs | 59 +- Ryujinx.Input/Motion/CemuHook/Client.cs | 14 +- Ryujinx/Configuration/AudioBackend.cs | 10 + Ryujinx/Configuration/ConfigurationFileFormat.cs | 276 +++++++ Ryujinx/Configuration/ConfigurationState.cs | 893 +++++++++++++++++++++ Ryujinx/Configuration/LoggerModule.cs | 88 ++ Ryujinx/Configuration/System/Language.cs | 23 + Ryujinx/Configuration/System/Region.cs | 13 + Ryujinx/Configuration/Ui/ColumnSort.cs | 8 + Ryujinx/Configuration/Ui/GuiColumns.cs | 16 + Ryujinx/Ui/Applet/GtkHostUiHandler.cs | 2 +- Ryujinx/Ui/MainWindow.cs | 67 +- Ryujinx/Ui/RendererWidgetBase.cs | 6 +- Ryujinx/Ui/Windows/ControllerWindow.cs | 2 +- Ryujinx/Ui/Windows/SettingsWindow.cs | 4 +- 36 files changed, 1715 insertions(+), 1543 deletions(-) delete mode 100644 Ryujinx.Common/Configuration/AudioBackend.cs delete mode 100644 Ryujinx.Common/Configuration/ConfigurationFileFormat.cs delete mode 100644 Ryujinx.Common/Configuration/ConfigurationState.cs delete mode 100644 Ryujinx.Common/Configuration/LoggerModule.cs delete mode 100644 Ryujinx.Common/Configuration/System/Language.cs delete mode 100644 Ryujinx.Common/Configuration/System/Region.cs delete mode 100644 Ryujinx.Common/Configuration/Ui/ColumnSort.cs delete mode 100644 Ryujinx.Common/Configuration/Ui/GuiColumns.cs create mode 100644 Ryujinx.HLE/HLEConfiguration.cs delete mode 100644 Ryujinx.HLE/HOS/Services/ServiceConfiguration.cs create mode 100644 Ryujinx/Configuration/AudioBackend.cs create mode 100644 Ryujinx/Configuration/ConfigurationFileFormat.cs create mode 100644 Ryujinx/Configuration/ConfigurationState.cs create mode 100644 Ryujinx/Configuration/LoggerModule.cs create mode 100644 Ryujinx/Configuration/System/Language.cs create mode 100644 Ryujinx/Configuration/System/Region.cs create mode 100644 Ryujinx/Configuration/Ui/ColumnSort.cs create mode 100644 Ryujinx/Configuration/Ui/GuiColumns.cs diff --git a/Ryujinx.Common/Configuration/AudioBackend.cs b/Ryujinx.Common/Configuration/AudioBackend.cs deleted file mode 100644 index e42df039..00000000 --- a/Ryujinx.Common/Configuration/AudioBackend.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace Ryujinx.Configuration -{ - public enum AudioBackend - { - Dummy, - OpenAl, - SoundIo, - SDL2 - } -} \ No newline at end of file diff --git a/Ryujinx.Common/Configuration/ConfigurationFileFormat.cs b/Ryujinx.Common/Configuration/ConfigurationFileFormat.cs deleted file mode 100644 index be9c6864..00000000 --- a/Ryujinx.Common/Configuration/ConfigurationFileFormat.cs +++ /dev/null @@ -1,276 +0,0 @@ -using System.Collections.Generic; -using System.IO; -using Ryujinx.Common.Configuration; -using Ryujinx.Common.Configuration.Hid; -using Ryujinx.Common.Logging; -using Ryujinx.Common.Utilities; -using Ryujinx.Configuration.System; -using Ryujinx.Configuration.Ui; - -namespace Ryujinx.Configuration -{ - public class ConfigurationFileFormat - { - /// - /// The current version of the file format - /// - public const int CurrentVersion = 25; - - public int Version { get; set; } - - /// - /// Enables or disables logging to a file on disk - /// - public bool EnableFileLog { get; set; } - - /// - /// Resolution Scale. An integer scale applied to applicable render targets. Values 1-4, or -1 to use a custom floating point scale instead. - /// - public int ResScale { get; set; } - - /// - /// Custom Resolution Scale. A custom floating point scale applied to applicable render targets. Only active when Resolution Scale is -1. - /// - public float ResScaleCustom { get; set; } - - /// - /// Max Anisotropy. Values range from 0 - 16. Set to -1 to let the game decide. - /// - public float MaxAnisotropy { get; set; } - - /// - /// Aspect Ratio applied to the renderer window. - /// - public AspectRatio AspectRatio { get; set; } - - /// - /// Dumps shaders in this local directory - /// - public string GraphicsShadersDumpPath { get; set; } - - /// - /// Enables printing debug log messages - /// - public bool LoggingEnableDebug { get; set; } - - /// - /// Enables printing stub log messages - /// - public bool LoggingEnableStub { get; set; } - - /// - /// Enables printing info log messages - /// - public bool LoggingEnableInfo { get; set; } - - /// - /// Enables printing warning log messages - /// - public bool LoggingEnableWarn { get; set; } - - /// - /// Enables printing error log messages - /// - public bool LoggingEnableError { get; set; } - - /// - /// Enables printing guest log messages - /// - public bool LoggingEnableGuest { get; set; } - - /// - /// Enables printing FS access log messages - /// - public bool LoggingEnableFsAccessLog { get; set; } - - /// - /// Controls which log messages are written to the log targets - /// - public LogClass[] LoggingFilteredClasses { get; set; } - - /// - /// Change Graphics API debug log level - /// - public GraphicsDebugLevel LoggingGraphicsDebugLevel { get; set; } - - - /// - /// Change System Language - /// - public Language SystemLanguage { get; set; } - - /// - /// Change System Region - /// - public Region SystemRegion { get; set; } - - /// - /// Change System TimeZone - /// - public string SystemTimeZone { get; set; } - - /// - /// Change System Time Offset in seconds - /// - public long SystemTimeOffset { get; set; } - - /// - /// Enables or disables Docked Mode - /// - public bool DockedMode { get; set; } - - /// - /// Enables or disables Discord Rich Presence - /// - public bool EnableDiscordIntegration { get; set; } - - /// - /// Checks for updates when Ryujinx starts when enabled - /// - public bool CheckUpdatesOnStart { get; set; } - - /// - /// Show "Confirm Exit" Dialog - /// - public bool ShowConfirmExit { get; set; } - - /// - /// Hide Cursor on Idle - /// - public bool HideCursorOnIdle { get; set; } - - /// - /// Enables or disables Vertical Sync - /// - public bool EnableVsync { get; set; } - - /// - /// Enables or disables Shader cache - /// - public bool EnableShaderCache { get; set; } - - /// - /// Enables or disables multi-core scheduling of threads - /// - public bool EnableMulticoreScheduling { get; set; } - - /// - /// Enables or disables profiled translation cache persistency - /// - public bool EnablePtc { get; set; } - - /// - /// Enables integrity checks on Game content files - /// - public bool EnableFsIntegrityChecks { get; set; } - - /// - /// Enables FS access log output to the console. Possible modes are 0-3 - /// - public int FsGlobalAccessLogMode { get; set; } - - /// - /// The selected audio backend - /// - public AudioBackend AudioBackend { get; set; } - - /// - /// Expands the RAM amount on the emulated system from 4GB to 6GB - /// - public bool ExpandRam { get; set; } - - /// - /// Enable or disable ignoring missing services - /// - public bool IgnoreMissingServices { get; set; } - - /// - /// Used to toggle columns in the GUI - /// - public GuiColumns GuiColumns { get; set; } - - /// - /// Used to configure column sort settings in the GUI - /// - public ColumnSort ColumnSort { get; set; } - - /// - /// A list of directories containing games to be used to load games into the games list - /// - public List GameDirs { get; set; } - - /// - /// Enable or disable custom themes in the GUI - /// - public bool EnableCustomTheme { get; set; } - - /// - /// Path to custom GUI theme - /// - public string CustomThemePath { get; set; } - - /// - /// Start games in fullscreen mode - /// - public bool StartFullscreen { get; set; } - - /// - /// Enable or disable keyboard support (Independent from controllers binding) - /// - public bool EnableKeyboard { get; set; } - - /// - /// Hotkey Keyboard Bindings - /// - public KeyboardHotkeys Hotkeys { get; set; } - - /// - /// Legacy keyboard control bindings - /// - /// Kept for file format compatibility (to avoid possible failure when parsing configuration on old versions) - /// TODO: Remove this when those older versions aren't in use anymore. - public List KeyboardConfig { get; set; } - - /// - /// Legacy controller control bindings - /// - /// Kept for file format compatibility (to avoid possible failure when parsing configuration on old versions) - /// TODO: Remove this when those older versions aren't in use anymore. - public List ControllerConfig { get; set; } - - /// - /// Input configurations - /// - public List InputConfig { get; set; } - - /// - /// Loads a configuration file from disk - /// - /// The path to the JSON configuration file - public static bool TryLoad(string path, out ConfigurationFileFormat configurationFileFormat) - { - try - { - configurationFileFormat = JsonHelper.DeserializeFromFile(path); - - return true; - } - catch - { - configurationFileFormat = null; - - return false; - } - } - - /// - /// Save a configuration file to disk - /// - /// The path to the JSON configuration file - public void SaveConfig(string path) - { - using FileStream fileStream = File.Create(path, 4096, FileOptions.WriteThrough); - JsonHelper.Serialize(fileStream, this, true); - } - } -} diff --git a/Ryujinx.Common/Configuration/ConfigurationState.cs b/Ryujinx.Common/Configuration/ConfigurationState.cs deleted file mode 100644 index 9ea5c282..00000000 --- a/Ryujinx.Common/Configuration/ConfigurationState.cs +++ /dev/null @@ -1,893 +0,0 @@ -using Ryujinx.Common; -using Ryujinx.Common.Configuration; -using Ryujinx.Common.Configuration.Hid; -using Ryujinx.Common.Configuration.Hid.Keyboard; -using Ryujinx.Common.Logging; -using Ryujinx.Configuration.System; -using Ryujinx.Configuration.Ui; -using System; -using System.Collections.Generic; - -namespace Ryujinx.Configuration -{ - public class ConfigurationState - { - /// - /// UI configuration section - /// - public class UiSection - { - public class Columns - { - public ReactiveObject FavColumn { get; private set; } - public ReactiveObject IconColumn { get; private set; } - public ReactiveObject AppColumn { get; private set; } - public ReactiveObject DevColumn { get; private set; } - public ReactiveObject VersionColumn { get; private set; } - public ReactiveObject TimePlayedColumn { get; private set; } - public ReactiveObject LastPlayedColumn { get; private set; } - public ReactiveObject FileExtColumn { get; private set; } - public ReactiveObject FileSizeColumn { get; private set; } - public ReactiveObject PathColumn { get; private set; } - - public Columns() - { - FavColumn = new ReactiveObject(); - IconColumn = new ReactiveObject(); - AppColumn = new ReactiveObject(); - DevColumn = new ReactiveObject(); - VersionColumn = new ReactiveObject(); - TimePlayedColumn = new ReactiveObject(); - LastPlayedColumn = new ReactiveObject(); - FileExtColumn = new ReactiveObject(); - FileSizeColumn = new ReactiveObject(); - PathColumn = new ReactiveObject(); - } - } - - public class ColumnSortSettings - { - public ReactiveObject SortColumnId { get; private set; } - public ReactiveObject SortAscending { get; private set; } - - public ColumnSortSettings() - { - SortColumnId = new ReactiveObject(); - SortAscending = new ReactiveObject(); - } - } - - /// - /// Used to toggle columns in the GUI - /// - public Columns GuiColumns { get; private set; } - - /// - /// Used to configure column sort settings in the GUI - /// - public ColumnSortSettings ColumnSort { get; private set; } - - /// - /// A list of directories containing games to be used to load games into the games list - /// - public ReactiveObject> GameDirs { get; private set; } - - /// - /// Enable or disable custom themes in the GUI - /// - public ReactiveObject EnableCustomTheme { get; private set; } - - /// - /// Path to custom GUI theme - /// - public ReactiveObject CustomThemePath { get; private set; } - - /// - /// Start games in fullscreen mode - /// - public ReactiveObject StartFullscreen { get; private set; } - - public UiSection() - { - GuiColumns = new Columns(); - ColumnSort = new ColumnSortSettings(); - GameDirs = new ReactiveObject>(); - EnableCustomTheme = new ReactiveObject(); - CustomThemePath = new ReactiveObject(); - StartFullscreen = new ReactiveObject(); - } - } - - /// - /// Logger configuration section - /// - public class LoggerSection - { - /// - /// Enables printing debug log messages - /// - public ReactiveObject EnableDebug { get; private set; } - - /// - /// Enables printing stub log messages - /// - public ReactiveObject EnableStub { get; private set; } - - /// - /// Enables printing info log messages - /// - public ReactiveObject EnableInfo { get; private set; } - - /// - /// Enables printing warning log messages - /// - public ReactiveObject EnableWarn { get; private set; } - - /// - /// Enables printing error log messages - /// - public ReactiveObject EnableError { get; private set; } - - /// - /// Enables printing guest log messages - /// - public ReactiveObject EnableGuest { get; private set; } - - /// - /// Enables printing FS access log messages - /// - public ReactiveObject EnableFsAccessLog { get; private set; } - - /// - /// Controls which log messages are written to the log targets - /// - public ReactiveObject FilteredClasses { get; private set; } - - /// - /// Enables or disables logging to a file on disk - /// - public ReactiveObject EnableFileLog { get; private set; } - - /// - /// Controls which OpenGL log messages are recorded in the log - /// - public ReactiveObject GraphicsDebugLevel { get; private set; } - - public LoggerSection() - { - EnableDebug = new ReactiveObject(); - EnableStub = new ReactiveObject(); - EnableInfo = new ReactiveObject(); - EnableWarn = new ReactiveObject(); - EnableError = new ReactiveObject(); - EnableGuest = new ReactiveObject(); - EnableFsAccessLog = new ReactiveObject(); - FilteredClasses = new ReactiveObject(); - EnableFileLog = new ReactiveObject(); - EnableFileLog.Event += static (sender, e) => LogValueChange(sender, e, nameof(EnableFileLog)); - GraphicsDebugLevel = new ReactiveObject(); - } - } - - /// - /// System configuration section - /// - public class SystemSection - { - /// - /// Change System Language - /// - public ReactiveObject Language { get; private set; } - - /// - /// Change System Region - /// - public ReactiveObject Region { get; private set; } - - /// - /// Change System TimeZone - /// - public ReactiveObject TimeZone { get; private set; } - - /// - /// System Time Offset in Seconds - /// - public ReactiveObject SystemTimeOffset { get; private set; } - - /// - /// Enables or disables Docked Mode - /// - public ReactiveObject EnableDockedMode { get; private set; } - - /// - /// Enables or disables profiled translation cache persistency - /// - public ReactiveObject EnablePtc { get; private set; } - - /// - /// Enables integrity checks on Game content files - /// - public ReactiveObject EnableFsIntegrityChecks { get; private set; } - - /// - /// Enables FS access log output to the console. Possible modes are 0-3 - /// - public ReactiveObject FsGlobalAccessLogMode { get; private set; } - - /// - /// The selected audio backend - /// - public ReactiveObject AudioBackend { get; private set; } - - /// - /// Defines the amount of RAM available on the emulated system, and how it is distributed - /// - public ReactiveObject ExpandRam { get; private set; } - - /// - /// Enable or disable ignoring missing services - /// - public ReactiveObject IgnoreMissingServices { get; private set; } - - public SystemSection() - { - Language = new ReactiveObject(); - Region = new ReactiveObject(); - TimeZone = new ReactiveObject(); - SystemTimeOffset = new ReactiveObject(); - EnableDockedMode = new ReactiveObject(); - EnableDockedMode.Event += static (sender, e) => LogValueChange(sender, e, nameof(EnableDockedMode)); - EnablePtc = new ReactiveObject(); - EnablePtc.Event += static (sender, e) => LogValueChange(sender, e, nameof(EnablePtc)); - EnableFsIntegrityChecks = new ReactiveObject(); - EnableFsIntegrityChecks.Event += static (sender, e) => LogValueChange(sender, e, nameof(EnableFsIntegrityChecks)); - FsGlobalAccessLogMode = new ReactiveObject(); - FsGlobalAccessLogMode.Event += static (sender, e) => LogValueChange(sender, e, nameof(FsGlobalAccessLogMode)); - AudioBackend = new ReactiveObject(); - AudioBackend.Event += static (sender, e) => LogValueChange(sender, e, nameof(AudioBackend)); - ExpandRam = new ReactiveObject(); - ExpandRam.Event += static (sender, e) => LogValueChange(sender, e, nameof(ExpandRam)); - IgnoreMissingServices = new ReactiveObject(); - IgnoreMissingServices.Event += static (sender, e) => LogValueChange(sender, e, nameof(IgnoreMissingServices)); - } - } - - /// - /// Hid configuration section - /// - public class HidSection - { - /// - /// Enable or disable keyboard support (Independent from controllers binding) - /// - public ReactiveObject EnableKeyboard { get; private set; } - - /// - /// Hotkey Keyboard Bindings - /// - public ReactiveObject Hotkeys { get; private set; } - - /// - /// Input device configuration. - /// NOTE: This ReactiveObject won't issue an event when the List has elements added or removed. - /// TODO: Implement a ReactiveList class. - /// - public ReactiveObject> InputConfig { get; private set; } - - public HidSection() - { - EnableKeyboard = new ReactiveObject(); - Hotkeys = new ReactiveObject(); - InputConfig = new ReactiveObject>(); - } - } - - /// - /// Graphics configuration section - /// - public class GraphicsSection - { - /// - /// Max Anisotropy. Values range from 0 - 16. Set to -1 to let the game decide. - /// - public ReactiveObject MaxAnisotropy { get; private set; } - - /// - /// Aspect Ratio applied to the renderer window. - /// - public ReactiveObject AspectRatio { get; private set; } - - /// - /// Resolution Scale. An integer scale applied to applicable render targets. Values 1-4, or -1 to use a custom floating point scale instead. - /// - public ReactiveObject ResScale { get; private set; } - - /// - /// Custom Resolution Scale. A custom floating point scale applied to applicable render targets. Only active when Resolution Scale is -1. - /// - public ReactiveObject ResScaleCustom { get; private set; } - - /// - /// Dumps shaders in this local directory - /// - public ReactiveObject ShadersDumpPath { get; private set; } - - /// - /// Enables or disables Vertical Sync - /// - public ReactiveObject EnableVsync { get; private set; } - - /// - /// Enables or disables Shader cache - /// - public ReactiveObject EnableShaderCache { get; private set; } - - public GraphicsSection() - { - ResScale = new ReactiveObject(); - ResScale.Event += static (sender, e) => LogValueChange(sender, e, nameof(ResScale)); - ResScaleCustom = new ReactiveObject(); - ResScaleCustom.Event += static (sender, e) => LogValueChange(sender, e, nameof(ResScaleCustom)); - MaxAnisotropy = new ReactiveObject(); - MaxAnisotropy.Event += static (sender, e) => LogValueChange(sender, e, nameof(MaxAnisotropy)); - AspectRatio = new ReactiveObject(); - AspectRatio.Event += static (sender, e) => LogValueChange(sender, e, nameof(AspectRatio)); - ShadersDumpPath = new ReactiveObject(); - EnableVsync = new ReactiveObject(); - EnableVsync.Event += static (sender, e) => LogValueChange(sender, e, nameof(EnableVsync)); - EnableShaderCache = new ReactiveObject(); - EnableShaderCache.Event += static (sender, e) => LogValueChange(sender, e, nameof(EnableShaderCache)); - } - } - - /// - /// The default configuration instance - /// - public static ConfigurationState Instance { get; private set; } - - /// - /// The Ui section - /// - public UiSection Ui { get; private set; } - - /// - /// The Logger section - /// - public LoggerSection Logger { get; private set; } - - /// - /// The System section - /// - public SystemSection System { get; private set; } - - /// - /// The Graphics section - /// - public GraphicsSection Graphics { get; private set; } - - /// - /// The Hid section - /// - public HidSection Hid { get; private set; } - - /// - /// Enables or disables Discord Rich Presence - /// - public ReactiveObject EnableDiscordIntegration { get; private set; } - - /// - /// Checks for updates when Ryujinx starts when enabled - /// - public ReactiveObject CheckUpdatesOnStart { get; private set; } - - /// - /// Show "Confirm Exit" Dialog - /// - public ReactiveObject ShowConfirmExit { get; private set; } - - /// - /// Hide Cursor on Idle - /// - public ReactiveObject HideCursorOnIdle { get; private set; } - - private ConfigurationState() - { - Ui = new UiSection(); - Logger = new LoggerSection(); - System = new SystemSection(); - Graphics = new GraphicsSection(); - Hid = new HidSection(); - EnableDiscordIntegration = new ReactiveObject(); - CheckUpdatesOnStart = new ReactiveObject(); - ShowConfirmExit = new ReactiveObject(); - HideCursorOnIdle = new ReactiveObject(); - } - - public ConfigurationFileFormat ToFileFormat() - { - ConfigurationFileFormat configurationFile = new ConfigurationFileFormat - { - Version = ConfigurationFileFormat.CurrentVersion, - EnableFileLog = Logger.EnableFileLog, - ResScale = Graphics.ResScale, - ResScaleCustom = Graphics.ResScaleCustom, - MaxAnisotropy = Graphics.MaxAnisotropy, - AspectRatio = Graphics.AspectRatio, - GraphicsShadersDumpPath = Graphics.ShadersDumpPath, - LoggingEnableDebug = Logger.EnableDebug, - LoggingEnableStub = Logger.EnableStub, - LoggingEnableInfo = Logger.EnableInfo, - LoggingEnableWarn = Logger.EnableWarn, - LoggingEnableError = Logger.EnableError, - LoggingEnableGuest = Logger.EnableGuest, - LoggingEnableFsAccessLog = Logger.EnableFsAccessLog, - LoggingFilteredClasses = Logger.FilteredClasses, - LoggingGraphicsDebugLevel = Logger.GraphicsDebugLevel, - SystemLanguage = System.Language, - SystemRegion = System.Region, - SystemTimeZone = System.TimeZone, - SystemTimeOffset = System.SystemTimeOffset, - DockedMode = System.EnableDockedMode, - EnableDiscordIntegration = EnableDiscordIntegration, - CheckUpdatesOnStart = CheckUpdatesOnStart, - ShowConfirmExit = ShowConfirmExit, - HideCursorOnIdle = HideCursorOnIdle, - EnableVsync = Graphics.EnableVsync, - EnableShaderCache = Graphics.EnableShaderCache, - EnablePtc = System.EnablePtc, - EnableFsIntegrityChecks = System.EnableFsIntegrityChecks, - FsGlobalAccessLogMode = System.FsGlobalAccessLogMode, - AudioBackend = System.AudioBackend, - ExpandRam = System.ExpandRam, - IgnoreMissingServices = System.IgnoreMissingServices, - GuiColumns = new GuiColumns - { - FavColumn = Ui.GuiColumns.FavColumn, - IconColumn = Ui.GuiColumns.IconColumn, - AppColumn = Ui.GuiColumns.AppColumn, - DevColumn = Ui.GuiColumns.DevColumn, - VersionColumn = Ui.GuiColumns.VersionColumn, - TimePlayedColumn = Ui.GuiColumns.TimePlayedColumn, - LastPlayedColumn = Ui.GuiColumns.LastPlayedColumn, - FileExtColumn = Ui.GuiColumns.FileExtColumn, - FileSizeColumn = Ui.GuiColumns.FileSizeColumn, - PathColumn = Ui.GuiColumns.PathColumn, - }, - ColumnSort = new ColumnSort - { - SortColumnId = Ui.ColumnSort.SortColumnId, - SortAscending = Ui.ColumnSort.SortAscending - }, - GameDirs = Ui.GameDirs, - EnableCustomTheme = Ui.EnableCustomTheme, - CustomThemePath = Ui.CustomThemePath, - StartFullscreen = Ui.StartFullscreen, - EnableKeyboard = Hid.EnableKeyboard, - Hotkeys = Hid.Hotkeys, - KeyboardConfig = new List(), - ControllerConfig = new List(), - InputConfig = Hid.InputConfig, - }; - - return configurationFile; - } - - public void LoadDefault() - { - Logger.EnableFileLog.Value = true; - Graphics.ResScale.Value = 1; - Graphics.ResScaleCustom.Value = 1.0f; - Graphics.MaxAnisotropy.Value = -1.0f; - Graphics.AspectRatio.Value = AspectRatio.Fixed16x9; - Graphics.ShadersDumpPath.Value = ""; - Logger.EnableDebug.Value = false; - Logger.EnableStub.Value = true; - Logger.EnableInfo.Value = true; - Logger.EnableWarn.Value = true; - Logger.EnableError.Value = true; - Logger.EnableGuest.Value = true; - Logger.EnableFsAccessLog.Value = false; - Logger.FilteredClasses.Value = Array.Empty(); - Logger.GraphicsDebugLevel.Value = GraphicsDebugLevel.None; - System.Language.Value = Language.AmericanEnglish; - System.Region.Value = Region.USA; - System.TimeZone.Value = "UTC"; - System.SystemTimeOffset.Value = 0; - System.EnableDockedMode.Value = true; - EnableDiscordIntegration.Value = true; - CheckUpdatesOnStart.Value = true; - ShowConfirmExit.Value = true; - HideCursorOnIdle.Value = false; - Graphics.EnableVsync.Value = true; - Graphics.EnableShaderCache.Value = true; - System.EnablePtc.Value = true; - System.EnableFsIntegrityChecks.Value = true; - System.FsGlobalAccessLogMode.Value = 0; - System.AudioBackend.Value = AudioBackend.OpenAl; - System.ExpandRam.Value = false; - System.IgnoreMissingServices.Value = false; - Ui.GuiColumns.FavColumn.Value = true; - Ui.GuiColumns.IconColumn.Value = true; - Ui.GuiColumns.AppColumn.Value = true; - Ui.GuiColumns.DevColumn.Value = true; - Ui.GuiColumns.VersionColumn.Value = true; - Ui.GuiColumns.TimePlayedColumn.Value = true; - Ui.GuiColumns.LastPlayedColumn.Value = true; - Ui.GuiColumns.FileExtColumn.Value = true; - Ui.GuiColumns.FileSizeColumn.Value = true; - Ui.GuiColumns.PathColumn.Value = true; - Ui.ColumnSort.SortColumnId.Value = 0; - Ui.ColumnSort.SortAscending.Value = false; - Ui.GameDirs.Value = new List(); - Ui.EnableCustomTheme.Value = false; - Ui.CustomThemePath.Value = ""; - Ui.StartFullscreen.Value = false; - Hid.EnableKeyboard.Value = false; - Hid.Hotkeys.Value = new KeyboardHotkeys - { - ToggleVsync = Key.Tab - }; - Hid.InputConfig.Value = new List - { - new StandardKeyboardInputConfig - { - Version = InputConfig.CurrentVersion, - Backend = InputBackendType.WindowKeyboard, - Id = "0", - PlayerIndex = PlayerIndex.Player1, - ControllerType = ControllerType.JoyconPair, - LeftJoycon = new LeftJoyconCommonConfig - { - DpadUp = Key.Up, - DpadDown = Key.Down, - DpadLeft = Key.Left, - DpadRight = Key.Right, - ButtonMinus = Key.Minus, - ButtonL = Key.E, - ButtonZl = Key.Q, - ButtonSl = Key.Unbound, - ButtonSr = Key.Unbound - }, - - LeftJoyconStick = new JoyconConfigKeyboardStick - { - StickUp = Key.W, - StickDown = Key.S, - StickLeft = Key.A, - StickRight = Key.D, - StickButton = Key.F, - }, - - RightJoycon = new RightJoyconCommonConfig - { - ButtonA = Key.Z, - ButtonB = Key.X, - ButtonX = Key.C, - ButtonY = Key.V, - ButtonPlus = Key.Plus, - ButtonR = Key.U, - ButtonZr = Key.O, - ButtonSl = Key.Unbound, - ButtonSr = Key.Unbound - }, - - RightJoyconStick = new JoyconConfigKeyboardStick - { - StickUp = Key.I, - StickDown = Key.K, - StickLeft = Key.J, - StickRight = Key.L, - StickButton = Key.H, - } - } - }; - } - - public void Load(ConfigurationFileFormat configurationFileFormat, string configurationFilePath) - { - bool configurationFileUpdated = false; - - if (configurationFileFormat.Version < 0 || configurationFileFormat.Version > ConfigurationFileFormat.CurrentVersion) - { - Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Unsupported configuration version {configurationFileFormat.Version}, loading default."); - - LoadDefault(); - - return; - } - - if (configurationFileFormat.Version < 2) - { - Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 2."); - - configurationFileFormat.SystemRegion = Region.USA; - - configurationFileUpdated = true; - } - - if (configurationFileFormat.Version < 3) - { - Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 3."); - - configurationFileFormat.SystemTimeZone = "UTC"; - - configurationFileUpdated = true; - } - - if (configurationFileFormat.Version < 4) - { - Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 4."); - - configurationFileFormat.MaxAnisotropy = -1; - - configurationFileUpdated = true; - } - - if (configurationFileFormat.Version < 5) - { - Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 5."); - - configurationFileFormat.SystemTimeOffset = 0; - - configurationFileUpdated = true; - } - - if (configurationFileFormat.Version < 8) - { - Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 8."); - - configurationFileFormat.EnablePtc = true; - - configurationFileUpdated = true; - } - - if (configurationFileFormat.Version < 9) - { - Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 9."); - - configurationFileFormat.ColumnSort = new ColumnSort - { - SortColumnId = 0, - SortAscending = false - }; - - configurationFileFormat.Hotkeys = new KeyboardHotkeys - { - ToggleVsync = Key.Tab - }; - - configurationFileUpdated = true; - } - - if (configurationFileFormat.Version < 10) - { - Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 10."); - - configurationFileFormat.AudioBackend = AudioBackend.OpenAl; - - configurationFileUpdated = true; - } - - if (configurationFileFormat.Version < 11) - { - Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 11."); - - configurationFileFormat.ResScale = 1; - configurationFileFormat.ResScaleCustom = 1.0f; - - configurationFileUpdated = true; - } - - if (configurationFileFormat.Version < 12) - { - Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 12."); - - configurationFileFormat.LoggingGraphicsDebugLevel = GraphicsDebugLevel.None; - - configurationFileUpdated = true; - } - - if (configurationFileFormat.Version < 14) - { - Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 14."); - - configurationFileFormat.CheckUpdatesOnStart = true; - - configurationFileUpdated = true; - } - - if (configurationFileFormat.Version < 16) - { - Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 16."); - - configurationFileFormat.EnableShaderCache = true; - - configurationFileUpdated = true; - } - - if (configurationFileFormat.Version < 17) - { - Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 17."); - - configurationFileFormat.StartFullscreen = false; - - configurationFileUpdated = true; - } - - if (configurationFileFormat.Version < 18) - { - Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 18."); - - configurationFileFormat.AspectRatio = AspectRatio.Fixed16x9; - - configurationFileUpdated = true; - } - - if (configurationFileFormat.Version < 20) - { - Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 20."); - - configurationFileFormat.ShowConfirmExit = true; - - configurationFileUpdated = true; - } - - if (configurationFileFormat.Version < 22) - { - Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 22."); - - configurationFileFormat.HideCursorOnIdle = false; - - configurationFileUpdated = true; - } - - if (configurationFileFormat.Version < 24) - { - Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 24."); - - configurationFileFormat.InputConfig = new List - { - new StandardKeyboardInputConfig - { - Version = InputConfig.CurrentVersion, - Backend = InputBackendType.WindowKeyboard, - Id = "0", - PlayerIndex = PlayerIndex.Player1, - ControllerType = ControllerType.JoyconPair, - LeftJoycon = new LeftJoyconCommonConfig - { - DpadUp = Key.Up, - DpadDown = Key.Down, - DpadLeft = Key.Left, - DpadRight = Key.Right, - ButtonMinus = Key.Minus, - ButtonL = Key.E, - ButtonZl = Key.Q, - ButtonSl = Key.Unbound, - ButtonSr = Key.Unbound - }, - - LeftJoyconStick = new JoyconConfigKeyboardStick - { - StickUp = Key.W, - StickDown = Key.S, - StickLeft = Key.A, - StickRight = Key.D, - StickButton = Key.F, - }, - - RightJoycon = new RightJoyconCommonConfig - { - ButtonA = Key.Z, - ButtonB = Key.X, - ButtonX = Key.C, - ButtonY = Key.V, - ButtonPlus = Key.Plus, - ButtonR = Key.U, - ButtonZr = Key.O, - ButtonSl = Key.Unbound, - ButtonSr = Key.Unbound - }, - - RightJoyconStick = new JoyconConfigKeyboardStick - { - StickUp = Key.I, - StickDown = Key.K, - StickLeft = Key.J, - StickRight = Key.L, - StickButton = Key.H, - } - } - }; - - configurationFileUpdated = true; - } - - if (configurationFileFormat.Version < 25) - { - Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 25."); - - configurationFileUpdated = true; - } - - Logger.EnableFileLog.Value = configurationFileFormat.EnableFileLog; - Graphics.ResScale.Value = configurationFileFormat.ResScale; - Graphics.ResScaleCustom.Value = configurationFileFormat.ResScaleCustom; - Graphics.MaxAnisotropy.Value = configurationFileFormat.MaxAnisotropy; - Graphics.AspectRatio.Value = configurationFileFormat.AspectRatio; - Graphics.ShadersDumpPath.Value = configurationFileFormat.GraphicsShadersDumpPath; - Logger.EnableDebug.Value = configurationFileFormat.LoggingEnableDebug; - Logger.EnableStub.Value = configurationFileFormat.LoggingEnableStub; - Logger.EnableInfo.Value = configurationFileFormat.LoggingEnableInfo; - Logger.EnableWarn.Value = configurationFileFormat.LoggingEnableWarn; - Logger.EnableError.Value = configurationFileFormat.LoggingEnableError; - Logger.EnableGuest.Value = configurationFileFormat.LoggingEnableGuest; - Logger.EnableFsAccessLog.Value = configurationFileFormat.LoggingEnableFsAccessLog; - Logger.FilteredClasses.Value = configurationFileFormat.LoggingFilteredClasses; - Logger.GraphicsDebugLevel.Value = configurationFileFormat.LoggingGraphicsDebugLevel; - System.Language.Value = configurationFileFormat.SystemLanguage; - System.Region.Value = configurationFileFormat.SystemRegion; - System.TimeZone.Value = configurationFileFormat.SystemTimeZone; - System.SystemTimeOffset.Value = configurationFileFormat.SystemTimeOffset; - System.EnableDockedMode.Value = configurationFileFormat.DockedMode; - EnableDiscordIntegration.Value = configurationFileFormat.EnableDiscordIntegration; - CheckUpdatesOnStart.Value = configurationFileFormat.CheckUpdatesOnStart; - ShowConfirmExit.Value = configurationFileFormat.ShowConfirmExit; - HideCursorOnIdle.Value = configurationFileFormat.HideCursorOnIdle; - Graphics.EnableVsync.Value = configurationFileFormat.EnableVsync; - Graphics.EnableShaderCache.Value = configurationFileFormat.EnableShaderCache; - System.EnablePtc.Value = configurationFileFormat.EnablePtc; - System.EnableFsIntegrityChecks.Value = configurationFileFormat.EnableFsIntegrityChecks; - System.FsGlobalAccessLogMode.Value = configurationFileFormat.FsGlobalAccessLogMode; - System.AudioBackend.Value = configurationFileFormat.AudioBackend; - System.ExpandRam.Value = configurationFileFormat.ExpandRam; - System.IgnoreMissingServices.Value = configurationFileFormat.IgnoreMissingServices; - Ui.GuiColumns.FavColumn.Value = configurationFileFormat.GuiColumns.FavColumn; - Ui.GuiColumns.IconColumn.Value = configurationFileFormat.GuiColumns.IconColumn; - Ui.GuiColumns.AppColumn.Value = configurationFileFormat.GuiColumns.AppColumn; - Ui.GuiColumns.DevColumn.Value = configurationFileFormat.GuiColumns.DevColumn; - Ui.GuiColumns.VersionColumn.Value = configurationFileFormat.GuiColumns.VersionColumn; - Ui.GuiColumns.TimePlayedColumn.Value = configurationFileFormat.GuiColumns.TimePlayedColumn; - Ui.GuiColumns.LastPlayedColumn.Value = configurationFileFormat.GuiColumns.LastPlayedColumn; - Ui.GuiColumns.FileExtColumn.Value = configurationFileFormat.GuiColumns.FileExtColumn; - Ui.GuiColumns.FileSizeColumn.Value = configurationFileFormat.GuiColumns.FileSizeColumn; - Ui.GuiColumns.PathColumn.Value = configurationFileFormat.GuiColumns.PathColumn; - Ui.ColumnSort.SortColumnId.Value = configurationFileFormat.ColumnSort.SortColumnId; - Ui.ColumnSort.SortAscending.Value = configurationFileFormat.ColumnSort.SortAscending; - Ui.GameDirs.Value = configurationFileFormat.GameDirs; - Ui.EnableCustomTheme.Value = configurationFileFormat.EnableCustomTheme; - Ui.CustomThemePath.Value = configurationFileFormat.CustomThemePath; - Ui.StartFullscreen.Value = configurationFileFormat.StartFullscreen; - Hid.EnableKeyboard.Value = configurationFileFormat.EnableKeyboard; - Hid.Hotkeys.Value = configurationFileFormat.Hotkeys; - Hid.InputConfig.Value = configurationFileFormat.InputConfig; - - if (Hid.InputConfig.Value == null) - { - Hid.InputConfig.Value = new List(); - } - - if (configurationFileUpdated) - { - ToFileFormat().SaveConfig(configurationFilePath); - - Common.Logging.Logger.Notice.Print(LogClass.Application, $"Configuration file updated to version {ConfigurationFileFormat.CurrentVersion}"); - } - } - - private static void LogValueChange(object sender, ReactiveEventArgs eventArgs, string valueName) - { - Common.Logging.Logger.Info?.Print(LogClass.Configuration, $"{valueName} set to: {eventArgs.NewValue}"); - } - - public static void Initialize() - { - if (Instance != null) - { - throw new InvalidOperationException("Configuration is already initialized"); - } - - Instance = new ConfigurationState(); - } - } -} diff --git a/Ryujinx.Common/Configuration/LoggerModule.cs b/Ryujinx.Common/Configuration/LoggerModule.cs deleted file mode 100644 index 20c0fb46..00000000 --- a/Ryujinx.Common/Configuration/LoggerModule.cs +++ /dev/null @@ -1,89 +0,0 @@ -using Ryujinx.Common; -using Ryujinx.Common.Logging; -using System; -using System.IO; - -namespace Ryujinx.Configuration -{ - public static class LoggerModule - { - public static void Initialize() - { - ConfigurationState.Instance.Logger.EnableDebug.Event += ReloadEnableDebug; - ConfigurationState.Instance.Logger.EnableStub.Event += ReloadEnableStub; - ConfigurationState.Instance.Logger.EnableInfo.Event += ReloadEnableInfo; - ConfigurationState.Instance.Logger.EnableWarn.Event += ReloadEnableWarning; - ConfigurationState.Instance.Logger.EnableError.Event += ReloadEnableError; - ConfigurationState.Instance.Logger.EnableGuest.Event += ReloadEnableGuest; - ConfigurationState.Instance.Logger.EnableFsAccessLog.Event += ReloadEnableFsAccessLog; - ConfigurationState.Instance.Logger.FilteredClasses.Event += ReloadFilteredClasses; - ConfigurationState.Instance.Logger.EnableFileLog.Event += ReloadFileLogger; - } - - private static void ReloadEnableDebug(object sender, ReactiveEventArgs e) - { - Logger.SetEnable(LogLevel.Debug, e.NewValue); - } - - private static void ReloadEnableStub(object sender, ReactiveEventArgs e) - { - Logger.SetEnable(LogLevel.Stub, e.NewValue); - } - - private static void ReloadEnableInfo(object sender, ReactiveEventArgs e) - { - Logger.SetEnable(LogLevel.Info, e.NewValue); - } - - private static void ReloadEnableWarning(object sender, ReactiveEventArgs e) - { - Logger.SetEnable(LogLevel.Warning, e.NewValue); - } - - private static void ReloadEnableError(object sender, ReactiveEventArgs e) - { - Logger.SetEnable(LogLevel.Error, e.NewValue); - } - - private static void ReloadEnableGuest(object sender, ReactiveEventArgs e) - { - Logger.SetEnable(LogLevel.Guest, e.NewValue); - } - - private static void ReloadEnableFsAccessLog(object sender, ReactiveEventArgs e) - { - Logger.SetEnable(LogLevel.AccessLog, e.NewValue); - } - - private static void ReloadFilteredClasses(object sender, ReactiveEventArgs e) - { - bool noFilter = e.NewValue.Length == 0; - - foreach (var logClass in EnumExtensions.GetValues()) - { - Logger.SetEnable(logClass, noFilter); - } - - foreach (var logClass in e.NewValue) - { - Logger.SetEnable(logClass, true); - } - } - - private static void ReloadFileLogger(object sender, ReactiveEventArgs e) - { - if (e.NewValue) - { - Logger.AddTarget(new AsyncLogTargetWrapper( - new FileLogTarget(AppDomain.CurrentDomain.BaseDirectory, "file"), - 1000, - AsyncLogTargetOverflowAction.Block - )); - } - else - { - Logger.RemoveTarget("file"); - } - } - } -} diff --git a/Ryujinx.Common/Configuration/System/Language.cs b/Ryujinx.Common/Configuration/System/Language.cs deleted file mode 100644 index d3af296b..00000000 --- a/Ryujinx.Common/Configuration/System/Language.cs +++ /dev/null @@ -1,23 +0,0 @@ -namespace Ryujinx.Configuration.System -{ - public enum Language - { - Japanese, - AmericanEnglish, - French, - German, - Italian, - Spanish, - Chinese, - Korean, - Dutch, - Portuguese, - Russian, - Taiwanese, - BritishEnglish, - CanadianFrench, - LatinAmericanSpanish, - SimplifiedChinese, - TraditionalChinese - } -} diff --git a/Ryujinx.Common/Configuration/System/Region.cs b/Ryujinx.Common/Configuration/System/Region.cs deleted file mode 100644 index 54b1c36f..00000000 --- a/Ryujinx.Common/Configuration/System/Region.cs +++ /dev/null @@ -1,13 +0,0 @@ -namespace Ryujinx.Configuration.System -{ - public enum Region - { - Japan, - USA, - Europe, - Australia, - China, - Korea, - Taiwan - } -} diff --git a/Ryujinx.Common/Configuration/Ui/ColumnSort.cs b/Ryujinx.Common/Configuration/Ui/ColumnSort.cs deleted file mode 100644 index fd8b5da1..00000000 --- a/Ryujinx.Common/Configuration/Ui/ColumnSort.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace Ryujinx.Configuration.Ui -{ - public struct ColumnSort - { - public int SortColumnId { get; set; } - public bool SortAscending { get; set; } - } -} \ No newline at end of file diff --git a/Ryujinx.Common/Configuration/Ui/GuiColumns.cs b/Ryujinx.Common/Configuration/Ui/GuiColumns.cs deleted file mode 100644 index de4f7369..00000000 --- a/Ryujinx.Common/Configuration/Ui/GuiColumns.cs +++ /dev/null @@ -1,16 +0,0 @@ -namespace Ryujinx.Configuration.Ui -{ - public struct GuiColumns - { - public bool FavColumn { get; set; } - public bool IconColumn { get; set; } - public bool AppColumn { get; set; } - public bool DevColumn { get; set; } - public bool VersionColumn { get; set; } - public bool TimePlayedColumn { get; set; } - public bool LastPlayedColumn { get; set; } - public bool FileExtColumn { get; set; } - public bool FileSizeColumn { get; set; } - public bool PathColumn { get; set; } - } -} diff --git a/Ryujinx.HLE/FileSystem/Content/ContentManager.cs b/Ryujinx.HLE/FileSystem/Content/ContentManager.cs index f2b62eef..a18838ab 100644 --- a/Ryujinx.HLE/FileSystem/Content/ContentManager.cs +++ b/Ryujinx.HLE/FileSystem/Content/ContentManager.cs @@ -197,7 +197,7 @@ namespace Ryujinx.HLE.FileSystem.Content } // fs must contain AOC nca files in its root - public void AddAocData(IFileSystem fs, string containerPath, ulong aocBaseId) + public void AddAocData(IFileSystem fs, string containerPath, ulong aocBaseId, IntegrityCheckLevel integrityCheckLevel) { _virtualFileSystem.ImportTickets(fs); @@ -214,7 +214,7 @@ namespace Ryujinx.HLE.FileSystem.Content continue; } - using var pfs0 = nca.OpenFileSystem(0, Switch.GetIntegrityCheckLevel()); + using var pfs0 = nca.OpenFileSystem(0, integrityCheckLevel); pfs0.OpenFile(out IFile cnmtFile, pfs0.EnumerateEntries().Single().FullPath.ToU8Span(), OpenMode.Read); @@ -265,7 +265,7 @@ namespace Ryujinx.HLE.FileSystem.Content public IList GetAocTitleIds() => _aocData.Where(e => e.Value.Enabled).Select(e => e.Key).ToList(); - public bool GetAocDataStorage(ulong aocTitleId, out IStorage aocStorage) + public bool GetAocDataStorage(ulong aocTitleId, out IStorage aocStorage, IntegrityCheckLevel integrityCheckLevel) { aocStorage = null; @@ -289,7 +289,7 @@ namespace Ryujinx.HLE.FileSystem.Content return false; // Print error? } - aocStorage = new Nca(_virtualFileSystem.KeySet, ncaFile.AsStorage()).OpenStorage(NcaSectionType.Data, Switch.GetIntegrityCheckLevel()); + aocStorage = new Nca(_virtualFileSystem.KeySet, ncaFile.AsStorage()).OpenStorage(NcaSectionType.Data, integrityCheckLevel); return true; } @@ -710,8 +710,6 @@ namespace Ryujinx.HLE.FileSystem.Content SystemVersion VerifyAndGetVersionZip(ZipArchive archive) { - IntegrityCheckLevel integrityCheckLevel = Switch.GetIntegrityCheckLevel(); - SystemVersion systemVersion = null; foreach (var entry in archive.Entries) @@ -751,7 +749,7 @@ namespace Ryujinx.HLE.FileSystem.Content { Nca metaNca = new Nca(_virtualFileSystem.KeySet, ncaStream.AsStorage()); - IFileSystem fs = metaNca.OpenFileSystem(NcaSectionType.Data, integrityCheckLevel); + IFileSystem fs = metaNca.OpenFileSystem(NcaSectionType.Data, IntegrityCheckLevel.ErrorOnInvalid); string cnmtPath = fs.EnumerateEntries("/", "*.cnmt").Single().FullPath; @@ -781,7 +779,7 @@ namespace Ryujinx.HLE.FileSystem.Content { Nca nca = new Nca(_virtualFileSystem.KeySet, ncaStream.AsStorage()); - var romfs = nca.OpenFileSystem(NcaSectionType.Data, integrityCheckLevel); + var romfs = nca.OpenFileSystem(NcaSectionType.Data, IntegrityCheckLevel.ErrorOnInvalid); if (romfs.OpenFile(out IFile systemVersionFile, "/file".ToU8Span(), OpenMode.Read).IsSuccess()) { @@ -816,7 +814,7 @@ namespace Ryujinx.HLE.FileSystem.Content { Nca metaNca = new Nca(_virtualFileSystem.KeySet, metaNcaStream.AsStorage()); - IFileSystem fs = metaNca.OpenFileSystem(NcaSectionType.Data, integrityCheckLevel); + IFileSystem fs = metaNca.OpenFileSystem(NcaSectionType.Data, IntegrityCheckLevel.ErrorOnInvalid); string cnmtPath = fs.EnumerateEntries("/", "*.cnmt").Single().FullPath; @@ -873,8 +871,6 @@ namespace Ryujinx.HLE.FileSystem.Content SystemVersion VerifyAndGetVersion(IFileSystem filesystem) { - IntegrityCheckLevel integrityCheckLevel = Switch.GetIntegrityCheckLevel(); - SystemVersion systemVersion = null; CnmtContentMetaEntry[] metaEntries = null; @@ -887,7 +883,7 @@ namespace Ryujinx.HLE.FileSystem.Content if (nca.Header.TitleId == SystemUpdateTitleId && nca.Header.ContentType == NcaContentType.Meta) { - IFileSystem fs = nca.OpenFileSystem(NcaSectionType.Data, integrityCheckLevel); + IFileSystem fs = nca.OpenFileSystem(NcaSectionType.Data, IntegrityCheckLevel.ErrorOnInvalid); string cnmtPath = fs.EnumerateEntries("/", "*.cnmt").Single().FullPath; @@ -905,7 +901,7 @@ namespace Ryujinx.HLE.FileSystem.Content } else if (nca.Header.TitleId == SystemVersionTitleId && nca.Header.ContentType == NcaContentType.Data) { - var romfs = nca.OpenFileSystem(NcaSectionType.Data, integrityCheckLevel); + var romfs = nca.OpenFileSystem(NcaSectionType.Data, IntegrityCheckLevel.ErrorOnInvalid); if (romfs.OpenFile(out IFile systemVersionFile, "/file".ToU8Span(), OpenMode.Read).IsSuccess()) { @@ -952,7 +948,7 @@ namespace Ryujinx.HLE.FileSystem.Content Nca metaNca = new Nca(_virtualFileSystem.KeySet, metaStorage); - IFileSystem fs = metaNca.OpenFileSystem(NcaSectionType.Data, integrityCheckLevel); + IFileSystem fs = metaNca.OpenFileSystem(NcaSectionType.Data, IntegrityCheckLevel.ErrorOnInvalid); string cnmtPath = fs.EnumerateEntries("/", "*.cnmt").Single().FullPath; @@ -1004,8 +1000,6 @@ namespace Ryujinx.HLE.FileSystem.Content public SystemVersion GetCurrentFirmwareVersion() { - IntegrityCheckLevel integrityCheckLevel = Switch.GetIntegrityCheckLevel(); - LoadEntries(); lock (_lock) @@ -1024,7 +1018,7 @@ namespace Ryujinx.HLE.FileSystem.Content if (nca.Header.TitleId == SystemVersionTitleId && nca.Header.ContentType == NcaContentType.Data) { - var romfs = nca.OpenFileSystem(NcaSectionType.Data, integrityCheckLevel); + var romfs = nca.OpenFileSystem(NcaSectionType.Data, IntegrityCheckLevel.ErrorOnInvalid); if (romfs.OpenFile(out IFile systemVersionFile, "/file".ToU8Span(), OpenMode.Read).IsSuccess()) { diff --git a/Ryujinx.HLE/HLEConfiguration.cs b/Ryujinx.HLE/HLEConfiguration.cs new file mode 100644 index 00000000..00c79169 --- /dev/null +++ b/Ryujinx.HLE/HLEConfiguration.cs @@ -0,0 +1,179 @@ +using LibHac.FsSystem; +using Ryujinx.Audio.Integration; +using Ryujinx.Common; +using Ryujinx.Common.Configuration; +using Ryujinx.Common.Configuration.Hid; +using Ryujinx.Graphics.GAL; +using Ryujinx.HLE.FileSystem; +using Ryujinx.HLE.FileSystem.Content; +using Ryujinx.HLE.HOS; +using Ryujinx.HLE.HOS.Services.Account.Acc; +using Ryujinx.HLE.HOS.SystemState; +using System; +using System.Collections.Generic; + +namespace Ryujinx.HLE +{ + /// + /// HLE configuration. + /// + public class HLEConfiguration + { + /// + /// The virtual file system used by the FS service. + /// + /// This cannot be changed after instantiation. + internal readonly VirtualFileSystem VirtualFileSystem; + + /// + /// The account manager used by the account service. + /// + /// This cannot be changed after instantiation. + internal readonly AccountManager AccountManager; + + /// + /// The content manager used by the NCM service. + /// + /// This cannot be changed after instantiation. + internal readonly ContentManager ContentManager; + + /// + /// The persistant information between run for multi-application capabilities. + /// + /// This cannot be changed after instantiation. + public readonly UserChannelPersistence UserChannelPersistence; + + /// + /// The GPU renderer to use for all GPU operations. + /// + /// This cannot be changed after instantiation. + internal readonly IRenderer GpuRenderer; + + /// + /// The audio device driver to use for all audio operations. + /// + /// This cannot be changed after instantiation. + internal readonly IHardwareDeviceDriver AudioDeviceDriver; + + /// + /// The handler for various UI related operations needed outside of HLE. + /// + /// This cannot be changed after instantiation. + internal readonly IHostUiHandler HostUiHandler; + + /// + /// Control the memory configuration used by the emulation context. + /// + /// This cannot be changed after instantiation. + internal readonly MemoryConfiguration MemoryConfiguration; + + /// + /// The system language to use in the settings service. + /// + /// This cannot be changed after instantiation. + internal readonly SystemLanguage SystemLanguage; + + /// + /// The system region to use in the settings service. + /// + /// This cannot be changed after instantiation. + internal readonly RegionCode Region; + + /// + /// Control the initial state of the vertical sync in the SurfaceFlinger service. + /// + internal readonly bool EnableVsync; + + /// + /// Control the initial state of the docked mode. + /// + internal readonly bool EnableDockedMode; + + /// + /// Control if the Profiled Translation Cache (PTC) should be used. + /// + internal readonly bool EnablePtc; + + /// + /// Control LibHac's integrity check level. + /// + /// This cannot be changed after instantiation. + internal readonly IntegrityCheckLevel FsIntegrityCheckLevel; + + /// + /// Control LibHac's global access logging level. Value must be between 0 and 3. + /// + /// This cannot be changed after instantiation. + internal readonly int FsGlobalAccessLogMode; + + /// + /// The system time offset to apply to the time service steady and local clocks. + /// + /// This cannot be changed after instantiation. + internal readonly long SystemTimeOffset; + + /// + /// The system timezone used by the time service. + /// + /// This cannot be changed after instantiation. + internal readonly string TimeZone; + + /// + /// Control the inital state of the ignore missing services setting. + /// If this is set to true, when a missing service is encountered, it will try to automatically handle it instead of throwing an exception. + /// + /// TODO: Update this again. + public bool IgnoreMissingServices { internal get; set; } + + /// + /// Aspect Ratio applied to the renderer window by the SurfaceFlinger service. + /// + public AspectRatio AspectRatio { internal get; set; } + + /// + /// An action called when HLE force a refresh of output after docked mode changed. + /// + public Action RefreshInputConfig { internal get; set; } + + public HLEConfiguration(VirtualFileSystem virtualFileSystem, + ContentManager contentManager, + AccountManager accountManager, + UserChannelPersistence userChannelPersistence, + IRenderer gpuRenderer, + IHardwareDeviceDriver audioDeviceDriver, + MemoryConfiguration memoryConfiguration, + IHostUiHandler hostUiHandler, + SystemLanguage systemLanguage, + RegionCode region, + bool enableVsync, + bool enableDockedMode, + bool enablePtc, + IntegrityCheckLevel fsIntegrityCheckLevel, + int fsGlobalAccessLogMode, + long systemTimeOffset, + string timeZone, + bool ignoreMissingServices, + AspectRatio aspectRatio) + { + VirtualFileSystem = virtualFileSystem; + AccountManager = accountManager; + ContentManager = contentManager; + UserChannelPersistence = userChannelPersistence; + GpuRenderer = gpuRenderer; + AudioDeviceDriver = audioDeviceDriver; + MemoryConfiguration = memoryConfiguration; + HostUiHandler = hostUiHandler; + SystemLanguage = systemLanguage; + Region = region; + EnableVsync = enableVsync; + EnableDockedMode = enableDockedMode; + EnablePtc = enablePtc; + FsIntegrityCheckLevel = fsIntegrityCheckLevel; + FsGlobalAccessLogMode = fsGlobalAccessLogMode; + SystemTimeOffset = systemTimeOffset; + TimeZone = timeZone; + IgnoreMissingServices = ignoreMissingServices; + AspectRatio = aspectRatio; + } + } +} diff --git a/Ryujinx.HLE/HOS/ApplicationLoader.cs b/Ryujinx.HLE/HOS/ApplicationLoader.cs index 05db567a..3832dd3e 100644 --- a/Ryujinx.HLE/HOS/ApplicationLoader.cs +++ b/Ryujinx.HLE/HOS/ApplicationLoader.cs @@ -10,7 +10,6 @@ using LibHac.Ns; using Ryujinx.Common.Configuration; using Ryujinx.Common.Logging; using Ryujinx.HLE.FileSystem; -using Ryujinx.HLE.FileSystem.Content; using Ryujinx.HLE.HOS.Kernel.Process; using Ryujinx.HLE.Loaders.Executables; using Ryujinx.HLE.Loaders.Npdm; @@ -49,10 +48,7 @@ namespace Ryujinx.HLE.HOS "sdk" }; - private readonly Switch _device; - private readonly ContentManager _contentManager; - private readonly VirtualFileSystem _fileSystem; - + private readonly Switch _device; private string _titleName; private string _displayVersion; private BlitStruct _controlData; @@ -66,12 +62,9 @@ namespace Ryujinx.HLE.HOS public string TitleIdText => TitleId.ToString("x16"); - public ApplicationLoader(Switch device, VirtualFileSystem fileSystem, ContentManager contentManager) + public ApplicationLoader(Switch device) { - _device = device; - _contentManager = contentManager; - _fileSystem = fileSystem; - + _device = device; _controlData = new BlitStruct(1); } @@ -79,14 +72,14 @@ namespace Ryujinx.HLE.HOS { if (romFsFile != null) { - _fileSystem.LoadRomFs(romFsFile); + _device.Configuration.VirtualFileSystem.LoadRomFs(romFsFile); } LocalFileSystem codeFs = new LocalFileSystem(exeFsDir); Npdm metaData = ReadNpdm(codeFs); - _fileSystem.ModLoader.CollectMods(new[] { TitleId }, _fileSystem.ModLoader.GetModsBasePath()); + _device.Configuration.VirtualFileSystem.ModLoader.CollectMods(new[] { TitleId }, _device.Configuration.VirtualFileSystem.ModLoader.GetModsBasePath()); if (TitleId != 0) { @@ -209,7 +202,7 @@ namespace Ryujinx.HLE.HOS public void LoadXci(string xciFile) { FileStream file = new FileStream(xciFile, FileMode.Open, FileAccess.Read); - Xci xci = new Xci(_fileSystem.KeySet, file.AsStorage()); + Xci xci = new Xci(_device.Configuration.VirtualFileSystem.KeySet, file.AsStorage()); if (!xci.HasPartition(XciPartitionType.Secure)) { @@ -226,7 +219,7 @@ namespace Ryujinx.HLE.HOS try { - (mainNca, patchNca, controlNca) = GetGameData(_fileSystem, securePartition, _device.UserChannelPersistence.Index); + (mainNca, patchNca, controlNca) = GetGameData(_device.Configuration.VirtualFileSystem, securePartition, _device.Configuration.UserChannelPersistence.Index); } catch (Exception e) { @@ -242,9 +235,9 @@ namespace Ryujinx.HLE.HOS return; } - _contentManager.LoadEntries(_device); - _contentManager.ClearAocData(); - _contentManager.AddAocData(securePartition, xciFile, mainNca.Header.TitleId); + _device.Configuration.ContentManager.LoadEntries(_device); + _device.Configuration.ContentManager.ClearAocData(); + _device.Configuration.ContentManager.AddAocData(securePartition, xciFile, mainNca.Header.TitleId, _device.Configuration.FsIntegrityCheckLevel); LoadNca(mainNca, patchNca, controlNca); } @@ -260,7 +253,7 @@ namespace Ryujinx.HLE.HOS try { - (mainNca, patchNca, controlNca) = GetGameData(_fileSystem, nsp, _device.UserChannelPersistence.Index); + (mainNca, patchNca, controlNca) = GetGameData(_device.Configuration.VirtualFileSystem, nsp, _device.Configuration.UserChannelPersistence.Index); } catch (Exception e) { @@ -278,8 +271,8 @@ namespace Ryujinx.HLE.HOS if (mainNca != null) { - _contentManager.ClearAocData(); - _contentManager.AddAocData(nsp, nspFile, mainNca.Header.TitleId); + _device.Configuration.ContentManager.ClearAocData(); + _device.Configuration.ContentManager.AddAocData(nsp, nspFile, mainNca.Header.TitleId, _device.Configuration.FsIntegrityCheckLevel); LoadNca(mainNca, patchNca, controlNca); @@ -293,7 +286,7 @@ namespace Ryujinx.HLE.HOS public void LoadNca(string ncaFile) { FileStream file = new FileStream(ncaFile, FileMode.Open, FileAccess.Read); - Nca nca = new Nca(_fileSystem.KeySet, file.AsStorage(false)); + Nca nca = new Nca(_device.Configuration.VirtualFileSystem.KeySet, file.AsStorage(false)); LoadNca(nca, null, null); } @@ -310,7 +303,7 @@ namespace Ryujinx.HLE.HOS IStorage dataStorage = null; IFileSystem codeFs = null; - (Nca updatePatchNca, Nca updateControlNca) = GetGameUpdateData(_fileSystem, mainNca.Header.TitleId.ToString("x16"), _device.UserChannelPersistence.Index, out _); + (Nca updatePatchNca, Nca updateControlNca) = GetGameUpdateData(_device.Configuration.VirtualFileSystem, mainNca.Header.TitleId.ToString("x16"), _device.Configuration.UserChannelPersistence.Index, out _); if (updatePatchNca != null) { @@ -323,7 +316,7 @@ namespace Ryujinx.HLE.HOS } // Load program 0 control NCA as we are going to need it for display version. - (_, Nca updateProgram0ControlNca) = GetGameUpdateData(_fileSystem, mainNca.Header.TitleId.ToString("x16"), 0, out _); + (_, Nca updateProgram0ControlNca) = GetGameUpdateData(_device.Configuration.VirtualFileSystem, mainNca.Header.TitleId.ToString("x16"), 0, out _); // Load Aoc string titleAocMetadataPath = Path.Combine(AppDataManager.GamesDirPath, mainNca.Header.TitleId.ToString("x16"), "dlc.json"); @@ -336,7 +329,7 @@ namespace Ryujinx.HLE.HOS { foreach (DlcNca dlcNca in dlcContainer.DlcNcaList) { - _contentManager.AddAocItem(dlcNca.TitleId, dlcContainer.Path, dlcNca.Path, dlcNca.Enabled); + _device.Configuration.ContentManager.AddAocItem(dlcNca.TitleId, dlcContainer.Path, dlcNca.Path, dlcNca.Enabled); } } } @@ -375,7 +368,7 @@ namespace Ryujinx.HLE.HOS Npdm metaData = ReadNpdm(codeFs); - _fileSystem.ModLoader.CollectMods(_contentManager.GetAocTitleIds().Prepend(TitleId), _fileSystem.ModLoader.GetModsBasePath()); + _device.Configuration.VirtualFileSystem.ModLoader.CollectMods(_device.Configuration.ContentManager.GetAocTitleIds().Prepend(TitleId), _device.Configuration.VirtualFileSystem.ModLoader.GetModsBasePath()); if (controlNca != null) { @@ -388,7 +381,7 @@ namespace Ryujinx.HLE.HOS // NOTE: Nintendo doesn't guarantee that the display version will be updated on sub programs when updating a multi program application. // BODY: As such, to avoid PTC cache confusion, we only trust the the program 0 display version when launching a sub program. - if (updateProgram0ControlNca != null && _device.UserChannelPersistence.Index != 0) + if (updateProgram0ControlNca != null && _device.Configuration.UserChannelPersistence.Index != 0) { string dummyTitleName = ""; BlitStruct dummyControl = new BlitStruct(1); @@ -402,9 +395,9 @@ namespace Ryujinx.HLE.HOS } else { - IStorage newStorage = _fileSystem.ModLoader.ApplyRomFsMods(TitleId, dataStorage); + IStorage newStorage = _device.Configuration.VirtualFileSystem.ModLoader.ApplyRomFsMods(TitleId, dataStorage); - _fileSystem.SetRomFs(newStorage.AsStream(FileAccess.Read)); + _device.Configuration.VirtualFileSystem.SetRomFs(newStorage.AsStream(FileAccess.Read)); } if (TitleId != 0) @@ -470,7 +463,7 @@ namespace Ryujinx.HLE.HOS private void LoadExeFs(IFileSystem codeFs, Npdm metaData = null) { - if (_fileSystem.ModLoader.ReplaceExefsPartition(TitleId, ref codeFs)) + if (_device.Configuration.VirtualFileSystem.ModLoader.ReplaceExefsPartition(TitleId, ref codeFs)) { metaData = null; //TODO: Check if we should retain old npdm } @@ -496,7 +489,7 @@ namespace Ryujinx.HLE.HOS } // ExeFs file replacements - ModLoadResult modLoadResult = _fileSystem.ModLoader.ApplyExefsMods(TitleId, nsos); + ModLoadResult modLoadResult = _device.Configuration.VirtualFileSystem.ModLoader.ApplyExefsMods(TitleId, nsos); // collect the nsos, ignoring ones that aren't used NsoExecutable[] programs = nsos.Where(x => x != null).ToArray(); @@ -507,9 +500,9 @@ namespace Ryujinx.HLE.HOS metaData = modLoadResult.Npdm; } - _fileSystem.ModLoader.ApplyNsoPatches(TitleId, programs); + _device.Configuration.VirtualFileSystem.ModLoader.ApplyNsoPatches(TitleId, programs); - _contentManager.LoadEntries(_device); + _device.Configuration.ContentManager.LoadEntries(_device); bool usePtc = _device.System.EnablePtc; @@ -528,7 +521,7 @@ namespace Ryujinx.HLE.HOS ProgramLoader.LoadNsos(_device.System.KernelContext, out ProcessTamperInfo tamperInfo, metaData, executables: programs); - _fileSystem.ModLoader.LoadCheats(TitleId, tamperInfo, _device.TamperMachine); + _device.Configuration.VirtualFileSystem.ModLoader.LoadCheats(TitleId, tamperInfo, _device.TamperMachine); } public void LoadProgram(string filePath) @@ -569,7 +562,7 @@ namespace Ryujinx.HLE.HOS if (romfsSize != 0) { - _fileSystem.SetRomFs(new HomebrewRomFsStream(input, obj.FileSize + (long)romfsOffset)); + _device.Configuration.VirtualFileSystem.SetRomFs(new HomebrewRomFsStream(input, obj.FileSize + (long)romfsOffset)); } if (nacpSize != 0) @@ -617,7 +610,7 @@ namespace Ryujinx.HLE.HOS executable = new NsoExecutable(new LocalStorage(filePath, FileAccess.Read), Path.GetFileNameWithoutExtension(filePath)); } - _contentManager.LoadEntries(_device); + _device.Configuration.ContentManager.LoadEntries(_device); _titleName = metaData.TitleName; TitleId = metaData.Aci0.TitleId; @@ -629,7 +622,7 @@ namespace Ryujinx.HLE.HOS ProgramLoader.LoadNsos(_device.System.KernelContext, out ProcessTamperInfo tamperInfo, metaData, executables: executable); - _fileSystem.ModLoader.LoadCheats(TitleId, tamperInfo, _device.TamperMachine); + _device.Configuration.VirtualFileSystem.ModLoader.LoadCheats(TitleId, tamperInfo, _device.TamperMachine); } private Npdm GetDefaultNpdm() @@ -664,7 +657,7 @@ namespace Ryujinx.HLE.HOS "No control file was found for this game. Using a dummy one instead. This may cause inaccuracies in some games."); } - FileSystemClient fileSystem = _fileSystem.FsClient; + FileSystemClient fileSystem = _device.Configuration.VirtualFileSystem.FsClient; Result resultCode = fileSystem.EnsureApplicationCacheStorage(out _, applicationId, ref control); if (resultCode.IsFailure()) diff --git a/Ryujinx.HLE/HOS/Horizon.cs b/Ryujinx.HLE/HOS/Horizon.cs index d8e1605a..13d7a2af 100644 --- a/Ryujinx.HLE/HOS/Horizon.cs +++ b/Ryujinx.HLE/HOS/Horizon.cs @@ -8,8 +8,6 @@ using Ryujinx.Audio.Integration; using Ryujinx.Audio.Output; using Ryujinx.Audio.Renderer.Device; using Ryujinx.Audio.Renderer.Server; -using Ryujinx.Common; -using Ryujinx.Configuration; using Ryujinx.HLE.FileSystem.Content; using Ryujinx.HLE.HOS.Font; using Ryujinx.HLE.HOS.Kernel; @@ -111,13 +109,13 @@ namespace Ryujinx.HLE.HOS internal LibHac.Horizon LibHacHorizonServer { get; private set; } internal HorizonClient LibHacHorizonClient { get; private set; } - public Horizon(Switch device, ContentManager contentManager, AccountManager accountManager, MemoryConfiguration memoryConfiguration) + public Horizon(Switch device) { KernelContext = new KernelContext( device, device.Memory, - memoryConfiguration.ToKernelMemorySize(), - memoryConfiguration.ToKernelMemoryArrange()); + device.Configuration.MemoryConfiguration.ToKernelMemorySize(), + device.Configuration.MemoryConfiguration.ToKernelMemoryArrange()); Device = device; @@ -166,8 +164,8 @@ namespace Ryujinx.HLE.HOS DisplayResolutionChangeEvent = new KEvent(KernelContext); - AccountManager = accountManager; - ContentManager = contentManager; + AccountManager = device.Configuration.AccountManager; + ContentManager = device.Configuration.ContentManager; CaptureManager = new CaptureManager(device); // TODO: use set:sys (and get external clock source id from settings) @@ -179,7 +177,7 @@ namespace Ryujinx.HLE.HOS TimeSpanType systemTime = TimeSpanType.FromSeconds((long)rtcValue); // Configure and setup internal offset - TimeSpanType internalOffset = TimeSpanType.FromSeconds(ConfigurationState.Instance.System.SystemTimeOffset); + TimeSpanType internalOffset = TimeSpanType.FromSeconds(device.Configuration.SystemTimeOffset); TimeSpanType systemTimeOffset = new TimeSpanType(systemTime.NanoSeconds + internalOffset.NanoSeconds); @@ -219,8 +217,6 @@ namespace Ryujinx.HLE.HOS SurfaceFlinger = new SurfaceFlinger(device); - ConfigurationState.Instance.System.EnableDockedMode.Event += OnDockedModeChange; - InitLibHacHorizon(); InitializeAudioRenderer(); } @@ -313,11 +309,11 @@ namespace Ryujinx.HLE.HOS LibHacHorizonClient = ryujinxClient; } - private void OnDockedModeChange(object sender, ReactiveEventArgs e) + public void ChangeDockedModeState(bool newState) { - if (e.NewValue != State.DockedMode) + if (newState != State.DockedMode) { - State.DockedMode = e.NewValue; + State.DockedMode = newState; PerformanceState.PerformanceMode = State.DockedMode ? PerformanceMode.Boost : PerformanceMode.Default; AppletState.Messages.Enqueue(MessageInfo.OperationModeChanged); @@ -326,8 +322,7 @@ namespace Ryujinx.HLE.HOS SignalDisplayResolutionChange(); - // Reconfigure controllers - Device.Hid.RefreshInputConfig(ConfigurationState.Instance.Hid.InputConfig.Value); + Device.Configuration.RefreshInputConfig?.Invoke(); } } @@ -388,8 +383,6 @@ namespace Ryujinx.HLE.HOS { if (!_isDisposed && disposing) { - ConfigurationState.Instance.System.EnableDockedMode.Event -= OnDockedModeChange; - _isDisposed = true; KProcess terminationProcess = new KProcess(KernelContext); diff --git a/Ryujinx.HLE/HOS/Services/Am/AppletOE/ApplicationProxyService/ApplicationProxy/IApplicationFunctions.cs b/Ryujinx.HLE/HOS/Services/Am/AppletOE/ApplicationProxyService/ApplicationProxy/IApplicationFunctions.cs index 7c04a4d1..e0633145 100644 --- a/Ryujinx.HLE/HOS/Services/Am/AppletOE/ApplicationProxyService/ApplicationProxy/IApplicationFunctions.cs +++ b/Ryujinx.HLE/HOS/Services/Am/AppletOE/ApplicationProxyService/ApplicationProxy/IApplicationFunctions.cs @@ -57,7 +57,7 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletOE.ApplicationProxyService.Applicati switch (kind) { case LaunchParameterKind.UserChannel: - storageData = context.Device.UserChannelPersistence.Pop(); + storageData = context.Device.Configuration.UserChannelPersistence.Pop(); break; case LaunchParameterKind.PreselectedUser: // Only the first 0x18 bytes of the Data seems to be actually used. @@ -453,7 +453,7 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletOE.ApplicationProxyService.Applicati // ClearUserChannel() public ResultCode ClearUserChannel(ServiceCtx context) { - context.Device.UserChannelPersistence.Clear(); + context.Device.Configuration.UserChannelPersistence.Clear(); return ResultCode.Success; } @@ -464,7 +464,7 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletOE.ApplicationProxyService.Applicati { AppletAE.IStorage data = GetObject(context, 0); - context.Device.UserChannelPersistence.Push(data.Data); + context.Device.Configuration.UserChannelPersistence.Push(data.Data); return ResultCode.Success; } @@ -473,7 +473,7 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletOE.ApplicationProxyService.Applicati // GetPreviousProgramIndex() -> s32 program_index public ResultCode GetPreviousProgramIndex(ServiceCtx context) { - int previousProgramIndex = context.Device.UserChannelPersistence.PreviousIndex; + int previousProgramIndex = context.Device.Configuration.UserChannelPersistence.PreviousIndex; context.ResponseData.Write(previousProgramIndex); diff --git a/Ryujinx.HLE/HOS/Services/Fs/IFileSystemProxy.cs b/Ryujinx.HLE/HOS/Services/Fs/IFileSystemProxy.cs index 05ad19fb..fd8844c7 100644 --- a/Ryujinx.HLE/HOS/Services/Fs/IFileSystemProxy.cs +++ b/Ryujinx.HLE/HOS/Services/Fs/IFileSystemProxy.cs @@ -396,7 +396,7 @@ namespace Ryujinx.HLE.HOS.Services.Fs // We do a mitm here to find if the request is for an AOC. // This is because AOC can be distributed over multiple containers in the emulator. - if (context.Device.System.ContentManager.GetAocDataStorage((ulong)titleId, out LibHac.Fs.IStorage aocStorage)) + if (context.Device.System.ContentManager.GetAocDataStorage((ulong)titleId, out LibHac.Fs.IStorage aocStorage, context.Device.Configuration.FsIntegrityCheckLevel)) { Logger.Info?.Print(LogClass.Loader, $"Opened AddOnContent Data TitleID={titleId:X16}"); diff --git a/Ryujinx.HLE/HOS/Services/Hid/Hid.cs b/Ryujinx.HLE/HOS/Services/Hid/Hid.cs index 1e85dbf7..61a12d9e 100644 --- a/Ryujinx.HLE/HOS/Services/Hid/Hid.cs +++ b/Ryujinx.HLE/HOS/Services/Hid/Hid.cs @@ -65,7 +65,7 @@ namespace Ryujinx.HLE.HOS.Services.Hid Npads = new NpadDevices(_device, true); } - internal void RefreshInputConfig(List inputConfig) + public void RefreshInputConfig(List inputConfig) { ControllerConfig[] npadConfig = new ControllerConfig[inputConfig.Count]; @@ -78,11 +78,6 @@ namespace Ryujinx.HLE.HOS.Services.Hid _device.Hid.Npads.Configure(npadConfig); } - internal void RefreshInputConfigEvent(object _, ReactiveEventArgs> args) - { - RefreshInputConfig(args.NewValue); - } - public ControllerKeys UpdateStickButtons(JoystickPosition leftStick, JoystickPosition rightStick) { const int stickButtonThreshold = short.MaxValue / 2; diff --git a/Ryujinx.HLE/HOS/Services/IpcService.cs b/Ryujinx.HLE/HOS/Services/IpcService.cs index 69d461de..e9582c26 100644 --- a/Ryujinx.HLE/HOS/Services/IpcService.cs +++ b/Ryujinx.HLE/HOS/Services/IpcService.cs @@ -109,7 +109,7 @@ namespace Ryujinx.HLE.HOS.Services bool serviceExists = service.HipcCommands.TryGetValue(commandId, out MethodInfo processRequest); - if (ServiceConfiguration.IgnoreMissingServices || serviceExists) + if (context.Device.Configuration.IgnoreMissingServices || serviceExists) { ResultCode result = ResultCode.Success; @@ -163,7 +163,7 @@ namespace Ryujinx.HLE.HOS.Services bool serviceExists = TipcCommands.TryGetValue(commandId, out MethodInfo processRequest); - if (ServiceConfiguration.IgnoreMissingServices || serviceExists) + if (context.Device.Configuration.IgnoreMissingServices || serviceExists) { ResultCode result = ResultCode.Success; diff --git a/Ryujinx.HLE/HOS/Services/ServiceConfiguration.cs b/Ryujinx.HLE/HOS/Services/ServiceConfiguration.cs deleted file mode 100644 index d73c76d9..00000000 --- a/Ryujinx.HLE/HOS/Services/ServiceConfiguration.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace Ryujinx.HLE.HOS.Services -{ - public static class ServiceConfiguration - { - public static bool IgnoreMissingServices { get; set; } - } -} \ No newline at end of file diff --git a/Ryujinx.HLE/HOS/Services/Sm/IUserInterface.cs b/Ryujinx.HLE/HOS/Services/Sm/IUserInterface.cs index 9a0ccbc3..8b1ec5b8 100644 --- a/Ryujinx.HLE/HOS/Services/Sm/IUserInterface.cs +++ b/Ryujinx.HLE/HOS/Services/Sm/IUserInterface.cs @@ -98,7 +98,7 @@ namespace Ryujinx.HLE.HOS.Services.Sm } else { - if (ServiceConfiguration.IgnoreMissingServices) + if (context.Device.Configuration.IgnoreMissingServices) { Logger.Warning?.Print(LogClass.Service, $"Missing service {name} ignored"); } diff --git a/Ryujinx.HLE/HOS/Services/SurfaceFlinger/SurfaceFlinger.cs b/Ryujinx.HLE/HOS/Services/SurfaceFlinger/SurfaceFlinger.cs index 556e6a3b..9d8e526f 100644 --- a/Ryujinx.HLE/HOS/Services/SurfaceFlinger/SurfaceFlinger.cs +++ b/Ryujinx.HLE/HOS/Services/SurfaceFlinger/SurfaceFlinger.cs @@ -1,6 +1,5 @@ using Ryujinx.Common.Configuration; using Ryujinx.Common.Logging; -using Ryujinx.Configuration; using Ryujinx.Graphics.GAL; using Ryujinx.Graphics.Gpu; using Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvMap; @@ -351,7 +350,7 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger bool flipX = item.Transform.HasFlag(NativeWindowTransform.FlipX); bool flipY = item.Transform.HasFlag(NativeWindowTransform.FlipY); - AspectRatio aspectRatio = ConfigurationState.Instance.Graphics.AspectRatio.Value; + AspectRatio aspectRatio = _device.Configuration.AspectRatio; bool isStretched = aspectRatio == AspectRatio.Stretched; ImageCrop crop = new ImageCrop( diff --git a/Ryujinx.HLE/HOS/Services/Time/TimeZone/TimeZoneContentManager.cs b/Ryujinx.HLE/HOS/Services/Time/TimeZone/TimeZoneContentManager.cs index b66ffc3f..963ea9fd 100644 --- a/Ryujinx.HLE/HOS/Services/Time/TimeZone/TimeZoneContentManager.cs +++ b/Ryujinx.HLE/HOS/Services/Time/TimeZone/TimeZoneContentManager.cs @@ -5,7 +5,6 @@ using LibHac.Fs.Fsa; using LibHac.FsSystem; using LibHac.FsSystem.NcaUtils; using Ryujinx.Common.Logging; -using Ryujinx.Configuration; using Ryujinx.HLE.Exceptions; using Ryujinx.HLE.FileSystem; using Ryujinx.HLE.FileSystem.Content; @@ -47,10 +46,8 @@ namespace Ryujinx.HLE.HOS.Services.Time.TimeZone InitializeLocationNameCache(); } - public string SanityCheckDeviceLocationName() + public string SanityCheckDeviceLocationName(string locationName) { - string locationName = ConfigurationState.Instance.System.TimeZone; - if (IsLocationNameValid(locationName)) { return locationName; @@ -58,8 +55,6 @@ namespace Ryujinx.HLE.HOS.Services.Time.TimeZone Logger.Warning?.Print(LogClass.ServiceTime, $"Invalid device TimeZone {locationName}, switching back to UTC"); - ConfigurationState.Instance.System.TimeZone.Value = "UTC"; - return "UTC"; } @@ -69,7 +64,7 @@ namespace Ryujinx.HLE.HOS.Services.Time.TimeZone SteadyClockTimePoint timeZoneUpdatedTimePoint = timeManager.StandardSteadyClock.GetCurrentTimePoint(null); - string deviceLocationName = SanityCheckDeviceLocationName(); + string deviceLocationName = SanityCheckDeviceLocationName(device.Configuration.TimeZone); ResultCode result = GetTimeZoneBinary(deviceLocationName, out Stream timeZoneBinaryStream, out LocalStorage ncaFile); diff --git a/Ryujinx.HLE/Switch.cs b/Ryujinx.HLE/Switch.cs index b88bdbfe..ee359dda 100644 --- a/Ryujinx.HLE/Switch.cs +++ b/Ryujinx.HLE/Switch.cs @@ -1,22 +1,14 @@ -using LibHac.FsSystem; using Ryujinx.Audio.Backends.CompatLayer; using Ryujinx.Audio.Integration; -using Ryujinx.Common; -using Ryujinx.Configuration; -using Ryujinx.Graphics.GAL; using Ryujinx.Graphics.Gpu; using Ryujinx.Graphics.Host1x; using Ryujinx.Graphics.Nvdec; using Ryujinx.Graphics.Vic; using Ryujinx.HLE.FileSystem; -using Ryujinx.HLE.FileSystem.Content; using Ryujinx.HLE.HOS; -using Ryujinx.HLE.HOS.Services; -using Ryujinx.HLE.HOS.Services.Account.Acc; using Ryujinx.HLE.HOS.Services.Apm; using Ryujinx.HLE.HOS.Services.Hid; using Ryujinx.HLE.HOS.Services.Nv.NvDrvServices; -using Ryujinx.HLE.HOS.SystemState; using Ryujinx.Memory; using System; @@ -24,69 +16,60 @@ namespace Ryujinx.HLE { public class Switch : IDisposable { - private MemoryConfiguration _memoryConfiguration; + public HLEConfiguration Configuration { get; } - public IHardwareDeviceDriver AudioDeviceDriver { get; private set; } + public IHardwareDeviceDriver AudioDeviceDriver { get; } - internal MemoryBlock Memory { get; private set; } + internal MemoryBlock Memory { get; } - public GpuContext Gpu { get; private set; } + public GpuContext Gpu { get; } - internal NvMemoryAllocator MemoryAllocator { get; private set; } + internal NvMemoryAllocator MemoryAllocator { get; } internal Host1xDevice Host1x { get; } - public VirtualFileSystem FileSystem { get; private set; } + public VirtualFileSystem FileSystem => Configuration.VirtualFileSystem; - public Horizon System { get; private set; } + public Horizon System { get; } public ApplicationLoader Application { get; } - public PerformanceStatistics Statistics { get; private set; } + public PerformanceStatistics Statistics { get; } - public UserChannelPersistence UserChannelPersistence { get; } + public Hid Hid { get; } - public Hid Hid { get; private set; } + public TamperMachine TamperMachine { get; } - public TamperMachine TamperMachine { get; private set; } - - public IHostUiHandler UiHandler { get; set; } + public IHostUiHandler UiHandler { get; } public bool EnableDeviceVsync { get; set; } = true; - public Switch( - VirtualFileSystem fileSystem, - ContentManager contentManager, - AccountManager accountManager, - UserChannelPersistence userChannelPersistence, - IRenderer renderer, - IHardwareDeviceDriver audioDeviceDriver, - MemoryConfiguration memoryConfiguration) + public Switch(HLEConfiguration configuration) { - if (renderer == null) + if (configuration.GpuRenderer == null) { - throw new ArgumentNullException(nameof(renderer)); + throw new ArgumentNullException(nameof(configuration.GpuRenderer)); } - if (audioDeviceDriver == null) + if (configuration.AudioDeviceDriver == null) { - throw new ArgumentNullException(nameof(audioDeviceDriver)); + throw new ArgumentNullException(nameof(configuration.AudioDeviceDriver)); } - if (userChannelPersistence == null) + if (configuration.UserChannelPersistence== null) { - throw new ArgumentNullException(nameof(userChannelPersistence)); + throw new ArgumentNullException(nameof(configuration.UserChannelPersistence)); } - UserChannelPersistence = userChannelPersistence; + Configuration = configuration; - _memoryConfiguration = memoryConfiguration; + UiHandler = configuration.HostUiHandler; - AudioDeviceDriver = new CompatLayerHardwareDeviceDriver(audioDeviceDriver); + AudioDeviceDriver = new CompatLayerHardwareDeviceDriver(configuration.AudioDeviceDriver); - Memory = new MemoryBlock(memoryConfiguration.ToDramSize()); + Memory = new MemoryBlock(configuration.MemoryConfiguration.ToDramSize()); - Gpu = new GpuContext(renderer); + Gpu = new GpuContext(configuration.GpuRenderer); MemoryAllocator = new NvMemoryAllocator(); @@ -111,9 +94,7 @@ namespace Ryujinx.HLE } }; - FileSystem = fileSystem; - - System = new Horizon(this, contentManager, accountManager, memoryConfiguration); + System = new Horizon(this); System.InitializeServices(); Statistics = new PerformanceStatistics(); @@ -121,45 +102,30 @@ namespace Ryujinx.HLE Hid = new Hid(this, System.HidBaseAddress); Hid.InitDevices(); - Application = new ApplicationLoader(this, fileSystem, contentManager); + Application = new ApplicationLoader(this); TamperMachine = new TamperMachine(); + + Initialize(); } - public void Initialize() + private void Initialize() { - System.State.SetLanguage((SystemLanguage)ConfigurationState.Instance.System.Language.Value); + System.State.SetLanguage(Configuration.SystemLanguage); - System.State.SetRegion((RegionCode)ConfigurationState.Instance.System.Region.Value); + System.State.SetRegion(Configuration.Region); - EnableDeviceVsync = ConfigurationState.Instance.Graphics.EnableVsync; + EnableDeviceVsync = Configuration.EnableVsync; - System.State.DockedMode = ConfigurationState.Instance.System.EnableDockedMode; + System.State.DockedMode = Configuration.EnableDockedMode; System.PerformanceState.PerformanceMode = System.State.DockedMode ? PerformanceMode.Boost : PerformanceMode.Default; - System.EnablePtc = ConfigurationState.Instance.System.EnablePtc; + System.EnablePtc = Configuration.EnablePtc; - System.FsIntegrityCheckLevel = GetIntegrityCheckLevel(); + System.FsIntegrityCheckLevel = Configuration.FsIntegrityCheckLevel; - System.GlobalAccessLogMode = ConfigurationState.Instance.System.FsGlobalAccessLogMode; - - ServiceConfiguration.IgnoreMissingServices = ConfigurationState.Instance.System.IgnoreMissingServices; - ConfigurationState.Instance.System.IgnoreMissingServices.Event += (object _, ReactiveEventArgs args) => - { - ServiceConfiguration.IgnoreMissingServices = args.NewValue; - }; - - // Configure controllers - Hid.RefreshInputConfig(ConfigurationState.Instance.Hid.InputConfig.Value); - ConfigurationState.Instance.Hid.InputConfig.Event += Hid.RefreshInputConfigEvent; - } - - public static IntegrityCheckLevel GetIntegrityCheckLevel() - { - return ConfigurationState.Instance.System.EnableFsIntegrityChecks - ? IntegrityCheckLevel.ErrorOnInvalid - : IntegrityCheckLevel.None; + System.GlobalAccessLogMode = Configuration.FsGlobalAccessLogMode; } public void LoadCart(string exeFsDir, string romFsFile = null) @@ -223,8 +189,6 @@ namespace Ryujinx.HLE { if (disposing) { - ConfigurationState.Instance.Hid.InputConfig.Event -= Hid.RefreshInputConfigEvent; - System.Dispose(); Host1x.Dispose(); AudioDeviceDriver.Dispose(); diff --git a/Ryujinx.Input/HLE/NpadManager.cs b/Ryujinx.Input/HLE/NpadManager.cs index 033a7ac5..abb820b0 100644 --- a/Ryujinx.Input/HLE/NpadManager.cs +++ b/Ryujinx.Input/HLE/NpadManager.cs @@ -1,8 +1,6 @@ using Ryujinx.Common.Configuration.Hid; using Ryujinx.Common.Configuration.Hid.Controller; using Ryujinx.Common.Configuration.Hid.Keyboard; -using Ryujinx.Configuration; -using Ryujinx.HLE.HOS; using Ryujinx.HLE.HOS.Services.Hid; using System; using System.Collections.Generic; @@ -10,6 +8,7 @@ using System.Diagnostics; using System.Runtime.CompilerServices; using CemuHookClient = Ryujinx.Input.Motion.CemuHook.Client; +using Switch = Ryujinx.HLE.Switch; namespace Ryujinx.Input.HLE { @@ -31,30 +30,41 @@ namespace Ryujinx.Input.HLE private bool _isDisposed; private List _inputConfig; + private bool _enableKeyboard; + private Switch _device; public NpadManager(IGamepadDriver keyboardDriver, IGamepadDriver gamepadDriver) { _controllers = new NpadController[MaxControllers]; - _cemuHookClient = new CemuHookClient(); + _cemuHookClient = new CemuHookClient(this); _keyboardDriver = keyboardDriver; _gamepadDriver = gamepadDriver; - _inputConfig = ConfigurationState.Instance.Hid.InputConfig.Value; + _inputConfig = new List(); + _enableKeyboard = false; _gamepadDriver.OnGamepadConnected += HandleOnGamepadConnected; _gamepadDriver.OnGamepadDisconnected += HandleOnGamepadDisconnected; } + private void RefreshInputConfigForHLE() + { + lock (_lock) + { + _device.Hid.RefreshInputConfig(_inputConfig); + } + } + private void HandleOnGamepadDisconnected(string obj) { // Force input reload - ReloadConfiguration(ConfigurationState.Instance.Hid.InputConfig.Value); + ReloadConfiguration(_inputConfig, _enableKeyboard); } private void HandleOnGamepadConnected(string id) { // Force input reload - ReloadConfiguration(ConfigurationState.Instance.Hid.InputConfig.Value); + ReloadConfiguration(_inputConfig, _enableKeyboard); } [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -83,7 +93,7 @@ namespace Ryujinx.Input.HLE } } - public void ReloadConfiguration(List inputConfig) + public void ReloadConfiguration(List inputConfig, bool enableKeyboard) { lock (_lock) { @@ -110,10 +120,9 @@ namespace Ryujinx.Input.HLE } _inputConfig = inputConfig; + _enableKeyboard = enableKeyboard; - // Enforce an update of the property that will be updated by HLE. - // TODO: Move that in the input manager maybe? - ConfigurationState.Instance.Hid.InputConfig.Value = inputConfig; + _device.Hid.RefreshInputConfig(inputConfig); } } @@ -133,7 +142,15 @@ namespace Ryujinx.Input.HLE } } - public void Update(Hid hleHid, TamperMachine tamperMachine) + public void Initialize(Switch device, List inputConfig, bool enableKeyboard) + { + _device = device; + _device.Configuration.RefreshInputConfig = RefreshInputConfigForHLE; + + ReloadConfiguration(inputConfig, enableKeyboard); + } + + public void Update() { lock (_lock) { @@ -159,11 +176,11 @@ namespace Ryujinx.Input.HLE inputState = controller.GetHLEInputState(); - inputState.Buttons |= hleHid.UpdateStickButtons(inputState.LStick, inputState.RStick); + inputState.Buttons |= _device.Hid.UpdateStickButtons(inputState.LStick, inputState.RStick); motionState = controller.GetHLEMotionState(); - if (ConfigurationState.Instance.Hid.EnableKeyboard) + if (_enableKeyboard) { hleKeyboardInput = controller.GetHLEKeyboardInput(); } @@ -181,15 +198,23 @@ namespace Ryujinx.Input.HLE hleMotionStates.Add(motionState); } - hleHid.Npads.Update(hleInputStates); - hleHid.Npads.UpdateSixAxis(hleMotionStates); + _device.Hid.Npads.Update(hleInputStates); + _device.Hid.Npads.UpdateSixAxis(hleMotionStates); if (hleKeyboardInput.HasValue) { - hleHid.Keyboard.Update(hleKeyboardInput.Value); + _device.Hid.Keyboard.Update(hleKeyboardInput.Value); } - tamperMachine.UpdateInput(hleInputStates); + _device.TamperMachine.UpdateInput(hleInputStates); + } + } + + internal InputConfig GetPlayerInputConfigByIndex(int index) + { + lock (_lock) + { + return _inputConfig.Find(x => x.PlayerIndex == (Ryujinx.Common.Configuration.Hid.PlayerIndex)index); } } diff --git a/Ryujinx.Input/Motion/CemuHook/Client.cs b/Ryujinx.Input/Motion/CemuHook/Client.cs index 395bd0b3..214e23f0 100644 --- a/Ryujinx.Input/Motion/CemuHook/Client.cs +++ b/Ryujinx.Input/Motion/CemuHook/Client.cs @@ -4,7 +4,7 @@ using Ryujinx.Common.Configuration.Hid; using Ryujinx.Common.Configuration.Hid.Controller; using Ryujinx.Common.Configuration.Hid.Controller.Motion; using Ryujinx.Common.Logging; -using Ryujinx.Configuration; +using Ryujinx.Input.HLE; using Ryujinx.Input.Motion.CemuHook.Protocol; using System; using System.Collections.Generic; @@ -29,12 +29,14 @@ namespace Ryujinx.Input.Motion.CemuHook private readonly bool[] _clientErrorStatus = new bool[Enum.GetValues(typeof(PlayerIndex)).Length]; private readonly long[] _clientRetryTimer = new long[Enum.GetValues(typeof(PlayerIndex)).Length]; + private NpadManager _npadManager; - public Client() + public Client(NpadManager npadManager) { - _hosts = new Dictionary(); - _motionData = new Dictionary>(); - _clients = new Dictionary(); + _npadManager = npadManager; + _hosts = new Dictionary(); + _motionData = new Dictionary>(); + _clients = new Dictionary(); CloseClients(); } @@ -323,7 +325,7 @@ namespace Ryujinx.Input.Motion.CemuHook ulong timestamp = inputData.MotionTimestamp; - InputConfig config = ConfigurationState.Instance.Hid.InputConfig.Value.Find(x => x.PlayerIndex == (PlayerIndex)clientId); + InputConfig config = _npadManager.GetPlayerInputConfigByIndex(clientId); lock (_motionData) { diff --git a/Ryujinx/Configuration/AudioBackend.cs b/Ryujinx/Configuration/AudioBackend.cs new file mode 100644 index 00000000..e42df039 --- /dev/null +++ b/Ryujinx/Configuration/AudioBackend.cs @@ -0,0 +1,10 @@ +namespace Ryujinx.Configuration +{ + public enum AudioBackend + { + Dummy, + OpenAl, + SoundIo, + SDL2 + } +} \ No newline at end of file diff --git a/Ryujinx/Configuration/ConfigurationFileFormat.cs b/Ryujinx/Configuration/ConfigurationFileFormat.cs new file mode 100644 index 00000000..be9c6864 --- /dev/null +++ b/Ryujinx/Configuration/ConfigurationFileFormat.cs @@ -0,0 +1,276 @@ +using System.Collections.Generic; +using System.IO; +using Ryujinx.Common.Configuration; +using Ryujinx.Common.Configuration.Hid; +using Ryujinx.Common.Logging; +using Ryujinx.Common.Utilities; +using Ryujinx.Configuration.System; +using Ryujinx.Configuration.Ui; + +namespace Ryujinx.Configuration +{ + public class ConfigurationFileFormat + { + /// + /// The current version of the file format + /// + public const int CurrentVersion = 25; + + public int Version { get; set; } + + /// + /// Enables or disables logging to a file on disk + /// + public bool EnableFileLog { get; set; } + + /// + /// Resolution Scale. An integer scale applied to applicable render targets. Values 1-4, or -1 to use a custom floating point scale instead. + /// + public int ResScale { get; set; } + + /// + /// Custom Resolution Scale. A custom floating point scale applied to applicable render targets. Only active when Resolution Scale is -1. + /// + public float ResScaleCustom { get; set; } + + /// + /// Max Anisotropy. Values range from 0 - 16. Set to -1 to let the game decide. + /// + public float MaxAnisotropy { get; set; } + + /// + /// Aspect Ratio applied to the renderer window. + /// + public AspectRatio AspectRatio { get; set; } + + /// + /// Dumps shaders in this local directory + /// + public string GraphicsShadersDumpPath { get; set; } + + /// + /// Enables printing debug log messages + /// + public bool LoggingEnableDebug { get; set; } + + /// + /// Enables printing stub log messages + /// + public bool LoggingEnableStub { get; set; } + + /// + /// Enables printing info log messages + /// + public bool LoggingEnableInfo { get; set; } + + /// + /// Enables printing warning log messages + /// + public bool LoggingEnableWarn { get; set; } + + /// + /// Enables printing error log messages + /// + public bool LoggingEnableError { get; set; } + + /// + /// Enables printing guest log messages + /// + public bool LoggingEnableGuest { get; set; } + + /// + /// Enables printing FS access log messages + /// + public bool LoggingEnableFsAccessLog { get; set; } + + /// + /// Controls which log messages are written to the log targets + /// + public LogClass[] LoggingFilteredClasses { get; set; } + + /// + /// Change Graphics API debug log level + /// + public GraphicsDebugLevel LoggingGraphicsDebugLevel { get; set; } + + + /// + /// Change System Language + /// + public Language SystemLanguage { get; set; } + + /// + /// Change System Region + /// + public Region SystemRegion { get; set; } + + /// + /// Change System TimeZone + /// + public string SystemTimeZone { get; set; } + + /// + /// Change System Time Offset in seconds + /// + public long SystemTimeOffset { get; set; } + + /// + /// Enables or disables Docked Mode + /// + public bool DockedMode { get; set; } + + /// + /// Enables or disables Discord Rich Presence + /// + public bool EnableDiscordIntegration { get; set; } + + /// + /// Checks for updates when Ryujinx starts when enabled + /// + public bool CheckUpdatesOnStart { get; set; } + + /// + /// Show "Confirm Exit" Dialog + /// + public bool ShowConfirmExit { get; set; } + + /// + /// Hide Cursor on Idle + /// + public bool HideCursorOnIdle { get; set; } + + /// + /// Enables or disables Vertical Sync + /// + public bool EnableVsync { get; set; } + + /// + /// Enables or disables Shader cache + /// + public bool EnableShaderCache { get; set; } + + /// + /// Enables or disables multi-core scheduling of threads + /// + public bool EnableMulticoreScheduling { get; set; } + + /// + /// Enables or disables profiled translation cache persistency + /// + public bool EnablePtc { get; set; } + + /// + /// Enables integrity checks on Game content files + /// + public bool EnableFsIntegrityChecks { get; set; } + + /// + /// Enables FS access log output to the console. Possible modes are 0-3 + /// + public int FsGlobalAccessLogMode { get; set; } + + /// + /// The selected audio backend + /// + public AudioBackend AudioBackend { get; set; } + + /// + /// Expands the RAM amount on the emulated system from 4GB to 6GB + /// + public bool ExpandRam { get; set; } + + /// + /// Enable or disable ignoring missing services + /// + public bool IgnoreMissingServices { get; set; } + + /// + /// Used to toggle columns in the GUI + /// + public GuiColumns GuiColumns { get; set; } + + /// + /// Used to configure column sort settings in the GUI + /// + public ColumnSort ColumnSort { get; set; } + + /// + /// A list of directories containing games to be used to load games into the games list + /// + public List GameDirs { get; set; } + + /// + /// Enable or disable custom themes in the GUI + /// + public bool EnableCustomTheme { get; set; } + + /// + /// Path to custom GUI theme + /// + public string CustomThemePath { get; set; } + + /// + /// Start games in fullscreen mode + /// + public bool StartFullscreen { get; set; } + + /// + /// Enable or disable keyboard support (Independent from controllers binding) + /// + public bool EnableKeyboard { get; set; } + + /// + /// Hotkey Keyboard Bindings + /// + public KeyboardHotkeys Hotkeys { get; set; } + + /// + /// Legacy keyboard control bindings + /// + /// Kept for file format compatibility (to avoid possible failure when parsing configuration on old versions) + /// TODO: Remove this when those older versions aren't in use anymore. + public List KeyboardConfig { get; set; } + + /// + /// Legacy controller control bindings + /// + /// Kept for file format compatibility (to avoid possible failure when parsing configuration on old versions) + /// TODO: Remove this when those older versions aren't in use anymore. + public List ControllerConfig { get; set; } + + /// + /// Input configurations + /// + public List InputConfig { get; set; } + + /// + /// Loads a configuration file from disk + /// + /// The path to the JSON configuration file + public static bool TryLoad(string path, out ConfigurationFileFormat configurationFileFormat) + { + try + { + configurationFileFormat = JsonHelper.DeserializeFromFile(path); + + return true; + } + catch + { + configurationFileFormat = null; + + return false; + } + } + + /// + /// Save a configuration file to disk + /// + /// The path to the JSON configuration file + public void SaveConfig(string path) + { + using FileStream fileStream = File.Create(path, 4096, FileOptions.WriteThrough); + JsonHelper.Serialize(fileStream, this, true); + } + } +} diff --git a/Ryujinx/Configuration/ConfigurationState.cs b/Ryujinx/Configuration/ConfigurationState.cs new file mode 100644 index 00000000..9ea5c282 --- /dev/null +++ b/Ryujinx/Configuration/ConfigurationState.cs @@ -0,0 +1,893 @@ +using Ryujinx.Common; +using Ryujinx.Common.Configuration; +using Ryujinx.Common.Configuration.Hid; +using Ryujinx.Common.Configuration.Hid.Keyboard; +using Ryujinx.Common.Logging; +using Ryujinx.Configuration.System; +using Ryujinx.Configuration.Ui; +using System; +using System.Collections.Generic; + +namespace Ryujinx.Configuration +{ + public class ConfigurationState + { + /// + /// UI configuration section + /// + public class UiSection + { + public class Columns + { + public ReactiveObject FavColumn { get; private set; } + public ReactiveObject IconColumn { get; private set; } + public ReactiveObject AppColumn { get; private set; } + public ReactiveObject DevColumn { get; private set; } + public ReactiveObject VersionColumn { get; private set; } + public ReactiveObject TimePlayedColumn { get; private set; } + public ReactiveObject LastPlayedColumn { get; private set; } + public ReactiveObject FileExtColumn { get; private set; } + public ReactiveObject FileSizeColumn { get; private set; } + public ReactiveObject PathColumn { get; private set; } + + public Columns() + { + FavColumn = new ReactiveObject(); + IconColumn = new ReactiveObject(); + AppColumn = new ReactiveObject(); + DevColumn = new ReactiveObject(); + VersionColumn = new ReactiveObject(); + TimePlayedColumn = new ReactiveObject(); + LastPlayedColumn = new ReactiveObject(); + FileExtColumn = new ReactiveObject(); + FileSizeColumn = new ReactiveObject(); + PathColumn = new ReactiveObject(); + } + } + + public class ColumnSortSettings + { + public ReactiveObject SortColumnId { get; private set; } + public ReactiveObject SortAscending { get; private set; } + + public ColumnSortSettings() + { + SortColumnId = new ReactiveObject(); + SortAscending = new ReactiveObject(); + } + } + + /// + /// Used to toggle columns in the GUI + /// + public Columns GuiColumns { get; private set; } + + /// + /// Used to configure column sort settings in the GUI + /// + public ColumnSortSettings ColumnSort { get; private set; } + + /// + /// A list of directories containing games to be used to load games into the games list + /// + public ReactiveObject> GameDirs { get; private set; } + + /// + /// Enable or disable custom themes in the GUI + /// + public ReactiveObject EnableCustomTheme { get; private set; } + + /// + /// Path to custom GUI theme + /// + public ReactiveObject CustomThemePath { get; private set; } + + /// + /// Start games in fullscreen mode + /// + public ReactiveObject StartFullscreen { get; private set; } + + public UiSection() + { + GuiColumns = new Columns(); + ColumnSort = new ColumnSortSettings(); + GameDirs = new ReactiveObject>(); + EnableCustomTheme = new ReactiveObject(); + CustomThemePath = new ReactiveObject(); + StartFullscreen = new ReactiveObject(); + } + } + + /// + /// Logger configuration section + /// + public class LoggerSection + { + /// + /// Enables printing debug log messages + /// + public ReactiveObject EnableDebug { get; private set; } + + /// + /// Enables printing stub log messages + /// + public ReactiveObject EnableStub { get; private set; } + + /// + /// Enables printing info log messages + /// + public ReactiveObject EnableInfo { get; private set; } + + /// + /// Enables printing warning log messages + /// + public ReactiveObject EnableWarn { get; private set; } + + /// + /// Enables printing error log messages + /// + public ReactiveObject EnableError { get; private set; } + + /// + /// Enables printing guest log messages + /// + public ReactiveObject EnableGuest { get; private set; } + + /// + /// Enables printing FS access log messages + /// + public ReactiveObject EnableFsAccessLog { get; private set; } + + /// + /// Controls which log messages are written to the log targets + /// + public ReactiveObject FilteredClasses { get; private set; } + + /// + /// Enables or disables logging to a file on disk + /// + public ReactiveObject EnableFileLog { get; private set; } + + /// + /// Controls which OpenGL log messages are recorded in the log + /// + public ReactiveObject GraphicsDebugLevel { get; private set; } + + public LoggerSection() + { + EnableDebug = new ReactiveObject(); + EnableStub = new ReactiveObject(); + EnableInfo = new ReactiveObject(); + EnableWarn = new ReactiveObject(); + EnableError = new ReactiveObject(); + EnableGuest = new ReactiveObject(); + EnableFsAccessLog = new ReactiveObject(); + FilteredClasses = new ReactiveObject(); + EnableFileLog = new ReactiveObject(); + EnableFileLog.Event += static (sender, e) => LogValueChange(sender, e, nameof(EnableFileLog)); + GraphicsDebugLevel = new ReactiveObject(); + } + } + + /// + /// System configuration section + /// + public class SystemSection + { + /// + /// Change System Language + /// + public ReactiveObject Language { get; private set; } + + /// + /// Change System Region + /// + public ReactiveObject Region { get; private set; } + + /// + /// Change System TimeZone + /// + public ReactiveObject TimeZone { get; private set; } + + /// + /// System Time Offset in Seconds + /// + public ReactiveObject SystemTimeOffset { get; private set; } + + /// + /// Enables or disables Docked Mode + /// + public ReactiveObject EnableDockedMode { get; private set; } + + /// + /// Enables or disables profiled translation cache persistency + /// + public ReactiveObject EnablePtc { get; private set; } + + /// + /// Enables integrity checks on Game content files + /// + public ReactiveObject EnableFsIntegrityChecks { get; private set; } + + /// + /// Enables FS access log output to the console. Possible modes are 0-3 + /// + public ReactiveObject FsGlobalAccessLogMode { get; private set; } + + /// + /// The selected audio backend + /// + public ReactiveObject AudioBackend { get; private set; } + + /// + /// Defines the amount of RAM available on the emulated system, and how it is distributed + /// + public ReactiveObject ExpandRam { get; private set; } + + /// + /// Enable or disable ignoring missing services + /// + public ReactiveObject IgnoreMissingServices { get; private set; } + + public SystemSection() + { + Language = new ReactiveObject(); + Region = new ReactiveObject(); + TimeZone = new ReactiveObject(); + SystemTimeOffset = new ReactiveObject(); + EnableDockedMode = new ReactiveObject(); + EnableDockedMode.Event += static (sender, e) => LogValueChange(sender, e, nameof(EnableDockedMode)); + EnablePtc = new ReactiveObject(); + EnablePtc.Event += static (sender, e) => LogValueChange(sender, e, nameof(EnablePtc)); + EnableFsIntegrityChecks = new ReactiveObject(); + EnableFsIntegrityChecks.Event += static (sender, e) => LogValueChange(sender, e, nameof(EnableFsIntegrityChecks)); + FsGlobalAccessLogMode = new ReactiveObject(); + FsGlobalAccessLogMode.Event += static (sender, e) => LogValueChange(sender, e, nameof(FsGlobalAccessLogMode)); + AudioBackend = new ReactiveObject(); + AudioBackend.Event += static (sender, e) => LogValueChange(sender, e, nameof(AudioBackend)); + ExpandRam = new ReactiveObject(); + ExpandRam.Event += static (sender, e) => LogValueChange(sender, e, nameof(ExpandRam)); + IgnoreMissingServices = new ReactiveObject(); + IgnoreMissingServices.Event += static (sender, e) => LogValueChange(sender, e, nameof(IgnoreMissingServices)); + } + } + + /// + /// Hid configuration section + /// + public class HidSection + { + /// + /// Enable or disable keyboard support (Independent from controllers binding) + /// + public ReactiveObject EnableKeyboard { get; private set; } + + /// + /// Hotkey Keyboard Bindings + /// + public ReactiveObject Hotkeys { get; private set; } + + /// + /// Input device configuration. + /// NOTE: This ReactiveObject won't issue an event when the List has elements added or removed. + /// TODO: Implement a ReactiveList class. + /// + public ReactiveObject> InputConfig { get; private set; } + + public HidSection() + { + EnableKeyboard = new ReactiveObject(); + Hotkeys = new ReactiveObject(); + InputConfig = new ReactiveObject>(); + } + } + + /// + /// Graphics configuration section + /// + public class GraphicsSection + { + /// + /// Max Anisotropy. Values range from 0 - 16. Set to -1 to let the game decide. + /// + public ReactiveObject MaxAnisotropy { get; private set; } + + /// + /// Aspect Ratio applied to the renderer window. + /// + public ReactiveObject AspectRatio { get; private set; } + + /// + /// Resolution Scale. An integer scale applied to applicable render targets. Values 1-4, or -1 to use a custom floating point scale instead. + /// + public ReactiveObject ResScale { get; private set; } + + /// + /// Custom Resolution Scale. A custom floating point scale applied to applicable render targets. Only active when Resolution Scale is -1. + /// + public ReactiveObject ResScaleCustom { get; private set; } + + /// + /// Dumps shaders in this local directory + /// + public ReactiveObject ShadersDumpPath { get; private set; } + + /// + /// Enables or disables Vertical Sync + /// + public ReactiveObject EnableVsync { get; private set; } + + /// + /// Enables or disables Shader cache + /// + public ReactiveObject EnableShaderCache { get; private set; } + + public GraphicsSection() + { + ResScale = new ReactiveObject(); + ResScale.Event += static (sender, e) => LogValueChange(sender, e, nameof(ResScale)); + ResScaleCustom = new ReactiveObject(); + ResScaleCustom.Event += static (sender, e) => LogValueChange(sender, e, nameof(ResScaleCustom)); + MaxAnisotropy = new ReactiveObject(); + MaxAnisotropy.Event += static (sender, e) => LogValueChange(sender, e, nameof(MaxAnisotropy)); + AspectRatio = new ReactiveObject(); + AspectRatio.Event += static (sender, e) => LogValueChange(sender, e, nameof(AspectRatio)); + ShadersDumpPath = new ReactiveObject(); + EnableVsync = new ReactiveObject(); + EnableVsync.Event += static (sender, e) => LogValueChange(sender, e, nameof(EnableVsync)); + EnableShaderCache = new ReactiveObject(); + EnableShaderCache.Event += static (sender, e) => LogValueChange(sender, e, nameof(EnableShaderCache)); + } + } + + /// + /// The default configuration instance + /// + public static ConfigurationState Instance { get; private set; } + + /// + /// The Ui section + /// + public UiSection Ui { get; private set; } + + /// + /// The Logger section + /// + public LoggerSection Logger { get; private set; } + + /// + /// The System section + /// + public SystemSection System { get; private set; } + + /// + /// The Graphics section + /// + public GraphicsSection Graphics { get; private set; } + + /// + /// The Hid section + /// + public HidSection Hid { get; private set; } + + /// + /// Enables or disables Discord Rich Presence + /// + public ReactiveObject EnableDiscordIntegration { get; private set; } + + /// + /// Checks for updates when Ryujinx starts when enabled + /// + public ReactiveObject CheckUpdatesOnStart { get; private set; } + + /// + /// Show "Confirm Exit" Dialog + /// + public ReactiveObject ShowConfirmExit { get; private set; } + + /// + /// Hide Cursor on Idle + /// + public ReactiveObject HideCursorOnIdle { get; private set; } + + private ConfigurationState() + { + Ui = new UiSection(); + Logger = new LoggerSection(); + System = new SystemSection(); + Graphics = new GraphicsSection(); + Hid = new HidSection(); + EnableDiscordIntegration = new ReactiveObject(); + CheckUpdatesOnStart = new ReactiveObject(); + ShowConfirmExit = new ReactiveObject(); + HideCursorOnIdle = new ReactiveObject(); + } + + public ConfigurationFileFormat ToFileFormat() + { + ConfigurationFileFormat configurationFile = new ConfigurationFileFormat + { + Version = ConfigurationFileFormat.CurrentVersion, + EnableFileLog = Logger.EnableFileLog, + ResScale = Graphics.ResScale, + ResScaleCustom = Graphics.ResScaleCustom, + MaxAnisotropy = Graphics.MaxAnisotropy, + AspectRatio = Graphics.AspectRatio, + GraphicsShadersDumpPath = Graphics.ShadersDumpPath, + LoggingEnableDebug = Logger.EnableDebug, + LoggingEnableStub = Logger.EnableStub, + LoggingEnableInfo = Logger.EnableInfo, + LoggingEnableWarn = Logger.EnableWarn, + LoggingEnableError = Logger.EnableError, + LoggingEnableGuest = Logger.EnableGuest, + LoggingEnableFsAccessLog = Logger.EnableFsAccessLog, + LoggingFilteredClasses = Logger.FilteredClasses, + LoggingGraphicsDebugLevel = Logger.GraphicsDebugLevel, + SystemLanguage = System.Language, + SystemRegion = System.Region, + SystemTimeZone = System.TimeZone, + SystemTimeOffset = System.SystemTimeOffset, + DockedMode = System.EnableDockedMode, + EnableDiscordIntegration = EnableDiscordIntegration, + CheckUpdatesOnStart = CheckUpdatesOnStart, + ShowConfirmExit = ShowConfirmExit, + HideCursorOnIdle = HideCursorOnIdle, + EnableVsync = Graphics.EnableVsync, + EnableShaderCache = Graphics.EnableShaderCache, + EnablePtc = System.EnablePtc, + EnableFsIntegrityChecks = System.EnableFsIntegrityChecks, + FsGlobalAccessLogMode = System.FsGlobalAccessLogMode, + AudioBackend = System.AudioBackend, + ExpandRam = System.ExpandRam, + IgnoreMissingServices = System.IgnoreMissingServices, + GuiColumns = new GuiColumns + { + FavColumn = Ui.GuiColumns.FavColumn, + IconColumn = Ui.GuiColumns.IconColumn, + AppColumn = Ui.GuiColumns.AppColumn, + DevColumn = Ui.GuiColumns.DevColumn, + VersionColumn = Ui.GuiColumns.VersionColumn, + TimePlayedColumn = Ui.GuiColumns.TimePlayedColumn, + LastPlayedColumn = Ui.GuiColumns.LastPlayedColumn, + FileExtColumn = Ui.GuiColumns.FileExtColumn, + FileSizeColumn = Ui.GuiColumns.FileSizeColumn, + PathColumn = Ui.GuiColumns.PathColumn, + }, + ColumnSort = new ColumnSort + { + SortColumnId = Ui.ColumnSort.SortColumnId, + SortAscending = Ui.ColumnSort.SortAscending + }, + GameDirs = Ui.GameDirs, + EnableCustomTheme = Ui.EnableCustomTheme, + CustomThemePath = Ui.CustomThemePath, + StartFullscreen = Ui.StartFullscreen, + EnableKeyboard = Hid.EnableKeyboard, + Hotkeys = Hid.Hotkeys, + KeyboardConfig = new List(), + ControllerConfig = new List(), + InputConfig = Hid.InputConfig, + }; + + return configurationFile; + } + + public void LoadDefault() + { + Logger.EnableFileLog.Value = true; + Graphics.ResScale.Value = 1; + Graphics.ResScaleCustom.Value = 1.0f; + Graphics.MaxAnisotropy.Value = -1.0f; + Graphics.AspectRatio.Value = AspectRatio.Fixed16x9; + Graphics.ShadersDumpPath.Value = ""; + Logger.EnableDebug.Value = false; + Logger.EnableStub.Value = true; + Logger.EnableInfo.Value = true; + Logger.EnableWarn.Value = true; + Logger.EnableError.Value = true; + Logger.EnableGuest.Value = true; + Logger.EnableFsAccessLog.Value = false; + Logger.FilteredClasses.Value = Array.Empty(); + Logger.GraphicsDebugLevel.Value = GraphicsDebugLevel.None; + System.Language.Value = Language.AmericanEnglish; + System.Region.Value = Region.USA; + System.TimeZone.Value = "UTC"; + System.SystemTimeOffset.Value = 0; + System.EnableDockedMode.Value = true; + EnableDiscordIntegration.Value = true; + CheckUpdatesOnStart.Value = true; + ShowConfirmExit.Value = true; + HideCursorOnIdle.Value = false; + Graphics.EnableVsync.Value = true; + Graphics.EnableShaderCache.Value = true; + System.EnablePtc.Value = true; + System.EnableFsIntegrityChecks.Value = true; + System.FsGlobalAccessLogMode.Value = 0; + System.AudioBackend.Value = AudioBackend.OpenAl; + System.ExpandRam.Value = false; + System.IgnoreMissingServices.Value = false; + Ui.GuiColumns.FavColumn.Value = true; + Ui.GuiColumns.IconColumn.Value = true; + Ui.GuiColumns.AppColumn.Value = true; + Ui.GuiColumns.DevColumn.Value = true; + Ui.GuiColumns.VersionColumn.Value = true; + Ui.GuiColumns.TimePlayedColumn.Value = true; + Ui.GuiColumns.LastPlayedColumn.Value = true; + Ui.GuiColumns.FileExtColumn.Value = true; + Ui.GuiColumns.FileSizeColumn.Value = true; + Ui.GuiColumns.PathColumn.Value = true; + Ui.ColumnSort.SortColumnId.Value = 0; + Ui.ColumnSort.SortAscending.Value = false; + Ui.GameDirs.Value = new List(); + Ui.EnableCustomTheme.Value = false; + Ui.CustomThemePath.Value = ""; + Ui.StartFullscreen.Value = false; + Hid.EnableKeyboard.Value = false; + Hid.Hotkeys.Value = new KeyboardHotkeys + { + ToggleVsync = Key.Tab + }; + Hid.InputConfig.Value = new List + { + new StandardKeyboardInputConfig + { + Version = InputConfig.CurrentVersion, + Backend = InputBackendType.WindowKeyboard, + Id = "0", + PlayerIndex = PlayerIndex.Player1, + ControllerType = ControllerType.JoyconPair, + LeftJoycon = new LeftJoyconCommonConfig + { + DpadUp = Key.Up, + DpadDown = Key.Down, + DpadLeft = Key.Left, + DpadRight = Key.Right, + ButtonMinus = Key.Minus, + ButtonL = Key.E, + ButtonZl = Key.Q, + ButtonSl = Key.Unbound, + ButtonSr = Key.Unbound + }, + + LeftJoyconStick = new JoyconConfigKeyboardStick + { + StickUp = Key.W, + StickDown = Key.S, + StickLeft = Key.A, + StickRight = Key.D, + StickButton = Key.F, + }, + + RightJoycon = new RightJoyconCommonConfig + { + ButtonA = Key.Z, + ButtonB = Key.X, + ButtonX = Key.C, + ButtonY = Key.V, + ButtonPlus = Key.Plus, + ButtonR = Key.U, + ButtonZr = Key.O, + ButtonSl = Key.Unbound, + ButtonSr = Key.Unbound + }, + + RightJoyconStick = new JoyconConfigKeyboardStick + { + StickUp = Key.I, + StickDown = Key.K, + StickLeft = Key.J, + StickRight = Key.L, + StickButton = Key.H, + } + } + }; + } + + public void Load(ConfigurationFileFormat configurationFileFormat, string configurationFilePath) + { + bool configurationFileUpdated = false; + + if (configurationFileFormat.Version < 0 || configurationFileFormat.Version > ConfigurationFileFormat.CurrentVersion) + { + Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Unsupported configuration version {configurationFileFormat.Version}, loading default."); + + LoadDefault(); + + return; + } + + if (configurationFileFormat.Version < 2) + { + Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 2."); + + configurationFileFormat.SystemRegion = Region.USA; + + configurationFileUpdated = true; + } + + if (configurationFileFormat.Version < 3) + { + Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 3."); + + configurationFileFormat.SystemTimeZone = "UTC"; + + configurationFileUpdated = true; + } + + if (configurationFileFormat.Version < 4) + { + Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 4."); + + configurationFileFormat.MaxAnisotropy = -1; + + configurationFileUpdated = true; + } + + if (configurationFileFormat.Version < 5) + { + Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 5."); + + configurationFileFormat.SystemTimeOffset = 0; + + configurationFileUpdated = true; + } + + if (configurationFileFormat.Version < 8) + { + Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 8."); + + configurationFileFormat.EnablePtc = true; + + configurationFileUpdated = true; + } + + if (configurationFileFormat.Version < 9) + { + Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 9."); + + configurationFileFormat.ColumnSort = new ColumnSort + { + SortColumnId = 0, + SortAscending = false + }; + + configurationFileFormat.Hotkeys = new KeyboardHotkeys + { + ToggleVsync = Key.Tab + }; + + configurationFileUpdated = true; + } + + if (configurationFileFormat.Version < 10) + { + Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 10."); + + configurationFileFormat.AudioBackend = AudioBackend.OpenAl; + + configurationFileUpdated = true; + } + + if (configurationFileFormat.Version < 11) + { + Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 11."); + + configurationFileFormat.ResScale = 1; + configurationFileFormat.ResScaleCustom = 1.0f; + + configurationFileUpdated = true; + } + + if (configurationFileFormat.Version < 12) + { + Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 12."); + + configurationFileFormat.LoggingGraphicsDebugLevel = GraphicsDebugLevel.None; + + configurationFileUpdated = true; + } + + if (configurationFileFormat.Version < 14) + { + Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 14."); + + configurationFileFormat.CheckUpdatesOnStart = true; + + configurationFileUpdated = true; + } + + if (configurationFileFormat.Version < 16) + { + Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 16."); + + configurationFileFormat.EnableShaderCache = true; + + configurationFileUpdated = true; + } + + if (configurationFileFormat.Version < 17) + { + Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 17."); + + configurationFileFormat.StartFullscreen = false; + + configurationFileUpdated = true; + } + + if (configurationFileFormat.Version < 18) + { + Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 18."); + + configurationFileFormat.AspectRatio = AspectRatio.Fixed16x9; + + configurationFileUpdated = true; + } + + if (configurationFileFormat.Version < 20) + { + Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 20."); + + configurationFileFormat.ShowConfirmExit = true; + + configurationFileUpdated = true; + } + + if (configurationFileFormat.Version < 22) + { + Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 22."); + + configurationFileFormat.HideCursorOnIdle = false; + + configurationFileUpdated = true; + } + + if (configurationFileFormat.Version < 24) + { + Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 24."); + + configurationFileFormat.InputConfig = new List + { + new StandardKeyboardInputConfig + { + Version = InputConfig.CurrentVersion, + Backend = InputBackendType.WindowKeyboard, + Id = "0", + PlayerIndex = PlayerIndex.Player1, + ControllerType = ControllerType.JoyconPair, + LeftJoycon = new LeftJoyconCommonConfig + { + DpadUp = Key.Up, + DpadDown = Key.Down, + DpadLeft = Key.Left, + DpadRight = Key.Right, + ButtonMinus = Key.Minus, + ButtonL = Key.E, + ButtonZl = Key.Q, + ButtonSl = Key.Unbound, + ButtonSr = Key.Unbound + }, + + LeftJoyconStick = new JoyconConfigKeyboardStick + { + StickUp = Key.W, + StickDown = Key.S, + StickLeft = Key.A, + StickRight = Key.D, + StickButton = Key.F, + }, + + RightJoycon = new RightJoyconCommonConfig + { + ButtonA = Key.Z, + ButtonB = Key.X, + ButtonX = Key.C, + ButtonY = Key.V, + ButtonPlus = Key.Plus, + ButtonR = Key.U, + ButtonZr = Key.O, + ButtonSl = Key.Unbound, + ButtonSr = Key.Unbound + }, + + RightJoyconStick = new JoyconConfigKeyboardStick + { + StickUp = Key.I, + StickDown = Key.K, + StickLeft = Key.J, + StickRight = Key.L, + StickButton = Key.H, + } + } + }; + + configurationFileUpdated = true; + } + + if (configurationFileFormat.Version < 25) + { + Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 25."); + + configurationFileUpdated = true; + } + + Logger.EnableFileLog.Value = configurationFileFormat.EnableFileLog; + Graphics.ResScale.Value = configurationFileFormat.ResScale; + Graphics.ResScaleCustom.Value = configurationFileFormat.ResScaleCustom; + Graphics.MaxAnisotropy.Value = configurationFileFormat.MaxAnisotropy; + Graphics.AspectRatio.Value = configurationFileFormat.AspectRatio; + Graphics.ShadersDumpPath.Value = configurationFileFormat.GraphicsShadersDumpPath; + Logger.EnableDebug.Value = configurationFileFormat.LoggingEnableDebug; + Logger.EnableStub.Value = configurationFileFormat.LoggingEnableStub; + Logger.EnableInfo.Value = configurationFileFormat.LoggingEnableInfo; + Logger.EnableWarn.Value = configurationFileFormat.LoggingEnableWarn; + Logger.EnableError.Value = configurationFileFormat.LoggingEnableError; + Logger.EnableGuest.Value = configurationFileFormat.LoggingEnableGuest; + Logger.EnableFsAccessLog.Value = configurationFileFormat.LoggingEnableFsAccessLog; + Logger.FilteredClasses.Value = configurationFileFormat.LoggingFilteredClasses; + Logger.GraphicsDebugLevel.Value = configurationFileFormat.LoggingGraphicsDebugLevel; + System.Language.Value = configurationFileFormat.SystemLanguage; + System.Region.Value = configurationFileFormat.SystemRegion; + System.TimeZone.Value = configurationFileFormat.SystemTimeZone; + System.SystemTimeOffset.Value = configurationFileFormat.SystemTimeOffset; + System.EnableDockedMode.Value = configurationFileFormat.DockedMode; + EnableDiscordIntegration.Value = configurationFileFormat.EnableDiscordIntegration; + CheckUpdatesOnStart.Value = configurationFileFormat.CheckUpdatesOnStart; + ShowConfirmExit.Value = configurationFileFormat.ShowConfirmExit; + HideCursorOnIdle.Value = configurationFileFormat.HideCursorOnIdle; + Graphics.EnableVsync.Value = configurationFileFormat.EnableVsync; + Graphics.EnableShaderCache.Value = configurationFileFormat.EnableShaderCache; + System.EnablePtc.Value = configurationFileFormat.EnablePtc; + System.EnableFsIntegrityChecks.Value = configurationFileFormat.EnableFsIntegrityChecks; + System.FsGlobalAccessLogMode.Value = configurationFileFormat.FsGlobalAccessLogMode; + System.AudioBackend.Value = configurationFileFormat.AudioBackend; + System.ExpandRam.Value = configurationFileFormat.ExpandRam; + System.IgnoreMissingServices.Value = configurationFileFormat.IgnoreMissingServices; + Ui.GuiColumns.FavColumn.Value = configurationFileFormat.GuiColumns.FavColumn; + Ui.GuiColumns.IconColumn.Value = configurationFileFormat.GuiColumns.IconColumn; + Ui.GuiColumns.AppColumn.Value = configurationFileFormat.GuiColumns.AppColumn; + Ui.GuiColumns.DevColumn.Value = configurationFileFormat.GuiColumns.DevColumn; + Ui.GuiColumns.VersionColumn.Value = configurationFileFormat.GuiColumns.VersionColumn; + Ui.GuiColumns.TimePlayedColumn.Value = configurationFileFormat.GuiColumns.TimePlayedColumn; + Ui.GuiColumns.LastPlayedColumn.Value = configurationFileFormat.GuiColumns.LastPlayedColumn; + Ui.GuiColumns.FileExtColumn.Value = configurationFileFormat.GuiColumns.FileExtColumn; + Ui.GuiColumns.FileSizeColumn.Value = configurationFileFormat.GuiColumns.FileSizeColumn; + Ui.GuiColumns.PathColumn.Value = configurationFileFormat.GuiColumns.PathColumn; + Ui.ColumnSort.SortColumnId.Value = configurationFileFormat.ColumnSort.SortColumnId; + Ui.ColumnSort.SortAscending.Value = configurationFileFormat.ColumnSort.SortAscending; + Ui.GameDirs.Value = configurationFileFormat.GameDirs; + Ui.EnableCustomTheme.Value = configurationFileFormat.EnableCustomTheme; + Ui.CustomThemePath.Value = configurationFileFormat.CustomThemePath; + Ui.StartFullscreen.Value = configurationFileFormat.StartFullscreen; + Hid.EnableKeyboard.Value = configurationFileFormat.EnableKeyboard; + Hid.Hotkeys.Value = configurationFileFormat.Hotkeys; + Hid.InputConfig.Value = configurationFileFormat.InputConfig; + + if (Hid.InputConfig.Value == null) + { + Hid.InputConfig.Value = new List(); + } + + if (configurationFileUpdated) + { + ToFileFormat().SaveConfig(configurationFilePath); + + Common.Logging.Logger.Notice.Print(LogClass.Application, $"Configuration file updated to version {ConfigurationFileFormat.CurrentVersion}"); + } + } + + private static void LogValueChange(object sender, ReactiveEventArgs eventArgs, string valueName) + { + Common.Logging.Logger.Info?.Print(LogClass.Configuration, $"{valueName} set to: {eventArgs.NewValue}"); + } + + public static void Initialize() + { + if (Instance != null) + { + throw new InvalidOperationException("Configuration is already initialized"); + } + + Instance = new ConfigurationState(); + } + } +} diff --git a/Ryujinx/Configuration/LoggerModule.cs b/Ryujinx/Configuration/LoggerModule.cs new file mode 100644 index 00000000..44631ea0 --- /dev/null +++ b/Ryujinx/Configuration/LoggerModule.cs @@ -0,0 +1,88 @@ +using Ryujinx.Common; +using Ryujinx.Common.Logging; +using System; + +namespace Ryujinx.Configuration +{ + public static class LoggerModule + { + public static void Initialize() + { + ConfigurationState.Instance.Logger.EnableDebug.Event += ReloadEnableDebug; + ConfigurationState.Instance.Logger.EnableStub.Event += ReloadEnableStub; + ConfigurationState.Instance.Logger.EnableInfo.Event += ReloadEnableInfo; + ConfigurationState.Instance.Logger.EnableWarn.Event += ReloadEnableWarning; + ConfigurationState.Instance.Logger.EnableError.Event += ReloadEnableError; + ConfigurationState.Instance.Logger.EnableGuest.Event += ReloadEnableGuest; + ConfigurationState.Instance.Logger.EnableFsAccessLog.Event += ReloadEnableFsAccessLog; + ConfigurationState.Instance.Logger.FilteredClasses.Event += ReloadFilteredClasses; + ConfigurationState.Instance.Logger.EnableFileLog.Event += ReloadFileLogger; + } + + private static void ReloadEnableDebug(object sender, ReactiveEventArgs e) + { + Logger.SetEnable(LogLevel.Debug, e.NewValue); + } + + private static void ReloadEnableStub(object sender, ReactiveEventArgs e) + { + Logger.SetEnable(LogLevel.Stub, e.NewValue); + } + + private static void ReloadEnableInfo(object sender, ReactiveEventArgs e) + { + Logger.SetEnable(LogLevel.Info, e.NewValue); + } + + private static void ReloadEnableWarning(object sender, ReactiveEventArgs e) + { + Logger.SetEnable(LogLevel.Warning, e.NewValue); + } + + private static void ReloadEnableError(object sender, ReactiveEventArgs e) + { + Logger.SetEnable(LogLevel.Error, e.NewValue); + } + + private static void ReloadEnableGuest(object sender, ReactiveEventArgs e) + { + Logger.SetEnable(LogLevel.Guest, e.NewValue); + } + + private static void ReloadEnableFsAccessLog(object sender, ReactiveEventArgs e) + { + Logger.SetEnable(LogLevel.AccessLog, e.NewValue); + } + + private static void ReloadFilteredClasses(object sender, ReactiveEventArgs e) + { + bool noFilter = e.NewValue.Length == 0; + + foreach (var logClass in EnumExtensions.GetValues()) + { + Logger.SetEnable(logClass, noFilter); + } + + foreach (var logClass in e.NewValue) + { + Logger.SetEnable(logClass, true); + } + } + + private static void ReloadFileLogger(object sender, ReactiveEventArgs e) + { + if (e.NewValue) + { + Logger.AddTarget(new AsyncLogTargetWrapper( + new FileLogTarget(AppDomain.CurrentDomain.BaseDirectory, "file"), + 1000, + AsyncLogTargetOverflowAction.Block + )); + } + else + { + Logger.RemoveTarget("file"); + } + } + } +} diff --git a/Ryujinx/Configuration/System/Language.cs b/Ryujinx/Configuration/System/Language.cs new file mode 100644 index 00000000..d3af296b --- /dev/null +++ b/Ryujinx/Configuration/System/Language.cs @@ -0,0 +1,23 @@ +namespace Ryujinx.Configuration.System +{ + public enum Language + { + Japanese, + AmericanEnglish, + French, + German, + Italian, + Spanish, + Chinese, + Korean, + Dutch, + Portuguese, + Russian, + Taiwanese, + BritishEnglish, + CanadianFrench, + LatinAmericanSpanish, + SimplifiedChinese, + TraditionalChinese + } +} diff --git a/Ryujinx/Configuration/System/Region.cs b/Ryujinx/Configuration/System/Region.cs new file mode 100644 index 00000000..54b1c36f --- /dev/null +++ b/Ryujinx/Configuration/System/Region.cs @@ -0,0 +1,13 @@ +namespace Ryujinx.Configuration.System +{ + public enum Region + { + Japan, + USA, + Europe, + Australia, + China, + Korea, + Taiwan + } +} diff --git a/Ryujinx/Configuration/Ui/ColumnSort.cs b/Ryujinx/Configuration/Ui/ColumnSort.cs new file mode 100644 index 00000000..fd8b5da1 --- /dev/null +++ b/Ryujinx/Configuration/Ui/ColumnSort.cs @@ -0,0 +1,8 @@ +namespace Ryujinx.Configuration.Ui +{ + public struct ColumnSort + { + public int SortColumnId { get; set; } + public bool SortAscending { get; set; } + } +} \ No newline at end of file diff --git a/Ryujinx/Configuration/Ui/GuiColumns.cs b/Ryujinx/Configuration/Ui/GuiColumns.cs new file mode 100644 index 00000000..de4f7369 --- /dev/null +++ b/Ryujinx/Configuration/Ui/GuiColumns.cs @@ -0,0 +1,16 @@ +namespace Ryujinx.Configuration.Ui +{ + public struct GuiColumns + { + public bool FavColumn { get; set; } + public bool IconColumn { get; set; } + public bool AppColumn { get; set; } + public bool DevColumn { get; set; } + public bool VersionColumn { get; set; } + public bool TimePlayedColumn { get; set; } + public bool LastPlayedColumn { get; set; } + public bool FileExtColumn { get; set; } + public bool FileSizeColumn { get; set; } + public bool PathColumn { get; set; } + } +} diff --git a/Ryujinx/Ui/Applet/GtkHostUiHandler.cs b/Ryujinx/Ui/Applet/GtkHostUiHandler.cs index d74ea3d5..c227ebd3 100644 --- a/Ryujinx/Ui/Applet/GtkHostUiHandler.cs +++ b/Ryujinx/Ui/Applet/GtkHostUiHandler.cs @@ -131,7 +131,7 @@ namespace Ryujinx.Ui.Applet public void ExecuteProgram(HLE.Switch device, ProgramSpecifyKind kind, ulong value) { - device.UserChannelPersistence.ExecuteProgram(kind, value); + device.Configuration.UserChannelPersistence.ExecuteProgram(kind, value); ((MainWindow)_parent).RendererWidget?.Exit(); } diff --git a/Ryujinx/Ui/MainWindow.cs b/Ryujinx/Ui/MainWindow.cs index a2a00992..1eef7554 100644 --- a/Ryujinx/Ui/MainWindow.cs +++ b/Ryujinx/Ui/MainWindow.cs @@ -2,12 +2,14 @@ using ARMeilleure.Translation; using ARMeilleure.Translation.PTC; using Gtk; using LibHac.Common; +using LibHac.FsSystem; using LibHac.Ns; using Ryujinx.Audio.Backends.Dummy; using Ryujinx.Audio.Backends.OpenAL; using Ryujinx.Audio.Backends.SDL2; using Ryujinx.Audio.Backends.SoundIo; using Ryujinx.Audio.Integration; +using Ryujinx.Common; using Ryujinx.Common.Configuration; using Ryujinx.Common.Logging; using Ryujinx.Common.System; @@ -18,6 +20,7 @@ using Ryujinx.HLE.FileSystem; using Ryujinx.HLE.FileSystem.Content; using Ryujinx.HLE.HOS; using Ryujinx.HLE.HOS.Services.Account.Acc; +using Ryujinx.HLE.HOS.SystemState; using Ryujinx.Input.GTK3; using Ryujinx.Input.HLE; using Ryujinx.Input.SDL2; @@ -166,6 +169,10 @@ namespace Ryujinx.Ui RendererWidgetBase.StatusUpdatedEvent += Update_StatusBar; + ConfigurationState.Instance.System.IgnoreMissingServices.Event += UpdateIgnoreMissingServicesState; + ConfigurationState.Instance.Graphics.AspectRatio.Event += UpdateAspectRatioState; + ConfigurationState.Instance.System.EnableDockedMode.Event += UpdateDockedModeState; + if (ConfigurationState.Instance.Ui.StartFullscreen) { _startFullScreen.Active = true; @@ -236,6 +243,30 @@ namespace Ryujinx.Ui InputManager = new InputManager(new GTK3KeyboardDriver(this), new SDL2GamepadDriver()); } + private void UpdateIgnoreMissingServicesState(object sender, ReactiveEventArgs args) + { + if (_emulationContext != null) + { + _emulationContext.Configuration.IgnoreMissingServices = args.NewValue; + } + } + + private void UpdateAspectRatioState(object sender, ReactiveEventArgs args) + { + if (_emulationContext != null) + { + _emulationContext.Configuration.AspectRatio = args.NewValue; + } + } + + private void UpdateDockedModeState(object sender, ReactiveEventArgs e) + { + if (_emulationContext != null) + { + _emulationContext.System.ChangeDockedModeState(e.NewValue); + } + } + private void WindowStateEvent_Changed(object o, WindowStateEventArgs args) { _fullScreen.Label = args.Event.NewWindowState.HasFlag(Gdk.WindowState.Fullscreen) ? "Exit Fullscreen" : "Enter Fullscreen"; @@ -380,19 +411,29 @@ namespace Ryujinx.Ui ? HLE.MemoryConfiguration.MemoryConfiguration6GB : HLE.MemoryConfiguration.MemoryConfiguration4GB; - _emulationContext = new HLE.Switch( - _virtualFileSystem, - _contentManager, - _accountManager, - _userChannelPersistence, - renderer, - deviceDriver, - memoryConfiguration) - { - UiHandler = _uiHandler - }; - - _emulationContext.Initialize(); + IntegrityCheckLevel fsIntegrityCheckLevel = ConfigurationState.Instance.System.EnableFsIntegrityChecks ? IntegrityCheckLevel.ErrorOnInvalid : IntegrityCheckLevel.None; + + HLE.HLEConfiguration configuration = new HLE.HLEConfiguration(_virtualFileSystem, + _contentManager, + _accountManager, + _userChannelPersistence, + renderer, + deviceDriver, + memoryConfiguration, + _uiHandler, + (SystemLanguage)ConfigurationState.Instance.System.Language.Value, + (RegionCode)ConfigurationState.Instance.System.Region.Value, + ConfigurationState.Instance.Graphics.EnableVsync, + ConfigurationState.Instance.System.EnableDockedMode, + ConfigurationState.Instance.System.EnablePtc, + fsIntegrityCheckLevel, + ConfigurationState.Instance.System.FsGlobalAccessLogMode, + ConfigurationState.Instance.System.SystemTimeOffset, + ConfigurationState.Instance.System.TimeZone, + ConfigurationState.Instance.System.IgnoreMissingServices, + ConfigurationState.Instance.Graphics.AspectRatio); + + _emulationContext = new HLE.Switch(configuration); } private void SetupProgressUiHandlers() diff --git a/Ryujinx/Ui/RendererWidgetBase.cs b/Ryujinx/Ui/RendererWidgetBase.cs index 1e388747..00882ba0 100644 --- a/Ryujinx/Ui/RendererWidgetBase.cs +++ b/Ryujinx/Ui/RendererWidgetBase.cs @@ -73,8 +73,6 @@ namespace Ryujinx.Ui NpadManager = _inputManager.CreateNpadManager(); _keyboardInterface = (IKeyboard)_inputManager.KeyboardDriver.GetGamepad("0"); - NpadManager.ReloadConfiguration(ConfigurationState.Instance.Hid.InputConfig.Value.ToList()); - WaitEvent = new ManualResetEvent(false); _glLogLevel = glLogLevel; @@ -300,6 +298,8 @@ namespace Ryujinx.Ui Device = device; Renderer = Device.Gpu.Renderer; Renderer?.Window.SetSize(_windowWidth, _windowHeight); + + NpadManager.Initialize(device, ConfigurationState.Instance.Hid.InputConfig, ConfigurationState.Instance.Hid.EnableKeyboard); } public void Render() @@ -488,7 +488,7 @@ namespace Ryujinx.Ui }); } - NpadManager.Update(Device.Hid, Device.TamperMachine); + NpadManager.Update(); if (_isFocused) { diff --git a/Ryujinx/Ui/Windows/ControllerWindow.cs b/Ryujinx/Ui/Windows/ControllerWindow.cs index 2732bdcb..0a3deec1 100644 --- a/Ryujinx/Ui/Windows/ControllerWindow.cs +++ b/Ryujinx/Ui/Windows/ControllerWindow.cs @@ -1143,7 +1143,7 @@ namespace Ryujinx.Ui.Windows if (_mainWindow.RendererWidget != null) { - _mainWindow.RendererWidget.NpadManager.ReloadConfiguration(newConfig); + _mainWindow.RendererWidget.NpadManager.ReloadConfiguration(newConfig, ConfigurationState.Instance.Hid.EnableKeyboard); } // Atomically replace and signal input change. diff --git a/Ryujinx/Ui/Windows/SettingsWindow.cs b/Ryujinx/Ui/Windows/SettingsWindow.cs index 94afb242..43fea4e2 100644 --- a/Ryujinx/Ui/Windows/SettingsWindow.cs +++ b/Ryujinx/Ui/Windows/SettingsWindow.cs @@ -263,7 +263,7 @@ namespace Ryujinx.Ui.Windows } _systemTimeZoneEntry.WidthChars = Math.Max(20, maxLocationLength + 1); // Ensure minimum Entry width - _systemTimeZoneEntry.Text = _timeZoneContentManager.SanityCheckDeviceLocationName(); + _systemTimeZoneEntry.Text = _timeZoneContentManager.SanityCheckDeviceLocationName(ConfigurationState.Instance.System.TimeZone); _systemTimeZoneCompletion.MatchFunc = TimeZoneMatchFunc; @@ -462,7 +462,7 @@ namespace Ryujinx.Ui.Windows { if (!_validTzRegions.Contains(_systemTimeZoneEntry.Text)) { - _systemTimeZoneEntry.Text = _timeZoneContentManager.SanityCheckDeviceLocationName(); + _systemTimeZoneEntry.Text = _timeZoneContentManager.SanityCheckDeviceLocationName(ConfigurationState.Instance.System.TimeZone); } } -- cgit v1.2.3