mirror of
https://github.com/GreemDev/Ryujinx
synced 2024-11-21 09:30:53 +01:00
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
210
CONFIG.md
210
CONFIG.md
|
@ -1,123 +1,124 @@
|
|||
## 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.
|
||||
|
||||
- `Logging_Enable_Trace` *(bool)*
|
||||
- `logging_enable_warn` *(bool)*
|
||||
|
||||
Enable the Trace Logging (Enabled in Debug recommended).
|
||||
|
||||
- `Logging_Enable_Debug` *(bool)*
|
||||
Enable the Warning Logging.
|
||||
|
||||
Enable the Debug Logging (Enabled in Debug recommended).
|
||||
- `logging_enable_error` *(bool)*
|
||||
|
||||
- `Logging_Enable_Warn` *(bool)*
|
||||
Enable the Error Logging.
|
||||
|
||||
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_file_log` *(bool)*
|
||||
|
||||
Enable writing the logging inside a Ryujinx.log file.
|
||||
|
||||
- `GamePad_Index` *(int)*
|
||||
|
||||
The index of the Controller Device.
|
||||
|
||||
- `GamePad_Deadzone` *(float)*
|
||||
- `system_language` *(string)*
|
||||
|
||||
The deadzone of both analog sticks on the Controller.
|
||||
Change System Language, [System Language list](https://gist.github.com/HorrorTroll/b6e4a88d774c3c9b3bdf54d79a7ca43b)
|
||||
|
||||
- `GamePad_Enable` *(bool)*
|
||||
|
||||
Whether or not to enable Controller Support.
|
||||
|
||||
- `Controls_Left_JoyConKeyboard_XX` *(int)*
|
||||
```
|
||||
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).
|
||||
- `docked_mode` *(bool)*
|
||||
|
||||
- `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)
|
||||
```
|
||||
Enable or Disable Docked Mode
|
||||
|
||||
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)
|
||||
```
|
||||
- `enable_vsync` *(bool)*
|
||||
|
||||
- Default Mapping
|
||||
- Controller
|
||||
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.
|
||||
- `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)*
|
||||
|
||||
### Default Mapping
|
||||
#### Controller
|
||||
- Left Joycon:
|
||||
- Analog Stick = Left Analog Stick
|
||||
- DPad Up = DPad Up
|
||||
|
@ -137,7 +138,8 @@
|
|||
- Plus = Start / Options
|
||||
- R = Right Shoulder Button
|
||||
- ZR = Right Trigger
|
||||
- Keyboard
|
||||
|
||||
#### Keyboard
|
||||
- Left Joycon:
|
||||
- Stick Up = W
|
||||
- Stick Down = S
|
||||
|
@ -166,7 +168,7 @@
|
|||
- R = U
|
||||
- ZR = O
|
||||
|
||||
- Valid Button Mappings
|
||||
### Valid Button Mappings
|
||||
- A = The A / Cross Button
|
||||
- B = The B / Circle 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)
|
||||
|
||||
- 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).
|
||||
|
||||
**Help**
|
||||
|
|
|
@ -1,14 +1,13 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
|
||||
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>();
|
||||
|
||||
|
@ -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>();
|
||||
|
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
|
||||
{
|
||||
Application,
|
||||
Audio,
|
||||
Cpu,
|
||||
Font,
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
|
||||
namespace Ryujinx.Common.Logging
|
||||
|
@ -14,9 +13,9 @@ namespace Ryujinx.Common.Logging
|
|||
private static readonly bool[] m_EnabledLevels;
|
||||
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()
|
||||
{
|
||||
|
@ -33,9 +32,30 @@ namespace Ryujinx.Common.Logging
|
|||
m_EnabledClasses[index] = true;
|
||||
}
|
||||
|
||||
m_LogTargets = new List<ILogTarget>();
|
||||
|
||||
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)
|
||||
{
|
||||
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>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Utf8Json" Version="1.3.7" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
|
@ -112,7 +112,6 @@ namespace Ryujinx.HLE
|
|||
if (disposing)
|
||||
{
|
||||
System.Dispose();
|
||||
|
||||
VsyncEvent.Dispose();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,6 +23,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Luea", "Ryujinx.LLE\Luea.cs
|
|||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Common", "Ryujinx.Common\Ryujinx.Common.csproj", "{5FD4E4F6-8928-4B3C-BE07-28A675C17226}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{464D8AB7-B056-4A99-B207-B8DCFB47AAA9}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
|
@ -73,6 +75,10 @@ Global
|
|||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
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
|
||||
SolutionGuid = {110169B3-3328-4730-8AB0-BA05BEF75C1A}
|
||||
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);
|
||||
|
||||
Config.Read(device);
|
||||
|
||||
Logger.Updated += Log.LogMessage;
|
||||
Configuration.Load("Config.jsonc");
|
||||
Configuration.Configure(device);
|
||||
|
||||
AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
|
||||
AppDomain.CurrentDomain.ProcessExit += CurrentDomain_ProcessExit;
|
||||
|
@ -40,13 +39,13 @@ namespace Ryujinx
|
|||
|
||||
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]);
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine("Loading as cart WITHOUT RomFS.");
|
||||
Logger.PrintInfo(LogClass.Application, "Loading as cart WITHOUT RomFS.");
|
||||
|
||||
device.LoadCart(args[0]);
|
||||
}
|
||||
|
@ -56,20 +55,20 @@ namespace Ryujinx
|
|||
switch (Path.GetExtension(args[0]).ToLowerInvariant())
|
||||
{
|
||||
case ".xci":
|
||||
Console.WriteLine("Loading as XCI.");
|
||||
Logger.PrintInfo(LogClass.Application, "Loading as XCI.");
|
||||
device.LoadXci(args[0]);
|
||||
break;
|
||||
case ".nca":
|
||||
Console.WriteLine("Loading as NCA.");
|
||||
Logger.PrintInfo(LogClass.Application, "Loading as NCA.");
|
||||
device.LoadNca(args[0]);
|
||||
break;
|
||||
case ".nsp":
|
||||
case ".pfs0":
|
||||
Console.WriteLine("Loading as NSP.");
|
||||
Logger.PrintInfo(LogClass.Application, "Loading as NSP.");
|
||||
device.LoadNsp(args[0]);
|
||||
break;
|
||||
default:
|
||||
Console.WriteLine("Loading as homebrew.");
|
||||
Logger.PrintInfo(LogClass.Application, "Loading as homebrew.");
|
||||
device.LoadProgram(args[0]);
|
||||
break;
|
||||
}
|
||||
|
@ -77,7 +76,7 @@ namespace Ryujinx
|
|||
}
|
||||
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))
|
||||
|
@ -88,11 +87,13 @@ namespace Ryujinx
|
|||
}
|
||||
|
||||
audioOut.Dispose();
|
||||
|
||||
Logger.Shutdown();
|
||||
}
|
||||
|
||||
private static void CurrentDomain_ProcessExit(object sender, EventArgs e)
|
||||
{
|
||||
Log.Close();
|
||||
Logger.Shutdown();
|
||||
}
|
||||
|
||||
private static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
|
||||
|
@ -103,7 +104,7 @@ namespace Ryujinx
|
|||
|
||||
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>
|
||||
<None Update="Ryujinx.conf">
|
||||
<None Update="Config.jsonc">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
|
|
|
@ -142,24 +142,24 @@ namespace Ryujinx
|
|||
{
|
||||
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
|
||||
if (leftJoystickDx == 0 && leftJoystickDy == 0)
|
||||
{
|
||||
(leftJoystickDx, leftJoystickDy) = Config.NpadController.GetLeftStick();
|
||||
(leftJoystickDx, leftJoystickDy) = Configuration.Instance.GamepadControls.GetLeftStick();
|
||||
}
|
||||
|
||||
if (rightJoystickDx == 0 && rightJoystickDy == 0)
|
||||
{
|
||||
(rightJoystickDx, rightJoystickDy) = Config.NpadController.GetRightStick();
|
||||
(rightJoystickDx, rightJoystickDy) = Configuration.Instance.GamepadControls.GetRightStick();
|
||||
}
|
||||
|
||||
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
|
||||
{
|
||||
Invalid,
|
||||
|
||||
LStick,
|
||||
RStick,
|
||||
LShoulder,
|
||||
RShoulder,
|
||||
LTrigger,
|
||||
RTrigger,
|
||||
LJoystick,
|
||||
RJoystick,
|
||||
DPadUp,
|
||||
DPadDown,
|
||||
DPadLeft,
|
||||
DPadRight,
|
||||
Start,
|
||||
Back,
|
||||
LShoulder,
|
||||
|
||||
RStick,
|
||||
A,
|
||||
B,
|
||||
X,
|
||||
Y,
|
||||
Start,
|
||||
RShoulder,
|
||||
|
||||
LTrigger,
|
||||
RTrigger,
|
||||
|
||||
LJoystick,
|
||||
RJoystick
|
||||
Y
|
||||
}
|
||||
|
||||
public struct NpadControllerLeft
|
||||
|
@ -60,34 +56,55 @@ namespace Ryujinx.UI.Input
|
|||
|
||||
public class NpadController
|
||||
{
|
||||
public bool Enabled { private set; get; }
|
||||
public int Index { private set; get; }
|
||||
public float Deadzone { private set; get; }
|
||||
public float TriggerThreshold { private set; get; }
|
||||
/// <summary>
|
||||
/// Enables or disables controller support
|
||||
/// </summary>
|
||||
public bool Enabled { get; private set; }
|
||||
|
||||
public NpadControllerLeft Left { private set; get; }
|
||||
public NpadControllerRight Right { private set; get; }
|
||||
/// <summary>
|
||||
/// 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(
|
||||
bool enabled,
|
||||
int index,
|
||||
float deadzone,
|
||||
float triggerThreshold,
|
||||
NpadControllerLeft left,
|
||||
NpadControllerRight right)
|
||||
bool enabled,
|
||||
int index,
|
||||
float deadzone,
|
||||
float triggerThreshold,
|
||||
NpadControllerLeft leftJoycon,
|
||||
NpadControllerRight rightJoycon)
|
||||
{
|
||||
Enabled = enabled;
|
||||
Index = index;
|
||||
Deadzone = deadzone;
|
||||
TriggerThreshold = triggerThreshold;
|
||||
Left = left;
|
||||
Right = right;
|
||||
LeftJoycon = leftJoycon;
|
||||
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()
|
||||
|
@ -101,23 +118,23 @@ namespace Ryujinx.UI.Input
|
|||
|
||||
HidControllerButtons buttons = 0;
|
||||
|
||||
if (IsPressed(gpState, Left.DPadUp)) buttons |= HidControllerButtons.DpadUp;
|
||||
if (IsPressed(gpState, Left.DPadDown)) buttons |= HidControllerButtons.DpadDown;
|
||||
if (IsPressed(gpState, Left.DPadLeft)) buttons |= HidControllerButtons.DpadLeft;
|
||||
if (IsPressed(gpState, Left.DPadRight)) buttons |= HidControllerButtons.DPadRight;
|
||||
if (IsPressed(gpState, Left.StickButton)) buttons |= HidControllerButtons.StickLeft;
|
||||
if (IsPressed(gpState, Left.ButtonMinus)) buttons |= HidControllerButtons.Minus;
|
||||
if (IsPressed(gpState, Left.ButtonL)) buttons |= HidControllerButtons.L;
|
||||
if (IsPressed(gpState, Left.ButtonZl)) buttons |= HidControllerButtons.Zl;
|
||||
if (IsPressed(gpState, LeftJoycon.DPadUp)) buttons |= HidControllerButtons.DpadUp;
|
||||
if (IsPressed(gpState, LeftJoycon.DPadDown)) buttons |= HidControllerButtons.DpadDown;
|
||||
if (IsPressed(gpState, LeftJoycon.DPadLeft)) buttons |= HidControllerButtons.DpadLeft;
|
||||
if (IsPressed(gpState, LeftJoycon.DPadRight)) buttons |= HidControllerButtons.DPadRight;
|
||||
if (IsPressed(gpState, LeftJoycon.StickButton)) buttons |= HidControllerButtons.StickLeft;
|
||||
if (IsPressed(gpState, LeftJoycon.ButtonMinus)) buttons |= HidControllerButtons.Minus;
|
||||
if (IsPressed(gpState, LeftJoycon.ButtonL)) buttons |= HidControllerButtons.L;
|
||||
if (IsPressed(gpState, LeftJoycon.ButtonZl)) buttons |= HidControllerButtons.Zl;
|
||||
|
||||
if (IsPressed(gpState, Right.ButtonA)) buttons |= HidControllerButtons.A;
|
||||
if (IsPressed(gpState, Right.ButtonB)) buttons |= HidControllerButtons.B;
|
||||
if (IsPressed(gpState, Right.ButtonX)) buttons |= HidControllerButtons.X;
|
||||
if (IsPressed(gpState, Right.ButtonY)) buttons |= HidControllerButtons.Y;
|
||||
if (IsPressed(gpState, Right.StickButton)) buttons |= HidControllerButtons.StickRight;
|
||||
if (IsPressed(gpState, Right.ButtonPlus)) buttons |= HidControllerButtons.Plus;
|
||||
if (IsPressed(gpState, Right.ButtonR)) buttons |= HidControllerButtons.R;
|
||||
if (IsPressed(gpState, Right.ButtonZr)) buttons |= HidControllerButtons.Zr;
|
||||
if (IsPressed(gpState, RightJoycon.ButtonA)) buttons |= HidControllerButtons.A;
|
||||
if (IsPressed(gpState, RightJoycon.ButtonB)) buttons |= HidControllerButtons.B;
|
||||
if (IsPressed(gpState, RightJoycon.ButtonX)) buttons |= HidControllerButtons.X;
|
||||
if (IsPressed(gpState, RightJoycon.ButtonY)) buttons |= HidControllerButtons.Y;
|
||||
if (IsPressed(gpState, RightJoycon.StickButton)) buttons |= HidControllerButtons.StickRight;
|
||||
if (IsPressed(gpState, RightJoycon.ButtonPlus)) buttons |= HidControllerButtons.Plus;
|
||||
if (IsPressed(gpState, RightJoycon.ButtonR)) buttons |= HidControllerButtons.R;
|
||||
if (IsPressed(gpState, RightJoycon.ButtonZr)) buttons |= HidControllerButtons.Zr;
|
||||
|
||||
return buttons;
|
||||
}
|
||||
|
@ -129,7 +146,7 @@ namespace Ryujinx.UI.Input
|
|||
return (0, 0);
|
||||
}
|
||||
|
||||
return GetStick(Left.Stick);
|
||||
return GetStick(LeftJoycon.Stick);
|
||||
}
|
||||
|
||||
public (short, short) GetRightStick()
|
||||
|
@ -139,7 +156,7 @@ namespace Ryujinx.UI.Input
|
|||
return (0, 0);
|
||||
}
|
||||
|
||||
return GetStick(Right.Stick);
|
||||
return GetStick(RightJoycon.Stick);
|
||||
}
|
||||
|
||||
private (short, short) GetStick(ControllerInputId joystick)
|
||||
|
|
|
@ -5,70 +5,69 @@ namespace Ryujinx.UI.Input
|
|||
{
|
||||
public struct NpadKeyboardLeft
|
||||
{
|
||||
public int StickUp;
|
||||
public int StickDown;
|
||||
public int StickLeft;
|
||||
public int StickRight;
|
||||
public int StickButton;
|
||||
public int DPadUp;
|
||||
public int DPadDown;
|
||||
public int DPadLeft;
|
||||
public int DPadRight;
|
||||
public int ButtonMinus;
|
||||
public int ButtonL;
|
||||
public int ButtonZl;
|
||||
public Key StickUp;
|
||||
public Key StickDown;
|
||||
public Key StickLeft;
|
||||
public Key StickRight;
|
||||
public Key StickButton;
|
||||
public Key DPadUp;
|
||||
public Key DPadDown;
|
||||
public Key DPadLeft;
|
||||
public Key DPadRight;
|
||||
public Key ButtonMinus;
|
||||
public Key ButtonL;
|
||||
public Key ButtonZl;
|
||||
}
|
||||
|
||||
public struct NpadKeyboardRight
|
||||
{
|
||||
public int StickUp;
|
||||
public int StickDown;
|
||||
public int StickLeft;
|
||||
public int StickRight;
|
||||
public int StickButton;
|
||||
public int ButtonA;
|
||||
public int ButtonB;
|
||||
public int ButtonX;
|
||||
public int ButtonY;
|
||||
public int ButtonPlus;
|
||||
public int ButtonR;
|
||||
public int ButtonZr;
|
||||
public Key StickUp;
|
||||
public Key StickDown;
|
||||
public Key StickLeft;
|
||||
public Key StickRight;
|
||||
public Key StickButton;
|
||||
public Key ButtonA;
|
||||
public Key ButtonB;
|
||||
public Key ButtonX;
|
||||
public Key ButtonY;
|
||||
public Key ButtonPlus;
|
||||
public Key ButtonR;
|
||||
public Key ButtonZr;
|
||||
}
|
||||
|
||||
public class NpadKeyboard
|
||||
{
|
||||
public NpadKeyboardLeft Left;
|
||||
public NpadKeyboardRight Right;
|
||||
/// <summary>
|
||||
/// Left JoyCon Keyboard Bindings
|
||||
/// </summary>
|
||||
public NpadKeyboardLeft LeftJoycon { get; private set; }
|
||||
|
||||
public NpadKeyboard(
|
||||
NpadKeyboardLeft left,
|
||||
NpadKeyboardRight right)
|
||||
{
|
||||
Left = left;
|
||||
Right = right;
|
||||
}
|
||||
/// <summary>
|
||||
/// Right JoyCon Keyboard Bindings
|
||||
/// </summary>
|
||||
public NpadKeyboardRight RightJoycon { get; private set; }
|
||||
|
||||
public HidControllerButtons GetButtons(KeyboardState keyboard)
|
||||
{
|
||||
HidControllerButtons buttons = 0;
|
||||
|
||||
if (keyboard[(Key)Left.StickButton]) buttons |= HidControllerButtons.StickLeft;
|
||||
if (keyboard[(Key)Left.DPadUp]) buttons |= HidControllerButtons.DpadUp;
|
||||
if (keyboard[(Key)Left.DPadDown]) buttons |= HidControllerButtons.DpadDown;
|
||||
if (keyboard[(Key)Left.DPadLeft]) buttons |= HidControllerButtons.DpadLeft;
|
||||
if (keyboard[(Key)Left.DPadRight]) buttons |= HidControllerButtons.DPadRight;
|
||||
if (keyboard[(Key)Left.ButtonMinus]) buttons |= HidControllerButtons.Minus;
|
||||
if (keyboard[(Key)Left.ButtonL]) buttons |= HidControllerButtons.L;
|
||||
if (keyboard[(Key)Left.ButtonZl]) buttons |= HidControllerButtons.Zl;
|
||||
if (keyboard[(Key)LeftJoycon.StickButton]) buttons |= HidControllerButtons.StickLeft;
|
||||
if (keyboard[(Key)LeftJoycon.DPadUp]) buttons |= HidControllerButtons.DpadUp;
|
||||
if (keyboard[(Key)LeftJoycon.DPadDown]) buttons |= HidControllerButtons.DpadDown;
|
||||
if (keyboard[(Key)LeftJoycon.DPadLeft]) buttons |= HidControllerButtons.DpadLeft;
|
||||
if (keyboard[(Key)LeftJoycon.DPadRight]) buttons |= HidControllerButtons.DPadRight;
|
||||
if (keyboard[(Key)LeftJoycon.ButtonMinus]) buttons |= HidControllerButtons.Minus;
|
||||
if (keyboard[(Key)LeftJoycon.ButtonL]) buttons |= HidControllerButtons.L;
|
||||
if (keyboard[(Key)LeftJoycon.ButtonZl]) buttons |= HidControllerButtons.Zl;
|
||||
|
||||
if (keyboard[(Key)Right.StickButton]) buttons |= HidControllerButtons.StickRight;
|
||||
if (keyboard[(Key)Right.ButtonA]) buttons |= HidControllerButtons.A;
|
||||
if (keyboard[(Key)Right.ButtonB]) buttons |= HidControllerButtons.B;
|
||||
if (keyboard[(Key)Right.ButtonX]) buttons |= HidControllerButtons.X;
|
||||
if (keyboard[(Key)Right.ButtonY]) buttons |= HidControllerButtons.Y;
|
||||
if (keyboard[(Key)Right.ButtonPlus]) buttons |= HidControllerButtons.Plus;
|
||||
if (keyboard[(Key)Right.ButtonR]) buttons |= HidControllerButtons.R;
|
||||
if (keyboard[(Key)Right.ButtonZr]) buttons |= HidControllerButtons.Zr;
|
||||
if (keyboard[(Key)RightJoycon.StickButton]) buttons |= HidControllerButtons.StickRight;
|
||||
if (keyboard[(Key)RightJoycon.ButtonA]) buttons |= HidControllerButtons.A;
|
||||
if (keyboard[(Key)RightJoycon.ButtonB]) buttons |= HidControllerButtons.B;
|
||||
if (keyboard[(Key)RightJoycon.ButtonX]) buttons |= HidControllerButtons.X;
|
||||
if (keyboard[(Key)RightJoycon.ButtonY]) buttons |= HidControllerButtons.Y;
|
||||
if (keyboard[(Key)RightJoycon.ButtonPlus]) buttons |= HidControllerButtons.Plus;
|
||||
if (keyboard[(Key)RightJoycon.ButtonR]) buttons |= HidControllerButtons.R;
|
||||
if (keyboard[(Key)RightJoycon.ButtonZr]) buttons |= HidControllerButtons.Zr;
|
||||
|
||||
return buttons;
|
||||
}
|
||||
|
@ -78,10 +77,10 @@ namespace Ryujinx.UI.Input
|
|||
short dx = 0;
|
||||
short dy = 0;
|
||||
|
||||
if (keyboard[(Key)Left.StickUp]) dy = short.MaxValue;
|
||||
if (keyboard[(Key)Left.StickDown]) dy = -short.MaxValue;
|
||||
if (keyboard[(Key)Left.StickLeft]) dx = -short.MaxValue;
|
||||
if (keyboard[(Key)Left.StickRight]) dx = short.MaxValue;
|
||||
if (keyboard[(Key)LeftJoycon.StickUp]) dy = short.MaxValue;
|
||||
if (keyboard[(Key)LeftJoycon.StickDown]) dy = -short.MaxValue;
|
||||
if (keyboard[(Key)LeftJoycon.StickLeft]) dx = -short.MaxValue;
|
||||
if (keyboard[(Key)LeftJoycon.StickRight]) dx = short.MaxValue;
|
||||
|
||||
return (dx, dy);
|
||||
}
|
||||
|
@ -91,10 +90,10 @@ namespace Ryujinx.UI.Input
|
|||
short dx = 0;
|
||||
short dy = 0;
|
||||
|
||||
if (keyboard[(Key)Right.StickUp]) dy = short.MaxValue;
|
||||
if (keyboard[(Key)Right.StickDown]) dy = -short.MaxValue;
|
||||
if (keyboard[(Key)Right.StickLeft]) dx = -short.MaxValue;
|
||||
if (keyboard[(Key)Right.StickRight]) dx = short.MaxValue;
|
||||
if (keyboard[(Key)RightJoycon.StickUp]) dy = short.MaxValue;
|
||||
if (keyboard[(Key)RightJoycon.StickDown]) dy = -short.MaxValue;
|
||||
if (keyboard[(Key)RightJoycon.StickLeft]) dx = -short.MaxValue;
|
||||
if (keyboard[(Key)RightJoycon.StickRight]) dx = short.MaxValue;
|
||||
|
||||
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