From 053a9cb5499b175bbec6f5fd277d2dbd98087bc3 Mon Sep 17 00:00:00 2001
From: LotP <22-lotp@users.noreply.git.ryujinx.app>
Date: Tue, 3 Jun 2025 23:20:55 -0500
Subject: [PATCH 01/57] fix: use accurate length for enumerating
See merge request ryubing/ryujinx!49
---
src/ARMeilleure/Translation/PTC/Ptc.cs | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/ARMeilleure/Translation/PTC/Ptc.cs b/src/ARMeilleure/Translation/PTC/Ptc.cs
index eb0a609f2..f36d4256d 100644
--- a/src/ARMeilleure/Translation/PTC/Ptc.cs
+++ b/src/ARMeilleure/Translation/PTC/Ptc.cs
@@ -193,7 +193,7 @@ namespace ARMeilleure.Translation.PTC
_infosStream.Seek(0L, SeekOrigin.Begin);
bool foundBadFunction = false;
- for (int index = 0; index < GetEntriesCount(); index++)
+ for (int index = 0; index < _infosStream.Length / Unsafe.SizeOf(); index++)
{
InfoEntry infoEntry = DeserializeStructure(_infosStream);
foreach (ulong address in blacklist)
From 051c794cc4865fc800b9e7f0c4f41b105bb4981a Mon Sep 17 00:00:00 2001
From: TheToid
Date: Tue, 3 Jun 2025 23:26:49 -0500
Subject: [PATCH 02/57] Use rcodesign for dylib signing where avaiilable and
clear out all "._" files...
See merge request ryubing/ryujinx!14
---
distribution/macos/create_app_bundle.sh | 16 +++++++++++-----
distribution/macos/create_macos_build_ava.sh | 12 ++++++++++++
.../macos/create_macos_build_headless.sh | 12 ++++++++++++
3 files changed, 35 insertions(+), 5 deletions(-)
diff --git a/distribution/macos/create_app_bundle.sh b/distribution/macos/create_app_bundle.sh
index cbe930d2d..0b4ab8e04 100755
--- a/distribution/macos/create_app_bundle.sh
+++ b/distribution/macos/create_app_bundle.sh
@@ -33,23 +33,29 @@ echo -n "APPL????" > "$APP_BUNDLE_DIRECTORY/Contents/PkgInfo"
echo "Running bundle fix up python script"
python3 bundle_fix_up.py "$APP_BUNDLE_DIRECTORY" MacOS/Ryujinx
-# Resign all dyplib files as ad-hoc after changing them
-find "$APP_BUNDLE_DIRECTORY/Contents/Frameworks" -type f -name "*.dylib" -exec codesign --force --sign - {} \;
-
# Now sign it
echo "Starting signing process"
if ! [ -x "$(command -v codesign)" ];
then
if ! [ -x "$(command -v rcodesign)" ];
then
- echo "Cannot find rcodesign on your system, please install rcodesign."
+ echo "Cannot find rcodesign on your system, please install rcodesign and ensure it is in your search path."
exit 1
fi
- # cargo install apple-codesign
echo "Using rcodesign for ad-hoc signing"
+
+ echo "Resigning all frameworks dylib files as ad-hoc"
+ find "$APP_BUNDLE_DIRECTORY/Contents/Frameworks" -type f -name "*.dylib" -exec rcodesign sign {} \;
+
+ echo "Signing app bundle as ad-hoc"
rcodesign sign --entitlements-xml-path "$ENTITLEMENTS_FILE_PATH" "$APP_BUNDLE_DIRECTORY"
else
echo "Using codesign for ad-hoc signing"
+
+ echo "Resigning all frameworks dylib files as ad-hoc"
+ find "$APP_BUNDLE_DIRECTORY/Contents/Frameworks" -type f -name "*.dylib" -exec codesign --force --sign - {} \;
+
+ echo "Signing app bundle as ad-hoc"
codesign --entitlements "$ENTITLEMENTS_FILE_PATH" -f -s - "$APP_BUNDLE_DIRECTORY"
fi
diff --git a/distribution/macos/create_macos_build_ava.sh b/distribution/macos/create_macos_build_ava.sh
index de6fab358..028486f51 100755
--- a/distribution/macos/create_macos_build_ava.sh
+++ b/distribution/macos/create_macos_build_ava.sh
@@ -20,6 +20,18 @@ SOURCE_REVISION_ID=$6
CONFIGURATION=$7
CANARY=$8
+if [[ "$(uname)" == "Darwin" ]]; then
+ echo "Clearing xattr on all dot undercsore files"
+ find "$BASE_DIR" -type f -name "._*" -exec sh -c '
+ for f; do
+ dir=$(dirname "$f")
+ base=$(basename "$f")
+ orig="$dir/${base#._}"
+ [ -f "$orig" ] && xattr -c "$orig" || true
+ done
+ ' sh {} +
+fi
+
if [ "$CANARY" == "1" ]; then
RELEASE_TAR_FILE_NAME=ryujinx-canary-$VERSION-macos_universal.app.tar
elif [ "$VERSION" == "1.1.0" ]; then
diff --git a/distribution/macos/create_macos_build_headless.sh b/distribution/macos/create_macos_build_headless.sh
index 5de862a2f..6052b202c 100755
--- a/distribution/macos/create_macos_build_headless.sh
+++ b/distribution/macos/create_macos_build_headless.sh
@@ -20,6 +20,18 @@ SOURCE_REVISION_ID=$6
CONFIGURATION=$7
CANARY=$8
+if [[ "$(uname)" == "Darwin" ]]; then
+ echo "Clearing xattr on all dot undercsore files"
+ find "$BASE_DIR" -type f -name "._*" -exec sh -c '
+ for f; do
+ dir=$(dirname "$f")
+ base=$(basename "$f")
+ orig="$dir/${base#._}"
+ [ -f "$orig" ] && xattr -c "$orig" || true
+ done
+ ' sh {} +
+fi
+
if [ "$CANARY" == "1" ]; then
RELEASE_TAR_FILE_NAME=nogui-ryujinx-canary-$VERSION-macos_universal.tar
elif [ "$VERSION" == "1.1.0" ]; then
From 0e84f2b1f0dd6991e02e7d5386d45c262aceee93 Mon Sep 17 00:00:00 2001
From: GreemDev
Date: Wed, 4 Jun 2025 04:31:41 -0500
Subject: [PATCH 03/57] infra: Send a Discord webhook message when a new build
is available
---
.github/workflows/canary.yml | 4 ++++
.github/workflows/release.yml | 4 ++++
2 files changed, 8 insertions(+)
diff --git a/.github/workflows/canary.yml b/.github/workflows/canary.yml
index b0678724a..211843ee2 100644
--- a/.github/workflows/canary.yml
+++ b/.github/workflows/canary.yml
@@ -333,3 +333,7 @@ jobs:
- name: Create release
run: |
gli --access-token=${{ secrets.GITLAB_TOKEN }} --project=ryubing/canary --command=CreateReleaseFromGenericPackageFiles "Ryubing-Canary|${{ steps.version_info.outputs.build_version }}|main|Canary ${{ steps.version_info.outputs.build_version }}|**[Full Changelog](https://git.ryujinx.app/ryubing/ryujinx/-/compare/Canary-${{ steps.version_info.outputs.prev_build_version }}...Canary-${{ steps.version_info.outputs.build_version }})**"
+
+ - name: Send notification webhook
+ run: |
+ gli --access-token=${{ secrets.GITLAB_TOKEN }} --project=ryubing/canary --command=SendUpdateMessage "${{ steps.version_info.outputs.build_version }}|FF4500|${{ secrets.CANARY_DISCORD_WEBHOOK }}|https://avatars.githubusercontent.com/u/192939710?s=200&v=4"
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index 4c443b969..7c7a2a9a4 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -295,3 +295,7 @@ jobs:
- name: Create release
run: |
gli --access-token=${{ secrets.GITLAB_TOKEN }} --project=ryubing/ryujinx --command=CreateReleaseFromGenericPackageFiles "Ryubing|${{ steps.version_info.outputs.build_version }}|${{ steps.version_info.outputs.git_short_hash }}|${{ steps.version_info.outputs.build_version }}|**[Full Changelog](https://git.ryujinx.app/ryubing/ryujinx/-/compare/${{ steps.version_info.outputs.prev_build_version }}...${{ steps.version_info.outputs.build_version }})**"
+
+ - name: Send notification webhook
+ run: |
+ gli --access-token=${{ secrets.GITLAB_TOKEN }} --project=ryubing/ryujinx --command=SendUpdateMessage "${{ steps.version_info.outputs.build_version }}|32cd32|${{ secrets.STABLE_DISCORD_WEBHOOK }}|https://avatars.githubusercontent.com/u/192939710?s=200&v=4|false"
From 3950e8adff3eac45d4a64ac82aefea8daedb8969 Mon Sep 17 00:00:00 2001
From: GreemDev
Date: Wed, 4 Jun 2025 21:05:35 -0500
Subject: [PATCH 04/57] infra: Embed milestone description in stable release
description in CI
---
.github/workflows/release.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index 7c7a2a9a4..361e72f09 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -294,7 +294,7 @@ jobs:
- name: Create release
run: |
- gli --access-token=${{ secrets.GITLAB_TOKEN }} --project=ryubing/ryujinx --command=CreateReleaseFromGenericPackageFiles "Ryubing|${{ steps.version_info.outputs.build_version }}|${{ steps.version_info.outputs.git_short_hash }}|${{ steps.version_info.outputs.build_version }}|**[Full Changelog](https://git.ryujinx.app/ryubing/ryujinx/-/compare/${{ steps.version_info.outputs.prev_build_version }}...${{ steps.version_info.outputs.build_version }})**"
+ gli --access-token=${{ secrets.GITLAB_TOKEN }} --project=ryubing/ryujinx --command=CreateReleaseFromGenericPackageFiles "Ryubing|${{ steps.version_info.outputs.build_version }}|${{ steps.version_info.outputs.git_short_hash }}|${{ steps.version_info.outputs.build_version }}|msd:${{ steps.version_info.outputs.build_version }}"
- name: Send notification webhook
run: |
From f2aea4fb225f8b818d4c502eff821cce0627e442 Mon Sep 17 00:00:00 2001
From: GreemDev
Date: Wed, 4 Jun 2025 21:05:54 -0500
Subject: [PATCH 05/57] misc: [ci skip] fix typo in comment & rename
CheckForUpdateAsync
---
src/Ryujinx/Systems/Updater/Updater.GitHub.cs | 2 +-
src/Ryujinx/Systems/Updater/Updater.GitLab.cs | 2 +-
src/Ryujinx/Systems/Updater/Updater.cs | 4 ++--
src/Ryujinx/UI/Windows/MainWindow.axaml.cs | 2 +-
4 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/src/Ryujinx/Systems/Updater/Updater.GitHub.cs b/src/Ryujinx/Systems/Updater/Updater.GitHub.cs
index 9d67e5351..e90610e66 100644
--- a/src/Ryujinx/Systems/Updater/Updater.GitHub.cs
+++ b/src/Ryujinx/Systems/Updater/Updater.GitHub.cs
@@ -88,7 +88,7 @@ namespace Ryujinx.Ava.Systems
}
}
- // If build not done, assume no new update are available.
+ // If build not done, assume no new update is available.
if (_buildUrl is null)
{
if (showVersionUpToDate)
diff --git a/src/Ryujinx/Systems/Updater/Updater.GitLab.cs b/src/Ryujinx/Systems/Updater/Updater.GitLab.cs
index cd3a3f411..7291ebc16 100644
--- a/src/Ryujinx/Systems/Updater/Updater.GitLab.cs
+++ b/src/Ryujinx/Systems/Updater/Updater.GitLab.cs
@@ -65,7 +65,7 @@ namespace Ryujinx.Ava.Systems
link.AssetName.StartsWith("ryujinx") && link.AssetName.EndsWith(_platformExt)
)?.Url;
- // If build URL not found, assume no new update are available.
+ // If build URL not found, assume no new update is available.
if (_buildUrl is null)
{
if (showVersionUpToDate)
diff --git a/src/Ryujinx/Systems/Updater/Updater.cs b/src/Ryujinx/Systems/Updater/Updater.cs
index c4e8a8cc6..59f94e61a 100644
--- a/src/Ryujinx/Systems/Updater/Updater.cs
+++ b/src/Ryujinx/Systems/Updater/Updater.cs
@@ -55,7 +55,7 @@ namespace Ryujinx.Ava.Systems
private static string _changelogUrlFormat = null;
- public static async Task> CheckForUpdateAsync(bool showVersionUpToDate = false)
+ public static async Task> CheckVersionAsync(bool showVersionUpToDate = false)
{
Optional<(Version, Version)> versionTuple;
@@ -83,7 +83,7 @@ namespace Ryujinx.Ava.Systems
_running = true;
- Optional<(Version, Version)> versionTuple = await CheckForUpdateAsync(showVersionUpToDate);
+ Optional<(Version, Version)> versionTuple = await CheckVersionAsync(showVersionUpToDate);
if (_running is false || !versionTuple.HasValue)
return;
diff --git a/src/Ryujinx/UI/Windows/MainWindow.axaml.cs b/src/Ryujinx/UI/Windows/MainWindow.axaml.cs
index 23a3f26f9..a2d7ff657 100644
--- a/src/Ryujinx/UI/Windows/MainWindow.axaml.cs
+++ b/src/Ryujinx/UI/Windows/MainWindow.axaml.cs
@@ -419,7 +419,7 @@ namespace Ryujinx.Ava.UI.Windows
.Catch(task => Logger.Error?.Print(LogClass.Application, $"Updater Error: {task.Exception}"));
break;
case UpdaterType.CheckInBackground:
- if ((await Updater.CheckForUpdateAsync()).TryGet(out (Version Current, Version Incoming) versions))
+ if ((await Updater.CheckVersionAsync()).TryGet(out (Version Current, Version Incoming) versions))
{
Dispatcher.UIThread.Post(() => RyujinxApp.MainWindow.ViewModel.UpdateAvailable = versions.Current < versions.Incoming);
}
From 0652d7e7402b5d32ada8c276912f818ba7195364 Mon Sep 17 00:00:00 2001
From: GreemDev
Date: Wed, 4 Jun 2025 23:18:44 -0500
Subject: [PATCH 06/57] misc: readme: stable and canary release channels from
gitlab
---
README.md | 14 +++++++-------
1 file changed, 7 insertions(+), 7 deletions(-)
diff --git a/README.md b/README.md
index a02a100e8..a9e04ccf6 100644
--- a/README.md
+++ b/README.md
@@ -7,8 +7,8 @@
# Ryujinx
-[](https://github.com/Ryubing/Stable-Releases/releases/latest)
-[](https://github.com/Ryubing/Canary-Releases/releases/latest)
+[](https://git.ryujinx.app/ryubing/ryujinx/-/releases)
+[](https://git.ryujinx.app/ryubing/canary/-/releases)
@@ -31,7 +31,7 @@
This is not a Ryujinx revival project. This is not a Phoenix project.
- Guides and documentation can be found on the Wiki tab.
+ Guides and documentation can be found on the Wiki tab.
@@ -49,13 +49,13 @@ Stable builds are made every so often, based on the `master` branch, that then g
These stable builds exist so that the end user can get a more **enjoyable and stable experience**.
They are released every month or so, to ensure consistent updates, while not being an annoying amount of individual updates to download over the course of that month.
-You can find the latest stable release [here](https://github.com/Ryubing/Stable-Releases/releases/latest).
+You can find the stable releases [here](https://git.ryujinx.app/ryubing/ryujinx/-/releases).
Canary builds are compiled automatically for each commit on the `master` branch.
While we strive to ensure optimal stability and performance prior to pushing an update, these builds **may be unstable or completely broken**.
These canary builds are only recommended for experienced users.
-You can find the latest canary release [here](https://github.com/Ryubing/Canary-Releases/releases/latest).
+You can find the canary releases [here](https://git.ryujinx.app/ryubing/canary/-/releases).
## Documentation
@@ -111,7 +111,7 @@ See [LICENSE.txt](LICENSE.txt) and [THIRDPARTY.md](distribution/legal/THIRDPARTY
## Credits
-- [LibHac](https://github.com/Thealexbarney/LibHac) is used for our file-system.
+- [LibHac](https://git.ryujinx.app/ryubing/libhac) is used for our file-system.
- [AmiiboAPI](https://www.amiiboapi.com) is used in our Amiibo emulation.
- [ldn_mitm](https://github.com/spacemeowx2/ldn_mitm) is used for one of our available multiplayer modes.
-- [ShellLink](https://github.com/securifybv/ShellLink) is used for Windows shortcut generation.
+- [ShellLink](https://github.com/securifybv/ShellLink) is used for Windows shortcut generation.
\ No newline at end of file
From 04561a0cd3447b535e72a22e6afa6f5ec691dc69 Mon Sep 17 00:00:00 2001
From: KeatonTheBot
Date: Thu, 5 Jun 2025 01:19:44 -0500
Subject: [PATCH 07/57] Vulkan: Use compute shader for non-indirect unsupported
topology index buffer conversions
See merge request ryubing/ryujinx!5
---
src/Ryujinx.Graphics.Vulkan/HelperShader.cs | 66 ++++++++-----------
.../IndexBufferPattern.cs | 22 -------
2 files changed, 27 insertions(+), 61 deletions(-)
diff --git a/src/Ryujinx.Graphics.Vulkan/HelperShader.cs b/src/Ryujinx.Graphics.Vulkan/HelperShader.cs
index 194179410..695046198 100644
--- a/src/Ryujinx.Graphics.Vulkan/HelperShader.cs
+++ b/src/Ryujinx.Graphics.Vulkan/HelperShader.cs
@@ -874,57 +874,42 @@ namespace Ryujinx.Graphics.Vulkan
public unsafe void ConvertIndexBuffer(VulkanRenderer gd,
CommandBufferScoped cbs,
- BufferHolder src,
- BufferHolder dst,
+ BufferHolder srcIndexBuffer,
+ BufferHolder dstIndexBuffer,
IndexBufferPattern pattern,
int indexSize,
int srcOffset,
int indexCount)
{
// TODO: Support conversion with primitive restart enabled.
- // TODO: Convert with a compute shader?
+ int primitiveCount = pattern.GetPrimitiveCount(indexCount);
int convertedCount = pattern.GetConvertedCount(indexCount);
int outputIndexSize = 4;
+
+ Buffer dstBuffer = dstIndexBuffer.GetBuffer().Get(cbs, 0, convertedCount * outputIndexSize).Value;
- Buffer srcBuffer = src.GetBuffer().Get(cbs, srcOffset, indexCount * indexSize).Value;
- Buffer dstBuffer = dst.GetBuffer().Get(cbs, 0, convertedCount * outputIndexSize).Value;
+ const int ParamsBufferSize = 16 * sizeof(int);
- gd.Api.CmdFillBuffer(cbs.CommandBuffer, dstBuffer, 0, Vk.WholeSize, 0);
+ Span shaderParams = stackalloc int[ParamsBufferSize / sizeof(int)];
- List bufferCopy = [];
- int outputOffset = 0;
+ shaderParams[8] = pattern.PrimitiveVertices;
+ shaderParams[9] = pattern.PrimitiveVerticesOut;
+ shaderParams[10] = indexSize;
+ shaderParams[11] = outputIndexSize;
+ shaderParams[12] = pattern.BaseIndex;
+ shaderParams[13] = pattern.IndexStride;
+ shaderParams[14] = srcOffset;
+ shaderParams[15] = primitiveCount;
- // Try to merge copies of adjacent indices to reduce copy count.
- int sequenceStart = 0;
- int sequenceLength = 0;
+ pattern.OffsetIndex.CopyTo(shaderParams[..pattern.OffsetIndex.Length]);
- foreach (int index in pattern.GetIndexMapping(indexCount))
- {
- if (sequenceLength > 0)
- {
- if (index == sequenceStart + sequenceLength && indexSize == outputIndexSize)
- {
- sequenceLength++;
- continue;
- }
+ using var patternScoped = gd.BufferManager.ReserveOrCreate(gd, cbs, ParamsBufferSize);
+ var patternBuffer = patternScoped.Holder;
- // Commit the copy so far.
- bufferCopy.Add(new BufferCopy((ulong)(srcOffset + sequenceStart * indexSize), (ulong)outputOffset, (ulong)(indexSize * sequenceLength)));
- outputOffset += outputIndexSize * sequenceLength;
- }
+ patternBuffer.SetDataUnchecked(patternScoped.Offset, shaderParams);
- sequenceStart = index;
- sequenceLength = 1;
- }
-
- if (sequenceLength > 0)
- {
- // Commit final pending copy.
- bufferCopy.Add(new BufferCopy((ulong)(srcOffset + sequenceStart * indexSize), (ulong)outputOffset, (ulong)(indexSize * sequenceLength)));
- }
-
- BufferCopy[] bufferCopyArray = bufferCopy.ToArray();
+ _pipeline.SetCommandBuffer(cbs);
BufferHolder.InsertBufferBarrier(
gd,
@@ -937,10 +922,11 @@ namespace Ryujinx.Graphics.Vulkan
0,
convertedCount * outputIndexSize);
- fixed (BufferCopy* pBufferCopy = bufferCopyArray)
- {
- gd.Api.CmdCopyBuffer(cbs.CommandBuffer, srcBuffer, dstBuffer, (uint)bufferCopyArray.Length, pBufferCopy);
- }
+ _pipeline.SetUniformBuffers([new BufferAssignment(0, new BufferRange(patternScoped.Handle, patternScoped.Offset, ParamsBufferSize))]);
+ _pipeline.SetStorageBuffers(1, new[] { srcIndexBuffer.GetBuffer(), dstIndexBuffer.GetBuffer() });
+
+ _pipeline.SetProgram(_programConvertIndexBuffer);
+ _pipeline.DispatchCompute(BitUtils.DivRoundUp(primitiveCount, 16), 1, 1);
BufferHolder.InsertBufferBarrier(
gd,
@@ -952,6 +938,8 @@ namespace Ryujinx.Graphics.Vulkan
PipelineStageFlags.AllCommandsBit,
0,
convertedCount * outputIndexSize);
+
+ _pipeline.Finish(gd, cbs);
}
public void CopyIncompatibleFormats(
diff --git a/src/Ryujinx.Graphics.Vulkan/IndexBufferPattern.cs b/src/Ryujinx.Graphics.Vulkan/IndexBufferPattern.cs
index 7b01dd4ca..9054b2e71 100644
--- a/src/Ryujinx.Graphics.Vulkan/IndexBufferPattern.cs
+++ b/src/Ryujinx.Graphics.Vulkan/IndexBufferPattern.cs
@@ -47,28 +47,6 @@ namespace Ryujinx.Graphics.Vulkan
return primitiveCount * OffsetIndex.Length;
}
- public IEnumerable GetIndexMapping(int indexCount)
- {
- int primitiveCount = GetPrimitiveCount(indexCount);
- int index = BaseIndex;
-
- for (int i = 0; i < primitiveCount; i++)
- {
- if (RepeatStart)
- {
- // Used for triangle fan
- yield return 0;
- }
-
- for (int j = RepeatStart ? 1 : 0; j < OffsetIndex.Length; j++)
- {
- yield return index + OffsetIndex[j];
- }
-
- index += IndexStride;
- }
- }
-
public BufferHandle GetRepeatingBuffer(int vertexCount, out int indexCount)
{
int primitiveCount = GetPrimitiveCount(vertexCount);
From 13e404bde03e8e8df8e51b61654536a07b9fe07b Mon Sep 17 00:00:00 2001
From: GreemDev
Date: Thu, 5 Jun 2025 01:57:09 -0500
Subject: [PATCH 08/57] infra: [ci skip] Move tag creation to the end of the
build process in CI
---
.github/workflows/canary.yml | 17 ++++-------------
1 file changed, 4 insertions(+), 13 deletions(-)
diff --git a/.github/workflows/canary.yml b/.github/workflows/canary.yml
index 211843ee2..7930515e3 100644
--- a/.github/workflows/canary.yml
+++ b/.github/workflows/canary.yml
@@ -34,19 +34,6 @@ jobs:
echo "build_version=${{ env.RYUJINX_BASE_VERSION }}.${{ github.run_number }}" >> $GITHUB_OUTPUT
echo "prev_build_version=${{ env.RYUJINX_BASE_VERSION }}.$((${{ github.run_number }} - 1))" >> $GITHUB_OUTPUT
shell: bash
-
- - name: Install GitLabCli
- run: |
- mkdir -p $HOME/.bin
- gh release download -R GreemDev/GLI -O gli -p 'GitLabCli-linux_x64'
- chmod +x gli
- mv gli $HOME/.bin/
- echo "$HOME/.bin" >> $GITHUB_PATH
- env:
- GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
-
- - name: Create GitLab tag
- run: gli --access-token=${{ secrets.GITLAB_TOKEN }} --project=ryubing/ryujinx --command=CreateTag "Canary-${{ steps.version_info.outputs.build_version }}|master"
- name: Create release
uses: ncipollo/release-action@v1
@@ -330,6 +317,10 @@ jobs:
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ - name: Create tag
+ run: |
+ gli --access-token=${{ secrets.GITLAB_TOKEN }} --project=ryubing/ryujinx --command=CreateTag "Canary-${{ steps.version_info.outputs.build_version }}|${{ steps.version_info.outputs.git_short_hash }}"
+
- name: Create release
run: |
gli --access-token=${{ secrets.GITLAB_TOKEN }} --project=ryubing/canary --command=CreateReleaseFromGenericPackageFiles "Ryubing-Canary|${{ steps.version_info.outputs.build_version }}|main|Canary ${{ steps.version_info.outputs.build_version }}|**[Full Changelog](https://git.ryujinx.app/ryubing/ryujinx/-/compare/Canary-${{ steps.version_info.outputs.prev_build_version }}...Canary-${{ steps.version_info.outputs.build_version }})**"
From 1e861b99a9ee0c7907194b9e7d397d5d1d8f0be4 Mon Sep 17 00:00:00 2001
From: GreemDev
Date: Thu, 5 Jun 2025 20:45:35 -0500
Subject: [PATCH 09/57] misc: Update LibHac
See merge request ryubing/libhac!3
---
Directory.Packages.props | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Directory.Packages.props b/Directory.Packages.props
index 68d5b1f27..450b86287 100644
--- a/Directory.Packages.props
+++ b/Directory.Packages.props
@@ -40,7 +40,7 @@
-
+
From 70abff072bc2994654231e3479997593d6bd12d9 Mon Sep 17 00:00:00 2001
From: GreemDev
Date: Thu, 5 Jun 2025 20:56:17 -0500
Subject: [PATCH 10/57] canary CI: checkout code before trying to get current
revision
---
.github/workflows/canary.yml | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/.github/workflows/canary.yml b/.github/workflows/canary.yml
index 7930515e3..86b17a542 100644
--- a/.github/workflows/canary.yml
+++ b/.github/workflows/canary.yml
@@ -299,6 +299,9 @@ jobs:
- macos_release
- release
steps:
+ - uses: actions/checkout@v4
+
+
- name: Get version info
id: version_info
run: |
@@ -327,4 +330,4 @@ jobs:
- name: Send notification webhook
run: |
- gli --access-token=${{ secrets.GITLAB_TOKEN }} --project=ryubing/canary --command=SendUpdateMessage "${{ steps.version_info.outputs.build_version }}|FF4500|${{ secrets.CANARY_DISCORD_WEBHOOK }}|https://avatars.githubusercontent.com/u/192939710?s=200&v=4"
+ gli --access-token=${{ secrets.GITLAB_TOKEN }} --project=ryubing/canary --command=SendUpdateMessage "${{ steps.version_info.outputs.build_version }}|FF4500|${{ secrets.CANARY_DISCORD_WEBHOOK }}|https://avatars.githubusercontent.com/u/192939710?s=200&v=4|false"
From 693837dca784ff59107d2ed983bd38d149c094fc Mon Sep 17 00:00:00 2001
From: GreemDev
Date: Thu, 5 Jun 2025 23:07:02 -0500
Subject: [PATCH 11/57] infra: [ci skip] make the canary release notes look
nicer
---
.github/workflows/canary.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.github/workflows/canary.yml b/.github/workflows/canary.yml
index 86b17a542..21d3c782e 100644
--- a/.github/workflows/canary.yml
+++ b/.github/workflows/canary.yml
@@ -326,7 +326,7 @@ jobs:
- name: Create release
run: |
- gli --access-token=${{ secrets.GITLAB_TOKEN }} --project=ryubing/canary --command=CreateReleaseFromGenericPackageFiles "Ryubing-Canary|${{ steps.version_info.outputs.build_version }}|main|Canary ${{ steps.version_info.outputs.build_version }}|**[Full Changelog](https://git.ryujinx.app/ryubing/ryujinx/-/compare/Canary-${{ steps.version_info.outputs.prev_build_version }}...Canary-${{ steps.version_info.outputs.build_version }})**"
+ gli --access-token=${{ secrets.GITLAB_TOKEN }} --project=ryubing/canary --command=CreateReleaseFromGenericPackageFiles "Ryubing-Canary|${{ steps.version_info.outputs.build_version }}|main|Canary ${{ steps.version_info.outputs.build_version }}|**Full Changelog:** [`${{ steps.version_info.outputs.prev_build_version }}...${{ steps.version_info.outputs.build_version }}`](https://git.ryujinx.app/ryubing/ryujinx/-/compare/Canary-${{ steps.version_info.outputs.prev_build_version }}...Canary-${{ steps.version_info.outputs.build_version }})"
- name: Send notification webhook
run: |
From b761a2c86d63a04f66fd131c4ff37fe9ad61abed Mon Sep 17 00:00:00 2001
From: GreemDev
Date: Sun, 8 Jun 2025 17:37:34 -0500
Subject: [PATCH 12/57] infra: Custom Update server instead of direct GitLab
API calls
This reduces the amount of requests for an update from 3 if an update is needed, or 2 if not; to 1 if an update is needed, and none if an update is not. The difference comes from using this update server to check if an update is needed, and not GETing a snippet content for the release channels.
---
.../GitLab/GitLabReleaseAssetJsonResponse.cs | 20 ----
.../GitLab/GitLabReleasesJsonResponse.cs | 19 ---
src/Ryujinx/Systems/Updater/Updater.GitLab.cs | 108 ++++++++++--------
src/Ryujinx/Systems/Updater/Updater.cs | 10 +-
4 files changed, 60 insertions(+), 97 deletions(-)
delete mode 100644 src/Ryujinx/Common/Models/GitLab/GitLabReleaseAssetJsonResponse.cs
delete mode 100644 src/Ryujinx/Common/Models/GitLab/GitLabReleasesJsonResponse.cs
diff --git a/src/Ryujinx/Common/Models/GitLab/GitLabReleaseAssetJsonResponse.cs b/src/Ryujinx/Common/Models/GitLab/GitLabReleaseAssetJsonResponse.cs
deleted file mode 100644
index a5b4bb619..000000000
--- a/src/Ryujinx/Common/Models/GitLab/GitLabReleaseAssetJsonResponse.cs
+++ /dev/null
@@ -1,20 +0,0 @@
-using System.Text.Json.Serialization;
-
-namespace Ryujinx.Ava.Common.Models.GitLab
-{
- public class GitLabReleaseAssetJsonResponse
- {
- [JsonPropertyName("links")]
- public GitLabReleaseAssetLinkJsonResponse[] Links { get; set; }
-
- public class GitLabReleaseAssetLinkJsonResponse
- {
- [JsonPropertyName("id")]
- public long Id { get; set; }
- [JsonPropertyName("name")]
- public string AssetName { get; set; }
- [JsonPropertyName("url")]
- public string Url { get; set; }
- }
- }
-}
diff --git a/src/Ryujinx/Common/Models/GitLab/GitLabReleasesJsonResponse.cs b/src/Ryujinx/Common/Models/GitLab/GitLabReleasesJsonResponse.cs
deleted file mode 100644
index 8d229a5f1..000000000
--- a/src/Ryujinx/Common/Models/GitLab/GitLabReleasesJsonResponse.cs
+++ /dev/null
@@ -1,19 +0,0 @@
-using System.Text.Json.Serialization;
-
-namespace Ryujinx.Ava.Common.Models.GitLab
-{
- public class GitLabReleasesJsonResponse
- {
- [JsonPropertyName("name")]
- public string Name { get; set; }
-
- [JsonPropertyName("tag_name")]
- public string TagName { get; set; }
-
- [JsonPropertyName("assets")]
- public GitLabReleaseAssetJsonResponse Assets { get; set; }
- }
-
- [JsonSerializable(typeof(GitLabReleasesJsonResponse), GenerationMode = JsonSourceGenerationMode.Metadata)]
- public partial class GitLabReleasesJsonSerializerContext : JsonSerializerContext;
-}
diff --git a/src/Ryujinx/Systems/Updater/Updater.GitLab.cs b/src/Ryujinx/Systems/Updater/Updater.GitLab.cs
index 7291ebc16..96afc7fc9 100644
--- a/src/Ryujinx/Systems/Updater/Updater.GitLab.cs
+++ b/src/Ryujinx/Systems/Updater/Updater.GitLab.cs
@@ -1,15 +1,13 @@
using Gommon;
using Ryujinx.Ava.Common.Locale;
-using Ryujinx.Ava.Common.Models.GitLab;
using Ryujinx.Ava.UI.Helpers;
using Ryujinx.Common;
using Ryujinx.Common.Helper;
using Ryujinx.Common.Logging;
-using Ryujinx.Common.Utilities;
using System;
-using System.Linq;
using System.Net.Http;
using System.Net.Http.Json;
+using System.Runtime.InteropServices;
using System.Text.Json.Serialization;
using System.Threading.Tasks;
@@ -17,7 +15,31 @@ namespace Ryujinx.Ava.Systems
{
internal static partial class Updater
{
- private static GitLabReleaseChannels.ChannelType _currentGitLabReleaseChannel;
+ private static string CreateUpdateQueryUrl()
+ {
+#pragma warning disable CS8524
+ var os = RunningPlatform.CurrentOS switch
+#pragma warning restore CS8524
+ {
+ OperatingSystemType.MacOS => "mac",
+ OperatingSystemType.Linux => "linux",
+ OperatingSystemType.Windows => "win"
+ };
+
+ var arch = RunningPlatform.Architecture switch
+ {
+ Architecture.Arm64 => "arm",
+ Architecture.X64 => "amd64",
+ _ => null
+ };
+
+ if (arch is null)
+ return null;
+
+ var rc = ReleaseInformation.IsCanaryBuild ? "canary" : "stable";
+
+ return $"https://update.ryujinx.app/latest/query?os={os}&arch={arch}&rc={rc}";
+ }
private static async Task> CheckGitLabVersionAsync(bool showVersionUpToDate = false)
{
@@ -35,38 +57,42 @@ namespace Ryujinx.Ava.Systems
return default;
}
- Logger.Info?.Print(LogClass.Application, "Checking for updates from https://git.ryujinx.app.");
+ if (CreateUpdateQueryUrl() is not {} updateUrl)
+ {
+ Logger.Error?.Print(LogClass.Application, "Could not determine URL for updates.");
+
+ _running = false;
+
+ return default;
+ }
+
+ Logger.Info?.Print(LogClass.Application, $"Checking for updates from {updateUrl}.");
// Get latest version number from GitLab API
using HttpClient jsonClient = ConstructHttpClient();
// GitLab instance is located in Ukraine. Connection times will vary across the world.
- jsonClient.Timeout = TimeSpan.FromSeconds(10);
+ jsonClient.Timeout = TimeSpan.FromSeconds(10);
- if (_currentGitLabReleaseChannel == null)
+ try
{
- GitLabReleaseChannels releaseChannels = await GitLabReleaseChannels.GetAsync(jsonClient);
+ UpdaterResponse response =
+ await jsonClient.GetFromJsonAsync(updateUrl, UpdaterResponseJsonContext.Default.UpdaterResponse);
- _currentGitLabReleaseChannel = ReleaseInformation.IsCanaryBuild
- ? releaseChannels.Canary
- : releaseChannels.Stable;
+ _buildVer = response.Tag;
+ _buildUrl = response.DownloadUrl;
+ _changelogUrlFormat = response.ReleaseUrlFormat;
+ }
+ catch (Exception e)
+ {
+ Logger.Error?.Print(LogClass.Application, $"An error occurred when parsing JSON response from API ({e.GetType().AsFullNamePrettyString()}): {e.Message}");
- Logger.Info?.Print(LogClass.Application, $"Loaded GitLab release channel for '{(ReleaseInformation.IsCanaryBuild ? "canary" : "stable")}'");
-
- _changelogUrlFormat = _currentGitLabReleaseChannel.UrlFormat;
+ _running = false;
+ return default;
}
- string fetchedJson = await jsonClient.GetStringAsync(_currentGitLabReleaseChannel.GetLatestReleaseApiUrl());
- GitLabReleasesJsonResponse fetched = JsonHelper.Deserialize(fetchedJson, _glSerializerContext.GitLabReleasesJsonResponse);
-
- _buildVer = fetched.TagName;
- _buildUrl = fetched.Assets.Links
- .FirstOrDefault(link =>
- link.AssetName.StartsWith("ryujinx") && link.AssetName.EndsWith(_platformExt)
- )?.Url;
-
// If build URL not found, assume no new update is available.
- if (_buildUrl is null)
+ if (_buildUrl is null or "")
{
if (showVersionUpToDate)
{
@@ -104,35 +130,17 @@ namespace Ryujinx.Ava.Systems
return (currentVersion, newVersion);
}
+
+ [JsonSerializable(typeof(UpdaterResponse))]
+ partial class UpdaterResponseJsonContext : JsonSerializerContext;
- [JsonSerializable(typeof(GitLabReleaseChannels))]
- partial class GitLabReleaseChannelPairContext : JsonSerializerContext;
-
- public class GitLabReleaseChannels
+ public class UpdaterResponse
{
- public static async Task GetAsync(HttpClient httpClient)
- => await httpClient.GetFromJsonAsync(
- "https://git.ryujinx.app/ryubing/ryujinx/-/snippets/1/raw/main/meta.json",
- GitLabReleaseChannelPairContext.Default.GitLabReleaseChannels);
+ [JsonPropertyName("tag")] public string Tag { get; set; }
+ [JsonPropertyName("download_url")] public string DownloadUrl { get; set; }
+ [JsonPropertyName("web_url")] public string ReleaseUrl { get; set; }
- [JsonPropertyName("stable")] public ChannelType Stable { get; set; }
- [JsonPropertyName("canary")] public ChannelType Canary { get; set; }
-
- public class ChannelType
- {
- [JsonPropertyName("id")] public long Id { get; set; }
-
- [JsonPropertyName("group")] public string Group { get; set; }
-
- [JsonPropertyName("project")] public string Project { get; set; }
-
- public string UrlFormat => $"https://git.ryujinx.app/{ToString()}/-/releases/{{0}}";
-
- public override string ToString() => $"{Group}/{Project}";
-
- public string GetLatestReleaseApiUrl() =>
- $"https://git.ryujinx.app/api/v4/projects/{Id}/releases/permalink/latest";
- }
+ [JsonIgnore] public string ReleaseUrlFormat => ReleaseUrl.Replace(Tag, "{0}");
}
}
}
diff --git a/src/Ryujinx/Systems/Updater/Updater.cs b/src/Ryujinx/Systems/Updater/Updater.cs
index 59f94e61a..f4d49a1d1 100644
--- a/src/Ryujinx/Systems/Updater/Updater.cs
+++ b/src/Ryujinx/Systems/Updater/Updater.cs
@@ -6,7 +6,6 @@ using ICSharpCode.SharpZipLib.Tar;
using ICSharpCode.SharpZipLib.Zip;
using Ryujinx.Ava.Common.Locale;
using Ryujinx.Ava.Common.Models.Github;
-using Ryujinx.Ava.Common.Models.GitLab;
using Ryujinx.Ava.UI.Helpers;
using Ryujinx.Ava.Utilities;
using Ryujinx.Common;
@@ -33,19 +32,14 @@ namespace Ryujinx.Ava.Systems
internal static partial class Updater
{
private static readonly GithubReleasesJsonSerializerContext _ghSerializerContext = new(JsonHelper.GetDefaultSerializerOptions());
- private static readonly GitLabReleasesJsonSerializerContext _glSerializerContext = new(JsonHelper.GetDefaultSerializerOptions());
-
+ private static readonly string _platformExt = BuildPlatformExtension();
private static readonly string _homeDir = AppDomain.CurrentDomain.BaseDirectory;
private static readonly string _updateDir = Path.Combine(Path.GetTempPath(), "Ryujinx", "update");
private static readonly string _updatePublishDir = Path.Combine(_updateDir, "publish");
private const int ConnectionCount = 4;
private static string _buildVer;
-
-
- private static readonly string _platformExt = BuildPlatformExtension();
-
private static string _buildUrl;
private static long _buildSize;
private static bool _updateSuccessful;
@@ -168,7 +162,7 @@ namespace Ryujinx.Ava.Systems
HttpClient result = new();
// Required by GitHub to interact with APIs.
- result.DefaultRequestHeaders.Add("User-Agent", "Ryujinx-Updater/1.0.0");
+ result.DefaultRequestHeaders.Add("User-Agent", $"Ryujinx-Updater/{ReleaseInformation.Version}");
return result;
}
From 8feeb977b74e829935d1296b239fa9a1fe84a546 Mon Sep 17 00:00:00 2001
From: GreemDev
Date: Sun, 8 Jun 2025 17:47:45 -0500
Subject: [PATCH 13/57] infra: [ci skip] fix canary changelog generation
---
.github/workflows/canary.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.github/workflows/canary.yml b/.github/workflows/canary.yml
index 21d3c782e..0defe9e8e 100644
--- a/.github/workflows/canary.yml
+++ b/.github/workflows/canary.yml
@@ -326,7 +326,7 @@ jobs:
- name: Create release
run: |
- gli --access-token=${{ secrets.GITLAB_TOKEN }} --project=ryubing/canary --command=CreateReleaseFromGenericPackageFiles "Ryubing-Canary|${{ steps.version_info.outputs.build_version }}|main|Canary ${{ steps.version_info.outputs.build_version }}|**Full Changelog:** [`${{ steps.version_info.outputs.prev_build_version }}...${{ steps.version_info.outputs.build_version }}`](https://git.ryujinx.app/ryubing/ryujinx/-/compare/Canary-${{ steps.version_info.outputs.prev_build_version }}...Canary-${{ steps.version_info.outputs.build_version }})"
+ gli --access-token=${{ secrets.GITLAB_TOKEN }} --project=ryubing/canary --command=CreateReleaseFromGenericPackageFiles "Ryubing-Canary|${{ steps.version_info.outputs.build_version }}|main|Canary ${{ steps.version_info.outputs.build_version }}|**Full Changelog:** [${{ steps.version_info.outputs.prev_build_version }}...${{ steps.version_info.outputs.build_version }}](https://git.ryujinx.app/ryubing/ryujinx/-/compare/Canary-${{ steps.version_info.outputs.prev_build_version }}...Canary-${{ steps.version_info.outputs.build_version }})"
- name: Send notification webhook
run: |
From b37aa61e475d9fe85a315d90aeccf536d5613d42 Mon Sep 17 00:00:00 2001
From: GreemDev
Date: Sun, 8 Jun 2025 17:55:36 -0500
Subject: [PATCH 14/57] infra: Remove GitHub uploading from Canary CI workflows
---
.github/workflows/canary.yml | 80 +-----------------------------------
1 file changed, 1 insertion(+), 79 deletions(-)
diff --git a/.github/workflows/canary.yml b/.github/workflows/canary.yml
index 0defe9e8e..8b8bca971 100644
--- a/.github/workflows/canary.yml
+++ b/.github/workflows/canary.yml
@@ -24,41 +24,6 @@ env:
RELEASE: 1
jobs:
- tag:
- name: Create tag
- runs-on: ubuntu-24.04
- steps:
- - name: Get version info
- id: version_info
- run: |
- echo "build_version=${{ env.RYUJINX_BASE_VERSION }}.${{ github.run_number }}" >> $GITHUB_OUTPUT
- echo "prev_build_version=${{ env.RYUJINX_BASE_VERSION }}.$((${{ github.run_number }} - 1))" >> $GITHUB_OUTPUT
- shell: bash
-
- - name: Create release
- uses: ncipollo/release-action@v1
- with:
- name: "Canary ${{ steps.version_info.outputs.build_version }}"
- tag: ${{ steps.version_info.outputs.build_version }}
- body: |
- # Canary builds:
-
- These builds are experimental and may sometimes not work, use [regular builds](https://github.com/${{ secrets.RC_OWNER }}/${{ secrets.RC_STABLE_NAME }}/releases/latest) instead if that sounds like something you don't want to deal with.
-
- | Platform | Artifact |
- |--|--|
- | Windows 64-bit | [Canary Windows Artifact](https://github.com/${{ secrets.RC_OWNER }}/${{ secrets.RC_CANARY_NAME }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-canary-${{ steps.version_info.outputs.build_version }}-win_x64.zip) |
- | Windows ARM 64-bit | [Canary Windows ARM Artifact](https://github.com/${{ secrets.RC_OWNER }}/${{ secrets.RC_CANARY_NAME }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-canary-${{ steps.version_info.outputs.build_version }}-win_arm64.zip) |
- | Linux 64-bit | [Canary Linux Artifact](https://github.com/${{ secrets.RC_OWNER }}/${{ secrets.RC_CANARY_NAME }}/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/${{ secrets.RC_OWNER }}/${{ secrets.RC_CANARY_NAME }}/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/${{ secrets.RC_OWNER }}/${{ secrets.RC_CANARY_NAME }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-canary-${{ steps.version_info.outputs.build_version }}-macos_universal.app.tar.gz) |
-
- **[Full Changelog](https://git.ryujinx.app/ryubing/ryujinx/-/compare/Canary-${{ steps.version_info.outputs.prev_build_version }}...Canary-${{ steps.version_info.outputs.build_version }})**
- omitBodyDuringUpdate: true
- owner: ${{ secrets.RC_OWNER }}
- repo: ${{ secrets.RC_CANARY_NAME }}
- token: ${{ secrets.ALT_RELEASE_TOKEN }}
-
release:
name: Release for ${{ matrix.platform.name }}
runs-on: ${{ matrix.platform.os }}
@@ -189,34 +154,7 @@ jobs:
gli --access-token=${{ secrets.GITLAB_TOKEN }} --project=ryubing/canary --command=UploadGenericPackage "Ryubing-Canary|${{ steps.version_info.outputs.build_version }}|release_output/ryujinx-canary-$BUILD_VERSION-$ARCH_NAME.AppImage"
gli --access-token=${{ secrets.GITLAB_TOKEN }} --project=ryubing/canary --command=UploadGenericPackage "Ryubing-Canary|${{ steps.version_info.outputs.build_version }}|release_output/ryujinx-canary-$BUILD_VERSION-$ARCH_NAME.AppImage.zsync"
- shell: bash
-
- - name: Pushing new release
- uses: ncipollo/release-action@v1
- with:
- name: ${{ steps.version_info.outputs.build_version }}
- artifacts: "release_output/*.tar.gz,release_output/*.zip,release_output/*AppImage*"
- tag: ${{ steps.version_info.outputs.build_version }}
- body: |
- # Canary builds:
-
- These builds are experimental and may sometimes not work, use [regular builds](https://github.com/${{ secrets.RC_OWNER }}/${{ secrets.RC_STABLE_NAME }}/releases/latest) instead if that sounds like something you don't want to deal with.
-
- | Platform | Artifact |
- |--|--|
- | Windows 64-bit | [Canary Windows Artifact](https://github.com/${{ secrets.RC_OWNER }}/${{ secrets.RC_CANARY_NAME }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-canary-${{ steps.version_info.outputs.build_version }}-win_x64.zip) |
- | Windows ARM 64-bit | [Canary Windows ARM Artifact](https://github.com/${{ secrets.RC_OWNER }}/${{ secrets.RC_CANARY_NAME }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-canary-${{ steps.version_info.outputs.build_version }}-win_arm64.zip) |
- | Linux 64-bit | [Canary Linux Artifact](https://github.com/${{ secrets.RC_OWNER }}/${{ secrets.RC_CANARY_NAME }}/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/${{ secrets.RC_OWNER }}/${{ secrets.RC_CANARY_NAME }}/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/${{ secrets.RC_OWNER }}/${{ secrets.RC_CANARY_NAME }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-canary-${{ steps.version_info.outputs.build_version }}-macos_universal.app.tar.gz) |
-
- **[Full Changelog](https://git.ryujinx.app/ryubing/ryujinx/-/compare/Canary-${{ steps.version_info.outputs.prev_build_version }}...Canary-${{ steps.version_info.outputs.build_version }})**
- omitBodyDuringUpdate: true
- allowUpdates: true
- replacesArtifacts: true
- owner: ${{ secrets.RC_OWNER }}
- repo: ${{ secrets.RC_CANARY_NAME }}
- token: ${{ secrets.ALT_RELEASE_TOKEN }}
+ shell: bash
macos_release:
name: Release MacOS universal
@@ -277,31 +215,15 @@ jobs:
./distribution/macos/create_macos_build_ava.sh . publish_tmp_ava publish_ava ./distribution/macos/entitlements.xml "${{ steps.version_info.outputs.build_version }}" "${{ steps.version_info.outputs.git_short_hash }}" Release 1
gli --access-token=${{ secrets.GITLAB_TOKEN }} --project=ryubing/canary --command=UploadGenericPackage "Ryubing-Canary|${{ steps.version_info.outputs.build_version }}|publish_ava/ryujinx-canary-${{ steps.version_info.outputs.build_version }}-macos_universal.app.tar.gz"
- - name: Pushing new release
- uses: ncipollo/release-action@v1
- with:
- name: "Canary ${{ steps.version_info.outputs.build_version }}"
- artifacts: "publish_ava/*.tar.gz"
- tag: ${{ steps.version_info.outputs.build_version }}
- body: ""
- omitBodyDuringUpdate: true
- allowUpdates: true
- replacesArtifacts: true
- owner: ${{ secrets.RC_OWNER }}
- repo: ${{ secrets.RC_CANARY_NAME }}
- token: ${{ secrets.ALT_RELEASE_TOKEN }}
-
create_gitlab_release:
name: Create GitLab Release
runs-on: ubuntu-24.04
needs:
- - tag
- macos_release
- release
steps:
- uses: actions/checkout@v4
-
- name: Get version info
id: version_info
run: |
From efa25d471ec03c8c74c5733cb3d425660716f291 Mon Sep 17 00:00:00 2001
From: GreemDev
Date: Sun, 8 Jun 2025 20:41:51 -0500
Subject: [PATCH 15/57] docs: compat: ingame: FANTASY LIFE i: The Girl Who
Steals Time
---
docs/compatibility.csv | 1 +
1 file changed, 1 insertion(+)
diff --git a/docs/compatibility.csv b/docs/compatibility.csv
index 37d350c03..7c4e5d91e 100644
--- a/docs/compatibility.csv
+++ b/docs/compatibility.csv
@@ -1125,6 +1125,7 @@
0100034012606000,"Family Mysteries: Poisonous Promises",audio;crash,menus,2021-11-26 12:35:06
010017C012726000,"Fantasy Friends",,playable,2022-10-17 19:42:39
0100767008502000,"FANTASY HERO ~unsigned legacy~",,playable,2022-07-26 12:28:52
+0100755017EE0000,"FANTASY LIFE i: The Girl Who Steals Time",gpu,ingame,2025-06-08 20:41:00
0100944003820000,"Fantasy Strike",online,playable,2021-02-27 01:59:18
01000E2012F6E000,"Fantasy Tavern Sextet -Vol.1 New World Days-",gpu;crash;Needs Update,ingame,2022-12-05 16:48:00
01005C10136CA000,"Fantasy Tavern Sextet -Vol.2 Adventurer's Days-",gpu;slow;crash,ingame,2021-11-06 02:57:29
From e3fba4e32fbd9f71e8125ae9241237a39dc8c5e6 Mon Sep 17 00:00:00 2001
From: GreemDev
Date: Sun, 8 Jun 2025 20:44:01 -0500
Subject: [PATCH 16/57] docs: compat: further clarify the issue with 'FANTASY
LIFE i: The Girl Who Steals Time' with 'crash' and 'vulkan-backend-bug'
labels.
---
docs/compatibility.csv | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/docs/compatibility.csv b/docs/compatibility.csv
index 7c4e5d91e..684fc7833 100644
--- a/docs/compatibility.csv
+++ b/docs/compatibility.csv
@@ -1125,7 +1125,7 @@
0100034012606000,"Family Mysteries: Poisonous Promises",audio;crash,menus,2021-11-26 12:35:06
010017C012726000,"Fantasy Friends",,playable,2022-10-17 19:42:39
0100767008502000,"FANTASY HERO ~unsigned legacy~",,playable,2022-07-26 12:28:52
-0100755017EE0000,"FANTASY LIFE i: The Girl Who Steals Time",gpu,ingame,2025-06-08 20:41:00
+0100755017EE0000,"FANTASY LIFE i: The Girl Who Steals Time",gpu;crash;vulkan-backend-bug,ingame,2025-06-08 20:41:00
0100944003820000,"Fantasy Strike",online,playable,2021-02-27 01:59:18
01000E2012F6E000,"Fantasy Tavern Sextet -Vol.1 New World Days-",gpu;crash;Needs Update,ingame,2022-12-05 16:48:00
01005C10136CA000,"Fantasy Tavern Sextet -Vol.2 Adventurer's Days-",gpu;slow;crash,ingame,2021-11-06 02:57:29
From b5e9acc50b2a433fc4e66d894f32bc3dee6b568a Mon Sep 17 00:00:00 2001
From: GreemDev
Date: Sun, 8 Jun 2025 21:06:02 -0500
Subject: [PATCH 17/57] misc: [ci skip] Cause GitHub fallback properly
---
src/Ryujinx/Systems/Updater/Updater.GitLab.cs | 7 +++----
1 file changed, 3 insertions(+), 4 deletions(-)
diff --git a/src/Ryujinx/Systems/Updater/Updater.GitLab.cs b/src/Ryujinx/Systems/Updater/Updater.GitLab.cs
index 96afc7fc9..d609af522 100644
--- a/src/Ryujinx/Systems/Updater/Updater.GitLab.cs
+++ b/src/Ryujinx/Systems/Updater/Updater.GitLab.cs
@@ -85,10 +85,9 @@ namespace Ryujinx.Ava.Systems
}
catch (Exception e)
{
- Logger.Error?.Print(LogClass.Application, $"An error occurred when parsing JSON response from API ({e.GetType().AsFullNamePrettyString()}): {e.Message}");
-
- _running = false;
- return default;
+ throw new AggregateException(
+ $"An error occurred when parsing JSON response from API ({e.GetType().AsFullNamePrettyString()}): {e.Message}",
+ e);
}
// If build URL not found, assume no new update is available.
From c95bf748b204f2f54d1613d3011cb4ed304751ab Mon Sep 17 00:00:00 2001
From: GreemDev
Date: Sun, 8 Jun 2025 22:31:32 -0500
Subject: [PATCH 18/57] infra: Update to Ryujinx.LibHac 0.20.0
This is identical to the previous version, it's just on NuGet.org so we can comment out the LibHacAlpha source in nuget.config.
---
Directory.Packages.props | 2 +-
nuget.config | 17 ++---------------
2 files changed, 3 insertions(+), 16 deletions(-)
diff --git a/Directory.Packages.props b/Directory.Packages.props
index 450b86287..ccbcb3f6b 100644
--- a/Directory.Packages.props
+++ b/Directory.Packages.props
@@ -40,7 +40,7 @@
-
+
diff --git a/nuget.config b/nuget.config
index 03523fc63..f24a44b48 100644
--- a/nuget.config
+++ b/nuget.config
@@ -4,20 +4,7 @@
-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
From 71dc71fee8dbc615649f264cf54b842744cdca1a Mon Sep 17 00:00:00 2001
From: GreemDev
Date: Sun, 8 Jun 2025 22:37:21 -0500
Subject: [PATCH 19/57] infra: [ci skip] Remove duplicate GLI install in canary
CI
---
.github/workflows/canary.yml | 10 ----------
1 file changed, 10 deletions(-)
diff --git a/.github/workflows/canary.yml b/.github/workflows/canary.yml
index 8b8bca971..db38c9f99 100644
--- a/.github/workflows/canary.yml
+++ b/.github/workflows/canary.yml
@@ -43,16 +43,6 @@ jobs:
- name: Overwrite csc problem matcher
run: echo "::add-matcher::.github/csc.json"
-
- - name: Install GitLabCli
- run: |
- mkdir -p $HOME/.bin
- gh release download -R GreemDev/GLI -O gli -p 'GitLabCli-linux_x64'
- chmod +x gli
- mv gli $HOME/.bin/
- echo "$HOME/.bin" >> $GITHUB_PATH
- env:
- GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Get version info
id: version_info
From 5108ab790f883f07bc7513e49d501a6b8d708fc0 Mon Sep 17 00:00:00 2001
From: GreemDev
Date: Mon, 9 Jun 2025 01:47:57 -0500
Subject: [PATCH 20/57] UI: RPC: [ci skip] Add BL2, BLTPS, and Minecraft
Dungeons RPC images
---
src/Ryujinx.Common/TitleIDs.cs | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/src/Ryujinx.Common/TitleIDs.cs b/src/Ryujinx.Common/TitleIDs.cs
index 34e903149..16c9ea05f 100644
--- a/src/Ryujinx.Common/TitleIDs.cs
+++ b/src/Ryujinx.Common/TitleIDs.cs
@@ -133,7 +133,6 @@ namespace Ryujinx.Common
"0100c1f0051b6000", // Donkey Kong Country: Tropical Freeze
"0100ed000d390000", // Dr. Kawashima's Brain Training
"010067b017588000", // Endless Ocean Luminous
- "0100d2f00d5c0000", // Nintendo Switch Sports
"01006b5012b32000", // Part Time UFO
"0100704000B3A000", // Snipperclips
"01006a800016e000", // Super Smash Bros. Ultimate
@@ -169,6 +168,8 @@ namespace Ryujinx.Common
"010056e00853a000", // A Hat in Time
"0100fd1014726000", // Baldurs Gate: Dark Alliance
"01008c2019598000", // Bluey: The Video Game
+ "010096f00ff22000", // Borderlands 2: Game of the Year Edition
+ "010007400ff24000", // Borderlands: The Pre-Sequel Ultimate Edition
"0100c6800b934000", // Brawlhalla
"0100dbf01000a000", // Burnout Paradise Remastered
"0100744001588000", // Cars 3: Driven to Win
From a16764d191cbc622624bad053aa3fbd6e1f32cb4 Mon Sep 17 00:00:00 2001
From: Goodfeat
Date: Mon, 9 Jun 2025 02:37:49 -0500
Subject: [PATCH 21/57] Moved "Graphics Backend Multitreading" item to Graphics
API & Optimization section
See merge request ryubing/ryujinx!13
---
assets/locales.json | 40 +++++++--------
.../Views/Settings/SettingsGraphicsView.axaml | 49 +++++++++----------
2 files changed, 42 insertions(+), 47 deletions(-)
diff --git a/assets/locales.json b/assets/locales.json
index 2c4b4ec7a..cace3a32f 100644
--- a/assets/locales.json
+++ b/assets/locales.json
@@ -5450,26 +5450,26 @@
{
"ID": "SettingsTabGraphicsAPI",
"Translations": {
- "ar_SA": "API الرسومات ",
- "de_DE": "Grafik-API",
- "el_GR": "API Γραφικά",
- "en_US": "Graphics API",
- "es_ES": "API de gráficos",
- "fr_FR": "API Graphique",
- "he_IL": "ממשק גראפי",
- "it_IT": "API grafica",
- "ja_JP": "グラフィックスAPI",
- "ko_KR": "그래픽 API",
- "no_NO": "Grafikk API",
- "pl_PL": "Graficzne API",
- "pt_BR": "API gráfica",
- "ru_RU": "Графические API",
- "sv_SE": "Grafik-API",
- "th_TH": "API กราฟฟิก",
- "tr_TR": "Grafikler API",
- "uk_UA": "Графічний API",
- "zh_CN": "图形 API",
- "zh_TW": "圖形 API"
+ "ar_SA": "API الرسومات و تحسين",
+ "de_DE": "Grafik-API & Optimierung",
+ "el_GR": "API Γραφικά & Βελτιστοποίηση",
+ "en_US": "Graphics API & Optimization",
+ "es_ES": "API de gráficos & Optimización",
+ "fr_FR": "API Graphique & Optimisation",
+ "he_IL": "ממשק גראפי & אופטימיזציה",
+ "it_IT": "API grafica & Ottimizzazione",
+ "ja_JP": "グラフィックスAPI&最適化",
+ "ko_KR": "그래픽 API & 최적화",
+ "no_NO": "Grafikk-API & Optimalisering",
+ "pl_PL": "Graficzne API & Optymalizacja",
+ "pt_BR": "API gráfica & Otimização",
+ "ru_RU": "Графический API & Оптимизация",
+ "sv_SE": "Grafik-API & Optimering",
+ "th_TH": "API กราฟฟิก & การเพิ่มประสิทธิภาพ",
+ "tr_TR": "Grafikler API & Optimizasyon",
+ "uk_UA": "Графічний API & Оптимізація",
+ "zh_CN": "图形 API & 优化",
+ "zh_TW": "圖形 API & 優化"
}
},
{
diff --git a/src/Ryujinx/UI/Views/Settings/SettingsGraphicsView.axaml b/src/Ryujinx/UI/Views/Settings/SettingsGraphicsView.axaml
index 219efcef8..5a91b0435 100644
--- a/src/Ryujinx/UI/Views/Settings/SettingsGraphicsView.axaml
+++ b/src/Ryujinx/UI/Views/Settings/SettingsGraphicsView.axaml
@@ -56,7 +56,27 @@
SelectedIndex="{Binding PreferredGpuIndex}"
ItemsSource="{Binding AvailableGpus}"/>
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -255,32 +275,7 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
Date: Mon, 9 Jun 2025 02:54:45 -0500
Subject: [PATCH 22/57] Update: Compatibility list
See merge request ryubing/ryujinx!29
---
assets/locales.json | 225 +++++++++++++
src/Ryujinx/Assets/Styles/Styles.xaml | 6 +
.../UI/ViewModels/CompatibilityViewModel.cs | 99 +++++-
.../UI/Windows/CompatibilityListWindow.axaml | 318 +++++++++++++++---
.../Windows/CompatibilityListWindow.axaml.cs | 24 ++
5 files changed, 615 insertions(+), 57 deletions(-)
diff --git a/assets/locales.json b/assets/locales.json
index cace3a32f..5335fe2a9 100644
--- a/assets/locales.json
+++ b/assets/locales.json
@@ -1847,6 +1847,131 @@
"zh_TW": "路徑"
}
},
+ {
+ "ID": "GameListSortStatusNameAscending",
+ "Translations": {
+ "ar_SA": "",
+ "de_DE": "",
+ "el_GR": "Όνομα: A-Z",
+ "en_US": "Title: A-Z",
+ "es_ES": "Título: A-Z",
+ "fr_FR": "Titre : A-Z",
+ "he_IL": "",
+ "it_IT": "Titolo: A-Z",
+ "ja_JP": "タイトル:A-Z",
+ "ko_KR": "제목: A-Z",
+ "no_NO": "Tittel: A-Z",
+ "pl_PL": "Tytuł: A-Z",
+ "pt_BR": "Título: A-Z",
+ "ru_RU": "Название: А-Z",
+ "sv_SE": "Titel: A-Z",
+ "th_TH": "ชื่อเรื่อง: A-Z",
+ "tr_TR": "Başlık: A-Z",
+ "uk_UA": "Назва: A-Z",
+ "zh_CN": "标题:A-Z",
+ "zh_TW": "標題:A-Z"
+ }
+ },
+ {
+ "ID": "GameListSortStatusNameDescending",
+ "Translations": {
+ "ar_SA": "",
+ "de_DE": "",
+ "el_GR": "Τίτλος: Z-A",
+ "en_US": "Title: Z-A",
+ "es_ES": "Título: Z-A",
+ "fr_FR": "Titre : Z-A",
+ "he_IL": "",
+ "it_IT": "Titolo: Z-A",
+ "ja_JP": "タイトル:Z-A",
+ "ko_KR": "제목: Z-A",
+ "no_NO": "Tittel: Z-A",
+ "pl_PL": "Tytuł: Z-A",
+ "pt_BR": "Título: Z-A",
+ "ru_RU": "Название: Z-A",
+ "sv_SE": "Titel: Z-A",
+ "th_TH": "ชื่อเรื่อง: Z-A",
+ "tr_TR": "Başlık: Z-A",
+ "uk_UA": "Назва: Z-A",
+ "zh_CN": "标题:Z-A",
+ "zh_TW": "標題:Z-A"
+ }
+ },
+ {
+ "ID": "GameListSortStatusDisable",
+ "Translations": {
+ "ar_SA": "",
+ "de_DE": "Status: Deaktiviert",
+ "el_GR": "Κατάσταση: Απενεργοποιημένο",
+ "en_US": "Status: Disabled",
+ "es_ES": "Estado: Desactivado",
+ "fr_FR": "Statut : Désactivé",
+ "he_IL": "",
+ "it_IT": "Stato: Disabilitato",
+ "ja_JP": "ステータス:無効",
+ "ko_KR": "상태: 비활성화됨",
+ "no_NO": "Status: Deaktivert",
+ "pl_PL": "Status: Wyłączony",
+ "pt_BR": "Status: Desativado",
+ "ru_RU": "Статус: Отключено",
+ "sv_SE": "Status: Inaktiverad",
+ "th_TH": "",
+ "tr_TR": "Durum: Devre Dışı",
+ "uk_UA": "Статус: Вимкнено",
+ "zh_CN": "状态:禁用",
+ "zh_TW": "狀態:停用"
+ }
+ },
+ {
+ "ID": "GameListSortStatusAscending",
+ "Translations": {
+ "ar_SA": "الحالة: تصاعدي",
+ "de_DE": "Status: Aufsteigend",
+ "el_GR": "Κατάσταση: Αναγόμενη",
+ "en_US": "Status: Ascending",
+ "es_ES": "",
+ "fr_FR": "Statut : Croissant",
+ "he_IL": "סטטוס: עולה",
+ "it_IT": "Stato: Crescente",
+ "ja_JP": "ステータス:昇順",
+ "ko_KR": "상태: 오름차순",
+ "no_NO": "Status: Stigende",
+ "pl_PL": "Stan: Rosnący",
+ "pt_BR": "Status: Crescente",
+ "ru_RU": "Статус: По возрастанию",
+ "sv_SE": "Status: Stigande",
+ "th_TH": "สถานะ: เพิ่มขึ้น",
+ "tr_TR": "Durum: Artan",
+ "uk_UA": "Статус: Зростання",
+ "zh_CN": "状态:升序",
+ "zh_TW": "狀態:遞增"
+ }
+ },
+ {
+ "ID": "GameListSortStatusDescending",
+ "Translations": {
+ "ar_SA": "الحالة: تنازلي",
+ "de_DE": "Status: Absteigend",
+ "el_GR": "Κατάσταση: Καθοδική",
+ "en_US": "Status: Descending",
+ "es_ES": "",
+ "fr_FR": "Statut : Décroissant",
+ "he_IL": "סטטוס: יורד",
+ "it_IT": "Stato: Decrescente",
+ "ja_JP": "ステータス:降順",
+ "ko_KR": "상태: 내림차순",
+ "no_NO": "Status: Synkende",
+ "pl_PL": "Stan: Malejący",
+ "pt_BR": "Status: Decrescente",
+ "ru_RU": "Статус: По Убыванию",
+ "sv_SE": "Status: Fallande",
+ "th_TH": "สถานะ: ลดลง",
+ "tr_TR": "Durum: Azalan",
+ "uk_UA": "Статус: Зменшення",
+ "zh_CN": "状态:降序",
+ "zh_TW": "狀態:遞減"
+ }
+ },
{
"ID": "GameListHeaderCompatibilityStatus",
"Translations": {
@@ -24372,6 +24497,106 @@
"zh_TW": "開啟相容性列表"
}
},
+ {
+ "ID": "CompatibilityListGamesAndApplications",
+ "Translations": {
+ "ar_SA": "",
+ "de_DE": "Spiele & Anwendungen",
+ "el_GR": "Παιχνίδια και Εφαρμογές",
+ "en_US": "Games & Applications",
+ "es_ES": "Juegos y Aplicaciones",
+ "fr_FR": "Jeux et Applications",
+ "he_IL": "משחקים ואפליקציות",
+ "it_IT": "Giochi e Applicazioni",
+ "ja_JP": "ゲームとアプリケーション",
+ "ko_KR": "게임 및 애플리케이션",
+ "no_NO": "Spill og Applikasjoner",
+ "pl_PL": "Gry i Aplikacje",
+ "pt_BR": "Jogos e Aplicativos",
+ "ru_RU": "Игры и Приложения",
+ "sv_SE": "Spel och Applikationer",
+ "th_TH": "",
+ "tr_TR": "Oyunlar ve Uygulamalar",
+ "uk_UA": "Ігри та Додатки",
+ "zh_CN": "游戏和应用程序",
+ "zh_TW": "遊戲與應用程式"
+ }
+ },
+ {
+ "ID": "CompatibilityListStatus",
+ "Translations": {
+ "ar_SA": "الحالة",
+ "de_DE": "",
+ "el_GR": "Κατάσταση",
+ "en_US": "Status",
+ "es_ES": "Estado",
+ "fr_FR": "Statut",
+ "he_IL": "מצב",
+ "it_IT": "Stato",
+ "ja_JP": "状況",
+ "ko_KR": "상태",
+ "no_NO": "",
+ "pl_PL": "Stan",
+ "pt_BR": "Estado",
+ "ru_RU": "Статус",
+ "sv_SE": "",
+ "th_TH": "สถานะ",
+ "tr_TR": "Durum",
+ "uk_UA": "Статус",
+ "zh_CN": "状态",
+ "zh_TW": "狀態"
+ }
+ },
+ {
+ "ID": "CompatibilityListDescription",
+ "Translations": {
+ "ar_SA": "",
+ "de_DE": "Probleme und Merkmale",
+ "el_GR": "Προβλήματα και Χαρακτηριστικά",
+ "en_US": "Issues & Features",
+ "es_ES": "Problemas y Características",
+ "fr_FR": "Problèmes et Caractéristiques",
+ "he_IL": "",
+ "it_IT": "Problemi e Caratteristiche",
+ "ja_JP": "問題点と特徴",
+ "ko_KR": "문제점 및 특징",
+ "no_NO": "Problemer og Egenskaper",
+ "pl_PL": "Problemy i Cechy",
+ "pt_BR": "Problemas e Características",
+ "ru_RU": "Проблемы и Особенности",
+ "sv_SE": "Problem och Egenskaper",
+ "th_TH": "",
+ "tr_TR": "Sorunlar ve Özellikler",
+ "uk_UA": "Проблеми та Особливості",
+ "zh_CN": "问题和特性",
+ "zh_TW": "問題與特性"
+ }
+ },
+ {
+ "ID": "CompatibilityListInfo",
+ "Translations": {
+ "ar_SA": "",
+ "de_DE": "",
+ "el_GR": "Πληροφορίες",
+ "en_US": "Info",
+ "es_ES": "Información",
+ "fr_FR": "",
+ "he_IL": "מידע",
+ "it_IT": "",
+ "ja_JP": "情報",
+ "ko_KR": "정보",
+ "no_NO": "",
+ "pl_PL": "Informacja",
+ "pt_BR": "",
+ "ru_RU": "Инфо",
+ "sv_SE": "",
+ "th_TH": "",
+ "tr_TR": "Bilgi",
+ "uk_UA": "Інфо",
+ "zh_CN": "信息",
+ "zh_TW": "資訊"
+ }
+ },
{
"ID": "CompatibilityListOnlyShowOwnedGames",
"Translations": {
diff --git a/src/Ryujinx/Assets/Styles/Styles.xaml b/src/Ryujinx/Assets/Styles/Styles.xaml
index ff9a528a5..ea6096792 100644
--- a/src/Ryujinx/Assets/Styles/Styles.xaml
+++ b/src/Ryujinx/Assets/Styles/Styles.xaml
@@ -372,6 +372,12 @@
+