Logger and Configuration Refactoring (#573)
* Logging: Refactor log targets into Ryujinx.Common * Logger: Implement JSON Log Target * Logger: Optimize Console/File logging targets Implement a simple ObjectPool to pool up StringBuilders to avoid causing excessive GCing of gen1/2 items when large amounts of log entries are being generated. We can also pre-determine the async overflow action at initialization time, allowing for an easy optimization in the message enqueue function, avoiding a number of comparisons. * Logger: Implement LogFormatters * Config: Refactor configuration file and loading * Config: Rename to .jsonc to avoid highlighting issues in VSC and GitHub * Resolve style nits * Config: Resolve incorrect default key binding * Config: Also update key binding default in schema * Tidy up namespace imports * Config: Update CONFIG.md to reflect new Config file
This commit is contained in:
parent
a694420d11
commit
d306115750
31 changed files with 1844 additions and 691 deletions
206
CONFIG.md
206
CONFIG.md
|
@ -1,123 +1,124 @@
|
||||||
## Config File
|
## Config File
|
||||||
|
|
||||||
`Ryujinx.conf` should be present in executable folder (It's an *.ini file) following this format:
|
`Config.jsonc` should be present in executable folder. The available settings follow:
|
||||||
|
|
||||||
- `Logging_Enable_Info` *(bool)*
|
- `graphics_shaders_dump_path` *(string)*
|
||||||
|
|
||||||
|
Dump shaders in local directory (e.g. `C:\ShaderDumps`)
|
||||||
|
|
||||||
|
- `logging_enable_debug` *(bool)*
|
||||||
|
|
||||||
|
Enable the Debug Logging.
|
||||||
|
|
||||||
|
- `logging_enable_stub` *(bool)*
|
||||||
|
|
||||||
|
Enable the Trace Logging.
|
||||||
|
|
||||||
|
- `logging_enable_info` *(bool)*
|
||||||
|
|
||||||
Enable the Informations Logging.
|
Enable the Informations Logging.
|
||||||
|
|
||||||
- `Logging_Enable_Trace` *(bool)*
|
- `logging_enable_warn` *(bool)*
|
||||||
|
|
||||||
Enable the Trace Logging (Enabled in Debug recommended).
|
Enable the Warning Logging.
|
||||||
|
|
||||||
- `Logging_Enable_Debug` *(bool)*
|
- `logging_enable_error` *(bool)*
|
||||||
|
|
||||||
Enable the Debug Logging (Enabled in Debug recommended).
|
Enable the Error Logging.
|
||||||
|
|
||||||
- `Logging_Enable_Warn` *(bool)*
|
- `enable_file_log` *(bool)*
|
||||||
|
|
||||||
Enable the Warning Logging (Enabled in Debug recommended).
|
|
||||||
|
|
||||||
- `Logging_Enable_Error` *(bool)*
|
|
||||||
|
|
||||||
Enable the Error Logging (Enabled in Debug recommended).
|
|
||||||
|
|
||||||
- `Logging_Enable_Fatal` *(bool)*
|
|
||||||
|
|
||||||
Enable the Fatal Logging (Enabled in Debug recommended).
|
|
||||||
|
|
||||||
- `Logging_Enable_Ipc` *(bool)*
|
|
||||||
|
|
||||||
Enable the Ipc Message Logging.
|
|
||||||
|
|
||||||
- `Logging_Enable_LogFile` *(bool)*
|
|
||||||
|
|
||||||
Enable writing the logging inside a Ryujinx.log file.
|
Enable writing the logging inside a Ryujinx.log file.
|
||||||
|
|
||||||
- `GamePad_Index` *(int)*
|
- `system_language` *(string)*
|
||||||
|
|
||||||
The index of the Controller Device.
|
Change System Language, [System Language list](https://gist.github.com/HorrorTroll/b6e4a88d774c3c9b3bdf54d79a7ca43b)
|
||||||
|
|
||||||
- `GamePad_Deadzone` *(float)*
|
- `docked_mode` *(bool)*
|
||||||
|
|
||||||
The deadzone of both analog sticks on the Controller.
|
Enable or Disable Docked Mode
|
||||||
|
|
||||||
- `GamePad_Enable` *(bool)*
|
- `enable_vsync` *(bool)*
|
||||||
|
|
||||||
|
Enable or Disable Game Vsync
|
||||||
|
|
||||||
|
- `enable_multicore_scheduling` *(bool)*
|
||||||
|
|
||||||
|
Enable or Disable Multi-core scheduling of threads
|
||||||
|
|
||||||
|
- `enable_fs_integrity_checks` *(bool)*
|
||||||
|
|
||||||
|
Enable integrity checks on Switch content files
|
||||||
|
|
||||||
|
- `controller_type` *(string)*
|
||||||
|
|
||||||
|
The primary controller's type.
|
||||||
|
Supported Values: `Handheld`, `ProController`, `NpadPair`, `NpadLeft`, `NpadRight`
|
||||||
|
|
||||||
|
- `keyboard_controls` *(object)* :
|
||||||
|
- `left_joycon` *(object)* :
|
||||||
|
Left JoyCon Keyboard Bindings
|
||||||
|
- `stick_up` *(string)*
|
||||||
|
- `stick_down` *(string)*
|
||||||
|
- `stick_left` *(string)*
|
||||||
|
- `stick_right` *(string)*
|
||||||
|
- `stick_button` *(string)*
|
||||||
|
- `dpad_up` *(string)*
|
||||||
|
- `dpad_down` *(string)*
|
||||||
|
- `dpad_left` *(string)*
|
||||||
|
- `dpad_right` *(string)*
|
||||||
|
- `button_minus` *(string)*
|
||||||
|
- `button_l` *(string)*
|
||||||
|
- `button_zl` *(string)*
|
||||||
|
- `right_joycon` *(object)* :
|
||||||
|
Right JoyCon Keyboard Bindings
|
||||||
|
- `stick_up` *(string)*
|
||||||
|
- `stick_down` *(string)*
|
||||||
|
- `stick_left` *(string)*
|
||||||
|
- `stick_right` *(string)*
|
||||||
|
- `stick_button` *(string)*
|
||||||
|
- `button_a` *(string)*
|
||||||
|
- `button_b` *(string)*
|
||||||
|
- `button_x` *(string)*
|
||||||
|
- `button_y` *(string)*
|
||||||
|
- `button_plus` *(string)*
|
||||||
|
- `button_r` *(string)*
|
||||||
|
- `button_zr` *(string)*
|
||||||
|
|
||||||
|
- `gamepad_controls` *(object)* :
|
||||||
|
- `enabled` *(bool)*
|
||||||
Whether or not to enable Controller Support.
|
Whether or not to enable Controller Support.
|
||||||
|
- `index` *(int)*
|
||||||
|
The index of the Controller Device.
|
||||||
|
- `deadzone` *(number)*
|
||||||
|
The deadzone of both analog sticks on the Controller.
|
||||||
|
- `trigger_threshold` *(number)*
|
||||||
|
The value of how pressed down each trigger has to be in order to register a button press
|
||||||
|
- `left_joycon` *(object)* :
|
||||||
|
Left JoyCon Controller Bindings
|
||||||
|
- `stick` *(string)*
|
||||||
|
- `stick_button` *(string)*
|
||||||
|
- `dpad_up` *(string)*
|
||||||
|
- `dpad_down` *(string)*
|
||||||
|
- `dpad_left` *(string)*
|
||||||
|
- `dpad_right` *(string)*
|
||||||
|
- `button_minus` *(string)*
|
||||||
|
- `button_l` *(string)*
|
||||||
|
- `button_zl` *(string)*
|
||||||
|
- `right_joycon` *(object)* :
|
||||||
|
Right JoyCon Controller Bindings
|
||||||
|
- `stick` *(string)*
|
||||||
|
- `stick_button` *(string)*
|
||||||
|
- `button_a` *(string)*
|
||||||
|
- `button_b` *(string)*
|
||||||
|
- `button_x` *(string)*
|
||||||
|
- `button_y` *(string)*
|
||||||
|
- `button_plus` *(string)*
|
||||||
|
- `button_r` *(string)*
|
||||||
|
- `button_zr` *(string)*
|
||||||
|
|
||||||
- `Controls_Left_JoyConKeyboard_XX` *(int)*
|
### Default Mapping
|
||||||
```
|
#### Controller
|
||||||
Controls_Left_JoyConKeyboard_Stick_Up (int)
|
|
||||||
Controls_Left_JoyConKeyboard_Stick_Down (int)
|
|
||||||
Controls_Left_JoyConKeyboard_Stick_Left (int)
|
|
||||||
Controls_Left_JoyConKeyboard_Stick_Right (int)
|
|
||||||
Controls_Left_JoyConKeyboard_Stick_Button (int)
|
|
||||||
Controls_Left_JoyConKeyboard_DPad_Up (int)
|
|
||||||
Controls_Left_JoyConKeyboard_DPad_Down (int)
|
|
||||||
Controls_Left_JoyConKeyboard_DPad_Left (int)
|
|
||||||
Controls_Left_JoyConKeyboard_DPad_Right (int)
|
|
||||||
Controls_Left_JoyConKeyboard_Button_Minus (int)
|
|
||||||
Controls_Left_JoyConKeyboard_Button_L (int)
|
|
||||||
Controls_Left_JoyConKeyboard_Button_ZL (int)
|
|
||||||
```
|
|
||||||
|
|
||||||
Keys of the Left Emulated Joycon, the values depend of the [OpenTK Enum Keys](https://github.com/opentk/opentk/blob/develop/src/OpenTK/Input/Key.cs).
|
|
||||||
|
|
||||||
OpenTK use a QWERTY layout, so pay attention if you use another Keyboard Layout.
|
|
||||||
|
|
||||||
Ex: `Controls_Left_JoyConKeyboard_Button_Minus = 52` > Tab key (All Layout).
|
|
||||||
|
|
||||||
- `Controls_Right_JoyConKeyboard_XX` *(int)*
|
|
||||||
```
|
|
||||||
Controls_Right_JoyConKeyboard_Stick_Up (int)
|
|
||||||
Controls_Right_JoyConKeyboard_Stick_Down (int)
|
|
||||||
Controls_Right_JoyConKeyboard_Stick_Left (int)
|
|
||||||
Controls_Right_JoyConKeyboard_Stick_Right (int)
|
|
||||||
Controls_Right_JoyConKeyboard_Stick_Button (int)
|
|
||||||
Controls_Right_JoyConKeyboard_Button_A (int)
|
|
||||||
Controls_Right_JoyConKeyboard_Button_B (int)
|
|
||||||
Controls_Right_JoyConKeyboard_Button_X (int)
|
|
||||||
Controls_Right_JoyConKeyboard_Button_Y (int)
|
|
||||||
Controls_Right_JoyConKeyboard_Button_Plus (int)
|
|
||||||
Controls_Right_JoyConKeyboard_Button_R (int)
|
|
||||||
Controls_Right_JoyConKeyboard_Button_ZR (int)
|
|
||||||
```
|
|
||||||
|
|
||||||
Keys of the right Emulated Joycon, the values depend of the [OpenTK Enum Keys](https://github.com/opentk/opentk/blob/develop/src/OpenTK/Input/Key.cs).
|
|
||||||
|
|
||||||
OpenTK use a QWERTY layout, so pay attention if you use another Keyboard Layout.
|
|
||||||
|
|
||||||
Ex: `Controls_Right_JoyConKeyboard_Button_A = 83` > A key (QWERTY Layout) / Q key (AZERTY Layout).
|
|
||||||
|
|
||||||
- `Controls_Left_JoyConController_XX` *(String)*
|
|
||||||
```
|
|
||||||
Controls_Left_JoyConController_Stick (String)
|
|
||||||
Controls_Left_JoyConController_Stick_Button (String)
|
|
||||||
Controls_Left_JoyConController_DPad_Up (String)
|
|
||||||
Controls_Left_JoyConController_DPad_Down (String)
|
|
||||||
Controls_Left_JoyConController_DPad_Left (String)
|
|
||||||
Controls_Left_JoyConController_DPad_Right (String)
|
|
||||||
Controls_Left_JoyConController_Button_Minus (String)
|
|
||||||
Controls_Left_JoyConController_Button_L (String)
|
|
||||||
Controls_Left_JoyConController_Button_ZL (String)
|
|
||||||
```
|
|
||||||
|
|
||||||
- `Controls_Right_JoyConController_XX` *(String)*
|
|
||||||
```
|
|
||||||
Controls_Right_JoyConController_Stick (String)
|
|
||||||
Controls_Right_JoyConController_Stick_Button (String)
|
|
||||||
Controls_Right_JoyConController_Button_A (String)
|
|
||||||
Controls_Right_JoyConController_Button_B (String)
|
|
||||||
Controls_Right_JoyConController_Button_X (String)
|
|
||||||
Controls_Right_JoyConController_Button_Y (String)
|
|
||||||
Controls_Right_JoyConController_Button_Plus (String)
|
|
||||||
Controls_Right_JoyConController_Button_R (String)
|
|
||||||
Controls_Right_JoyConController_Button_ZR (String)
|
|
||||||
```
|
|
||||||
|
|
||||||
- Default Mapping
|
|
||||||
- Controller
|
|
||||||
- Left Joycon:
|
- Left Joycon:
|
||||||
- Analog Stick = Left Analog Stick
|
- Analog Stick = Left Analog Stick
|
||||||
- DPad Up = DPad Up
|
- DPad Up = DPad Up
|
||||||
|
@ -137,7 +138,8 @@
|
||||||
- Plus = Start / Options
|
- Plus = Start / Options
|
||||||
- R = Right Shoulder Button
|
- R = Right Shoulder Button
|
||||||
- ZR = Right Trigger
|
- ZR = Right Trigger
|
||||||
- Keyboard
|
|
||||||
|
#### Keyboard
|
||||||
- Left Joycon:
|
- Left Joycon:
|
||||||
- Stick Up = W
|
- Stick Up = W
|
||||||
- Stick Down = S
|
- Stick Down = S
|
||||||
|
@ -166,7 +168,7 @@
|
||||||
- R = U
|
- R = U
|
||||||
- ZR = O
|
- ZR = O
|
||||||
|
|
||||||
- Valid Button Mappings
|
### Valid Button Mappings
|
||||||
- A = The A / Cross Button
|
- A = The A / Cross Button
|
||||||
- B = The B / Circle Button
|
- B = The B / Circle Button
|
||||||
- X = The X / Square Button
|
- X = The X / Square Button
|
||||||
|
|
|
@ -18,7 +18,7 @@ or just drag'n'drop the homebrew *.NRO / *.NSO or the game *.NSP / *.XCI on the
|
||||||
|
|
||||||
- Controller Input is supported, see [CONFIG.md](CONFIG.md)
|
- Controller Input is supported, see [CONFIG.md](CONFIG.md)
|
||||||
|
|
||||||
- Config File: `Ryujinx.conf` should be present in executable folder.
|
- Config File: `Config.jsonc` should be present in executable folder.
|
||||||
For more information [you can go here](CONFIG.md).
|
For more information [you can go here](CONFIG.md).
|
||||||
|
|
||||||
**Help**
|
**Help**
|
||||||
|
|
|
@ -1,14 +1,13 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using System.Text;
|
|
||||||
|
|
||||||
namespace Ryujinx.Common
|
namespace Ryujinx.Common
|
||||||
{
|
{
|
||||||
public static class StructIOExtension
|
public static class BinaryReaderExtensions
|
||||||
{
|
{
|
||||||
public unsafe static T ReadStruct<T>(this BinaryReader reader) where T : struct
|
public unsafe static T ReadStruct<T>(this BinaryReader reader)
|
||||||
|
where T : struct
|
||||||
{
|
{
|
||||||
int size = Marshal.SizeOf<T>();
|
int size = Marshal.SizeOf<T>();
|
||||||
|
|
||||||
|
@ -20,7 +19,8 @@ namespace Ryujinx.Common
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public unsafe static void WriteStruct<T>(this BinaryWriter writer, T value) where T : struct
|
public unsafe static void WriteStruct<T>(this BinaryWriter writer, T value)
|
||||||
|
where T : struct
|
||||||
{
|
{
|
||||||
long size = Marshal.SizeOf<T>();
|
long size = Marshal.SizeOf<T>();
|
||||||
|
|
12
Ryujinx.Common/Extensions/EnumExtensions.cs
Normal file
12
Ryujinx.Common/Extensions/EnumExtensions.cs
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Ryujinx.Common
|
||||||
|
{
|
||||||
|
public static class EnumExtensions
|
||||||
|
{
|
||||||
|
public static T[] GetValues<T>()
|
||||||
|
{
|
||||||
|
return (T[])Enum.GetValues(typeof(T));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
53
Ryujinx.Common/Logging/Formatters/DefaultLogFormatter.cs
Normal file
53
Ryujinx.Common/Logging/Formatters/DefaultLogFormatter.cs
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace Ryujinx.Common.Logging
|
||||||
|
{
|
||||||
|
internal class DefaultLogFormatter : ILogFormatter
|
||||||
|
{
|
||||||
|
private static readonly ObjectPool<StringBuilder> _stringBuilderPool = SharedPools.Default<StringBuilder>();
|
||||||
|
|
||||||
|
public string Format(LogEventArgs args)
|
||||||
|
{
|
||||||
|
StringBuilder sb = _stringBuilderPool.Allocate();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
sb.Clear();
|
||||||
|
|
||||||
|
sb.AppendFormat(@"{0:hh\:mm\:ss\.fff}", args.Time);
|
||||||
|
sb.Append(" | ");
|
||||||
|
sb.AppendFormat("{0:d4}", args.ThreadId);
|
||||||
|
sb.Append(' ');
|
||||||
|
sb.Append(args.Message);
|
||||||
|
|
||||||
|
if (args.Data != null)
|
||||||
|
{
|
||||||
|
PropertyInfo[] props = args.Data.GetType().GetProperties();
|
||||||
|
|
||||||
|
sb.Append(' ');
|
||||||
|
|
||||||
|
foreach (var prop in props)
|
||||||
|
{
|
||||||
|
sb.Append(prop.Name);
|
||||||
|
sb.Append(": ");
|
||||||
|
sb.Append(prop.GetValue(args.Data));
|
||||||
|
sb.Append(" - ");
|
||||||
|
}
|
||||||
|
|
||||||
|
// We remove the final '-' from the string
|
||||||
|
if (props.Length > 0)
|
||||||
|
{
|
||||||
|
sb.Remove(sb.Length - 3, 3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return sb.ToString();
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
_stringBuilderPool.Release(sb);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
7
Ryujinx.Common/Logging/Formatters/ILogFormatter.cs
Normal file
7
Ryujinx.Common/Logging/Formatters/ILogFormatter.cs
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
namespace Ryujinx.Common.Logging
|
||||||
|
{
|
||||||
|
interface ILogFormatter
|
||||||
|
{
|
||||||
|
string Format(LogEventArgs args);
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,6 +2,7 @@ namespace Ryujinx.Common.Logging
|
||||||
{
|
{
|
||||||
public enum LogClass
|
public enum LogClass
|
||||||
{
|
{
|
||||||
|
Application,
|
||||||
Audio,
|
Audio,
|
||||||
Cpu,
|
Cpu,
|
||||||
Font,
|
Font,
|
||||||
|
|
|
@ -1,8 +1,7 @@
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Reflection;
|
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
using System.Text;
|
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
|
|
||||||
namespace Ryujinx.Common.Logging
|
namespace Ryujinx.Common.Logging
|
||||||
|
@ -14,9 +13,9 @@ namespace Ryujinx.Common.Logging
|
||||||
private static readonly bool[] m_EnabledLevels;
|
private static readonly bool[] m_EnabledLevels;
|
||||||
private static readonly bool[] m_EnabledClasses;
|
private static readonly bool[] m_EnabledClasses;
|
||||||
|
|
||||||
public static event EventHandler<LogEventArgs> Updated;
|
private static readonly List<ILogTarget> m_LogTargets;
|
||||||
|
|
||||||
public static bool EnableFileLog { get; set; }
|
public static event EventHandler<LogEventArgs> Updated;
|
||||||
|
|
||||||
static Logger()
|
static Logger()
|
||||||
{
|
{
|
||||||
|
@ -33,9 +32,30 @@ namespace Ryujinx.Common.Logging
|
||||||
m_EnabledClasses[index] = true;
|
m_EnabledClasses[index] = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_LogTargets = new List<ILogTarget>();
|
||||||
|
|
||||||
m_Time = Stopwatch.StartNew();
|
m_Time = Stopwatch.StartNew();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void AddTarget(ILogTarget target)
|
||||||
|
{
|
||||||
|
m_LogTargets.Add(target);
|
||||||
|
|
||||||
|
Updated += target.Log;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Shutdown()
|
||||||
|
{
|
||||||
|
Updated = null;
|
||||||
|
|
||||||
|
foreach(var target in m_LogTargets)
|
||||||
|
{
|
||||||
|
target.Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
m_LogTargets.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
public static void SetEnable(LogLevel logLevel, bool enabled)
|
public static void SetEnable(LogLevel logLevel, bool enabled)
|
||||||
{
|
{
|
||||||
m_EnabledLevels[(int)logLevel] = enabled;
|
m_EnabledLevels[(int)logLevel] = enabled;
|
||||||
|
|
76
Ryujinx.Common/Logging/Targets/AsyncLogTargetWrapper.cs
Normal file
76
Ryujinx.Common/Logging/Targets/AsyncLogTargetWrapper.cs
Normal file
|
@ -0,0 +1,76 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Concurrent;
|
||||||
|
using System.Threading;
|
||||||
|
|
||||||
|
namespace Ryujinx.Common.Logging
|
||||||
|
{
|
||||||
|
public enum AsyncLogTargetOverflowAction
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Block until there's more room in the queue
|
||||||
|
/// </summary>
|
||||||
|
Block = 0,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Discard the overflowing item
|
||||||
|
/// </summary>
|
||||||
|
Discard = 1
|
||||||
|
}
|
||||||
|
|
||||||
|
public class AsyncLogTargetWrapper : ILogTarget
|
||||||
|
{
|
||||||
|
private ILogTarget _target;
|
||||||
|
|
||||||
|
private Thread _messageThread;
|
||||||
|
|
||||||
|
private BlockingCollection<LogEventArgs> _messageQueue;
|
||||||
|
|
||||||
|
private readonly int _overflowTimeout;
|
||||||
|
|
||||||
|
public AsyncLogTargetWrapper(ILogTarget target)
|
||||||
|
: this(target, -1, AsyncLogTargetOverflowAction.Block)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
public AsyncLogTargetWrapper(ILogTarget target, int queueLimit, AsyncLogTargetOverflowAction overflowAction)
|
||||||
|
{
|
||||||
|
_target = target;
|
||||||
|
_messageQueue = new BlockingCollection<LogEventArgs>(queueLimit);
|
||||||
|
_overflowTimeout = overflowAction == AsyncLogTargetOverflowAction.Block ? -1 : 0;
|
||||||
|
|
||||||
|
_messageThread = new Thread(() => {
|
||||||
|
while (!_messageQueue.IsCompleted)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
_target.Log(this, _messageQueue.Take());
|
||||||
|
}
|
||||||
|
catch (InvalidOperationException)
|
||||||
|
{
|
||||||
|
// IOE means that Take() was called on a completed collection.
|
||||||
|
// Some other thread can call CompleteAdding after we pass the
|
||||||
|
// IsCompleted check but before we call Take.
|
||||||
|
// We can simply catch the exception since the loop will break
|
||||||
|
// on the next iteration.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
_messageThread.IsBackground = true;
|
||||||
|
_messageThread.Start();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Log(object sender, LogEventArgs e)
|
||||||
|
{
|
||||||
|
if (!_messageQueue.IsAddingCompleted)
|
||||||
|
{
|
||||||
|
_messageQueue.TryAdd(e, _overflowTimeout);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
_messageQueue.CompleteAdding();
|
||||||
|
_messageThread.Join();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
48
Ryujinx.Common/Logging/Targets/ConsoleLogTarget.cs
Normal file
48
Ryujinx.Common/Logging/Targets/ConsoleLogTarget.cs
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Concurrent;
|
||||||
|
|
||||||
|
namespace Ryujinx.Common.Logging
|
||||||
|
{
|
||||||
|
public class ConsoleLogTarget : ILogTarget
|
||||||
|
{
|
||||||
|
private static readonly ConcurrentDictionary<LogLevel, ConsoleColor> _logColors;
|
||||||
|
|
||||||
|
private readonly ILogFormatter _formatter;
|
||||||
|
|
||||||
|
static ConsoleLogTarget()
|
||||||
|
{
|
||||||
|
_logColors = new ConcurrentDictionary<LogLevel, ConsoleColor> {
|
||||||
|
[ LogLevel.Stub ] = ConsoleColor.DarkGray,
|
||||||
|
[ LogLevel.Info ] = ConsoleColor.White,
|
||||||
|
[ LogLevel.Warning ] = ConsoleColor.Yellow,
|
||||||
|
[ LogLevel.Error ] = ConsoleColor.Red
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public ConsoleLogTarget()
|
||||||
|
{
|
||||||
|
_formatter = new DefaultLogFormatter();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Log(object sender, LogEventArgs args)
|
||||||
|
{
|
||||||
|
if (_logColors.TryGetValue(args.Level, out ConsoleColor color))
|
||||||
|
{
|
||||||
|
Console.ForegroundColor = color;
|
||||||
|
|
||||||
|
Console.WriteLine(_formatter.Format(args));
|
||||||
|
|
||||||
|
Console.ResetColor();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Console.WriteLine(_formatter.Format(args));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
Console.ResetColor();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
36
Ryujinx.Common/Logging/Targets/FileLogTarget.cs
Normal file
36
Ryujinx.Common/Logging/Targets/FileLogTarget.cs
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
using System.IO;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace Ryujinx.Common.Logging
|
||||||
|
{
|
||||||
|
public class FileLogTarget : ILogTarget
|
||||||
|
{
|
||||||
|
private static readonly ObjectPool<StringBuilder> _stringBuilderPool = SharedPools.Default<StringBuilder>();
|
||||||
|
|
||||||
|
private readonly StreamWriter _logWriter;
|
||||||
|
private readonly ILogFormatter _formatter;
|
||||||
|
|
||||||
|
public FileLogTarget(string path)
|
||||||
|
: this(path, FileShare.Read, FileMode.Append)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
public FileLogTarget(string path, FileShare fileShare, FileMode fileMode)
|
||||||
|
{
|
||||||
|
_logWriter = new StreamWriter(File.Open(path, fileMode, FileAccess.Write, fileShare));
|
||||||
|
_formatter = new DefaultLogFormatter();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Log(object sender, LogEventArgs args)
|
||||||
|
{
|
||||||
|
_logWriter.WriteLine(_formatter.Format(args));
|
||||||
|
_logWriter.Flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
_logWriter.WriteLine("---- End of Log ----");
|
||||||
|
_logWriter.Flush();
|
||||||
|
_logWriter.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
9
Ryujinx.Common/Logging/Targets/ILogTarget.cs
Normal file
9
Ryujinx.Common/Logging/Targets/ILogTarget.cs
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Ryujinx.Common.Logging
|
||||||
|
{
|
||||||
|
public interface ILogTarget : IDisposable
|
||||||
|
{
|
||||||
|
void Log(object sender, LogEventArgs args);
|
||||||
|
}
|
||||||
|
}
|
35
Ryujinx.Common/Logging/Targets/JsonLogTarget.cs
Normal file
35
Ryujinx.Common/Logging/Targets/JsonLogTarget.cs
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
using System.IO;
|
||||||
|
using Utf8Json;
|
||||||
|
|
||||||
|
namespace Ryujinx.Common.Logging
|
||||||
|
{
|
||||||
|
public class JsonLogTarget : ILogTarget
|
||||||
|
{
|
||||||
|
private Stream _stream;
|
||||||
|
private bool _leaveOpen;
|
||||||
|
|
||||||
|
public JsonLogTarget(Stream stream)
|
||||||
|
{
|
||||||
|
_stream = stream;
|
||||||
|
}
|
||||||
|
|
||||||
|
public JsonLogTarget(Stream stream, bool leaveOpen)
|
||||||
|
{
|
||||||
|
_stream = stream;
|
||||||
|
_leaveOpen = leaveOpen;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Log(object sender, LogEventArgs e)
|
||||||
|
{
|
||||||
|
JsonSerializer.Serialize(_stream, e);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
if (!_leaveOpen)
|
||||||
|
{
|
||||||
|
_stream.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
75
Ryujinx.Common/Pools/ObjectPool.cs
Normal file
75
Ryujinx.Common/Pools/ObjectPool.cs
Normal file
|
@ -0,0 +1,75 @@
|
||||||
|
using System;
|
||||||
|
using System.Threading;
|
||||||
|
|
||||||
|
namespace Ryujinx.Common
|
||||||
|
{
|
||||||
|
public class ObjectPool<T>
|
||||||
|
where T : class
|
||||||
|
{
|
||||||
|
private T _firstItem;
|
||||||
|
private readonly T[] _items;
|
||||||
|
|
||||||
|
private readonly Func<T> _factory;
|
||||||
|
|
||||||
|
public ObjectPool(Func<T> factory, int size)
|
||||||
|
{
|
||||||
|
_items = new T[size - 1];
|
||||||
|
_factory = factory;
|
||||||
|
}
|
||||||
|
|
||||||
|
public T Allocate()
|
||||||
|
{
|
||||||
|
var instance = _firstItem;
|
||||||
|
|
||||||
|
if (instance == null || instance != Interlocked.CompareExchange(ref _firstItem, null, instance))
|
||||||
|
{
|
||||||
|
instance = AllocateInternal();
|
||||||
|
}
|
||||||
|
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
private T AllocateInternal()
|
||||||
|
{
|
||||||
|
var items = _items;
|
||||||
|
|
||||||
|
for (int i = 0; i < items.Length; i++)
|
||||||
|
{
|
||||||
|
var instance = items[i];
|
||||||
|
|
||||||
|
if (instance != null && instance == Interlocked.CompareExchange(ref items[i], null, instance))
|
||||||
|
{
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return _factory();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Release(T obj)
|
||||||
|
{
|
||||||
|
if (_firstItem == null)
|
||||||
|
{
|
||||||
|
_firstItem = obj;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ReleaseInternal(obj);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ReleaseInternal(T obj)
|
||||||
|
{
|
||||||
|
var items = _items;
|
||||||
|
|
||||||
|
for (int i = 0; i < items.Length; i++)
|
||||||
|
{
|
||||||
|
if (items[i] == null)
|
||||||
|
{
|
||||||
|
items[i] = obj;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
17
Ryujinx.Common/Pools/SharedPools.cs
Normal file
17
Ryujinx.Common/Pools/SharedPools.cs
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
namespace Ryujinx.Common
|
||||||
|
{
|
||||||
|
public static class SharedPools
|
||||||
|
{
|
||||||
|
private static class DefaultPool<T>
|
||||||
|
where T : class, new()
|
||||||
|
{
|
||||||
|
public static readonly ObjectPool<T> Instance = new ObjectPool<T>(() => new T(), 20);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ObjectPool<T> Default<T>()
|
||||||
|
where T : class, new()
|
||||||
|
{
|
||||||
|
return DefaultPool<T>.Instance;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -13,4 +13,8 @@
|
||||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Utf8Json" Version="1.3.7" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|
|
@ -112,7 +112,6 @@ namespace Ryujinx.HLE
|
||||||
if (disposing)
|
if (disposing)
|
||||||
{
|
{
|
||||||
System.Dispose();
|
System.Dispose();
|
||||||
|
|
||||||
VsyncEvent.Dispose();
|
VsyncEvent.Dispose();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,6 +23,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Luea", "Ryujinx.LLE\Luea.cs
|
||||||
EndProject
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Common", "Ryujinx.Common\Ryujinx.Common.csproj", "{5FD4E4F6-8928-4B3C-BE07-28A675C17226}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Common", "Ryujinx.Common\Ryujinx.Common.csproj", "{5FD4E4F6-8928-4B3C-BE07-28A675C17226}"
|
||||||
EndProject
|
EndProject
|
||||||
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{464D8AB7-B056-4A99-B207-B8DCFB47AAA9}"
|
||||||
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
Debug|Any CPU = Debug|Any CPU
|
Debug|Any CPU = Debug|Any CPU
|
||||||
|
@ -73,6 +75,10 @@ Global
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
|
GlobalSection(NestedProjects) = preSolution
|
||||||
|
{EBB55AEA-C7D7-4DEB-BF96-FA1789E225E9} = {464D8AB7-B056-4A99-B207-B8DCFB47AAA9}
|
||||||
|
{D8F72938-78EF-4E8C-BAFE-531C9C3C8F15} = {464D8AB7-B056-4A99-B207-B8DCFB47AAA9}
|
||||||
|
EndGlobalSection
|
||||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||||
SolutionGuid = {110169B3-3328-4730-8AB0-BA05BEF75C1A}
|
SolutionGuid = {110169B3-3328-4730-8AB0-BA05BEF75C1A}
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
|
|
|
@ -1,203 +0,0 @@
|
||||||
using LibHac.IO;
|
|
||||||
using Ryujinx.Common.Logging;
|
|
||||||
using Ryujinx.HLE;
|
|
||||||
using Ryujinx.HLE.HOS.SystemState;
|
|
||||||
using Ryujinx.HLE.Input;
|
|
||||||
using Ryujinx.UI.Input;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Globalization;
|
|
||||||
using System.IO;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Reflection;
|
|
||||||
|
|
||||||
namespace Ryujinx
|
|
||||||
{
|
|
||||||
public static class Config
|
|
||||||
{
|
|
||||||
public static NpadKeyboard NpadKeyboard { get; private set; }
|
|
||||||
public static NpadController NpadController { get; private set; }
|
|
||||||
|
|
||||||
public static void Read(Switch device)
|
|
||||||
{
|
|
||||||
string iniFolder = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location);
|
|
||||||
|
|
||||||
string iniPath = Path.Combine(iniFolder, "Ryujinx.conf");
|
|
||||||
|
|
||||||
IniParser parser = new IniParser(iniPath);
|
|
||||||
|
|
||||||
GraphicsConfig.ShadersDumpPath = parser.Value("Graphics_Shaders_Dump_Path");
|
|
||||||
|
|
||||||
Logger.SetEnable(LogLevel.Debug, Convert.ToBoolean(parser.Value("Logging_Enable_Debug")));
|
|
||||||
Logger.SetEnable(LogLevel.Stub, Convert.ToBoolean(parser.Value("Logging_Enable_Stub")));
|
|
||||||
Logger.SetEnable(LogLevel.Info, Convert.ToBoolean(parser.Value("Logging_Enable_Info")));
|
|
||||||
Logger.SetEnable(LogLevel.Warning, Convert.ToBoolean(parser.Value("Logging_Enable_Warn")));
|
|
||||||
Logger.SetEnable(LogLevel.Error, Convert.ToBoolean(parser.Value("Logging_Enable_Error")));
|
|
||||||
|
|
||||||
string[] filteredLogClasses = parser.Value("Logging_Filtered_Classes").Split(',', StringSplitOptions.RemoveEmptyEntries);
|
|
||||||
|
|
||||||
//When the classes are specified on the list, we only
|
|
||||||
//enable the classes that are on the list.
|
|
||||||
//So, first disable everything, then enable
|
|
||||||
//the classes that the user added to the list.
|
|
||||||
if (filteredLogClasses.Length > 0)
|
|
||||||
{
|
|
||||||
foreach (LogClass Class in Enum.GetValues(typeof(LogClass)))
|
|
||||||
{
|
|
||||||
Logger.SetEnable(Class, false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (string logClass in filteredLogClasses)
|
|
||||||
{
|
|
||||||
if (!string.IsNullOrEmpty(logClass.Trim()))
|
|
||||||
{
|
|
||||||
foreach (LogClass Class in Enum.GetValues(typeof(LogClass)))
|
|
||||||
{
|
|
||||||
if (Class.ToString().ToLower().Contains(logClass.Trim().ToLower()))
|
|
||||||
{
|
|
||||||
Logger.SetEnable(Class, true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Logger.EnableFileLog = Convert.ToBoolean(parser.Value("Enable_File_Log"));
|
|
||||||
|
|
||||||
SystemLanguage SetLanguage = Enum.Parse<SystemLanguage>(parser.Value("System_Language"));
|
|
||||||
|
|
||||||
device.System.State.SetLanguage(SetLanguage);
|
|
||||||
|
|
||||||
device.System.State.DockedMode = Convert.ToBoolean(parser.Value("Docked_Mode"));
|
|
||||||
|
|
||||||
device.EnableDeviceVsync = Convert.ToBoolean(parser.Value("Enable_Vsync"));
|
|
||||||
|
|
||||||
if (Convert.ToBoolean(parser.Value("Enable_MultiCore_Scheduling")))
|
|
||||||
{
|
|
||||||
device.System.EnableMultiCoreScheduling();
|
|
||||||
}
|
|
||||||
|
|
||||||
device.System.FsIntegrityCheckLevel = Convert.ToBoolean(parser.Value("Enable_FS_Integrity_Checks"))
|
|
||||||
? IntegrityCheckLevel.ErrorOnInvalid
|
|
||||||
: IntegrityCheckLevel.None;
|
|
||||||
|
|
||||||
HidControllerType ControllerType = Enum.Parse<HidControllerType>(parser.Value("Controller_Type"));
|
|
||||||
|
|
||||||
device.Hid.InitilizePrimaryController(ControllerType);
|
|
||||||
|
|
||||||
NpadKeyboard = new NpadKeyboard(
|
|
||||||
|
|
||||||
new NpadKeyboardLeft
|
|
||||||
{
|
|
||||||
StickUp = Convert.ToInt16(parser.Value("Controls_Left_JoyConKeyboard_Stick_Up")),
|
|
||||||
StickDown = Convert.ToInt16(parser.Value("Controls_Left_JoyConKeyboard_Stick_Down")),
|
|
||||||
StickLeft = Convert.ToInt16(parser.Value("Controls_Left_JoyConKeyboard_Stick_Left")),
|
|
||||||
StickRight = Convert.ToInt16(parser.Value("Controls_Left_JoyConKeyboard_Stick_Right")),
|
|
||||||
StickButton = Convert.ToInt16(parser.Value("Controls_Left_JoyConKeyboard_Stick_Button")),
|
|
||||||
DPadUp = Convert.ToInt16(parser.Value("Controls_Left_JoyConKeyboard_DPad_Up")),
|
|
||||||
DPadDown = Convert.ToInt16(parser.Value("Controls_Left_JoyConKeyboard_DPad_Down")),
|
|
||||||
DPadLeft = Convert.ToInt16(parser.Value("Controls_Left_JoyConKeyboard_DPad_Left")),
|
|
||||||
DPadRight = Convert.ToInt16(parser.Value("Controls_Left_JoyConKeyboard_DPad_Right")),
|
|
||||||
ButtonMinus = Convert.ToInt16(parser.Value("Controls_Left_JoyConKeyboard_Button_Minus")),
|
|
||||||
ButtonL = Convert.ToInt16(parser.Value("Controls_Left_JoyConKeyboard_Button_L")),
|
|
||||||
ButtonZl = Convert.ToInt16(parser.Value("Controls_Left_JoyConKeyboard_Button_ZL"))
|
|
||||||
},
|
|
||||||
|
|
||||||
new NpadKeyboardRight
|
|
||||||
{
|
|
||||||
StickUp = Convert.ToInt16(parser.Value("Controls_Right_JoyConKeyboard_Stick_Up")),
|
|
||||||
StickDown = Convert.ToInt16(parser.Value("Controls_Right_JoyConKeyboard_Stick_Down")),
|
|
||||||
StickLeft = Convert.ToInt16(parser.Value("Controls_Right_JoyConKeyboard_Stick_Left")),
|
|
||||||
StickRight = Convert.ToInt16(parser.Value("Controls_Right_JoyConKeyboard_Stick_Right")),
|
|
||||||
StickButton = Convert.ToInt16(parser.Value("Controls_Right_JoyConKeyboard_Stick_Button")),
|
|
||||||
ButtonA = Convert.ToInt16(parser.Value("Controls_Right_JoyConKeyboard_Button_A")),
|
|
||||||
ButtonB = Convert.ToInt16(parser.Value("Controls_Right_JoyConKeyboard_Button_B")),
|
|
||||||
ButtonX = Convert.ToInt16(parser.Value("Controls_Right_JoyConKeyboard_Button_X")),
|
|
||||||
ButtonY = Convert.ToInt16(parser.Value("Controls_Right_JoyConKeyboard_Button_Y")),
|
|
||||||
ButtonPlus = Convert.ToInt16(parser.Value("Controls_Right_JoyConKeyboard_Button_Plus")),
|
|
||||||
ButtonR = Convert.ToInt16(parser.Value("Controls_Right_JoyConKeyboard_Button_R")),
|
|
||||||
ButtonZr = Convert.ToInt16(parser.Value("Controls_Right_JoyConKeyboard_Button_ZR"))
|
|
||||||
});
|
|
||||||
|
|
||||||
NpadController = new NpadController(
|
|
||||||
Convert.ToBoolean(parser.Value("GamePad_Enable")),
|
|
||||||
Convert.ToInt32 (parser.Value("GamePad_Index")),
|
|
||||||
(float)Convert.ToDouble (parser.Value("GamePad_Deadzone"), CultureInfo.InvariantCulture),
|
|
||||||
(float)Convert.ToDouble (parser.Value("GamePad_Trigger_Threshold"), CultureInfo.InvariantCulture),
|
|
||||||
|
|
||||||
new NpadControllerLeft
|
|
||||||
{
|
|
||||||
Stick = ToId(parser.Value("Controls_Left_JoyConController_Stick")),
|
|
||||||
StickButton = ToId(parser.Value("Controls_Left_JoyConController_Stick_Button")),
|
|
||||||
DPadUp = ToId(parser.Value("Controls_Left_JoyConController_DPad_Up")),
|
|
||||||
DPadDown = ToId(parser.Value("Controls_Left_JoyConController_DPad_Down")),
|
|
||||||
DPadLeft = ToId(parser.Value("Controls_Left_JoyConController_DPad_Left")),
|
|
||||||
DPadRight = ToId(parser.Value("Controls_Left_JoyConController_DPad_Right")),
|
|
||||||
ButtonMinus = ToId(parser.Value("Controls_Left_JoyConController_Button_Minus")),
|
|
||||||
ButtonL = ToId(parser.Value("Controls_Left_JoyConController_Button_L")),
|
|
||||||
ButtonZl = ToId(parser.Value("Controls_Left_JoyConController_Button_ZL"))
|
|
||||||
},
|
|
||||||
|
|
||||||
new NpadControllerRight
|
|
||||||
{
|
|
||||||
Stick = ToId(parser.Value("Controls_Right_JoyConController_Stick")),
|
|
||||||
StickButton = ToId(parser.Value("Controls_Right_JoyConController_Stick_Button")),
|
|
||||||
ButtonA = ToId(parser.Value("Controls_Right_JoyConController_Button_A")),
|
|
||||||
ButtonB = ToId(parser.Value("Controls_Right_JoyConController_Button_B")),
|
|
||||||
ButtonX = ToId(parser.Value("Controls_Right_JoyConController_Button_X")),
|
|
||||||
ButtonY = ToId(parser.Value("Controls_Right_JoyConController_Button_Y")),
|
|
||||||
ButtonPlus = ToId(parser.Value("Controls_Right_JoyConController_Button_Plus")),
|
|
||||||
ButtonR = ToId(parser.Value("Controls_Right_JoyConController_Button_R")),
|
|
||||||
ButtonZr = ToId(parser.Value("Controls_Right_JoyConController_Button_ZR"))
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private static ControllerInputId ToId(string key)
|
|
||||||
{
|
|
||||||
switch (key.ToUpper())
|
|
||||||
{
|
|
||||||
case "LSTICK": return ControllerInputId.LStick;
|
|
||||||
case "DPADUP": return ControllerInputId.DPadUp;
|
|
||||||
case "DPADDOWN": return ControllerInputId.DPadDown;
|
|
||||||
case "DPADLEFT": return ControllerInputId.DPadLeft;
|
|
||||||
case "DPADRIGHT": return ControllerInputId.DPadRight;
|
|
||||||
case "BACK": return ControllerInputId.Back;
|
|
||||||
case "LSHOULDER": return ControllerInputId.LShoulder;
|
|
||||||
case "LTRIGGER": return ControllerInputId.LTrigger;
|
|
||||||
|
|
||||||
case "RSTICK": return ControllerInputId.RStick;
|
|
||||||
case "A": return ControllerInputId.A;
|
|
||||||
case "B": return ControllerInputId.B;
|
|
||||||
case "X": return ControllerInputId.X;
|
|
||||||
case "Y": return ControllerInputId.Y;
|
|
||||||
case "START": return ControllerInputId.Start;
|
|
||||||
case "RSHOULDER": return ControllerInputId.RShoulder;
|
|
||||||
case "RTRIGGER": return ControllerInputId.RTrigger;
|
|
||||||
|
|
||||||
case "LJOYSTICK": return ControllerInputId.LJoystick;
|
|
||||||
case "RJOYSTICK": return ControllerInputId.RJoystick;
|
|
||||||
|
|
||||||
default: return ControllerInputId.Invalid;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//https://stackoverflow.com/a/37772571
|
|
||||||
public class IniParser
|
|
||||||
{
|
|
||||||
private readonly Dictionary<string, string> _values;
|
|
||||||
|
|
||||||
public IniParser(string path)
|
|
||||||
{
|
|
||||||
_values = File.ReadLines(path)
|
|
||||||
.Where(line => !string.IsNullOrWhiteSpace(line) && !line.StartsWith('#'))
|
|
||||||
.Select(line => line.Split('=', 2))
|
|
||||||
.ToDictionary(parts => parts[0].Trim(), parts => parts.Length > 1 ? parts[1].Trim() : null);
|
|
||||||
}
|
|
||||||
|
|
||||||
public string Value(string name)
|
|
||||||
{
|
|
||||||
return _values.TryGetValue(name, out string value) ? value : null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
124
Ryujinx/Config.jsonc
Normal file
124
Ryujinx/Config.jsonc
Normal file
|
@ -0,0 +1,124 @@
|
||||||
|
{
|
||||||
|
"$schema": "./_schema.json",
|
||||||
|
|
||||||
|
// Dump shaders in local directory (e.g. `C:\ShaderDumps`)
|
||||||
|
"graphics_shaders_dump_path": "",
|
||||||
|
|
||||||
|
// Enable print debug logs
|
||||||
|
"logging_enable_debug": false,
|
||||||
|
|
||||||
|
// Enable print stubbed calls logs
|
||||||
|
"logging_enable_stub": true,
|
||||||
|
|
||||||
|
// Enable print informations logs
|
||||||
|
"logging_enable_info": true,
|
||||||
|
|
||||||
|
// Enable print warning logs
|
||||||
|
"logging_enable_warn": true,
|
||||||
|
|
||||||
|
// Enable print error logs
|
||||||
|
"logging_enable_error": true,
|
||||||
|
|
||||||
|
// Filtered log classes, in a JSON array, eg. `[ "Loader", "ServiceFs" ]`
|
||||||
|
"logging_filtered_classes": [ ],
|
||||||
|
|
||||||
|
// Enable file logging
|
||||||
|
"enable_file_log": true,
|
||||||
|
|
||||||
|
// Change System Language
|
||||||
|
// System Language list: https://gist.github.com/HorrorTroll/b6e4a88d774c3c9b3bdf54d79a7ca43b
|
||||||
|
"system_language": "AmericanEnglish",
|
||||||
|
|
||||||
|
// Enable or Disable Docked Mode
|
||||||
|
"docked_mode": false,
|
||||||
|
|
||||||
|
// Enable or Disable Game Vsync
|
||||||
|
"enable_vsync": true,
|
||||||
|
|
||||||
|
// Enable or Disable Multi-core scheduling of threads
|
||||||
|
"enable_multicore_scheduling": false,
|
||||||
|
|
||||||
|
// Enable integrity checks on Switch content files
|
||||||
|
"enable_fs_integrity_checks": true,
|
||||||
|
|
||||||
|
// The primary controller's type
|
||||||
|
// Supported Values: Handheld, ProController, NpadPair, NpadLeft, NpadRight
|
||||||
|
"controller_type": "Handheld",
|
||||||
|
|
||||||
|
// Keyboard Controls
|
||||||
|
// https://github.com/opentk/opentk/blob/master/src/OpenTK/Input/Key.cs
|
||||||
|
"keyboard_controls": {
|
||||||
|
// Left JoyCon Keyboard Bindings
|
||||||
|
"left_joycon": {
|
||||||
|
"stick_up": "W",
|
||||||
|
"stick_down": "S",
|
||||||
|
"stick_left": "A",
|
||||||
|
"stick_right": "D",
|
||||||
|
"stick_button": "F",
|
||||||
|
"dpad_up": "Up",
|
||||||
|
"dpad_down": "Down",
|
||||||
|
"dpad_left": "Left",
|
||||||
|
"dpad_right": "Right",
|
||||||
|
"button_minus": "Minus",
|
||||||
|
"button_l": "E",
|
||||||
|
"button_zl": "Q"
|
||||||
|
},
|
||||||
|
|
||||||
|
// Right JoyCon Keyboard Bindings
|
||||||
|
"right_joycon": {
|
||||||
|
"stick_up": "I",
|
||||||
|
"stick_down": "K",
|
||||||
|
"stick_left": "J",
|
||||||
|
"stick_right": "L",
|
||||||
|
"stick_button": "H",
|
||||||
|
"button_a": "Z",
|
||||||
|
"button_b": "X",
|
||||||
|
"button_x": "C",
|
||||||
|
"button_y": "V",
|
||||||
|
"button_plus": "Plus",
|
||||||
|
"button_r": "U",
|
||||||
|
"button_zr": "O"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// Controller Controls
|
||||||
|
"gamepad_controls": {
|
||||||
|
// Whether or not to enable Controller support
|
||||||
|
"enabled": true,
|
||||||
|
|
||||||
|
// Controller Device Index
|
||||||
|
"index": 0,
|
||||||
|
|
||||||
|
// Controller Analog Stick Deadzone
|
||||||
|
"deadzone": 0.05,
|
||||||
|
|
||||||
|
// The value of how pressed down each trigger has to be in order to register a button press
|
||||||
|
"trigger_threshold": 0.5,
|
||||||
|
|
||||||
|
// Left JoyCon Controller Bindings
|
||||||
|
"left_joycon": {
|
||||||
|
"stick": "LJoystick",
|
||||||
|
"stick_button": "LStick",
|
||||||
|
"dpad_up": "DPadUp",
|
||||||
|
"dpad_down": "DPadDown",
|
||||||
|
"dpad_left": "DPadLeft",
|
||||||
|
"dpad_right": "DPadRight",
|
||||||
|
"button_minus": "Back",
|
||||||
|
"button_l": "LShoulder",
|
||||||
|
"button_zl": "LTrigger"
|
||||||
|
},
|
||||||
|
|
||||||
|
// Right JoyCon Controller Bindings
|
||||||
|
"right_joycon": {
|
||||||
|
"stick": "RJoystick",
|
||||||
|
"stick_button": "RStick",
|
||||||
|
"button_a": "B",
|
||||||
|
"button_b": "A",
|
||||||
|
"button_x": "Y",
|
||||||
|
"button_y": "X",
|
||||||
|
"button_plus": "Start",
|
||||||
|
"button_r": "RShoulder",
|
||||||
|
"button_zr": "RTrigger"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
239
Ryujinx/Configuration.cs
Normal file
239
Ryujinx/Configuration.cs
Normal file
|
@ -0,0 +1,239 @@
|
||||||
|
using LibHac.IO;
|
||||||
|
using OpenTK.Input;
|
||||||
|
using Ryujinx.Common;
|
||||||
|
using Ryujinx.Common.Logging;
|
||||||
|
using Ryujinx.HLE;
|
||||||
|
using Ryujinx.HLE.HOS.SystemState;
|
||||||
|
using Ryujinx.HLE.Input;
|
||||||
|
using Ryujinx.UI.Input;
|
||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Utf8Json;
|
||||||
|
using Utf8Json.Resolvers;
|
||||||
|
|
||||||
|
namespace Ryujinx
|
||||||
|
{
|
||||||
|
public class Configuration
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The default configuration instance
|
||||||
|
/// </summary>
|
||||||
|
public static Configuration Instance { get; private set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Dumps shaders in this local directory
|
||||||
|
/// </summary>
|
||||||
|
public string GraphicsShadersDumpPath { get; private set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Enables printing debug log messages
|
||||||
|
/// </summary>
|
||||||
|
public bool LoggingEnableDebug { get; private set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Enables printing stub log messages
|
||||||
|
/// </summary>
|
||||||
|
public bool LoggingEnableStub { get; private set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Enables printing info log messages
|
||||||
|
/// </summary>
|
||||||
|
public bool LoggingEnableInfo { get; private set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Enables printing warning log messages
|
||||||
|
/// </summary>
|
||||||
|
public bool LoggingEnableWarn { get; private set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Enables printing error log messages
|
||||||
|
/// </summary>
|
||||||
|
public bool LoggingEnableError { get; private set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Controls which log messages are written to the log targets
|
||||||
|
/// </summary>
|
||||||
|
public LogClass[] LoggingFilteredClasses { get; private set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Enables or disables logging to a file on disk
|
||||||
|
/// </summary>
|
||||||
|
public bool EnableFileLog { get; private set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Change System Language
|
||||||
|
/// </summary>
|
||||||
|
public SystemLanguage SystemLanguage { get; private set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Enables or disables Docked Mode
|
||||||
|
/// </summary>
|
||||||
|
public bool DockedMode { get; private set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Enables or disables Vertical Sync
|
||||||
|
/// </summary>
|
||||||
|
public bool EnableVsync { get; private set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Enables or disables multi-core scheduling of threads
|
||||||
|
/// </summary>
|
||||||
|
public bool EnableMultiCoreScheduling { get; private set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Enables integrity checks on Game content files
|
||||||
|
/// </summary>
|
||||||
|
public bool EnableFsIntegrityChecks { get; private set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The primary controller's type
|
||||||
|
/// </summary>
|
||||||
|
public HidControllerType ControllerType { get; private set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Keyboard control bindings
|
||||||
|
/// </summary>
|
||||||
|
public NpadKeyboard KeyboardControls { get; private set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Controller control bindings
|
||||||
|
/// </summary>
|
||||||
|
public NpadController GamepadControls { get; private 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)
|
||||||
|
{
|
||||||
|
var resolver = CompositeResolver.Create(
|
||||||
|
new[] { new ConfigurationEnumFormatter<Key>() },
|
||||||
|
new[] { StandardResolver.AllowPrivateSnakeCase }
|
||||||
|
);
|
||||||
|
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
var resolver = CompositeResolver.Create(
|
||||||
|
new[] { new ConfigurationEnumFormatter<Key>() },
|
||||||
|
new[] { StandardResolver.AllowPrivateSnakeCase }
|
||||||
|
);
|
||||||
|
|
||||||
|
using (Stream stream = File.OpenRead(path))
|
||||||
|
{
|
||||||
|
Instance = await JsonSerializer.DeserializeAsync<Configuration>(stream, resolver);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Configures a <see cref="Switch"/> instance
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="device">The instance to configure</param>
|
||||||
|
public static void Configure(Switch device)
|
||||||
|
{
|
||||||
|
if (Instance == null)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException("Configuration has not been loaded yet.");
|
||||||
|
}
|
||||||
|
|
||||||
|
GraphicsConfig.ShadersDumpPath = Instance.GraphicsShadersDumpPath;
|
||||||
|
|
||||||
|
Logger.AddTarget(new AsyncLogTargetWrapper(
|
||||||
|
new ConsoleLogTarget(),
|
||||||
|
1000,
|
||||||
|
AsyncLogTargetOverflowAction.Block
|
||||||
|
));
|
||||||
|
|
||||||
|
if (Instance.EnableFileLog)
|
||||||
|
{
|
||||||
|
Logger.AddTarget(new AsyncLogTargetWrapper(
|
||||||
|
new FileLogTarget("Ryujinx.log"),
|
||||||
|
1000,
|
||||||
|
AsyncLogTargetOverflowAction.Block
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
Logger.SetEnable(LogLevel.Debug, Instance.LoggingEnableDebug);
|
||||||
|
Logger.SetEnable(LogLevel.Stub, Instance.LoggingEnableStub);
|
||||||
|
Logger.SetEnable(LogLevel.Info, Instance.LoggingEnableInfo);
|
||||||
|
Logger.SetEnable(LogLevel.Warning, Instance.LoggingEnableWarn);
|
||||||
|
Logger.SetEnable(LogLevel.Error, Instance.LoggingEnableError);
|
||||||
|
|
||||||
|
if (Instance.LoggingFilteredClasses.Length > 0)
|
||||||
|
{
|
||||||
|
foreach (var logClass in EnumExtensions.GetValues<LogClass>())
|
||||||
|
{
|
||||||
|
Logger.SetEnable(logClass, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var logClass in Instance.LoggingFilteredClasses)
|
||||||
|
{
|
||||||
|
Logger.SetEnable(logClass, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
device.EnableDeviceVsync = Instance.EnableVsync;
|
||||||
|
|
||||||
|
device.System.State.DockedMode = Instance.DockedMode;
|
||||||
|
|
||||||
|
device.System.State.SetLanguage(Instance.SystemLanguage);
|
||||||
|
|
||||||
|
if (Instance.EnableMultiCoreScheduling)
|
||||||
|
{
|
||||||
|
device.System.EnableMultiCoreScheduling();
|
||||||
|
}
|
||||||
|
|
||||||
|
device.System.FsIntegrityCheckLevel = Instance.EnableFsIntegrityChecks
|
||||||
|
? IntegrityCheckLevel.ErrorOnInvalid
|
||||||
|
: IntegrityCheckLevel.None;
|
||||||
|
|
||||||
|
if(Instance.GamepadControls.Enabled)
|
||||||
|
{
|
||||||
|
if (GamePad.GetName(Instance.GamepadControls.Index) == "Unmapped Controller")
|
||||||
|
{
|
||||||
|
Instance.GamepadControls.SetEnabled(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
device.Hid.InitilizePrimaryController(Instance.ControllerType);
|
||||||
|
}
|
||||||
|
|
||||||
|
private class ConfigurationEnumFormatter<T> : IJsonFormatter<T>
|
||||||
|
where T : struct
|
||||||
|
{
|
||||||
|
public void Serialize(ref JsonWriter writer, T value, IJsonFormatterResolver formatterResolver)
|
||||||
|
{
|
||||||
|
formatterResolver.GetFormatterWithVerify<string>()
|
||||||
|
.Serialize(ref writer, value.ToString(), formatterResolver);
|
||||||
|
}
|
||||||
|
|
||||||
|
public T Deserialize(ref JsonReader reader, IJsonFormatterResolver formatterResolver)
|
||||||
|
{
|
||||||
|
if (reader.ReadIsNull())
|
||||||
|
{
|
||||||
|
return default(T);
|
||||||
|
}
|
||||||
|
|
||||||
|
var enumName = formatterResolver.GetFormatterWithVerify<string>()
|
||||||
|
.Deserialize(ref reader, formatterResolver);
|
||||||
|
|
||||||
|
if(Enum.TryParse<T>(enumName, out T result))
|
||||||
|
{
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
return default(T);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -20,9 +20,8 @@ namespace Ryujinx
|
||||||
|
|
||||||
Switch device = new Switch(renderer, audioOut);
|
Switch device = new Switch(renderer, audioOut);
|
||||||
|
|
||||||
Config.Read(device);
|
Configuration.Load("Config.jsonc");
|
||||||
|
Configuration.Configure(device);
|
||||||
Logger.Updated += Log.LogMessage;
|
|
||||||
|
|
||||||
AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
|
AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
|
||||||
AppDomain.CurrentDomain.ProcessExit += CurrentDomain_ProcessExit;
|
AppDomain.CurrentDomain.ProcessExit += CurrentDomain_ProcessExit;
|
||||||
|
@ -40,13 +39,13 @@ namespace Ryujinx
|
||||||
|
|
||||||
if (romFsFiles.Length > 0)
|
if (romFsFiles.Length > 0)
|
||||||
{
|
{
|
||||||
Console.WriteLine("Loading as cart with RomFS.");
|
Logger.PrintInfo(LogClass.Application, "Loading as cart with RomFS.");
|
||||||
|
|
||||||
device.LoadCart(args[0], romFsFiles[0]);
|
device.LoadCart(args[0], romFsFiles[0]);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Console.WriteLine("Loading as cart WITHOUT RomFS.");
|
Logger.PrintInfo(LogClass.Application, "Loading as cart WITHOUT RomFS.");
|
||||||
|
|
||||||
device.LoadCart(args[0]);
|
device.LoadCart(args[0]);
|
||||||
}
|
}
|
||||||
|
@ -56,20 +55,20 @@ namespace Ryujinx
|
||||||
switch (Path.GetExtension(args[0]).ToLowerInvariant())
|
switch (Path.GetExtension(args[0]).ToLowerInvariant())
|
||||||
{
|
{
|
||||||
case ".xci":
|
case ".xci":
|
||||||
Console.WriteLine("Loading as XCI.");
|
Logger.PrintInfo(LogClass.Application, "Loading as XCI.");
|
||||||
device.LoadXci(args[0]);
|
device.LoadXci(args[0]);
|
||||||
break;
|
break;
|
||||||
case ".nca":
|
case ".nca":
|
||||||
Console.WriteLine("Loading as NCA.");
|
Logger.PrintInfo(LogClass.Application, "Loading as NCA.");
|
||||||
device.LoadNca(args[0]);
|
device.LoadNca(args[0]);
|
||||||
break;
|
break;
|
||||||
case ".nsp":
|
case ".nsp":
|
||||||
case ".pfs0":
|
case ".pfs0":
|
||||||
Console.WriteLine("Loading as NSP.");
|
Logger.PrintInfo(LogClass.Application, "Loading as NSP.");
|
||||||
device.LoadNsp(args[0]);
|
device.LoadNsp(args[0]);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
Console.WriteLine("Loading as homebrew.");
|
Logger.PrintInfo(LogClass.Application, "Loading as homebrew.");
|
||||||
device.LoadProgram(args[0]);
|
device.LoadProgram(args[0]);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -77,7 +76,7 @@ namespace Ryujinx
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Console.WriteLine("Please specify the folder with the NSOs/IStorage or a NSO/NRO.");
|
Logger.PrintInfo(LogClass.Application, "Please specify the folder with the NSOs/IStorage or a NSO/NRO.");
|
||||||
}
|
}
|
||||||
|
|
||||||
using (GlScreen screen = new GlScreen(device, renderer))
|
using (GlScreen screen = new GlScreen(device, renderer))
|
||||||
|
@ -88,11 +87,13 @@ namespace Ryujinx
|
||||||
}
|
}
|
||||||
|
|
||||||
audioOut.Dispose();
|
audioOut.Dispose();
|
||||||
|
|
||||||
|
Logger.Shutdown();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void CurrentDomain_ProcessExit(object sender, EventArgs e)
|
private static void CurrentDomain_ProcessExit(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
Log.Close();
|
Logger.Shutdown();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
|
private static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
|
||||||
|
@ -103,7 +104,7 @@ namespace Ryujinx
|
||||||
|
|
||||||
if (e.IsTerminating)
|
if (e.IsTerminating)
|
||||||
{
|
{
|
||||||
Log.Close();
|
Logger.Shutdown();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,107 +0,0 @@
|
||||||
#Enable cpu memory checks (slow)
|
|
||||||
Enable_Memory_Checks = false
|
|
||||||
|
|
||||||
#Dump shaders in local directory (e.g. `C:\ShaderDumps`)
|
|
||||||
Graphics_Shaders_Dump_Path =
|
|
||||||
|
|
||||||
#Enable print debug logs
|
|
||||||
Logging_Enable_Debug = false
|
|
||||||
|
|
||||||
#Enable print stubbed calls logs
|
|
||||||
Logging_Enable_Stub = true
|
|
||||||
|
|
||||||
#Enable print informations logs
|
|
||||||
Logging_Enable_Info = true
|
|
||||||
|
|
||||||
#Enable print warning logs
|
|
||||||
Logging_Enable_Warn = true
|
|
||||||
|
|
||||||
#Enable print error logs
|
|
||||||
Logging_Enable_Error = true
|
|
||||||
|
|
||||||
#Filtered log classes, seperated by ", ", eg. `Logging_Filtered_Classes = Loader, ServiceFS`
|
|
||||||
Logging_Filtered_Classes =
|
|
||||||
|
|
||||||
#Enable file logging
|
|
||||||
Enable_File_Log = false
|
|
||||||
|
|
||||||
#System Language list: https://gist.github.com/HorrorTroll/b6e4a88d774c3c9b3bdf54d79a7ca43b
|
|
||||||
#Change System Language
|
|
||||||
System_Language = AmericanEnglish
|
|
||||||
|
|
||||||
#Enable or Disable Docked Mode
|
|
||||||
Docked_Mode = false
|
|
||||||
|
|
||||||
#Enable Game Vsync
|
|
||||||
Enable_Vsync = true
|
|
||||||
|
|
||||||
#Enable or Disable Multi-core scheduling of threads
|
|
||||||
Enable_MultiCore_Scheduling = false
|
|
||||||
|
|
||||||
#Enable integrity checks on Switch content files
|
|
||||||
Enable_FS_Integrity_Checks = true
|
|
||||||
|
|
||||||
#Controller Device Index
|
|
||||||
GamePad_Index = 0
|
|
||||||
|
|
||||||
#Controller Analog Stick Deadzone
|
|
||||||
GamePad_Deadzone = 0.05
|
|
||||||
|
|
||||||
#The value of how pressed down each trigger has to be in order to register a button press
|
|
||||||
GamePad_Trigger_Threshold = 0.5
|
|
||||||
|
|
||||||
#Whether or not to enable Controller support
|
|
||||||
GamePad_Enable = true
|
|
||||||
|
|
||||||
#The primary controller's type. Supported Values: ProController, Handheld, NpadPair, NpadLeft, NpadRight
|
|
||||||
Controller_Type = Handheld
|
|
||||||
|
|
||||||
#https://github.com/opentk/opentk/blob/develop/src/OpenTK/Input/Key.cs
|
|
||||||
Controls_Left_JoyConKeyboard_Stick_Up = 105
|
|
||||||
Controls_Left_JoyConKeyboard_Stick_Down = 101
|
|
||||||
Controls_Left_JoyConKeyboard_Stick_Left = 83
|
|
||||||
Controls_Left_JoyConKeyboard_Stick_Right = 86
|
|
||||||
Controls_Left_JoyConKeyboard_Stick_Button = 88
|
|
||||||
Controls_Left_JoyConKeyboard_DPad_Up = 45
|
|
||||||
Controls_Left_JoyConKeyboard_DPad_Down = 46
|
|
||||||
Controls_Left_JoyConKeyboard_DPad_Left = 47
|
|
||||||
Controls_Left_JoyConKeyboard_DPad_Right = 48
|
|
||||||
Controls_Left_JoyConKeyboard_Button_Minus = 120
|
|
||||||
Controls_Left_JoyConKeyboard_Button_L = 87
|
|
||||||
Controls_Left_JoyConKeyboard_Button_ZL = 99
|
|
||||||
|
|
||||||
Controls_Right_JoyConKeyboard_Stick_Up = 91
|
|
||||||
Controls_Right_JoyConKeyboard_Stick_Down = 93
|
|
||||||
Controls_Right_JoyConKeyboard_Stick_Left = 92
|
|
||||||
Controls_Right_JoyConKeyboard_Stick_Right = 94
|
|
||||||
Controls_Right_JoyConKeyboard_Stick_Button = 90
|
|
||||||
Controls_Right_JoyConKeyboard_Button_A = 108
|
|
||||||
Controls_Right_JoyConKeyboard_Button_B = 106
|
|
||||||
Controls_Right_JoyConKeyboard_Button_X = 85
|
|
||||||
Controls_Right_JoyConKeyboard_Button_Y = 104
|
|
||||||
Controls_Right_JoyConKeyboard_Button_Plus = 121
|
|
||||||
Controls_Right_JoyConKeyboard_Button_R = 103
|
|
||||||
Controls_Right_JoyConKeyboard_Button_ZR = 97
|
|
||||||
|
|
||||||
#Controller Controls
|
|
||||||
|
|
||||||
Controls_Left_JoyConController_Stick_Button = LStick
|
|
||||||
Controls_Left_JoyConController_DPad_Up = DPadUp
|
|
||||||
Controls_Left_JoyConController_DPad_Down = DPadDown
|
|
||||||
Controls_Left_JoyConController_DPad_Left = DPadLeft
|
|
||||||
Controls_Left_JoyConController_DPad_Right = DPadRight
|
|
||||||
Controls_Left_JoyConController_Button_Minus = Back
|
|
||||||
Controls_Left_JoyConController_Button_L = LShoulder
|
|
||||||
Controls_Left_JoyConController_Button_ZL = LTrigger
|
|
||||||
|
|
||||||
Controls_Right_JoyConController_Stick_Button = RStick
|
|
||||||
Controls_Right_JoyConController_Button_A = B
|
|
||||||
Controls_Right_JoyConController_Button_B = A
|
|
||||||
Controls_Right_JoyConController_Button_X = Y
|
|
||||||
Controls_Right_JoyConController_Button_Y = X
|
|
||||||
Controls_Right_JoyConController_Button_Plus = Start
|
|
||||||
Controls_Right_JoyConController_Button_R = RShoulder
|
|
||||||
Controls_Right_JoyConController_Button_ZR = RTrigger
|
|
||||||
|
|
||||||
Controls_Left_JoyConController_Stick = LJoystick
|
|
||||||
Controls_Right_JoyConController_Stick = RJoystick
|
|
|
@ -20,7 +20,7 @@
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Update="Ryujinx.conf">
|
<None Update="Config.jsonc">
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
</None>
|
</None>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
|
@ -142,24 +142,24 @@ namespace Ryujinx
|
||||||
{
|
{
|
||||||
KeyboardState keyboard = _keyboard.Value;
|
KeyboardState keyboard = _keyboard.Value;
|
||||||
|
|
||||||
currentButton = Config.NpadKeyboard.GetButtons(keyboard);
|
currentButton = Configuration.Instance.KeyboardControls.GetButtons(keyboard);
|
||||||
|
|
||||||
(leftJoystickDx, leftJoystickDy) = Config.NpadKeyboard.GetLeftStick(keyboard);
|
(leftJoystickDx, leftJoystickDy) = Configuration.Instance.KeyboardControls.GetLeftStick(keyboard);
|
||||||
|
|
||||||
(rightJoystickDx, rightJoystickDy) = Config.NpadKeyboard.GetRightStick(keyboard);
|
(rightJoystickDx, rightJoystickDy) = Configuration.Instance.KeyboardControls.GetRightStick(keyboard);
|
||||||
}
|
}
|
||||||
|
|
||||||
currentButton |= Config.NpadController.GetButtons();
|
currentButton |= Configuration.Instance.GamepadControls.GetButtons();
|
||||||
|
|
||||||
//Keyboard has priority stick-wise
|
//Keyboard has priority stick-wise
|
||||||
if (leftJoystickDx == 0 && leftJoystickDy == 0)
|
if (leftJoystickDx == 0 && leftJoystickDy == 0)
|
||||||
{
|
{
|
||||||
(leftJoystickDx, leftJoystickDy) = Config.NpadController.GetLeftStick();
|
(leftJoystickDx, leftJoystickDy) = Configuration.Instance.GamepadControls.GetLeftStick();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rightJoystickDx == 0 && rightJoystickDy == 0)
|
if (rightJoystickDx == 0 && rightJoystickDy == 0)
|
||||||
{
|
{
|
||||||
(rightJoystickDx, rightJoystickDy) = Config.NpadController.GetRightStick();
|
(rightJoystickDx, rightJoystickDy) = Configuration.Instance.GamepadControls.GetRightStick();
|
||||||
}
|
}
|
||||||
|
|
||||||
leftJoystick = new HidJoystickPosition
|
leftJoystick = new HidJoystickPosition
|
||||||
|
|
|
@ -1,140 +0,0 @@
|
||||||
using Ryujinx.Common.Logging;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Concurrent;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.IO;
|
|
||||||
using System.Reflection;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading;
|
|
||||||
|
|
||||||
namespace Ryujinx
|
|
||||||
{
|
|
||||||
static class Log
|
|
||||||
{
|
|
||||||
private static readonly string _path;
|
|
||||||
|
|
||||||
private static StreamWriter _logWriter;
|
|
||||||
|
|
||||||
private static Thread _messageThread;
|
|
||||||
|
|
||||||
private static BlockingCollection<LogEventArgs> _messageQueue;
|
|
||||||
|
|
||||||
private static Dictionary<LogLevel, ConsoleColor> _logColors;
|
|
||||||
|
|
||||||
static Log()
|
|
||||||
{
|
|
||||||
_logColors = new Dictionary<LogLevel, ConsoleColor>()
|
|
||||||
{
|
|
||||||
{ LogLevel.Stub, ConsoleColor.DarkGray },
|
|
||||||
{ LogLevel.Info, ConsoleColor.White },
|
|
||||||
{ LogLevel.Warning, ConsoleColor.Yellow },
|
|
||||||
{ LogLevel.Error, ConsoleColor.Red }
|
|
||||||
};
|
|
||||||
|
|
||||||
_messageQueue = new BlockingCollection<LogEventArgs>(10);
|
|
||||||
|
|
||||||
_messageThread = new Thread(() =>
|
|
||||||
{
|
|
||||||
while (!_messageQueue.IsCompleted)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
PrintLog(_messageQueue.Take());
|
|
||||||
}
|
|
||||||
catch (InvalidOperationException)
|
|
||||||
{
|
|
||||||
// IOE means that Take() was called on a completed collection.
|
|
||||||
// Some other thread can call CompleteAdding after we pass the
|
|
||||||
// IsCompleted check but before we call Take.
|
|
||||||
// We can simply catch the exception since the loop will break
|
|
||||||
// on the next iteration.
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
_path = Path.Combine(Environment.CurrentDirectory, "Ryujinx.log");
|
|
||||||
|
|
||||||
if (Logger.EnableFileLog)
|
|
||||||
{
|
|
||||||
_logWriter = new StreamWriter(File.Open(_path,FileMode.Create, FileAccess.Write));
|
|
||||||
}
|
|
||||||
|
|
||||||
_messageThread.IsBackground = true;
|
|
||||||
_messageThread.Start();
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void PrintLog(LogEventArgs e)
|
|
||||||
{
|
|
||||||
StringBuilder sb = new StringBuilder();
|
|
||||||
|
|
||||||
sb.AppendFormat(@"{0:hh\:mm\:ss\.fff}", e.Time);
|
|
||||||
sb.Append(" | ");
|
|
||||||
sb.AppendFormat("{0:d4}", e.ThreadId);
|
|
||||||
sb.Append(' ');
|
|
||||||
sb.Append(e.Message);
|
|
||||||
|
|
||||||
if (e.Data != null)
|
|
||||||
{
|
|
||||||
PropertyInfo[] props = e.Data.GetType().GetProperties();
|
|
||||||
|
|
||||||
sb.Append(' ');
|
|
||||||
|
|
||||||
foreach (var prop in props)
|
|
||||||
{
|
|
||||||
sb.Append(prop.Name);
|
|
||||||
sb.Append(": ");
|
|
||||||
sb.Append(prop.GetValue(e.Data));
|
|
||||||
sb.Append(" - ");
|
|
||||||
}
|
|
||||||
|
|
||||||
// We remove the final '-' from the string
|
|
||||||
if (props.Length > 0)
|
|
||||||
{
|
|
||||||
sb.Remove(sb.Length - 3, 3);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
string message = sb.ToString();
|
|
||||||
|
|
||||||
if (_logColors.TryGetValue(e.Level, out ConsoleColor color))
|
|
||||||
{
|
|
||||||
Console.ForegroundColor = color;
|
|
||||||
|
|
||||||
Console.WriteLine(message);
|
|
||||||
|
|
||||||
Console.ResetColor();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Console.WriteLine(message);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Logger.EnableFileLog)
|
|
||||||
{
|
|
||||||
_logWriter.WriteLine(message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void LogMessage(object sender, LogEventArgs e)
|
|
||||||
{
|
|
||||||
if (!_messageQueue.IsAddingCompleted)
|
|
||||||
{
|
|
||||||
_messageQueue.Add(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void Close()
|
|
||||||
{
|
|
||||||
_messageQueue.CompleteAdding();
|
|
||||||
|
|
||||||
_messageThread.Join();
|
|
||||||
|
|
||||||
if (Logger.EnableFileLog)
|
|
||||||
{
|
|
||||||
_logWriter.Flush();
|
|
||||||
_logWriter.Close();
|
|
||||||
_logWriter.Dispose();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -8,28 +8,24 @@ namespace Ryujinx.UI.Input
|
||||||
public enum ControllerInputId
|
public enum ControllerInputId
|
||||||
{
|
{
|
||||||
Invalid,
|
Invalid,
|
||||||
|
|
||||||
LStick,
|
LStick,
|
||||||
|
RStick,
|
||||||
|
LShoulder,
|
||||||
|
RShoulder,
|
||||||
|
LTrigger,
|
||||||
|
RTrigger,
|
||||||
|
LJoystick,
|
||||||
|
RJoystick,
|
||||||
DPadUp,
|
DPadUp,
|
||||||
DPadDown,
|
DPadDown,
|
||||||
DPadLeft,
|
DPadLeft,
|
||||||
DPadRight,
|
DPadRight,
|
||||||
|
Start,
|
||||||
Back,
|
Back,
|
||||||
LShoulder,
|
|
||||||
|
|
||||||
RStick,
|
|
||||||
A,
|
A,
|
||||||
B,
|
B,
|
||||||
X,
|
X,
|
||||||
Y,
|
Y
|
||||||
Start,
|
|
||||||
RShoulder,
|
|
||||||
|
|
||||||
LTrigger,
|
|
||||||
RTrigger,
|
|
||||||
|
|
||||||
LJoystick,
|
|
||||||
RJoystick
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public struct NpadControllerLeft
|
public struct NpadControllerLeft
|
||||||
|
@ -60,34 +56,55 @@ namespace Ryujinx.UI.Input
|
||||||
|
|
||||||
public class NpadController
|
public class NpadController
|
||||||
{
|
{
|
||||||
public bool Enabled { private set; get; }
|
/// <summary>
|
||||||
public int Index { private set; get; }
|
/// Enables or disables controller support
|
||||||
public float Deadzone { private set; get; }
|
/// </summary>
|
||||||
public float TriggerThreshold { private set; get; }
|
public bool Enabled { get; private set; }
|
||||||
|
|
||||||
public NpadControllerLeft Left { private set; get; }
|
/// <summary>
|
||||||
public NpadControllerRight Right { private set; get; }
|
/// Controller Device Index
|
||||||
|
/// </summary>
|
||||||
|
public int Index { get; private set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Controller Analog Stick Deadzone
|
||||||
|
/// </summary>
|
||||||
|
public float Deadzone { get; private set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Controller Trigger Threshold
|
||||||
|
/// </summary>
|
||||||
|
public float TriggerThreshold { get; private set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Left JoyCon Controller Bindings
|
||||||
|
/// </summary>
|
||||||
|
public NpadControllerLeft LeftJoycon { get; private set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Right JoyCon Controller Bindings
|
||||||
|
/// </summary>
|
||||||
|
public NpadControllerRight RightJoycon { get; private set; }
|
||||||
|
|
||||||
public NpadController(
|
public NpadController(
|
||||||
bool enabled,
|
bool enabled,
|
||||||
int index,
|
int index,
|
||||||
float deadzone,
|
float deadzone,
|
||||||
float triggerThreshold,
|
float triggerThreshold,
|
||||||
NpadControllerLeft left,
|
NpadControllerLeft leftJoycon,
|
||||||
NpadControllerRight right)
|
NpadControllerRight rightJoycon)
|
||||||
{
|
{
|
||||||
Enabled = enabled;
|
Enabled = enabled;
|
||||||
Index = index;
|
Index = index;
|
||||||
Deadzone = deadzone;
|
Deadzone = deadzone;
|
||||||
TriggerThreshold = triggerThreshold;
|
TriggerThreshold = triggerThreshold;
|
||||||
Left = left;
|
LeftJoycon = leftJoycon;
|
||||||
Right = right;
|
RightJoycon = rightJoycon;
|
||||||
|
|
||||||
//Unmapped controllers are problematic, skip them
|
|
||||||
if (GamePad.GetName(index) == "Unmapped Controller")
|
|
||||||
{
|
|
||||||
Enabled = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void SetEnabled(bool enabled)
|
||||||
|
{
|
||||||
|
Enabled = enabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
public HidControllerButtons GetButtons()
|
public HidControllerButtons GetButtons()
|
||||||
|
@ -101,23 +118,23 @@ namespace Ryujinx.UI.Input
|
||||||
|
|
||||||
HidControllerButtons buttons = 0;
|
HidControllerButtons buttons = 0;
|
||||||
|
|
||||||
if (IsPressed(gpState, Left.DPadUp)) buttons |= HidControllerButtons.DpadUp;
|
if (IsPressed(gpState, LeftJoycon.DPadUp)) buttons |= HidControllerButtons.DpadUp;
|
||||||
if (IsPressed(gpState, Left.DPadDown)) buttons |= HidControllerButtons.DpadDown;
|
if (IsPressed(gpState, LeftJoycon.DPadDown)) buttons |= HidControllerButtons.DpadDown;
|
||||||
if (IsPressed(gpState, Left.DPadLeft)) buttons |= HidControllerButtons.DpadLeft;
|
if (IsPressed(gpState, LeftJoycon.DPadLeft)) buttons |= HidControllerButtons.DpadLeft;
|
||||||
if (IsPressed(gpState, Left.DPadRight)) buttons |= HidControllerButtons.DPadRight;
|
if (IsPressed(gpState, LeftJoycon.DPadRight)) buttons |= HidControllerButtons.DPadRight;
|
||||||
if (IsPressed(gpState, Left.StickButton)) buttons |= HidControllerButtons.StickLeft;
|
if (IsPressed(gpState, LeftJoycon.StickButton)) buttons |= HidControllerButtons.StickLeft;
|
||||||
if (IsPressed(gpState, Left.ButtonMinus)) buttons |= HidControllerButtons.Minus;
|
if (IsPressed(gpState, LeftJoycon.ButtonMinus)) buttons |= HidControllerButtons.Minus;
|
||||||
if (IsPressed(gpState, Left.ButtonL)) buttons |= HidControllerButtons.L;
|
if (IsPressed(gpState, LeftJoycon.ButtonL)) buttons |= HidControllerButtons.L;
|
||||||
if (IsPressed(gpState, Left.ButtonZl)) buttons |= HidControllerButtons.Zl;
|
if (IsPressed(gpState, LeftJoycon.ButtonZl)) buttons |= HidControllerButtons.Zl;
|
||||||
|
|
||||||
if (IsPressed(gpState, Right.ButtonA)) buttons |= HidControllerButtons.A;
|
if (IsPressed(gpState, RightJoycon.ButtonA)) buttons |= HidControllerButtons.A;
|
||||||
if (IsPressed(gpState, Right.ButtonB)) buttons |= HidControllerButtons.B;
|
if (IsPressed(gpState, RightJoycon.ButtonB)) buttons |= HidControllerButtons.B;
|
||||||
if (IsPressed(gpState, Right.ButtonX)) buttons |= HidControllerButtons.X;
|
if (IsPressed(gpState, RightJoycon.ButtonX)) buttons |= HidControllerButtons.X;
|
||||||
if (IsPressed(gpState, Right.ButtonY)) buttons |= HidControllerButtons.Y;
|
if (IsPressed(gpState, RightJoycon.ButtonY)) buttons |= HidControllerButtons.Y;
|
||||||
if (IsPressed(gpState, Right.StickButton)) buttons |= HidControllerButtons.StickRight;
|
if (IsPressed(gpState, RightJoycon.StickButton)) buttons |= HidControllerButtons.StickRight;
|
||||||
if (IsPressed(gpState, Right.ButtonPlus)) buttons |= HidControllerButtons.Plus;
|
if (IsPressed(gpState, RightJoycon.ButtonPlus)) buttons |= HidControllerButtons.Plus;
|
||||||
if (IsPressed(gpState, Right.ButtonR)) buttons |= HidControllerButtons.R;
|
if (IsPressed(gpState, RightJoycon.ButtonR)) buttons |= HidControllerButtons.R;
|
||||||
if (IsPressed(gpState, Right.ButtonZr)) buttons |= HidControllerButtons.Zr;
|
if (IsPressed(gpState, RightJoycon.ButtonZr)) buttons |= HidControllerButtons.Zr;
|
||||||
|
|
||||||
return buttons;
|
return buttons;
|
||||||
}
|
}
|
||||||
|
@ -129,7 +146,7 @@ namespace Ryujinx.UI.Input
|
||||||
return (0, 0);
|
return (0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
return GetStick(Left.Stick);
|
return GetStick(LeftJoycon.Stick);
|
||||||
}
|
}
|
||||||
|
|
||||||
public (short, short) GetRightStick()
|
public (short, short) GetRightStick()
|
||||||
|
@ -139,7 +156,7 @@ namespace Ryujinx.UI.Input
|
||||||
return (0, 0);
|
return (0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
return GetStick(Right.Stick);
|
return GetStick(RightJoycon.Stick);
|
||||||
}
|
}
|
||||||
|
|
||||||
private (short, short) GetStick(ControllerInputId joystick)
|
private (short, short) GetStick(ControllerInputId joystick)
|
||||||
|
|
|
@ -5,70 +5,69 @@ namespace Ryujinx.UI.Input
|
||||||
{
|
{
|
||||||
public struct NpadKeyboardLeft
|
public struct NpadKeyboardLeft
|
||||||
{
|
{
|
||||||
public int StickUp;
|
public Key StickUp;
|
||||||
public int StickDown;
|
public Key StickDown;
|
||||||
public int StickLeft;
|
public Key StickLeft;
|
||||||
public int StickRight;
|
public Key StickRight;
|
||||||
public int StickButton;
|
public Key StickButton;
|
||||||
public int DPadUp;
|
public Key DPadUp;
|
||||||
public int DPadDown;
|
public Key DPadDown;
|
||||||
public int DPadLeft;
|
public Key DPadLeft;
|
||||||
public int DPadRight;
|
public Key DPadRight;
|
||||||
public int ButtonMinus;
|
public Key ButtonMinus;
|
||||||
public int ButtonL;
|
public Key ButtonL;
|
||||||
public int ButtonZl;
|
public Key ButtonZl;
|
||||||
}
|
}
|
||||||
|
|
||||||
public struct NpadKeyboardRight
|
public struct NpadKeyboardRight
|
||||||
{
|
{
|
||||||
public int StickUp;
|
public Key StickUp;
|
||||||
public int StickDown;
|
public Key StickDown;
|
||||||
public int StickLeft;
|
public Key StickLeft;
|
||||||
public int StickRight;
|
public Key StickRight;
|
||||||
public int StickButton;
|
public Key StickButton;
|
||||||
public int ButtonA;
|
public Key ButtonA;
|
||||||
public int ButtonB;
|
public Key ButtonB;
|
||||||
public int ButtonX;
|
public Key ButtonX;
|
||||||
public int ButtonY;
|
public Key ButtonY;
|
||||||
public int ButtonPlus;
|
public Key ButtonPlus;
|
||||||
public int ButtonR;
|
public Key ButtonR;
|
||||||
public int ButtonZr;
|
public Key ButtonZr;
|
||||||
}
|
}
|
||||||
|
|
||||||
public class NpadKeyboard
|
public class NpadKeyboard
|
||||||
{
|
{
|
||||||
public NpadKeyboardLeft Left;
|
/// <summary>
|
||||||
public NpadKeyboardRight Right;
|
/// Left JoyCon Keyboard Bindings
|
||||||
|
/// </summary>
|
||||||
|
public NpadKeyboardLeft LeftJoycon { get; private set; }
|
||||||
|
|
||||||
public NpadKeyboard(
|
/// <summary>
|
||||||
NpadKeyboardLeft left,
|
/// Right JoyCon Keyboard Bindings
|
||||||
NpadKeyboardRight right)
|
/// </summary>
|
||||||
{
|
public NpadKeyboardRight RightJoycon { get; private set; }
|
||||||
Left = left;
|
|
||||||
Right = right;
|
|
||||||
}
|
|
||||||
|
|
||||||
public HidControllerButtons GetButtons(KeyboardState keyboard)
|
public HidControllerButtons GetButtons(KeyboardState keyboard)
|
||||||
{
|
{
|
||||||
HidControllerButtons buttons = 0;
|
HidControllerButtons buttons = 0;
|
||||||
|
|
||||||
if (keyboard[(Key)Left.StickButton]) buttons |= HidControllerButtons.StickLeft;
|
if (keyboard[(Key)LeftJoycon.StickButton]) buttons |= HidControllerButtons.StickLeft;
|
||||||
if (keyboard[(Key)Left.DPadUp]) buttons |= HidControllerButtons.DpadUp;
|
if (keyboard[(Key)LeftJoycon.DPadUp]) buttons |= HidControllerButtons.DpadUp;
|
||||||
if (keyboard[(Key)Left.DPadDown]) buttons |= HidControllerButtons.DpadDown;
|
if (keyboard[(Key)LeftJoycon.DPadDown]) buttons |= HidControllerButtons.DpadDown;
|
||||||
if (keyboard[(Key)Left.DPadLeft]) buttons |= HidControllerButtons.DpadLeft;
|
if (keyboard[(Key)LeftJoycon.DPadLeft]) buttons |= HidControllerButtons.DpadLeft;
|
||||||
if (keyboard[(Key)Left.DPadRight]) buttons |= HidControllerButtons.DPadRight;
|
if (keyboard[(Key)LeftJoycon.DPadRight]) buttons |= HidControllerButtons.DPadRight;
|
||||||
if (keyboard[(Key)Left.ButtonMinus]) buttons |= HidControllerButtons.Minus;
|
if (keyboard[(Key)LeftJoycon.ButtonMinus]) buttons |= HidControllerButtons.Minus;
|
||||||
if (keyboard[(Key)Left.ButtonL]) buttons |= HidControllerButtons.L;
|
if (keyboard[(Key)LeftJoycon.ButtonL]) buttons |= HidControllerButtons.L;
|
||||||
if (keyboard[(Key)Left.ButtonZl]) buttons |= HidControllerButtons.Zl;
|
if (keyboard[(Key)LeftJoycon.ButtonZl]) buttons |= HidControllerButtons.Zl;
|
||||||
|
|
||||||
if (keyboard[(Key)Right.StickButton]) buttons |= HidControllerButtons.StickRight;
|
if (keyboard[(Key)RightJoycon.StickButton]) buttons |= HidControllerButtons.StickRight;
|
||||||
if (keyboard[(Key)Right.ButtonA]) buttons |= HidControllerButtons.A;
|
if (keyboard[(Key)RightJoycon.ButtonA]) buttons |= HidControllerButtons.A;
|
||||||
if (keyboard[(Key)Right.ButtonB]) buttons |= HidControllerButtons.B;
|
if (keyboard[(Key)RightJoycon.ButtonB]) buttons |= HidControllerButtons.B;
|
||||||
if (keyboard[(Key)Right.ButtonX]) buttons |= HidControllerButtons.X;
|
if (keyboard[(Key)RightJoycon.ButtonX]) buttons |= HidControllerButtons.X;
|
||||||
if (keyboard[(Key)Right.ButtonY]) buttons |= HidControllerButtons.Y;
|
if (keyboard[(Key)RightJoycon.ButtonY]) buttons |= HidControllerButtons.Y;
|
||||||
if (keyboard[(Key)Right.ButtonPlus]) buttons |= HidControllerButtons.Plus;
|
if (keyboard[(Key)RightJoycon.ButtonPlus]) buttons |= HidControllerButtons.Plus;
|
||||||
if (keyboard[(Key)Right.ButtonR]) buttons |= HidControllerButtons.R;
|
if (keyboard[(Key)RightJoycon.ButtonR]) buttons |= HidControllerButtons.R;
|
||||||
if (keyboard[(Key)Right.ButtonZr]) buttons |= HidControllerButtons.Zr;
|
if (keyboard[(Key)RightJoycon.ButtonZr]) buttons |= HidControllerButtons.Zr;
|
||||||
|
|
||||||
return buttons;
|
return buttons;
|
||||||
}
|
}
|
||||||
|
@ -78,10 +77,10 @@ namespace Ryujinx.UI.Input
|
||||||
short dx = 0;
|
short dx = 0;
|
||||||
short dy = 0;
|
short dy = 0;
|
||||||
|
|
||||||
if (keyboard[(Key)Left.StickUp]) dy = short.MaxValue;
|
if (keyboard[(Key)LeftJoycon.StickUp]) dy = short.MaxValue;
|
||||||
if (keyboard[(Key)Left.StickDown]) dy = -short.MaxValue;
|
if (keyboard[(Key)LeftJoycon.StickDown]) dy = -short.MaxValue;
|
||||||
if (keyboard[(Key)Left.StickLeft]) dx = -short.MaxValue;
|
if (keyboard[(Key)LeftJoycon.StickLeft]) dx = -short.MaxValue;
|
||||||
if (keyboard[(Key)Left.StickRight]) dx = short.MaxValue;
|
if (keyboard[(Key)LeftJoycon.StickRight]) dx = short.MaxValue;
|
||||||
|
|
||||||
return (dx, dy);
|
return (dx, dy);
|
||||||
}
|
}
|
||||||
|
@ -91,10 +90,10 @@ namespace Ryujinx.UI.Input
|
||||||
short dx = 0;
|
short dx = 0;
|
||||||
short dy = 0;
|
short dy = 0;
|
||||||
|
|
||||||
if (keyboard[(Key)Right.StickUp]) dy = short.MaxValue;
|
if (keyboard[(Key)RightJoycon.StickUp]) dy = short.MaxValue;
|
||||||
if (keyboard[(Key)Right.StickDown]) dy = -short.MaxValue;
|
if (keyboard[(Key)RightJoycon.StickDown]) dy = -short.MaxValue;
|
||||||
if (keyboard[(Key)Right.StickLeft]) dx = -short.MaxValue;
|
if (keyboard[(Key)RightJoycon.StickLeft]) dx = -short.MaxValue;
|
||||||
if (keyboard[(Key)Right.StickRight]) dx = short.MaxValue;
|
if (keyboard[(Key)RightJoycon.StickRight]) dx = short.MaxValue;
|
||||||
|
|
||||||
return (dx, dy);
|
return (dx, dy);
|
||||||
}
|
}
|
||||||
|
|
823
Ryujinx/_schema.json
Normal file
823
Ryujinx/_schema.json
Normal file
|
@ -0,0 +1,823 @@
|
||||||
|
{
|
||||||
|
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||||
|
"$id": "https://ryujinx.org/_schema/config.json",
|
||||||
|
"type": "object",
|
||||||
|
"title": "Ryujinx Configuration Schema",
|
||||||
|
"required": [
|
||||||
|
"graphics_shaders_dump_path",
|
||||||
|
"logging_enable_debug",
|
||||||
|
"logging_enable_stub",
|
||||||
|
"logging_enable_info",
|
||||||
|
"logging_enable_warn",
|
||||||
|
"logging_enable_error",
|
||||||
|
"logging_filtered_classes",
|
||||||
|
"enable_file_log",
|
||||||
|
"system_language",
|
||||||
|
"docked_mode",
|
||||||
|
"enable_vsync",
|
||||||
|
"enable_multicore_scheduling",
|
||||||
|
"enable_fs_integrity_checks",
|
||||||
|
"controller_type",
|
||||||
|
"keyboard_controls",
|
||||||
|
"gamepad_controls"
|
||||||
|
],
|
||||||
|
"definitions": {
|
||||||
|
"key": {
|
||||||
|
"type": "string",
|
||||||
|
"enum": [
|
||||||
|
"ShiftLeft",
|
||||||
|
"LShift",
|
||||||
|
"ShiftRight",
|
||||||
|
"RShift",
|
||||||
|
"ControlLeft",
|
||||||
|
"LControl",
|
||||||
|
"ControlRight",
|
||||||
|
"RControl",
|
||||||
|
"AltLeft",
|
||||||
|
"LAlt",
|
||||||
|
"AltRight",
|
||||||
|
"RAlt",
|
||||||
|
"WinLeft",
|
||||||
|
"LWin",
|
||||||
|
"WinRight",
|
||||||
|
"RWin",
|
||||||
|
"Menu",
|
||||||
|
"F1",
|
||||||
|
"F2",
|
||||||
|
"F3",
|
||||||
|
"F4",
|
||||||
|
"F5",
|
||||||
|
"F6",
|
||||||
|
"F7",
|
||||||
|
"F8",
|
||||||
|
"F9",
|
||||||
|
"F10",
|
||||||
|
"F11",
|
||||||
|
"F12",
|
||||||
|
"F13",
|
||||||
|
"F14",
|
||||||
|
"F15",
|
||||||
|
"F16",
|
||||||
|
"F17",
|
||||||
|
"F18",
|
||||||
|
"F19",
|
||||||
|
"F20",
|
||||||
|
"F21",
|
||||||
|
"F22",
|
||||||
|
"F23",
|
||||||
|
"F24",
|
||||||
|
"F25",
|
||||||
|
"F26",
|
||||||
|
"F27",
|
||||||
|
"F28",
|
||||||
|
"F29",
|
||||||
|
"F30",
|
||||||
|
"F31",
|
||||||
|
"F32",
|
||||||
|
"F33",
|
||||||
|
"F34",
|
||||||
|
"F35",
|
||||||
|
"Up",
|
||||||
|
"Down",
|
||||||
|
"Left",
|
||||||
|
"Right",
|
||||||
|
"Enter",
|
||||||
|
"Escape",
|
||||||
|
"Space",
|
||||||
|
"Tab",
|
||||||
|
"BackSpace",
|
||||||
|
"Back",
|
||||||
|
"Insert",
|
||||||
|
"Delete",
|
||||||
|
"PageUp",
|
||||||
|
"PageDown",
|
||||||
|
"Home",
|
||||||
|
"End",
|
||||||
|
"CapsLock",
|
||||||
|
"ScrollLock",
|
||||||
|
"PrintScreen",
|
||||||
|
"Pause",
|
||||||
|
"NumLock",
|
||||||
|
"Clear",
|
||||||
|
"Sleep",
|
||||||
|
"Keypad0",
|
||||||
|
"Keypad1",
|
||||||
|
"Keypad2",
|
||||||
|
"Keypad3",
|
||||||
|
"Keypad4",
|
||||||
|
"Keypad5",
|
||||||
|
"Keypad6",
|
||||||
|
"Keypad7",
|
||||||
|
"Keypad8",
|
||||||
|
"Keypad9",
|
||||||
|
"KeypadDivide",
|
||||||
|
"KeypadMultiply",
|
||||||
|
"KeypadSubtract",
|
||||||
|
"KeypadMinus",
|
||||||
|
"KeypadAdd",
|
||||||
|
"KeypadPlus",
|
||||||
|
"KeypadDecimal",
|
||||||
|
"KeypadPeriod",
|
||||||
|
"KeypadEnter",
|
||||||
|
"A",
|
||||||
|
"B",
|
||||||
|
"C",
|
||||||
|
"D",
|
||||||
|
"E",
|
||||||
|
"F",
|
||||||
|
"G",
|
||||||
|
"H",
|
||||||
|
"I",
|
||||||
|
"J",
|
||||||
|
"K",
|
||||||
|
"L",
|
||||||
|
"M",
|
||||||
|
"N",
|
||||||
|
"O",
|
||||||
|
"P",
|
||||||
|
"Q",
|
||||||
|
"R",
|
||||||
|
"S",
|
||||||
|
"T",
|
||||||
|
"U",
|
||||||
|
"V",
|
||||||
|
"W",
|
||||||
|
"X",
|
||||||
|
"Y",
|
||||||
|
"Z",
|
||||||
|
"Number0",
|
||||||
|
"Number1",
|
||||||
|
"Number2",
|
||||||
|
"Number3",
|
||||||
|
"Number4",
|
||||||
|
"Number5",
|
||||||
|
"Number6",
|
||||||
|
"Number7",
|
||||||
|
"Number8",
|
||||||
|
"Number9",
|
||||||
|
"Tilde",
|
||||||
|
"Grave",
|
||||||
|
"Minus",
|
||||||
|
"Plus",
|
||||||
|
"BracketLeft",
|
||||||
|
"LBracket",
|
||||||
|
"BracketRight",
|
||||||
|
"RBracket",
|
||||||
|
"Semicolon",
|
||||||
|
"Quote",
|
||||||
|
"Comma",
|
||||||
|
"Period",
|
||||||
|
"Slash",
|
||||||
|
"BackSlash",
|
||||||
|
"NonUSBackSlash",
|
||||||
|
"LastKey"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"input": {
|
||||||
|
"type": "string",
|
||||||
|
"enum": [
|
||||||
|
"DPadUp",
|
||||||
|
"DPadDown",
|
||||||
|
"DPadLeft",
|
||||||
|
"DPadRight",
|
||||||
|
"LStick",
|
||||||
|
"RStick",
|
||||||
|
"LShoulder",
|
||||||
|
"RShoulder",
|
||||||
|
"LTrigger",
|
||||||
|
"RTrigger",
|
||||||
|
"LJoystick",
|
||||||
|
"RJoystick",
|
||||||
|
"A",
|
||||||
|
"B",
|
||||||
|
"X",
|
||||||
|
"Y",
|
||||||
|
"Start",
|
||||||
|
"Back"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"properties": {
|
||||||
|
"graphics_shaders_dump_path": {
|
||||||
|
"$id": "#/properties/graphics_shaders_dump_path",
|
||||||
|
"type": "string",
|
||||||
|
"title": "Graphics Shaders Dump Path",
|
||||||
|
"description": "Dumps shaders in this local directory",
|
||||||
|
"default": "",
|
||||||
|
"examples": [
|
||||||
|
"C:\\ShaderDumps"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"logging_enable_debug": {
|
||||||
|
"$id": "#/properties/logging_enable_debug",
|
||||||
|
"type": "boolean",
|
||||||
|
"title": "Logging Enable Debug",
|
||||||
|
"description": "Enables printing debug log messages",
|
||||||
|
"default": false,
|
||||||
|
"examples": [
|
||||||
|
true,
|
||||||
|
false
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"logging_enable_stub": {
|
||||||
|
"$id": "#/properties/logging_enable_stub",
|
||||||
|
"type": "boolean",
|
||||||
|
"title": "Logging Enable Stub",
|
||||||
|
"description": "Enables printing stub log messages",
|
||||||
|
"default": true,
|
||||||
|
"examples": [
|
||||||
|
true,
|
||||||
|
false
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"logging_enable_info": {
|
||||||
|
"$id": "#/properties/logging_enable_info",
|
||||||
|
"type": "boolean",
|
||||||
|
"title": "Logging Enable Info",
|
||||||
|
"description": "Enables printing info log messages",
|
||||||
|
"default": true,
|
||||||
|
"examples": [
|
||||||
|
true,
|
||||||
|
false
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"logging_enable_warn": {
|
||||||
|
"$id": "#/properties/logging_enable_warn",
|
||||||
|
"type": "boolean",
|
||||||
|
"title": "Logging Enable Warn",
|
||||||
|
"description": "Enables printing warning log messages",
|
||||||
|
"default": true,
|
||||||
|
"examples": [
|
||||||
|
true,
|
||||||
|
false
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"logging_enable_error": {
|
||||||
|
"$id": "#/properties/logging_enable_error",
|
||||||
|
"type": "boolean",
|
||||||
|
"title": "Logging Enable Error",
|
||||||
|
"description": "Enables printing error log messages",
|
||||||
|
"default": true,
|
||||||
|
"examples": [
|
||||||
|
true,
|
||||||
|
false
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"logging_filtered_classes": {
|
||||||
|
"$id": "#/properties/logging_filtered_classes",
|
||||||
|
"type": "array",
|
||||||
|
"title": "Logging Filtered Classes",
|
||||||
|
"description": "Controls which log messages are written to the log targets",
|
||||||
|
"items": {
|
||||||
|
"type": "string",
|
||||||
|
"enum": [
|
||||||
|
"Application",
|
||||||
|
"Audio",
|
||||||
|
"Cpu",
|
||||||
|
"Font",
|
||||||
|
"Emulation",
|
||||||
|
"Gpu",
|
||||||
|
"Hid",
|
||||||
|
"Kernel",
|
||||||
|
"KernelIpc",
|
||||||
|
"KernelScheduler",
|
||||||
|
"KernelSvc",
|
||||||
|
"Loader",
|
||||||
|
"Service",
|
||||||
|
"ServiceAcc",
|
||||||
|
"ServiceAm",
|
||||||
|
"ServiceApm",
|
||||||
|
"ServiceAudio",
|
||||||
|
"ServiceBsd",
|
||||||
|
"ServiceCaps",
|
||||||
|
"ServiceFriend",
|
||||||
|
"ServiceFs",
|
||||||
|
"ServiceHid",
|
||||||
|
"ServiceIrs",
|
||||||
|
"ServiceLdr",
|
||||||
|
"ServiceLm",
|
||||||
|
"ServiceMm",
|
||||||
|
"ServiceNfp",
|
||||||
|
"ServiceNifm",
|
||||||
|
"ServiceNs",
|
||||||
|
"ServiceNv",
|
||||||
|
"ServicePctl",
|
||||||
|
"ServicePl",
|
||||||
|
"ServicePrepo",
|
||||||
|
"ServicePsm",
|
||||||
|
"ServiceSet",
|
||||||
|
"ServiceSfdnsres",
|
||||||
|
"ServiceSm",
|
||||||
|
"ServiceSsl",
|
||||||
|
"ServiceSss",
|
||||||
|
"ServiceTime",
|
||||||
|
"ServiceVi"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"enable_file_log": {
|
||||||
|
"$id": "#/properties/enable_file_log",
|
||||||
|
"type": "boolean",
|
||||||
|
"title": "Enable File Log",
|
||||||
|
"description": "Enables logging to a file on disk",
|
||||||
|
"default": true,
|
||||||
|
"examples": [
|
||||||
|
true,
|
||||||
|
false
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"system_language": {
|
||||||
|
"$id": "#/properties/system_language",
|
||||||
|
"type": "string",
|
||||||
|
"title": "System Language",
|
||||||
|
"description": "Change System Language",
|
||||||
|
"default": "AmericanEnglish",
|
||||||
|
"enum": [
|
||||||
|
"Japanese",
|
||||||
|
"AmericanEnglish",
|
||||||
|
"French",
|
||||||
|
"German",
|
||||||
|
"Italian",
|
||||||
|
"Spanish",
|
||||||
|
"Chinese",
|
||||||
|
"Korean",
|
||||||
|
"Dutch",
|
||||||
|
"Portuguese",
|
||||||
|
"Russian",
|
||||||
|
"Taiwanese",
|
||||||
|
"BritishEnglish",
|
||||||
|
"CanadianFrench",
|
||||||
|
"LatinAmericanSpanish",
|
||||||
|
"SimplifiedChinese",
|
||||||
|
"TraditionalChinese"
|
||||||
|
],
|
||||||
|
"examples": [
|
||||||
|
"AmericanEnglish"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"docked_mode": {
|
||||||
|
"$id": "#/properties/docked_mode",
|
||||||
|
"type": "boolean",
|
||||||
|
"title": "Enable Docked Mode",
|
||||||
|
"description": "Enables or disables Docked Mode",
|
||||||
|
"default": false,
|
||||||
|
"examples": [
|
||||||
|
true,
|
||||||
|
false
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"enable_vsync": {
|
||||||
|
"$id": "#/properties/enable_vsync",
|
||||||
|
"type": "boolean",
|
||||||
|
"title": "Enable Vertical Sync",
|
||||||
|
"description": "Enables or disables Vertical Sync",
|
||||||
|
"default": true,
|
||||||
|
"examples": [
|
||||||
|
true,
|
||||||
|
false
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"enable_multicore_scheduling": {
|
||||||
|
"$id": "#/properties/enable_multicore_scheduling",
|
||||||
|
"type": "boolean",
|
||||||
|
"title": "Enable Multicore Scheduling",
|
||||||
|
"description": "Enables or disables multi-core scheduling of threads",
|
||||||
|
"default": false,
|
||||||
|
"examples": [
|
||||||
|
true,
|
||||||
|
false
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"enable_fs_integrity_checks": {
|
||||||
|
"$id": "#/properties/enable_fs_integrity_checks",
|
||||||
|
"type": "boolean",
|
||||||
|
"title": "Enable Filesystem Integrity Checks",
|
||||||
|
"description": "Enables integrity checks on Game content files. Only applies to ROMs loaded as XCI files",
|
||||||
|
"default": true,
|
||||||
|
"examples": [
|
||||||
|
true,
|
||||||
|
false
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"controller_type": {
|
||||||
|
"$id": "#/properties/controller_type",
|
||||||
|
"type": "string",
|
||||||
|
"title": "Controller Type",
|
||||||
|
"default": "Handheld",
|
||||||
|
"enum": [
|
||||||
|
"Handheld",
|
||||||
|
"ProController",
|
||||||
|
"NpadPair",
|
||||||
|
"NpadLeft",
|
||||||
|
"NpadRight"
|
||||||
|
],
|
||||||
|
"examples": [
|
||||||
|
"Handheld",
|
||||||
|
"ProController",
|
||||||
|
"NpadPair",
|
||||||
|
"NpadLeft",
|
||||||
|
"NpadRight"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"keyboard_controls": {
|
||||||
|
"$id": "#/properties/keyboard_controls",
|
||||||
|
"type": "object",
|
||||||
|
"title": "Keyboard Controls",
|
||||||
|
"required": [
|
||||||
|
"left_joycon",
|
||||||
|
"right_joycon"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"left_joycon": {
|
||||||
|
"$id": "#/properties/keyboard_controls/properties/left_joycon",
|
||||||
|
"type": "object",
|
||||||
|
"title": "Left JoyCon Controls",
|
||||||
|
"required": [
|
||||||
|
"stick_up",
|
||||||
|
"stick_down",
|
||||||
|
"stick_left",
|
||||||
|
"stick_right",
|
||||||
|
"stick_button",
|
||||||
|
"dpad_up",
|
||||||
|
"dpad_down",
|
||||||
|
"dpad_left",
|
||||||
|
"dpad_right",
|
||||||
|
"button_minus",
|
||||||
|
"button_l",
|
||||||
|
"button_zl"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"stick_up": {
|
||||||
|
"$id": "#/properties/keyboard_controls/properties/left_joycon/properties/stick_up",
|
||||||
|
"$ref": "#/definitions/key",
|
||||||
|
"title": "Stick Up",
|
||||||
|
"default": "w"
|
||||||
|
},
|
||||||
|
"stick_down": {
|
||||||
|
"$id": "#/properties/keyboard_controls/properties/left_joycon/properties/stick_down",
|
||||||
|
"$ref": "#/definitions/key",
|
||||||
|
"title": "Stick Down",
|
||||||
|
"default": "S"
|
||||||
|
},
|
||||||
|
"stick_left": {
|
||||||
|
"$id": "#/properties/keyboard_controls/properties/left_joycon/properties/stick_left",
|
||||||
|
"$ref": "#/definitions/key",
|
||||||
|
"title": "Stick Left",
|
||||||
|
"default": "A"
|
||||||
|
},
|
||||||
|
"stick_right": {
|
||||||
|
"$id": "#/properties/keyboard_controls/properties/left_joycon/properties/stick_right",
|
||||||
|
"$ref": "#/definitions/key",
|
||||||
|
"title": "Stick Right",
|
||||||
|
"default": "D"
|
||||||
|
},
|
||||||
|
"stick_button": {
|
||||||
|
"$id": "#/properties/keyboard_controls/properties/left_joycon/properties/stick_button",
|
||||||
|
"$ref": "#/definitions/key",
|
||||||
|
"title": "Stick Button",
|
||||||
|
"default": "F"
|
||||||
|
},
|
||||||
|
"dpad_up": {
|
||||||
|
"$id": "#/properties/keyboard_controls/properties/left_joycon/properties/dpad_up",
|
||||||
|
"$ref": "#/definitions/key",
|
||||||
|
"title": "Dpad Up",
|
||||||
|
"default": "Up"
|
||||||
|
},
|
||||||
|
"dpad_down": {
|
||||||
|
"$id": "#/properties/keyboard_controls/properties/left_joycon/properties/dpad_down",
|
||||||
|
"$ref": "#/definitions/key",
|
||||||
|
"title": "Dpad Down",
|
||||||
|
"default": "Down"
|
||||||
|
},
|
||||||
|
"dpad_left": {
|
||||||
|
"$id": "#/properties/keyboard_controls/properties/left_joycon/properties/dpad_left",
|
||||||
|
"$ref": "#/definitions/key",
|
||||||
|
"title": "Dpad Left",
|
||||||
|
"default": "Left"
|
||||||
|
},
|
||||||
|
"dpad_right": {
|
||||||
|
"$id": "#/properties/keyboard_controls/properties/left_joycon/properties/dpad_right",
|
||||||
|
"$ref": "#/definitions/key",
|
||||||
|
"title": "Dpad Right",
|
||||||
|
"default": "Right"
|
||||||
|
},
|
||||||
|
"button_minus": {
|
||||||
|
"$id": "#/properties/keyboard_controls/properties/left_joycon/properties/button_minus",
|
||||||
|
"$ref": "#/definitions/key",
|
||||||
|
"title": "Button Minus",
|
||||||
|
"default": "Minus"
|
||||||
|
},
|
||||||
|
"button_l": {
|
||||||
|
"$id": "#/properties/keyboard_controls/properties/left_joycon/properties/button_l",
|
||||||
|
"$ref": "#/definitions/key",
|
||||||
|
"title": "Button L",
|
||||||
|
"default": "E"
|
||||||
|
},
|
||||||
|
"button_zl": {
|
||||||
|
"$id": "#/properties/keyboard_controls/properties/left_joycon/properties/button_zl",
|
||||||
|
"$ref": "#/definitions/key",
|
||||||
|
"title": "Button ZL",
|
||||||
|
"default": "Q"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"right_joycon": {
|
||||||
|
"$id": "#/properties/keyboard_controls/properties/right_joycon",
|
||||||
|
"type": "object",
|
||||||
|
"title": "Right JoyCon Controls",
|
||||||
|
"required": [
|
||||||
|
"stick_up",
|
||||||
|
"stick_down",
|
||||||
|
"stick_left",
|
||||||
|
"stick_right",
|
||||||
|
"stick_button",
|
||||||
|
"button_a",
|
||||||
|
"button_b",
|
||||||
|
"button_x",
|
||||||
|
"button_y",
|
||||||
|
"button_plus",
|
||||||
|
"button_r",
|
||||||
|
"button_zr"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"stick_up": {
|
||||||
|
"$id": "#/properties/keyboard_controls/properties/right_joycon/properties/stick_up",
|
||||||
|
"$ref": "#/definitions/key",
|
||||||
|
"title": "Stick Up",
|
||||||
|
"default": "I"
|
||||||
|
},
|
||||||
|
"stick_down": {
|
||||||
|
"$id": "#/properties/keyboard_controls/properties/right_joycon/properties/stick_down",
|
||||||
|
"$ref": "#/definitions/key",
|
||||||
|
"title": "Stick Down",
|
||||||
|
"default": "K"
|
||||||
|
},
|
||||||
|
"stick_left": {
|
||||||
|
"$id": "#/properties/keyboard_controls/properties/right_joycon/properties/stick_left",
|
||||||
|
"$ref": "#/definitions/key",
|
||||||
|
"title": "Stick Left",
|
||||||
|
"default": "J"
|
||||||
|
},
|
||||||
|
"stick_right": {
|
||||||
|
"$id": "#/properties/keyboard_controls/properties/right_joycon/properties/stick_right",
|
||||||
|
"$ref": "#/definitions/key",
|
||||||
|
"title": "Stick Right",
|
||||||
|
"default": "L"
|
||||||
|
},
|
||||||
|
"stick_button": {
|
||||||
|
"$id": "#/properties/keyboard_controls/properties/right_joycon/properties/stick_button",
|
||||||
|
"$ref": "#/definitions/key",
|
||||||
|
"title": "Stick Button",
|
||||||
|
"default": "H"
|
||||||
|
},
|
||||||
|
"button_a": {
|
||||||
|
"$id": "#/properties/keyboard_controls/properties/right_joycon/properties/button_a",
|
||||||
|
"$ref": "#/definitions/key",
|
||||||
|
"title": "Button A",
|
||||||
|
"default": "Z"
|
||||||
|
},
|
||||||
|
"button_b": {
|
||||||
|
"$id": "#/properties/keyboard_controls/properties/right_joycon/properties/button_b",
|
||||||
|
"$ref": "#/definitions/key",
|
||||||
|
"title": "Button B",
|
||||||
|
"default": "X"
|
||||||
|
},
|
||||||
|
"button_x": {
|
||||||
|
"$id": "#/properties/keyboard_controls/properties/right_joycon/properties/button_x",
|
||||||
|
"$ref": "#/definitions/key",
|
||||||
|
"title": "Button X",
|
||||||
|
"default": "C"
|
||||||
|
},
|
||||||
|
"button_y": {
|
||||||
|
"$id": "#/properties/keyboard_controls/properties/right_joycon/properties/button_y",
|
||||||
|
"$ref": "#/definitions/key",
|
||||||
|
"title": "Button Y",
|
||||||
|
"default": "V"
|
||||||
|
},
|
||||||
|
"button_plus": {
|
||||||
|
"$id": "#/properties/keyboard_controls/properties/right_joycon/properties/button_plus",
|
||||||
|
"$ref": "#/definitions/key",
|
||||||
|
"title": "Button Plus",
|
||||||
|
"default": "Plus"
|
||||||
|
},
|
||||||
|
"button_r": {
|
||||||
|
"$id": "#/properties/keyboard_controls/properties/right_joycon/properties/button_r",
|
||||||
|
"$ref": "#/definitions/key",
|
||||||
|
"title": "Button R",
|
||||||
|
"default": "U"
|
||||||
|
},
|
||||||
|
"button_zr": {
|
||||||
|
"$id": "#/properties/keyboard_controls/properties/right_joycon/properties/button_zr",
|
||||||
|
"$ref": "#/definitions/key",
|
||||||
|
"title": "Button Zr",
|
||||||
|
"default": "O"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"gamepad_controls": {
|
||||||
|
"$id": "#/properties/gamepad_controls",
|
||||||
|
"type": "object",
|
||||||
|
"title": "GamePad Controls",
|
||||||
|
"required": [
|
||||||
|
"left_joycon",
|
||||||
|
"right_joycon"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"enable": {
|
||||||
|
"$id": "#/properties/gamepad_controls/properties/enable",
|
||||||
|
"type": "boolean",
|
||||||
|
"title": "Gamepad Enable",
|
||||||
|
"description": "Enables or disables controller support",
|
||||||
|
"default": true,
|
||||||
|
"examples": [
|
||||||
|
true,
|
||||||
|
false
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"index": {
|
||||||
|
"$id": "#/properties/gamepad_controls/properties/index",
|
||||||
|
"type": "integer",
|
||||||
|
"title": "Gamepad Index",
|
||||||
|
"description": "Controller Device Index",
|
||||||
|
"default": 0,
|
||||||
|
"minimum": 0,
|
||||||
|
"examples": [
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
2
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"deadzone": {
|
||||||
|
"$id": "#/properties/gamepad_controls/properties/deadzone",
|
||||||
|
"type": "number",
|
||||||
|
"title": "Gamepad Deadzone",
|
||||||
|
"description": "Controller Analog Stick Deadzone",
|
||||||
|
"default": 0.05,
|
||||||
|
"minimum": -32768.0,
|
||||||
|
"maximum": 32767.0,
|
||||||
|
"examples": [
|
||||||
|
0.05
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"trigger_threshold": {
|
||||||
|
"$id": "#/properties/gamepad_controls/properties/trigger_threshold",
|
||||||
|
"type": "number",
|
||||||
|
"title": "Controller Trigger Threshold",
|
||||||
|
"description": "The value of how pressed down each trigger has to be in order to register a button press",
|
||||||
|
"default": 0.5,
|
||||||
|
"minimum": 0.0,
|
||||||
|
"maximum": 1.0,
|
||||||
|
"examples": [
|
||||||
|
0.5
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"left_joycon": {
|
||||||
|
"$id": "#/properties/gamepad_controls/properties/left_joycon",
|
||||||
|
"type": "object",
|
||||||
|
"title": "Left JoyCon Controls",
|
||||||
|
"required": [
|
||||||
|
"stick",
|
||||||
|
"stick_button",
|
||||||
|
"dpad_up",
|
||||||
|
"dpad_down",
|
||||||
|
"dpad_left",
|
||||||
|
"dpad_right",
|
||||||
|
"button_minus",
|
||||||
|
"button_l",
|
||||||
|
"button_zl"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"stick": {
|
||||||
|
"$id": "#/properties/gamepad_controls/properties/left_joycon/properties/stick",
|
||||||
|
"$ref": "#/definitions/input",
|
||||||
|
"title": "Stick",
|
||||||
|
"default": "LJoystick"
|
||||||
|
},
|
||||||
|
"stick_button": {
|
||||||
|
"$id": "#/properties/gamepad_controls/properties/left_joycon/properties/stick_button",
|
||||||
|
"$ref": "#/definitions/input",
|
||||||
|
"title": "Stick Button",
|
||||||
|
"default": "LStick"
|
||||||
|
},
|
||||||
|
"dpad_up": {
|
||||||
|
"$id": "#/properties/gamepad_controls/properties/left_joycon/properties/dpad_up",
|
||||||
|
"$ref": "#/definitions/input",
|
||||||
|
"title": "Dpad Up",
|
||||||
|
"default": "DPadUp"
|
||||||
|
},
|
||||||
|
"dpad_down": {
|
||||||
|
"$id": "#/properties/gamepad_controls/properties/left_joycon/properties/dpad_down",
|
||||||
|
"$ref": "#/definitions/input",
|
||||||
|
"title": "Dpad Down",
|
||||||
|
"default": "DPadDown"
|
||||||
|
},
|
||||||
|
"dpad_left": {
|
||||||
|
"$id": "#/properties/gamepad_controls/properties/left_joycon/properties/dpad_left",
|
||||||
|
"$ref": "#/definitions/input",
|
||||||
|
"title": "Dpad Left",
|
||||||
|
"default": "DPadLeft"
|
||||||
|
},
|
||||||
|
"dpad_right": {
|
||||||
|
"$id": "#/properties/gamepad_controls/properties/left_joycon/properties/dpad_right",
|
||||||
|
"$ref": "#/definitions/input",
|
||||||
|
"title": "Dpad Right",
|
||||||
|
"default": "DPadRight"
|
||||||
|
},
|
||||||
|
"button_minus": {
|
||||||
|
"$id": "#/properties/gamepad_controls/properties/left_joycon/properties/button_minus",
|
||||||
|
"$ref": "#/definitions/input",
|
||||||
|
"title": "Button Minus",
|
||||||
|
"default": "Back"
|
||||||
|
},
|
||||||
|
"button_l": {
|
||||||
|
"$id": "#/properties/gamepad_controls/properties/left_joycon/properties/button_l",
|
||||||
|
"$ref": "#/definitions/input",
|
||||||
|
"title": "Button L",
|
||||||
|
"default": "LShoulder"
|
||||||
|
},
|
||||||
|
"button_zl": {
|
||||||
|
"$id": "#/properties/gamepad_controls/properties/left_joycon/properties/button_zl",
|
||||||
|
"$ref": "#/definitions/input",
|
||||||
|
"title": "Button ZL",
|
||||||
|
"default": "LTrigger"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"right_joycon": {
|
||||||
|
"$id": "#/properties/gamepad_controls/properties/right_joycon",
|
||||||
|
"type": "object",
|
||||||
|
"title": "Right JoyCon Controls",
|
||||||
|
"required": [
|
||||||
|
"stick",
|
||||||
|
"stick_button",
|
||||||
|
"button_a",
|
||||||
|
"button_b",
|
||||||
|
"button_x",
|
||||||
|
"button_y",
|
||||||
|
"button_plus",
|
||||||
|
"button_r",
|
||||||
|
"button_zr"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"stick": {
|
||||||
|
"$id": "#/properties/gamepad_controls/properties/right_joycon/properties/stick",
|
||||||
|
"$ref": "#/definitions/input",
|
||||||
|
"title": "Stick",
|
||||||
|
"default": "RJoystick"
|
||||||
|
},
|
||||||
|
"stick_button": {
|
||||||
|
"$id": "#/properties/gamepad_controls/properties/right_joycon/properties/stick_button",
|
||||||
|
"$ref": "#/definitions/input",
|
||||||
|
"title": "Stick Button",
|
||||||
|
"default": "RStick"
|
||||||
|
},
|
||||||
|
"button_a": {
|
||||||
|
"$id": "#/properties/gamepad_controls/properties/right_joycon/properties/button_a",
|
||||||
|
"$ref": "#/definitions/input",
|
||||||
|
"title": "Button A",
|
||||||
|
"default": "B"
|
||||||
|
},
|
||||||
|
"button_b": {
|
||||||
|
"$id": "#/properties/gamepad_controls/properties/right_joycon/properties/button_b",
|
||||||
|
"$ref": "#/definitions/input",
|
||||||
|
"title": "Button B",
|
||||||
|
"default": "A"
|
||||||
|
},
|
||||||
|
"button_x": {
|
||||||
|
"$id": "#/properties/gamepad_controls/properties/right_joycon/properties/button_x",
|
||||||
|
"$ref": "#/definitions/input",
|
||||||
|
"title": "Button X",
|
||||||
|
"default": "Y"
|
||||||
|
},
|
||||||
|
"button_y": {
|
||||||
|
"$id": "#/properties/gamepad_controls/properties/right_joycon/properties/button_y",
|
||||||
|
"$ref": "#/definitions/input",
|
||||||
|
"title": "Button Y",
|
||||||
|
"default": "X"
|
||||||
|
},
|
||||||
|
"button_plus": {
|
||||||
|
"$id": "#/properties/gamepad_controls/properties/right_joycon/properties/button_plus",
|
||||||
|
"$ref": "#/definitions/input",
|
||||||
|
"title": "Button Plus",
|
||||||
|
"default": "Start"
|
||||||
|
},
|
||||||
|
"button_r": {
|
||||||
|
"$id": "#/properties/gamepad_controls/properties/right_joycon/properties/button_r",
|
||||||
|
"$ref": "#/definitions/input",
|
||||||
|
"title": "Button R",
|
||||||
|
"default": "RShoulder"
|
||||||
|
},
|
||||||
|
"button_zr": {
|
||||||
|
"$id": "#/properties/gamepad_controls/properties/right_joycon/properties/button_zr",
|
||||||
|
"$ref": "#/definitions/input",
|
||||||
|
"title": "Button ZR",
|
||||||
|
"default": "RTrigger"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue