diff --git a/Ryujinx.Common/Configuration/ConfigurationFileFormat.cs b/Ryujinx.Common/Configuration/ConfigurationFileFormat.cs
index 812dc2c308..ff5a67c4e7 100644
--- a/Ryujinx.Common/Configuration/ConfigurationFileFormat.cs
+++ b/Ryujinx.Common/Configuration/ConfigurationFileFormat.cs
@@ -1,16 +1,12 @@
-using JsonPrettyPrinterPlus;
-using Ryujinx.Common.Logging;
-using System;
using System.Collections.Generic;
using System.IO;
-using System.Text;
-using Utf8Json;
-using Utf8Json.Resolvers;
+using Ryujinx.Common.Configuration.Hid;
+using Ryujinx.Common.Logging;
+using Ryujinx.Common.Utilities;
using Ryujinx.Configuration.System;
using Ryujinx.Configuration.Hid;
-using Ryujinx.Common.Configuration.Hid;
-using Ryujinx.UI.Input;
using Ryujinx.Configuration.Ui;
+using Ryujinx.UI.Input;
namespace Ryujinx.Configuration
{
@@ -179,15 +175,7 @@ namespace Ryujinx.Configuration
/// The path to the JSON configuration file
public static ConfigurationFileFormat Load(string path)
{
- var resolver = CompositeResolver.Create(
- new[] { new ConfigurationEnumFormatter() },
- new[] { StandardResolver.AllowPrivateSnakeCase }
- );
-
- using (Stream stream = File.OpenRead(path))
- {
- return JsonSerializer.Deserialize(stream, resolver);
- }
+ return JsonHelper.DeserializeFromFile(path);
}
///
@@ -196,41 +184,7 @@ namespace Ryujinx.Configuration
/// The path to the JSON configuration file
public void SaveConfig(string path)
{
- IJsonFormatterResolver resolver = CompositeResolver.Create(
- new[] { new ConfigurationEnumFormatter() },
- new[] { StandardResolver.AllowPrivateSnakeCase }
- );
-
- byte[] data = JsonSerializer.Serialize(this, resolver);
- File.WriteAllText(path, Encoding.UTF8.GetString(data, 0, data.Length).PrettyPrintJson());
- }
-
- public class ConfigurationEnumFormatter : IJsonFormatter
- where T : struct
- {
- public void Serialize(ref JsonWriter writer, T value, IJsonFormatterResolver formatterResolver)
- {
- formatterResolver.GetFormatterWithVerify()
- .Serialize(ref writer, value.ToString(), formatterResolver);
- }
-
- public T Deserialize(ref JsonReader reader, IJsonFormatterResolver formatterResolver)
- {
- if (reader.ReadIsNull())
- {
- return default(T);
- }
-
- string enumName = formatterResolver.GetFormatterWithVerify()
- .Deserialize(ref reader, formatterResolver);
-
- if (Enum.TryParse(enumName, out T result))
- {
- return result;
- }
-
- return default(T);
- }
+ File.WriteAllText(path, JsonHelper.Serialize(this, true));
}
}
}
\ No newline at end of file
diff --git a/Ryujinx.Common/Configuration/Hid/KeyboardHotkeys.cs b/Ryujinx.Common/Configuration/Hid/KeyboardHotkeys.cs
index 1d0b050492..30cc8d8449 100644
--- a/Ryujinx.Common/Configuration/Hid/KeyboardHotkeys.cs
+++ b/Ryujinx.Common/Configuration/Hid/KeyboardHotkeys.cs
@@ -2,6 +2,6 @@
{
public struct KeyboardHotkeys
{
- public Key ToggleVsync;
+ public Key ToggleVsync { get; set; }
}
}
diff --git a/Ryujinx.Common/Configuration/Hid/NpadController.cs b/Ryujinx.Common/Configuration/Hid/NpadController.cs
index f00865d556..94b985d55c 100644
--- a/Ryujinx.Common/Configuration/Hid/NpadController.cs
+++ b/Ryujinx.Common/Configuration/Hid/NpadController.cs
@@ -5,31 +5,31 @@
///
/// Enables or disables controller support
///
- public bool Enabled;
+ public bool Enabled { get; set; }
///
/// Controller Device Index
///
- public int Index;
+ public int Index { get; set; }
///
/// Controller Analog Stick Deadzone
///
- public float Deadzone;
+ public float Deadzone { get; set; }
///
/// Controller Trigger Threshold
///
- public float TriggerThreshold;
+ public float TriggerThreshold { get; set; }
///
/// Left JoyCon Controller Bindings
///
- public NpadControllerLeft LeftJoycon;
+ public NpadControllerLeft LeftJoycon { get; set; }
///
/// Right JoyCon Controller Bindings
///
- public NpadControllerRight RightJoycon;
+ public NpadControllerRight RightJoycon { get; set; }
}
}
diff --git a/Ryujinx.Common/Configuration/Hid/NpadControllerLeft.cs b/Ryujinx.Common/Configuration/Hid/NpadControllerLeft.cs
index 54ac0f03ae..c221b5e8a0 100644
--- a/Ryujinx.Common/Configuration/Hid/NpadControllerLeft.cs
+++ b/Ryujinx.Common/Configuration/Hid/NpadControllerLeft.cs
@@ -2,14 +2,14 @@
{
public struct NpadControllerLeft
{
- public ControllerInputId Stick;
- public ControllerInputId StickButton;
- public ControllerInputId ButtonMinus;
- public ControllerInputId ButtonL;
- public ControllerInputId ButtonZl;
- public ControllerInputId DPadUp;
- public ControllerInputId DPadDown;
- public ControllerInputId DPadLeft;
- public ControllerInputId DPadRight;
+ public ControllerInputId Stick { get; set; }
+ public ControllerInputId StickButton { get; set; }
+ public ControllerInputId ButtonMinus { get; set; }
+ public ControllerInputId ButtonL { get; set; }
+ public ControllerInputId ButtonZl { get; set; }
+ public ControllerInputId DPadUp { get; set; }
+ public ControllerInputId DPadDown { get; set; }
+ public ControllerInputId DPadLeft { get; set; }
+ public ControllerInputId DPadRight { get; set; }
}
}
diff --git a/Ryujinx.Common/Configuration/Hid/NpadControllerRight.cs b/Ryujinx.Common/Configuration/Hid/NpadControllerRight.cs
index 315136d9f6..f52f6f16df 100644
--- a/Ryujinx.Common/Configuration/Hid/NpadControllerRight.cs
+++ b/Ryujinx.Common/Configuration/Hid/NpadControllerRight.cs
@@ -2,14 +2,14 @@
{
public struct NpadControllerRight
{
- public ControllerInputId Stick;
- public ControllerInputId StickButton;
- public ControllerInputId ButtonA;
- public ControllerInputId ButtonB;
- public ControllerInputId ButtonX;
- public ControllerInputId ButtonY;
- public ControllerInputId ButtonPlus;
- public ControllerInputId ButtonR;
- public ControllerInputId ButtonZr;
+ public ControllerInputId Stick { get; set; }
+ public ControllerInputId StickButton { get; set; }
+ public ControllerInputId ButtonA { get; set; }
+ public ControllerInputId ButtonB { get; set; }
+ public ControllerInputId ButtonX { get; set; }
+ public ControllerInputId ButtonY { get; set; }
+ public ControllerInputId ButtonPlus { get; set; }
+ public ControllerInputId ButtonR { get; set; }
+ public ControllerInputId ButtonZr { get; set; }
}
}
diff --git a/Ryujinx.Common/Configuration/Hid/NpadKeyboard.cs b/Ryujinx.Common/Configuration/Hid/NpadKeyboard.cs
index 911f5119ea..5ae82756b7 100644
--- a/Ryujinx.Common/Configuration/Hid/NpadKeyboard.cs
+++ b/Ryujinx.Common/Configuration/Hid/NpadKeyboard.cs
@@ -5,16 +5,16 @@ namespace Ryujinx.UI.Input
///
/// Left JoyCon Keyboard Bindings
///
- public Configuration.Hid.NpadKeyboardLeft LeftJoycon;
+ public Configuration.Hid.NpadKeyboardLeft LeftJoycon { get; set; }
///
/// Right JoyCon Keyboard Bindings
///
- public Configuration.Hid.NpadKeyboardRight RightJoycon;
+ public Configuration.Hid.NpadKeyboardRight RightJoycon { get; set; }
///
/// Hotkey Keyboard Bindings
///
- public Configuration.Hid.KeyboardHotkeys Hotkeys;
+ public Configuration.Hid.KeyboardHotkeys Hotkeys { get; set; }
}
}
diff --git a/Ryujinx.Common/Configuration/Hid/NpadKeyboardLeft.cs b/Ryujinx.Common/Configuration/Hid/NpadKeyboardLeft.cs
index 799cdfdb8a..4a61d93233 100644
--- a/Ryujinx.Common/Configuration/Hid/NpadKeyboardLeft.cs
+++ b/Ryujinx.Common/Configuration/Hid/NpadKeyboardLeft.cs
@@ -2,17 +2,17 @@
{
public struct NpadKeyboardLeft
{
- 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 Key StickUp { get; set; }
+ public Key StickDown { get; set; }
+ public Key StickLeft { get; set; }
+ public Key StickRight { get; set; }
+ public Key StickButton { get; set; }
+ public Key DPadUp { get; set; }
+ public Key DPadDown { get; set; }
+ public Key DPadLeft { get; set; }
+ public Key DPadRight { get; set; }
+ public Key ButtonMinus { get; set; }
+ public Key ButtonL { get; set; }
+ public Key ButtonZl { get; set; }
}
}
diff --git a/Ryujinx.Common/Configuration/Hid/NpadKeyboardRight.cs b/Ryujinx.Common/Configuration/Hid/NpadKeyboardRight.cs
index 311504bb7e..0677b57327 100644
--- a/Ryujinx.Common/Configuration/Hid/NpadKeyboardRight.cs
+++ b/Ryujinx.Common/Configuration/Hid/NpadKeyboardRight.cs
@@ -2,17 +2,17 @@
{
public struct NpadKeyboardRight
{
- 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 Key StickUp { get; set; }
+ public Key StickDown { get; set; }
+ public Key StickLeft { get; set; }
+ public Key StickRight { get; set; }
+ public Key StickButton { get; set; }
+ public Key ButtonA { get; set; }
+ public Key ButtonB { get; set; }
+ public Key ButtonX { get; set; }
+ public Key ButtonY { get; set; }
+ public Key ButtonPlus { get; set; }
+ public Key ButtonR { get; set; }
+ public Key ButtonZr { get; set; }
}
}
diff --git a/Ryujinx.Common/Configuration/Ui/GuiColumns.cs b/Ryujinx.Common/Configuration/Ui/GuiColumns.cs
index 2b3524aa82..de4f7369b2 100644
--- a/Ryujinx.Common/Configuration/Ui/GuiColumns.cs
+++ b/Ryujinx.Common/Configuration/Ui/GuiColumns.cs
@@ -2,15 +2,15 @@
{
public struct GuiColumns
{
- public bool FavColumn;
- public bool IconColumn;
- public bool AppColumn;
- public bool DevColumn;
- public bool VersionColumn;
- public bool TimePlayedColumn;
- public bool LastPlayedColumn;
- public bool FileExtColumn;
- public bool FileSizeColumn;
- public bool PathColumn;
+ public bool FavColumn { get; set; }
+ public bool IconColumn { get; set; }
+ public bool AppColumn { get; set; }
+ public bool DevColumn { get; set; }
+ public bool VersionColumn { get; set; }
+ public bool TimePlayedColumn { get; set; }
+ public bool LastPlayedColumn { get; set; }
+ public bool FileExtColumn { get; set; }
+ public bool FileSizeColumn { get; set; }
+ public bool PathColumn { get; set; }
}
}
diff --git a/Ryujinx.Common/Logging/Targets/JsonLogTarget.cs b/Ryujinx.Common/Logging/Targets/JsonLogTarget.cs
index 3729b18d13..95f96576c0 100644
--- a/Ryujinx.Common/Logging/Targets/JsonLogTarget.cs
+++ b/Ryujinx.Common/Logging/Targets/JsonLogTarget.cs
@@ -1,6 +1,5 @@
-using System;
-using System.IO;
-using Utf8Json;
+using System.IO;
+using System.Text.Json;
namespace Ryujinx.Common.Logging
{
@@ -26,7 +25,12 @@ namespace Ryujinx.Common.Logging
public void Log(object sender, LogEventArgs e)
{
- JsonSerializer.Serialize(_stream, e);
+ string text = JsonSerializer.Serialize(e);
+
+ using (BinaryWriter writer = new BinaryWriter(_stream))
+ {
+ writer.Write(text);
+ }
}
public void Dispose()
diff --git a/Ryujinx.Common/Ryujinx.Common.csproj b/Ryujinx.Common/Ryujinx.Common.csproj
index e902d26ab2..3eb75730be 100644
--- a/Ryujinx.Common/Ryujinx.Common.csproj
+++ b/Ryujinx.Common/Ryujinx.Common.csproj
@@ -27,12 +27,8 @@
-
- NU1701
-
-
diff --git a/Ryujinx.Common/Utilities/JsonHelper.cs b/Ryujinx.Common/Utilities/JsonHelper.cs
new file mode 100644
index 0000000000..5aa461830e
--- /dev/null
+++ b/Ryujinx.Common/Utilities/JsonHelper.cs
@@ -0,0 +1,106 @@
+using System.IO;
+using System.Text;
+using System.Text.Json;
+using System.Text.Json.Serialization;
+
+namespace Ryujinx.Common.Utilities
+{
+ public class JsonHelper
+ {
+ public static JsonNamingPolicy SnakeCase { get; }
+
+ private class SnakeCaseNamingPolicy : JsonNamingPolicy
+ {
+ public override string ConvertName(string name)
+ {
+ if (string.IsNullOrEmpty(name))
+ {
+ return name;
+ }
+
+ StringBuilder builder = new StringBuilder();
+
+ for (int i = 0; i < name.Length; i++)
+ {
+ char c = name[i];
+
+ if (char.IsUpper(c))
+ {
+ if (i == 0 || char.IsUpper(name[i - 1]))
+ {
+ builder.Append(char.ToLowerInvariant(c));
+ }
+ else
+ {
+ builder.Append("_");
+ builder.Append(char.ToLowerInvariant(c));
+ }
+ }
+ else
+ {
+ builder.Append(c);
+ }
+ }
+
+ return builder.ToString();
+ }
+ }
+
+ static JsonHelper()
+ {
+ SnakeCase = new SnakeCaseNamingPolicy();
+ }
+
+ public static JsonSerializerOptions GetDefaultSerializerOptions(bool prettyPrint = false)
+ {
+ JsonSerializerOptions options = new JsonSerializerOptions
+ {
+ DictionaryKeyPolicy = SnakeCase,
+ PropertyNamingPolicy = SnakeCase,
+ WriteIndented = prettyPrint,
+ AllowTrailingCommas = true,
+ ReadCommentHandling = JsonCommentHandling.Skip
+ };
+
+ options.Converters.Add(new JsonStringEnumConverter());
+
+ return options;
+ }
+
+ public static T Deserialize(Stream stream)
+ {
+ using (BinaryReader reader = new BinaryReader(stream))
+ {
+ return JsonSerializer.Deserialize(reader.ReadBytes((int)(stream.Length - stream.Position)), GetDefaultSerializerOptions());
+ }
+ }
+
+ public static T DeserializeFromFile(string path)
+ {
+ return Deserialize(File.ReadAllText(path));
+ }
+
+ public static T Deserialize(string json)
+ {
+ return JsonSerializer.Deserialize(json, GetDefaultSerializerOptions());
+ }
+
+ public static void Serialize(Stream stream, TValue obj, bool prettyPrint = false)
+ {
+ using (BinaryWriter writer = new BinaryWriter(stream))
+ {
+ writer.Write(SerializeToUtf8Bytes(obj, prettyPrint));
+ }
+ }
+
+ public static string Serialize(TValue obj, bool prettyPrint = false)
+ {
+ return JsonSerializer.Serialize(obj, GetDefaultSerializerOptions(prettyPrint));
+ }
+
+ public static byte[] SerializeToUtf8Bytes(T obj, bool prettyPrint = false)
+ {
+ return JsonSerializer.SerializeToUtf8Bytes(obj, GetDefaultSerializerOptions(prettyPrint));
+ }
+ }
+}
diff --git a/Ryujinx.Debugger/Profiler/ProfilerConfiguration.cs b/Ryujinx.Debugger/Profiler/ProfilerConfiguration.cs
index e0842f2e1f..73ef8f5555 100644
--- a/Ryujinx.Debugger/Profiler/ProfilerConfiguration.cs
+++ b/Ryujinx.Debugger/Profiler/ProfilerConfiguration.cs
@@ -1,8 +1,5 @@
-using Gdk;
-using System;
+using Ryujinx.Common.Utilities;
using System.IO;
-using Utf8Json;
-using Utf8Json.Resolvers;
namespace Ryujinx.Debugger.Profiler
{
@@ -21,48 +18,12 @@ namespace Ryujinx.Debugger.Profiler
/// The path to the JSON configuration file
public static ProfilerConfiguration Load(string path)
{
- var resolver = CompositeResolver.Create(
- new[] { new ConfigurationEnumFormatter() },
- new[] { StandardResolver.AllowPrivateSnakeCase }
- );
-
if (!File.Exists(path))
{
throw new FileNotFoundException($"Profiler configuration file {path} not found");
}
- using (Stream stream = File.OpenRead(path))
- {
- return JsonSerializer.Deserialize(stream, resolver);
- }
- }
-
- private class ConfigurationEnumFormatter : IJsonFormatter
- where T : struct
- {
- public void Serialize(ref JsonWriter writer, T value, IJsonFormatterResolver formatterResolver)
- {
- formatterResolver.GetFormatterWithVerify()
- .Serialize(ref writer, value.ToString(), formatterResolver);
- }
-
- public T Deserialize(ref JsonReader reader, IJsonFormatterResolver formatterResolver)
- {
- if (reader.ReadIsNull())
- {
- return default(T);
- }
-
- string enumName = formatterResolver.GetFormatterWithVerify()
- .Deserialize(ref reader, formatterResolver);
-
- if (Enum.TryParse(enumName, out T result))
- {
- return result;
- }
-
- return default(T);
- }
+ return JsonHelper.DeserializeFromFile(path);
}
}
}
diff --git a/Ryujinx.HLE/HOS/Horizon.cs b/Ryujinx.HLE/HOS/Horizon.cs
index 2dfa275713..76185d7b91 100644
--- a/Ryujinx.HLE/HOS/Horizon.cs
+++ b/Ryujinx.HLE/HOS/Horizon.cs
@@ -39,11 +39,10 @@ using System.IO;
using System.Linq;
using System.Reflection;
using System.Threading;
-using Utf8Json;
-using Utf8Json.Resolvers;
using TimeServiceManager = Ryujinx.HLE.HOS.Services.Time.TimeManager;
using NsoExecutable = Ryujinx.HLE.Loaders.Executables.NsoExecutable;
+using JsonHelper = Ryujinx.Common.Utilities.JsonHelper;
using static LibHac.Fs.ApplicationSaveDataManagement;
@@ -540,49 +539,47 @@ namespace Ryujinx.HLE.HOS
IStorage dataStorage = null;
IFileSystem codeFs = null;
- if (File.Exists(Path.Combine(Device.FileSystem.GetBasePath(), "games", mainNca.Header.TitleId.ToString("x16"), "updates.json")))
+ string titleUpdateMetadataPath = System.IO.Path.Combine(Device.FileSystem.GetBasePath(), "games", mainNca.Header.TitleId.ToString("x16"), "updates.json");
+
+ if (File.Exists(titleUpdateMetadataPath))
{
- using (Stream stream = File.OpenRead(Path.Combine(Device.FileSystem.GetBasePath(), "games", mainNca.Header.TitleId.ToString("x16"), "updates.json")))
+ string updatePath = JsonHelper.DeserializeFromFile(titleUpdateMetadataPath).Selected;
+
+ if (File.Exists(updatePath))
{
- IJsonFormatterResolver resolver = CompositeResolver.Create(StandardResolver.AllowPrivateSnakeCase);
- string updatePath = JsonSerializer.Deserialize(stream, resolver).Selected;
+ FileStream file = new FileStream(updatePath, FileMode.Open, FileAccess.Read);
+ PartitionFileSystem nsp = new PartitionFileSystem(file.AsStorage());
- if (File.Exists(updatePath))
+ foreach (DirectoryEntryEx ticketEntry in nsp.EnumerateEntries("/", "*.tik"))
{
- FileStream file = new FileStream(updatePath, FileMode.Open, FileAccess.Read);
- PartitionFileSystem nsp = new PartitionFileSystem(file.AsStorage());
+ Result result = nsp.OpenFile(out IFile ticketFile, ticketEntry.FullPath.ToU8Span(), OpenMode.Read);
- foreach (DirectoryEntryEx ticketEntry in nsp.EnumerateEntries("/", "*.tik"))
+ if (result.IsSuccess())
{
- Result result = nsp.OpenFile(out IFile ticketFile, ticketEntry.FullPath.ToU8Span(), OpenMode.Read);
+ Ticket ticket = new Ticket(ticketFile.AsStream());
- if (result.IsSuccess())
- {
- Ticket ticket = new Ticket(ticketFile.AsStream());
+ KeySet.ExternalKeySet.Add(new RightsId(ticket.RightsId), new AccessKey(ticket.GetTitleKey(KeySet)));
+ }
+ }
- KeySet.ExternalKeySet.Add(new RightsId(ticket.RightsId), new AccessKey(ticket.GetTitleKey(KeySet)));
- }
+ foreach (DirectoryEntryEx fileEntry in nsp.EnumerateEntries("/", "*.nca"))
+ {
+ nsp.OpenFile(out IFile ncaFile, fileEntry.FullPath.ToU8Span(), OpenMode.Read).ThrowIfFailure();
+
+ Nca nca = new Nca(KeySet, ncaFile.AsStorage());
+
+ if ($"{nca.Header.TitleId.ToString("x16")[..^3]}000" != mainNca.Header.TitleId.ToString("x16"))
+ {
+ break;
}
- foreach (DirectoryEntryEx fileEntry in nsp.EnumerateEntries("/", "*.nca"))
+ if (nca.Header.ContentType == NcaContentType.Program)
{
- nsp.OpenFile(out IFile ncaFile, fileEntry.FullPath.ToU8Span(), OpenMode.Read).ThrowIfFailure();
-
- Nca nca = new Nca(KeySet, ncaFile.AsStorage());
-
- if ($"{nca.Header.TitleId.ToString("x16")[..^3]}000" != mainNca.Header.TitleId.ToString("x16"))
- {
- break;
- }
-
- if (nca.Header.ContentType == NcaContentType.Program)
- {
- patchNca = nca;
- }
- else if (nca.Header.ContentType == NcaContentType.Control)
- {
- controlNca = nca;
- }
+ patchNca = nca;
+ }
+ else if (nca.Header.ContentType == NcaContentType.Control)
+ {
+ controlNca = nca;
}
}
}
diff --git a/Ryujinx/Config.json b/Ryujinx/Config.json
index 7a5fe97239..8df901e226 100644
--- a/Ryujinx/Config.json
+++ b/Ryujinx/Config.json
@@ -1,103 +1,103 @@
{
- "version": 5,
- "max_anisotropy": -1,
- "graphics_shaders_dump_path": "",
- "logging_enable_debug": false,
- "logging_enable_stub": true,
- "logging_enable_info": true,
- "logging_enable_warn": true,
- "logging_enable_error": true,
- "logging_enable_guest": true,
- "logging_enable_fs_access_log": false,
- "logging_filtered_classes": [],
- "enable_file_log": true,
- "system_language": "AmericanEnglish",
- "system_region": "USA",
- "system_time_zone": "UTC",
- "system_time_offset": 0,
- "docked_mode": false,
- "enable_discord_integration": true,
- "enable_vsync": true,
- "enable_multicore_scheduling": true,
- "enable_fs_integrity_checks": true,
- "fs_global_access_log_mode": 0,
- "ignore_missing_services": false,
- "controller_type": "Handheld",
- "gui_columns": {
- "fav_column": true,
- "icon_column": true,
- "app_column": true,
- "dev_column": true,
- "version_column": true,
- "time_played_column": true,
- "last_played_column": true,
- "file_ext_column": true,
- "file_size_column": true,
- "path_column": true
+ "version": 5,
+ "max_anisotropy": -1,
+ "graphics_shaders_dump_path": "",
+ "logging_enable_debug": false,
+ "logging_enable_stub": true,
+ "logging_enable_info": true,
+ "logging_enable_warn": true,
+ "logging_enable_error": true,
+ "logging_enable_guest": true,
+ "logging_enable_fs_access_log": false,
+ "logging_filtered_classes": [],
+ "enable_file_log": true,
+ "system_language": "AmericanEnglish",
+ "system_region": "USA",
+ "system_time_zone": "UTC",
+ "system_time_offset": 0,
+ "docked_mode": false,
+ "enable_discord_integration": true,
+ "enable_vsync": true,
+ "enable_multicore_scheduling": true,
+ "enable_fs_integrity_checks": true,
+ "fs_global_access_log_mode": 0,
+ "ignore_missing_services": false,
+ "controller_type": "Handheld",
+ "gui_columns": {
+ "fav_column": true,
+ "icon_column": true,
+ "app_column": true,
+ "dev_column": true,
+ "version_column": true,
+ "time_played_column": true,
+ "last_played_column": true,
+ "file_ext_column": true,
+ "file_size_column": true,
+ "path_column": true
+ },
+ "game_dirs": [],
+ "enable_custom_theme": false,
+ "custom_theme_path": "",
+ "enable_keyboard": false,
+ "keyboard_controls": {
+ "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"
},
- "game_dirs": [],
- "enable_custom_theme": false,
- "custom_theme_path": "",
- "enable_keyboard": false,
- "keyboard_controls": {
- "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": {
- "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"
- },
- "hotkeys": {
- "toggle_vsync": "Tab"
- }
+ "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"
},
- "joystick_controls": {
- "enabled": true,
- "index": 0,
- "deadzone": 0.05,
- "trigger_threshold": 0.5,
- "left_joycon": {
- "stick": "Axis0",
- "stick_button": "Button8",
- "button_minus": "Button6",
- "button_l": "Button4",
- "button_zl": "Axis2",
- "dpad_up": "Hat0Up",
- "dpad_down": "Hat0Down",
- "dpad_left": "Hat0Left",
- "dpad_right": "Hat0Right"
- },
- "right_joycon": {
- "stick": "Axis3",
- "stick_button": "Button9",
- "button_a": "Button1",
- "button_b": "Button0",
- "button_x": "Button3",
- "button_y": "Button2",
- "button_plus": "Button7",
- "button_r": "Button5",
- "button_zr": "Axis5"
- }
+ "hotkeys": {
+ "toggle_vsync": "Tab"
}
+ },
+ "joystick_controls": {
+ "enabled": true,
+ "index": 0,
+ "deadzone": 0.05,
+ "trigger_threshold": 0.5,
+ "left_joycon": {
+ "stick": "Axis0",
+ "stick_button": "Button8",
+ "button_minus": "Button6",
+ "button_l": "Button4",
+ "button_zl": "Axis2",
+ "dpad_up": "Hat0Up",
+ "dpad_down": "Hat0Down",
+ "dpad_left": "Hat0Left",
+ "dpad_right": "Hat0Right"
+ },
+ "right_joycon": {
+ "stick": "Axis3",
+ "stick_button": "Button9",
+ "button_a": "Button1",
+ "button_b": "Button0",
+ "button_x": "Button3",
+ "button_y": "Button2",
+ "button_plus": "Button7",
+ "button_r": "Button5",
+ "button_zr": "Axis5"
+ }
+ }
}
\ No newline at end of file
diff --git a/Ryujinx/Ui/AboutWindow.cs b/Ryujinx/Ui/AboutWindow.cs
index cae7777666..6a18058a5a 100644
--- a/Ryujinx/Ui/AboutWindow.cs
+++ b/Ryujinx/Ui/AboutWindow.cs
@@ -1,11 +1,8 @@
using Gtk;
using System;
using System.Diagnostics;
-using System.IO;
using System.Reflection;
using System.Runtime.InteropServices;
-using Utf8Json;
-using Utf8Json.Resolvers;
using GUI = Gtk.Builder.ObjectAttribute;
diff --git a/Ryujinx/Ui/ApplicationLibrary.cs b/Ryujinx/Ui/ApplicationLibrary.cs
index f55fa1ec66..b4700300a8 100644
--- a/Ryujinx/Ui/ApplicationLibrary.cs
+++ b/Ryujinx/Ui/ApplicationLibrary.cs
@@ -18,10 +18,10 @@ using System.Globalization;
using System.IO;
using System.Reflection;
using System.Text;
-using Utf8Json;
-using Utf8Json.Resolvers;
+using System.Text.Json;
using RightsId = LibHac.Fs.RightsId;
+using JsonHelper = Ryujinx.Common.Utilities.JsonHelper;
namespace Ryujinx.Ui
{
@@ -509,8 +509,6 @@ namespace Ryujinx.Ui
string metadataFolder = Path.Combine(_virtualFileSystem.GetBasePath(), "games", titleId, "gui");
string metadataFile = Path.Combine(metadataFolder, "metadata.json");
- IJsonFormatterResolver resolver = CompositeResolver.Create(StandardResolver.AllowPrivateSnakeCase);
-
ApplicationMetadata appMetadata;
if (!File.Exists(metadataFile))
@@ -526,27 +524,24 @@ namespace Ryujinx.Ui
using (FileStream stream = File.Create(metadataFile, 4096, FileOptions.WriteThrough))
{
- JsonSerializer.Serialize(stream, appMetadata, resolver);
+ JsonHelper.Serialize(stream, appMetadata, true);
}
}
- using (Stream stream = File.OpenRead(metadataFile))
+ try
{
- try
+ appMetadata = JsonHelper.DeserializeFromFile(metadataFile);
+ }
+ catch (JsonException)
+ {
+ Logger.PrintWarning(LogClass.Application, $"Failed to parse metadata json for {titleId}. Loading defaults.");
+
+ appMetadata = new ApplicationMetadata
{
- appMetadata = JsonSerializer.Deserialize(stream, resolver);
- }
- catch (JsonParsingException)
- {
- Logger.PrintWarning(LogClass.Application, $"Failed to parse metadata json for {titleId}. Loading defaults.");
-
- appMetadata = new ApplicationMetadata
- {
- Favorite = false,
- TimePlayed = 0,
- LastPlayed = "Never"
- };
- }
+ Favorite = false,
+ TimePlayed = 0,
+ LastPlayed = "Never"
+ };
}
if (modifyFunction != null)
@@ -555,7 +550,7 @@ namespace Ryujinx.Ui
using (FileStream stream = File.Create(metadataFile, 4096, FileOptions.WriteThrough))
{
- JsonSerializer.Serialize(stream, appMetadata, resolver);
+ JsonHelper.Serialize(stream, appMetadata, true);
}
}
@@ -653,57 +648,53 @@ namespace Ryujinx.Ui
if (File.Exists(jsonPath))
{
- using (Stream stream = File.OpenRead(jsonPath))
+ string updatePath = JsonHelper.DeserializeFromFile(jsonPath).Selected;
+
+ if (!File.Exists(updatePath))
{
- IJsonFormatterResolver resolver = CompositeResolver.Create(StandardResolver.AllowPrivateSnakeCase);
- string updatePath = JsonSerializer.Deserialize(stream, resolver).Selected;
+ version = "";
- if (!File.Exists(updatePath))
+ return false;
+ }
+
+ using (FileStream file = new FileStream(updatePath, FileMode.Open, FileAccess.Read))
+ {
+ PartitionFileSystem nsp = new PartitionFileSystem(file.AsStorage());
+
+ foreach (DirectoryEntryEx ticketEntry in nsp.EnumerateEntries("/", "*.tik"))
{
- version = "";
+ Result result = nsp.OpenFile(out IFile ticketFile, ticketEntry.FullPath.ToU8Span(), OpenMode.Read);
- return false;
+ if (result.IsSuccess())
+ {
+ Ticket ticket = new Ticket(ticketFile.AsStream());
+
+ _virtualFileSystem.KeySet.ExternalKeySet.Add(new RightsId(ticket.RightsId), new AccessKey(ticket.GetTitleKey(_virtualFileSystem.KeySet)));
+ }
}
- using (FileStream file = new FileStream(updatePath, FileMode.Open, FileAccess.Read))
+ foreach (DirectoryEntryEx fileEntry in nsp.EnumerateEntries("/", "*.nca"))
{
- PartitionFileSystem nsp = new PartitionFileSystem(file.AsStorage());
+ nsp.OpenFile(out IFile ncaFile, fileEntry.FullPath.ToU8Span(), OpenMode.Read).ThrowIfFailure();
- foreach (DirectoryEntryEx ticketEntry in nsp.EnumerateEntries("/", "*.tik"))
+ Nca nca = new Nca(_virtualFileSystem.KeySet, ncaFile.AsStorage());
+
+ if ($"{nca.Header.TitleId.ToString("x16")[..^3]}000" != titleId)
{
- Result result = nsp.OpenFile(out IFile ticketFile, ticketEntry.FullPath.ToU8Span(), OpenMode.Read);
-
- if (result.IsSuccess())
- {
- Ticket ticket = new Ticket(ticketFile.AsStream());
-
- _virtualFileSystem.KeySet.ExternalKeySet.Add(new RightsId(ticket.RightsId), new AccessKey(ticket.GetTitleKey(_virtualFileSystem.KeySet)));
- }
+ break;
}
- foreach (DirectoryEntryEx fileEntry in nsp.EnumerateEntries("/", "*.nca"))
+ if (nca.Header.ContentType == NcaContentType.Control)
{
- nsp.OpenFile(out IFile ncaFile, fileEntry.FullPath.ToU8Span(), OpenMode.Read).ThrowIfFailure();
+ ApplicationControlProperty controlData = new ApplicationControlProperty();
- Nca nca = new Nca(_virtualFileSystem.KeySet, ncaFile.AsStorage());
+ nca.OpenFileSystem(NcaSectionType.Data, IntegrityCheckLevel.None).OpenFile(out IFile nacpFile, "/control.nacp".ToU8Span(), OpenMode.Read).ThrowIfFailure();
- if ($"{nca.Header.TitleId.ToString("x16")[..^3]}000" != titleId)
- {
- break;
- }
+ nacpFile.Read(out long _, 0, SpanHelpers.AsByteSpan(ref controlData), ReadOption.None).ThrowIfFailure();
- if (nca.Header.ContentType == NcaContentType.Control)
- {
- ApplicationControlProperty controlData = new ApplicationControlProperty();
+ version = controlData.DisplayVersion.ToString();
- nca.OpenFileSystem(NcaSectionType.Data, IntegrityCheckLevel.None).OpenFile(out IFile nacpFile, "/control.nacp".ToU8Span(), OpenMode.Read).ThrowIfFailure();
-
- nacpFile.Read(out long _, 0, SpanHelpers.AsByteSpan(ref controlData), ReadOption.None).ThrowIfFailure();
-
- version = controlData.DisplayVersion.ToString();
-
- return true;
- }
+ return true;
}
}
}
diff --git a/Ryujinx/Ui/GameTableContextMenu.cs b/Ryujinx/Ui/GameTableContextMenu.cs
index 8bead1e3dd..a1433f5121 100644
--- a/Ryujinx/Ui/GameTableContextMenu.cs
+++ b/Ryujinx/Ui/GameTableContextMenu.cs
@@ -11,6 +11,7 @@ using LibHac.Ns;
using LibHac.Spl;
using Ryujinx.Common.Configuration;
using Ryujinx.Common.Logging;
+using Ryujinx.Common.Utilities;
using Ryujinx.HLE.FileSystem;
using System;
using System.Buffers;
@@ -19,8 +20,6 @@ using System.Globalization;
using System.IO;
using System.Reflection;
using System.Threading;
-using Utf8Json;
-using Utf8Json.Resolvers;
using static LibHac.Fs.ApplicationSaveDataManagement;
using GUI = Gtk.Builder.ObjectAttribute;
@@ -274,43 +273,39 @@ namespace Ryujinx.Ui
if (File.Exists(titleUpdateMetadataPath))
{
- using (Stream stream = File.OpenRead(titleUpdateMetadataPath))
+ string updatePath = JsonHelper.DeserializeFromFile(titleUpdateMetadataPath).Selected;
+
+ if (File.Exists(updatePath))
{
- IJsonFormatterResolver resolver = CompositeResolver.Create(StandardResolver.AllowPrivateSnakeCase);
- string updatePath = JsonSerializer.Deserialize(stream, resolver).Selected;
+ FileStream updateFile = new FileStream(updatePath, FileMode.Open, FileAccess.Read);
+ PartitionFileSystem nsp = new PartitionFileSystem(updateFile.AsStorage());
- if (File.Exists(updatePath))
+ foreach (DirectoryEntryEx ticketEntry in nsp.EnumerateEntries("/", "*.tik"))
{
- FileStream updateFile = new FileStream(updatePath, FileMode.Open, FileAccess.Read);
- PartitionFileSystem nsp = new PartitionFileSystem(updateFile.AsStorage());
+ Result result = nsp.OpenFile(out IFile ticketFile, ticketEntry.FullPath.ToU8Span(), OpenMode.Read);
- foreach (DirectoryEntryEx ticketEntry in nsp.EnumerateEntries("/", "*.tik"))
+ if (result.IsSuccess())
{
- Result result = nsp.OpenFile(out IFile ticketFile, ticketEntry.FullPath.ToU8Span(), OpenMode.Read);
+ Ticket ticket = new Ticket(ticketFile.AsStream());
- if (result.IsSuccess())
- {
- Ticket ticket = new Ticket(ticketFile.AsStream());
+ _virtualFileSystem.KeySet.ExternalKeySet.Add(new LibHac.Fs.RightsId(ticket.RightsId), new AccessKey(ticket.GetTitleKey(_virtualFileSystem.KeySet)));
+ }
+ }
- _virtualFileSystem.KeySet.ExternalKeySet.Add(new LibHac.Fs.RightsId(ticket.RightsId), new AccessKey(ticket.GetTitleKey(_virtualFileSystem.KeySet)));
- }
+ foreach (DirectoryEntryEx fileEntry in nsp.EnumerateEntries("/", "*.nca"))
+ {
+ nsp.OpenFile(out IFile ncaFile, fileEntry.FullPath.ToU8Span(), OpenMode.Read).ThrowIfFailure();
+
+ Nca nca = new Nca(_virtualFileSystem.KeySet, ncaFile.AsStorage());
+
+ if ($"{nca.Header.TitleId.ToString("x16")[..^3]}000" != mainNca.Header.TitleId.ToString("x16"))
+ {
+ break;
}
- foreach (DirectoryEntryEx fileEntry in nsp.EnumerateEntries("/", "*.nca"))
+ if (nca.Header.ContentType == NcaContentType.Program)
{
- nsp.OpenFile(out IFile ncaFile, fileEntry.FullPath.ToU8Span(), OpenMode.Read).ThrowIfFailure();
-
- Nca nca = new Nca(_virtualFileSystem.KeySet, ncaFile.AsStorage());
-
- if ($"{nca.Header.TitleId.ToString("x16")[..^3]}000" != mainNca.Header.TitleId.ToString("x16"))
- {
- break;
- }
-
- if (nca.Header.ContentType == NcaContentType.Program)
- {
- patchNca = nca;
- }
+ patchNca = nca;
}
}
}
diff --git a/Ryujinx/Ui/TitleUpdateWindow.cs b/Ryujinx/Ui/TitleUpdateWindow.cs
index 01025d6ddf..a6d64a793f 100644
--- a/Ryujinx/Ui/TitleUpdateWindow.cs
+++ b/Ryujinx/Ui/TitleUpdateWindow.cs
@@ -1,5 +1,4 @@
using Gtk;
-using JsonPrettyPrinterPlus;
using LibHac;
using LibHac.Common;
using LibHac.Fs;
@@ -12,11 +11,9 @@ using Ryujinx.HLE.FileSystem;
using System;
using System.Collections.Generic;
using System.IO;
-using System.Text;
-using Utf8Json;
-using Utf8Json.Resolvers;
using GUI = Gtk.Builder.ObjectAttribute;
+using JsonHelper = Ryujinx.Common.Utilities.JsonHelper;
namespace Ryujinx.Ui
{
@@ -47,12 +44,9 @@ namespace Ryujinx.Ui
try
{
- using (Stream stream = File.OpenRead(System.IO.Path.Combine(_virtualFileSystem.GetBasePath(), "games", _titleId, "updates.json")))
- {
- IJsonFormatterResolver resolver = CompositeResolver.Create(StandardResolver.AllowPrivateSnakeCase);
+ string path = System.IO.Path.Combine(_virtualFileSystem.GetBasePath(), "games", _titleId, "updates.json");
- _titleUpdateWindowData = JsonSerializer.Deserialize(stream, resolver);
- }
+ _titleUpdateWindowData = JsonHelper.DeserializeFromFile(path);
}
catch
{
@@ -185,12 +179,9 @@ namespace Ryujinx.Ui
}
}
- IJsonFormatterResolver resolver = CompositeResolver.Create(StandardResolver.AllowPrivateSnakeCase);
-
string path = System.IO.Path.Combine(_virtualFileSystem.GetBasePath(), "games", _titleId, "updates.json");
- byte[] data = JsonSerializer.Serialize(_titleUpdateWindowData, resolver);
- File.WriteAllText(path, Encoding.UTF8.GetString(data, 0, data.Length).PrettyPrintJson());
+ File.WriteAllText(path, JsonHelper.Serialize(_titleUpdateWindowData, true));
MainWindow.UpdateGameTable();
Dispose();