Merge branch 'GreemDev:master' into frenchlocalebut2
This commit is contained in:
commit
66c582f6cd
28
.github/workflows/canary.yml
vendored
28
.github/workflows/canary.yml
vendored
@ -61,9 +61,9 @@ jobs:
|
|||||||
|
|
||||||
| Platform | Artifact |
|
| 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) |
|
| 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 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) |
|
| 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) |
|
| 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 }}
|
**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 |
|
| 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 |
|
| 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 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 |
|
| 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 |
|
| 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 }}"
|
"**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
|
omitBodyDuringUpdate: true
|
||||||
@ -272,19 +272,7 @@ jobs:
|
|||||||
name: "Canary ${{ steps.version_info.outputs.build_version }}"
|
name: "Canary ${{ steps.version_info.outputs.build_version }}"
|
||||||
artifacts: "publish_ava/*.tar.gz, publish_headless/*.tar.gz"
|
artifacts: "publish_ava/*.tar.gz, publish_headless/*.tar.gz"
|
||||||
tag: ${{ steps.version_info.outputs.build_version }}
|
tag: ${{ steps.version_info.outputs.build_version }}
|
||||||
body: |
|
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 }}"
|
|
||||||
omitBodyDuringUpdate: true
|
omitBodyDuringUpdate: true
|
||||||
allowUpdates: true
|
allowUpdates: true
|
||||||
replacesArtifacts: true
|
replacesArtifacts: true
|
||||||
|
25
.github/workflows/release.yml
vendored
25
.github/workflows/release.yml
vendored
@ -57,9 +57,9 @@ jobs:
|
|||||||
# Regular builds:
|
# Regular builds:
|
||||||
| Platform | Artifact |
|
| 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) |
|
| 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 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) |
|
| 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) |
|
| 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 }}
|
**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:
|
# Regular builds:
|
||||||
| Platform | Artifact |
|
| 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 |
|
| 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 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 |
|
| 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 |
|
| 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 }}"
|
"**Full Changelog**: https://github.com/${{ github.repository }}/compare/${{ steps.version_info.outputs.prev_build_version }}...${{ steps.version_info.outputs.build_version }}"
|
||||||
omitBodyDuringUpdate: true
|
omitBodyDuringUpdate: true
|
||||||
@ -261,16 +261,7 @@ jobs:
|
|||||||
name: ${{ steps.version_info.outputs.build_version }}
|
name: ${{ steps.version_info.outputs.build_version }}
|
||||||
artifacts: "publish/*.tar.gz, publish_headless/*.tar.gz"
|
artifacts: "publish/*.tar.gz, publish_headless/*.tar.gz"
|
||||||
tag: ${{ steps.version_info.outputs.build_version }}
|
tag: ${{ steps.version_info.outputs.build_version }}
|
||||||
body: |
|
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 }}"
|
|
||||||
omitBodyDuringUpdate: true
|
omitBodyDuringUpdate: true
|
||||||
allowUpdates: true
|
allowUpdates: true
|
||||||
replacesArtifacts: true
|
replacesArtifacts: true
|
||||||
|
File diff suppressed because one or more lines are too long
Before Width: | Height: | Size: 48 KiB |
@ -14,20 +14,20 @@ namespace Ryujinx.BuildValidationTasks
|
|||||||
{
|
{
|
||||||
string path = System.Reflection.Assembly.GetExecutingAssembly().Location;
|
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
|
//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
|
else
|
||||||
{
|
{
|
||||||
path = path.Split(new string[] { "src" }, StringSplitOptions.None)[0];
|
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;
|
path = new FileInfo(path).Directory!.GetDirectories("src")[0].GetDirectories("Ryujinx")[0].GetDirectories("Assets")[0].GetFiles("locales.json")[0].FullName;
|
||||||
}
|
}
|
||||||
|
|
||||||
string data;
|
string data;
|
||||||
|
|
||||||
using (StreamReader sr = new StreamReader(path))
|
using (StreamReader sr = new(path))
|
||||||
{
|
{
|
||||||
data = sr.ReadToEnd();
|
data = sr.ReadToEnd();
|
||||||
}
|
}
|
||||||
@ -38,13 +38,10 @@ namespace Ryujinx.BuildValidationTasks
|
|||||||
{
|
{
|
||||||
LocalesEntry locale = json.Locales[i];
|
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(langCode, string.Empty);
|
||||||
{
|
Log.LogMessage(MessageImportance.High, $"Added '{langCode}' to Locale '{locale.ID}'");
|
||||||
locale.Translations.Add(language, "");
|
|
||||||
Log.LogMessage(MessageImportance.High, $"Added {{{language}}} to Locale {{{locale.ID}}}");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
locale.Translations = locale.Translations.OrderBy(pair => pair.Key).ToDictionary(pair => pair.Key, pair => pair.Value);
|
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);
|
string jsonString = JsonConvert.SerializeObject(json, Formatting.Indented);
|
||||||
|
|
||||||
using (StreamWriter sw = new StreamWriter(path))
|
using (StreamWriter sw = new(path))
|
||||||
{
|
{
|
||||||
sw.Write(jsonString);
|
sw.Write(jsonString);
|
||||||
}
|
}
|
||||||
|
@ -6,7 +6,6 @@ namespace Ryujinx.Common
|
|||||||
// DO NOT EDIT, filled by CI
|
// DO NOT EDIT, filled by CI
|
||||||
public static class ReleaseInformation
|
public static class ReleaseInformation
|
||||||
{
|
{
|
||||||
private const string FlatHubChannel = "flathub";
|
|
||||||
private const string CanaryChannel = "canary";
|
private const string CanaryChannel = "canary";
|
||||||
private const string ReleaseChannel = "release";
|
private const string ReleaseChannel = "release";
|
||||||
|
|
||||||
@ -29,8 +28,6 @@ namespace Ryujinx.Common
|
|||||||
!ReleaseChannelRepo.StartsWith("%%") &&
|
!ReleaseChannelRepo.StartsWith("%%") &&
|
||||||
!ConfigFileName.StartsWith("%%");
|
!ConfigFileName.StartsWith("%%");
|
||||||
|
|
||||||
public static bool IsFlatHubBuild => IsValid && ReleaseChannelOwner.Equals(FlatHubChannel);
|
|
||||||
|
|
||||||
public static bool IsCanaryBuild => IsValid && ReleaseChannelName.Equals(CanaryChannel);
|
public static bool IsCanaryBuild => IsValid && ReleaseChannelName.Equals(CanaryChannel);
|
||||||
|
|
||||||
public static bool IsReleaseBuild => IsValid && ReleaseChannelName.Equals(ReleaseChannel);
|
public static bool IsReleaseBuild => IsValid && ReleaseChannelName.Equals(ReleaseChannel);
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Text.Json;
|
using System.Text.Json;
|
||||||
@ -27,9 +28,14 @@ namespace Ryujinx.Common.Utilities
|
|||||||
ReadCommentHandling = JsonCommentHandling.Skip
|
ReadCommentHandling = JsonCommentHandling.Skip
|
||||||
};
|
};
|
||||||
|
|
||||||
public static string Serialize<T>(T value, JsonTypeInfo<T> typeInfo) => JsonSerializer.Serialize(value, typeInfo);
|
public static string Serialize<T>(T value, JsonTypeInfo<T> typeInfo)
|
||||||
|
=> JsonSerializer.Serialize(value, typeInfo);
|
||||||
|
|
||||||
public static T Deserialize<T>(string value, JsonTypeInfo<T> typeInfo) => JsonSerializer.Deserialize(value, typeInfo);
|
public static T Deserialize<T>(string value, JsonTypeInfo<T> typeInfo)
|
||||||
|
=> JsonSerializer.Deserialize(value, typeInfo);
|
||||||
|
|
||||||
|
public static T Deserialize<T>(ReadOnlySpan<byte> utf8Value, JsonTypeInfo<T> typeInfo)
|
||||||
|
=> JsonSerializer.Deserialize<T>(utf8Value, typeInfo);
|
||||||
|
|
||||||
public static void SerializeToFile<T>(string filePath, T value, JsonTypeInfo<T> typeInfo)
|
public static void SerializeToFile<T>(string filePath, T value, JsonTypeInfo<T> typeInfo)
|
||||||
{
|
{
|
||||||
|
@ -230,25 +230,20 @@ namespace Ryujinx.Cpu.AppleHv
|
|||||||
{
|
{
|
||||||
if (size == 0)
|
if (size == 0)
|
||||||
{
|
{
|
||||||
return Enumerable.Empty<HostMemoryRange>();
|
yield break;
|
||||||
}
|
}
|
||||||
|
|
||||||
var guestRegions = GetPhysicalRegionsImpl(va, size);
|
var guestRegions = GetPhysicalRegionsImpl(va, size);
|
||||||
if (guestRegions == null)
|
if (guestRegions == null)
|
||||||
{
|
{
|
||||||
return null;
|
yield break;
|
||||||
}
|
}
|
||||||
|
|
||||||
var regions = new HostMemoryRange[guestRegions.Count];
|
foreach (var guestRegion in guestRegions)
|
||||||
|
|
||||||
for (int i = 0; i < regions.Length; i++)
|
|
||||||
{
|
{
|
||||||
var guestRegion = guestRegions[i];
|
|
||||||
nint pointer = _backingMemory.GetPointer(guestRegion.Address, guestRegion.Size);
|
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
@ -256,23 +251,24 @@ namespace Ryujinx.Cpu.AppleHv
|
|||||||
{
|
{
|
||||||
if (size == 0)
|
if (size == 0)
|
||||||
{
|
{
|
||||||
return Enumerable.Empty<MemoryRange>();
|
yield break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return GetPhysicalRegionsImpl(va, size);
|
foreach (var physicalRegion in GetPhysicalRegionsImpl(va, size))
|
||||||
|
{
|
||||||
|
yield return physicalRegion;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<MemoryRange> GetPhysicalRegionsImpl(ulong va, ulong size)
|
private IEnumerable<MemoryRange> GetPhysicalRegionsImpl(ulong va, ulong size)
|
||||||
{
|
{
|
||||||
if (!ValidateAddress(va) || !ValidateAddressAndSize(va, size))
|
if (!ValidateAddress(va) || !ValidateAddressAndSize(va, size))
|
||||||
{
|
{
|
||||||
return null;
|
yield break;
|
||||||
}
|
}
|
||||||
|
|
||||||
int pages = GetPagesCount(va, (uint)size, out va);
|
int pages = GetPagesCount(va, (uint)size, out va);
|
||||||
|
|
||||||
var regions = new List<MemoryRange>();
|
|
||||||
|
|
||||||
ulong regionStart = GetPhysicalAddressInternal(va);
|
ulong regionStart = GetPhysicalAddressInternal(va);
|
||||||
ulong regionSize = PageSize;
|
ulong regionSize = PageSize;
|
||||||
|
|
||||||
@ -280,14 +276,14 @@ namespace Ryujinx.Cpu.AppleHv
|
|||||||
{
|
{
|
||||||
if (!ValidateAddress(va + PageSize))
|
if (!ValidateAddress(va + PageSize))
|
||||||
{
|
{
|
||||||
return null;
|
yield break;
|
||||||
}
|
}
|
||||||
|
|
||||||
ulong newPa = GetPhysicalAddressInternal(va + PageSize);
|
ulong newPa = GetPhysicalAddressInternal(va + PageSize);
|
||||||
|
|
||||||
if (GetPhysicalAddressInternal(va) + PageSize != newPa)
|
if (GetPhysicalAddressInternal(va) + PageSize != newPa)
|
||||||
{
|
{
|
||||||
regions.Add(new MemoryRange(regionStart, regionSize));
|
yield return new MemoryRange(regionStart, regionSize);
|
||||||
regionStart = newPa;
|
regionStart = newPa;
|
||||||
regionSize = 0;
|
regionSize = 0;
|
||||||
}
|
}
|
||||||
@ -296,9 +292,7 @@ namespace Ryujinx.Cpu.AppleHv
|
|||||||
regionSize += PageSize;
|
regionSize += PageSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
regions.Add(new MemoryRange(regionStart, regionSize));
|
yield return new MemoryRange(regionStart, regionSize);
|
||||||
|
|
||||||
return regions;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <remarks>
|
/// <remarks>
|
||||||
|
@ -115,6 +115,9 @@ namespace Ryujinx.Cpu.Jit.HostTracked
|
|||||||
}
|
}
|
||||||
|
|
||||||
private readonly AddressIntrusiveRedBlackTree<Mapping> _mappingTree;
|
private readonly AddressIntrusiveRedBlackTree<Mapping> _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;
|
private readonly object _lock;
|
||||||
|
|
||||||
public Block(MemoryTracking tracking, Func<ulong, ulong> readPtCallback, MemoryBlock memory, ulong size, object locker) : base(memory, size)
|
public Block(MemoryTracking tracking, Func<ulong, ulong> 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 MemoryTracking _tracking;
|
||||||
private readonly Func<ulong, ulong> _readPtCallback;
|
private readonly Func<ulong, ulong> _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;
|
private readonly object _lock;
|
||||||
|
|
||||||
public AddressSpacePartitionAllocator(
|
public AddressSpacePartitionAllocator(
|
||||||
|
@ -250,25 +250,20 @@ namespace Ryujinx.Cpu.Jit
|
|||||||
{
|
{
|
||||||
if (size == 0)
|
if (size == 0)
|
||||||
{
|
{
|
||||||
return Enumerable.Empty<HostMemoryRange>();
|
yield break;
|
||||||
}
|
}
|
||||||
|
|
||||||
var guestRegions = GetPhysicalRegionsImpl(va, size);
|
var guestRegions = GetPhysicalRegionsImpl(va, size);
|
||||||
if (guestRegions == null)
|
if (guestRegions == null)
|
||||||
{
|
{
|
||||||
return null;
|
yield break;
|
||||||
}
|
}
|
||||||
|
|
||||||
var regions = new HostMemoryRange[guestRegions.Count];
|
foreach (var guestRegion in guestRegions)
|
||||||
|
|
||||||
for (int i = 0; i < regions.Length; i++)
|
|
||||||
{
|
{
|
||||||
var guestRegion = guestRegions[i];
|
|
||||||
nint pointer = _backingMemory.GetPointer(guestRegion.Address, guestRegion.Size);
|
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
@ -276,23 +271,24 @@ namespace Ryujinx.Cpu.Jit
|
|||||||
{
|
{
|
||||||
if (size == 0)
|
if (size == 0)
|
||||||
{
|
{
|
||||||
return Enumerable.Empty<MemoryRange>();
|
yield break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return GetPhysicalRegionsImpl(va, size);
|
foreach (var physicalRegion in GetPhysicalRegionsImpl(va, size))
|
||||||
|
{
|
||||||
|
yield return physicalRegion;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<MemoryRange> GetPhysicalRegionsImpl(ulong va, ulong size)
|
private IEnumerable<MemoryRange> GetPhysicalRegionsImpl(ulong va, ulong size)
|
||||||
{
|
{
|
||||||
if (!ValidateAddress(va) || !ValidateAddressAndSize(va, size))
|
if (!ValidateAddress(va) || !ValidateAddressAndSize(va, size))
|
||||||
{
|
{
|
||||||
return null;
|
yield break;
|
||||||
}
|
}
|
||||||
|
|
||||||
int pages = GetPagesCount(va, (uint)size, out va);
|
int pages = GetPagesCount(va, (uint)size, out va);
|
||||||
|
|
||||||
var regions = new List<MemoryRange>();
|
|
||||||
|
|
||||||
ulong regionStart = GetPhysicalAddressInternal(va);
|
ulong regionStart = GetPhysicalAddressInternal(va);
|
||||||
ulong regionSize = PageSize;
|
ulong regionSize = PageSize;
|
||||||
|
|
||||||
@ -300,14 +296,14 @@ namespace Ryujinx.Cpu.Jit
|
|||||||
{
|
{
|
||||||
if (!ValidateAddress(va + PageSize))
|
if (!ValidateAddress(va + PageSize))
|
||||||
{
|
{
|
||||||
return null;
|
yield break;
|
||||||
}
|
}
|
||||||
|
|
||||||
ulong newPa = GetPhysicalAddressInternal(va + PageSize);
|
ulong newPa = GetPhysicalAddressInternal(va + PageSize);
|
||||||
|
|
||||||
if (GetPhysicalAddressInternal(va) + PageSize != newPa)
|
if (GetPhysicalAddressInternal(va) + PageSize != newPa)
|
||||||
{
|
{
|
||||||
regions.Add(new MemoryRange(regionStart, regionSize));
|
yield return new MemoryRange(regionStart, regionSize);
|
||||||
regionStart = newPa;
|
regionStart = newPa;
|
||||||
regionSize = 0;
|
regionSize = 0;
|
||||||
}
|
}
|
||||||
@ -316,9 +312,7 @@ namespace Ryujinx.Cpu.Jit
|
|||||||
regionSize += PageSize;
|
regionSize += PageSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
regions.Add(new MemoryRange(regionStart, regionSize));
|
yield return new MemoryRange(regionStart, regionSize);
|
||||||
|
|
||||||
return regions;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
|
@ -475,17 +475,15 @@ namespace Ryujinx.Cpu.Jit
|
|||||||
return GetPhysicalRegionsImpl(va, size);
|
return GetPhysicalRegionsImpl(va, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<MemoryRange> GetPhysicalRegionsImpl(ulong va, ulong size)
|
private IEnumerable<MemoryRange> GetPhysicalRegionsImpl(ulong va, ulong size)
|
||||||
{
|
{
|
||||||
if (!ValidateAddress(va) || !ValidateAddressAndSize(va, size))
|
if (!ValidateAddress(va) || !ValidateAddressAndSize(va, size))
|
||||||
{
|
{
|
||||||
return null;
|
yield break;
|
||||||
}
|
}
|
||||||
|
|
||||||
int pages = GetPagesCount(va, (uint)size, out va);
|
int pages = GetPagesCount(va, (uint)size, out va);
|
||||||
|
|
||||||
var regions = new List<MemoryRange>();
|
|
||||||
|
|
||||||
ulong regionStart = GetPhysicalAddressInternal(va);
|
ulong regionStart = GetPhysicalAddressInternal(va);
|
||||||
ulong regionSize = PageSize;
|
ulong regionSize = PageSize;
|
||||||
|
|
||||||
@ -493,14 +491,14 @@ namespace Ryujinx.Cpu.Jit
|
|||||||
{
|
{
|
||||||
if (!ValidateAddress(va + PageSize))
|
if (!ValidateAddress(va + PageSize))
|
||||||
{
|
{
|
||||||
return null;
|
yield break;
|
||||||
}
|
}
|
||||||
|
|
||||||
ulong newPa = GetPhysicalAddressInternal(va + PageSize);
|
ulong newPa = GetPhysicalAddressInternal(va + PageSize);
|
||||||
|
|
||||||
if (GetPhysicalAddressInternal(va) + PageSize != newPa)
|
if (GetPhysicalAddressInternal(va) + PageSize != newPa)
|
||||||
{
|
{
|
||||||
regions.Add(new MemoryRange(regionStart, regionSize));
|
yield return new MemoryRange(regionStart, regionSize);
|
||||||
regionStart = newPa;
|
regionStart = newPa;
|
||||||
regionSize = 0;
|
regionSize = 0;
|
||||||
}
|
}
|
||||||
@ -509,9 +507,7 @@ namespace Ryujinx.Cpu.Jit
|
|||||||
regionSize += PageSize;
|
regionSize += PageSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
regions.Add(new MemoryRange(regionStart, regionSize));
|
yield return new MemoryRange(regionStart, regionSize);
|
||||||
|
|
||||||
return regions;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
|
@ -8,8 +8,6 @@ namespace Ryujinx.Cpu.LightningJit.CodeGen.Arm64
|
|||||||
{
|
{
|
||||||
public IEnumerable<ulong> GetCallStack(nint framePointer, nint codeRegionStart, int codeRegionSize, nint codeRegion2Start, int codeRegion2Size)
|
public IEnumerable<ulong> GetCallStack(nint framePointer, nint codeRegionStart, int codeRegionSize, nint codeRegion2Start, int codeRegion2Size)
|
||||||
{
|
{
|
||||||
List<ulong> functionPointers = new();
|
|
||||||
|
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
nint functionPointer = Marshal.ReadIntPtr(framePointer, nint.Size);
|
nint functionPointer = Marshal.ReadIntPtr(framePointer, nint.Size);
|
||||||
@ -20,11 +18,9 @@ namespace Ryujinx.Cpu.LightningJit.CodeGen.Arm64
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
functionPointers.Add((ulong)functionPointer - 4);
|
yield return (ulong)functionPointer - 4;
|
||||||
framePointer = Marshal.ReadIntPtr(framePointer);
|
framePointer = Marshal.ReadIntPtr(framePointer);
|
||||||
}
|
}
|
||||||
|
|
||||||
return functionPointers;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -168,16 +168,14 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
return BinarySearch(list, offset, size) >= 0;
|
return BinarySearch(list, offset, size) >= 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public readonly List<Range> FindOverlaps(int offset, int size)
|
public readonly IEnumerable<Range> FindOverlaps(int offset, int size)
|
||||||
{
|
{
|
||||||
var list = _ranges;
|
var list = _ranges;
|
||||||
if (list == null)
|
if (list == null)
|
||||||
{
|
{
|
||||||
return null;
|
yield break;
|
||||||
}
|
}
|
||||||
|
|
||||||
List<Range> result = null;
|
|
||||||
|
|
||||||
int index = BinarySearch(list, offset, size);
|
int index = BinarySearch(list, offset, size);
|
||||||
|
|
||||||
if (index >= 0)
|
if (index >= 0)
|
||||||
@ -189,12 +187,10 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
(result ??= new List<Range>()).Add(list[index++]);
|
yield return list[index++];
|
||||||
}
|
}
|
||||||
while (index < list.Count && list[index].OverlapsWith(offset, size));
|
while (index < list.Count && list[index].OverlapsWith(offset, size));
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int BinarySearch(List<Range> list, int offset, int size)
|
private static int BinarySearch(List<Range> list, int offset, int size)
|
||||||
|
@ -62,7 +62,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
_api = api;
|
_api = api;
|
||||||
_physicalDevice = physicalDevice;
|
_physicalDevice = physicalDevice;
|
||||||
|
|
||||||
int totalFormats = Enum.GetNames(typeof(Format)).Length;
|
int totalFormats = Enum.GetNames<Format>().Length;
|
||||||
|
|
||||||
_bufferTable = new FormatFeatureFlags[totalFormats];
|
_bufferTable = new FormatFeatureFlags[totalFormats];
|
||||||
_optimalTable = new FormatFeatureFlags[totalFormats];
|
_optimalTable = new FormatFeatureFlags[totalFormats];
|
||||||
@ -148,7 +148,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
return (formatFeatureFlags & flags) == flags;
|
return (formatFeatureFlags & flags) == flags;
|
||||||
}
|
}
|
||||||
|
|
||||||
public VkFormat ConvertToVkFormat(Format srcFormat)
|
public VkFormat ConvertToVkFormat(Format srcFormat, bool storageFeatureFlagRequired)
|
||||||
{
|
{
|
||||||
var format = FormatTable.GetFormat(srcFormat);
|
var format = FormatTable.GetFormat(srcFormat);
|
||||||
|
|
||||||
@ -165,7 +165,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
requiredFeatures |= FormatFeatureFlags.ColorAttachmentBit;
|
requiredFeatures |= FormatFeatureFlags.ColorAttachmentBit;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (srcFormat.IsImageCompatible())
|
if (srcFormat.IsImageCompatible() && storageFeatureFlagRequired)
|
||||||
{
|
{
|
||||||
requiredFeatures |= FormatFeatureFlags.StorageImageBit;
|
requiredFeatures |= FormatFeatureFlags.StorageImageBit;
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
|
|
||||||
static FormatTable()
|
static FormatTable()
|
||||||
{
|
{
|
||||||
_table = new VkFormat[Enum.GetNames(typeof(Format)).Length];
|
_table = new VkFormat[Enum.GetNames<Format>().Length];
|
||||||
_reverseMap = new Dictionary<VkFormat, Format>();
|
_reverseMap = new Dictionary<VkFormat, Format>();
|
||||||
|
|
||||||
#pragma warning disable IDE0055 // Disable formatting
|
#pragma warning disable IDE0055 // Disable formatting
|
||||||
|
@ -29,11 +29,17 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
int colorCount = 0;
|
int colorCount = 0;
|
||||||
int maxColorAttachmentIndex = -1;
|
int maxColorAttachmentIndex = -1;
|
||||||
|
|
||||||
|
bool isNotMsOrSupportsStorage = gd.Capabilities.SupportsShaderStorageImageMultisample ||
|
||||||
|
!state.DepthStencilFormat.IsImageCompatible();
|
||||||
|
|
||||||
for (int i = 0; i < state.AttachmentEnable.Length; i++)
|
for (int i = 0; i < state.AttachmentEnable.Length; i++)
|
||||||
{
|
{
|
||||||
if (state.AttachmentEnable[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;
|
attachmentIndices[attachmentCount++] = i;
|
||||||
colorCount++;
|
colorCount++;
|
||||||
@ -43,7 +49,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
|
|
||||||
if (state.DepthStencilEnable)
|
if (state.DepthStencilEnable)
|
||||||
{
|
{
|
||||||
attachmentFormats[attachmentCount++] = gd.FormatCapabilities.ConvertToVkFormat(state.DepthStencilFormat);
|
attachmentFormats[attachmentCount++] = gd.FormatCapabilities.ConvertToVkFormat(state.DepthStencilFormat, isNotMsOrSupportsStorage);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (attachmentCount != 0)
|
if (attachmentCount != 0)
|
||||||
@ -296,7 +302,10 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
{
|
{
|
||||||
if (state.AttachmentEnable[i])
|
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;
|
maxColorAttachmentIndex = i;
|
||||||
|
|
||||||
if (state.AttachmentFormats[i].IsInteger())
|
if (state.AttachmentFormats[i].IsInteger())
|
||||||
@ -310,7 +319,10 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
|
|
||||||
if (state.DepthStencilEnable)
|
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);
|
pipeline.ColorBlendAttachmentStateCount = (uint)(maxColorAttachmentIndex + 1);
|
||||||
|
@ -13,7 +13,7 @@ namespace Ryujinx.Graphics.Vulkan.Queries
|
|||||||
{
|
{
|
||||||
_pipeline = pipeline;
|
_pipeline = pipeline;
|
||||||
|
|
||||||
int count = Enum.GetNames(typeof(CounterType)).Length;
|
int count = Enum.GetNames<CounterType>().Length;
|
||||||
|
|
||||||
_counterQueues = new CounterQueue[count];
|
_counterQueues = new CounterQueue[count];
|
||||||
|
|
||||||
|
@ -77,7 +77,9 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
_device = device;
|
_device = device;
|
||||||
_info = info;
|
_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 levels = (uint)info.Levels;
|
||||||
var layers = (uint)info.GetLayers();
|
var layers = (uint)info.GetLayers();
|
||||||
var depth = (uint)(info.Target == Target.Texture3D ? info.Depth : 1);
|
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 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;
|
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;
|
var usage = DefaultUsageFlags;
|
||||||
|
|
||||||
@ -318,9 +320,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
usage |= ImageUsageFlags.ColorAttachmentBit;
|
usage |= ImageUsageFlags.ColorAttachmentBit;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool supportsMsStorage = capabilities.SupportsShaderStorageImageMultisample;
|
if ((format.IsImageCompatible() && isMsImageStorageSupported) || extendedUsage)
|
||||||
|
|
||||||
if (format.IsImageCompatible() && (supportsMsStorage || !target.IsMultisample()))
|
|
||||||
{
|
{
|
||||||
usage |= ImageUsageFlags.StorageBit;
|
usage |= ImageUsageFlags.StorageBit;
|
||||||
}
|
}
|
||||||
|
@ -61,8 +61,11 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
|
|
||||||
gd.Textures.Add(this);
|
gd.Textures.Add(this);
|
||||||
|
|
||||||
var format = _gd.FormatCapabilities.ConvertToVkFormat(info.Format);
|
bool isMsImageStorageSupported = gd.Capabilities.SupportsShaderStorageImageMultisample || !info.Target.IsMultisample();
|
||||||
var usage = TextureStorage.GetImageUsage(info.Format, info.Target, gd.Capabilities);
|
|
||||||
|
var format = _gd.FormatCapabilities.ConvertToVkFormat(info.Format, isMsImageStorageSupported);
|
||||||
|
var usage = TextureStorage.GetImageUsage(info.Format, gd.Capabilities, isMsImageStorageSupported, false);
|
||||||
|
|
||||||
var levels = (uint)info.Levels;
|
var levels = (uint)info.Levels;
|
||||||
var layers = (uint)info.GetLayers();
|
var layers = (uint)info.GetLayers();
|
||||||
|
|
||||||
|
@ -341,7 +341,7 @@ namespace Ryujinx.HLE.HOS
|
|||||||
{
|
{
|
||||||
if (VirtualAmiibo.ApplicationBytes.Length > 0)
|
if (VirtualAmiibo.ApplicationBytes.Length > 0)
|
||||||
{
|
{
|
||||||
VirtualAmiibo.ApplicationBytes = new byte[0];
|
VirtualAmiibo.ApplicationBytes = Array.Empty<byte>();
|
||||||
VirtualAmiibo.InputBin = string.Empty;
|
VirtualAmiibo.InputBin = string.Empty;
|
||||||
}
|
}
|
||||||
if (NfpDevices[nfpDeviceId].State == NfpDeviceState.SearchingForTag)
|
if (NfpDevices[nfpDeviceId].State == NfpDeviceState.SearchingForTag)
|
||||||
@ -356,7 +356,7 @@ namespace Ryujinx.HLE.HOS
|
|||||||
VirtualAmiibo.InputBin = path;
|
VirtualAmiibo.InputBin = path;
|
||||||
if (VirtualAmiibo.ApplicationBytes.Length > 0)
|
if (VirtualAmiibo.ApplicationBytes.Length > 0)
|
||||||
{
|
{
|
||||||
VirtualAmiibo.ApplicationBytes = new byte[0];
|
VirtualAmiibo.ApplicationBytes = Array.Empty<byte>();
|
||||||
}
|
}
|
||||||
byte[] encryptedData = File.ReadAllBytes(path);
|
byte[] encryptedData = File.ReadAllBytes(path);
|
||||||
VirtualAmiiboFile newFile = AmiiboBinReader.ReadBinFile(encryptedData);
|
VirtualAmiiboFile newFile = AmiiboBinReader.ReadBinFile(encryptedData);
|
||||||
|
@ -15,6 +15,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Common
|
|||||||
private readonly long[] _current2;
|
private readonly long[] _current2;
|
||||||
private readonly long[] _peak;
|
private readonly long[] _peak;
|
||||||
|
|
||||||
|
// type is not Lock due to Monitor class usage
|
||||||
private readonly object _lock = new();
|
private readonly object _lock = new();
|
||||||
|
|
||||||
private readonly LinkedList<KThread> _waitingThreads;
|
private readonly LinkedList<KThread> _waitingThreads;
|
||||||
|
@ -5,10 +5,10 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
|
|||||||
class KCriticalSection
|
class KCriticalSection
|
||||||
{
|
{
|
||||||
private readonly KernelContext _context;
|
private readonly KernelContext _context;
|
||||||
private readonly object _lock = new();
|
|
||||||
private int _recursionCount;
|
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)
|
public KCriticalSection(KernelContext context)
|
||||||
{
|
{
|
||||||
@ -17,7 +17,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
|
|||||||
|
|
||||||
public void Enter()
|
public void Enter()
|
||||||
{
|
{
|
||||||
Monitor.Enter(_lock);
|
Monitor.Enter(Lock);
|
||||||
|
|
||||||
_recursionCount++;
|
_recursionCount++;
|
||||||
}
|
}
|
||||||
@ -33,7 +33,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
|
|||||||
{
|
{
|
||||||
ulong scheduledCoresMask = KScheduler.SelectThreads(_context);
|
ulong scheduledCoresMask = KScheduler.SelectThreads(_context);
|
||||||
|
|
||||||
Monitor.Exit(_lock);
|
Monitor.Exit(Lock);
|
||||||
|
|
||||||
KThread currentThread = KernelStatic.GetCurrentThread();
|
KThread currentThread = KernelStatic.GetCurrentThread();
|
||||||
bool isCurrentThreadSchedulable = currentThread != null && currentThread.IsSchedulable;
|
bool isCurrentThreadSchedulable = currentThread != null && currentThread.IsSchedulable;
|
||||||
@ -56,7 +56,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Monitor.Exit(_lock);
|
Monitor.Exit(Lock);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -357,7 +357,6 @@ namespace Ryujinx.HLE.HOS
|
|||||||
{
|
{
|
||||||
string cheatName = DefaultCheatName;
|
string cheatName = DefaultCheatName;
|
||||||
List<string> instructions = new();
|
List<string> instructions = new();
|
||||||
List<Cheat> cheats = new();
|
|
||||||
|
|
||||||
using StreamReader cheatData = cheatFile.OpenText();
|
using StreamReader cheatData = cheatFile.OpenText();
|
||||||
while (cheatData.ReadLine() is { } line)
|
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");
|
Logger.Warning?.Print(LogClass.ModLoader, $"Ignoring cheat '{cheatFile.FullName}' because it is malformed");
|
||||||
|
|
||||||
return Array.Empty<Cheat>();
|
yield break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add the previous section to the list.
|
// Add the previous section to the list.
|
||||||
if (instructions.Count > 0)
|
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.
|
// Start a new cheat section.
|
||||||
@ -396,10 +395,8 @@ namespace Ryujinx.HLE.HOS
|
|||||||
// Add the last section being processed.
|
// Add the last section being processed.
|
||||||
if (instructions.Count > 0)
|
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
|
// Assumes searchDirPaths don't overlap
|
||||||
|
@ -23,18 +23,18 @@ namespace Ryujinx.HLE.HOS.Services
|
|||||||
|
|
||||||
public IpcService(ServerBase server = null)
|
public IpcService(ServerBase server = null)
|
||||||
{
|
{
|
||||||
CmifCommands = typeof(IpcService).Assembly.GetTypes()
|
CmifCommands = GetType().Assembly.GetTypes()
|
||||||
.Where(type => type == GetType())
|
.Where(type => type == GetType())
|
||||||
.SelectMany(type => type.GetMethods(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public))
|
.SelectMany(type => type.GetMethods(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public))
|
||||||
.SelectMany(methodInfo => methodInfo.GetCustomAttributes(typeof(CommandCmifAttribute))
|
.SelectMany(methodInfo => methodInfo.GetCustomAttributes<CommandCmifAttribute>()
|
||||||
.Select(command => (((CommandCmifAttribute)command).Id, methodInfo)))
|
.Select(command => (command.Id, methodInfo)))
|
||||||
.ToDictionary(command => command.Id, command => command.methodInfo);
|
.ToDictionary(command => command.Id, command => command.methodInfo);
|
||||||
|
|
||||||
TipcCommands = typeof(IpcService).Assembly.GetTypes()
|
TipcCommands = GetType().Assembly.GetTypes()
|
||||||
.Where(type => type == GetType())
|
.Where(type => type == GetType())
|
||||||
.SelectMany(type => type.GetMethods(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public))
|
.SelectMany(type => type.GetMethods(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public))
|
||||||
.SelectMany(methodInfo => methodInfo.GetCustomAttributes(typeof(CommandTipcAttribute))
|
.SelectMany(methodInfo => methodInfo.GetCustomAttributes<CommandTipcAttribute>()
|
||||||
.Select(command => (((CommandTipcAttribute)command).Id, methodInfo)))
|
.Select(command => (command.Id, methodInfo)))
|
||||||
.ToDictionary(command => command.Id, command => command.methodInfo);
|
.ToDictionary(command => command.Id, command => command.methodInfo);
|
||||||
|
|
||||||
Server = server;
|
Server = server;
|
||||||
|
@ -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)
|
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<NetworkInfo>();
|
||||||
ulong maxGames = bufferSize / networkInfoSize;
|
ulong maxGames = bufferSize / networkInfoSize;
|
||||||
|
|
||||||
MemoryHelper.FillWithZeros(memory, bufferPosition, (int)bufferSize);
|
MemoryHelper.FillWithZeros(memory, bufferPosition, (int)bufferSize);
|
||||||
|
@ -33,12 +33,15 @@ namespace Ryujinx.HLE.HOS.Services.Nfc.AmiiboDecryption
|
|||||||
const int pageSize = 4;
|
const int pageSize = 4;
|
||||||
const int totalBytes = totalPages * pageSize;
|
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);
|
AmiiboDump amiiboDump = amiiboDecryptor.DecryptAmiiboDump(fileBytes);
|
||||||
|
|
||||||
byte[] titleId = new byte[8];
|
byte[] titleId = new byte[8];
|
||||||
@ -171,7 +174,15 @@ namespace Ryujinx.HLE.HOS.Services.Nfc.AmiiboDecryption
|
|||||||
return false;
|
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 amiiboDump = amiiboDecryptor.DecryptAmiiboDump(readBytes);
|
||||||
|
|
||||||
byte[] oldData = amiiboDump.GetData();
|
byte[] oldData = amiiboDump.GetData();
|
||||||
@ -231,7 +242,15 @@ namespace Ryujinx.HLE.HOS.Services.Nfc.AmiiboDecryption
|
|||||||
return false;
|
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 amiiboDump = amiiboDecryptor.DecryptAmiiboDump(readBytes);
|
||||||
amiiboDump.AmiiboNickname = newNickName;
|
amiiboDump.AmiiboNickname = newNickName;
|
||||||
byte[] oldData = amiiboDump.GetData();
|
byte[] oldData = amiiboDump.GetData();
|
||||||
@ -314,10 +333,9 @@ namespace Ryujinx.HLE.HOS.Services.Nfc.AmiiboDecryption
|
|||||||
return Path.Combine(AppDataManager.KeysDirPath, "key_retail.bin");
|
return Path.Combine(AppDataManager.KeysDirPath, "key_retail.bin");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static bool HasKeyRetailBinPath()
|
public static bool HasAmiiboKeyFile => File.Exists(GetKeyRetailBinPath());
|
||||||
{
|
|
||||||
return File.Exists(GetKeyRetailBinPath());
|
|
||||||
}
|
|
||||||
public static DateTime DateTimeFromTag(ushort value)
|
public static DateTime DateTimeFromTag(ushort value)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
|
@ -2,12 +2,12 @@ using System.IO;
|
|||||||
|
|
||||||
namespace Ryujinx.HLE.HOS.Services.Nfc.AmiiboDecryption
|
namespace Ryujinx.HLE.HOS.Services.Nfc.AmiiboDecryption
|
||||||
{
|
{
|
||||||
public class AmiiboDecrypter
|
public class AmiiboDecryptor
|
||||||
{
|
{
|
||||||
public AmiiboMasterKey DataKey { get; private set; }
|
public AmiiboMasterKey DataKey { get; private set; }
|
||||||
public AmiiboMasterKey TagKey { get; private set; }
|
public AmiiboMasterKey TagKey { get; private set; }
|
||||||
|
|
||||||
public AmiiboDecrypter(string keyRetailBinPath)
|
public AmiiboDecryptor(string keyRetailBinPath)
|
||||||
{
|
{
|
||||||
var combinedKeys = File.ReadAllBytes(keyRetailBinPath);
|
var combinedKeys = File.ReadAllBytes(keyRetailBinPath);
|
||||||
var keys = AmiiboMasterKey.FromCombinedBin(combinedKeys);
|
var keys = AmiiboMasterKey.FromCombinedBin(combinedKeys);
|
||||||
@ -18,7 +18,7 @@ namespace Ryujinx.HLE.HOS.Services.Nfc.AmiiboDecryption
|
|||||||
public AmiiboDump DecryptAmiiboDump(byte[] encryptedDumpData)
|
public AmiiboDump DecryptAmiiboDump(byte[] encryptedDumpData)
|
||||||
{
|
{
|
||||||
// Initialize AmiiboDump with encrypted data
|
// 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
|
// Unlock (decrypt) the dump
|
||||||
amiiboDump.Unlock();
|
amiiboDump.Unlock();
|
||||||
@ -32,7 +32,7 @@ namespace Ryujinx.HLE.HOS.Services.Nfc.AmiiboDecryption
|
|||||||
public AmiiboDump EncryptAmiiboDump(byte[] decryptedDumpData)
|
public AmiiboDump EncryptAmiiboDump(byte[] decryptedDumpData)
|
||||||
{
|
{
|
||||||
// Initialize AmiiboDump with decrypted data
|
// 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
|
// Lock (encrypt) the dump
|
||||||
amiiboDump.Lock();
|
amiiboDump.Lock();
|
@ -36,7 +36,7 @@ namespace Ryujinx.HLE.HOS.Services.Nfc.AmiiboDecryption
|
|||||||
|
|
||||||
private byte[] DeriveKey(AmiiboMasterKey key, bool deriveAes, out byte[] derivedAesKey, out byte[] derivedAesIv)
|
private byte[] DeriveKey(AmiiboMasterKey key, bool deriveAes, out byte[] derivedAesKey, out byte[] derivedAesIv)
|
||||||
{
|
{
|
||||||
List<byte> seed = new List<byte>();
|
List<byte> seed = [];
|
||||||
|
|
||||||
// Start with the type string (14 bytes)
|
// Start with the type string (14 bytes)
|
||||||
seed.AddRange(key.TypeString);
|
seed.AddRange(key.TypeString);
|
||||||
|
@ -33,10 +33,7 @@ namespace Ryujinx.HLE.HOS.Services.Nfc.AmiiboDecryption
|
|||||||
byte[] dataBin = combinedBin.Take(80).ToArray();
|
byte[] dataBin = combinedBin.Take(80).ToArray();
|
||||||
byte[] tagBin = combinedBin.Skip(80).Take(80).ToArray();
|
byte[] tagBin = combinedBin.Skip(80).Take(80).ToArray();
|
||||||
|
|
||||||
AmiiboMasterKey dataKey = new AmiiboMasterKey(dataBin);
|
return (new AmiiboMasterKey(dataBin), new AmiiboMasterKey(tagBin));
|
||||||
AmiiboMasterKey tagKey = new AmiiboMasterKey(tagBin);
|
|
||||||
|
|
||||||
return (dataKey, tagKey);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,7 +16,7 @@ namespace Ryujinx.HLE.HOS.Services.Nfc.Nfp
|
|||||||
static class VirtualAmiibo
|
static class VirtualAmiibo
|
||||||
{
|
{
|
||||||
public static uint OpenedApplicationAreaId;
|
public static uint OpenedApplicationAreaId;
|
||||||
public static byte[] ApplicationBytes = new byte[0];
|
public static byte[] ApplicationBytes = Array.Empty<byte>();
|
||||||
public static string InputBin = string.Empty;
|
public static string InputBin = string.Empty;
|
||||||
public static string NickName = string.Empty;
|
public static string NickName = string.Empty;
|
||||||
private static readonly AmiiboJsonSerializerContext _serializerContext = AmiiboJsonSerializerContext.Default;
|
private static readonly AmiiboJsonSerializerContext _serializerContext = AmiiboJsonSerializerContext.Default;
|
||||||
@ -137,7 +137,7 @@ namespace Ryujinx.HLE.HOS.Services.Nfc.Nfp
|
|||||||
if (ApplicationBytes.Length > 0)
|
if (ApplicationBytes.Length > 0)
|
||||||
{
|
{
|
||||||
byte[] bytes = ApplicationBytes;
|
byte[] bytes = ApplicationBytes;
|
||||||
ApplicationBytes = new byte[0];
|
ApplicationBytes = Array.Empty<byte>();
|
||||||
return bytes;
|
return bytes;
|
||||||
}
|
}
|
||||||
VirtualAmiiboFile virtualAmiiboFile = LoadAmiiboFile(amiiboId);
|
VirtualAmiiboFile virtualAmiiboFile = LoadAmiiboFile(amiiboId);
|
||||||
|
@ -94,7 +94,7 @@ namespace Ryujinx.HLE.HOS.Services.Sm
|
|||||||
{
|
{
|
||||||
if (_services.TryGetValue(name, out Type type))
|
if (_services.TryGetValue(name, out Type type))
|
||||||
{
|
{
|
||||||
ServiceAttribute serviceAttribute = (ServiceAttribute)type.GetCustomAttributes(typeof(ServiceAttribute)).First(service => ((ServiceAttribute)service).Name == name);
|
ServiceAttribute serviceAttribute = type.GetCustomAttributes<ServiceAttribute>().First(service => service.Name == name);
|
||||||
|
|
||||||
IpcService service = GetServiceInstance(type, context, serviceAttribute.Parameter);
|
IpcService service = GetServiceInstance(type, context, serviceAttribute.Parameter);
|
||||||
|
|
||||||
|
@ -10,6 +10,7 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd.Impl
|
|||||||
private ulong _value;
|
private ulong _value;
|
||||||
private readonly EventFdFlags _flags;
|
private readonly EventFdFlags _flags;
|
||||||
|
|
||||||
|
// type is not Lock due to Monitor class usage
|
||||||
private readonly object _lock = new();
|
private readonly object _lock = new();
|
||||||
|
|
||||||
public bool Blocking { get => !_flags.HasFlag(EventFdFlags.NonBlocking); set => throw new NotSupportedException(); }
|
public bool Blocking { get => !_flags.HasFlag(EventFdFlags.NonBlocking); set => throw new NotSupportedException(); }
|
||||||
|
@ -34,14 +34,14 @@ namespace Ryujinx.Horizon.Kernel.Generators
|
|||||||
private const string TypeResult = NamespaceHorizonCommon + "." + TypeResultName;
|
private const string TypeResult = NamespaceHorizonCommon + "." + TypeResultName;
|
||||||
private const string TypeExecutionContext = "IExecutionContext";
|
private const string TypeExecutionContext = "IExecutionContext";
|
||||||
|
|
||||||
private static readonly string[] _expectedResults = new string[]
|
private static readonly string[] _expectedResults =
|
||||||
{
|
[
|
||||||
$"{TypeResultName}.Success",
|
$"{TypeResultName}.Success",
|
||||||
$"{TypeKernelResultName}.TimedOut",
|
$"{TypeKernelResultName}.TimedOut",
|
||||||
$"{TypeKernelResultName}.Cancelled",
|
$"{TypeKernelResultName}.Cancelled",
|
||||||
$"{TypeKernelResultName}.PortRemoteClosed",
|
$"{TypeKernelResultName}.PortRemoteClosed",
|
||||||
$"{TypeKernelResultName}.InvalidState",
|
$"{TypeKernelResultName}.InvalidState",
|
||||||
};
|
];
|
||||||
|
|
||||||
private readonly struct OutParameter
|
private readonly struct OutParameter
|
||||||
{
|
{
|
||||||
|
@ -106,10 +106,13 @@ namespace Ryujinx.Memory
|
|||||||
{
|
{
|
||||||
if (size == 0)
|
if (size == 0)
|
||||||
{
|
{
|
||||||
return Enumerable.Empty<HostMemoryRange>();
|
yield break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return GetHostRegionsImpl(va, size);
|
foreach (var hostRegion in GetHostRegionsImpl(va, size))
|
||||||
|
{
|
||||||
|
yield return hostRegion;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
@ -117,51 +120,36 @@ namespace Ryujinx.Memory
|
|||||||
{
|
{
|
||||||
if (size == 0)
|
if (size == 0)
|
||||||
{
|
{
|
||||||
return Enumerable.Empty<MemoryRange>();
|
yield break;
|
||||||
}
|
}
|
||||||
|
|
||||||
var hostRegions = GetHostRegionsImpl(va, size);
|
var hostRegions = GetHostRegionsImpl(va, size);
|
||||||
if (hostRegions == null)
|
if (hostRegions == null)
|
||||||
{
|
{
|
||||||
return null;
|
yield break;
|
||||||
}
|
}
|
||||||
|
|
||||||
var regions = new MemoryRange[hostRegions.Count];
|
|
||||||
|
|
||||||
ulong backingStart = (ulong)_backingMemory.Pointer;
|
ulong backingStart = (ulong)_backingMemory.Pointer;
|
||||||
ulong backingEnd = backingStart + _backingMemory.Size;
|
ulong backingEnd = backingStart + _backingMemory.Size;
|
||||||
|
|
||||||
int count = 0;
|
foreach (var hostRegion in hostRegions)
|
||||||
|
|
||||||
for (int i = 0; i < regions.Length; i++)
|
|
||||||
{
|
{
|
||||||
var hostRegion = hostRegions[i];
|
|
||||||
|
|
||||||
if (hostRegion.Address >= backingStart && hostRegion.Address < backingEnd)
|
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<MemoryRange>(regions, 0, count);
|
|
||||||
}
|
|
||||||
|
|
||||||
return regions;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<HostMemoryRange> GetHostRegionsImpl(ulong va, ulong size)
|
private IEnumerable<HostMemoryRange> GetHostRegionsImpl(ulong va, ulong size)
|
||||||
{
|
{
|
||||||
if (!ValidateAddress(va) || !ValidateAddressAndSize(va, size))
|
if (!ValidateAddress(va) || !ValidateAddressAndSize(va, size))
|
||||||
{
|
{
|
||||||
return null;
|
yield break;
|
||||||
}
|
}
|
||||||
|
|
||||||
int pages = GetPagesCount(va, size, out va);
|
int pages = GetPagesCount(va, size, out va);
|
||||||
|
|
||||||
var regions = new List<HostMemoryRange>();
|
|
||||||
|
|
||||||
nuint regionStart = GetHostAddress(va);
|
nuint regionStart = GetHostAddress(va);
|
||||||
ulong regionSize = PageSize;
|
ulong regionSize = PageSize;
|
||||||
|
|
||||||
@ -169,14 +157,14 @@ namespace Ryujinx.Memory
|
|||||||
{
|
{
|
||||||
if (!ValidateAddress(va + PageSize))
|
if (!ValidateAddress(va + PageSize))
|
||||||
{
|
{
|
||||||
return null;
|
yield break;
|
||||||
}
|
}
|
||||||
|
|
||||||
nuint newHostAddress = GetHostAddress(va + PageSize);
|
nuint newHostAddress = GetHostAddress(va + PageSize);
|
||||||
|
|
||||||
if (GetHostAddress(va) + PageSize != newHostAddress)
|
if (GetHostAddress(va) + PageSize != newHostAddress)
|
||||||
{
|
{
|
||||||
regions.Add(new HostMemoryRange(regionStart, regionSize));
|
yield return new HostMemoryRange(regionStart, regionSize);
|
||||||
regionStart = newHostAddress;
|
regionStart = newHostAddress;
|
||||||
regionSize = 0;
|
regionSize = 0;
|
||||||
}
|
}
|
||||||
@ -185,9 +173,7 @@ namespace Ryujinx.Memory
|
|||||||
regionSize += PageSize;
|
regionSize += PageSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
regions.Add(new HostMemoryRange(regionStart, regionSize));
|
yield return new HostMemoryRange(regionStart, regionSize);
|
||||||
|
|
||||||
return regions;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
@ -38,7 +38,7 @@ namespace Ryujinx.UI.App.Common
|
|||||||
|
|
||||||
public string TimePlayedString => ValueFormatUtils.FormatTimeSpan(TimePlayed);
|
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);
|
public string FileSizeString => ValueFormatUtils.FormatFileSize(FileSize);
|
||||||
|
|
||||||
|
@ -23,7 +23,7 @@ namespace Ryujinx.UI.Common.Helper
|
|||||||
[LibraryImport("shell32.dll", SetLastError = true)]
|
[LibraryImport("shell32.dll", SetLastError = true)]
|
||||||
public static partial void SHChangeNotify(uint wEventId, uint uFlags, nint dwItem1, nint dwItem2);
|
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
|
public static bool AreMimeTypesRegistered
|
||||||
{
|
{
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
using Gommon;
|
||||||
using Ryujinx.Common.Logging;
|
using Ryujinx.Common.Logging;
|
||||||
using System;
|
using System;
|
||||||
using System.Diagnostics;
|
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)
|
public static void LocateFile(string path)
|
||||||
{
|
{
|
||||||
if (File.Exists(path))
|
if (File.Exists(path))
|
||||||
|
@ -4,11 +4,10 @@
|
|||||||
<ResourceDictionary x:Key="Default">
|
<ResourceDictionary x:Key="Default">
|
||||||
<SolidColorBrush x:Key="DataGridSelectionBackgroundBrush"
|
<SolidColorBrush x:Key="DataGridSelectionBackgroundBrush"
|
||||||
Color="{DynamicResource DataGridSelectionColor}" />
|
Color="{DynamicResource DataGridSelectionColor}" />
|
||||||
|
<Color x:Key="ControlFillColorSecondary">#008AA8</Color>
|
||||||
<Color x:Key="DataGridSelectionColor">#FF00FABB</Color>
|
<Color x:Key="DataGridSelectionColor">#FF00FABB</Color>
|
||||||
<Color x:Key="ThemeContentBackgroundColor">#FFF0F0F0</Color>
|
<Color x:Key="ThemeContentBackgroundColor">#FFF0F0F0</Color>
|
||||||
<Color x:Key="ThemeControlBorderColor">#FFd6d6d6</Color>
|
<Color x:Key="ThemeControlBorderColor">#FFd6d6d6</Color>
|
||||||
<Color x:Key="TextOnAccentFillColorPrimary">#FFFFFFFF</Color>
|
|
||||||
<Color x:Key="SystemChromeWhiteColor">#FFFFFFFF</Color>
|
|
||||||
<Color x:Key="ThemeForegroundColor">#FF000000</Color>
|
<Color x:Key="ThemeForegroundColor">#FF000000</Color>
|
||||||
<Color x:Key="MenuFlyoutPresenterBorderColor">#C1C1C1</Color>
|
<Color x:Key="MenuFlyoutPresenterBorderColor">#C1C1C1</Color>
|
||||||
<Color x:Key="AppListBackgroundColor">#b3ffffff</Color>
|
<Color x:Key="AppListBackgroundColor">#b3ffffff</Color>
|
||||||
@ -22,16 +21,19 @@
|
|||||||
<ResourceDictionary x:Key="Light">
|
<ResourceDictionary x:Key="Light">
|
||||||
<SolidColorBrush x:Key="DataGridSelectionBackgroundBrush"
|
<SolidColorBrush x:Key="DataGridSelectionBackgroundBrush"
|
||||||
Color="{DynamicResource DataGridSelectionColor}" />
|
Color="{DynamicResource DataGridSelectionColor}" />
|
||||||
|
<Color x:Key="ControlFillColorSecondary">#3ddcff</Color>
|
||||||
<Color x:Key="DataGridSelectionColor">#FF00FABB</Color>
|
<Color x:Key="DataGridSelectionColor">#FF00FABB</Color>
|
||||||
<Color x:Key="ThemeContentBackgroundColor">#FFF0F0F0</Color>
|
<Color x:Key="ThemeContentBackgroundColor">#dedede</Color>
|
||||||
<Color x:Key="ThemeControlBorderColor">#FFd6d6d6</Color>
|
<Color x:Key="ThemeControlBorderColor">#c2c2c2</Color>
|
||||||
<Color x:Key="TextOnAccentFillColorPrimary">#FFFFFFFF</Color>
|
|
||||||
<Color x:Key="SystemChromeWhiteColor">#FFFFFFFF</Color>
|
|
||||||
<Color x:Key="ThemeForegroundColor">#FF000000</Color>
|
<Color x:Key="ThemeForegroundColor">#FF000000</Color>
|
||||||
<Color x:Key="MenuFlyoutPresenterBorderColor">#C1C1C1</Color>
|
<Color x:Key="MenuFlyoutPresenterBorderColor">#C1C1C1</Color>
|
||||||
<Color x:Key="AppListBackgroundColor">#b3ffffff</Color>
|
<Color x:Key="AppListBackgroundColor">#b3ffffff</Color>
|
||||||
<Color x:Key="AppListHoverBackgroundColor">#80cccccc</Color>
|
<Color x:Key="AppListHoverBackgroundColor">#80cccccc</Color>
|
||||||
<Color x:Key="SecondaryTextColor">#A0000000</Color>
|
<Color x:Key="SecondaryTextColor">#A0000000</Color>
|
||||||
|
<Color x:Key="FavoriteApplicationIconColor">#fffcd12a</Color>
|
||||||
|
<Color x:Key="Switch">#13c3a4</Color>
|
||||||
|
<Color x:Key="Unbounded">#FFFF4554</Color>
|
||||||
|
<Color x:Key="Custom">#6483F5</Color>
|
||||||
</ResourceDictionary>
|
</ResourceDictionary>
|
||||||
<ResourceDictionary x:Key="Dark">
|
<ResourceDictionary x:Key="Dark">
|
||||||
<SolidColorBrush x:Key="DataGridSelectionBackgroundBrush"
|
<SolidColorBrush x:Key="DataGridSelectionBackgroundBrush"
|
||||||
@ -40,13 +42,15 @@
|
|||||||
<Color x:Key="DataGridSelectionColor">#FF00FABB</Color>
|
<Color x:Key="DataGridSelectionColor">#FF00FABB</Color>
|
||||||
<Color x:Key="ThemeContentBackgroundColor">#FF2D2D2D</Color>
|
<Color x:Key="ThemeContentBackgroundColor">#FF2D2D2D</Color>
|
||||||
<Color x:Key="ThemeControlBorderColor">#FF505050</Color>
|
<Color x:Key="ThemeControlBorderColor">#FF505050</Color>
|
||||||
<Color x:Key="TextOnAccentFillColorPrimary">#FFFFFFFF</Color>
|
|
||||||
<Color x:Key="SystemChromeWhiteColor">#FFFFFFFF</Color>
|
|
||||||
<Color x:Key="ThemeForegroundColor">#FFFFFFFF</Color>
|
<Color x:Key="ThemeForegroundColor">#FFFFFFFF</Color>
|
||||||
<Color x:Key="MenuFlyoutPresenterBorderColor">#3D3D3D</Color>
|
<Color x:Key="MenuFlyoutPresenterBorderColor">#3D3D3D</Color>
|
||||||
<Color x:Key="AppListBackgroundColor">#0FFFFFFF</Color>
|
<Color x:Key="AppListBackgroundColor">#0FFFFFFF</Color>
|
||||||
<Color x:Key="AppListHoverBackgroundColor">#1EFFFFFF</Color>
|
<Color x:Key="AppListHoverBackgroundColor">#1EFFFFFF</Color>
|
||||||
<Color x:Key="SecondaryTextColor">#A0FFFFFF</Color>
|
<Color x:Key="SecondaryTextColor">#A0FFFFFF</Color>
|
||||||
|
<Color x:Key="FavoriteApplicationIconColor">#fffcd12a</Color>
|
||||||
|
<Color x:Key="Switch">#FF2EEAC9</Color>
|
||||||
|
<Color x:Key="Unbounded">#FFFF4554</Color>
|
||||||
|
<Color x:Key="Custom">#6483F5</Color>
|
||||||
</ResourceDictionary>
|
</ResourceDictionary>
|
||||||
</ResourceDictionary.ThemeDictionaries>
|
</ResourceDictionary.ThemeDictionaries>
|
||||||
</ResourceDictionary>
|
</ResourceDictionary>
|
||||||
|
@ -705,7 +705,7 @@
|
|||||||
"he_IL": "",
|
"he_IL": "",
|
||||||
"it_IT": "",
|
"it_IT": "",
|
||||||
"ja_JP": "",
|
"ja_JP": "",
|
||||||
"ko_KR": "",
|
"ko_KR": "Amiibo 스캔(빈에서)",
|
||||||
"no_NO": "",
|
"no_NO": "",
|
||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "",
|
"pt_BR": "",
|
||||||
@ -1077,6 +1077,54 @@
|
|||||||
"zh_TW": ""
|
"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",
|
"ID": "MenuBarHelp",
|
||||||
"Translations": {
|
"Translations": {
|
||||||
@ -1125,6 +1173,30 @@
|
|||||||
"zh_TW": "檢查更新"
|
"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",
|
"ID": "MenuBarHelpFaq",
|
||||||
"Translations": {
|
"Translations": {
|
||||||
@ -1137,7 +1209,7 @@
|
|||||||
"he_IL": "",
|
"he_IL": "",
|
||||||
"it_IT": "",
|
"it_IT": "",
|
||||||
"ja_JP": "",
|
"ja_JP": "",
|
||||||
"ko_KR": "",
|
"ko_KR": "자주 묻는 질문(FAQ) 및 문제해결 페이지",
|
||||||
"no_NO": "",
|
"no_NO": "",
|
||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "",
|
"pt_BR": "",
|
||||||
@ -1161,7 +1233,7 @@
|
|||||||
"he_IL": "",
|
"he_IL": "",
|
||||||
"it_IT": "",
|
"it_IT": "",
|
||||||
"ja_JP": "",
|
"ja_JP": "",
|
||||||
"ko_KR": "",
|
"ko_KR": "공식 Ryujinx 위키에서 자주 묻는 질문(FAQ) 및 문제 해결 페이지 열기",
|
||||||
"no_NO": "",
|
"no_NO": "",
|
||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "",
|
"pt_BR": "",
|
||||||
@ -1185,7 +1257,7 @@
|
|||||||
"he_IL": "",
|
"he_IL": "",
|
||||||
"it_IT": "",
|
"it_IT": "",
|
||||||
"ja_JP": "",
|
"ja_JP": "",
|
||||||
"ko_KR": "",
|
"ko_KR": "설치 및 구성 안내",
|
||||||
"no_NO": "",
|
"no_NO": "",
|
||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "",
|
"pt_BR": "",
|
||||||
@ -1209,7 +1281,7 @@
|
|||||||
"he_IL": "",
|
"he_IL": "",
|
||||||
"it_IT": "",
|
"it_IT": "",
|
||||||
"ja_JP": "",
|
"ja_JP": "",
|
||||||
"ko_KR": "",
|
"ko_KR": "공식 Ryujinx 위키에서 설정 및 구성 안내 열기",
|
||||||
"no_NO": "",
|
"no_NO": "",
|
||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "",
|
"pt_BR": "",
|
||||||
@ -1233,7 +1305,7 @@
|
|||||||
"he_IL": "",
|
"he_IL": "",
|
||||||
"it_IT": "",
|
"it_IT": "",
|
||||||
"ja_JP": "",
|
"ja_JP": "",
|
||||||
"ko_KR": "",
|
"ko_KR": "멀티플레이어(LDN/LAN) 안내",
|
||||||
"no_NO": "",
|
"no_NO": "",
|
||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "",
|
"pt_BR": "",
|
||||||
@ -1257,7 +1329,7 @@
|
|||||||
"he_IL": "",
|
"he_IL": "",
|
||||||
"it_IT": "",
|
"it_IT": "",
|
||||||
"ja_JP": "",
|
"ja_JP": "",
|
||||||
"ko_KR": "",
|
"ko_KR": "공식 Ryujinx 위키에서 멀티플레이어 안내 열기",
|
||||||
"no_NO": "",
|
"no_NO": "",
|
||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "",
|
"pt_BR": "",
|
||||||
@ -2424,25 +2496,25 @@
|
|||||||
{
|
{
|
||||||
"ID": "StatusBarSystemVersion",
|
"ID": "StatusBarSystemVersion",
|
||||||
"Translations": {
|
"Translations": {
|
||||||
"ar_SA": "إصدار النظام: {0}",
|
"ar_SA": "",
|
||||||
"de_DE": "Systemversion: {0}",
|
"de_DE": "",
|
||||||
"el_GR": "Έκδοση Συστήματος: {0}",
|
"el_GR": "",
|
||||||
"en_US": "System Version: {0}",
|
"en_US": "Firmware Version: {0}",
|
||||||
"es_ES": "Versión del sistema: {0}",
|
"es_ES": "",
|
||||||
"fr_FR": "Version du Firmware: {0}",
|
"fr_FR": "Version du Firmware: {0}",
|
||||||
"he_IL": "גרסת מערכת: {0}",
|
"he_IL": "",
|
||||||
"it_IT": "Versione di sistema: {0}",
|
"it_IT": "",
|
||||||
"ja_JP": "システムバージョン: {0}",
|
"ja_JP": "",
|
||||||
"ko_KR": "시스템 버전 : {0}",
|
"ko_KR": "",
|
||||||
"no_NO": "System versjon: {0}",
|
"no_NO": "",
|
||||||
"pl_PL": "Wersja systemu: {0}",
|
"pl_PL": "",
|
||||||
"pt_BR": "Versão do firmware: {0}",
|
"pt_BR": "Versão do firmware: {0}",
|
||||||
"ru_RU": "Версия прошивки: {0}",
|
"ru_RU": "Версия прошивки: {0}",
|
||||||
"th_TH": "เวอร์ชั่นของระบบ: {0}",
|
"th_TH": "",
|
||||||
"tr_TR": "Sistem Sürümü: {0}",
|
"tr_TR": "",
|
||||||
"uk_UA": "Версія системи: {0}",
|
"uk_UA": "",
|
||||||
"zh_CN": "系统固件版本:{0}",
|
"zh_CN": "系统固件版本:{0}",
|
||||||
"zh_TW": "系統版本: {0}"
|
"zh_TW": ""
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -3765,6 +3837,30 @@
|
|||||||
"zh_TW": "系統時鐘:"
|
"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",
|
"ID": "SettingsTabSystemEnablePptc",
|
||||||
"Translations": {
|
"Translations": {
|
||||||
@ -8049,7 +8145,7 @@
|
|||||||
"he_IL": "",
|
"he_IL": "",
|
||||||
"it_IT": "",
|
"it_IT": "",
|
||||||
"ja_JP": "",
|
"ja_JP": "",
|
||||||
"ko_KR": "지우기",
|
"ko_KR": "",
|
||||||
"no_NO": "Tøm",
|
"no_NO": "Tøm",
|
||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "",
|
"pt_BR": "",
|
||||||
@ -11841,7 +11937,7 @@
|
|||||||
"he_IL": "",
|
"he_IL": "",
|
||||||
"it_IT": "",
|
"it_IT": "",
|
||||||
"ja_JP": "",
|
"ja_JP": "",
|
||||||
"ko_KR": "",
|
"ko_KR": "{0} : {1}",
|
||||||
"no_NO": "",
|
"no_NO": "",
|
||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "",
|
"pt_BR": "",
|
||||||
@ -14541,6 +14637,30 @@
|
|||||||
"zh_TW": "變更系統時鐘"
|
"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",
|
"ID": "VSyncToggleTooltip",
|
||||||
"Translations": {
|
"Translations": {
|
||||||
@ -16125,30 +16245,6 @@
|
|||||||
"zh_TW": "CPU 模式"
|
"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",
|
"ID": "UpdaterDisabledWarningTitle",
|
||||||
"Translations": {
|
"Translations": {
|
||||||
@ -18753,7 +18849,7 @@
|
|||||||
"he_IL": "",
|
"he_IL": "",
|
||||||
"it_IT": "",
|
"it_IT": "",
|
||||||
"ja_JP": "",
|
"ja_JP": "",
|
||||||
"ko_KR": "",
|
"ko_KR": "{0:n0}MB",
|
||||||
"no_NO": "",
|
"no_NO": "",
|
||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "",
|
"pt_BR": "",
|
||||||
@ -19041,7 +19137,7 @@
|
|||||||
"he_IL": "{0} הרחבות משחק",
|
"he_IL": "{0} הרחבות משחק",
|
||||||
"it_IT": "",
|
"it_IT": "",
|
||||||
"ja_JP": "",
|
"ja_JP": "",
|
||||||
"ko_KR": "",
|
"ko_KR": "{0} DLC 사용 가능",
|
||||||
"no_NO": "{0} Nedlastbare innhold(er)",
|
"no_NO": "{0} Nedlastbare innhold(er)",
|
||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "",
|
"pt_BR": "",
|
||||||
@ -21177,7 +21273,7 @@
|
|||||||
"he_IL": "",
|
"he_IL": "",
|
||||||
"it_IT": "",
|
"it_IT": "",
|
||||||
"ja_JP": "",
|
"ja_JP": "",
|
||||||
"ko_KR": "",
|
"ko_KR": "수직 동기화 :",
|
||||||
"no_NO": "",
|
"no_NO": "",
|
||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "",
|
"pt_BR": "",
|
||||||
@ -21201,7 +21297,7 @@
|
|||||||
"he_IL": "",
|
"he_IL": "",
|
||||||
"it_IT": "",
|
"it_IT": "",
|
||||||
"ja_JP": "",
|
"ja_JP": "",
|
||||||
"ko_KR": "",
|
"ko_KR": "사용자 정의 주사율 활성화(실험적)",
|
||||||
"no_NO": "",
|
"no_NO": "",
|
||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "",
|
"pt_BR": "",
|
||||||
@ -21225,7 +21321,7 @@
|
|||||||
"he_IL": "",
|
"he_IL": "",
|
||||||
"it_IT": "",
|
"it_IT": "",
|
||||||
"ja_JP": "",
|
"ja_JP": "",
|
||||||
"ko_KR": "",
|
"ko_KR": "스위치",
|
||||||
"no_NO": "",
|
"no_NO": "",
|
||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "",
|
"pt_BR": "",
|
||||||
@ -21249,7 +21345,7 @@
|
|||||||
"he_IL": "",
|
"he_IL": "",
|
||||||
"it_IT": "",
|
"it_IT": "",
|
||||||
"ja_JP": "",
|
"ja_JP": "",
|
||||||
"ko_KR": "",
|
"ko_KR": "무제한",
|
||||||
"no_NO": "",
|
"no_NO": "",
|
||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "",
|
"pt_BR": "",
|
||||||
@ -21273,7 +21369,7 @@
|
|||||||
"he_IL": "",
|
"he_IL": "",
|
||||||
"it_IT": "",
|
"it_IT": "",
|
||||||
"ja_JP": "",
|
"ja_JP": "",
|
||||||
"ko_KR": "",
|
"ko_KR": "사용자 정의 주사율",
|
||||||
"no_NO": "",
|
"no_NO": "",
|
||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "",
|
"pt_BR": "",
|
||||||
@ -21297,7 +21393,7 @@
|
|||||||
"he_IL": "",
|
"he_IL": "",
|
||||||
"it_IT": "",
|
"it_IT": "",
|
||||||
"ja_JP": "",
|
"ja_JP": "",
|
||||||
"ko_KR": "",
|
"ko_KR": "에뮬레이트된 수직 동기화. '스위치'는 스위치의 60Hz 주사율을 에뮬레이트합니다. '무한'은 무제한 주사율입니다.",
|
||||||
"no_NO": "",
|
"no_NO": "",
|
||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "",
|
"pt_BR": "",
|
||||||
@ -21321,7 +21417,7 @@
|
|||||||
"he_IL": "",
|
"he_IL": "",
|
||||||
"it_IT": "",
|
"it_IT": "",
|
||||||
"ja_JP": "",
|
"ja_JP": "",
|
||||||
"ko_KR": "",
|
"ko_KR": "에뮬레이트된 수직 동기화. '스위치'는 스위치의 60Hz 주사율을 에뮬레이트합니다. '무한'은 무제한 주사율입니다. '사용자 지정'은 지정된 사용자 지정 주사율을 에뮬레이트합니다.",
|
||||||
"no_NO": "",
|
"no_NO": "",
|
||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "",
|
"pt_BR": "",
|
||||||
@ -21345,7 +21441,7 @@
|
|||||||
"he_IL": "",
|
"he_IL": "",
|
||||||
"it_IT": "",
|
"it_IT": "",
|
||||||
"ja_JP": "",
|
"ja_JP": "",
|
||||||
"ko_KR": "",
|
"ko_KR": "사용자가 에뮬레이트된 화면 주사율을 지정할 수 있습니다. 일부 타이틀에서는 게임플레이 로직 속도가 빨라지거나 느려질 수 있습니다. 다른 타이틀에서는 주사율의 배수로 FPS를 제한하거나 예측할 수 없는 동작으로 이어질 수 있습니다. 이는 실험적 기능으로 게임 플레이에 어떤 영향을 미칠지 보장할 수 없습니다. \n\n모르면 끔으로 두세요.",
|
||||||
"no_NO": "",
|
"no_NO": "",
|
||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "",
|
"pt_BR": "",
|
||||||
@ -21369,7 +21465,7 @@
|
|||||||
"he_IL": "",
|
"he_IL": "",
|
||||||
"it_IT": "",
|
"it_IT": "",
|
||||||
"ja_JP": "",
|
"ja_JP": "",
|
||||||
"ko_KR": "",
|
"ko_KR": "사용자 정의 주사율 목표 값입니다.",
|
||||||
"no_NO": "",
|
"no_NO": "",
|
||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "",
|
"pt_BR": "",
|
||||||
@ -21393,7 +21489,7 @@
|
|||||||
"he_IL": "",
|
"he_IL": "",
|
||||||
"it_IT": "",
|
"it_IT": "",
|
||||||
"ja_JP": "",
|
"ja_JP": "",
|
||||||
"ko_KR": "",
|
"ko_KR": "일반 스위치 주사율의 백분율로 나타낸 사용자 지정 주사율입니다.",
|
||||||
"no_NO": "",
|
"no_NO": "",
|
||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "",
|
"pt_BR": "",
|
||||||
@ -21417,7 +21513,7 @@
|
|||||||
"he_IL": "",
|
"he_IL": "",
|
||||||
"it_IT": "",
|
"it_IT": "",
|
||||||
"ja_JP": "",
|
"ja_JP": "",
|
||||||
"ko_KR": "",
|
"ko_KR": "사용자 정의 주사율 % :",
|
||||||
"no_NO": "",
|
"no_NO": "",
|
||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "",
|
"pt_BR": "",
|
||||||
@ -21441,7 +21537,7 @@
|
|||||||
"he_IL": "",
|
"he_IL": "",
|
||||||
"it_IT": "",
|
"it_IT": "",
|
||||||
"ja_JP": "",
|
"ja_JP": "",
|
||||||
"ko_KR": "",
|
"ko_KR": "사용자 정의 주사율 값 :",
|
||||||
"no_NO": "",
|
"no_NO": "",
|
||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "",
|
"pt_BR": "",
|
||||||
@ -21465,7 +21561,7 @@
|
|||||||
"he_IL": "",
|
"he_IL": "",
|
||||||
"it_IT": "",
|
"it_IT": "",
|
||||||
"ja_JP": "",
|
"ja_JP": "",
|
||||||
"ko_KR": "",
|
"ko_KR": "간격",
|
||||||
"no_NO": "",
|
"no_NO": "",
|
||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "",
|
"pt_BR": "",
|
||||||
@ -21489,7 +21585,7 @@
|
|||||||
"he_IL": "",
|
"he_IL": "",
|
||||||
"it_IT": "",
|
"it_IT": "",
|
||||||
"ja_JP": "",
|
"ja_JP": "",
|
||||||
"ko_KR": "",
|
"ko_KR": "수직 동기화 모드 전환 :",
|
||||||
"no_NO": "",
|
"no_NO": "",
|
||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "",
|
"pt_BR": "",
|
||||||
@ -21513,7 +21609,7 @@
|
|||||||
"he_IL": "",
|
"he_IL": "",
|
||||||
"it_IT": "",
|
"it_IT": "",
|
||||||
"ja_JP": "",
|
"ja_JP": "",
|
||||||
"ko_KR": "",
|
"ko_KR": "사용자 정의 주사율 증가",
|
||||||
"no_NO": "",
|
"no_NO": "",
|
||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "",
|
"pt_BR": "",
|
||||||
@ -21537,7 +21633,7 @@
|
|||||||
"he_IL": "",
|
"he_IL": "",
|
||||||
"it_IT": "",
|
"it_IT": "",
|
||||||
"ja_JP": "",
|
"ja_JP": "",
|
||||||
"ko_KR": "",
|
"ko_KR": "사용자 정의 주사율 감소",
|
||||||
"no_NO": "",
|
"no_NO": "",
|
||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "",
|
"pt_BR": "",
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
using Gommon;
|
||||||
using Ryujinx.Ava.UI.ViewModels;
|
using Ryujinx.Ava.UI.ViewModels;
|
||||||
using Ryujinx.Common;
|
using Ryujinx.Common;
|
||||||
using Ryujinx.Common.Logging;
|
using Ryujinx.Common.Logging;
|
||||||
@ -7,12 +8,7 @@ using System;
|
|||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Globalization;
|
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.Json.Serialization;
|
||||||
using System.Text.Unicode;
|
|
||||||
|
|
||||||
namespace Ryujinx.Ava.Common.Locale
|
namespace Ryujinx.Ava.Common.Locale
|
||||||
{
|
{
|
||||||
@ -147,39 +143,33 @@ namespace Ryujinx.Ava.Common.Locale
|
|||||||
LocaleChanged?.Invoke();
|
LocaleChanged?.Invoke();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#nullable enable
|
||||||
|
|
||||||
|
private static LocalesJson? _localeData;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
private static Dictionary<LocaleKeys, string> LoadJsonLanguage(string languageCode)
|
private static Dictionary<LocaleKeys, string> LoadJsonLanguage(string languageCode)
|
||||||
{
|
{
|
||||||
var localeStrings = new Dictionary<LocaleKeys, string>();
|
var localeStrings = new Dictionary<LocaleKeys, string>();
|
||||||
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.
|
if (locale.Translations.Count != _localeData.Value.Languages.Count)
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
LocalesJson json = JsonHelper.Deserialize(fileData, LocalesJsonContext.Default.LocalesJson);
|
|
||||||
|
|
||||||
foreach (LocalesEntry locale in json.Locales)
|
|
||||||
{
|
|
||||||
if (locale.Translations.Count != json.Languages.Count)
|
|
||||||
{
|
{
|
||||||
Logger.Error?.Print(LogClass.UI, $"Locale key {{{locale.ID}}} is missing languages!");
|
throw new Exception($"Locale key {{{locale.ID}}} is missing languages! Has {locale.Translations.Count} translations, expected {_localeData.Value.Languages.Count}!");
|
||||||
throw new Exception("Missing locale data!");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Enum.TryParse<LocaleKeys>(locale.ID, out var localeKey))
|
if (!Enum.TryParse<LocaleKeys>(locale.ID, out var localeKey))
|
||||||
{
|
continue;
|
||||||
if (locale.Translations.TryGetValue(languageCode, out string val) && val != "")
|
|
||||||
{
|
localeStrings[localeKey] =
|
||||||
localeStrings[localeKey] = val;
|
locale.Translations.TryGetValue(languageCode, out string val) && val != string.Empty
|
||||||
}
|
? val
|
||||||
else
|
: locale.Translations[DefaultLanguageCode];
|
||||||
{
|
|
||||||
locale.Translations.TryGetValue("en_US", out val);
|
|
||||||
localeStrings[localeKey] = val;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return localeStrings;
|
return localeStrings;
|
||||||
@ -200,5 +190,5 @@ namespace Ryujinx.Ava.Common.Locale
|
|||||||
|
|
||||||
[JsonSourceGenerationOptions(WriteIndented = true)]
|
[JsonSourceGenerationOptions(WriteIndented = true)]
|
||||||
[JsonSerializable(typeof(LocalesJson))]
|
[JsonSerializable(typeof(LocalesJson))]
|
||||||
internal partial class LocalesJsonContext : JsonSerializerContext { }
|
internal partial class LocalesJsonContext : JsonSerializerContext;
|
||||||
}
|
}
|
||||||
|
@ -17,7 +17,6 @@
|
|||||||
<MenuItem
|
<MenuItem
|
||||||
Click="CreateApplicationShortcut_Click"
|
Click="CreateApplicationShortcut_Click"
|
||||||
Header="{ext:Locale GameListContextMenuCreateShortcut}"
|
Header="{ext:Locale GameListContextMenuCreateShortcut}"
|
||||||
IsEnabled="{Binding CreateShortcutEnabled}"
|
|
||||||
Icon="{ext:Icon fa-solid fa-bookmark}"
|
Icon="{ext:Icon fa-solid fa-bookmark}"
|
||||||
ToolTip.Tip="{OnPlatform Default={ext:Locale GameListContextMenuCreateShortcutToolTip}, macOS={ext:Locale GameListContextMenuCreateShortcutToolTipMacOS}}" />
|
ToolTip.Tip="{OnPlatform Default={ext:Locale GameListContextMenuCreateShortcutToolTip}, macOS={ext:Locale GameListContextMenuCreateShortcutToolTipMacOS}}" />
|
||||||
<Separator />
|
<Separator />
|
||||||
|
@ -97,7 +97,7 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
|
|||||||
{
|
{
|
||||||
if (IsModified)
|
if (IsModified)
|
||||||
{
|
{
|
||||||
|
|
||||||
_playerIdChoose = value;
|
_playerIdChoose = value;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -105,7 +105,7 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
|
|||||||
IsModified = false;
|
IsModified = false;
|
||||||
_playerId = value;
|
_playerId = value;
|
||||||
|
|
||||||
if (!Enum.IsDefined(typeof(PlayerIndex), _playerId))
|
if (!Enum.IsDefined<PlayerIndex>(_playerId))
|
||||||
{
|
{
|
||||||
_playerId = PlayerIndex.Player1;
|
_playerId = PlayerIndex.Player1;
|
||||||
|
|
||||||
|
@ -127,6 +127,9 @@ namespace Ryujinx.Ava.UI.ViewModels
|
|||||||
|
|
||||||
public IEnumerable<LdnGameData> LastLdnGameData;
|
public IEnumerable<LdnGameData> 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 =
|
public static readonly Bitmap IconBitmap =
|
||||||
new(Assembly.GetAssembly(typeof(ConfigurationState))!.GetManifestResourceStream("Ryujinx.UI.Common.Resources.Logo_Thiccjinx.png")!);
|
new(Assembly.GetAssembly(typeof(ConfigurationState))!.GetManifestResourceStream("Ryujinx.UI.Common.Resources.Logo_Thiccjinx.png")!);
|
||||||
|
|
||||||
@ -330,6 +333,9 @@ namespace Ryujinx.Ava.UI.ViewModels
|
|||||||
OnPropertyChanged();
|
OnPropertyChanged();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool CanScanAmiiboBinaries => AmiiboBinReader.HasAmiiboKeyFile;
|
||||||
|
|
||||||
public bool ShowLoadProgress
|
public bool ShowLoadProgress
|
||||||
{
|
{
|
||||||
get => _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 OpenBcatSaveDirectoryEnabled => !SelectedApplication.ControlHolder.ByteSpan.IsZeros() && SelectedApplication.ControlHolder.Value.BcatDeliveryCacheStorageSize > 0;
|
||||||
|
|
||||||
public bool CreateShortcutEnabled => !ReleaseInformation.IsFlatHubBuild;
|
|
||||||
|
|
||||||
public string LoadHeading
|
public string LoadHeading
|
||||||
{
|
{
|
||||||
get => _loadHeading;
|
get => _loadHeading;
|
||||||
@ -2009,7 +2013,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.StatusBarSystemVersion, "0.0");
|
LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.StatusBarSystemVersion, "NaN");
|
||||||
}
|
}
|
||||||
|
|
||||||
IsAppletMenuActive = hasApplet;
|
IsAppletMenuActive = hasApplet;
|
||||||
|
@ -330,6 +330,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
|||||||
}
|
}
|
||||||
|
|
||||||
public DateTimeOffset CurrentDate { get; set; }
|
public DateTimeOffset CurrentDate { get; set; }
|
||||||
|
|
||||||
public TimeSpan CurrentTime { get; set; }
|
public TimeSpan CurrentTime { get; set; }
|
||||||
|
|
||||||
internal AvaloniaList<TimeZone> TimeZones { get; set; }
|
internal AvaloniaList<TimeZone> TimeZones { get; set; }
|
||||||
@ -453,6 +454,18 @@ namespace Ryujinx.Ava.UI.ViewModels
|
|||||||
Dispatcher.UIThread.Post(() => OnPropertyChanged(nameof(PreferredGpuIndex)));
|
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()
|
public async Task LoadTimeZones()
|
||||||
{
|
{
|
||||||
_timeZoneContentManager = new TimeZoneContentManager();
|
_timeZoneContentManager = new TimeZoneContentManager();
|
||||||
|
@ -247,6 +247,7 @@
|
|||||||
Click="OpenBinFile"
|
Click="OpenBinFile"
|
||||||
Header="{ext:Locale MenuBarActionsScanAmiiboBin}"
|
Header="{ext:Locale MenuBarActionsScanAmiiboBin}"
|
||||||
Icon="{ext:Icon mdi-cube-scan}"
|
Icon="{ext:Icon mdi-cube-scan}"
|
||||||
|
IsVisible="{Binding CanScanAmiiboBinaries}"
|
||||||
IsEnabled="{Binding IsAmiiboBinRequested}" />
|
IsEnabled="{Binding IsAmiiboBinRequested}" />
|
||||||
<MenuItem
|
<MenuItem
|
||||||
Command="{Binding TakeScreenshot}"
|
Command="{Binding TakeScreenshot}"
|
||||||
@ -286,9 +287,16 @@
|
|||||||
<MenuItem VerticalAlignment="Center" Header="{ext:Locale MenuBarViewWindow}">
|
<MenuItem VerticalAlignment="Center" Header="{ext:Locale MenuBarViewWindow}">
|
||||||
<MenuItem Header="{ext:Locale MenuBarViewWindow720}" Tag="1280 720" Click="ChangeWindowSize_Click" />
|
<MenuItem Header="{ext:Locale MenuBarViewWindow720}" Tag="1280 720" Click="ChangeWindowSize_Click" />
|
||||||
<MenuItem Header="{ext:Locale MenuBarViewWindow1080}" Tag="1920 1080" Click="ChangeWindowSize_Click" />
|
<MenuItem Header="{ext:Locale MenuBarViewWindow1080}" Tag="1920 1080" Click="ChangeWindowSize_Click" />
|
||||||
|
<MenuItem Header="{ext:Locale MenuBarViewWindow1440}" Tag="2560 1440" Click="ChangeWindowSize_Click" />
|
||||||
|
<MenuItem Header="{ext:Locale MenuBarViewWindow2160}" Tag="3840 2160" Click="ChangeWindowSize_Click" />
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
<MenuItem VerticalAlignment="Center" Header="{ext:Locale MenuBarHelp}">
|
<MenuItem VerticalAlignment="Center" Header="{ext:Locale MenuBarHelp}">
|
||||||
|
<MenuItem
|
||||||
|
Click="OpenAboutWindow"
|
||||||
|
Header="{ext:Locale MenuBarHelpAbout}"
|
||||||
|
Icon="{ext:Icon fa-solid fa-circle-info}"
|
||||||
|
ToolTip.Tip="{ext:Locale OpenAboutTooltip}" />
|
||||||
<MenuItem
|
<MenuItem
|
||||||
Name="UpdateMenuItem"
|
Name="UpdateMenuItem"
|
||||||
IsEnabled="{Binding CanUpdate}"
|
IsEnabled="{Binding CanUpdate}"
|
||||||
@ -297,30 +305,26 @@
|
|||||||
Icon="{ext:Icon mdi-update}"
|
Icon="{ext:Icon mdi-update}"
|
||||||
ToolTip.Tip="{ext:Locale CheckUpdatesTooltip}" />
|
ToolTip.Tip="{ext:Locale CheckUpdatesTooltip}" />
|
||||||
<Separator />
|
<Separator />
|
||||||
<MenuItem
|
<MenuItem VerticalAlignment="Center" Header="{ext:Locale MenuBarHelpFaqAndGuides}" Icon="{ext:Icon fa-solid fa-question}" >
|
||||||
Click="MenuItem_OnClick"
|
<MenuItem
|
||||||
Header="{ext:Locale MenuBarHelpFaq}"
|
Click="MenuItem_OnClick"
|
||||||
Icon="{ext:Icon fa-github}"
|
Header="{ext:Locale MenuBarHelpFaq}"
|
||||||
Tag="https://github.com/GreemDev/Ryujinx/wiki/FAQ-and-Troubleshooting"
|
Icon="{ext:Icon fa-github}"
|
||||||
ToolTip.Tip="{ext:Locale MenuBarHelpFaqTooltip}" />
|
Tag="https://github.com/GreemDev/Ryujinx/wiki/FAQ-and-Troubleshooting"
|
||||||
<MenuItem
|
ToolTip.Tip="{ext:Locale MenuBarHelpFaqTooltip}" />
|
||||||
Click="MenuItem_OnClick"
|
<MenuItem
|
||||||
Header="{ext:Locale MenuBarHelpSetup}"
|
Click="MenuItem_OnClick"
|
||||||
Icon="{ext:Icon fa-github}"
|
Header="{ext:Locale MenuBarHelpSetup}"
|
||||||
Tag="https://github.com/GreemDev/Ryujinx/wiki/Ryujinx-Setup-&-Configuration-Guide"
|
Icon="{ext:Icon fa-github}"
|
||||||
ToolTip.Tip="{ext:Locale MenuBarHelpSetupTooltip}" />
|
Tag="https://github.com/GreemDev/Ryujinx/wiki/Ryujinx-Setup-&-Configuration-Guide"
|
||||||
<MenuItem
|
ToolTip.Tip="{ext:Locale MenuBarHelpSetupTooltip}" />
|
||||||
Click="MenuItem_OnClick"
|
<MenuItem
|
||||||
Header="{ext:Locale MenuBarHelpMultiplayer}"
|
Click="MenuItem_OnClick"
|
||||||
Icon="{ext:Icon fa-github}"
|
Header="{ext:Locale MenuBarHelpMultiplayer}"
|
||||||
Tag="https://github.com/GreemDev/Ryujinx/wiki/Multiplayer%E2%80%90(LDN%E2%80%90Local%E2%80%90Wireless)%E2%80%90Guide"
|
Icon="{ext:Icon fa-github}"
|
||||||
ToolTip.Tip="{ext:Locale MenuBarHelpMultiplayerTooltip}" />
|
Tag="https://github.com/GreemDev/Ryujinx/wiki/Multiplayer%E2%80%90(LDN%E2%80%90Local%E2%80%90Wireless)%E2%80%90Guide"
|
||||||
<Separator />
|
ToolTip.Tip="{ext:Locale MenuBarHelpMultiplayerTooltip}" />
|
||||||
<MenuItem
|
</MenuItem>
|
||||||
Click="OpenAboutWindow"
|
|
||||||
Header="{ext:Locale MenuBarHelpAbout}"
|
|
||||||
Icon="{ext:Icon fa-solid fa-circle-info}"
|
|
||||||
ToolTip.Tip="{ext:Locale OpenAboutTooltip}" />
|
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
</Menu>
|
</Menu>
|
||||||
</DockPanel>
|
</DockPanel>
|
||||||
|
@ -178,7 +178,7 @@ namespace Ryujinx.Ava.UI.Views.Main
|
|||||||
private void ScanBinAmiiboMenuItem_AttachedToVisualTree(object sender, VisualTreeAttachmentEventArgs e)
|
private void ScanBinAmiiboMenuItem_AttachedToVisualTree(object sender, VisualTreeAttachmentEventArgs e)
|
||||||
{
|
{
|
||||||
if (sender is MenuItem)
|
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)
|
private async void InstallFileTypes_Click(object sender, RoutedEventArgs e)
|
||||||
|
@ -52,7 +52,7 @@ namespace Ryujinx.Ava.UI.Views.Main
|
|||||||
private void AspectRatioStatus_OnClick(object sender, RoutedEventArgs e)
|
private void AspectRatioStatus_OnClick(object sender, RoutedEventArgs e)
|
||||||
{
|
{
|
||||||
AspectRatio aspectRatio = ConfigurationState.Instance.Graphics.AspectRatio.Value;
|
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<AspectRatio>().Length - 1 ? AspectRatio.Fixed4x3 : aspectRatio + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Refresh_OnClick(object sender, RoutedEventArgs e) => Window.LoadApplications();
|
private void Refresh_OnClick(object sender, RoutedEventArgs e) => Window.LoadApplications();
|
||||||
|
@ -181,8 +181,17 @@
|
|||||||
SelectedTime="{Binding CurrentTime}"
|
SelectedTime="{Binding CurrentTime}"
|
||||||
Width="350"
|
Width="350"
|
||||||
ToolTip.Tip="{ext:Locale TimeTooltip}" />
|
ToolTip.Tip="{ext:Locale TimeTooltip}" />
|
||||||
|
<Button
|
||||||
|
Margin="10, 0, 0, 0"
|
||||||
|
VerticalAlignment="Center"
|
||||||
|
Click="MatchSystemTime_OnClick"
|
||||||
|
Background="{DynamicResource SystemAccentColor}"
|
||||||
|
ToolTip.Tip="{ext:Locale MatchTimeTooltip}">
|
||||||
|
<TextBlock Text="{ext:Locale SettingsTabSystemSystemTimeMatch}" />
|
||||||
|
</Button>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
<StackPanel Margin="0,0,0,10"
|
<Separator />
|
||||||
|
<StackPanel Margin="0,10,0,10"
|
||||||
Orientation="Horizontal">
|
Orientation="Horizontal">
|
||||||
<TextBlock
|
<TextBlock
|
||||||
VerticalAlignment="Center"
|
VerticalAlignment="Center"
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
|
using Avalonia;
|
||||||
using Avalonia.Controls;
|
using Avalonia.Controls;
|
||||||
|
using Avalonia.Interactivity;
|
||||||
using Ryujinx.Ava.UI.ViewModels;
|
using Ryujinx.Ava.UI.ViewModels;
|
||||||
using TimeZone = Ryujinx.Ava.UI.Models.TimeZone;
|
using TimeZone = Ryujinx.Ava.UI.Models.TimeZone;
|
||||||
|
|
||||||
@ -33,5 +35,7 @@ namespace Ryujinx.Ava.UI.Views.Settings
|
|||||||
ViewModel.ValidateAndSetTimeZone(timeZone.Location);
|
ViewModel.ValidateAndSetTimeZone(timeZone.Location);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void MatchSystemTime_OnClick(object sender, RoutedEventArgs e) => ViewModel.MatchSystemTime();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -686,22 +686,11 @@ namespace Ryujinx.Ava
|
|||||||
#else
|
#else
|
||||||
if (showWarnings)
|
if (showWarnings)
|
||||||
{
|
{
|
||||||
if (ReleaseInformation.IsFlatHubBuild)
|
Dispatcher.UIThread.InvokeAsync(() =>
|
||||||
{
|
ContentDialogHelper.CreateWarningDialog(
|
||||||
Dispatcher.UIThread.InvokeAsync(() =>
|
LocaleManager.Instance[LocaleKeys.UpdaterDisabledWarningTitle],
|
||||||
ContentDialogHelper.CreateWarningDialog(
|
LocaleManager.Instance[LocaleKeys.DialogUpdaterDirtyBuildSubMessage])
|
||||||
LocaleManager.Instance[LocaleKeys.UpdaterDisabledWarningTitle],
|
|
||||||
LocaleManager.Instance[LocaleKeys.DialogUpdaterFlatpakNotSupportedMessage])
|
|
||||||
);
|
);
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Dispatcher.UIThread.InvokeAsync(() =>
|
|
||||||
ContentDialogHelper.CreateWarningDialog(
|
|
||||||
LocaleManager.Instance[LocaleKeys.UpdaterDisabledWarningTitle],
|
|
||||||
LocaleManager.Instance[LocaleKeys.DialogUpdaterDirtyBuildSubMessage])
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user