diff --git a/.github/workflows/canary.yml b/.github/workflows/canary.yml
index b352e82d7..3100671e9 100644
--- a/.github/workflows/canary.yml
+++ b/.github/workflows/canary.yml
@@ -61,9 +61,9 @@ jobs:
| Platform | Artifact |
|--|--|
- | Windows 64 bit | [Canary Windows Artifact](https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-canary-${{ steps.version_info.outputs.build_version }}-win_x64.zip) |
- | Linux 64 bit | [Canary Linux Artifact](https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-canary-${{ steps.version_info.outputs.build_version }}-linux_x64.tar.gz) |
- | Linux arm 64 bit | [Canary Linux arm Artifact](https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-canary-${{ steps.version_info.outputs.build_version }}-linux_arm64.tar.gz) |
+ | Windows 64-bit | [Canary Windows Artifact](https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-canary-${{ steps.version_info.outputs.build_version }}-win_x64.zip) |
+ | Linux 64-bit | [Canary Linux Artifact](https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-canary-${{ steps.version_info.outputs.build_version }}-linux_x64.tar.gz) |
+ | Linux ARM 64-bit | [Canary Linux ARM Artifact](https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-canary-${{ steps.version_info.outputs.build_version }}-linux_arm64.tar.gz) |
| macOS | [Canary macOS artifact](https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-canary-${{ steps.version_info.outputs.build_version }}-macos_universal.app.tar.gz) |
**Full Changelog**: https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_SOURCE_REPO }}/compare/Canary-${{ steps.version_info.outputs.prev_build_version }}...Canary-${{ steps.version_info.outputs.build_version }}
@@ -200,10 +200,10 @@ jobs:
| Platform | Artifact |
|--|--|
- | Windows 64 bit | https://github.com/${{ github.repository }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-canary-${{ steps.version_info.outputs.build_version }}-win_x64.zip |
- | Linux 64 bit | https://github.com/${{ github.repository }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-canary-${{ steps.version_info.outputs.build_version }}-linux_x64.tar.gz |
- | Linux arm 64 bit | https://github.com/${{ github.repository }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-canary-${{ steps.version_info.outputs.build_version }}-linux_arm64.tar.gz |
- | Macos | https://github.com/${{ github.repository }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-canary-${{ steps.version_info.outputs.build_version }}-macos_universal.app.tar.gz |
+ | Windows 64-bit | https://github.com/${{ github.repository }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-canary-${{ steps.version_info.outputs.build_version }}-win_x64.zip |
+ | Linux 64-bit | https://github.com/${{ github.repository }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-canary-${{ steps.version_info.outputs.build_version }}-linux_x64.tar.gz |
+ | Linux ARM 64-bit | https://github.com/${{ github.repository }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-canary-${{ steps.version_info.outputs.build_version }}-linux_arm64.tar.gz |
+ | macOS | https://github.com/${{ github.repository }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-canary-${{ steps.version_info.outputs.build_version }}-macos_universal.app.tar.gz |
"**Full Changelog**: https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_SOURCE_REPO }}/compare/Canary-${{ steps.version_info.outputs.prev_build_version }}...Canary-${{ steps.version_info.outputs.build_version }}"
omitBodyDuringUpdate: true
@@ -272,19 +272,7 @@ jobs:
name: "Canary ${{ steps.version_info.outputs.build_version }}"
artifacts: "publish_ava/*.tar.gz, publish_headless/*.tar.gz"
tag: ${{ steps.version_info.outputs.build_version }}
- body: |
- # Canary builds:
-
- These builds are experimental and may sometimes not work, use [regular builds](https://github.com/GreemDev/Ryujinx/releases/latest) instead if that sounds like something you don't want to deal with.
-
- | Platform | Artifact |
- |--|--|
- | Windows 64 bit | https://github.com/${{ github.repository }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-canary-${{ steps.version_info.outputs.build_version }}-win_x64.zip |
- | Linux 64 bit | https://github.com/${{ github.repository }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-canary-${{ steps.version_info.outputs.build_version }}-linux_x64.tar.gz |
- | Linux arm 64 bit | https://github.com/${{ github.repository }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-canary-${{ steps.version_info.outputs.build_version }}-linux_arm64.tar.gz |
- | Macos | https://github.com/${{ github.repository }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-canary-${{ steps.version_info.outputs.build_version }}-macos_universal.app.tar.gz |
-
- "**Full Changelog**: https://github.com/${{ github.repository }}/compare/Canary-${{ steps.version_info.outputs.prev_build_version }}...Canary-${{ steps.version_info.outputs.build_version }}"
+ body: ""
omitBodyDuringUpdate: true
allowUpdates: true
replacesArtifacts: true
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index 815321dfe..59c31c71b 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -57,9 +57,9 @@ jobs:
# Regular builds:
| Platform | Artifact |
|--|--|
- | Windows 64 bit | [Release Windows Artifact](https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-${{ steps.version_info.outputs.build_version }}-win_x64.zip) |
- | Linux 64 bit | [Release Linux Artifact](https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-${{ steps.version_info.outputs.build_version }}-linux_x64.tar.gz) |
- | Linux arm 64 bit | [Release Linux arm Artifact](https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-${{ steps.version_info.outputs.build_version }}-linux_arm64.tar.gz) |
+ | Windows 64-bit | [Release Windows Artifact](https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-${{ steps.version_info.outputs.build_version }}-win_x64.zip) |
+ | Linux 64-bit | [Release Linux Artifact](https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-${{ steps.version_info.outputs.build_version }}-linux_x64.tar.gz) |
+ | Linux ARM 64-bit | [Release Linux ARM Artifact](https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-${{ steps.version_info.outputs.build_version }}-linux_arm64.tar.gz) |
| macOS | [Release macOS Artifact](https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-${{ steps.version_info.outputs.build_version }}-macos_universal.app.tar.gz) |
**Full Changelog**: https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/compare/${{ steps.version_info.outputs.prev_build_version }}...${{ steps.version_info.outputs.build_version }}
@@ -189,10 +189,10 @@ jobs:
# Regular builds:
| Platform | Artifact |
|--|--|
- | Windows 64 bit | https://github.com/${{ github.repository }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-${{ steps.version_info.outputs.build_version }}-win_x64.zip |
- | Linux 64 bit | https://github.com/${{ github.repository }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-${{ steps.version_info.outputs.build_version }}-linux_x64.tar.gz |
- | Linux arm 64 bit | https://github.com/${{ github.repository }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-${{ steps.version_info.outputs.build_version }}-linux_arm64.tar.gz |
- | Macos | https://github.com/${{ github.repository }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-${{ steps.version_info.outputs.build_version }}-macos_universal.app.tar.gz |
+ | Windows 64-bit | https://github.com/${{ github.repository }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-${{ steps.version_info.outputs.build_version }}-win_x64.zip |
+ | Linux 64-bit | https://github.com/${{ github.repository }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-${{ steps.version_info.outputs.build_version }}-linux_x64.tar.gz |
+ | Linux ARM 64-bit | https://github.com/${{ github.repository }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-${{ steps.version_info.outputs.build_version }}-linux_arm64.tar.gz |
+ | macOS | https://github.com/${{ github.repository }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-${{ steps.version_info.outputs.build_version }}-macos_universal.app.tar.gz |
"**Full Changelog**: https://github.com/${{ github.repository }}/compare/${{ steps.version_info.outputs.prev_build_version }}...${{ steps.version_info.outputs.build_version }}"
omitBodyDuringUpdate: true
@@ -261,16 +261,7 @@ jobs:
name: ${{ steps.version_info.outputs.build_version }}
artifacts: "publish/*.tar.gz, publish_headless/*.tar.gz"
tag: ${{ steps.version_info.outputs.build_version }}
- body: |
- # Regular builds:
- | Platform | Artifact |
- |--|--|
- | Windows 64 bit | https://github.com/${{ github.repository }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-${{ steps.version_info.outputs.build_version }}-win_x64.zip |
- | Linux 64 bit | https://github.com/${{ github.repository }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-${{ steps.version_info.outputs.build_version }}-linux_x64.tar.gz |
- | Linux arm 64 bit | https://github.com/${{ github.repository }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-${{ steps.version_info.outputs.build_version }}-linux_arm64.tar.gz |
- | Macos | https://github.com/${{ github.repository }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-${{ steps.version_info.outputs.build_version }}-macos_universal.app.tar.gz |
-
- "**Full Changelog**: https://github.com/${{ github.repository }}/compare/${{ steps.version_info.outputs.prev_build_version }}...${{ steps.version_info.outputs.build_version }}"
+ body: ""
omitBodyDuringUpdate: true
allowUpdates: true
replacesArtifacts: true
diff --git a/distribution/misc/macOS.svg b/distribution/misc/macOS.svg
deleted file mode 100644
index 4bdd453a8..000000000
--- a/distribution/misc/macOS.svg
+++ /dev/null
@@ -1,61 +0,0 @@
-
diff --git a/src/Ryujinx.BuildValidationTasks/LocaleValidationTask.cs b/src/Ryujinx.BuildValidationTasks/LocaleValidationTask.cs
index 183228fdd..6dc3d8aa8 100644
--- a/src/Ryujinx.BuildValidationTasks/LocaleValidationTask.cs
+++ b/src/Ryujinx.BuildValidationTasks/LocaleValidationTask.cs
@@ -14,20 +14,20 @@ namespace Ryujinx.BuildValidationTasks
{
string path = System.Reflection.Assembly.GetExecutingAssembly().Location;
- if (path.Split(new string[] { "src" }, StringSplitOptions.None).Length == 1 )
+ if (path.Split(["src"], StringSplitOptions.None).Length == 1)
{
//i assume that we are in a build directory in the solution dir
- path = new FileInfo(path).Directory.Parent.GetDirectories("src")[0].GetDirectories("Ryujinx")[0].GetDirectories("Assets")[0].GetFiles("locales.json")[0].FullName;
+ path = new FileInfo(path).Directory!.Parent!.GetDirectories("src")[0].GetDirectories("Ryujinx")[0].GetDirectories("Assets")[0].GetFiles("locales.json")[0].FullName;
}
else
{
- path = path.Split(new string[] { "src" }, StringSplitOptions.None)[0];
- path = new FileInfo(path).Directory.GetDirectories("src")[0].GetDirectories("Ryujinx")[0].GetDirectories("Assets")[0].GetFiles("locales.json")[0].FullName;
+ path = path.Split(["src"], StringSplitOptions.None)[0];
+ path = new FileInfo(path).Directory!.GetDirectories("src")[0].GetDirectories("Ryujinx")[0].GetDirectories("Assets")[0].GetFiles("locales.json")[0].FullName;
}
string data;
- using (StreamReader sr = new StreamReader(path))
+ using (StreamReader sr = new(path))
{
data = sr.ReadToEnd();
}
@@ -38,13 +38,10 @@ namespace Ryujinx.BuildValidationTasks
{
LocalesEntry locale = json.Locales[i];
- foreach (string language in json.Languages)
+ foreach (string langCode in json.Languages.Where(it => !locale.Translations.ContainsKey(it)))
{
- if (!locale.Translations.ContainsKey(language))
- {
- locale.Translations.Add(language, "");
- Log.LogMessage(MessageImportance.High, $"Added {{{language}}} to Locale {{{locale.ID}}}");
- }
+ locale.Translations.Add(langCode, string.Empty);
+ Log.LogMessage(MessageImportance.High, $"Added '{langCode}' to Locale '{locale.ID}'");
}
locale.Translations = locale.Translations.OrderBy(pair => pair.Key).ToDictionary(pair => pair.Key, pair => pair.Value);
@@ -53,7 +50,7 @@ namespace Ryujinx.BuildValidationTasks
string jsonString = JsonConvert.SerializeObject(json, Formatting.Indented);
- using (StreamWriter sw = new StreamWriter(path))
+ using (StreamWriter sw = new(path))
{
sw.Write(jsonString);
}
diff --git a/src/Ryujinx.Common/ReleaseInformation.cs b/src/Ryujinx.Common/ReleaseInformation.cs
index 011d9848a..cbf93013f 100644
--- a/src/Ryujinx.Common/ReleaseInformation.cs
+++ b/src/Ryujinx.Common/ReleaseInformation.cs
@@ -6,7 +6,6 @@ namespace Ryujinx.Common
// DO NOT EDIT, filled by CI
public static class ReleaseInformation
{
- private const string FlatHubChannel = "flathub";
private const string CanaryChannel = "canary";
private const string ReleaseChannel = "release";
@@ -29,8 +28,6 @@ namespace Ryujinx.Common
!ReleaseChannelRepo.StartsWith("%%") &&
!ConfigFileName.StartsWith("%%");
- public static bool IsFlatHubBuild => IsValid && ReleaseChannelOwner.Equals(FlatHubChannel);
-
public static bool IsCanaryBuild => IsValid && ReleaseChannelName.Equals(CanaryChannel);
public static bool IsReleaseBuild => IsValid && ReleaseChannelName.Equals(ReleaseChannel);
diff --git a/src/Ryujinx.Common/Utilities/JsonHelper.cs b/src/Ryujinx.Common/Utilities/JsonHelper.cs
index 276dd5f8c..82eeaddc1 100644
--- a/src/Ryujinx.Common/Utilities/JsonHelper.cs
+++ b/src/Ryujinx.Common/Utilities/JsonHelper.cs
@@ -1,3 +1,4 @@
+using System;
using System.IO;
using System.Text;
using System.Text.Json;
@@ -27,9 +28,14 @@ namespace Ryujinx.Common.Utilities
ReadCommentHandling = JsonCommentHandling.Skip
};
- public static string Serialize(T value, JsonTypeInfo typeInfo) => JsonSerializer.Serialize(value, typeInfo);
+ public static string Serialize(T value, JsonTypeInfo typeInfo)
+ => JsonSerializer.Serialize(value, typeInfo);
- public static T Deserialize(string value, JsonTypeInfo typeInfo) => JsonSerializer.Deserialize(value, typeInfo);
+ public static T Deserialize(string value, JsonTypeInfo typeInfo)
+ => JsonSerializer.Deserialize(value, typeInfo);
+
+ public static T Deserialize(ReadOnlySpan utf8Value, JsonTypeInfo typeInfo)
+ => JsonSerializer.Deserialize(utf8Value, typeInfo);
public static void SerializeToFile(string filePath, T value, JsonTypeInfo typeInfo)
{
diff --git a/src/Ryujinx.Cpu/AppleHv/HvMemoryManager.cs b/src/Ryujinx.Cpu/AppleHv/HvMemoryManager.cs
index bb56a4344..74c39d6a8 100644
--- a/src/Ryujinx.Cpu/AppleHv/HvMemoryManager.cs
+++ b/src/Ryujinx.Cpu/AppleHv/HvMemoryManager.cs
@@ -230,25 +230,20 @@ namespace Ryujinx.Cpu.AppleHv
{
if (size == 0)
{
- return Enumerable.Empty();
+ yield break;
}
var guestRegions = GetPhysicalRegionsImpl(va, size);
if (guestRegions == null)
{
- return null;
+ yield break;
}
- var regions = new HostMemoryRange[guestRegions.Count];
-
- for (int i = 0; i < regions.Length; i++)
+ foreach (var guestRegion in guestRegions)
{
- var guestRegion = guestRegions[i];
nint pointer = _backingMemory.GetPointer(guestRegion.Address, guestRegion.Size);
- regions[i] = new HostMemoryRange((nuint)(ulong)pointer, guestRegion.Size);
+ yield return new HostMemoryRange((nuint)(ulong)pointer, guestRegion.Size);
}
-
- return regions;
}
///
@@ -256,23 +251,24 @@ namespace Ryujinx.Cpu.AppleHv
{
if (size == 0)
{
- return Enumerable.Empty();
+ yield break;
}
- return GetPhysicalRegionsImpl(va, size);
+ foreach (var physicalRegion in GetPhysicalRegionsImpl(va, size))
+ {
+ yield return physicalRegion;
+ }
}
- private List GetPhysicalRegionsImpl(ulong va, ulong size)
+ private IEnumerable GetPhysicalRegionsImpl(ulong va, ulong size)
{
if (!ValidateAddress(va) || !ValidateAddressAndSize(va, size))
{
- return null;
+ yield break;
}
int pages = GetPagesCount(va, (uint)size, out va);
- var regions = new List();
-
ulong regionStart = GetPhysicalAddressInternal(va);
ulong regionSize = PageSize;
@@ -280,14 +276,14 @@ namespace Ryujinx.Cpu.AppleHv
{
if (!ValidateAddress(va + PageSize))
{
- return null;
+ yield break;
}
ulong newPa = GetPhysicalAddressInternal(va + PageSize);
if (GetPhysicalAddressInternal(va) + PageSize != newPa)
{
- regions.Add(new MemoryRange(regionStart, regionSize));
+ yield return new MemoryRange(regionStart, regionSize);
regionStart = newPa;
regionSize = 0;
}
@@ -296,9 +292,7 @@ namespace Ryujinx.Cpu.AppleHv
regionSize += PageSize;
}
- regions.Add(new MemoryRange(regionStart, regionSize));
-
- return regions;
+ yield return new MemoryRange(regionStart, regionSize);
}
///
diff --git a/src/Ryujinx.Cpu/Jit/HostTracked/AddressSpacePartitionAllocator.cs b/src/Ryujinx.Cpu/Jit/HostTracked/AddressSpacePartitionAllocator.cs
index a49e0179d..f39b295cd 100644
--- a/src/Ryujinx.Cpu/Jit/HostTracked/AddressSpacePartitionAllocator.cs
+++ b/src/Ryujinx.Cpu/Jit/HostTracked/AddressSpacePartitionAllocator.cs
@@ -115,6 +115,9 @@ namespace Ryujinx.Cpu.Jit.HostTracked
}
private readonly AddressIntrusiveRedBlackTree _mappingTree;
+
+ // type is not Lock due to the unique usage of this mechanism,
+ // an arbitrary object is used as the lock passed in by constructor.
private readonly object _lock;
public Block(MemoryTracking tracking, Func readPtCallback, MemoryBlock memory, ulong size, object locker) : base(memory, size)
@@ -174,6 +177,9 @@ namespace Ryujinx.Cpu.Jit.HostTracked
private readonly MemoryTracking _tracking;
private readonly Func _readPtCallback;
+
+ // type is not Lock due to the unique usage of this mechanism,
+ // an arbitrary object is used as the lock passed in by constructor.
private readonly object _lock;
public AddressSpacePartitionAllocator(
diff --git a/src/Ryujinx.Cpu/Jit/MemoryManager.cs b/src/Ryujinx.Cpu/Jit/MemoryManager.cs
index 049e508d0..076fb6ad8 100644
--- a/src/Ryujinx.Cpu/Jit/MemoryManager.cs
+++ b/src/Ryujinx.Cpu/Jit/MemoryManager.cs
@@ -250,25 +250,20 @@ namespace Ryujinx.Cpu.Jit
{
if (size == 0)
{
- return Enumerable.Empty();
+ yield break;
}
var guestRegions = GetPhysicalRegionsImpl(va, size);
if (guestRegions == null)
{
- return null;
+ yield break;
}
- var regions = new HostMemoryRange[guestRegions.Count];
-
- for (int i = 0; i < regions.Length; i++)
+ foreach (var guestRegion in guestRegions)
{
- var guestRegion = guestRegions[i];
nint pointer = _backingMemory.GetPointer(guestRegion.Address, guestRegion.Size);
- regions[i] = new HostMemoryRange((nuint)(ulong)pointer, guestRegion.Size);
+ yield return new HostMemoryRange((nuint)(ulong)pointer, guestRegion.Size);
}
-
- return regions;
}
///
@@ -276,23 +271,24 @@ namespace Ryujinx.Cpu.Jit
{
if (size == 0)
{
- return Enumerable.Empty();
+ yield break;
}
- return GetPhysicalRegionsImpl(va, size);
+ foreach (var physicalRegion in GetPhysicalRegionsImpl(va, size))
+ {
+ yield return physicalRegion;
+ }
}
- private List GetPhysicalRegionsImpl(ulong va, ulong size)
+ private IEnumerable GetPhysicalRegionsImpl(ulong va, ulong size)
{
if (!ValidateAddress(va) || !ValidateAddressAndSize(va, size))
{
- return null;
+ yield break;
}
int pages = GetPagesCount(va, (uint)size, out va);
- var regions = new List();
-
ulong regionStart = GetPhysicalAddressInternal(va);
ulong regionSize = PageSize;
@@ -300,14 +296,14 @@ namespace Ryujinx.Cpu.Jit
{
if (!ValidateAddress(va + PageSize))
{
- return null;
+ yield break;
}
ulong newPa = GetPhysicalAddressInternal(va + PageSize);
if (GetPhysicalAddressInternal(va) + PageSize != newPa)
{
- regions.Add(new MemoryRange(regionStart, regionSize));
+ yield return new MemoryRange(regionStart, regionSize);
regionStart = newPa;
regionSize = 0;
}
@@ -316,9 +312,7 @@ namespace Ryujinx.Cpu.Jit
regionSize += PageSize;
}
- regions.Add(new MemoryRange(regionStart, regionSize));
-
- return regions;
+ yield return new MemoryRange(regionStart, regionSize);
}
///
diff --git a/src/Ryujinx.Cpu/Jit/MemoryManagerHostTracked.cs b/src/Ryujinx.Cpu/Jit/MemoryManagerHostTracked.cs
index 4dab212a7..499f991f2 100644
--- a/src/Ryujinx.Cpu/Jit/MemoryManagerHostTracked.cs
+++ b/src/Ryujinx.Cpu/Jit/MemoryManagerHostTracked.cs
@@ -475,17 +475,15 @@ namespace Ryujinx.Cpu.Jit
return GetPhysicalRegionsImpl(va, size);
}
- private List GetPhysicalRegionsImpl(ulong va, ulong size)
+ private IEnumerable GetPhysicalRegionsImpl(ulong va, ulong size)
{
if (!ValidateAddress(va) || !ValidateAddressAndSize(va, size))
{
- return null;
+ yield break;
}
int pages = GetPagesCount(va, (uint)size, out va);
- var regions = new List();
-
ulong regionStart = GetPhysicalAddressInternal(va);
ulong regionSize = PageSize;
@@ -493,14 +491,14 @@ namespace Ryujinx.Cpu.Jit
{
if (!ValidateAddress(va + PageSize))
{
- return null;
+ yield break;
}
ulong newPa = GetPhysicalAddressInternal(va + PageSize);
if (GetPhysicalAddressInternal(va) + PageSize != newPa)
{
- regions.Add(new MemoryRange(regionStart, regionSize));
+ yield return new MemoryRange(regionStart, regionSize);
regionStart = newPa;
regionSize = 0;
}
@@ -509,9 +507,7 @@ namespace Ryujinx.Cpu.Jit
regionSize += PageSize;
}
- regions.Add(new MemoryRange(regionStart, regionSize));
-
- return regions;
+ yield return new MemoryRange(regionStart, regionSize);
}
///
diff --git a/src/Ryujinx.Cpu/LightningJit/CodeGen/Arm64/StackWalker.cs b/src/Ryujinx.Cpu/LightningJit/CodeGen/Arm64/StackWalker.cs
index 3ce7c4f9c..1432c4598 100644
--- a/src/Ryujinx.Cpu/LightningJit/CodeGen/Arm64/StackWalker.cs
+++ b/src/Ryujinx.Cpu/LightningJit/CodeGen/Arm64/StackWalker.cs
@@ -8,8 +8,6 @@ namespace Ryujinx.Cpu.LightningJit.CodeGen.Arm64
{
public IEnumerable GetCallStack(nint framePointer, nint codeRegionStart, int codeRegionSize, nint codeRegion2Start, int codeRegion2Size)
{
- List functionPointers = new();
-
while (true)
{
nint functionPointer = Marshal.ReadIntPtr(framePointer, nint.Size);
@@ -20,11 +18,9 @@ namespace Ryujinx.Cpu.LightningJit.CodeGen.Arm64
break;
}
- functionPointers.Add((ulong)functionPointer - 4);
+ yield return (ulong)functionPointer - 4;
framePointer = Marshal.ReadIntPtr(framePointer);
}
-
- return functionPointers;
}
}
}
diff --git a/src/Ryujinx.Graphics.Vulkan/BufferMirrorRangeList.cs b/src/Ryujinx.Graphics.Vulkan/BufferMirrorRangeList.cs
index 5722ca1ac..e79248a47 100644
--- a/src/Ryujinx.Graphics.Vulkan/BufferMirrorRangeList.cs
+++ b/src/Ryujinx.Graphics.Vulkan/BufferMirrorRangeList.cs
@@ -168,16 +168,14 @@ namespace Ryujinx.Graphics.Vulkan
return BinarySearch(list, offset, size) >= 0;
}
- public readonly List FindOverlaps(int offset, int size)
+ public readonly IEnumerable FindOverlaps(int offset, int size)
{
var list = _ranges;
if (list == null)
{
- return null;
+ yield break;
}
- List result = null;
-
int index = BinarySearch(list, offset, size);
if (index >= 0)
@@ -189,12 +187,10 @@ namespace Ryujinx.Graphics.Vulkan
do
{
- (result ??= new List()).Add(list[index++]);
+ yield return list[index++];
}
while (index < list.Count && list[index].OverlapsWith(offset, size));
}
-
- return result;
}
private static int BinarySearch(List list, int offset, int size)
diff --git a/src/Ryujinx.Graphics.Vulkan/FormatCapabilities.cs b/src/Ryujinx.Graphics.Vulkan/FormatCapabilities.cs
index 5a3bd61bd..09f22889c 100644
--- a/src/Ryujinx.Graphics.Vulkan/FormatCapabilities.cs
+++ b/src/Ryujinx.Graphics.Vulkan/FormatCapabilities.cs
@@ -62,7 +62,7 @@ namespace Ryujinx.Graphics.Vulkan
_api = api;
_physicalDevice = physicalDevice;
- int totalFormats = Enum.GetNames(typeof(Format)).Length;
+ int totalFormats = Enum.GetNames().Length;
_bufferTable = new FormatFeatureFlags[totalFormats];
_optimalTable = new FormatFeatureFlags[totalFormats];
@@ -148,7 +148,7 @@ namespace Ryujinx.Graphics.Vulkan
return (formatFeatureFlags & flags) == flags;
}
- public VkFormat ConvertToVkFormat(Format srcFormat)
+ public VkFormat ConvertToVkFormat(Format srcFormat, bool storageFeatureFlagRequired)
{
var format = FormatTable.GetFormat(srcFormat);
@@ -165,7 +165,7 @@ namespace Ryujinx.Graphics.Vulkan
requiredFeatures |= FormatFeatureFlags.ColorAttachmentBit;
}
- if (srcFormat.IsImageCompatible())
+ if (srcFormat.IsImageCompatible() && storageFeatureFlagRequired)
{
requiredFeatures |= FormatFeatureFlags.StorageImageBit;
}
diff --git a/src/Ryujinx.Graphics.Vulkan/FormatTable.cs b/src/Ryujinx.Graphics.Vulkan/FormatTable.cs
index 98796d9bf..305224cad 100644
--- a/src/Ryujinx.Graphics.Vulkan/FormatTable.cs
+++ b/src/Ryujinx.Graphics.Vulkan/FormatTable.cs
@@ -12,7 +12,7 @@ namespace Ryujinx.Graphics.Vulkan
static FormatTable()
{
- _table = new VkFormat[Enum.GetNames(typeof(Format)).Length];
+ _table = new VkFormat[Enum.GetNames().Length];
_reverseMap = new Dictionary();
#pragma warning disable IDE0055 // Disable formatting
diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineConverter.cs b/src/Ryujinx.Graphics.Vulkan/PipelineConverter.cs
index 85069c6b2..8a895f927 100644
--- a/src/Ryujinx.Graphics.Vulkan/PipelineConverter.cs
+++ b/src/Ryujinx.Graphics.Vulkan/PipelineConverter.cs
@@ -29,11 +29,17 @@ namespace Ryujinx.Graphics.Vulkan
int colorCount = 0;
int maxColorAttachmentIndex = -1;
+ bool isNotMsOrSupportsStorage = gd.Capabilities.SupportsShaderStorageImageMultisample ||
+ !state.DepthStencilFormat.IsImageCompatible();
+
for (int i = 0; i < state.AttachmentEnable.Length; i++)
{
if (state.AttachmentEnable[i])
{
- attachmentFormats[attachmentCount] = gd.FormatCapabilities.ConvertToVkFormat(state.AttachmentFormats[i]);
+ bool isNotMsOrSupportsStorageAttachments = gd.Capabilities.SupportsShaderStorageImageMultisample ||
+ !state.AttachmentFormats[i].IsImageCompatible();
+
+ attachmentFormats[attachmentCount] = gd.FormatCapabilities.ConvertToVkFormat(state.AttachmentFormats[i], isNotMsOrSupportsStorageAttachments);
attachmentIndices[attachmentCount++] = i;
colorCount++;
@@ -43,7 +49,7 @@ namespace Ryujinx.Graphics.Vulkan
if (state.DepthStencilEnable)
{
- attachmentFormats[attachmentCount++] = gd.FormatCapabilities.ConvertToVkFormat(state.DepthStencilFormat);
+ attachmentFormats[attachmentCount++] = gd.FormatCapabilities.ConvertToVkFormat(state.DepthStencilFormat, isNotMsOrSupportsStorage);
}
if (attachmentCount != 0)
@@ -296,7 +302,10 @@ namespace Ryujinx.Graphics.Vulkan
{
if (state.AttachmentEnable[i])
{
- pipeline.Internal.AttachmentFormats[attachmentCount++] = gd.FormatCapabilities.ConvertToVkFormat(state.AttachmentFormats[i]);
+ bool isNotMsOrSupportsStorage = gd.Capabilities.SupportsShaderStorageImageMultisample ||
+ !state.AttachmentFormats[i].IsImageCompatible();
+
+ pipeline.Internal.AttachmentFormats[attachmentCount++] = gd.FormatCapabilities.ConvertToVkFormat(state.AttachmentFormats[i], isNotMsOrSupportsStorage);
maxColorAttachmentIndex = i;
if (state.AttachmentFormats[i].IsInteger())
@@ -310,7 +319,10 @@ namespace Ryujinx.Graphics.Vulkan
if (state.DepthStencilEnable)
{
- pipeline.Internal.AttachmentFormats[attachmentCount++] = gd.FormatCapabilities.ConvertToVkFormat(state.DepthStencilFormat);
+ bool isNotMsOrSupportsStorage = !state.DepthStencilFormat.IsImageCompatible() ||
+ gd.Capabilities.SupportsShaderStorageImageMultisample;
+
+ pipeline.Internal.AttachmentFormats[attachmentCount++] = gd.FormatCapabilities.ConvertToVkFormat(state.DepthStencilFormat, isNotMsOrSupportsStorage);
}
pipeline.ColorBlendAttachmentStateCount = (uint)(maxColorAttachmentIndex + 1);
diff --git a/src/Ryujinx.Graphics.Vulkan/Queries/Counters.cs b/src/Ryujinx.Graphics.Vulkan/Queries/Counters.cs
index 518ede5f3..c07e1c09c 100644
--- a/src/Ryujinx.Graphics.Vulkan/Queries/Counters.cs
+++ b/src/Ryujinx.Graphics.Vulkan/Queries/Counters.cs
@@ -13,7 +13,7 @@ namespace Ryujinx.Graphics.Vulkan.Queries
{
_pipeline = pipeline;
- int count = Enum.GetNames(typeof(CounterType)).Length;
+ int count = Enum.GetNames().Length;
_counterQueues = new CounterQueue[count];
diff --git a/src/Ryujinx.Graphics.Vulkan/TextureStorage.cs b/src/Ryujinx.Graphics.Vulkan/TextureStorage.cs
index 10b36a3f9..51ef528d4 100644
--- a/src/Ryujinx.Graphics.Vulkan/TextureStorage.cs
+++ b/src/Ryujinx.Graphics.Vulkan/TextureStorage.cs
@@ -77,7 +77,9 @@ namespace Ryujinx.Graphics.Vulkan
_device = device;
_info = info;
- var format = _gd.FormatCapabilities.ConvertToVkFormat(info.Format);
+ bool isMsImageStorageSupported = gd.Capabilities.SupportsShaderStorageImageMultisample || !info.Target.IsMultisample();
+
+ var format = _gd.FormatCapabilities.ConvertToVkFormat(info.Format, isMsImageStorageSupported);
var levels = (uint)info.Levels;
var layers = (uint)info.GetLayers();
var depth = (uint)(info.Target == Target.Texture3D ? info.Depth : 1);
@@ -91,7 +93,7 @@ namespace Ryujinx.Graphics.Vulkan
var sampleCountFlags = ConvertToSampleCountFlags(gd.Capabilities.SupportedSampleCounts, (uint)info.Samples);
- var usage = GetImageUsage(info.Format, info.Target, gd.Capabilities);
+ var usage = GetImageUsage(info.Format, gd.Capabilities, isMsImageStorageSupported, true);
var flags = ImageCreateFlags.CreateMutableFormatBit | ImageCreateFlags.CreateExtendedUsageBit;
@@ -305,7 +307,7 @@ namespace Ryujinx.Graphics.Vulkan
}
}
- public static ImageUsageFlags GetImageUsage(Format format, Target target, in HardwareCapabilities capabilities)
+ public static ImageUsageFlags GetImageUsage(Format format, in HardwareCapabilities capabilities, bool isMsImageStorageSupported, bool extendedUsage)
{
var usage = DefaultUsageFlags;
@@ -318,9 +320,7 @@ namespace Ryujinx.Graphics.Vulkan
usage |= ImageUsageFlags.ColorAttachmentBit;
}
- bool supportsMsStorage = capabilities.SupportsShaderStorageImageMultisample;
-
- if (format.IsImageCompatible() && (supportsMsStorage || !target.IsMultisample()))
+ if ((format.IsImageCompatible() && isMsImageStorageSupported) || extendedUsage)
{
usage |= ImageUsageFlags.StorageBit;
}
diff --git a/src/Ryujinx.Graphics.Vulkan/TextureView.cs b/src/Ryujinx.Graphics.Vulkan/TextureView.cs
index b7b936809..64d976a45 100644
--- a/src/Ryujinx.Graphics.Vulkan/TextureView.cs
+++ b/src/Ryujinx.Graphics.Vulkan/TextureView.cs
@@ -61,8 +61,11 @@ namespace Ryujinx.Graphics.Vulkan
gd.Textures.Add(this);
- var format = _gd.FormatCapabilities.ConvertToVkFormat(info.Format);
- var usage = TextureStorage.GetImageUsage(info.Format, info.Target, gd.Capabilities);
+ bool isMsImageStorageSupported = gd.Capabilities.SupportsShaderStorageImageMultisample || !info.Target.IsMultisample();
+
+ var format = _gd.FormatCapabilities.ConvertToVkFormat(info.Format, isMsImageStorageSupported);
+ var usage = TextureStorage.GetImageUsage(info.Format, gd.Capabilities, isMsImageStorageSupported, false);
+
var levels = (uint)info.Levels;
var layers = (uint)info.GetLayers();
diff --git a/src/Ryujinx.HLE/HOS/Horizon.cs b/src/Ryujinx.HLE/HOS/Horizon.cs
index c585aed54..f9c5ddecf 100644
--- a/src/Ryujinx.HLE/HOS/Horizon.cs
+++ b/src/Ryujinx.HLE/HOS/Horizon.cs
@@ -341,7 +341,7 @@ namespace Ryujinx.HLE.HOS
{
if (VirtualAmiibo.ApplicationBytes.Length > 0)
{
- VirtualAmiibo.ApplicationBytes = new byte[0];
+ VirtualAmiibo.ApplicationBytes = Array.Empty();
VirtualAmiibo.InputBin = string.Empty;
}
if (NfpDevices[nfpDeviceId].State == NfpDeviceState.SearchingForTag)
@@ -356,7 +356,7 @@ namespace Ryujinx.HLE.HOS
VirtualAmiibo.InputBin = path;
if (VirtualAmiibo.ApplicationBytes.Length > 0)
{
- VirtualAmiibo.ApplicationBytes = new byte[0];
+ VirtualAmiibo.ApplicationBytes = Array.Empty();
}
byte[] encryptedData = File.ReadAllBytes(path);
VirtualAmiiboFile newFile = AmiiboBinReader.ReadBinFile(encryptedData);
diff --git a/src/Ryujinx.HLE/HOS/Kernel/Common/KResourceLimit.cs b/src/Ryujinx.HLE/HOS/Kernel/Common/KResourceLimit.cs
index 90231b460..1763edce2 100644
--- a/src/Ryujinx.HLE/HOS/Kernel/Common/KResourceLimit.cs
+++ b/src/Ryujinx.HLE/HOS/Kernel/Common/KResourceLimit.cs
@@ -15,6 +15,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Common
private readonly long[] _current2;
private readonly long[] _peak;
+ // type is not Lock due to Monitor class usage
private readonly object _lock = new();
private readonly LinkedList _waitingThreads;
diff --git a/src/Ryujinx.HLE/HOS/Kernel/Threading/KCriticalSection.cs b/src/Ryujinx.HLE/HOS/Kernel/Threading/KCriticalSection.cs
index bfa6b68f6..b3fe5f1b6 100644
--- a/src/Ryujinx.HLE/HOS/Kernel/Threading/KCriticalSection.cs
+++ b/src/Ryujinx.HLE/HOS/Kernel/Threading/KCriticalSection.cs
@@ -5,10 +5,10 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
class KCriticalSection
{
private readonly KernelContext _context;
- private readonly object _lock = new();
private int _recursionCount;
-
- public object Lock => _lock;
+
+ // type is not Lock due to Monitor class usage
+ public object Lock { get; } = new();
public KCriticalSection(KernelContext context)
{
@@ -17,7 +17,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
public void Enter()
{
- Monitor.Enter(_lock);
+ Monitor.Enter(Lock);
_recursionCount++;
}
@@ -33,7 +33,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
{
ulong scheduledCoresMask = KScheduler.SelectThreads(_context);
- Monitor.Exit(_lock);
+ Monitor.Exit(Lock);
KThread currentThread = KernelStatic.GetCurrentThread();
bool isCurrentThreadSchedulable = currentThread != null && currentThread.IsSchedulable;
@@ -56,7 +56,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
}
else
{
- Monitor.Exit(_lock);
+ Monitor.Exit(Lock);
}
}
}
diff --git a/src/Ryujinx.HLE/HOS/ModLoader.cs b/src/Ryujinx.HLE/HOS/ModLoader.cs
index d8c62fc66..4bd695ae5 100644
--- a/src/Ryujinx.HLE/HOS/ModLoader.cs
+++ b/src/Ryujinx.HLE/HOS/ModLoader.cs
@@ -357,7 +357,6 @@ namespace Ryujinx.HLE.HOS
{
string cheatName = DefaultCheatName;
List instructions = new();
- List cheats = new();
using StreamReader cheatData = cheatFile.OpenText();
while (cheatData.ReadLine() is { } line)
@@ -373,13 +372,13 @@ namespace Ryujinx.HLE.HOS
Logger.Warning?.Print(LogClass.ModLoader, $"Ignoring cheat '{cheatFile.FullName}' because it is malformed");
- return Array.Empty();
+ yield break;
}
// Add the previous section to the list.
if (instructions.Count > 0)
{
- cheats.Add(new Cheat($"<{cheatName} Cheat>", cheatFile, instructions));
+ yield return new Cheat($"<{cheatName} Cheat>", cheatFile, instructions);
}
// Start a new cheat section.
@@ -396,10 +395,8 @@ namespace Ryujinx.HLE.HOS
// Add the last section being processed.
if (instructions.Count > 0)
{
- cheats.Add(new Cheat($"<{cheatName} Cheat>", cheatFile, instructions));
+ yield return new Cheat($"<{cheatName} Cheat>", cheatFile, instructions);
}
-
- return cheats;
}
// Assumes searchDirPaths don't overlap
diff --git a/src/Ryujinx.HLE/HOS/Services/IpcService.cs b/src/Ryujinx.HLE/HOS/Services/IpcService.cs
index 808f21c0e..cd3df4edf 100644
--- a/src/Ryujinx.HLE/HOS/Services/IpcService.cs
+++ b/src/Ryujinx.HLE/HOS/Services/IpcService.cs
@@ -23,18 +23,18 @@ namespace Ryujinx.HLE.HOS.Services
public IpcService(ServerBase server = null)
{
- CmifCommands = typeof(IpcService).Assembly.GetTypes()
+ CmifCommands = GetType().Assembly.GetTypes()
.Where(type => type == GetType())
.SelectMany(type => type.GetMethods(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public))
- .SelectMany(methodInfo => methodInfo.GetCustomAttributes(typeof(CommandCmifAttribute))
- .Select(command => (((CommandCmifAttribute)command).Id, methodInfo)))
+ .SelectMany(methodInfo => methodInfo.GetCustomAttributes()
+ .Select(command => (command.Id, methodInfo)))
.ToDictionary(command => command.Id, command => command.methodInfo);
- TipcCommands = typeof(IpcService).Assembly.GetTypes()
+ TipcCommands = GetType().Assembly.GetTypes()
.Where(type => type == GetType())
.SelectMany(type => type.GetMethods(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public))
- .SelectMany(methodInfo => methodInfo.GetCustomAttributes(typeof(CommandTipcAttribute))
- .Select(command => (((CommandTipcAttribute)command).Id, methodInfo)))
+ .SelectMany(methodInfo => methodInfo.GetCustomAttributes()
+ .Select(command => (command.Id, methodInfo)))
.ToDictionary(command => command.Id, command => command.methodInfo);
Server = server;
diff --git a/src/Ryujinx.HLE/HOS/Services/Ldn/UserServiceCreator/IUserLocalCommunicationService.cs b/src/Ryujinx.HLE/HOS/Services/Ldn/UserServiceCreator/IUserLocalCommunicationService.cs
index 9f65aed4b..b8b3014f1 100644
--- a/src/Ryujinx.HLE/HOS/Services/Ldn/UserServiceCreator/IUserLocalCommunicationService.cs
+++ b/src/Ryujinx.HLE/HOS/Services/Ldn/UserServiceCreator/IUserLocalCommunicationService.cs
@@ -444,7 +444,7 @@ namespace Ryujinx.HLE.HOS.Services.Ldn.UserServiceCreator
private ResultCode ScanInternal(IVirtualMemoryManager memory, ushort channel, ScanFilter scanFilter, ulong bufferPosition, ulong bufferSize, out ulong counter)
{
- ulong networkInfoSize = (ulong)Marshal.SizeOf(typeof(NetworkInfo));
+ ulong networkInfoSize = (ulong)Marshal.SizeOf();
ulong maxGames = bufferSize / networkInfoSize;
MemoryHelper.FillWithZeros(memory, bufferPosition, (int)bufferSize);
diff --git a/src/Ryujinx.HLE/HOS/Services/Nfc/AmiiboDecryption/AmiiboBinReader.cs b/src/Ryujinx.HLE/HOS/Services/Nfc/AmiiboDecryption/AmiiboBinReader.cs
index 13a5ef998..03063cb53 100644
--- a/src/Ryujinx.HLE/HOS/Services/Nfc/AmiiboDecryption/AmiiboBinReader.cs
+++ b/src/Ryujinx.HLE/HOS/Services/Nfc/AmiiboDecryption/AmiiboBinReader.cs
@@ -33,12 +33,15 @@ namespace Ryujinx.HLE.HOS.Services.Nfc.AmiiboDecryption
const int pageSize = 4;
const int totalBytes = totalPages * pageSize;
- if (fileBytes.Length < totalBytes)
+ if (fileBytes.Length == 532)
{
- return new VirtualAmiiboFile();
+ // add 8 bytes to the end of the file
+ byte[] newFileBytes = new byte[totalBytes];
+ Array.Copy(fileBytes, newFileBytes, fileBytes.Length);
+ fileBytes = newFileBytes;
}
- AmiiboDecrypter amiiboDecryptor = new AmiiboDecrypter(keyRetailBinPath);
+ AmiiboDecryptor amiiboDecryptor = new(keyRetailBinPath);
AmiiboDump amiiboDump = amiiboDecryptor.DecryptAmiiboDump(fileBytes);
byte[] titleId = new byte[8];
@@ -171,7 +174,15 @@ namespace Ryujinx.HLE.HOS.Services.Nfc.AmiiboDecryption
return false;
}
- AmiiboDecrypter amiiboDecryptor = new AmiiboDecrypter(keyRetailBinPath);
+ if (readBytes.Length == 532)
+ {
+ // add 8 bytes to the end of the file
+ byte[] newFileBytes = new byte[540];
+ Array.Copy(readBytes, newFileBytes, readBytes.Length);
+ readBytes = newFileBytes;
+ }
+
+ AmiiboDecryptor amiiboDecryptor = new AmiiboDecryptor(keyRetailBinPath);
AmiiboDump amiiboDump = amiiboDecryptor.DecryptAmiiboDump(readBytes);
byte[] oldData = amiiboDump.GetData();
@@ -231,7 +242,15 @@ namespace Ryujinx.HLE.HOS.Services.Nfc.AmiiboDecryption
return false;
}
- AmiiboDecrypter amiiboDecryptor = new AmiiboDecrypter(keyRetailBinPath);
+ if (readBytes.Length == 532)
+ {
+ // add 8 bytes to the end of the file
+ byte[] newFileBytes = new byte[540];
+ Array.Copy(readBytes, newFileBytes, readBytes.Length);
+ readBytes = newFileBytes;
+ }
+
+ AmiiboDecryptor amiiboDecryptor = new AmiiboDecryptor(keyRetailBinPath);
AmiiboDump amiiboDump = amiiboDecryptor.DecryptAmiiboDump(readBytes);
amiiboDump.AmiiboNickname = newNickName;
byte[] oldData = amiiboDump.GetData();
@@ -314,10 +333,9 @@ namespace Ryujinx.HLE.HOS.Services.Nfc.AmiiboDecryption
return Path.Combine(AppDataManager.KeysDirPath, "key_retail.bin");
}
- public static bool HasKeyRetailBinPath()
- {
- return File.Exists(GetKeyRetailBinPath());
- }
+ public static bool HasAmiiboKeyFile => File.Exists(GetKeyRetailBinPath());
+
+
public static DateTime DateTimeFromTag(ushort value)
{
try
diff --git a/src/Ryujinx.HLE/HOS/Services/Nfc/AmiiboDecryption/AmiiboDecrypter.cs b/src/Ryujinx.HLE/HOS/Services/Nfc/AmiiboDecryption/AmiiboDecryptor.cs
similarity index 77%
rename from src/Ryujinx.HLE/HOS/Services/Nfc/AmiiboDecryption/AmiiboDecrypter.cs
rename to src/Ryujinx.HLE/HOS/Services/Nfc/AmiiboDecryption/AmiiboDecryptor.cs
index 71758c947..cc6d02ea2 100644
--- a/src/Ryujinx.HLE/HOS/Services/Nfc/AmiiboDecryption/AmiiboDecrypter.cs
+++ b/src/Ryujinx.HLE/HOS/Services/Nfc/AmiiboDecryption/AmiiboDecryptor.cs
@@ -2,12 +2,12 @@ using System.IO;
namespace Ryujinx.HLE.HOS.Services.Nfc.AmiiboDecryption
{
- public class AmiiboDecrypter
+ public class AmiiboDecryptor
{
public AmiiboMasterKey DataKey { get; private set; }
public AmiiboMasterKey TagKey { get; private set; }
- public AmiiboDecrypter(string keyRetailBinPath)
+ public AmiiboDecryptor(string keyRetailBinPath)
{
var combinedKeys = File.ReadAllBytes(keyRetailBinPath);
var keys = AmiiboMasterKey.FromCombinedBin(combinedKeys);
@@ -18,7 +18,7 @@ namespace Ryujinx.HLE.HOS.Services.Nfc.AmiiboDecryption
public AmiiboDump DecryptAmiiboDump(byte[] encryptedDumpData)
{
// Initialize AmiiboDump with encrypted data
- AmiiboDump amiiboDump = new AmiiboDump(encryptedDumpData, DataKey, TagKey, isLocked: true);
+ AmiiboDump amiiboDump = new(encryptedDumpData, DataKey, TagKey, isLocked: true);
// Unlock (decrypt) the dump
amiiboDump.Unlock();
@@ -32,7 +32,7 @@ namespace Ryujinx.HLE.HOS.Services.Nfc.AmiiboDecryption
public AmiiboDump EncryptAmiiboDump(byte[] decryptedDumpData)
{
// Initialize AmiiboDump with decrypted data
- AmiiboDump amiiboDump = new AmiiboDump(decryptedDumpData, DataKey, TagKey, isLocked: false);
+ AmiiboDump amiiboDump = new(decryptedDumpData, DataKey, TagKey, isLocked: false);
// Lock (encrypt) the dump
amiiboDump.Lock();
diff --git a/src/Ryujinx.HLE/HOS/Services/Nfc/AmiiboDecryption/AmiiboDump.cs b/src/Ryujinx.HLE/HOS/Services/Nfc/AmiiboDecryption/AmiiboDump.cs
index 7343a40ca..37d587dac 100644
--- a/src/Ryujinx.HLE/HOS/Services/Nfc/AmiiboDecryption/AmiiboDump.cs
+++ b/src/Ryujinx.HLE/HOS/Services/Nfc/AmiiboDecryption/AmiiboDump.cs
@@ -36,7 +36,7 @@ namespace Ryujinx.HLE.HOS.Services.Nfc.AmiiboDecryption
private byte[] DeriveKey(AmiiboMasterKey key, bool deriveAes, out byte[] derivedAesKey, out byte[] derivedAesIv)
{
- List seed = new List();
+ List seed = [];
// Start with the type string (14 bytes)
seed.AddRange(key.TypeString);
diff --git a/src/Ryujinx.HLE/HOS/Services/Nfc/AmiiboDecryption/AmiiboMasterKey.cs b/src/Ryujinx.HLE/HOS/Services/Nfc/AmiiboDecryption/AmiiboMasterKey.cs
index f61f8c84d..940dc4c85 100644
--- a/src/Ryujinx.HLE/HOS/Services/Nfc/AmiiboDecryption/AmiiboMasterKey.cs
+++ b/src/Ryujinx.HLE/HOS/Services/Nfc/AmiiboDecryption/AmiiboMasterKey.cs
@@ -33,10 +33,7 @@ namespace Ryujinx.HLE.HOS.Services.Nfc.AmiiboDecryption
byte[] dataBin = combinedBin.Take(80).ToArray();
byte[] tagBin = combinedBin.Skip(80).Take(80).ToArray();
- AmiiboMasterKey dataKey = new AmiiboMasterKey(dataBin);
- AmiiboMasterKey tagKey = new AmiiboMasterKey(tagBin);
-
- return (dataKey, tagKey);
+ return (new AmiiboMasterKey(dataBin), new AmiiboMasterKey(tagBin));
}
}
}
diff --git a/src/Ryujinx.HLE/HOS/Services/Nfc/Nfp/VirtualAmiibo.cs b/src/Ryujinx.HLE/HOS/Services/Nfc/Nfp/VirtualAmiibo.cs
index ee43fc307..2cb35472f 100644
--- a/src/Ryujinx.HLE/HOS/Services/Nfc/Nfp/VirtualAmiibo.cs
+++ b/src/Ryujinx.HLE/HOS/Services/Nfc/Nfp/VirtualAmiibo.cs
@@ -16,7 +16,7 @@ namespace Ryujinx.HLE.HOS.Services.Nfc.Nfp
static class VirtualAmiibo
{
public static uint OpenedApplicationAreaId;
- public static byte[] ApplicationBytes = new byte[0];
+ public static byte[] ApplicationBytes = Array.Empty();
public static string InputBin = string.Empty;
public static string NickName = string.Empty;
private static readonly AmiiboJsonSerializerContext _serializerContext = AmiiboJsonSerializerContext.Default;
@@ -137,7 +137,7 @@ namespace Ryujinx.HLE.HOS.Services.Nfc.Nfp
if (ApplicationBytes.Length > 0)
{
byte[] bytes = ApplicationBytes;
- ApplicationBytes = new byte[0];
+ ApplicationBytes = Array.Empty();
return bytes;
}
VirtualAmiiboFile virtualAmiiboFile = LoadAmiiboFile(amiiboId);
diff --git a/src/Ryujinx.HLE/HOS/Services/Sm/IUserInterface.cs b/src/Ryujinx.HLE/HOS/Services/Sm/IUserInterface.cs
index 7a90c664e..271b8fc84 100644
--- a/src/Ryujinx.HLE/HOS/Services/Sm/IUserInterface.cs
+++ b/src/Ryujinx.HLE/HOS/Services/Sm/IUserInterface.cs
@@ -94,7 +94,7 @@ namespace Ryujinx.HLE.HOS.Services.Sm
{
if (_services.TryGetValue(name, out Type type))
{
- ServiceAttribute serviceAttribute = (ServiceAttribute)type.GetCustomAttributes(typeof(ServiceAttribute)).First(service => ((ServiceAttribute)service).Name == name);
+ ServiceAttribute serviceAttribute = type.GetCustomAttributes().First(service => service.Name == name);
IpcService service = GetServiceInstance(type, context, serviceAttribute.Parameter);
diff --git a/src/Ryujinx.HLE/HOS/Services/Sockets/Bsd/Impl/EventFileDescriptor.cs b/src/Ryujinx.HLE/HOS/Services/Sockets/Bsd/Impl/EventFileDescriptor.cs
index 5b9e6811d..05fc91d32 100644
--- a/src/Ryujinx.HLE/HOS/Services/Sockets/Bsd/Impl/EventFileDescriptor.cs
+++ b/src/Ryujinx.HLE/HOS/Services/Sockets/Bsd/Impl/EventFileDescriptor.cs
@@ -10,6 +10,7 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd.Impl
private ulong _value;
private readonly EventFdFlags _flags;
+ // type is not Lock due to Monitor class usage
private readonly object _lock = new();
public bool Blocking { get => !_flags.HasFlag(EventFdFlags.NonBlocking); set => throw new NotSupportedException(); }
diff --git a/src/Ryujinx.Horizon.Kernel.Generators/SyscallGenerator.cs b/src/Ryujinx.Horizon.Kernel.Generators/SyscallGenerator.cs
index 7419a839a..06b98e09d 100644
--- a/src/Ryujinx.Horizon.Kernel.Generators/SyscallGenerator.cs
+++ b/src/Ryujinx.Horizon.Kernel.Generators/SyscallGenerator.cs
@@ -34,14 +34,14 @@ namespace Ryujinx.Horizon.Kernel.Generators
private const string TypeResult = NamespaceHorizonCommon + "." + TypeResultName;
private const string TypeExecutionContext = "IExecutionContext";
- private static readonly string[] _expectedResults = new string[]
- {
+ private static readonly string[] _expectedResults =
+ [
$"{TypeResultName}.Success",
$"{TypeKernelResultName}.TimedOut",
$"{TypeKernelResultName}.Cancelled",
$"{TypeKernelResultName}.PortRemoteClosed",
$"{TypeKernelResultName}.InvalidState",
- };
+ ];
private readonly struct OutParameter
{
diff --git a/src/Ryujinx.Memory/AddressSpaceManager.cs b/src/Ryujinx.Memory/AddressSpaceManager.cs
index 807c5c0f4..7bd572d7a 100644
--- a/src/Ryujinx.Memory/AddressSpaceManager.cs
+++ b/src/Ryujinx.Memory/AddressSpaceManager.cs
@@ -106,10 +106,13 @@ namespace Ryujinx.Memory
{
if (size == 0)
{
- return Enumerable.Empty();
+ yield break;
}
- return GetHostRegionsImpl(va, size);
+ foreach (var hostRegion in GetHostRegionsImpl(va, size))
+ {
+ yield return hostRegion;
+ }
}
///
@@ -117,51 +120,36 @@ namespace Ryujinx.Memory
{
if (size == 0)
{
- return Enumerable.Empty();
+ yield break;
}
var hostRegions = GetHostRegionsImpl(va, size);
if (hostRegions == null)
{
- return null;
+ yield break;
}
- var regions = new MemoryRange[hostRegions.Count];
-
ulong backingStart = (ulong)_backingMemory.Pointer;
ulong backingEnd = backingStart + _backingMemory.Size;
- int count = 0;
-
- for (int i = 0; i < regions.Length; i++)
+ foreach (var hostRegion in hostRegions)
{
- var hostRegion = hostRegions[i];
-
if (hostRegion.Address >= backingStart && hostRegion.Address < backingEnd)
{
- regions[count++] = new MemoryRange(hostRegion.Address - backingStart, hostRegion.Size);
+ yield return new MemoryRange(hostRegion.Address - backingStart, hostRegion.Size);
}
}
-
- if (count != regions.Length)
- {
- return new ArraySegment(regions, 0, count);
- }
-
- return regions;
}
- private List GetHostRegionsImpl(ulong va, ulong size)
+ private IEnumerable GetHostRegionsImpl(ulong va, ulong size)
{
if (!ValidateAddress(va) || !ValidateAddressAndSize(va, size))
{
- return null;
+ yield break;
}
int pages = GetPagesCount(va, size, out va);
- var regions = new List();
-
nuint regionStart = GetHostAddress(va);
ulong regionSize = PageSize;
@@ -169,14 +157,14 @@ namespace Ryujinx.Memory
{
if (!ValidateAddress(va + PageSize))
{
- return null;
+ yield break;
}
nuint newHostAddress = GetHostAddress(va + PageSize);
if (GetHostAddress(va) + PageSize != newHostAddress)
{
- regions.Add(new HostMemoryRange(regionStart, regionSize));
+ yield return new HostMemoryRange(regionStart, regionSize);
regionStart = newHostAddress;
regionSize = 0;
}
@@ -185,9 +173,7 @@ namespace Ryujinx.Memory
regionSize += PageSize;
}
- regions.Add(new HostMemoryRange(regionStart, regionSize));
-
- return regions;
+ yield return new HostMemoryRange(regionStart, regionSize);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
diff --git a/src/Ryujinx.UI.Common/App/ApplicationData.cs b/src/Ryujinx.UI.Common/App/ApplicationData.cs
index 151220f39..657b9a022 100644
--- a/src/Ryujinx.UI.Common/App/ApplicationData.cs
+++ b/src/Ryujinx.UI.Common/App/ApplicationData.cs
@@ -38,7 +38,7 @@ namespace Ryujinx.UI.App.Common
public string TimePlayedString => ValueFormatUtils.FormatTimeSpan(TimePlayed);
- public string LastPlayedString => ValueFormatUtils.FormatDateTime(LastPlayed) ?? LocalizedNever();
+ public string LastPlayedString => ValueFormatUtils.FormatDateTime(LastPlayed)?.Replace(" ", "\n") ?? LocalizedNever();
public string FileSizeString => ValueFormatUtils.FormatFileSize(FileSize);
diff --git a/src/Ryujinx.UI.Common/Helper/FileAssociationHelper.cs b/src/Ryujinx.UI.Common/Helper/FileAssociationHelper.cs
index 9333a1b76..44860d080 100644
--- a/src/Ryujinx.UI.Common/Helper/FileAssociationHelper.cs
+++ b/src/Ryujinx.UI.Common/Helper/FileAssociationHelper.cs
@@ -23,7 +23,7 @@ namespace Ryujinx.UI.Common.Helper
[LibraryImport("shell32.dll", SetLastError = true)]
public static partial void SHChangeNotify(uint wEventId, uint uFlags, nint dwItem1, nint dwItem2);
- public static bool IsTypeAssociationSupported => (OperatingSystem.IsLinux() || OperatingSystem.IsWindows()) && !ReleaseInformation.IsFlatHubBuild;
+ public static bool IsTypeAssociationSupported => (OperatingSystem.IsLinux() || OperatingSystem.IsWindows());
public static bool AreMimeTypesRegistered
{
diff --git a/src/Ryujinx.UI.Common/Helper/OpenHelper.cs b/src/Ryujinx.UI.Common/Helper/OpenHelper.cs
index 8b0e1f1fd..bf398a355 100644
--- a/src/Ryujinx.UI.Common/Helper/OpenHelper.cs
+++ b/src/Ryujinx.UI.Common/Helper/OpenHelper.cs
@@ -1,3 +1,4 @@
+using Gommon;
using Ryujinx.Common.Logging;
using System;
using System.Diagnostics;
@@ -34,6 +35,8 @@ namespace Ryujinx.UI.Common.Helper
}
}
+ public static void OpenFolder(FilePath path) => OpenFolder(path.Path);
+
public static void LocateFile(string path)
{
if (File.Exists(path))
diff --git a/src/Ryujinx/Assets/Styles/Themes.xaml b/src/Ryujinx/Assets/Styles/Themes.xaml
index 46e298035..3a0bd4217 100644
--- a/src/Ryujinx/Assets/Styles/Themes.xaml
+++ b/src/Ryujinx/Assets/Styles/Themes.xaml
@@ -4,11 +4,10 @@
+ #008AA8
#FF00FABB
#FFF0F0F0
#FFd6d6d6
- #FFFFFFFF
- #FFFFFFFF
#FF000000
#C1C1C1
#b3ffffff
@@ -22,16 +21,19 @@
+ #3ddcff
#FF00FABB
- #FFF0F0F0
- #FFd6d6d6
- #FFFFFFFF
- #FFFFFFFF
+ #dedede
+ #c2c2c2
#FF000000
#C1C1C1
#b3ffffff
#80cccccc
#A0000000
+ #fffcd12a
+ #13c3a4
+ #FFFF4554
+ #6483F5
#FF00FABB
#FF2D2D2D
#FF505050
- #FFFFFFFF
- #FFFFFFFF
#FFFFFFFF
#3D3D3D
#0FFFFFFF
#1EFFFFFF
#A0FFFFFF
+ #fffcd12a
+ #FF2EEAC9
+ #FFFF4554
+ #6483F5
diff --git a/src/Ryujinx/Assets/locales.json b/src/Ryujinx/Assets/locales.json
index a85c8c06a..cfe2b817a 100644
--- a/src/Ryujinx/Assets/locales.json
+++ b/src/Ryujinx/Assets/locales.json
@@ -705,7 +705,7 @@
"he_IL": "",
"it_IT": "",
"ja_JP": "",
- "ko_KR": "",
+ "ko_KR": "Amiibo 스캔(빈에서)",
"no_NO": "",
"pl_PL": "",
"pt_BR": "",
@@ -1077,6 +1077,54 @@
"zh_TW": ""
}
},
+ {
+ "ID": "MenuBarViewWindow1440",
+ "Translations": {
+ "ar_SA": "",
+ "de_DE": "",
+ "el_GR": "",
+ "en_US": "1440p",
+ "es_ES": "",
+ "fr_FR": "",
+ "he_IL": "",
+ "it_IT": "",
+ "ja_JP": "",
+ "ko_KR": "",
+ "no_NO": "",
+ "pl_PL": "",
+ "pt_BR": "",
+ "ru_RU": "",
+ "th_TH": "",
+ "tr_TR": "",
+ "uk_UA": "",
+ "zh_CN": "",
+ "zh_TW": ""
+ }
+ },
+ {
+ "ID": "MenuBarViewWindow2160",
+ "Translations": {
+ "ar_SA": "",
+ "de_DE": "",
+ "el_GR": "",
+ "en_US": "2160p",
+ "es_ES": "",
+ "fr_FR": "",
+ "he_IL": "",
+ "it_IT": "",
+ "ja_JP": "",
+ "ko_KR": "",
+ "no_NO": "",
+ "pl_PL": "",
+ "pt_BR": "",
+ "ru_RU": "",
+ "th_TH": "",
+ "tr_TR": "",
+ "uk_UA": "",
+ "zh_CN": "",
+ "zh_TW": ""
+ }
+ },
{
"ID": "MenuBarHelp",
"Translations": {
@@ -1125,6 +1173,30 @@
"zh_TW": "檢查更新"
}
},
+ {
+ "ID": "MenuBarHelpFaqAndGuides",
+ "Translations": {
+ "ar_SA": "",
+ "de_DE": "",
+ "el_GR": "",
+ "en_US": "FAQ & Guides",
+ "es_ES": "",
+ "fr_FR": "",
+ "he_IL": "",
+ "it_IT": "",
+ "ja_JP": "",
+ "ko_KR": "",
+ "no_NO": "",
+ "pl_PL": "",
+ "pt_BR": "",
+ "ru_RU": "",
+ "th_TH": "",
+ "tr_TR": "",
+ "uk_UA": "",
+ "zh_CN": "",
+ "zh_TW": ""
+ }
+ },
{
"ID": "MenuBarHelpFaq",
"Translations": {
@@ -1137,7 +1209,7 @@
"he_IL": "",
"it_IT": "",
"ja_JP": "",
- "ko_KR": "",
+ "ko_KR": "자주 묻는 질문(FAQ) 및 문제해결 페이지",
"no_NO": "",
"pl_PL": "",
"pt_BR": "",
@@ -1161,7 +1233,7 @@
"he_IL": "",
"it_IT": "",
"ja_JP": "",
- "ko_KR": "",
+ "ko_KR": "공식 Ryujinx 위키에서 자주 묻는 질문(FAQ) 및 문제 해결 페이지 열기",
"no_NO": "",
"pl_PL": "",
"pt_BR": "",
@@ -1185,7 +1257,7 @@
"he_IL": "",
"it_IT": "",
"ja_JP": "",
- "ko_KR": "",
+ "ko_KR": "설치 및 구성 안내",
"no_NO": "",
"pl_PL": "",
"pt_BR": "",
@@ -1209,7 +1281,7 @@
"he_IL": "",
"it_IT": "",
"ja_JP": "",
- "ko_KR": "",
+ "ko_KR": "공식 Ryujinx 위키에서 설정 및 구성 안내 열기",
"no_NO": "",
"pl_PL": "",
"pt_BR": "",
@@ -1233,7 +1305,7 @@
"he_IL": "",
"it_IT": "",
"ja_JP": "",
- "ko_KR": "",
+ "ko_KR": "멀티플레이어(LDN/LAN) 안내",
"no_NO": "",
"pl_PL": "",
"pt_BR": "",
@@ -1257,7 +1329,7 @@
"he_IL": "",
"it_IT": "",
"ja_JP": "",
- "ko_KR": "",
+ "ko_KR": "공식 Ryujinx 위키에서 멀티플레이어 안내 열기",
"no_NO": "",
"pl_PL": "",
"pt_BR": "",
@@ -2424,25 +2496,25 @@
{
"ID": "StatusBarSystemVersion",
"Translations": {
- "ar_SA": "إصدار النظام: {0}",
- "de_DE": "Systemversion: {0}",
- "el_GR": "Έκδοση Συστήματος: {0}",
- "en_US": "System Version: {0}",
- "es_ES": "Versión del sistema: {0}",
+ "ar_SA": "",
+ "de_DE": "",
+ "el_GR": "",
+ "en_US": "Firmware Version: {0}",
+ "es_ES": "",
"fr_FR": "Version du Firmware: {0}",
- "he_IL": "גרסת מערכת: {0}",
- "it_IT": "Versione di sistema: {0}",
- "ja_JP": "システムバージョン: {0}",
- "ko_KR": "시스템 버전 : {0}",
- "no_NO": "System versjon: {0}",
- "pl_PL": "Wersja systemu: {0}",
+ "he_IL": "",
+ "it_IT": "",
+ "ja_JP": "",
+ "ko_KR": "",
+ "no_NO": "",
+ "pl_PL": "",
"pt_BR": "Versão do firmware: {0}",
"ru_RU": "Версия прошивки: {0}",
- "th_TH": "เวอร์ชั่นของระบบ: {0}",
- "tr_TR": "Sistem Sürümü: {0}",
- "uk_UA": "Версія системи: {0}",
+ "th_TH": "",
+ "tr_TR": "",
+ "uk_UA": "",
"zh_CN": "系统固件版本:{0}",
- "zh_TW": "系統版本: {0}"
+ "zh_TW": ""
}
},
{
@@ -3765,6 +3837,30 @@
"zh_TW": "系統時鐘:"
}
},
+ {
+ "ID": "SettingsTabSystemSystemTimeMatch",
+ "Translations": {
+ "ar_SA": "",
+ "de_DE": "",
+ "el_GR": "",
+ "en_US": "Resync to PC Date & Time",
+ "es_ES": "",
+ "fr_FR": "",
+ "he_IL": "",
+ "it_IT": "",
+ "ja_JP": "",
+ "ko_KR": "",
+ "no_NO": "",
+ "pl_PL": "",
+ "pt_BR": "",
+ "ru_RU": "",
+ "th_TH": "",
+ "tr_TR": "",
+ "uk_UA": "",
+ "zh_CN": "",
+ "zh_TW": ""
+ }
+ },
{
"ID": "SettingsTabSystemEnablePptc",
"Translations": {
@@ -8049,7 +8145,7 @@
"he_IL": "",
"it_IT": "",
"ja_JP": "",
- "ko_KR": "지우기",
+ "ko_KR": "",
"no_NO": "Tøm",
"pl_PL": "",
"pt_BR": "",
@@ -11841,7 +11937,7 @@
"he_IL": "",
"it_IT": "",
"ja_JP": "",
- "ko_KR": "",
+ "ko_KR": "{0} : {1}",
"no_NO": "",
"pl_PL": "",
"pt_BR": "",
@@ -14541,6 +14637,30 @@
"zh_TW": "變更系統時鐘"
}
},
+ {
+ "ID": "MatchTimeTooltip",
+ "Translations": {
+ "ar_SA": "",
+ "de_DE": "",
+ "el_GR": "",
+ "en_US": "Resync System Time to match your PC's current date & time.\n\nThis is not an active setting, it can still fall out of sync; in which case just click this button again.",
+ "es_ES": "",
+ "fr_FR": "",
+ "he_IL": "",
+ "it_IT": "",
+ "ja_JP": "",
+ "ko_KR": "",
+ "no_NO": "",
+ "pl_PL": "",
+ "pt_BR": "",
+ "ru_RU": "",
+ "th_TH": "",
+ "tr_TR": "",
+ "uk_UA": "",
+ "zh_CN": "",
+ "zh_TW": ""
+ }
+ },
{
"ID": "VSyncToggleTooltip",
"Translations": {
@@ -16125,30 +16245,6 @@
"zh_TW": "CPU 模式"
}
},
- {
- "ID": "DialogUpdaterFlatpakNotSupportedMessage",
- "Translations": {
- "ar_SA": "الرجاء تحديث ريوجينكس عبر فلات هاب.",
- "de_DE": "Bitte aktualisiere Ryujinx über FlatHub",
- "el_GR": "Παρακαλούμε ενημερώστε το Ryujinx μέσω FlatHub.",
- "en_US": "Please update Ryujinx via FlatHub.",
- "es_ES": "Por favor, actualiza Ryujinx a través de FlatHub.",
- "fr_FR": "Merci de mettre à jour Ryujinx via FlatHub.",
- "he_IL": "בבקשה עדכן את ריוג'ינקס דרך פלאטהב.",
- "it_IT": "Aggiorna Ryujinx tramite FlatHub.",
- "ja_JP": "FlatHub を使用して Ryujinx をアップデートしてください.",
- "ko_KR": "FlatHub를 통해 Ryujinx를 업데이트하세요.",
- "no_NO": "Vennligst oppdater Ryujinx via FlatHub.",
- "pl_PL": "Zaktualizuj Ryujinx przez FlatHub.",
- "pt_BR": "Por favor, atualize o Ryujinx pelo FlatHub.",
- "ru_RU": "Пожалуйста, обновите Ryujinx через FlatHub.",
- "th_TH": "โปรดอัปเดต Ryujinx ผ่านช่องทาง FlatHub",
- "tr_TR": "Lütfen Ryujinx'i FlatHub aracılığıyla güncelleyin.",
- "uk_UA": "",
- "zh_CN": "请通过 FlatHub 更新 Ryujinx 模拟器。",
- "zh_TW": "請透過 Flathub 更新 Ryujinx。"
- }
- },
{
"ID": "UpdaterDisabledWarningTitle",
"Translations": {
@@ -18753,7 +18849,7 @@
"he_IL": "",
"it_IT": "",
"ja_JP": "",
- "ko_KR": "",
+ "ko_KR": "{0:n0}MB",
"no_NO": "",
"pl_PL": "",
"pt_BR": "",
@@ -19041,7 +19137,7 @@
"he_IL": "{0} הרחבות משחק",
"it_IT": "",
"ja_JP": "",
- "ko_KR": "",
+ "ko_KR": "{0} DLC 사용 가능",
"no_NO": "{0} Nedlastbare innhold(er)",
"pl_PL": "",
"pt_BR": "",
@@ -21177,7 +21273,7 @@
"he_IL": "",
"it_IT": "",
"ja_JP": "",
- "ko_KR": "",
+ "ko_KR": "수직 동기화 :",
"no_NO": "",
"pl_PL": "",
"pt_BR": "",
@@ -21201,7 +21297,7 @@
"he_IL": "",
"it_IT": "",
"ja_JP": "",
- "ko_KR": "",
+ "ko_KR": "사용자 정의 주사율 활성화(실험적)",
"no_NO": "",
"pl_PL": "",
"pt_BR": "",
@@ -21225,7 +21321,7 @@
"he_IL": "",
"it_IT": "",
"ja_JP": "",
- "ko_KR": "",
+ "ko_KR": "스위치",
"no_NO": "",
"pl_PL": "",
"pt_BR": "",
@@ -21249,7 +21345,7 @@
"he_IL": "",
"it_IT": "",
"ja_JP": "",
- "ko_KR": "",
+ "ko_KR": "무제한",
"no_NO": "",
"pl_PL": "",
"pt_BR": "",
@@ -21273,7 +21369,7 @@
"he_IL": "",
"it_IT": "",
"ja_JP": "",
- "ko_KR": "",
+ "ko_KR": "사용자 정의 주사율",
"no_NO": "",
"pl_PL": "",
"pt_BR": "",
@@ -21297,7 +21393,7 @@
"he_IL": "",
"it_IT": "",
"ja_JP": "",
- "ko_KR": "",
+ "ko_KR": "에뮬레이트된 수직 동기화. '스위치'는 스위치의 60Hz 주사율을 에뮬레이트합니다. '무한'은 무제한 주사율입니다.",
"no_NO": "",
"pl_PL": "",
"pt_BR": "",
@@ -21321,7 +21417,7 @@
"he_IL": "",
"it_IT": "",
"ja_JP": "",
- "ko_KR": "",
+ "ko_KR": "에뮬레이트된 수직 동기화. '스위치'는 스위치의 60Hz 주사율을 에뮬레이트합니다. '무한'은 무제한 주사율입니다. '사용자 지정'은 지정된 사용자 지정 주사율을 에뮬레이트합니다.",
"no_NO": "",
"pl_PL": "",
"pt_BR": "",
@@ -21345,7 +21441,7 @@
"he_IL": "",
"it_IT": "",
"ja_JP": "",
- "ko_KR": "",
+ "ko_KR": "사용자가 에뮬레이트된 화면 주사율을 지정할 수 있습니다. 일부 타이틀에서는 게임플레이 로직 속도가 빨라지거나 느려질 수 있습니다. 다른 타이틀에서는 주사율의 배수로 FPS를 제한하거나 예측할 수 없는 동작으로 이어질 수 있습니다. 이는 실험적 기능으로 게임 플레이에 어떤 영향을 미칠지 보장할 수 없습니다. \n\n모르면 끔으로 두세요.",
"no_NO": "",
"pl_PL": "",
"pt_BR": "",
@@ -21369,7 +21465,7 @@
"he_IL": "",
"it_IT": "",
"ja_JP": "",
- "ko_KR": "",
+ "ko_KR": "사용자 정의 주사율 목표 값입니다.",
"no_NO": "",
"pl_PL": "",
"pt_BR": "",
@@ -21393,7 +21489,7 @@
"he_IL": "",
"it_IT": "",
"ja_JP": "",
- "ko_KR": "",
+ "ko_KR": "일반 스위치 주사율의 백분율로 나타낸 사용자 지정 주사율입니다.",
"no_NO": "",
"pl_PL": "",
"pt_BR": "",
@@ -21417,7 +21513,7 @@
"he_IL": "",
"it_IT": "",
"ja_JP": "",
- "ko_KR": "",
+ "ko_KR": "사용자 정의 주사율 % :",
"no_NO": "",
"pl_PL": "",
"pt_BR": "",
@@ -21441,7 +21537,7 @@
"he_IL": "",
"it_IT": "",
"ja_JP": "",
- "ko_KR": "",
+ "ko_KR": "사용자 정의 주사율 값 :",
"no_NO": "",
"pl_PL": "",
"pt_BR": "",
@@ -21465,7 +21561,7 @@
"he_IL": "",
"it_IT": "",
"ja_JP": "",
- "ko_KR": "",
+ "ko_KR": "간격",
"no_NO": "",
"pl_PL": "",
"pt_BR": "",
@@ -21489,7 +21585,7 @@
"he_IL": "",
"it_IT": "",
"ja_JP": "",
- "ko_KR": "",
+ "ko_KR": "수직 동기화 모드 전환 :",
"no_NO": "",
"pl_PL": "",
"pt_BR": "",
@@ -21513,7 +21609,7 @@
"he_IL": "",
"it_IT": "",
"ja_JP": "",
- "ko_KR": "",
+ "ko_KR": "사용자 정의 주사율 증가",
"no_NO": "",
"pl_PL": "",
"pt_BR": "",
@@ -21537,7 +21633,7 @@
"he_IL": "",
"it_IT": "",
"ja_JP": "",
- "ko_KR": "",
+ "ko_KR": "사용자 정의 주사율 감소",
"no_NO": "",
"pl_PL": "",
"pt_BR": "",
diff --git a/src/Ryujinx/Common/LocaleManager.cs b/src/Ryujinx/Common/LocaleManager.cs
index 2ea5c83ee..f29efb15a 100644
--- a/src/Ryujinx/Common/LocaleManager.cs
+++ b/src/Ryujinx/Common/LocaleManager.cs
@@ -1,3 +1,4 @@
+using Gommon;
using Ryujinx.Ava.UI.ViewModels;
using Ryujinx.Common;
using Ryujinx.Common.Logging;
@@ -7,12 +8,7 @@ using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Globalization;
-using System.IO;
-using System.Linq;
-using System.Text.Encodings.Web;
-using System.Text.Json;
using System.Text.Json.Serialization;
-using System.Text.Unicode;
namespace Ryujinx.Ava.Common.Locale
{
@@ -147,39 +143,33 @@ namespace Ryujinx.Ava.Common.Locale
LocaleChanged?.Invoke();
}
+ #nullable enable
+
+ private static LocalesJson? _localeData;
+
+ #nullable disable
+
private static Dictionary LoadJsonLanguage(string languageCode)
{
var localeStrings = new Dictionary();
- string fileData = EmbeddedResources.ReadAllText($"Ryujinx/Assets/locales.json");
- if (fileData == null)
+ _localeData ??= EmbeddedResources.ReadAllText("Ryujinx/Assets/locales.json")
+ .Into(it => JsonHelper.Deserialize(it, LocalesJsonContext.Default.LocalesJson));
+
+ foreach (LocalesEntry locale in _localeData.Value.Locales)
{
- // We were unable to find file for that language code.
- return null;
- }
-
- LocalesJson json = JsonHelper.Deserialize(fileData, LocalesJsonContext.Default.LocalesJson);
-
- foreach (LocalesEntry locale in json.Locales)
- {
- if (locale.Translations.Count != json.Languages.Count)
+ if (locale.Translations.Count != _localeData.Value.Languages.Count)
{
- Logger.Error?.Print(LogClass.UI, $"Locale key {{{locale.ID}}} is missing languages!");
- throw new Exception("Missing locale data!");
+ throw new Exception($"Locale key {{{locale.ID}}} is missing languages! Has {locale.Translations.Count} translations, expected {_localeData.Value.Languages.Count}!");
}
- if (Enum.TryParse(locale.ID, out var localeKey))
- {
- if (locale.Translations.TryGetValue(languageCode, out string val) && val != "")
- {
- localeStrings[localeKey] = val;
- }
- else
- {
- locale.Translations.TryGetValue("en_US", out val);
- localeStrings[localeKey] = val;
- }
- }
+ if (!Enum.TryParse(locale.ID, out var localeKey))
+ continue;
+
+ localeStrings[localeKey] =
+ locale.Translations.TryGetValue(languageCode, out string val) && val != string.Empty
+ ? val
+ : locale.Translations[DefaultLanguageCode];
}
return localeStrings;
@@ -200,5 +190,5 @@ namespace Ryujinx.Ava.Common.Locale
[JsonSourceGenerationOptions(WriteIndented = true)]
[JsonSerializable(typeof(LocalesJson))]
- internal partial class LocalesJsonContext : JsonSerializerContext { }
+ internal partial class LocalesJsonContext : JsonSerializerContext;
}
diff --git a/src/Ryujinx/UI/Controls/ApplicationContextMenu.axaml b/src/Ryujinx/UI/Controls/ApplicationContextMenu.axaml
index 951f7f616..7708936ca 100644
--- a/src/Ryujinx/UI/Controls/ApplicationContextMenu.axaml
+++ b/src/Ryujinx/UI/Controls/ApplicationContextMenu.axaml
@@ -17,7 +17,6 @@
diff --git a/src/Ryujinx/UI/ViewModels/Input/InputViewModel.cs b/src/Ryujinx/UI/ViewModels/Input/InputViewModel.cs
index f11d6e404..493e6659d 100644
--- a/src/Ryujinx/UI/ViewModels/Input/InputViewModel.cs
+++ b/src/Ryujinx/UI/ViewModels/Input/InputViewModel.cs
@@ -97,7 +97,7 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
{
if (IsModified)
{
-
+
_playerIdChoose = value;
return;
}
@@ -105,7 +105,7 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
IsModified = false;
_playerId = value;
- if (!Enum.IsDefined(typeof(PlayerIndex), _playerId))
+ if (!Enum.IsDefined(_playerId))
{
_playerId = PlayerIndex.Player1;
diff --git a/src/Ryujinx/UI/ViewModels/MainWindowViewModel.cs b/src/Ryujinx/UI/ViewModels/MainWindowViewModel.cs
index 283f9b9da..ae373c267 100644
--- a/src/Ryujinx/UI/ViewModels/MainWindowViewModel.cs
+++ b/src/Ryujinx/UI/ViewModels/MainWindowViewModel.cs
@@ -127,6 +127,9 @@ namespace Ryujinx.Ava.UI.ViewModels
public IEnumerable LastLdnGameData;
+ // The UI specifically uses a thicker bordered variant of the icon to avoid crunching out the border at lower resolutions.
+ // For an example of this, download canary 1.2.95, then open the settings menu, and look at the icon in the top-left.
+ // The border gets reduced to colored pixels in the 4 corners.
public static readonly Bitmap IconBitmap =
new(Assembly.GetAssembly(typeof(ConfigurationState))!.GetManifestResourceStream("Ryujinx.UI.Common.Resources.Logo_Thiccjinx.png")!);
@@ -330,6 +333,9 @@ namespace Ryujinx.Ava.UI.ViewModels
OnPropertyChanged();
}
}
+
+ public bool CanScanAmiiboBinaries => AmiiboBinReader.HasAmiiboKeyFile;
+
public bool ShowLoadProgress
{
get => _showLoadProgress;
@@ -418,8 +424,6 @@ namespace Ryujinx.Ava.UI.ViewModels
public bool OpenBcatSaveDirectoryEnabled => !SelectedApplication.ControlHolder.ByteSpan.IsZeros() && SelectedApplication.ControlHolder.Value.BcatDeliveryCacheStorageSize > 0;
- public bool CreateShortcutEnabled => !ReleaseInformation.IsFlatHubBuild;
-
public string LoadHeading
{
get => _loadHeading;
@@ -2009,7 +2013,7 @@ namespace Ryujinx.Ava.UI.ViewModels
}
else
{
- LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.StatusBarSystemVersion, "0.0");
+ LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.StatusBarSystemVersion, "NaN");
}
IsAppletMenuActive = hasApplet;
diff --git a/src/Ryujinx/UI/ViewModels/SettingsViewModel.cs b/src/Ryujinx/UI/ViewModels/SettingsViewModel.cs
index a5abeb36b..0824e3f86 100644
--- a/src/Ryujinx/UI/ViewModels/SettingsViewModel.cs
+++ b/src/Ryujinx/UI/ViewModels/SettingsViewModel.cs
@@ -330,6 +330,7 @@ namespace Ryujinx.Ava.UI.ViewModels
}
public DateTimeOffset CurrentDate { get; set; }
+
public TimeSpan CurrentTime { get; set; }
internal AvaloniaList TimeZones { get; set; }
@@ -453,6 +454,18 @@ namespace Ryujinx.Ava.UI.ViewModels
Dispatcher.UIThread.Post(() => OnPropertyChanged(nameof(PreferredGpuIndex)));
}
+ public void MatchSystemTime()
+ {
+ var dto = DateTimeOffset.Now;
+
+ CurrentDate = new DateTimeOffset(dto.Year, dto.Month, dto.Day, 0, 0, 0, dto.Offset);
+
+ CurrentTime = dto.TimeOfDay;
+
+ OnPropertyChanged(nameof(CurrentDate));
+ OnPropertyChanged(nameof(CurrentTime));
+ }
+
public async Task LoadTimeZones()
{
_timeZoneContentManager = new TimeZoneContentManager();
diff --git a/src/Ryujinx/UI/Views/Main/MainMenuBarView.axaml b/src/Ryujinx/UI/Views/Main/MainMenuBarView.axaml
index d9690e8ce..7d8135dcf 100644
--- a/src/Ryujinx/UI/Views/Main/MainMenuBarView.axaml
+++ b/src/Ryujinx/UI/Views/Main/MainMenuBarView.axaml
@@ -247,6 +247,7 @@
Click="OpenBinFile"
Header="{ext:Locale MenuBarActionsScanAmiiboBin}"
Icon="{ext:Icon mdi-cube-scan}"
+ IsVisible="{Binding CanScanAmiiboBinaries}"
IsEnabled="{Binding IsAmiiboBinRequested}" />
+
-
-
-
-
-
+
+
+
+
+
diff --git a/src/Ryujinx/UI/Views/Main/MainMenuBarView.axaml.cs b/src/Ryujinx/UI/Views/Main/MainMenuBarView.axaml.cs
index 79600a3fb..fa900be81 100644
--- a/src/Ryujinx/UI/Views/Main/MainMenuBarView.axaml.cs
+++ b/src/Ryujinx/UI/Views/Main/MainMenuBarView.axaml.cs
@@ -178,7 +178,7 @@ namespace Ryujinx.Ava.UI.Views.Main
private void ScanBinAmiiboMenuItem_AttachedToVisualTree(object sender, VisualTreeAttachmentEventArgs e)
{
if (sender is MenuItem)
- ViewModel.IsAmiiboBinRequested = ViewModel.IsAmiiboRequested && AmiiboBinReader.HasKeyRetailBinPath();
+ ViewModel.IsAmiiboBinRequested = ViewModel.IsAmiiboRequested && AmiiboBinReader.HasAmiiboKeyFile;
}
private async void InstallFileTypes_Click(object sender, RoutedEventArgs e)
diff --git a/src/Ryujinx/UI/Views/Main/MainStatusBarView.axaml.cs b/src/Ryujinx/UI/Views/Main/MainStatusBarView.axaml.cs
index dd4ed8297..1b017dbeb 100644
--- a/src/Ryujinx/UI/Views/Main/MainStatusBarView.axaml.cs
+++ b/src/Ryujinx/UI/Views/Main/MainStatusBarView.axaml.cs
@@ -52,7 +52,7 @@ namespace Ryujinx.Ava.UI.Views.Main
private void AspectRatioStatus_OnClick(object sender, RoutedEventArgs e)
{
AspectRatio aspectRatio = ConfigurationState.Instance.Graphics.AspectRatio.Value;
- ConfigurationState.Instance.Graphics.AspectRatio.Value = (int)aspectRatio + 1 > Enum.GetNames(typeof(AspectRatio)).Length - 1 ? AspectRatio.Fixed4x3 : aspectRatio + 1;
+ ConfigurationState.Instance.Graphics.AspectRatio.Value = (int)aspectRatio + 1 > Enum.GetNames().Length - 1 ? AspectRatio.Fixed4x3 : aspectRatio + 1;
}
private void Refresh_OnClick(object sender, RoutedEventArgs e) => Window.LoadApplications();
diff --git a/src/Ryujinx/UI/Views/Settings/SettingsSystemView.axaml b/src/Ryujinx/UI/Views/Settings/SettingsSystemView.axaml
index e04e541c3..9295413ba 100644
--- a/src/Ryujinx/UI/Views/Settings/SettingsSystemView.axaml
+++ b/src/Ryujinx/UI/Views/Settings/SettingsSystemView.axaml
@@ -181,8 +181,17 @@
SelectedTime="{Binding CurrentTime}"
Width="350"
ToolTip.Tip="{ext:Locale TimeTooltip}" />
+
-
+
ViewModel.MatchSystemTime();
}
}
diff --git a/src/Ryujinx/Updater.cs b/src/Ryujinx/Updater.cs
index e240ad141..21d991d97 100644
--- a/src/Ryujinx/Updater.cs
+++ b/src/Ryujinx/Updater.cs
@@ -686,22 +686,11 @@ namespace Ryujinx.Ava
#else
if (showWarnings)
{
- if (ReleaseInformation.IsFlatHubBuild)
- {
- Dispatcher.UIThread.InvokeAsync(() =>
- ContentDialogHelper.CreateWarningDialog(
- LocaleManager.Instance[LocaleKeys.UpdaterDisabledWarningTitle],
- LocaleManager.Instance[LocaleKeys.DialogUpdaterFlatpakNotSupportedMessage])
+ Dispatcher.UIThread.InvokeAsync(() =>
+ ContentDialogHelper.CreateWarningDialog(
+ LocaleManager.Instance[LocaleKeys.UpdaterDisabledWarningTitle],
+ LocaleManager.Instance[LocaleKeys.DialogUpdaterDirtyBuildSubMessage])
);
- }
- else
- {
- Dispatcher.UIThread.InvokeAsync(() =>
- ContentDialogHelper.CreateWarningDialog(
- LocaleManager.Instance[LocaleKeys.UpdaterDisabledWarningTitle],
- LocaleManager.Instance[LocaleKeys.DialogUpdaterDirtyBuildSubMessage])
- );
- }
}
return false;