From 0e84f2b1f0dd6991e02e7d5386d45c262aceee93 Mon Sep 17 00:00:00 2001 From: GreemDev Date: Wed, 4 Jun 2025 04:31:41 -0500 Subject: [PATCH 01/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 02/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 03/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 04/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 -[![Latest release](https://img.shields.io/github/v/release/Ryubing/Stable-Releases?label=stable)](https://github.com/Ryubing/Stable-Releases/releases/latest) -[![Latest canary release](https://img.shields.io/github/v/release/Ryubing/Canary-Releases?label=canary)](https://github.com/Ryubing/Canary-Releases/releases/latest) +[![Latest release](https://img.shields.io/gitlab/v/release/ryubing%2Fryujinx?gitlab_url=https%3A%2F%2Fgit.ryujinx.app&label=stable&color=32cd32)](https://git.ryujinx.app/ryubing/ryujinx/-/releases) +[![Latest canary release](https://img.shields.io/gitlab/v/release/ryubing%2Fcanary?gitlab_url=https%3A%2F%2Fgit.ryujinx.app&label=canary&color=FF4500)](https://git.ryujinx.app/ryubing/canary/-/releases)
Discord @@ -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 05/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 06/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 07/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 08/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 09/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 10/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 11/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 12/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 13/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 14/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 15/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 16/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 17/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 18/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 19/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 20/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 @@ +