diff --git a/src/Ryujinx.Common/Configuration/DirtyHacks.cs b/src/Ryujinx.Common/Configuration/DirtyHacks.cs
new file mode 100644
index 000000000..6a6d4949c
--- /dev/null
+++ b/src/Ryujinx.Common/Configuration/DirtyHacks.cs
@@ -0,0 +1,11 @@
+using System;
+
+namespace Ryujinx.Common.Configuration
+{
+ [Flags]
+ public enum DirtyHacks
+ {
+ None = 0,
+ Xc2MenuSoftlockFix = 1 << 10
+ }
+}
diff --git a/src/Ryujinx.Common/Extensions/StreamExtensions.cs b/src/Ryujinx.Common/Extensions/StreamExtensions.cs
index 4b02781c9..59ff44edc 100644
--- a/src/Ryujinx.Common/Extensions/StreamExtensions.cs
+++ b/src/Ryujinx.Common/Extensions/StreamExtensions.cs
@@ -8,10 +8,10 @@ namespace Ryujinx.Common
public static class StreamExtensions
{
///
- /// Writes a to this stream.
+ /// Writes an int span to this stream.
///
/// This default implementation converts each buffer value to a stack-allocated
- /// byte array, then writes it to the Stream using .
+ /// byte array, then writes it to the Stream using .
///
/// The stream to be written to
/// The buffer of values to be written
diff --git a/src/Ryujinx.Common/TitleIDs.cs b/src/Ryujinx.Common/TitleIDs.cs
index b75ee1299..31d895051 100644
--- a/src/Ryujinx.Common/TitleIDs.cs
+++ b/src/Ryujinx.Common/TitleIDs.cs
@@ -8,6 +8,8 @@ namespace Ryujinx.Common
{
public static class TitleIDs
{
+ public static ReactiveObject> CurrentApplication { get; set; } = new();
+
public static GraphicsBackend SelectGraphicsBackend(string titleId, GraphicsBackend currentBackend)
{
switch (currentBackend)
@@ -33,6 +35,7 @@ namespace Ryujinx.Common
"010028600EBDA000", // Mario 3D World
"0100152000022000", // Mario Kart 8 Deluxe
"01005CA01580E000", // Persona 5
+ "01001f5010dfa000", // Pokemon Legends Arceus
"01008C0016544000", // Sea of Stars
"01006A800016E000", // Smash Ultimate
"0100000000010000", // Super Mario Odyessy
diff --git a/src/Ryujinx.Graphics.Gpu/GraphicsConfig.cs b/src/Ryujinx.Graphics.Gpu/GraphicsConfig.cs
index fbb7399ca..066ac28f7 100644
--- a/src/Ryujinx.Graphics.Gpu/GraphicsConfig.cs
+++ b/src/Ryujinx.Graphics.Gpu/GraphicsConfig.cs
@@ -46,7 +46,7 @@ namespace Ryujinx.Graphics.Gpu
/// Enables or disables high-level emulation of common GPU Macro code.
///
public static bool EnableMacroHLE = true;
-
+
///
/// Title id of the current running game.
/// Used by the shader cache.
diff --git a/src/Ryujinx.Graphics.Gpu/Shader/ShaderCache.cs b/src/Ryujinx.Graphics.Gpu/Shader/ShaderCache.cs
index 0924c60f8..3a02eb615 100644
--- a/src/Ryujinx.Graphics.Gpu/Shader/ShaderCache.cs
+++ b/src/Ryujinx.Graphics.Gpu/Shader/ShaderCache.cs
@@ -1,3 +1,4 @@
+using Ryujinx.Common;
using Ryujinx.Common.Configuration;
using Ryujinx.Common.Logging;
using Ryujinx.Graphics.GAL;
diff --git a/src/Ryujinx.Graphics.Metal/Window.cs b/src/Ryujinx.Graphics.Metal/Window.cs
index 7d9a51a9e..1823c0b9a 100644
--- a/src/Ryujinx.Graphics.Metal/Window.cs
+++ b/src/Ryujinx.Graphics.Metal/Window.cs
@@ -22,13 +22,15 @@ namespace Ryujinx.Graphics.Metal
private int _requestedWidth;
private int _requestedHeight;
-
- // private bool _vsyncEnabled;
+
private AntiAliasing _currentAntiAliasing;
private bool _updateEffect;
private IPostProcessingEffect _effect;
private IScalingFilter _scalingFilter;
private bool _isLinear;
+
+ public bool IsVSyncEnabled => _metalLayer.DisplaySyncEnabled;
+
// private float _scalingFilterLevel;
private bool _updateScalingFilter;
private ScalingFilter _currentScalingFilter;
@@ -40,7 +42,7 @@ namespace Ryujinx.Graphics.Metal
_metalLayer = metalLayer;
}
- private unsafe void ResizeIfNeeded()
+ private void ResizeIfNeeded()
{
if (_requestedWidth != 0 && _requestedHeight != 0)
{
@@ -54,7 +56,7 @@ namespace Ryujinx.Graphics.Metal
}
}
- public unsafe void Present(ITexture texture, ImageCrop crop, Action swapBuffersCallback)
+ public void Present(ITexture texture, ImageCrop crop, Action swapBuffersCallback)
{
if (_renderer.Pipeline is Pipeline pipeline && texture is Texture tex)
{
@@ -141,15 +143,7 @@ namespace Ryujinx.Graphics.Metal
public void ChangeVSyncMode(VSyncMode vSyncMode)
{
- switch (vSyncMode)
- {
- case VSyncMode.Unbounded:
- _metalLayer.DisplaySyncEnabled = false;
- break;
- case VSyncMode.Switch:
- _metalLayer.DisplaySyncEnabled = true;
- break;
- }
+ _metalLayer.DisplaySyncEnabled = vSyncMode is VSyncMode.Switch;
}
public void SetAntiAliasing(AntiAliasing effect)
diff --git a/src/Ryujinx.Graphics.Nvdec.Vp9/BitDepth.cs b/src/Ryujinx.Graphics.Nvdec.Vp9/BitDepth.cs
index a43c83580..fdf0aff9c 100644
--- a/src/Ryujinx.Graphics.Nvdec.Vp9/BitDepth.cs
+++ b/src/Ryujinx.Graphics.Nvdec.Vp9/BitDepth.cs
@@ -2,8 +2,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
{
internal enum BitDepth
{
- Bits8 = 8, /**< 8 bits */
- Bits10 = 10, /**< 10 bits */
- Bits12 = 12, /**< 12 bits */
+ Bits8 = 8, // < 8 bits
+ Bits10 = 10, // < 10 bits
+ Bits12 = 12, // < 12 bits
}
}
diff --git a/src/Ryujinx.Graphics.Vulkan/VulkanRenderer.cs b/src/Ryujinx.Graphics.Vulkan/VulkanRenderer.cs
index ad4b18e50..a4fcf5353 100644
--- a/src/Ryujinx.Graphics.Vulkan/VulkanRenderer.cs
+++ b/src/Ryujinx.Graphics.Vulkan/VulkanRenderer.cs
@@ -1,3 +1,4 @@
+using Gommon;
using Ryujinx.Common.Configuration;
using Ryujinx.Common.Logging;
using Ryujinx.Graphics.GAL;
@@ -890,7 +891,12 @@ namespace Ryujinx.Graphics.Vulkan
private void PrintGpuInformation()
{
- Logger.Notice.Print(LogClass.Gpu, $"{GpuVendor} {GpuRenderer} ({GpuVersion})");
+ string gpuInfoMessage = $"{GpuRenderer} ({GpuVersion})";
+ if (!GpuRenderer.StartsWithIgnoreCase(GpuVendor))
+ gpuInfoMessage = gpuInfoMessage.Prepend(GpuVendor);
+
+ Logger.Notice.Print(LogClass.Gpu, gpuInfoMessage);
+
Logger.Notice.Print(LogClass.Gpu, $"GPU Memory: {GetTotalGPUMemory() / (1024 * 1024)} MiB");
}
diff --git a/src/Ryujinx.HLE/HLEConfiguration.cs b/src/Ryujinx.HLE/HLEConfiguration.cs
index 52c2b3da4..b44a09b22 100644
--- a/src/Ryujinx.HLE/HLEConfiguration.cs
+++ b/src/Ryujinx.HLE/HLEConfiguration.cs
@@ -188,6 +188,11 @@ namespace Ryujinx.HLE
/// An action called when HLE force a refresh of output after docked mode changed.
///
public Action RefreshInputConfig { internal get; set; }
+
+ ///
+ /// The desired hacky workarounds.
+ ///
+ public DirtyHacks Hacks { internal get; set; }
public HLEConfiguration(VirtualFileSystem virtualFileSystem,
LibHacHorizonManager libHacHorizonManager,
@@ -218,7 +223,8 @@ namespace Ryujinx.HLE
bool multiplayerDisableP2p,
string multiplayerLdnPassphrase,
string multiplayerLdnServer,
- int customVSyncInterval)
+ int customVSyncInterval,
+ DirtyHacks dirtyHacks = DirtyHacks.None)
{
VirtualFileSystem = virtualFileSystem;
LibHacHorizonManager = libHacHorizonManager;
@@ -250,6 +256,7 @@ namespace Ryujinx.HLE
MultiplayerDisableP2p = multiplayerDisableP2p;
MultiplayerLdnPassphrase = multiplayerLdnPassphrase;
MultiplayerLdnServer = multiplayerLdnServer;
+ Hacks = dirtyHacks;
}
}
}
diff --git a/src/Ryujinx.HLE/HOS/Services/Fs/FileSystemProxy/IStorage.cs b/src/Ryujinx.HLE/HOS/Services/Fs/FileSystemProxy/IStorage.cs
index 4299a6c74..07ab8b386 100644
--- a/src/Ryujinx.HLE/HOS/Services/Fs/FileSystemProxy/IStorage.cs
+++ b/src/Ryujinx.HLE/HOS/Services/Fs/FileSystemProxy/IStorage.cs
@@ -1,6 +1,9 @@
using LibHac;
using LibHac.Common;
using LibHac.Sf;
+using Ryujinx.Common;
+using Ryujinx.Common.Configuration;
+using System.Threading;
namespace Ryujinx.HLE.HOS.Services.Fs.FileSystemProxy
{
@@ -13,6 +16,8 @@ namespace Ryujinx.HLE.HOS.Services.Fs.FileSystemProxy
_baseStorage = SharedRef.CreateMove(ref baseStorage);
}
+ private const string Xc2TitleId = "0100e95004038000";
+
[CommandCmif(0)]
// Read(u64 offset, u64 length) -> buffer buffer
public ResultCode Read(ServiceCtx context)
@@ -33,6 +38,13 @@ namespace Ryujinx.HLE.HOS.Services.Fs.FileSystemProxy
using var region = context.Memory.GetWritableRegion(bufferAddress, (int)bufferLen, true);
Result result = _baseStorage.Get.Read((long)offset, new OutBuffer(region.Memory.Span), (long)size);
+
+ if (context.Device.DirtyHacks.HasFlag(DirtyHacks.Xc2MenuSoftlockFix) && TitleIDs.CurrentApplication.Value == Xc2TitleId)
+ {
+ // Add a load-bearing sleep to avoid XC2 softlock
+ // https://web.archive.org/web/20240728045136/https://github.com/Ryujinx/Ryujinx/issues/2357
+ Thread.Sleep(2);
+ }
return (ResultCode)result.Value;
}
diff --git a/src/Ryujinx.HLE/Loaders/Processes/Extensions/FileSystemExtensions.cs b/src/Ryujinx.HLE/Loaders/Processes/Extensions/FileSystemExtensions.cs
index 97284f3bb..d1d13b00f 100644
--- a/src/Ryujinx.HLE/Loaders/Processes/Extensions/FileSystemExtensions.cs
+++ b/src/Ryujinx.HLE/Loaders/Processes/Extensions/FileSystemExtensions.cs
@@ -4,8 +4,10 @@ using LibHac.Fs.Fsa;
using LibHac.Loader;
using LibHac.Ns;
using LibHac.Tools.FsSystem;
+using Ryujinx.Common;
using Ryujinx.Common.Configuration;
using Ryujinx.Common.Logging;
+using Ryujinx.Graphics.Gpu;
using Ryujinx.HLE.Loaders.Executables;
using Ryujinx.Memory;
using System;
@@ -102,7 +104,7 @@ namespace Ryujinx.HLE.Loaders.Processes.Extensions
}
// Initialize GPU.
- Graphics.Gpu.GraphicsConfig.TitleId = programId.ToString("X16");
+ GraphicsConfig.TitleId = programId.ToString("X16");
device.Gpu.HostInitalized.Set();
if (!MemoryBlock.SupportsFlags(MemoryAllocationFlags.ViewCompatible))
diff --git a/src/Ryujinx.HLE/Loaders/Processes/ProcessLoader.cs b/src/Ryujinx.HLE/Loaders/Processes/ProcessLoader.cs
index fe8360f04..ebbeb1398 100644
--- a/src/Ryujinx.HLE/Loaders/Processes/ProcessLoader.cs
+++ b/src/Ryujinx.HLE/Loaders/Processes/ProcessLoader.cs
@@ -6,7 +6,9 @@ using LibHac.Ns;
using LibHac.Tools.Fs;
using LibHac.Tools.FsSystem;
using LibHac.Tools.FsSystem.NcaUtils;
+using Ryujinx.Common;
using Ryujinx.Common.Logging;
+using Ryujinx.Graphics.Gpu;
using Ryujinx.HLE.Loaders.Executables;
using Ryujinx.HLE.Loaders.Processes.Extensions;
using System;
@@ -59,6 +61,8 @@ namespace Ryujinx.HLE.Loaders.Processes
{
_latestPid = processResult.ProcessId;
+ TitleIDs.CurrentApplication.Value = processResult.ProgramIdText;
+
return true;
}
}
@@ -86,6 +90,8 @@ namespace Ryujinx.HLE.Loaders.Processes
{
_latestPid = processResult.ProcessId;
+ TitleIDs.CurrentApplication.Value = processResult.ProgramIdText;
+
return true;
}
}
@@ -113,6 +119,8 @@ namespace Ryujinx.HLE.Loaders.Processes
if (processResult.ProgramId > 0x01000000000007FF)
{
_latestPid = processResult.ProcessId;
+
+ TitleIDs.CurrentApplication.Value = processResult.ProgramIdText;
}
return true;
@@ -132,6 +140,8 @@ namespace Ryujinx.HLE.Loaders.Processes
{
_latestPid = processResult.ProcessId;
+ TitleIDs.CurrentApplication.Value = processResult.ProgramIdText;
+
return true;
}
}
@@ -183,14 +193,17 @@ namespace Ryujinx.HLE.Loaders.Processes
if (nacpData.Value.PresenceGroupId != 0)
{
programId = nacpData.Value.PresenceGroupId;
+ TitleIDs.CurrentApplication.Value = programId.ToString("X16");
}
else if (nacpData.Value.SaveDataOwnerId != 0)
{
programId = nacpData.Value.SaveDataOwnerId;
+ TitleIDs.CurrentApplication.Value = programId.ToString("X16");
}
else if (nacpData.Value.AddOnContentBaseId != 0)
{
programId = nacpData.Value.AddOnContentBaseId - 0x1000;
+ TitleIDs.CurrentApplication.Value = programId.ToString("X16");
}
}
@@ -204,7 +217,7 @@ namespace Ryujinx.HLE.Loaders.Processes
}
// Explicitly null TitleId to disable the shader cache.
- Graphics.Gpu.GraphicsConfig.TitleId = null;
+ GraphicsConfig.TitleId = null;
_device.Gpu.HostInitalized.Set();
ProcessResult processResult = ProcessLoaderHelper.LoadNsos(_device,
diff --git a/src/Ryujinx.HLE/Switch.cs b/src/Ryujinx.HLE/Switch.cs
index d0afdf173..c630c71c7 100644
--- a/src/Ryujinx.HLE/Switch.cs
+++ b/src/Ryujinx.HLE/Switch.cs
@@ -2,6 +2,7 @@ using LibHac.Common;
using LibHac.Ns;
using Ryujinx.Audio.Backends.CompatLayer;
using Ryujinx.Audio.Integration;
+using Ryujinx.Common;
using Ryujinx.Common.Configuration;
using Ryujinx.Graphics.Gpu;
using Ryujinx.HLE.FileSystem;
@@ -17,6 +18,8 @@ namespace Ryujinx.HLE
{
public class Switch : IDisposable
{
+ public static Switch Shared { get; private set; }
+
public HLEConfiguration Configuration { get; }
public IHardwareDeviceDriver AudioDeviceDriver { get; }
public MemoryBlock Memory { get; }
@@ -37,6 +40,8 @@ namespace Ryujinx.HLE
public bool IsFrameAvailable => Gpu.Window.IsFrameAvailable;
+ public DirtyHacks DirtyHacks { get; }
+
public Switch(HLEConfiguration configuration)
{
ArgumentNullException.ThrowIfNull(configuration.GpuRenderer);
@@ -72,8 +77,11 @@ namespace Ryujinx.HLE
System.EnablePtc = Configuration.EnablePtc;
System.FsIntegrityCheckLevel = Configuration.FsIntegrityCheckLevel;
System.GlobalAccessLogMode = Configuration.FsGlobalAccessLogMode;
+ DirtyHacks = Configuration.Hacks;
UpdateVSyncInterval();
#pragma warning restore IDE0055
+
+ Shared = this;
}
public void ProcessFrame()
@@ -142,6 +150,9 @@ namespace Ryujinx.HLE
AudioDeviceDriver.Dispose();
FileSystem.Dispose();
Memory.Dispose();
+
+ TitleIDs.CurrentApplication.Value = null;
+ Shared = null;
}
}
}
diff --git a/src/Ryujinx.UI.Common/Configuration/ConfigurationFileFormat.cs b/src/Ryujinx.UI.Common/Configuration/ConfigurationFileFormat.cs
index 027e1052b..8b123be01 100644
--- a/src/Ryujinx.UI.Common/Configuration/ConfigurationFileFormat.cs
+++ b/src/Ryujinx.UI.Common/Configuration/ConfigurationFileFormat.cs
@@ -17,7 +17,7 @@ namespace Ryujinx.UI.Common.Configuration
///
/// The current version of the file format
///
- public const int CurrentVersion = 57;
+ public const int CurrentVersion = 58;
///
/// Version of the configuration file format
@@ -429,7 +429,17 @@ namespace Ryujinx.UI.Common.Configuration
/// Uses Hypervisor over JIT if available
///
public bool UseHypervisor { get; set; }
-
+
+ ///
+ /// Show toggles for dirty hacks in the UI.
+ ///
+ public bool ShowDirtyHacks { get; set; }
+
+ ///
+ /// The packed value of the enabled dirty hacks.
+ ///
+ public int EnabledDirtyHacks { get; set; }
+
///
/// Loads a configuration file from disk
///
diff --git a/src/Ryujinx.UI.Common/Configuration/ConfigurationState.Migration.cs b/src/Ryujinx.UI.Common/Configuration/ConfigurationState.Migration.cs
index a41ea2cd7..8652b4331 100644
--- a/src/Ryujinx.UI.Common/Configuration/ConfigurationState.Migration.cs
+++ b/src/Ryujinx.UI.Common/Configuration/ConfigurationState.Migration.cs
@@ -735,6 +735,9 @@ namespace Ryujinx.UI.Common.Configuration
Multiplayer.DisableP2p.Value = configurationFileFormat.MultiplayerDisableP2p;
Multiplayer.LdnPassphrase.Value = configurationFileFormat.MultiplayerLdnPassphrase;
Multiplayer.LdnServer.Value = configurationFileFormat.LdnServer;
+
+ Hacks.ShowDirtyHacks.Value = configurationFileFormat.ShowDirtyHacks;
+ Hacks.Xc2MenuSoftlockFix.Value = ((DirtyHacks)configurationFileFormat.EnabledDirtyHacks).HasFlag(DirtyHacks.Xc2MenuSoftlockFix);
if (configurationFileUpdated)
{
diff --git a/src/Ryujinx.UI.Common/Configuration/ConfigurationState.Model.cs b/src/Ryujinx.UI.Common/Configuration/ConfigurationState.Model.cs
index f28ce0348..2ae56d50a 100644
--- a/src/Ryujinx.UI.Common/Configuration/ConfigurationState.Model.cs
+++ b/src/Ryujinx.UI.Common/Configuration/ConfigurationState.Model.cs
@@ -1,4 +1,5 @@
using ARMeilleure;
+using Gommon;
using Ryujinx.Common;
using Ryujinx.Common.Configuration;
using Ryujinx.Common.Configuration.Hid;
@@ -617,6 +618,49 @@ namespace Ryujinx.UI.Common.Configuration
}
}
+ public class HacksSection
+ {
+ ///
+ /// Show toggles for dirty hacks in the UI.
+ ///
+ public ReactiveObject ShowDirtyHacks { get; private set; }
+
+ public ReactiveObject Xc2MenuSoftlockFix { get; private set; }
+
+ public HacksSection()
+ {
+ ShowDirtyHacks = new ReactiveObject();
+ Xc2MenuSoftlockFix = new ReactiveObject();
+ Xc2MenuSoftlockFix.Event += HackChanged;
+ }
+
+ private void HackChanged(object sender, ReactiveEventArgs rxe)
+ {
+ Ryujinx.Common.Logging.Logger.Info?.Print(LogClass.Configuration, $"EnabledDirtyHacks set to: {EnabledHacks}", "LogValueChange");
+ }
+
+ public DirtyHacks EnabledHacks
+ {
+ get
+ {
+ DirtyHacks dirtyHacks = DirtyHacks.None;
+
+ if (Xc2MenuSoftlockFix)
+ Apply(DirtyHacks.Xc2MenuSoftlockFix);
+
+ return dirtyHacks;
+
+ void Apply(DirtyHacks hack)
+ {
+ if (dirtyHacks is not DirtyHacks.None)
+ dirtyHacks |= hack;
+ else
+ dirtyHacks = hack;
+ }
+ }
+ }
+ }
+
///
/// The default configuration instance
///
@@ -651,6 +695,11 @@ namespace Ryujinx.UI.Common.Configuration
/// The Multiplayer section
///
public MultiplayerSection Multiplayer { get; private set; }
+
+ ///
+ /// The Dirty Hacks section
+ ///
+ public HacksSection Hacks { get; private set; }
///
/// Enables or disables Discord Rich Presence
@@ -700,6 +749,7 @@ namespace Ryujinx.UI.Common.Configuration
Graphics = new GraphicsSection();
Hid = new HidSection();
Multiplayer = new MultiplayerSection();
+ Hacks = new HacksSection();
EnableDiscordIntegration = new ReactiveObject();
CheckUpdatesOnStart = new ReactiveObject();
ShowConfirmExit = new ReactiveObject();
diff --git a/src/Ryujinx.UI.Common/Configuration/ConfigurationState.cs b/src/Ryujinx.UI.Common/Configuration/ConfigurationState.cs
index 90bdc3409..8ae76ecc5 100644
--- a/src/Ryujinx.UI.Common/Configuration/ConfigurationState.cs
+++ b/src/Ryujinx.UI.Common/Configuration/ConfigurationState.cs
@@ -138,6 +138,8 @@ namespace Ryujinx.UI.Common.Configuration
MultiplayerDisableP2p = Multiplayer.DisableP2p,
MultiplayerLdnPassphrase = Multiplayer.LdnPassphrase,
LdnServer = Multiplayer.LdnServer,
+ ShowDirtyHacks = Hacks.ShowDirtyHacks,
+ EnabledDirtyHacks = (int)Hacks.EnabledHacks,
};
return configurationFile;
diff --git a/src/Ryujinx.UI.Common/DiscordIntegrationModule.cs b/src/Ryujinx.UI.Common/DiscordIntegrationModule.cs
index 574aaff87..efeeb2586 100644
--- a/src/Ryujinx.UI.Common/DiscordIntegrationModule.cs
+++ b/src/Ryujinx.UI.Common/DiscordIntegrationModule.cs
@@ -2,6 +2,7 @@ using DiscordRPC;
using Humanizer;
using Humanizer.Localisation;
using Ryujinx.Common;
+using Ryujinx.HLE;
using Ryujinx.HLE.Loaders.Processes;
using Ryujinx.UI.App.Common;
using Ryujinx.UI.Common.Configuration;
@@ -44,6 +45,16 @@ namespace Ryujinx.UI.Common
};
ConfigurationState.Instance.EnableDiscordIntegration.Event += Update;
+ TitleIDs.CurrentApplication.Event += (_, e) =>
+ {
+ if (e.NewValue)
+ SwitchToPlayingState(
+ ApplicationLibrary.LoadAndSaveMetaData(e.NewValue),
+ Switch.Shared.Processes.ActiveApplication
+ );
+ else
+ SwitchToMainState();
+ };
}
private static void Update(object sender, ReactiveEventArgs evnt)
@@ -69,7 +80,7 @@ namespace Ryujinx.UI.Common
}
}
- public static void SwitchToPlayingState(ApplicationMetadata appMeta, ProcessResult procRes)
+ private static void SwitchToPlayingState(ApplicationMetadata appMeta, ProcessResult procRes)
{
_discordClient?.SetPresence(new RichPresence
{
@@ -88,7 +99,7 @@ namespace Ryujinx.UI.Common
});
}
- public static void SwitchToMainState() => _discordClient?.SetPresence(_discordPresenceMain);
+ private static void SwitchToMainState() => _discordClient?.SetPresence(_discordPresenceMain);
private static string TruncateToByteLength(string input)
{
diff --git a/src/Ryujinx/AppHost.cs b/src/Ryujinx/AppHost.cs
index 909eb05d5..1f538868b 100644
--- a/src/Ryujinx/AppHost.cs
+++ b/src/Ryujinx/AppHost.cs
@@ -311,6 +311,7 @@ namespace Ryujinx.Ava
Device.VSyncMode = e.NewValue;
Device.UpdateVSyncInterval();
}
+
_renderer.Window?.ChangeVSyncMode(e.NewValue);
_viewModel.ShowCustomVSyncIntervalPicker = (e.NewValue == VSyncMode.Custom);
@@ -577,7 +578,6 @@ namespace Ryujinx.Ava
public void Stop()
{
_isActive = false;
- DiscordIntegrationModule.SwitchToMainState();
}
private void Exit()
@@ -861,13 +861,11 @@ namespace Ryujinx.Ava
return false;
}
-
- ApplicationMetadata appMeta = ApplicationLibrary.LoadAndSaveMetaData(Device.Processes.ActiveApplication.ProgramIdText,
+
+ ApplicationLibrary.LoadAndSaveMetaData(Device.Processes.ActiveApplication.ProgramIdText,
appMetadata => appMetadata.UpdatePreGame()
);
- DiscordIntegrationModule.SwitchToPlayingState(appMeta, Device.Processes.ActiveApplication);
-
return true;
}
@@ -923,7 +921,7 @@ namespace Ryujinx.Ava
// Initialize Configuration.
var memoryConfiguration = ConfigurationState.Instance.System.DramSize.Value;
- Device = new HLE.Switch(new HLEConfiguration(
+ Device = new Switch(new HLEConfiguration(
VirtualFileSystem,
_viewModel.LibHacHorizonManager,
ContentManager,
@@ -953,7 +951,8 @@ namespace Ryujinx.Ava
ConfigurationState.Instance.Multiplayer.DisableP2p,
ConfigurationState.Instance.Multiplayer.LdnPassphrase,
ConfigurationState.Instance.Multiplayer.LdnServer,
- ConfigurationState.Instance.Graphics.CustomVSyncInterval.Value));
+ ConfigurationState.Instance.Graphics.CustomVSyncInterval.Value,
+ ConfigurationState.Instance.Hacks.ShowDirtyHacks ? ConfigurationState.Instance.Hacks.EnabledHacks : DirtyHacks.None));
}
private static IHardwareDeviceDriver InitializeAudio()
diff --git a/src/Ryujinx/Assets/locales.json b/src/Ryujinx/Assets/locales.json
index 23aff8f13..6bede7999 100644
--- a/src/Ryujinx/Assets/locales.json
+++ b/src/Ryujinx/Assets/locales.json
@@ -1564,7 +1564,7 @@
"pl_PL": "Wersja",
"pt_BR": "Versão",
"ru_RU": "Версия",
- "sv_SE": "",
+ "sv_SE": "Version",
"th_TH": "เวอร์ชั่น",
"tr_TR": "Sürüm",
"uk_UA": "Версія",
@@ -2213,8 +2213,8 @@
"no_NO": "",
"pl_PL": "",
"pt_BR": "",
- "ru_RU": "",
- "sv_SE": "",
+ "ru_RU": "ExeFS",
+ "sv_SE": "ExeFS",
"th_TH": "",
"tr_TR": "",
"uk_UA": "",
@@ -2263,8 +2263,8 @@
"no_NO": "",
"pl_PL": "",
"pt_BR": "",
- "ru_RU": "",
- "sv_SE": "",
+ "ru_RU": "RomFS",
+ "sv_SE": "RomFS",
"th_TH": "",
"tr_TR": "",
"uk_UA": "",
@@ -2310,7 +2310,7 @@
"it_IT": "",
"ja_JP": "ロゴ",
"ko_KR": "로고",
- "no_NO": "",
+ "no_NO": "Logo",
"pl_PL": "",
"pt_BR": "",
"ru_RU": "Лого",
@@ -3260,11 +3260,11 @@
"it_IT": "Sistema",
"ja_JP": "システム",
"ko_KR": "시스템",
- "no_NO": "",
+ "no_NO": "System",
"pl_PL": "",
"pt_BR": "Sistema",
"ru_RU": "Система",
- "sv_SE": "",
+ "sv_SE": "System",
"th_TH": "ระบบ",
"tr_TR": "Sistem",
"uk_UA": "Система",
@@ -3335,11 +3335,11 @@
"it_IT": "Giappone",
"ja_JP": "日本",
"ko_KR": "일본",
- "no_NO": "",
+ "no_NO": "Japan",
"pl_PL": "Japonia",
"pt_BR": "Japão",
"ru_RU": "Япония",
- "sv_SE": "",
+ "sv_SE": "Japan",
"th_TH": "ญี่ปุ่น",
"tr_TR": "Japonya",
"uk_UA": "Японія",
@@ -3360,11 +3360,11 @@
"it_IT": "Stati Uniti d'America",
"ja_JP": "アメリカ",
"ko_KR": "미국",
- "no_NO": "",
+ "no_NO": "USA",
"pl_PL": "Stany Zjednoczone",
"pt_BR": "EUA",
"ru_RU": "США",
- "sv_SE": "",
+ "sv_SE": "USA",
"th_TH": "สหรัฐอเมริกา",
"tr_TR": "ABD",
"uk_UA": "США",
@@ -3410,7 +3410,7 @@
"it_IT": "",
"ja_JP": "オーストラリア",
"ko_KR": "호주",
- "no_NO": "",
+ "no_NO": "Australia",
"pl_PL": "",
"pt_BR": "Austrália",
"ru_RU": "Австралия",
@@ -3460,11 +3460,11 @@
"it_IT": "Corea",
"ja_JP": "韓国",
"ko_KR": "한국",
- "no_NO": "",
+ "no_NO": "Korea",
"pl_PL": "",
"pt_BR": "Coreia",
"ru_RU": "Корея",
- "sv_SE": "",
+ "sv_SE": "Korea",
"th_TH": "เกาหลี",
"tr_TR": "Kore",
"uk_UA": "Корея",
@@ -3485,11 +3485,11 @@
"it_IT": "",
"ja_JP": "台湾",
"ko_KR": "대만",
- "no_NO": "",
+ "no_NO": "Taiwan",
"pl_PL": "Tajwan",
"pt_BR": "",
"ru_RU": "Тайвань",
- "sv_SE": "",
+ "sv_SE": "Taiwan",
"th_TH": "ไต้หวัน",
"tr_TR": "Tayvan",
"uk_UA": "Тайвань",
@@ -3955,7 +3955,7 @@
"el_GR": "Ζώνη Ώρας Συστήματος:",
"en_US": "System Time Zone:",
"es_ES": "Zona horaria del sistema:",
- "fr_FR": "Fuseau horaire du système\u00A0:",
+ "fr_FR": "Fuseau horaire du système :",
"he_IL": "אזור זמן מערכת:",
"it_IT": "Fuso orario del sistema:",
"ja_JP": "タイムゾーン:",
@@ -4135,11 +4135,11 @@
"it_IT": "",
"ja_JP": "ダミー",
"ko_KR": "더미",
- "no_NO": "",
+ "no_NO": "Dummy",
"pl_PL": "Atrapa",
"pt_BR": "Nenhuma",
"ru_RU": "Без звука",
- "sv_SE": "",
+ "sv_SE": "Dummy",
"th_TH": "",
"tr_TR": "Yapay",
"uk_UA": "",
@@ -4163,8 +4163,8 @@
"no_NO": "",
"pl_PL": "",
"pt_BR": "",
- "ru_RU": "",
- "sv_SE": "",
+ "ru_RU": "OpenAL",
+ "sv_SE": "OpenAL",
"th_TH": "",
"tr_TR": "",
"uk_UA": "",
@@ -4188,8 +4188,8 @@
"no_NO": "Lyd Inn/Ut",
"pl_PL": "",
"pt_BR": "",
- "ru_RU": "",
- "sv_SE": "",
+ "ru_RU": "SoundIO",
+ "sv_SE": "SoundIO",
"th_TH": "",
"tr_TR": "",
"uk_UA": "",
@@ -4213,8 +4213,8 @@
"no_NO": "",
"pl_PL": "",
"pt_BR": "",
- "ru_RU": "",
- "sv_SE": "",
+ "ru_RU": "SDL2",
+ "sv_SE": "SDL2",
"th_TH": "",
"tr_TR": "",
"uk_UA": "",
@@ -4230,12 +4230,12 @@
"el_GR": "Μικροδιορθώσεις",
"en_US": "Hacks",
"es_ES": "",
- "fr_FR": "",
+ "fr_FR": "Hacks",
"he_IL": "האצות",
"it_IT": "Espedienti",
"ja_JP": "ハック",
"ko_KR": "핵",
- "no_NO": "",
+ "no_NO": "Hacks",
"pl_PL": "Hacki",
"pt_BR": "",
"ru_RU": "Хаки",
@@ -4314,7 +4314,7 @@
"pl_PL": "",
"pt_BR": "",
"ru_RU": "4ГиБ",
- "sv_SE": "",
+ "sv_SE": "4GiB",
"th_TH": "",
"tr_TR": "",
"uk_UA": "4Гб",
@@ -4339,7 +4339,7 @@
"pl_PL": "",
"pt_BR": "",
"ru_RU": "6ГиБ",
- "sv_SE": "",
+ "sv_SE": "6GiB",
"th_TH": "",
"tr_TR": "",
"uk_UA": "6Гб",
@@ -4364,7 +4364,7 @@
"pl_PL": "",
"pt_BR": "",
"ru_RU": "8ГиБ",
- "sv_SE": "",
+ "sv_SE": "8GiB",
"th_TH": "",
"tr_TR": "",
"uk_UA": "8Гб",
@@ -4389,7 +4389,7 @@
"pl_PL": "",
"pt_BR": "",
"ru_RU": "12ГиБ",
- "sv_SE": "",
+ "sv_SE": "12GiB",
"th_TH": "",
"tr_TR": "",
"uk_UA": "12Гб",
@@ -4585,11 +4585,11 @@
"it_IT": "",
"ja_JP": "",
"ko_KR": "2배",
- "no_NO": "",
+ "no_NO": "2x",
"pl_PL": "",
"pt_BR": "",
- "ru_RU": "",
- "sv_SE": "",
+ "ru_RU": "2x",
+ "sv_SE": "2x",
"th_TH": "",
"tr_TR": "",
"uk_UA": "",
@@ -4610,11 +4610,11 @@
"it_IT": "",
"ja_JP": "",
"ko_KR": "4배",
- "no_NO": "",
+ "no_NO": "4x",
"pl_PL": "",
"pt_BR": "",
- "ru_RU": "",
- "sv_SE": "",
+ "ru_RU": "4x",
+ "sv_SE": "4x",
"th_TH": "",
"tr_TR": "",
"uk_UA": "",
@@ -4635,11 +4635,11 @@
"it_IT": "",
"ja_JP": "",
"ko_KR": "8배",
- "no_NO": "",
+ "no_NO": "8x",
"pl_PL": "",
"pt_BR": "",
- "ru_RU": "",
- "sv_SE": "",
+ "ru_RU": "8x",
+ "sv_SE": "8x",
"th_TH": "",
"tr_TR": "",
"uk_UA": "",
@@ -4660,11 +4660,11 @@
"it_IT": "",
"ja_JP": "",
"ko_KR": "16배",
- "no_NO": "",
+ "no_NO": "16x",
"pl_PL": "",
"pt_BR": "",
- "ru_RU": "",
- "sv_SE": "",
+ "ru_RU": "16x",
+ "sv_SE": "16x",
"th_TH": "",
"tr_TR": "",
"uk_UA": "",
@@ -4760,11 +4760,11 @@
"it_IT": "",
"ja_JP": "",
"ko_KR": "2배(1440p/2160p)",
- "no_NO": "",
+ "no_NO": "2x (1440p/2160p)",
"pl_PL": "",
"pt_BR": "",
- "ru_RU": "",
- "sv_SE": "",
+ "ru_RU": "2x (1440p/2160p)",
+ "sv_SE": "2x (1440p/2160p)",
"th_TH": "",
"tr_TR": "",
"uk_UA": "",
@@ -4785,11 +4785,11 @@
"it_IT": "",
"ja_JP": "",
"ko_KR": "3배(2160p/3240p)",
- "no_NO": "",
+ "no_NO": "3x (2160p/3240p)",
"pl_PL": "",
"pt_BR": "",
- "ru_RU": "",
- "sv_SE": "",
+ "ru_RU": "3x (2160p/3240p)",
+ "sv_SE": "3x (2160p/3240p)",
"th_TH": "",
"tr_TR": "",
"uk_UA": "",
@@ -4863,8 +4863,8 @@
"no_NO": "",
"pl_PL": "",
"pt_BR": "",
- "ru_RU": "",
- "sv_SE": "",
+ "ru_RU": "4:3",
+ "sv_SE": "4:3",
"th_TH": "",
"tr_TR": "",
"uk_UA": "",
@@ -4888,8 +4888,8 @@
"no_NO": "",
"pl_PL": "",
"pt_BR": "",
- "ru_RU": "",
- "sv_SE": "",
+ "ru_RU": "16:9",
+ "sv_SE": "16:9",
"th_TH": "",
"tr_TR": "",
"uk_UA": "",
@@ -4913,8 +4913,8 @@
"no_NO": "",
"pl_PL": "",
"pt_BR": "",
- "ru_RU": "",
- "sv_SE": "",
+ "ru_RU": "16:10",
+ "sv_SE": "16:10",
"th_TH": "",
"tr_TR": "",
"uk_UA": "",
@@ -4938,8 +4938,8 @@
"no_NO": "",
"pl_PL": "",
"pt_BR": "",
- "ru_RU": "",
- "sv_SE": "",
+ "ru_RU": "21:9",
+ "sv_SE": "21:9",
"th_TH": "",
"tr_TR": "",
"uk_UA": "",
@@ -4960,11 +4960,11 @@
"it_IT": "",
"ja_JP": "",
"ko_KR": "",
- "no_NO": "",
+ "no_NO": "32:9",
"pl_PL": "",
"pt_BR": "",
- "ru_RU": "",
- "sv_SE": "",
+ "ru_RU": "32:9",
+ "sv_SE": "32:9",
"th_TH": "",
"tr_TR": "",
"uk_UA": "",
@@ -5060,7 +5060,7 @@
"it_IT": "Log",
"ja_JP": "ロギング",
"ko_KR": "로그 기록",
- "no_NO": "",
+ "no_NO": "Logging",
"pl_PL": "Dziennik zdarzeń",
"pt_BR": "Log",
"ru_RU": "Журналирование",
@@ -5085,7 +5085,7 @@
"it_IT": "Log",
"ja_JP": "ロギング",
"ko_KR": "로그 기록",
- "no_NO": "",
+ "no_NO": "Logging",
"pl_PL": "Dziennik zdarzeń",
"pt_BR": "Log",
"ru_RU": "Журналирование",
@@ -6113,8 +6113,8 @@
"no_NO": "",
"pl_PL": "Pro Kontroler",
"pt_BR": "",
- "ru_RU": "",
- "sv_SE": "",
+ "ru_RU": "Pro Controller",
+ "sv_SE": "Pro Controller",
"th_TH": "โปรคอนโทรลเลอร์",
"tr_TR": "Profesyonel Kumanda",
"uk_UA": "Контролер Pro",
@@ -8088,8 +8088,8 @@
"no_NO": "",
"pl_PL": "",
"pt_BR": "",
- "ru_RU": "",
- "sv_SE": "",
+ "ru_RU": "Enter",
+ "sv_SE": "Enter",
"th_TH": "",
"tr_TR": "",
"uk_UA": "",
@@ -8114,7 +8114,7 @@
"pl_PL": "",
"pt_BR": "",
"ru_RU": "Esc",
- "sv_SE": "",
+ "sv_SE": "Escape",
"th_TH": "",
"tr_TR": "Esc",
"uk_UA": "",
@@ -8163,8 +8163,8 @@
"no_NO": "",
"pl_PL": "",
"pt_BR": "",
- "ru_RU": "",
- "sv_SE": "",
+ "ru_RU": "Tab",
+ "sv_SE": "Tab",
"th_TH": "",
"tr_TR": "",
"uk_UA": "",
@@ -8188,8 +8188,8 @@
"no_NO": "Tilbaketast",
"pl_PL": "",
"pt_BR": "",
- "ru_RU": "",
- "sv_SE": "",
+ "ru_RU": "Backspace",
+ "sv_SE": "Backspace",
"th_TH": "",
"tr_TR": "Geri tuşu",
"uk_UA": "",
@@ -8213,8 +8213,8 @@
"no_NO": "Sett inn",
"pl_PL": "",
"pt_BR": "",
- "ru_RU": "",
- "sv_SE": "",
+ "ru_RU": "Insert",
+ "sv_SE": "Insert",
"th_TH": "",
"tr_TR": "",
"uk_UA": "",
@@ -8238,8 +8238,8 @@
"no_NO": "Slett",
"pl_PL": "",
"pt_BR": "",
- "ru_RU": "",
- "sv_SE": "",
+ "ru_RU": "Delete",
+ "sv_SE": "Delete",
"th_TH": "",
"tr_TR": "",
"uk_UA": "",
@@ -8263,8 +8263,8 @@
"no_NO": "Side opp",
"pl_PL": "",
"pt_BR": "",
- "ru_RU": "",
- "sv_SE": "",
+ "ru_RU": "Page Up",
+ "sv_SE": "Page Up",
"th_TH": "",
"tr_TR": "",
"uk_UA": "",
@@ -8288,8 +8288,8 @@
"no_NO": "Side ned",
"pl_PL": "",
"pt_BR": "",
- "ru_RU": "",
- "sv_SE": "",
+ "ru_RU": "Page Down",
+ "sv_SE": "Page Down",
"th_TH": "",
"tr_TR": "",
"uk_UA": "",
@@ -8313,8 +8313,8 @@
"no_NO": "Hjem",
"pl_PL": "",
"pt_BR": "",
- "ru_RU": "",
- "sv_SE": "",
+ "ru_RU": "Home",
+ "sv_SE": "Home",
"th_TH": "",
"tr_TR": "",
"uk_UA": "",
@@ -8338,8 +8338,8 @@
"no_NO": "Avslutt",
"pl_PL": "",
"pt_BR": "",
- "ru_RU": "",
- "sv_SE": "",
+ "ru_RU": "End",
+ "sv_SE": "End",
"th_TH": "",
"tr_TR": "",
"uk_UA": "",
@@ -8363,8 +8363,8 @@
"no_NO": "Skiftelås",
"pl_PL": "",
"pt_BR": "",
- "ru_RU": "",
- "sv_SE": "",
+ "ru_RU": "Caps Lock",
+ "sv_SE": "Caps Lock",
"th_TH": "",
"tr_TR": "",
"uk_UA": "",
@@ -8388,8 +8388,8 @@
"no_NO": "Rullelås",
"pl_PL": "",
"pt_BR": "",
- "ru_RU": "",
- "sv_SE": "",
+ "ru_RU": "Scroll Lock",
+ "sv_SE": "Scroll Lock",
"th_TH": "",
"tr_TR": "",
"uk_UA": "",
@@ -8413,8 +8413,8 @@
"no_NO": "Skjermbilde",
"pl_PL": "",
"pt_BR": "",
- "ru_RU": "",
- "sv_SE": "",
+ "ru_RU": "Print Screen",
+ "sv_SE": "Print Screen",
"th_TH": "",
"tr_TR": "",
"uk_UA": "",
@@ -8438,8 +8438,8 @@
"no_NO": "Stans midlertidig",
"pl_PL": "",
"pt_BR": "",
- "ru_RU": "",
- "sv_SE": "",
+ "ru_RU": "Pause",
+ "sv_SE": "Pause",
"th_TH": "",
"tr_TR": "",
"uk_UA": "",
@@ -8463,8 +8463,8 @@
"no_NO": "Numerisk Lås",
"pl_PL": "",
"pt_BR": "",
- "ru_RU": "",
- "sv_SE": "",
+ "ru_RU": "Num Lock",
+ "sv_SE": "Num Lock",
"th_TH": "",
"tr_TR": "",
"uk_UA": "",
@@ -8514,7 +8514,7 @@
"pl_PL": "",
"pt_BR": "",
"ru_RU": "Блок цифр 0",
- "sv_SE": "",
+ "sv_SE": "Keypad 0",
"th_TH": "",
"tr_TR": "",
"uk_UA": "",
@@ -8539,7 +8539,7 @@
"pl_PL": "",
"pt_BR": "",
"ru_RU": "Блок цифр 1",
- "sv_SE": "",
+ "sv_SE": "Keypad 1",
"th_TH": "",
"tr_TR": "",
"uk_UA": "",
@@ -8564,7 +8564,7 @@
"pl_PL": "",
"pt_BR": "",
"ru_RU": "Блок цифр 2",
- "sv_SE": "",
+ "sv_SE": "Keypad 2",
"th_TH": "",
"tr_TR": "",
"uk_UA": "",
@@ -8589,7 +8589,7 @@
"pl_PL": "",
"pt_BR": "",
"ru_RU": "Блок цифр 3",
- "sv_SE": "",
+ "sv_SE": "Keypad 3",
"th_TH": "",
"tr_TR": "",
"uk_UA": "",
@@ -8614,7 +8614,7 @@
"pl_PL": "",
"pt_BR": "",
"ru_RU": "Блок цифр 4",
- "sv_SE": "",
+ "sv_SE": "Keypad 4",
"th_TH": "",
"tr_TR": "",
"uk_UA": "",
@@ -8639,7 +8639,7 @@
"pl_PL": "",
"pt_BR": "",
"ru_RU": "Блок цифр 5",
- "sv_SE": "",
+ "sv_SE": "Keypad 5",
"th_TH": "",
"tr_TR": "",
"uk_UA": "",
@@ -8664,7 +8664,7 @@
"pl_PL": "",
"pt_BR": "",
"ru_RU": "Блок цифр 6",
- "sv_SE": "",
+ "sv_SE": "Keypad 6",
"th_TH": "",
"tr_TR": "",
"uk_UA": "",
@@ -8689,7 +8689,7 @@
"pl_PL": "",
"pt_BR": "",
"ru_RU": "Блок цифр 7",
- "sv_SE": "",
+ "sv_SE": "Keypad 7",
"th_TH": "",
"tr_TR": "",
"uk_UA": "",
@@ -8714,7 +8714,7 @@
"pl_PL": "",
"pt_BR": "",
"ru_RU": "Блок цифр 8",
- "sv_SE": "",
+ "sv_SE": "Keypad 8",
"th_TH": "",
"tr_TR": "",
"uk_UA": "",
@@ -8739,7 +8739,7 @@
"pl_PL": "",
"pt_BR": "",
"ru_RU": "Блок цифр 9",
- "sv_SE": "",
+ "sv_SE": "Keypad 9",
"th_TH": "",
"tr_TR": "",
"uk_UA": "",
@@ -8889,7 +8889,7 @@
"pl_PL": "",
"pt_BR": "",
"ru_RU": "Enter (блок цифр)",
- "sv_SE": "",
+ "sv_SE": "Keypad Enter",
"th_TH": "",
"tr_TR": "",
"uk_UA": "",
@@ -8913,7 +8913,7 @@
"no_NO": "",
"pl_PL": "",
"pt_BR": "",
- "ru_RU": "",
+ "ru_RU": "0",
"sv_SE": "",
"th_TH": "",
"tr_TR": "",
@@ -8938,7 +8938,7 @@
"no_NO": "",
"pl_PL": "",
"pt_BR": "",
- "ru_RU": "",
+ "ru_RU": "1",
"sv_SE": "",
"th_TH": "",
"tr_TR": "",
@@ -8963,7 +8963,7 @@
"no_NO": "",
"pl_PL": "",
"pt_BR": "",
- "ru_RU": "",
+ "ru_RU": "2",
"sv_SE": "",
"th_TH": "",
"tr_TR": "",
@@ -8988,7 +8988,7 @@
"no_NO": "",
"pl_PL": "",
"pt_BR": "",
- "ru_RU": "",
+ "ru_RU": "3",
"sv_SE": "",
"th_TH": "",
"tr_TR": "",
@@ -9013,7 +9013,7 @@
"no_NO": "",
"pl_PL": "",
"pt_BR": "",
- "ru_RU": "",
+ "ru_RU": "4",
"sv_SE": "",
"th_TH": "",
"tr_TR": "",
@@ -9038,7 +9038,7 @@
"no_NO": "",
"pl_PL": "",
"pt_BR": "",
- "ru_RU": "",
+ "ru_RU": "5",
"sv_SE": "",
"th_TH": "",
"tr_TR": "",
@@ -9063,7 +9063,7 @@
"no_NO": "",
"pl_PL": "",
"pt_BR": "",
- "ru_RU": "",
+ "ru_RU": "6",
"sv_SE": "",
"th_TH": "",
"tr_TR": "",
@@ -9088,7 +9088,7 @@
"no_NO": "",
"pl_PL": "",
"pt_BR": "",
- "ru_RU": "",
+ "ru_RU": "7",
"sv_SE": "",
"th_TH": "",
"tr_TR": "",
@@ -9113,7 +9113,7 @@
"no_NO": "",
"pl_PL": "",
"pt_BR": "",
- "ru_RU": "",
+ "ru_RU": "8",
"sv_SE": "",
"th_TH": "",
"tr_TR": "",
@@ -9138,7 +9138,7 @@
"no_NO": "",
"pl_PL": "",
"pt_BR": "",
- "ru_RU": "",
+ "ru_RU": "9",
"sv_SE": "",
"th_TH": "",
"tr_TR": "",
@@ -9163,7 +9163,7 @@
"no_NO": "",
"pl_PL": "",
"pt_BR": "",
- "ru_RU": "",
+ "ru_RU": "~",
"sv_SE": "",
"th_TH": "",
"tr_TR": "",
@@ -9188,7 +9188,7 @@
"no_NO": "",
"pl_PL": "",
"pt_BR": "",
- "ru_RU": "",
+ "ru_RU": "`",
"sv_SE": "",
"th_TH": "",
"tr_TR": "",
@@ -9213,7 +9213,7 @@
"no_NO": "",
"pl_PL": "",
"pt_BR": "",
- "ru_RU": "",
+ "ru_RU": "-",
"sv_SE": "",
"th_TH": "",
"tr_TR": "",
@@ -9238,7 +9238,7 @@
"no_NO": "",
"pl_PL": "",
"pt_BR": "",
- "ru_RU": "",
+ "ru_RU": "+",
"sv_SE": "",
"th_TH": "",
"tr_TR": "",
@@ -9263,7 +9263,7 @@
"no_NO": "",
"pl_PL": "",
"pt_BR": "",
- "ru_RU": "",
+ "ru_RU": "[",
"sv_SE": "",
"th_TH": "",
"tr_TR": "",
@@ -9288,7 +9288,7 @@
"no_NO": "",
"pl_PL": "",
"pt_BR": "",
- "ru_RU": "",
+ "ru_RU": "]",
"sv_SE": "",
"th_TH": "",
"tr_TR": "",
@@ -9313,7 +9313,7 @@
"no_NO": "",
"pl_PL": "",
"pt_BR": "",
- "ru_RU": "",
+ "ru_RU": ";",
"sv_SE": "",
"th_TH": "",
"tr_TR": "",
@@ -9363,7 +9363,7 @@
"no_NO": "",
"pl_PL": "",
"pt_BR": "",
- "ru_RU": "",
+ "ru_RU": ",",
"sv_SE": "",
"th_TH": "",
"tr_TR": "",
@@ -9388,7 +9388,7 @@
"no_NO": "",
"pl_PL": "",
"pt_BR": "",
- "ru_RU": "",
+ "ru_RU": ".",
"sv_SE": "",
"th_TH": "",
"tr_TR": "",
@@ -9413,7 +9413,7 @@
"no_NO": "",
"pl_PL": "",
"pt_BR": "",
- "ru_RU": "",
+ "ru_RU": "/",
"sv_SE": "",
"th_TH": "",
"tr_TR": "",
@@ -9738,7 +9738,7 @@
"no_NO": "",
"pl_PL": "",
"pt_BR": "",
- "ru_RU": "",
+ "ru_RU": "-",
"sv_SE": "",
"th_TH": "",
"tr_TR": "",
@@ -9763,7 +9763,7 @@
"no_NO": "",
"pl_PL": "",
"pt_BR": "",
- "ru_RU": "",
+ "ru_RU": "+",
"sv_SE": "",
"th_TH": "",
"tr_TR": "4",
@@ -9789,7 +9789,7 @@
"pl_PL": "",
"pt_BR": "",
"ru_RU": "Кнопка меню",
- "sv_SE": "",
+ "sv_SE": "Guide",
"th_TH": "",
"tr_TR": "Rehber",
"uk_UA": "",
@@ -12438,7 +12438,7 @@
"no_NO": "",
"pl_PL": "",
"pt_BR": "",
- "ru_RU": "",
+ "ru_RU": "{0}: {1}",
"sv_SE": "",
"th_TH": "",
"tr_TR": "",
@@ -14289,7 +14289,7 @@
"pl_PL": "Seria Amiibo",
"pt_BR": "Franquia Amiibo",
"ru_RU": "Серия Amiibo",
- "sv_SE": "",
+ "sv_SE": "Amiibo Series",
"th_TH": "",
"tr_TR": "Amiibo Serisi",
"uk_UA": "Серія Amiibo",
@@ -15755,7 +15755,7 @@
"el_GR": "",
"en_US": "Aspect Ratio applied to the renderer window.\n\nOnly change this if you're using an aspect ratio mod for your game, otherwise the graphics will be stretched.\n\nLeave on 16:9 if unsure.",
"es_ES": "Relación de aspecto aplicada a la ventana del renderizador.\n\nSolamente modificar esto si estás utilizando un mod de relación de aspecto para su juego, en cualquier otro caso los gráficos se estirarán.\n\nDejar en 16:9 si no sabe que hacer.",
- "fr_FR": "Format\u00A0d'affichage appliqué à la fenêtre du moteur de rendu.\n\nChangez cela uniquement si vous utilisez un mod changeant le format\u00A0d'affichage pour votre jeu, sinon les graphismes seront étirés.\n\nLaissez sur 16:9 si vous n'êtes pas sûr.",
+ "fr_FR": "Format d'affichage appliqué à la fenêtre du moteur de rendu.\n\nChangez cela uniquement si vous utilisez un mod changeant le format d'affichage pour votre jeu, sinon les graphismes seront étirés.\n\nLaissez sur 16:9 si vous n'êtes pas sûr.",
"he_IL": "",
"it_IT": "Proporzioni dello schermo applicate alla finestra di renderizzazione.\n\nCambialo solo se stai usando una mod di proporzioni per il tuo gioco, altrimenti la grafica verrà allungata.\n\nLasciare il 16:9 se incerto.",
"ja_JP": "レンダリングウインドウに適用するアスペクト比です.\n\nゲームにアスペクト比を変更する mod を使用している場合のみ変更してください.\n\nわからない場合は16:9のままにしておいてください.\n",
@@ -17428,23 +17428,23 @@
"ar_SA": "الإصدار: {0}",
"de_DE": "",
"el_GR": "",
- "en_US": "Version {0} - {1}",
- "es_ES": "Versión {0} - {1}",
+ "en_US": "Version {0}",
+ "es_ES": "Versión {0}",
"fr_FR": "",
- "he_IL": "גרסה {0} - {1}",
- "it_IT": "Versione {0} - {1}",
- "ja_JP": "バージョン {0} - {1}",
- "ko_KR": "버전 {0} - {1}",
- "no_NO": "Versjon {0} - {1}",
- "pl_PL": "Wersja {0} - {1}",
- "pt_BR": "Versão {0} - {1}",
- "ru_RU": "Версия {0} - {1}",
- "sv_SE": "",
- "th_TH": "เวอร์ชั่น {0} - {1}",
- "tr_TR": "Sürüm {0} - {1}",
- "uk_UA": "Версія {0} - {1}",
- "zh_CN": "游戏更新的版本 {0} - {1}",
- "zh_TW": "版本 {0} - {1}"
+ "he_IL": "גרסה: {0}",
+ "it_IT": "Versione {0}",
+ "ja_JP": "バージョン {0}",
+ "ko_KR": "버전 {0}",
+ "no_NO": "Versjon {0}",
+ "pl_PL": "Wersja {0}",
+ "pt_BR": "Versão {0}",
+ "ru_RU": "Версия {0}",
+ "sv_SE": "Version {0}",
+ "th_TH": "เวอร์ชั่น {0}",
+ "tr_TR": "Sürüm {0}",
+ "uk_UA": "Версія {0}",
+ "zh_CN": "游戏更新的版本 {0}",
+ "zh_TW": "版本 {0}"
}
},
{
@@ -17664,7 +17664,7 @@
"pl_PL": "",
"pt_BR": "Ryujinx - Informação",
"ru_RU": "Ryujinx - Информация",
- "sv_SE": "",
+ "sv_SE": "Ryujinx - Info",
"th_TH": "Ryujinx – ข้อมูล",
"tr_TR": "Ryujinx - Bilgi",
"uk_UA": "Ryujin x - Інформація",
@@ -18813,8 +18813,8 @@
"no_NO": "",
"pl_PL": "",
"pt_BR": "",
- "ru_RU": "",
- "sv_SE": "",
+ "ru_RU": "Amiibo",
+ "sv_SE": "Amiibo",
"th_TH": "",
"tr_TR": "",
"uk_UA": "",
@@ -19435,7 +19435,7 @@
"it_IT": "",
"ja_JP": "",
"ko_KR": "XCI 파일 트리머",
- "no_NO": "",
+ "no_NO": "XCI File Trimmer",
"pl_PL": "",
"pt_BR": "",
"ru_RU": "Уменьшение размера XCI файлов",
@@ -19639,7 +19639,7 @@
"pl_PL": "",
"pt_BR": "",
"ru_RU": "{0:n0} Мб",
- "sv_SE": "",
+ "sv_SE": "{0:n0} Mb",
"th_TH": "",
"tr_TR": "",
"uk_UA": "{0:n0} Мб",
@@ -20914,7 +20914,7 @@
"pl_PL": "Głoś",
"pt_BR": "",
"ru_RU": "Громкость",
- "sv_SE": "",
+ "sv_SE": "Vol",
"th_TH": "ระดับเสียง",
"tr_TR": "Ses",
"uk_UA": "Гуч.",
@@ -21055,7 +21055,7 @@
"el_GR": "Όνομα",
"en_US": "Name",
"es_ES": "Nombre",
- "fr_FR": "Nom\u00A0",
+ "fr_FR": "Nom ",
"he_IL": "שם",
"it_IT": "Nome",
"ja_JP": "名称",
@@ -21388,8 +21388,8 @@
"no_NO": "",
"pl_PL": "",
"pt_BR": "",
- "ru_RU": "",
- "sv_SE": "",
+ "ru_RU": "FSR",
+ "sv_SE": "FSR",
"th_TH": "",
"tr_TR": "",
"uk_UA": "",
@@ -21888,8 +21888,8 @@
"no_NO": "",
"pl_PL": "",
"pt_BR": "",
- "ru_RU": "",
- "sv_SE": "",
+ "ru_RU": "ldn_mitm",
+ "sv_SE": "ldn_mitm",
"th_TH": "",
"tr_TR": "",
"uk_UA": "",
@@ -21913,8 +21913,8 @@
"no_NO": "",
"pl_PL": "",
"pt_BR": "",
- "ru_RU": "",
- "sv_SE": "",
+ "ru_RU": "RyuLDN",
+ "sv_SE": "RyuLDN",
"th_TH": "",
"tr_TR": "",
"uk_UA": "",
@@ -22214,7 +22214,7 @@
"pl_PL": "",
"pt_BR": "",
"ru_RU": "Вертикальная синхронизация:",
- "sv_SE": "",
+ "sv_SE": "VSync:",
"th_TH": "",
"tr_TR": "",
"uk_UA": "Вертикальна синхронізація (VSync):",
@@ -22255,7 +22255,7 @@
"el_GR": "",
"en_US": "Switch",
"es_ES": "",
- "fr_FR": "",
+ "fr_FR": "Switch",
"he_IL": "",
"it_IT": "",
"ja_JP": "",
@@ -22264,7 +22264,7 @@
"pl_PL": "",
"pt_BR": "",
"ru_RU": "Консоль",
- "sv_SE": "",
+ "sv_SE": "Switch",
"th_TH": "",
"tr_TR": "",
"uk_UA": "",
@@ -22598,4 +22598,4 @@
}
}
]
-}
\ No newline at end of file
+}
diff --git a/src/Ryujinx/Ryujinx.csproj b/src/Ryujinx/Ryujinx.csproj
index 2a5e2558a..e18d4e9e6 100644
--- a/src/Ryujinx/Ryujinx.csproj
+++ b/src/Ryujinx/Ryujinx.csproj
@@ -143,4 +143,10 @@
+
+
+ SettingsHacksView.axaml
+ Code
+
+
\ No newline at end of file
diff --git a/src/Ryujinx/UI/ViewModels/BaseModel.cs b/src/Ryujinx/UI/ViewModels/BaseModel.cs
index d8f2e9096..e27c52867 100644
--- a/src/Ryujinx/UI/ViewModels/BaseModel.cs
+++ b/src/Ryujinx/UI/ViewModels/BaseModel.cs
@@ -13,8 +13,9 @@ namespace Ryujinx.Ava.UI.ViewModels
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
- protected void OnPropertiesChanged(params ReadOnlySpan propertyNames)
+ protected void OnPropertiesChanged(string firstPropertyName, params ReadOnlySpan propertyNames)
{
+ OnPropertyChanged(firstPropertyName);
foreach (var propertyName in propertyNames)
{
OnPropertyChanged(propertyName);
diff --git a/src/Ryujinx/UI/ViewModels/SettingsViewModel.cs b/src/Ryujinx/UI/ViewModels/SettingsViewModel.cs
index 9feaaba9b..ecd2d40dd 100644
--- a/src/Ryujinx/UI/ViewModels/SettingsViewModel.cs
+++ b/src/Ryujinx/UI/ViewModels/SettingsViewModel.cs
@@ -1,6 +1,7 @@
using Avalonia.Collections;
using Avalonia.Controls;
using Avalonia.Threading;
+using Gommon;
using LibHac.Tools.FsSystem;
using Ryujinx.Audio.Backends.OpenAL;
using Ryujinx.Audio.Backends.SDL2;
@@ -62,7 +63,9 @@ namespace Ryujinx.Ava.UI.ViewModels
private int _networkInterfaceIndex;
private int _multiplayerModeIndex;
private string _ldnPassphrase;
- private string _LdnServer;
+ private string _ldnServer;
+
+ private bool _xc2MenuSoftlockFix = ConfigurationState.Instance.Hacks.Xc2MenuSoftlockFix;
public int ResolutionScale
{
@@ -162,9 +165,7 @@ namespace Ryujinx.Ava.UI.ViewModels
get => _vSyncMode;
set
{
- if (value == VSyncMode.Custom ||
- value == VSyncMode.Switch ||
- value == VSyncMode.Unbounded)
+ if (value is VSyncMode.Custom or VSyncMode.Switch or VSyncMode.Unbounded)
{
_vSyncMode = value;
OnPropertyChanged();
@@ -258,6 +259,8 @@ namespace Ryujinx.Ava.UI.ViewModels
public bool UseHypervisor { get; set; }
public bool DisableP2P { get; set; }
+ public bool ShowDirtyHacks => ConfigurationState.Instance.Hacks.ShowDirtyHacks;
+
public string TimeZone { get; set; }
public string ShaderDumpPath { get; set; }
@@ -274,6 +277,17 @@ namespace Ryujinx.Ava.UI.ViewModels
}
}
+ public bool Xc2MenuSoftlockFixEnabled
+ {
+ get => _xc2MenuSoftlockFix;
+ set
+ {
+ _xc2MenuSoftlockFix = value;
+
+ OnPropertyChanged();
+ }
+ }
+
public int Language { get; set; }
public int Region { get; set; }
public int FsGlobalAccessLogMode { get; set; }
@@ -374,10 +388,10 @@ namespace Ryujinx.Ava.UI.ViewModels
public string LdnServer
{
- get => _LdnServer;
+ get => _ldnServer;
set
{
- _LdnServer = value;
+ _ldnServer = value;
OnPropertyChanged();
}
}
@@ -746,6 +760,9 @@ namespace Ryujinx.Ava.UI.ViewModels
config.Multiplayer.DisableP2p.Value = DisableP2P;
config.Multiplayer.LdnPassphrase.Value = LdnPassphrase;
config.Multiplayer.LdnServer.Value = LdnServer;
+
+ // Dirty Hacks
+ config.Hacks.Xc2MenuSoftlockFix.Value = Xc2MenuSoftlockFixEnabled;
config.ToFileFormat().SaveConfig(Program.ConfigurationPath);
@@ -779,5 +796,18 @@ namespace Ryujinx.Ava.UI.ViewModels
RevertIfNotSaved();
CloseWindow?.Invoke();
}
+
+ public static string Xc2MenuFixTooltip { get; } = Lambda.String(sb =>
+ {
+ sb.AppendLine(
+ "This fix applies a 2ms delay (via 'Thread.Sleep(2)') every time the game tries to read data from the emulated Switch filesystem.")
+ .AppendLine();
+
+ sb.AppendLine("From the issue on GitHub:").AppendLine();
+ sb.Append(
+ "When clicking very fast from game main menu to 2nd submenu, " +
+ "there is a low chance that the game will softlock, " +
+ "the submenu won't show up, while background music is still there.");
+ });
}
}
diff --git a/src/Ryujinx/UI/Views/Settings/SettingsHacksView.axaml b/src/Ryujinx/UI/Views/Settings/SettingsHacksView.axaml
new file mode 100644
index 000000000..b7817f064
--- /dev/null
+++ b/src/Ryujinx/UI/Views/Settings/SettingsHacksView.axaml
@@ -0,0 +1,48 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Ryujinx/UI/Views/Settings/SettingsHacksView.axaml.cs b/src/Ryujinx/UI/Views/Settings/SettingsHacksView.axaml.cs
new file mode 100644
index 000000000..f9e0958ca
--- /dev/null
+++ b/src/Ryujinx/UI/Views/Settings/SettingsHacksView.axaml.cs
@@ -0,0 +1,17 @@
+using Avalonia.Controls;
+using Avalonia.Interactivity;
+using Ryujinx.Ava.UI.ViewModels;
+using Ryujinx.UI.Common.Configuration;
+
+namespace Ryujinx.Ava.UI.Views.Settings
+{
+ public partial class SettingsHacksView : UserControl
+ {
+ public SettingsViewModel ViewModel;
+
+ public SettingsHacksView()
+ {
+ InitializeComponent();
+ }
+ }
+}
diff --git a/src/Ryujinx/UI/Windows/SettingsWindow.axaml b/src/Ryujinx/UI/Windows/SettingsWindow.axaml
index 2bf5b55e7..59302b6fc 100644
--- a/src/Ryujinx/UI/Windows/SettingsWindow.axaml
+++ b/src/Ryujinx/UI/Windows/SettingsWindow.axaml
@@ -37,6 +37,7 @@
+
+