Start rewriting the Configuration system

TODO:
- Move ConfigurationState to Ryujinx.Common or a new project
- Make controllers reloadable
This commit is contained in:
Thog 2019-11-21 19:39:12 +01:00
parent bb7600e215
commit ba74f814e9
No known key found for this signature in database
GPG key ID: 0CD291558FAFDBC6
16 changed files with 978 additions and 424 deletions

View file

@ -37,6 +37,13 @@ namespace Ryujinx.Common.Logging
m_LogTargets = new List<ILogTarget>();
m_Time = Stopwatch.StartNew();
// logger should log to console by default
AddTarget(new AsyncLogTargetWrapper(
new ConsoleLogTarget("console"),
1000,
AsyncLogTargetOverflowAction.Block
));
}
public static void RestartTime()
@ -44,6 +51,19 @@ namespace Ryujinx.Common.Logging
m_Time.Restart();
}
private static ILogTarget GetTarget(string targetName)
{
foreach (var target in m_LogTargets)
{
if (target.GetName().Equals(targetName))
{
return target;
}
}
return null;
}
public static void AddTarget(ILogTarget target)
{
m_LogTargets.Add(target);
@ -51,6 +71,24 @@ namespace Ryujinx.Common.Logging
Updated += target.Log;
}
public static void RemoveTarget(string target)
{
ILogTarget logTarget = GetTarget(target);
// TODO: remove this
if (logTarget == null)
throw new Exception();
if (logTarget != null)
{
Updated -= logTarget.Log;
m_LogTargets.Remove(logTarget);
logTarget.Dispose();
}
}
public static void Shutdown()
{
Updated = null;

View file

@ -72,5 +72,10 @@ namespace Ryujinx.Common.Logging
_messageQueue.CompleteAdding();
_messageThread.Join();
}
public string GetName()
{
return _target.GetName();
}
}
}

View file

@ -9,6 +9,8 @@ namespace Ryujinx.Common.Logging
private readonly ILogFormatter _formatter;
private readonly string _name;
static ConsoleLogTarget()
{
_logColors = new ConcurrentDictionary<LogLevel, ConsoleColor> {
@ -19,9 +21,10 @@ namespace Ryujinx.Common.Logging
};
}
public ConsoleLogTarget()
public ConsoleLogTarget(string name)
{
_formatter = new DefaultLogFormatter();
_name = name;
}
public void Log(object sender, LogEventArgs args)
@ -44,5 +47,10 @@ namespace Ryujinx.Common.Logging
{
Console.ResetColor();
}
public string GetName()
{
return _name;
}
}
}

View file

@ -9,13 +9,15 @@ namespace Ryujinx.Common.Logging
private readonly StreamWriter _logWriter;
private readonly ILogFormatter _formatter;
private readonly string _name;
public FileLogTarget(string path)
: this(path, FileShare.Read, FileMode.Append)
public FileLogTarget(string path, string name)
: this(path, name, FileShare.Read, FileMode.Append)
{ }
public FileLogTarget(string path, FileShare fileShare, FileMode fileMode)
public FileLogTarget(string path, string name, FileShare fileShare, FileMode fileMode)
{
_name = name;
_logWriter = new StreamWriter(File.Open(path, fileMode, FileAccess.Write, fileShare));
_formatter = new DefaultLogFormatter();
}
@ -32,5 +34,10 @@ namespace Ryujinx.Common.Logging
_logWriter.Flush();
_logWriter.Dispose();
}
public string GetName()
{
return _name;
}
}
}

View file

@ -5,5 +5,7 @@ namespace Ryujinx.Common.Logging
public interface ILogTarget : IDisposable
{
void Log(object sender, LogEventArgs args);
string GetName();
}
}

View file

@ -7,10 +7,12 @@ namespace Ryujinx.Common.Logging
{
private Stream _stream;
private bool _leaveOpen;
private string _name;
public JsonLogTarget(Stream stream)
public JsonLogTarget(Stream stream, string name)
{
_stream = stream;
_name = name;
}
public JsonLogTarget(Stream stream, bool leaveOpen)
@ -31,5 +33,10 @@ namespace Ryujinx.Common.Logging
_stream.Dispose();
}
}
public string GetName()
{
return _name;
}
}
}

View file

@ -0,0 +1,57 @@
using System;
using System.Threading;
namespace Ryujinx.Common
{
public class ReactiveObject<T>
{
private ReaderWriterLock _readerWriterLock = new ReaderWriterLock();
private T _value;
public event EventHandler<ReactiveEventArgs<T>> Event;
public T Value
{
get
{
_readerWriterLock.AcquireReaderLock(int.MaxValue);
T value = _value;
_readerWriterLock.ReleaseReaderLock();
return value;
}
set
{
_readerWriterLock.AcquireWriterLock(int.MaxValue);
T oldValue = _value;
_value = value;
_readerWriterLock.ReleaseWriterLock();
if (oldValue == null || !oldValue.Equals(_value))
{
Event?.Invoke(this, new ReactiveEventArgs<T>(oldValue, value));
}
}
}
public static implicit operator T(ReactiveObject<T> obj)
{
return obj.Value;
}
}
public class ReactiveEventArgs<T>
{
public T OldValue { get; private set; }
public T Value { get; private set; }
public ReactiveEventArgs(T oldValue, T value)
{
OldValue = oldValue;
Value = value;
}
}
}

View file

@ -1,8 +1,11 @@
using LibHac.FsSystem;
using Ryujinx.Audio;
using Ryujinx.Graphics;
using Ryujinx.Graphics.Gal;
using Ryujinx.HLE.FileSystem;
using Ryujinx.HLE.HOS;
using Ryujinx.HLE.HOS.Services;
using Ryujinx.HLE.HOS.SystemState;
using Ryujinx.HLE.Input;
using System;
using System.Threading;
@ -60,6 +63,29 @@ namespace Ryujinx.HLE
VsyncEvent = new AutoResetEvent(true);
}
// TODO: Use Configuration when it will be moved to Common.
public void Initialize(SystemLanguage language, bool enableMulticoreScheduling, bool enableDockedMode, bool enableVsync, bool enableFsIntegrityChecks, int fsGlobalAccessLogMode, bool ignoreMissingServices)
{
System.State.SetLanguage(language);
EnableDeviceVsync = enableVsync;
System.State.DockedMode = enableDockedMode;
if (enableMulticoreScheduling)
{
System.EnableMultiCoreScheduling();
}
System.FsIntegrityCheckLevel = enableFsIntegrityChecks
? IntegrityCheckLevel.ErrorOnInvalid
: IntegrityCheckLevel.None;
System.GlobalAccessLogMode = fsGlobalAccessLogMode;
ServiceConfiguration.IgnoreMissingServices = ignoreMissingServices;
}
public void LoadCart(string exeFsDir, string romFsFile = null)
{
System.LoadCart(exeFsDir, romFsFile);

View file

@ -0,0 +1,391 @@
using Ryujinx.Common;
using Ryujinx.Common.Logging;
using Ryujinx.HLE.HOS.SystemState;
using Ryujinx.HLE.Input;
using Ryujinx.Ui.Input;
using System;
using System.Collections.Generic;
namespace Ryujinx.Configuration
{
public class ConfigurationState
{
/// <summary>
/// UI configuration section
/// </summary>
public class UiSection
{
public class Columns
{
public ReactiveObject<bool> FavColumn { get; private set; }
public ReactiveObject<bool> IconColumn { get; private set; }
public ReactiveObject<bool> AppColumn { get; private set; }
public ReactiveObject<bool> DevColumn { get; private set; }
public ReactiveObject<bool> VersionColumn { get; private set; }
public ReactiveObject<bool> TimePlayedColumn { get; private set; }
public ReactiveObject<bool> LastPlayedColumn { get; private set; }
public ReactiveObject<bool> FileExtColumn { get; private set; }
public ReactiveObject<bool> FileSizeColumn { get; private set; }
public ReactiveObject<bool> PathColumn { get; private set; }
public Columns()
{
FavColumn = new ReactiveObject<bool>();
IconColumn = new ReactiveObject<bool>();
AppColumn = new ReactiveObject<bool>();
DevColumn = new ReactiveObject<bool>();
VersionColumn = new ReactiveObject<bool>();
TimePlayedColumn = new ReactiveObject<bool>();
LastPlayedColumn = new ReactiveObject<bool>();
FileExtColumn = new ReactiveObject<bool>();
FileSizeColumn = new ReactiveObject<bool>();
PathColumn = new ReactiveObject<bool>();
}
}
/// <summary>
/// Used to toggle columns in the GUI
/// </summary>
// TODO: UPDATE THIS TO MASTER
public Columns GuiColumns { get; private set; }
/// <summary>
/// A list of directories containing games to be used to load games into the games list
/// </summary>
public ReactiveObject<List<string>> GameDirs { get; private set; }
/// <summary>
/// Enable or disable custom themes in the GUI
/// </summary>
public ReactiveObject<bool> EnableCustomTheme { get; private set; }
/// <summary>
/// Path to custom GUI theme
/// </summary>
public ReactiveObject<string> CustomThemePath { get; private set; }
public UiSection()
{
GuiColumns = new Columns();
GameDirs = new ReactiveObject<List<string>>();
EnableCustomTheme = new ReactiveObject<bool>();
CustomThemePath = new ReactiveObject<string>();
}
}
/// <summary>
/// Logger configuration section
/// </summary>
public class LoggerSection
{
/// <summary>
/// Enables printing debug log messages
/// </summary>
public ReactiveObject<bool> EnableDebug { get; private set; }
/// <summary>
/// Enables printing stub log messages
/// </summary>
public ReactiveObject<bool> EnableStub { get; private set; }
/// <summary>
/// Enables printing info log messages
/// </summary>
public ReactiveObject<bool> EnableInfo { get; private set; }
/// <summary>
/// Enables printing warning log messages
/// </summary>
public ReactiveObject<bool> EnableWarn { get; private set; }
/// <summary>
/// Enables printing error log messages
/// </summary>
public ReactiveObject<bool> EnableError { get; private set; }
/// <summary>
/// Enables printing guest log messages
/// </summary>
public ReactiveObject<bool> EnableGuest { get; private set; }
/// <summary>
/// Enables printing FS access log messages
/// </summary>
public ReactiveObject<bool> EnableFsAccessLog { get; private set; }
/// <summary>
/// Controls which log messages are written to the log targets
/// </summary>
public ReactiveObject<LogClass[]> FilteredClasses { get; private set; }
/// <summary>
/// Enables or disables logging to a file on disk
/// </summary>
public ReactiveObject<bool> EnableFileLog { get; private set; }
public LoggerSection()
{
EnableDebug = new ReactiveObject<bool>();
EnableStub = new ReactiveObject<bool>();
EnableInfo = new ReactiveObject<bool>();
EnableWarn = new ReactiveObject<bool>();
EnableError = new ReactiveObject<bool>();
EnableGuest = new ReactiveObject<bool>();
EnableFsAccessLog = new ReactiveObject<bool>();
FilteredClasses = new ReactiveObject<LogClass[]>();
EnableFileLog = new ReactiveObject<bool>();
}
}
/// <summary>
/// System configuration section
/// </summary>
public class SystemSection
{
/// <summary>
/// Change System Language
/// </summary>
public ReactiveObject<SystemLanguage> Language { get; private set; }
/// <summary>
/// Enables or disables Docked Mode
/// </summary>
public ReactiveObject<bool> EnableDockedMode { get; private set; }
/// <summary>
/// Enables or disables multi-core scheduling of threads
/// </summary>
public ReactiveObject<bool> EnableMulticoreScheduling { get; private set; }
/// <summary>
/// Enables integrity checks on Game content files
/// </summary>
public ReactiveObject<bool> EnableFsIntegrityChecks { get; private set; }
/// <summary>
/// Enables FS access log output to the console. Possible modes are 0-3
/// </summary>
public ReactiveObject<int> FsGlobalAccessLogMode { get; private set; }
/// <summary>
/// Enable or disable ignoring missing services
/// </summary>
public ReactiveObject<bool> IgnoreMissingServices { get; private set; }
public SystemSection()
{
Language = new ReactiveObject<SystemLanguage>();
EnableDockedMode = new ReactiveObject<bool>();
EnableMulticoreScheduling = new ReactiveObject<bool>();
EnableFsIntegrityChecks = new ReactiveObject<bool>();
FsGlobalAccessLogMode = new ReactiveObject<int>();
IgnoreMissingServices = new ReactiveObject<bool>();
}
}
/// <summary>
/// Hid configuration section
/// </summary>
public class HidSection
{
/// <summary>
/// The primary controller's type
/// </summary>
public ReactiveObject<ControllerStatus> ControllerType { get; private set; }
/// <summary>
/// Enable or disable keyboard support (Independent from controllers binding)
/// </summary>
public ReactiveObject<bool> EnableKeyboard { get; private set; }
/// <summary>
/// Keyboard control bindings
/// </summary>
public ReactiveObject<NpadKeyboard> KeyboardControls { get; private set; }
/// <summary>
/// Controller control bindings
/// </summary>
public ReactiveObject<Ui.Input.NpadController> JoystickControls { get; private set; }
public HidSection()
{
ControllerType = new ReactiveObject<ControllerStatus>();
EnableKeyboard = new ReactiveObject<bool>();
KeyboardControls = new ReactiveObject<NpadKeyboard>();
JoystickControls = new ReactiveObject<Ui.Input.NpadController>();
}
}
/// <summary>
/// Graphics configuration section
/// </summary>
public class GraphicsSection
{
/// <summary>
/// Dumps shaders in this local directory
/// </summary>
public ReactiveObject<string> ShadersDumpPath { get; private set; }
/// <summary>
/// Enables or disables Vertical Sync
/// </summary>
public ReactiveObject<bool> EnableVsync { get; private set; }
public GraphicsSection()
{
ShadersDumpPath = new ReactiveObject<string>();
EnableVsync = new ReactiveObject<bool>();
}
}
/// <summary>
/// The default configuration instance
/// </summary>
public static ConfigurationState Instance { get; private set; }
/// <summary>
/// The Ui section
/// </summary>
public UiSection Ui { get; private set; }
/// <summary>
/// The Logger section
/// </summary>
public LoggerSection Logger { get; private set; }
/// <summary>
/// The System section
/// </summary>
public SystemSection System { get; private set; }
/// <summary>
/// The Graphics section
/// </summary>
public GraphicsSection Graphics { get; private set; }
/// <summary>
/// The Hid section
/// </summary>
public HidSection Hid { get; private set; }
/// <summary>
/// Enables or disables Discord Rich Presence
/// </summary>
public ReactiveObject<bool> EnableDiscordIntegration { get; private set; }
private ConfigurationState()
{
Ui = new UiSection();
Logger = new LoggerSection();
System = new SystemSection();
Graphics = new GraphicsSection();
Hid = new HidSection();
EnableDiscordIntegration = new ReactiveObject<bool>();
}
public ConfigurationFileFormat ToFileFormat()
{
ConfigurationFileFormat configurationFile = new ConfigurationFileFormat
{
Version = 1,
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,
EnableFileLog = Logger.EnableFileLog,
SystemLanguage = System.Language,
DockedMode = System.EnableDockedMode,
EnableDiscordIntegration = EnableDiscordIntegration,
EnableVsync = Graphics.EnableVsync,
EnableMulticoreScheduling = System.EnableMulticoreScheduling,
EnableFsIntegrityChecks = System.EnableFsIntegrityChecks,
FsGlobalAccessLogMode = System.FsGlobalAccessLogMode,
IgnoreMissingServices = System.IgnoreMissingServices,
ControllerType = Hid.ControllerType,
GuiColumns = new Ui.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,
},
GameDirs = Ui.GameDirs,
EnableCustomTheme = Ui.EnableCustomTheme,
CustomThemePath = Ui.CustomThemePath,
EnableKeyboard = Hid.EnableKeyboard,
KeyboardControls = Hid.KeyboardControls,
JoystickControls = Hid.JoystickControls
};
return configurationFile;
}
public void Load(ConfigurationFileFormat configurationFileFormat)
{
if (configurationFileFormat.Version != 1 && configurationFileFormat.Version != 0)
{
// TODO: load default configuration
throw new System.NotSupportedException($"Unsupported configuration version {configurationFileFormat.Version}");
}
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.EnableFileLog.Value = configurationFileFormat.EnableFileLog;
System.Language.Value = configurationFileFormat.SystemLanguage;
System.EnableDockedMode.Value = configurationFileFormat.DockedMode;
System.EnableDockedMode.Value = configurationFileFormat.DockedMode;
EnableDiscordIntegration.Value = configurationFileFormat.EnableDiscordIntegration;
Graphics.EnableVsync.Value = configurationFileFormat.EnableVsync;
System.EnableMulticoreScheduling.Value = configurationFileFormat.EnableMulticoreScheduling;
System.EnableFsIntegrityChecks.Value = configurationFileFormat.EnableFsIntegrityChecks;
System.FsGlobalAccessLogMode.Value = configurationFileFormat.FsGlobalAccessLogMode;
System.IgnoreMissingServices.Value = configurationFileFormat.IgnoreMissingServices;
Hid.ControllerType.Value = configurationFileFormat.ControllerType;
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.GameDirs.Value = configurationFileFormat.GameDirs;
Ui.EnableCustomTheme.Value = configurationFileFormat.EnableCustomTheme;
Ui.CustomThemePath.Value = configurationFileFormat.CustomThemePath;
Hid.EnableKeyboard.Value = configurationFileFormat.EnableKeyboard;
Hid.KeyboardControls.Value = configurationFileFormat.KeyboardControls;
Hid.JoystickControls.Value = configurationFileFormat.JoystickControls;
}
public static void Initialize()
{
if (Instance != null)
{
throw new InvalidOperationException("Configuration is already initialized!");
}
Instance = new ConfigurationState();
}
}
}

View file

@ -13,18 +13,14 @@ using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Threading.Tasks;
using Utf8Json;
using Utf8Json.Resolvers;
namespace Ryujinx
namespace Ryujinx.Configuration
{
public class Configuration
public class ConfigurationFileFormat
{
/// <summary>
/// The default configuration instance
/// </summary>
public static Configuration Instance { get; private set; }
public int Version { get; set; }
/// <summary>
/// Dumps shaders in this local directory
@ -154,13 +150,13 @@ namespace Ryujinx
/// <summary>
/// Controller control bindings
/// </summary>
public Ui.Input.NpadController JoystickControls { get; private set; }
public Ui.Input.NpadController JoystickControls { get; set; }
/// <summary>
/// Loads a configuration file from disk
/// </summary>
/// <param name="path">The path to the JSON configuration file</param>
public static void Load(string path)
public static ConfigurationFileFormat Load(string path)
{
var resolver = CompositeResolver.Create(
new[] { new ConfigurationEnumFormatter<Key>() },
@ -169,24 +165,7 @@ namespace Ryujinx
using (Stream stream = File.OpenRead(path))
{
Instance = JsonSerializer.Deserialize<Configuration>(stream, resolver);
}
}
/// <summary>
/// Loads a configuration file asynchronously from disk
/// </summary>
/// <param name="path">The path to the JSON configuration file</param>
public static async Task LoadAsync(string path)
{
IJsonFormatterResolver resolver = CompositeResolver.Create(
new[] { new ConfigurationEnumFormatter<Key>() },
new[] { StandardResolver.AllowPrivateSnakeCase }
);
using (Stream stream = File.OpenRead(path))
{
Instance = await JsonSerializer.DeserializeAsync<Configuration>(stream, resolver);
return JsonSerializer.Deserialize<ConfigurationFileFormat>(stream, resolver);
}
}
@ -194,108 +173,17 @@ namespace Ryujinx
/// Save a configuration file to disk
/// </summary>
/// <param name="path">The path to the JSON configuration file</param>
public static void SaveConfig(Configuration config, string path)
public void SaveConfig(string path)
{
IJsonFormatterResolver resolver = CompositeResolver.Create(
new[] { new ConfigurationEnumFormatter<Key>() },
new[] { StandardResolver.AllowPrivateSnakeCase }
);
byte[] data = JsonSerializer.Serialize(config, resolver);
byte[] data = JsonSerializer.Serialize(this, resolver);
File.WriteAllText(path, Encoding.UTF8.GetString(data, 0, data.Length).PrettyPrintJson());
}
/// <summary>
/// Configures a <see cref="Switch"/> instance
/// </summary>
/// <param name="device">The instance to configure</param>
public static void InitialConfigure(Switch device)
{
if (Instance == null)
{
throw new InvalidOperationException("Configuration has not been loaded yet.");
}
SwitchSettings.ConfigureSettings(Instance);
Logger.AddTarget(new AsyncLogTargetWrapper(
new ConsoleLogTarget(),
1000,
AsyncLogTargetOverflowAction.Block
));
if (Instance.EnableFileLog)
{
Logger.AddTarget(new AsyncLogTargetWrapper(
new FileLogTarget(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Ryujinx.log")),
1000,
AsyncLogTargetOverflowAction.Block
));
}
Configure(device, Instance);
}
public static void Configure(Switch device, Configuration SwitchConfig)
{
GraphicsConfig.ShadersDumpPath = SwitchConfig.GraphicsShadersDumpPath;
Logger.SetEnable(LogLevel.Debug, SwitchConfig.LoggingEnableDebug );
Logger.SetEnable(LogLevel.Stub, SwitchConfig.LoggingEnableStub );
Logger.SetEnable(LogLevel.Info, SwitchConfig.LoggingEnableInfo );
Logger.SetEnable(LogLevel.Warning, SwitchConfig.LoggingEnableWarn );
Logger.SetEnable(LogLevel.Error, SwitchConfig.LoggingEnableError );
Logger.SetEnable(LogLevel.Guest, SwitchConfig.LoggingEnableGuest );
Logger.SetEnable(LogLevel.AccessLog, SwitchConfig.LoggingEnableFsAccessLog);
if (SwitchConfig.LoggingFilteredClasses.Length > 0)
{
foreach (var logClass in EnumExtensions.GetValues<LogClass>())
{
Logger.SetEnable(logClass, false);
}
foreach (var logClass in SwitchConfig.LoggingFilteredClasses)
{
Logger.SetEnable(logClass, true);
}
}
MainWindow.DiscordIntegrationEnabled = SwitchConfig.EnableDiscordIntegration;
device.EnableDeviceVsync = SwitchConfig.EnableVsync;
device.System.State.DockedMode = SwitchConfig.DockedMode;
device.System.State.SetLanguage(SwitchConfig.SystemLanguage);
if (SwitchConfig.EnableMulticoreScheduling)
{
device.System.EnableMultiCoreScheduling();
}
device.System.FsIntegrityCheckLevel = SwitchConfig.EnableFsIntegrityChecks
? IntegrityCheckLevel.ErrorOnInvalid
: IntegrityCheckLevel.None;
device.System.GlobalAccessLogMode = SwitchConfig.FsGlobalAccessLogMode;
ServiceConfiguration.IgnoreMissingServices = SwitchConfig.IgnoreMissingServices;
}
public static void ConfigureHid(Switch device, Configuration SwitchConfig)
{
if (SwitchConfig.JoystickControls.Enabled)
{
if (!Joystick.GetState(SwitchConfig.JoystickControls.Index).IsConnected)
{
SwitchConfig.JoystickControls.SetEnabled(false);
}
}
device.Hid.InitializePrimaryController(SwitchConfig.ControllerType);
device.Hid.InitializeKeyboard();
}
private class ConfigurationEnumFormatter<T> : IJsonFormatter<T>
where T : struct
{

View file

@ -0,0 +1,90 @@
using DiscordRPC;
using Ryujinx.Common;
using System;
using System.IO;
using System.Linq;
namespace Ryujinx.Configuration
{
static class DiscordIntegrationModule
{
private static DiscordRpcClient DiscordClient;
public static RichPresence DiscordPresence { get; private set; }
public static void Initialize()
{
DiscordPresence = new RichPresence
{
Assets = new Assets
{
LargeImageKey = "ryujinx",
LargeImageText = "Ryujinx is an emulator for the Nintendo Switch"
},
Details = "Main Menu",
State = "Idling",
Timestamps = new Timestamps(DateTime.UtcNow)
};
ConfigurationState.Instance.EnableDiscordIntegration.Event += Update;
}
private static void Update(object sender, ReactiveEventArgs<bool> e)
{
if (e.OldValue != e.Value)
{
// If the integration was active, disable it and unload everything
if (e.OldValue)
{
DiscordClient?.Dispose();
DiscordClient = null;
}
// If we need to activate it and the client isn't active, initialize it
if (e.Value && DiscordClient == null)
{
DiscordClient = new DiscordRpcClient("568815339807309834");
DiscordClient.Initialize();
DiscordClient.SetPresence(DiscordPresence);
}
}
}
public static void SwitchToPlayingState(string titleId, string titleName)
{
if (File.ReadAllLines(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "RPsupported.dat")).Contains(titleId))
{
DiscordPresence.Assets.LargeImageKey = titleId;
}
string state = titleId;
if (state == null)
{
state = "Ryujinx";
}
else
{
state = state.ToUpper();
}
string details = "Idling";
if (titleName != null)
{
details = $"Playing {titleName}";
}
DiscordPresence.Details = details;
DiscordPresence.State = state;
DiscordPresence.Assets.LargeImageText = titleName;
DiscordPresence.Assets.SmallImageKey = "ryujinx";
DiscordPresence.Assets.SmallImageText = "Ryujinx is an emulator for the Nintendo Switch";
DiscordPresence.Timestamps = new Timestamps(DateTime.UtcNow);
DiscordClient?.SetPresence(DiscordPresence);
}
}
}

View file

@ -0,0 +1,112 @@
using Ryujinx.Common;
using Ryujinx.Common.Logging;
using System;
using System.IO;
namespace Ryujinx.Configuration
{
public static class LoggerModule
{
public static void Initialize()
{
AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
AppDomain.CurrentDomain.ProcessExit += CurrentDomain_ProcessExit;
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<bool> e)
{
Logger.SetEnable(LogLevel.Debug, e.Value);
}
private static void ReloadEnableStub(object sender, ReactiveEventArgs<bool> e)
{
Logger.SetEnable(LogLevel.Stub, e.Value);
}
private static void ReloadEnableInfo(object sender, ReactiveEventArgs<bool> e)
{
Logger.SetEnable(LogLevel.Info, e.Value);
}
private static void ReloadEnableWarning(object sender, ReactiveEventArgs<bool> e)
{
Logger.SetEnable(LogLevel.Warning, e.Value);
}
private static void ReloadEnableError(object sender, ReactiveEventArgs<bool> e)
{
Logger.SetEnable(LogLevel.Error, e.Value);
}
private static void ReloadEnableGuest(object sender, ReactiveEventArgs<bool> e)
{
Logger.SetEnable(LogLevel.Guest, e.Value);
}
private static void ReloadEnableFsAccessLog(object sender, ReactiveEventArgs<bool> e)
{
Logger.SetEnable(LogLevel.AccessLog, e.Value);
}
private static void ReloadFilteredClasses(object sender, ReactiveEventArgs<LogClass[]> e)
{
bool noFilter = e.Value.Length == 0;
foreach (var logClass in EnumExtensions.GetValues<LogClass>())
{
Logger.SetEnable(logClass, noFilter);
}
foreach (var logClass in e.Value)
{
Logger.SetEnable(logClass, true);
}
}
private static void ReloadFileLogger(object sender, ReactiveEventArgs<bool> e)
{
if (e.Value != e.OldValue)
{
if (e.Value)
{
Logger.AddTarget(new AsyncLogTargetWrapper(
new FileLogTarget(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Ryujinx.log"), "file"),
1000,
AsyncLogTargetOverflowAction.Block
));
}
else
{
Logger.RemoveTarget("file");
}
}
}
private static void CurrentDomain_ProcessExit(object sender, EventArgs e)
{
Logger.Shutdown();
}
private static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
{
var exception = e.ExceptionObject as Exception;
Logger.PrintError(LogClass.Emulation, $"Unhandled exception caught: {exception}");
if (e.IsTerminating)
{
Logger.Shutdown();
}
}
}
}

View file

@ -1,5 +1,6 @@
using Gtk;
using Ryujinx.Common.Logging;
using Ryujinx.Configuration;
using Ryujinx.Profiler;
using Ryujinx.Ui;
using System;
@ -16,9 +17,20 @@ namespace Ryujinx
string systemPath = Environment.GetEnvironmentVariable("Path", EnvironmentVariableTarget.Machine);
Environment.SetEnvironmentVariable("Path", $"{Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "bin")};{systemPath}");
AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
AppDomain.CurrentDomain.ProcessExit += CurrentDomain_ProcessExit;
GLib.ExceptionManager.UnhandledException += Glib_UnhandledException;
GLib.ExceptionManager.UnhandledException += Glib_UnhandledException;
// Initialize the configuration
ConfigurationState.Initialize();
// Initialize the logger system
LoggerModule.Initialize();
// Initialize Discord integration
DiscordIntegrationModule.Initialize();
// Now load the configuration as the other subsystem are now registered
ConfigurationFileFormat configurationFileFormat = ConfigurationFileFormat.Load(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Config.json"));
ConfigurationState.Instance.Load(configurationFileFormat);
Profile.Initialize();
@ -42,23 +54,6 @@ namespace Ryujinx
Application.Run();
}
private static void CurrentDomain_ProcessExit(object sender, EventArgs e)
{
Logger.Shutdown();
}
private static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
{
Exception exception = e.ExceptionObject as Exception;
Logger.PrintError(LogClass.Emulation, $"Unhandled exception caught: {exception}");
if (e.IsTerminating)
{
Logger.Shutdown();
}
}
private static void Glib_UnhandledException(GLib.UnhandledExceptionArgs e)
{
Exception exception = e.ExceptionObject as Exception;

View file

@ -1,10 +1,10 @@
using OpenTK;
using OpenTK.Graphics;
using OpenTK.Input;
using Ryujinx.Configuration;
using Ryujinx.Graphics.Gal;
using Ryujinx.HLE;
using Ryujinx.HLE.Input;
using Ryujinx.Profiler.UI;
using System;
using System.Threading;
@ -162,16 +162,16 @@ namespace Ryujinx.Ui
#endif
// Normal Input
currentHotkeyButtons = Configuration.Instance.KeyboardControls.GetHotkeyButtons(keyboard);
currentButton = Configuration.Instance.KeyboardControls.GetButtons(keyboard);
currentHotkeyButtons = ConfigurationState.Instance.Hid.KeyboardControls.Value.GetHotkeyButtons(keyboard);
currentButton = ConfigurationState.Instance.Hid.KeyboardControls.Value.GetButtons(keyboard);
if (Configuration.Instance.EnableKeyboard)
if (ConfigurationState.Instance.Hid.EnableKeyboard)
{
hidKeyboard = Configuration.Instance.KeyboardControls.GetKeysDown(keyboard);
hidKeyboard = ConfigurationState.Instance.Hid.KeyboardControls.Value.GetKeysDown(keyboard);
}
(leftJoystickDx, leftJoystickDy) = Configuration.Instance.KeyboardControls.GetLeftStick(keyboard);
(rightJoystickDx, rightJoystickDy) = Configuration.Instance.KeyboardControls.GetRightStick(keyboard);
(leftJoystickDx, leftJoystickDy) = ConfigurationState.Instance.Hid.KeyboardControls.Value.GetLeftStick(keyboard);
(rightJoystickDx, rightJoystickDy) = ConfigurationState.Instance.Hid.KeyboardControls.Value.GetRightStick(keyboard);
}
if (!hidKeyboard.HasValue)
@ -183,17 +183,17 @@ namespace Ryujinx.Ui
};
}
currentButton |= Configuration.Instance.JoystickControls.GetButtons();
currentButton |= ConfigurationState.Instance.Hid.JoystickControls.Value.GetButtons();
// Keyboard has priority stick-wise
if (leftJoystickDx == 0 && leftJoystickDy == 0)
{
(leftJoystickDx, leftJoystickDy) = Configuration.Instance.JoystickControls.GetLeftStick();
(leftJoystickDx, leftJoystickDy) = ConfigurationState.Instance.Hid.JoystickControls.Value.GetLeftStick();
}
if (rightJoystickDx == 0 && rightJoystickDy == 0)
{
(rightJoystickDx, rightJoystickDy) = Configuration.Instance.JoystickControls.GetRightStick();
(rightJoystickDx, rightJoystickDy) = ConfigurationState.Instance.Hid.JoystickControls.Value.GetRightStick();
}
leftJoystick = new JoystickPosition
@ -269,7 +269,7 @@ namespace Ryujinx.Ui
_device.Hid.SetTouchPoints();
}
if (Configuration.Instance.EnableKeyboard && hidKeyboard.HasValue)
if (ConfigurationState.Instance.Hid.EnableKeyboard && hidKeyboard.HasValue)
{
_device.Hid.WriteKeyboard(hidKeyboard.Value);
}

View file

@ -1,24 +1,25 @@
using DiscordRPC;
using Gtk;
using JsonPrettyPrinterPlus;
using Ryujinx.Audio;
using Ryujinx.Common.Logging;
using Ryujinx.Graphics.Gal.OpenGL;
using Ryujinx.Graphics.Gal;
using Ryujinx.HLE.FileSystem;
using Ryujinx.Graphics.Gal.OpenGL;
using Ryujinx.Profiler;
using System;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.Threading;
using Utf8Json;
using Utf8Json.Resolvers;
using Ryujinx.Configuration;
using System.Diagnostics;
using OpenTK.Input;
using Ryujinx.Ui.Input;
using GUI = Gtk.Builder.ObjectAttribute;
using System.Threading.Tasks;
using Utf8Json;
using JsonPrettyPrinterPlus;
using Utf8Json.Resolvers;
using Ryujinx.HLE.FileSystem;
namespace Ryujinx.Ui
{
@ -50,12 +51,6 @@ namespace Ryujinx.Ui
private static TreeView _treeView;
public static bool DiscordIntegrationEnabled { get; set; }
public static DiscordRpcClient DiscordClient;
public static RichPresence DiscordPresence;
#pragma warning disable CS0649
#pragma warning disable IDE0044
[GUI] Window _mainWin;
@ -71,7 +66,9 @@ namespace Ryujinx.Ui
[GUI] CheckMenuItem _fileExtToggle;
[GUI] CheckMenuItem _fileSizeToggle;
[GUI] CheckMenuItem _pathToggle;
[GUI] Box _box;
[GUI] TreeView _gameTable;
[GUI] GLArea _glScreen;
[GUI] Label _progressLabel;
[GUI] LevelBar _progressBar;
#pragma warning restore CS0649
@ -91,60 +88,39 @@ namespace Ryujinx.Ui
_audioOut = InitializeAudioEngine();
_device = new HLE.Switch(_renderer, _audioOut);
// TODO: Initialization and dispose of HLE.Switch when starting/stoping emulation.
_device = InitializeSwitchInstance();
_treeView = _gameTable;
Configuration.Load(System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Config.json"));
Configuration.InitialConfigure(_device);
ApplyTheme();
if (DiscordIntegrationEnabled)
{
DiscordClient = new DiscordRpcClient("568815339807309834");
DiscordPresence = new RichPresence
{
Assets = new Assets
{
LargeImageKey = "ryujinx",
LargeImageText = "Ryujinx is an emulator for the Nintendo Switch"
},
Details = "Main Menu",
State = "Idling",
Timestamps = new Timestamps(DateTime.UtcNow)
};
DiscordClient.Initialize();
DiscordClient.SetPresence(DiscordPresence);
}
_mainWin.Icon = new Gdk.Pixbuf(Assembly.GetExecutingAssembly(), "Ryujinx.Ui.assets.Icon.png");
_stopEmulation.Sensitive = false;
if (SwitchSettings.SwitchConfig.GuiColumns.FavColumn) { _favToggle.Active = true; }
if (SwitchSettings.SwitchConfig.GuiColumns.IconColumn) { _iconToggle.Active = true; }
if (SwitchSettings.SwitchConfig.GuiColumns.AppColumn) { _appToggle.Active = true; }
if (SwitchSettings.SwitchConfig.GuiColumns.DevColumn) { _developerToggle.Active = true; }
if (SwitchSettings.SwitchConfig.GuiColumns.VersionColumn) { _versionToggle.Active = true; }
if (SwitchSettings.SwitchConfig.GuiColumns.TimePlayedColumn) { _timePlayedToggle.Active = true; }
if (SwitchSettings.SwitchConfig.GuiColumns.LastPlayedColumn) { _lastPlayedToggle.Active = true; }
if (SwitchSettings.SwitchConfig.GuiColumns.FileExtColumn) { _fileExtToggle.Active = true; }
if (SwitchSettings.SwitchConfig.GuiColumns.FileSizeColumn) { _fileSizeToggle.Active = true; }
if (SwitchSettings.SwitchConfig.GuiColumns.PathColumn) { _pathToggle.Active = true; }
if (ConfigurationState.Instance.Ui.GuiColumns.FavColumn) { _favToggle.Active = true; }
if (ConfigurationState.Instance.Ui.GuiColumns.IconColumn) { _iconToggle.Active = true; }
if (ConfigurationState.Instance.Ui.GuiColumns.AppColumn) { _appToggle.Active = true; }
if (ConfigurationState.Instance.Ui.GuiColumns.DevColumn) { _developerToggle.Active = true; }
if (ConfigurationState.Instance.Ui.GuiColumns.VersionColumn) { _versionToggle.Active = true; }
if (ConfigurationState.Instance.Ui.GuiColumns.TimePlayedColumn) { _timePlayedToggle.Active = true; }
if (ConfigurationState.Instance.Ui.GuiColumns.LastPlayedColumn) { _lastPlayedToggle.Active = true; }
if (ConfigurationState.Instance.Ui.GuiColumns.FileExtColumn) { _fileExtToggle.Active = true; }
if (ConfigurationState.Instance.Ui.GuiColumns.FileSizeColumn) { _fileSizeToggle.Active = true; }
if (ConfigurationState.Instance.Ui.GuiColumns.PathColumn) { _pathToggle.Active = true; }
_gameTable.Model = _tableStore = new ListStore(
typeof(bool),
typeof(Gdk.Pixbuf),
typeof(string),
typeof(string),
typeof(string),
typeof(string),
typeof(string),
typeof(string),
typeof(string),
typeof(bool),
typeof(Gdk.Pixbuf),
typeof(string),
typeof(string),
typeof(string),
typeof(string),
typeof(string),
typeof(string),
typeof(string),
typeof(string));
_tableStore.SetSortFunc(5, TimePlayedSort);
_tableStore.SetSortFunc(6, LastPlayedSort);
_tableStore.SetSortFunc(8, FileSizeSort);
@ -158,22 +134,22 @@ namespace Ryujinx.Ui
internal static void ApplyTheme()
{
if (!SwitchSettings.SwitchConfig.EnableCustomTheme)
if (!ConfigurationState.Instance.Ui.EnableCustomTheme)
{
return;
}
if (File.Exists(SwitchSettings.SwitchConfig.CustomThemePath) && (System.IO.Path.GetExtension(SwitchSettings.SwitchConfig.CustomThemePath) == ".css"))
if (File.Exists(ConfigurationState.Instance.Ui.CustomThemePath) && (System.IO.Path.GetExtension(ConfigurationState.Instance.Ui.CustomThemePath) == ".css"))
{
CssProvider cssProvider = new CssProvider();
cssProvider.LoadFromPath(SwitchSettings.SwitchConfig.CustomThemePath);
cssProvider.LoadFromPath(ConfigurationState.Instance.Ui.CustomThemePath);
StyleContext.AddProviderForScreen(Gdk.Screen.Default, cssProvider, 800);
}
else
{
Logger.PrintWarning(LogClass.Application, $"The \"custom_theme_path\" section in \"Config.json\" contains an invalid path: \"{SwitchSettings.SwitchConfig.CustomThemePath}\".");
Logger.PrintWarning(LogClass.Application, $"The \"custom_theme_path\" section in \"Config.json\" contains an invalid path: \"{ConfigurationState.Instance.Ui.CustomThemePath}\".");
}
}
@ -187,16 +163,16 @@ namespace Ryujinx.Ui
CellRendererToggle favToggle = new CellRendererToggle();
favToggle.Toggled += FavToggle_Toggled;
if (SwitchSettings.SwitchConfig.GuiColumns.FavColumn) { _gameTable.AppendColumn("Fav", favToggle, "active", 0); }
if (SwitchSettings.SwitchConfig.GuiColumns.IconColumn) { _gameTable.AppendColumn("Icon", new CellRendererPixbuf(), "pixbuf", 1); }
if (SwitchSettings.SwitchConfig.GuiColumns.AppColumn) { _gameTable.AppendColumn("Application", new CellRendererText(), "text", 2); }
if (SwitchSettings.SwitchConfig.GuiColumns.DevColumn) { _gameTable.AppendColumn("Developer", new CellRendererText(), "text", 3); }
if (SwitchSettings.SwitchConfig.GuiColumns.VersionColumn) { _gameTable.AppendColumn("Version", new CellRendererText(), "text", 4); }
if (SwitchSettings.SwitchConfig.GuiColumns.TimePlayedColumn) { _gameTable.AppendColumn("Time Played", new CellRendererText(), "text", 5); }
if (SwitchSettings.SwitchConfig.GuiColumns.LastPlayedColumn) { _gameTable.AppendColumn("Last Played", new CellRendererText(), "text", 6); }
if (SwitchSettings.SwitchConfig.GuiColumns.FileExtColumn) { _gameTable.AppendColumn("File Ext", new CellRendererText(), "text", 7); }
if (SwitchSettings.SwitchConfig.GuiColumns.FileSizeColumn) { _gameTable.AppendColumn("File Size", new CellRendererText(), "text", 8); }
if (SwitchSettings.SwitchConfig.GuiColumns.PathColumn) { _gameTable.AppendColumn("Path", new CellRendererText(), "text", 9); }
if (ConfigurationState.Instance.Ui.GuiColumns.FavColumn) { _gameTable.AppendColumn("Fav", favToggle, "active", 0); }
if (ConfigurationState.Instance.Ui.GuiColumns.IconColumn) { _gameTable.AppendColumn("Icon", new CellRendererPixbuf(), "pixbuf", 1); }
if (ConfigurationState.Instance.Ui.GuiColumns.AppColumn) { _gameTable.AppendColumn("Application", new CellRendererText(), "text", 2); }
if (ConfigurationState.Instance.Ui.GuiColumns.DevColumn) { _gameTable.AppendColumn("Developer", new CellRendererText(), "text", 3); }
if (ConfigurationState.Instance.Ui.GuiColumns.VersionColumn) { _gameTable.AppendColumn("Version", new CellRendererText(), "text", 4); }
if (ConfigurationState.Instance.Ui.GuiColumns.TimePlayedColumn) { _gameTable.AppendColumn("Time Played", new CellRendererText(), "text", 5); }
if (ConfigurationState.Instance.Ui.GuiColumns.LastPlayedColumn) { _gameTable.AppendColumn("Last Played", new CellRendererText(), "text", 6); }
if (ConfigurationState.Instance.Ui.GuiColumns.FileExtColumn) { _gameTable.AppendColumn("File Ext", new CellRendererText(), "text", 7); }
if (ConfigurationState.Instance.Ui.GuiColumns.FileSizeColumn) { _gameTable.AppendColumn("File Size", new CellRendererText(), "text", 8); }
if (ConfigurationState.Instance.Ui.GuiColumns.PathColumn) { _gameTable.AppendColumn("Path", new CellRendererText(), "text", 9); }
foreach (TreeViewColumn column in _gameTable.Columns)
{
@ -211,15 +187,24 @@ namespace Ryujinx.Ui
else if (column.Title == "Path") { _pathColumn = column; }
}
if (SwitchSettings.SwitchConfig.GuiColumns.FavColumn) { _favColumn.SortColumnId = 0; }
if (SwitchSettings.SwitchConfig.GuiColumns.IconColumn) { _appColumn.SortColumnId = 2; }
if (SwitchSettings.SwitchConfig.GuiColumns.AppColumn) { _devColumn.SortColumnId = 3; }
if (SwitchSettings.SwitchConfig.GuiColumns.DevColumn) { _versionColumn.SortColumnId = 4; }
if (SwitchSettings.SwitchConfig.GuiColumns.TimePlayedColumn) { _timePlayedColumn.SortColumnId = 5; }
if (SwitchSettings.SwitchConfig.GuiColumns.LastPlayedColumn) { _lastPlayedColumn.SortColumnId = 6; }
if (SwitchSettings.SwitchConfig.GuiColumns.FileExtColumn) { _fileExtColumn.SortColumnId = 7; }
if (SwitchSettings.SwitchConfig.GuiColumns.FileSizeColumn) { _fileSizeColumn.SortColumnId = 8; }
if (SwitchSettings.SwitchConfig.GuiColumns.PathColumn) { _pathColumn.SortColumnId = 9; }
if (ConfigurationState.Instance.Ui.GuiColumns.FavColumn) { _favColumn.SortColumnId = 0; }
if (ConfigurationState.Instance.Ui.GuiColumns.IconColumn) { _appColumn.SortColumnId = 2; }
if (ConfigurationState.Instance.Ui.GuiColumns.AppColumn) { _devColumn.SortColumnId = 3; }
if (ConfigurationState.Instance.Ui.GuiColumns.DevColumn) { _versionColumn.SortColumnId = 4; }
if (ConfigurationState.Instance.Ui.GuiColumns.TimePlayedColumn) { _timePlayedColumn.SortColumnId = 5; }
if (ConfigurationState.Instance.Ui.GuiColumns.LastPlayedColumn) { _lastPlayedColumn.SortColumnId = 6; }
if (ConfigurationState.Instance.Ui.GuiColumns.FileExtColumn) { _fileExtColumn.SortColumnId = 7; }
if (ConfigurationState.Instance.Ui.GuiColumns.FileSizeColumn) { _fileSizeColumn.SortColumnId = 8; }
if (ConfigurationState.Instance.Ui.GuiColumns.PathColumn) { _pathColumn.SortColumnId = 9; }
}
private HLE.Switch InitializeSwitchInstance()
{
HLE.Switch instance = new HLE.Switch(_renderer, _audioOut);
instance.Initialize(ConfigurationState.Instance.System.Language, ConfigurationState.Instance.System.EnableMulticoreScheduling, ConfigurationState.Instance.System.EnableDockedMode, ConfigurationState.Instance.Graphics.EnableVsync, ConfigurationState.Instance.System.EnableFsIntegrityChecks, ConfigurationState.Instance.System.FsGlobalAccessLogMode, ConfigurationState.Instance.System.IgnoreMissingServices);
return instance;
}
internal static async Task UpdateGameTable()
@ -233,7 +218,7 @@ namespace Ryujinx.Ui
_tableStore.Clear();
await Task.Run(() => ApplicationLibrary.LoadApplications(SwitchSettings.SwitchConfig.GameDirs, _device.System.KeySet, _device.System.State.DesiredTitleLanguage));
await Task.Run(() => ApplicationLibrary.LoadApplications(ConfigurationState.Instance.Ui.GameDirs, _device.System.KeySet, _device.System.State.DesiredTitleLanguage));
_updatingGameTable = false;
}
@ -248,6 +233,9 @@ namespace Ryujinx.Ui
{
Logger.RestartTime();
// TODO: move this somewhere else + reloadable
GraphicsConfig.ShadersDumpPath = ConfigurationState.Instance.Graphics.ShadersDumpPath;
if (Directory.Exists(path))
{
string[] romFsFiles = Directory.GetFiles(path, "*.istorage");
@ -313,40 +301,7 @@ namespace Ryujinx.Ui
_gameLoaded = true;
_stopEmulation.Sensitive = true;
if (DiscordIntegrationEnabled)
{
if (File.ReadAllLines(System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "RPsupported.dat")).Contains(_device.System.TitleId))
{
DiscordPresence.Assets.LargeImageKey = _device.System.TitleId;
}
string state = _device.System.TitleId;
if (state == null)
{
state = "Ryujinx";
}
else
{
state = state.ToUpper();
}
string details = "Idling";
if (_device.System.TitleName != null)
{
details = $"Playing {_device.System.TitleName}";
}
DiscordPresence.Details = details;
DiscordPresence.State = state;
DiscordPresence.Assets.LargeImageText = _device.System.TitleName;
DiscordPresence.Assets.SmallImageKey = "ryujinx";
DiscordPresence.Assets.SmallImageText = "Ryujinx is an emulator for the Nintendo Switch";
DiscordPresence.Timestamps = new Timestamps(DateTime.UtcNow);
DiscordClient.SetPresence(DiscordPresence);
}
DiscordIntegrationModule.SwitchToPlayingState(_device.System.TitleId, _device.System.TitleName);
string metadataFolder = System.IO.Path.Combine(new VirtualFileSystem().GetBasePath(), "games", _device.System.TitleId, "gui");
string metadataFile = System.IO.Path.Combine(metadataFolder, "metadata.json");
@ -382,10 +337,26 @@ namespace Ryujinx.Ui
}
}
// TODO: Make HLE.Switch handle the state itself + reloading
private static void ConfigureHid()
{
NpadController controller = ConfigurationState.Instance.Hid.JoystickControls.Value;
if (controller.Enabled)
{
if (!Joystick.GetState(controller.Index).IsConnected)
{
controller.SetEnabled(false);
}
}
_device.Hid.InitializePrimaryController(ConfigurationState.Instance.Hid.ControllerType);
_device.Hid.InitializeKeyboard();
}
private static void CreateGameWindow()
{
Configuration.ConfigureHid(_device, SwitchSettings.SwitchConfig);
ConfigureHid();
using (_screen = new GlScreen(_device, _renderer))
{
_screen.MainLoop();
@ -394,6 +365,7 @@ namespace Ryujinx.Ui
}
}
private static void End()
{
if (_ending)
@ -444,7 +416,6 @@ namespace Ryujinx.Ui
Profile.FinishProfiling();
_device.Dispose();
_audioOut.Dispose();
DiscordClient?.Dispose();
Logger.Shutdown();
Environment.Exit(0);
}
@ -527,7 +498,7 @@ namespace Ryujinx.Ui
private void Row_Activated(object sender, RowActivatedArgs args)
{
_tableStore.GetIter(out TreeIter treeIter, new TreePath(args.Path.ToString()));
string path = (string)_tableStore.GetValue(treeIter, 9);
string path = (string)_tableStore.GetValue(treeIter, 8);
LoadApplication(path);
}
@ -607,13 +578,13 @@ namespace Ryujinx.Ui
private void Settings_Pressed(object sender, EventArgs args)
{
SwitchSettings settingsWin = new SwitchSettings(_device);
SwitchSettings settingsWin = new SwitchSettings();
settingsWin.Show();
}
private void Update_Pressed(object sender, EventArgs args)
private void Update_Pressed(object o, EventArgs args)
{
string ryuUpdater = System.IO.Path.Combine(new VirtualFileSystem().GetBasePath(), "RyuUpdater.exe");
string ryuUpdater = System.IO.Path.Combine(new VirtualFileSystem().GetBasePath(), "RyuFS", "RyuUpdater.exe");
try
{
@ -633,121 +604,81 @@ namespace Ryujinx.Ui
private void Fav_Toggled(object sender, EventArgs args)
{
GuiColumns updatedColumns = SwitchSettings.SwitchConfig.GuiColumns;
updatedColumns.FavColumn = _favToggle.Active;
SwitchSettings.SwitchConfig.GuiColumns = updatedColumns;
Configuration.SaveConfig(SwitchSettings.SwitchConfig, System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Config.json"));
ConfigurationState.Instance.Ui.GuiColumns.FavColumn.Value = _favToggle.Active;
SaveConfig();
UpdateColumns();
}
private void Icon_Toggled(object sender, EventArgs args)
{
GuiColumns updatedColumns = SwitchSettings.SwitchConfig.GuiColumns;
updatedColumns.IconColumn = _iconToggle.Active;
SwitchSettings.SwitchConfig.GuiColumns = updatedColumns;
Configuration.SaveConfig(SwitchSettings.SwitchConfig, System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Config.json"));
ConfigurationState.Instance.Ui.GuiColumns.IconColumn.Value = _iconToggle.Active;
SaveConfig();
UpdateColumns();
}
private void Title_Toggled(object sender, EventArgs args)
{
GuiColumns updatedColumns = SwitchSettings.SwitchConfig.GuiColumns;
updatedColumns.AppColumn = _appToggle.Active;
SwitchSettings.SwitchConfig.GuiColumns = updatedColumns;
Configuration.SaveConfig(SwitchSettings.SwitchConfig, System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Config.json"));
ConfigurationState.Instance.Ui.GuiColumns.AppColumn.Value = _appToggle.Active;
SaveConfig();
UpdateColumns();
}
private void Developer_Toggled(object sender, EventArgs args)
{
GuiColumns updatedColumns = SwitchSettings.SwitchConfig.GuiColumns;
updatedColumns.DevColumn = _developerToggle.Active;
SwitchSettings.SwitchConfig.GuiColumns = updatedColumns;
Configuration.SaveConfig(SwitchSettings.SwitchConfig, System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Config.json"));
ConfigurationState.Instance.Ui.GuiColumns.DevColumn.Value = _developerToggle.Active;
SaveConfig();
UpdateColumns();
}
private void Version_Toggled(object sender, EventArgs args)
{
GuiColumns updatedColumns = SwitchSettings.SwitchConfig.GuiColumns;
updatedColumns.VersionColumn = _versionToggle.Active;
SwitchSettings.SwitchConfig.GuiColumns = updatedColumns;
Configuration.SaveConfig(SwitchSettings.SwitchConfig, System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Config.json"));
ConfigurationState.Instance.Ui.GuiColumns.VersionColumn.Value = _versionToggle.Active;
SaveConfig();
UpdateColumns();
}
private void TimePlayed_Toggled(object sender, EventArgs args)
{
GuiColumns updatedColumns = SwitchSettings.SwitchConfig.GuiColumns;
updatedColumns.TimePlayedColumn = _timePlayedToggle.Active;
SwitchSettings.SwitchConfig.GuiColumns = updatedColumns;
Configuration.SaveConfig(SwitchSettings.SwitchConfig, System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Config.json"));
ConfigurationState.Instance.Ui.GuiColumns.TimePlayedColumn.Value = _timePlayedToggle.Active;
SaveConfig();
UpdateColumns();
}
private void LastPlayed_Toggled(object sender, EventArgs args)
{
GuiColumns updatedColumns = SwitchSettings.SwitchConfig.GuiColumns;
updatedColumns.LastPlayedColumn = _lastPlayedToggle.Active;
SwitchSettings.SwitchConfig.GuiColumns = updatedColumns;
Configuration.SaveConfig(SwitchSettings.SwitchConfig, System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Config.json"));
ConfigurationState.Instance.Ui.GuiColumns.LastPlayedColumn.Value = _lastPlayedToggle.Active;
SaveConfig();
UpdateColumns();
}
private void FileExt_Toggled(object sender, EventArgs args)
{
GuiColumns updatedColumns = SwitchSettings.SwitchConfig.GuiColumns;
updatedColumns.FileExtColumn = _fileExtToggle.Active;
SwitchSettings.SwitchConfig.GuiColumns = updatedColumns;
Configuration.SaveConfig(SwitchSettings.SwitchConfig, System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Config.json"));
ConfigurationState.Instance.Ui.GuiColumns.FileExtColumn.Value = _fileExtToggle.Active;
SaveConfig();
UpdateColumns();
}
private void FileSize_Toggled(object sender, EventArgs args)
private void FileSize_Toggled(object o, EventArgs args)
{
GuiColumns updatedColumns = SwitchSettings.SwitchConfig.GuiColumns;
updatedColumns.FileSizeColumn = _fileSizeToggle.Active;
SwitchSettings.SwitchConfig.GuiColumns = updatedColumns;
Configuration.SaveConfig(SwitchSettings.SwitchConfig, System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Config.json"));
ConfigurationState.Instance.Ui.GuiColumns.FileSizeColumn.Value = _fileSizeToggle.Active;
SaveConfig();
UpdateColumns();
}
private void Path_Toggled(object sender, EventArgs args)
private void Path_Toggled(object o, EventArgs args)
{
GuiColumns updatedColumns = SwitchSettings.SwitchConfig.GuiColumns;
updatedColumns.PathColumn = _pathToggle.Active;
SwitchSettings.SwitchConfig.GuiColumns = updatedColumns;
Configuration.SaveConfig(SwitchSettings.SwitchConfig, System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Config.json"));
ConfigurationState.Instance.Ui.GuiColumns.PathColumn.Value = _pathToggle.Active;
SaveConfig();
UpdateColumns();
}
@ -865,5 +796,10 @@ namespace Ryujinx.Ui
return 0;
}
}
public static void SaveConfig()
{
ConfigurationState.Instance.ToFileFormat().SaveConfig(System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Config.json"));
}
}
}

View file

@ -7,6 +7,8 @@ using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using Ryujinx.Configuration;
using Ryujinx.Common.Logging;
using GUI = Gtk.Builder.ObjectAttribute;
@ -14,10 +16,6 @@ namespace Ryujinx.Ui
{
public class SwitchSettings : Window
{
internal static Configuration SwitchConfig { get; set; }
private readonly HLE.Switch _device;
private static ListStore _gameDirsBoxStore;
private static bool _listeningForKeypress;
@ -83,16 +81,12 @@ namespace Ryujinx.Ui
#pragma warning restore CS0649
#pragma warning restore IDE0044
public static void ConfigureSettings(Configuration instance) { SwitchConfig = instance; }
public SwitchSettings() : this(new Builder("Ryujinx.Ui.SwitchSettings.glade")) { }
public SwitchSettings(HLE.Switch device) : this(new Builder("Ryujinx.Ui.SwitchSettings.glade"), device) { }
private SwitchSettings(Builder builder, HLE.Switch device) : base(builder.GetObject("_settingsWin").Handle)
private SwitchSettings(Builder builder) : base(builder.GetObject("_settingsWin").Handle)
{
builder.Autoconnect(this);
_device = device;
_settingsWin.Icon = new Gdk.Pixbuf(Assembly.GetExecutingAssembly(), "Ryujinx.Ui.assets.Icon.png");
_controller1Image.Pixbuf = new Gdk.Pixbuf(Assembly.GetExecutingAssembly(), "Ryujinx.Ui.assets.JoyCon.png", 500, 500);
@ -124,60 +118,60 @@ namespace Ryujinx.Ui
_controller1Type.Changed += (sender, args) => Controller_Changed(sender, args, _controller1Type.ActiveId, _controller1Image);
//Setup Currents
if (SwitchConfig.EnableFileLog) _fileLogToggle.Click();
if (SwitchConfig.LoggingEnableError) _errorLogToggle.Click();
if (SwitchConfig.LoggingEnableWarn) _warningLogToggle.Click();
if (SwitchConfig.LoggingEnableInfo) _infoLogToggle.Click();
if (SwitchConfig.LoggingEnableStub) _stubLogToggle.Click();
if (SwitchConfig.LoggingEnableDebug) _debugLogToggle.Click();
if (SwitchConfig.LoggingEnableGuest) _guestLogToggle.Click();
if (SwitchConfig.LoggingEnableFsAccessLog) _fsAccessLogToggle.Click();
if (SwitchConfig.DockedMode) _dockedModeToggle.Click();
if (SwitchConfig.EnableDiscordIntegration) _discordToggle.Click();
if (SwitchConfig.EnableVsync) _vSyncToggle.Click();
if (SwitchConfig.EnableMulticoreScheduling) _multiSchedToggle.Click();
if (SwitchConfig.EnableFsIntegrityChecks) _fsicToggle.Click();
if (SwitchConfig.IgnoreMissingServices) _ignoreToggle.Click();
if (SwitchConfig.EnableKeyboard) _directKeyboardAccess.Click();
if (SwitchConfig.EnableCustomTheme) _custThemeToggle.Click();
if (ConfigurationState.Instance.Logger.EnableFileLog) { _fileLogToggle.Click(); }
if (ConfigurationState.Instance.Logger.EnableError) { _errorLogToggle.Click(); }
if (ConfigurationState.Instance.Logger.EnableWarn) { _warningLogToggle.Click(); }
if (ConfigurationState.Instance.Logger.EnableInfo) { _infoLogToggle.Click(); }
if (ConfigurationState.Instance.Logger.EnableStub) { _stubLogToggle.Click(); }
if (ConfigurationState.Instance.Logger.EnableDebug) { _debugLogToggle.Click(); }
if (ConfigurationState.Instance.Logger.EnableGuest) { _guestLogToggle.Click(); }
if (ConfigurationState.Instance.Logger.EnableFsAccessLog) { _fsAccessLogToggle.Click(); }
if (ConfigurationState.Instance.System.EnableDockedMode) { _dockedModeToggle.Click(); }
if (ConfigurationState.Instance.EnableDiscordIntegration) { _discordToggle.Click(); }
if (ConfigurationState.Instance.Graphics.EnableVsync) { _vSyncToggle.Click(); }
if (ConfigurationState.Instance.System.EnableMulticoreScheduling) { _multiSchedToggle.Click(); }
if (ConfigurationState.Instance.System.EnableFsIntegrityChecks) { _fsicToggle.Click(); }
if (ConfigurationState.Instance.System.IgnoreMissingServices) { _ignoreToggle.Click(); }
if (ConfigurationState.Instance.Hid.EnableKeyboard) { _directKeyboardAccess.Click(); }
if (ConfigurationState.Instance.Ui.EnableCustomTheme) { _custThemeToggle.Click(); }
_systemLanguageSelect.SetActiveId(SwitchConfig.SystemLanguage.ToString());
_controller1Type .SetActiveId(SwitchConfig.ControllerType.ToString());
_systemLanguageSelect.SetActiveId(ConfigurationState.Instance.System.Language.Value.ToString());
_controller1Type .SetActiveId(ConfigurationState.Instance.Hid.ControllerType.Value.ToString());
Controller_Changed(null, null, _controller1Type.ActiveId, _controller1Image);
_lStickUp1.Label = SwitchConfig.KeyboardControls.LeftJoycon.StickUp.ToString();
_lStickDown1.Label = SwitchConfig.KeyboardControls.LeftJoycon.StickDown.ToString();
_lStickLeft1.Label = SwitchConfig.KeyboardControls.LeftJoycon.StickLeft.ToString();
_lStickRight1.Label = SwitchConfig.KeyboardControls.LeftJoycon.StickRight.ToString();
_lStickButton1.Label = SwitchConfig.KeyboardControls.LeftJoycon.StickButton.ToString();
_dpadUp1.Label = SwitchConfig.KeyboardControls.LeftJoycon.DPadUp.ToString();
_dpadDown1.Label = SwitchConfig.KeyboardControls.LeftJoycon.DPadDown.ToString();
_dpadLeft1.Label = SwitchConfig.KeyboardControls.LeftJoycon.DPadLeft.ToString();
_dpadRight1.Label = SwitchConfig.KeyboardControls.LeftJoycon.DPadRight.ToString();
_minus1.Label = SwitchConfig.KeyboardControls.LeftJoycon.ButtonMinus.ToString();
_l1.Label = SwitchConfig.KeyboardControls.LeftJoycon.ButtonL.ToString();
_zL1.Label = SwitchConfig.KeyboardControls.LeftJoycon.ButtonZl.ToString();
_rStickUp1.Label = SwitchConfig.KeyboardControls.RightJoycon.StickUp.ToString();
_rStickDown1.Label = SwitchConfig.KeyboardControls.RightJoycon.StickDown.ToString();
_rStickLeft1.Label = SwitchConfig.KeyboardControls.RightJoycon.StickLeft.ToString();
_rStickRight1.Label = SwitchConfig.KeyboardControls.RightJoycon.StickRight.ToString();
_rStickButton1.Label = SwitchConfig.KeyboardControls.RightJoycon.StickButton.ToString();
_a1.Label = SwitchConfig.KeyboardControls.RightJoycon.ButtonA.ToString();
_b1.Label = SwitchConfig.KeyboardControls.RightJoycon.ButtonB.ToString();
_x1.Label = SwitchConfig.KeyboardControls.RightJoycon.ButtonX.ToString();
_y1.Label = SwitchConfig.KeyboardControls.RightJoycon.ButtonY.ToString();
_plus1.Label = SwitchConfig.KeyboardControls.RightJoycon.ButtonPlus.ToString();
_r1.Label = SwitchConfig.KeyboardControls.RightJoycon.ButtonR.ToString();
_zR1.Label = SwitchConfig.KeyboardControls.RightJoycon.ButtonZr.ToString();
_lStickUp1.Label = ConfigurationState.Instance.Hid.KeyboardControls.Value.LeftJoycon.StickUp.ToString();
_lStickDown1.Label = ConfigurationState.Instance.Hid.KeyboardControls.Value.LeftJoycon.StickDown.ToString();
_lStickLeft1.Label = ConfigurationState.Instance.Hid.KeyboardControls.Value.LeftJoycon.StickLeft.ToString();
_lStickRight1.Label = ConfigurationState.Instance.Hid.KeyboardControls.Value.LeftJoycon.StickRight.ToString();
_lStickButton1.Label = ConfigurationState.Instance.Hid.KeyboardControls.Value.LeftJoycon.StickButton.ToString();
_dpadUp1.Label = ConfigurationState.Instance.Hid.KeyboardControls.Value.LeftJoycon.DPadUp.ToString();
_dpadDown1.Label = ConfigurationState.Instance.Hid.KeyboardControls.Value.LeftJoycon.DPadDown.ToString();
_dpadLeft1.Label = ConfigurationState.Instance.Hid.KeyboardControls.Value.LeftJoycon.DPadLeft.ToString();
_dpadRight1.Label = ConfigurationState.Instance.Hid.KeyboardControls.Value.LeftJoycon.DPadRight.ToString();
_minus1.Label = ConfigurationState.Instance.Hid.KeyboardControls.Value.LeftJoycon.ButtonMinus.ToString();
_l1.Label = ConfigurationState.Instance.Hid.KeyboardControls.Value.LeftJoycon.ButtonL.ToString();
_zL1.Label = ConfigurationState.Instance.Hid.KeyboardControls.Value.LeftJoycon.ButtonZl.ToString();
_rStickUp1.Label = ConfigurationState.Instance.Hid.KeyboardControls.Value.RightJoycon.StickUp.ToString();
_rStickDown1.Label = ConfigurationState.Instance.Hid.KeyboardControls.Value.RightJoycon.StickDown.ToString();
_rStickLeft1.Label = ConfigurationState.Instance.Hid.KeyboardControls.Value.RightJoycon.StickLeft.ToString();
_rStickRight1.Label = ConfigurationState.Instance.Hid.KeyboardControls.Value.RightJoycon.StickRight.ToString();
_rStickButton1.Label = ConfigurationState.Instance.Hid.KeyboardControls.Value.RightJoycon.StickButton.ToString();
_a1.Label = ConfigurationState.Instance.Hid.KeyboardControls.Value.RightJoycon.ButtonA.ToString();
_b1.Label = ConfigurationState.Instance.Hid.KeyboardControls.Value.RightJoycon.ButtonB.ToString();
_x1.Label = ConfigurationState.Instance.Hid.KeyboardControls.Value.RightJoycon.ButtonX.ToString();
_y1.Label = ConfigurationState.Instance.Hid.KeyboardControls.Value.RightJoycon.ButtonY.ToString();
_plus1.Label = ConfigurationState.Instance.Hid.KeyboardControls.Value.RightJoycon.ButtonPlus.ToString();
_r1.Label = ConfigurationState.Instance.Hid.KeyboardControls.Value.RightJoycon.ButtonR.ToString();
_zR1.Label = ConfigurationState.Instance.Hid.KeyboardControls.Value.RightJoycon.ButtonZr.ToString();
_custThemePath.Buffer.Text = SwitchConfig.CustomThemePath;
_graphicsShadersDumpPath.Buffer.Text = SwitchConfig.GraphicsShadersDumpPath;
_fsLogSpinAdjustment.Value = SwitchConfig.FsGlobalAccessLogMode;
_custThemePath.Buffer.Text = ConfigurationState.Instance.Ui.CustomThemePath;
_graphicsShadersDumpPath.Buffer.Text = ConfigurationState.Instance.Graphics.ShadersDumpPath;
_fsLogSpinAdjustment.Value = ConfigurationState.Instance.System.FsGlobalAccessLogMode;
_gameDirsBox.AppendColumn("", new CellRendererText(), "text", 0);
_gameDirsBoxStore = new ListStore(typeof(string));
_gameDirsBox.Model = _gameDirsBoxStore;
foreach (string gameDir in SwitchConfig.GameDirs)
foreach (string gameDir in ConfigurationState.Instance.Ui.GameDirs.Value)
{
_gameDirsBoxStore.AppendValues(gameDir);
}
@ -325,24 +319,24 @@ namespace Ryujinx.Ui
_gameDirsBoxStore.IterNext(ref treeIter);
}
SwitchConfig.LoggingEnableError = _errorLogToggle.Active;
SwitchConfig.LoggingEnableWarn = _warningLogToggle.Active;
SwitchConfig.LoggingEnableInfo = _infoLogToggle.Active;
SwitchConfig.LoggingEnableStub = _stubLogToggle.Active;
SwitchConfig.LoggingEnableDebug = _debugLogToggle.Active;
SwitchConfig.LoggingEnableGuest = _guestLogToggle.Active;
SwitchConfig.LoggingEnableFsAccessLog = _fsAccessLogToggle.Active;
SwitchConfig.EnableFileLog = _fileLogToggle.Active;
SwitchConfig.DockedMode = _dockedModeToggle.Active;
SwitchConfig.EnableDiscordIntegration = _discordToggle.Active;
SwitchConfig.EnableVsync = _vSyncToggle.Active;
SwitchConfig.EnableMulticoreScheduling = _multiSchedToggle.Active;
SwitchConfig.EnableFsIntegrityChecks = _fsicToggle.Active;
SwitchConfig.IgnoreMissingServices = _ignoreToggle.Active;
SwitchConfig.EnableKeyboard = _directKeyboardAccess.Active;
SwitchConfig.EnableCustomTheme = _custThemeToggle.Active;
ConfigurationState.Instance.Logger.EnableError.Value = _errorLogToggle.Active;
ConfigurationState.Instance.Logger.EnableWarn.Value = _warningLogToggle.Active;
ConfigurationState.Instance.Logger.EnableInfo.Value = _infoLogToggle.Active;
ConfigurationState.Instance.Logger.EnableStub.Value = _stubLogToggle.Active;
ConfigurationState.Instance.Logger.EnableDebug.Value = _debugLogToggle.Active;
ConfigurationState.Instance.Logger.EnableGuest.Value = _guestLogToggle.Active;
ConfigurationState.Instance.Logger.EnableFsAccessLog.Value = _fsAccessLogToggle.Active;
ConfigurationState.Instance.Logger.EnableFileLog.Value = _fileLogToggle.Active;
ConfigurationState.Instance.System.EnableDockedMode.Value = _dockedModeToggle.Active;
ConfigurationState.Instance.EnableDiscordIntegration.Value = _discordToggle.Active;
ConfigurationState.Instance.Graphics.EnableVsync.Value = _vSyncToggle.Active;
ConfigurationState.Instance.System.EnableMulticoreScheduling.Value = _multiSchedToggle.Active;
ConfigurationState.Instance.System.EnableFsIntegrityChecks.Value = _fsicToggle.Active;
ConfigurationState.Instance.System.IgnoreMissingServices.Value = _ignoreToggle.Active;
ConfigurationState.Instance.Hid.EnableKeyboard.Value = _directKeyboardAccess.Active;
ConfigurationState.Instance.Ui.EnableCustomTheme.Value = _custThemeToggle.Active;
SwitchConfig.KeyboardControls.LeftJoycon = new NpadKeyboardLeft()
ConfigurationState.Instance.Hid.KeyboardControls.Value.LeftJoycon = new NpadKeyboardLeft()
{
StickUp = (OpenTK.Input.Key)Enum.Parse(typeof(OpenTK.Input.Key), _lStickUp1.Label),
StickDown = (OpenTK.Input.Key)Enum.Parse(typeof(OpenTK.Input.Key), _lStickDown1.Label),
@ -358,7 +352,7 @@ namespace Ryujinx.Ui
ButtonZl = (OpenTK.Input.Key)Enum.Parse(typeof(OpenTK.Input.Key), _zL1.Label),
};
SwitchConfig.KeyboardControls.RightJoycon = new NpadKeyboardRight()
ConfigurationState.Instance.Hid.KeyboardControls.Value.RightJoycon = new NpadKeyboardRight()
{
StickUp = (OpenTK.Input.Key)Enum.Parse(typeof(OpenTK.Input.Key), _rStickUp1.Label),
StickDown = (OpenTK.Input.Key)Enum.Parse(typeof(OpenTK.Input.Key), _rStickDown1.Label),
@ -374,16 +368,14 @@ namespace Ryujinx.Ui
ButtonZr = (OpenTK.Input.Key)Enum.Parse(typeof(OpenTK.Input.Key), _zR1.Label),
};
SwitchConfig.SystemLanguage = (SystemLanguage)Enum.Parse(typeof(SystemLanguage), _systemLanguageSelect.ActiveId);
SwitchConfig.ControllerType = (ControllerStatus)Enum.Parse(typeof(ControllerStatus), _controller1Type.ActiveId);
SwitchConfig.CustomThemePath = _custThemePath.Buffer.Text;
SwitchConfig.GraphicsShadersDumpPath = _graphicsShadersDumpPath.Buffer.Text;
SwitchConfig.GameDirs = gameDirs;
SwitchConfig.FsGlobalAccessLogMode = (int)_fsLogSpinAdjustment.Value;
Configuration.SaveConfig(SwitchConfig, System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Config.json"));
Configuration.Configure(_device, SwitchConfig);
ConfigurationState.Instance.System.Language.Value = (SystemLanguage)Enum.Parse(typeof(SystemLanguage), _systemLanguageSelect.ActiveId);
ConfigurationState.Instance.Hid.ControllerType.Value = (ControllerStatus)Enum.Parse(typeof(ControllerStatus), _controller1Type.ActiveId);
ConfigurationState.Instance.Ui.CustomThemePath.Value = _custThemePath.Buffer.Text;
ConfigurationState.Instance.Graphics.ShadersDumpPath.Value = _graphicsShadersDumpPath.Buffer.Text;
ConfigurationState.Instance.Ui.GameDirs.Value = gameDirs;
ConfigurationState.Instance.System.FsGlobalAccessLogMode.Value = (int)_fsLogSpinAdjustment.Value;
MainWindow.SaveConfig();
MainWindow.ApplyTheme();
#pragma warning disable CS4014
MainWindow.UpdateGameTable();