From b71a4cb7456eae7a265ab70add956fdbe9958bd9 Mon Sep 17 00:00:00 2001 From: GreemDev Date: Sat, 26 Apr 2025 19:14:08 -0500 Subject: [PATCH 001/105] docs: compat: Breakout Beyond & Nikoderiko: The Magical World --- docs/compatibility.csv | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/compatibility.csv b/docs/compatibility.csv index c46a0d1e9..37d350c03 100644 --- a/docs/compatibility.csv +++ b/docs/compatibility.csv @@ -601,6 +601,7 @@ 010060200A4BE000,"Brawlout",ldn-untested;online,playable,2021-06-04 17:35:35 0100C1B00E1CA000,"Brawlout Demo",demo,playable,2021-02-13 22:46:53 010022C016DC8000,"Breakout: Recharged",slow,ingame,2022-11-06 15:32:57 +010048A021C40000,"Breakout Beyond",,playable,2025-04-26 19:11:35 01000AA013A5E000,"Breathedge",UE4;nvdec,playable,2021-05-06 15:44:28 01003D50100F4000,"Breathing Fear",,playable,2020-07-14 15:12:29 010026800BB06000,"Brick Breaker",nvdec;online,playable,2020-12-15 18:26:23 @@ -2028,6 +2029,7 @@ 0100628004BCE000,"Nights of Azure 2: Bride of the New Moon",crash;nvdec;regression,menus,2022-11-24 16:00:39 010042300C4F6000,"Nightshade/百花百狼",nvdec,playable,2020-05-10 19:43:31 0100AA0008736000,"Nihilumbra",,playable,2020-05-10 16:00:12 +01009FA01FF6C000,"Nikoderiko: The Magical World",gpu,ingame,2025-04-26 19:13:31 0100D03003F0E000,"Nine Parchments",ldn-untested,playable,2022-08-07 12:32:08 0100E2F014F46000,"NINJA GAIDEN Σ",nvdec,playable,2022-11-13 16:27:02 0100696014F4A000,"NINJA GAIDEN Σ2",nvdec,playable,2024-07-31 21:53:48 From 9b429afbb4d8d0223e7a8c76f8ce417635b00a96 Mon Sep 17 00:00:00 2001 From: LotP <22-lotp@users.noreply.git.ryujinx.app> Date: Sun, 27 Apr 2025 16:57:57 -0500 Subject: [PATCH 002/105] fix: PPTC blacklist trigger conditions See merge request ryubing/ryujinx!28 --- src/ARMeilleure/Translation/PTC/Ptc.cs | 4 ++-- src/ARMeilleure/Translation/Translator.cs | 12 ++++++++---- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/src/ARMeilleure/Translation/PTC/Ptc.cs b/src/ARMeilleure/Translation/PTC/Ptc.cs index b3baa4413..72f9d5a0a 100644 --- a/src/ARMeilleure/Translation/PTC/Ptc.cs +++ b/src/ARMeilleure/Translation/PTC/Ptc.cs @@ -33,7 +33,7 @@ namespace ARMeilleure.Translation.PTC private const string OuterHeaderMagicString = "PTCohd\0\0"; private const string InnerHeaderMagicString = "PTCihd\0\0"; - private const uint InternalVersion = 7007; //! To be incremented manually for each change to the ARMeilleure project. + private const uint InternalVersion = 7008; //! To be incremented manually for each change to the ARMeilleure project. private const string ActualDir = "0"; private const string BackupDir = "1"; @@ -873,7 +873,7 @@ namespace ARMeilleure.Translation.PTC Debug.Assert(Profiler.IsAddressInStaticCodeRange(address)); - TranslatedFunction func = translator.Translate(address, executionMode, highCq); + TranslatedFunction func = translator.Translate(address, executionMode, highCq, pptcTranslation: true); if (func == null) { diff --git a/src/ARMeilleure/Translation/Translator.cs b/src/ARMeilleure/Translation/Translator.cs index 14c80f24b..d8528cfd6 100644 --- a/src/ARMeilleure/Translation/Translator.cs +++ b/src/ARMeilleure/Translation/Translator.cs @@ -219,7 +219,7 @@ namespace ARMeilleure.Translation } } - internal TranslatedFunction Translate(ulong address, ExecutionMode mode, bool highCq, bool singleStep = false) + internal TranslatedFunction Translate(ulong address, ExecutionMode mode, bool highCq, bool singleStep = false, bool pptcTranslation = false) { ArmEmitterContext context = new( Memory, @@ -246,7 +246,7 @@ namespace ARMeilleure.Translation context.Branch(context.GetLabel(address)); } - ControlFlowGraph cfg = EmitAndGetCFG(context, blocks, out Range funcRange, out Counter counter); + ControlFlowGraph cfg = EmitAndGetCFG(context, blocks, out Range funcRange, out Counter counter, pptcTranslation); if (cfg == null) { @@ -326,7 +326,8 @@ namespace ARMeilleure.Translation ArmEmitterContext context, Block[] blocks, out Range range, - out Counter counter) + out Counter counter, + bool pptcTranslation) { counter = null; @@ -411,7 +412,10 @@ namespace ARMeilleure.Translation if (opCode.Instruction.Emitter != null) { opCode.Instruction.Emitter(context); - if (opCode.Instruction.Name == InstName.Und && blkIndex == 0) + // if we're pre-compiling PPTC functions, and we hit an Undefined instruction as the first + // instruction in the block, mark the function as blacklisted + // this way, we don't pre-compile Exlaunch hooks, which allows ExeFS mods to run with PPTC + if (pptcTranslation && opCode.Instruction.Name == InstName.Und && blkIndex == 0) { range = new Range(rangeStart, rangeEnd); return null; From d8e3ab39740ef150df75d4b83434017ac7e45490 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hack=E8=8C=B6=E3=82=93?= Date: Mon, 28 Apr 2025 23:29:41 -0500 Subject: [PATCH 003/105] Update Korean translation See merge request [ryubing/ryujinx!30](https://git.ryujinx.app/ryubing/ryujinx/-/merge_requests/30) --- assets/locales.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/assets/locales.json b/assets/locales.json index ef621b1af..d7d42dded 100644 --- a/assets/locales.json +++ b/assets/locales.json @@ -7034,7 +7034,7 @@ "he_IL": "", "it_IT": "", "ja_JP": "", - "ko_KR": "", + "ko_KR": "발견된 구성 :\n\n이름 : \t{0}\n가이드 : \t{1}\n\n 컨트롤러 연결 대기 중...", "no_NO": "", "pl_PL": "", "pt_BR": "", @@ -24484,7 +24484,7 @@ "he_IL": "", "it_IT": "", "ja_JP": "", - "ko_KR": "불가능", + "ko_KR": "불가", "no_NO": "Ingenting", "pl_PL": "", "pt_BR": "Nada", From 6904d6a461e44335caadba2e7c8aa766704728d3 Mon Sep 17 00:00:00 2001 From: GreemDev Date: Sun, 4 May 2025 03:26:54 -0500 Subject: [PATCH 004/105] fix: Prevent loading the Switch Verification homebrew specifically. Its intended purpose is to be installed on a modded real Switch. It is wholly useless and pointless to use it in the emulator, and this will give those users a hint they might be doing something incorrectly. --- src/Ryujinx.HLE/Loaders/Processes/ProcessLoader.cs | 7 ++++++- src/Ryujinx/Headless/HeadlessRyujinx.cs | 2 +- src/Ryujinx/Systems/AppLibrary/ApplicationLibrary.cs | 4 ++++ 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/src/Ryujinx.HLE/Loaders/Processes/ProcessLoader.cs b/src/Ryujinx.HLE/Loaders/Processes/ProcessLoader.cs index 4c0866531..3d97a8e9f 100644 --- a/src/Ryujinx.HLE/Loaders/Processes/ProcessLoader.cs +++ b/src/Ryujinx.HLE/Loaders/Processes/ProcessLoader.cs @@ -9,6 +9,7 @@ using LibHac.Tools.FsSystem.NcaUtils; using Ryujinx.Common; using Ryujinx.Common.Logging; using Ryujinx.Graphics.Gpu; +using Ryujinx.HLE.HOS.SystemState; using Ryujinx.HLE.Loaders.Executables; using Ryujinx.HLE.Loaders.Processes.Extensions; using System; @@ -158,7 +159,7 @@ namespace Ryujinx.HLE.Loaders.Processes return false; } - + public bool LoadNxo(string path) { BlitStruct nacpData = new(1); @@ -195,6 +196,10 @@ namespace Ryujinx.HLE.Loaders.Processes programName = nacpData.Value.Title[(int)_device.System.State.DesiredTitleLanguage].NameString.ToString(); + if ("Switch Verfication" == + nacpData.Value.Title[(int)TitleLanguage.AmericanEnglish].NameString.ToString()) + throw new InvalidOperationException(); + if (string.IsNullOrWhiteSpace(programName)) { programName = Array.Find(nacpData.Value.Title.ItemsRo.ToArray(), x => x.Name[0] != 0).NameString.ToString(); diff --git a/src/Ryujinx/Headless/HeadlessRyujinx.cs b/src/Ryujinx/Headless/HeadlessRyujinx.cs index f346f1f63..cb35fc661 100644 --- a/src/Ryujinx/Headless/HeadlessRyujinx.cs +++ b/src/Ryujinx/Headless/HeadlessRyujinx.cs @@ -489,7 +489,7 @@ namespace Ryujinx.Headless return false; } } - catch (ArgumentOutOfRangeException) + catch { Logger.Error?.Print(LogClass.Application, "The specified file is not supported by Ryujinx."); diff --git a/src/Ryujinx/Systems/AppLibrary/ApplicationLibrary.cs b/src/Ryujinx/Systems/AppLibrary/ApplicationLibrary.cs index b7321d6c1..8d4b38a81 100644 --- a/src/Ryujinx/Systems/AppLibrary/ApplicationLibrary.cs +++ b/src/Ryujinx/Systems/AppLibrary/ApplicationLibrary.cs @@ -421,6 +421,10 @@ namespace Ryujinx.Ava.Systems.AppLibrary Read(assetOffset + (int)nacpOffset, (int)nacpSize).AsSpan().CopyTo(controlHolder.ByteSpan); GetApplicationInformation(ref controlHolder.Value, ref application); + + if ("Switch Verification" == controlHolder.Value + .Title[(int)TitleLanguage.AmericanEnglish].NameString.ToString()) + return false; } else { From 321bdecbc23ea35116b2faea16d879f49eed2737 Mon Sep 17 00:00:00 2001 From: WilliamWsyHK <25-WilliamWsyHK@users.noreply.git.ryujinx.app> Date: Sun, 11 May 2025 12:47:54 -0500 Subject: [PATCH 005/105] Typo for "Verification" See merge request [ryubing/ryujinx!32](https://git.ryujinx.app/ryubing/ryujinx/-/merge_requests/32) --- src/Ryujinx.HLE/Loaders/Processes/ProcessLoader.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Ryujinx.HLE/Loaders/Processes/ProcessLoader.cs b/src/Ryujinx.HLE/Loaders/Processes/ProcessLoader.cs index 3d97a8e9f..3ff26196f 100644 --- a/src/Ryujinx.HLE/Loaders/Processes/ProcessLoader.cs +++ b/src/Ryujinx.HLE/Loaders/Processes/ProcessLoader.cs @@ -196,7 +196,7 @@ namespace Ryujinx.HLE.Loaders.Processes programName = nacpData.Value.Title[(int)_device.System.State.DesiredTitleLanguage].NameString.ToString(); - if ("Switch Verfication" == + if ("Switch Verification" == nacpData.Value.Title[(int)TitleLanguage.AmericanEnglish].NameString.ToString()) throw new InvalidOperationException(); From 21971a2be708b2980131e01d54026538730490fa Mon Sep 17 00:00:00 2001 From: GreemDev Date: Tue, 13 May 2025 00:32:38 -0500 Subject: [PATCH 006/105] infra: Switch to [Ryujinx.LibHac](https://git.ryujinx.app/ryubing/libhac) The original repository disappeared a few days ago, and we had a backup. --- Directory.Packages.props | 2 +- src/Ryujinx.HLE/Ryujinx.HLE.csproj | 2 +- src/Ryujinx.Horizon/Ryujinx.Horizon.csproj | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Directory.Packages.props b/Directory.Packages.props index adf48c1de..50004350a 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -23,7 +23,6 @@ - @@ -41,6 +40,7 @@ + diff --git a/src/Ryujinx.HLE/Ryujinx.HLE.csproj b/src/Ryujinx.HLE/Ryujinx.HLE.csproj index f551f1a18..5139d9276 100644 --- a/src/Ryujinx.HLE/Ryujinx.HLE.csproj +++ b/src/Ryujinx.HLE/Ryujinx.HLE.csproj @@ -23,7 +23,7 @@ - + diff --git a/src/Ryujinx.Horizon/Ryujinx.Horizon.csproj b/src/Ryujinx.Horizon/Ryujinx.Horizon.csproj index 727513484..5ee37b7fa 100644 --- a/src/Ryujinx.Horizon/Ryujinx.Horizon.csproj +++ b/src/Ryujinx.Horizon/Ryujinx.Horizon.csproj @@ -14,6 +14,6 @@ - + From 28b8dc14c7925ce14fd780c8bb07aa0c8b39658b Mon Sep 17 00:00:00 2001 From: KeatonTheBot Date: Tue, 13 May 2025 19:27:24 -0500 Subject: [PATCH 007/105] Vulkan: Restrict feedback loop detection to AMD RDNA 3 GPUs See merge request [ryubing/ryujinx!25](https://git.ryujinx.app/ryubing/ryujinx/-/merge_requests/25) --- src/Ryujinx.Common/Helpers/Patterns.cs | 4 +++ src/Ryujinx.Graphics.Vulkan/PipelineBase.cs | 26 +++++++++++-------- .../PipelineDynamicState.cs | 14 +++++----- src/Ryujinx.Graphics.Vulkan/VulkanRenderer.cs | 5 ++++ 4 files changed, 32 insertions(+), 17 deletions(-) diff --git a/src/Ryujinx.Common/Helpers/Patterns.cs b/src/Ryujinx.Common/Helpers/Patterns.cs index 84cc1353a..943debc3b 100644 --- a/src/Ryujinx.Common/Helpers/Patterns.cs +++ b/src/Ryujinx.Common/Helpers/Patterns.cs @@ -9,6 +9,7 @@ namespace Ryujinx.Common.Helper public static readonly Regex Numeric = NumericRegex(); public static readonly Regex AmdGcn = AmdGcnRegex(); + public static readonly Regex AmdRdna3 = AmdRdna3Regex(); public static readonly Regex NvidiaConsumerClass = NvidiaConsumerClassRegex(); public static readonly Regex DomainLp1Ns = DomainLp1NsRegex(); @@ -46,6 +47,9 @@ namespace Ryujinx.Common.Helper "Radeon (((HD|R(5|7|9|X)) )?((M?[2-6]\\d{2}(\\D|$))|([7-8]\\d{3}(\\D|$))|Fury|Nano))|(Pro Duo)")] internal static partial Regex AmdGcnRegex(); + [GeneratedRegex("Radeon ([7-8](\\d{2}\\d?)[MS]|PRO [VW]7(\\d{2}\\d?)|RX 7\\d{3}([MS]?| XTX?| GRE)?)")] + public static partial Regex AmdRdna3Regex(); + [GeneratedRegex("NVIDIA GeForce (R|G)?TX? (\\d{3}\\d?)M?")] internal static partial Regex NvidiaConsumerClassRegex(); diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs b/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs index 191811593..49fe133dd 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs @@ -1527,24 +1527,28 @@ namespace Ryujinx.Graphics.Vulkan private bool ChangeFeedbackLoop(FeedbackLoopAspects aspects) { - if (_feedbackLoop != aspects) + // AMD RDNA 3 GPUs only + if (Gd.IsAmdRdna3) { - if (Gd.Capabilities.SupportsDynamicAttachmentFeedbackLoop) + if (_feedbackLoop != aspects) { - DynamicState.SetFeedbackLoop(aspects); - } - else - { - _newState.FeedbackLoopAspects = aspects; - } + if (Gd.Capabilities.SupportsDynamicAttachmentFeedbackLoop) + { + DynamicState.SetFeedbackLoop(aspects); + } + else + { + _newState.FeedbackLoopAspects = aspects; + } - _feedbackLoop = aspects; + _feedbackLoop = aspects; - return true; + return true; + } } return false; - } + } [MethodImpl(MethodImplOptions.AggressiveInlining)] private bool UpdateFeedbackLoop() diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs b/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs index ad26ff7b3..b6105589e 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs @@ -1,6 +1,7 @@ using Ryujinx.Common.Memory; using Silk.NET.Vulkan; using Silk.NET.Vulkan.Extensions.EXT; +using System; namespace Ryujinx.Graphics.Vulkan { @@ -27,6 +28,7 @@ namespace Ryujinx.Graphics.Vulkan public uint ViewportsCount; public Array16 Viewports; + [Flags] private enum DirtyFlags { None = 0, @@ -190,14 +192,14 @@ namespace Ryujinx.Graphics.Vulkan private readonly void RecordFeedbackLoop(ExtAttachmentFeedbackLoopDynamicState api, CommandBuffer commandBuffer) { - ImageAspectFlags aspects = (_feedbackLoopAspects & FeedbackLoopAspects.Color) != 0 ? ImageAspectFlags.ColorBit : 0; + ImageAspectFlags aspects = (_feedbackLoopAspects & FeedbackLoopAspects.Color) != 0 ? ImageAspectFlags.ColorBit : 0; - if ((_feedbackLoopAspects & FeedbackLoopAspects.Depth) != 0) - { - aspects |= ImageAspectFlags.DepthBit | ImageAspectFlags.StencilBit; - } + if ((_feedbackLoopAspects & FeedbackLoopAspects.Depth) != 0) + { + aspects |= ImageAspectFlags.DepthBit | ImageAspectFlags.StencilBit; + } - api.CmdSetAttachmentFeedbackLoopEnable(commandBuffer, aspects); + api.CmdSetAttachmentFeedbackLoopEnable(commandBuffer, aspects); } } } diff --git a/src/Ryujinx.Graphics.Vulkan/VulkanRenderer.cs b/src/Ryujinx.Graphics.Vulkan/VulkanRenderer.cs index e90606dcf..1dc55ca0a 100644 --- a/src/Ryujinx.Graphics.Vulkan/VulkanRenderer.cs +++ b/src/Ryujinx.Graphics.Vulkan/VulkanRenderer.cs @@ -92,6 +92,7 @@ namespace Ryujinx.Graphics.Vulkan internal bool IsAmdWindows { get; private set; } internal bool IsIntelWindows { get; private set; } internal bool IsAmdGcn { get; private set; } + internal bool IsAmdRdna3 { get; private set; } internal bool IsNvidiaPreTuring { get; private set; } internal bool IsIntelArc { get; private set; } internal bool IsQualcommProprietary { get; private set; } @@ -377,6 +378,10 @@ namespace Ryujinx.Graphics.Vulkan GpuVersion = $"Vulkan v{ParseStandardVulkanVersion(properties.ApiVersion)}, Driver v{ParseDriverVersion(ref properties)}"; IsAmdGcn = !IsMoltenVk && Vendor == Vendor.Amd && Patterns.AmdGcn.IsMatch(GpuRenderer); + + IsAmdRdna3 = Vendor == Vendor.Amd && (Patterns.AmdRdna3.IsMatch(GpuRenderer) + // ROG Ally (X) Device IDs + || properties.DeviceID is 0x15BF or 0x15C8); if (Vendor == Vendor.Nvidia) { From 1d4928e859e15410fe9ffdbd2cdb13b59d048507 Mon Sep 17 00:00:00 2001 From: GreemDev Date: Wed, 14 May 2025 15:52:14 -0500 Subject: [PATCH 008/105] infra: Update LibHac to v0.20.0. See merge request [ryubing/ryujinx!33](https://git.ryujinx.app/ryubing/ryujinx/-/merge_requests/33) --- Directory.Packages.props | 2 +- .../FileSystem/EncryptedFileSystemCreator.cs | 5 ++-- src/Ryujinx.HLE/HOS/ModLoader.cs | 2 +- .../HOS/Services/Fs/IFileSystemProxy.cs | 25 ++++++++----------- .../Ldn/UserServiceCreator/INetworkClient.cs | 2 +- .../IUserLocalCommunicationService.cs | 4 +-- .../UserServiceCreator/LdnDisabledClient.cs | 2 +- .../LdnMitm/LdnMitmClient.cs | 2 +- .../LdnRyu/LdnMasterProxyClient.cs | 4 +-- .../IParentalControlService.cs | 11 +++++++- .../QueryPlayStatisticsManager.cs | 5 +++- .../Extensions/FileSystemExtensions.cs | 8 +++++- .../Loaders/Processes/ProcessLoader.cs | 18 ++++++++----- .../Loaders/Processes/ProcessLoaderHelper.cs | 2 +- .../Loaders/Processes/ProcessResult.cs | 8 +++++- .../Systems/AppLibrary/ApplicationData.cs | 2 +- .../Systems/AppLibrary/ApplicationLibrary.cs | 6 ++--- src/Ryujinx/Systems/AppLibrary/LdnGameData.cs | 7 +++--- 18 files changed, 71 insertions(+), 44 deletions(-) diff --git a/Directory.Packages.props b/Directory.Packages.props index 50004350a..a44024c31 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -40,7 +40,7 @@ - + diff --git a/src/Ryujinx.HLE/FileSystem/EncryptedFileSystemCreator.cs b/src/Ryujinx.HLE/FileSystem/EncryptedFileSystemCreator.cs index 64b02a282..7fa244997 100644 --- a/src/Ryujinx.HLE/FileSystem/EncryptedFileSystemCreator.cs +++ b/src/Ryujinx.HLE/FileSystem/EncryptedFileSystemCreator.cs @@ -3,13 +3,14 @@ using LibHac.Common; using LibHac.Fs; using LibHac.Fs.Fsa; using LibHac.FsSrv.FsCreator; +using System.Runtime.CompilerServices; namespace Ryujinx.HLE.FileSystem { public class EncryptedFileSystemCreator : IEncryptedFileSystemCreator { public Result Create(ref SharedRef outEncryptedFileSystem, - ref SharedRef baseFileSystem, IEncryptedFileSystemCreator.KeyId idIndex, + ref readonly SharedRef baseFileSystem, IEncryptedFileSystemCreator.KeyId idIndex, in EncryptionSeed encryptionSeed) { if (idIndex < IEncryptedFileSystemCreator.KeyId.Save || idIndex > IEncryptedFileSystemCreator.KeyId.CustomStorage) @@ -18,7 +19,7 @@ namespace Ryujinx.HLE.FileSystem } // TODO: Reenable when AesXtsFileSystem is fixed. - outEncryptedFileSystem = SharedRef.CreateMove(ref baseFileSystem); + outEncryptedFileSystem = SharedRef.CreateMove(ref baseFileSystem.Ref); return Result.Success; } diff --git a/src/Ryujinx.HLE/HOS/ModLoader.cs b/src/Ryujinx.HLE/HOS/ModLoader.cs index 2e8798009..6d6da6240 100644 --- a/src/Ryujinx.HLE/HOS/ModLoader.cs +++ b/src/Ryujinx.HLE/HOS/ModLoader.cs @@ -791,7 +791,7 @@ namespace Ryujinx.HLE.HOS { string buildId = p switch { - NsoExecutable nso => Convert.ToHexString(nso.BuildId.ItemsRo.ToArray()).TrimEnd('0'), + NsoExecutable nso => Convert.ToHexString(nso.BuildId).TrimEnd('0'), NroExecutable nro => Convert.ToHexString(nro.Header.BuildId).TrimEnd('0'), _ => string.Empty, }; diff --git a/src/Ryujinx.HLE/HOS/Services/Fs/IFileSystemProxy.cs b/src/Ryujinx.HLE/HOS/Services/Fs/IFileSystemProxy.cs index d353ce64f..638203466 100644 --- a/src/Ryujinx.HLE/HOS/Services/Fs/IFileSystemProxy.cs +++ b/src/Ryujinx.HLE/HOS/Services/Fs/IFileSystemProxy.cs @@ -16,6 +16,7 @@ using Ryujinx.HLE.HOS.Services.Fs.FileSystemProxy; using Ryujinx.Memory; using System; using System.IO; +using System.Text; using static Ryujinx.HLE.Utilities.StringUtils; using GameCardHandle = System.UInt32; using IFile = Ryujinx.HLE.HOS.Services.Fs.FileSystemProxy.IFile; @@ -753,17 +754,9 @@ namespace Ryujinx.HLE.HOS.Services.Fs public ResultCode OpenCloudBackupWorkStorageFileSystem(ServiceCtx context) { CloudBackupWorkStorageId storageId = (CloudBackupWorkStorageId)context.RequestData.ReadInt32(); - using SharedRef fileSystem = new(); - - Result result = _baseFileSystemProxy.Get.OpenCloudBackupWorkStorageFileSystem(ref fileSystem.Ref, storageId); - if (result.IsFailure()) - { - return (ResultCode)result.Value; - } - - MakeObject(context, new FileSystemProxy.IFileSystem(ref fileSystem.Ref)); - - return ResultCode.Success; + + Logger.Stub?.PrintStub(LogClass.ServiceFs, new { storageId }); + throw new NotImplementedException(); // reimplementing behavior from LibHac 0.19.0 } [CommandCmif(130)] @@ -1028,7 +1021,7 @@ namespace Ryujinx.HLE.HOS.Services.Fs { ref readonly FspPath path = ref FileSystemProxyHelper.GetFspPath(context); - Result result = _baseFileSystemProxy.Get.GetRightsIdByPath(out RightsId rightsId, in path); + Result result = _baseFileSystemProxy.Get.GetRightsIdAndKeyGenerationByPath(out RightsId rightsId, out byte _, in path, ContentAttributes.All); if (result.IsFailure()) { return (ResultCode)result.Value; @@ -1044,7 +1037,7 @@ namespace Ryujinx.HLE.HOS.Services.Fs { ref readonly FspPath path = ref FileSystemProxyHelper.GetFspPath(context); - Result result = _baseFileSystemProxy.Get.GetRightsIdAndKeyGenerationByPath(out RightsId rightsId, out byte keyGeneration, in path); + Result result = _baseFileSystemProxy.Get.GetRightsIdAndKeyGenerationByPath(out RightsId rightsId, out byte keyGeneration, in path, ContentAttributes.All); if (result.IsFailure()) { return (ResultCode)result.Value; @@ -1240,8 +1233,10 @@ namespace Ryujinx.HLE.HOS.Services.Fs { BisPartitionId partitionId = (BisPartitionId)context.RequestData.ReadInt32(); ref readonly FspPath path = ref FileSystemProxyHelper.GetFspPath(context); - - return (ResultCode)_baseFileSystemProxy.Get.SetBisRootForHost(partitionId, in path).Value; + + Logger.Stub?.PrintStub(LogClass.ServiceFs, new { partitionId, path }); + + throw new NotImplementedException(); // reimplementing behavior from LibHac 0.19.0 } [CommandCmif(1001)] diff --git a/src/Ryujinx.HLE/HOS/Services/Ldn/UserServiceCreator/INetworkClient.cs b/src/Ryujinx.HLE/HOS/Services/Ldn/UserServiceCreator/INetworkClient.cs index 028ab6cfc..4254ba887 100644 --- a/src/Ryujinx.HLE/HOS/Services/Ldn/UserServiceCreator/INetworkClient.cs +++ b/src/Ryujinx.HLE/HOS/Services/Ldn/UserServiceCreator/INetworkClient.cs @@ -17,7 +17,7 @@ namespace Ryujinx.HLE.HOS.Services.Ldn.UserServiceCreator NetworkError ConnectPrivate(ConnectPrivateRequest request); ResultCode Reject(DisconnectReason disconnectReason, uint nodeId); NetworkInfo[] Scan(ushort channel, ScanFilter scanFilter); - void SetGameVersion(byte[] versionString); + void SetGameVersion(ReadOnlySpan versionString); void SetStationAcceptPolicy(AcceptPolicy acceptPolicy); void SetAdvertiseData(byte[] data); bool CreateNetwork(CreateAccessPointRequest request, byte[] advertiseData); diff --git a/src/Ryujinx.HLE/HOS/Services/Ldn/UserServiceCreator/IUserLocalCommunicationService.cs b/src/Ryujinx.HLE/HOS/Services/Ldn/UserServiceCreator/IUserLocalCommunicationService.cs index 9f7e6206b..ef898a611 100644 --- a/src/Ryujinx.HLE/HOS/Services/Ldn/UserServiceCreator/IUserLocalCommunicationService.cs +++ b/src/Ryujinx.HLE/HOS/Services/Ldn/UserServiceCreator/IUserLocalCommunicationService.cs @@ -62,7 +62,7 @@ namespace Ryujinx.HLE.HOS.Services.Ldn.UserServiceCreator // TODO: Call nn::arp::GetApplicationControlProperty here when implemented. ApplicationControlProperty controlProperty = context.Device.Processes.ActiveApplication.ApplicationControlProperties; - foreach (ulong localCommunicationId in controlProperty.LocalCommunicationId.ItemsRo) + foreach (ulong localCommunicationId in controlProperty.LocalCommunicationId) { if (localCommunicationId == localCommunicationIdChecked) { @@ -1114,7 +1114,7 @@ namespace Ryujinx.HLE.HOS.Services.Ldn.UserServiceCreator } // TODO: Call nn::arp::GetApplicationLaunchProperty here when implemented. - NetworkClient.SetGameVersion(context.Device.Processes.ActiveApplication.ApplicationControlProperties.DisplayVersion.Items.ToArray()); + NetworkClient.SetGameVersion(context.Device.Processes.ActiveApplication.ApplicationControlProperties.DisplayVersion); resultCode = ResultCode.Success; diff --git a/src/Ryujinx.HLE/HOS/Services/Ldn/UserServiceCreator/LdnDisabledClient.cs b/src/Ryujinx.HLE/HOS/Services/Ldn/UserServiceCreator/LdnDisabledClient.cs index cb9f47359..e7a874895 100644 --- a/src/Ryujinx.HLE/HOS/Services/Ldn/UserServiceCreator/LdnDisabledClient.cs +++ b/src/Ryujinx.HLE/HOS/Services/Ldn/UserServiceCreator/LdnDisabledClient.cs @@ -61,7 +61,7 @@ namespace Ryujinx.HLE.HOS.Services.Ldn.UserServiceCreator public void SetAdvertiseData(byte[] data) { } - public void SetGameVersion(byte[] versionString) { } + public void SetGameVersion(ReadOnlySpan versionString) { } public void SetStationAcceptPolicy(AcceptPolicy acceptPolicy) { } diff --git a/src/Ryujinx.HLE/HOS/Services/Ldn/UserServiceCreator/LdnMitm/LdnMitmClient.cs b/src/Ryujinx.HLE/HOS/Services/Ldn/UserServiceCreator/LdnMitm/LdnMitmClient.cs index 35fc783c2..12a15e491 100644 --- a/src/Ryujinx.HLE/HOS/Services/Ldn/UserServiceCreator/LdnMitm/LdnMitmClient.cs +++ b/src/Ryujinx.HLE/HOS/Services/Ldn/UserServiceCreator/LdnMitm/LdnMitmClient.cs @@ -85,7 +85,7 @@ namespace Ryujinx.HLE.HOS.Services.Ldn.UserServiceCreator.LdnMitm _lanDiscovery.SetAdvertiseData(data); } - public void SetGameVersion(byte[] versionString) + public void SetGameVersion(ReadOnlySpan versionString) { // NOTE: This method is not implemented in ldn_mitm Logger.Stub?.PrintMsg(LogClass.ServiceLdn, "LdnMitmClient SetGameVersion"); diff --git a/src/Ryujinx.HLE/HOS/Services/Ldn/UserServiceCreator/LdnRyu/LdnMasterProxyClient.cs b/src/Ryujinx.HLE/HOS/Services/Ldn/UserServiceCreator/LdnRyu/LdnMasterProxyClient.cs index c2bbcb471..91af49d14 100644 --- a/src/Ryujinx.HLE/HOS/Services/Ldn/UserServiceCreator/LdnRyu/LdnMasterProxyClient.cs +++ b/src/Ryujinx.HLE/HOS/Services/Ldn/UserServiceCreator/LdnRyu/LdnMasterProxyClient.cs @@ -346,9 +346,9 @@ namespace Ryujinx.HLE.HOS.Services.Ldn.UserServiceCreator.LdnRyu } } - public void SetGameVersion(byte[] versionString) + public void SetGameVersion(ReadOnlySpan versionString) { - _gameVersion = versionString; + _gameVersion = versionString.ToArray(); if (_gameVersion.Length < 0x10) { diff --git a/src/Ryujinx.HLE/HOS/Services/Pctl/ParentalControlServiceFactory/IParentalControlService.cs b/src/Ryujinx.HLE/HOS/Services/Pctl/ParentalControlServiceFactory/IParentalControlService.cs index 9b026a1c3..21a873393 100644 --- a/src/Ryujinx.HLE/HOS/Services/Pctl/ParentalControlServiceFactory/IParentalControlService.cs +++ b/src/Ryujinx.HLE/HOS/Services/Pctl/ParentalControlServiceFactory/IParentalControlService.cs @@ -55,7 +55,16 @@ namespace Ryujinx.HLE.HOS.Services.Pctl.ParentalControlServiceFactory _titleId = titleId; // TODO: Call nn::arp::GetApplicationControlProperty here when implemented, if it return ResultCode.Success we assign fields. - _ratingAge = Array.ConvertAll(context.Device.Processes.ActiveApplication.ApplicationControlProperties.RatingAge.ItemsRo.ToArray(), Convert.ToInt32); + + int[] tempRatingAge = new int[32]; + + for (int i = 0; i < 32; i++) + { + tempRatingAge[i] = Convert.ToInt32(context.Device.Processes.ActiveApplication.ApplicationControlProperties.RatingAge[i]); + } + + Array.Copy(tempRatingAge, _ratingAge, tempRatingAge.Length); + _parentalControlFlag = context.Device.Processes.ActiveApplication.ApplicationControlProperties.ParentalControlFlag; } } diff --git a/src/Ryujinx.HLE/HOS/Services/Sdb/Pdm/QueryService/QueryPlayStatisticsManager.cs b/src/Ryujinx.HLE/HOS/Services/Sdb/Pdm/QueryService/QueryPlayStatisticsManager.cs index 701cdd94e..a8fed55af 100644 --- a/src/Ryujinx.HLE/HOS/Services/Sdb/Pdm/QueryService/QueryPlayStatisticsManager.cs +++ b/src/Ryujinx.HLE/HOS/Services/Sdb/Pdm/QueryService/QueryPlayStatisticsManager.cs @@ -45,7 +45,10 @@ namespace Ryujinx.HLE.HOS.Services.Sdb.Pdm.QueryService // Check if input title ids are in the whitelist. foreach (ulong titleId in titleIds) { - if (!context.Device.Processes.ActiveApplication.ApplicationControlProperties.PlayLogQueryableApplicationId.ItemsRo.Contains(titleId)) + ReadOnlySpan temp = context.Device.Processes.ActiveApplication + .ApplicationControlProperties.PlayLogQueryableApplicationId; + + if (!temp.Contains(titleId)) { return (ResultCode)Am.ResultCode.ObjectInvalid; } diff --git a/src/Ryujinx.HLE/Loaders/Processes/Extensions/FileSystemExtensions.cs b/src/Ryujinx.HLE/Loaders/Processes/Extensions/FileSystemExtensions.cs index dec52e2e3..33448d893 100644 --- a/src/Ryujinx.HLE/Loaders/Processes/Extensions/FileSystemExtensions.cs +++ b/src/Ryujinx.HLE/Loaders/Processes/Extensions/FileSystemExtensions.cs @@ -91,7 +91,13 @@ namespace Ryujinx.HLE.Loaders.Processes.Extensions if (string.IsNullOrWhiteSpace(programName)) { - programName = Array.Find(nacpData.Value.Title.ItemsRo.ToArray(), x => x.Name[0] != 0).NameString.ToString(); + foreach (ApplicationControlProperty.ApplicationTitle nacpTitles in nacpData.Value.Title) + { + if (nacpTitles.Name[0] != 0) + continue; + + programName = nacpTitles.NameString.ToString(); + } } } diff --git a/src/Ryujinx.HLE/Loaders/Processes/ProcessLoader.cs b/src/Ryujinx.HLE/Loaders/Processes/ProcessLoader.cs index 3ff26196f..51165d590 100644 --- a/src/Ryujinx.HLE/Loaders/Processes/ProcessLoader.cs +++ b/src/Ryujinx.HLE/Loaders/Processes/ProcessLoader.cs @@ -195,16 +195,22 @@ namespace Ryujinx.HLE.Loaders.Processes nacpStorage.Read(0, nacpData.ByteSpan); programName = nacpData.Value.Title[(int)_device.System.State.DesiredTitleLanguage].NameString.ToString(); + + if (string.IsNullOrWhiteSpace(programName)) + { + foreach (ApplicationControlProperty.ApplicationTitle nacpTitles in nacpData.Value.Title) + { + if (nacpTitles.Name[0] != 0) + continue; + + programName = nacpTitles.NameString.ToString(); + } + } if ("Switch Verification" == nacpData.Value.Title[(int)TitleLanguage.AmericanEnglish].NameString.ToString()) throw new InvalidOperationException(); - - if (string.IsNullOrWhiteSpace(programName)) - { - programName = Array.Find(nacpData.Value.Title.ItemsRo.ToArray(), x => x.Name[0] != 0).NameString.ToString(); - } - + if (nacpData.Value.PresenceGroupId != 0) { programId = nacpData.Value.PresenceGroupId; diff --git a/src/Ryujinx.HLE/Loaders/Processes/ProcessLoaderHelper.cs b/src/Ryujinx.HLE/Loaders/Processes/ProcessLoaderHelper.cs index cedd11ae9..5729052e8 100644 --- a/src/Ryujinx.HLE/Loaders/Processes/ProcessLoaderHelper.cs +++ b/src/Ryujinx.HLE/Loaders/Processes/ProcessLoaderHelper.cs @@ -258,7 +258,7 @@ namespace Ryujinx.HLE.Loaders.Processes { buildIds[i] = (executables[i] switch { - NsoExecutable nso => Convert.ToHexString(nso.BuildId.ItemsRo.ToArray()), + NsoExecutable nso => Convert.ToHexString(nso.BuildId), NroExecutable nro => Convert.ToHexString(nro.Header.BuildId), _ => string.Empty }).ToUpper(); diff --git a/src/Ryujinx.HLE/Loaders/Processes/ProcessResult.cs b/src/Ryujinx.HLE/Loaders/Processes/ProcessResult.cs index 6fd9408ed..f34fdb8ad 100644 --- a/src/Ryujinx.HLE/Loaders/Processes/ProcessResult.cs +++ b/src/Ryujinx.HLE/Loaders/Processes/ProcessResult.cs @@ -59,7 +59,13 @@ namespace Ryujinx.HLE.Loaders.Processes if (string.IsNullOrWhiteSpace(Name)) { - Name = Array.Find(ApplicationControlProperties.Title.ItemsRo.ToArray(), x => x.Name[0] != 0).NameString.ToString(); + foreach (ApplicationControlProperty.ApplicationTitle nacpTitles in ApplicationControlProperties.Title) + { + if (nacpTitles.Name[0] != 0) + continue; + + Name = nacpTitles.NameString.ToString(); + } } DisplayVersion = ApplicationControlProperties.DisplayVersionString.ToString(); diff --git a/src/Ryujinx/Systems/AppLibrary/ApplicationData.cs b/src/Ryujinx/Systems/AppLibrary/ApplicationData.cs index 0819b86b8..9e288e9a1 100644 --- a/src/Ryujinx/Systems/AppLibrary/ApplicationData.cs +++ b/src/Ryujinx/Systems/AppLibrary/ApplicationData.cs @@ -221,7 +221,7 @@ namespace Ryujinx.Ava.Systems.AppLibrary NsoReader reader = new(); reader.Initialize(nsoFile.Release().AsStorage().AsFile(OpenMode.Read)).ThrowIfFailure(); - return Convert.ToHexString(reader.Header.ModuleId.ItemsRo.ToArray()).Replace("-", string.Empty).ToUpper()[..16]; + return Convert.ToHexString(reader.Header.ModuleId).Replace("-", string.Empty).ToUpper()[..16]; } } } diff --git a/src/Ryujinx/Systems/AppLibrary/ApplicationLibrary.cs b/src/Ryujinx/Systems/AppLibrary/ApplicationLibrary.cs index 8d4b38a81..618bc2b66 100644 --- a/src/Ryujinx/Systems/AppLibrary/ApplicationLibrary.cs +++ b/src/Ryujinx/Systems/AppLibrary/ApplicationLibrary.cs @@ -1367,7 +1367,7 @@ namespace Ryujinx.Ava.Systems.AppLibrary { _ = Enum.TryParse(DesiredLanguage.ToString(), out TitleLanguage desiredTitleLanguage); - if (controlData.Title.ItemsRo.Length > (int)desiredTitleLanguage) + if (controlData.Title.Length > (int)desiredTitleLanguage) { data.Name = controlData.Title[(int)desiredTitleLanguage].NameString.ToString(); data.Developer = controlData.Title[(int)desiredTitleLanguage].PublisherString.ToString(); @@ -1380,7 +1380,7 @@ namespace Ryujinx.Ava.Systems.AppLibrary if (string.IsNullOrWhiteSpace(data.Name)) { - foreach (ref readonly ApplicationControlProperty.ApplicationTitle controlTitle in controlData.Title.ItemsRo) + foreach (ref readonly ApplicationControlProperty.ApplicationTitle controlTitle in controlData.Title) { if (!controlTitle.NameString.IsEmpty()) { @@ -1393,7 +1393,7 @@ namespace Ryujinx.Ava.Systems.AppLibrary if (string.IsNullOrWhiteSpace(data.Developer)) { - foreach (ref readonly ApplicationControlProperty.ApplicationTitle controlTitle in controlData.Title.ItemsRo) + foreach (ref readonly ApplicationControlProperty.ApplicationTitle controlTitle in controlData.Title) { if (!controlTitle.PublisherString.IsEmpty()) { diff --git a/src/Ryujinx/Systems/AppLibrary/LdnGameData.cs b/src/Ryujinx/Systems/AppLibrary/LdnGameData.cs index 6750983d6..dc27b4e5c 100644 --- a/src/Ryujinx/Systems/AppLibrary/LdnGameData.cs +++ b/src/Ryujinx/Systems/AppLibrary/LdnGameData.cs @@ -20,10 +20,11 @@ namespace Ryujinx.Ava.Systems.AppLibrary public static Array GetArrayForApp( LdnGameData[] receivedData, ref ApplicationControlProperty acp) { - LibHac.Common.FixedArrays.Array8 communicationId = acp.LocalCommunicationId; - + ReadOnlySpan communicationId = acp.LocalCommunicationId; + ulong[] allowedTitleIds = communicationId.ToArray(); + return new Array(receivedData.Where(game => - communicationId.Items.Contains(game.TitleId.ToULong()) + allowedTitleIds.Contains(game.TitleId.ToULong()) )); } From e1c0b3acabee5635fa94d2fd9fb289e759595828 Mon Sep 17 00:00:00 2001 From: GreemDev Date: Wed, 14 May 2025 18:10:54 -0500 Subject: [PATCH 009/105] hle: fix: TargetInvocationException when initializing IParentalControlService The original implementation was a little overengineered (and didn't work). I suppose the games I tested simply didn't init the service. --- .../IParentalControlService.cs | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/Ryujinx.HLE/HOS/Services/Pctl/ParentalControlServiceFactory/IParentalControlService.cs b/src/Ryujinx.HLE/HOS/Services/Pctl/ParentalControlServiceFactory/IParentalControlService.cs index 21a873393..6ba6db8ba 100644 --- a/src/Ryujinx.HLE/HOS/Services/Pctl/ParentalControlServiceFactory/IParentalControlService.cs +++ b/src/Ryujinx.HLE/HOS/Services/Pctl/ParentalControlServiceFactory/IParentalControlService.cs @@ -56,15 +56,13 @@ namespace Ryujinx.HLE.HOS.Services.Pctl.ParentalControlServiceFactory // TODO: Call nn::arp::GetApplicationControlProperty here when implemented, if it return ResultCode.Success we assign fields. - int[] tempRatingAge = new int[32]; + _ratingAge = new int[context.Device.Processes.ActiveApplication.ApplicationControlProperties.RatingAge.Length]; - for (int i = 0; i < 32; i++) + for (int i = 0; i < _ratingAge.Length; i++) { - tempRatingAge[i] = Convert.ToInt32(context.Device.Processes.ActiveApplication.ApplicationControlProperties.RatingAge[i]); + _ratingAge[i] = Convert.ToInt32(context.Device.Processes.ActiveApplication.ApplicationControlProperties.RatingAge[i]); } - Array.Copy(tempRatingAge, _ratingAge, tempRatingAge.Length); - _parentalControlFlag = context.Device.Processes.ActiveApplication.ApplicationControlProperties.ParentalControlFlag; } } From f1eb911d25c2fabdc946de5558585265611560bb Mon Sep 17 00:00:00 2001 From: GreemDev Date: Wed, 14 May 2025 21:35:19 -0500 Subject: [PATCH 010/105] Revert "hle: fix: TargetInvocationException when initializing IParentalControlService" This reverts commit e1c0b3acabee5635fa94d2fd9fb289e759595828. --- .../IParentalControlService.cs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/Ryujinx.HLE/HOS/Services/Pctl/ParentalControlServiceFactory/IParentalControlService.cs b/src/Ryujinx.HLE/HOS/Services/Pctl/ParentalControlServiceFactory/IParentalControlService.cs index 6ba6db8ba..21a873393 100644 --- a/src/Ryujinx.HLE/HOS/Services/Pctl/ParentalControlServiceFactory/IParentalControlService.cs +++ b/src/Ryujinx.HLE/HOS/Services/Pctl/ParentalControlServiceFactory/IParentalControlService.cs @@ -56,13 +56,15 @@ namespace Ryujinx.HLE.HOS.Services.Pctl.ParentalControlServiceFactory // TODO: Call nn::arp::GetApplicationControlProperty here when implemented, if it return ResultCode.Success we assign fields. - _ratingAge = new int[context.Device.Processes.ActiveApplication.ApplicationControlProperties.RatingAge.Length]; + int[] tempRatingAge = new int[32]; - for (int i = 0; i < _ratingAge.Length; i++) + for (int i = 0; i < 32; i++) { - _ratingAge[i] = Convert.ToInt32(context.Device.Processes.ActiveApplication.ApplicationControlProperties.RatingAge[i]); + tempRatingAge[i] = Convert.ToInt32(context.Device.Processes.ActiveApplication.ApplicationControlProperties.RatingAge[i]); } + Array.Copy(tempRatingAge, _ratingAge, tempRatingAge.Length); + _parentalControlFlag = context.Device.Processes.ActiveApplication.ApplicationControlProperties.ParentalControlFlag; } } From e18e27fbc551631454534155bbb8e78b4c3b7ef9 Mon Sep 17 00:00:00 2001 From: GreemDev Date: Wed, 14 May 2025 21:35:20 -0500 Subject: [PATCH 011/105] Revert "infra: Update LibHac to v0.20.0." This seems to have broken some mods. This reverts commit 1d4928e859e15410fe9ffdbd2cdb13b59d048507. --- Directory.Packages.props | 2 +- .../FileSystem/EncryptedFileSystemCreator.cs | 5 ++-- src/Ryujinx.HLE/HOS/ModLoader.cs | 2 +- .../HOS/Services/Fs/IFileSystemProxy.cs | 25 +++++++++++-------- .../Ldn/UserServiceCreator/INetworkClient.cs | 2 +- .../IUserLocalCommunicationService.cs | 4 +-- .../UserServiceCreator/LdnDisabledClient.cs | 2 +- .../LdnMitm/LdnMitmClient.cs | 2 +- .../LdnRyu/LdnMasterProxyClient.cs | 4 +-- .../IParentalControlService.cs | 11 +------- .../QueryPlayStatisticsManager.cs | 5 +--- .../Extensions/FileSystemExtensions.cs | 8 +----- .../Loaders/Processes/ProcessLoader.cs | 18 +++++-------- .../Loaders/Processes/ProcessLoaderHelper.cs | 2 +- .../Loaders/Processes/ProcessResult.cs | 8 +----- .../Systems/AppLibrary/ApplicationData.cs | 2 +- .../Systems/AppLibrary/ApplicationLibrary.cs | 6 ++--- src/Ryujinx/Systems/AppLibrary/LdnGameData.cs | 7 +++--- 18 files changed, 44 insertions(+), 71 deletions(-) diff --git a/Directory.Packages.props b/Directory.Packages.props index a44024c31..50004350a 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -40,7 +40,7 @@ - + diff --git a/src/Ryujinx.HLE/FileSystem/EncryptedFileSystemCreator.cs b/src/Ryujinx.HLE/FileSystem/EncryptedFileSystemCreator.cs index 7fa244997..64b02a282 100644 --- a/src/Ryujinx.HLE/FileSystem/EncryptedFileSystemCreator.cs +++ b/src/Ryujinx.HLE/FileSystem/EncryptedFileSystemCreator.cs @@ -3,14 +3,13 @@ using LibHac.Common; using LibHac.Fs; using LibHac.Fs.Fsa; using LibHac.FsSrv.FsCreator; -using System.Runtime.CompilerServices; namespace Ryujinx.HLE.FileSystem { public class EncryptedFileSystemCreator : IEncryptedFileSystemCreator { public Result Create(ref SharedRef outEncryptedFileSystem, - ref readonly SharedRef baseFileSystem, IEncryptedFileSystemCreator.KeyId idIndex, + ref SharedRef baseFileSystem, IEncryptedFileSystemCreator.KeyId idIndex, in EncryptionSeed encryptionSeed) { if (idIndex < IEncryptedFileSystemCreator.KeyId.Save || idIndex > IEncryptedFileSystemCreator.KeyId.CustomStorage) @@ -19,7 +18,7 @@ namespace Ryujinx.HLE.FileSystem } // TODO: Reenable when AesXtsFileSystem is fixed. - outEncryptedFileSystem = SharedRef.CreateMove(ref baseFileSystem.Ref); + outEncryptedFileSystem = SharedRef.CreateMove(ref baseFileSystem); return Result.Success; } diff --git a/src/Ryujinx.HLE/HOS/ModLoader.cs b/src/Ryujinx.HLE/HOS/ModLoader.cs index 6d6da6240..2e8798009 100644 --- a/src/Ryujinx.HLE/HOS/ModLoader.cs +++ b/src/Ryujinx.HLE/HOS/ModLoader.cs @@ -791,7 +791,7 @@ namespace Ryujinx.HLE.HOS { string buildId = p switch { - NsoExecutable nso => Convert.ToHexString(nso.BuildId).TrimEnd('0'), + NsoExecutable nso => Convert.ToHexString(nso.BuildId.ItemsRo.ToArray()).TrimEnd('0'), NroExecutable nro => Convert.ToHexString(nro.Header.BuildId).TrimEnd('0'), _ => string.Empty, }; diff --git a/src/Ryujinx.HLE/HOS/Services/Fs/IFileSystemProxy.cs b/src/Ryujinx.HLE/HOS/Services/Fs/IFileSystemProxy.cs index 638203466..d353ce64f 100644 --- a/src/Ryujinx.HLE/HOS/Services/Fs/IFileSystemProxy.cs +++ b/src/Ryujinx.HLE/HOS/Services/Fs/IFileSystemProxy.cs @@ -16,7 +16,6 @@ using Ryujinx.HLE.HOS.Services.Fs.FileSystemProxy; using Ryujinx.Memory; using System; using System.IO; -using System.Text; using static Ryujinx.HLE.Utilities.StringUtils; using GameCardHandle = System.UInt32; using IFile = Ryujinx.HLE.HOS.Services.Fs.FileSystemProxy.IFile; @@ -754,9 +753,17 @@ namespace Ryujinx.HLE.HOS.Services.Fs public ResultCode OpenCloudBackupWorkStorageFileSystem(ServiceCtx context) { CloudBackupWorkStorageId storageId = (CloudBackupWorkStorageId)context.RequestData.ReadInt32(); - - Logger.Stub?.PrintStub(LogClass.ServiceFs, new { storageId }); - throw new NotImplementedException(); // reimplementing behavior from LibHac 0.19.0 + using SharedRef fileSystem = new(); + + Result result = _baseFileSystemProxy.Get.OpenCloudBackupWorkStorageFileSystem(ref fileSystem.Ref, storageId); + if (result.IsFailure()) + { + return (ResultCode)result.Value; + } + + MakeObject(context, new FileSystemProxy.IFileSystem(ref fileSystem.Ref)); + + return ResultCode.Success; } [CommandCmif(130)] @@ -1021,7 +1028,7 @@ namespace Ryujinx.HLE.HOS.Services.Fs { ref readonly FspPath path = ref FileSystemProxyHelper.GetFspPath(context); - Result result = _baseFileSystemProxy.Get.GetRightsIdAndKeyGenerationByPath(out RightsId rightsId, out byte _, in path, ContentAttributes.All); + Result result = _baseFileSystemProxy.Get.GetRightsIdByPath(out RightsId rightsId, in path); if (result.IsFailure()) { return (ResultCode)result.Value; @@ -1037,7 +1044,7 @@ namespace Ryujinx.HLE.HOS.Services.Fs { ref readonly FspPath path = ref FileSystemProxyHelper.GetFspPath(context); - Result result = _baseFileSystemProxy.Get.GetRightsIdAndKeyGenerationByPath(out RightsId rightsId, out byte keyGeneration, in path, ContentAttributes.All); + Result result = _baseFileSystemProxy.Get.GetRightsIdAndKeyGenerationByPath(out RightsId rightsId, out byte keyGeneration, in path); if (result.IsFailure()) { return (ResultCode)result.Value; @@ -1233,10 +1240,8 @@ namespace Ryujinx.HLE.HOS.Services.Fs { BisPartitionId partitionId = (BisPartitionId)context.RequestData.ReadInt32(); ref readonly FspPath path = ref FileSystemProxyHelper.GetFspPath(context); - - Logger.Stub?.PrintStub(LogClass.ServiceFs, new { partitionId, path }); - - throw new NotImplementedException(); // reimplementing behavior from LibHac 0.19.0 + + return (ResultCode)_baseFileSystemProxy.Get.SetBisRootForHost(partitionId, in path).Value; } [CommandCmif(1001)] diff --git a/src/Ryujinx.HLE/HOS/Services/Ldn/UserServiceCreator/INetworkClient.cs b/src/Ryujinx.HLE/HOS/Services/Ldn/UserServiceCreator/INetworkClient.cs index 4254ba887..028ab6cfc 100644 --- a/src/Ryujinx.HLE/HOS/Services/Ldn/UserServiceCreator/INetworkClient.cs +++ b/src/Ryujinx.HLE/HOS/Services/Ldn/UserServiceCreator/INetworkClient.cs @@ -17,7 +17,7 @@ namespace Ryujinx.HLE.HOS.Services.Ldn.UserServiceCreator NetworkError ConnectPrivate(ConnectPrivateRequest request); ResultCode Reject(DisconnectReason disconnectReason, uint nodeId); NetworkInfo[] Scan(ushort channel, ScanFilter scanFilter); - void SetGameVersion(ReadOnlySpan versionString); + void SetGameVersion(byte[] versionString); void SetStationAcceptPolicy(AcceptPolicy acceptPolicy); void SetAdvertiseData(byte[] data); bool CreateNetwork(CreateAccessPointRequest request, byte[] advertiseData); diff --git a/src/Ryujinx.HLE/HOS/Services/Ldn/UserServiceCreator/IUserLocalCommunicationService.cs b/src/Ryujinx.HLE/HOS/Services/Ldn/UserServiceCreator/IUserLocalCommunicationService.cs index ef898a611..9f7e6206b 100644 --- a/src/Ryujinx.HLE/HOS/Services/Ldn/UserServiceCreator/IUserLocalCommunicationService.cs +++ b/src/Ryujinx.HLE/HOS/Services/Ldn/UserServiceCreator/IUserLocalCommunicationService.cs @@ -62,7 +62,7 @@ namespace Ryujinx.HLE.HOS.Services.Ldn.UserServiceCreator // TODO: Call nn::arp::GetApplicationControlProperty here when implemented. ApplicationControlProperty controlProperty = context.Device.Processes.ActiveApplication.ApplicationControlProperties; - foreach (ulong localCommunicationId in controlProperty.LocalCommunicationId) + foreach (ulong localCommunicationId in controlProperty.LocalCommunicationId.ItemsRo) { if (localCommunicationId == localCommunicationIdChecked) { @@ -1114,7 +1114,7 @@ namespace Ryujinx.HLE.HOS.Services.Ldn.UserServiceCreator } // TODO: Call nn::arp::GetApplicationLaunchProperty here when implemented. - NetworkClient.SetGameVersion(context.Device.Processes.ActiveApplication.ApplicationControlProperties.DisplayVersion); + NetworkClient.SetGameVersion(context.Device.Processes.ActiveApplication.ApplicationControlProperties.DisplayVersion.Items.ToArray()); resultCode = ResultCode.Success; diff --git a/src/Ryujinx.HLE/HOS/Services/Ldn/UserServiceCreator/LdnDisabledClient.cs b/src/Ryujinx.HLE/HOS/Services/Ldn/UserServiceCreator/LdnDisabledClient.cs index e7a874895..cb9f47359 100644 --- a/src/Ryujinx.HLE/HOS/Services/Ldn/UserServiceCreator/LdnDisabledClient.cs +++ b/src/Ryujinx.HLE/HOS/Services/Ldn/UserServiceCreator/LdnDisabledClient.cs @@ -61,7 +61,7 @@ namespace Ryujinx.HLE.HOS.Services.Ldn.UserServiceCreator public void SetAdvertiseData(byte[] data) { } - public void SetGameVersion(ReadOnlySpan versionString) { } + public void SetGameVersion(byte[] versionString) { } public void SetStationAcceptPolicy(AcceptPolicy acceptPolicy) { } diff --git a/src/Ryujinx.HLE/HOS/Services/Ldn/UserServiceCreator/LdnMitm/LdnMitmClient.cs b/src/Ryujinx.HLE/HOS/Services/Ldn/UserServiceCreator/LdnMitm/LdnMitmClient.cs index 12a15e491..35fc783c2 100644 --- a/src/Ryujinx.HLE/HOS/Services/Ldn/UserServiceCreator/LdnMitm/LdnMitmClient.cs +++ b/src/Ryujinx.HLE/HOS/Services/Ldn/UserServiceCreator/LdnMitm/LdnMitmClient.cs @@ -85,7 +85,7 @@ namespace Ryujinx.HLE.HOS.Services.Ldn.UserServiceCreator.LdnMitm _lanDiscovery.SetAdvertiseData(data); } - public void SetGameVersion(ReadOnlySpan versionString) + public void SetGameVersion(byte[] versionString) { // NOTE: This method is not implemented in ldn_mitm Logger.Stub?.PrintMsg(LogClass.ServiceLdn, "LdnMitmClient SetGameVersion"); diff --git a/src/Ryujinx.HLE/HOS/Services/Ldn/UserServiceCreator/LdnRyu/LdnMasterProxyClient.cs b/src/Ryujinx.HLE/HOS/Services/Ldn/UserServiceCreator/LdnRyu/LdnMasterProxyClient.cs index 91af49d14..c2bbcb471 100644 --- a/src/Ryujinx.HLE/HOS/Services/Ldn/UserServiceCreator/LdnRyu/LdnMasterProxyClient.cs +++ b/src/Ryujinx.HLE/HOS/Services/Ldn/UserServiceCreator/LdnRyu/LdnMasterProxyClient.cs @@ -346,9 +346,9 @@ namespace Ryujinx.HLE.HOS.Services.Ldn.UserServiceCreator.LdnRyu } } - public void SetGameVersion(ReadOnlySpan versionString) + public void SetGameVersion(byte[] versionString) { - _gameVersion = versionString.ToArray(); + _gameVersion = versionString; if (_gameVersion.Length < 0x10) { diff --git a/src/Ryujinx.HLE/HOS/Services/Pctl/ParentalControlServiceFactory/IParentalControlService.cs b/src/Ryujinx.HLE/HOS/Services/Pctl/ParentalControlServiceFactory/IParentalControlService.cs index 21a873393..9b026a1c3 100644 --- a/src/Ryujinx.HLE/HOS/Services/Pctl/ParentalControlServiceFactory/IParentalControlService.cs +++ b/src/Ryujinx.HLE/HOS/Services/Pctl/ParentalControlServiceFactory/IParentalControlService.cs @@ -55,16 +55,7 @@ namespace Ryujinx.HLE.HOS.Services.Pctl.ParentalControlServiceFactory _titleId = titleId; // TODO: Call nn::arp::GetApplicationControlProperty here when implemented, if it return ResultCode.Success we assign fields. - - int[] tempRatingAge = new int[32]; - - for (int i = 0; i < 32; i++) - { - tempRatingAge[i] = Convert.ToInt32(context.Device.Processes.ActiveApplication.ApplicationControlProperties.RatingAge[i]); - } - - Array.Copy(tempRatingAge, _ratingAge, tempRatingAge.Length); - + _ratingAge = Array.ConvertAll(context.Device.Processes.ActiveApplication.ApplicationControlProperties.RatingAge.ItemsRo.ToArray(), Convert.ToInt32); _parentalControlFlag = context.Device.Processes.ActiveApplication.ApplicationControlProperties.ParentalControlFlag; } } diff --git a/src/Ryujinx.HLE/HOS/Services/Sdb/Pdm/QueryService/QueryPlayStatisticsManager.cs b/src/Ryujinx.HLE/HOS/Services/Sdb/Pdm/QueryService/QueryPlayStatisticsManager.cs index a8fed55af..701cdd94e 100644 --- a/src/Ryujinx.HLE/HOS/Services/Sdb/Pdm/QueryService/QueryPlayStatisticsManager.cs +++ b/src/Ryujinx.HLE/HOS/Services/Sdb/Pdm/QueryService/QueryPlayStatisticsManager.cs @@ -45,10 +45,7 @@ namespace Ryujinx.HLE.HOS.Services.Sdb.Pdm.QueryService // Check if input title ids are in the whitelist. foreach (ulong titleId in titleIds) { - ReadOnlySpan temp = context.Device.Processes.ActiveApplication - .ApplicationControlProperties.PlayLogQueryableApplicationId; - - if (!temp.Contains(titleId)) + if (!context.Device.Processes.ActiveApplication.ApplicationControlProperties.PlayLogQueryableApplicationId.ItemsRo.Contains(titleId)) { return (ResultCode)Am.ResultCode.ObjectInvalid; } diff --git a/src/Ryujinx.HLE/Loaders/Processes/Extensions/FileSystemExtensions.cs b/src/Ryujinx.HLE/Loaders/Processes/Extensions/FileSystemExtensions.cs index 33448d893..dec52e2e3 100644 --- a/src/Ryujinx.HLE/Loaders/Processes/Extensions/FileSystemExtensions.cs +++ b/src/Ryujinx.HLE/Loaders/Processes/Extensions/FileSystemExtensions.cs @@ -91,13 +91,7 @@ namespace Ryujinx.HLE.Loaders.Processes.Extensions if (string.IsNullOrWhiteSpace(programName)) { - foreach (ApplicationControlProperty.ApplicationTitle nacpTitles in nacpData.Value.Title) - { - if (nacpTitles.Name[0] != 0) - continue; - - programName = nacpTitles.NameString.ToString(); - } + programName = Array.Find(nacpData.Value.Title.ItemsRo.ToArray(), x => x.Name[0] != 0).NameString.ToString(); } } diff --git a/src/Ryujinx.HLE/Loaders/Processes/ProcessLoader.cs b/src/Ryujinx.HLE/Loaders/Processes/ProcessLoader.cs index 51165d590..3ff26196f 100644 --- a/src/Ryujinx.HLE/Loaders/Processes/ProcessLoader.cs +++ b/src/Ryujinx.HLE/Loaders/Processes/ProcessLoader.cs @@ -195,22 +195,16 @@ namespace Ryujinx.HLE.Loaders.Processes nacpStorage.Read(0, nacpData.ByteSpan); programName = nacpData.Value.Title[(int)_device.System.State.DesiredTitleLanguage].NameString.ToString(); - - if (string.IsNullOrWhiteSpace(programName)) - { - foreach (ApplicationControlProperty.ApplicationTitle nacpTitles in nacpData.Value.Title) - { - if (nacpTitles.Name[0] != 0) - continue; - - programName = nacpTitles.NameString.ToString(); - } - } if ("Switch Verification" == nacpData.Value.Title[(int)TitleLanguage.AmericanEnglish].NameString.ToString()) throw new InvalidOperationException(); - + + if (string.IsNullOrWhiteSpace(programName)) + { + programName = Array.Find(nacpData.Value.Title.ItemsRo.ToArray(), x => x.Name[0] != 0).NameString.ToString(); + } + if (nacpData.Value.PresenceGroupId != 0) { programId = nacpData.Value.PresenceGroupId; diff --git a/src/Ryujinx.HLE/Loaders/Processes/ProcessLoaderHelper.cs b/src/Ryujinx.HLE/Loaders/Processes/ProcessLoaderHelper.cs index 5729052e8..cedd11ae9 100644 --- a/src/Ryujinx.HLE/Loaders/Processes/ProcessLoaderHelper.cs +++ b/src/Ryujinx.HLE/Loaders/Processes/ProcessLoaderHelper.cs @@ -258,7 +258,7 @@ namespace Ryujinx.HLE.Loaders.Processes { buildIds[i] = (executables[i] switch { - NsoExecutable nso => Convert.ToHexString(nso.BuildId), + NsoExecutable nso => Convert.ToHexString(nso.BuildId.ItemsRo.ToArray()), NroExecutable nro => Convert.ToHexString(nro.Header.BuildId), _ => string.Empty }).ToUpper(); diff --git a/src/Ryujinx.HLE/Loaders/Processes/ProcessResult.cs b/src/Ryujinx.HLE/Loaders/Processes/ProcessResult.cs index f34fdb8ad..6fd9408ed 100644 --- a/src/Ryujinx.HLE/Loaders/Processes/ProcessResult.cs +++ b/src/Ryujinx.HLE/Loaders/Processes/ProcessResult.cs @@ -59,13 +59,7 @@ namespace Ryujinx.HLE.Loaders.Processes if (string.IsNullOrWhiteSpace(Name)) { - foreach (ApplicationControlProperty.ApplicationTitle nacpTitles in ApplicationControlProperties.Title) - { - if (nacpTitles.Name[0] != 0) - continue; - - Name = nacpTitles.NameString.ToString(); - } + Name = Array.Find(ApplicationControlProperties.Title.ItemsRo.ToArray(), x => x.Name[0] != 0).NameString.ToString(); } DisplayVersion = ApplicationControlProperties.DisplayVersionString.ToString(); diff --git a/src/Ryujinx/Systems/AppLibrary/ApplicationData.cs b/src/Ryujinx/Systems/AppLibrary/ApplicationData.cs index 9e288e9a1..0819b86b8 100644 --- a/src/Ryujinx/Systems/AppLibrary/ApplicationData.cs +++ b/src/Ryujinx/Systems/AppLibrary/ApplicationData.cs @@ -221,7 +221,7 @@ namespace Ryujinx.Ava.Systems.AppLibrary NsoReader reader = new(); reader.Initialize(nsoFile.Release().AsStorage().AsFile(OpenMode.Read)).ThrowIfFailure(); - return Convert.ToHexString(reader.Header.ModuleId).Replace("-", string.Empty).ToUpper()[..16]; + return Convert.ToHexString(reader.Header.ModuleId.ItemsRo.ToArray()).Replace("-", string.Empty).ToUpper()[..16]; } } } diff --git a/src/Ryujinx/Systems/AppLibrary/ApplicationLibrary.cs b/src/Ryujinx/Systems/AppLibrary/ApplicationLibrary.cs index 618bc2b66..8d4b38a81 100644 --- a/src/Ryujinx/Systems/AppLibrary/ApplicationLibrary.cs +++ b/src/Ryujinx/Systems/AppLibrary/ApplicationLibrary.cs @@ -1367,7 +1367,7 @@ namespace Ryujinx.Ava.Systems.AppLibrary { _ = Enum.TryParse(DesiredLanguage.ToString(), out TitleLanguage desiredTitleLanguage); - if (controlData.Title.Length > (int)desiredTitleLanguage) + if (controlData.Title.ItemsRo.Length > (int)desiredTitleLanguage) { data.Name = controlData.Title[(int)desiredTitleLanguage].NameString.ToString(); data.Developer = controlData.Title[(int)desiredTitleLanguage].PublisherString.ToString(); @@ -1380,7 +1380,7 @@ namespace Ryujinx.Ava.Systems.AppLibrary if (string.IsNullOrWhiteSpace(data.Name)) { - foreach (ref readonly ApplicationControlProperty.ApplicationTitle controlTitle in controlData.Title) + foreach (ref readonly ApplicationControlProperty.ApplicationTitle controlTitle in controlData.Title.ItemsRo) { if (!controlTitle.NameString.IsEmpty()) { @@ -1393,7 +1393,7 @@ namespace Ryujinx.Ava.Systems.AppLibrary if (string.IsNullOrWhiteSpace(data.Developer)) { - foreach (ref readonly ApplicationControlProperty.ApplicationTitle controlTitle in controlData.Title) + foreach (ref readonly ApplicationControlProperty.ApplicationTitle controlTitle in controlData.Title.ItemsRo) { if (!controlTitle.PublisherString.IsEmpty()) { diff --git a/src/Ryujinx/Systems/AppLibrary/LdnGameData.cs b/src/Ryujinx/Systems/AppLibrary/LdnGameData.cs index dc27b4e5c..6750983d6 100644 --- a/src/Ryujinx/Systems/AppLibrary/LdnGameData.cs +++ b/src/Ryujinx/Systems/AppLibrary/LdnGameData.cs @@ -20,11 +20,10 @@ namespace Ryujinx.Ava.Systems.AppLibrary public static Array GetArrayForApp( LdnGameData[] receivedData, ref ApplicationControlProperty acp) { - ReadOnlySpan communicationId = acp.LocalCommunicationId; - ulong[] allowedTitleIds = communicationId.ToArray(); - + LibHac.Common.FixedArrays.Array8 communicationId = acp.LocalCommunicationId; + return new Array(receivedData.Where(game => - allowedTitleIds.Contains(game.TitleId.ToULong()) + communicationId.Items.Contains(game.TitleId.ToULong()) )); } From f6c1e9711060170ffe9f217fea9e2e8aff96c7ab Mon Sep 17 00:00:00 2001 From: GreemDev Date: Sun, 18 May 2025 02:26:39 -0500 Subject: [PATCH 012/105] infra: Update to Ryujinx.LibHac 0.20.0. This time it's pulled in via GitLab package registry. --- Directory.Packages.props | 2 +- nuget.config | 23 ++++++++++++++---- .../FileSystem/EncryptedFileSystemCreator.cs | 4 ++-- src/Ryujinx.HLE/HOS/ModLoader.cs | 2 +- .../HOS/Services/Fs/IFileSystemProxy.cs | 24 +++++++------------ .../Ldn/UserServiceCreator/INetworkClient.cs | 2 +- .../IUserLocalCommunicationService.cs | 4 ++-- .../UserServiceCreator/LdnDisabledClient.cs | 2 +- .../LdnMitm/LdnMitmClient.cs | 2 +- .../LdnRyu/LdnMasterProxyClient.cs | 4 ++-- .../IParentalControlService.cs | 8 ++++++- .../QueryPlayStatisticsManager.cs | 2 +- .../Extensions/FileSystemExtensions.cs | 8 ++++++- .../Loaders/Processes/ProcessLoader.cs | 8 ++++++- .../Loaders/Processes/ProcessLoaderHelper.cs | 2 +- .../Loaders/Processes/ProcessResult.cs | 8 ++++++- .../Systems/AppLibrary/ApplicationData.cs | 2 +- .../Systems/AppLibrary/ApplicationLibrary.cs | 6 ++--- src/Ryujinx/Systems/AppLibrary/LdnGameData.cs | 2 +- 19 files changed, 74 insertions(+), 41 deletions(-) diff --git a/Directory.Packages.props b/Directory.Packages.props index 50004350a..37dcd292a 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -40,7 +40,7 @@ - + diff --git a/nuget.config b/nuget.config index 80f5bd7fc..821d83c99 100644 --- a/nuget.config +++ b/nuget.config @@ -1,7 +1,22 @@  + - - - - + + + + + + + + + + + + + + + + + diff --git a/src/Ryujinx.HLE/FileSystem/EncryptedFileSystemCreator.cs b/src/Ryujinx.HLE/FileSystem/EncryptedFileSystemCreator.cs index 64b02a282..d9f7d5dcf 100644 --- a/src/Ryujinx.HLE/FileSystem/EncryptedFileSystemCreator.cs +++ b/src/Ryujinx.HLE/FileSystem/EncryptedFileSystemCreator.cs @@ -9,7 +9,7 @@ namespace Ryujinx.HLE.FileSystem public class EncryptedFileSystemCreator : IEncryptedFileSystemCreator { public Result Create(ref SharedRef outEncryptedFileSystem, - ref SharedRef baseFileSystem, IEncryptedFileSystemCreator.KeyId idIndex, + ref readonly SharedRef baseFileSystem, IEncryptedFileSystemCreator.KeyId idIndex, in EncryptionSeed encryptionSeed) { if (idIndex < IEncryptedFileSystemCreator.KeyId.Save || idIndex > IEncryptedFileSystemCreator.KeyId.CustomStorage) @@ -18,7 +18,7 @@ namespace Ryujinx.HLE.FileSystem } // TODO: Reenable when AesXtsFileSystem is fixed. - outEncryptedFileSystem = SharedRef.CreateMove(ref baseFileSystem); + outEncryptedFileSystem = SharedRef.CreateMove(ref baseFileSystem.Ref); return Result.Success; } diff --git a/src/Ryujinx.HLE/HOS/ModLoader.cs b/src/Ryujinx.HLE/HOS/ModLoader.cs index 2e8798009..6d6da6240 100644 --- a/src/Ryujinx.HLE/HOS/ModLoader.cs +++ b/src/Ryujinx.HLE/HOS/ModLoader.cs @@ -791,7 +791,7 @@ namespace Ryujinx.HLE.HOS { string buildId = p switch { - NsoExecutable nso => Convert.ToHexString(nso.BuildId.ItemsRo.ToArray()).TrimEnd('0'), + NsoExecutable nso => Convert.ToHexString(nso.BuildId).TrimEnd('0'), NroExecutable nro => Convert.ToHexString(nro.Header.BuildId).TrimEnd('0'), _ => string.Empty, }; diff --git a/src/Ryujinx.HLE/HOS/Services/Fs/IFileSystemProxy.cs b/src/Ryujinx.HLE/HOS/Services/Fs/IFileSystemProxy.cs index d353ce64f..dcd55d579 100644 --- a/src/Ryujinx.HLE/HOS/Services/Fs/IFileSystemProxy.cs +++ b/src/Ryujinx.HLE/HOS/Services/Fs/IFileSystemProxy.cs @@ -753,17 +753,9 @@ namespace Ryujinx.HLE.HOS.Services.Fs public ResultCode OpenCloudBackupWorkStorageFileSystem(ServiceCtx context) { CloudBackupWorkStorageId storageId = (CloudBackupWorkStorageId)context.RequestData.ReadInt32(); - using SharedRef fileSystem = new(); - - Result result = _baseFileSystemProxy.Get.OpenCloudBackupWorkStorageFileSystem(ref fileSystem.Ref, storageId); - if (result.IsFailure()) - { - return (ResultCode)result.Value; - } - - MakeObject(context, new FileSystemProxy.IFileSystem(ref fileSystem.Ref)); - - return ResultCode.Success; + + Logger.Stub?.PrintStub(LogClass.ServiceFs, new { storageId }); + throw new NotImplementedException(); // reimplementing behavior from LibHac 0.19.0 } [CommandCmif(130)] @@ -1028,7 +1020,7 @@ namespace Ryujinx.HLE.HOS.Services.Fs { ref readonly FspPath path = ref FileSystemProxyHelper.GetFspPath(context); - Result result = _baseFileSystemProxy.Get.GetRightsIdByPath(out RightsId rightsId, in path); + Result result = _baseFileSystemProxy.Get.GetRightsIdAndKeyGenerationByPath(out RightsId rightsId, out _, in path, ContentAttributes.None); if (result.IsFailure()) { return (ResultCode)result.Value; @@ -1044,7 +1036,7 @@ namespace Ryujinx.HLE.HOS.Services.Fs { ref readonly FspPath path = ref FileSystemProxyHelper.GetFspPath(context); - Result result = _baseFileSystemProxy.Get.GetRightsIdAndKeyGenerationByPath(out RightsId rightsId, out byte keyGeneration, in path); + Result result = _baseFileSystemProxy.Get.GetRightsIdAndKeyGenerationByPath(out RightsId rightsId, out byte keyGeneration, in path, ContentAttributes.None); if (result.IsFailure()) { return (ResultCode)result.Value; @@ -1240,8 +1232,10 @@ namespace Ryujinx.HLE.HOS.Services.Fs { BisPartitionId partitionId = (BisPartitionId)context.RequestData.ReadInt32(); ref readonly FspPath path = ref FileSystemProxyHelper.GetFspPath(context); - - return (ResultCode)_baseFileSystemProxy.Get.SetBisRootForHost(partitionId, in path).Value; + + Logger.Stub?.PrintStub(LogClass.ServiceFs, new { partitionId, path }); + + throw new NotImplementedException(); // reimplementing behavior from LibHac 0.19.0 } [CommandCmif(1001)] diff --git a/src/Ryujinx.HLE/HOS/Services/Ldn/UserServiceCreator/INetworkClient.cs b/src/Ryujinx.HLE/HOS/Services/Ldn/UserServiceCreator/INetworkClient.cs index 028ab6cfc..4254ba887 100644 --- a/src/Ryujinx.HLE/HOS/Services/Ldn/UserServiceCreator/INetworkClient.cs +++ b/src/Ryujinx.HLE/HOS/Services/Ldn/UserServiceCreator/INetworkClient.cs @@ -17,7 +17,7 @@ namespace Ryujinx.HLE.HOS.Services.Ldn.UserServiceCreator NetworkError ConnectPrivate(ConnectPrivateRequest request); ResultCode Reject(DisconnectReason disconnectReason, uint nodeId); NetworkInfo[] Scan(ushort channel, ScanFilter scanFilter); - void SetGameVersion(byte[] versionString); + void SetGameVersion(ReadOnlySpan versionString); void SetStationAcceptPolicy(AcceptPolicy acceptPolicy); void SetAdvertiseData(byte[] data); bool CreateNetwork(CreateAccessPointRequest request, byte[] advertiseData); diff --git a/src/Ryujinx.HLE/HOS/Services/Ldn/UserServiceCreator/IUserLocalCommunicationService.cs b/src/Ryujinx.HLE/HOS/Services/Ldn/UserServiceCreator/IUserLocalCommunicationService.cs index 9f7e6206b..ef898a611 100644 --- a/src/Ryujinx.HLE/HOS/Services/Ldn/UserServiceCreator/IUserLocalCommunicationService.cs +++ b/src/Ryujinx.HLE/HOS/Services/Ldn/UserServiceCreator/IUserLocalCommunicationService.cs @@ -62,7 +62,7 @@ namespace Ryujinx.HLE.HOS.Services.Ldn.UserServiceCreator // TODO: Call nn::arp::GetApplicationControlProperty here when implemented. ApplicationControlProperty controlProperty = context.Device.Processes.ActiveApplication.ApplicationControlProperties; - foreach (ulong localCommunicationId in controlProperty.LocalCommunicationId.ItemsRo) + foreach (ulong localCommunicationId in controlProperty.LocalCommunicationId) { if (localCommunicationId == localCommunicationIdChecked) { @@ -1114,7 +1114,7 @@ namespace Ryujinx.HLE.HOS.Services.Ldn.UserServiceCreator } // TODO: Call nn::arp::GetApplicationLaunchProperty here when implemented. - NetworkClient.SetGameVersion(context.Device.Processes.ActiveApplication.ApplicationControlProperties.DisplayVersion.Items.ToArray()); + NetworkClient.SetGameVersion(context.Device.Processes.ActiveApplication.ApplicationControlProperties.DisplayVersion); resultCode = ResultCode.Success; diff --git a/src/Ryujinx.HLE/HOS/Services/Ldn/UserServiceCreator/LdnDisabledClient.cs b/src/Ryujinx.HLE/HOS/Services/Ldn/UserServiceCreator/LdnDisabledClient.cs index cb9f47359..e7a874895 100644 --- a/src/Ryujinx.HLE/HOS/Services/Ldn/UserServiceCreator/LdnDisabledClient.cs +++ b/src/Ryujinx.HLE/HOS/Services/Ldn/UserServiceCreator/LdnDisabledClient.cs @@ -61,7 +61,7 @@ namespace Ryujinx.HLE.HOS.Services.Ldn.UserServiceCreator public void SetAdvertiseData(byte[] data) { } - public void SetGameVersion(byte[] versionString) { } + public void SetGameVersion(ReadOnlySpan versionString) { } public void SetStationAcceptPolicy(AcceptPolicy acceptPolicy) { } diff --git a/src/Ryujinx.HLE/HOS/Services/Ldn/UserServiceCreator/LdnMitm/LdnMitmClient.cs b/src/Ryujinx.HLE/HOS/Services/Ldn/UserServiceCreator/LdnMitm/LdnMitmClient.cs index 35fc783c2..12a15e491 100644 --- a/src/Ryujinx.HLE/HOS/Services/Ldn/UserServiceCreator/LdnMitm/LdnMitmClient.cs +++ b/src/Ryujinx.HLE/HOS/Services/Ldn/UserServiceCreator/LdnMitm/LdnMitmClient.cs @@ -85,7 +85,7 @@ namespace Ryujinx.HLE.HOS.Services.Ldn.UserServiceCreator.LdnMitm _lanDiscovery.SetAdvertiseData(data); } - public void SetGameVersion(byte[] versionString) + public void SetGameVersion(ReadOnlySpan versionString) { // NOTE: This method is not implemented in ldn_mitm Logger.Stub?.PrintMsg(LogClass.ServiceLdn, "LdnMitmClient SetGameVersion"); diff --git a/src/Ryujinx.HLE/HOS/Services/Ldn/UserServiceCreator/LdnRyu/LdnMasterProxyClient.cs b/src/Ryujinx.HLE/HOS/Services/Ldn/UserServiceCreator/LdnRyu/LdnMasterProxyClient.cs index c2bbcb471..91af49d14 100644 --- a/src/Ryujinx.HLE/HOS/Services/Ldn/UserServiceCreator/LdnRyu/LdnMasterProxyClient.cs +++ b/src/Ryujinx.HLE/HOS/Services/Ldn/UserServiceCreator/LdnRyu/LdnMasterProxyClient.cs @@ -346,9 +346,9 @@ namespace Ryujinx.HLE.HOS.Services.Ldn.UserServiceCreator.LdnRyu } } - public void SetGameVersion(byte[] versionString) + public void SetGameVersion(ReadOnlySpan versionString) { - _gameVersion = versionString; + _gameVersion = versionString.ToArray(); if (_gameVersion.Length < 0x10) { diff --git a/src/Ryujinx.HLE/HOS/Services/Pctl/ParentalControlServiceFactory/IParentalControlService.cs b/src/Ryujinx.HLE/HOS/Services/Pctl/ParentalControlServiceFactory/IParentalControlService.cs index 9b026a1c3..c6e89b417 100644 --- a/src/Ryujinx.HLE/HOS/Services/Pctl/ParentalControlServiceFactory/IParentalControlService.cs +++ b/src/Ryujinx.HLE/HOS/Services/Pctl/ParentalControlServiceFactory/IParentalControlService.cs @@ -55,7 +55,13 @@ namespace Ryujinx.HLE.HOS.Services.Pctl.ParentalControlServiceFactory _titleId = titleId; // TODO: Call nn::arp::GetApplicationControlProperty here when implemented, if it return ResultCode.Success we assign fields. - _ratingAge = Array.ConvertAll(context.Device.Processes.ActiveApplication.ApplicationControlProperties.RatingAge.ItemsRo.ToArray(), Convert.ToInt32); + _ratingAge = new int[context.Device.Processes.ActiveApplication.ApplicationControlProperties.RatingAge.Length]; + + for (int i = 0; i < _ratingAge.Length; i++) + { + _ratingAge[i] = Convert.ToInt32(context.Device.Processes.ActiveApplication.ApplicationControlProperties.RatingAge[i]); + } + _parentalControlFlag = context.Device.Processes.ActiveApplication.ApplicationControlProperties.ParentalControlFlag; } } diff --git a/src/Ryujinx.HLE/HOS/Services/Sdb/Pdm/QueryService/QueryPlayStatisticsManager.cs b/src/Ryujinx.HLE/HOS/Services/Sdb/Pdm/QueryService/QueryPlayStatisticsManager.cs index 701cdd94e..b34ff0476 100644 --- a/src/Ryujinx.HLE/HOS/Services/Sdb/Pdm/QueryService/QueryPlayStatisticsManager.cs +++ b/src/Ryujinx.HLE/HOS/Services/Sdb/Pdm/QueryService/QueryPlayStatisticsManager.cs @@ -45,7 +45,7 @@ namespace Ryujinx.HLE.HOS.Services.Sdb.Pdm.QueryService // Check if input title ids are in the whitelist. foreach (ulong titleId in titleIds) { - if (!context.Device.Processes.ActiveApplication.ApplicationControlProperties.PlayLogQueryableApplicationId.ItemsRo.Contains(titleId)) + if (!context.Device.Processes.ActiveApplication.ApplicationControlProperties.PlayLogQueryableApplicationId.AsReadOnlySpan().Contains(titleId)) { return (ResultCode)Am.ResultCode.ObjectInvalid; } diff --git a/src/Ryujinx.HLE/Loaders/Processes/Extensions/FileSystemExtensions.cs b/src/Ryujinx.HLE/Loaders/Processes/Extensions/FileSystemExtensions.cs index dec52e2e3..23faca9d1 100644 --- a/src/Ryujinx.HLE/Loaders/Processes/Extensions/FileSystemExtensions.cs +++ b/src/Ryujinx.HLE/Loaders/Processes/Extensions/FileSystemExtensions.cs @@ -91,7 +91,13 @@ namespace Ryujinx.HLE.Loaders.Processes.Extensions if (string.IsNullOrWhiteSpace(programName)) { - programName = Array.Find(nacpData.Value.Title.ItemsRo.ToArray(), x => x.Name[0] != 0).NameString.ToString(); + foreach (ApplicationControlProperty.ApplicationTitle appTitle in nacpData.Value.Title) + { + if (appTitle.Name[0] != 0) + continue; + + programName = appTitle.NameString.ToString(); + } } } diff --git a/src/Ryujinx.HLE/Loaders/Processes/ProcessLoader.cs b/src/Ryujinx.HLE/Loaders/Processes/ProcessLoader.cs index 3ff26196f..16dc1ae82 100644 --- a/src/Ryujinx.HLE/Loaders/Processes/ProcessLoader.cs +++ b/src/Ryujinx.HLE/Loaders/Processes/ProcessLoader.cs @@ -202,7 +202,13 @@ namespace Ryujinx.HLE.Loaders.Processes if (string.IsNullOrWhiteSpace(programName)) { - programName = Array.Find(nacpData.Value.Title.ItemsRo.ToArray(), x => x.Name[0] != 0).NameString.ToString(); + foreach (ApplicationControlProperty.ApplicationTitle nacpTitles in nacpData.Value.Title) + { + if (nacpTitles.Name[0] != 0) + continue; + + programName = nacpTitles.NameString.ToString(); + } } if (nacpData.Value.PresenceGroupId != 0) diff --git a/src/Ryujinx.HLE/Loaders/Processes/ProcessLoaderHelper.cs b/src/Ryujinx.HLE/Loaders/Processes/ProcessLoaderHelper.cs index cedd11ae9..5729052e8 100644 --- a/src/Ryujinx.HLE/Loaders/Processes/ProcessLoaderHelper.cs +++ b/src/Ryujinx.HLE/Loaders/Processes/ProcessLoaderHelper.cs @@ -258,7 +258,7 @@ namespace Ryujinx.HLE.Loaders.Processes { buildIds[i] = (executables[i] switch { - NsoExecutable nso => Convert.ToHexString(nso.BuildId.ItemsRo.ToArray()), + NsoExecutable nso => Convert.ToHexString(nso.BuildId), NroExecutable nro => Convert.ToHexString(nro.Header.BuildId), _ => string.Empty }).ToUpper(); diff --git a/src/Ryujinx.HLE/Loaders/Processes/ProcessResult.cs b/src/Ryujinx.HLE/Loaders/Processes/ProcessResult.cs index 6fd9408ed..53ccddc68 100644 --- a/src/Ryujinx.HLE/Loaders/Processes/ProcessResult.cs +++ b/src/Ryujinx.HLE/Loaders/Processes/ProcessResult.cs @@ -59,7 +59,13 @@ namespace Ryujinx.HLE.Loaders.Processes if (string.IsNullOrWhiteSpace(Name)) { - Name = Array.Find(ApplicationControlProperties.Title.ItemsRo.ToArray(), x => x.Name[0] != 0).NameString.ToString(); + foreach (ApplicationControlProperty.ApplicationTitle appTitle in ApplicationControlProperties.Title) + { + if (appTitle.Name[0] != 0) + continue; + + Name = appTitle.NameString.ToString(); + } } DisplayVersion = ApplicationControlProperties.DisplayVersionString.ToString(); diff --git a/src/Ryujinx/Systems/AppLibrary/ApplicationData.cs b/src/Ryujinx/Systems/AppLibrary/ApplicationData.cs index 0819b86b8..9e288e9a1 100644 --- a/src/Ryujinx/Systems/AppLibrary/ApplicationData.cs +++ b/src/Ryujinx/Systems/AppLibrary/ApplicationData.cs @@ -221,7 +221,7 @@ namespace Ryujinx.Ava.Systems.AppLibrary NsoReader reader = new(); reader.Initialize(nsoFile.Release().AsStorage().AsFile(OpenMode.Read)).ThrowIfFailure(); - return Convert.ToHexString(reader.Header.ModuleId.ItemsRo.ToArray()).Replace("-", string.Empty).ToUpper()[..16]; + return Convert.ToHexString(reader.Header.ModuleId).Replace("-", string.Empty).ToUpper()[..16]; } } } diff --git a/src/Ryujinx/Systems/AppLibrary/ApplicationLibrary.cs b/src/Ryujinx/Systems/AppLibrary/ApplicationLibrary.cs index 8d4b38a81..618bc2b66 100644 --- a/src/Ryujinx/Systems/AppLibrary/ApplicationLibrary.cs +++ b/src/Ryujinx/Systems/AppLibrary/ApplicationLibrary.cs @@ -1367,7 +1367,7 @@ namespace Ryujinx.Ava.Systems.AppLibrary { _ = Enum.TryParse(DesiredLanguage.ToString(), out TitleLanguage desiredTitleLanguage); - if (controlData.Title.ItemsRo.Length > (int)desiredTitleLanguage) + if (controlData.Title.Length > (int)desiredTitleLanguage) { data.Name = controlData.Title[(int)desiredTitleLanguage].NameString.ToString(); data.Developer = controlData.Title[(int)desiredTitleLanguage].PublisherString.ToString(); @@ -1380,7 +1380,7 @@ namespace Ryujinx.Ava.Systems.AppLibrary if (string.IsNullOrWhiteSpace(data.Name)) { - foreach (ref readonly ApplicationControlProperty.ApplicationTitle controlTitle in controlData.Title.ItemsRo) + foreach (ref readonly ApplicationControlProperty.ApplicationTitle controlTitle in controlData.Title) { if (!controlTitle.NameString.IsEmpty()) { @@ -1393,7 +1393,7 @@ namespace Ryujinx.Ava.Systems.AppLibrary if (string.IsNullOrWhiteSpace(data.Developer)) { - foreach (ref readonly ApplicationControlProperty.ApplicationTitle controlTitle in controlData.Title.ItemsRo) + foreach (ref readonly ApplicationControlProperty.ApplicationTitle controlTitle in controlData.Title) { if (!controlTitle.PublisherString.IsEmpty()) { diff --git a/src/Ryujinx/Systems/AppLibrary/LdnGameData.cs b/src/Ryujinx/Systems/AppLibrary/LdnGameData.cs index 6750983d6..895aec222 100644 --- a/src/Ryujinx/Systems/AppLibrary/LdnGameData.cs +++ b/src/Ryujinx/Systems/AppLibrary/LdnGameData.cs @@ -23,7 +23,7 @@ namespace Ryujinx.Ava.Systems.AppLibrary LibHac.Common.FixedArrays.Array8 communicationId = acp.LocalCommunicationId; return new Array(receivedData.Where(game => - communicationId.Items.Contains(game.TitleId.ToULong()) + communicationId.AsReadOnlySpan().Contains(game.TitleId.ToULong()) )); } From 11cc80f7fcc50507f142e93b73622df5d52957fa Mon Sep 17 00:00:00 2001 From: GreemDev Date: Sun, 18 May 2025 03:10:38 -0500 Subject: [PATCH 013/105] infra: Generate .nupkg when building ARMeilleure, Ryujinx.Common, and Ryujinx.Memory. Additionally added a script to push them to Ryubing GitLab package registry. This script is my use only since it assumes you have the necessary authentication locally & on the server. TODO: figure out a way to get proper versioning for them. --- BuildAndPushLibraries.sh | 19 +++++++++++++++++++ nuget.config | 1 + src/ARMeilleure/ARMeilleure.csproj | 1 + src/Ryujinx.Common/Ryujinx.Common.csproj | 1 + src/Ryujinx.Memory/Ryujinx.Memory.csproj | 1 + 5 files changed, 23 insertions(+) create mode 100644 BuildAndPushLibraries.sh diff --git a/BuildAndPushLibraries.sh b/BuildAndPushLibraries.sh new file mode 100644 index 000000000..e5455e09b --- /dev/null +++ b/BuildAndPushLibraries.sh @@ -0,0 +1,19 @@ +function pub { + dotnet publish -c release +} + +function package { + cd src/$1 + pub + mv bin/Release/$1.1.0.0.nupkg ../../pkgs/$1.1.0.0.nupkg + cd ../../ +} + +rm -rf pkgs +mkdir pkgs + +package ARMeilleure +package Ryujinx.Common +package Ryujinx.Memory + +dotnet nuget push pkgs/*.nupkg --source RyubingPkgs \ No newline at end of file diff --git a/nuget.config b/nuget.config index 821d83c99..03523fc63 100644 --- a/nuget.config +++ b/nuget.config @@ -5,6 +5,7 @@ + diff --git a/src/ARMeilleure/ARMeilleure.csproj b/src/ARMeilleure/ARMeilleure.csproj index 5b6c5a6da..49d0d7a3d 100644 --- a/src/ARMeilleure/ARMeilleure.csproj +++ b/src/ARMeilleure/ARMeilleure.csproj @@ -3,6 +3,7 @@ true $(DefaultItemExcludes);._* + true diff --git a/src/Ryujinx.Common/Ryujinx.Common.csproj b/src/Ryujinx.Common/Ryujinx.Common.csproj index de163aae7..e31d2f3bc 100644 --- a/src/Ryujinx.Common/Ryujinx.Common.csproj +++ b/src/Ryujinx.Common/Ryujinx.Common.csproj @@ -4,6 +4,7 @@ true $(DefineConstants);$(ExtraDefineConstants) $(DefaultItemExcludes);._* + true diff --git a/src/Ryujinx.Memory/Ryujinx.Memory.csproj b/src/Ryujinx.Memory/Ryujinx.Memory.csproj index eda3ed17f..9cdeba3f1 100644 --- a/src/Ryujinx.Memory/Ryujinx.Memory.csproj +++ b/src/Ryujinx.Memory/Ryujinx.Memory.csproj @@ -3,6 +3,7 @@ true $(DefaultItemExcludes);._* + true From df3b5b4bd82aefd53fc68a64bae45d40114ca240 Mon Sep 17 00:00:00 2001 From: GreemDev Date: Tue, 20 May 2025 03:28:03 -0500 Subject: [PATCH 014/105] gpu: tweak: Do not log missing Votevtg implementation. --- src/Ryujinx.Graphics.Shader/Instructions/InstEmit.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Ryujinx.Graphics.Shader/Instructions/InstEmit.cs b/src/Ryujinx.Graphics.Shader/Instructions/InstEmit.cs index 0c2f90b7e..d77621db6 100644 --- a/src/Ryujinx.Graphics.Shader/Instructions/InstEmit.cs +++ b/src/Ryujinx.Graphics.Shader/Instructions/InstEmit.cs @@ -331,7 +331,8 @@ namespace Ryujinx.Graphics.Shader.Instructions { context.GetOp(); - context.TranslatorContext.GpuAccessor.Log("Shader instruction Votevtg is not implemented."); + // This instruction is proprietary and will not be implemented. Commenting it out to avoid false reports. + //context.TranslatorContext.GpuAccessor.Log("Shader instruction Votevtg is not implemented."); } public static void Vset(EmitterContext context) From 92440afcd7c0c5a9f4e463a023283324ec3eba7f Mon Sep 17 00:00:00 2001 From: GreemDev Date: Tue, 20 May 2025 04:19:54 -0500 Subject: [PATCH 015/105] UI: Show Total Time Played at the bottom of the UI in the status bar next to game total. Does not show up in-game, and is recalculated every time the game list is reloaded. --- assets/locales.json | 27 +++++++++++++- .../Systems/AppLibrary/ApplicationLibrary.cs | 36 +++++++++++++++++++ .../UI/ViewModels/MainWindowViewModel.cs | 22 ++++++++++++ .../UI/Views/Main/MainStatusBarView.axaml | 10 +++++- src/Ryujinx/UI/Windows/MainWindow.axaml.cs | 2 ++ 5 files changed, 95 insertions(+), 2 deletions(-) diff --git a/assets/locales.json b/assets/locales.json index d7d42dded..9762ea8fe 100644 --- a/assets/locales.json +++ b/assets/locales.json @@ -1947,6 +1947,31 @@ "zh_TW": "LDN 上在線的玩家數量: {0}" } }, + { + "ID": "GameListLabelTotalTimePlayed", + "Translations": { + "ar_SA": "", + "de_DE": "Gesamte Spielzeit: {0}", + "el_GR": "Συνολικός χρόνος παιχνιδιού: {0}", + "en_US": "Total Play Time: {0}", + "es_ES": "Tiempo total de juego: {0}", + "fr_FR": "Temps de jeu total: {0}", + "he_IL": "", + "it_IT": "Tempo totale di gioco: {0}", + "ja_JP": "", + "ko_KR": "", + "no_NO": "", + "pl_PL": "Całkowity czas gry: {0}", + "pt_BR": "Tempo total de jogo: {0}", + "ru_RU": "", + "sv_SE": "", + "th_TH": "", + "tr_TR": "Toplam Oyun Süresi: {0}", + "uk_UA": "", + "zh_CN": "", + "zh_TW": "" + } + }, { "ID": "GameListContextMenuOpenUserSaveDirectory", "Translations": { @@ -24748,4 +24773,4 @@ } } ] -} \ No newline at end of file +} diff --git a/src/Ryujinx/Systems/AppLibrary/ApplicationLibrary.cs b/src/Ryujinx/Systems/AppLibrary/ApplicationLibrary.cs index 618bc2b66..9ac484768 100644 --- a/src/Ryujinx/Systems/AppLibrary/ApplicationLibrary.cs +++ b/src/Ryujinx/Systems/AppLibrary/ApplicationLibrary.cs @@ -51,6 +51,26 @@ namespace Ryujinx.Ava.Systems.AppLibrary public readonly IObservableCache<(TitleUpdateModel TitleUpdate, bool IsSelected), TitleUpdateModel> TitleUpdates; public readonly IObservableCache<(DownloadableContentModel Dlc, bool IsEnabled), DownloadableContentModel> DownloadableContents; + private Gommon.Optional _totalTimePlayed; + + public Gommon.Optional TotalTimePlayed + { + get => _totalTimePlayed; + private set + { + _totalTimePlayed = value; + _totalTimePlayedChanged.Call(value); + } + } + + public event Action> TotalTimePlayedRecalculated + { + add => _totalTimePlayedChanged.Add(value); + remove => _totalTimePlayedChanged.Remove(value); + } + + private readonly Event> _totalTimePlayedChanged = new(); + private readonly byte[] _nspIcon; private readonly byte[] _xciIcon; private readonly byte[] _ncaIcon; @@ -825,6 +845,22 @@ namespace Ryujinx.Ava.Systems.AppLibrary } } + public Task RefreshTotalTimePlayedAsync() + { + TotalTimePlayed = Gommon.Optional.None; + + TimeSpan temporary = TimeSpan.Zero; + + foreach (var installedApplication in Applications.Items) + { + temporary += LoadAndSaveMetaData(installedApplication.IdString).TimePlayed; + } + + TotalTimePlayed = temporary; + + return Task.CompletedTask; + } + public async Task RefreshLdn() { if (ConfigurationState.Instance.Multiplayer.Mode == MultiplayerMode.LdnRyu) diff --git a/src/Ryujinx/UI/ViewModels/MainWindowViewModel.cs b/src/Ryujinx/UI/ViewModels/MainWindowViewModel.cs index b0cd6a556..f265f4c06 100644 --- a/src/Ryujinx/UI/ViewModels/MainWindowViewModel.cs +++ b/src/Ryujinx/UI/ViewModels/MainWindowViewModel.cs @@ -25,6 +25,7 @@ using Ryujinx.Ava.UI.Renderer; using Ryujinx.Ava.UI.Windows; using Ryujinx.Ava.Systems.AppLibrary; using Ryujinx.Ava.Systems.Configuration; +using Ryujinx.Ava.Utilities; using Ryujinx.Common; using Ryujinx.Common.Configuration; using Ryujinx.Common.Helper; @@ -112,6 +113,7 @@ namespace Ryujinx.Ava.UI.ViewModels await Updater.BeginUpdateAsync(true); }); + private bool _showTotalTimePlayed; private bool _showLoadProgress; private bool _isGameRunning; private bool _isAmiiboRequested; @@ -197,6 +199,8 @@ namespace Ryujinx.Ava.UI.ViewModels #if DEBUG topLevel.AttachDevTools(new KeyGesture(Avalonia.Input.Key.F12, KeyModifiers.Control)); #endif + + Window.ApplicationLibrary.TotalTimePlayedRecalculated += TotalTimePlayed_Recalculated; } #region Properties @@ -299,6 +303,24 @@ namespace Ryujinx.Ava.UI.ViewModels OnPropertyChanged(nameof(ShowFirmwareStatus)); } } + + private void TotalTimePlayed_Recalculated(Optional ts) + { + ShowTotalTimePlayed = ts.HasValue; + + if (ts.HasValue) + LocaleManager.Instance.SetDynamicValues(LocaleKeys.GameListLabelTotalTimePlayed, ValueFormatUtils.FormatTimeSpan(ts.Value)); + } + + public bool ShowTotalTimePlayed + { + get => _showTotalTimePlayed && EnableNonGameRunningControls; + set + { + _showTotalTimePlayed = value; + OnPropertyChanged(); + } + } public ApplicationData ListSelectedApplication { diff --git a/src/Ryujinx/UI/Views/Main/MainStatusBarView.axaml b/src/Ryujinx/UI/Views/Main/MainStatusBarView.axaml index 02cc1fc7b..296936565 100644 --- a/src/Ryujinx/UI/Views/Main/MainStatusBarView.axaml +++ b/src/Ryujinx/UI/Views/Main/MainStatusBarView.axaml @@ -29,7 +29,7 @@ Margin="5" VerticalAlignment="Center" IsVisible="{Binding EnableNonGameRunningControls}"> - + diff --git a/src/Ryujinx/UI/Views/Dialog/AboutView.axaml.cs b/src/Ryujinx/UI/Views/Dialog/AboutView.axaml.cs index 4e89bfd86..ce86156b9 100644 --- a/src/Ryujinx/UI/Views/Dialog/AboutView.axaml.cs +++ b/src/Ryujinx/UI/Views/Dialog/AboutView.axaml.cs @@ -6,7 +6,6 @@ using Ryujinx.Ava.Common.Locale; using Ryujinx.Ava.UI.Controls; using Ryujinx.Ava.UI.Helpers; using Ryujinx.Ava.UI.ViewModels; -using Ryujinx.Common; using Ryujinx.Common.Helper; using System.Threading.Tasks; using Button = Avalonia.Controls.Button; @@ -18,9 +17,6 @@ namespace Ryujinx.Ava.UI.Views.Dialog public AboutView() { InitializeComponent(); - - GitRepoButton.Tag = - $"https://git.ryujinx.app/{ReleaseInformation.ReleaseChannelOwner}/{ReleaseInformation.ReleaseChannelSourceRepo}"; } public static async Task Show() From 6f59a14ec603de90af93fd55cf29fb8125209229 Mon Sep 17 00:00:00 2001 From: Goodfeat Date: Fri, 23 May 2025 06:27:33 -0500 Subject: [PATCH 020/105] Small Fix: now it is enough to activate dirty hack in global settings for the option... See merge request [ryubing/ryujinx!20](https://git.ryujinx.app/ryubing/ryujinx/-/merge_requests/20) --- .../Systems/Configuration/ConfigurationState.Migration.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Ryujinx/Systems/Configuration/ConfigurationState.Migration.cs b/src/Ryujinx/Systems/Configuration/ConfigurationState.Migration.cs index f7bc22913..5843b5963 100644 --- a/src/Ryujinx/Systems/Configuration/ConfigurationState.Migration.cs +++ b/src/Ryujinx/Systems/Configuration/ConfigurationState.Migration.cs @@ -157,8 +157,8 @@ namespace Ryujinx.Ava.Systems.Configuration Multiplayer.LdnServer.Value = cff.LdnServer; { - Hacks.ShowDirtyHacks.Value = cff.ShowDirtyHacks; - + Hacks.ShowDirtyHacks.Value = shouldLoadFromFile ? cff.ShowDirtyHacks: Hacks.ShowDirtyHacks.Value; // Get from global config only + DirtyHacks hacks = new (cff.DirtyHacks ?? []); Hacks.Xc2MenuSoftlockFix.Value = hacks.IsEnabled(DirtyHack.Xc2MenuSoftlockFix); From be7285f7fcf77e28b08c77a196c312670bc66917 Mon Sep 17 00:00:00 2001 From: shinyoyo Date: Fri, 23 May 2025 17:09:38 -0500 Subject: [PATCH 021/105] Update Simplified Chinese translation. See merge request [ryubing/ryujinx!37](https://git.ryujinx.app/ryubing/ryujinx/-/merge_requests/37) --- assets/locales.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/assets/locales.json b/assets/locales.json index dc2679f3d..aa7a0548f 100644 --- a/assets/locales.json +++ b/assets/locales.json @@ -1968,7 +1968,7 @@ "th_TH": "", "tr_TR": "Toplam Oyun Süresi: {0}", "uk_UA": "", - "zh_CN": "", + "zh_CN": "总游戏时间: {0}", "zh_TW": "" } }, @@ -23293,7 +23293,7 @@ "th_TH": "ด", "tr_TR": "", "uk_UA": "", - "zh_CN": "", + "zh_CN": "查看更新日志", "zh_TW": "" } }, From 1c411082dbb5ebe9436261bed481559d08b60cbf Mon Sep 17 00:00:00 2001 From: KeatonTheBot Date: Fri, 23 May 2025 17:12:37 -0500 Subject: [PATCH 022/105] Optimize XMAD instruction sequence into a single 32-bit multiply when possible See merge request [ryubing/ryujinx!24](https://git.ryujinx.app/ryubing/ryujinx/-/merge_requests/24) --- .../Translation/Optimizations/Optimizer.cs | 7 +- .../Optimizations/XmadOptimizer.cs | 342 ++++++++++++++++++ 2 files changed, 348 insertions(+), 1 deletion(-) create mode 100644 src/Ryujinx.Graphics.Shader/Translation/Optimizations/XmadOptimizer.cs diff --git a/src/Ryujinx.Graphics.Shader/Translation/Optimizations/Optimizer.cs b/src/Ryujinx.Graphics.Shader/Translation/Optimizations/Optimizer.cs index 1be7c5c52..022532af8 100644 --- a/src/Ryujinx.Graphics.Shader/Translation/Optimizations/Optimizer.cs +++ b/src/Ryujinx.Graphics.Shader/Translation/Optimizations/Optimizer.cs @@ -9,6 +9,11 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations { public static void RunPass(TransformContext context) { + for (int blkIndex = 0; blkIndex < context.Blocks.Length; blkIndex++) + { + XmadOptimizer.RunPass(context.Blocks[blkIndex]); + } + RunOptimizationPasses(context.Blocks, context.ResourceManager); // TODO: Some of those are not optimizations and shouldn't be here. @@ -355,7 +360,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations operation.TurnIntoCopy(attrMulLhs); } - private static void RemoveNode(BasicBlock block, LinkedListNode llNode) + public static void RemoveNode(BasicBlock block, LinkedListNode llNode) { // Remove a node from the nodes list, and also remove itself // from all the use lists on the operands that this node uses. diff --git a/src/Ryujinx.Graphics.Shader/Translation/Optimizations/XmadOptimizer.cs b/src/Ryujinx.Graphics.Shader/Translation/Optimizations/XmadOptimizer.cs new file mode 100644 index 000000000..3cae50fd8 --- /dev/null +++ b/src/Ryujinx.Graphics.Shader/Translation/Optimizations/XmadOptimizer.cs @@ -0,0 +1,342 @@ +using Ryujinx.Graphics.Shader.IntermediateRepresentation; +using System.Collections.Generic; + +namespace Ryujinx.Graphics.Shader.Translation.Optimizations +{ + static class XmadOptimizer + { + public static void RunPass(BasicBlock block) + { + for (LinkedListNode node = block.Operations.First; node != null; node = node.Next) + { + if (!(node.Value is Operation operation)) + { + continue; + } + + if (TryMatchXmadPattern(operation, out Operand x, out Operand y, out Operand addend)) + { + LinkedListNode nextNode; + + if (addend != null) + { + Operand temp = OperandHelper.Local(); + + nextNode = block.Operations.AddAfter(node, new Operation(Instruction.Multiply, temp, x, y)); + nextNode = block.Operations.AddAfter(nextNode, new Operation(Instruction.Add, operation.Dest, temp, addend)); + } + else + { + nextNode = block.Operations.AddAfter(node, new Operation(Instruction.Multiply, operation.Dest, x, y)); + } + + Optimizer.RemoveNode(block, node); + node = nextNode; + } + } + } + + private static bool TryMatchXmadPattern(Operation operation, out Operand x, out Operand y, out Operand addend) + { + return TryMatchXmad32x32Pattern(operation, out x, out y, out addend) || + TryMatchXmad32x16Pattern(operation, out x, out y, out addend); + } + + private static bool TryMatchXmad32x32Pattern(Operation operation, out Operand x, out Operand y, out Operand addend) + { + x = null; + y = null; + addend = null; + + if (operation.Inst != Instruction.Add) + { + return false; + } + + Operand src1 = operation.GetSource(0); + Operand src2 = operation.GetSource(1); + + if (!(src2.AsgOp is Operation addOp) || addOp.Inst != Instruction.Add) + { + return false; + } + + Operand lowTimesLowResult = GetCopySource(addOp.GetSource(0)); + + if (!(lowTimesLowResult.AsgOp is Operation lowTimesLowOp)) + { + return false; + } + + if (!TryMatchLowTimesLow(lowTimesLowOp, out x, out y, out addend)) + { + return false; + } + + Operand lowTimesHighResult = GetCopySource(GetShifted16Source(addOp.GetSource(1), Instruction.ShiftLeft)); + + if (!(lowTimesHighResult.AsgOp is Operation lowTimesHighOp)) + { + return false; + } + + if (!TryMatchLowTimesHigh(lowTimesHighOp, x, y)) + { + return false; + } + + if (!(src1.AsgOp is Operation highTimesHighOp)) + { + return false; + } + + if (!TryMatchHighTimesHigh(highTimesHighOp, x, lowTimesHighResult)) + { + return false; + } + + return true; + } + + private static bool TryMatchXmad32x16Pattern(Operation operation, out Operand x, out Operand y, out Operand addend) + { + x = null; + y = null; + addend = null; + + if (operation.Inst != Instruction.Add) + { + return false; + } + + Operand src1 = operation.GetSource(0); + Operand src2 = operation.GetSource(1); + + Operand lowTimesLowResult = GetCopySource(src2); + + if (!(lowTimesLowResult.AsgOp is Operation lowTimesLowOp)) + { + return false; + } + + if (!TryMatchLowTimesLow(lowTimesLowOp, out x, out y, out addend)) + { + return false; + } + + Operand highTimesLowResult = src1; + + if (!(highTimesLowResult.AsgOp is Operation highTimesLowOp)) + { + return false; + } + + if (!TryMatchHighTimesLow(highTimesLowOp, x, y)) + { + return false; + } + + return y.Type == OperandType.Constant && (ushort)y.Value == y.Value; + } + + private static bool TryMatchLowTimesLow(Operation operation, out Operand x, out Operand y, out Operand addend) + { + // x = x & 0xFFFF + // y = y & 0xFFFF + // lowTimesLow = x * y + + x = null; + y = null; + addend = null; + + if (operation.Inst == Instruction.Add) + { + if (!(operation.GetSource(0).AsgOp is Operation mulOp)) + { + return false; + } + + addend = operation.GetSource(1); + operation = mulOp; + } + + if (operation.Inst != Instruction.Multiply) + { + return false; + } + + Operand src1 = GetMasked16Source(operation.GetSource(0)); + Operand src2 = GetMasked16Source(operation.GetSource(1)); + + if (src1 == null || src2 == null) + { + return false; + } + + x = src1; + y = src2; + + return true; + } + + private static bool TryMatchLowTimesHigh(Operation operation, Operand x, Operand y) + { + // xLow = x & 0xFFFF + // yHigh = y >> 16 + // lowTimesHigh = xLow * yHigh + // result = (lowTimesHigh & 0xFFFF) | (y << 16) + + if (operation.Inst != Instruction.BitwiseOr) + { + return false; + } + + Operand mulResult = GetMasked16Source(operation.GetSource(0)); + + if (mulResult == null) + { + return false; + } + + mulResult = GetCopySource(mulResult); + + if (!(mulResult.AsgOp is Operation mulOp) || mulOp.Inst != Instruction.Multiply) + { + return false; + } + + if (GetMasked16Source(mulOp.GetSource(0)) != x) + { + return false; + } + + if (GetShifted16Source(mulOp.GetSource(1), Instruction.ShiftRightU32) != y) + { + return false; + } + + if (GetShifted16Source(operation.GetSource(1), Instruction.ShiftLeft) != y) + { + return false; + } + + return true; + } + + private static bool TryMatchHighTimesLow(Operation operation, Operand x, Operand y) + { + // xHigh = x >> 16 + // yLow = y & 0xFFFF + // highTimesLow = xHigh * yLow + // result = highTimesLow << 16 + + if (operation.Inst != Instruction.ShiftLeft || !IsConst(operation.GetSource(1), 16)) + { + return false; + } + + Operand mulResult = operation.GetSource(0); + + if (!(mulResult.AsgOp is Operation mulOp) || mulOp.Inst != Instruction.Multiply) + { + return false; + } + + if (GetShifted16Source(mulOp.GetSource(0), Instruction.ShiftRightU32) != x) + { + return false; + } + + Operand src2 = GetMasked16Source(mulOp.GetSource(1)); + + if (src2.Type != y.Type || src2.Value != y.Value) + { + return false; + } + + return true; + } + + private static bool TryMatchHighTimesHigh(Operation operation, Operand x, Operand lowTimesHighResult) + { + // xHigh = x >> 16 + // lowTimesHighResultHigh = lowTimesHighResult >> 16 + // highTimesHigh = xHigh * lowTimesHighResultHigh + // result = highTimesHigh << 16 + + if (operation.Inst != Instruction.ShiftLeft || !IsConst(operation.GetSource(1), 16)) + { + return false; + } + + Operand mulResult = operation.GetSource(0); + + if (!(mulResult.AsgOp is Operation mulOp) || mulOp.Inst != Instruction.Multiply) + { + return false; + } + + if (GetShifted16Source(mulOp.GetSource(0), Instruction.ShiftRightU32) != x) + { + return false; + } + + if (GetCopySource(GetShifted16Source(mulOp.GetSource(1), Instruction.ShiftRightU32)) != lowTimesHighResult) + { + return false; + } + + return true; + } + + private static Operand GetMasked16Source(Operand value) + { + if (!(value.AsgOp is Operation maskOp)) + { + return null; + } + + if (maskOp.Inst != Instruction.BitwiseAnd || !IsConst(maskOp.GetSource(1), ushort.MaxValue)) + { + return null; + } + + return maskOp.GetSource(0); + } + + private static Operand GetShifted16Source(Operand value, Instruction shiftInst) + { + if (!(value.AsgOp is Operation shiftOp)) + { + return null; + } + + if (shiftOp.Inst != shiftInst || !IsConst(shiftOp.GetSource(1), 16)) + { + return null; + } + + return shiftOp.GetSource(0); + } + + private static Operand GetCopySource(Operand value) + { + while (value.AsgOp is Operation operation && IsCopy(operation)) + { + value = operation.GetSource(0); + } + + return value; + } + + private static bool IsCopy(Operation operation) + { + return operation.Inst == Instruction.Copy || (operation.Inst == Instruction.Add && IsConst(operation.GetSource(1), 0)); + } + + private static bool IsConst(Operand operand, int value) + { + return operand.Type == OperandType.Constant && operand.Value == value; + } + } +} From 2aa072fbfa81aaa24e2df428e1167c2e00a3c8fc Mon Sep 17 00:00:00 2001 From: GreemDev Date: Sat, 24 May 2025 17:00:30 -0500 Subject: [PATCH 023/105] fix: Super Mario Party Jamboree audio renderer crashing See merge request ryubing/ryujinx!34 --- src/Ryujinx.Audio/Renderer/Dsp/AdpcmHelper.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Ryujinx.Audio/Renderer/Dsp/AdpcmHelper.cs b/src/Ryujinx.Audio/Renderer/Dsp/AdpcmHelper.cs index 8b497fe2a..1a5802a37 100644 --- a/src/Ryujinx.Audio/Renderer/Dsp/AdpcmHelper.cs +++ b/src/Ryujinx.Audio/Renderer/Dsp/AdpcmHelper.cs @@ -81,14 +81,14 @@ namespace Ryujinx.Audio.Renderer.Dsp [MethodImpl(MethodImplOptions.AggressiveInlining)] private static short GetCoefficientAtIndex(ReadOnlySpan coefficients, int index) { - if ((uint)index >= (uint)coefficients.Length) + if ((uint)index < (uint)coefficients.Length) { - Logger.Error?.Print(LogClass.AudioRenderer, $"Out of bound read for coefficient at index {index}"); - - return 0; + return coefficients[index]; } - return coefficients[index]; + Logger.Error?.Print(LogClass.AudioRenderer, $"Out of bound read for coefficient at index {index}"); + + return 0; } [MethodImpl(MethodImplOptions.AggressiveInlining)] From ae070c76d7c5572af14589d2923e4adf8823dbc1 Mon Sep 17 00:00:00 2001 From: KeatonTheBot Date: Sun, 25 May 2025 22:34:56 -0500 Subject: [PATCH 024/105] ffmpeg: Fix green screen issues on Linux See merge request ryubing/ryujinx!40 --- src/Ryujinx.Graphics.Nvdec.FFmpeg/Native/FFmpegApi.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Ryujinx.Graphics.Nvdec.FFmpeg/Native/FFmpegApi.cs b/src/Ryujinx.Graphics.Nvdec.FFmpeg/Native/FFmpegApi.cs index 1134b0c6b..13e456dfb 100644 --- a/src/Ryujinx.Graphics.Nvdec.FFmpeg/Native/FFmpegApi.cs +++ b/src/Ryujinx.Graphics.Nvdec.FFmpeg/Native/FFmpegApi.cs @@ -12,8 +12,8 @@ namespace Ryujinx.Graphics.Nvdec.FFmpeg.Native private static readonly Dictionary _librariesWhitelist = new() { - { AvCodecLibraryName, (58, 61) }, - { AvUtilLibraryName, (56, 59) }, + { AvCodecLibraryName, (59, 60) }, + { AvUtilLibraryName, (57, 58) }, }; private static string FormatLibraryNameForCurrentOs(string libraryName, int version) From fd9f1614767116f5e681314ae160dd22e96f7240 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hack=E8=8C=B6=E3=82=93?= Date: Mon, 26 May 2025 15:10:50 -0500 Subject: [PATCH 025/105] Update Korean translation See merge request ryubing/ryujinx!42 --- assets/locales.json | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/assets/locales.json b/assets/locales.json index aa7a0548f..08eade16e 100644 --- a/assets/locales.json +++ b/assets/locales.json @@ -1959,7 +1959,7 @@ "he_IL": "", "it_IT": "Tempo totale di gioco: {0}", "ja_JP": "", - "ko_KR": "", + "ko_KR": "총 플레이 시간 : {0}", "no_NO": "", "pl_PL": "Całkowity czas gry: {0}", "pt_BR": "Tempo total de jogo: {0}", @@ -3159,7 +3159,7 @@ "he_IL": "{1}/{0} משחקים נטענו", "it_IT": "{0}/{1} giochi caricati", "ja_JP": "{0}/{1} ゲーム", - "ko_KR": "{0}/{1}개의 게임 불러옴", + "ko_KR": "{0}/{1}개의 게임 확인", "no_NO": "{0}/{1} Spill Lastet", "pl_PL": "{0}/{1} Załadowane gry", "pt_BR": "{0}/{1} Jogos Carregados", @@ -16434,7 +16434,7 @@ "he_IL": "מצב עגינה גורם למערכת המדומה להתנהג כ-נינטנדו סוויץ' בתחנת עגינתו. זה משפר את הנאמנות הגרפית ברוב המשחקים.\n לעומת זאת, השבתה של תכונה זו תגרום למערכת המדומה להתנהג כ- נינטנדו סוויץ' נייד, ולהפחית את איכות הגרפיקה.\n\nהגדירו את שלט שחקן 1 אם אתם מתכננים להשתמש במצב עגינה; הגדירו את פקדי כף היד אם אתם מתכננים להשתמש במצב נייד.\n\nמוטב להשאיר דלוק אם אתם לא בטוחים.", "it_IT": "La modalità TV fa sì che il sistema emulato si comporti come una Nintendo Switch posizionata nella sua base. Ciò migliora la qualità grafica nella maggior parte dei giochi. Al contrario, disabilitandola il sistema emulato si comporterà come una Nintendo Switch in modalità portatile, riducendo la qualità grafica.\n\nConfigura i controlli del giocatore 1 se intendi usare la modalità TV; configura i controlli della modalità portatile se intendi usare quest'ultima.\n\nNel dubbio, lascia l'opzione attiva.", "ja_JP": "有効にすると,ドッキングされた Nintendo Switch をエミュレートします.多くのゲームではグラフィックス品質が向上します.\n無効にすると,携帯モードの Nintendo Switch をエミュレートします.グラフィックスの品質は低下します.\n\nドッキングモード有効ならプレイヤー1の,無効なら携帯の入力を設定してください.\n\nよくわからない場合はオンのままにしてください.", - "ko_KR": "도킹 모드를 사용하면 에뮬레이트된 시스템이 도킹된 Nintendo Switch처럼 동작합니다. 이 경우, 대부분의 게임에서 그래픽 충실도를 향상시킵니다. 반대로 이 기능을 비활성화하면 에뮬레이트된 시스템이 휴대용 Nintendo Switch처럼 작동하여 그래픽 품질이 저하됩니다.\n\n도킹 모드를 사용할 계획이라면 플레이어 1 컨트롤을 구성하세요. 휴대용 모드를 사용하려는 경우 휴대용 컨트롤을 구성하십시오.\n\n모르면 켬으로 두세요.", + "ko_KR": "도킹 모드를 사용하면 에뮬레이트된 시스템이 도킹된 Nintendo Switch처럼 동작합니다. 이 경우, 대부분의 게임에서 그래픽 충실도를 향상시킵니다. 반대로 이 기능을 비활성화하면 에뮬레이트된 시스템이 휴대용 Nintendo Switch처럼 작동하여 그래픽 품질이 저하됩니다.\n\n도킹 모드를 사용할 계획이라면 플레이어 1 컨트롤을 구성하세요. 휴대용 모드를 사용하려는 경우 휴대용 컨트롤을 구성하십시오.\n\n모르면 체크 상태로 두세요.", "no_NO": "Forankret modus gjør at systemet oppføre seg som en forankret Nintendo Switch. Dette forbedrer grafikkkvaliteten i de fleste spill. Motsatt vil deaktivering av dette gjøre at systemet oppføre seg som en håndholdt Nintendo Switch, noe som reduserer grafikkkvaliteten.\n\nKonfigurer spiller 1 kontroller hvis du planlegger å bruke forankret modus; konfigurer håndholdte kontroller hvis du planlegger å bruke håndholdte modus.\n\nLa PÅ hvis du er usikker.", "pl_PL": "Tryb Zadokowany sprawia, że emulowany system zachowuje się jak zadokowany Nintendo Switch. Poprawia to jakość grafiki w większości gier. I odwrotnie, wyłączenie tej opcji sprawi, że emulowany system będzie zachowywał się jak przenośny Nintendo Switch, zmniejszając jakość grafiki.\n\nSkonfiguruj sterowanie gracza 1, jeśli planujesz używać trybu Zadokowanego; Skonfiguruj sterowanie przenośne, jeśli planujesz używać trybu przenośnego.\n\nPozostaw WŁĄCZONY, jeśli nie masz pewności.", "pt_BR": "O modo TV faz o sistema emulado se comportar como um Nintendo Switch na TV, o que melhora a fidelidade gráfica na maioria dos jogos. Por outro lado, desativar essa opção fará o sistema emulado se comportar como um Nintendo Switch portátil, reduzindo a qualidade gráfica.\n\nConfigure os controles do jogador 1 se planeja usar o modo TV; configure os controles de portátil se planeja usar o modo Portátil.\n\nMantenha ativado se estiver em dúvida.", @@ -16459,7 +16459,7 @@ "he_IL": "", "it_IT": "Supporto per l'accesso diretto alla tastiera (HID). Fornisce ai giochi l'accesso alla tastiera come dispositivo di inserimento del testo.\n\nFunziona solo con i giochi che supportano nativamente l'utilizzo della tastiera su hardware Switch.\n\nNel dubbio, lascia l'opzione disattivata.", "ja_JP": "直接キーボード アクセス (HID) のサポートです. テキスト入力デバイスとしてキーボードへのゲームアクセスを提供します.\n\nSwitchハードウェアでキーボードの使用をネイティブにサポートしているゲームでのみ動作します.\n\nわからない場合はオフのままにしてください.", - "ko_KR": "키보드 직접 접속(HID)을 지원합니다. 텍스트 입력 장치로 키보드에 대한 게임 접속을 제공합니다.\n\nSwitch 하드웨어에서 키보드 사용을 기본적으로 지원하는 게임에서만 작동합니다.\n\n모르면 끔으로 두세요.", + "ko_KR": "키보드 직접 접속(HID)을 지원합니다. 텍스트 입력 장치로 키보드에 대한 게임 접속을 제공합니다.\n\nSwitch 하드웨어에서 키보드 사용을 기본적으로 지원하는 게임에서만 작동합니다.\n\n모르면 체크 해제 상태로 두세요.", "no_NO": "Direkte tastaturtilgang (HID) støtte. Gir deg spill-tilgang til tastaturet som en tekstinnlegg-enhet.\n\nfungerer kun med spill som lokalt støtter tastaturbruk på Ninteno SwitchTM maskinvare.\n\nLa være AV hvis du er usikker.", "pl_PL": "Obsługa bezpośredniego dostępu do klawiatury (HID). Zapewnia dostęp gier do klawiatury jako urządzenia do wprowadzania tekstu.\n\nDziała tylko z grami, które natywnie wspierają użycie klawiatury w urządzeniu Switch hardware.\n\nPozostaw wyłączone w razie braku pewności.", "pt_BR": "Suporte para acesso direto ao teclado (HID). Permite que os jogos acessem seu teclado como um dispositivo de entrada de texto.\n\nFunciona apenas com jogos que suportam o uso de teclado nativamente no hardware do Switch.\n\nDeixe desativado se estiver em dúvida.", @@ -16484,7 +16484,7 @@ "he_IL": "", "it_IT": "Supporto per l'accesso diretto al mouse (HID). Fornisce ai giochi l'accesso al mouse come dispositivo di puntamento.\n\nFunziona solo con i rari giochi che supportano nativamente l'utilizzo del mouse su hardware Switch.\n\nQuando questa opzione è attivata, il touchscreen potrebbe non funzionare.\n\nNel dubbio, lascia l'opzione disattivata.", "ja_JP": "直接マウスアクセス (HID) のサポートです. ポインティングデバイスとしてマウスへのゲームアクセスを提供します.\n\nSwitchハードウェアでマウスの使用をネイティブにサポートしているゲームでのみ動作します.\n\n有効にしている場合, タッチスクリーン機能は動作しない場合があります.\n\nわからない場合はオフのままにしてください.", - "ko_KR": "마우스 직접 접속(HID)을 지원합니다. 마우스에 대한 게임 접속을 포인팅 장치로 제공합니다.\n\nSwitch 하드웨어에서 마우스 컨트롤을 기본적으로 지원하는 게임에서만 작동하며 거의 없습니다.\n\n활성화하면 터치 스크린 기능이 작동하지 않을 수 있습니다.\n\n모르면 끔으로 두세요.", + "ko_KR": "마우스 직접 접속(HID)을 지원합니다. 마우스에 대한 게임 접속을 포인팅 장치로 제공합니다.\n\nSwitch 하드웨어에서 마우스 컨트롤을 기본적으로 지원하는 게임에서만 작동하며 거의 없습니다.\n\n활성화하면 터치 스크린 기능이 작동하지 않을 수 있습니다.\n\n모르면 체크 해제 상태로 두세요.", "no_NO": "Direkte musepeker (HID) støtte. Gir deg spill-tilgang til musepeker.\n\nfungerer kun med spill som lokalt støtter musepekere på Ninteno SwitchTM maskinvare.\n\nNår aktivert, kan det hende touch funksjoner ikke fungerer\n\nLa være AV hvis du er usikker.", "pl_PL": "Obsługa bezpośredniego dostępu do myszy (HID). Zapewnia dostęp gier do myszy jako urządzenia wskazującego.\n\nDziała tylko z grami, które natywnie obsługują przyciski myszy w urządzeniu Switch, które są nieliczne i daleko między nimi.\n\nPo włączeniu funkcja ekranu dotykowego może nie działać.\n\nPozostaw wyłączone w razie wątpliwości.", "pt_BR": "Suporte para acesso direto ao mouse (HID). Permite que os jogos acessem seu mouse como um dispositivo de apontamento.\n\nFunciona apenas com jogos que suportam controles de mouse nativamente no hardware do Switch, o que é raro.\n\nQuando ativado, a funcionalidade de tela sensível ao toque pode não funcionar.\n\nDeixe desativado se estiver em dúvida.", @@ -16634,7 +16634,7 @@ "he_IL": "", "it_IT": "Sincronizzazione verticale della console emulata. Funziona essenzialmente come un limitatore del framerate per la maggior parte dei giochi; disabilitarla può far girare giochi a velocità più alta, allungare le schermate di caricamento o farle bloccare.\n\nPuò essere attivata mentre giochi con un tasto di scelta rapida (F1 per impostazione predefinita). Ti consigliamo di farlo se hai intenzione di disabilitarla.\n\nNel dubbio, lascia l'opzione attiva.", "ja_JP": "エミュレートされたゲーム機の垂直同期です. 多くのゲームにおいて, フレームリミッタとして機能します. 無効にすると, ゲームが高速で実行されたり, ロード中に時間がかかったり, 止まったりすることがあります.\n\n設定したホットキー(デフォルトではF1)で, ゲーム内で切り替え可能です. 無効にする場合は, この操作を行うことをおすすめします.\n\nよくわからない場合はオンのままにしてください.", - "ko_KR": "에뮬레이트된 콘솔의 수직 동기화입니다. 기본적으로 대부분의 게임에서 프레임 제한 기능으로, 비활성화하면 게임이 더 빠른 속도로 실행되거나 로딩 화면이 더 오래 걸리거나 멈출 수 있습니다.\n\n게임 내에서 원하는 단축키(기본값은 F1)로 전환할 수 있습니다. 비활성화하려면 이 작업을 수행하는 것이 좋습니다.\n\n모르면 켬으로 두세요.", + "ko_KR": "에뮬레이트된 콘솔의 수직 동기화입니다. 기본적으로 대부분의 게임에서 프레임 제한 기능으로, 비활성화하면 게임이 더 빠른 속도로 실행되거나 로딩 화면이 더 오래 걸리거나 멈출 수 있습니다.\n\n게임 내에서 원하는 단축키(기본값은 F1)로 전환할 수 있습니다. 비활성화하려면 이 작업을 수행하는 것이 좋습니다.\n\n모르면 체크 상태로 두세요.", "no_NO": "Emuler konsollens loddrett synkronisering. på ett vis en bildefrekvens begrensning for de fleste spill; deaktivering kan få spill til å kjøre med høyere hastighet, eller til å laste skjermene tar lengre tid eller sitter fast.\n\nkan byttes inn i spillet med en hurtigtast for preferansen (F1 som standard). Vi anbefaler å gjøre dette hvis du planlegger å deaktivere dette.\n\nLa være PÅ hvis du er usikker.", "pl_PL": "Synchronizacja pionowa emulowanej konsoli. Zasadniczo ogranicznik klatek dla większości gier; wyłączenie jej może spowodować, że gry będą działać z większą szybkością, ekrany wczytywania wydłużą się lub nawet utkną.\n\nMoże być przełączana w grze za pomocą preferowanego skrótu klawiszowego. Zalecamy to zrobić, jeśli planujesz ją wyłączyć.\n\nW razie wątpliwości pozostaw WŁĄCZONĄ.", "pt_BR": "V-Sync do console emulado. Funciona essencialmente como um limitador de quadros para a maioria dos jogos; desativá-lo pode fazer com que os jogos rodem em uma velocidade mais alta ou que telas de carregamento demorem mais ou travem.\n\nPode ser alternado durante o jogo com uma tecla de atalho de sua preferência (F1 por padrão). Recomendamos isso caso planeje desativá-lo.\n\nMantenha ligado se estiver em dúvida.", @@ -16659,7 +16659,7 @@ "he_IL": "שומר את פונקציות ה-JIT המתורגמות כך שלא יצטרכו לעבור תרגום שוב כאשר משחק עולה.\n\nמפחית תקיעות ומשפר מהירות עלייה של המערכת אחרי הפתיחה הראשונה של המשחק.\n\nמוטב להשאיר דלוק אם לא בטוחים.", "it_IT": "Salva le funzioni JIT tradotte in modo che non debbano essere tradotte tutte le volte che si avvia un determinato gioco.\n\nRiduce i fenomeni di stuttering e velocizza sensibilmente gli avvii successivi del gioco.\n\nNel dubbio, lascia l'opzione attiva.", "ja_JP": "翻訳されたJIT関数をセーブすることで, ゲームをロードするたびに毎回翻訳する処理を不要とします.\n\n一度ゲームを起動すれば,二度目以降の起動時遅延を大きく軽減できます.\n\nよくわからない場合はオンのままにしてください.", - "ko_KR": "번역된 JIT 함수를 저장하여 게임을 불러올 때마다 번역할 필요가 없도록 합니다.\n\n게임을 처음 부팅한 후 끊김 현상을 줄이고 부팅 시간을 크게 단축합니다.\n\n모르면 켬으로 두세요.", + "ko_KR": "번역된 JIT 함수를 저장하여 게임을 불러올 때마다 번역할 필요가 없도록 합니다.\n\n게임을 처음 부팅한 후 끊김 현상을 줄이고 부팅 시간을 크게 단축합니다.\n\n모르면 체크 상태로 두세요.", "no_NO": "Lagrer oversatte JIT funksjoner så de ikke trenger og bli oversatt hver gang spillet laster.\n\nKan redusere hakkete spilling og gjør at spillet starter opp raskere ved første oppstart.\n\nLa være PÅ om usikker.", "pl_PL": "Zapisuje przetłumaczone funkcje JIT, dzięki czemu nie muszą być tłumaczone za każdym razem, gdy gra się ładuje.\n\nZmniejsza zacinanie się i znacznie przyspiesza uruchamianie po pierwszym uruchomieniu gry.\n\nJeśli nie masz pewności, pozostaw WŁĄCZONE", "pt_BR": "Salva funções JIT traduzidas para que elas não precisem ser traduzidas toda vez que o jogo for carregado.\n\nReduz a trepidação e acelera significativamente os tempos de inicialização após a primeira inicialização de um jogo.\n\nDeixe LIGADO se não tiver certeza.", @@ -16709,7 +16709,7 @@ "he_IL": "בודק לקבצים שגויים כאשר משחק עולה, ואם מתגלים כאלו, מציג את מזהה השגיאה שלהם לקובץ הלוג.\n\nאין לכך השפעה על הביצועים ונועד לעזור לבדיקה וניפוי שגיאות של האמולטור.\n\nמוטב להשאיר דלוק אם לא בטוחים.", "it_IT": "Controlla la presenza di file corrotti quando si avvia un gioco. Se vengono rilevati dei file corrotti, verrà mostrato un errore di hash nel log.\n\nQuesta opzione non influisce sulle prestazioni ed è pensata per facilitare la risoluzione dei problemi.\n\nNel dubbio, lascia l'opzione attiva.", "ja_JP": "ゲーム起動時にファイル破損をチェックし,破損が検出されたらログにハッシュエラーを表示します..\n\nパフォーマンスには影響なく, トラブルシューティングに役立ちます.\n\nよくわからない場合はオンのままにしてください.", - "ko_KR": "게임을 부팅할 때 손상된 파일을 확인하고, 손상된 파일이 감지되면 로그에 해시 오류를 표시합니다.\n\n성능에 영향을 미치지 않으며 문제 해결에 도움이 됩니다.\n\n모르면 켬으로 두세요.", + "ko_KR": "게임을 부팅할 때 손상된 파일을 확인하고, 손상된 파일이 감지되면 로그에 해시 오류를 표시합니다.\n\n성능에 영향을 미치지 않으며 문제 해결에 도움이 됩니다.\n\n모르면 체크 상태로 두세요.", "no_NO": "Sjekker for korrupte filer ved oppstart av et spill, og dersom korrupte filer oppdages, viser en hashfeil i loggen.\n\nhar ingen innvirkning på ytelsen og er ment å hjelpe med feilsøking.\n\nLa være PÅ hvis usikker.", "pl_PL": "Sprawdza pliki podczas uruchamiania gry i jeśli zostaną wykryte uszkodzone pliki, wyświetla w dzienniku błąd hash.\n\nNie ma wpływu na wydajność i ma pomóc w rozwiązywaniu problemów.\n\nPozostaw WŁĄCZONE, jeśli nie masz pewności.", "pt_BR": "Verifica se há arquivos corrompidos ao inicializar um jogo e, se forem detectados, exibe um erro de hash no log.\n\nNão tem impacto no desempenho e tem como objetivo ajudar na solução de problemas.\n\nDeixe LIGADO se não tiver certeza.", @@ -16884,7 +16884,7 @@ "he_IL": "מנצל תצורת מצב-זיכרון חלופית לחכות את מכשיר הפיתוח של הסוויץ'.\n\nזה שימושי להחלפת חבילות מרקמים באיכותיים יותר או כאלו ברזולוציית 4k. לא משפר ביצועים.\n\nמוטב להשאיר כבוי אם לא בטוחים.", "it_IT": "Utilizza un layout di memoria alternativo per imitare un'unità di sviluppo di Switch.\n\nQuesta opzione è utile soltanto per i pacchetti di texture ad alta risoluzione o per le mod che aumentano la risoluzione a 4K. NON migliora le prestazioni.\n\nNel dubbio, lascia l'opzione disattivata.", "ja_JP": "エミュレートされたシステムのメモリ容量を 4GiB から 6GiB に増加します.\n\n高解像度のテクスチャパックや 4K解像度の mod を使用する場合に有用です. パフォーマンスを改善するものではありません.\n\nよくわからない場合はオフのままにしてください.", - "ko_KR": "Switch 개발 모델을 모방하기 위해 8GB DRAM이 포함된 대체 메모리 모드를 활용합니다.\n\n이는 고해상도 텍스처 팩 또는 4K 해상도 모드에만 유용합니다. 성능을 개선하지 않습니다.\n\n모르면 끔으로 두세요.", + "ko_KR": "Switch 개발 모델을 모방하기 위해 8GB DRAM이 포함된 대체 메모리 모드를 활용합니다.\n\n이는 고해상도 텍스처 팩 또는 4K 해상도 모드에만 유용합니다. 성능을 개선하지 않습니다.\n\n모르면 체크 해제 상태로 두세요.", "no_NO": "Bruker en alternativ minnemodus med 8GiB i DRAM for og etterligne Switch utvikler modeller.\n\nDette er bare nyttig for teksturpakker eller 4k oppløsningsmoduler. Forbedrer IKKE ytelsen.\n\nLa AV hvis usikker.", "pl_PL": "Wykorzystuje alternatywny układ MemoryMode, aby naśladować model rozwojowy Switcha.\n\nJest to przydatne tylko w przypadku pakietów tekstur o wyższej rozdzielczości lub modów w rozdzielczości 4k. NIE poprawia wydajności.\n\nW razie wątpliwości pozostaw WYŁĄCZONE.", "pt_BR": "Utiliza um modo de memória alternativo com 6, 8 ou 12 GB de DRAM para imitar um modelo de desenvolvimento do Switch.\n\nIsso só é útil para pacotes de textura de alta resolução ou mods de resolução 4k. NÃO melhora o desempenho.\n\nDeixe em 4 GB se não tiver certeza.", @@ -16909,7 +16909,7 @@ "he_IL": "מתעלם מפעולות שלא קיבלו מימוש במערכת ההפעלה Horizon OS. זה עלול לעזור לעקוף קריסות של היישום במשחקים מסויימים.\n\nמוטב להשאיר כבוי אם לא בטוחים.", "it_IT": "Ignora i servizi non implementati del sistema operativo Horizon. Può aiutare ad aggirare gli arresti anomali che si verificano avviando alcuni giochi.\n\nNel dubbio, lascia l'opzione disattivata.", "ja_JP": "未実装の Horizon OS サービスを無視します. 特定のゲームにおいて起動時のクラッシュを回避できる場合があります.\n\nよくわからない場合はオフのままにしてください.", - "ko_KR": "구현되지 않은 Horizon OS 서비스는 무시됩니다. 특정 게임을 부팅할 때, 발생하는 충돌을 우회하는 데 도움이 될 수 있습니다.\n\n모르면 끔으로 두세요.", + "ko_KR": "구현되지 않은 Horizon OS 서비스는 무시됩니다. 특정 게임을 부팅할 때, 발생하는 충돌을 우회하는 데 도움이 될 수 있습니다.\n\n모르면 체크 해제 상태로 두세요.", "no_NO": "Ignorerer ikke implementerte Horisont OS-tjenester. Dette kan hjelpe med å omgå krasj ved oppstart av enkelte spill.\n\nLa AV hvis du er usikker.", "pl_PL": "Ignoruje niezaimplementowane usługi Horizon OS. Może to pomóc w ominięciu awarii podczas uruchamiania niektórych gier.\n\nW razie wątpliwości pozostaw WYŁĄCZONE.", "pt_BR": "Ignora serviços não implementados do Horizon OS. Isso pode ajudar a contornar travamentos ao inicializar certos jogos.\n\nDeixe OFF se não tiver certeza.", @@ -16934,7 +16934,7 @@ "he_IL": "", "it_IT": "", "ja_JP": "", - "ko_KR": "앱이 실행 중일 때, 게임패드의 연결이 끊어지면 컨트롤러 애플릿 대화 상자가 나타나지 않습니다.\n\n모르시면 끔으로 두십시오.", + "ko_KR": "앱이 실행 중일 때, 게임패드의 연결이 끊어지면 컨트롤러 애플릿 대화 상자가 나타나지 않습니다.\n\n모르시면 체크 해제 상태로 두십시오.", "no_NO": "Håndkontroller-appleten vises ikke hvis gamepaden kobles fra mens et program kjører.", "pl_PL": "", "pt_BR": "A caixa de diálogo do Applet do controlador não aparecerá se o controle for desconectado enquanto um aplicativo estiver em execução.\n\nDeixe a opção DESLIGADO se não tiver certeza.", @@ -17034,7 +17034,7 @@ "he_IL": "שומר זכרון מטמון של הצללות, דבר שמפחית תקיעות בריצות מסוימות.\n\nמוטב להשאיר דלוק אם לא בטוחים.", "it_IT": "Salva una cache degli shader su disco che riduce i fenomeni di stuttering nelle esecuzioni successive.\n\nNel dubbio, lascia l'opzione attiva.", "ja_JP": "ディスクシェーダーキャッシュをセーブし,次回以降の実行時遅延を軽減します.\n\nよくわからない場合はオンのままにしてください.", - "ko_KR": "후속 실행 시 끊김 현상을 줄이는 디스크 셰이더 캐시를 저장합니다.\n\n모르면 켬으로 두세요.", + "ko_KR": "후속 실행 시 끊김 현상을 줄이는 디스크 셰이더 캐시를 저장합니다.\n\n모르면 체크 상태로 두세요.", "no_NO": "Lagrer en disk shader cache som reduserer hakking jo flere ganger du spiller.\n\nLa være PÅ om usikker.", "pl_PL": "Zapisuje pamięć podręczną shaderów na dysku, co zmniejsza zacinanie się w kolejnych uruchomieniach.\n\nPozostaw WŁĄCZONE, jeśli nie masz pewności.", "pt_BR": "Salva um cache de shader no disco que reduz a trepidação em execuções subsequentes.\n\nDeixe LIGADO se não tiver certeza.", @@ -18009,7 +18009,7 @@ "he_IL": "מאפשר ליישומים באמולצייה להתחבר לאינטרנט.\n\nמשחקים עם חיבור לאן יכולים להתחבר אחד לשני כשאופצייה זו מופעלת והמערכות מתחברות לאותה נקודת גישה. כמו כן זה כולל שורות פקודות אמיתיות גם.\n\nאופצייה זו לא מאפשרת חיבור לשרתי נינטנדו. כשהאופצייה דלוקה היא עלולה לגרום לקריסת היישום במשחקים מסויימים שמנסים להתחבר לאינטרנט.\n\nמוטב להשאיר כבוי אם לא בטוחים.", "it_IT": "Consente all'applicazione emulata di connettersi a Internet.\n\nI giochi che dispongono di una modalità LAN possono connettersi tra di loro quando questa opzione è abilitata e sono connessi alla stessa rete, comprese le console reali.\n\nQuesta opzione NON consente la connessione ai server di Nintendo. Potrebbe causare arresti anomali in alcuni giochi che provano a connettersi a Internet.\n\nNel dubbio, lascia l'opzione disattivata.", "ja_JP": "エミュレートしたアプリケーションをインターネットに接続できるようにします.\n\nLAN モードを持つゲーム同士は,この機能を有効にして同じアクセスポイントに接続すると接続できます. 実機も含まれます.\n\n任天堂のサーバーには接続できません. インターネットに接続しようとすると,特定のゲームでクラッシュすることがあります.\n\nよくわからない場合はオフのままにしてください.", - "ko_KR": "에뮬레이트된 앱을 인터넷에 연결할 수 있습니다.\n\nLAN 모드가 있는 게임은 이 기능이 활성화되고 시스템이 동일한 접속 포인트에 연결되어 있을 때 서로 연결할 수 있습니다. 이는 실제 콘솔도 포함됩니다.\n\nNintendo 서버 연결을 허용하지 않습니다. 인터넷에 연결을 시도하는 특정 게임에서 충돌이 발생할 수 있습니다.\n\n모르면 끔으로 두세요.", + "ko_KR": "에뮬레이트된 앱을 인터넷에 연결할 수 있습니다.\n\nLAN 모드가 있는 게임은 이 기능이 활성화되고 시스템이 동일한 접속 포인트에 연결되어 있을 때 서로 연결할 수 있습니다. 이는 실제 콘솔도 포함됩니다.\n\nNintendo 서버 연결을 허용하지 않습니다. 인터넷에 연결을 시도하는 특정 게임에서 충돌이 발생할 수 있습니다.\n\n모르면 체크 해제 상태로 두세요.", "no_NO": "Tillater emulert applikasjon å koble til Internett.\n\nSpill med en LAN-modus kan koble til hverandre når dette er aktivert og systemene er koblet til det samme tilgangspunktet. Dette inkluderer ekte konsoller også.\n\ntillater IKKE tilkobling til Nintendo servere. Kan forårsake krasjing i enkelte spill som prøver å koble til Internett.\n\nLa stå AV hvis du er usikker.", "pl_PL": "Pozwala emulowanej aplikacji na łączenie się z Internetem.\n\nGry w trybie LAN mogą łączyć się ze sobą, gdy ta opcja jest włączona, a systemy są połączone z tym samym punktem dostępu. Dotyczy to również prawdziwych konsol.\n\nNie pozwala na łączenie się z serwerami Nintendo. Może powodować awarie niektórych gier, które próbują połączyć się z Internetem.\n\nPozostaw WYŁĄCZONE, jeśli nie masz pewności.", "pt_BR": "Permite que o aplicativo emulado se conecte à Internet.\n\nJogos com modo LAN podem se conectar uns aos outros quando isso está habilitado e os sistemas estão conectados ao mesmo ponto de acesso. Isso inclui consoles reais também.\n\nNÃO permite a conexão com servidores Nintendo. Pode causar travamentos em certos jogos que tentam se conectar à Internet.\n\nDeixe DESLIGADO se não tiver certeza.", @@ -18209,7 +18209,7 @@ "he_IL": "מעבד", "it_IT": "", "ja_JP": "", - "ko_KR": "", + "ko_KR": "중앙처리장치", "no_NO": "Prosessor", "pl_PL": "", "pt_BR": "", @@ -22134,7 +22134,7 @@ "he_IL": "", "it_IT": "Comprime le texture ASTC per ridurre l'utilizzo di VRAM.\n\nI giochi che utilizzano questo formato di texture includono Astral Chain, Bayonetta 3, Fire Emblem Engage, Metroid Prime Remastered, Super Mario Bros. Wonder e The Legend of Zelda: Tears of the Kingdom.\n\nLe schede grafiche con 4GiB o meno di VRAM probabilmente si bloccheranno ad un certo punto durante l'esecuzione di questi giochi.\n\nAttiva questa opzione solo se sei a corto di VRAM nei giochi sopra menzionati. Nel dubbio, lascia l'opzione disattivata.", "ja_JP": "VRAM使用量を減らすためにASTCテクスチャを圧縮します.\n\nこのテクスチャフォーマットを使用するゲームには, Astral Chain, Bayonetta 3, Fire Emblem Engage, Metroid Prime Remastered, Super Mario Bros. Wonder, The Legend of Zelda: Tears of the Kingdomが含まれます.\n\nVRAMが4GB以下のグラフィックカードでは, これらのゲームを実行中にクラッシュする可能性があります.\n\n前述のゲームでVRAMが不足している場合のみ有効にしてください. 不明な場合はオフにしてください.", - "ko_KR": "VRAM 사용량을 줄이기 위해 ASTC 텍스처를 압축합니다.\n\n이 텍스처 형식을 사용하는 게임에는 Astral Chain, Bayonetta 3, Fire Emblem Engage, Metroid Prime Remastered, Super Mario Bros. Wonder, The Legend of Zelda: Tears of the Kingdom이 있습니다.\n\n4GiB VRAM 이하의 그래픽 카드는 이러한 게임을 실행하는 동안 어느 시점에서 충돌할 가능성이 있습니다.\n\n위에서 언급한 게임에서 VRAM이 부족한 경우에만 활성화합니다. 모르면 끔으로 두세요.", + "ko_KR": "VRAM 사용량을 줄이기 위해 ASTC 텍스처를 압축합니다.\n\n이 텍스처 형식을 사용하는 게임에는 애스트럴 체인, 베요네타 3, 파이어 엠블렘 인게이지, 메트로이드 프라임 리마스터, 슈퍼 마리오브라더스 원더, 젤다의 전설 티어스 오브 더 킹덤이 있습니다.\n\n4GiB VRAM 이하의 그래픽 카드는 이러한 게임을 실행하는 동안 어느 시점에서 충돌할 가능성이 있습니다.\n\n위에서 언급한 게임에서 VRAM이 부족한 경우에만 활성화합니다. 모르면 체크 해제 상태로 두세요.", "no_NO": "Kompresser ASTC-teksturer for å redusere VRAM-bruk.\n\nSpill som bruker dette teksturformatet, inkluderer Astral Chain, Bayonetta 3, Fire Emblem Engage, Metroid Prime Remastered, Super Mario Bros. Wonder and The Legend of Zelda: Tears of the Kingdom.\n\nGrafikkkort med 4GiB VRAM eller mindre, vil sannsynligvis krasje på et tidspunkt når spillene kjører.\n\nAktiver bare hvis du går tom for VRAM på nevnte spill. La AV om du er usikker.", "pl_PL": "", "pt_BR": "Compacta texturas ASTC para reduzir o uso de VRAM.\n\nJogos que usam esse formato de textura incluem Astral Chain, Bayonetta 3, Fire Emblem Engage, Metroid Prime Remastered, Super Mario Bros. Wonder e The Legend of Zelda: Tears of the Kingdom.\n\nPlacas gráficas com 4GB VRAM ou menos provavelmente travarão em algum momento durante a execução desses jogos.\n\nHabilite somente se estiver ficando sem VRAM nos jogos mencionados acima. Deixe DESLIGADO se não tiver certeza.", @@ -22384,7 +22384,7 @@ "he_IL": "אמולצייה ברמה גבוהה של כרטיס גראפי עם קוד מקרו.\n\nמשפר את ביצועי היישום אך עלול לגרום לגליצ'ים חזותיים במשחקים מסויימים.\n\nמוטב להשאיר דלוק אם אינך בטוח.", "it_IT": "Emulazione di alto livello del codice macro della GPU.\n\nMigliora le prestazioni, ma può causare anomalie grafiche in alcuni giochi.\n\nNel dubbio, lascia l'opzione attiva.", "ja_JP": "GPU マクロコードの高レベルエミュレーションです.\n\nパフォーマンスを向上させますが, 一部のゲームでグラフィックに不具合が発生する可能性があります.\n\nよくわからない場合はオンのままにしてください.", - "ko_KR": "GPU 매크로 코드의 고수준 에뮬레이션입니다.\n\n성능은 향상되지만 일부 게임에서 그래픽 오류가 발생할 수 있습니다.\n\n모르면 켬으로 두세요.", + "ko_KR": "GPU 매크로 코드의 고수준 에뮬레이션입니다.\n\n성능은 향상되지만 일부 게임에서 그래픽 오류가 발생할 수 있습니다.\n\n모르면 체크 상태로 두세요.", "no_NO": "High-level emulering av GPU makrokode.\n\nForbedrer ytelse, men kan forårsake grafiske glitches i noen spill.\n\nForlat PÅ hvis usikker.", "pl_PL": "Wysokopoziomowa emulacja kodu GPU Macro.\n\nPoprawia wydajność, ale może powodować błędy graficzne w niektórych grach.\n\nW razie wątpliwości pozostaw WŁĄCZONE.", "pt_BR": "Habilita emulação de alto nível de códigos Macro da GPU.\n\nMelhora a performance, mas pode causar problemas gráficos em alguns jogos.\n\nEm caso de dúvida, deixe ATIVADO.", @@ -23284,7 +23284,7 @@ "he_IL": "", "it_IT": "", "ja_JP": "", - "ko_KR": "", + "ko_KR": "변경 로그 보기", "no_NO": "", "pl_PL": "", "pt_BR": "", @@ -23934,7 +23934,7 @@ "he_IL": "", "it_IT": "Consente all'utente di specificare una frequenza di aggiornamento emulata. In alcuni titoli potrebbe aumentare o diminuire la velocità del gameplay, mentre in altri potrebbe consentire di limitare il framerate a un multiplo della frequenza di aggiornamento, o causare comportamenti imprevedibili. Questa funzionalità è sperimentale, e non ci sono certezze sul modo in cui influenzerà il gameplay.\n\nNel dubbio, lascia l'opzione disattivata.", "ja_JP": "", - "ko_KR": "사용자가 에뮬레이트된 화면 주사율을 지정할 수 있습니다. 일부 타이틀에서는 게임플레이 로직 속도가 빨라지거나 느려질 수 있습니다. 다른 타이틀에서는 주사율의 배수로 FPS를 제한하거나 예측할 수 없는 동작으로 이어질 수 있습니다. 이는 실험적 기능으로 게임 플레이에 어떤 영향을 미칠지 보장할 수 없습니다. \n\n모르면 끔으로 두세요.", + "ko_KR": "사용자가 에뮬레이트된 화면 주사율을 지정할 수 있습니다. 일부 타이틀에서는 게임플레이 로직 속도가 빨라지거나 느려질 수 있습니다. 다른 타이틀에서는 주사율의 배수로 FPS를 제한하거나 예측할 수 없는 동작으로 이어질 수 있습니다. 이는 실험적 기능으로 게임 플레이에 어떤 영향을 미칠지 보장할 수 없습니다. \n\n모르면 체크 해제 상태로 두세요.", "no_NO": "Gjør det mulig for brukeren å angi en emulert oppdateringsfrekvens. I noen titler kan dette øke eller senke hastigheten på spillogikken. I andre titler kan det gjøre det mulig å begrense FPS til et multiplum av oppdateringsfrekvensen, eller føre til uforutsigbar oppførsel. Dette er en eksperimentell funksjon, og det gis ingen garantier for hvordan spillingen påvirkes. \n\nLa AV stå hvis du er usikker.", "pl_PL": "", "pt_BR": "Permite que o usuário especifique uma taxa de atualização emulada. Em alguns títulos, isso pode acelerar ou desacelerar a taxa de lógica do jogo. Em outros títulos, pode permitir limitar o FPS em algum múltiplo da taxa de atualização ou levar a um comportamento imprevisível. Este é um recurso experimental, sem garantias de como o jogo será afetado. \n\nDeixe OFF se não tiver certeza.", From f14d65b543bac6d24bf3b6a957ef9b59a297906e Mon Sep 17 00:00:00 2001 From: GreemDev Date: Mon, 26 May 2025 17:00:54 -0500 Subject: [PATCH 026/105] update changelog --- CHANGELOG.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index dd0f2ccfa..9dac7f328 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,8 +2,10 @@ All updates to this Ryujinx branch will be documented in this file. +## [1.3.1]() - 2025-04-23 +A list of notable changes can be found on the release linked in the version number above. -## [1.2.86]() - 2025-03-13 +## [1.2.86]() - 2025-03-13 A list of notable changes can be found on the release linked in the version number above. ## [1.2.82]() - 2025-02-16 From 1d923ba7b0837c05d0a2e206be5a253ee167a905 Mon Sep 17 00:00:00 2001 From: MrKev <41-mrkev@users.noreply.git.ryujinx.app> Date: Tue, 27 May 2025 16:46:54 -0500 Subject: [PATCH 027/105] =?UTF-8?q?Fix=20JWT=20Claims=20and=20Socket=20Fla?= =?UTF-8?q?g=20Handling=20to=20Improve=20Just=20Dance=C2=AE=20Server=20Con?= =?UTF-8?q?nection?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit See merge request ryubing/ryujinx!38 --- .../Services/Account/Acc/AccountService/ManagerServer.cs | 7 ++++--- src/Ryujinx.HLE/HOS/Services/Sockets/Bsd/IClient.cs | 6 ++++-- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/src/Ryujinx.HLE/HOS/Services/Account/Acc/AccountService/ManagerServer.cs b/src/Ryujinx.HLE/HOS/Services/Account/Acc/AccountService/ManagerServer.cs index 2f0454a89..8c86788b1 100644 --- a/src/Ryujinx.HLE/HOS/Services/Account/Acc/AccountService/ManagerServer.cs +++ b/src/Ryujinx.HLE/HOS/Services/Account/Acc/AccountService/ManagerServer.cs @@ -5,6 +5,7 @@ using Ryujinx.HLE.HOS.Kernel.Threading; using Ryujinx.HLE.HOS.Services.Account.Acc.AsyncContext; using System; using System.Collections.Generic; +using System.Security.Claims; using System.Security.Cryptography; using System.Security.Principal; using System.Text; @@ -38,7 +39,7 @@ namespace Ryujinx.HLE.HOS.Services.Account.Acc.AccountService RsaSecurityKey secKey = new(parameters); - SigningCredentials credentials = new(secKey, "RS256"); + SigningCredentials credentials = new(secKey, SecurityAlgorithms.RsaSha256); credentials.Key.KeyId = parameters.ToString(); @@ -49,11 +50,11 @@ namespace Ryujinx.HLE.HOS.Services.Account.Acc.AccountService RandomNumberGenerator.Fill(deviceId); byte[] deviceAccountId = new byte[0x10]; - RandomNumberGenerator.Fill(deviceId); + RandomNumberGenerator.Fill(deviceAccountId); SecurityTokenDescriptor descriptor = new() { - Subject = new GenericIdentity(Convert.ToHexString(rawUserId).ToLower()), + Subject = new ClaimsIdentity([new Claim(JwtRegisteredClaimNames.Sub, Convert.ToHexString(rawUserId).ToLower())]), SigningCredentials = credentials, Audience = "ed9e2f05d286f7b8", Issuer = "https://e0d67c509fb203858ebcb2fe3f88c2aa.baas.nintendo.com", diff --git a/src/Ryujinx.HLE/HOS/Services/Sockets/Bsd/IClient.cs b/src/Ryujinx.HLE/HOS/Services/Sockets/Bsd/IClient.cs index 0a592d542..d4beb066c 100644 --- a/src/Ryujinx.HLE/HOS/Services/Sockets/Bsd/IClient.cs +++ b/src/Ryujinx.HLE/HOS/Services/Sockets/Bsd/IClient.cs @@ -876,13 +876,15 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd { errno = LinuxError.SUCCESS; + // F_GETFL if (cmd == 0x3) { result = !socket.Blocking ? 0x800 : 0; } - else if (cmd == 0x4 && arg == 0x800) + // F_SETFL + else if (cmd == 0x4) { - socket.Blocking = false; + socket.Blocking = (arg & 0x800) != 0; result = 0; } else From cf0185da17bfba62c955d7141384a833778613de Mon Sep 17 00:00:00 2001 From: GreemDev Date: Tue, 27 May 2025 22:56:45 -0500 Subject: [PATCH 028/105] Add LotP to About window --- src/Ryujinx/UI/ViewModels/AboutWindowViewModel.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Ryujinx/UI/ViewModels/AboutWindowViewModel.cs b/src/Ryujinx/UI/ViewModels/AboutWindowViewModel.cs index 734647690..e3225d19d 100644 --- a/src/Ryujinx/UI/ViewModels/AboutWindowViewModel.cs +++ b/src/Ryujinx/UI/ViewModels/AboutWindowViewModel.cs @@ -14,8 +14,8 @@ namespace Ryujinx.Ava.UI.ViewModels [ObservableProperty] private Bitmap _gitLabLogo; [ObservableProperty] private Bitmap _discordLogo; [ObservableProperty] private string _version; - - public string Developers => "GreemDev"; + + public string Developers => "GreemDev, LotP"; public string FormerDevelopers => LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.AboutPageDeveloperListMore, "gdkchan, Ac_K, marysaka, rip in peri peri, LDj3SNuD, emmaus, Thealexbarney, GoffyDude, TSRBerry, IsaacMarovitz"); From be6919d9312c7fd2df8c17c2bc116dc31457df01 Mon Sep 17 00:00:00 2001 From: GreemDev Date: Tue, 27 May 2025 23:20:51 -0500 Subject: [PATCH 029/105] cpu: turbo: Increase Turbo cap to 1000% and remove the discrepancy between the slider and number box max values. --- src/Ryujinx/UI/Views/Settings/SettingsCPUView.axaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Ryujinx/UI/Views/Settings/SettingsCPUView.axaml b/src/Ryujinx/UI/Views/Settings/SettingsCPUView.axaml index b3a4b66f9..0be13d9a5 100644 --- a/src/Ryujinx/UI/Views/Settings/SettingsCPUView.axaml +++ b/src/Ryujinx/UI/Views/Settings/SettingsCPUView.axaml @@ -109,7 +109,7 @@ SimpleNumberFormat="F0" SpinButtonPlacementMode="Hidden" Minimum="50" - Maximum="300" /> + Maximum="1000" /> + Maximum="1000" /> From cd72ba00757862986b484b8c9911ba8adba56e8a Mon Sep 17 00:00:00 2001 From: GreemDev Date: Tue, 27 May 2025 23:46:43 -0500 Subject: [PATCH 030/105] headless: Load global input configs by default. Added an option `--disable-main-input-config` to disable this behavior. --- src/Ryujinx/Headless/HeadlessRyujinx.cs | 4 +--- src/Ryujinx/Headless/Options.cs | 3 +++ 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/Ryujinx/Headless/HeadlessRyujinx.cs b/src/Ryujinx/Headless/HeadlessRyujinx.cs index cb35fc661..288b6ecce 100644 --- a/src/Ryujinx/Headless/HeadlessRyujinx.cs +++ b/src/Ryujinx/Headless/HeadlessRyujinx.cs @@ -165,10 +165,8 @@ namespace Ryujinx.Headless ReloadConfig(); - if (option.InheritConfig) - { + if (!option.DisableMainInputConfig) option.InheritMainConfigInput(originalArgs, ConfigurationState.Instance); - } _virtualFileSystem = VirtualFileSystem.CreateInstance(); _libHacHorizonManager = new LibHacHorizonManager(); diff --git a/src/Ryujinx/Headless/Options.cs b/src/Ryujinx/Headless/Options.cs index 27df69e5b..162758afa 100644 --- a/src/Ryujinx/Headless/Options.cs +++ b/src/Ryujinx/Headless/Options.cs @@ -193,6 +193,9 @@ namespace Ryujinx.Headless [Option("use-main-config", Required = false, Default = false, HelpText = "Use the settings from what was configured via the UI.")] public bool InheritConfig { get; set; } + + [Option("disable-main-input-config", Required = false, Default = false, HelpText = "Do not use the input-related settings from what was configured via the UI.")] + public bool DisableMainInputConfig { get; set; } [Option("root-data-dir", Required = false, HelpText = "Set the custom folder path for Ryujinx data.")] public string BaseDataDir { get; set; } From 68733038642540f802c02887108bd33a5b76d69a Mon Sep 17 00:00:00 2001 From: GreemDev Date: Wed, 28 May 2025 00:12:55 -0500 Subject: [PATCH 031/105] UI: Show "Paused" in place of FPS and FIFO when emulation is paused. --- src/Ryujinx/Systems/AppHost.cs | 4 ++-- src/Ryujinx/UI/Views/Main/MainStatusBarView.axaml | 9 ++++++++- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/src/Ryujinx/Systems/AppHost.cs b/src/Ryujinx/Systems/AppHost.cs index 7b07000b4..c20b89b5e 100644 --- a/src/Ryujinx/Systems/AppHost.cs +++ b/src/Ryujinx/Systems/AppHost.cs @@ -1116,8 +1116,8 @@ namespace Ryujinx.Ava.Systems LocaleManager.Instance[LocaleKeys.VolumeShort] + $": {(int)(Device.GetVolume() * 100)}%", dockedMode, ConfigurationState.Instance.Graphics.AspectRatio.Value.ToText(), - FormatGameFrameRate(), - Device.Statistics.FormatFifoPercent(), + Device.System.IsPaused ? LocaleManager.GetUnformatted(LocaleKeys.Paused) : FormatGameFrameRate(), + Device.System.IsPaused ? string.Empty : Device.Statistics.FormatFifoPercent(), _displayCount)); } diff --git a/src/Ryujinx/UI/Views/Main/MainStatusBarView.axaml b/src/Ryujinx/UI/Views/Main/MainStatusBarView.axaml index 296936565..b649ae767 100644 --- a/src/Ryujinx/UI/Views/Main/MainStatusBarView.axaml +++ b/src/Ryujinx/UI/Views/Main/MainStatusBarView.axaml @@ -249,7 +249,14 @@ IsVisible="{Binding !ShowLoadProgress}" Text="{Binding GameStatusText}" TextAlignment="Start" /> - + + + + + + + + Date: Wed, 28 May 2025 00:13:27 -0500 Subject: [PATCH 032/105] UI: RPC: link to release channels on logo in RPC --- src/Ryujinx/Systems/DiscordIntegrationModule.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Ryujinx/Systems/DiscordIntegrationModule.cs b/src/Ryujinx/Systems/DiscordIntegrationModule.cs index 8a3b42ac8..437d35ec1 100644 --- a/src/Ryujinx/Systems/DiscordIntegrationModule.cs +++ b/src/Ryujinx/Systems/DiscordIntegrationModule.cs @@ -23,7 +23,7 @@ namespace Ryujinx.Ava.Systems private static readonly string _description = ReleaseInformation.IsValid - ? $"{VersionString} {ReleaseInformation.ReleaseChannelOwner}/{ReleaseInformation.ReleaseChannelSourceRepo}" + ? $"{VersionString} {ReleaseInformation.ReleaseChannelOwner}/{ReleaseInformation.ReleaseChannelRepo}" : "dev build"; private const string ApplicationId = "1293250299716173864"; From a32a87e0c9a4a9433bb6b1f6320326fb56be1bfc Mon Sep 17 00:00:00 2001 From: KeatonTheBot Date: Wed, 28 May 2025 05:59:16 -0500 Subject: [PATCH 033/105] Workaround undefined behavior in bad dual source blend states See merge request ryubing/ryujinx!4 --- .../CodeGen/Glsl/Declarations.cs | 8 ++----- .../Translation/Translator.cs | 22 ++++++++++++++++--- 2 files changed, 21 insertions(+), 9 deletions(-) diff --git a/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/Declarations.cs b/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/Declarations.cs index 2677cba07..335222cee 100644 --- a/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/Declarations.cs +++ b/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/Declarations.cs @@ -512,13 +512,9 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl if (context.Definitions.Stage == ShaderStage.Fragment && context.Definitions.DualSourceBlend) { IoDefinition firstOutput = outputs.ElementAtOrDefault(0); - IoDefinition secondOutput = outputs.ElementAtOrDefault(1); - if (firstOutput.Location + 1 == secondOutput.Location) - { - DeclareOutputDualSourceBlendAttribute(context, firstOutput.Location); - outputs = outputs.Skip(2); - } + DeclareOutputDualSourceBlendAttribute(context, firstOutput.Location); + outputs = outputs.Skip(2); } foreach (IoDefinition ioDefinition in outputs) diff --git a/src/Ryujinx.Graphics.Shader/Translation/Translator.cs b/src/Ryujinx.Graphics.Shader/Translation/Translator.cs index 7f276044a..2a1110632 100644 --- a/src/Ryujinx.Graphics.Shader/Translation/Translator.cs +++ b/src/Ryujinx.Graphics.Shader/Translation/Translator.cs @@ -181,13 +181,29 @@ namespace Ryujinx.Graphics.Shader.Translation private static void EmitOutputsInitialization(EmitterContext context, AttributeUsage attributeUsage, IGpuAccessor gpuAccessor, ShaderStage stage) { - // Compute has no output attributes, and fragment is the last stage, so we - // don't need to initialize outputs on those stages. - if (stage == ShaderStage.Compute || stage == ShaderStage.Fragment) + // Compute has no output attributes, so we + // don't need to initialize outputs on that stage. + if (stage == ShaderStage.Compute) { return; } + if (stage == ShaderStage.Fragment) + { + // Fragment is the last stage, so we don't need to + // initialize outputs unless we're using DSB, in which + // we need to make sure the ouput has a valid value. + if (gpuAccessor.QueryGraphicsState().DualSourceBlendEnable) + { + for (int i = 0; i < 4; i++) + { + context.Store(StorageKind.Output, IoVariable.FragmentOutputColor, null, Const(1), Const(i), ConstF(0)); + } + } + + return; + } + if (stage == ShaderStage.Vertex) { InitializeVertexOutputs(context); From 1156307ef913b1cd86ee083b7c8a0526c68c9567 Mon Sep 17 00:00:00 2001 From: GreemDev Date: Wed, 28 May 2025 23:35:44 -0500 Subject: [PATCH 034/105] PPTC: fix rare EndOfStreamException in ContainsBlacklistedFunctions --- src/ARMeilleure/Translation/PTC/Ptc.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ARMeilleure/Translation/PTC/Ptc.cs b/src/ARMeilleure/Translation/PTC/Ptc.cs index 72f9d5a0a..33e46973a 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; index++) { InfoEntry infoEntry = DeserializeStructure(_infosStream); foreach (ulong address in blacklist) @@ -201,7 +201,7 @@ namespace ARMeilleure.Translation.PTC if (infoEntry.Address == address) { containsBlacklistedFunctions = true; - Logger.Warning?.Print(LogClass.Ptc, "PPTC cache invalidated: Found blacklisted functions in PPTC cache"); + Logger.Warning?.Print(LogClass.Ptc, "Translation cache invalidated: Found blacklisted functions"); foundBadFunction = true; break; } From 9233fe86b03472e6537d853d11cdfe64faf5d09d Mon Sep 17 00:00:00 2001 From: GreemDev Date: Wed, 28 May 2025 23:52:06 -0500 Subject: [PATCH 035/105] [ci skip] infra: After a quick test, ARMeilleure didn't even use anything from Ryujinx.Common. --- BuildAndPushLibraries.sh | 1 - src/ARMeilleure/ARMeilleure.csproj | 1 - 2 files changed, 2 deletions(-) diff --git a/BuildAndPushLibraries.sh b/BuildAndPushLibraries.sh index e5455e09b..4bd6cfc55 100644 --- a/BuildAndPushLibraries.sh +++ b/BuildAndPushLibraries.sh @@ -13,7 +13,6 @@ rm -rf pkgs mkdir pkgs package ARMeilleure -package Ryujinx.Common package Ryujinx.Memory dotnet nuget push pkgs/*.nupkg --source RyubingPkgs \ No newline at end of file diff --git a/src/ARMeilleure/ARMeilleure.csproj b/src/ARMeilleure/ARMeilleure.csproj index 49d0d7a3d..c3a82d4cd 100644 --- a/src/ARMeilleure/ARMeilleure.csproj +++ b/src/ARMeilleure/ARMeilleure.csproj @@ -7,7 +7,6 @@ - From 960421a7c192cc484b358fb091ce0549389f7e6e Mon Sep 17 00:00:00 2001 From: GreemDev Date: Thu, 29 May 2025 01:20:21 -0500 Subject: [PATCH 036/105] misc: Swap the context menu actions to Commands --- .../UI/Controls/ApplicationContextMenu.axaml | 78 ++- .../Controls/ApplicationContextMenu.axaml.cs | 550 +++++++++--------- src/Ryujinx/UI/Helpers/Commands.cs | 16 +- .../UI/ViewModels/MainWindowViewModel.cs | 374 ++++++++++++ 4 files changed, 695 insertions(+), 323 deletions(-) diff --git a/src/Ryujinx/UI/Controls/ApplicationContextMenu.axaml b/src/Ryujinx/UI/Controls/ApplicationContextMenu.axaml index 64b30e211..fee589297 100644 --- a/src/Ryujinx/UI/Controls/ApplicationContextMenu.axaml +++ b/src/Ryujinx/UI/Controls/ApplicationContextMenu.axaml @@ -6,140 +6,166 @@ xmlns:viewModels="clr-namespace:Ryujinx.Ava.UI.ViewModels" x:DataType="viewModels:MainWindowViewModel"> diff --git a/src/Ryujinx/UI/Controls/ApplicationContextMenu.axaml.cs b/src/Ryujinx/UI/Controls/ApplicationContextMenu.axaml.cs index 64377ba51..6f93676e2 100644 --- a/src/Ryujinx/UI/Controls/ApplicationContextMenu.axaml.cs +++ b/src/Ryujinx/UI/Controls/ApplicationContextMenu.axaml.cs @@ -1,7 +1,7 @@ using Avalonia.Controls; -using Avalonia.Interactivity; using Avalonia.Markup.Xaml; using Avalonia.Platform.Storage; +using CommunityToolkit.Mvvm.Input; using LibHac.Fs; using LibHac.Tools.FsSystem.NcaUtils; using Ryujinx.Ava.Common; @@ -26,7 +26,6 @@ namespace Ryujinx.Ava.UI.Controls { public class ApplicationContextMenu : MenuFlyout { - public ApplicationContextMenu() { InitializeComponent(); @@ -36,39 +35,35 @@ namespace Ryujinx.Ava.UI.Controls { AvaloniaXamlLoader.Load(this); } + + public static RelayCommand ToggleFavorite { get; } = + Commands.CreateConditional(vm => vm?.SelectedApplication != null, + viewModel => + { + viewModel.SelectedApplication.Favorite = !viewModel.SelectedApplication.Favorite; - public void ToggleFavorite_Click(object sender, RoutedEventArgs args) - { - if (sender is not MenuItem { DataContext: MainWindowViewModel { SelectedApplication: not null } viewModel }) - return; + ApplicationLibrary.LoadAndSaveMetaData(viewModel.SelectedApplication.IdString, appMetadata => + { + appMetadata.Favorite = viewModel.SelectedApplication.Favorite; + }); - viewModel.SelectedApplication.Favorite = !viewModel.SelectedApplication.Favorite; - - ApplicationLibrary.LoadAndSaveMetaData(viewModel.SelectedApplication.IdString, appMetadata => - { - appMetadata.Favorite = viewModel.SelectedApplication.Favorite; - }); - - viewModel.RefreshView(); - } - - public void OpenUserSaveDirectory_Click(object sender, RoutedEventArgs args) - { - if (sender is MenuItem { DataContext: MainWindowViewModel { SelectedApplication: not null } viewModel }) - OpenSaveDirectory(viewModel, SaveDataType.Account, new UserId((ulong)viewModel.AccountManager.LastOpenedUser.UserId.High, (ulong)viewModel.AccountManager.LastOpenedUser.UserId.Low)); - } - - public void OpenDeviceSaveDirectory_Click(object sender, RoutedEventArgs args) - { - if (sender is MenuItem { DataContext: MainWindowViewModel { SelectedApplication: not null } viewModel }) - OpenSaveDirectory(viewModel, SaveDataType.Device, default); - } - - public void OpenBcatSaveDirectory_Click(object sender, RoutedEventArgs args) - { - if (sender is MenuItem { DataContext: MainWindowViewModel { SelectedApplication: not null } viewModel }) - OpenSaveDirectory(viewModel, SaveDataType.Bcat, default); - } + viewModel.RefreshView(); + } + ); + + public static RelayCommand OpenUserSaveDirectory { get; } = + Commands.CreateConditional(vm => vm?.SelectedApplication != null, + viewModel => + OpenSaveDirectory(viewModel, SaveDataType.Account, new UserId((ulong)viewModel.AccountManager.LastOpenedUser.UserId.High, (ulong)viewModel.AccountManager.LastOpenedUser.UserId.Low)) + ); + + public static RelayCommand OpenDeviceSaveDirectory { get; } = + Commands.CreateConditional(vm => vm?.SelectedApplication != null, + viewModel => OpenSaveDirectory(viewModel, SaveDataType.Device, default)); + + public static RelayCommand OpenBcatSaveDirectory { get; } = + Commands.CreateConditional(vm => vm?.SelectedApplication != null, + viewModel => OpenSaveDirectory(viewModel, SaveDataType.Bcat, default)); private static void OpenSaveDirectory(MainWindowViewModel viewModel, SaveDataType saveDataType, UserId userId) { @@ -76,159 +71,151 @@ namespace Ryujinx.Ava.UI.Controls ApplicationHelper.OpenSaveDir(in saveDataFilter, viewModel.SelectedApplication.Id, viewModel.SelectedApplication.ControlHolder, viewModel.SelectedApplication.Name); } - - public async void OpenTitleUpdateManager_Click(object sender, RoutedEventArgs args) - { - if (sender is MenuItem { DataContext: MainWindowViewModel { SelectedApplication: not null } viewModel }) - await TitleUpdateManagerView.Show(viewModel.ApplicationLibrary, viewModel.SelectedApplication); - } - - public async void OpenDownloadableContentManager_Click(object sender, RoutedEventArgs args) - { - if (sender is MenuItem { DataContext: MainWindowViewModel { SelectedApplication: not null } viewModel }) - await DownloadableContentManagerView.Show(viewModel.ApplicationLibrary, viewModel.SelectedApplication); - } - - public async void OpenCheatManager_Click(object sender, RoutedEventArgs args) - { - if (sender is MenuItem { DataContext: MainWindowViewModel { SelectedApplication: not null } viewModel }) - await StyleableAppWindow.ShowAsync( + + public static AsyncRelayCommand OpenTitleUpdateManager { get; } = + Commands.CreateConditional(vm => vm?.SelectedApplication != null, + viewModel => TitleUpdateManagerView.Show(viewModel.ApplicationLibrary, viewModel.SelectedApplication) + ); + + public static AsyncRelayCommand OpenDownloadableContentManager { get; } = + Commands.CreateConditional(vm => vm?.SelectedApplication != null, + viewModel => DownloadableContentManagerView.Show(viewModel.ApplicationLibrary, viewModel.SelectedApplication) + ); + + public static AsyncRelayCommand OpenCheatManager { get; } = + Commands.CreateConditional(vm => vm?.SelectedApplication != null, + viewModel => StyleableAppWindow.ShowAsync( new CheatWindow( viewModel.VirtualFileSystem, viewModel.SelectedApplication.IdString, viewModel.SelectedApplication.Name, viewModel.SelectedApplication.Path ) - ); - } + )); + + public static RelayCommand OpenModsDirectory { get; } = + Commands.CreateConditional(vm => vm?.SelectedApplication != null, + viewModel => + { + string modsBasePath = ModLoader.GetModsBasePath(); + string titleModsPath = ModLoader.GetApplicationDir(modsBasePath, viewModel.SelectedApplication.IdString); - public void OpenModsDirectory_Click(object sender, RoutedEventArgs args) - { - if (sender is not MenuItem { DataContext: MainWindowViewModel { SelectedApplication: not null } viewModel }) - return; + OpenHelper.OpenFolder(titleModsPath); + }); + + public static RelayCommand OpenSdModsDirectory { get; } = + Commands.CreateConditional(vm => vm?.SelectedApplication != null, + viewModel => + { + string sdModsBasePath = ModLoader.GetSdModsBasePath(); + string titleModsPath = ModLoader.GetApplicationDir(sdModsBasePath, viewModel.SelectedApplication.IdString); - string modsBasePath = ModLoader.GetModsBasePath(); - string titleModsPath = ModLoader.GetApplicationDir(modsBasePath, viewModel.SelectedApplication.IdString); + OpenHelper.OpenFolder(titleModsPath); + }); - OpenHelper.OpenFolder(titleModsPath); - } - - public void OpenSdModsDirectory_Click(object sender, RoutedEventArgs args) - { - if (sender is not MenuItem { DataContext: MainWindowViewModel { SelectedApplication: not null } viewModel }) - return; - - string sdModsBasePath = ModLoader.GetSdModsBasePath(); - string titleModsPath = ModLoader.GetApplicationDir(sdModsBasePath, viewModel.SelectedApplication.IdString); - - OpenHelper.OpenFolder(titleModsPath); - } - - public async void OpenModManager_Click(object sender, RoutedEventArgs args) - { - if (sender is MenuItem { DataContext: MainWindowViewModel { SelectedApplication: not null } viewModel }) + public static AsyncRelayCommand OpenModManager { get; } = + Commands.CreateConditional(vm => vm?.SelectedApplication != null, + async viewModel => + { await ModManagerView.Show( - viewModel.SelectedApplication.Id, - viewModel.SelectedApplication.IdBase, - viewModel.ApplicationLibrary, + viewModel.SelectedApplication.Id, + viewModel.SelectedApplication.IdBase, + viewModel.ApplicationLibrary, viewModel.SelectedApplication.Name); - } - - public async void PurgePtcCache_Click(object sender, RoutedEventArgs args) - { - if (sender is not MenuItem { DataContext: MainWindowViewModel { SelectedApplication: not null } viewModel }) - return; - - UserResult result = await ContentDialogHelper.CreateLocalizedConfirmationDialog( - LocaleManager.Instance[LocaleKeys.DialogWarning], - LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.DialogPPTCDeletionMessage, viewModel.SelectedApplication.Name) - ); - - if (result == UserResult.Yes) + }); + + public static AsyncRelayCommand PurgePtcCache { get; } = + Commands.CreateConditional(vm => vm?.SelectedApplication != null, + async viewModel => { - DirectoryInfo mainDir = new(Path.Combine(AppDataManager.GamesDirPath, viewModel.SelectedApplication.IdString, "cache", "cpu", "0")); - DirectoryInfo backupDir = new(Path.Combine(AppDataManager.GamesDirPath, viewModel.SelectedApplication.IdString, "cache", "cpu", "1")); + UserResult result = await ContentDialogHelper.CreateLocalizedConfirmationDialog( + LocaleManager.Instance[LocaleKeys.DialogWarning], + LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.DialogPPTCDeletionMessage, viewModel.SelectedApplication.Name) + ); - List cacheFiles = []; - - if (mainDir.Exists) + if (result == UserResult.Yes) { - cacheFiles.AddRange(mainDir.EnumerateFiles("*.cache")); - } + DirectoryInfo mainDir = new(Path.Combine(AppDataManager.GamesDirPath, viewModel.SelectedApplication.IdString, "cache", "cpu", "0")); + DirectoryInfo backupDir = new(Path.Combine(AppDataManager.GamesDirPath, viewModel.SelectedApplication.IdString, "cache", "cpu", "1")); - if (backupDir.Exists) - { - cacheFiles.AddRange(backupDir.EnumerateFiles("*.cache")); - } + List cacheFiles = []; - if (cacheFiles.Count > 0) - { - foreach (FileInfo file in cacheFiles) + if (mainDir.Exists) { - try + cacheFiles.AddRange(mainDir.EnumerateFiles("*.cache")); + } + + if (backupDir.Exists) + { + cacheFiles.AddRange(backupDir.EnumerateFiles("*.cache")); + } + + if (cacheFiles.Count > 0) + { + foreach (FileInfo file in cacheFiles) { - file.Delete(); - } - catch (Exception ex) - { - await ContentDialogHelper.CreateErrorDialog(LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.DialogPPTCDeletionErrorMessage, file.Name, ex)); + try + { + file.Delete(); + } + catch (Exception ex) + { + await ContentDialogHelper.CreateErrorDialog(LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.DialogPPTCDeletionErrorMessage, file.Name, ex)); + } } } } - } - } - - public async void NukePtcCache_Click(object sender, RoutedEventArgs args) - { - if (sender is not MenuItem { DataContext: MainWindowViewModel { SelectedApplication: not null } viewModel }) - return; - - UserResult result = await ContentDialogHelper.CreateLocalizedConfirmationDialog( - LocaleManager.Instance[LocaleKeys.DialogWarning], - LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.DialogPPTCNukeMessage, viewModel.SelectedApplication.Name) - ); - - if (result == UserResult.Yes) + }); + + public static AsyncRelayCommand NukePtcCache { get; } = + Commands.CreateConditional(vm => vm?.SelectedApplication != null, + async viewModel => { - DirectoryInfo mainDir = new(Path.Combine(AppDataManager.GamesDirPath, viewModel.SelectedApplication.IdString, "cache", "cpu", "0")); - DirectoryInfo backupDir = new(Path.Combine(AppDataManager.GamesDirPath, viewModel.SelectedApplication.IdString, "cache", "cpu", "1")); + UserResult result = await ContentDialogHelper.CreateLocalizedConfirmationDialog( + LocaleManager.Instance[LocaleKeys.DialogWarning], + LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.DialogPPTCNukeMessage, viewModel.SelectedApplication.Name) + ); - List cacheFiles = []; - - if (mainDir.Exists) + if (result == UserResult.Yes) { - cacheFiles.AddRange(mainDir.EnumerateFiles("*.cache")); - cacheFiles.AddRange(mainDir.EnumerateFiles("*.info")); - } + DirectoryInfo mainDir = new(Path.Combine(AppDataManager.GamesDirPath, viewModel.SelectedApplication.IdString, "cache", "cpu", "0")); + DirectoryInfo backupDir = new(Path.Combine(AppDataManager.GamesDirPath, viewModel.SelectedApplication.IdString, "cache", "cpu", "1")); - if (backupDir.Exists) - { - cacheFiles.AddRange(backupDir.EnumerateFiles("*.cache")); - cacheFiles.AddRange(backupDir.EnumerateFiles("*.info")); - } + List cacheFiles = []; - if (cacheFiles.Count > 0) - { - foreach (FileInfo file in cacheFiles) + if (mainDir.Exists) { - try + cacheFiles.AddRange(mainDir.EnumerateFiles("*.cache")); + cacheFiles.AddRange(mainDir.EnumerateFiles("*.info")); + } + + if (backupDir.Exists) + { + cacheFiles.AddRange(backupDir.EnumerateFiles("*.cache")); + cacheFiles.AddRange(backupDir.EnumerateFiles("*.info")); + } + + if (cacheFiles.Count > 0) + { + foreach (FileInfo file in cacheFiles) { - file.Delete(); - } - catch (Exception ex) - { - await ContentDialogHelper.CreateErrorDialog(LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.DialogPPTCDeletionErrorMessage, file.Name, ex)); + try + { + file.Delete(); + } + catch (Exception ex) + { + await ContentDialogHelper.CreateErrorDialog(LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.DialogPPTCDeletionErrorMessage, file.Name, ex)); + } } } } - } - } - - public async void PurgeShaderCache_Click(object sender, RoutedEventArgs args) - { - if (sender is not MenuItem { DataContext: MainWindowViewModel { SelectedApplication: not null } viewModel }) - return; - + }); + + public static AsyncRelayCommand PurgeShaderCache { get; } = + Commands.CreateConditional(vm => vm?.SelectedApplication != null, + async viewModel => + { UserResult result = await ContentDialogHelper.CreateLocalizedConfirmationDialog( LocaleManager.Instance[LocaleKeys.DialogWarning], LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.DialogShaderDeletionMessage, viewModel.SelectedApplication.Name) @@ -274,158 +261,143 @@ namespace Ryujinx.Ava.UI.Controls } } } - } - } - - public void OpenPtcDirectory_Click(object sender, RoutedEventArgs args) - { - if (sender is not MenuItem { DataContext: MainWindowViewModel { SelectedApplication: not null } viewModel }) - return; - - string ptcDir = Path.Combine(AppDataManager.GamesDirPath, viewModel.SelectedApplication.IdString, "cache", "cpu"); - string mainDir = Path.Combine(ptcDir, "0"); - string backupDir = Path.Combine(ptcDir, "1"); - - if (!Directory.Exists(ptcDir)) + } + }); + + public static RelayCommand OpenPtcDirectory { get; } = + Commands.CreateConditional(vm => vm?.SelectedApplication != null, + viewModel => { - Directory.CreateDirectory(ptcDir); - Directory.CreateDirectory(mainDir); - Directory.CreateDirectory(backupDir); - } + string ptcDir = Path.Combine(AppDataManager.GamesDirPath, viewModel.SelectedApplication.IdString, "cache", "cpu"); + string mainDir = Path.Combine(ptcDir, "0"); + string backupDir = Path.Combine(ptcDir, "1"); - OpenHelper.OpenFolder(ptcDir); - } - - public void OpenShaderCacheDirectory_Click(object sender, RoutedEventArgs args) - { - if (sender is MenuItem { DataContext: MainWindowViewModel { SelectedApplication: not null } viewModel }) - { - string shaderCacheDir = Path.Combine(AppDataManager.GamesDirPath, viewModel.SelectedApplication.IdString.ToLower(), "cache", "shader"); - - if (!Directory.Exists(shaderCacheDir)) + if (!Directory.Exists(ptcDir)) { - Directory.CreateDirectory(shaderCacheDir); + Directory.CreateDirectory(ptcDir); + Directory.CreateDirectory(mainDir); + Directory.CreateDirectory(backupDir); } - OpenHelper.OpenFolder(shaderCacheDir); - } - } - - public async void ExtractApplicationExeFs_Click(object sender, RoutedEventArgs args) - { - if (sender is MenuItem { DataContext: MainWindowViewModel { SelectedApplication: not null } viewModel }) - { - await ApplicationHelper.ExtractSection( - viewModel.StorageProvider, - NcaSectionType.Code, - viewModel.SelectedApplication.Path, - viewModel.SelectedApplication.Name); - } - } - - public async void ExtractApplicationRomFs_Click(object sender, RoutedEventArgs args) - { - if (sender is MenuItem { DataContext: MainWindowViewModel { SelectedApplication: not null } viewModel }) - await ApplicationHelper.ExtractSection( - viewModel.StorageProvider, - NcaSectionType.Data, - viewModel.SelectedApplication.Path, - viewModel.SelectedApplication.Name); - } - - public async void ExtractAocRomFs_Click(object sender, RoutedEventArgs args) - { - if (sender is not MenuItem { DataContext: MainWindowViewModel { SelectedApplication: not null } viewModel }) - return; - - DownloadableContentModel selectedDlc = await DlcSelectView.Show(viewModel.SelectedApplication.Id, viewModel.ApplicationLibrary); - - if (selectedDlc is not null) - { - await ApplicationHelper.ExtractAoc( - viewModel.StorageProvider, - selectedDlc.ContainerPath, - selectedDlc.FileName); - } - } - - public async void ExtractApplicationLogo_Click(object sender, RoutedEventArgs args) - { - if (sender is not MenuItem { DataContext: MainWindowViewModel { SelectedApplication: not null } viewModel }) - return; - - IReadOnlyList result = await viewModel.StorageProvider.OpenFolderPickerAsync(new FolderPickerOpenOptions - { - Title = LocaleManager.Instance[LocaleKeys.FolderDialogExtractTitle], - AllowMultiple = false, + OpenHelper.OpenFolder(ptcDir); }); + + public static RelayCommand OpenShaderCacheDirectory { get; } = + Commands.CreateConditional(vm => vm?.SelectedApplication != null, + viewModel => + { + string shaderCacheDir = Path.Combine(AppDataManager.GamesDirPath, viewModel.SelectedApplication.IdString.ToLower(), "cache", "shader"); - if (result.Count == 0) - return; + if (!Directory.Exists(shaderCacheDir)) + { + Directory.CreateDirectory(shaderCacheDir); + } - ApplicationHelper.ExtractSection( - result[0].Path.LocalPath, - NcaSectionType.Logo, - viewModel.SelectedApplication.Path, - viewModel.SelectedApplication.Name); + OpenHelper.OpenFolder(shaderCacheDir); + }); + + public static AsyncRelayCommand ExtractApplicationExeFs { get; } = + Commands.CreateConditional(vm => vm?.SelectedApplication != null, + async viewModel => + { + await ApplicationHelper.ExtractSection( + viewModel.StorageProvider, + NcaSectionType.Code, + viewModel.SelectedApplication.Path, + viewModel.SelectedApplication.Name); + }); + + public static AsyncRelayCommand ExtractApplicationRomFs { get; } = + Commands.CreateConditional(vm => vm?.SelectedApplication != null, + async viewModel => + { + await ApplicationHelper.ExtractSection( + viewModel.StorageProvider, + NcaSectionType.Data, + viewModel.SelectedApplication.Path, + viewModel.SelectedApplication.Name); + }); + + public static AsyncRelayCommand ExtractApplicationAocRomFs { get; } = + Commands.CreateConditional(vm => vm?.SelectedApplication != null, + async viewModel => + { + DownloadableContentModel selectedDlc = await DlcSelectView.Show(viewModel.SelectedApplication.Id, viewModel.ApplicationLibrary); + + if (selectedDlc is not null) + { + await ApplicationHelper.ExtractAoc( + viewModel.StorageProvider, + selectedDlc.ContainerPath, + selectedDlc.FileName); + } + }); + + public static AsyncRelayCommand ExtractApplicationLogo { get; } = + Commands.CreateConditional(vm => vm?.SelectedApplication != null, + async viewModel => + { + IReadOnlyList result = await viewModel.StorageProvider.OpenFolderPickerAsync(new FolderPickerOpenOptions + { + Title = LocaleManager.Instance[LocaleKeys.FolderDialogExtractTitle], + AllowMultiple = false, + }); - IStorageFile iconFile = await result[0].CreateFileAsync($"{viewModel.SelectedApplication.IdString}.png"); - await using Stream fileStream = await iconFile.OpenWriteAsync(); + if (result.Count == 0) + return; - using SKBitmap bitmap = SKBitmap.Decode(viewModel.SelectedApplication.Icon) - .Resize(new SKSizeI(512, 512), SKFilterQuality.High); + ApplicationHelper.ExtractSection( + result[0].Path.LocalPath, + NcaSectionType.Logo, + viewModel.SelectedApplication.Path, + viewModel.SelectedApplication.Name); - using SKData png = bitmap.Encode(SKEncodedImageFormat.Png, 100); + IStorageFile iconFile = await result[0].CreateFileAsync($"{viewModel.SelectedApplication.IdString}.png"); + await using Stream fileStream = await iconFile.OpenWriteAsync(); - png.SaveTo(fileStream); - } + using SKBitmap bitmap = SKBitmap.Decode(viewModel.SelectedApplication.Icon) + .Resize(new SKSizeI(512, 512), SKFilterQuality.High); - public void CreateApplicationShortcut_Click(object sender, RoutedEventArgs args) - { - if (sender is MenuItem { DataContext: MainWindowViewModel { SelectedApplication: not null } viewModel }) - ShortcutHelper.CreateAppShortcut( + using SKData png = bitmap.Encode(SKEncodedImageFormat.Png, 100); + + png.SaveTo(fileStream); + }); + + public static RelayCommand CreateApplicationShortcut { get; } = + Commands.CreateConditional(vm => vm?.SelectedApplication != null, + viewModel => ShortcutHelper.CreateAppShortcut( viewModel.SelectedApplication.Path, viewModel.SelectedApplication.Name, viewModel.SelectedApplication.IdString, viewModel.SelectedApplication.Icon - ); - } + )); + + public static AsyncRelayCommand EditGameConfiguration { get; } = + Commands.CreateConditional(vm => vm?.SelectedApplication != null, + async viewModel => + { + await StyleableAppWindow.ShowAsync(new GameSpecificSettingsWindow(viewModel)); - public async void EditGameConfiguration_Click(object sender, RoutedEventArgs args) - { - if (sender is MenuItem { DataContext: MainWindowViewModel { SelectedApplication: not null } viewModel }) - { - await StyleableAppWindow.ShowAsync(new GameSpecificSettingsWindow(viewModel)); + // just checking for file presence + viewModel.SelectedApplication.HasIndependentConfiguration = File.Exists(Program.GetDirGameUserConfig(viewModel.SelectedApplication.IdString,false,false)); - // just checking for file presence - viewModel.SelectedApplication.HasIndependentConfiguration = File.Exists(Program.GetDirGameUserConfig(viewModel.SelectedApplication.IdString,false,false)); - - viewModel.RefreshView(); - } - } - - public async void OpenApplicationCompatibility_Click(object sender, RoutedEventArgs args) - { - if (sender is MenuItem { DataContext: MainWindowViewModel { SelectedApplication: not null } viewModel }) - await CompatibilityListWindow.Show(viewModel.SelectedApplication.IdString); - } - - public async void OpenApplicationData_Click(object sender, RoutedEventArgs args) - { - if (sender is MenuItem { DataContext: MainWindowViewModel { SelectedApplication: not null } viewModel }) - await ApplicationDataView.Show(viewModel.SelectedApplication); - } - - public async void RunApplication_Click(object sender, RoutedEventArgs args) - { - if (sender is MenuItem { DataContext: MainWindowViewModel { SelectedApplication: not null } viewModel }) - await viewModel.LoadApplication(viewModel.SelectedApplication); - } - - public async void TrimXCI_Click(object sender, RoutedEventArgs args) - { - if (sender is MenuItem { DataContext: MainWindowViewModel { SelectedApplication: not null } viewModel }) - await viewModel.TrimXCIFile(viewModel.SelectedApplication.Path); - } + viewModel.RefreshView(); + }); + + public static AsyncRelayCommand OpenApplicationCompatibility { get; } = + Commands.CreateConditional(vm => vm?.SelectedApplication != null, + viewModel => CompatibilityListWindow.Show(viewModel.SelectedApplication.IdString)); + + public static AsyncRelayCommand OpenApplicationData { get; } = + Commands.CreateConditional(vm => vm?.SelectedApplication != null, + viewModel => ApplicationDataView.Show(viewModel.SelectedApplication)); + + public static AsyncRelayCommand RunApplication { get; } = + Commands.CreateConditional(vm => vm?.SelectedApplication != null, + viewModel => viewModel.LoadApplication(viewModel.SelectedApplication)); + + public static AsyncRelayCommand TrimXci { get; } = + Commands.CreateConditional(vm => vm?.SelectedApplication != null, + viewModel => viewModel.TrimXCIFile(viewModel.SelectedApplication.Path)); } } diff --git a/src/Ryujinx/UI/Helpers/Commands.cs b/src/Ryujinx/UI/Helpers/Commands.cs index 868b49158..7a65c61a1 100644 --- a/src/Ryujinx/UI/Helpers/Commands.cs +++ b/src/Ryujinx/UI/Helpers/Commands.cs @@ -9,12 +9,12 @@ namespace Ryujinx.Ava.UI.Helpers { public static RelayCommand Create(Action action) => new(action); - public static RelayCommand CreateConditional(Action action, Func canExecute) + public static RelayCommand CreateConditional(Func canExecute, Action action) => new(action, canExecute); public static RelayCommand Create(Action action) => new(action); - public static RelayCommand CreateConditional(Action action, Predicate canExecute) + public static RelayCommand CreateConditional(Predicate canExecute, Action action) => new(action, canExecute); public static AsyncRelayCommand Create(Func action) @@ -31,18 +31,18 @@ namespace Ryujinx.Ava.UI.Helpers public static AsyncRelayCommand CreateSilentFail(Func action) => new(action, AsyncRelayCommandOptions.FlowExceptionsToTaskScheduler); - public static AsyncRelayCommand CreateConditional(Func action, Func canExecute) + public static AsyncRelayCommand CreateConditional(Func canExecute, Func action) => new(action, canExecute, AsyncRelayCommandOptions.None); - public static AsyncRelayCommand CreateConcurrentConditional(Func action, Func canExecute) + public static AsyncRelayCommand CreateConcurrentConditional(Func canExecute, Func action) => new(action, canExecute, AsyncRelayCommandOptions.AllowConcurrentExecutions); - public static AsyncRelayCommand CreateSilentFailConditional(Func action, Func canExecute) + public static AsyncRelayCommand CreateSilentFailConditional(Func canExecute, Func action) => new(action, canExecute, AsyncRelayCommandOptions.FlowExceptionsToTaskScheduler); - public static AsyncRelayCommand CreateConditional(Func action, Predicate canExecute) + public static AsyncRelayCommand CreateConditional(Predicate canExecute, Func action) => new(action, canExecute, AsyncRelayCommandOptions.None); - public static AsyncRelayCommand CreateConcurrentConditional(Func action, Predicate canExecute) + public static AsyncRelayCommand CreateConcurrentConditional(Predicate canExecute, Func action) => new(action, canExecute, AsyncRelayCommandOptions.AllowConcurrentExecutions); - public static AsyncRelayCommand CreateSilentFailConditional(Func action, Predicate canExecute) + public static AsyncRelayCommand CreateSilentFailConditional(Predicate canExecute, Func action) => new(action, canExecute, AsyncRelayCommandOptions.FlowExceptionsToTaskScheduler); } } diff --git a/src/Ryujinx/UI/ViewModels/MainWindowViewModel.cs b/src/Ryujinx/UI/ViewModels/MainWindowViewModel.cs index f265f4c06..61af0db34 100644 --- a/src/Ryujinx/UI/ViewModels/MainWindowViewModel.cs +++ b/src/Ryujinx/UI/ViewModels/MainWindowViewModel.cs @@ -12,9 +12,12 @@ using DynamicData.Binding; using FluentAvalonia.UI.Controls; using Gommon; using LibHac.Common; +using LibHac.Fs; using LibHac.Ns; +using LibHac.Tools.FsSystem.NcaUtils; using Ryujinx.Ava.Common; using Ryujinx.Ava.Common.Locale; +using Ryujinx.Ava.Common.Models; using Ryujinx.Ava.Input; using Ryujinx.Ava.Systems; using Ryujinx.Ava.UI.Controls; @@ -25,6 +28,7 @@ using Ryujinx.Ava.UI.Renderer; using Ryujinx.Ava.UI.Windows; using Ryujinx.Ava.Systems.AppLibrary; using Ryujinx.Ava.Systems.Configuration; +using Ryujinx.Ava.UI.Views.Dialog; using Ryujinx.Ava.Utilities; using Ryujinx.Common; using Ryujinx.Common.Configuration; @@ -51,7 +55,9 @@ using System.Threading; using System.Threading.Tasks; using Key = Ryujinx.Input.Key; using MissingKeyException = LibHac.Common.Keys.MissingKeyException; +using Path = System.IO.Path; using ShaderCacheLoadingState = Ryujinx.Graphics.Gpu.Shader.ShaderCacheState; +using UserId = Ryujinx.HLE.HOS.Services.Account.Acc.UserId; namespace Ryujinx.Ava.UI.ViewModels { @@ -1955,5 +1961,373 @@ namespace Ryujinx.Ava.UI.ViewModels } #endregion + + #region Context Menu commands + + public static RelayCommand ToggleFavorite { get; } = + Commands.CreateConditional(vm => vm?.SelectedApplication != null, + viewModel => + { + viewModel.SelectedApplication.Favorite = !viewModel.SelectedApplication.Favorite; + + ApplicationLibrary.LoadAndSaveMetaData(viewModel.SelectedApplication.IdString, appMetadata => + { + appMetadata.Favorite = viewModel.SelectedApplication.Favorite; + }); + + viewModel.RefreshView(); + } + ); + + public static RelayCommand OpenUserSaveDirectory { get; } = + Commands.CreateConditional(vm => vm?.SelectedApplication != null, + viewModel => + OpenSaveDirectory(viewModel, SaveDataType.Account, new LibHac.Fs.UserId((ulong)viewModel.AccountManager.LastOpenedUser.UserId.High, (ulong)viewModel.AccountManager.LastOpenedUser.UserId.Low)) + ); + + public static RelayCommand OpenDeviceSaveDirectory { get; } = + Commands.CreateConditional(vm => vm?.SelectedApplication != null, + viewModel => OpenSaveDirectory(viewModel, SaveDataType.Device, default)); + + public static RelayCommand OpenBcatSaveDirectory { get; } = + Commands.CreateConditional(vm => vm?.SelectedApplication != null, + viewModel => OpenSaveDirectory(viewModel, SaveDataType.Bcat, default)); + + private static void OpenSaveDirectory(MainWindowViewModel viewModel, SaveDataType saveDataType, LibHac.Fs.UserId userId) + { + SaveDataFilter saveDataFilter = SaveDataFilter.Make(viewModel.SelectedApplication.Id, saveDataType, userId, saveDataId: default, index: default); + + ApplicationHelper.OpenSaveDir(in saveDataFilter, viewModel.SelectedApplication.Id, viewModel.SelectedApplication.ControlHolder, viewModel.SelectedApplication.Name); + } + + public static AsyncRelayCommand OpenTitleUpdateManager { get; } = + Commands.CreateConditional(vm => vm?.SelectedApplication != null, + viewModel => TitleUpdateManagerView.Show(viewModel.ApplicationLibrary, viewModel.SelectedApplication) + ); + + public static AsyncRelayCommand OpenDownloadableContentManager { get; } = + Commands.CreateConditional(vm => vm?.SelectedApplication != null, + viewModel => DownloadableContentManagerView.Show(viewModel.ApplicationLibrary, viewModel.SelectedApplication) + ); + + public static AsyncRelayCommand OpenCheatManager { get; } = + Commands.CreateConditional(vm => vm?.SelectedApplication != null, + viewModel => StyleableAppWindow.ShowAsync( + new CheatWindow( + viewModel.VirtualFileSystem, + viewModel.SelectedApplication.IdString, + viewModel.SelectedApplication.Name, + viewModel.SelectedApplication.Path + ) + )); + + public static RelayCommand OpenModsDirectory { get; } = + Commands.CreateConditional(vm => vm?.SelectedApplication != null, + viewModel => + { + string modsBasePath = ModLoader.GetModsBasePath(); + string titleModsPath = ModLoader.GetApplicationDir(modsBasePath, viewModel.SelectedApplication.IdString); + + OpenHelper.OpenFolder(titleModsPath); + }); + + public static RelayCommand OpenSdModsDirectory { get; } = + Commands.CreateConditional(vm => vm?.SelectedApplication != null, + viewModel => + { + string sdModsBasePath = ModLoader.GetSdModsBasePath(); + string titleModsPath = ModLoader.GetApplicationDir(sdModsBasePath, viewModel.SelectedApplication.IdString); + + OpenHelper.OpenFolder(titleModsPath); + }); + + public static AsyncRelayCommand OpenModManager { get; } = + Commands.CreateConditional(vm => vm?.SelectedApplication != null, + async viewModel => + { + await ModManagerView.Show( + viewModel.SelectedApplication.Id, + viewModel.SelectedApplication.IdBase, + viewModel.ApplicationLibrary, + viewModel.SelectedApplication.Name); + }); + + public static AsyncRelayCommand PurgePtcCache { get; } = + Commands.CreateConditional(vm => vm?.SelectedApplication != null, + async viewModel => + { + UserResult result = await ContentDialogHelper.CreateLocalizedConfirmationDialog( + LocaleManager.Instance[LocaleKeys.DialogWarning], + LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.DialogPPTCDeletionMessage, viewModel.SelectedApplication.Name) + ); + + if (result == UserResult.Yes) + { + DirectoryInfo mainDir = new(Path.Combine(AppDataManager.GamesDirPath, viewModel.SelectedApplication.IdString, "cache", "cpu", "0")); + DirectoryInfo backupDir = new(Path.Combine(AppDataManager.GamesDirPath, viewModel.SelectedApplication.IdString, "cache", "cpu", "1")); + + List cacheFiles = []; + + if (mainDir.Exists) + { + cacheFiles.AddRange(mainDir.EnumerateFiles("*.cache")); + } + + if (backupDir.Exists) + { + cacheFiles.AddRange(backupDir.EnumerateFiles("*.cache")); + } + + if (cacheFiles.Count > 0) + { + foreach (FileInfo file in cacheFiles) + { + try + { + file.Delete(); + } + catch (Exception ex) + { + await ContentDialogHelper.CreateErrorDialog(LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.DialogPPTCDeletionErrorMessage, file.Name, ex)); + } + } + } + } + }); + + public static AsyncRelayCommand NukePtcCache { get; } = + Commands.CreateConditional(vm => vm?.SelectedApplication != null, + async viewModel => + { + UserResult result = await ContentDialogHelper.CreateLocalizedConfirmationDialog( + LocaleManager.Instance[LocaleKeys.DialogWarning], + LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.DialogPPTCNukeMessage, viewModel.SelectedApplication.Name) + ); + + if (result == UserResult.Yes) + { + DirectoryInfo mainDir = new(Path.Combine(AppDataManager.GamesDirPath, viewModel.SelectedApplication.IdString, "cache", "cpu", "0")); + DirectoryInfo backupDir = new(Path.Combine(AppDataManager.GamesDirPath, viewModel.SelectedApplication.IdString, "cache", "cpu", "1")); + + List cacheFiles = []; + + if (mainDir.Exists) + { + cacheFiles.AddRange(mainDir.EnumerateFiles("*.cache")); + cacheFiles.AddRange(mainDir.EnumerateFiles("*.info")); + } + + if (backupDir.Exists) + { + cacheFiles.AddRange(backupDir.EnumerateFiles("*.cache")); + cacheFiles.AddRange(backupDir.EnumerateFiles("*.info")); + } + + if (cacheFiles.Count > 0) + { + foreach (FileInfo file in cacheFiles) + { + try + { + file.Delete(); + } + catch (Exception ex) + { + await ContentDialogHelper.CreateErrorDialog(LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.DialogPPTCDeletionErrorMessage, file.Name, ex)); + } + } + } + } + }); + + public static AsyncRelayCommand PurgeShaderCache { get; } = + Commands.CreateConditional(vm => vm?.SelectedApplication != null, + async viewModel => + { + UserResult result = await ContentDialogHelper.CreateLocalizedConfirmationDialog( + LocaleManager.Instance[LocaleKeys.DialogWarning], + LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.DialogShaderDeletionMessage, viewModel.SelectedApplication.Name) + ); + + if (result == UserResult.Yes) + { + DirectoryInfo shaderCacheDir = new(Path.Combine(AppDataManager.GamesDirPath, viewModel.SelectedApplication.IdString, "cache", "shader")); + + List oldCacheDirectories = []; + List newCacheFiles = []; + + if (shaderCacheDir.Exists) + { + oldCacheDirectories.AddRange(shaderCacheDir.EnumerateDirectories("*")); + newCacheFiles.AddRange(shaderCacheDir.GetFiles("*.toc")); + newCacheFiles.AddRange(shaderCacheDir.GetFiles("*.data")); + } + + if ((oldCacheDirectories.Count > 0 || newCacheFiles.Count > 0)) + { + foreach (DirectoryInfo directory in oldCacheDirectories) + { + try + { + directory.Delete(true); + } + catch (Exception ex) + { + await ContentDialogHelper.CreateErrorDialog(LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.DialogPPTCDeletionErrorMessage, directory.Name, ex)); + } + } + + foreach (FileInfo file in newCacheFiles) + { + try + { + file.Delete(); + } + catch (Exception ex) + { + await ContentDialogHelper.CreateErrorDialog(LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.ShaderCachePurgeError, file.Name, ex)); + } + } + } + } + }); + + public static RelayCommand OpenPtcDirectory { get; } = + Commands.CreateConditional(vm => vm?.SelectedApplication != null, + viewModel => + { + string ptcDir = Path.Combine(AppDataManager.GamesDirPath, viewModel.SelectedApplication.IdString, "cache", "cpu"); + string mainDir = Path.Combine(ptcDir, "0"); + string backupDir = Path.Combine(ptcDir, "1"); + + if (!Directory.Exists(ptcDir)) + { + Directory.CreateDirectory(ptcDir); + Directory.CreateDirectory(mainDir); + Directory.CreateDirectory(backupDir); + } + + OpenHelper.OpenFolder(ptcDir); + }); + + public static RelayCommand OpenShaderCacheDirectory { get; } = + Commands.CreateConditional(vm => vm?.SelectedApplication != null, + viewModel => + { + string shaderCacheDir = Path.Combine(AppDataManager.GamesDirPath, viewModel.SelectedApplication.IdString.ToLower(), "cache", "shader"); + + if (!Directory.Exists(shaderCacheDir)) + { + Directory.CreateDirectory(shaderCacheDir); + } + + OpenHelper.OpenFolder(shaderCacheDir); + }); + + public static AsyncRelayCommand ExtractApplicationExeFs { get; } = + Commands.CreateConditional(vm => vm?.SelectedApplication != null, + async viewModel => + { + await ApplicationHelper.ExtractSection( + viewModel.StorageProvider, + NcaSectionType.Code, + viewModel.SelectedApplication.Path, + viewModel.SelectedApplication.Name); + }); + + public static AsyncRelayCommand ExtractApplicationRomFs { get; } = + Commands.CreateConditional(vm => vm?.SelectedApplication != null, + async viewModel => + { + await ApplicationHelper.ExtractSection( + viewModel.StorageProvider, + NcaSectionType.Data, + viewModel.SelectedApplication.Path, + viewModel.SelectedApplication.Name); + }); + + public static AsyncRelayCommand ExtractApplicationAocRomFs { get; } = + Commands.CreateConditional(vm => vm?.SelectedApplication != null, + async viewModel => + { + DownloadableContentModel selectedDlc = await DlcSelectView.Show(viewModel.SelectedApplication.Id, viewModel.ApplicationLibrary); + + if (selectedDlc is not null) + { + await ApplicationHelper.ExtractAoc( + viewModel.StorageProvider, + selectedDlc.ContainerPath, + selectedDlc.FileName); + } + }); + + public static AsyncRelayCommand ExtractApplicationLogo { get; } = + Commands.CreateConditional(vm => vm?.SelectedApplication != null, + async viewModel => + { + IReadOnlyList result = await viewModel.StorageProvider.OpenFolderPickerAsync(new FolderPickerOpenOptions + { + Title = LocaleManager.Instance[LocaleKeys.FolderDialogExtractTitle], + AllowMultiple = false, + }); + + if (result.Count == 0) + return; + + ApplicationHelper.ExtractSection( + result[0].Path.LocalPath, + NcaSectionType.Logo, + viewModel.SelectedApplication.Path, + viewModel.SelectedApplication.Name); + + IStorageFile iconFile = await result[0].CreateFileAsync($"{viewModel.SelectedApplication.IdString}.png"); + await using Stream fileStream = await iconFile.OpenWriteAsync(); + + using SKBitmap bitmap = SKBitmap.Decode(viewModel.SelectedApplication.Icon) + .Resize(new SKSizeI(512, 512), SKFilterQuality.High); + + using SKData png = bitmap.Encode(SKEncodedImageFormat.Png, 100); + + png.SaveTo(fileStream); + }); + + public static RelayCommand CreateApplicationShortcut { get; } = + Commands.CreateConditional(vm => vm?.SelectedApplication != null, + viewModel => ShortcutHelper.CreateAppShortcut( + viewModel.SelectedApplication.Path, + viewModel.SelectedApplication.Name, + viewModel.SelectedApplication.IdString, + viewModel.SelectedApplication.Icon + )); + + public static AsyncRelayCommand EditGameConfiguration { get; } = + Commands.CreateConditional(vm => vm?.SelectedApplication != null, + async viewModel => + { + await StyleableAppWindow.ShowAsync(new GameSpecificSettingsWindow(viewModel)); + + // just checking for file presence + viewModel.SelectedApplication.HasIndependentConfiguration = File.Exists(Program.GetDirGameUserConfig(viewModel.SelectedApplication.IdString,false,false)); + + viewModel.RefreshView(); + }); + + public static AsyncRelayCommand OpenApplicationCompatibility { get; } = + Commands.CreateConditional(vm => vm?.SelectedApplication != null, + viewModel => CompatibilityListWindow.Show(viewModel.SelectedApplication.IdString)); + + public static AsyncRelayCommand OpenApplicationData { get; } = + Commands.CreateConditional(vm => vm?.SelectedApplication != null, + viewModel => ApplicationDataView.Show(viewModel.SelectedApplication)); + + public static AsyncRelayCommand RunApplication { get; } = + Commands.CreateConditional(vm => vm?.SelectedApplication != null, + viewModel => viewModel.LoadApplication(viewModel.SelectedApplication)); + + public static AsyncRelayCommand TrimXci { get; } = + Commands.CreateConditional(vm => vm?.SelectedApplication != null, + viewModel => viewModel.TrimXCIFile(viewModel.SelectedApplication.Path)); + + #endregion } } From 81412c7dd5f35cef695d48ce2000f600dd977b5f Mon Sep 17 00:00:00 2001 From: GreemDev Date: Thu, 29 May 2025 02:09:21 -0500 Subject: [PATCH 037/105] misc: fix duplicated code (oops), reorder the commands in-code to match the UI --- .../HOS/Services/Account/Acc/Types/UserId.cs | 12 +- .../Controls/ApplicationContextMenu.axaml.cs | 364 -------------- .../UI/ViewModels/MainWindowViewModel.cs | 443 +++++++++--------- 3 files changed, 236 insertions(+), 583 deletions(-) diff --git a/src/Ryujinx.HLE/HOS/Services/Account/Acc/Types/UserId.cs b/src/Ryujinx.HLE/HOS/Services/Account/Acc/Types/UserId.cs index c9c78af9a..a6b1a47b6 100644 --- a/src/Ryujinx.HLE/HOS/Services/Account/Acc/Types/UserId.cs +++ b/src/Ryujinx.HLE/HOS/Services/Account/Acc/Types/UserId.cs @@ -51,14 +51,8 @@ namespace Ryujinx.HLE.HOS.Services.Account.Acc return High.ToString("x16") + Low.ToString("x16"); } - public Uid ToLibHacUid() - { - return new Uid((ulong)High, (ulong)Low); - } - - public UInt128 ToUInt128() - { - return new UInt128((ulong)High, (ulong)Low); - } + public Uid ToLibHacUid() => new((ulong)High, (ulong)Low); + public LibHac.Fs.UserId ToLibHac() => new((ulong)High, (ulong)Low); + public UInt128 ToUInt128() => new((ulong)High, (ulong)Low); } } diff --git a/src/Ryujinx/UI/Controls/ApplicationContextMenu.axaml.cs b/src/Ryujinx/UI/Controls/ApplicationContextMenu.axaml.cs index 6f93676e2..1f9f6c691 100644 --- a/src/Ryujinx/UI/Controls/ApplicationContextMenu.axaml.cs +++ b/src/Ryujinx/UI/Controls/ApplicationContextMenu.axaml.cs @@ -35,369 +35,5 @@ namespace Ryujinx.Ava.UI.Controls { AvaloniaXamlLoader.Load(this); } - - public static RelayCommand ToggleFavorite { get; } = - Commands.CreateConditional(vm => vm?.SelectedApplication != null, - viewModel => - { - viewModel.SelectedApplication.Favorite = !viewModel.SelectedApplication.Favorite; - - ApplicationLibrary.LoadAndSaveMetaData(viewModel.SelectedApplication.IdString, appMetadata => - { - appMetadata.Favorite = viewModel.SelectedApplication.Favorite; - }); - - viewModel.RefreshView(); - } - ); - - public static RelayCommand OpenUserSaveDirectory { get; } = - Commands.CreateConditional(vm => vm?.SelectedApplication != null, - viewModel => - OpenSaveDirectory(viewModel, SaveDataType.Account, new UserId((ulong)viewModel.AccountManager.LastOpenedUser.UserId.High, (ulong)viewModel.AccountManager.LastOpenedUser.UserId.Low)) - ); - - public static RelayCommand OpenDeviceSaveDirectory { get; } = - Commands.CreateConditional(vm => vm?.SelectedApplication != null, - viewModel => OpenSaveDirectory(viewModel, SaveDataType.Device, default)); - - public static RelayCommand OpenBcatSaveDirectory { get; } = - Commands.CreateConditional(vm => vm?.SelectedApplication != null, - viewModel => OpenSaveDirectory(viewModel, SaveDataType.Bcat, default)); - - private static void OpenSaveDirectory(MainWindowViewModel viewModel, SaveDataType saveDataType, UserId userId) - { - SaveDataFilter saveDataFilter = SaveDataFilter.Make(viewModel.SelectedApplication.Id, saveDataType, userId, saveDataId: default, index: default); - - ApplicationHelper.OpenSaveDir(in saveDataFilter, viewModel.SelectedApplication.Id, viewModel.SelectedApplication.ControlHolder, viewModel.SelectedApplication.Name); - } - - public static AsyncRelayCommand OpenTitleUpdateManager { get; } = - Commands.CreateConditional(vm => vm?.SelectedApplication != null, - viewModel => TitleUpdateManagerView.Show(viewModel.ApplicationLibrary, viewModel.SelectedApplication) - ); - - public static AsyncRelayCommand OpenDownloadableContentManager { get; } = - Commands.CreateConditional(vm => vm?.SelectedApplication != null, - viewModel => DownloadableContentManagerView.Show(viewModel.ApplicationLibrary, viewModel.SelectedApplication) - ); - - public static AsyncRelayCommand OpenCheatManager { get; } = - Commands.CreateConditional(vm => vm?.SelectedApplication != null, - viewModel => StyleableAppWindow.ShowAsync( - new CheatWindow( - viewModel.VirtualFileSystem, - viewModel.SelectedApplication.IdString, - viewModel.SelectedApplication.Name, - viewModel.SelectedApplication.Path - ) - )); - - public static RelayCommand OpenModsDirectory { get; } = - Commands.CreateConditional(vm => vm?.SelectedApplication != null, - viewModel => - { - string modsBasePath = ModLoader.GetModsBasePath(); - string titleModsPath = ModLoader.GetApplicationDir(modsBasePath, viewModel.SelectedApplication.IdString); - - OpenHelper.OpenFolder(titleModsPath); - }); - - public static RelayCommand OpenSdModsDirectory { get; } = - Commands.CreateConditional(vm => vm?.SelectedApplication != null, - viewModel => - { - string sdModsBasePath = ModLoader.GetSdModsBasePath(); - string titleModsPath = ModLoader.GetApplicationDir(sdModsBasePath, viewModel.SelectedApplication.IdString); - - OpenHelper.OpenFolder(titleModsPath); - }); - - public static AsyncRelayCommand OpenModManager { get; } = - Commands.CreateConditional(vm => vm?.SelectedApplication != null, - async viewModel => - { - await ModManagerView.Show( - viewModel.SelectedApplication.Id, - viewModel.SelectedApplication.IdBase, - viewModel.ApplicationLibrary, - viewModel.SelectedApplication.Name); - }); - - public static AsyncRelayCommand PurgePtcCache { get; } = - Commands.CreateConditional(vm => vm?.SelectedApplication != null, - async viewModel => - { - UserResult result = await ContentDialogHelper.CreateLocalizedConfirmationDialog( - LocaleManager.Instance[LocaleKeys.DialogWarning], - LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.DialogPPTCDeletionMessage, viewModel.SelectedApplication.Name) - ); - - if (result == UserResult.Yes) - { - DirectoryInfo mainDir = new(Path.Combine(AppDataManager.GamesDirPath, viewModel.SelectedApplication.IdString, "cache", "cpu", "0")); - DirectoryInfo backupDir = new(Path.Combine(AppDataManager.GamesDirPath, viewModel.SelectedApplication.IdString, "cache", "cpu", "1")); - - List cacheFiles = []; - - if (mainDir.Exists) - { - cacheFiles.AddRange(mainDir.EnumerateFiles("*.cache")); - } - - if (backupDir.Exists) - { - cacheFiles.AddRange(backupDir.EnumerateFiles("*.cache")); - } - - if (cacheFiles.Count > 0) - { - foreach (FileInfo file in cacheFiles) - { - try - { - file.Delete(); - } - catch (Exception ex) - { - await ContentDialogHelper.CreateErrorDialog(LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.DialogPPTCDeletionErrorMessage, file.Name, ex)); - } - } - } - } - }); - - public static AsyncRelayCommand NukePtcCache { get; } = - Commands.CreateConditional(vm => vm?.SelectedApplication != null, - async viewModel => - { - UserResult result = await ContentDialogHelper.CreateLocalizedConfirmationDialog( - LocaleManager.Instance[LocaleKeys.DialogWarning], - LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.DialogPPTCNukeMessage, viewModel.SelectedApplication.Name) - ); - - if (result == UserResult.Yes) - { - DirectoryInfo mainDir = new(Path.Combine(AppDataManager.GamesDirPath, viewModel.SelectedApplication.IdString, "cache", "cpu", "0")); - DirectoryInfo backupDir = new(Path.Combine(AppDataManager.GamesDirPath, viewModel.SelectedApplication.IdString, "cache", "cpu", "1")); - - List cacheFiles = []; - - if (mainDir.Exists) - { - cacheFiles.AddRange(mainDir.EnumerateFiles("*.cache")); - cacheFiles.AddRange(mainDir.EnumerateFiles("*.info")); - } - - if (backupDir.Exists) - { - cacheFiles.AddRange(backupDir.EnumerateFiles("*.cache")); - cacheFiles.AddRange(backupDir.EnumerateFiles("*.info")); - } - - if (cacheFiles.Count > 0) - { - foreach (FileInfo file in cacheFiles) - { - try - { - file.Delete(); - } - catch (Exception ex) - { - await ContentDialogHelper.CreateErrorDialog(LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.DialogPPTCDeletionErrorMessage, file.Name, ex)); - } - } - } - } - }); - - public static AsyncRelayCommand PurgeShaderCache { get; } = - Commands.CreateConditional(vm => vm?.SelectedApplication != null, - async viewModel => - { - UserResult result = await ContentDialogHelper.CreateLocalizedConfirmationDialog( - LocaleManager.Instance[LocaleKeys.DialogWarning], - LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.DialogShaderDeletionMessage, viewModel.SelectedApplication.Name) - ); - - if (result == UserResult.Yes) - { - DirectoryInfo shaderCacheDir = new(Path.Combine(AppDataManager.GamesDirPath, viewModel.SelectedApplication.IdString, "cache", "shader")); - - List oldCacheDirectories = []; - List newCacheFiles = []; - - if (shaderCacheDir.Exists) - { - oldCacheDirectories.AddRange(shaderCacheDir.EnumerateDirectories("*")); - newCacheFiles.AddRange(shaderCacheDir.GetFiles("*.toc")); - newCacheFiles.AddRange(shaderCacheDir.GetFiles("*.data")); - } - - if ((oldCacheDirectories.Count > 0 || newCacheFiles.Count > 0)) - { - foreach (DirectoryInfo directory in oldCacheDirectories) - { - try - { - directory.Delete(true); - } - catch (Exception ex) - { - await ContentDialogHelper.CreateErrorDialog(LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.DialogPPTCDeletionErrorMessage, directory.Name, ex)); - } - } - - foreach (FileInfo file in newCacheFiles) - { - try - { - file.Delete(); - } - catch (Exception ex) - { - await ContentDialogHelper.CreateErrorDialog(LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.ShaderCachePurgeError, file.Name, ex)); - } - } - } - } - }); - - public static RelayCommand OpenPtcDirectory { get; } = - Commands.CreateConditional(vm => vm?.SelectedApplication != null, - viewModel => - { - string ptcDir = Path.Combine(AppDataManager.GamesDirPath, viewModel.SelectedApplication.IdString, "cache", "cpu"); - string mainDir = Path.Combine(ptcDir, "0"); - string backupDir = Path.Combine(ptcDir, "1"); - - if (!Directory.Exists(ptcDir)) - { - Directory.CreateDirectory(ptcDir); - Directory.CreateDirectory(mainDir); - Directory.CreateDirectory(backupDir); - } - - OpenHelper.OpenFolder(ptcDir); - }); - - public static RelayCommand OpenShaderCacheDirectory { get; } = - Commands.CreateConditional(vm => vm?.SelectedApplication != null, - viewModel => - { - string shaderCacheDir = Path.Combine(AppDataManager.GamesDirPath, viewModel.SelectedApplication.IdString.ToLower(), "cache", "shader"); - - if (!Directory.Exists(shaderCacheDir)) - { - Directory.CreateDirectory(shaderCacheDir); - } - - OpenHelper.OpenFolder(shaderCacheDir); - }); - - public static AsyncRelayCommand ExtractApplicationExeFs { get; } = - Commands.CreateConditional(vm => vm?.SelectedApplication != null, - async viewModel => - { - await ApplicationHelper.ExtractSection( - viewModel.StorageProvider, - NcaSectionType.Code, - viewModel.SelectedApplication.Path, - viewModel.SelectedApplication.Name); - }); - - public static AsyncRelayCommand ExtractApplicationRomFs { get; } = - Commands.CreateConditional(vm => vm?.SelectedApplication != null, - async viewModel => - { - await ApplicationHelper.ExtractSection( - viewModel.StorageProvider, - NcaSectionType.Data, - viewModel.SelectedApplication.Path, - viewModel.SelectedApplication.Name); - }); - - public static AsyncRelayCommand ExtractApplicationAocRomFs { get; } = - Commands.CreateConditional(vm => vm?.SelectedApplication != null, - async viewModel => - { - DownloadableContentModel selectedDlc = await DlcSelectView.Show(viewModel.SelectedApplication.Id, viewModel.ApplicationLibrary); - - if (selectedDlc is not null) - { - await ApplicationHelper.ExtractAoc( - viewModel.StorageProvider, - selectedDlc.ContainerPath, - selectedDlc.FileName); - } - }); - - public static AsyncRelayCommand ExtractApplicationLogo { get; } = - Commands.CreateConditional(vm => vm?.SelectedApplication != null, - async viewModel => - { - IReadOnlyList result = await viewModel.StorageProvider.OpenFolderPickerAsync(new FolderPickerOpenOptions - { - Title = LocaleManager.Instance[LocaleKeys.FolderDialogExtractTitle], - AllowMultiple = false, - }); - - if (result.Count == 0) - return; - - ApplicationHelper.ExtractSection( - result[0].Path.LocalPath, - NcaSectionType.Logo, - viewModel.SelectedApplication.Path, - viewModel.SelectedApplication.Name); - - IStorageFile iconFile = await result[0].CreateFileAsync($"{viewModel.SelectedApplication.IdString}.png"); - await using Stream fileStream = await iconFile.OpenWriteAsync(); - - using SKBitmap bitmap = SKBitmap.Decode(viewModel.SelectedApplication.Icon) - .Resize(new SKSizeI(512, 512), SKFilterQuality.High); - - using SKData png = bitmap.Encode(SKEncodedImageFormat.Png, 100); - - png.SaveTo(fileStream); - }); - - public static RelayCommand CreateApplicationShortcut { get; } = - Commands.CreateConditional(vm => vm?.SelectedApplication != null, - viewModel => ShortcutHelper.CreateAppShortcut( - viewModel.SelectedApplication.Path, - viewModel.SelectedApplication.Name, - viewModel.SelectedApplication.IdString, - viewModel.SelectedApplication.Icon - )); - - public static AsyncRelayCommand EditGameConfiguration { get; } = - Commands.CreateConditional(vm => vm?.SelectedApplication != null, - async viewModel => - { - await StyleableAppWindow.ShowAsync(new GameSpecificSettingsWindow(viewModel)); - - // just checking for file presence - viewModel.SelectedApplication.HasIndependentConfiguration = File.Exists(Program.GetDirGameUserConfig(viewModel.SelectedApplication.IdString,false,false)); - - viewModel.RefreshView(); - }); - - public static AsyncRelayCommand OpenApplicationCompatibility { get; } = - Commands.CreateConditional(vm => vm?.SelectedApplication != null, - viewModel => CompatibilityListWindow.Show(viewModel.SelectedApplication.IdString)); - - public static AsyncRelayCommand OpenApplicationData { get; } = - Commands.CreateConditional(vm => vm?.SelectedApplication != null, - viewModel => ApplicationDataView.Show(viewModel.SelectedApplication)); - - public static AsyncRelayCommand RunApplication { get; } = - Commands.CreateConditional(vm => vm?.SelectedApplication != null, - viewModel => viewModel.LoadApplication(viewModel.SelectedApplication)); - - public static AsyncRelayCommand TrimXci { get; } = - Commands.CreateConditional(vm => vm?.SelectedApplication != null, - viewModel => viewModel.TrimXCIFile(viewModel.SelectedApplication.Path)); } } diff --git a/src/Ryujinx/UI/ViewModels/MainWindowViewModel.cs b/src/Ryujinx/UI/ViewModels/MainWindowViewModel.cs index 61af0db34..020d96794 100644 --- a/src/Ryujinx/UI/ViewModels/MainWindowViewModel.cs +++ b/src/Ryujinx/UI/ViewModels/MainWindowViewModel.cs @@ -1963,8 +1963,12 @@ namespace Ryujinx.Ava.UI.ViewModels #endregion #region Context Menu commands + + public static AsyncRelayCommand RunApplication { get; } = + Commands.CreateConditional(vm => vm?.SelectedApplication != null, + viewModel => viewModel.LoadApplication(viewModel.SelectedApplication)); - public static RelayCommand ToggleFavorite { get; } = + public static RelayCommand ToggleFavorite { get; } = Commands.CreateConditional(vm => vm?.SelectedApplication != null, viewModel => { @@ -1979,39 +1983,73 @@ namespace Ryujinx.Ava.UI.ViewModels } ); - public static RelayCommand OpenUserSaveDirectory { get; } = - Commands.CreateConditional(vm => vm?.SelectedApplication != null, - viewModel => - OpenSaveDirectory(viewModel, SaveDataType.Account, new LibHac.Fs.UserId((ulong)viewModel.AccountManager.LastOpenedUser.UserId.High, (ulong)viewModel.AccountManager.LastOpenedUser.UserId.Low)) - ); + public static RelayCommand CreateApplicationShortcut { get; } = + Commands.CreateConditional(vm => vm?.SelectedApplication != null, + viewModel => ShortcutHelper.CreateAppShortcut( + viewModel.SelectedApplication.Path, + viewModel.SelectedApplication.Name, + viewModel.SelectedApplication.IdString, + viewModel.SelectedApplication.Icon + )); + public static AsyncRelayCommand EditGameConfiguration { get; } = + Commands.CreateConditional(vm => vm?.SelectedApplication != null, + async viewModel => + { + await StyleableAppWindow.ShowAsync(new GameSpecificSettingsWindow(viewModel)); + + // just checking for file presence + viewModel.SelectedApplication.HasIndependentConfiguration = File.Exists( + Program.GetDirGameUserConfig(viewModel.SelectedApplication.IdString, false, false)); + + viewModel.RefreshView(); + }); + + public static AsyncRelayCommand OpenApplicationCompatibility { get; } = + Commands.CreateConditional(vm => vm?.SelectedApplication != null, + viewModel => CompatibilityListWindow.Show(viewModel.SelectedApplication.IdString)); + + public static AsyncRelayCommand OpenApplicationData { get; } = + Commands.CreateConditional(vm => vm?.SelectedApplication != null, + viewModel => ApplicationDataView.Show(viewModel.SelectedApplication)); + + public static RelayCommand OpenUserSaveDirectory { get; } = + Commands.CreateConditional(vm => vm?.SelectedApplication != null, + viewModel => + OpenSaveDirectory(viewModel, SaveDataType.Account, viewModel.AccountManager.LastOpenedUser.UserId.ToLibHac()) + ); + public static RelayCommand OpenDeviceSaveDirectory { get; } = Commands.CreateConditional(vm => vm?.SelectedApplication != null, viewModel => OpenSaveDirectory(viewModel, SaveDataType.Device, default)); - + public static RelayCommand OpenBcatSaveDirectory { get; } = - Commands.CreateConditional(vm => vm?.SelectedApplication != null, + Commands.CreateConditional(vm => vm?.SelectedApplication != null, viewModel => OpenSaveDirectory(viewModel, SaveDataType.Bcat, default)); - private static void OpenSaveDirectory(MainWindowViewModel viewModel, SaveDataType saveDataType, LibHac.Fs.UserId userId) + private static void OpenSaveDirectory(MainWindowViewModel viewModel, SaveDataType saveDataType, + LibHac.Fs.UserId userId) { - SaveDataFilter saveDataFilter = SaveDataFilter.Make(viewModel.SelectedApplication.Id, saveDataType, userId, saveDataId: default, index: default); + SaveDataFilter saveDataFilter = SaveDataFilter.Make(viewModel.SelectedApplication.Id, saveDataType, userId, + saveDataId: default, index: default); - ApplicationHelper.OpenSaveDir(in saveDataFilter, viewModel.SelectedApplication.Id, viewModel.SelectedApplication.ControlHolder, viewModel.SelectedApplication.Name); + ApplicationHelper.OpenSaveDir(in saveDataFilter, viewModel.SelectedApplication.Id, + viewModel.SelectedApplication.ControlHolder, viewModel.SelectedApplication.Name); } - + public static AsyncRelayCommand OpenTitleUpdateManager { get; } = - Commands.CreateConditional(vm => vm?.SelectedApplication != null, + Commands.CreateConditional(vm => vm?.SelectedApplication != null, viewModel => TitleUpdateManagerView.Show(viewModel.ApplicationLibrary, viewModel.SelectedApplication) ); - + public static AsyncRelayCommand OpenDownloadableContentManager { get; } = - Commands.CreateConditional(vm => vm?.SelectedApplication != null, - viewModel => DownloadableContentManagerView.Show(viewModel.ApplicationLibrary, viewModel.SelectedApplication) + Commands.CreateConditional(vm => vm?.SelectedApplication != null, + viewModel => + DownloadableContentManagerView.Show(viewModel.ApplicationLibrary, viewModel.SelectedApplication) ); - + public static AsyncRelayCommand OpenCheatManager { get; } = - Commands.CreateConditional(vm => vm?.SelectedApplication != null, + Commands.CreateConditional(vm => vm?.SelectedApplication != null, viewModel => StyleableAppWindow.ShowAsync( new CheatWindow( viewModel.VirtualFileSystem, @@ -2021,8 +2059,16 @@ namespace Ryujinx.Ava.UI.ViewModels ) )); + public static AsyncRelayCommand OpenModManager { get; } = + Commands.CreateConditional(vm => vm?.SelectedApplication != null, + viewModel => ModManagerView.Show( + viewModel.SelectedApplication.Id, + viewModel.SelectedApplication.IdBase, + viewModel.ApplicationLibrary, + viewModel.SelectedApplication.Name)); + public static RelayCommand OpenModsDirectory { get; } = - Commands.CreateConditional(vm => vm?.SelectedApplication != null, + Commands.CreateConditional(vm => vm?.SelectedApplication != null, viewModel => { string modsBasePath = ModLoader.GetModsBasePath(); @@ -2030,191 +2076,202 @@ namespace Ryujinx.Ava.UI.ViewModels OpenHelper.OpenFolder(titleModsPath); }); - + public static RelayCommand OpenSdModsDirectory { get; } = - Commands.CreateConditional(vm => vm?.SelectedApplication != null, + Commands.CreateConditional(vm => vm?.SelectedApplication != null, viewModel => - { - string sdModsBasePath = ModLoader.GetSdModsBasePath(); - string titleModsPath = ModLoader.GetApplicationDir(sdModsBasePath, viewModel.SelectedApplication.IdString); + { + string sdModsBasePath = ModLoader.GetSdModsBasePath(); + string titleModsPath = ModLoader.GetApplicationDir(sdModsBasePath, viewModel.SelectedApplication.IdString); - OpenHelper.OpenFolder(titleModsPath); - }); - - public static AsyncRelayCommand OpenModManager { get; } = - Commands.CreateConditional(vm => vm?.SelectedApplication != null, - async viewModel => - { - await ModManagerView.Show( - viewModel.SelectedApplication.Id, - viewModel.SelectedApplication.IdBase, - viewModel.ApplicationLibrary, - viewModel.SelectedApplication.Name); - }); + OpenHelper.OpenFolder(titleModsPath); + }); + + public static AsyncRelayCommand TrimXci { get; } = + Commands.CreateConditional(vm => vm?.SelectedApplication != null, + viewModel => viewModel.TrimXCIFile(viewModel.SelectedApplication.Path)); public static AsyncRelayCommand PurgePtcCache { get; } = - Commands.CreateConditional(vm => vm?.SelectedApplication != null, + Commands.CreateConditional(vm => vm?.SelectedApplication != null, async viewModel => - { - UserResult result = await ContentDialogHelper.CreateLocalizedConfirmationDialog( - LocaleManager.Instance[LocaleKeys.DialogWarning], - LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.DialogPPTCDeletionMessage, viewModel.SelectedApplication.Name) - ); - - if (result == UserResult.Yes) { - DirectoryInfo mainDir = new(Path.Combine(AppDataManager.GamesDirPath, viewModel.SelectedApplication.IdString, "cache", "cpu", "0")); - DirectoryInfo backupDir = new(Path.Combine(AppDataManager.GamesDirPath, viewModel.SelectedApplication.IdString, "cache", "cpu", "1")); + UserResult result = await ContentDialogHelper.CreateLocalizedConfirmationDialog( + LocaleManager.Instance[LocaleKeys.DialogWarning], + LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.DialogPPTCDeletionMessage, + viewModel.SelectedApplication.Name) + ); - List cacheFiles = []; - - if (mainDir.Exists) + if (result == UserResult.Yes) { - cacheFiles.AddRange(mainDir.EnumerateFiles("*.cache")); - } + DirectoryInfo mainDir = new(Path.Combine(AppDataManager.GamesDirPath, + viewModel.SelectedApplication.IdString, "cache", "cpu", "0")); + DirectoryInfo backupDir = new(Path.Combine(AppDataManager.GamesDirPath, + viewModel.SelectedApplication.IdString, "cache", "cpu", "1")); - if (backupDir.Exists) - { - cacheFiles.AddRange(backupDir.EnumerateFiles("*.cache")); - } + List cacheFiles = []; - if (cacheFiles.Count > 0) - { - foreach (FileInfo file in cacheFiles) + if (mainDir.Exists) { - try + cacheFiles.AddRange(mainDir.EnumerateFiles("*.cache")); + } + + if (backupDir.Exists) + { + cacheFiles.AddRange(backupDir.EnumerateFiles("*.cache")); + } + + if (cacheFiles.Count > 0) + { + foreach (FileInfo file in cacheFiles) { - file.Delete(); - } - catch (Exception ex) - { - await ContentDialogHelper.CreateErrorDialog(LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.DialogPPTCDeletionErrorMessage, file.Name, ex)); + try + { + file.Delete(); + } + catch (Exception ex) + { + await ContentDialogHelper.CreateErrorDialog( + LocaleManager.Instance.UpdateAndGetDynamicValue( + LocaleKeys.DialogPPTCDeletionErrorMessage, file.Name, ex)); + } } } } - } - }); - + }); + public static AsyncRelayCommand NukePtcCache { get; } = - Commands.CreateConditional(vm => vm?.SelectedApplication != null, + Commands.CreateConditional(vm => vm?.SelectedApplication != null, async viewModel => - { - UserResult result = await ContentDialogHelper.CreateLocalizedConfirmationDialog( - LocaleManager.Instance[LocaleKeys.DialogWarning], - LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.DialogPPTCNukeMessage, viewModel.SelectedApplication.Name) - ); - - if (result == UserResult.Yes) { - DirectoryInfo mainDir = new(Path.Combine(AppDataManager.GamesDirPath, viewModel.SelectedApplication.IdString, "cache", "cpu", "0")); - DirectoryInfo backupDir = new(Path.Combine(AppDataManager.GamesDirPath, viewModel.SelectedApplication.IdString, "cache", "cpu", "1")); + UserResult result = await ContentDialogHelper.CreateLocalizedConfirmationDialog( + LocaleManager.Instance[LocaleKeys.DialogWarning], + LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.DialogPPTCNukeMessage, + viewModel.SelectedApplication.Name) + ); - List cacheFiles = []; - - if (mainDir.Exists) + if (result == UserResult.Yes) { - cacheFiles.AddRange(mainDir.EnumerateFiles("*.cache")); - cacheFiles.AddRange(mainDir.EnumerateFiles("*.info")); - } + DirectoryInfo mainDir = new(Path.Combine(AppDataManager.GamesDirPath, + viewModel.SelectedApplication.IdString, "cache", "cpu", "0")); + DirectoryInfo backupDir = new(Path.Combine(AppDataManager.GamesDirPath, + viewModel.SelectedApplication.IdString, "cache", "cpu", "1")); - if (backupDir.Exists) - { - cacheFiles.AddRange(backupDir.EnumerateFiles("*.cache")); - cacheFiles.AddRange(backupDir.EnumerateFiles("*.info")); - } + List cacheFiles = []; - if (cacheFiles.Count > 0) - { - foreach (FileInfo file in cacheFiles) + if (mainDir.Exists) { - try + cacheFiles.AddRange(mainDir.EnumerateFiles("*.cache")); + cacheFiles.AddRange(mainDir.EnumerateFiles("*.info")); + } + + if (backupDir.Exists) + { + cacheFiles.AddRange(backupDir.EnumerateFiles("*.cache")); + cacheFiles.AddRange(backupDir.EnumerateFiles("*.info")); + } + + if (cacheFiles.Count > 0) + { + foreach (FileInfo file in cacheFiles) { - file.Delete(); - } - catch (Exception ex) - { - await ContentDialogHelper.CreateErrorDialog(LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.DialogPPTCDeletionErrorMessage, file.Name, ex)); + try + { + file.Delete(); + } + catch (Exception ex) + { + await ContentDialogHelper.CreateErrorDialog( + LocaleManager.Instance.UpdateAndGetDynamicValue( + LocaleKeys.DialogPPTCDeletionErrorMessage, file.Name, ex)); + } } } } - } - }); - + }); + public static AsyncRelayCommand PurgeShaderCache { get; } = - Commands.CreateConditional(vm => vm?.SelectedApplication != null, + Commands.CreateConditional(vm => vm?.SelectedApplication != null, async viewModel => - { - UserResult result = await ContentDialogHelper.CreateLocalizedConfirmationDialog( - LocaleManager.Instance[LocaleKeys.DialogWarning], - LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.DialogShaderDeletionMessage, viewModel.SelectedApplication.Name) - ); - - if (result == UserResult.Yes) - { - DirectoryInfo shaderCacheDir = new(Path.Combine(AppDataManager.GamesDirPath, viewModel.SelectedApplication.IdString, "cache", "shader")); - - List oldCacheDirectories = []; - List newCacheFiles = []; - - if (shaderCacheDir.Exists) { - oldCacheDirectories.AddRange(shaderCacheDir.EnumerateDirectories("*")); - newCacheFiles.AddRange(shaderCacheDir.GetFiles("*.toc")); - newCacheFiles.AddRange(shaderCacheDir.GetFiles("*.data")); - } + UserResult result = await ContentDialogHelper.CreateLocalizedConfirmationDialog( + LocaleManager.Instance[LocaleKeys.DialogWarning], + LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.DialogShaderDeletionMessage, + viewModel.SelectedApplication.Name) + ); - if ((oldCacheDirectories.Count > 0 || newCacheFiles.Count > 0)) - { - foreach (DirectoryInfo directory in oldCacheDirectories) + if (result == UserResult.Yes) { - try + DirectoryInfo shaderCacheDir = new(Path.Combine(AppDataManager.GamesDirPath, + viewModel.SelectedApplication.IdString, "cache", "shader")); + + List oldCacheDirectories = []; + List newCacheFiles = []; + + if (shaderCacheDir.Exists) { - directory.Delete(true); + oldCacheDirectories.AddRange(shaderCacheDir.EnumerateDirectories("*")); + newCacheFiles.AddRange(shaderCacheDir.GetFiles("*.toc")); + newCacheFiles.AddRange(shaderCacheDir.GetFiles("*.data")); } - catch (Exception ex) + + if ((oldCacheDirectories.Count > 0 || newCacheFiles.Count > 0)) { - await ContentDialogHelper.CreateErrorDialog(LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.DialogPPTCDeletionErrorMessage, directory.Name, ex)); + foreach (DirectoryInfo directory in oldCacheDirectories) + { + try + { + directory.Delete(true); + } + catch (Exception ex) + { + await ContentDialogHelper.CreateErrorDialog( + LocaleManager.Instance.UpdateAndGetDynamicValue( + LocaleKeys.DialogPPTCDeletionErrorMessage, directory.Name, ex)); + } + } + + foreach (FileInfo file in newCacheFiles) + { + try + { + file.Delete(); + } + catch (Exception ex) + { + await ContentDialogHelper.CreateErrorDialog( + LocaleManager.Instance.UpdateAndGetDynamicValue( + LocaleKeys.ShaderCachePurgeError, file.Name, ex)); + } + } } } + }); - foreach (FileInfo file in newCacheFiles) - { - try - { - file.Delete(); - } - catch (Exception ex) - { - await ContentDialogHelper.CreateErrorDialog(LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.ShaderCachePurgeError, file.Name, ex)); - } - } - } - } - }); - public static RelayCommand OpenPtcDirectory { get; } = - Commands.CreateConditional(vm => vm?.SelectedApplication != null, + Commands.CreateConditional(vm => vm?.SelectedApplication != null, viewModel => - { - string ptcDir = Path.Combine(AppDataManager.GamesDirPath, viewModel.SelectedApplication.IdString, "cache", "cpu"); - string mainDir = Path.Combine(ptcDir, "0"); - string backupDir = Path.Combine(ptcDir, "1"); - - if (!Directory.Exists(ptcDir)) { - Directory.CreateDirectory(ptcDir); - Directory.CreateDirectory(mainDir); - Directory.CreateDirectory(backupDir); - } + string ptcDir = Path.Combine(AppDataManager.GamesDirPath, viewModel.SelectedApplication.IdString, + "cache", "cpu"); + string mainDir = Path.Combine(ptcDir, "0"); + string backupDir = Path.Combine(ptcDir, "1"); + + if (!Directory.Exists(ptcDir)) + { + Directory.CreateDirectory(ptcDir); + Directory.CreateDirectory(mainDir); + Directory.CreateDirectory(backupDir); + } + + OpenHelper.OpenFolder(ptcDir); + }); - OpenHelper.OpenFolder(ptcDir); - }); - public static RelayCommand OpenShaderCacheDirectory { get; } = - Commands.CreateConditional(vm => vm?.SelectedApplication != null, + Commands.CreateConditional(vm => vm?.SelectedApplication != null, viewModel => { - string shaderCacheDir = Path.Combine(AppDataManager.GamesDirPath, viewModel.SelectedApplication.IdString.ToLower(), "cache", "shader"); + string shaderCacheDir = Path.Combine(AppDataManager.GamesDirPath, + viewModel.SelectedApplication.IdString.ToLower(), "cache", "shader"); if (!Directory.Exists(shaderCacheDir)) { @@ -2225,7 +2282,7 @@ namespace Ryujinx.Ava.UI.ViewModels }); public static AsyncRelayCommand ExtractApplicationExeFs { get; } = - Commands.CreateConditional(vm => vm?.SelectedApplication != null, + Commands.CreateConditional(vm => vm?.SelectedApplication != null, async viewModel => { await ApplicationHelper.ExtractSection( @@ -2234,9 +2291,9 @@ namespace Ryujinx.Ava.UI.ViewModels viewModel.SelectedApplication.Path, viewModel.SelectedApplication.Name); }); - + public static AsyncRelayCommand ExtractApplicationRomFs { get; } = - Commands.CreateConditional(vm => vm?.SelectedApplication != null, + Commands.CreateConditional(vm => vm?.SelectedApplication != null, async viewModel => { await ApplicationHelper.ExtractSection( @@ -2245,13 +2302,14 @@ namespace Ryujinx.Ava.UI.ViewModels viewModel.SelectedApplication.Path, viewModel.SelectedApplication.Name); }); - + public static AsyncRelayCommand ExtractApplicationAocRomFs { get; } = - Commands.CreateConditional(vm => vm?.SelectedApplication != null, + Commands.CreateConditional(vm => vm?.SelectedApplication != null, async viewModel => { - DownloadableContentModel selectedDlc = await DlcSelectView.Show(viewModel.SelectedApplication.Id, viewModel.ApplicationLibrary); - + DownloadableContentModel selectedDlc = await DlcSelectView.Show(viewModel.SelectedApplication.Id, + viewModel.ApplicationLibrary); + if (selectedDlc is not null) { await ApplicationHelper.ExtractAoc( @@ -2260,16 +2318,17 @@ namespace Ryujinx.Ava.UI.ViewModels selectedDlc.FileName); } }); - + public static AsyncRelayCommand ExtractApplicationLogo { get; } = - Commands.CreateConditional(vm => vm?.SelectedApplication != null, + Commands.CreateConditional(vm => vm?.SelectedApplication != null, async viewModel => { - IReadOnlyList result = await viewModel.StorageProvider.OpenFolderPickerAsync(new FolderPickerOpenOptions - { - Title = LocaleManager.Instance[LocaleKeys.FolderDialogExtractTitle], - AllowMultiple = false, - }); + IReadOnlyList result = await viewModel.StorageProvider.OpenFolderPickerAsync( + new FolderPickerOpenOptions + { + Title = LocaleManager.Instance[LocaleKeys.FolderDialogExtractTitle], + AllowMultiple = false, + }); if (result.Count == 0) return; @@ -2280,7 +2339,8 @@ namespace Ryujinx.Ava.UI.ViewModels viewModel.SelectedApplication.Path, viewModel.SelectedApplication.Name); - IStorageFile iconFile = await result[0].CreateFileAsync($"{viewModel.SelectedApplication.IdString}.png"); + IStorageFile iconFile = + await result[0].CreateFileAsync($"{viewModel.SelectedApplication.IdString}.png"); await using Stream fileStream = await iconFile.OpenWriteAsync(); using SKBitmap bitmap = SKBitmap.Decode(viewModel.SelectedApplication.Icon) @@ -2291,43 +2351,6 @@ namespace Ryujinx.Ava.UI.ViewModels png.SaveTo(fileStream); }); - public static RelayCommand CreateApplicationShortcut { get; } = - Commands.CreateConditional(vm => vm?.SelectedApplication != null, - viewModel => ShortcutHelper.CreateAppShortcut( - viewModel.SelectedApplication.Path, - viewModel.SelectedApplication.Name, - viewModel.SelectedApplication.IdString, - viewModel.SelectedApplication.Icon - )); - - public static AsyncRelayCommand EditGameConfiguration { get; } = - Commands.CreateConditional(vm => vm?.SelectedApplication != null, - async viewModel => - { - await StyleableAppWindow.ShowAsync(new GameSpecificSettingsWindow(viewModel)); - - // just checking for file presence - viewModel.SelectedApplication.HasIndependentConfiguration = File.Exists(Program.GetDirGameUserConfig(viewModel.SelectedApplication.IdString,false,false)); - - viewModel.RefreshView(); - }); - - public static AsyncRelayCommand OpenApplicationCompatibility { get; } = - Commands.CreateConditional(vm => vm?.SelectedApplication != null, - viewModel => CompatibilityListWindow.Show(viewModel.SelectedApplication.IdString)); - - public static AsyncRelayCommand OpenApplicationData { get; } = - Commands.CreateConditional(vm => vm?.SelectedApplication != null, - viewModel => ApplicationDataView.Show(viewModel.SelectedApplication)); - - public static AsyncRelayCommand RunApplication { get; } = - Commands.CreateConditional(vm => vm?.SelectedApplication != null, - viewModel => viewModel.LoadApplication(viewModel.SelectedApplication)); - - public static AsyncRelayCommand TrimXci { get; } = - Commands.CreateConditional(vm => vm?.SelectedApplication != null, - viewModel => viewModel.TrimXCIFile(viewModel.SelectedApplication.Path)); - #endregion } } From 84686d50cdd8757db8c310ee28992cb49ed4c625 Mon Sep 17 00:00:00 2001 From: GreemDev Date: Thu, 29 May 2025 02:37:52 -0500 Subject: [PATCH 038/105] Revert "PPTC: fix rare EndOfStreamException in ContainsBlacklistedFunctions" This reverts commit 1156307ef913b1cd86ee083b7c8a0526c68c9567 --- src/ARMeilleure/Translation/PTC/Ptc.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ARMeilleure/Translation/PTC/Ptc.cs b/src/ARMeilleure/Translation/PTC/Ptc.cs index 33e46973a..72f9d5a0a 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 < _infosStream.Length; index++) + for (int index = 0; index < GetEntriesCount(); index++) { InfoEntry infoEntry = DeserializeStructure(_infosStream); foreach (ulong address in blacklist) @@ -201,7 +201,7 @@ namespace ARMeilleure.Translation.PTC if (infoEntry.Address == address) { containsBlacklistedFunctions = true; - Logger.Warning?.Print(LogClass.Ptc, "Translation cache invalidated: Found blacklisted functions"); + Logger.Warning?.Print(LogClass.Ptc, "PPTC cache invalidated: Found blacklisted functions in PPTC cache"); foundBadFunction = true; break; } From 4c281062baba1ff0e3a0de312d0e7cbea1f0fd69 Mon Sep 17 00:00:00 2001 From: GreemDev Date: Thu, 29 May 2025 15:52:49 -0500 Subject: [PATCH 039/105] test new canary release channel repo --- .github/workflows/canary.yml | 46 +++++++++++++++++------------------- 1 file changed, 22 insertions(+), 24 deletions(-) diff --git a/.github/workflows/canary.yml b/.github/workflows/canary.yml index 0207442a2..a9511465e 100644 --- a/.github/workflows/canary.yml +++ b/.github/workflows/canary.yml @@ -56,24 +56,24 @@ jobs: with: name: "Canary ${{ steps.version_info.outputs.build_version }}" tag: ${{ steps.version_info.outputs.build_version }} - body: | + body: | # Canary builds: These builds are experimental and may sometimes not work, use [regular builds](https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/Stable-Releases/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/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-canary-${{ steps.version_info.outputs.build_version }}-win_x64.zip) | - | Windows ARM 64-bit | [Canary Windows ARM Artifact](https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-canary-${{ steps.version_info.outputs.build_version }}-win_arm64.zip) | - | Linux 64-bit | [Canary Linux Artifact](https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-canary-${{ steps.version_info.outputs.build_version }}-linux_x64.tar.gz) | - | Linux ARM 64-bit | [Canary Linux ARM Artifact](https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-canary-${{ steps.version_info.outputs.build_version }}-linux_arm64.tar.gz) | - | macOS | [Canary macOS Artifact](https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-canary-${{ steps.version_info.outputs.build_version }}-macos_universal.app.tar.gz) | + | 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: ${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }} - repo: ${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }} - token: ${{ secrets.RELEASE_TOKEN }} + owner: ${{ secrets.RC_OWNER }} + repo: ${{ secrets.RC_CANARY_NAME }} + token: ${{ secrets.ALT_RELEASE_TOKEN }} release: name: Release for ${{ matrix.platform.name }} @@ -110,7 +110,6 @@ jobs: sed -r --in-place 's/\%\%RYUJINX_TARGET_RELEASE_CHANNEL_NAME\%\%/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_NAME }}/g;' src/Ryujinx.Common/ReleaseInformation.cs sed -r --in-place 's/\%\%RYUJINX_TARGET_RELEASE_CHANNEL_OWNER\%\%/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/g;' src/Ryujinx.Common/ReleaseInformation.cs sed -r --in-place 's/\%\%RYUJINX_TARGET_RELEASE_CHANNEL_REPO\%\%/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/g;' src/Ryujinx.Common/ReleaseInformation.cs - sed -r --in-place 's/\%\%RYUJINX_TARGET_RELEASE_CHANNEL_SOURCE_REPO\%\%/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_SOURCE_REPO }}/g;' src/Ryujinx.Common/ReleaseInformation.cs sed -r --in-place 's/\%\%RYUJINX_CONFIG_FILE_NAME\%\%/Config\.json/g;' src/Ryujinx.Common/ReleaseInformation.cs sed -r --in-place '/^Name=Ryujinx$/s/Name=Ryujinx/Name=Ryujinx-Canary/' distribution/linux/Ryujinx.desktop shell: bash @@ -169,7 +168,7 @@ jobs: exit 1 fi - export UFLAG="gh-releases-zsync|${{ github.repository_owner }}|Canary-Releases|latest|*-$ARCH_NAME.AppImage.zsync" + export UFLAG="gh-releases-zsync|${{ secrets.RC_OWNER }}${{ secrets.RC_CANARY_NAME }}|latest|*-$ARCH_NAME.AppImage.zsync" BUILDDIR=publish OUTDIR=publish_appimage distribution/linux/appimage/build-appimage.sh pushd publish_appimage @@ -187,23 +186,23 @@ jobs: body: | # Canary builds: - These builds are experimental and may sometimes not work, use [regular builds](https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/releases/latest) instead if that sounds like something you don't want to deal with. + These builds are experimental and may sometimes not work, use [regular builds](https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/Stable-Releases/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/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-canary-${{ steps.version_info.outputs.build_version }}-win_x64.zip) | - | Windows ARM 64-bit | [Canary Windows ARM Artifact](https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-canary-${{ steps.version_info.outputs.build_version }}-win_arm64.zip) | - | Linux 64-bit | [Canary Linux Artifact](https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-canary-${{ steps.version_info.outputs.build_version }}-linux_x64.tar.gz) | - | Linux ARM 64-bit | [Canary Linux ARM Artifact](https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-canary-${{ steps.version_info.outputs.build_version }}-linux_arm64.tar.gz) | - | macOS | [Canary macOS Artifact](https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-canary-${{ steps.version_info.outputs.build_version }}-macos_universal.app.tar.gz) | + | 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: ${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }} - repo: ${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }} - token: ${{ secrets.RELEASE_TOKEN }} + owner: ${{ secrets.RC_OWNER }} + repo: ${{ secrets.RC_CANARY_NAME }} + token: ${{ secrets.ALT_RELEASE_TOKEN }} macos_release: name: Release MacOS universal @@ -246,7 +245,6 @@ jobs: sed -r --in-place 's/\%\%RYUJINX_TARGET_RELEASE_CHANNEL_NAME\%\%/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_NAME }}/g;' src/Ryujinx.Common/ReleaseInformation.cs sed -r --in-place 's/\%\%RYUJINX_TARGET_RELEASE_CHANNEL_OWNER\%\%/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/g;' src/Ryujinx.Common/ReleaseInformation.cs sed -r --in-place 's/\%\%RYUJINX_TARGET_RELEASE_CHANNEL_REPO\%\%/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/g;' src/Ryujinx.Common/ReleaseInformation.cs - sed -r --in-place 's/\%\%RYUJINX_TARGET_RELEASE_CHANNEL_SOURCE_REPO\%\%/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_SOURCE_REPO }}/g;' src/Ryujinx.Common/ReleaseInformation.cs sed -r --in-place 's/\%\%RYUJINX_CONFIG_FILE_NAME\%\%/Config\.json/g;' src/Ryujinx.Common/ReleaseInformation.cs shell: bash @@ -264,6 +262,6 @@ jobs: omitBodyDuringUpdate: true allowUpdates: true replacesArtifacts: true - owner: ${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }} - repo: ${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }} - token: ${{ secrets.RELEASE_TOKEN }} + owner: ${{ secrets.RC_OWNER }} + repo: ${{ secrets.RC_CANARY_NAME }} + token: ${{ secrets.ALT_RELEASE_TOKEN }} From 92b2947f04183803cdd70bea2779ace854597da9 Mon Sep 17 00:00:00 2001 From: GreemDev Date: Thu, 29 May 2025 16:14:51 -0500 Subject: [PATCH 040/105] fix invalid link in canary release message & change stable too --- .github/workflows/canary.yml | 5 ++--- .github/workflows/release.yml | 41 ++++++++++++++++------------------- 2 files changed, 21 insertions(+), 25 deletions(-) diff --git a/.github/workflows/canary.yml b/.github/workflows/canary.yml index a9511465e..dce71799f 100644 --- a/.github/workflows/canary.yml +++ b/.github/workflows/canary.yml @@ -22,7 +22,6 @@ env: RYUJINX_BASE_VERSION: "1.3" RYUJINX_TARGET_RELEASE_CHANNEL_NAME: "canary" RYUJINX_TARGET_RELEASE_CHANNEL_OWNER: "Ryubing" - RYUJINX_TARGET_RELEASE_CHANNEL_SOURCE_REPO: "Ryujinx" RYUJINX_TARGET_RELEASE_CHANNEL_REPO: "Canary-Releases" RELEASE: 1 @@ -59,7 +58,7 @@ jobs: body: | # Canary builds: - These builds are experimental and may sometimes not work, use [regular builds](https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/Stable-Releases/releases/latest) instead if that sounds like something you don't want to deal with. + 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 | |--|--| @@ -186,7 +185,7 @@ jobs: body: | # Canary builds: - These builds are experimental and may sometimes not work, use [regular builds](https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/Stable-Releases/releases/latest) instead if that sounds like something you don't want to deal with. + 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 | |--|--| diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index a0901cfa9..b3fe9c1ec 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -12,7 +12,6 @@ env: RYUJINX_BASE_VERSION: "1.3" RYUJINX_TARGET_RELEASE_CHANNEL_NAME: "release" RYUJINX_TARGET_RELEASE_CHANNEL_OWNER: "Ryubing" - RYUJINX_TARGET_RELEASE_CHANNEL_SOURCE_REPO: "Ryujinx" RYUJINX_TARGET_RELEASE_CHANNEL_REPO: "Stable-Releases" RELEASE: 1 @@ -50,17 +49,17 @@ jobs: # Stable builds: | Platform | Artifact | |--|--| - | Windows 64-bit | [Stable Windows Artifact](https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-${{ steps.version_info.outputs.build_version }}-win_x64.zip) | - | Windows ARM 64-bit | [Stable Windows ARM Artifact](https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-${{ steps.version_info.outputs.build_version }}-win_arm64.zip) | - | Linux 64-bit | [Stable Linux Artifact](https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-${{ steps.version_info.outputs.build_version }}-linux_x64.tar.gz) | - | Linux ARM 64-bit | [Stable Linux ARM Artifact](https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-${{ steps.version_info.outputs.build_version }}-linux_arm64.tar.gz) | - | macOS | [Stable macOS Artifact](https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-${{ steps.version_info.outputs.build_version }}-macos_universal.app.tar.gz) | + | Windows 64-bit | [Stable Windows Artifact](https://github.com/${{ secrets.RC_OWNER }}/${{ secrets.RC_STABLE_NAME }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-${{ steps.version_info.outputs.build_version }}-win_x64.zip) | + | Windows ARM 64-bit | [Stable Windows ARM Artifact](https://github.com/${{ secrets.RC_OWNER }}/${{ secrets.RC_STABLE_NAME }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-${{ steps.version_info.outputs.build_version }}-win_arm64.zip) | + | Linux 64-bit | [Stable Linux Artifact](https://github.com/${{ secrets.RC_OWNER }}/${{ secrets.RC_STABLE_NAME }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-${{ steps.version_info.outputs.build_version }}-linux_x64.tar.gz) | + | Linux ARM 64-bit | [Stable Linux ARM Artifact](https://github.com/${{ secrets.RC_OWNER }}/${{ secrets.RC_STABLE_NAME }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-${{ steps.version_info.outputs.build_version }}-linux_arm64.tar.gz) | + | macOS | [Stable macOS Artifact](https://github.com/${{ secrets.RC_OWNER }}/${{ secrets.RC_STABLE_NAME }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-${{ steps.version_info.outputs.build_version }}-macos_universal.app.tar.gz) | **[Full Changelog](https://git.ryujinx.app/ryubing/ryujinx/-/compare/${{ steps.version_info.outputs.prev_build_version }}...${{ steps.version_info.outputs.build_version }})** omitBodyDuringUpdate: true - owner: ${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }} - repo: ${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }} - token: ${{ secrets.RELEASE_TOKEN }} + owner: ${{ secrets.RC_OWNER }} + repo: ${{ secrets.RC_STABLE_NAME }} + token: ${{ secrets.ALT_RELEASE_TOKEN }} release: name: Release for ${{ matrix.platform.name }} @@ -97,7 +96,6 @@ jobs: sed -r --in-place 's/\%\%RYUJINX_TARGET_RELEASE_CHANNEL_NAME\%\%/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_NAME }}/g;' src/Ryujinx.Common/ReleaseInformation.cs sed -r --in-place 's/\%\%RYUJINX_TARGET_RELEASE_CHANNEL_OWNER\%\%/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/g;' src/Ryujinx.Common/ReleaseInformation.cs sed -r --in-place 's/\%\%RYUJINX_TARGET_RELEASE_CHANNEL_REPO\%\%/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/g;' src/Ryujinx.Common/ReleaseInformation.cs - sed -r --in-place 's/\%\%RYUJINX_TARGET_RELEASE_CHANNEL_SOURCE_REPO\%\%/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_SOURCE_REPO }}/g;' src/Ryujinx.Common/ReleaseInformation.cs sed -r --in-place 's/\%\%RYUJINX_CONFIG_FILE_NAME\%\%/Config\.json/g;' src/Ryujinx.Common/ReleaseInformation.cs shell: bash @@ -174,19 +172,19 @@ jobs: # Stable builds: | Platform | Artifact | |--|--| - | Windows 64-bit | [Stable Windows Artifact](https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-${{ steps.version_info.outputs.build_version }}-win_x64.zip) | - | Windows ARM 64-bit | [Stable Windows ARM Artifact](https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-${{ steps.version_info.outputs.build_version }}-win_arm64.zip) | - | Linux 64-bit | [Stable Linux Artifact](https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-${{ steps.version_info.outputs.build_version }}-linux_x64.tar.gz) | - | Linux ARM 64-bit | [Stable Linux ARM Artifact](https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-${{ steps.version_info.outputs.build_version }}-linux_arm64.tar.gz) | - | macOS | [Stable macOS Artifact](https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-${{ steps.version_info.outputs.build_version }}-macos_universal.app.tar.gz) | + | Windows 64-bit | [Stable Windows Artifact](https://github.com/${{ secrets.RC_OWNER }}/${{ secrets.RC_STABLE_NAME }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-${{ steps.version_info.outputs.build_version }}-win_x64.zip) | + | Windows ARM 64-bit | [Stable Windows ARM Artifact](https://github.com/${{ secrets.RC_OWNER }}/${{ secrets.RC_STABLE_NAME }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-${{ steps.version_info.outputs.build_version }}-win_arm64.zip) | + | Linux 64-bit | [Stable Linux Artifact](https://github.com/${{ secrets.RC_OWNER }}/${{ secrets.RC_STABLE_NAME }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-${{ steps.version_info.outputs.build_version }}-linux_x64.tar.gz) | + | Linux ARM 64-bit | [Stable Linux ARM Artifact](https://github.com/${{ secrets.RC_OWNER }}/${{ secrets.RC_STABLE_NAME }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-${{ steps.version_info.outputs.build_version }}-linux_arm64.tar.gz) | + | macOS | [Stable macOS Artifact](https://github.com/${{ secrets.RC_OWNER }}/${{ secrets.RC_STABLE_NAME }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-${{ steps.version_info.outputs.build_version }}-macos_universal.app.tar.gz) | **[Full Changelog](https://git.ryujinx.app/ryubing/ryujinx/-/compare/${{ steps.version_info.outputs.prev_build_version }}...${{ steps.version_info.outputs.build_version }})** omitBodyDuringUpdate: true allowUpdates: true replacesArtifacts: true - owner: ${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }} - repo: ${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }} - token: ${{ secrets.RELEASE_TOKEN }} + owner: ${{ secrets.RC_OWNER }} + repo: ${{ secrets.RC_STABLE_NAME }} + token: ${{ secrets.ALT_RELEASE_TOKEN }} macos_release: name: Release MacOS universal @@ -229,7 +227,6 @@ jobs: sed -r --in-place 's/\%\%RYUJINX_TARGET_RELEASE_CHANNEL_NAME\%\%/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_NAME }}/g;' src/Ryujinx.Common/ReleaseInformation.cs sed -r --in-place 's/\%\%RYUJINX_TARGET_RELEASE_CHANNEL_OWNER\%\%/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/g;' src/Ryujinx.Common/ReleaseInformation.cs sed -r --in-place 's/\%\%RYUJINX_TARGET_RELEASE_CHANNEL_REPO\%\%/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/g;' src/Ryujinx.Common/ReleaseInformation.cs - sed -r --in-place 's/\%\%RYUJINX_TARGET_RELEASE_CHANNEL_SOURCE_REPO\%\%/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_SOURCE_REPO }}/g;' src/Ryujinx.Common/ReleaseInformation.cs sed -r --in-place 's/\%\%RYUJINX_CONFIG_FILE_NAME\%\%/Config\.json/g;' src/Ryujinx.Common/ReleaseInformation.cs shell: bash @@ -247,6 +244,6 @@ jobs: omitBodyDuringUpdate: true allowUpdates: true replacesArtifacts: true - owner: ${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }} - repo: ${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }} - token: ${{ secrets.RELEASE_TOKEN }} + owner: ${{ secrets.RC_OWNER }} + repo: ${{ secrets.RC_STABLE_NAME }} + token: ${{ secrets.ALT_RELEASE_TOKEN }} From 3429361a5d35d94fd20d434b1887fcf365658ba9 Mon Sep 17 00:00:00 2001 From: GreemDev Date: Thu, 29 May 2025 17:35:43 -0500 Subject: [PATCH 041/105] UI: RPC: Remove release channel from RPC logo hover --- src/Ryujinx/Systems/DiscordIntegrationModule.cs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/Ryujinx/Systems/DiscordIntegrationModule.cs b/src/Ryujinx/Systems/DiscordIntegrationModule.cs index 437d35ec1..f658aa9ec 100644 --- a/src/Ryujinx/Systems/DiscordIntegrationModule.cs +++ b/src/Ryujinx/Systems/DiscordIntegrationModule.cs @@ -21,10 +21,7 @@ namespace Ryujinx.Ava.Systems private static string VersionString => (ReleaseInformation.IsCanaryBuild ? "Canary " : string.Empty) + $"v{ReleaseInformation.Version}"; - private static readonly string _description = - ReleaseInformation.IsValid - ? $"{VersionString} {ReleaseInformation.ReleaseChannelOwner}/{ReleaseInformation.ReleaseChannelRepo}" - : "dev build"; + private static readonly string _description = ReleaseInformation.IsValid ? VersionString : "dev build"; private const string ApplicationId = "1293250299716173864"; From 813d05bdf7b008501cd7ff5a8fb53c5cf0bf6e09 Mon Sep 17 00:00:00 2001 From: GreemDev Date: Thu, 29 May 2025 17:36:24 -0500 Subject: [PATCH 042/105] misc: Remove internal release channel constants --- .github/workflows/canary.yml | 4 ---- .github/workflows/release.yml | 6 ------ src/Ryujinx.Common/ReleaseInformation.cs | 12 +++--------- 3 files changed, 3 insertions(+), 19 deletions(-) diff --git a/.github/workflows/canary.yml b/.github/workflows/canary.yml index dce71799f..de3dd6892 100644 --- a/.github/workflows/canary.yml +++ b/.github/workflows/canary.yml @@ -21,8 +21,6 @@ env: DOTNET_CLI_TELEMETRY_OPTOUT: 1 RYUJINX_BASE_VERSION: "1.3" RYUJINX_TARGET_RELEASE_CHANNEL_NAME: "canary" - RYUJINX_TARGET_RELEASE_CHANNEL_OWNER: "Ryubing" - RYUJINX_TARGET_RELEASE_CHANNEL_REPO: "Canary-Releases" RELEASE: 1 jobs: @@ -107,8 +105,6 @@ jobs: sed -r --in-place 's/\%\%RYUJINX_BUILD_VERSION\%\%/${{ steps.version_info.outputs.build_version }}/g;' src/Ryujinx.Common/ReleaseInformation.cs sed -r --in-place 's/\%\%RYUJINX_BUILD_GIT_HASH\%\%/${{ steps.version_info.outputs.git_short_hash }}/g;' src/Ryujinx.Common/ReleaseInformation.cs sed -r --in-place 's/\%\%RYUJINX_TARGET_RELEASE_CHANNEL_NAME\%\%/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_NAME }}/g;' src/Ryujinx.Common/ReleaseInformation.cs - sed -r --in-place 's/\%\%RYUJINX_TARGET_RELEASE_CHANNEL_OWNER\%\%/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/g;' src/Ryujinx.Common/ReleaseInformation.cs - sed -r --in-place 's/\%\%RYUJINX_TARGET_RELEASE_CHANNEL_REPO\%\%/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/g;' src/Ryujinx.Common/ReleaseInformation.cs sed -r --in-place 's/\%\%RYUJINX_CONFIG_FILE_NAME\%\%/Config\.json/g;' src/Ryujinx.Common/ReleaseInformation.cs sed -r --in-place '/^Name=Ryujinx$/s/Name=Ryujinx/Name=Ryujinx-Canary/' distribution/linux/Ryujinx.desktop shell: bash diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index b3fe9c1ec..85c494dcb 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -11,8 +11,6 @@ env: DOTNET_CLI_TELEMETRY_OPTOUT: 1 RYUJINX_BASE_VERSION: "1.3" RYUJINX_TARGET_RELEASE_CHANNEL_NAME: "release" - RYUJINX_TARGET_RELEASE_CHANNEL_OWNER: "Ryubing" - RYUJINX_TARGET_RELEASE_CHANNEL_REPO: "Stable-Releases" RELEASE: 1 jobs: @@ -94,8 +92,6 @@ jobs: sed -r --in-place 's/\%\%RYUJINX_BUILD_VERSION\%\%/${{ steps.version_info.outputs.build_version }}/g;' src/Ryujinx.Common/ReleaseInformation.cs sed -r --in-place 's/\%\%RYUJINX_BUILD_GIT_HASH\%\%/${{ steps.version_info.outputs.git_short_hash }}/g;' src/Ryujinx.Common/ReleaseInformation.cs sed -r --in-place 's/\%\%RYUJINX_TARGET_RELEASE_CHANNEL_NAME\%\%/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_NAME }}/g;' src/Ryujinx.Common/ReleaseInformation.cs - sed -r --in-place 's/\%\%RYUJINX_TARGET_RELEASE_CHANNEL_OWNER\%\%/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/g;' src/Ryujinx.Common/ReleaseInformation.cs - sed -r --in-place 's/\%\%RYUJINX_TARGET_RELEASE_CHANNEL_REPO\%\%/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/g;' src/Ryujinx.Common/ReleaseInformation.cs sed -r --in-place 's/\%\%RYUJINX_CONFIG_FILE_NAME\%\%/Config\.json/g;' src/Ryujinx.Common/ReleaseInformation.cs shell: bash @@ -225,8 +221,6 @@ jobs: sed -r --in-place 's/\%\%RYUJINX_BUILD_VERSION\%\%/${{ steps.version_info.outputs.build_version }}/g;' src/Ryujinx.Common/ReleaseInformation.cs sed -r --in-place 's/\%\%RYUJINX_BUILD_GIT_HASH\%\%/${{ steps.version_info.outputs.git_short_hash }}/g;' src/Ryujinx.Common/ReleaseInformation.cs sed -r --in-place 's/\%\%RYUJINX_TARGET_RELEASE_CHANNEL_NAME\%\%/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_NAME }}/g;' src/Ryujinx.Common/ReleaseInformation.cs - sed -r --in-place 's/\%\%RYUJINX_TARGET_RELEASE_CHANNEL_OWNER\%\%/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/g;' src/Ryujinx.Common/ReleaseInformation.cs - sed -r --in-place 's/\%\%RYUJINX_TARGET_RELEASE_CHANNEL_REPO\%\%/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/g;' src/Ryujinx.Common/ReleaseInformation.cs sed -r --in-place 's/\%\%RYUJINX_CONFIG_FILE_NAME\%\%/Config\.json/g;' src/Ryujinx.Common/ReleaseInformation.cs shell: bash diff --git a/src/Ryujinx.Common/ReleaseInformation.cs b/src/Ryujinx.Common/ReleaseInformation.cs index b539caa6e..fe47ce2ed 100644 --- a/src/Ryujinx.Common/ReleaseInformation.cs +++ b/src/Ryujinx.Common/ReleaseInformation.cs @@ -1,6 +1,7 @@ using Ryujinx.Common.Utilities; using System; using System.Net.Http; +using System.Net.Http.Json; using System.Reflection; using System.Text.Json.Serialization; using System.Threading.Tasks; @@ -14,22 +15,15 @@ namespace Ryujinx.Common private const string ReleaseChannel = "release"; private const string BuildVersion = "%%RYUJINX_BUILD_VERSION%%"; - public const string BuildGitHash = "%%RYUJINX_BUILD_GIT_HASH%%"; + private const string BuildGitHash = "%%RYUJINX_BUILD_GIT_HASH%%"; private const string ReleaseChannelName = "%%RYUJINX_TARGET_RELEASE_CHANNEL_NAME%%"; private const string ConfigFileName = "%%RYUJINX_CONFIG_FILE_NAME%%"; - public const string ReleaseChannelOwner = "%%RYUJINX_TARGET_RELEASE_CHANNEL_OWNER%%"; - public const string ReleaseChannelSourceRepo = "%%RYUJINX_TARGET_RELEASE_CHANNEL_SOURCE_REPO%%"; - public const string ReleaseChannelRepo = "%%RYUJINX_TARGET_RELEASE_CHANNEL_REPO%%"; - public static string ConfigName => !ConfigFileName.StartsWith("%%") ? ConfigFileName : "Config.json"; public static bool IsValid => !BuildGitHash.StartsWith("%%") && !ReleaseChannelName.StartsWith("%%") && - !ReleaseChannelOwner.StartsWith("%%") && - !ReleaseChannelSourceRepo.StartsWith("%%") && - !ReleaseChannelRepo.StartsWith("%%") && !ConfigFileName.StartsWith("%%"); public static bool IsCanaryBuild => IsValid && ReleaseChannelName.Equals(CanaryChannel); @@ -48,7 +42,7 @@ namespace Ryujinx.Common public static async Task GetReleaseChannelsAsync(HttpClient httpClient) { - ReleaseChannelPair releaseChannelPair = JsonHelper.Deserialize(await httpClient.GetStringAsync("https://ryujinx.app/api/release-channels"), ReleaseChannelPairContext.Default.ReleaseChannelPair); + ReleaseChannelPair releaseChannelPair = await httpClient.GetFromJsonAsync("https://ryujinx.app/api/release-channels", ReleaseChannelPairContext.Default.ReleaseChannelPair); return new ReleaseChannels(releaseChannelPair); } } From 417df486b147264a92ec5cb5c1dd630b4b1c3780 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hack=E8=8C=B6=E3=82=93?= Date: Thu, 29 May 2025 19:09:03 -0500 Subject: [PATCH 043/105] Update Korean translation See merge request ryubing/ryujinx!43 --- assets/locales.json | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/assets/locales.json b/assets/locales.json index 08eade16e..2c4b4ec7a 100644 --- a/assets/locales.json +++ b/assets/locales.json @@ -3159,7 +3159,7 @@ "he_IL": "{1}/{0} משחקים נטענו", "it_IT": "{0}/{1} giochi caricati", "ja_JP": "{0}/{1} ゲーム", - "ko_KR": "{0}/{1}개의 게임 확인", + "ko_KR": "{0}/{1}개의 게임 타이틀", "no_NO": "{0}/{1} Spill Lastet", "pl_PL": "{0}/{1} Załadowane gry", "pt_BR": "{0}/{1} Jogos Carregados", @@ -7109,7 +7109,7 @@ "he_IL": "מושבת", "it_IT": "Disabilitato", "ja_JP": "無効", - "ko_KR": "비활성화됨", + "ko_KR": "비활성화", "no_NO": "Deaktivert", "pl_PL": "Wyłączone", "pt_BR": "Desabilitado", @@ -19684,7 +19684,7 @@ "he_IL": "מוריד עדכון...", "it_IT": "Download dell'aggiornamento...", "ja_JP": "アップデートをダウンロード中...", - "ko_KR": "업데이트 내려받기 중...", + "ko_KR": "업데이트 내려받는 중...", "no_NO": "Laster ned oppdatering...", "pl_PL": "Pobieranie Aktualizacji...", "pt_BR": "Baixando Atualização...", @@ -23409,7 +23409,7 @@ "he_IL": "", "it_IT": "Disabilitato", "ja_JP": "無効", - "ko_KR": "비활성화됨", + "ko_KR": "비활성화", "no_NO": "Deaktivert", "pl_PL": "Wyłączone", "pt_BR": "Desativado", @@ -24534,7 +24534,7 @@ "he_IL": "", "it_IT": "", "ja_JP": "", - "ko_KR": "어떠한 충돌이나 GPU 버그 없이 부팅 및 플레이가 가능하며, 일반 PC에서 충분히 즐길 수 있을 만큼 빠른 속도입니다.", + "ko_KR": "어떠한 충돌이나 GPU 버그 없이 부팅 및 플레이가 가능하며, 일반 PC에서 충분히 즐길 수 있을 만큼 쾌적한 속도입니다.", "no_NO": "Starter opp og spiller uten krasj eller GPU-feil av noe slag, og med en hastighet som er rask nok til å ha rimelig glede av på en gjennomsnittlig PC.", "pl_PL": "", "pt_BR": "Inicializa e roda sem travamentos ou bugs de GPU de qualquer tipo, e em uma velocidade rápida o suficiente para ser aproveitado em um PC comum.", @@ -24559,7 +24559,7 @@ "he_IL": "", "it_IT": "", "ja_JP": "", - "ko_KR": "부팅하고 게임에 들어가지만 충돌, 교착 상태, GPU 버그, 방해가 될 정도로 나쁜 오디오 또는 너무 느린 문제 중 하나 이상으로 인해 문제가 발생합니다. 게임은 여전히 ​​가능할 수 있습니다.", + "ko_KR": "부팅하고 게임에 진입하지만 충돌, 교착, GPU 버그, 오디오에 문제가 있거나 버벅임 중 하나 이상으로 인해 문제가 발생합니다. 게임은 어쨌든 진행할 수 있습니다.", "no_NO": "Starter og går i gang i spillet, men lider av ett eller flere av følgende: krasjer, fastlåser, GPU-feil, distraherende dårlig lyd eller er rett og slett for tregt. Spillet kan fortsatt spilles helt til ende, men ikke slik det er ment å spilles.", "pl_PL": "", "pt_BR": "Inicializa e entra no jogo, mas sofre de um ou mais dos seguintes: travamentos, deadlocks, bugs de GPU, áudio ruim que distrai ou é simplesmente muito lento. O jogo ainda pode ser jogado até o fim, mas não da forma como foi criado para ser jogado.", @@ -24634,7 +24634,7 @@ "he_IL": "", "it_IT": "", "ja_JP": "", - "ko_KR": "부팅되지 않거나 활동 흔적이 보이지 않습니다.", + "ko_KR": "부팅되지 않거나 동작하지 않습니다.", "no_NO": "Starter ikke opp eller viser ingen tegn til aktivitet.", "pl_PL": "", "pt_BR": "Não inicializa ou não mostra sinais de atividade.", From 361d0c56324bb8c001e9da029f8809d73b60b09b Mon Sep 17 00:00:00 2001 From: MrKev <41-mrkev@users.noreply.git.ryujinx.app> Date: Fri, 30 May 2025 17:08:34 -0500 Subject: [PATCH 044/105] Fix ~3500 analyser issues See merge request ryubing/ryujinx!44 --- .editorconfig | 45 ++-- .../CodeGen/Arm64/Arm64Optimizer.cs | 2 +- src/ARMeilleure/CodeGen/Arm64/Assembler.cs | 1 + .../CodeGen/Arm64/CodeGenCommon.cs | 2 +- .../CodeGen/Arm64/CodeGenContext.cs | 3 +- .../CodeGen/Arm64/CodeGenerator.cs | 13 +- .../CodeGen/Arm64/CodeGeneratorIntrinsic.cs | 1 - .../CodeGen/Arm64/HardwareCapabilities.cs | 1 + src/ARMeilleure/CodeGen/Arm64/PreAllocator.cs | 34 +-- .../CodeGen/Optimizations/ConstantFolding.cs | 22 ++ .../CodeGen/Optimizations/Optimizer.cs | 10 +- .../RegisterAllocators/LinearScanAllocator.cs | 6 +- src/ARMeilleure/CodeGen/X86/Assembler.cs | 2 +- src/ARMeilleure/CodeGen/X86/AssemblerTable.cs | 1 - src/ARMeilleure/CodeGen/X86/CodeGenContext.cs | 3 +- src/ARMeilleure/CodeGen/X86/CodeGenerator.cs | 10 +- src/ARMeilleure/CodeGen/X86/PreAllocator.cs | 19 +- src/ARMeilleure/CodeGen/X86/X86Optimizer.cs | 12 +- src/ARMeilleure/CodeGen/X86/X86Register.cs | 1 - src/ARMeilleure/Decoders/Decoder.cs | 27 +-- src/ARMeilleure/Decoders/DecoderHelper.cs | 1 + src/ARMeilleure/Decoders/OpCode32SimdDupGP.cs | 1 + .../Decoders/OpCode32SimdMemPair.cs | 2 +- .../Decoders/OpCode32SimdMemSingle.cs | 2 +- src/ARMeilleure/Decoders/OpCodeMemImm.cs | 4 +- src/ARMeilleure/Decoders/OpCodeTable.cs | 2 + src/ARMeilleure/Diagnostics/IRDumper.cs | 18 +- src/ARMeilleure/Instructions/InstEmitAlu32.cs | 2 + .../Instructions/InstEmitAluHelper.cs | 3 +- .../Instructions/InstEmitHashHelper.cs | 2 +- .../Instructions/InstEmitHelper.cs | 1 + .../Instructions/InstEmitMemoryEx.cs | 2 +- .../Instructions/InstEmitMemoryExHelper.cs | 1 + .../Instructions/InstEmitMemoryHelper.cs | 11 +- src/ARMeilleure/Instructions/InstEmitMul.cs | 1 - .../Instructions/InstEmitSimdArithmetic.cs | 2 +- .../Instructions/InstEmitSimdArithmetic32.cs | 8 + .../Instructions/InstEmitSimdCvt.cs | 10 +- .../Instructions/InstEmitSimdCvt32.cs | 4 +- .../Instructions/InstEmitSimdHelper.cs | 12 +- .../Instructions/InstEmitSimdHelper32.cs | 7 +- .../Instructions/InstEmitSimdHelper32Arm64.cs | 1 + .../Instructions/InstEmitSimdLogical32.cs | 1 + .../Instructions/InstEmitSimdMemory32.cs | 1 + .../Instructions/InstEmitSimdShift.cs | 11 +- .../Instructions/NativeInterface.cs | 4 +- src/ARMeilleure/Instructions/SoftFloat.cs | 34 +-- .../IntermediateRepresentation/Intrinsic.cs | 1 - .../IntermediateRepresentation/Operand.cs | 2 +- .../IntermediateRepresentation/OperandType.cs | 4 +- src/ARMeilleure/Memory/MemoryManagerType.cs | 4 +- src/ARMeilleure/State/ExecutionContext.cs | 6 +- src/ARMeilleure/State/NativeContext.cs | 2 + src/ARMeilleure/Translation/Cache/JitCache.cs | 3 +- src/ARMeilleure/Translation/Delegates.cs | 4 +- src/ARMeilleure/Translation/Dominance.cs | 2 +- src/ARMeilleure/Translation/IntervalTree.cs | 20 +- src/ARMeilleure/Translation/PTC/Ptc.cs | 18 +- .../Translation/PTC/PtcProfiler.cs | 17 +- .../OpenALHardwareDeviceDriver.cs | 2 +- .../SDL2HardwareDeviceDriver.cs | 2 - .../CompatLayerHardwareDeviceDriver.cs | 4 +- .../Dummy/DummyHardwareDeviceDriver.cs | 4 +- .../Common/AudioDeviceSession.cs | 2 +- src/Ryujinx.Audio/Input/AudioInputManager.cs | 2 +- src/Ryujinx.Audio/Input/AudioInputSystem.cs | 4 +- .../Integration/IHardwareDevice.cs | 2 +- .../Output/AudioOutputManager.cs | 2 +- src/Ryujinx.Audio/Output/AudioOutputSystem.cs | 4 +- .../Renderer/Device/VirtualDevice.cs | 2 +- .../Device/VirtualDeviceSessionRegistry.cs | 4 +- .../Renderer/Dsp/Command/DelayCommand.cs | 1 - .../Renderer/Dsp/State/DelayState.cs | 2 +- .../Renderer/Dsp/UpsamplerHelper.cs | 4 + .../Parameter/EffectInParameterVersion1.cs | 2 +- .../Parameter/EffectInParameterVersion2.cs | 2 +- .../Renderer/Server/AudioRenderSystem.cs | 14 +- .../Renderer/Server/CommandBuffer.cs | 1 - .../CommandProcessingTimeEstimatorVersion2.cs | 46 ++-- .../CommandProcessingTimeEstimatorVersion3.cs | 54 ++--- .../CommandProcessingTimeEstimatorVersion4.cs | 4 +- .../CommandProcessingTimeEstimatorVersion5.cs | 12 +- .../Renderer/Server/MemoryPool/PoolMapper.cs | 2 +- .../Splitter/SplitterDestinationVersion1.cs | 4 +- .../Splitter/SplitterDestinationVersion2.cs | 4 +- .../Renderer/Server/StateUpdater.cs | 6 +- .../Renderer/Server/Voice/WaveBuffer.cs | 1 - .../LocalesValidationTask.cs | 22 +- .../Collections/IntervalTree.cs | 6 +- .../Collections/IntrusiveRedBlackTree.cs | 4 + .../Collections/IntrusiveRedBlackTreeImpl.cs | 16 ++ .../Collections/TreeDictionary.cs | 18 +- .../Configuration/AppDataManager.cs | 2 + .../Configuration/AspectRatioExtensions.cs | 4 +- src/Ryujinx.Common/Configuration/DirtyHack.cs | 24 +- .../GenericControllerInputConfig.cs | 2 +- .../Controller/JoyconConfigControllerStick.cs | 4 +- .../Hid/Controller/LedConfigController.cs | 8 +- src/Ryujinx.Common/Configuration/VSyncMode.cs | 2 +- .../NVAPI/NvapiUnicodeString.cs | 2 +- src/Ryujinx.Common/Hash128.cs | 13 +- src/Ryujinx.Common/Helpers/ConsoleHelper.cs | 2 +- .../Helpers/FileAssociationHelper.cs | 15 +- src/Ryujinx.Common/Helpers/Patterns.cs | 2 +- src/Ryujinx.Common/Helpers/RefEvent.cs | 6 +- src/Ryujinx.Common/Helpers/RunningPlatform.cs | 22 +- src/Ryujinx.Common/Logging/Logger.cs | 2 +- .../Logging/Targets/ConsoleLogTarget.cs | 2 +- .../Logging/Targets/FileLogTarget.cs | 2 +- .../PreciseSleep/NanosleepEvent.cs | 1 + src/Ryujinx.Common/ReactiveObject.cs | 10 +- src/Ryujinx.Common/ReleaseInformation.cs | 14 +- src/Ryujinx.Common/RyujinxException.cs | 2 +- src/Ryujinx.Common/SharedConstants.cs | 2 +- .../SystemInterop/ForceDpiAware.cs | 3 +- .../SystemInterop/StdErrAdapter.cs | 9 +- src/Ryujinx.Common/TitleIDs.cs | 4 +- src/Ryujinx.Common/Utilities/BitUtils.cs | 6 +- .../Utilities/FileSystemUtils.cs | 2 +- src/Ryujinx.Common/Utilities/JsonHelper.cs | 6 +- src/Ryujinx.Common/Utilities/Rainbow.cs | 13 +- src/Ryujinx.Common/Utilities/StreamUtils.cs | 2 +- .../Utilities/XCIFileTrimmer.cs | 14 +- src/Ryujinx.Cpu/AddressTable.cs | 4 +- .../AppleHv/HvAddressSpaceRange.cs | 2 +- src/Ryujinx.Cpu/AppleHv/HvExecutionContext.cs | 2 +- src/Ryujinx.Cpu/ITickSource.cs | 4 +- .../AddressIntrusiveRedBlackTree.cs | 1 + .../AddressSpacePartitionAllocator.cs | 4 +- .../LightningJit/Arm32/InstName.cs | 2 +- .../LightningJit/Arm32/InstTableT32.cs | 2 +- .../Arm32/Target/Arm64/Compiler.cs | 5 +- .../Arm32/Target/Arm64/InstEmitAlu.cs | 1 + .../Arm32/Target/Arm64/InstEmitFlow.cs | 2 +- .../Arm32/Target/Arm64/InstEmitNeonCommon.cs | 30 +-- .../Arm32/Target/Arm64/InstEmitNeonMemory.cs | 2 +- .../Arm32/Target/Arm64/InstEmitNeonMove.cs | 4 +- .../Arm32/Target/Arm64/InstEmitSystem.cs | 3 + .../Arm32/Target/Arm64/InstEmitVfpCompare.cs | 2 +- .../Arm32/Target/Arm64/InstEmitVfpConvert.cs | 2 +- .../LightningJit/Arm64/InstName.cs | 2 +- .../Arm64/Target/Arm64/Compiler.cs | 9 +- .../Arm64/Target/Arm64/Decoder.cs | 4 +- .../Arm64/Target/Arm64/InstEmitSystem.cs | 3 +- .../Arm64/Target/Arm64/InstTable.cs | 2 +- .../LightningJit/Cache/JitCache.cs | 6 +- .../LightningJit/CodeGen/Arm64/Assembler.cs | 1 + .../CodeGen/Arm64/CodeGenCommon.cs | 2 +- .../LightningJit/CodeGen/OperandType.cs | 2 +- src/Ryujinx.Cpu/LightningJit/Translator.cs | 2 +- src/Ryujinx.Cpu/TickSource.cs | 13 +- src/Ryujinx.Graphics.GAL/IRenderer.cs | 2 +- .../Multithreading/BufferMap.cs | 1 - src/Ryujinx.Graphics.GAL/Target.cs | 14 +- src/Ryujinx.Graphics.GAL/TextureCreateInfo.cs | 6 +- src/Ryujinx.Graphics.GAL/ViewportSwizzle.cs | 1 - .../Engine/DeviceStateWithShadow.cs | 4 +- .../Engine/MME/MacroJitCompiler.cs | 1 + .../Engine/SetMmeShadowRamControlMode.cs | 2 +- .../Threed/ComputeDraw/VtgAsComputeContext.cs | 9 + .../Threed/ComputeDraw/VtgAsComputeState.cs | 4 +- .../Engine/Threed/IndirectDrawType.cs | 1 - .../Threed/SpecializationStateUpdater.cs | 6 +- .../Engine/Threed/StateUpdater.cs | 2 +- src/Ryujinx.Graphics.Gpu/GpuContext.cs | 4 +- src/Ryujinx.Graphics.Gpu/GraphicsConfig.cs | 28 ++- .../Image/AutoDeleteCache.cs | 1 - src/Ryujinx.Graphics.Gpu/Image/FormatTable.cs | 2 - src/Ryujinx.Graphics.Gpu/Image/Pool.cs | 1 + .../Image/SamplerDescriptor.cs | 3 + src/Ryujinx.Graphics.Gpu/Image/Texture.cs | 10 +- .../Image/TextureBindingsManager.cs | 4 +- .../Image/TextureCompatibility.cs | 32 +-- .../Image/TextureGroup.cs | 2 - src/Ryujinx.Graphics.Gpu/Image/TextureInfo.cs | 4 +- src/Ryujinx.Graphics.Gpu/Image/TexturePool.cs | 11 +- src/Ryujinx.Graphics.Gpu/Memory/Buffer.cs | 2 +- .../Memory/BufferBackingState.cs | 2 +- .../Memory/BufferStage.cs | 3 - .../Memory/BufferUpdater.cs | 2 +- .../Memory/PhysicalMemory.cs | 3 + src/Ryujinx.Graphics.Gpu/Memory/PteKind.cs | 2 +- .../DiskCache/BackgroundDiskCacheWriter.cs | 1 + .../Shader/DiskCache/BinarySerializer.cs | 2 + .../Shader/DiskCache/DiskCacheGuestStorage.cs | 4 +- .../Shader/DiskCache/DiskCacheHostStorage.cs | 2 +- .../DiskCache/ShaderBinarySerializer.cs | 3 +- .../Shader/GpuChannelGraphicsState.cs | 2 +- .../Native/FFmpegApi.cs | 1 - src/Ryujinx.Graphics.Nvdec.Vp9/BitDepth.cs | 2 +- src/Ryujinx.Graphics.Nvdec.Vp9/CodecErr.cs | 28 +-- .../Common/BitUtils.cs | 2 +- .../Common/MemoryAllocator.cs | 2 +- .../Common/MemoryUtil.cs | 2 +- src/Ryujinx.Graphics.Nvdec.Vp9/Constants.cs | 4 +- src/Ryujinx.Graphics.Nvdec.Vp9/DSubExp.cs | 4 +- src/Ryujinx.Graphics.Nvdec.Vp9/DecodeFrame.cs | 53 ++--- src/Ryujinx.Graphics.Nvdec.Vp9/DecodeMv.cs | 44 ++-- src/Ryujinx.Graphics.Nvdec.Vp9/Decoder.cs | 69 +++--- src/Ryujinx.Graphics.Nvdec.Vp9/Detokenize.cs | 14 +- .../Dsp/Convolve.cs | 4 +- src/Ryujinx.Graphics.Nvdec.Vp9/Dsp/Filter.cs | 2 +- .../Dsp/IntraPred.cs | 2 +- src/Ryujinx.Graphics.Nvdec.Vp9/Dsp/InvTxfm.cs | 150 ++++++------- .../Dsp/LoopFilterAuto.cs | 4 +- .../Dsp/LoopFilterScalar.cs | 2 +- .../Dsp/LoopFilterSse2.cs | 19 +- src/Ryujinx.Graphics.Nvdec.Vp9/Dsp/Prob.cs | 4 +- src/Ryujinx.Graphics.Nvdec.Vp9/Dsp/Reader.cs | 21 +- .../Dsp/TxfmCommon.cs | 2 +- src/Ryujinx.Graphics.Nvdec.Vp9/Entropy.cs | 4 +- src/Ryujinx.Graphics.Nvdec.Vp9/EntropyMode.cs | 58 ++--- src/Ryujinx.Graphics.Nvdec.Vp9/EntropyMv.cs | 7 +- .../FrameBuffers.cs | 2 +- src/Ryujinx.Graphics.Nvdec.Vp9/Idct.cs | 32 +-- .../InternalErrorException.cs | 2 +- .../InternalErrorInfo.cs | 2 +- src/Ryujinx.Graphics.Nvdec.Vp9/LoopFilter.cs | 52 +++-- src/Ryujinx.Graphics.Nvdec.Vp9/Luts.cs | 12 +- src/Ryujinx.Graphics.Nvdec.Vp9/PredCommon.cs | 12 +- src/Ryujinx.Graphics.Nvdec.Vp9/Prob.cs | 4 +- src/Ryujinx.Graphics.Nvdec.Vp9/QuantCommon.cs | 22 +- .../ReadBitBuffer.cs | 6 +- src/Ryujinx.Graphics.Nvdec.Vp9/ReconInter.cs | 9 +- src/Ryujinx.Graphics.Nvdec.Vp9/ReconIntra.cs | 4 +- src/Ryujinx.Graphics.Nvdec.Vp9/TileBuffer.cs | 2 +- .../TileWorkerData.cs | 2 +- .../Types/BModeInfo.cs | 2 +- .../Types/BitstreamProfile.cs | 4 +- .../Types/BlockSize.cs | 4 +- src/Ryujinx.Graphics.Nvdec.Vp9/Types/Buf2D.cs | 2 +- .../Types/BufferPool.cs | 4 +- .../Types/FrameType.cs | 2 +- .../Types/LoopFilter.cs | 2 +- .../Types/LoopFilterInfoN.cs | 2 +- .../Types/LoopFilterMask.cs | 2 +- .../Types/LoopFilterThresh.cs | 2 +- .../Types/MacroBlockD.cs | 14 +- .../Types/MacroBlockDPlane.cs | 2 +- .../Types/ModeInfo.cs | 6 +- .../Types/MotionVectorContext.cs | 2 +- src/Ryujinx.Graphics.Nvdec.Vp9/Types/Mv.cs | 16 +- src/Ryujinx.Graphics.Nvdec.Vp9/Types/Mv32.cs | 2 +- .../Types/MvClassType.cs | 2 +- .../Types/MvJointType.cs | 2 +- src/Ryujinx.Graphics.Nvdec.Vp9/Types/MvRef.cs | 2 +- .../Types/PartitionType.cs | 2 +- .../Types/PlaneType.cs | 4 +- .../Types/Position.cs | 2 +- .../Types/PredictionMode.cs | 4 +- .../Types/RefBuffer.cs | 2 +- .../Types/RefCntBuffer.cs | 4 +- .../Types/ReferenceMode.cs | 4 +- .../Types/ScaleFactors.cs | 20 +- .../Types/SegLvlFeatures.cs | 4 +- .../Types/Segmentation.cs | 4 +- .../Types/Surface.cs | 19 +- .../Types/TileInfo.cs | 2 +- .../Types/TxMode.cs | 4 +- .../Types/TxSize.cs | 4 +- .../Types/TxType.cs | 4 +- .../Types/Vp9Common.cs | 28 ++- .../Types/Vp9Decoder.cs | 7 +- .../Types/VpxCodecFrameBuffer.cs | 4 +- .../Types/VpxColorRange.cs | 4 +- .../Types/VpxColorSpace.cs | 4 +- src/Ryujinx.Graphics.OpenGL/Debugger.cs | 1 + src/Ryujinx.Graphics.OpenGL/FormatTable.cs | 8 +- src/Ryujinx.Graphics.OpenGL/HwCapabilities.cs | 10 +- .../Image/TextureCopy.cs | 2 +- .../Image/TextureView.cs | 11 +- .../Queries/BufferedQuery.cs | 1 + .../Queries/CounterQueue.cs | 1 + src/Ryujinx.Graphics.OpenGL/ResourcePool.cs | 1 + src/Ryujinx.Graphics.OpenGL/Sync.cs | 1 - src/Ryujinx.Graphics.OpenGL/VertexArray.cs | 4 +- src/Ryujinx.Graphics.OpenGL/Window.cs | 3 + .../CodeGen/Glsl/Declarations.cs | 6 +- .../CodeGen/Glsl/Instructions/InstGen.cs | 2 +- .../Glsl/Instructions/InstGenMemory.cs | 1 + .../CodeGen/Glsl/Instructions/InstType.cs | 1 - .../CodeGen/Glsl/Instructions/IoMap.cs | 6 +- .../CodeGen/Glsl/NumberFormatter.cs | 4 +- .../CodeGen/Glsl/OperandManager.cs | 4 +- .../CodeGen/Spirv/Instructions.cs | 1 + .../CodeGen/Spirv/IoMap.cs | 6 +- .../CodeGen/Spirv/SpirvGenerator.cs | 4 +- .../Decoders/Decoder.cs | 14 +- .../Instructions/AttributeMap.cs | 19 +- .../Instructions/InstEmitAttribute.cs | 22 +- .../Instructions/InstEmitConversion.cs | 44 ++-- .../Instructions/InstEmitFloatComparison.cs | 2 +- .../Instructions/InstEmitMemory.cs | 19 +- .../Instructions/InstEmitMove.cs | 7 +- .../Instructions/InstEmitShift.cs | 2 +- .../Instructions/InstEmitSurface.cs | 4 +- .../Instructions/InstEmitTexture.cs | 31 +-- .../IntermediateRepresentation/Instruction.cs | 6 +- .../IntermediateRepresentation/StorageKind.cs | 16 +- .../TextureFlags.cs | 1 - src/Ryujinx.Graphics.Shader/ShaderStage.cs | 10 +- .../StructuredIr/GotoElimination.cs | 6 +- .../StructuredIr/InstructionInfo.cs | 10 +- .../StructuredIr/ShaderProperties.cs | 2 +- .../StructuredIr/StructuredProgram.cs | 2 +- src/Ryujinx.Graphics.Shader/TextureHandle.cs | 4 +- .../Translation/AggregateType.cs | 1 - .../Translation/ControlFlowGraph.cs | 6 +- .../Translation/HelperFunctionManager.cs | 1 - .../Optimizations/ConstantFolding.cs | 1 + .../Optimizations/GlobalToStorage.cs | 24 +- .../Optimizations/Simplification.cs | 1 + .../Translation/Optimizations/Utils.cs | 4 +- .../Optimizations/XmadOptimizer.cs | 26 +-- .../Translation/ShaderHeader.cs | 2 + .../Transforms/GeometryToCompute.cs | 2 + .../Translation/Transforms/VertexToCompute.cs | 1 + .../Translation/TranslatorContext.cs | 8 +- .../Astc/AstcDecoder.cs | 6 +- src/Ryujinx.Graphics.Texture/Astc/Bits.cs | 1 + .../Astc/IntegerEncoded.cs | 1 + .../Encoders/BC7Encoder.cs | 4 +- .../LayoutConverter.cs | 7 + .../OffsetCalculator.cs | 1 - .../Utils/BC67Utils.cs | 6 +- .../Image/SurfaceReader.cs | 1 + src/Ryujinx.Graphics.Vic/Types/FrameFormat.cs | 4 +- src/Ryujinx.Graphics.Video/Vp9PictureInfo.cs | 2 +- src/Ryujinx.Graphics.Vulkan/BufferHolder.cs | 4 +- .../BufferMirrorRangeList.cs | 2 +- .../DescriptorSetTemplate.cs | 4 +- .../DescriptorSetUpdater.cs | 26 +-- src/Ryujinx.Graphics.Vulkan/FenceHelper.cs | 1 + .../FormatCapabilities.cs | 8 +- src/Ryujinx.Graphics.Vulkan/HelperShader.cs | 46 ++-- .../MoltenVK/MVKInitialization.cs | 1 + src/Ryujinx.Graphics.Vulkan/PipelineBase.cs | 2 +- .../PipelineDynamicState.cs | 12 +- src/Ryujinx.Graphics.Vulkan/PipelineState.cs | 10 +- .../Queries/BufferedQuery.cs | 2 + .../Queries/CounterQueue.cs | 1 + src/Ryujinx.Graphics.Vulkan/SamplerHolder.cs | 2 +- .../ShaderCollection.cs | 7 +- src/Ryujinx.Graphics.Vulkan/TextureStorage.cs | 4 +- src/Ryujinx.Graphics.Vulkan/TextureView.cs | 6 +- src/Ryujinx.Graphics.Vulkan/VulkanRenderer.cs | 14 +- src/Ryujinx.Graphics.Vulkan/Window.cs | 2 + .../IpcServiceGenerator.cs | 2 +- src/Ryujinx.HLE/FileSystem/ContentManager.cs | 32 ++- .../FileSystem/EncryptedFileSystemCreator.cs | 2 +- .../FileSystem/VirtualFileSystem.cs | 2 +- .../HOS/Applets/Browser/BrowserApplet.cs | 5 +- .../HOS/Applets/Cabinet/CabinetApplet.cs | 11 +- .../Applets/Controller/ControllerApplet.cs | 5 +- .../HOS/Applets/Dummy/DummyApplet.cs | 11 +- .../HOS/Applets/Error/ErrorApplet.cs | 2 +- .../PlayerSelect/PlayerSelectApplet.cs | 24 +- .../SoftwareKeyboardApplet.cs | 13 +- .../SoftwareKeyboardRendererBase.cs | 1 + .../HOS/ArmProcessContextFactory.cs | 1 + .../HOS/Diagnostics/Demangler/Demangler.cs | 97 +++++--- src/Ryujinx.HLE/HOS/Horizon.cs | 3 + .../HOS/Kernel/Ipc/KServerSession.cs | 2 +- .../HOS/Kernel/Memory/KCodeMemory.cs | 2 +- .../HOS/Kernel/Memory/KPageTableBase.cs | 1 + .../HOS/Kernel/Process/HleProcessDebugger.cs | 2 + .../HOS/Kernel/Process/KProcess.cs | 25 +-- .../Kernel/Process/ProcessCreationFlags.cs | 1 - .../HOS/Kernel/SupervisorCall/Syscall.cs | 25 ++- .../HOS/Kernel/Threading/KCriticalSection.cs | 2 +- .../HOS/Kernel/Threading/KScheduler.cs | 5 +- .../HOS/Kernel/Threading/KThread.cs | 2 +- src/Ryujinx.HLE/HOS/ModLoader.cs | 24 +- .../Services/Account/Acc/AccountManager.cs | 1 + .../Am/AppletAE/Storage/StorageHelper.cs | 3 +- .../HOS/Services/Caps/CaptureManager.cs | 2 +- .../Services/Caps/IAlbumApplicationService.cs | 2 +- .../Caps/IScreenShotApplicationService.cs | 2 - .../Fs/FileSystemProxy/IFileSystem.cs | 2 +- .../Services/Fs/FileSystemProxy/IStorage.cs | 4 +- .../HOS/Services/Fs/IFileSystemProxy.cs | 6 +- .../HOS/Services/Hid/HidServer/HidUtils.cs | 6 +- .../HOS/Services/Hid/IHidServer.cs | 99 ++++----- .../HOS/Services/Hid/IHidbusServer.cs | 2 - .../HOS/Services/Hid/Irs/IIrSensorServer.cs | 6 +- .../Hid/Types/SharedMemory/SharedMemory.cs | 2 +- src/Ryujinx.HLE/HOS/Services/IpcService.cs | 17 +- .../IUserLocalCommunicationService.cs | 16 +- .../UserServiceCreator/LdnMitm/LanProtocol.cs | 1 + .../LdnRyu/LdnMasterProxyClient.cs | 2 - .../LdnRyu/Proxy/LdnProxy.cs | 1 + .../LdnRyu/Proxy/LdnProxySocket.cs | 2 +- .../LdnRyu/Proxy/P2pProxyServer.cs | 2 +- .../HOS/Services/Loader/ResultCode.cs | 1 - .../HOS/Services/Mii/MiiDatabaseManager.cs | 3 +- .../HOS/Services/Mii/Types/CharInfo.cs | 50 +++++ .../Nfc/AmiiboDecryption/AmiiboBinReader.cs | 32 +-- .../Nfc/AmiiboDecryption/AmiiboDump.cs | 43 ++-- .../HOS/Services/Nfc/Nfp/NfpManager/INfp.cs | 7 +- .../HOS/Services/Nfc/Nfp/VirtualAmiibo.cs | 5 + .../NvHostChannel/NvHostChannelDeviceFile.cs | 4 +- .../NvHostCtrl/NvHostCtrlDeviceFile.cs | 20 +- .../HOS/Services/Nv/NvMemoryAllocator.cs | 5 + .../IParentalControlService.cs | 3 +- .../HOS/Services/Ro/IRoInterface.cs | 3 +- .../HOS/Services/Sdb/Pl/SharedFontManager.cs | 3 +- src/Ryujinx.HLE/HOS/Services/ServerBase.cs | 18 +- .../HOS/Services/Settings/ISettingsServer.cs | 2 +- .../HOS/Services/Sm/IUserInterface.cs | 2 +- .../HOS/Services/Sockets/Bsd/IClient.cs | 12 +- .../Impl/EventFileDescriptorPollManager.cs | 2 +- .../Sockets/Bsd/Impl/ManagedSocket.cs | 16 +- .../HOS/Services/Sockets/Bsd/Impl/WSAError.cs | 1 - .../Sockets/Bsd/Proxy/SocketHelpers.cs | 3 +- .../Sockets/Bsd/Types/BsdSocketOption.cs | 1 - .../Services/Sockets/Bsd/Types/LinuxError.cs | 1 - .../HOS/Services/Sockets/Nsd/IManager.cs | 3 - .../Sockets/Nsd/Manager/FqdnResolver.cs | 8 +- .../HOS/Services/Spl/IGeneralInterface.cs | 1 + .../HOS/Services/Ssl/ISslService.cs | 12 +- .../Services/Ssl/SslService/ISslConnection.cs | 3 +- .../SurfaceFlinger/BufferQueueConsumer.cs | 2 +- .../SurfaceFlinger/BufferQueueCore.cs | 2 +- .../SurfaceFlinger/BufferQueueProducer.cs | 3 +- .../HOS/Services/SurfaceFlinger/Status.cs | 1 - .../Services/SurfaceFlinger/SurfaceFlinger.cs | 8 +- .../SurfaceFlinger/Types/AndroidFence.cs | 1 - .../SurfaceFlinger/Types/Color/ColorFormat.cs | 1 - .../Time/Clock/Types/ClockSnapshot.cs | 1 - .../HOS/Services/Time/ResultCode.cs | 1 - .../HOS/Services/Time/TimeZone/TimeZone.cs | 12 +- .../Time/TimeZone/TimeZoneContentManager.cs | 2 +- .../IManagerDisplayService.cs | 2 - .../ISystemDisplayService.cs | 2 - .../RootService/IApplicationDisplayService.cs | 4 +- .../HOS/Tamper/AtmosphereCompiler.cs | 2 +- src/Ryujinx.HLE/HOS/TamperMachine.cs | 4 +- src/Ryujinx.HLE/HleConfiguration.cs | 4 +- src/Ryujinx.HLE/Loaders/Elf/ElfDynamicTag.cs | 2 - src/Ryujinx.HLE/Loaders/Elf/ElfSymbol.cs | 4 +- .../Loaders/Mods/IPSwitchPatcher.cs | 6 +- src/Ryujinx.HLE/Loaders/Mods/MemPatch.cs | 2 +- .../Loaders/Processes/ProcessLoader.cs | 6 +- src/Ryujinx.HLE/PerformanceStatistics.cs | 6 +- src/Ryujinx.HLE/StructHelpers.cs | 10 +- src/Ryujinx.HLE/Switch.cs | 4 +- src/Ryujinx.HLE/UI/IHostUIHandler.cs | 4 +- .../Utilities/PartitionFileSystemUtils.cs | 2 +- src/Ryujinx.Horizon.Common/ResultNames.cs | 5 +- .../Hipc/HipcGenerator.cs | 7 +- .../SyscallGenerator.cs | 4 +- .../SyscallSyntaxReceiver.cs | 2 +- src/Ryujinx.Horizon/HorizonStatic.cs | 6 +- src/Ryujinx.Horizon/Prepo/Ipc/PrepoService.cs | 14 +- src/Ryujinx.Horizon/Prepo/Types/PlayReport.cs | 6 +- .../Sdk/Audio/Detail/AudioDevice.cs | 4 +- .../Sdk/Audio/Detail/AudioInManager.cs | 4 +- .../Sdk/Audio/Detail/AudioOutManager.cs | 2 +- .../Detail/HardwareOpusDecoderManager.cs | 10 +- .../Sdk/Ngc/Detail/ContentsReader.cs | 3 + .../Sdk/Ngc/Detail/ProfanityFilterBase.cs | 14 +- .../Sdk/OsTypes/Impl/InterProcessEvent.cs | 2 + .../Sdk/OsTypes/Impl/MultiWaitImpl.cs | 2 + .../Sdk/Sf/Cmif/ServiceDispatchTableBase.cs | 4 +- .../Sdk/Sf/Hipc/ServerSessionManager.cs | 1 + .../Sdk/Sf/HipcCommandProcessor.cs | 5 +- src/Ryujinx.Input.SDL2/SDL2Gamepad.cs | 16 +- src/Ryujinx.Input.SDL2/SDL2GamepadDriver.cs | 17 +- src/Ryujinx.Input.SDL2/SDL2JoyCon.cs | 22 +- src/Ryujinx.Input.SDL2/SDL2JoyConPair.cs | 12 +- src/Ryujinx.Input.SDL2/SDL2Keyboard.cs | 2 +- src/Ryujinx.Input.SDL2/SDL2MouseDriver.cs | 2 +- src/Ryujinx.Input/GamepadFeaturesFlag.cs | 2 +- src/Ryujinx.Input/GamepadStateSnapshot.cs | 1 - src/Ryujinx.Input/IGamepadDriver.cs | 2 +- src/Ryujinx.Input/Motion/CemuHook/Client.cs | 6 +- src/Ryujinx.Input/MotionInputId.cs | 2 +- .../Tracking/IMultiRegionHandle.cs | 1 - .../Tracking/MultiRegionHandle.cs | 1 + src/Ryujinx.Memory/Tracking/RegionHandle.cs | 3 +- .../Tracking/SmartMultiRegionHandle.cs | 5 + src/Ryujinx.Memory/Tracking/VirtualRegion.cs | 3 +- .../VirtualMemoryManagerBase.cs | 1 - src/Ryujinx.SDL2.Common/SDL2Driver.cs | 6 +- .../MultiRegionTrackingTests.cs | 10 +- src/Ryujinx.Tests.Memory/TrackingTests.cs | 1 + .../Ryujinx.Tests.Unicorn.csproj | 4 +- .../Audio/Renderer/Server/PoolMapperTests.cs | 1 - src/Ryujinx.Tests/Cpu/CpuTest.cs | 7 +- src/Ryujinx.Tests/Cpu/CpuTest32.cs | 8 +- src/Ryujinx.Tests/Cpu/CpuTestAluRs32.cs | 1 - src/Ryujinx.Tests/Cpu/CpuTestBf32.cs | 2 + src/Ryujinx.Tests/Cpu/CpuTestMisc32.cs | 3 + src/Ryujinx.Tests/Cpu/CpuTestSimdMemory32.cs | 2 + src/Ryujinx.Tests/Cpu/CpuTestSimdMov32.cs | 2 + src/Ryujinx.Tests/Cpu/CpuTestSimdRegElem.cs | 1 - src/Ryujinx.Tests/Cpu/CpuTestT32Flow.cs | 1 + src/Ryujinx.Tests/Cpu/CpuTestThumb.cs | 5 + src/Ryujinx.Tests/Cpu/EnvironmentTests.cs | 4 +- src/Ryujinx.Tests/Memory/PartialUnmaps.cs | 7 +- src/Ryujinx.Tests/Ryujinx.Tests.csproj | 4 +- src/Ryujinx.Tests/TreeDictionaryTests.cs | 4 +- .../LocaleGenerator.cs | 1 + src/Ryujinx/Common/ApplicationHelper.cs | 17 +- src/Ryujinx/Common/LocaleManager.cs | 18 +- .../Common/Markup/BasicMarkupExtension.cs | 4 +- src/Ryujinx/Common/Markup/MarkupExtensions.cs | 12 +- .../Github/GithubReleasesJsonResponse.cs | 2 +- .../Common/Models/XCITrimmerFileModel.cs | 8 +- src/Ryujinx/Common/XCITrimmerLog.cs | 2 +- src/Ryujinx/Headless/HeadlessRyujinx.Init.cs | 8 +- src/Ryujinx/Headless/HeadlessRyujinx.cs | 35 +-- src/Ryujinx/Headless/Options.cs | 72 +++--- src/Ryujinx/Headless/Windows/OpenGLWindow.cs | 2 +- src/Ryujinx/Headless/Windows/WindowBase.cs | 8 +- src/Ryujinx/Input/AvaloniaKeyboardDriver.cs | 2 +- src/Ryujinx/Program.cs | 29 +-- src/Ryujinx/Systems/AppHost.cs | 29 +-- .../Systems/AppLibrary/ApplicationData.cs | 24 +- .../Systems/AppLibrary/ApplicationLibrary.cs | 43 ++-- src/Ryujinx/Systems/AppLibrary/LdnGameData.cs | 4 +- .../LdnGameDataReceivedEventArgs.cs | 6 +- src/Ryujinx/Systems/CompatibilityDatabase.cs | 36 ++- .../Configuration/ConfigurationFileFormat.cs | 20 +- .../ConfigurationState.Migration.cs | 81 ++++--- .../Configuration/ConfigurationState.Model.cs | 44 ++-- .../Systems/Configuration/FileTypes.cs | 2 +- .../Systems/Configuration/LoggerModule.cs | 16 +- .../Systems/Configuration/System/Region.cs | 2 +- .../Systems/Configuration/UI/FocusLostType.cs | 2 +- .../Systems/Configuration/UI/UpdaterType.cs | 2 +- .../Systems/DiscordIntegrationModule.cs | 17 +- src/Ryujinx/Systems/PlayReport/Analyzer.cs | 17 +- src/Ryujinx/Systems/PlayReport/Delegates.cs | 2 +- .../Systems/PlayReport/MatchedValues.cs | 10 +- .../PlayReport/PlayReports.Formatters.cs | 210 +++++++++--------- src/Ryujinx/Systems/PlayReport/PlayReports.cs | 2 +- src/Ryujinx/Systems/PlayReport/Specs.cs | 17 +- src/Ryujinx/Systems/PlayReport/Value.cs | 8 +- src/Ryujinx/Systems/Rebooter.cs | 4 +- src/Ryujinx/Systems/Updater.cs | 43 ++-- src/Ryujinx/UI/Applet/AvaHostUIHandler.cs | 22 +- .../UI/Applet/ProfileSelectorDialog.axaml.cs | 10 +- .../Controls/ApplicationContextMenu.axaml.cs | 4 +- .../UI/Controls/MiniVerticalSeparator.cs | 2 +- .../UI/Controls/NavigationDialogHost.axaml.cs | 4 +- src/Ryujinx/UI/Controls/RyujinxControl.cs | 2 +- src/Ryujinx/UI/Controls/RyujinxLogo.cs | 4 +- .../UI/Helpers/AvaloniaListExtensions.cs | 2 +- src/Ryujinx/UI/Helpers/Commands.cs | 8 +- src/Ryujinx/UI/Helpers/ContentDialogHelper.cs | 14 +- .../DownloadableContentLabelConverter.cs | 1 - .../Helpers/Converters/KeyValueConverter.cs | 3 + .../Converters/MultiplayerInfoConverter.cs | 2 +- .../Converters/PlayabilityStatusConverter.cs | 6 +- .../XCITrimmerFileStatusConverter.cs | 2 +- .../XCITrimmerFileStatusDetailConverter.cs | 2 +- src/Ryujinx/UI/Helpers/IconColorPicker.cs | 1 - src/Ryujinx/UI/Helpers/LoggerAdapter.cs | 11 +- src/Ryujinx/UI/Helpers/NotificationHelper.cs | 18 +- src/Ryujinx/UI/Helpers/Win32NativeInterop.cs | 1 - .../XCITrimmerOperationOutcomeHelper.cs | 2 +- .../UI/Models/Input/GamepadInputConfig.cs | 30 +-- .../UI/Models/Input/KeyboardInputConfig.cs | 12 +- .../UI/Models/Input/StickVisualizer.cs | 14 +- src/Ryujinx/UI/Models/ModModel.cs | 2 +- src/Ryujinx/UI/Models/SaveModel.cs | 2 +- .../UI/Models/StatusUpdatedEventArgs.cs | 6 +- src/Ryujinx/UI/Renderer/EmbeddedWindow.cs | 10 +- src/Ryujinx/UI/Renderer/RendererHost.cs | 6 +- src/Ryujinx/UI/RyujinxApp.axaml.cs | 9 +- .../UI/ViewModels/AboutWindowViewModel.cs | 10 +- .../UI/ViewModels/ApplicationDataViewModel.cs | 6 +- .../UI/ViewModels/CompatibilityViewModel.cs | 12 +- .../UI/ViewModels/DlcSelectViewModel.cs | 8 +- .../DownloadableContentManagerViewModel.cs | 18 +- .../Input/ControllerInputViewModel.cs | 16 +- .../UI/ViewModels/Input/InputViewModel.cs | 125 +++++------ .../UI/ViewModels/Input/LedInputViewModel.cs | 23 +- .../UI/ViewModels/MainWindowViewModel.cs | 113 +++++----- .../UI/ViewModels/ModManagerViewModel.cs | 15 +- .../UI/ViewModels/SettingsHacksViewModel.cs | 12 +- .../UI/ViewModels/SettingsViewModel.cs | 66 +++--- .../UI/ViewModels/TitleUpdateViewModel.cs | 18 +- .../UserFirmwareAvatarSelectorViewModel.cs | 2 +- .../UI/ViewModels/UserSaveManagerViewModel.cs | 10 +- .../UI/ViewModels/XciTrimmerViewModel.cs | 52 ++--- .../UI/Views/Dialog/AboutView.axaml.cs | 2 +- .../Views/Dialog/ApplicationDataView.axaml.cs | 18 +- .../UI/Views/Dialog/DlcSelectView.axaml.cs | 4 +- .../DownloadableContentManagerView.axaml.cs | 2 +- .../UI/Views/Dialog/ModManagerView.axaml.cs | 4 +- .../Dialog/TitleUpdateManagerView.axaml.cs | 2 +- .../Views/Input/ControllerInputView.axaml.cs | 12 +- src/Ryujinx/UI/Views/Input/InputView.axaml.cs | 7 +- .../UI/Views/Input/KeyboardInputView.axaml.cs | 10 +- .../UI/Views/Input/LedInputView.axaml.cs | 27 ++- .../UI/Views/Main/MainMenuBarView.axaml.cs | 32 +-- .../UI/Views/Main/MainStatusBarView.axaml.cs | 2 +- .../Views/Misc/ApplicationGridView.axaml.cs | 2 +- .../Views/Misc/ApplicationListView.axaml.cs | 12 +- .../Settings/SettingsHotkeysView.axaml.cs | 8 +- .../UI/Views/Settings/SettingsUIView.axaml.cs | 4 +- .../UI/Views/User/UserEditorView.axaml.cs | 2 +- .../UserProfileImageSelectorView.axaml.cs | 1 + .../Views/User/UserSaveManagerView.axaml.cs | 2 +- src/Ryujinx/UI/Windows/CheatWindow.axaml.cs | 4 +- .../Windows/CompatibilityListWindow.axaml.cs | 10 +- .../GameSpecificSettingsWindow.axaml.cs | 8 +- src/Ryujinx/UI/Windows/MainWindow.axaml.cs | 72 +++--- .../UI/Windows/SettingsWindow.axaml.cs | 6 +- src/Ryujinx/UI/Windows/StyleableWindow.cs | 8 +- src/Ryujinx/Utilities/AppletMetadata.cs | 8 +- src/Ryujinx/Utilities/CommandLineState.cs | 11 +- src/Ryujinx/Utilities/SetupValidator.cs | 4 +- .../Utilities/StorageProviderExtensions.cs | 12 +- src/Ryujinx/Utilities/TitleHelper.cs | 2 +- src/Ryujinx/Utilities/ValueFormatUtils.cs | 18 +- .../Autogenerated/CoreGrammar.cs | 73 +++++- .../Autogenerated/GlslStd450Grammar.cs | 1 - .../Autogenerated/OpenClGrammar.cs | 1 - src/Spv.Generator/Module.cs | 12 +- 622 files changed, 3080 insertions(+), 2652 deletions(-) diff --git a/.editorconfig b/.editorconfig index 76edc491c..1059bcdeb 100644 --- a/.editorconfig +++ b/.editorconfig @@ -16,6 +16,17 @@ tab_width = 4 # New line preferences end_of_line = lf insert_final_newline = true +dotnet_style_coalesce_expression = true:suggestion +dotnet_style_null_propagation = true:suggestion +dotnet_style_prefer_is_null_check_over_reference_equality_method = true:suggestion +dotnet_style_prefer_auto_properties = true:silent +dotnet_style_object_initializer = true:suggestion +dotnet_style_collection_initializer = true:suggestion +dotnet_style_prefer_simplified_boolean_expressions = true:suggestion +dotnet_style_prefer_conditional_expression_over_assignment = true:silent +dotnet_style_prefer_conditional_expression_over_return = true:silent +dotnet_style_operator_placement_when_wrapping = beginning_of_line +dotnet_style_explicit_tuple_names = true:suggestion # Markdown, JSON, YAML, props and csproj files [*.{md,json,yml,props,csproj}] @@ -106,7 +117,7 @@ csharp_style_conditional_delegate_call = true:suggestion csharp_prefer_static_local_function = true:suggestion csharp_preferred_modifier_order = public,private,protected,internal,static,extern,new,virtual,abstract,sealed,override,readonly,unsafe,volatile,async:silent csharp_style_prefer_readonly_struct = true -csharp_style_prefer_method_group_conversion = true +csharp_style_prefer_method_group_conversion = true:silent # Code-block preferences csharp_prefer_braces = true:silent @@ -177,9 +188,9 @@ csharp_preserve_single_line_statements = false # Naming rules -dotnet_naming_rule.interfaces_should_be_prefixed_with_I.severity = suggestion +dotnet_naming_rule.interfaces_should_be_prefixed_with_i.severity = suggestion dotnet_naming_rule.interfaces_should_be_prefixed_with_I.symbols = interface -dotnet_naming_rule.interfaces_should_be_prefixed_with_I.style = IPascalCase +dotnet_naming_rule.interfaces_should_be_prefixed_with_i.style = IPascalCase dotnet_naming_rule.types_should_be_pascal_case.severity = suggestion dotnet_naming_rule.types_should_be_pascal_case.symbols = types @@ -236,28 +247,22 @@ dotnet_naming_style.IPascalCase.required_suffix = dotnet_naming_style.IPascalCase.word_separator = dotnet_naming_style.IPascalCase.capitalization = pascal_case -# TODO: -# .NET 8 migration (new warnings are caused by the NET 8 C# compiler and analyzer) -# The following info messages might need to be fixed in the source code instead of hiding the actual message -# Without the following lines, dotnet format would fail -# Disable "Collection initialization can be simplified" +# Other settings +csharp_style_prefer_top_level_statements = true:suggestion +csharp_style_prefer_primary_constructors = false:suggestion +csharp_prefer_system_threading_lock = true:suggestion + + +# Analyzers +dotnet_diagnostic.CA1069.severity = none # CA1069: Enums values should not be duplicated +# Disable Collection initialization can be simplified dotnet_diagnostic.IDE0028.severity = none dotnet_diagnostic.IDE0300.severity = none dotnet_diagnostic.IDE0301.severity = none dotnet_diagnostic.IDE0302.severity = none dotnet_diagnostic.IDE0305.severity = none -# Disable "'new' expression can be simplified" -dotnet_diagnostic.IDE0090.severity = none -# Disable "Use primary constructor" -dotnet_diagnostic.IDE0290.severity = none -# Disable "Member '' does not access instance data and can be marked as static" -dotnet_diagnostic.CA1822.severity = none -# Disable "Change type of field '' from '' to '' for improved performance" -dotnet_diagnostic.CA1859.severity = none -# Disable "Prefer 'static readonly' fields over constant array arguments if the called method is called repeatedly and is not mutating the passed array" -dotnet_diagnostic.CA1861.severity = none -# Disable "Prefer using 'string.Equals(string, StringComparison)' to perform a case-insensitive comparison, but keep in mind that this might cause subtle changes in behavior, so make sure to conduct thorough testing after applying the suggestion, or if culturally sensitive comparison is not required, consider using 'StringComparison.OrdinalIgnoreCase'" -dotnet_diagnostic.CA1862.severity = none +dotnet_diagnostic.CS9113.severity = none # CS9113: Parameter 'value' is unread +dotnet_diagnostic.IDE0130.severity = none # IDE0130: Namespace does not match folder structure [src/Ryujinx/UI/ViewModels/**.cs] # Disable "mark members as static" rule for ViewModels diff --git a/src/ARMeilleure/CodeGen/Arm64/Arm64Optimizer.cs b/src/ARMeilleure/CodeGen/Arm64/Arm64Optimizer.cs index a433cea65..112193f46 100644 --- a/src/ARMeilleure/CodeGen/Arm64/Arm64Optimizer.cs +++ b/src/ARMeilleure/CodeGen/Arm64/Arm64Optimizer.cs @@ -254,7 +254,7 @@ namespace ARMeilleure.CodeGen.Arm64 private static bool IsMemoryLoadOrStore(Instruction inst) { - return inst == Instruction.Load || inst == Instruction.Store; + return inst is Instruction.Load or Instruction.Store; } private static bool ConstTooLong(Operand constOp, OperandType accessType) diff --git a/src/ARMeilleure/CodeGen/Arm64/Assembler.cs b/src/ARMeilleure/CodeGen/Arm64/Assembler.cs index 47902ddc8..0d493426b 100644 --- a/src/ARMeilleure/CodeGen/Arm64/Assembler.cs +++ b/src/ARMeilleure/CodeGen/Arm64/Assembler.cs @@ -774,6 +774,7 @@ namespace ARMeilleure.CodeGen.Arm64 instI |= 1 << 22; // sh flag imm >>= 12; } + WriteInstructionAuto(instI | (EncodeUImm12(imm, 0) << 10), rd, rn); } else diff --git a/src/ARMeilleure/CodeGen/Arm64/CodeGenCommon.cs b/src/ARMeilleure/CodeGen/Arm64/CodeGenCommon.cs index 1f0148d5e..af5f1a8c7 100644 --- a/src/ARMeilleure/CodeGen/Arm64/CodeGenCommon.cs +++ b/src/ARMeilleure/CodeGen/Arm64/CodeGenCommon.cs @@ -52,7 +52,7 @@ namespace ARMeilleure.CodeGen.Arm64 // Any value AND all ones will be equal itself, so it's effectively a no-op. // Any value OR all ones will be equal all ones, so one can just use MOV. // Any value XOR all ones will be equal its inverse, so one can just use MVN. - if (value == 0 || value == ulong.MaxValue) + if (value is 0 or ulong.MaxValue) { immN = 0; immS = 0; diff --git a/src/ARMeilleure/CodeGen/Arm64/CodeGenContext.cs b/src/ARMeilleure/CodeGen/Arm64/CodeGenContext.cs index 46cd863cf..e4d9f46fa 100644 --- a/src/ARMeilleure/CodeGen/Arm64/CodeGenContext.cs +++ b/src/ARMeilleure/CodeGen/Arm64/CodeGenContext.cs @@ -1,6 +1,7 @@ using ARMeilleure.CodeGen.Linking; using ARMeilleure.CodeGen.RegisterAllocators; using ARMeilleure.IntermediateRepresentation; +using Microsoft.IO; using Ryujinx.Common.Memory; using System; using System.Collections.Generic; @@ -14,7 +15,7 @@ namespace ARMeilleure.CodeGen.Arm64 private const int CbnzInstLength = 4; private const int LdrLitInstLength = 4; - private readonly Stream _stream; + private readonly RecyclableMemoryStream _stream; public int StreamOffset => (int)_stream.Length; diff --git a/src/ARMeilleure/CodeGen/Arm64/CodeGenerator.cs b/src/ARMeilleure/CodeGen/Arm64/CodeGenerator.cs index 8f88f2e27..fbf4c1eb4 100644 --- a/src/ARMeilleure/CodeGen/Arm64/CodeGenerator.cs +++ b/src/ARMeilleure/CodeGen/Arm64/CodeGenerator.cs @@ -189,8 +189,8 @@ namespace ARMeilleure.CodeGen.Arm64 // The only blocks which can have 0 successors are exit blocks. Operation last = block.Operations.Last; - Debug.Assert(last.Instruction == Instruction.Tailcall || - last.Instruction == Instruction.Return); + Debug.Assert(last.Instruction is Instruction.Tailcall or + Instruction.Return); } else { @@ -464,7 +464,7 @@ namespace ARMeilleure.CodeGen.Arm64 Operand dest = operation.Destination; Operand source = operation.GetSource(0); - Debug.Assert(dest.Type == OperandType.FP32 || dest.Type == OperandType.FP64); + Debug.Assert(dest.Type is OperandType.FP32 or OperandType.FP64); Debug.Assert(dest.Type != source.Type); Debug.Assert(source.Type != OperandType.V128); @@ -483,7 +483,7 @@ namespace ARMeilleure.CodeGen.Arm64 Operand dest = operation.Destination; Operand source = operation.GetSource(0); - Debug.Assert(dest.Type == OperandType.FP32 || dest.Type == OperandType.FP64); + Debug.Assert(dest.Type is OperandType.FP32 or OperandType.FP64); Debug.Assert(dest.Type != source.Type); Debug.Assert(source.Type.IsInteger()); @@ -1463,7 +1463,7 @@ namespace ARMeilleure.CodeGen.Arm64 private static bool IsLoadOrStore(Operation operation) { - return operation.Instruction == Instruction.Load || operation.Instruction == Instruction.Store; + return operation.Instruction is Instruction.Load or Instruction.Store; } private static OperandType GetMemOpValueType(Operation operation) @@ -1499,6 +1499,7 @@ namespace ARMeilleure.CodeGen.Arm64 return false; } } + if (memOp.Index != default) { return false; @@ -1553,7 +1554,7 @@ namespace ARMeilleure.CodeGen.Arm64 private static void EnsureSameReg(Operand op1, Operand op2) { - Debug.Assert(op1.Kind == OperandKind.Register || op1.Kind == OperandKind.Memory); + Debug.Assert(op1.Kind is OperandKind.Register or OperandKind.Memory); Debug.Assert(op1.Kind == op2.Kind); Debug.Assert(op1.Value == op2.Value); } diff --git a/src/ARMeilleure/CodeGen/Arm64/CodeGeneratorIntrinsic.cs b/src/ARMeilleure/CodeGen/Arm64/CodeGeneratorIntrinsic.cs index b87370557..390dc5b2e 100644 --- a/src/ARMeilleure/CodeGen/Arm64/CodeGeneratorIntrinsic.cs +++ b/src/ARMeilleure/CodeGen/Arm64/CodeGeneratorIntrinsic.cs @@ -509,7 +509,6 @@ namespace ARMeilleure.CodeGen.Arm64 context.Assembler.WriteInstruction(instruction, rd, rn); } - } private static void GenerateScalarTernary( diff --git a/src/ARMeilleure/CodeGen/Arm64/HardwareCapabilities.cs b/src/ARMeilleure/CodeGen/Arm64/HardwareCapabilities.cs index fbaf16d04..fa9e7fe2e 100644 --- a/src/ARMeilleure/CodeGen/Arm64/HardwareCapabilities.cs +++ b/src/ARMeilleure/CodeGen/Arm64/HardwareCapabilities.cs @@ -137,6 +137,7 @@ namespace ARMeilleure.CodeGen.Arm64 { return val != 0; } + return false; } diff --git a/src/ARMeilleure/CodeGen/Arm64/PreAllocator.cs b/src/ARMeilleure/CodeGen/Arm64/PreAllocator.cs index a82c6939f..76a231d6c 100644 --- a/src/ARMeilleure/CodeGen/Arm64/PreAllocator.cs +++ b/src/ARMeilleure/CodeGen/Arm64/PreAllocator.cs @@ -736,19 +736,19 @@ namespace ARMeilleure.CodeGen.Arm64 { IntrinsicInfo info = IntrinsicTable.GetInfo(intrinsic & ~(Intrinsic.Arm64VTypeMask | Intrinsic.Arm64VSizeMask)); - return info.Type == IntrinsicType.ScalarBinaryRd || - info.Type == IntrinsicType.ScalarTernaryFPRdByElem || - info.Type == IntrinsicType.ScalarTernaryShlRd || - info.Type == IntrinsicType.ScalarTernaryShrRd || - info.Type == IntrinsicType.Vector128BinaryRd || - info.Type == IntrinsicType.VectorBinaryRd || - info.Type == IntrinsicType.VectorInsertByElem || - info.Type == IntrinsicType.VectorTernaryRd || - info.Type == IntrinsicType.VectorTernaryRdBitwise || - info.Type == IntrinsicType.VectorTernaryFPRdByElem || - info.Type == IntrinsicType.VectorTernaryRdByElem || - info.Type == IntrinsicType.VectorTernaryShlRd || - info.Type == IntrinsicType.VectorTernaryShrRd; + return info.Type is IntrinsicType.ScalarBinaryRd or + IntrinsicType.ScalarTernaryFPRdByElem or + IntrinsicType.ScalarTernaryShlRd or + IntrinsicType.ScalarTernaryShrRd or + IntrinsicType.Vector128BinaryRd or + IntrinsicType.VectorBinaryRd or + IntrinsicType.VectorInsertByElem or + IntrinsicType.VectorTernaryRd or + IntrinsicType.VectorTernaryRdBitwise or + IntrinsicType.VectorTernaryFPRdByElem or + IntrinsicType.VectorTernaryRdByElem or + IntrinsicType.VectorTernaryShlRd or + IntrinsicType.VectorTernaryShrRd; } private static bool HasConstSrc1(Operation node, ulong value) @@ -849,7 +849,7 @@ namespace ARMeilleure.CodeGen.Arm64 Comparison compType = (Comparison)comp.AsInt32(); - return compType == Comparison.Equal || compType == Comparison.NotEqual; + return compType is Comparison.Equal or Comparison.NotEqual; } } @@ -871,9 +871,9 @@ namespace ARMeilleure.CodeGen.Arm64 IntrinsicInfo info = IntrinsicTable.GetInfo(intrinsic & ~(Intrinsic.Arm64VTypeMask | Intrinsic.Arm64VSizeMask)); // Those have integer inputs that don't support consts. - return info.Type != IntrinsicType.ScalarFPConvGpr && - info.Type != IntrinsicType.ScalarFPConvFixedGpr && - info.Type != IntrinsicType.SetRegister; + return info.Type is not IntrinsicType.ScalarFPConvGpr and + not IntrinsicType.ScalarFPConvFixedGpr and + not IntrinsicType.SetRegister; } return false; diff --git a/src/ARMeilleure/CodeGen/Optimizations/ConstantFolding.cs b/src/ARMeilleure/CodeGen/Optimizations/ConstantFolding.cs index be3dff58c..c7aa1ee5f 100644 --- a/src/ARMeilleure/CodeGen/Optimizations/ConstantFolding.cs +++ b/src/ARMeilleure/CodeGen/Optimizations/ConstantFolding.cs @@ -37,6 +37,7 @@ namespace ARMeilleure.CodeGen.Optimizations { EvaluateBinaryI64(operation, (x, y) => x + y); } + break; case Instruction.BitwiseAnd: @@ -48,6 +49,7 @@ namespace ARMeilleure.CodeGen.Optimizations { EvaluateBinaryI64(operation, (x, y) => x & y); } + break; case Instruction.BitwiseExclusiveOr: @@ -59,6 +61,7 @@ namespace ARMeilleure.CodeGen.Optimizations { EvaluateBinaryI64(operation, (x, y) => x ^ y); } + break; case Instruction.BitwiseNot: @@ -70,6 +73,7 @@ namespace ARMeilleure.CodeGen.Optimizations { EvaluateUnaryI64(operation, (x) => ~x); } + break; case Instruction.BitwiseOr: @@ -81,6 +85,7 @@ namespace ARMeilleure.CodeGen.Optimizations { EvaluateBinaryI64(operation, (x, y) => x | y); } + break; case Instruction.ConvertI64ToI32: @@ -88,6 +93,7 @@ namespace ARMeilleure.CodeGen.Optimizations { EvaluateUnaryI32(operation, (x) => x); } + break; case Instruction.Compare: @@ -129,6 +135,7 @@ namespace ARMeilleure.CodeGen.Optimizations break; } } + break; case Instruction.Copy: @@ -140,6 +147,7 @@ namespace ARMeilleure.CodeGen.Optimizations { EvaluateUnaryI64(operation, (x) => x); } + break; case Instruction.Divide: @@ -151,6 +159,7 @@ namespace ARMeilleure.CodeGen.Optimizations { EvaluateBinaryI64(operation, (x, y) => y != 0 ? x / y : 0); } + break; case Instruction.DivideUI: @@ -162,6 +171,7 @@ namespace ARMeilleure.CodeGen.Optimizations { EvaluateBinaryI64(operation, (x, y) => y != 0 ? (long)((ulong)x / (ulong)y) : 0); } + break; case Instruction.Multiply: @@ -173,6 +183,7 @@ namespace ARMeilleure.CodeGen.Optimizations { EvaluateBinaryI64(operation, (x, y) => x * y); } + break; case Instruction.Negate: @@ -184,6 +195,7 @@ namespace ARMeilleure.CodeGen.Optimizations { EvaluateUnaryI64(operation, (x) => -x); } + break; case Instruction.ShiftLeft: @@ -195,6 +207,7 @@ namespace ARMeilleure.CodeGen.Optimizations { EvaluateBinaryI64(operation, (x, y) => x << (int)y); } + break; case Instruction.ShiftRightSI: @@ -206,6 +219,7 @@ namespace ARMeilleure.CodeGen.Optimizations { EvaluateBinaryI64(operation, (x, y) => x >> (int)y); } + break; case Instruction.ShiftRightUI: @@ -217,6 +231,7 @@ namespace ARMeilleure.CodeGen.Optimizations { EvaluateBinaryI64(operation, (x, y) => (long)((ulong)x >> (int)y)); } + break; case Instruction.SignExtend16: @@ -228,6 +243,7 @@ namespace ARMeilleure.CodeGen.Optimizations { EvaluateUnaryI64(operation, (x) => (short)x); } + break; case Instruction.SignExtend32: @@ -239,6 +255,7 @@ namespace ARMeilleure.CodeGen.Optimizations { EvaluateUnaryI64(operation, (x) => (int)x); } + break; case Instruction.SignExtend8: @@ -250,6 +267,7 @@ namespace ARMeilleure.CodeGen.Optimizations { EvaluateUnaryI64(operation, (x) => (sbyte)x); } + break; case Instruction.ZeroExtend16: @@ -261,6 +279,7 @@ namespace ARMeilleure.CodeGen.Optimizations { EvaluateUnaryI64(operation, (x) => (ushort)x); } + break; case Instruction.ZeroExtend32: @@ -272,6 +291,7 @@ namespace ARMeilleure.CodeGen.Optimizations { EvaluateUnaryI64(operation, (x) => (uint)x); } + break; case Instruction.ZeroExtend8: @@ -283,6 +303,7 @@ namespace ARMeilleure.CodeGen.Optimizations { EvaluateUnaryI64(operation, (x) => (byte)x); } + break; case Instruction.Subtract: @@ -294,6 +315,7 @@ namespace ARMeilleure.CodeGen.Optimizations { EvaluateBinaryI64(operation, (x, y) => x - y); } + break; } } diff --git a/src/ARMeilleure/CodeGen/Optimizations/Optimizer.cs b/src/ARMeilleure/CodeGen/Optimizations/Optimizer.cs index 1afc3a782..cbc6ab784 100644 --- a/src/ARMeilleure/CodeGen/Optimizations/Optimizer.cs +++ b/src/ARMeilleure/CodeGen/Optimizations/Optimizer.cs @@ -227,11 +227,11 @@ namespace ARMeilleure.CodeGen.Optimizations private static bool HasSideEffects(Operation node) { - return node.Instruction == Instruction.Call - || node.Instruction == Instruction.Tailcall - || node.Instruction == Instruction.CompareAndSwap - || node.Instruction == Instruction.CompareAndSwap16 - || node.Instruction == Instruction.CompareAndSwap8; + return node.Instruction is Instruction.Call + or Instruction.Tailcall + or Instruction.CompareAndSwap + or Instruction.CompareAndSwap16 + or Instruction.CompareAndSwap8; } private static bool IsPropagableCompare(Operation operation) diff --git a/src/ARMeilleure/CodeGen/RegisterAllocators/LinearScanAllocator.cs b/src/ARMeilleure/CodeGen/RegisterAllocators/LinearScanAllocator.cs index 76c636b55..92fedf7bf 100644 --- a/src/ARMeilleure/CodeGen/RegisterAllocators/LinearScanAllocator.cs +++ b/src/ARMeilleure/CodeGen/RegisterAllocators/LinearScanAllocator.cs @@ -847,7 +847,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators // If this is a copy (or copy-like operation), set the copy source interval as well. // This is used for register preferencing later on, which allows the copy to be eliminated // in some cases. - if (node.Instruction == Instruction.Copy || node.Instruction == Instruction.ZeroExtend32) + if (node.Instruction is Instruction.Copy or Instruction.ZeroExtend32) { Operand source = node.GetSource(0); @@ -1120,8 +1120,8 @@ namespace ARMeilleure.CodeGen.RegisterAllocators private static bool IsLocalOrRegister(OperandKind kind) { - return kind == OperandKind.LocalVariable || - kind == OperandKind.Register; + return kind is OperandKind.LocalVariable or + OperandKind.Register; } } } diff --git a/src/ARMeilleure/CodeGen/X86/Assembler.cs b/src/ARMeilleure/CodeGen/X86/Assembler.cs index 46dadbfce..c27ee43cb 100644 --- a/src/ARMeilleure/CodeGen/X86/Assembler.cs +++ b/src/ARMeilleure/CodeGen/X86/Assembler.cs @@ -1478,7 +1478,7 @@ namespace ARMeilleure.CodeGen.X86 private static bool Is64Bits(OperandType type) { - return type == OperandType.I64 || type == OperandType.FP64; + return type is OperandType.I64 or OperandType.FP64; } private static bool IsImm8(ulong immediate, OperandType type) diff --git a/src/ARMeilleure/CodeGen/X86/AssemblerTable.cs b/src/ARMeilleure/CodeGen/X86/AssemblerTable.cs index 8910e8891..4b226803b 100644 --- a/src/ARMeilleure/CodeGen/X86/AssemblerTable.cs +++ b/src/ARMeilleure/CodeGen/X86/AssemblerTable.cs @@ -13,7 +13,6 @@ namespace ARMeilleure.CodeGen.X86 private const int BadOp = 0; [Flags] - [SuppressMessage("Design", "CA1069: Enums values should not be duplicated")] private enum InstructionFlags { None = 0, diff --git a/src/ARMeilleure/CodeGen/X86/CodeGenContext.cs b/src/ARMeilleure/CodeGen/X86/CodeGenContext.cs index d4d4c2058..afae3211f 100644 --- a/src/ARMeilleure/CodeGen/X86/CodeGenContext.cs +++ b/src/ARMeilleure/CodeGen/X86/CodeGenContext.cs @@ -1,5 +1,6 @@ using ARMeilleure.CodeGen.RegisterAllocators; using ARMeilleure.IntermediateRepresentation; +using Microsoft.IO; using Ryujinx.Common.Memory; using System.IO; using System.Numerics; @@ -8,7 +9,7 @@ namespace ARMeilleure.CodeGen.X86 { class CodeGenContext { - private readonly Stream _stream; + private readonly RecyclableMemoryStream _stream; private readonly Operand[] _blockLabels; public int StreamOffset => (int)_stream.Length; diff --git a/src/ARMeilleure/CodeGen/X86/CodeGenerator.cs b/src/ARMeilleure/CodeGen/X86/CodeGenerator.cs index 1122c6940..86acea4a8 100644 --- a/src/ARMeilleure/CodeGen/X86/CodeGenerator.cs +++ b/src/ARMeilleure/CodeGen/X86/CodeGenerator.cs @@ -175,8 +175,8 @@ namespace ARMeilleure.CodeGen.X86 // The only blocks which can have 0 successors are exit blocks. Operation last = block.Operations.Last; - Debug.Assert(last.Instruction == Instruction.Tailcall || - last.Instruction == Instruction.Return); + Debug.Assert(last.Instruction is Instruction.Tailcall or + Instruction.Return); } else { @@ -478,7 +478,7 @@ namespace ARMeilleure.CodeGen.X86 Debug.Assert(HardwareCapabilities.SupportsVexEncoding); Debug.Assert(dest.Kind == OperandKind.Register && src1.Kind == OperandKind.Register && src2.Kind == OperandKind.Register); - Debug.Assert(src3.Kind == OperandKind.Register || src3.Kind == OperandKind.Memory); + Debug.Assert(src3.Kind is OperandKind.Register or OperandKind.Memory); EnsureSameType(dest, src1, src2, src3); Debug.Assert(dest.Type == OperandType.V128); @@ -788,7 +788,7 @@ namespace ARMeilleure.CodeGen.X86 Operand dest = operation.Destination; Operand source = operation.GetSource(0); - Debug.Assert(dest.Type == OperandType.FP32 || dest.Type == OperandType.FP64); + Debug.Assert(dest.Type is OperandType.FP32 or OperandType.FP64); if (dest.Type == OperandType.FP32) { @@ -1723,7 +1723,7 @@ namespace ARMeilleure.CodeGen.X86 return; } - Debug.Assert(op1.Kind == OperandKind.Register || op1.Kind == OperandKind.Memory); + Debug.Assert(op1.Kind is OperandKind.Register or OperandKind.Memory); Debug.Assert(op1.Kind == op2.Kind); Debug.Assert(op1.Value == op2.Value); } diff --git a/src/ARMeilleure/CodeGen/X86/PreAllocator.cs b/src/ARMeilleure/CodeGen/X86/PreAllocator.cs index 915f283c7..6b93efdfb 100644 --- a/src/ARMeilleure/CodeGen/X86/PreAllocator.cs +++ b/src/ARMeilleure/CodeGen/X86/PreAllocator.cs @@ -66,6 +66,7 @@ namespace ARMeilleure.CodeGen.X86 { PreAllocatorSystemV.InsertCallCopies(block.Operations, node); } + break; case Instruction.ConvertToFPUI: @@ -81,6 +82,7 @@ namespace ARMeilleure.CodeGen.X86 { nextNode = PreAllocatorSystemV.InsertLoadArgumentCopy(cctx, ref buffer, block.Operations, preservedArgs, node); } + break; case Instruction.Negate: @@ -88,6 +90,7 @@ namespace ARMeilleure.CodeGen.X86 { GenerateNegate(block.Operations, node); } + break; case Instruction.Return: @@ -99,6 +102,7 @@ namespace ARMeilleure.CodeGen.X86 { PreAllocatorSystemV.InsertReturnCopy(block.Operations, node); } + break; case Instruction.Tailcall: @@ -110,6 +114,7 @@ namespace ARMeilleure.CodeGen.X86 { PreAllocatorSystemV.InsertTailcallCopies(block.Operations, node); } + break; case Instruction.VectorInsert8: @@ -117,6 +122,7 @@ namespace ARMeilleure.CodeGen.X86 { GenerateVectorInsert8(block.Operations, node); } + break; case Instruction.Extended: @@ -132,6 +138,7 @@ namespace ARMeilleure.CodeGen.X86 node.SetSources([Const(stackOffset)]); } + break; } } @@ -312,9 +319,9 @@ namespace ARMeilleure.CodeGen.X86 case Instruction.Extended: { - bool isBlend = node.Intrinsic == Intrinsic.X86Blendvpd || - node.Intrinsic == Intrinsic.X86Blendvps || - node.Intrinsic == Intrinsic.X86Pblendvb; + bool isBlend = node.Intrinsic is Intrinsic.X86Blendvpd or + Intrinsic.X86Blendvps or + Intrinsic.X86Pblendvb; // BLENDVPD, BLENDVPS, PBLENDVB last operand is always implied to be XMM0 when VEX is not supported. // SHA256RNDS2 always has an implied XMM0 as a last operand. @@ -513,8 +520,8 @@ namespace ARMeilleure.CodeGen.X86 Operand dest = node.Destination; Operand source = node.GetSource(0); - Debug.Assert(dest.Type == OperandType.FP32 || - dest.Type == OperandType.FP64, $"Invalid destination type \"{dest.Type}\"."); + Debug.Assert(dest.Type is OperandType.FP32 or + OperandType.FP64, $"Invalid destination type \"{dest.Type}\"."); Operation currentNode = node; @@ -761,7 +768,7 @@ namespace ARMeilleure.CodeGen.X86 Comparison compType = (Comparison)comp.AsInt32(); - return compType == Comparison.Equal || compType == Comparison.NotEqual; + return compType is Comparison.Equal or Comparison.NotEqual; } } diff --git a/src/ARMeilleure/CodeGen/X86/X86Optimizer.cs b/src/ARMeilleure/CodeGen/X86/X86Optimizer.cs index d72442c5a..49dc1c8a4 100644 --- a/src/ARMeilleure/CodeGen/X86/X86Optimizer.cs +++ b/src/ARMeilleure/CodeGen/X86/X86Optimizer.cs @@ -248,12 +248,12 @@ namespace ARMeilleure.CodeGen.X86 private static bool IsMemoryLoadOrStore(Instruction inst) { - return inst == Instruction.Load || - inst == Instruction.Load16 || - inst == Instruction.Load8 || - inst == Instruction.Store || - inst == Instruction.Store16 || - inst == Instruction.Store8; + return inst is Instruction.Load or + Instruction.Load16 or + Instruction.Load8 or + Instruction.Store or + Instruction.Store16 or + Instruction.Store8; } } } diff --git a/src/ARMeilleure/CodeGen/X86/X86Register.cs b/src/ARMeilleure/CodeGen/X86/X86Register.cs index 0a6563663..bcce4f974 100644 --- a/src/ARMeilleure/CodeGen/X86/X86Register.cs +++ b/src/ARMeilleure/CodeGen/X86/X86Register.cs @@ -2,7 +2,6 @@ using System.Diagnostics.CodeAnalysis; namespace ARMeilleure.CodeGen.X86 { - [SuppressMessage("Design", "CA1069: Enums values should not be duplicated")] enum X86Register { Invalid = -1, diff --git a/src/ARMeilleure/Decoders/Decoder.cs b/src/ARMeilleure/Decoders/Decoder.cs index 3946e2f2e..29c939f5d 100644 --- a/src/ARMeilleure/Decoders/Decoder.cs +++ b/src/ARMeilleure/Decoders/Decoder.cs @@ -254,8 +254,8 @@ namespace ARMeilleure.Decoders } // Compare and branch instructions are always conditional. - if (opCode.Instruction.Name == InstName.Cbz || - opCode.Instruction.Name == InstName.Cbnz) + if (opCode.Instruction.Name is InstName.Cbz or + InstName.Cbnz) { return false; } @@ -274,9 +274,10 @@ namespace ARMeilleure.Decoders { if (opCode is OpCodeT32) { - return opCode.Instruction.Name != InstName.Tst && opCode.Instruction.Name != InstName.Teq && - opCode.Instruction.Name != InstName.Cmp && opCode.Instruction.Name != InstName.Cmn; + return opCode.Instruction.Name is not InstName.Tst and not InstName.Teq and + not InstName.Cmp and not InstName.Cmn; } + return true; } @@ -284,7 +285,7 @@ namespace ARMeilleure.Decoders // register (Rt == 15 or (mask & (1 << 15)) != 0), and cases where there is // a write back to PC (wback == true && Rn == 15), however the later may // be "undefined" depending on the CPU, so compilers should not produce that. - if (opCode is IOpCode32Mem || opCode is IOpCode32MemMult) + if (opCode is IOpCode32Mem or IOpCode32MemMult) { int rt, rn; @@ -326,15 +327,15 @@ namespace ARMeilleure.Decoders } // Explicit branch instructions. - return opCode is IOpCode32BImm || - opCode is IOpCode32BReg; + return opCode is IOpCode32BImm or + IOpCode32BReg; } private static bool IsCall(OpCode opCode) { - return opCode.Instruction.Name == InstName.Bl || - opCode.Instruction.Name == InstName.Blr || - opCode.Instruction.Name == InstName.Blx; + return opCode.Instruction.Name is InstName.Bl or + InstName.Blr or + InstName.Blx; } private static bool IsException(OpCode opCode) @@ -344,9 +345,9 @@ namespace ARMeilleure.Decoders private static bool IsTrap(OpCode opCode) { - return opCode.Instruction.Name == InstName.Brk || - opCode.Instruction.Name == InstName.Trap || - opCode.Instruction.Name == InstName.Und; + return opCode.Instruction.Name is InstName.Brk or + InstName.Trap or + InstName.Und; } public static OpCode DecodeOpCode(IMemoryManager memory, ulong address, ExecutionMode mode) diff --git a/src/ARMeilleure/Decoders/DecoderHelper.cs b/src/ARMeilleure/Decoders/DecoderHelper.cs index c39a8a88b..b0026ac91 100644 --- a/src/ARMeilleure/Decoders/DecoderHelper.cs +++ b/src/ARMeilleure/Decoders/DecoderHelper.cs @@ -162,6 +162,7 @@ namespace ARMeilleure.Decoders } } } + return false; } } diff --git a/src/ARMeilleure/Decoders/OpCode32SimdDupGP.cs b/src/ARMeilleure/Decoders/OpCode32SimdDupGP.cs index 57adea5e6..9f2d6b60b 100644 --- a/src/ARMeilleure/Decoders/OpCode32SimdDupGP.cs +++ b/src/ARMeilleure/Decoders/OpCode32SimdDupGP.cs @@ -20,6 +20,7 @@ namespace ARMeilleure.Decoders Instruction = InstDescriptor.Undefined; return; } + Q = ((opCode >> 21) & 0x1) != 0; RegisterSize = Q ? RegisterSize.Simd128 : RegisterSize.Simd64; diff --git a/src/ARMeilleure/Decoders/OpCode32SimdMemPair.cs b/src/ARMeilleure/Decoders/OpCode32SimdMemPair.cs index b35ac039b..0c4b912e7 100644 --- a/src/ARMeilleure/Decoders/OpCode32SimdMemPair.cs +++ b/src/ARMeilleure/Decoders/OpCode32SimdMemPair.cs @@ -40,7 +40,7 @@ namespace ARMeilleure.Decoders Rn = (opCode >> 16) & 0xf; WBack = Rm != RegisterAlias.Aarch32Pc; - RegisterIndex = Rm != RegisterAlias.Aarch32Pc && Rm != RegisterAlias.Aarch32Sp; + RegisterIndex = Rm is not RegisterAlias.Aarch32Pc and not RegisterAlias.Aarch32Sp; Regs = _regsMap[(opCode >> 8) & 0xf]; diff --git a/src/ARMeilleure/Decoders/OpCode32SimdMemSingle.cs b/src/ARMeilleure/Decoders/OpCode32SimdMemSingle.cs index 5df45000f..203d78ffe 100644 --- a/src/ARMeilleure/Decoders/OpCode32SimdMemSingle.cs +++ b/src/ARMeilleure/Decoders/OpCode32SimdMemSingle.cs @@ -45,7 +45,7 @@ namespace ARMeilleure.Decoders Rn = (opCode >> 16) & 0xf; WBack = Rm != RegisterAlias.Aarch32Pc; - RegisterIndex = Rm != RegisterAlias.Aarch32Pc && Rm != RegisterAlias.Aarch32Sp; + RegisterIndex = Rm is not RegisterAlias.Aarch32Pc and not RegisterAlias.Aarch32Sp; } } } diff --git a/src/ARMeilleure/Decoders/OpCodeMemImm.cs b/src/ARMeilleure/Decoders/OpCodeMemImm.cs index 4d5eeb1ed..8c55116fe 100644 --- a/src/ARMeilleure/Decoders/OpCodeMemImm.cs +++ b/src/ARMeilleure/Decoders/OpCodeMemImm.cs @@ -28,8 +28,8 @@ namespace ARMeilleure.Decoders MemOp type = WBack ? (MemOp)((opCode >> 10) & 3) : MemOp.Unsigned; PostIdx = type == MemOp.PostIndexed; - Unscaled = type == MemOp.Unscaled || - type == MemOp.Unprivileged; + Unscaled = type is MemOp.Unscaled or + MemOp.Unprivileged; // Unscaled and Unprivileged doesn't write back, // but they do use the 9-bits Signed Immediate. diff --git a/src/ARMeilleure/Decoders/OpCodeTable.cs b/src/ARMeilleure/Decoders/OpCodeTable.cs index d5e630f9b..d0cf9aec1 100644 --- a/src/ARMeilleure/Decoders/OpCodeTable.cs +++ b/src/ARMeilleure/Decoders/OpCodeTable.cs @@ -1381,6 +1381,7 @@ namespace ARMeilleure.Decoders { thumbEncoding = $"1110{thumbEncoding.AsSpan(4)}"; } + SetT32(thumbEncoding, name, emitter, makeOpT32); } @@ -1409,6 +1410,7 @@ namespace ARMeilleure.Decoders { throw new ArgumentException("Invalid ASIMD instruction encoding"); } + SetT32(thumbEncoding, name, emitter, makeOpT32); } diff --git a/src/ARMeilleure/Diagnostics/IRDumper.cs b/src/ARMeilleure/Diagnostics/IRDumper.cs index dcde1e360..c0397021c 100644 --- a/src/ARMeilleure/Diagnostics/IRDumper.cs +++ b/src/ARMeilleure/Diagnostics/IRDumper.cs @@ -9,7 +9,7 @@ namespace ARMeilleure.Diagnostics { class IRDumper { - private const string Indentation = " "; + private const char Indentation = ' '; private int _indentLevel; @@ -30,14 +30,11 @@ namespace ARMeilleure.Diagnostics private void Indent() { - _builder.EnsureCapacity(_builder.Capacity + _indentLevel * Indentation.Length); + if (_indentLevel == 0) + return; - for (int index = 0; index < _indentLevel; index++) - { -#pragma warning disable CA1834 // Use StringBuilder.Append(char) for single character strings - _builder.Append(Indentation); -#pragma warning restore CA1834 - } + _builder.EnsureCapacity(_builder.Capacity + _indentLevel); + _builder.Append(Indentation, _indentLevel); } private void IncreaseIndentation() @@ -235,8 +232,8 @@ namespace ARMeilleure.Diagnostics { _builder.Append('.').Append(operation.Intrinsic); } - else if (operation.Instruction == Instruction.BranchIf || - operation.Instruction == Instruction.Compare) + else if (operation.Instruction is Instruction.BranchIf or + Instruction.Compare) { comparison = true; } @@ -262,6 +259,7 @@ namespace ARMeilleure.Diagnostics DumpOperand(source); } } + break; } diff --git a/src/ARMeilleure/Instructions/InstEmitAlu32.cs b/src/ARMeilleure/Instructions/InstEmitAlu32.cs index 2e659fd5f..d7514040c 100644 --- a/src/ARMeilleure/Instructions/InstEmitAlu32.cs +++ b/src/ARMeilleure/Instructions/InstEmitAlu32.cs @@ -899,6 +899,7 @@ namespace ARMeilleure.Instructions { n = context.ShiftLeft(n, Const(shift)); } + break; case ShiftType.Asr: if (shift == 32) @@ -909,6 +910,7 @@ namespace ARMeilleure.Instructions { n = context.ShiftRightSI(n, Const(shift)); } + break; } diff --git a/src/ARMeilleure/Instructions/InstEmitAluHelper.cs b/src/ARMeilleure/Instructions/InstEmitAluHelper.cs index 4d4a31f7b..fe1c66d3c 100644 --- a/src/ARMeilleure/Instructions/InstEmitAluHelper.cs +++ b/src/ARMeilleure/Instructions/InstEmitAluHelper.cs @@ -266,7 +266,7 @@ namespace ARMeilleure.Instructions } } - private static Exception InvalidOpCodeType(OpCode opCode) + private static InvalidOperationException InvalidOpCodeType(OpCode opCode) { return new InvalidOperationException($"Invalid OpCode type \"{opCode?.GetType().Name ?? "null"}\"."); } @@ -318,6 +318,7 @@ namespace ARMeilleure.Instructions { m = GetRrxC(context, m, setCarry); } + break; } } diff --git a/src/ARMeilleure/Instructions/InstEmitHashHelper.cs b/src/ARMeilleure/Instructions/InstEmitHashHelper.cs index 9b1ad8721..19a607dfc 100644 --- a/src/ARMeilleure/Instructions/InstEmitHashHelper.cs +++ b/src/ARMeilleure/Instructions/InstEmitHashHelper.cs @@ -17,7 +17,7 @@ namespace ARMeilleure.Instructions public static Operand EmitCrc32(ArmEmitterContext context, Operand crc, Operand value, int size, bool castagnoli) { Debug.Assert(crc.Type.IsInteger() && value.Type.IsInteger()); - Debug.Assert(size >= 0 && size < 4); + Debug.Assert(size is >= 0 and < 4); Debug.Assert((size < 3) || (value.Type == OperandType.I64)); if (castagnoli && Optimizations.UseSse42) diff --git a/src/ARMeilleure/Instructions/InstEmitHelper.cs b/src/ARMeilleure/Instructions/InstEmitHelper.cs index 7a515f94f..a633e39ee 100644 --- a/src/ARMeilleure/Instructions/InstEmitHelper.cs +++ b/src/ARMeilleure/Instructions/InstEmitHelper.cs @@ -90,6 +90,7 @@ namespace ARMeilleure.Instructions { value = context.ConvertI64ToI32(value); } + Operand reg = Register(GetRegisterAlias(context.Mode, regIndex), RegisterType.Integer, OperandType.I32); context.Copy(reg, value); diff --git a/src/ARMeilleure/Instructions/InstEmitMemoryEx.cs b/src/ARMeilleure/Instructions/InstEmitMemoryEx.cs index 8c95b33c5..e4283e5a3 100644 --- a/src/ARMeilleure/Instructions/InstEmitMemoryEx.cs +++ b/src/ARMeilleure/Instructions/InstEmitMemoryEx.cs @@ -140,7 +140,7 @@ namespace ARMeilleure.Instructions if (pair) { - Debug.Assert(op.Size == 2 || op.Size == 3, "Invalid size for pairwise store."); + Debug.Assert(op.Size is 2 or 3, "Invalid size for pairwise store."); Operand t2 = GetIntOrZR(context, op.Rt2); diff --git a/src/ARMeilleure/Instructions/InstEmitMemoryExHelper.cs b/src/ARMeilleure/Instructions/InstEmitMemoryExHelper.cs index 7fca5b853..fd2562b14 100644 --- a/src/ARMeilleure/Instructions/InstEmitMemoryExHelper.cs +++ b/src/ARMeilleure/Instructions/InstEmitMemoryExHelper.cs @@ -42,6 +42,7 @@ namespace ARMeilleure.Instructions { context.Store(exValuePtr, Const(0UL)); } + if (size < 4) { context.Store(context.Add(exValuePtr, Const(exValuePtr.Type, 8L)), Const(0UL)); diff --git a/src/ARMeilleure/Instructions/InstEmitMemoryHelper.cs b/src/ARMeilleure/Instructions/InstEmitMemoryHelper.cs index ace6fe1ce..bb7e997b2 100644 --- a/src/ARMeilleure/Instructions/InstEmitMemoryHelper.cs +++ b/src/ARMeilleure/Instructions/InstEmitMemoryHelper.cs @@ -59,7 +59,7 @@ namespace ARMeilleure.Instructions { Operand value = GetInt(context, rt); - if (ext == Extension.Sx32 || ext == Extension.Sx64) + if (ext is Extension.Sx32 or Extension.Sx64) { OperandType destType = ext == Extension.Sx64 ? OperandType.I64 : OperandType.I32; @@ -123,9 +123,9 @@ namespace ARMeilleure.Instructions private static bool IsSimd(ArmEmitterContext context) { - return context.CurrOp is IOpCodeSimd && - !(context.CurrOp is OpCodeSimdMemMs || - context.CurrOp is OpCodeSimdMemSs); + return context.CurrOp is IOpCodeSimd and + not (OpCodeSimdMemMs or + OpCodeSimdMemSs); } public static Operand EmitReadInt(ArmEmitterContext context, Operand address, int size) @@ -717,7 +717,7 @@ namespace ARMeilleure.Instructions }; } - private static Exception InvalidOpCodeType(OpCode opCode) + private static InvalidOperationException InvalidOpCodeType(OpCode opCode) { return new InvalidOperationException($"Invalid OpCode type \"{opCode?.GetType().Name ?? "null"}\"."); } @@ -768,6 +768,7 @@ namespace ARMeilleure.Instructions { m = InstEmitAluHelper.GetRrxC(context, m, setCarry); } + break; } } diff --git a/src/ARMeilleure/Instructions/InstEmitMul.cs b/src/ARMeilleure/Instructions/InstEmitMul.cs index 89dc09938..cb48deb03 100644 --- a/src/ARMeilleure/Instructions/InstEmitMul.cs +++ b/src/ARMeilleure/Instructions/InstEmitMul.cs @@ -33,7 +33,6 @@ namespace ARMeilleure.Instructions public static void Umsubl(ArmEmitterContext context) => EmitMull(context, MullFlags.Subtract); [Flags] - [SuppressMessage("Design", "CA1069: Enums values should not be duplicated")] private enum MullFlags { Subtract = 0, diff --git a/src/ARMeilleure/Instructions/InstEmitSimdArithmetic.cs b/src/ARMeilleure/Instructions/InstEmitSimdArithmetic.cs index 694633f97..cee7a4ed8 100644 --- a/src/ARMeilleure/Instructions/InstEmitSimdArithmetic.cs +++ b/src/ARMeilleure/Instructions/InstEmitSimdArithmetic.cs @@ -5266,7 +5266,7 @@ namespace ARMeilleure.Instructions private static Operand EmitSse2Sll_128(ArmEmitterContext context, Operand op, int shift) { // The upper part of op is assumed to be zero. - Debug.Assert(shift >= 0 && shift < 64); + Debug.Assert(shift is >= 0 and < 64); if (shift == 0) { diff --git a/src/ARMeilleure/Instructions/InstEmitSimdArithmetic32.cs b/src/ARMeilleure/Instructions/InstEmitSimdArithmetic32.cs index 284f3f576..bcd6ce09e 100644 --- a/src/ARMeilleure/Instructions/InstEmitSimdArithmetic32.cs +++ b/src/ARMeilleure/Instructions/InstEmitSimdArithmetic32.cs @@ -231,10 +231,12 @@ namespace ARMeilleure.Instructions { result |= (long)((i >= end || i < start) ? 0x80 : b++) << (i * 8); } + for (int i = 8; i < 16; i++) { result2 |= (long)((i >= end || i < start) ? 0x80 : b++) << ((i - 8) * 8); } + return (result2, result); } @@ -261,6 +263,7 @@ namespace ARMeilleure.Instructions nMaskHigh = nMaskLow + 0x0808080808080808L; mMaskHigh = mMaskLow + 0x0808080808080808L; } + nMask = X86GetElements(context, nMaskHigh, nMaskLow); mMask = X86GetElements(context, mMaskHigh, mMaskLow); Operand nPart = context.AddIntrinsic(Intrinsic.X86Pshufb, n, nMask); @@ -285,6 +288,7 @@ namespace ARMeilleure.Instructions { extract = EmitVectorExtractZx32(context, op.Qn, op.In + byteOff, op.Size); } + byteOff++; res = EmitVectorInsert(context, res, extract, op.Id + index, op.Size); @@ -1304,6 +1308,7 @@ namespace ARMeilleure.Instructions case 2: return context.AddIntrinsic(Intrinsic.X86Shufps, op1, op1, Const(1 | (0 << 2) | (3 << 4) | (2 << 6))); } + break; case 2: // Rev32 @@ -1316,6 +1321,7 @@ namespace ARMeilleure.Instructions mask = X86GetElements(context, 0x0d0c0f0e_09080b0aL, 0x05040706_01000302L); return context.AddIntrinsic(Intrinsic.X86Pshufb, op1, mask); } + break; case 1: // Rev16 @@ -1341,6 +1347,7 @@ namespace ARMeilleure.Instructions case 3: return context.ByteSwap(op1); } + break; case 1: switch (op.Size) @@ -1355,6 +1362,7 @@ namespace ARMeilleure.Instructions context.BitwiseOr(context.ShiftRightUI(context.BitwiseAnd(op1, Const(0x0000ffff00000000ul)), Const(16)), context.ShiftLeft(context.BitwiseAnd(op1, Const(0x00000000ffff0000ul)), Const(16)))); } + break; case 2: // Swap upper and lower halves. diff --git a/src/ARMeilleure/Instructions/InstEmitSimdCvt.cs b/src/ARMeilleure/Instructions/InstEmitSimdCvt.cs index a5d4744f7..cf427eeae 100644 --- a/src/ARMeilleure/Instructions/InstEmitSimdCvt.cs +++ b/src/ARMeilleure/Instructions/InstEmitSimdCvt.cs @@ -1119,7 +1119,7 @@ namespace ARMeilleure.Instructions private static Operand EmitFPConvert(ArmEmitterContext context, Operand value, int size, bool signed) { - Debug.Assert(value.Type == OperandType.I32 || value.Type == OperandType.I64); + Debug.Assert(value.Type is OperandType.I32 or OperandType.I64); Debug.Assert((uint)size < 2); OperandType type = size == 0 ? OperandType.FP32 : OperandType.FP64; @@ -1136,7 +1136,7 @@ namespace ARMeilleure.Instructions private static Operand EmitScalarFcvts(ArmEmitterContext context, Operand value, int fBits) { - Debug.Assert(value.Type == OperandType.FP32 || value.Type == OperandType.FP64); + Debug.Assert(value.Type is OperandType.FP32 or OperandType.FP64); value = EmitF2iFBitsMul(context, value, fBits); @@ -1160,7 +1160,7 @@ namespace ARMeilleure.Instructions private static Operand EmitScalarFcvtu(ArmEmitterContext context, Operand value, int fBits) { - Debug.Assert(value.Type == OperandType.FP32 || value.Type == OperandType.FP64); + Debug.Assert(value.Type is OperandType.FP32 or OperandType.FP64); value = EmitF2iFBitsMul(context, value, fBits); @@ -1184,7 +1184,7 @@ namespace ARMeilleure.Instructions private static Operand EmitF2iFBitsMul(ArmEmitterContext context, Operand value, int fBits) { - Debug.Assert(value.Type == OperandType.FP32 || value.Type == OperandType.FP64); + Debug.Assert(value.Type is OperandType.FP32 or OperandType.FP64); if (fBits == 0) { @@ -1203,7 +1203,7 @@ namespace ARMeilleure.Instructions private static Operand EmitI2fFBitsMul(ArmEmitterContext context, Operand value, int fBits) { - Debug.Assert(value.Type == OperandType.FP32 || value.Type == OperandType.FP64); + Debug.Assert(value.Type is OperandType.FP32 or OperandType.FP64); if (fBits == 0) { diff --git a/src/ARMeilleure/Instructions/InstEmitSimdCvt32.cs b/src/ARMeilleure/Instructions/InstEmitSimdCvt32.cs index c35ffede4..f93552977 100644 --- a/src/ARMeilleure/Instructions/InstEmitSimdCvt32.cs +++ b/src/ARMeilleure/Instructions/InstEmitSimdCvt32.cs @@ -385,6 +385,7 @@ namespace ARMeilleure.Instructions { res = context.AddIntrinsic(Intrinsic.X86Cvtsd2ss, context.VectorZero(), res); } + res = context.AddIntrinsic(Intrinsic.X86Vcvtps2ph, res, Const(X86GetRoundControl(FPRoundingMode.ToNearest))); res = context.VectorExtract16(res, 0); InsertScalar16(context, op.Vd, op.T, res); @@ -397,6 +398,7 @@ namespace ARMeilleure.Instructions { res = context.AddIntrinsic(Intrinsic.X86Cvtss2sd, context.VectorZero(), res); } + res = context.VectorExtract(op.Size == 1 ? OperandType.I64 : OperandType.I32, res, 0); InsertScalar(context, op.Vd, res); } @@ -635,7 +637,7 @@ namespace ARMeilleure.Instructions private static Operand EmitFPConvert(ArmEmitterContext context, Operand value, OperandType type, bool signed) { - Debug.Assert(value.Type == OperandType.I32 || value.Type == OperandType.I64); + Debug.Assert(value.Type is OperandType.I32 or OperandType.I64); if (signed) { diff --git a/src/ARMeilleure/Instructions/InstEmitSimdHelper.cs b/src/ARMeilleure/Instructions/InstEmitSimdHelper.cs index d86830f70..11d0c93b4 100644 --- a/src/ARMeilleure/Instructions/InstEmitSimdHelper.cs +++ b/src/ARMeilleure/Instructions/InstEmitSimdHelper.cs @@ -363,7 +363,7 @@ namespace ARMeilleure.Instructions public static Operand EmitCountSetBits8(ArmEmitterContext context, Operand op) // "size" is 8 (SIMD&FP Inst.). { - Debug.Assert(op.Type == OperandType.I32 || op.Type == OperandType.I64); + Debug.Assert(op.Type is OperandType.I32 or OperandType.I64); Operand op0 = context.Subtract(op, context.BitwiseAnd(context.ShiftRightUI(op, Const(1)), Const(op.Type, 0x55L))); @@ -489,7 +489,7 @@ namespace ARMeilleure.Instructions public static Operand EmitRoundByRMode(ArmEmitterContext context, Operand op) { - Debug.Assert(op.Type == OperandType.FP32 || op.Type == OperandType.FP64); + Debug.Assert(op.Type is OperandType.FP32 or OperandType.FP64); Operand lbl1 = Label(); Operand lbl2 = Label(); @@ -1676,7 +1676,7 @@ namespace ARMeilleure.Instructions int eSize = 8 << size; Debug.Assert(op.Type == OperandType.I64); - Debug.Assert(eSize == 8 || eSize == 16 || eSize == 32 || eSize == 64); + Debug.Assert(eSize is 8 or 16 or 32 or 64); Operand lbl1 = Label(); Operand lblEnd = Label(); @@ -1709,7 +1709,7 @@ namespace ARMeilleure.Instructions int eSize = 8 << size; Debug.Assert(op.Type == OperandType.I64); - Debug.Assert(eSize == 8 || eSize == 16 || eSize == 32 || eSize == 64); + Debug.Assert(eSize is 8 or 16 or 32 or 64); Operand lblEnd = Label(); @@ -1735,7 +1735,7 @@ namespace ARMeilleure.Instructions int eSizeDst = 8 << sizeDst; Debug.Assert(op.Type == OperandType.I64); - Debug.Assert(eSizeDst == 8 || eSizeDst == 16 || eSizeDst == 32); + Debug.Assert(eSizeDst is 8 or 16 or 32); Operand lbl1 = Label(); Operand lblEnd = Label(); @@ -1768,7 +1768,7 @@ namespace ARMeilleure.Instructions int eSizeDst = 8 << sizeDst; Debug.Assert(op.Type == OperandType.I64); - Debug.Assert(eSizeDst == 8 || eSizeDst == 16 || eSizeDst == 32); + Debug.Assert(eSizeDst is 8 or 16 or 32); Operand lblEnd = Label(); diff --git a/src/ARMeilleure/Instructions/InstEmitSimdHelper32.cs b/src/ARMeilleure/Instructions/InstEmitSimdHelper32.cs index 2f021a1a1..c053fe27b 100644 --- a/src/ARMeilleure/Instructions/InstEmitSimdHelper32.cs +++ b/src/ARMeilleure/Instructions/InstEmitSimdHelper32.cs @@ -31,7 +31,7 @@ namespace ARMeilleure.Instructions { Debug.Assert(type != OperandType.V128); - if (type == OperandType.FP64 || type == OperandType.I64) + if (type is OperandType.FP64 or OperandType.I64) { // From dreg. return context.VectorExtract(type, GetVecA32(reg >> 1), reg & 1); @@ -48,7 +48,7 @@ namespace ARMeilleure.Instructions Debug.Assert(value.Type != OperandType.V128); Operand vec, insert; - if (value.Type == OperandType.FP64 || value.Type == OperandType.I64) + if (value.Type is OperandType.FP64 or OperandType.I64) { // From dreg. vec = GetVecA32(reg >> 1); @@ -71,7 +71,7 @@ namespace ARMeilleure.Instructions public static void InsertScalar16(ArmEmitterContext context, int reg, bool top, Operand value) { - Debug.Assert(value.Type == OperandType.FP32 || value.Type == OperandType.I32); + Debug.Assert(value.Type is OperandType.FP32 or OperandType.I32); Operand vec, insert; vec = GetVecA32(reg >> 2); @@ -880,6 +880,7 @@ namespace ARMeilleure.Instructions { res = EmitMoveDoubleWordToSide(context, res, side, op.Vd); } + res = EmitDoubleWordInsert(context, d, res, op.Vd); } diff --git a/src/ARMeilleure/Instructions/InstEmitSimdHelper32Arm64.cs b/src/ARMeilleure/Instructions/InstEmitSimdHelper32Arm64.cs index 568c07122..a1ca417b4 100644 --- a/src/ARMeilleure/Instructions/InstEmitSimdHelper32Arm64.cs +++ b/src/ARMeilleure/Instructions/InstEmitSimdHelper32Arm64.cs @@ -146,6 +146,7 @@ namespace ARMeilleure.Instructions { res = EmitMoveDoubleWordToSide(context, res, side, op.Vd); } + res = EmitDoubleWordInsert(context, d, res, op.Vd); } diff --git a/src/ARMeilleure/Instructions/InstEmitSimdLogical32.cs b/src/ARMeilleure/Instructions/InstEmitSimdLogical32.cs index 26d093447..1b0ef341b 100644 --- a/src/ARMeilleure/Instructions/InstEmitSimdLogical32.cs +++ b/src/ARMeilleure/Instructions/InstEmitSimdLogical32.cs @@ -268,6 +268,7 @@ namespace ARMeilleure.Instructions { m = context.BitwiseNot(m); } + return context.BitwiseExclusiveOr( context.BitwiseAnd(m, context.BitwiseExclusiveOr(d, n)), d); diff --git a/src/ARMeilleure/Instructions/InstEmitSimdMemory32.cs b/src/ARMeilleure/Instructions/InstEmitSimdMemory32.cs index 3808ef929..4d39b5fde 100644 --- a/src/ARMeilleure/Instructions/InstEmitSimdMemory32.cs +++ b/src/ARMeilleure/Instructions/InstEmitSimdMemory32.cs @@ -110,6 +110,7 @@ namespace ARMeilleure.Instructions EmitStoreSimd(context, address, d >> 1, index, op.Size); } } + offset += eBytes; d += op.Increment; } diff --git a/src/ARMeilleure/Instructions/InstEmitSimdShift.cs b/src/ARMeilleure/Instructions/InstEmitSimdShift.cs index ee7340adb..3469434c0 100644 --- a/src/ARMeilleure/Instructions/InstEmitSimdShift.cs +++ b/src/ARMeilleure/Instructions/InstEmitSimdShift.cs @@ -1634,7 +1634,7 @@ namespace ARMeilleure.Instructions int eSize = 8 << size; Debug.Assert(op.Type == OperandType.I64); - Debug.Assert(eSize == 8 || eSize == 16 || eSize == 32 || eSize == 64); + Debug.Assert(eSize is 8 or 16 or 32 or 64); Operand res = context.AllocateLocal(OperandType.I64); @@ -1657,7 +1657,7 @@ namespace ARMeilleure.Instructions int eSize = 8 << size; Debug.Assert(op.Type == OperandType.I64); - Debug.Assert(eSize == 8 || eSize == 16 || eSize == 32 || eSize == 64); + Debug.Assert(eSize is 8 or 16 or 32 or 64); Operand lblEnd = Label(); @@ -1732,7 +1732,7 @@ namespace ARMeilleure.Instructions Debug.Assert(op.Type == OperandType.I64); Debug.Assert(shiftLsB.Type == OperandType.I32); - Debug.Assert(eSize == 8 || eSize == 16 || eSize == 32 || eSize == 64); + Debug.Assert(eSize is 8 or 16 or 32 or 64); Operand lbl1 = Label(); Operand lblEnd = Label(); @@ -1769,7 +1769,7 @@ namespace ARMeilleure.Instructions Debug.Assert(op.Type == OperandType.I64); Debug.Assert(shiftLsB.Type == OperandType.I32); - Debug.Assert(eSize == 8 || eSize == 16 || eSize == 32 || eSize == 64); + Debug.Assert(eSize is 8 or 16 or 32 or 64); Operand lbl1 = Label(); Operand lbl2 = Label(); @@ -1813,6 +1813,7 @@ namespace ARMeilleure.Instructions ? EmitSignedSrcSatQ(context, shl, size, signedDst: true) : EmitUnsignedSrcSatQ(context, shl, size, signedDst: false)); } + context.Branch(lblEnd); context.MarkLabel(lblEnd); @@ -1850,6 +1851,7 @@ namespace ARMeilleure.Instructions { context.Copy(res, sar); } + context.Branch(lblEnd); context.MarkLabel(lblEnd); @@ -1906,6 +1908,7 @@ namespace ARMeilleure.Instructions Operand right = context.BitwiseOr(shr, context.ShiftRightUI(oneShl63UL, context.Subtract(shift, one))); context.Copy(res, context.ConditionalSelect(isEqual, oneUL, right)); } + context.Branch(lblEnd); context.MarkLabel(lblEnd); diff --git a/src/ARMeilleure/Instructions/NativeInterface.cs b/src/ARMeilleure/Instructions/NativeInterface.cs index 9d6279613..b4922629b 100644 --- a/src/ARMeilleure/Instructions/NativeInterface.cs +++ b/src/ARMeilleure/Instructions/NativeInterface.cs @@ -69,13 +69,13 @@ namespace ARMeilleure.Instructions [UnmanagedCallersOnly] public static ulong GetCtrEl0() { - return GetContext().CtrEl0; + return ExecutionContext.CtrEl0; } [UnmanagedCallersOnly] public static ulong GetDczidEl0() { - return GetContext().DczidEl0; + return ExecutionContext.DczidEl0; } [UnmanagedCallersOnly] diff --git a/src/ARMeilleure/Instructions/SoftFloat.cs b/src/ARMeilleure/Instructions/SoftFloat.cs index a2bb23be8..ccc45cc64 100644 --- a/src/ARMeilleure/Instructions/SoftFloat.cs +++ b/src/ARMeilleure/Instructions/SoftFloat.cs @@ -24,7 +24,7 @@ namespace ARMeilleure.Instructions { uint src = (uint)idx + 256u; - Debug.Assert(256u <= src && src < 512u); + Debug.Assert(src is >= 256u and < 512u); src = (src << 1) + 1u; @@ -32,7 +32,7 @@ namespace ARMeilleure.Instructions uint dst = (aux + 1u) >> 1; - Debug.Assert(256u <= dst && dst < 512u); + Debug.Assert(dst is >= 256u and < 512u); tbl[idx] = (byte)(dst - 256u); } @@ -48,7 +48,7 @@ namespace ARMeilleure.Instructions { uint src = (uint)idx + 128u; - Debug.Assert(128u <= src && src < 512u); + Debug.Assert(src is >= 128u and < 512u); if (src < 256u) { @@ -69,7 +69,7 @@ namespace ARMeilleure.Instructions uint dst = (aux + 1u) >> 1; - Debug.Assert(256u <= dst && dst < 512u); + Debug.Assert(dst is >= 256u and < 512u); tbl[idx] = (byte)(dst - 256u); } @@ -322,7 +322,7 @@ namespace ARMeilleure.Instructions float result; - if (type == FPType.SNaN || type == FPType.QNaN) + if (type is FPType.SNaN or FPType.QNaN) { if ((context.Fpcr & FPCR.Dn) != 0) { @@ -498,7 +498,7 @@ namespace ARMeilleure.Instructions double result; - if (type == FPType.SNaN || type == FPType.QNaN) + if (type is FPType.SNaN or FPType.QNaN) { if ((context.Fpcr & FPCR.Dn) != 0) { @@ -676,7 +676,7 @@ namespace ARMeilleure.Instructions ushort resultBits; - if (type == FPType.SNaN || type == FPType.QNaN) + if (type is FPType.SNaN or FPType.QNaN) { if (altHp) { @@ -1086,7 +1086,7 @@ namespace ARMeilleure.Instructions { return FPMaxFpscrImpl(value1, value2, standardFpscr == 1); } - + private static float FPMaxFpscrImpl(float value1, float value2, bool standardFpscr) { ExecutionContext context = NativeInterface.GetContext(); @@ -1522,7 +1522,7 @@ namespace ARMeilleure.Instructions float result; - if (type == FPType.SNaN || type == FPType.QNaN) + if (type is FPType.SNaN or FPType.QNaN) { result = FPProcessNaN(type, op, context, fpcr); } @@ -1689,7 +1689,7 @@ namespace ARMeilleure.Instructions float result; - if (type == FPType.SNaN || type == FPType.QNaN) + if (type is FPType.SNaN or FPType.QNaN) { result = FPProcessNaN(type, op, context, fpcr); } @@ -1726,7 +1726,7 @@ namespace ARMeilleure.Instructions float result; - if (type == FPType.SNaN || type == FPType.QNaN) + if (type is FPType.SNaN or FPType.QNaN) { result = FPProcessNaN(type, op, context, fpcr); } @@ -1920,7 +1920,7 @@ namespace ARMeilleure.Instructions float result; - if (type == FPType.SNaN || type == FPType.QNaN) + if (type is FPType.SNaN or FPType.QNaN) { result = FPProcessNaN(type, op, context, fpcr); } @@ -2211,7 +2211,7 @@ namespace ARMeilleure.Instructions ushort resultBits; - if (type == FPType.SNaN || type == FPType.QNaN) + if (type is FPType.SNaN or FPType.QNaN) { if (altHp) { @@ -3057,7 +3057,7 @@ namespace ARMeilleure.Instructions double result; - if (type == FPType.SNaN || type == FPType.QNaN) + if (type is FPType.SNaN or FPType.QNaN) { result = FPProcessNaN(type, op, context, fpcr); } @@ -3224,7 +3224,7 @@ namespace ARMeilleure.Instructions double result; - if (type == FPType.SNaN || type == FPType.QNaN) + if (type is FPType.SNaN or FPType.QNaN) { result = FPProcessNaN(type, op, context, fpcr); } @@ -3261,7 +3261,7 @@ namespace ARMeilleure.Instructions double result; - if (type == FPType.SNaN || type == FPType.QNaN) + if (type is FPType.SNaN or FPType.QNaN) { result = FPProcessNaN(type, op, context, fpcr); } @@ -3455,7 +3455,7 @@ namespace ARMeilleure.Instructions double result; - if (type == FPType.SNaN || type == FPType.QNaN) + if (type is FPType.SNaN or FPType.QNaN) { result = FPProcessNaN(type, op, context, fpcr); } diff --git a/src/ARMeilleure/IntermediateRepresentation/Intrinsic.cs b/src/ARMeilleure/IntermediateRepresentation/Intrinsic.cs index b9cab6674..9d87c13b3 100644 --- a/src/ARMeilleure/IntermediateRepresentation/Intrinsic.cs +++ b/src/ARMeilleure/IntermediateRepresentation/Intrinsic.cs @@ -4,7 +4,6 @@ using System.Diagnostics.CodeAnalysis; namespace ARMeilleure.IntermediateRepresentation { [Flags] - [SuppressMessage("Design", "CA1069: Enums values should not be duplicated")] enum Intrinsic : ushort { // X86 (SSE and AVX) diff --git a/src/ARMeilleure/IntermediateRepresentation/Operand.cs b/src/ARMeilleure/IntermediateRepresentation/Operand.cs index 9966308e6..2b3545004 100644 --- a/src/ARMeilleure/IntermediateRepresentation/Operand.cs +++ b/src/ARMeilleure/IntermediateRepresentation/Operand.cs @@ -446,7 +446,7 @@ namespace ARMeilleure.IntermediateRepresentation Data* data = null; // If constant or register, then try to look up in the intern table before allocating. - if (kind == OperandKind.Constant || kind == OperandKind.Register) + if (kind is OperandKind.Constant or OperandKind.Register) { uint hash = (uint)HashCode.Combine(kind, type, value); diff --git a/src/ARMeilleure/IntermediateRepresentation/OperandType.cs b/src/ARMeilleure/IntermediateRepresentation/OperandType.cs index 67ebdcde4..fec22eed6 100644 --- a/src/ARMeilleure/IntermediateRepresentation/OperandType.cs +++ b/src/ARMeilleure/IntermediateRepresentation/OperandType.cs @@ -16,8 +16,8 @@ namespace ARMeilleure.IntermediateRepresentation { public static bool IsInteger(this OperandType type) { - return type == OperandType.I32 || - type == OperandType.I64; + return type is OperandType.I32 or + OperandType.I64; } public static RegisterType ToRegisterType(this OperandType type) diff --git a/src/ARMeilleure/Memory/MemoryManagerType.cs b/src/ARMeilleure/Memory/MemoryManagerType.cs index bc8ae2635..cad7c3558 100644 --- a/src/ARMeilleure/Memory/MemoryManagerType.cs +++ b/src/ARMeilleure/Memory/MemoryManagerType.cs @@ -47,12 +47,12 @@ namespace ARMeilleure.Memory { public static bool IsHostMapped(this MemoryManagerType type) { - return type == MemoryManagerType.HostMapped || type == MemoryManagerType.HostMappedUnsafe; + return type is MemoryManagerType.HostMapped or MemoryManagerType.HostMappedUnsafe; } public static bool IsHostTracked(this MemoryManagerType type) { - return type == MemoryManagerType.HostTracked || type == MemoryManagerType.HostTrackedUnsafe; + return type is MemoryManagerType.HostTracked or MemoryManagerType.HostTrackedUnsafe; } public static bool IsHostMappedOrTracked(this MemoryManagerType type) diff --git a/src/ARMeilleure/State/ExecutionContext.cs b/src/ARMeilleure/State/ExecutionContext.cs index 6996ec221..223e59d79 100644 --- a/src/ARMeilleure/State/ExecutionContext.cs +++ b/src/ARMeilleure/State/ExecutionContext.cs @@ -16,10 +16,8 @@ namespace ARMeilleure.State public ulong Pc => _nativeContext.GetPc(); -#pragma warning disable CA1822 // Mark member as static - public uint CtrEl0 => 0x8444c004; - public uint DczidEl0 => 0x00000004; -#pragma warning restore CA1822 + public static uint CtrEl0 => 0x8444c004; + public static uint DczidEl0 => 0x00000004; public ulong CntfrqEl0 => _counter.Frequency; public ulong CntpctEl0 => _counter.Counter; diff --git a/src/ARMeilleure/State/NativeContext.cs b/src/ARMeilleure/State/NativeContext.cs index 140b6f7a7..c90e522a9 100644 --- a/src/ARMeilleure/State/NativeContext.cs +++ b/src/ARMeilleure/State/NativeContext.cs @@ -111,6 +111,7 @@ namespace ARMeilleure.State { value |= GetStorage().Flags[flag] != 0 ? 1u << flag : 0u; } + return value; } @@ -155,6 +156,7 @@ namespace ARMeilleure.State value |= GetStorage().FpFlags[flag] != 0 ? bit : 0u; } } + return value; } diff --git a/src/ARMeilleure/Translation/Cache/JitCache.cs b/src/ARMeilleure/Translation/Cache/JitCache.cs index e480985b1..7931fb360 100644 --- a/src/ARMeilleure/Translation/Cache/JitCache.cs +++ b/src/ARMeilleure/Translation/Cache/JitCache.cs @@ -24,7 +24,7 @@ namespace ARMeilleure.Translation.Cache private static JitCacheInvalidation _jitCacheInvalidator; - private static List _cacheAllocators = []; + private static readonly List _cacheAllocators = []; private static readonly List _cacheEntries = []; @@ -205,7 +205,6 @@ namespace ARMeilleure.Translation.Cache return allocOffsetNew; } - private static int AlignCodeSize(int codeSize) { return checked(codeSize + (CodeAlignment - 1)) & ~(CodeAlignment - 1); diff --git a/src/ARMeilleure/Translation/Delegates.cs b/src/ARMeilleure/Translation/Delegates.cs index d4f46108c..f44e8dc54 100644 --- a/src/ARMeilleure/Translation/Delegates.cs +++ b/src/ARMeilleure/Translation/Delegates.cs @@ -32,7 +32,7 @@ namespace ARMeilleure.Translation return _delegates.Values[index].FuncPtr; // O(1). } - + public static int GetDelegateIndex(MethodInfo info) { ArgumentNullException.ThrowIfNull(info); @@ -48,7 +48,7 @@ namespace ARMeilleure.Translation return index; } - + private static void SetDelegateInfo(MethodInfo method) { string key = GetKey(method); diff --git a/src/ARMeilleure/Translation/Dominance.cs b/src/ARMeilleure/Translation/Dominance.cs index b62714fdf..e2185bd85 100644 --- a/src/ARMeilleure/Translation/Dominance.cs +++ b/src/ARMeilleure/Translation/Dominance.cs @@ -77,7 +77,7 @@ namespace ARMeilleure.Translation { continue; } - + for (int pBlkIndex = 0; pBlkIndex < block.Predecessors.Count; pBlkIndex++) { BasicBlock current = block.Predecessors[pBlkIndex]; diff --git a/src/ARMeilleure/Translation/IntervalTree.cs b/src/ARMeilleure/Translation/IntervalTree.cs index 2fa431a8b..f4abe3bd5 100644 --- a/src/ARMeilleure/Translation/IntervalTree.cs +++ b/src/ARMeilleure/Translation/IntervalTree.cs @@ -124,7 +124,7 @@ namespace ARMeilleure.Translation /// /// The node to search for values within /// The list to add values to - private void AddToList(IntervalTreeNode node, List list) + private static void AddToList(IntervalTreeNode node, List list) { if (node == null) { @@ -165,6 +165,7 @@ namespace ARMeilleure.Translation return node; } } + return null; } @@ -175,7 +176,7 @@ namespace ARMeilleure.Translation /// End of the range /// Overlaps array to place results in /// Overlaps count to update - private void GetKeys(IntervalTreeNode node, TK start, TK end, ref TK[] overlaps, ref int overlapCount) + private static void GetKeys(IntervalTreeNode node, TK start, TK end, ref TK[] overlaps, ref int overlapCount) { if (node == null || start.CompareTo(node.Max) >= 0) { @@ -311,6 +312,7 @@ namespace ARMeilleure.Translation return false; } } + IntervalTreeNode newNode = new(start, end, value, parent); if (newNode.Parent == null) { @@ -422,12 +424,14 @@ namespace ARMeilleure.Translation { return Maximum(node.Left); } + IntervalTreeNode parent = node.Parent; while (parent != null && node == parent.Left) { node = parent; parent = parent.Parent; } + return parent; } @@ -452,6 +456,7 @@ namespace ARMeilleure.Translation RotateLeft(ParentOf(ptr)); sibling = RightOf(ParentOf(ptr)); } + if (ColorOf(LeftOf(sibling)) == Black && ColorOf(RightOf(sibling)) == Black) { SetColor(sibling, Red); @@ -466,6 +471,7 @@ namespace ARMeilleure.Translation RotateRight(sibling); sibling = RightOf(ParentOf(ptr)); } + SetColor(sibling, ColorOf(ParentOf(ptr))); SetColor(ParentOf(ptr), Black); SetColor(RightOf(sibling), Black); @@ -484,6 +490,7 @@ namespace ARMeilleure.Translation RotateRight(ParentOf(ptr)); sibling = LeftOf(ParentOf(ptr)); } + if (ColorOf(RightOf(sibling)) == Black && ColorOf(LeftOf(sibling)) == Black) { SetColor(sibling, Red); @@ -498,6 +505,7 @@ namespace ARMeilleure.Translation RotateLeft(sibling); sibling = LeftOf(ParentOf(ptr)); } + SetColor(sibling, ColorOf(ParentOf(ptr))); SetColor(ParentOf(ptr), Black); SetColor(LeftOf(sibling), Black); @@ -506,6 +514,7 @@ namespace ARMeilleure.Translation } } } + SetColor(ptr, Black); } @@ -532,6 +541,7 @@ namespace ARMeilleure.Translation balanceNode = ParentOf(balanceNode); RotateLeft(balanceNode); } + SetColor(ParentOf(balanceNode), Black); SetColor(ParentOf(ParentOf(balanceNode)), Red); RotateRight(ParentOf(ParentOf(balanceNode))); @@ -555,12 +565,14 @@ namespace ARMeilleure.Translation balanceNode = ParentOf(balanceNode); RotateRight(balanceNode); } + SetColor(ParentOf(balanceNode), Black); SetColor(ParentOf(ParentOf(balanceNode)), Red); RotateLeft(ParentOf(ParentOf(balanceNode))); } } } + SetColor(_root, Black); } @@ -574,6 +586,7 @@ namespace ARMeilleure.Translation { node.Right.Parent = node; } + IntervalTreeNode nodeParent = ParentOf(node); right.Parent = nodeParent; if (nodeParent == null) @@ -588,6 +601,7 @@ namespace ARMeilleure.Translation { nodeParent.Right = right; } + right.Left = node; node.Parent = right; @@ -605,6 +619,7 @@ namespace ARMeilleure.Translation { node.Left.Parent = node; } + IntervalTreeNode nodeParent = ParentOf(node); left.Parent = nodeParent; if (nodeParent == null) @@ -619,6 +634,7 @@ namespace ARMeilleure.Translation { nodeParent.Left = left; } + left.Right = node; node.Parent = left; diff --git a/src/ARMeilleure/Translation/PTC/Ptc.cs b/src/ARMeilleure/Translation/PTC/Ptc.cs index 72f9d5a0a..eb0a609f2 100644 --- a/src/ARMeilleure/Translation/PTC/Ptc.cs +++ b/src/ARMeilleure/Translation/PTC/Ptc.cs @@ -835,8 +835,6 @@ namespace ARMeilleure.Translation.PTC return; } - - int degreeOfParallelism = Environment.ProcessorCount; if (Optimizations.LowPower) @@ -896,13 +894,12 @@ namespace ARMeilleure.Translation.PTC } } - List threads = Enumerable.Range(0, degreeOfParallelism) - .Select(idx => + .Select(idx => new Thread(TranslateFuncs) { - IsBackground = true, - Name = "Ptc.TranslateThread." + idx + IsBackground = true, + Name = "Ptc.TranslateThread." + idx } ).ToList(); @@ -912,6 +909,7 @@ namespace ARMeilleure.Translation.PTC { thread.Start(); } + foreach (Thread thread in threads) { thread.Join(); @@ -925,8 +923,8 @@ namespace ARMeilleure.Translation.PTC sw.Stop(); PtcStateChanged?.Invoke(PtcLoadingState.Loaded, _translateCount, _translateTotalCount); - - Logger.Info?.Print(LogClass.Ptc, + + Logger.Info?.Print(LogClass.Ptc, $"{_translateCount} of {_translateTotalCount} functions translated in {sw.Elapsed.TotalSeconds} seconds " + $"| {"function".ToQuantity(_translateTotalCount - _translateCount)} blacklisted " + $"| Thread count: {degreeOfParallelism}"); @@ -1164,8 +1162,8 @@ namespace ARMeilleure.Translation.PTC public void Close() { - if (State == PtcState.Enabled || - State == PtcState.Continuing) + if (State is PtcState.Enabled or + PtcState.Continuing) { State = PtcState.Closing; } diff --git a/src/ARMeilleure/Translation/PTC/PtcProfiler.cs b/src/ARMeilleure/Translation/PTC/PtcProfiler.cs index f3aaa58ff..c7e399433 100644 --- a/src/ARMeilleure/Translation/PTC/PtcProfiler.cs +++ b/src/ARMeilleure/Translation/PTC/PtcProfiler.cs @@ -1,5 +1,6 @@ using ARMeilleure.State; using Humanizer; +using Microsoft.IO; using Ryujinx.Common; using Ryujinx.Common.Logging; using Ryujinx.Common.Memory; @@ -26,7 +27,7 @@ namespace ARMeilleure.Translation.PTC private const uint InternalVersion = 7007; //! Not to be incremented manually for each change to the ARMeilleure project. - private static readonly uint[] _migrateInternalVersions = + private static readonly uint[] _migrateInternalVersions = [ 1866, 5518, @@ -75,7 +76,7 @@ namespace ARMeilleure.Translation.PTC Enabled = false; } - private void TimerElapsed(object _, ElapsedEventArgs __) + private void TimerElapsed(object _, ElapsedEventArgs __) => new Thread(PreSave) { Name = "Ptc.DiskWriter" }.Start(); public void AddEntry(ulong address, ExecutionMode mode, bool highCq, bool blacklist = false) @@ -151,7 +152,7 @@ namespace ARMeilleure.Translation.PTC if (!funcProfile.Blacklist) continue; - if (!funcs.Contains(ptr)) + if (!funcs.Contains(ptr)) funcs.Add(ptr); } @@ -219,7 +220,7 @@ namespace ARMeilleure.Translation.PTC return false; } - using MemoryStream stream = MemoryStreamManager.Shared.GetStream(); + using RecyclableMemoryStream stream = MemoryStreamManager.Shared.GetStream(); Debug.Assert(stream.Seek(0L, SeekOrigin.Begin) == 0L && stream.Length == 0L); try @@ -293,10 +294,10 @@ namespace ARMeilleure.Translation.PTC { if (migrateEntryFunc != null) { - return DeserializeAndUpdateDictionary(stream, (Stream stream) => { return new FuncProfile(DeserializeStructure(stream)); }, migrateEntryFunc); + return DeserializeAndUpdateDictionary(stream, stream => { return new FuncProfile(DeserializeStructure(stream)); }, migrateEntryFunc); } - return DeserializeDictionary(stream, (Stream stream) => { return new FuncProfile(DeserializeStructure(stream)); }); + return DeserializeDictionary(stream, stream => { return new FuncProfile(DeserializeStructure(stream)); }); } private static ReadOnlySpan GetReadOnlySpan(MemoryStream memoryStream) @@ -467,8 +468,8 @@ namespace ARMeilleure.Translation.PTC public void Start() { - if (_ptc.State == PtcState.Enabled || - _ptc.State == PtcState.Continuing) + if (_ptc.State is PtcState.Enabled or + PtcState.Continuing) { Enabled = true; diff --git a/src/Ryujinx.Audio.Backends.OpenAL/OpenALHardwareDeviceDriver.cs b/src/Ryujinx.Audio.Backends.OpenAL/OpenALHardwareDeviceDriver.cs index 25f91f8e9..8be6197f6 100644 --- a/src/Ryujinx.Audio.Backends.OpenAL/OpenALHardwareDeviceDriver.cs +++ b/src/Ryujinx.Audio.Backends.OpenAL/OpenALHardwareDeviceDriver.cs @@ -178,7 +178,7 @@ namespace Ryujinx.Audio.Backends.OpenAL public bool SupportsChannelCount(uint channelCount) { - return channelCount == 1 || channelCount == 2 || channelCount == 6; + return channelCount is 1 or 2 or 6; } public bool SupportsDirection(Direction direction) diff --git a/src/Ryujinx.Audio.Backends.SDL2/SDL2HardwareDeviceDriver.cs b/src/Ryujinx.Audio.Backends.SDL2/SDL2HardwareDeviceDriver.cs index 2d04073d7..d5381209e 100644 --- a/src/Ryujinx.Audio.Backends.SDL2/SDL2HardwareDeviceDriver.cs +++ b/src/Ryujinx.Audio.Backends.SDL2/SDL2HardwareDeviceDriver.cs @@ -24,10 +24,8 @@ namespace Ryujinx.Audio.Backends.SDL2 // TODO: Add this to SDL2-CS // NOTE: We use a DllImport here because of marshaling issue for spec. -#pragma warning disable SYSLIB1054 [DllImport("SDL2")] private static extern int SDL_GetDefaultAudioInfo(nint name, out SDL_AudioSpec spec, int isCapture); -#pragma warning restore SYSLIB1054 public SDL2HardwareDeviceDriver() { diff --git a/src/Ryujinx.Audio/Backends/CompatLayer/CompatLayerHardwareDeviceDriver.cs b/src/Ryujinx.Audio/Backends/CompatLayer/CompatLayerHardwareDeviceDriver.cs index a2c2cdcd0..8bc2a6016 100644 --- a/src/Ryujinx.Audio/Backends/CompatLayer/CompatLayerHardwareDeviceDriver.cs +++ b/src/Ryujinx.Audio/Backends/CompatLayer/CompatLayerHardwareDeviceDriver.cs @@ -162,7 +162,7 @@ namespace Ryujinx.Audio.Backends.CompatLayer public bool SupportsChannelCount(uint channelCount) { - return channelCount == 1 || channelCount == 2 || channelCount == 6; + return channelCount is 1 or 2 or 6; } public bool SupportsSampleFormat(SampleFormat sampleFormat) @@ -184,7 +184,7 @@ namespace Ryujinx.Audio.Backends.CompatLayer public bool SupportsDirection(Direction direction) { - return direction == Direction.Input || direction == Direction.Output; + return direction is Direction.Input or Direction.Output; } } } diff --git a/src/Ryujinx.Audio/Backends/Dummy/DummyHardwareDeviceDriver.cs b/src/Ryujinx.Audio/Backends/Dummy/DummyHardwareDeviceDriver.cs index 5991b816f..2cd15c092 100644 --- a/src/Ryujinx.Audio/Backends/Dummy/DummyHardwareDeviceDriver.cs +++ b/src/Ryujinx.Audio/Backends/Dummy/DummyHardwareDeviceDriver.cs @@ -73,12 +73,12 @@ namespace Ryujinx.Audio.Backends.Dummy public bool SupportsDirection(Direction direction) { - return direction == Direction.Output || direction == Direction.Input; + return direction is Direction.Output or Direction.Input; } public bool SupportsChannelCount(uint channelCount) { - return channelCount == 1 || channelCount == 2 || channelCount == 6; + return channelCount is 1 or 2 or 6; } } } diff --git a/src/Ryujinx.Audio/Common/AudioDeviceSession.cs b/src/Ryujinx.Audio/Common/AudioDeviceSession.cs index a0e04c80d..6ba001e80 100644 --- a/src/Ryujinx.Audio/Common/AudioDeviceSession.cs +++ b/src/Ryujinx.Audio/Common/AudioDeviceSession.cs @@ -109,7 +109,7 @@ namespace Ryujinx.Audio.Common /// The state of the session public AudioDeviceState GetState() { - Debug.Assert(_state == AudioDeviceState.Started || _state == AudioDeviceState.Stopped); + Debug.Assert(_state is AudioDeviceState.Started or AudioDeviceState.Stopped); return _state; } diff --git a/src/Ryujinx.Audio/Input/AudioInputManager.cs b/src/Ryujinx.Audio/Input/AudioInputManager.cs index 5defef0f7..3869867e0 100644 --- a/src/Ryujinx.Audio/Input/AudioInputManager.cs +++ b/src/Ryujinx.Audio/Input/AudioInputManager.cs @@ -166,7 +166,7 @@ namespace Ryujinx.Audio.Input /// /// If true, filter disconnected devices /// The list of all audio inputs name - public string[] ListAudioIns(bool filtered) + public static string[] ListAudioIns(bool filtered) { if (filtered) { diff --git a/src/Ryujinx.Audio/Input/AudioInputSystem.cs b/src/Ryujinx.Audio/Input/AudioInputSystem.cs index 65b99745d..d1d4b0381 100644 --- a/src/Ryujinx.Audio/Input/AudioInputSystem.cs +++ b/src/Ryujinx.Audio/Input/AudioInputSystem.cs @@ -91,12 +91,12 @@ namespace Ryujinx.Audio.Input return ResultCode.DeviceNotFound; } - if (configuration.SampleRate != 0 && configuration.SampleRate != Constants.TargetSampleRate) + if (configuration.SampleRate is not 0 and not Constants.TargetSampleRate) { return ResultCode.UnsupportedSampleRate; } - if (configuration.ChannelCount != 0 && configuration.ChannelCount != 1 && configuration.ChannelCount != 2 && configuration.ChannelCount != 6) + if (configuration.ChannelCount is not 0 and not 1 and not 2 and not 6) { return ResultCode.UnsupportedChannelConfiguration; } diff --git a/src/Ryujinx.Audio/Integration/IHardwareDevice.cs b/src/Ryujinx.Audio/Integration/IHardwareDevice.cs index f9ade9dbc..42d543f55 100644 --- a/src/Ryujinx.Audio/Integration/IHardwareDevice.cs +++ b/src/Ryujinx.Audio/Integration/IHardwareDevice.cs @@ -47,7 +47,7 @@ namespace Ryujinx.Audio.Integration { uint channelCount = GetChannelCount(); - Debug.Assert(channelCount > 0 && channelCount <= Constants.ChannelCountMax); + Debug.Assert(channelCount is > 0 and <= Constants.ChannelCountMax); return channelCount != Constants.ChannelCountMax; } diff --git a/src/Ryujinx.Audio/Output/AudioOutputManager.cs b/src/Ryujinx.Audio/Output/AudioOutputManager.cs index 556088bc2..4e2971743 100644 --- a/src/Ryujinx.Audio/Output/AudioOutputManager.cs +++ b/src/Ryujinx.Audio/Output/AudioOutputManager.cs @@ -165,7 +165,7 @@ namespace Ryujinx.Audio.Output /// Get the list of all audio outputs name. /// /// The list of all audio outputs name - public string[] ListAudioOuts() + public static string[] ListAudioOuts() { return [Constants.DefaultDeviceOutputName]; } diff --git a/src/Ryujinx.Audio/Output/AudioOutputSystem.cs b/src/Ryujinx.Audio/Output/AudioOutputSystem.cs index dc7d52ced..3cf6e0722 100644 --- a/src/Ryujinx.Audio/Output/AudioOutputSystem.cs +++ b/src/Ryujinx.Audio/Output/AudioOutputSystem.cs @@ -91,12 +91,12 @@ namespace Ryujinx.Audio.Output return ResultCode.DeviceNotFound; } - if (configuration.SampleRate != 0 && configuration.SampleRate != Constants.TargetSampleRate) + if (configuration.SampleRate is not 0 and not Constants.TargetSampleRate) { return ResultCode.UnsupportedSampleRate; } - if (configuration.ChannelCount != 0 && configuration.ChannelCount != 1 && configuration.ChannelCount != 2 && configuration.ChannelCount != 6) + if (configuration.ChannelCount is not 0 and not 1 and not 2 and not 6) { return ResultCode.UnsupportedChannelConfiguration; } diff --git a/src/Ryujinx.Audio/Renderer/Device/VirtualDevice.cs b/src/Ryujinx.Audio/Renderer/Device/VirtualDevice.cs index 439be6bd8..f5ba9a271 100644 --- a/src/Ryujinx.Audio/Renderer/Device/VirtualDevice.cs +++ b/src/Ryujinx.Audio/Renderer/Device/VirtualDevice.cs @@ -58,7 +58,7 @@ namespace Ryujinx.Audio.Renderer.Device /// The new master volume. public void UpdateMasterVolume(float volume) { - Debug.Assert(volume >= 0.0f && volume <= 1.0f); + Debug.Assert(volume is >= 0.0f and <= 1.0f); MasterVolume = volume; } diff --git a/src/Ryujinx.Audio/Renderer/Device/VirtualDeviceSessionRegistry.cs b/src/Ryujinx.Audio/Renderer/Device/VirtualDeviceSessionRegistry.cs index 4ad70619e..5c42ed991 100644 --- a/src/Ryujinx.Audio/Renderer/Device/VirtualDeviceSessionRegistry.cs +++ b/src/Ryujinx.Audio/Renderer/Device/VirtualDeviceSessionRegistry.cs @@ -17,9 +17,7 @@ namespace Ryujinx.Audio.Renderer.Device /// The default . /// /// This is used when the USB device is the default one on older revision. -#pragma warning disable CA1822 // Mark member as static - public VirtualDevice DefaultDevice => VirtualDevice.Devices[0]; -#pragma warning restore CA1822 + public static VirtualDevice DefaultDevice => VirtualDevice.Devices[0]; /// /// The current active . diff --git a/src/Ryujinx.Audio/Renderer/Dsp/Command/DelayCommand.cs b/src/Ryujinx.Audio/Renderer/Dsp/Command/DelayCommand.cs index 21cf69504..ecd3c3c93 100644 --- a/src/Ryujinx.Audio/Renderer/Dsp/Command/DelayCommand.cs +++ b/src/Ryujinx.Audio/Renderer/Dsp/Command/DelayCommand.cs @@ -129,7 +129,6 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command delayFeedbackCrossGain, 0.0f, delayFeedbackBaseGain, delayFeedbackCrossGain, 0.0f, delayFeedbackCrossGain, delayFeedbackCrossGain, delayFeedbackBaseGain); - for (int i = 0; i < sampleCount; i++) { Vector4 channelInput = new() diff --git a/src/Ryujinx.Audio/Renderer/Dsp/State/DelayState.cs b/src/Ryujinx.Audio/Renderer/Dsp/State/DelayState.cs index 17ad2a40d..1dfc2d28b 100644 --- a/src/Ryujinx.Audio/Renderer/Dsp/State/DelayState.cs +++ b/src/Ryujinx.Audio/Renderer/Dsp/State/DelayState.cs @@ -40,7 +40,7 @@ namespace Ryujinx.Audio.Renderer.Dsp.State DelayFeedbackBaseGain = (1.0f - channelSpread) * FeedbackGain; - if (parameter.ChannelCount == 4 || parameter.ChannelCount == 6) + if (parameter.ChannelCount is 4 or 6) { DelayFeedbackCrossGain = channelSpread * 0.5f * FeedbackGain; } diff --git a/src/Ryujinx.Audio/Renderer/Dsp/UpsamplerHelper.cs b/src/Ryujinx.Audio/Renderer/Dsp/UpsamplerHelper.cs index 5732cdb21..8d833b712 100644 --- a/src/Ryujinx.Audio/Renderer/Dsp/UpsamplerHelper.cs +++ b/src/Ryujinx.Audio/Renderer/Dsp/UpsamplerHelper.cs @@ -27,6 +27,7 @@ namespace Ryujinx.Audio.Renderer.Dsp { return 1.0f; } + return (MathF.Sin(MathF.PI * x) / (MathF.PI * x)); } @@ -141,6 +142,7 @@ namespace Ryujinx.Audio.Renderer.Dsp state.Phase = (state.Phase + 1) % 6; } + break; case 3.0f: for (int i = 0; i < outputSampleCount; i++) @@ -161,6 +163,7 @@ namespace Ryujinx.Audio.Renderer.Dsp state.Phase = (state.Phase + 1) % 3; } + break; case 1.5f: // Upsample by 3 then decimate by 2. @@ -183,6 +186,7 @@ namespace Ryujinx.Audio.Renderer.Dsp state.Phase = (state.Phase + 1) % 3; } + break; default: throw new ArgumentOutOfRangeException(nameof(state), state.Scale, null); diff --git a/src/Ryujinx.Audio/Renderer/Parameter/EffectInParameterVersion1.cs b/src/Ryujinx.Audio/Renderer/Parameter/EffectInParameterVersion1.cs index 46686e3b4..73fea4c36 100644 --- a/src/Ryujinx.Audio/Renderer/Parameter/EffectInParameterVersion1.cs +++ b/src/Ryujinx.Audio/Renderer/Parameter/EffectInParameterVersion1.cs @@ -91,7 +91,7 @@ namespace Ryujinx.Audio.Renderer.Parameter /// Returns true if the channel count is valid. public static bool IsChannelCountValid(int channelCount) { - return channelCount == 1 || channelCount == 2 || channelCount == 4 || channelCount == 6; + return channelCount is 1 or 2 or 4 or 6; } } } diff --git a/src/Ryujinx.Audio/Renderer/Parameter/EffectInParameterVersion2.cs b/src/Ryujinx.Audio/Renderer/Parameter/EffectInParameterVersion2.cs index 3854c7148..779bc8fb7 100644 --- a/src/Ryujinx.Audio/Renderer/Parameter/EffectInParameterVersion2.cs +++ b/src/Ryujinx.Audio/Renderer/Parameter/EffectInParameterVersion2.cs @@ -91,7 +91,7 @@ namespace Ryujinx.Audio.Renderer.Parameter /// Returns true if the channel count is valid. public static bool IsChannelCountValid(int channelCount) { - return channelCount == 1 || channelCount == 2 || channelCount == 4 || channelCount == 6; + return channelCount is 1 or 2 or 4 or 6; } } } diff --git a/src/Ryujinx.Audio/Renderer/Server/AudioRenderSystem.cs b/src/Ryujinx.Audio/Renderer/Server/AudioRenderSystem.cs index 33082225a..ee2f23479 100644 --- a/src/Ryujinx.Audio/Renderer/Server/AudioRenderSystem.cs +++ b/src/Ryujinx.Audio/Renderer/Server/AudioRenderSystem.cs @@ -532,13 +532,13 @@ namespace Ryujinx.Audio.Renderer.Server CommandType commandType = command.CommandType; - if (commandType == CommandType.AdpcmDataSourceVersion1 || - commandType == CommandType.AdpcmDataSourceVersion2 || - commandType == CommandType.PcmInt16DataSourceVersion1 || - commandType == CommandType.PcmInt16DataSourceVersion2 || - commandType == CommandType.PcmFloatDataSourceVersion1 || - commandType == CommandType.PcmFloatDataSourceVersion2 || - commandType == CommandType.Performance) + if (commandType is CommandType.AdpcmDataSourceVersion1 or + CommandType.AdpcmDataSourceVersion2 or + CommandType.PcmInt16DataSourceVersion1 or + CommandType.PcmInt16DataSourceVersion2 or + CommandType.PcmFloatDataSourceVersion1 or + CommandType.PcmFloatDataSourceVersion2 or + CommandType.Performance) { break; } diff --git a/src/Ryujinx.Audio/Renderer/Server/CommandBuffer.cs b/src/Ryujinx.Audio/Renderer/Server/CommandBuffer.cs index 4c353b37e..d65897e45 100644 --- a/src/Ryujinx.Audio/Renderer/Server/CommandBuffer.cs +++ b/src/Ryujinx.Audio/Renderer/Server/CommandBuffer.cs @@ -467,7 +467,6 @@ namespace Ryujinx.Audio.Renderer.Server } } - /// /// Generate a new . /// diff --git a/src/Ryujinx.Audio/Renderer/Server/CommandProcessingTimeEstimatorVersion2.cs b/src/Ryujinx.Audio/Renderer/Server/CommandProcessingTimeEstimatorVersion2.cs index ef1326924..1e9b6c53e 100644 --- a/src/Ryujinx.Audio/Renderer/Server/CommandProcessingTimeEstimatorVersion2.cs +++ b/src/Ryujinx.Audio/Renderer/Server/CommandProcessingTimeEstimatorVersion2.cs @@ -20,7 +20,7 @@ namespace Ryujinx.Audio.Renderer.Server public uint Estimate(PerformanceCommand command) { - Debug.Assert(_sampleCount == 160 || _sampleCount == 240); + Debug.Assert(_sampleCount is 160 or 240); if (_sampleCount == 160) { @@ -32,7 +32,7 @@ namespace Ryujinx.Audio.Renderer.Server public uint Estimate(ClearMixBufferCommand command) { - Debug.Assert(_sampleCount == 160 || _sampleCount == 240); + Debug.Assert(_sampleCount is 160 or 240); float costPerBuffer = 668.8f; float baseCost = 193.2f; @@ -48,7 +48,7 @@ namespace Ryujinx.Audio.Renderer.Server public uint Estimate(BiquadFilterCommand command) { - Debug.Assert(_sampleCount == 160 || _sampleCount == 240); + Debug.Assert(_sampleCount is 160 or 240); if (_sampleCount == 160) { @@ -62,7 +62,7 @@ namespace Ryujinx.Audio.Renderer.Server { const float CostPerSample = 7.245f; - Debug.Assert(_sampleCount == 160 || _sampleCount == 240); + Debug.Assert(_sampleCount is 160 or 240); int volumeCount = 0; @@ -79,7 +79,7 @@ namespace Ryujinx.Audio.Renderer.Server public uint Estimate(MixRampCommand command) { - Debug.Assert(_sampleCount == 160 || _sampleCount == 240); + Debug.Assert(_sampleCount is 160 or 240); if (_sampleCount == 160) { @@ -91,7 +91,7 @@ namespace Ryujinx.Audio.Renderer.Server public uint Estimate(DepopPrepareCommand command) { - Debug.Assert(_sampleCount == 160 || _sampleCount == 240); + Debug.Assert(_sampleCount is 160 or 240); if (_sampleCount == 160) { @@ -103,7 +103,7 @@ namespace Ryujinx.Audio.Renderer.Server public uint Estimate(VolumeRampCommand command) { - Debug.Assert(_sampleCount == 160 || _sampleCount == 240); + Debug.Assert(_sampleCount is 160 or 240); if (_sampleCount == 160) { @@ -115,7 +115,7 @@ namespace Ryujinx.Audio.Renderer.Server public uint Estimate(PcmInt16DataSourceCommandVersion1 command) { - Debug.Assert(_sampleCount == 160 || _sampleCount == 240); + Debug.Assert(_sampleCount is 160 or 240); float costPerSample = 1195.5f; float baseCost = 7797.0f; @@ -131,7 +131,7 @@ namespace Ryujinx.Audio.Renderer.Server public uint Estimate(AdpcmDataSourceCommandVersion1 command) { - Debug.Assert(_sampleCount == 160 || _sampleCount == 240); + Debug.Assert(_sampleCount is 160 or 240); float costPerSample = 3564.1f; float baseCost = 6225.5f; @@ -147,7 +147,7 @@ namespace Ryujinx.Audio.Renderer.Server public uint Estimate(DepopForMixBuffersCommand command) { - Debug.Assert(_sampleCount == 160 || _sampleCount == 240); + Debug.Assert(_sampleCount is 160 or 240); if (_sampleCount == 160) { @@ -159,7 +159,7 @@ namespace Ryujinx.Audio.Renderer.Server public uint Estimate(CopyMixBufferCommand command) { - Debug.Assert(_sampleCount == 160 || _sampleCount == 240); + Debug.Assert(_sampleCount is 160 or 240); if (_sampleCount == 160) { @@ -171,7 +171,7 @@ namespace Ryujinx.Audio.Renderer.Server public uint Estimate(MixCommand command) { - Debug.Assert(_sampleCount == 160 || _sampleCount == 240); + Debug.Assert(_sampleCount is 160 or 240); if (_sampleCount == 160) { @@ -183,7 +183,7 @@ namespace Ryujinx.Audio.Renderer.Server public uint Estimate(DelayCommand command) { - Debug.Assert(_sampleCount == 160 || _sampleCount == 240); + Debug.Assert(_sampleCount is 160 or 240); if (_sampleCount == 160) { @@ -234,7 +234,7 @@ namespace Ryujinx.Audio.Renderer.Server public uint Estimate(ReverbCommand command) { - Debug.Assert(_sampleCount == 160 || _sampleCount == 240); + Debug.Assert(_sampleCount is 160 or 240); if (_sampleCount == 160) { @@ -285,7 +285,7 @@ namespace Ryujinx.Audio.Renderer.Server public uint Estimate(Reverb3dCommand command) { - Debug.Assert(_sampleCount == 160 || _sampleCount == 240); + Debug.Assert(_sampleCount is 160 or 240); if (_sampleCount == 160) { @@ -335,7 +335,7 @@ namespace Ryujinx.Audio.Renderer.Server public uint Estimate(AuxiliaryBufferCommand command) { - Debug.Assert(_sampleCount == 160 || _sampleCount == 240); + Debug.Assert(_sampleCount is 160 or 240); if (_sampleCount == 160) { @@ -357,7 +357,7 @@ namespace Ryujinx.Audio.Renderer.Server public uint Estimate(VolumeCommand command) { - Debug.Assert(_sampleCount == 160 || _sampleCount == 240); + Debug.Assert(_sampleCount is 160 or 240); if (_sampleCount == 160) { @@ -369,7 +369,7 @@ namespace Ryujinx.Audio.Renderer.Server public uint Estimate(CircularBufferSinkCommand command) { - Debug.Assert(_sampleCount == 160 || _sampleCount == 240); + Debug.Assert(_sampleCount is 160 or 240); float costPerBuffer = 1726.0f; float baseCost = 1369.7f; @@ -385,7 +385,7 @@ namespace Ryujinx.Audio.Renderer.Server public uint Estimate(DownMixSurroundToStereoCommand command) { - Debug.Assert(_sampleCount == 160 || _sampleCount == 240); + Debug.Assert(_sampleCount is 160 or 240); if (_sampleCount == 160) { @@ -397,7 +397,7 @@ namespace Ryujinx.Audio.Renderer.Server public uint Estimate(UpsampleCommand command) { - Debug.Assert(_sampleCount == 160 || _sampleCount == 240); + Debug.Assert(_sampleCount is 160 or 240); if (_sampleCount == 160) { @@ -409,8 +409,8 @@ namespace Ryujinx.Audio.Renderer.Server public uint Estimate(DeviceSinkCommand command) { - Debug.Assert(_sampleCount == 160 || _sampleCount == 240); - Debug.Assert(command.InputCount == 2 || command.InputCount == 6); + Debug.Assert(_sampleCount is 160 or 240); + Debug.Assert(command.InputCount is 2 or 6); if (command.InputCount == 2) { @@ -433,7 +433,7 @@ namespace Ryujinx.Audio.Renderer.Server public uint Estimate(PcmFloatDataSourceCommandVersion1 command) { // NOTE: This was added between REV7 and REV8 and for some reasons the estimator v2 was changed... - Debug.Assert(_sampleCount == 160 || _sampleCount == 240); + Debug.Assert(_sampleCount is 160 or 240); float costPerSample = 3490.9f; float baseCost = 10091.0f; diff --git a/src/Ryujinx.Audio/Renderer/Server/CommandProcessingTimeEstimatorVersion3.cs b/src/Ryujinx.Audio/Renderer/Server/CommandProcessingTimeEstimatorVersion3.cs index 31a5347b4..85e016019 100644 --- a/src/Ryujinx.Audio/Renderer/Server/CommandProcessingTimeEstimatorVersion3.cs +++ b/src/Ryujinx.Audio/Renderer/Server/CommandProcessingTimeEstimatorVersion3.cs @@ -23,7 +23,7 @@ namespace Ryujinx.Audio.Renderer.Server public uint Estimate(PerformanceCommand command) { - Debug.Assert(SampleCount == 160 || SampleCount == 240); + Debug.Assert(SampleCount is 160 or 240); if (SampleCount == 160) { @@ -35,7 +35,7 @@ namespace Ryujinx.Audio.Renderer.Server public uint Estimate(ClearMixBufferCommand command) { - Debug.Assert(SampleCount == 160 || SampleCount == 240); + Debug.Assert(SampleCount is 160 or 240); float costPerBuffer = 440.68f; float baseCost = 0; @@ -50,7 +50,7 @@ namespace Ryujinx.Audio.Renderer.Server public uint Estimate(BiquadFilterCommand command) { - Debug.Assert(SampleCount == 160 || SampleCount == 240); + Debug.Assert(SampleCount is 160 or 240); if (SampleCount == 160) { @@ -64,7 +64,7 @@ namespace Ryujinx.Audio.Renderer.Server { float costPerSample = 6.4434f; - Debug.Assert(SampleCount == 160 || SampleCount == 240); + Debug.Assert(SampleCount is 160 or 240); if (SampleCount == 160) { @@ -86,7 +86,7 @@ namespace Ryujinx.Audio.Renderer.Server public uint Estimate(MixRampCommand command) { - Debug.Assert(SampleCount == 160 || SampleCount == 240); + Debug.Assert(SampleCount is 160 or 240); if (SampleCount == 160) { @@ -103,7 +103,7 @@ namespace Ryujinx.Audio.Renderer.Server public uint Estimate(VolumeRampCommand command) { - Debug.Assert(SampleCount == 160 || SampleCount == 240); + Debug.Assert(SampleCount is 160 or 240); if (SampleCount == 160) { @@ -115,7 +115,7 @@ namespace Ryujinx.Audio.Renderer.Server public uint Estimate(PcmInt16DataSourceCommandVersion1 command) { - Debug.Assert(SampleCount == 160 || SampleCount == 240); + Debug.Assert(SampleCount is 160 or 240); float costPerSample = 710.143f; float baseCost = 7853.286f; @@ -131,7 +131,7 @@ namespace Ryujinx.Audio.Renderer.Server public uint Estimate(AdpcmDataSourceCommandVersion1 command) { - Debug.Assert(SampleCount == 160 || SampleCount == 240); + Debug.Assert(SampleCount is 160 or 240); float costPerSample = 3564.1f; float baseCost = 9736.702f; @@ -147,7 +147,7 @@ namespace Ryujinx.Audio.Renderer.Server public uint Estimate(DepopForMixBuffersCommand command) { - Debug.Assert(SampleCount == 160 || SampleCount == 240); + Debug.Assert(SampleCount is 160 or 240); if (SampleCount == 160) { @@ -159,7 +159,7 @@ namespace Ryujinx.Audio.Renderer.Server public uint Estimate(CopyMixBufferCommand command) { - Debug.Assert(SampleCount == 160 || SampleCount == 240); + Debug.Assert(SampleCount is 160 or 240); if (SampleCount == 160) { @@ -171,7 +171,7 @@ namespace Ryujinx.Audio.Renderer.Server public uint Estimate(MixCommand command) { - Debug.Assert(SampleCount == 160 || SampleCount == 240); + Debug.Assert(SampleCount is 160 or 240); if (SampleCount == 160) { @@ -183,7 +183,7 @@ namespace Ryujinx.Audio.Renderer.Server public virtual uint Estimate(DelayCommand command) { - Debug.Assert(SampleCount == 160 || SampleCount == 240); + Debug.Assert(SampleCount is 160 or 240); if (SampleCount == 160) { @@ -233,7 +233,7 @@ namespace Ryujinx.Audio.Renderer.Server public virtual uint Estimate(ReverbCommand command) { - Debug.Assert(SampleCount == 160 || SampleCount == 240); + Debug.Assert(SampleCount is 160 or 240); if (SampleCount == 160) { @@ -283,7 +283,7 @@ namespace Ryujinx.Audio.Renderer.Server public virtual uint Estimate(Reverb3dCommand command) { - Debug.Assert(SampleCount == 160 || SampleCount == 240); + Debug.Assert(SampleCount is 160 or 240); if (SampleCount == 160) { @@ -333,7 +333,7 @@ namespace Ryujinx.Audio.Renderer.Server public uint Estimate(AuxiliaryBufferCommand command) { - Debug.Assert(SampleCount == 160 || SampleCount == 240); + Debug.Assert(SampleCount is 160 or 240); if (SampleCount == 160) { @@ -355,7 +355,7 @@ namespace Ryujinx.Audio.Renderer.Server public uint Estimate(VolumeCommand command) { - Debug.Assert(SampleCount == 160 || SampleCount == 240); + Debug.Assert(SampleCount is 160 or 240); if (SampleCount == 160) { @@ -367,7 +367,7 @@ namespace Ryujinx.Audio.Renderer.Server public uint Estimate(CircularBufferSinkCommand command) { - Debug.Assert(SampleCount == 160 || SampleCount == 240); + Debug.Assert(SampleCount is 160 or 240); float costPerBuffer = 770.26f; float baseCost = 0f; @@ -382,7 +382,7 @@ namespace Ryujinx.Audio.Renderer.Server public uint Estimate(DownMixSurroundToStereoCommand command) { - Debug.Assert(SampleCount == 160 || SampleCount == 240); + Debug.Assert(SampleCount is 160 or 240); if (SampleCount == 160) { @@ -394,7 +394,7 @@ namespace Ryujinx.Audio.Renderer.Server public uint Estimate(UpsampleCommand command) { - Debug.Assert(SampleCount == 160 || SampleCount == 240); + Debug.Assert(SampleCount is 160 or 240); if (SampleCount == 160) { @@ -406,8 +406,8 @@ namespace Ryujinx.Audio.Renderer.Server public uint Estimate(DeviceSinkCommand command) { - Debug.Assert(SampleCount == 160 || SampleCount == 240); - Debug.Assert(command.InputCount == 2 || command.InputCount == 6); + Debug.Assert(SampleCount is 160 or 240); + Debug.Assert(command.InputCount is 2 or 6); if (command.InputCount == 2) { @@ -429,7 +429,7 @@ namespace Ryujinx.Audio.Renderer.Server public uint Estimate(PcmFloatDataSourceCommandVersion1 command) { - Debug.Assert(SampleCount == 160 || SampleCount == 240); + Debug.Assert(SampleCount is 160 or 240); float costPerSample = 3490.9f; float baseCost = 10090.9f; @@ -445,7 +445,7 @@ namespace Ryujinx.Audio.Renderer.Server public uint Estimate(DataSourceVersion2Command command) { - Debug.Assert(SampleCount == 160 || SampleCount == 240); + Debug.Assert(SampleCount is 160 or 240); (float baseCost, float costPerSample) = GetCostByFormat(SampleCount, command.SampleFormat, command.SrcQuality); @@ -454,7 +454,7 @@ namespace Ryujinx.Audio.Renderer.Server private static (float, float) GetCostByFormat(uint sampleCount, SampleFormat format, SampleRateConversionQuality quality) { - Debug.Assert(sampleCount == 160 || sampleCount == 240); + Debug.Assert(sampleCount is 160 or 240); switch (format) { @@ -546,7 +546,7 @@ namespace Ryujinx.Audio.Renderer.Server private uint EstimateLimiterCommandCommon(LimiterParameter parameter, bool enabled) { - Debug.Assert(SampleCount == 160 || SampleCount == 240); + Debug.Assert(SampleCount is 160 or 240); if (SampleCount == 160) { @@ -596,14 +596,14 @@ namespace Ryujinx.Audio.Renderer.Server public uint Estimate(LimiterCommandVersion1 command) { - Debug.Assert(SampleCount == 160 || SampleCount == 240); + Debug.Assert(SampleCount is 160 or 240); return EstimateLimiterCommandCommon(command.Parameter, command.IsEffectEnabled); } public uint Estimate(LimiterCommandVersion2 command) { - Debug.Assert(SampleCount == 160 || SampleCount == 240); + Debug.Assert(SampleCount is 160 or 240); if (!command.Parameter.StatisticsEnabled || !command.IsEffectEnabled) { diff --git a/src/Ryujinx.Audio/Renderer/Server/CommandProcessingTimeEstimatorVersion4.cs b/src/Ryujinx.Audio/Renderer/Server/CommandProcessingTimeEstimatorVersion4.cs index fb357120d..3cb04e385 100644 --- a/src/Ryujinx.Audio/Renderer/Server/CommandProcessingTimeEstimatorVersion4.cs +++ b/src/Ryujinx.Audio/Renderer/Server/CommandProcessingTimeEstimatorVersion4.cs @@ -12,7 +12,7 @@ namespace Ryujinx.Audio.Renderer.Server public override uint Estimate(MultiTapBiquadFilterCommand command) { - Debug.Assert(SampleCount == 160 || SampleCount == 240); + Debug.Assert(SampleCount is 160 or 240); if (SampleCount == 160) { @@ -24,7 +24,7 @@ namespace Ryujinx.Audio.Renderer.Server public override uint Estimate(CaptureBufferCommand command) { - Debug.Assert(SampleCount == 160 || SampleCount == 240); + Debug.Assert(SampleCount is 160 or 240); if (SampleCount == 160) { diff --git a/src/Ryujinx.Audio/Renderer/Server/CommandProcessingTimeEstimatorVersion5.cs b/src/Ryujinx.Audio/Renderer/Server/CommandProcessingTimeEstimatorVersion5.cs index bc9ba073d..fe6103f2b 100644 --- a/src/Ryujinx.Audio/Renderer/Server/CommandProcessingTimeEstimatorVersion5.cs +++ b/src/Ryujinx.Audio/Renderer/Server/CommandProcessingTimeEstimatorVersion5.cs @@ -13,7 +13,7 @@ namespace Ryujinx.Audio.Renderer.Server public override uint Estimate(DelayCommand command) { - Debug.Assert(SampleCount == 160 || SampleCount == 240); + Debug.Assert(SampleCount is 160 or 240); if (SampleCount == 160) { @@ -63,7 +63,7 @@ namespace Ryujinx.Audio.Renderer.Server public override uint Estimate(ReverbCommand command) { - Debug.Assert(SampleCount == 160 || SampleCount == 240); + Debug.Assert(SampleCount is 160 or 240); if (SampleCount == 160) { @@ -113,7 +113,7 @@ namespace Ryujinx.Audio.Renderer.Server public override uint Estimate(Reverb3dCommand command) { - Debug.Assert(SampleCount == 160 || SampleCount == 240); + Debug.Assert(SampleCount is 160 or 240); if (SampleCount == 160) { @@ -163,7 +163,7 @@ namespace Ryujinx.Audio.Renderer.Server public override uint Estimate(CompressorCommand command) { - Debug.Assert(SampleCount == 160 || SampleCount == 240); + Debug.Assert(SampleCount is 160 or 240); if (SampleCount == 160) { @@ -241,7 +241,7 @@ namespace Ryujinx.Audio.Renderer.Server public override uint Estimate(BiquadFilterAndMixCommand command) { - Debug.Assert(SampleCount == 160 || SampleCount == 240); + Debug.Assert(SampleCount is 160 or 240); if (command.HasVolumeRamp) { @@ -265,7 +265,7 @@ namespace Ryujinx.Audio.Renderer.Server public override uint Estimate(MultiTapBiquadFilterAndMixCommand command) { - Debug.Assert(SampleCount == 160 || SampleCount == 240); + Debug.Assert(SampleCount is 160 or 240); if (command.HasVolumeRamp) { diff --git a/src/Ryujinx.Audio/Renderer/Server/MemoryPool/PoolMapper.cs b/src/Ryujinx.Audio/Renderer/Server/MemoryPool/PoolMapper.cs index f67d0c124..535e2fd79 100644 --- a/src/Ryujinx.Audio/Renderer/Server/MemoryPool/PoolMapper.cs +++ b/src/Ryujinx.Audio/Renderer/Server/MemoryPool/PoolMapper.cs @@ -257,7 +257,7 @@ namespace Ryujinx.Audio.Renderer.Server.MemoryPool const uint PageSize = 0x1000; - if (inputState != MemoryPoolUserState.RequestAttach && inputState != MemoryPoolUserState.RequestDetach) + if (inputState is not MemoryPoolUserState.RequestAttach and not MemoryPoolUserState.RequestDetach) { return UpdateResult.Success; } diff --git a/src/Ryujinx.Audio/Renderer/Server/Splitter/SplitterDestinationVersion1.cs b/src/Ryujinx.Audio/Renderer/Server/Splitter/SplitterDestinationVersion1.cs index ce8f33685..5b5242f0d 100644 --- a/src/Ryujinx.Audio/Renderer/Server/Splitter/SplitterDestinationVersion1.cs +++ b/src/Ryujinx.Audio/Renderer/Server/Splitter/SplitterDestinationVersion1.cs @@ -153,7 +153,7 @@ namespace Ryujinx.Audio.Renderer.Server.Splitter /// The volume for the given destination. public float GetMixVolume(int destinationIndex) { - Debug.Assert(destinationIndex >= 0 && destinationIndex < Constants.MixBufferCountMax); + Debug.Assert(destinationIndex is >= 0 and < Constants.MixBufferCountMax); return MixBufferVolume[destinationIndex]; } @@ -165,7 +165,7 @@ namespace Ryujinx.Audio.Renderer.Server.Splitter /// The volume for the given destination. public float GetMixVolumePrev(int destinationIndex) { - Debug.Assert(destinationIndex >= 0 && destinationIndex < Constants.MixBufferCountMax); + Debug.Assert(destinationIndex is >= 0 and < Constants.MixBufferCountMax); return PreviousMixBufferVolume[destinationIndex]; } diff --git a/src/Ryujinx.Audio/Renderer/Server/Splitter/SplitterDestinationVersion2.cs b/src/Ryujinx.Audio/Renderer/Server/Splitter/SplitterDestinationVersion2.cs index 5f96ef3aa..1a4a38e44 100644 --- a/src/Ryujinx.Audio/Renderer/Server/Splitter/SplitterDestinationVersion2.cs +++ b/src/Ryujinx.Audio/Renderer/Server/Splitter/SplitterDestinationVersion2.cs @@ -160,7 +160,7 @@ namespace Ryujinx.Audio.Renderer.Server.Splitter /// The volume for the given destination. public float GetMixVolume(int destinationIndex) { - Debug.Assert(destinationIndex >= 0 && destinationIndex < Constants.MixBufferCountMax); + Debug.Assert(destinationIndex is >= 0 and < Constants.MixBufferCountMax); return MixBufferVolume[destinationIndex]; } @@ -172,7 +172,7 @@ namespace Ryujinx.Audio.Renderer.Server.Splitter /// The volume for the given destination. public float GetMixVolumePrev(int destinationIndex) { - Debug.Assert(destinationIndex >= 0 && destinationIndex < Constants.MixBufferCountMax); + Debug.Assert(destinationIndex is >= 0 and < Constants.MixBufferCountMax); return PreviousMixBufferVolume[destinationIndex]; } diff --git a/src/Ryujinx.Audio/Renderer/Server/StateUpdater.cs b/src/Ryujinx.Audio/Renderer/Server/StateUpdater.cs index f8d87f2d1..9c4d1243a 100644 --- a/src/Ryujinx.Audio/Renderer/Server/StateUpdater.cs +++ b/src/Ryujinx.Audio/Renderer/Server/StateUpdater.cs @@ -86,9 +86,9 @@ namespace Ryujinx.Audio.Renderer.Server PoolMapper.UpdateResult updateResult = mapper.Update(ref memoryPool, in parameter, ref outStatus); - if (updateResult != PoolMapper.UpdateResult.Success && - updateResult != PoolMapper.UpdateResult.MapError && - updateResult != PoolMapper.UpdateResult.UnmapError) + if (updateResult is not PoolMapper.UpdateResult.Success and + not PoolMapper.UpdateResult.MapError and + not PoolMapper.UpdateResult.UnmapError) { if (updateResult != PoolMapper.UpdateResult.InvalidParameter) { diff --git a/src/Ryujinx.Audio/Renderer/Server/Voice/WaveBuffer.cs b/src/Ryujinx.Audio/Renderer/Server/Voice/WaveBuffer.cs index a9946ba44..1c76e7280 100644 --- a/src/Ryujinx.Audio/Renderer/Server/Voice/WaveBuffer.cs +++ b/src/Ryujinx.Audio/Renderer/Server/Voice/WaveBuffer.cs @@ -20,7 +20,6 @@ namespace Ryujinx.Audio.Renderer.Server.Voice /// Only used by . public AddressInfo ContextAddressInfo; - /// /// First sample to play of the wavebuffer. /// diff --git a/src/Ryujinx.BuildValidationTasks/LocalesValidationTask.cs b/src/Ryujinx.BuildValidationTasks/LocalesValidationTask.cs index bc2131035..17f9be5a0 100644 --- a/src/Ryujinx.BuildValidationTasks/LocalesValidationTask.cs +++ b/src/Ryujinx.BuildValidationTasks/LocalesValidationTask.cs @@ -1,14 +1,21 @@ using System; using System.Collections.Generic; -using System.Linq; using System.IO; -using System.Text.Json; +using System.Linq; using System.Text.Encodings.Web; +using System.Text.Json; namespace Ryujinx.BuildValidationTasks { public class LocalesValidationTask : IValidationTask { + static readonly JsonSerializerOptions _jsonOptions = new() + { + WriteIndented = true, + NewLine = "\n", + Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping + }; + public LocalesValidationTask() { } public bool Execute(string projectPath, bool isGitRunner) @@ -38,8 +45,6 @@ namespace Ryujinx.BuildValidationTasks throw new JsonException(e.Message); //shorter and easier stacktrace } - - bool encounteredIssue = false; for (int i = 0; i < json.Locales.Count; i++) @@ -83,14 +88,7 @@ namespace Ryujinx.BuildValidationTasks if (isGitRunner && encounteredIssue) throw new JsonException("1 or more locales are invalid!"); - JsonSerializerOptions jsonOptions = new() - { - WriteIndented = true, - NewLine = "\n", - Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping - }; - - string jsonString = JsonSerializer.Serialize(json, jsonOptions); + string jsonString = JsonSerializer.Serialize(json, _jsonOptions); using (StreamWriter sw = new(path)) { diff --git a/src/Ryujinx.Common/Collections/IntervalTree.cs b/src/Ryujinx.Common/Collections/IntervalTree.cs index 695487dda..27503c5b7 100644 --- a/src/Ryujinx.Common/Collections/IntervalTree.cs +++ b/src/Ryujinx.Common/Collections/IntervalTree.cs @@ -122,7 +122,7 @@ namespace Ryujinx.Common.Collections /// /// The node to search for RangeNodes within /// The list to add RangeNodes to - private void AddToList(IntervalTreeNode node, List> list) + private static void AddToList(IntervalTreeNode node, List> list) { if (node == null) { @@ -163,6 +163,7 @@ namespace Ryujinx.Common.Collections return node; } } + return null; } @@ -173,7 +174,7 @@ namespace Ryujinx.Common.Collections /// End of the range /// Overlaps array to place results in /// Overlaps count to update - private void GetValues(IntervalTreeNode node, TKey start, TKey end, ref TValue[] overlaps, ref int overlapCount) + private static void GetValues(IntervalTreeNode node, TKey start, TKey end, ref TValue[] overlaps, ref int overlapCount) { if (node == null || start.CompareTo(node.Max) >= 0) { @@ -313,6 +314,7 @@ namespace Ryujinx.Common.Collections return node; } } + IntervalTreeNode newNode = new(start, end, value, parent); if (newNode.Parent == null) { diff --git a/src/Ryujinx.Common/Collections/IntrusiveRedBlackTree.cs b/src/Ryujinx.Common/Collections/IntrusiveRedBlackTree.cs index 9e56f707b..423cd22c8 100644 --- a/src/Ryujinx.Common/Collections/IntrusiveRedBlackTree.cs +++ b/src/Ryujinx.Common/Collections/IntrusiveRedBlackTree.cs @@ -64,6 +64,7 @@ namespace Ryujinx.Common.Collections return node; } } + return null; } @@ -112,6 +113,7 @@ namespace Ryujinx.Common.Collections return node; } } + newNode.Parent = parent; if (parent == null) { @@ -125,6 +127,7 @@ namespace Ryujinx.Common.Collections { parent.Right = newNode; } + Count++; return newNode; } @@ -274,6 +277,7 @@ namespace Ryujinx.Common.Collections return node; } } + return null; } } diff --git a/src/Ryujinx.Common/Collections/IntrusiveRedBlackTreeImpl.cs b/src/Ryujinx.Common/Collections/IntrusiveRedBlackTreeImpl.cs index 49f97223a..abd3723fe 100644 --- a/src/Ryujinx.Common/Collections/IntrusiveRedBlackTreeImpl.cs +++ b/src/Ryujinx.Common/Collections/IntrusiveRedBlackTreeImpl.cs @@ -39,12 +39,14 @@ namespace Ryujinx.Common.Collections { return Minimum(node.Right); } + T parent = node.Parent; while (parent != null && node == parent.Right) { node = parent; parent = parent.Parent; } + return parent; } @@ -59,12 +61,14 @@ namespace Ryujinx.Common.Collections { return Maximum(node.Left); } + T parent = node.Parent; while (parent != null && node == parent.Left) { node = parent; parent = parent.Parent; } + return parent; } @@ -120,6 +124,7 @@ namespace Ryujinx.Common.Collections RotateLeft(ParentOf(ptr)); sibling = RightOf(ParentOf(ptr)); } + if (ColorOf(LeftOf(sibling)) == Black && ColorOf(RightOf(sibling)) == Black) { SetColor(sibling, Red); @@ -134,6 +139,7 @@ namespace Ryujinx.Common.Collections RotateRight(sibling); sibling = RightOf(ParentOf(ptr)); } + SetColor(sibling, ColorOf(ParentOf(ptr))); SetColor(ParentOf(ptr), Black); SetColor(RightOf(sibling), Black); @@ -152,6 +158,7 @@ namespace Ryujinx.Common.Collections RotateRight(ParentOf(ptr)); sibling = LeftOf(ParentOf(ptr)); } + if (ColorOf(RightOf(sibling)) == Black && ColorOf(LeftOf(sibling)) == Black) { SetColor(sibling, Red); @@ -166,6 +173,7 @@ namespace Ryujinx.Common.Collections RotateLeft(sibling); sibling = LeftOf(ParentOf(ptr)); } + SetColor(sibling, ColorOf(ParentOf(ptr))); SetColor(ParentOf(ptr), Black); SetColor(LeftOf(sibling), Black); @@ -174,6 +182,7 @@ namespace Ryujinx.Common.Collections } } } + SetColor(ptr, Black); } @@ -200,6 +209,7 @@ namespace Ryujinx.Common.Collections balanceNode = ParentOf(balanceNode); RotateLeft(balanceNode); } + SetColor(ParentOf(balanceNode), Black); SetColor(ParentOf(ParentOf(balanceNode)), Red); RotateRight(ParentOf(ParentOf(balanceNode))); @@ -223,12 +233,14 @@ namespace Ryujinx.Common.Collections balanceNode = ParentOf(balanceNode); RotateRight(balanceNode); } + SetColor(ParentOf(balanceNode), Black); SetColor(ParentOf(ParentOf(balanceNode)), Red); RotateLeft(ParentOf(ParentOf(balanceNode))); } } } + SetColor(Root, Black); } @@ -242,6 +254,7 @@ namespace Ryujinx.Common.Collections { node.Right.Parent = node; } + T nodeParent = ParentOf(node); right.Parent = nodeParent; if (nodeParent == null) @@ -256,6 +269,7 @@ namespace Ryujinx.Common.Collections { nodeParent.Right = right; } + right.Left = node; node.Parent = right; } @@ -271,6 +285,7 @@ namespace Ryujinx.Common.Collections { node.Left.Parent = node; } + T nodeParent = ParentOf(node); left.Parent = nodeParent; if (nodeParent == null) @@ -285,6 +300,7 @@ namespace Ryujinx.Common.Collections { nodeParent.Left = left; } + left.Right = node; node.Parent = left; } diff --git a/src/Ryujinx.Common/Collections/TreeDictionary.cs b/src/Ryujinx.Common/Collections/TreeDictionary.cs index 18f48188a..af104d268 100644 --- a/src/Ryujinx.Common/Collections/TreeDictionary.cs +++ b/src/Ryujinx.Common/Collections/TreeDictionary.cs @@ -78,6 +78,7 @@ namespace Ryujinx.Common.Collections { return node.Key; } + return default; } @@ -94,6 +95,7 @@ namespace Ryujinx.Common.Collections { return node.Key; } + return default; } @@ -111,6 +113,7 @@ namespace Ryujinx.Common.Collections return successor != null ? successor.Key : default; } + return default; } @@ -128,6 +131,7 @@ namespace Ryujinx.Common.Collections return predecessor != null ? predecessor.Key : default; } + return default; } @@ -147,6 +151,7 @@ namespace Ryujinx.Common.Collections { nodes.Enqueue(this.Root); } + while (nodes.TryDequeue(out Node node)) { list.Add(new KeyValuePair(node.Key, node.Value)); @@ -154,11 +159,13 @@ namespace Ryujinx.Common.Collections { nodes.Enqueue(node.Left); } + if (node.Right != null) { nodes.Enqueue(node.Right); } } + return list; } @@ -184,7 +191,7 @@ namespace Ryujinx.Common.Collections /// /// The node to search for nodes within /// The list to add node to - private void AddToList(Node node, List> list) + private static void AddToList(Node node, List> list) { if (node == null) { @@ -225,6 +232,7 @@ namespace Ryujinx.Common.Collections return node; } } + return null; } @@ -274,6 +282,7 @@ namespace Ryujinx.Common.Collections return node; } } + Node newNode = new(key, value, parent); if (newNode.Parent == null) { @@ -287,6 +296,7 @@ namespace Ryujinx.Common.Collections { parent.Right = newNode; } + Count++; return newNode; } @@ -392,6 +402,7 @@ namespace Ryujinx.Common.Collections ptr = parent; parent = parent.Parent; } + return parent; } } @@ -400,6 +411,7 @@ namespace Ryujinx.Common.Collections return tmp; } } + return null; } @@ -444,6 +456,7 @@ namespace Ryujinx.Common.Collections ptr = parent; parent = parent.Parent; } + return parent; } } @@ -452,6 +465,7 @@ namespace Ryujinx.Common.Collections return tmp; } } + return null; } @@ -502,6 +516,7 @@ namespace Ryujinx.Common.Collections { return node.Key.Equals(item.Key) && node.Value.Equals(item.Value); } + return false; } @@ -588,6 +603,7 @@ namespace Ryujinx.Common.Collections { queue.Enqueue(node.Left); } + if (null != node.Right) { queue.Enqueue(node.Right); diff --git a/src/Ryujinx.Common/Configuration/AppDataManager.cs b/src/Ryujinx.Common/Configuration/AppDataManager.cs index ca8e389ba..cb26be2d5 100644 --- a/src/Ryujinx.Common/Configuration/AppDataManager.cs +++ b/src/Ryujinx.Common/Configuration/AppDataManager.cs @@ -280,6 +280,7 @@ namespace Ryujinx.Common.Configuration { Logger.Error?.Print(LogClass.Application, $"Unable to resolve the symlink for Ryujinx application data: {symlinkException}. Follow the symlink at {correctApplicationDataDirectoryPath} and move your data back to the Application Support folder."); } + return; } @@ -304,6 +305,7 @@ namespace Ryujinx.Common.Configuration { Logger.Error?.Print(LogClass.Application, $"Unable to resolve the symlink for Ryujinx application data: {symlinkException}. Follow the symlink at {correctApplicationDataDirectoryPath} and move your data back to the Application Support folder."); } + return; } diff --git a/src/Ryujinx.Common/Configuration/AspectRatioExtensions.cs b/src/Ryujinx.Common/Configuration/AspectRatioExtensions.cs index 05dbe67d9..f3a9e1646 100644 --- a/src/Ryujinx.Common/Configuration/AspectRatioExtensions.cs +++ b/src/Ryujinx.Common/Configuration/AspectRatioExtensions.cs @@ -35,8 +35,8 @@ namespace Ryujinx.Common.Configuration #pragma warning restore IDE0055 }; } - - + + public static float ToFloatY(this AspectRatio aspectRatio) { diff --git a/src/Ryujinx.Common/Configuration/DirtyHack.cs b/src/Ryujinx.Common/Configuration/DirtyHack.cs index 71ac88f56..ae3416a27 100644 --- a/src/Ryujinx.Common/Configuration/DirtyHack.cs +++ b/src/Ryujinx.Common/Configuration/DirtyHack.cs @@ -1,4 +1,4 @@ -using Gommon; +using Gommon; using System; using System.Collections.Generic; using System.Linq; @@ -17,9 +17,9 @@ namespace Ryujinx.Common.Configuration { public DirtyHack Hack => hack; public int Value => value; - - - + + + public ulong Pack() => Raw.PackBitFields(PackedFormat); public static EnabledDirtyHack Unpack(ulong packedHack) @@ -28,26 +28,26 @@ namespace Ryujinx.Common.Configuration // ReSharper disable once PatternAlwaysMatches if (unpackedFields is not [uint hack, uint value]) throw new Exception("The unpack operation on the integer resulted in an invalid unpacked result."); - + return new EnabledDirtyHack((DirtyHack)hack, (int)value); } - + private uint[] Raw => [(uint)Hack, (uint)Value.CoerceAtLeast(0)]; - + public static readonly byte[] PackedFormat = [8, 32]; } public class DirtyHacks : Dictionary { - public DirtyHacks(IEnumerable hacks) + public DirtyHacks(IEnumerable hacks) => hacks.ForEach(edh => Add(edh.Hack, edh.Value)); - public DirtyHacks(ulong[] packedHacks) : this(packedHacks.Select(EnabledDirtyHack.Unpack)) {} + public DirtyHacks(ulong[] packedHacks) : this(packedHacks.Select(EnabledDirtyHack.Unpack)) { } - public ulong[] PackEntries() + public ulong[] PackEntries() => Entries.Select(it => it.Pack()).ToArray(); - - public EnabledDirtyHack[] Entries + + public EnabledDirtyHack[] Entries => this .Select(it => new EnabledDirtyHack(it.Key, it.Value)) .ToArray(); diff --git a/src/Ryujinx.Common/Configuration/Hid/Controller/GenericControllerInputConfig.cs b/src/Ryujinx.Common/Configuration/Hid/Controller/GenericControllerInputConfig.cs index fbb19767c..c99da6f4a 100644 --- a/src/Ryujinx.Common/Configuration/Hid/Controller/GenericControllerInputConfig.cs +++ b/src/Ryujinx.Common/Configuration/Hid/Controller/GenericControllerInputConfig.cs @@ -78,7 +78,7 @@ namespace Ryujinx.Common.Configuration.Hid.Controller /// Controller Rumble Settings /// public RumbleConfigController Rumble { get; set; } - + /// /// Controller LED Settings /// diff --git a/src/Ryujinx.Common/Configuration/Hid/Controller/JoyconConfigControllerStick.cs b/src/Ryujinx.Common/Configuration/Hid/Controller/JoyconConfigControllerStick.cs index 076530744..70af4071d 100644 --- a/src/Ryujinx.Common/Configuration/Hid/Controller/JoyconConfigControllerStick.cs +++ b/src/Ryujinx.Common/Configuration/Hid/Controller/JoyconConfigControllerStick.cs @@ -1,7 +1,7 @@ namespace Ryujinx.Common.Configuration.Hid.Controller { - public class JoyconConfigControllerStick - where TButton : unmanaged + public class JoyconConfigControllerStick + where TButton : unmanaged where TStick : unmanaged { public TStick Joystick { get; set; } diff --git a/src/Ryujinx.Common/Configuration/Hid/Controller/LedConfigController.cs b/src/Ryujinx.Common/Configuration/Hid/Controller/LedConfigController.cs index 93b75d32c..5edeff0ac 100644 --- a/src/Ryujinx.Common/Configuration/Hid/Controller/LedConfigController.cs +++ b/src/Ryujinx.Common/Configuration/Hid/Controller/LedConfigController.cs @@ -1,4 +1,4 @@ -namespace Ryujinx.Common.Configuration.Hid.Controller +namespace Ryujinx.Common.Configuration.Hid.Controller { public class LedConfigController { @@ -6,17 +6,17 @@ /// Enable LED color changing by the emulator /// public bool EnableLed { get; set; } - + /// /// Ignores the color and disables the LED entirely. /// public bool TurnOffLed { get; set; } - + /// /// Ignores the color and uses the rainbow color functionality for the LED. /// public bool UseRainbow { get; set; } - + /// /// Packed RGB int of the color /// diff --git a/src/Ryujinx.Common/Configuration/VSyncMode.cs b/src/Ryujinx.Common/Configuration/VSyncMode.cs index e0bf2591f..21505bf2a 100644 --- a/src/Ryujinx.Common/Configuration/VSyncMode.cs +++ b/src/Ryujinx.Common/Configuration/VSyncMode.cs @@ -6,7 +6,7 @@ namespace Ryujinx.Common.Configuration Unbounded, Custom } - + public static class VSyncModeExtensions { public static VSyncMode Next(this VSyncMode vsync, bool customEnabled = false) => diff --git a/src/Ryujinx.Common/GraphicsDriver/NVAPI/NvapiUnicodeString.cs b/src/Ryujinx.Common/GraphicsDriver/NVAPI/NvapiUnicodeString.cs index f3e0ffd02..5b0992dce 100644 --- a/src/Ryujinx.Common/GraphicsDriver/NVAPI/NvapiUnicodeString.cs +++ b/src/Ryujinx.Common/GraphicsDriver/NVAPI/NvapiUnicodeString.cs @@ -22,7 +22,7 @@ namespace Ryujinx.Common.GraphicsDriver.NVAPI int index = text.IndexOf('\0'); if (index > -1) { - text = text.Remove(index); + text = text[..index]; } return text; diff --git a/src/Ryujinx.Common/Hash128.cs b/src/Ryujinx.Common/Hash128.cs index baee3e7d2..e95a15caa 100644 --- a/src/Ryujinx.Common/Hash128.cs +++ b/src/Ryujinx.Common/Hash128.cs @@ -528,7 +528,7 @@ namespace Ryujinx.Common private static Hash128 Xxh3Len1To3128b(ReadOnlySpan input, ReadOnlySpan secret, ulong seed) { - Debug.Assert(1 <= input.Length && input.Length <= 3); + Debug.Assert(input.Length is >= 1 and <= 3); byte c1 = input[0]; byte c2 = input[input.Length >> 1]; @@ -550,7 +550,7 @@ namespace Ryujinx.Common private static Hash128 Xxh3Len4To8128b(ReadOnlySpan input, ReadOnlySpan secret, ulong seed) { - Debug.Assert(4 <= input.Length && input.Length <= 8); + Debug.Assert(input.Length is >= 4 and <= 8); seed ^= BinaryPrimitives.ReverseEndianness((uint)seed) << 32; @@ -575,7 +575,7 @@ namespace Ryujinx.Common private static Hash128 Xxh3Len9To16128b(ReadOnlySpan input, ReadOnlySpan secret, ulong seed) { - Debug.Assert(9 <= input.Length && input.Length <= 16); + Debug.Assert(input.Length is >= 9 and <= 16); ulong bitFlipL = (BinaryPrimitives.ReadUInt64LittleEndian(secret[32..]) ^ BinaryPrimitives.ReadUInt64LittleEndian(secret[40..])) - seed; ulong bitFlipH = (BinaryPrimitives.ReadUInt64LittleEndian(secret[48..]) ^ BinaryPrimitives.ReadUInt64LittleEndian(secret[56..])) + seed; @@ -647,7 +647,7 @@ namespace Ryujinx.Common private static Hash128 Xxh3Len17To128128b(ReadOnlySpan input, ReadOnlySpan secret, ulong seed) { Debug.Assert(secret.Length >= SecretSizeMin); - Debug.Assert(16 < input.Length && input.Length <= 128); + Debug.Assert(input.Length is > 16 and <= 128); Hash128 acc = new() { @@ -663,10 +663,13 @@ namespace Ryujinx.Common { acc = Xxh128Mix32b(acc, input[48..], input[^64..], secret[96..], seed); } + acc = Xxh128Mix32b(acc, input[32..], input[^48..], secret[64..], seed); } + acc = Xxh128Mix32b(acc, input[16..], input[^32..], secret[32..], seed); } + acc = Xxh128Mix32b(acc, input, input[^16..], secret, seed); Hash128 h128 = new() @@ -683,7 +686,7 @@ namespace Ryujinx.Common private static Hash128 Xxh3Len129To240128b(ReadOnlySpan input, ReadOnlySpan secret, ulong seed) { Debug.Assert(secret.Length >= SecretSizeMin); - Debug.Assert(128 < input.Length && input.Length <= 240); + Debug.Assert(input.Length is > 128 and <= 240); Hash128 acc = new(); diff --git a/src/Ryujinx.Common/Helpers/ConsoleHelper.cs b/src/Ryujinx.Common/Helpers/ConsoleHelper.cs index 105c9881e..2b3c11b1e 100644 --- a/src/Ryujinx.Common/Helpers/ConsoleHelper.cs +++ b/src/Ryujinx.Common/Helpers/ConsoleHelper.cs @@ -19,7 +19,7 @@ namespace Ryujinx.Common.Helper [SupportedOSPlatform("windows")] [LibraryImport("user32")] private static partial nint GetForegroundWindow(); - + [SupportedOSPlatform("windows")] [LibraryImport("user32")] [return: MarshalAs(UnmanagedType.Bool)] diff --git a/src/Ryujinx.Common/Helpers/FileAssociationHelper.cs b/src/Ryujinx.Common/Helpers/FileAssociationHelper.cs index 6e14a796e..b61dd8ee2 100644 --- a/src/Ryujinx.Common/Helpers/FileAssociationHelper.cs +++ b/src/Ryujinx.Common/Helpers/FileAssociationHelper.cs @@ -23,7 +23,7 @@ namespace Ryujinx.Common.Helper public static partial void SHChangeNotify(uint wEventId, uint uFlags, nint dwItem1, nint dwItem2); public static bool IsTypeAssociationSupported => (OperatingSystem.IsLinux() || OperatingSystem.IsWindows()); - + public static bool AreMimeTypesRegistered { get @@ -92,21 +92,21 @@ namespace Ryujinx.Common.Helper [SupportedOSPlatform("windows")] private static bool AreMimeTypesRegisteredWindows() { - return _fileExtensions.Aggregate(false, + return _fileExtensions.Aggregate(false, (current, ext) => current | CheckRegistering(ext) ); - + static bool CheckRegistering(string ext) { RegistryKey key = Registry.CurrentUser.OpenSubKey(@$"Software\Classes\{ext}"); RegistryKey openCmd = key?.OpenSubKey(@"shell\open\command"); - + if (openCmd is null) { return false; } - + string keyValue = (string)openCmd.GetValue(string.Empty); return keyValue is not null && (keyValue.Contains("Ryujinx") || keyValue.Contains(AppDomain.CurrentDomain.FriendlyName)); @@ -116,7 +116,7 @@ namespace Ryujinx.Common.Helper [SupportedOSPlatform("windows")] private static bool InstallWindowsMimeTypes(bool uninstall = false) { - bool registered = _fileExtensions.Aggregate(false, + bool registered = _fileExtensions.Aggregate(false, (current, ext) => current | RegisterExtension(ext, uninstall) ); @@ -124,7 +124,7 @@ namespace Ryujinx.Common.Helper SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_FLUSH, nint.Zero, nint.Zero); return registered; - + static bool RegisterExtension(string ext, bool uninstall = false) { string keyString = @$"Software\Classes\{ext}"; @@ -136,6 +136,7 @@ namespace Ryujinx.Common.Helper { return true; } + Logger.Debug?.Print(LogClass.Application, $"Removing type association {ext}"); Registry.CurrentUser.DeleteSubKeyTree(keyString); Logger.Debug?.Print(LogClass.Application, $"Removed type association {ext}"); diff --git a/src/Ryujinx.Common/Helpers/Patterns.cs b/src/Ryujinx.Common/Helpers/Patterns.cs index 943debc3b..56b555f48 100644 --- a/src/Ryujinx.Common/Helpers/Patterns.cs +++ b/src/Ryujinx.Common/Helpers/Patterns.cs @@ -1,4 +1,4 @@ -using System.Text.RegularExpressions; +using System.Text.RegularExpressions; namespace Ryujinx.Common.Helper { diff --git a/src/Ryujinx.Common/Helpers/RefEvent.cs b/src/Ryujinx.Common/Helpers/RefEvent.cs index f339dfb7c..5487135ce 100644 --- a/src/Ryujinx.Common/Helpers/RefEvent.cs +++ b/src/Ryujinx.Common/Helpers/RefEvent.cs @@ -1,4 +1,4 @@ -using Gommon; +using Gommon; using System.Collections.Generic; using System.Threading; @@ -7,10 +7,10 @@ namespace Ryujinx.Common.Helper public class RefEvent { public delegate void Handler(ref T arg); - + private readonly Lock _subLock = new(); private readonly List _subscriptions = []; - + public bool HasSubscribers { get diff --git a/src/Ryujinx.Common/Helpers/RunningPlatform.cs b/src/Ryujinx.Common/Helpers/RunningPlatform.cs index 7ec2f18df..8bc7f65aa 100644 --- a/src/Ryujinx.Common/Helpers/RunningPlatform.cs +++ b/src/Ryujinx.Common/Helpers/RunningPlatform.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Runtime.InteropServices; // ReSharper disable MemberCanBePrivate.Global // ReSharper disable InconsistentNaming @@ -9,14 +9,14 @@ namespace Ryujinx.Common.Helper { MacOS, Linux, - Windows + Windows } - + public static class RunningPlatform { - public static readonly OperatingSystemType CurrentOS - = IsMacOS - ? OperatingSystemType.MacOS + public static readonly OperatingSystemType CurrentOS + = IsMacOS + ? OperatingSystemType.MacOS : IsWindows ? OperatingSystemType.Windows : IsLinux @@ -25,21 +25,21 @@ namespace Ryujinx.Common.Helper public static Architecture Architecture => RuntimeInformation.OSArchitecture; public static Architecture CurrentProcessArchitecture => RuntimeInformation.ProcessArchitecture; - + public static bool IsMacOS => OperatingSystem.IsMacOS(); public static bool IsWindows => OperatingSystem.IsWindows(); public static bool IsLinux => OperatingSystem.IsLinux(); - + public static bool IsArm => Architecture is Architecture.Arm64; - + public static bool IsX64 => Architecture is Architecture.X64; public static bool IsIntelMac => IsMacOS && IsX64; public static bool IsArmMac => IsMacOS && IsArm; - + public static bool IsX64Windows => IsWindows && IsX64; public static bool IsArmWindows => IsWindows && IsArm; - + public static bool IsX64Linux => IsLinux && IsX64; public static bool IsArmLinux => IsLinux && IsArmMac; } diff --git a/src/Ryujinx.Common/Logging/Logger.cs b/src/Ryujinx.Common/Logging/Logger.cs index 1830c14df..e6f68599a 100644 --- a/src/Ryujinx.Common/Logging/Logger.cs +++ b/src/Ryujinx.Common/Logging/Logger.cs @@ -158,7 +158,7 @@ namespace Ryujinx.Common.Logging _time.Restart(); } - private static ILogTarget GetTarget(string targetName) + private static ILogTarget GetTarget(string targetName) => _logTargets.FirstOrDefault(target => target.Name.Equals(targetName)); public static void AddTarget(ILogTarget target) diff --git a/src/Ryujinx.Common/Logging/Targets/ConsoleLogTarget.cs b/src/Ryujinx.Common/Logging/Targets/ConsoleLogTarget.cs index 42ba00cd5..391cc5131 100644 --- a/src/Ryujinx.Common/Logging/Targets/ConsoleLogTarget.cs +++ b/src/Ryujinx.Common/Logging/Targets/ConsoleLogTarget.cs @@ -5,7 +5,7 @@ namespace Ryujinx.Common.Logging.Targets { public class ConsoleLogTarget : ILogTarget { - private readonly ILogFormatter _formatter; + private readonly DefaultLogFormatter _formatter; private readonly string _name; diff --git a/src/Ryujinx.Common/Logging/Targets/FileLogTarget.cs b/src/Ryujinx.Common/Logging/Targets/FileLogTarget.cs index 94e9359c8..181bd489a 100644 --- a/src/Ryujinx.Common/Logging/Targets/FileLogTarget.cs +++ b/src/Ryujinx.Common/Logging/Targets/FileLogTarget.cs @@ -8,7 +8,7 @@ namespace Ryujinx.Common.Logging.Targets public class FileLogTarget : ILogTarget { private readonly StreamWriter _logWriter; - private readonly ILogFormatter _formatter; + private readonly DefaultLogFormatter _formatter; private readonly string _name; string ILogTarget.Name { get => _name; } diff --git a/src/Ryujinx.Common/PreciseSleep/NanosleepEvent.cs b/src/Ryujinx.Common/PreciseSleep/NanosleepEvent.cs index f54fb09c1..962bc2a51 100644 --- a/src/Ryujinx.Common/PreciseSleep/NanosleepEvent.cs +++ b/src/Ryujinx.Common/PreciseSleep/NanosleepEvent.cs @@ -54,6 +54,7 @@ namespace Ryujinx.Common.PreciseSleep // Too many threads on the pool. return false; } + _waitEvent.WaitOne(1); _pool.IgnoreSignal(); diff --git a/src/Ryujinx.Common/ReactiveObject.cs b/src/Ryujinx.Common/ReactiveObject.cs index bb2ece81c..0e807eb7a 100644 --- a/src/Ryujinx.Common/ReactiveObject.cs +++ b/src/Ryujinx.Common/ReactiveObject.cs @@ -42,8 +42,8 @@ namespace Ryujinx.Common } } } - - public void LogChangesToValue(string valueName, LogClass logClass = LogClass.Configuration) + + public void LogChangesToValue(string valueName, LogClass logClass = LogClass.Configuration) => Event += (_, e) => ReactiveObjectHelper.LogValueChange(logClass, e, valueName); public static implicit operator T(ReactiveObject obj) => obj.Value; @@ -55,12 +55,12 @@ namespace Ryujinx.Common { if (eventArgs.AreValuesEqual) return; - + string message = string.Create(CultureInfo.InvariantCulture, $"{valueName} set to: {eventArgs.NewValue}"); Logger.Info?.Print(logClass, message); } - + public static void Toggle(this ReactiveObject rBoolean) => rBoolean.Value = !rBoolean.Value; } @@ -78,7 +78,7 @@ namespace Ryujinx.Common if (OldValue == null && NewValue != null) return false; - + if (OldValue != null && NewValue == null) return false; diff --git a/src/Ryujinx.Common/ReleaseInformation.cs b/src/Ryujinx.Common/ReleaseInformation.cs index fe47ce2ed..66971364c 100644 --- a/src/Ryujinx.Common/ReleaseInformation.cs +++ b/src/Ryujinx.Common/ReleaseInformation.cs @@ -27,19 +27,19 @@ namespace Ryujinx.Common !ConfigFileName.StartsWith("%%"); public static bool IsCanaryBuild => IsValid && ReleaseChannelName.Equals(CanaryChannel); - + public static bool IsReleaseBuild => IsValid && ReleaseChannelName.Equals(ReleaseChannel); public static string Version => IsValid ? BuildVersion : Assembly.GetEntryAssembly()!.GetCustomAttribute()?.InformationalVersion; public static string GetChangelogUrl(Version currentVersion, Version newVersion, ReleaseChannels.Channel releaseChannel) => - IsCanaryBuild + IsCanaryBuild ? $"https://git.ryujinx.app/ryubing/ryujinx/-/compare/Canary-{currentVersion}...Canary-{newVersion}" : GetChangelogForVersion(newVersion, releaseChannel); - + public static string GetChangelogForVersion(Version version, ReleaseChannels.Channel releaseChannel) => $"https://github.com/{releaseChannel}/releases/{version}"; - + public static async Task GetReleaseChannelsAsync(HttpClient httpClient) { ReleaseChannelPair releaseChannelPair = await httpClient.GetFromJsonAsync("https://ryujinx.app/api/release-channels", ReleaseChannelPairContext.Default.ReleaseChannelPair); @@ -57,7 +57,7 @@ namespace Ryujinx.Common public readonly Channel Stable; public readonly Channel Canary; - + public readonly struct Channel { public Channel(string raw) @@ -66,7 +66,7 @@ namespace Ryujinx.Common Owner = parts[0]; Repo = parts[1]; } - + public readonly string Owner; public readonly string Repo; @@ -76,7 +76,7 @@ namespace Ryujinx.Common $"https://api.github.com/repos/{ToString()}/releases/latest"; } } - + [JsonSerializable(typeof(ReleaseChannelPair))] partial class ReleaseChannelPairContext : JsonSerializerContext; diff --git a/src/Ryujinx.Common/RyujinxException.cs b/src/Ryujinx.Common/RyujinxException.cs index dbb5184e4..590072a5d 100644 --- a/src/Ryujinx.Common/RyujinxException.cs +++ b/src/Ryujinx.Common/RyujinxException.cs @@ -1,4 +1,4 @@ -using System; +using System; namespace Ryujinx.Common { diff --git a/src/Ryujinx.Common/SharedConstants.cs b/src/Ryujinx.Common/SharedConstants.cs index f40afeb2b..fe7814c67 100644 --- a/src/Ryujinx.Common/SharedConstants.cs +++ b/src/Ryujinx.Common/SharedConstants.cs @@ -1,4 +1,4 @@ -namespace Ryujinx.Common +namespace Ryujinx.Common { public static class SharedConstants { diff --git a/src/Ryujinx.Common/SystemInterop/ForceDpiAware.cs b/src/Ryujinx.Common/SystemInterop/ForceDpiAware.cs index 330638171..a89dcd1ad 100644 --- a/src/Ryujinx.Common/SystemInterop/ForceDpiAware.cs +++ b/src/Ryujinx.Common/SystemInterop/ForceDpiAware.cs @@ -57,7 +57,7 @@ namespace Ryujinx.Common.SystemInterop { string xdgSessionType = Environment.GetEnvironmentVariable("XDG_SESSION_TYPE")?.ToLower(); - if (xdgSessionType == null || xdgSessionType == "x11") + if (xdgSessionType is null or "x11") { nint display = XOpenDisplay(null); string dpiString = Marshal.PtrToStringAnsi(XGetDefault(display, "Xft", "dpi")); @@ -65,6 +65,7 @@ namespace Ryujinx.Common.SystemInterop { userDpiScale = XDisplayWidth(display, 0) * 25.4 / XDisplayWidthMM(display, 0); } + _ = XCloseDisplay(display); } else if (xdgSessionType == "wayland") diff --git a/src/Ryujinx.Common/SystemInterop/StdErrAdapter.cs b/src/Ryujinx.Common/SystemInterop/StdErrAdapter.cs index a04c404d8..4936cd874 100644 --- a/src/Ryujinx.Common/SystemInterop/StdErrAdapter.cs +++ b/src/Ryujinx.Common/SystemInterop/StdErrAdapter.cs @@ -12,8 +12,8 @@ namespace Ryujinx.Common.SystemInterop public partial class StdErrAdapter : IDisposable { private bool _disposable; - private Stream _pipeReader; - private Stream _pipeWriter; + private FileStream _pipeReader; + private FileStream _pipeWriter; private CancellationTokenSource _cancellationTokenSource; private Task _worker; @@ -46,7 +46,7 @@ namespace Ryujinx.Common.SystemInterop [SupportedOSPlatform("macos")] private async Task EventWorkerAsync(CancellationToken cancellationToken) { - using TextReader reader = new StreamReader(_pipeReader, leaveOpen: true); + using StreamReader reader = new(_pipeReader, leaveOpen: true); string line; while (cancellationToken.IsCancellationRequested == false && (line = await reader.ReadLineAsync(cancellationToken)) != null) { @@ -92,13 +92,12 @@ namespace Ryujinx.Common.SystemInterop [SupportedOSPlatform("linux")] [SupportedOSPlatform("macos")] - private static Stream CreateFileDescriptorStream(int fd) + private static FileStream CreateFileDescriptorStream(int fd) { return new FileStream( new SafeFileHandle(fd, ownsHandle: true), FileAccess.ReadWrite ); } - } } diff --git a/src/Ryujinx.Common/TitleIDs.cs b/src/Ryujinx.Common/TitleIDs.cs index 3201a5c6b..34e903149 100644 --- a/src/Ryujinx.Common/TitleIDs.cs +++ b/src/Ryujinx.Common/TitleIDs.cs @@ -6,8 +6,8 @@ namespace Ryujinx.Common public static class TitleIDs { public static ReactiveObject> CurrentApplication { get; } = new(); - - public static string GetDiscordGameAsset(string titleId) + + public static string GetDiscordGameAsset(string titleId) => DiscordGameAssetKeys.Contains(titleId) ? titleId : "game"; public static readonly string[] DiscordGameAssetKeys = diff --git a/src/Ryujinx.Common/Utilities/BitUtils.cs b/src/Ryujinx.Common/Utilities/BitUtils.cs index acbdde1f6..c99a8635d 100644 --- a/src/Ryujinx.Common/Utilities/BitUtils.cs +++ b/src/Ryujinx.Common/Utilities/BitUtils.cs @@ -40,10 +40,10 @@ namespace Ryujinx.Common return (value >> 32) | (value << 32); } - + // Never actually written bit packing logic before, so I looked it up. // This code is from https://gist.github.com/Alan-FGR/04938e93e2bffdf5802ceb218a37c195 - + public static ulong PackBitFields(this uint[] values, byte[] bitFields) { ulong retVal = values[0]; //we set the first value right away @@ -52,6 +52,7 @@ namespace Ryujinx.Common retVal <<= bitFields[f]; // we shift the previous value retVal += values[f];// and add our current value } + return retVal; } @@ -68,6 +69,7 @@ namespace Ryujinx.Common int leftShift = 64 - curPos; // we figure how much left shift we gotta apply for the other numbers to overflow into oblivion retArr[f] = (uint)((packed << leftShift) >> leftShift + lastEnd); // we do magic } + return retArr; } } diff --git a/src/Ryujinx.Common/Utilities/FileSystemUtils.cs b/src/Ryujinx.Common/Utilities/FileSystemUtils.cs index 97510fd9d..6ec92044e 100644 --- a/src/Ryujinx.Common/Utilities/FileSystemUtils.cs +++ b/src/Ryujinx.Common/Utilities/FileSystemUtils.cs @@ -49,7 +49,7 @@ namespace Ryujinx.Common.Utilities public static string SanitizeFileName(string fileName) { - HashSet reservedChars = new(Path.GetInvalidFileNameChars()); + HashSet reservedChars = [.. Path.GetInvalidFileNameChars()]; return string.Concat(fileName.Select(c => reservedChars.Contains(c) ? '_' : c)); } } diff --git a/src/Ryujinx.Common/Utilities/JsonHelper.cs b/src/Ryujinx.Common/Utilities/JsonHelper.cs index 82eeaddc1..2493f3ec4 100644 --- a/src/Ryujinx.Common/Utilities/JsonHelper.cs +++ b/src/Ryujinx.Common/Utilities/JsonHelper.cs @@ -28,13 +28,13 @@ namespace Ryujinx.Common.Utilities ReadCommentHandling = JsonCommentHandling.Skip }; - public static string Serialize(T value, JsonTypeInfo typeInfo) + public static string Serialize(T value, JsonTypeInfo typeInfo) => JsonSerializer.Serialize(value, typeInfo); - public static T Deserialize(string value, JsonTypeInfo typeInfo) + public static T Deserialize(string value, JsonTypeInfo typeInfo) => JsonSerializer.Deserialize(value, typeInfo); - public static T Deserialize(ReadOnlySpan utf8Value, JsonTypeInfo typeInfo) + public static T Deserialize(ReadOnlySpan utf8Value, JsonTypeInfo typeInfo) => JsonSerializer.Deserialize(utf8Value, typeInfo); public static void SerializeToFile(string filePath, T value, JsonTypeInfo typeInfo) diff --git a/src/Ryujinx.Common/Utilities/Rainbow.cs b/src/Ryujinx.Common/Utilities/Rainbow.cs index eb1c187c4..93129bf10 100644 --- a/src/Ryujinx.Common/Utilities/Rainbow.cs +++ b/src/Ryujinx.Common/Utilities/Rainbow.cs @@ -1,4 +1,4 @@ -using Gommon; +using Gommon; using Ryujinx.Common.Helper; using System; using System.Drawing; @@ -31,12 +31,12 @@ namespace Ryujinx.Common.Utilities { CyclingEnabled = false; } - - + + public static float Speed { get; set; } = 1; private static readonly Lock _lock = new(); - + private static Color _color = Color.Blue; public static ref Color Color @@ -55,7 +55,7 @@ namespace Ryujinx.Common.Utilities lock (_lock) { _color = HsbToRgb((_color.GetHue() + Speed) / 360); - + _updatedHandler.Call(ref _color); } } @@ -63,7 +63,7 @@ namespace Ryujinx.Common.Utilities public static void Reset() { _updatedHandler.Clear(); - + lock (_lock) _color = Color.Blue; } @@ -124,6 +124,7 @@ namespace Ryujinx.Common.Utilities break; } } + return Color.FromArgb(Convert.ToByte(255), Convert.ToByte(r), Convert.ToByte(g), Convert.ToByte(b)); } } diff --git a/src/Ryujinx.Common/Utilities/StreamUtils.cs b/src/Ryujinx.Common/Utilities/StreamUtils.cs index 60391a902..e5246dfe7 100644 --- a/src/Ryujinx.Common/Utilities/StreamUtils.cs +++ b/src/Ryujinx.Common/Utilities/StreamUtils.cs @@ -59,7 +59,7 @@ namespace Ryujinx.Common.Utilities public static async Task StreamToBytesAsync(Stream input, CancellationToken cancellationToken = default) { - using MemoryStream stream = MemoryStreamManager.Shared.GetStream(); + using RecyclableMemoryStream stream = MemoryStreamManager.Shared.GetStream(); await input.CopyToAsync(stream, cancellationToken); diff --git a/src/Ryujinx.Common/Utilities/XCIFileTrimmer.cs b/src/Ryujinx.Common/Utilities/XCIFileTrimmer.cs index 5b233d1e0..90738798a 100644 --- a/src/Ryujinx.Common/Utilities/XCIFileTrimmer.cs +++ b/src/Ryujinx.Common/Utilities/XCIFileTrimmer.cs @@ -183,7 +183,6 @@ namespace Ryujinx.Common.Utilities { CloseReaders(); } - } else { @@ -205,7 +204,7 @@ namespace Ryujinx.Common.Utilities while (true) { - if (cancelToken.HasValue && cancelToken.Value.IsCancellationRequested) + if (cancelToken.HasValue && cancelToken.Value.IsCancellationRequested) { return false; } @@ -257,7 +256,7 @@ namespace Ryujinx.Common.Utilities { return OperationOutcome.Cancelled; } - else + else { return OperationOutcome.FreeSpaceCheckFailed; } @@ -294,7 +293,7 @@ namespace Ryujinx.Common.Utilities { #if !XCI_TRIMMER_READ_ONLY_MODE - outfileStream.SetLength(TrimmedFileSizeB); + outfileStream.SetLength(TrimmedFileSizeB); #endif return OperationOutcome.Successful; } @@ -367,7 +366,7 @@ namespace Ryujinx.Common.Utilities { return OperationOutcome.Cancelled; } - else + else { return OperationOutcome.Successful; } @@ -404,9 +403,9 @@ namespace Ryujinx.Common.Utilities } long bytesToWrite = Math.Min(XCIFileTrimmer.BufferSize, bytesLeftToWriteB); - + #if !XCI_TRIMMER_READ_ONLY_MODE - outfileStream.Write(buffer, 0, (int)bytesToWrite); + outfileStream.Write(buffer, 0, (int)bytesToWrite); #endif bytesLeftToWriteB -= bytesToWrite; @@ -511,6 +510,7 @@ namespace Ryujinx.Common.Utilities Log?.Write(LogType.Error, $"The source file doesn't look like an XCI file as the Cartridge Size is incorrect (0x{cartSizeId:X2})"); return false; } + _cartSizeB = cartSizeNGB * XCIFileTrimmer.CartSizeMBinFormattedGB * XCIFileTrimmer.BytesInAMegabyte; // Read data size diff --git a/src/Ryujinx.Cpu/AddressTable.cs b/src/Ryujinx.Cpu/AddressTable.cs index 3310f7ddd..91a65e899 100644 --- a/src/Ryujinx.Cpu/AddressTable.cs +++ b/src/Ryujinx.Cpu/AddressTable.cs @@ -51,7 +51,7 @@ namespace ARMeilleure.Common { SparseMemoryBlock block = new(size, pageInit, null); - _trackingEvent = (ulong address, ulong size, bool write) => + _trackingEvent = (address, size, write) => { ulong pointer = (ulong)block.Block.Pointer + address; ensureMapped((IntPtr)pointer); @@ -181,7 +181,7 @@ namespace ARMeilleure.Common public static AddressTable CreateForArm(bool for64Bits, MemoryManagerType type) { // Assume software memory means that we don't want to use any signal handlers. - bool sparse = type != MemoryManagerType.SoftwareMmu && type != MemoryManagerType.SoftwarePageTable; + bool sparse = type is not MemoryManagerType.SoftwareMmu and not MemoryManagerType.SoftwarePageTable; return new AddressTable(AddressTablePresets.GetArmPreset(for64Bits, sparse), sparse); } diff --git a/src/Ryujinx.Cpu/AppleHv/HvAddressSpaceRange.cs b/src/Ryujinx.Cpu/AppleHv/HvAddressSpaceRange.cs index 7754431fa..c8edc6c6f 100644 --- a/src/Ryujinx.Cpu/AppleHv/HvAddressSpaceRange.cs +++ b/src/Ryujinx.Cpu/AppleHv/HvAddressSpaceRange.cs @@ -359,7 +359,7 @@ namespace Ryujinx.Cpu.AppleHv private static void ValidateEntriesCount(int count) { - Debug.Assert(count >= 0 && count <= LevelCount, $"Entries count {count} is invalid."); + Debug.Assert(count is >= 0 and <= LevelCount, $"Entries count {count} is invalid."); } public void Dispose() diff --git a/src/Ryujinx.Cpu/AppleHv/HvExecutionContext.cs b/src/Ryujinx.Cpu/AppleHv/HvExecutionContext.cs index fc2b76d15..53cea5385 100644 --- a/src/Ryujinx.Cpu/AppleHv/HvExecutionContext.cs +++ b/src/Ryujinx.Cpu/AppleHv/HvExecutionContext.cs @@ -159,7 +159,7 @@ namespace Ryujinx.Cpu.AppleHv address = SynchronousException(memoryManager, ref vcpu); HvApi.hv_vcpu_set_reg(vcpu.Handle, HvReg.PC, address).ThrowOnError(); } - else if (reason == HvExitReason.Canceled || reason == HvExitReason.VTimerActivated) + else if (reason is HvExitReason.Canceled or HvExitReason.VTimerActivated) { if (GetAndClearInterruptRequested()) { diff --git a/src/Ryujinx.Cpu/ITickSource.cs b/src/Ryujinx.Cpu/ITickSource.cs index 4aff612f0..3eba8b524 100644 --- a/src/Ryujinx.Cpu/ITickSource.cs +++ b/src/Ryujinx.Cpu/ITickSource.cs @@ -9,12 +9,12 @@ namespace Ryujinx.Cpu public interface ITickSource : ICounter { public const long RealityTickScalar = 100; - + /// /// Time elapsed since the counter was created. /// TimeSpan ElapsedTime { get; } - + /// /// Clock tick scalar, in percent points (100 = 1.0). /// diff --git a/src/Ryujinx.Cpu/Jit/HostTracked/AddressIntrusiveRedBlackTree.cs b/src/Ryujinx.Cpu/Jit/HostTracked/AddressIntrusiveRedBlackTree.cs index 0e2443303..d3a24c8bf 100644 --- a/src/Ryujinx.Cpu/Jit/HostTracked/AddressIntrusiveRedBlackTree.cs +++ b/src/Ryujinx.Cpu/Jit/HostTracked/AddressIntrusiveRedBlackTree.cs @@ -29,6 +29,7 @@ namespace Ryujinx.Cpu.Jit.HostTracked return node; } } + return null; } } diff --git a/src/Ryujinx.Cpu/Jit/HostTracked/AddressSpacePartitionAllocator.cs b/src/Ryujinx.Cpu/Jit/HostTracked/AddressSpacePartitionAllocator.cs index f39b295cd..c22fbd5df 100644 --- a/src/Ryujinx.Cpu/Jit/HostTracked/AddressSpacePartitionAllocator.cs +++ b/src/Ryujinx.Cpu/Jit/HostTracked/AddressSpacePartitionAllocator.cs @@ -115,7 +115,7 @@ namespace Ryujinx.Cpu.Jit.HostTracked } private readonly AddressIntrusiveRedBlackTree _mappingTree; - + // type is not Lock due to the unique usage of this mechanism, // an arbitrary object is used as the lock passed in by constructor. private readonly object _lock; @@ -177,7 +177,7 @@ namespace Ryujinx.Cpu.Jit.HostTracked private readonly MemoryTracking _tracking; private readonly Func _readPtCallback; - + // type is not Lock due to the unique usage of this mechanism, // an arbitrary object is used as the lock passed in by constructor. private readonly object _lock; diff --git a/src/Ryujinx.Cpu/LightningJit/Arm32/InstName.cs b/src/Ryujinx.Cpu/LightningJit/Arm32/InstName.cs index 2ee67aa0a..809fbf25e 100644 --- a/src/Ryujinx.Cpu/LightningJit/Arm32/InstName.cs +++ b/src/Ryujinx.Cpu/LightningJit/Arm32/InstName.cs @@ -531,7 +531,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm32 { public static bool IsCall(this InstName name) { - return name == InstName.BlI || name == InstName.BlxR; + return name is InstName.BlI or InstName.BlxR; } public static bool IsSystem(this InstName name) diff --git a/src/Ryujinx.Cpu/LightningJit/Arm32/InstTableT32.cs b/src/Ryujinx.Cpu/LightningJit/Arm32/InstTableT32.cs index 09222f43e..0a0774845 100644 --- a/src/Ryujinx.Cpu/LightningJit/Arm32/InstTableT32.cs +++ b/src/Ryujinx.Cpu/LightningJit/Arm32/InstTableT32.cs @@ -526,7 +526,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm32 new(0x00000041, 0x00000041) ]; - List insts = + List insts = [ new(0xF1400000, 0xFBE08000, InstName.AdcI, T.AdcIT1, IsaVersion.v80, InstFlags.Rd), new(0xEB400000, 0xFFE08000, InstName.AdcR, T.AdcRT2, IsaVersion.v80, InstFlags.Rd), diff --git a/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/Compiler.cs b/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/Compiler.cs index 3121d4f95..643d1e20d 100644 --- a/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/Compiler.cs +++ b/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/Compiler.cs @@ -493,7 +493,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64 { delta = targetIndex - branchIndex; - if (delta >= -Encodable26BitsOffsetLimit && delta < Encodable26BitsOffsetLimit) + if (delta is >= (-Encodable26BitsOffsetLimit) and < Encodable26BitsOffsetLimit) { writer.WriteInstructionAt(branchIndex, encoding | (uint)(delta & 0x3ffffff)); @@ -559,7 +559,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64 } } - Debug.Assert(name == InstName.B || name == InstName.Cbnz, $"Unknown branch instruction \"{name}\"."); + Debug.Assert(name is InstName.B or InstName.Cbnz, $"Unknown branch instruction \"{name}\"."); } private static void RewriteCallInstructionWithTarget(in Context context, uint targetAddress, uint nextAddress, int branchIndex) @@ -745,6 +745,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64 InstEmitSystem.WriteUdf(context.Writer, context.RegisterAllocator, context.TailMerger, context.GetReservedStackOffset(), pc, imm); break; } + context.LoadFromContext(); break; case BranchType.ReadCntpct: diff --git a/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitAlu.cs b/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitAlu.cs index c0762819e..30479137c 100644 --- a/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitAlu.cs +++ b/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitAlu.cs @@ -736,6 +736,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64 { m = GetRrxC(context, dest, m, carryOut); } + break; } } diff --git a/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitFlow.cs b/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitFlow.cs index 6a8c2abdd..8190bd7ea 100644 --- a/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitFlow.cs +++ b/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitFlow.cs @@ -142,7 +142,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64 int tempRegister; int tempGuestAddress = -1; - bool inlineLookup = guestAddress.Kind != OperandKind.Constant && + bool inlineLookup = guestAddress.Kind != OperandKind.Constant && funcTable is { Sparse: true }; if (guestAddress.Kind == OperandKind.Constant) diff --git a/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitNeonCommon.cs b/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitNeonCommon.cs index dce6556e4..eb5b56364 100644 --- a/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitNeonCommon.cs +++ b/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitNeonCommon.cs @@ -118,7 +118,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64 public static void EmitScalarUnaryF(CodeGenContext context, uint rd, uint rm, uint size, Action action) { - Debug.Assert(size == 1 || size == 2 || size == 3); + Debug.Assert(size is 1 or 2 or 3); bool singleRegs = size != 3; @@ -133,7 +133,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64 public static void EmitScalarUnaryF(CodeGenContext context, uint rd, uint rm, uint size, Action action, Action actionHalf) { - Debug.Assert(size == 1 || size == 2 || size == 3); + Debug.Assert(size is 1 or 2 or 3); bool singleRegs = size != 3; @@ -161,7 +161,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64 uint sf, Action action) { - Debug.Assert(size == 1 || size == 2 || size == 3); + Debug.Assert(size is 1 or 2 or 3); bool singleRegs = size != 3; @@ -182,7 +182,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64 uint sf, Action action) { - Debug.Assert(size == 1 || size == 2 || size == 3); + Debug.Assert(size is 1 or 2 or 3); bool singleRegs = size != 3; @@ -197,7 +197,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64 public static void EmitScalarUnaryFixedF(CodeGenContext context, uint rd, uint rm, uint fbits, uint size, bool is16Bit, Action action) { - Debug.Assert(size == 1 || size == 2 || size == 3); + Debug.Assert(size is 1 or 2 or 3); bool singleRegs = size != 3; @@ -214,7 +214,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64 public static void EmitScalarBinaryF(CodeGenContext context, uint rd, uint rn, uint rm, uint size, Action action) { - Debug.Assert(size == 1 || size == 2 || size == 3); + Debug.Assert(size is 1 or 2 or 3); bool singleRegs = size != 3; @@ -252,7 +252,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64 public static void EmitScalarTernaryRdF(CodeGenContext context, uint rd, uint rn, uint rm, uint size, Action action) { - Debug.Assert(size == 1 || size == 2 || size == 3); + Debug.Assert(size is 1 or 2 or 3); bool singleRegs = size != 3; @@ -276,7 +276,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64 uint size, Action action) { - Debug.Assert(size == 1 || size == 2 || size == 3); + Debug.Assert(size is 1 or 2 or 3); bool singleRegs = size != 3; @@ -300,7 +300,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64 bool negD, bool negProduct) { - Debug.Assert(size == 1 || size == 2 || size == 3); + Debug.Assert(size is 1 or 2 or 3); bool singleRegs = size != 3; @@ -918,7 +918,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64 Action action, Action actionHalf) { - Debug.Assert(sz == 0 || sz == 1); + Debug.Assert(sz is 0 or 1); if (q == 0) { @@ -962,7 +962,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64 Action action, Action actionHalf) { - Debug.Assert(size == 1 || size == 2 || size == 3); + Debug.Assert(size is 1 or 2 or 3); Debug.Assert(size != 3 || q == 1); if (q == 0) @@ -1007,7 +1007,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64 uint q, Action action) { - Debug.Assert(size == 1 || size == 2 || size == 3); + Debug.Assert(size is 1 or 2 or 3); Debug.Assert(size != 3 || q == 1); (uint immb, uint immh) = GetImmbImmh(fbits, size); @@ -1040,7 +1040,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64 Action action, Action actionHalf) { - Debug.Assert(sz == 0 || sz == 1); + Debug.Assert(sz is 0 or 1); if (q == 0) { @@ -1100,7 +1100,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64 Action action, Action actionHalf) { - Debug.Assert(sz == 0 || sz == 1); + Debug.Assert(sz is 0 or 1); if (q == 0) { @@ -1148,7 +1148,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64 uint q, bool negProduct) { - Debug.Assert(sz == 0 || sz == 1); + Debug.Assert(sz is 0 or 1); if (q == 0) { diff --git a/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitNeonMemory.cs b/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitNeonMemory.cs index e77dc0a29..18017351a 100644 --- a/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitNeonMemory.cs +++ b/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitNeonMemory.cs @@ -467,7 +467,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64 private static void EmitMemory1234InstructionCore(CodeGenContext context, uint rn, uint rm, int bytes, Action callback) { bool wBack = rm != RegisterUtils.PcRegister; - bool registerIndex = rm != RegisterUtils.PcRegister && rm != RegisterUtils.SpRegister; + bool registerIndex = rm is not RegisterUtils.PcRegister and not RegisterUtils.SpRegister; Operand rnOperand = InstEmitCommon.GetInputGpr(context, rn); diff --git a/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitNeonMove.cs b/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitNeonMove.cs index 08a0673aa..f22cb5839 100644 --- a/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitNeonMove.cs +++ b/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitNeonMove.cs @@ -252,7 +252,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64 } else { - Debug.Assert(opc1 == 0 || opc1 == 1); + Debug.Assert(opc1 is 0 or 1); Debug.Assert(opc2 == 0); index = opc1 & 1u; @@ -307,7 +307,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64 } else { - Debug.Assert(opc1 == 0 || opc1 == 1); + Debug.Assert(opc1 is 0 or 1); Debug.Assert(opc2 == 0); Debug.Assert(!u); diff --git a/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitSystem.cs b/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitSystem.cs index 21e40b6aa..10a3298e7 100644 --- a/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitSystem.cs +++ b/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitSystem.cs @@ -60,6 +60,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64 return; } } + break; } } @@ -109,6 +110,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64 break; } } + break; } @@ -142,6 +144,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64 context.Arm64Assembler.B(0); return; } + break; } diff --git a/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitVfpCompare.cs b/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitVfpCompare.cs index c1b51750f..66873818e 100644 --- a/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitVfpCompare.cs +++ b/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitVfpCompare.cs @@ -27,7 +27,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64 private static void EmitVcmpVcmpe(CodeGenContext context, uint cond, uint rd, uint rm, uint size, bool zero, bool e) { - Debug.Assert(size == 1 || size == 2 || size == 3); + Debug.Assert(size is 1 or 2 or 3); bool singleRegs = size != 3; uint ftype = size ^ 2u; diff --git a/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitVfpConvert.cs b/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitVfpConvert.cs index 8e4886950..aef833256 100644 --- a/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitVfpConvert.cs +++ b/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitVfpConvert.cs @@ -231,7 +231,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64 { bool unsigned = (op & 1) == 0; - Debug.Assert(size == 1 || size == 2 || size == 3); + Debug.Assert(size is 1 or 2 or 3); bool singleRegs = size != 3; diff --git a/src/Ryujinx.Cpu/LightningJit/Arm64/InstName.cs b/src/Ryujinx.Cpu/LightningJit/Arm64/InstName.cs index 3391a2c14..af3b872a5 100644 --- a/src/Ryujinx.Cpu/LightningJit/Arm64/InstName.cs +++ b/src/Ryujinx.Cpu/LightningJit/Arm64/InstName.cs @@ -1044,7 +1044,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm64 { public static bool IsCall(this InstName name) { - return name == InstName.Bl || name == InstName.Blr; + return name is InstName.Bl or InstName.Blr; } public static bool IsControlFlowOrException(this InstName name) diff --git a/src/Ryujinx.Cpu/LightningJit/Arm64/Target/Arm64/Compiler.cs b/src/Ryujinx.Cpu/LightningJit/Arm64/Target/Arm64/Compiler.cs index 1e087591c..e45d74f9b 100644 --- a/src/Ryujinx.Cpu/LightningJit/Arm64/Target/Arm64/Compiler.cs +++ b/src/Ryujinx.Cpu/LightningJit/Arm64/Target/Arm64/Compiler.cs @@ -545,6 +545,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm64.Target.Arm64 context.GetReservedStackOffset(), isTail: true); } + break; case InstName.Ret: @@ -565,6 +566,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm64.Target.Arm64 context.TailMerger.AddUnconditionalReturn(writer, asm); } + break; case InstName.BCond: @@ -574,7 +576,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm64.Target.Arm64 case InstName.Tbz: uint branchMask; - if (name == InstName.Tbnz || name == InstName.Tbz) + if (name is InstName.Tbnz or InstName.Tbz) { originalOffset = ImmUtils.ExtractSImm14Times4(encoding); branchMask = 0x3fff; @@ -631,7 +633,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm64.Target.Arm64 { delta = targetIndex - branchIndex; - if (delta >= -Encodable26BitsOffsetLimit && delta < Encodable26BitsOffsetLimit) + if (delta is >= (-Encodable26BitsOffsetLimit) and < Encodable26BitsOffsetLimit) { writer.WriteInstructionAt(branchIndex, (encoding & ~0x3ffffffu) | (uint)(delta & 0x3ffffff)); break; @@ -652,7 +654,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm64.Target.Arm64 case InstName.Tbz: uint branchMask; - if (name == InstName.Tbnz || name == InstName.Tbz) + if (name is InstName.Tbnz or InstName.Tbz) { originalOffset = ImmUtils.ExtractSImm14Times4(encoding); branchMask = 0x3fff; @@ -709,6 +711,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm64.Target.Arm64 writer.WriteInstructionAt(movedBranchIndex, (encoding & ~(branchMask << 5)) | (uint)((delta & branchMask) << 5)); WriteTailCallConstant(context, ref asm, blockIndex, targetAddress); } + break; default: diff --git a/src/Ryujinx.Cpu/LightningJit/Arm64/Target/Arm64/Decoder.cs b/src/Ryujinx.Cpu/LightningJit/Arm64/Target/Arm64/Decoder.cs index 33d319668..ad221c7aa 100644 --- a/src/Ryujinx.Cpu/LightningJit/Arm64/Target/Arm64/Decoder.cs +++ b/src/Ryujinx.Cpu/LightningJit/Arm64/Target/Arm64/Decoder.cs @@ -72,7 +72,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm64.Target.Arm64 case InstName.Cbz: case InstName.Tbnz: case InstName.Tbz: - if (name == InstName.Tbnz || name == InstName.Tbz) + if (name is InstName.Tbnz or InstName.Tbz) { originalOffset = ImmUtils.ExtractSImm14Times4(encoding); } @@ -369,7 +369,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm64.Target.Arm64 case InstName.Cbz: case InstName.Tbnz: case InstName.Tbz: - int imm = name == InstName.Tbnz || name == InstName.Tbz + int imm = name is InstName.Tbnz or InstName.Tbz ? ImmUtils.ExtractSImm14Times4(encoding) : ImmUtils.ExtractSImm19Times4(encoding); diff --git a/src/Ryujinx.Cpu/LightningJit/Arm64/Target/Arm64/InstEmitSystem.cs b/src/Ryujinx.Cpu/LightningJit/Arm64/Target/Arm64/InstEmitSystem.cs index 98939839c..1bd69bc4b 100644 --- a/src/Ryujinx.Cpu/LightningJit/Arm64/Target/Arm64/InstEmitSystem.cs +++ b/src/Ryujinx.Cpu/LightningJit/Arm64/Target/Arm64/InstEmitSystem.cs @@ -230,7 +230,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm64.Target.Arm64 case InstName.Bl: case InstName.Blr: case InstName.Br: - if (name == InstName.BUncond || name == InstName.Bl) + if (name is InstName.BUncond or InstName.Bl) { int imm = ImmUtils.ExtractSImm26Times4(encoding); @@ -283,6 +283,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm64.Target.Arm64 isTail); } } + break; default: diff --git a/src/Ryujinx.Cpu/LightningJit/Arm64/Target/Arm64/InstTable.cs b/src/Ryujinx.Cpu/LightningJit/Arm64/Target/Arm64/InstTable.cs index b1dc9b30c..984545800 100644 --- a/src/Ryujinx.Cpu/LightningJit/Arm64/Target/Arm64/InstTable.cs +++ b/src/Ryujinx.Cpu/LightningJit/Arm64/Target/Arm64/InstTable.cs @@ -451,7 +451,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm64.Target.Arm64 new(0x00000000, 0x20001000) ]; - List insts = + List insts = [ new(0x5AC02000, 0x7FFFFC00, InstName.Abs, IsaVersion.v89, InstFlags.RdRn), new(0x5EE0B800, 0xFFFFFC00, InstName.AbsAdvsimdS, IsaVersion.v80, InstFlags.RdRnFpSimd), diff --git a/src/Ryujinx.Cpu/LightningJit/Cache/JitCache.cs b/src/Ryujinx.Cpu/LightningJit/Cache/JitCache.cs index 96bb05819..4ab54ecb7 100644 --- a/src/Ryujinx.Cpu/LightningJit/Cache/JitCache.cs +++ b/src/Ryujinx.Cpu/LightningJit/Cache/JitCache.cs @@ -150,7 +150,7 @@ namespace Ryujinx.Cpu.LightningJit.Cache for (int i = _activeRegionIndex; i < _jitRegions.Count; i++) { int allocOffset = _cacheAllocator.Allocate(codeSize); - + if (allocOffset >= 0) { _jitRegions[i].ExpandIfNeeded((ulong)allocOffset + (ulong)codeSize); @@ -163,11 +163,11 @@ namespace Ryujinx.Cpu.LightningJit.Cache ReservedRegion newRegion = new(_jitRegions[0].Allocator, CacheSize); _jitRegions.Add(newRegion); _activeRegionIndex = _jitRegions.Count - 1; - + int newRegionNumber = _activeRegionIndex; Logger.Warning?.Print(LogClass.Cpu, $"JIT Cache Region {exhaustedRegion} exhausted, creating new Cache Region {newRegionNumber} ({((long)(newRegionNumber + 1) * CacheSize).Bytes()} Total Allocation)."); - + _cacheAllocator = new CacheMemoryAllocator(CacheSize); int allocOffsetNew = _cacheAllocator.Allocate(codeSize); diff --git a/src/Ryujinx.Cpu/LightningJit/CodeGen/Arm64/Assembler.cs b/src/Ryujinx.Cpu/LightningJit/CodeGen/Arm64/Assembler.cs index dd130dbeb..3eeda20bf 100644 --- a/src/Ryujinx.Cpu/LightningJit/CodeGen/Arm64/Assembler.cs +++ b/src/Ryujinx.Cpu/LightningJit/CodeGen/Arm64/Assembler.cs @@ -4360,6 +4360,7 @@ namespace Ryujinx.Cpu.LightningJit.CodeGen.Arm64 instI |= 1 << 22; // sh flag imm >>= 12; } + WriteInstructionAuto(instI | (EncodeUImm12(imm, 0) << 10), rd, rn); } else diff --git a/src/Ryujinx.Cpu/LightningJit/CodeGen/Arm64/CodeGenCommon.cs b/src/Ryujinx.Cpu/LightningJit/CodeGen/Arm64/CodeGenCommon.cs index db6a71593..f1aca983f 100644 --- a/src/Ryujinx.Cpu/LightningJit/CodeGen/Arm64/CodeGenCommon.cs +++ b/src/Ryujinx.Cpu/LightningJit/CodeGen/Arm64/CodeGenCommon.cs @@ -28,7 +28,7 @@ namespace Ryujinx.Cpu.LightningJit.CodeGen.Arm64 // Any value AND all ones will be equal itself, so it's effectively a no-op. // Any value OR all ones will be equal all ones, so one can just use MOV. // Any value XOR all ones will be equal its inverse, so one can just use MVN. - if (value == 0 || value == ulong.MaxValue) + if (value is 0 or ulong.MaxValue) { immN = 0; immS = 0; diff --git a/src/Ryujinx.Cpu/LightningJit/CodeGen/OperandType.cs b/src/Ryujinx.Cpu/LightningJit/CodeGen/OperandType.cs index 6191f791b..cd36c6781 100644 --- a/src/Ryujinx.Cpu/LightningJit/CodeGen/OperandType.cs +++ b/src/Ryujinx.Cpu/LightningJit/CodeGen/OperandType.cs @@ -16,7 +16,7 @@ namespace Ryujinx.Cpu.LightningJit.CodeGen { public static bool IsInteger(this OperandType type) { - return type == OperandType.I32 || type == OperandType.I64; + return type is OperandType.I32 or OperandType.I64; } public static int GetSizeInBytes(this OperandType type) diff --git a/src/Ryujinx.Cpu/LightningJit/Translator.cs b/src/Ryujinx.Cpu/LightningJit/Translator.cs index 5f3fe8783..f3ae0a9c5 100644 --- a/src/Ryujinx.Cpu/LightningJit/Translator.cs +++ b/src/Ryujinx.Cpu/LightningJit/Translator.cs @@ -54,7 +54,7 @@ namespace Ryujinx.Cpu.LightningJit } } - private static IStackWalker CreateStackWalker() + private static StackWalker CreateStackWalker() { if (RuntimeInformation.ProcessArchitecture == Architecture.Arm64) { diff --git a/src/Ryujinx.Cpu/TickSource.cs b/src/Ryujinx.Cpu/TickSource.cs index 3bc01d6b9..3aa616a8d 100644 --- a/src/Ryujinx.Cpu/TickSource.cs +++ b/src/Ryujinx.Cpu/TickSource.cs @@ -14,33 +14,30 @@ namespace Ryujinx.Cpu /// public ulong Counter => (ulong)(ElapsedSeconds * Frequency); - - - public long TickScalar { get; set; } + public long TickScalar { get; set; } + private static long _acumElapsedTicks; - private static long _lastElapsedTicks; - private long ElapsedTicks { get { long elapsedTicks = _tickCounter.ElapsedTicks; - + _acumElapsedTicks += (elapsedTicks - _lastElapsedTicks) * TickScalar / 100; _lastElapsedTicks = elapsedTicks; - + return _acumElapsedTicks; } } /// - + public TimeSpan ElapsedTime => Stopwatch.GetElapsedTime(0, ElapsedTicks); /// diff --git a/src/Ryujinx.Graphics.GAL/IRenderer.cs b/src/Ryujinx.Graphics.GAL/IRenderer.cs index 9d822e7c2..cc51ed67b 100644 --- a/src/Ryujinx.Graphics.GAL/IRenderer.cs +++ b/src/Ryujinx.Graphics.GAL/IRenderer.cs @@ -20,7 +20,7 @@ namespace Ryujinx.Graphics.GAL Logger.Info?.PrintMsg(LogClass.Gpu, $"Backend Threading ({backendThreading}): True"); return new ThreadedRenderer(this); } - + Logger.Info?.PrintMsg(LogClass.Gpu, $"Backend Threading ({backendThreading}): False"); return this; diff --git a/src/Ryujinx.Graphics.GAL/Multithreading/BufferMap.cs b/src/Ryujinx.Graphics.GAL/Multithreading/BufferMap.cs index 48bec3633..5e273d420 100644 --- a/src/Ryujinx.Graphics.GAL/Multithreading/BufferMap.cs +++ b/src/Ryujinx.Graphics.GAL/Multithreading/BufferMap.cs @@ -77,7 +77,6 @@ namespace Ryujinx.Graphics.GAL.Multithreading { // Blocks until the handle is available. - lock (_bufferMap) { if (_bufferMap.TryGetValue(handle, out BufferHandle result)) diff --git a/src/Ryujinx.Graphics.GAL/Target.cs b/src/Ryujinx.Graphics.GAL/Target.cs index 73497546e..1c184981d 100644 --- a/src/Ryujinx.Graphics.GAL/Target.cs +++ b/src/Ryujinx.Graphics.GAL/Target.cs @@ -18,17 +18,17 @@ namespace Ryujinx.Graphics.GAL { public static bool IsMultisample(this Target target) { - return target == Target.Texture2DMultisample || target == Target.Texture2DMultisampleArray; + return target is Target.Texture2DMultisample or Target.Texture2DMultisampleArray; } public static bool HasDepthOrLayers(this Target target) { - return target == Target.Texture3D || - target == Target.Texture1DArray || - target == Target.Texture2DArray || - target == Target.Texture2DMultisampleArray || - target == Target.Cubemap || - target == Target.CubemapArray; + return target is Target.Texture3D or + Target.Texture1DArray or + Target.Texture2DArray or + Target.Texture2DMultisampleArray or + Target.Cubemap or + Target.CubemapArray; } } } diff --git a/src/Ryujinx.Graphics.GAL/TextureCreateInfo.cs b/src/Ryujinx.Graphics.GAL/TextureCreateInfo.cs index 79c84db01..27a2ac896 100644 --- a/src/Ryujinx.Graphics.GAL/TextureCreateInfo.cs +++ b/src/Ryujinx.Graphics.GAL/TextureCreateInfo.cs @@ -98,9 +98,9 @@ namespace Ryujinx.Graphics.GAL public int GetLayers() { - if (Target == Target.Texture2DArray || - Target == Target.Texture2DMultisampleArray || - Target == Target.CubemapArray) + if (Target is Target.Texture2DArray or + Target.Texture2DMultisampleArray or + Target.CubemapArray) { return Depth; } diff --git a/src/Ryujinx.Graphics.GAL/ViewportSwizzle.cs b/src/Ryujinx.Graphics.GAL/ViewportSwizzle.cs index 9352c8162..69de93ad5 100644 --- a/src/Ryujinx.Graphics.GAL/ViewportSwizzle.cs +++ b/src/Ryujinx.Graphics.GAL/ViewportSwizzle.cs @@ -2,7 +2,6 @@ using System.Diagnostics.CodeAnalysis; namespace Ryujinx.Graphics.GAL { - [SuppressMessage("Design", "CA1069: Enums values should not be duplicated")] public enum ViewportSwizzle { PositiveX = 0, diff --git a/src/Ryujinx.Graphics.Gpu/Engine/DeviceStateWithShadow.cs b/src/Ryujinx.Graphics.Gpu/Engine/DeviceStateWithShadow.cs index ccfba79a4..aacaf2f4b 100644 --- a/src/Ryujinx.Graphics.Gpu/Engine/DeviceStateWithShadow.cs +++ b/src/Ryujinx.Graphics.Gpu/Engine/DeviceStateWithShadow.cs @@ -85,8 +85,8 @@ namespace Ryujinx.Graphics.Gpu.Engine { _state.WriteWithRedundancyCheck(offset, value, out changed); } - else if (shadowRamControl == SetMmeShadowRamControlMode.MethodTrack || - shadowRamControl == SetMmeShadowRamControlMode.MethodTrackWithFilter) + else if (shadowRamControl is SetMmeShadowRamControlMode.MethodTrack or + SetMmeShadowRamControlMode.MethodTrackWithFilter) { _shadowState.Write(offset, value); _state.WriteWithRedundancyCheck(offset, value, out changed); diff --git a/src/Ryujinx.Graphics.Gpu/Engine/MME/MacroJitCompiler.cs b/src/Ryujinx.Graphics.Gpu/Engine/MME/MacroJitCompiler.cs index ea8bb2d61..cd711f1b3 100644 --- a/src/Ryujinx.Graphics.Gpu/Engine/MME/MacroJitCompiler.cs +++ b/src/Ryujinx.Graphics.Gpu/Engine/MME/MacroJitCompiler.cs @@ -290,6 +290,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.MME _ilGen.Emit(OpCodes.Shl); break; } + break; case AluOperation.ReadImmediate: diff --git a/src/Ryujinx.Graphics.Gpu/Engine/SetMmeShadowRamControlMode.cs b/src/Ryujinx.Graphics.Gpu/Engine/SetMmeShadowRamControlMode.cs index b9a5c74a3..c07cb1044 100644 --- a/src/Ryujinx.Graphics.Gpu/Engine/SetMmeShadowRamControlMode.cs +++ b/src/Ryujinx.Graphics.Gpu/Engine/SetMmeShadowRamControlMode.cs @@ -15,7 +15,7 @@ namespace Ryujinx.Graphics.Gpu.Engine { public static bool IsTrack(this SetMmeShadowRamControlMode mode) { - return mode == SetMmeShadowRamControlMode.MethodTrack || mode == SetMmeShadowRamControlMode.MethodTrackWithFilter; + return mode is SetMmeShadowRamControlMode.MethodTrack or SetMmeShadowRamControlMode.MethodTrackWithFilter; } public static bool IsPassthrough(this SetMmeShadowRamControlMode mode) diff --git a/src/Ryujinx.Graphics.Gpu/Engine/Threed/ComputeDraw/VtgAsComputeContext.cs b/src/Ryujinx.Graphics.Gpu/Engine/Threed/ComputeDraw/VtgAsComputeContext.cs index eba1b6030..ed9da4a5c 100644 --- a/src/Ryujinx.Graphics.Gpu/Engine/Threed/ComputeDraw/VtgAsComputeContext.cs +++ b/src/Ryujinx.Graphics.Gpu/Engine/Threed/ComputeDraw/VtgAsComputeContext.cs @@ -285,6 +285,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed.ComputeDraw { data[index] = index; } + break; case PrimitiveTopology.LineLoop: data[^1] = 0; @@ -294,6 +295,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed.ComputeDraw data[index] = index >> 1; data[index + 1] = (index >> 1) + 1; } + break; case PrimitiveTopology.LineStrip: for (int index = 0; index < ((data.Length - 1) & ~1); index += 2) @@ -301,6 +303,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed.ComputeDraw data[index] = index >> 1; data[index + 1] = (index >> 1) + 1; } + break; case PrimitiveTopology.TriangleStrip: int tsTrianglesCount = data.Length / 3; @@ -330,6 +333,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed.ComputeDraw data[baseIndex + 2] = tsOutIndex++; } } + break; case PrimitiveTopology.TriangleFan: case PrimitiveTopology.Polygon: @@ -342,6 +346,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed.ComputeDraw data[index + 1] = tfOutIndex; data[index + 2] = ++tfOutIndex; } + break; case PrimitiveTopology.Quads: int qQuadsCount = data.Length / 6; @@ -358,6 +363,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed.ComputeDraw data[index + 4] = qIndex + 2; data[index + 5] = qIndex + 3; } + break; case PrimitiveTopology.QuadStrip: int qsQuadsCount = data.Length / 6; @@ -384,6 +390,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed.ComputeDraw data[index + 4] = qIndex + 2; data[index + 5] = qIndex + 3; } + break; case PrimitiveTopology.LineStripAdjacency: for (int index = 0; index < ((data.Length - 3) & ~3); index += 4) @@ -395,6 +402,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed.ComputeDraw data[index + 2] = lIndex + 2; data[index + 3] = lIndex + 3; } + break; case PrimitiveTopology.TriangleStripAdjacency: int tsaTrianglesCount = data.Length / 6; @@ -433,6 +441,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed.ComputeDraw data[baseIndex + 5] = tsaOutIndex++; } } + break; } diff --git a/src/Ryujinx.Graphics.Gpu/Engine/Threed/ComputeDraw/VtgAsComputeState.cs b/src/Ryujinx.Graphics.Gpu/Engine/Threed/ComputeDraw/VtgAsComputeState.cs index 0d59275ff..a66ea7dbe 100644 --- a/src/Ryujinx.Graphics.Gpu/Engine/Threed/ComputeDraw/VtgAsComputeState.cs +++ b/src/Ryujinx.Graphics.Gpu/Engine/Threed/ComputeDraw/VtgAsComputeState.cs @@ -170,8 +170,6 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed.ComputeDraw int vbStride = vertexBuffer.UnpackStride(); ulong vbSize = GetVertexBufferSize(address, endAddress.Pack(), vbStride, _indexed, instanced, _firstVertex, _count); - ulong oldVbSize = vbSize; - ulong attributeOffset = (ulong)vertexAttrib.UnpackOffset(); int componentSize = format.GetScalarSize(); @@ -477,7 +475,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed.ComputeDraw private readonly ulong GetVertexBufferSize(ulong vbAddress, ulong vbEndAddress, int vbStride, bool indexed, bool instanced, int firstVertex, int vertexCount) { IndexType indexType = _state.State.IndexBufferState.Type; - bool indexTypeSmall = indexType == IndexType.UByte || indexType == IndexType.UShort; + bool indexTypeSmall = indexType is IndexType.UByte or IndexType.UShort; ulong vbSize = vbEndAddress - vbAddress + 1; ulong size; diff --git a/src/Ryujinx.Graphics.Gpu/Engine/Threed/IndirectDrawType.cs b/src/Ryujinx.Graphics.Gpu/Engine/Threed/IndirectDrawType.cs index 331b1976b..402e3ff80 100644 --- a/src/Ryujinx.Graphics.Gpu/Engine/Threed/IndirectDrawType.cs +++ b/src/Ryujinx.Graphics.Gpu/Engine/Threed/IndirectDrawType.cs @@ -5,7 +5,6 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed /// /// Indirect draw type, which can be indexed or non-indexed, with or without a draw count. /// - [SuppressMessage("Design", "CA1069: Enums values should not be duplicated")] enum IndirectDrawType { /// diff --git a/src/Ryujinx.Graphics.Gpu/Engine/Threed/SpecializationStateUpdater.cs b/src/Ryujinx.Graphics.Gpu/Engine/Threed/SpecializationStateUpdater.cs index 4eea80687..c76adbca6 100644 --- a/src/Ryujinx.Graphics.Gpu/Engine/Threed/SpecializationStateUpdater.cs +++ b/src/Ryujinx.Graphics.Gpu/Engine/Threed/SpecializationStateUpdater.cs @@ -253,9 +253,9 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed { value |= AttributeType.Packed; - if (type == VertexAttribType.Snorm || - type == VertexAttribType.Sint || - type == VertexAttribType.Sscaled) + if (type is VertexAttribType.Snorm or + VertexAttribType.Sint or + VertexAttribType.Sscaled) { value |= AttributeType.PackedRgb10A2Signed; } diff --git a/src/Ryujinx.Graphics.Gpu/Engine/Threed/StateUpdater.cs b/src/Ryujinx.Graphics.Gpu/Engine/Threed/StateUpdater.cs index 4620821cb..e6af3fb5e 100644 --- a/src/Ryujinx.Graphics.Gpu/Engine/Threed/StateUpdater.cs +++ b/src/Ryujinx.Graphics.Gpu/Engine/Threed/StateUpdater.cs @@ -1104,7 +1104,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed private void UpdateVertexBufferState() { IndexType indexType = _state.State.IndexBufferState.Type; - bool indexTypeSmall = indexType == IndexType.UByte || indexType == IndexType.UShort; + bool indexTypeSmall = indexType is IndexType.UByte or IndexType.UShort; _drawState.IsAnyVbInstanced = false; diff --git a/src/Ryujinx.Graphics.Gpu/GpuContext.cs b/src/Ryujinx.Graphics.Gpu/GpuContext.cs index d1c608dd6..d0b8277da 100644 --- a/src/Ryujinx.Graphics.Gpu/GpuContext.cs +++ b/src/Ryujinx.Graphics.Gpu/GpuContext.cs @@ -91,13 +91,13 @@ namespace Ryujinx.Graphics.Gpu /// Support buffer updater. /// internal SupportBufferUpdater SupportBufferUpdater { get; } - + /// /// Enabled dirty hacks. /// Used for workarounds to emulator bugs we can't fix/don't know how to fix yet. /// internal DirtyHacks DirtyHacks { get; } - + /// /// Host hardware capabilities. diff --git a/src/Ryujinx.Graphics.Gpu/GraphicsConfig.cs b/src/Ryujinx.Graphics.Gpu/GraphicsConfig.cs index 066ac28f7..715a4d92b 100644 --- a/src/Ryujinx.Graphics.Gpu/GraphicsConfig.cs +++ b/src/Ryujinx.Graphics.Gpu/GraphicsConfig.cs @@ -1,6 +1,5 @@ namespace Ryujinx.Graphics.Gpu { -#pragma warning disable CA2211 // Non-constant fields should not be visible /// /// General GPU and graphics configuration. /// @@ -9,25 +8,25 @@ namespace Ryujinx.Graphics.Gpu /// /// Resolution scale. /// - public static float ResScale = 1f; + public static float ResScale { get; set; } = 1f; /// /// Max Anisotropy. Values range from 0 - 16. Set to -1 to let the game decide. /// - public static float MaxAnisotropy = -1; + public static float MaxAnisotropy { get; set; } = -1; /// /// Base directory used to write shader code dumps. /// Set to null to disable code dumping. /// - public static string ShadersDumpPath; + public static string ShadersDumpPath { get; set; } /// /// Fast GPU time calculates the internal GPU time ticks as if the GPU was capable of /// processing commands almost instantly, instead of using the host timer. /// This can avoid lower resolution on some games when GPU performance is poor. /// - public static bool FastGpuTime = true; + public static bool FastGpuTime { get; set; } = true; /// /// Enables or disables fast 2d engine texture copies entirely on CPU when possible. @@ -35,43 +34,42 @@ namespace Ryujinx.Graphics.Gpu /// as textures will not need to be created for the copy, and the data does not need to be /// flushed from GPU. /// - public static bool Fast2DCopy = true; + public static bool Fast2DCopy { get; set; } = true; /// /// Enables or disables the Just-in-Time compiler for GPU Macro code. /// - public static bool EnableMacroJit = true; + public static bool EnableMacroJit { get; set; } = true; /// /// Enables or disables high-level emulation of common GPU Macro code. /// - public static bool EnableMacroHLE = true; - + public static bool EnableMacroHLE { get; set; } = true; + /// /// Title id of the current running game. /// Used by the shader cache. /// - public static string TitleId; + public static string TitleId { get; set; } /// /// Enables or disables the shader cache. /// - public static bool EnableShaderCache; + public static bool EnableShaderCache { get; set; } /// /// Enables or disables shader SPIR-V compilation. /// - public static bool EnableSpirvCompilationOnVulkan = true; + public static bool EnableSpirvCompilationOnVulkan { get; set; } = true; /// /// Enables or disables recompression of compressed textures that are not natively supported by the host. /// - public static bool EnableTextureRecompression = false; + public static bool EnableTextureRecompression { get; set; } = false; /// /// Enables or disables color space passthrough, if available. /// - public static bool EnableColorSpacePassthrough = false; + public static bool EnableColorSpacePassthrough { get; set; } = false; } -#pragma warning restore CA2211 } diff --git a/src/Ryujinx.Graphics.Gpu/Image/AutoDeleteCache.cs b/src/Ryujinx.Graphics.Gpu/Image/AutoDeleteCache.cs index afdbcbd3e..99b34112f 100644 --- a/src/Ryujinx.Graphics.Gpu/Image/AutoDeleteCache.cs +++ b/src/Ryujinx.Graphics.Gpu/Image/AutoDeleteCache.cs @@ -56,7 +56,6 @@ namespace Ryujinx.Graphics.Gpu.Image private const ulong TextureSizeCapacity8GiB = 6 * GiB; private const ulong TextureSizeCapacity12GiB = 12 * GiB; - private const float MemoryScaleFactor = 0.50f; private ulong _maxCacheMemoryUsage = DefaultTextureSizeCapacity; diff --git a/src/Ryujinx.Graphics.Gpu/Image/FormatTable.cs b/src/Ryujinx.Graphics.Gpu/Image/FormatTable.cs index 45e1971a8..ee217714c 100644 --- a/src/Ryujinx.Graphics.Gpu/Image/FormatTable.cs +++ b/src/Ryujinx.Graphics.Gpu/Image/FormatTable.cs @@ -10,7 +10,6 @@ namespace Ryujinx.Graphics.Gpu.Image static class FormatTable { #pragma warning disable IDE0055 // Disable formatting - [SuppressMessage("Design", "CA1069: Enums values should not be duplicated")] private enum TextureFormat : uint { // Formats @@ -249,7 +248,6 @@ namespace Ryujinx.Graphics.Gpu.Image A5B5G5R1Unorm = A5B5G5R1 | RUnorm | GUnorm | BUnorm | AUnorm, // 0x24913 } - [SuppressMessage("Design", "CA1069: Enums values should not be duplicated")] private enum VertexAttributeFormat : uint { // Width diff --git a/src/Ryujinx.Graphics.Gpu/Image/Pool.cs b/src/Ryujinx.Graphics.Gpu/Image/Pool.cs index e12fedc74..3cc65a92b 100644 --- a/src/Ryujinx.Graphics.Gpu/Image/Pool.cs +++ b/src/Ryujinx.Graphics.Gpu/Image/Pool.cs @@ -248,6 +248,7 @@ namespace Ryujinx.Graphics.Gpu.Image Items = null; } + _memoryTracking.Dispose(); } } diff --git a/src/Ryujinx.Graphics.Gpu/Image/SamplerDescriptor.cs b/src/Ryujinx.Graphics.Gpu/Image/SamplerDescriptor.cs index c742e1796..cd97d68dd 100644 --- a/src/Ryujinx.Graphics.Gpu/Image/SamplerDescriptor.cs +++ b/src/Ryujinx.Graphics.Gpu/Image/SamplerDescriptor.cs @@ -175,6 +175,7 @@ namespace Ryujinx.Graphics.Gpu.Image case SamplerMinFilter.Linear: return MinFilter.Linear; } + break; case SamplerMipFilter.Nearest: @@ -185,6 +186,7 @@ namespace Ryujinx.Graphics.Gpu.Image case SamplerMinFilter.Linear: return MinFilter.LinearMipmapNearest; } + break; case SamplerMipFilter.Linear: @@ -195,6 +197,7 @@ namespace Ryujinx.Graphics.Gpu.Image case SamplerMinFilter.Linear: return MinFilter.LinearMipmapLinear; } + break; } diff --git a/src/Ryujinx.Graphics.Gpu/Image/Texture.cs b/src/Ryujinx.Graphics.Gpu/Image/Texture.cs index 984d614d4..9540df548 100644 --- a/src/Ryujinx.Graphics.Gpu/Image/Texture.cs +++ b/src/Ryujinx.Graphics.Gpu/Image/Texture.cs @@ -1355,7 +1355,7 @@ namespace Ryujinx.Graphics.Gpu.Image /// True if anisotropic filtering can be forced, false otherwise private bool CanTextureForceAnisotropy() { - if (!(Target == Target.Texture2D || Target == Target.Texture2DArray)) + if (Target is not (Target.Texture2D or Target.Texture2DArray)) { return false; } @@ -1379,16 +1379,16 @@ namespace Ryujinx.Graphics.Gpu.Image { case Target.Texture1D: case Target.Texture1DArray: - return target == Target.Texture1D || target == Target.Texture1DArray; + return target is Target.Texture1D or Target.Texture1DArray; case Target.Texture2D: case Target.Texture2DArray: - return target == Target.Texture2D || target == Target.Texture2DArray; + return target is Target.Texture2D or Target.Texture2DArray; case Target.Cubemap: case Target.CubemapArray: - return target == Target.Cubemap || target == Target.CubemapArray; + return target is Target.Cubemap or Target.CubemapArray; case Target.Texture2DMultisample: case Target.Texture2DMultisampleArray: - return target == Target.Texture2DMultisample || target == Target.Texture2DMultisampleArray; + return target is Target.Texture2DMultisample or Target.Texture2DMultisampleArray; case Target.Texture3D: return target == Target.Texture3D; default: diff --git a/src/Ryujinx.Graphics.Gpu/Image/TextureBindingsManager.cs b/src/Ryujinx.Graphics.Gpu/Image/TextureBindingsManager.cs index aa1ac1d57..35f099c67 100644 --- a/src/Ryujinx.Graphics.Gpu/Image/TextureBindingsManager.cs +++ b/src/Ryujinx.Graphics.Gpu/Image/TextureBindingsManager.cs @@ -784,8 +784,8 @@ namespace Ryujinx.Graphics.Gpu.Image samplerHandle = samplerWordOffset; } - if (handleType == TextureHandleType.SeparateSamplerId || - handleType == TextureHandleType.SeparateConstantSamplerHandle) + if (handleType is TextureHandleType.SeparateSamplerId or + TextureHandleType.SeparateConstantSamplerHandle) { samplerHandle <<= 20; } diff --git a/src/Ryujinx.Graphics.Gpu/Image/TextureCompatibility.cs b/src/Ryujinx.Graphics.Gpu/Image/TextureCompatibility.cs index 8bed6363b..f2cbca832 100644 --- a/src/Ryujinx.Graphics.Gpu/Image/TextureCompatibility.cs +++ b/src/Ryujinx.Graphics.Gpu/Image/TextureCompatibility.cs @@ -207,8 +207,8 @@ namespace Ryujinx.Graphics.Gpu.Image return false; // Flushing this format is not supported, as it may have been converted to another host format. } - if (info.Target == Target.Texture2DMultisample || - info.Target == Target.Texture2DMultisampleArray) + if (info.Target is Target.Texture2DMultisample or + Target.Texture2DMultisampleArray) { return false; // Flushing multisample textures is not supported, the host does not allow getting their data. } @@ -758,43 +758,45 @@ namespace Ryujinx.Graphics.Gpu.Image { case Target.Texture1D: case Target.Texture1DArray: - result = rhs.Target == Target.Texture1D || - rhs.Target == Target.Texture1DArray; + result = rhs.Target is Target.Texture1D or + Target.Texture1DArray; break; case Target.Texture2D: - result = rhs.Target == Target.Texture2D || - rhs.Target == Target.Texture2DArray; + result = rhs.Target is Target.Texture2D or + Target.Texture2DArray; break; case Target.Texture2DArray: - result = rhs.Target == Target.Texture2D || - rhs.Target == Target.Texture2DArray; + result = rhs.Target is Target.Texture2D or + Target.Texture2DArray; - if (rhs.Target == Target.Cubemap || rhs.Target == Target.CubemapArray) + if (rhs.Target is Target.Cubemap or Target.CubemapArray) { return caps.SupportsCubemapView ? TextureViewCompatibility.Full : TextureViewCompatibility.CopyOnly; } + break; case Target.Cubemap: case Target.CubemapArray: - result = rhs.Target == Target.Cubemap || - rhs.Target == Target.CubemapArray; + result = rhs.Target is Target.Cubemap or + Target.CubemapArray; - if (rhs.Target == Target.Texture2D || rhs.Target == Target.Texture2DArray) + if (rhs.Target is Target.Texture2D or Target.Texture2DArray) { return caps.SupportsCubemapView ? TextureViewCompatibility.Full : TextureViewCompatibility.CopyOnly; } + break; case Target.Texture2DMultisample: case Target.Texture2DMultisampleArray: - if (rhs.Target == Target.Texture2D || rhs.Target == Target.Texture2DArray) + if (rhs.Target is Target.Texture2D or Target.Texture2DArray) { return TextureViewCompatibility.CopyOnly; } - result = rhs.Target == Target.Texture2DMultisample || - rhs.Target == Target.Texture2DMultisampleArray; + result = rhs.Target is Target.Texture2DMultisample or + Target.Texture2DMultisampleArray; break; case Target.Texture3D: diff --git a/src/Ryujinx.Graphics.Gpu/Image/TextureGroup.cs b/src/Ryujinx.Graphics.Gpu/Image/TextureGroup.cs index 8c27e286a..7f38df129 100644 --- a/src/Ryujinx.Graphics.Gpu/Image/TextureGroup.cs +++ b/src/Ryujinx.Graphics.Gpu/Image/TextureGroup.cs @@ -218,7 +218,6 @@ namespace Ryujinx.Graphics.Gpu.Image } } - /// /// Flushes incompatible overlaps if the storage format requires it, and they have been modified. /// This allows unsupported host formats to accept data written to format aliased textures. @@ -1133,7 +1132,6 @@ namespace Ryujinx.Graphics.Gpu.Image SignalAllDirty(); } - /// /// Removes a view from the group, removing it from all overlap lists. /// diff --git a/src/Ryujinx.Graphics.Gpu/Image/TextureInfo.cs b/src/Ryujinx.Graphics.Gpu/Image/TextureInfo.cs index 94d2e0bfc..cb2ccf54d 100644 --- a/src/Ryujinx.Graphics.Gpu/Image/TextureInfo.cs +++ b/src/Ryujinx.Graphics.Gpu/Image/TextureInfo.cs @@ -216,7 +216,7 @@ namespace Ryujinx.Graphics.Gpu.Image /// The number of texture layers public static int GetLayers(Target target, int depthOrLayers) { - if (target == Target.Texture2DArray || target == Target.Texture2DMultisampleArray) + if (target is Target.Texture2DArray or Target.Texture2DMultisampleArray) { return depthOrLayers; } @@ -241,7 +241,7 @@ namespace Ryujinx.Graphics.Gpu.Image /// The number of texture slices public int GetSlices() { - if (Target == Target.Texture3D || Target == Target.Texture2DArray || Target == Target.Texture2DMultisampleArray) + if (Target is Target.Texture3D or Target.Texture2DArray or Target.Texture2DMultisampleArray) { return DepthOrLayers; } diff --git a/src/Ryujinx.Graphics.Gpu/Image/TexturePool.cs b/src/Ryujinx.Graphics.Gpu/Image/TexturePool.cs index 4a16fa90a..fd1609c23 100644 --- a/src/Ryujinx.Graphics.Gpu/Image/TexturePool.cs +++ b/src/Ryujinx.Graphics.Gpu/Image/TexturePool.cs @@ -454,6 +454,7 @@ namespace Ryujinx.Graphics.Gpu.Image // If this is null, a request was already queued to decrement reference. texture.DecrementReferenceCount(this, request.ID); } + continue; } } @@ -544,7 +545,7 @@ namespace Ryujinx.Graphics.Gpu.Image int width = target == Target.TextureBuffer ? descriptor.UnpackBufferTextureWidth() : descriptor.UnpackWidth(); int height = descriptor.UnpackHeight(); - if (target == Target.Texture2DMultisample || target == Target.Texture2DMultisampleArray) + if (target is Target.Texture2DMultisample or Target.Texture2DMultisampleArray) { // This is divided back before the backend texture is created. width *= samplesInX; @@ -699,8 +700,8 @@ namespace Ryujinx.Graphics.Gpu.Image { int maxSize = width; - if (target != Target.Texture1D && - target != Target.Texture1DArray) + if (target is not Target.Texture1D and + not Target.Texture1DArray) { maxSize = Math.Max(maxSize, height); } @@ -761,8 +762,8 @@ namespace Ryujinx.Graphics.Gpu.Image /// True if the swizzle component is equal to the red or green, false otherwise private static bool IsRG(SwizzleComponent component) { - return component == SwizzleComponent.Red || - component == SwizzleComponent.Green; + return component is SwizzleComponent.Red or + SwizzleComponent.Green; } /// diff --git a/src/Ryujinx.Graphics.Gpu/Memory/Buffer.cs b/src/Ryujinx.Graphics.Gpu/Memory/Buffer.cs index 227ff1253..a2448d76f 100644 --- a/src/Ryujinx.Graphics.Gpu/Memory/Buffer.cs +++ b/src/Ryujinx.Graphics.Gpu/Memory/Buffer.cs @@ -705,7 +705,7 @@ namespace Ryujinx.Graphics.Gpu.Memory { BufferHandle handle = Handle; - return (ulong address, ulong size, ulong _) => + return (address, size, _) => { FlushImpl(handle, address, size); }; diff --git a/src/Ryujinx.Graphics.Gpu/Memory/BufferBackingState.cs b/src/Ryujinx.Graphics.Gpu/Memory/BufferBackingState.cs index 56bc9143f..a9b1f50e2 100644 --- a/src/Ryujinx.Graphics.Gpu/Memory/BufferBackingState.cs +++ b/src/Ryujinx.Graphics.Gpu/Memory/BufferBackingState.cs @@ -63,7 +63,7 @@ namespace Ryujinx.Graphics.Gpu.Memory // Backend managed is always auto, unified memory is always host. _desiredType = BufferBackingType.HostMemory; - _canSwap = _systemMemoryType != SystemMemoryType.BackendManaged && _systemMemoryType != SystemMemoryType.UnifiedMemory; + _canSwap = _systemMemoryType is not SystemMemoryType.BackendManaged and not SystemMemoryType.UnifiedMemory; if (_canSwap) { diff --git a/src/Ryujinx.Graphics.Gpu/Memory/BufferStage.cs b/src/Ryujinx.Graphics.Gpu/Memory/BufferStage.cs index d56abda28..8a9f37658 100644 --- a/src/Ryujinx.Graphics.Gpu/Memory/BufferStage.cs +++ b/src/Ryujinx.Graphics.Gpu/Memory/BufferStage.cs @@ -29,10 +29,7 @@ namespace Ryujinx.Graphics.Gpu.Memory StorageRead = 0x40, StorageWrite = 0x80, - -#pragma warning disable CA1069 // Enums values should not be duplicated StorageAtomic = 0xc0 -#pragma warning restore CA1069 // Enums values should not be duplicated } /// diff --git a/src/Ryujinx.Graphics.Gpu/Memory/BufferUpdater.cs b/src/Ryujinx.Graphics.Gpu/Memory/BufferUpdater.cs index fab78971d..f7fc65a4e 100644 --- a/src/Ryujinx.Graphics.Gpu/Memory/BufferUpdater.cs +++ b/src/Ryujinx.Graphics.Gpu/Memory/BufferUpdater.cs @@ -76,7 +76,7 @@ namespace Ryujinx.Graphics.Gpu.Memory BufferRange range = new(_handle, 0, data.Length); _renderer.Pipeline.SetUniformBuffers([new BufferAssignment(0, range)]); } - }; + } _renderer.SetBufferData(_handle, _startOffset, data[_startOffset.._endOffset]); diff --git a/src/Ryujinx.Graphics.Gpu/Memory/PhysicalMemory.cs b/src/Ryujinx.Graphics.Gpu/Memory/PhysicalMemory.cs index 8a78b99e0..0b1424b8a 100644 --- a/src/Ryujinx.Graphics.Gpu/Memory/PhysicalMemory.cs +++ b/src/Ryujinx.Graphics.Gpu/Memory/PhysicalMemory.cs @@ -157,6 +157,7 @@ namespace Ryujinx.Graphics.Gpu.Memory { _cpuMemory.GetSpan(currentRange.Address, size, tracked).CopyTo(data.Slice(offset, size)); } + offset += size; } @@ -204,6 +205,7 @@ namespace Ryujinx.Graphics.Gpu.Memory { GetSpan(currentRange.Address, size).CopyTo(memorySpan.Slice(offset, size)); } + offset += size; } @@ -339,6 +341,7 @@ namespace Ryujinx.Graphics.Gpu.Memory { writeCallback(currentRange.Address, data.Slice(offset, size)); } + offset += size; } } diff --git a/src/Ryujinx.Graphics.Gpu/Memory/PteKind.cs b/src/Ryujinx.Graphics.Gpu/Memory/PteKind.cs index 1585328f0..bdaddc1ee 100644 --- a/src/Ryujinx.Graphics.Gpu/Memory/PteKind.cs +++ b/src/Ryujinx.Graphics.Gpu/Memory/PteKind.cs @@ -262,7 +262,7 @@ namespace Ryujinx.Graphics.Gpu.Memory /// True if pitch, false otherwise public static bool IsPitch(this PteKind kind) { - return kind == PteKind.Pitch || kind == PteKind.PitchNoSwizzle; + return kind is PteKind.Pitch or PteKind.PitchNoSwizzle; } } } diff --git a/src/Ryujinx.Graphics.Gpu/Shader/DiskCache/BackgroundDiskCacheWriter.cs b/src/Ryujinx.Graphics.Gpu/Shader/DiskCache/BackgroundDiskCacheWriter.cs index e0f17ba9c..0e89a20a1 100644 --- a/src/Ryujinx.Graphics.Gpu/Shader/DiskCache/BackgroundDiskCacheWriter.cs +++ b/src/Ryujinx.Graphics.Gpu/Shader/DiskCache/BackgroundDiskCacheWriter.cs @@ -108,6 +108,7 @@ namespace Ryujinx.Graphics.Gpu.Shader.DiskCache { Logger.Error?.Print(LogClass.Gpu, $"Error writing shader to disk cache. {ioException.Message}"); } + break; } } diff --git a/src/Ryujinx.Graphics.Gpu/Shader/DiskCache/BinarySerializer.cs b/src/Ryujinx.Graphics.Gpu/Shader/DiskCache/BinarySerializer.cs index 3837092c9..76975c13b 100644 --- a/src/Ryujinx.Graphics.Gpu/Shader/DiskCache/BinarySerializer.cs +++ b/src/Ryujinx.Graphics.Gpu/Shader/DiskCache/BinarySerializer.cs @@ -203,6 +203,7 @@ namespace Ryujinx.Graphics.Gpu.Shader.DiskCache { offset += stream.Read(data[offset..]); } + stream.Dispose(); break; case CompressionAlgorithm.Brotli: @@ -211,6 +212,7 @@ namespace Ryujinx.Graphics.Gpu.Shader.DiskCache { offset += stream.Read(data[offset..]); } + stream.Dispose(); break; } diff --git a/src/Ryujinx.Graphics.Gpu/Shader/DiskCache/DiskCacheGuestStorage.cs b/src/Ryujinx.Graphics.Gpu/Shader/DiskCache/DiskCacheGuestStorage.cs index f8fa06482..1e2f9146f 100644 --- a/src/Ryujinx.Graphics.Gpu/Shader/DiskCache/DiskCacheGuestStorage.cs +++ b/src/Ryujinx.Graphics.Gpu/Shader/DiskCache/DiskCacheGuestStorage.cs @@ -379,8 +379,8 @@ namespace Ryujinx.Graphics.Gpu.Shader.DiskCache /// Code and constant buffer data hash /// Entry index private int WriteNewEntry( - Stream tocFileStream, - Stream dataFileStream, + FileStream tocFileStream, + FileStream dataFileStream, ref TocHeader header, ReadOnlySpan data, ReadOnlySpan cb1Data, diff --git a/src/Ryujinx.Graphics.Gpu/Shader/DiskCache/DiskCacheHostStorage.cs b/src/Ryujinx.Graphics.Gpu/Shader/DiskCache/DiskCacheHostStorage.cs index 22ffe4812..6444b18e3 100644 --- a/src/Ryujinx.Graphics.Gpu/Shader/DiskCache/DiskCacheHostStorage.cs +++ b/src/Ryujinx.Graphics.Gpu/Shader/DiskCache/DiskCacheHostStorage.cs @@ -737,7 +737,7 @@ namespace Ryujinx.Graphics.Gpu.Shader.DiskCache /// Magic value to be written /// Shader codegen version, only valid for the host file /// File creation timestamp - private static void CreateToc(Stream tocFileStream, ref TocHeader header, uint magic, uint codegenVersion, ulong timestamp) + private static void CreateToc(FileStream tocFileStream, ref TocHeader header, uint magic, uint codegenVersion, ulong timestamp) { BinarySerializer writer = new(tocFileStream); diff --git a/src/Ryujinx.Graphics.Gpu/Shader/DiskCache/ShaderBinarySerializer.cs b/src/Ryujinx.Graphics.Gpu/Shader/DiskCache/ShaderBinarySerializer.cs index 8e8bf8e5e..f30973a09 100644 --- a/src/Ryujinx.Graphics.Gpu/Shader/DiskCache/ShaderBinarySerializer.cs +++ b/src/Ryujinx.Graphics.Gpu/Shader/DiskCache/ShaderBinarySerializer.cs @@ -1,3 +1,4 @@ +using Microsoft.IO; using Ryujinx.Common; using Ryujinx.Common.Memory; using Ryujinx.Graphics.GAL; @@ -12,7 +13,7 @@ namespace Ryujinx.Graphics.Gpu.Shader.DiskCache { public static byte[] Pack(ShaderSource[] sources) { - using MemoryStream output = MemoryStreamManager.Shared.GetStream(); + using RecyclableMemoryStream output = MemoryStreamManager.Shared.GetStream(); output.Write(sources.Length); diff --git a/src/Ryujinx.Graphics.Gpu/Shader/GpuChannelGraphicsState.cs b/src/Ryujinx.Graphics.Gpu/Shader/GpuChannelGraphicsState.cs index 765bef7d4..694b67ab9 100644 --- a/src/Ryujinx.Graphics.Gpu/Shader/GpuChannelGraphicsState.cs +++ b/src/Ryujinx.Graphics.Gpu/Shader/GpuChannelGraphicsState.cs @@ -133,7 +133,7 @@ namespace Ryujinx.Graphics.Gpu.Shader }; } - bool isQuad = Topology == PrimitiveTopology.Quads || Topology == PrimitiveTopology.QuadStrip; + bool isQuad = Topology is PrimitiveTopology.Quads or PrimitiveTopology.QuadStrip; bool halvePrimitiveId = !hostSupportsQuads && !hasGeometryShader && isQuad; return new GpuGraphicsState( diff --git a/src/Ryujinx.Graphics.Nvdec.FFmpeg/Native/FFmpegApi.cs b/src/Ryujinx.Graphics.Nvdec.FFmpeg/Native/FFmpegApi.cs index 13e456dfb..f78bad75d 100644 --- a/src/Ryujinx.Graphics.Nvdec.FFmpeg/Native/FFmpegApi.cs +++ b/src/Ryujinx.Graphics.Nvdec.FFmpeg/Native/FFmpegApi.cs @@ -36,7 +36,6 @@ namespace Ryujinx.Graphics.Nvdec.FFmpeg.Native } } - private static bool TryLoadWhitelistedLibrary(string libraryName, Assembly assembly, DllImportSearchPath? searchPath, out nint handle) { handle = nint.Zero; diff --git a/src/Ryujinx.Graphics.Nvdec.Vp9/BitDepth.cs b/src/Ryujinx.Graphics.Nvdec.Vp9/BitDepth.cs index 1f0c65c7b..fdf0aff9c 100644 --- a/src/Ryujinx.Graphics.Nvdec.Vp9/BitDepth.cs +++ b/src/Ryujinx.Graphics.Nvdec.Vp9/BitDepth.cs @@ -6,4 +6,4 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 Bits10 = 10, // < 10 bits Bits12 = 12, // < 12 bits } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Graphics.Nvdec.Vp9/CodecErr.cs b/src/Ryujinx.Graphics.Nvdec.Vp9/CodecErr.cs index 9bcf4ac01..331e0c13f 100644 --- a/src/Ryujinx.Graphics.Nvdec.Vp9/CodecErr.cs +++ b/src/Ryujinx.Graphics.Nvdec.Vp9/CodecErr.cs @@ -1,4 +1,4 @@ -namespace Ryujinx.Graphics.Nvdec.Vp9 +namespace Ryujinx.Graphics.Nvdec.Vp9 { internal enum CodecErr { @@ -49,18 +49,18 @@ /// UnsupFeature, - /// - /// The coded data for this stream is corrupt or incomplete. - /// - /// - /// There was a problem decoding the current frame.
- /// This return code should only be used - /// for failures that prevent future pictures from being properly decoded.
- ///
- /// This error MAY be treated as fatal to the stream or MAY be treated as fatal to the current GOP.
- /// If decoding is continued for the current GOP, artifacts may be present. - ///
- CorruptFrame, + /// + /// The coded data for this stream is corrupt or incomplete. + /// + /// + /// There was a problem decoding the current frame.
+ /// This return code should only be used + /// for failures that prevent future pictures from being properly decoded.
+ ///
+ /// This error MAY be treated as fatal to the stream or MAY be treated as fatal to the current GOP.
+ /// If decoding is continued for the current GOP, artifacts may be present. + ///
+ CorruptFrame, /// /// An application-supplied parameter is not valid. @@ -72,4 +72,4 @@ /// ListEnd } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Graphics.Nvdec.Vp9/Common/BitUtils.cs b/src/Ryujinx.Graphics.Nvdec.Vp9/Common/BitUtils.cs index 900b9d1c1..82a2aa47f 100644 --- a/src/Ryujinx.Graphics.Nvdec.Vp9/Common/BitUtils.cs +++ b/src/Ryujinx.Graphics.Nvdec.Vp9/Common/BitUtils.cs @@ -56,4 +56,4 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Common return numValues > 0 ? GetMsb(numValues) + 1 : 0; } } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Graphics.Nvdec.Vp9/Common/MemoryAllocator.cs b/src/Ryujinx.Graphics.Nvdec.Vp9/Common/MemoryAllocator.cs index 6d108d86e..c98052094 100644 --- a/src/Ryujinx.Graphics.Nvdec.Vp9/Common/MemoryAllocator.cs +++ b/src/Ryujinx.Graphics.Nvdec.Vp9/Common/MemoryAllocator.cs @@ -61,7 +61,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Common ArrayPtr allocation = new(ptr, length); - allocation.AsSpan().Fill(default); + allocation.AsSpan().Clear(); return allocation; } diff --git a/src/Ryujinx.Graphics.Nvdec.Vp9/Common/MemoryUtil.cs b/src/Ryujinx.Graphics.Nvdec.Vp9/Common/MemoryUtil.cs index 66c41f8cc..afdc6b0b2 100644 --- a/src/Ryujinx.Graphics.Nvdec.Vp9/Common/MemoryUtil.cs +++ b/src/Ryujinx.Graphics.Nvdec.Vp9/Common/MemoryUtil.cs @@ -20,4 +20,4 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Common new Span(ptr, length).Fill(value); } } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Graphics.Nvdec.Vp9/Constants.cs b/src/Ryujinx.Graphics.Nvdec.Vp9/Constants.cs index 4d7f919e5..69a34239d 100644 --- a/src/Ryujinx.Graphics.Nvdec.Vp9/Constants.cs +++ b/src/Ryujinx.Graphics.Nvdec.Vp9/Constants.cs @@ -1,4 +1,4 @@ -using Ryujinx.Graphics.Nvdec.Vp9.Types; +using Ryujinx.Graphics.Nvdec.Vp9.Types; namespace Ryujinx.Graphics.Nvdec.Vp9 { @@ -97,4 +97,4 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 public const int SkipContexts = 3; public const int InterModeContexts = 7; } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Graphics.Nvdec.Vp9/DSubExp.cs b/src/Ryujinx.Graphics.Nvdec.Vp9/DSubExp.cs index 72cfba8f3..b25f04ad0 100644 --- a/src/Ryujinx.Graphics.Nvdec.Vp9/DSubExp.cs +++ b/src/Ryujinx.Graphics.Nvdec.Vp9/DSubExp.cs @@ -1,4 +1,4 @@ -using System.Diagnostics; +using System.Diagnostics; namespace Ryujinx.Graphics.Nvdec.Vp9 { @@ -44,4 +44,4 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 return Prob.MaxProb - InvRecenterNonneg(v, Prob.MaxProb - 1 - m); } } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Graphics.Nvdec.Vp9/DecodeFrame.cs b/src/Ryujinx.Graphics.Nvdec.Vp9/DecodeFrame.cs index 3e7d6b030..541f29e96 100644 --- a/src/Ryujinx.Graphics.Nvdec.Vp9/DecodeFrame.cs +++ b/src/Ryujinx.Graphics.Nvdec.Vp9/DecodeFrame.cs @@ -1,4 +1,4 @@ -using Ryujinx.Common.Memory; +using Ryujinx.Common.Memory; using Ryujinx.Graphics.Nvdec.Vp9.Common; using Ryujinx.Graphics.Nvdec.Vp9.Dsp; using Ryujinx.Graphics.Nvdec.Vp9.Types; @@ -63,7 +63,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 { for (int j = 0; j < Constants.InterModes - 1; ++j) { - r.DiffUpdateProb( ref fc.InterModeProb[i][j]); + r.DiffUpdateProb(ref fc.InterModeProb[i][j]); } } } @@ -172,15 +172,15 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 { if (txSize <= TxSize.Tx16X16 && eob <= 10) { - dqcoeff.AsSpan().Slice(0, 4 * (4 << (int)txSize)).Clear(); + dqcoeff.AsSpan()[..(4 * (4 << (int)txSize))].Clear(); } else if (txSize == TxSize.Tx32X32 && eob <= 34) { - dqcoeff.AsSpan().Slice(0, 256).Clear(); + dqcoeff.AsSpan()[..256].Clear(); } else { - dqcoeff.AsSpan().Slice(0, 16 << ((int)txSize << 1)).Clear(); + dqcoeff.AsSpan()[..(16 << ((int)txSize << 1))].Clear(); } } } @@ -263,15 +263,15 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 { if (txType == TxType.DctDct && txSize <= TxSize.Tx16X16 && eob <= 10) { - dqcoeff.AsSpan().Slice(0, 4 * (4 << (int)txSize)).Clear(); + dqcoeff.AsSpan()[..(4 * (4 << (int)txSize))].Clear(); } else if (txSize == TxSize.Tx32X32 && eob <= 34) { - dqcoeff.AsSpan().Slice(0, 256).Clear(); + dqcoeff.AsSpan()[..256].Clear(); } else { - dqcoeff.AsSpan().Slice(0, 16 << ((int)txSize << 1)).Clear(); + dqcoeff.AsSpan()[..(16 << ((int)txSize << 1))].Clear(); } } } @@ -289,7 +289,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 PredictionMode mode = plane == 0 ? mi.Mode : mi.UvMode; int dstOffset = (4 * row * pd.Dst.Stride) + (4 * col); byte* dst = &pd.Dst.Buf.ToPointer()[dstOffset]; - Span dstSpan = pd.Dst.Buf.AsSpan().Slice(dstOffset); + Span dstSpan = pd.Dst.Buf.AsSpan()[dstOffset..]; if (mi.SbType < BlockSize.Block8X8) { @@ -329,7 +329,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 ref MacroBlockDPlane pd = ref xd.Plane[plane]; Luts.ScanOrder sc = Luts.DefaultScanOrders[(int)txSize]; int eob = Detokenize.DecodeBlockTokens(ref twd, plane, sc, col, row, txSize, mi.SegmentId); - Span dst = pd.Dst.Buf.AsSpan().Slice((4 * row * pd.Dst.Stride) + (4 * col)); + Span dst = pd.Dst.Buf.AsSpan()[((4 * row * pd.Dst.Stride) + (4 * col))..]; if (eob > 0) { @@ -1024,8 +1024,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 // Update the partition context at the end notes. Set partition bits // of block sizes larger than the current one to be one, and partition // bits of smaller block sizes to be zero. - aboveCtx.Slice(0, bw).Fill(Luts.PartitionContextLookup[(int)subsize].Above); - leftCtx.Slice(0, bw).Fill(Luts.PartitionContextLookup[(int)subsize].Left); + aboveCtx[..bw].Fill(Luts.PartitionContextLookup[(int)subsize].Above); + leftCtx[..bw].Fill(Luts.PartitionContextLookup[(int)subsize].Left); } private static PartitionType ReadPartition( @@ -1174,7 +1174,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 { for (int m = 0; m < Entropy.UnconstrainedNodes; ++m) { - r.DiffUpdateProb( ref coefProbs[i][j][k][l][m]); + r.DiffUpdateProb(ref coefProbs[i][j][k][l][m]); } } } @@ -1262,9 +1262,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 private static void SetupFrameSize(MemoryAllocator allocator, ref Vp9Common cm, ref ReadBitBuffer rb) { - int width = 0, height = 0; ref BufferPool pool = ref cm.BufferPool.Value; - rb.ReadFrameSize(out width, out height); + rb.ReadFrameSize(out int width, out int height); cm.ResizeContextBuffers(allocator, width, height); SetupRenderSize(ref cm, ref rb); @@ -1608,13 +1607,13 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 GetTileBuffers(ref cm, data, tileCols, ref tileBuffers); - tileBuffers.AsSpan().Slice(0, tileCols).Sort(CompareTileBuffers); + tileBuffers.AsSpan()[..tileCols].Sort(CompareTileBuffers); if (numWorkers == tileCols) { TileBuffer largest = tileBuffers[0]; Span buffers = tileBuffers.AsSpan(); - buffers.Slice(1).CopyTo(buffers.Slice(0, tileBuffers.Length - 1)); + buffers[1..].CopyTo(buffers[..(tileBuffers.Length - 1)]); tileBuffers[tileCols - 1] = largest; } else @@ -1734,9 +1733,13 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 private static bool ReadSyncCode(ref ReadBitBuffer rb) { - return rb.ReadLiteral(8) == SyncCode0 && - rb.ReadLiteral(8) == SyncCode1 && - rb.ReadLiteral(8) == SyncCode2; + int readSyncCode0 = rb.ReadLiteral(8); + int readSyncCode1 = rb.ReadLiteral(8); + int readSyncCode2 = rb.ReadLiteral(8); + + return readSyncCode0 == SyncCode0 && + readSyncCode1 == SyncCode1 && + readSyncCode2 == SyncCode2; } private static void RefCntFb(ref Array12 bufs, ref int idx, int newIdx) @@ -2014,7 +2017,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 for (int i = 0; i < Constants.IntraInterContexts; i++) { - r.DiffUpdateProb( ref fc.IntraInterProb[i]); + r.DiffUpdateProb(ref fc.IntraInterProb[i]); } cm.ReferenceMode = cm.ReadFrameReferenceMode(ref r); @@ -2029,7 +2032,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 { for (int i = 0; i < Constants.IntraModes - 1; ++i) { - r.DiffUpdateProb( ref fc.YModeProb[j][i]); + r.DiffUpdateProb(ref fc.YModeProb[j][i]); } } @@ -2037,7 +2040,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 { for (int i = 0; i < Constants.PartitionTypes - 1; ++i) { - r.DiffUpdateProb( ref fc.PartitionProb[j][i]); + r.DiffUpdateProb(ref fc.PartitionProb[j][i]); } } @@ -2119,7 +2122,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 allocator.Free(cm.TileWorkerData); } - cm.CheckMemError( ref cm.TileWorkerData, allocator.Allocate(numTileWorkers)); + cm.CheckMemError(ref cm.TileWorkerData, allocator.Allocate(numTileWorkers)); cm.TotalTiles = tileRows * tileCols; } @@ -2168,4 +2171,4 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 } } } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Graphics.Nvdec.Vp9/DecodeMv.cs b/src/Ryujinx.Graphics.Nvdec.Vp9/DecodeMv.cs index 8b7ad4de1..b2c8d494d 100644 --- a/src/Ryujinx.Graphics.Nvdec.Vp9/DecodeMv.cs +++ b/src/Ryujinx.Graphics.Nvdec.Vp9/DecodeMv.cs @@ -1,4 +1,4 @@ -using Ryujinx.Common.Memory; +using Ryujinx.Common.Memory; using Ryujinx.Graphics.Nvdec.Vp9.Dsp; using Ryujinx.Graphics.Nvdec.Vp9.Types; using Ryujinx.Graphics.Video; @@ -59,9 +59,12 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 { switch (maxTxSize) { - case TxSize.Tx8X8: return fc.Tx8x8Prob[ctx].AsSpan(); - case TxSize.Tx16X16: return fc.Tx16x16Prob[ctx].AsSpan(); - case TxSize.Tx32X32: return fc.Tx32x32Prob[ctx].AsSpan(); + case TxSize.Tx8X8: + return fc.Tx8x8Prob[ctx].AsSpan(); + case TxSize.Tx16X16: + return fc.Tx16x16Prob[ctx].AsSpan(); + case TxSize.Tx32X32: + return fc.Tx32x32Prob[ctx].AsSpan(); default: Debug.Assert(false, "Invalid maxTxSize."); return ReadOnlySpan.Empty; @@ -72,9 +75,12 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 { switch (maxTxSize) { - case TxSize.Tx8X8: return counts.Tx8x8[ctx].AsSpan(); - case TxSize.Tx16X16: return counts.Tx16x16[ctx].AsSpan(); - case TxSize.Tx32X32: return counts.Tx32x32[ctx].AsSpan(); + case TxSize.Tx8X8: + return counts.Tx8x8[ctx].AsSpan(); + case TxSize.Tx16X16: + return counts.Tx16x16[ctx].AsSpan(); + case TxSize.Tx32X32: + return counts.Tx32x32[ctx].AsSpan(); default: Debug.Assert(false, "Invalid maxTxSize."); return Span.Empty; @@ -129,13 +135,13 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 } } - Debug.Assert(segmentId >= 0 && segmentId < Constants.MaxSegments); + Debug.Assert(segmentId is >= 0 and < Constants.MaxSegments); return segmentId; } private static void SetSegmentId(ref Vp9Common cm, int miOffset, int xMis, int yMis, int segmentId) { - Debug.Assert(segmentId >= 0 && segmentId < Constants.MaxSegments); + Debug.Assert(segmentId is >= 0 and < Constants.MaxSegments); for (int y = 0; y < yMis; y++) { @@ -412,7 +418,6 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 { BlockSize bsize = mi.SbType; - switch (bsize) { case BlockSize.Block4X4: @@ -494,7 +499,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 ZeroPair(ref mv); break; } - default: return false; + default: + return false; } return ret; @@ -609,7 +615,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 bool earlyBreak = mode != PredictionMode.NearMv; // Blank the reference vector list - mvRefList.Slice(0, Constants.MaxMvRefCandidates).Fill(new Mv()); + mvRefList[..Constants.MaxMvRefCandidates].Clear(); i = 0; if (isSub8X8 != 0) @@ -760,7 +766,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 refmvCount = 1; } - Done: + Done: // Clamp vectors for (i = 0; i < refmvCount; ++i) { @@ -950,7 +956,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 int j = (idy * 2) + idx; bMode = ReadInterMode(ref cm, ref xd, ref r, interModeCtx); - if (bMode == PredictionMode.NearestMv || bMode == PredictionMode.NearMv) + if (bMode is PredictionMode.NearestMv or PredictionMode.NearMv) { for (refr = 0; refr < 1 + isCompound; ++refr) { @@ -1018,7 +1024,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 private static PredictionMode LeftBlockMode(Ptr curMi, Ptr leftMi, int b) { - if (b == 0 || b == 2) + if (b is 0 or 2) { if (leftMi.IsNull || leftMi.Value.IsInterBlock()) { @@ -1028,13 +1034,13 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 return leftMi.Value.GetYMode(b + 1); } - Debug.Assert(b == 1 || b == 3); + Debug.Assert(b is 1 or 3); return curMi.Value.Bmi[b - 1].Mode; } private static PredictionMode AboveBlockMode(Ptr curMi, Ptr aboveMi, int b) { - if (b == 0 || b == 1) + if (b is 0 or 1) { if (aboveMi.IsNull || aboveMi.Value.IsInterBlock()) { @@ -1044,7 +1050,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 return aboveMi.Value.GetYMode(b + 2); } - Debug.Assert(b == 2 || b == 3); + Debug.Assert(b is 2 or 3); return curMi.Value.Bmi[b - 2].Mode; } @@ -1154,4 +1160,4 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 } } } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Graphics.Nvdec.Vp9/Decoder.cs b/src/Ryujinx.Graphics.Nvdec.Vp9/Decoder.cs index 009611b27..f788d57f4 100644 --- a/src/Ryujinx.Graphics.Nvdec.Vp9/Decoder.cs +++ b/src/Ryujinx.Graphics.Nvdec.Vp9/Decoder.cs @@ -1,4 +1,4 @@ -using Ryujinx.Common.Memory; +using Ryujinx.Common.Memory; using Ryujinx.Graphics.Nvdec.Vp9.Common; using Ryujinx.Graphics.Nvdec.Vp9.Types; using Ryujinx.Graphics.Video; @@ -29,49 +29,53 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 ReadOnlySpan mvsIn, Span mvsOut) { - Vp9Common cm = new(); + Vp9Common cm = new() + { + FrameType = pictureInfo.IsKeyFrame ? FrameType.KeyFrame : FrameType.InterFrame, + IntraOnly = pictureInfo.IntraOnly, - cm.FrameType = pictureInfo.IsKeyFrame ? FrameType.KeyFrame : FrameType.InterFrame; - cm.IntraOnly = pictureInfo.IntraOnly; + Width = output.Width, + Height = output.Height, + SubsamplingX = 1, + SubsamplingY = 1, - cm.Width = output.Width; - cm.Height = output.Height; - cm.SubsamplingX = 1; - cm.SubsamplingY = 1; + UsePrevFrameMvs = pictureInfo.UsePrevInFindMvRefs, - cm.UsePrevFrameMvs = pictureInfo.UsePrevInFindMvRefs; + RefFrameSignBias = pictureInfo.RefFrameSignBias, - cm.RefFrameSignBias = pictureInfo.RefFrameSignBias; + BaseQindex = pictureInfo.BaseQIndex, + YDcDeltaQ = pictureInfo.YDcDeltaQ, + UvAcDeltaQ = pictureInfo.UvAcDeltaQ, + UvDcDeltaQ = pictureInfo.UvDcDeltaQ, - cm.BaseQindex = pictureInfo.BaseQIndex; - cm.YDcDeltaQ = pictureInfo.YDcDeltaQ; - cm.UvAcDeltaQ = pictureInfo.UvAcDeltaQ; - cm.UvDcDeltaQ = pictureInfo.UvDcDeltaQ; + TxMode = (TxMode)pictureInfo.TransformMode, + + AllowHighPrecisionMv = pictureInfo.AllowHighPrecisionMv, + + InterpFilter = (byte)pictureInfo.InterpFilter, + + ReferenceMode = (ReferenceMode)pictureInfo.ReferenceMode, + + CompFixedRef = pictureInfo.CompFixedRef, + CompVarRef = pictureInfo.CompVarRef, + + BitDepth = BitDepth.Bits8, + + Log2TileCols = pictureInfo.Log2TileCols, + Log2TileRows = pictureInfo.Log2TileRows, + + Fc = new Ptr(ref pictureInfo.Entropy), + Counts = new Ptr(ref pictureInfo.BackwardUpdateCounts) + }; cm.Mb.Lossless = pictureInfo.Lossless; cm.Mb.Bd = 8; - cm.TxMode = (TxMode)pictureInfo.TransformMode; - - cm.AllowHighPrecisionMv = pictureInfo.AllowHighPrecisionMv; - - cm.InterpFilter = (byte)pictureInfo.InterpFilter; - if (cm.InterpFilter != Constants.Switchable) { cm.InterpFilter = LiteralToFilter[cm.InterpFilter]; } - cm.ReferenceMode = (ReferenceMode)pictureInfo.ReferenceMode; - - cm.CompFixedRef = pictureInfo.CompFixedRef; - cm.CompVarRef = pictureInfo.CompVarRef; - - cm.BitDepth = BitDepth.Bits8; - - cm.Log2TileCols = pictureInfo.Log2TileCols; - cm.Log2TileRows = pictureInfo.Log2TileRows; - cm.Seg.Enabled = pictureInfo.SegmentEnabled; cm.Seg.UpdateMap = pictureInfo.SegmentMapUpdate; cm.Seg.TemporalUpdate = pictureInfo.SegmentMapTemporalUpdate; @@ -85,9 +89,6 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 cm.Lf.RefDeltas = pictureInfo.RefDeltas; cm.Lf.ModeDeltas = pictureInfo.ModeDeltas; - cm.Fc = new Ptr(ref pictureInfo.Entropy); - cm.Counts = new Ptr(ref pictureInfo.BackwardUpdateCounts); - cm.FrameRefs[0].Buf = (Surface)pictureInfo.LastReference; cm.FrameRefs[1].Buf = (Surface)pictureInfo.GoldenReference; cm.FrameRefs[2].Buf = (Surface)pictureInfo.AltReference; @@ -164,4 +165,4 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 _allocator.Dispose(); } } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Graphics.Nvdec.Vp9/Detokenize.cs b/src/Ryujinx.Graphics.Nvdec.Vp9/Detokenize.cs index 092d298dc..530eec441 100644 --- a/src/Ryujinx.Graphics.Nvdec.Vp9/Detokenize.cs +++ b/src/Ryujinx.Graphics.Nvdec.Vp9/Detokenize.cs @@ -1,4 +1,4 @@ -using Ryujinx.Common.Memory; +using Ryujinx.Common.Memory; using Ryujinx.Graphics.Nvdec.Vp9.Dsp; using Ryujinx.Graphics.Nvdec.Vp9.Types; using Ryujinx.Graphics.Video; @@ -48,7 +48,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 ReadOnlySpan cat6Prob = xd.Bd == 12 ? Luts.Cat6ProbHigh12 : xd.Bd == 10 - ? Luts.Cat6ProbHigh12.Slice(2) + ? Luts.Cat6ProbHigh12[2..] : Luts.Cat6Prob; int cat6Bits = xd.Bd == 12 ? 18 : xd.Bd == 10 ? 16 : 14; // Keep value, range, and count as locals. The compiler produces better @@ -61,7 +61,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 { int val = -1; band = bandTranslate[0]; - bandTranslate = bandTranslate.Slice(1); + bandTranslate = bandTranslate[1..]; ref Array3 prob = ref coefProbs[band][ctx]; if (!xd.Counts.IsNull) { @@ -98,7 +98,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 ctx = GetCoefContext(nb, tokenCache, c); band = bandTranslate[0]; - bandTranslate = bandTranslate.Slice(1); + bandTranslate = bandTranslate[1..]; prob = ref coefProbs[band][ctx]; } @@ -234,8 +234,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 ref MacroBlockDPlane pd = ref xd.Plane[plane]; ref Array2 dequant = ref pd.SegDequant[segId]; int eob; - Span a = pd.AboveContext.AsSpan().Slice(x); - Span l = pd.LeftContext.AsSpan().Slice(y); + Span a = pd.AboveContext.AsSpan()[x..]; + Span l = pd.LeftContext.AsSpan()[y..]; int ctx; int ctxShiftA = 0; int ctxShiftL = 0; @@ -320,4 +320,4 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 return eob; } } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Graphics.Nvdec.Vp9/Dsp/Convolve.cs b/src/Ryujinx.Graphics.Nvdec.Vp9/Dsp/Convolve.cs index 8cea09aec..839a9c400 100644 --- a/src/Ryujinx.Graphics.Nvdec.Vp9/Dsp/Convolve.cs +++ b/src/Ryujinx.Graphics.Nvdec.Vp9/Dsp/Convolve.cs @@ -1,4 +1,4 @@ -using Ryujinx.Common.Memory; +using Ryujinx.Common.Memory; using Ryujinx.Graphics.Nvdec.Vp9.Common; using System.Diagnostics; using System.Runtime.CompilerServices; @@ -944,4 +944,4 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp } } } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Graphics.Nvdec.Vp9/Dsp/Filter.cs b/src/Ryujinx.Graphics.Nvdec.Vp9/Dsp/Filter.cs index 1dbbc8de5..a32221e09 100644 --- a/src/Ryujinx.Graphics.Nvdec.Vp9/Dsp/Filter.cs +++ b/src/Ryujinx.Graphics.Nvdec.Vp9/Dsp/Filter.cs @@ -9,4 +9,4 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp public const int SubpelShifts = 1 << SubpelBits; public const int SubpelTaps = 8; } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Graphics.Nvdec.Vp9/Dsp/IntraPred.cs b/src/Ryujinx.Graphics.Nvdec.Vp9/Dsp/IntraPred.cs index df72e160d..926cc88e3 100644 --- a/src/Ryujinx.Graphics.Nvdec.Vp9/Dsp/IntraPred.cs +++ b/src/Ryujinx.Graphics.Nvdec.Vp9/Dsp/IntraPred.cs @@ -1,4 +1,4 @@ -using Ryujinx.Graphics.Nvdec.Vp9.Common; +using Ryujinx.Graphics.Nvdec.Vp9.Common; namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp { diff --git a/src/Ryujinx.Graphics.Nvdec.Vp9/Dsp/InvTxfm.cs b/src/Ryujinx.Graphics.Nvdec.Vp9/Dsp/InvTxfm.cs index a36ea2dcf..7a1601395 100644 --- a/src/Ryujinx.Graphics.Nvdec.Vp9/Dsp/InvTxfm.cs +++ b/src/Ryujinx.Graphics.Nvdec.Vp9/Dsp/InvTxfm.cs @@ -1,4 +1,4 @@ -using Ryujinx.Graphics.Nvdec.Vp9.Common; +using Ryujinx.Graphics.Nvdec.Vp9.Common; using System; using System.Diagnostics; using System.Runtime.CompilerServices; @@ -114,8 +114,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp op[1] = WrapLow(b1); op[2] = WrapLow(c1); op[3] = WrapLow(d1); - ip = ip.Slice(4); - op = op.Slice(4); + ip = ip[4..]; + op = op[4..]; } Span ip2 = output; @@ -137,8 +137,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp dest[stride * 2] = ClipPixelAdd(dest[stride * 2], WrapLow(c1)); dest[stride * 3] = ClipPixelAdd(dest[stride * 3], WrapLow(d1)); - ip2 = ip2.Slice(1); - dest = dest.Slice(1); + ip2 = ip2[1..]; + dest = dest[1..]; } } @@ -165,8 +165,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp dest[stride * 1] = ClipPixelAdd(dest[stride * 1], e1); dest[stride * 2] = ClipPixelAdd(dest[stride * 2], e1); dest[stride * 3] = ClipPixelAdd(dest[stride * 3], e1); - ip2 = ip2.Slice(1); - dest = dest.Slice(1); + ip2 = ip2[1..]; + dest = dest[1..]; } } @@ -180,7 +180,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp if ((x0 | x1 | x2 | x3) == 0) { - output.Slice(0, 4).Clear(); + output[..4].Clear(); return; } @@ -244,8 +244,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp for (int i = 0; i < 4; ++i) { Idct4(input, outptr); - input = input.Slice(4); - outptr = outptr.Slice(4); + input = input[4..]; + outptr = outptr[4..]; } // Columns @@ -279,7 +279,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp dest[1] = ClipPixelAdd(dest[1], a1); dest[2] = ClipPixelAdd(dest[2], a1); dest[3] = ClipPixelAdd(dest[3], a1); - dest = dest.Slice(stride); + dest = dest[stride..]; } } @@ -297,7 +297,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp if ((x0 | x1 | x2 | x3 | x4 | x5 | x6 | x7) == 0) { - output.Slice(0, 8).Clear(); + output[..8].Clear(); return; } @@ -430,8 +430,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp for (int i = 0; i < 8; ++i) { Idct8(input, outptr); - input = input.Slice(8); - outptr = outptr.Slice(8); + input = input[8..]; + outptr = outptr[8..]; } // Then transform columns @@ -466,8 +466,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp for (int i = 0; i < 4; ++i) { Idct8(input, outptr); - input = input.Slice(8); - outptr = outptr.Slice(8); + input = input[8..]; + outptr = outptr[8..]; } // Then transform columns @@ -501,7 +501,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp dest[i] = ClipPixelAdd(dest[i], a1); } - dest = dest.Slice(stride); + dest = dest[stride..]; } } @@ -528,7 +528,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp if ((x0 | x1 | x2 | x3 | x4 | x5 | x6 | x7 | x8 | x9 | x10 | x11 | x12 | x13 | x14 | x15) == 0) { - output.Slice(0, 16).Clear(); + output[..16].Clear(); return; } @@ -854,8 +854,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp for (int i = 0; i < 16; ++i) { Idct16(input, outptr); - input = input.Slice(16); - outptr = outptr.Slice(16); + input = input[16..]; + outptr = outptr[16..]; } // Then transform columns @@ -890,8 +890,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp for (int i = 0; i < 8; ++i) { Idct16(input, outptr); - input = input.Slice(16); - outptr = outptr.Slice(16); + input = input[16..]; + outptr = outptr[16..]; } // Then transform columns @@ -926,8 +926,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp for (int i = 0; i < 4; ++i) { Idct16(input, outptr); - input = input.Slice(16); - outptr = outptr.Slice(16); + input = input[16..]; + outptr = outptr[16..]; } // Then transform columns @@ -961,7 +961,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp dest[i] = ClipPixelAdd(dest[i], a1); } - dest = dest.Slice(stride); + dest = dest[stride..]; } } @@ -1358,11 +1358,11 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp } else { - outptr.Slice(0, 32).Clear(); + outptr[..32].Clear(); } - input = input.Slice(32); - outptr = outptr.Slice(32); + input = input[32..]; + outptr = outptr[32..]; } // Columns @@ -1397,8 +1397,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp for (int i = 0; i < 16; ++i) { Idct32(input, outptr); - input = input.Slice(32); - outptr = outptr.Slice(32); + input = input[32..]; + outptr = outptr[32..]; } // Columns @@ -1433,8 +1433,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp for (int i = 0; i < 8; ++i) { Idct32(input, outptr); - input = input.Slice(32); - outptr = outptr.Slice(32); + input = input[32..]; + outptr = outptr[32..]; } // Columns @@ -1469,7 +1469,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp dest[i] = ClipPixelAdd(dest[i], a1); } - dest = dest.Slice(stride); + dest = dest[stride..]; } } @@ -1501,8 +1501,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp op[1] = HighbdWrapLow(b1, bd); op[2] = HighbdWrapLow(c1, bd); op[3] = HighbdWrapLow(d1, bd); - ip = ip.Slice(4); - op = op.Slice(4); + ip = ip[4..]; + op = op[4..]; } ReadOnlySpan ip2 = output; @@ -1524,8 +1524,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp dest[stride * 2] = HighbdClipPixelAdd(dest[stride * 2], HighbdWrapLow(c1, bd), bd); dest[stride * 3] = HighbdClipPixelAdd(dest[stride * 3], HighbdWrapLow(d1, bd), bd); - ip2 = ip2.Slice(1); - dest = dest.Slice(1); + ip2 = ip2[1..]; + dest = dest[1..]; } } @@ -1552,8 +1552,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp dest[stride * 1] = HighbdClipPixelAdd(dest[stride * 1], e1, bd); dest[stride * 2] = HighbdClipPixelAdd(dest[stride * 2], e1, bd); dest[stride * 3] = HighbdClipPixelAdd(dest[stride * 3], e1, bd); - ip2 = ip2.Slice(1); - dest = dest.Slice(1); + ip2 = ip2[1..]; + dest = dest[1..]; } } @@ -1568,13 +1568,13 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp if (DetectInvalidHighbdInput(input, 4) != 0) { Debug.Assert(false, "invalid highbd txfm input"); - output.Slice(0, 4).Clear(); + output[..4].Clear(); return; } if ((x0 | x1 | x2 | x3) == 0) { - output.Slice(0, 4).Clear(); + output[..4].Clear(); return; } @@ -1611,7 +1611,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp if (DetectInvalidHighbdInput(input, 4) != 0) { Debug.Assert(false, "invalid highbd txfm input"); - output.Slice(0, 4).Clear(); + output[..4].Clear(); return; } @@ -1644,8 +1644,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp for (int i = 0; i < 4; ++i) { HighbdIdct4(input, outptr, bd); - input = input.Slice(4); - outptr = outptr.Slice(4); + input = input[4..]; + outptr = outptr[4..]; } // Columns @@ -1679,7 +1679,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp dest[1] = HighbdClipPixelAdd(dest[1], a1, bd); dest[2] = HighbdClipPixelAdd(dest[2], a1, bd); dest[3] = HighbdClipPixelAdd(dest[3], a1, bd); - dest = dest.Slice(stride); + dest = dest[stride..]; } } @@ -1698,13 +1698,13 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp if (DetectInvalidHighbdInput(input, 8) != 0) { Debug.Assert(false, "invalid highbd txfm input"); - output.Slice(0, 8).Clear(); + output[..8].Clear(); return; } if ((x0 | x1 | x2 | x3 | x4 | x5 | x6 | x7) == 0) { - output.Slice(0, 8).Clear(); + output[..8].Clear(); return; } @@ -1777,7 +1777,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp if (DetectInvalidHighbdInput(input, 8) != 0) { Debug.Assert(false, "invalid highbd txfm input"); - output.Slice(0, 8).Clear(); + output[..8].Clear(); return; } @@ -1835,8 +1835,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp for (int i = 0; i < 8; ++i) { HighbdIdct8(input, outptr, bd); - input = input.Slice(8); - outptr = outptr.Slice(8); + input = input[8..]; + outptr = outptr[8..]; } // Then transform columns @@ -1871,8 +1871,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp for (int i = 0; i < 4; ++i) { HighbdIdct8(input, outptr, bd); - input = input.Slice(8); - outptr = outptr.Slice(8); + input = input[8..]; + outptr = outptr[8..]; } // Then transform columns @@ -1906,7 +1906,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp dest[i] = HighbdClipPixelAdd(dest[i], a1, bd); } - dest = dest.Slice(stride); + dest = dest[stride..]; } } @@ -1933,13 +1933,13 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp if (DetectInvalidHighbdInput(input, 16) != 0) { Debug.Assert(false, "invalid highbd txfm input"); - output.Slice(0, 16).Clear(); + output[..16].Clear(); return; } if ((x0 | x1 | x2 | x3 | x4 | x5 | x6 | x7 | x8 | x9 | x10 | x11 | x12 | x13 | x14 | x15) == 0) { - output.Slice(0, 16).Clear(); + output[..16].Clear(); return; } @@ -2095,7 +2095,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp if (DetectInvalidHighbdInput(input, 16) != 0) { Debug.Assert(false, "invalid highbd txfm input"); - output.Slice(0, 16).Clear(); + output[..16].Clear(); return; } @@ -2272,8 +2272,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp for (int i = 0; i < 16; ++i) { HighbdIdct16(input, outptr, bd); - input = input.Slice(16); - outptr = outptr.Slice(16); + input = input[16..]; + outptr = outptr[16..]; } // Then transform columns @@ -2308,8 +2308,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp for (int i = 0; i < 8; ++i) { HighbdIdct16(input, outptr, bd); - input = input.Slice(16); - outptr = outptr.Slice(16); + input = input[16..]; + outptr = outptr[16..]; } // Then transform columns @@ -2325,7 +2325,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp for (int j = 0; j < 16; ++j) { destT[i] = HighbdClipPixelAdd(destT[i], BitUtils.RoundPowerOfTwo(tempOut[j], 6), bd); - destT = destT.Slice(stride); + destT = destT[stride..]; } } } @@ -2345,8 +2345,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp for (int i = 0; i < 4; ++i) { HighbdIdct16(input, outptr, bd); - input = input.Slice(16); - outptr = outptr.Slice(16); + input = input[16..]; + outptr = outptr[16..]; } // Then transform columns @@ -2380,7 +2380,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp dest[i] = HighbdClipPixelAdd(dest[i], a1, bd); } - dest = dest.Slice(stride); + dest = dest[stride..]; } } @@ -2394,7 +2394,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp if (DetectInvalidHighbdInput(input, 32) != 0) { Debug.Assert(false, "invalid highbd txfm input"); - output.Slice(0, 32).Clear(); + output[..32].Clear(); return; } @@ -2784,11 +2784,11 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp } else { - outptr.Slice(0, 32).Clear(); + outptr[..32].Clear(); } - input = input.Slice(32); - outptr = outptr.Slice(32); + input = input[32..]; + outptr = outptr[32..]; } // Columns @@ -2823,8 +2823,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp for (int i = 0; i < 16; ++i) { HighbdIdct32(input, outptr, bd); - input = input.Slice(32); - outptr = outptr.Slice(32); + input = input[32..]; + outptr = outptr[32..]; } // Columns @@ -2840,7 +2840,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp for (int j = 0; j < 32; ++j) { destT[i] = HighbdClipPixelAdd(destT[i], BitUtils.RoundPowerOfTwo(tempOut[j], 6), bd); - destT = destT.Slice(stride); + destT = destT[stride..]; } } } @@ -2860,8 +2860,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp for (int i = 0; i < 8; ++i) { HighbdIdct32(input, outptr, bd); - input = input.Slice(32); - outptr = outptr.Slice(32); + input = input[32..]; + outptr = outptr[32..]; } // Columns @@ -2896,8 +2896,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp dest[i] = HighbdClipPixelAdd(dest[i], a1, bd); } - dest = dest.Slice(stride); + dest = dest[stride..]; } } } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Graphics.Nvdec.Vp9/Dsp/LoopFilterAuto.cs b/src/Ryujinx.Graphics.Nvdec.Vp9/Dsp/LoopFilterAuto.cs index fbd87e17f..ee33acc5f 100644 --- a/src/Ryujinx.Graphics.Nvdec.Vp9/Dsp/LoopFilterAuto.cs +++ b/src/Ryujinx.Graphics.Nvdec.Vp9/Dsp/LoopFilterAuto.cs @@ -1,4 +1,4 @@ -using Ryujinx.Common.Memory; +using Ryujinx.Common.Memory; using System; using System.Runtime.Intrinsics.X86; @@ -226,4 +226,4 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp } } } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Graphics.Nvdec.Vp9/Dsp/LoopFilterScalar.cs b/src/Ryujinx.Graphics.Nvdec.Vp9/Dsp/LoopFilterScalar.cs index 79c3f1235..dcb779442 100644 --- a/src/Ryujinx.Graphics.Nvdec.Vp9/Dsp/LoopFilterScalar.cs +++ b/src/Ryujinx.Graphics.Nvdec.Vp9/Dsp/LoopFilterScalar.cs @@ -1090,4 +1090,4 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp HighBdMbLpfVerticalEdgeW(s, pitch, blimit, limit, thresh, 16, bd); } } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Graphics.Nvdec.Vp9/Dsp/LoopFilterSse2.cs b/src/Ryujinx.Graphics.Nvdec.Vp9/Dsp/LoopFilterSse2.cs index 0d9f496ae..bf522636a 100644 --- a/src/Ryujinx.Graphics.Nvdec.Vp9/Dsp/LoopFilterSse2.cs +++ b/src/Ryujinx.Graphics.Nvdec.Vp9/Dsp/LoopFilterSse2.cs @@ -1,4 +1,4 @@ -using Ryujinx.Common.Memory; +using Ryujinx.Common.Memory; using System; using System.Runtime.Intrinsics; using System.Runtime.Intrinsics.X86; @@ -133,8 +133,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp } Vector128 ff = Sse2.CompareEqual(zero, zero); - Vector128 q1P1, q0P0, p3P2, p2P1, p1P0, q3Q2, q2Q1, q1Q0, ps1Ps0, qs1Qs0; - Vector128 mask, hev; + Vector128 q1P1, q0P0, p3P2, p2P1, p1P0, q3Q2, q2Q1, q1Q0; p3P2 = Sse2.UnpackLow(Sse2.LoadScalarVector128((long*)(s.ToPointer() - (3 * pitch))), Sse2.LoadScalarVector128((long*)(s.ToPointer() - (4 * pitch)))).AsByte(); @@ -149,8 +148,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp q1Q0 = Sse2.UnpackHigh(q0P0.AsInt64(), q1P1.AsInt64()).AsByte(); q2Q1 = Sse2.UnpackLow(Sse2.ShiftRightLogical128BitLane(q1P1, 8).AsInt64(), q3Q2.AsInt64()).AsByte(); - FilterHevMask(q1P1, q0P0, p3P2, p2P1, p1P0, q3Q2, q2Q1, q1Q0, limitV, threshV, out hev, out mask); - Filter4(p1P0, q1Q0, hev, mask, ff, out ps1Ps0, out qs1Qs0); + FilterHevMask(q1P1, q0P0, p3P2, p2P1, p1P0, q3Q2, q2Q1, q1Q0, limitV, threshV, out Vector128 hev, out Vector128 mask); + Filter4(p1P0, q1Q0, hev, mask, ff, out Vector128 ps1Ps0, out Vector128 qs1Qs0); Sse.StoreHigh((float*)(s.ToPointer() - (2 * pitch)), ps1Ps0.AsSingle()); // *op1 Sse2.StoreScalar((long*)(s.ToPointer() - (1 * pitch)), ps1Ps0.AsInt64()); // *op0 @@ -178,8 +177,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp Vector128 ff = Sse2.CompareEqual(zero, zero); Vector128 x0, x1, x2, x3; - Vector128 q1P1, q0P0, p3P2, p2P1, p1P0, q3Q2, q2Q1, q1Q0, ps1Ps0, qs1Qs0; - Vector128 mask, hev; + Vector128 q1P1, q0P0, p3P2, p2P1, p1P0, q3Q2, q2Q1, q1Q0; // 00 10 01 11 02 12 03 13 04 14 05 15 06 16 07 17 q1Q0 = Sse2.UnpackLow( @@ -230,8 +228,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp p2P1 = Sse2.UnpackLow(q1P1.AsInt64(), p3P2.AsInt64()).AsByte(); q2Q1 = Sse2.UnpackLow(Sse2.ShiftRightLogical128BitLane(q1P1, 8).AsInt64(), q3Q2.AsInt64()).AsByte(); - FilterHevMask(q1P1, q0P0, p3P2, p2P1, p1P0, q3Q2, q2Q1, q1Q0, limitV, threshV, out hev, out mask); - Filter4(p1P0, q1Q0, hev, mask, ff, out ps1Ps0, out qs1Qs0); + FilterHevMask(q1P1, q0P0, p3P2, p2P1, p1P0, q3Q2, q2Q1, q1Q0, limitV, threshV, out Vector128 hev, out Vector128 mask); + Filter4(p1P0, q1Q0, hev, mask, ff, out Vector128 ps1Ps0, out Vector128 qs1Qs0); // Transpose 8x4 to 4x8 // qs1qs0: 20 21 22 23 24 25 26 27 30 31 32 33 34 34 36 37 @@ -1262,6 +1260,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp flat = Sse2.CompareEqual(flat, zero); flat = Sse2.And(flat, mask); } + { Vector128 four = Vector128.Create((short)4); ArrayPtr src = s; @@ -1834,4 +1833,4 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp Transpose8X16(tDst.Slice(8), tDst.Slice(8 + (8 * 16)), 16, s.Slice(-8 + (8 * pitch)), pitch); } } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Graphics.Nvdec.Vp9/Dsp/Prob.cs b/src/Ryujinx.Graphics.Nvdec.Vp9/Dsp/Prob.cs index df82dc7a9..dc89ecfd4 100644 --- a/src/Ryujinx.Graphics.Nvdec.Vp9/Dsp/Prob.cs +++ b/src/Ryujinx.Graphics.Nvdec.Vp9/Dsp/Prob.cs @@ -1,4 +1,4 @@ -using Ryujinx.Graphics.Nvdec.Vp9.Common; +using Ryujinx.Graphics.Nvdec.Vp9.Common; using System; using System.Diagnostics; @@ -68,4 +68,4 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp TreeMergeProbsImpl(0, tree, preProbs, counts, probs); } } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Graphics.Nvdec.Vp9/Dsp/Reader.cs b/src/Ryujinx.Graphics.Nvdec.Vp9/Dsp/Reader.cs index e6f34d266..6b570cc60 100644 --- a/src/Ryujinx.Graphics.Nvdec.Vp9/Dsp/Reader.cs +++ b/src/Ryujinx.Graphics.Nvdec.Vp9/Dsp/Reader.cs @@ -1,4 +1,4 @@ -using Ryujinx.Common.Memory; +using Ryujinx.Common.Memory; using Ryujinx.Graphics.Nvdec.Vp9.Types; using System; using System.Buffers.Binary; @@ -63,7 +63,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp ulong bigEndianValues = BinaryPrimitives.ReadUInt64BigEndian(buffer); nv = bigEndianValues >> (BdValueSize - bits); count += bits; - buffer = buffer.Slice(bits >> 3); + buffer = buffer[(bits >> 3)..]; value = Value | (nv << (shift & 0x7)); } else @@ -82,7 +82,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp { count += 8; value |= (ulong)buffer[0] << shift; - buffer = buffer.Slice(1); + buffer = buffer[1..]; shift -= 8; } } @@ -96,7 +96,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp Count = count; } - public bool HasError() + public readonly bool HasError() { // Check if we have reached the end of the buffer. // @@ -112,7 +112,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp // // 1 if we have tried to decode bits after the end of stream was encountered. // 0 No error. - return Count > BdValueSize && Count < LotsOfBits; + return Count is > BdValueSize and < LotsOfBits; } public int Read(int prob) @@ -149,6 +149,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp value <<= shift; count -= shift; } + Value = value; Count = count; Range = range; @@ -200,14 +201,15 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp if (value >= bigsplit) { - range = range - split; - value = value - bigsplit; + range -= split; + value -= bigsplit; { int shift = _norm[range]; range <<= shift; value <<= shift; count -= shift; } + return 1; } @@ -218,13 +220,14 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp value <<= shift; count -= shift; } + return 0; } public ArrayPtr FindEnd() { // Find the end of the coded buffer - while (Count > 8 && Count < BdValueSize) + while (Count is > 8 and < BdValueSize) { Count -= 8; _buffer = _buffer.Slice(-1); @@ -307,4 +310,4 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp } } } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Graphics.Nvdec.Vp9/Dsp/TxfmCommon.cs b/src/Ryujinx.Graphics.Nvdec.Vp9/Dsp/TxfmCommon.cs index d84c0bb16..175f43704 100644 --- a/src/Ryujinx.Graphics.Nvdec.Vp9/Dsp/TxfmCommon.cs +++ b/src/Ryujinx.Graphics.Nvdec.Vp9/Dsp/TxfmCommon.cs @@ -51,4 +51,4 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp public const short SinPi39 = 13377; public const short SinPi49 = 15212; } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Graphics.Nvdec.Vp9/Entropy.cs b/src/Ryujinx.Graphics.Nvdec.Vp9/Entropy.cs index 380879453..736b78fc6 100644 --- a/src/Ryujinx.Graphics.Nvdec.Vp9/Entropy.cs +++ b/src/Ryujinx.Graphics.Nvdec.Vp9/Entropy.cs @@ -1,4 +1,4 @@ -using Ryujinx.Graphics.Nvdec.Vp9.Types; +using Ryujinx.Graphics.Nvdec.Vp9.Types; using System; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; @@ -620,4 +620,4 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 internal const int CoefCountSatAfterKey = 24; internal const int CoefMaxUpdateFactorAfterKey = 128; } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Graphics.Nvdec.Vp9/EntropyMode.cs b/src/Ryujinx.Graphics.Nvdec.Vp9/EntropyMode.cs index 586045976..624acbaa5 100644 --- a/src/Ryujinx.Graphics.Nvdec.Vp9/EntropyMode.cs +++ b/src/Ryujinx.Graphics.Nvdec.Vp9/EntropyMode.cs @@ -1,4 +1,4 @@ -using Ryujinx.Common.Memory; +using Ryujinx.Common.Memory; using Ryujinx.Graphics.Nvdec.Vp9.Common; using Ryujinx.Graphics.Nvdec.Vp9.Types; using Ryujinx.Graphics.Video; @@ -252,35 +252,35 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 private static readonly byte[] _defaultSingleRefP = [33, 16, 77, 74, 142, 142, 172, 170, 238, 247]; private static readonly byte[] _defaultTxProbs = [3, 136, 37, 5, 52, 13, 20, 152, 15, 101, 100, 66]; - static EntropyMode() - { - byte[][] kfPartitionProbs = - [ - // 8x8 . 4x4 - [158, 97, 94], // a/l both not split - [93, 24, 99], // a split, l not split - [85, 119, 44], // l split, a not split - [62, 59, 67], // a/l both split + //static EntropyMode() + //{ + // byte[][] kfPartitionProbs = + // [ + // // 8x8 . 4x4 + // [158, 97, 94], // a/l both not split + // [93, 24, 99], // a split, l not split + // [85, 119, 44], // l split, a not split + // [62, 59, 67], // a/l both split - // 16x16 . 8x8 - [149, 53, 53], // a/l both not split - [94, 20, 48], // a split, l not split - [83, 53, 24], // l split, a not split - [52, 18, 18], // a/l both split + // // 16x16 . 8x8 + // [149, 53, 53], // a/l both not split + // [94, 20, 48], // a split, l not split + // [83, 53, 24], // l split, a not split + // [52, 18, 18], // a/l both split - // 32x32 . 16x16 - [150, 40, 39], // a/l both not split - [78, 12, 26], // a split, l not split - [67, 33, 11], // l split, a not split - [24, 7, 5], // a/l both split + // // 32x32 . 16x16 + // [150, 40, 39], // a/l both not split + // [78, 12, 26], // a split, l not split + // [67, 33, 11], // l split, a not split + // [24, 7, 5], // a/l both split - // 64x64 . 32x32 - [174, 35, 49], // a/l both not split - [68, 11, 27], // a split, l not split - [57, 15, 9], // l split, a not split - [12, 3, 3] // a/l both split - ]; - } + // // 64x64 . 32x32 + // [174, 35, 49], // a/l both not split + // [68, 11, 27], // a split, l not split + // [57, 15, 9], // l split, a not split + // [12, 3, 3] // a/l both split + // ]; + //} private static readonly byte[] _defaultSkipProbs = [192, 128, 64]; @@ -296,7 +296,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 Entropy.CopyProbs(ref fc.CompInterProb, _defaultCompInterP); Entropy.CopyProbs(ref fc.CompRefProb, _defaultCompRefP); Entropy.CopyProbs(ref fc.SingleRefProb, _defaultSingleRefP); - Entropy.CopyProbs(ref fc.Tx32x32Prob, _defaultTxProbs.AsSpan().Slice(0, 6)); + Entropy.CopyProbs(ref fc.Tx32x32Prob, _defaultTxProbs.AsSpan()[..6]); Entropy.CopyProbs(ref fc.Tx16x16Prob, _defaultTxProbs.AsSpan().Slice(6, 4)); Entropy.CopyProbs(ref fc.Tx8x8Prob, _defaultTxProbs.AsSpan().Slice(10, 2)); Entropy.CopyProbs(ref fc.SkipProb, _defaultSkipProbs); @@ -387,4 +387,4 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 cm.FrameContextIdx = 0; } } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Graphics.Nvdec.Vp9/EntropyMv.cs b/src/Ryujinx.Graphics.Nvdec.Vp9/EntropyMv.cs index 4fa8e6d4c..511460a19 100644 --- a/src/Ryujinx.Graphics.Nvdec.Vp9/EntropyMv.cs +++ b/src/Ryujinx.Graphics.Nvdec.Vp9/EntropyMv.cs @@ -1,4 +1,4 @@ -using Ryujinx.Common.Memory; +using Ryujinx.Common.Memory; using Ryujinx.Graphics.Nvdec.Vp9.Types; using Ryujinx.Graphics.Video; using System.Diagnostics; @@ -12,7 +12,6 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 /* Symbols for coding which components are zero jointly */ public const int Joints = 4; - public static readonly sbyte[] JointTree = [ -(sbyte)MvJointType.Zero, 2, -(sbyte)MvJointType.Hnzvz, 4, @@ -33,12 +32,12 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 private static bool JointVertical(MvJointType type) { - return type == MvJointType.Hzvnz || type == MvJointType.Hnzvnz; + return type is MvJointType.Hzvnz or MvJointType.Hnzvnz; } private static bool JointHorizontal(MvJointType type) { - return type == MvJointType.Hnzvz || type == MvJointType.Hnzvnz; + return type is MvJointType.Hnzvz or MvJointType.Hnzvnz; } private static readonly byte[] _logInBase2 = diff --git a/src/Ryujinx.Graphics.Nvdec.Vp9/FrameBuffers.cs b/src/Ryujinx.Graphics.Nvdec.Vp9/FrameBuffers.cs index a5692c446..ac28735ec 100644 --- a/src/Ryujinx.Graphics.Nvdec.Vp9/FrameBuffers.cs +++ b/src/Ryujinx.Graphics.Nvdec.Vp9/FrameBuffers.cs @@ -1,4 +1,4 @@ -using Ryujinx.Common.Memory; +using Ryujinx.Common.Memory; using Ryujinx.Graphics.Nvdec.Vp9.Common; using Ryujinx.Graphics.Nvdec.Vp9.Types; diff --git a/src/Ryujinx.Graphics.Nvdec.Vp9/Idct.cs b/src/Ryujinx.Graphics.Nvdec.Vp9/Idct.cs index f080fc825..2796a56e9 100644 --- a/src/Ryujinx.Graphics.Nvdec.Vp9/Idct.cs +++ b/src/Ryujinx.Graphics.Nvdec.Vp9/Idct.cs @@ -1,4 +1,4 @@ -using Ryujinx.Graphics.Nvdec.Vp9.Common; +using Ryujinx.Graphics.Nvdec.Vp9.Common; using Ryujinx.Graphics.Nvdec.Vp9.Types; using System; using static Ryujinx.Graphics.Nvdec.Vp9.Dsp.InvTxfm; @@ -11,7 +11,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 private delegate void HighbdTransform1D(ReadOnlySpan input, Span output, int bd); - private struct Transform2D + private readonly struct Transform2D { public readonly Transform1D Cols; // Vertical and horizontal public readonly Transform1D Rows; // Vertical and horizontal @@ -23,7 +23,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 } } - private struct HighbdTransform2D + private readonly struct HighbdTransform2D { public readonly HighbdTransform1D Cols; // Vertical and horizontal public readonly HighbdTransform1D Rows; // Vertical and horizontal @@ -54,8 +54,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 for (int i = 0; i < 4; ++i) { _iht4[txType].Rows(input, outptr); - input = input.Slice(4); - outptr = outptr.Slice(4); + input = input[4..]; + outptr = outptr[4..]; } // Inverse transform column vectors @@ -95,8 +95,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 for (int i = 0; i < 8; ++i) { ht.Rows(input, outptr); - input = input.Slice(8); - outptr = outptr.Slice(8); + input = input[8..]; + outptr = outptr[8..]; } // Inverse transform column vectors @@ -136,8 +136,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 for (int i = 0; i < 16; ++i) { ht.Rows(input, outptr); - input = input.Slice(16); - outptr = outptr.Slice(16); + input = input[16..]; + outptr = outptr[16..]; } // Columns @@ -305,8 +305,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 for (int i = 0; i < 4; ++i) { _highbdIht4[txType].Rows(input, outptr, bd); - input = input.Slice(4); - outptr = outptr.Slice(4); + input = input[4..]; + outptr = outptr[4..]; } // Inverse transform column vectors. @@ -346,8 +346,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 for (int i = 0; i < 8; ++i) { ht.Rows(input, outptr, bd); - input = input.Slice(8); - outptr = output.Slice(8); + input = input[8..]; + outptr = output[8..]; } // Inverse transform column vectors. @@ -388,8 +388,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 for (int i = 0; i < 16; ++i) { ht.Rows(input, outptr, bd); - input = input.Slice(16); - outptr = output.Slice(16); + input = input[16..]; + outptr = output[16..]; } // Columns @@ -540,4 +540,4 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 } } } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Graphics.Nvdec.Vp9/InternalErrorException.cs b/src/Ryujinx.Graphics.Nvdec.Vp9/InternalErrorException.cs index efcd9c23b..6d74e09f6 100644 --- a/src/Ryujinx.Graphics.Nvdec.Vp9/InternalErrorException.cs +++ b/src/Ryujinx.Graphics.Nvdec.Vp9/InternalErrorException.cs @@ -12,4 +12,4 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 { } } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Graphics.Nvdec.Vp9/InternalErrorInfo.cs b/src/Ryujinx.Graphics.Nvdec.Vp9/InternalErrorInfo.cs index 9acfc211d..cfec81ed1 100644 --- a/src/Ryujinx.Graphics.Nvdec.Vp9/InternalErrorInfo.cs +++ b/src/Ryujinx.Graphics.Nvdec.Vp9/InternalErrorInfo.cs @@ -11,4 +11,4 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 throw new InternalErrorException(message); } } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Graphics.Nvdec.Vp9/LoopFilter.cs b/src/Ryujinx.Graphics.Nvdec.Vp9/LoopFilter.cs index 937a196dd..ada7ae400 100644 --- a/src/Ryujinx.Graphics.Nvdec.Vp9/LoopFilter.cs +++ b/src/Ryujinx.Graphics.Nvdec.Vp9/LoopFilter.cs @@ -1,4 +1,4 @@ -using Ryujinx.Common.Memory; +using Ryujinx.Common.Memory; using Ryujinx.Graphics.Nvdec.Vp9.Common; using Ryujinx.Graphics.Nvdec.Vp9.Dsp; using Ryujinx.Graphics.Nvdec.Vp9.Types; @@ -62,7 +62,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 _curSbCol.AsSpan().Fill(-1); } - public void SyncRead(int r, int c) + public readonly void SyncRead(int r, int c) { if (_curSbCol == null) { @@ -84,7 +84,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 } } - public void SyncWrite(int r, int c, int sbCols) + public readonly void SyncWrite(int r, int c, int sbCols) { if (_curSbCol == null) { @@ -336,7 +336,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 private static Span GetLfm(ref Types.LoopFilter lf, int miRow, int miCol) { - return lf.Lfm.AsSpan().Slice((miCol >> 3) + ((miRow >> 3) * lf.LfmStride)); + return lf.Lfm.AsSpan()[((miCol >> 3) + ((miRow >> 3) * lf.LfmStride))..]; } // 8x8 blocks in a superblock. A "1" represents the first block in a 16x16 @@ -380,7 +380,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 for (int i = 0; i < bh; i++) { - MemoryMarshal.CreateSpan(ref lfm.LflY[index], 64 - index).Slice(0, bw).Fill((byte)filterLevel); + MemoryMarshal.CreateSpan(ref lfm.LflY[index], 64 - index)[..bw].Fill((byte)filterLevel); index += 8; } @@ -445,7 +445,6 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 const ushort LeftBorderUv = 0x1111; const ushort AboveBorderUv = 0x000f; - // The largest loopfilter we have is 16x16 so we use the 16x16 mask // for 32x32 transforms also. lfm.LeftY[(int)TxSize.Tx16X16] |= lfm.LeftY[(int)TxSize.Tx32X32]; @@ -775,7 +774,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 } ss[0] = ss[0].Slice(8); - lfl = lfl.Slice(1); + lfl = lfl[1..]; mask16X16 >>= 1; mask8X8 >>= 1; mask4X4 >>= 1; @@ -903,7 +902,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 } ss[0] = ss[0].Slice(8); - lfl = lfl.Slice(1); + lfl = lfl[1..]; mask16X16 >>= 1; mask8X8 >>= 1; mask4X4 >>= 1; @@ -1060,7 +1059,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 } s = s.Slice(8 * count); - lfl = lfl.Slice(count); + lfl = lfl[count..]; mask16X16 >>= count; mask8X8 >>= count; mask4X4 >>= count; @@ -1222,7 +1221,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 } s = s.Slice(8 * count); - lfl = lfl.Slice(count); + lfl = lfl[count..]; mask16X16 >>= count; mask8X8 >>= count; mask4X4 >>= count; @@ -1270,7 +1269,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 } s = s.Slice(8); - lfl = lfl.Slice(1); + lfl = lfl[1..]; mask16X16 >>= 1; mask8X8 >>= 1; mask4X4 >>= 1; @@ -1315,7 +1314,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 } s = s.Slice(8); - lfl = lfl.Slice(1); + lfl = lfl[1..]; mask16X16 >>= 1; mask8X8 >>= 1; mask4X4 >>= 1; @@ -1348,7 +1347,6 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 Span mask4X4Int = stackalloc int[Constants.MiBlockSize]; Span lfl = stackalloc byte[Constants.MiBlockSize * Constants.MiBlockSize]; - for (int r = 0; r < Constants.MiBlockSize && miRow + r < cm.MiRows; r += rowStep) { uint mask16X16C = 0; @@ -1478,7 +1476,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 mask4X4C & borderMask, (uint)mask4X4Int[r], cm.LfInfo.Lfthr.AsSpan(), - lfl.Slice(r << 3), + lfl[(r << 3)..], (int)cm.BitDepth); } else @@ -1491,7 +1489,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 mask4X4C & borderMask, (uint)mask4X4Int[r], cm.LfInfo.Lfthr.AsSpan(), - lfl.Slice(r << 3)); + lfl[(r << 3)..]); } dst.Buf = dst.Buf.Slice(8 * dst.Stride); @@ -1532,7 +1530,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 mask4X4R, mask4X4IntR, cm.LfInfo.Lfthr.AsSpan(), - lfl.Slice(r << 3), + lfl[(r << 3)..], (int)cm.BitDepth); } else @@ -1545,7 +1543,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 mask4X4R, mask4X4IntR, cm.LfInfo.Lfthr.AsSpan(), - lfl.Slice(r << 3)); + lfl[(r << 3)..]); } dst.Buf = dst.Buf.Slice(8 * dst.Stride); @@ -1579,7 +1577,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 (uint)mask4X4, (uint)mask4X4Int, cm.LfInfo.Lfthr.AsSpan(), - lfm.LflY.AsSpan().Slice(r << 3), + lfm.LflY.AsSpan()[(r << 3)..], (int)cm.BitDepth); } else @@ -1594,7 +1592,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 (uint)mask4X4, (uint)mask4X4Int, cm.LfInfo.Lfthr.AsSpan(), - lfm.LflY.AsSpan().Slice(r << 3)); + lfm.LflY.AsSpan()[(r << 3)..]); } dst.Buf = dst.Buf.Slice(16 * dst.Stride); @@ -1640,7 +1638,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 mask4X4R, (uint)mask4X4Int & 0xff, cm.LfInfo.Lfthr.AsSpan(), - lfm.LflY.AsSpan().Slice(r << 3), + lfm.LflY.AsSpan()[(r << 3)..], (int)cm.BitDepth); } else @@ -1653,7 +1651,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 mask4X4R, (uint)mask4X4Int & 0xff, cm.LfInfo.Lfthr.AsSpan(), - lfm.LflY.AsSpan().Slice(r << 3)); + lfm.LflY.AsSpan()[(r << 3)..]); } dst.Buf = dst.Buf.Slice(8 * dst.Stride); @@ -1700,7 +1698,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 mask4X4, mask4X4Int, cm.LfInfo.Lfthr.AsSpan(), - lflUv.Slice(r << 1), + lflUv[(r << 1)..], (int)cm.BitDepth); } else @@ -1715,7 +1713,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 mask4X4, mask4X4Int, cm.LfInfo.Lfthr.AsSpan(), - lflUv.Slice(r << 1)); + lflUv[(r << 1)..]); } dst.Buf = dst.Buf.Slice(16 * dst.Stride); @@ -1763,7 +1761,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 mask4X4R, mask4X4IntR, cm.LfInfo.Lfthr.AsSpan(), - lflUv.Slice(r << 1), + lflUv[(r << 1)..], (int)cm.BitDepth); } else @@ -1776,7 +1774,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 mask4X4R, mask4X4IntR, cm.LfInfo.Lfthr.AsSpan(), - lflUv.Slice(r << 1)); + lflUv[(r << 1)..]); } dst.Buf = dst.Buf.Slice(8 * dst.Stride); @@ -1831,7 +1829,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 ArrayPtr> mi = cm.MiGridVisible.Slice(miRow * cm.MiStride); Span lfm = GetLfm(ref cm.Lf, miRow, 0); - for (miCol = 0; miCol < cm.MiCols; miCol += Constants.MiBlockSize, lfm = lfm.Slice(1)) + for (miCol = 0; miCol < cm.MiCols; miCol += Constants.MiBlockSize, lfm = lfm[1..]) { int r = miRow >> Constants.MiBlockSizeLog2; int c = miCol >> Constants.MiBlockSizeLog2; @@ -1963,4 +1961,4 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 return new ArrayPtr((ushort*)s.ToPointer(), s.Length / 2); } } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Graphics.Nvdec.Vp9/Luts.cs b/src/Ryujinx.Graphics.Nvdec.Vp9/Luts.cs index d54dbeec5..acd771284 100644 --- a/src/Ryujinx.Graphics.Nvdec.Vp9/Luts.cs +++ b/src/Ryujinx.Graphics.Nvdec.Vp9/Luts.cs @@ -1,4 +1,4 @@ -using Ryujinx.Common.Memory; +using Ryujinx.Common.Memory; using Ryujinx.Graphics.Nvdec.Vp9.Types; using System; @@ -270,11 +270,11 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 private static Array8 NewArray8Short(short e0, short e1, short e2, short e3, short e4, short e5, short e6, short e7) { - Array8 output = new() - { - [0] = e0, - [1] = e1, - [2] = e2, + Array8 output = new() + { + [0] = e0, + [1] = e1, + [2] = e2, [3] = e3, [4] = e4, [5] = e5, diff --git a/src/Ryujinx.Graphics.Nvdec.Vp9/PredCommon.cs b/src/Ryujinx.Graphics.Nvdec.Vp9/PredCommon.cs index 30cab3b60..cf91eedeb 100644 --- a/src/Ryujinx.Graphics.Nvdec.Vp9/PredCommon.cs +++ b/src/Ryujinx.Graphics.Nvdec.Vp9/PredCommon.cs @@ -1,4 +1,4 @@ -using Ryujinx.Graphics.Nvdec.Vp9.Types; +using Ryujinx.Graphics.Nvdec.Vp9.Types; using System.Diagnostics; namespace Ryujinx.Graphics.Nvdec.Vp9 @@ -61,7 +61,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 ctx = 1; } - Debug.Assert(ctx >= 0 && ctx < Constants.CompInterContexts); + Debug.Assert(ctx is >= 0 and < Constants.CompInterContexts); return ctx; } @@ -186,7 +186,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 predContext = 2; } - Debug.Assert(predContext >= 0 && predContext < Constants.RefContexts); + Debug.Assert(predContext is >= 0 and < Constants.RefContexts); return predContext; } @@ -294,7 +294,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 predContext = 2; } - Debug.Assert(predContext >= 0 && predContext < Constants.RefContexts); + Debug.Assert(predContext is >= 0 and < Constants.RefContexts); return predContext; } @@ -430,8 +430,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 predContext = 2; } - Debug.Assert(predContext >= 0 && predContext < Constants.RefContexts); + Debug.Assert(predContext is >= 0 and < Constants.RefContexts); return predContext; } } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Graphics.Nvdec.Vp9/Prob.cs b/src/Ryujinx.Graphics.Nvdec.Vp9/Prob.cs index ca6fa351a..6967e63a6 100644 --- a/src/Ryujinx.Graphics.Nvdec.Vp9/Prob.cs +++ b/src/Ryujinx.Graphics.Nvdec.Vp9/Prob.cs @@ -1,4 +1,4 @@ -using Ryujinx.Common.Memory; +using Ryujinx.Common.Memory; using Ryujinx.Graphics.Nvdec.Vp9.Common; using System; using System.Diagnostics; @@ -91,4 +91,4 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 TreeMergeProbsImpl(0, tree, preProbs, counts, probs); } } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Graphics.Nvdec.Vp9/QuantCommon.cs b/src/Ryujinx.Graphics.Nvdec.Vp9/QuantCommon.cs index 3542c90c4..36e4f2704 100644 --- a/src/Ryujinx.Graphics.Nvdec.Vp9/QuantCommon.cs +++ b/src/Ryujinx.Graphics.Nvdec.Vp9/QuantCommon.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Diagnostics; namespace Ryujinx.Graphics.Nvdec.Vp9 @@ -117,9 +117,12 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 { switch (bitDepth) { - case BitDepth.Bits8: return _dcQlookup[Math.Clamp(qindex + delta, 0, MaxQ)]; - case BitDepth.Bits10: return _dcQlookup10[Math.Clamp(qindex + delta, 0, MaxQ)]; - case BitDepth.Bits12: return _dcQlookup12[Math.Clamp(qindex + delta, 0, MaxQ)]; + case BitDepth.Bits8: + return _dcQlookup[Math.Clamp(qindex + delta, 0, MaxQ)]; + case BitDepth.Bits10: + return _dcQlookup10[Math.Clamp(qindex + delta, 0, MaxQ)]; + case BitDepth.Bits12: + return _dcQlookup12[Math.Clamp(qindex + delta, 0, MaxQ)]; default: Debug.Assert(false, "bitDepth should be Bits8, Bits10 or Bits12"); return -1; @@ -130,13 +133,16 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 { switch (bitDepth) { - case BitDepth.Bits8: return _acQlookup[Math.Clamp(qindex + delta, 0, MaxQ)]; - case BitDepth.Bits10: return _acQlookup10[Math.Clamp(qindex + delta, 0, MaxQ)]; - case BitDepth.Bits12: return _acQlookup12[Math.Clamp(qindex + delta, 0, MaxQ)]; + case BitDepth.Bits8: + return _acQlookup[Math.Clamp(qindex + delta, 0, MaxQ)]; + case BitDepth.Bits10: + return _acQlookup10[Math.Clamp(qindex + delta, 0, MaxQ)]; + case BitDepth.Bits12: + return _acQlookup12[Math.Clamp(qindex + delta, 0, MaxQ)]; default: Debug.Assert(false, "bitDepth should be Bits8, Bits10 or Bits12"); return -1; } } } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Graphics.Nvdec.Vp9/ReadBitBuffer.cs b/src/Ryujinx.Graphics.Nvdec.Vp9/ReadBitBuffer.cs index a4e07a1c0..f3e908085 100644 --- a/src/Ryujinx.Graphics.Nvdec.Vp9/ReadBitBuffer.cs +++ b/src/Ryujinx.Graphics.Nvdec.Vp9/ReadBitBuffer.cs @@ -1,4 +1,4 @@ -using Ryujinx.Graphics.Nvdec.Vp9.Common; +using Ryujinx.Graphics.Nvdec.Vp9.Common; using Ryujinx.Graphics.Nvdec.Vp9.Types; using System; @@ -16,7 +16,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 return data > max ? max : data; } - public ulong BytesRead() + public readonly ulong BytesRead() { return (BitOffset + 7) >> 3; } @@ -81,4 +81,4 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 return (BitstreamProfile)profile; } } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Graphics.Nvdec.Vp9/ReconInter.cs b/src/Ryujinx.Graphics.Nvdec.Vp9/ReconInter.cs index 35dbf1cab..e332fd208 100644 --- a/src/Ryujinx.Graphics.Nvdec.Vp9/ReconInter.cs +++ b/src/Ryujinx.Graphics.Nvdec.Vp9/ReconInter.cs @@ -1,4 +1,4 @@ -using Ryujinx.Common.Memory; +using Ryujinx.Common.Memory; using Ryujinx.Graphics.Nvdec.Vp9.Types; using System; using System.Diagnostics; @@ -98,7 +98,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 int spelBottom = spelTop - SubpelShifts; Mv clampedMv = new() { - Row = (short)(srcMv.Row * (1 << (1 - ssY))), Col = (short)(srcMv.Col * (1 << (1 - ssX))) + Row = (short)(srcMv.Row * (1 << (1 - ssY))), + Col = (short)(srcMv.Col * (1 << (1 - ssX))) }; Debug.Assert(ssX <= 1); @@ -132,7 +133,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 res = mi.MvPredQ4(refr); break; default: - Debug.Assert(ssIdx <= 3 && ssIdx >= 0); + Debug.Assert(ssIdx is <= 3 and >= 0); break; } @@ -213,4 +214,4 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 } } } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Graphics.Nvdec.Vp9/ReconIntra.cs b/src/Ryujinx.Graphics.Nvdec.Vp9/ReconIntra.cs index 877469787..e85c501c7 100644 --- a/src/Ryujinx.Graphics.Nvdec.Vp9/ReconIntra.cs +++ b/src/Ryujinx.Graphics.Nvdec.Vp9/ReconIntra.cs @@ -1,4 +1,4 @@ -using Ryujinx.Graphics.Nvdec.Vp9.Common; +using Ryujinx.Graphics.Nvdec.Vp9.Common; using Ryujinx.Graphics.Nvdec.Vp9.Types; using System; using static Ryujinx.Graphics.Nvdec.Vp9.Dsp.IntraPred; @@ -632,4 +632,4 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 plane); } } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Graphics.Nvdec.Vp9/TileBuffer.cs b/src/Ryujinx.Graphics.Nvdec.Vp9/TileBuffer.cs index 18b9d7f47..b6adb95ff 100644 --- a/src/Ryujinx.Graphics.Nvdec.Vp9/TileBuffer.cs +++ b/src/Ryujinx.Graphics.Nvdec.Vp9/TileBuffer.cs @@ -8,4 +8,4 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 public ArrayPtr Data; public int Size; } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Graphics.Nvdec.Vp9/TileWorkerData.cs b/src/Ryujinx.Graphics.Nvdec.Vp9/TileWorkerData.cs index 8c62dca75..526195f87 100644 --- a/src/Ryujinx.Graphics.Nvdec.Vp9/TileWorkerData.cs +++ b/src/Ryujinx.Graphics.Nvdec.Vp9/TileWorkerData.cs @@ -28,4 +28,4 @@ namespace Ryujinx.Graphics.Nvdec.Vp9 return (left * 2) + above + (bsl * Constants.PartitionPloffset); } } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Graphics.Nvdec.Vp9/Types/BModeInfo.cs b/src/Ryujinx.Graphics.Nvdec.Vp9/Types/BModeInfo.cs index a9d32d0b4..4ff82820e 100644 --- a/src/Ryujinx.Graphics.Nvdec.Vp9/Types/BModeInfo.cs +++ b/src/Ryujinx.Graphics.Nvdec.Vp9/Types/BModeInfo.cs @@ -7,4 +7,4 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types public PredictionMode Mode; public Array2 Mv; // First, second inter predictor motion vectors } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Graphics.Nvdec.Vp9/Types/BitstreamProfile.cs b/src/Ryujinx.Graphics.Nvdec.Vp9/Types/BitstreamProfile.cs index 13293f460..e2ced8c95 100644 --- a/src/Ryujinx.Graphics.Nvdec.Vp9/Types/BitstreamProfile.cs +++ b/src/Ryujinx.Graphics.Nvdec.Vp9/Types/BitstreamProfile.cs @@ -1,4 +1,4 @@ -namespace Ryujinx.Graphics.Nvdec.Vp9.Types +namespace Ryujinx.Graphics.Nvdec.Vp9.Types { public enum BitstreamProfile { @@ -8,4 +8,4 @@ Profile3, MaxProfiles } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Graphics.Nvdec.Vp9/Types/BlockSize.cs b/src/Ryujinx.Graphics.Nvdec.Vp9/Types/BlockSize.cs index cee162ab7..e52b05ec6 100644 --- a/src/Ryujinx.Graphics.Nvdec.Vp9/Types/BlockSize.cs +++ b/src/Ryujinx.Graphics.Nvdec.Vp9/Types/BlockSize.cs @@ -1,4 +1,4 @@ -namespace Ryujinx.Graphics.Nvdec.Vp9.Types +namespace Ryujinx.Graphics.Nvdec.Vp9.Types { internal enum BlockSize { @@ -18,4 +18,4 @@ BlockSizes, BlockInvalid = BlockSizes } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Graphics.Nvdec.Vp9/Types/Buf2D.cs b/src/Ryujinx.Graphics.Nvdec.Vp9/Types/Buf2D.cs index 575189490..1313a2e1f 100644 --- a/src/Ryujinx.Graphics.Nvdec.Vp9/Types/Buf2D.cs +++ b/src/Ryujinx.Graphics.Nvdec.Vp9/Types/Buf2D.cs @@ -7,4 +7,4 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types public ArrayPtr Buf; public int Stride; } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Graphics.Nvdec.Vp9/Types/BufferPool.cs b/src/Ryujinx.Graphics.Nvdec.Vp9/Types/BufferPool.cs index bfe87d5a5..8af54d42a 100644 --- a/src/Ryujinx.Graphics.Nvdec.Vp9/Types/BufferPool.cs +++ b/src/Ryujinx.Graphics.Nvdec.Vp9/Types/BufferPool.cs @@ -1,4 +1,4 @@ -using Ryujinx.Common.Memory; +using Ryujinx.Common.Memory; namespace Ryujinx.Graphics.Nvdec.Vp9.Types { @@ -15,4 +15,4 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types // Frame buffers allocated internally by the codec. public InternalFrameBufferList IntFrameBuffers; } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Graphics.Nvdec.Vp9/Types/FrameType.cs b/src/Ryujinx.Graphics.Nvdec.Vp9/Types/FrameType.cs index 8b0935e29..21f021c5b 100644 --- a/src/Ryujinx.Graphics.Nvdec.Vp9/Types/FrameType.cs +++ b/src/Ryujinx.Graphics.Nvdec.Vp9/Types/FrameType.cs @@ -5,4 +5,4 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types KeyFrame = 0, InterFrame = 1, } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Graphics.Nvdec.Vp9/Types/LoopFilter.cs b/src/Ryujinx.Graphics.Nvdec.Vp9/Types/LoopFilter.cs index 4207c54d7..2c75b780b 100644 --- a/src/Ryujinx.Graphics.Nvdec.Vp9/Types/LoopFilter.cs +++ b/src/Ryujinx.Graphics.Nvdec.Vp9/Types/LoopFilter.cs @@ -37,4 +37,4 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types ModeDeltas[1] = 0; } } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Graphics.Nvdec.Vp9/Types/LoopFilterInfoN.cs b/src/Ryujinx.Graphics.Nvdec.Vp9/Types/LoopFilterInfoN.cs index 2a88df3e1..be6243071 100644 --- a/src/Ryujinx.Graphics.Nvdec.Vp9/Types/LoopFilterInfoN.cs +++ b/src/Ryujinx.Graphics.Nvdec.Vp9/Types/LoopFilterInfoN.cs @@ -7,4 +7,4 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types public Array64 Lfthr; public Array8>> Lvl; } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Graphics.Nvdec.Vp9/Types/LoopFilterMask.cs b/src/Ryujinx.Graphics.Nvdec.Vp9/Types/LoopFilterMask.cs index 4aea49425..69a38b926 100644 --- a/src/Ryujinx.Graphics.Nvdec.Vp9/Types/LoopFilterMask.cs +++ b/src/Ryujinx.Graphics.Nvdec.Vp9/Types/LoopFilterMask.cs @@ -21,4 +21,4 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types public ushort Int4X4Uv; public Array64 LflY; } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Graphics.Nvdec.Vp9/Types/LoopFilterThresh.cs b/src/Ryujinx.Graphics.Nvdec.Vp9/Types/LoopFilterThresh.cs index 7fa3c6355..546213215 100644 --- a/src/Ryujinx.Graphics.Nvdec.Vp9/Types/LoopFilterThresh.cs +++ b/src/Ryujinx.Graphics.Nvdec.Vp9/Types/LoopFilterThresh.cs @@ -12,4 +12,4 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types public Array16 HevThr; #pragma warning restore CS0649 } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Graphics.Nvdec.Vp9/Types/MacroBlockD.cs b/src/Ryujinx.Graphics.Nvdec.Vp9/Types/MacroBlockD.cs index bc6b7be32..47c218994 100644 --- a/src/Ryujinx.Graphics.Nvdec.Vp9/Types/MacroBlockD.cs +++ b/src/Ryujinx.Graphics.Nvdec.Vp9/Types/MacroBlockD.cs @@ -1,4 +1,4 @@ -using Ryujinx.Common.Memory; +using Ryujinx.Common.Memory; using Ryujinx.Graphics.Nvdec.Vp9.Common; using Ryujinx.Graphics.Video; @@ -55,7 +55,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types public Ptr ErrorInfo; - public int GetPredContextSegId() + public readonly int GetPredContextSegId() { sbyte aboveSip = !AboveMi.IsNull ? AboveMi.Value.SegIdPredicted : (sbyte)0; sbyte leftSip = !LeftMi.IsNull ? LeftMi.Value.SegIdPredicted : (sbyte)0; @@ -63,14 +63,14 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types return aboveSip + leftSip; } - public int GetSkipContext() + public readonly int GetSkipContext() { int aboveSkip = !AboveMi.IsNull ? AboveMi.Value.Skip : 0; int leftSkip = !LeftMi.IsNull ? LeftMi.Value.Skip : 0; return aboveSkip + leftSkip; } - public int GetPredContextSwitchableInterp() + public readonly int GetPredContextSwitchableInterp() { // Note: // The mode info data structure has a one element border above and to the @@ -104,7 +104,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types // 1 - intra/inter, inter/intra // 2 - intra/--, --/intra // 3 - intra/intra - public int GetIntraInterContext() + public readonly int GetIntraInterContext() { if (!AboveMi.IsNull && !LeftMi.IsNull) { @@ -127,7 +127,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types // The mode info data structure has a one element border above and to the // left of the entries corresponding to real blocks. // The prediction flags in these dummy entries are initialized to 0. - public int GetTxSizeContext() + public readonly int GetTxSizeContext() { int maxTxSize = (int)Luts.MaxTxSizeLookup[(int)Mi[0].Value.SbType]; int aboveCtx = !AboveMi.IsNull && AboveMi.Value.Skip == 0 ? (int)AboveMi.Value.TxSize : maxTxSize; @@ -190,4 +190,4 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types } } } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Graphics.Nvdec.Vp9/Types/MacroBlockDPlane.cs b/src/Ryujinx.Graphics.Nvdec.Vp9/Types/MacroBlockDPlane.cs index d5b64f078..ebf044e64 100644 --- a/src/Ryujinx.Graphics.Nvdec.Vp9/Types/MacroBlockDPlane.cs +++ b/src/Ryujinx.Graphics.Nvdec.Vp9/Types/MacroBlockDPlane.cs @@ -19,4 +19,4 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types // Log2 of N4W, N4H public byte N4Wl, N4Hl; } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Graphics.Nvdec.Vp9/Types/ModeInfo.cs b/src/Ryujinx.Graphics.Nvdec.Vp9/Types/ModeInfo.cs index 39f545a76..9fd961bb9 100644 --- a/src/Ryujinx.Graphics.Nvdec.Vp9/Types/ModeInfo.cs +++ b/src/Ryujinx.Graphics.Nvdec.Vp9/Types/ModeInfo.cs @@ -1,4 +1,4 @@ -using Ryujinx.Common.Memory; +using Ryujinx.Common.Memory; using System.Diagnostics; namespace Ryujinx.Graphics.Nvdec.Vp9.Types @@ -32,7 +32,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types return SbType < BlockSize.Block8X8 ? Bmi[block].Mode : Mode; } - public TxSize GetUvTxSize(ref MacroBlockDPlane pd) + public readonly TxSize GetUvTxSize(ref MacroBlockDPlane pd) { Debug.Assert(SbType < BlockSize.Block8X8 || Luts.SsSizeLookup[(int)SbType][pd.SubsamplingX][pd.SubsamplingY] != BlockSize.BlockInvalid); @@ -104,4 +104,4 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types return mv; } } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Graphics.Nvdec.Vp9/Types/MotionVectorContext.cs b/src/Ryujinx.Graphics.Nvdec.Vp9/Types/MotionVectorContext.cs index 138b8a0ee..bad5af280 100644 --- a/src/Ryujinx.Graphics.Nvdec.Vp9/Types/MotionVectorContext.cs +++ b/src/Ryujinx.Graphics.Nvdec.Vp9/Types/MotionVectorContext.cs @@ -11,4 +11,4 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types BothIntra = 6, InvalidCase = 9, } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Graphics.Nvdec.Vp9/Types/Mv.cs b/src/Ryujinx.Graphics.Nvdec.Vp9/Types/Mv.cs index 6e0accfb3..8a70107b3 100644 --- a/src/Ryujinx.Graphics.Nvdec.Vp9/Types/Mv.cs +++ b/src/Ryujinx.Graphics.Nvdec.Vp9/Types/Mv.cs @@ -1,4 +1,4 @@ -using Ryujinx.Common.Memory; +using Ryujinx.Common.Memory; using Ryujinx.Graphics.Video; using System; using System.Diagnostics; @@ -44,7 +44,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types 9, 9, 9, 9, 9, 9, 9, 9, 9, 10 ]; - public bool UseHp() + public readonly bool UseHp() { const int KMvRefThresh = 64; // Threshold for use of high-precision 1/8 mv return Math.Abs(Row) < KMvRefThresh && Math.Abs(Col) < KMvRefThresh; @@ -52,12 +52,12 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types public static bool JointVertical(MvJointType type) { - return type == MvJointType.Hzvnz || type == MvJointType.Hnzvnz; + return type is MvJointType.Hzvnz or MvJointType.Hnzvnz; } public static bool JointHorizontal(MvJointType type) { - return type == MvJointType.Hnzvz || type == MvJointType.Hnzvnz; + return type is MvJointType.Hnzvz or MvJointType.Hnzvnz; } private static int ClassBase(MvClassType c) @@ -110,7 +110,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types } } - public MvJointType GetJoint() + public readonly MvJointType GetJoint() { if (Row == 0) { @@ -120,7 +120,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types return Col == 0 ? MvJointType.Hzvnz : MvJointType.Hnzvnz; } - internal void Inc(Ptr counts) + internal readonly void Inc(Ptr counts) { if (!counts.IsNull) { @@ -173,10 +173,10 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types } } - public bool IsValid() + public readonly bool IsValid() { return Row is > Constants.MvLow and < Constants.MvUpp && Col is > Constants.MvLow and < Constants.MvUpp; } } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Graphics.Nvdec.Vp9/Types/Mv32.cs b/src/Ryujinx.Graphics.Nvdec.Vp9/Types/Mv32.cs index d3561fe58..5231ca6a6 100644 --- a/src/Ryujinx.Graphics.Nvdec.Vp9/Types/Mv32.cs +++ b/src/Ryujinx.Graphics.Nvdec.Vp9/Types/Mv32.cs @@ -5,4 +5,4 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types public int Row; public int Col; } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Graphics.Nvdec.Vp9/Types/MvClassType.cs b/src/Ryujinx.Graphics.Nvdec.Vp9/Types/MvClassType.cs index 0e233b2f2..d933e7117 100644 --- a/src/Ryujinx.Graphics.Nvdec.Vp9/Types/MvClassType.cs +++ b/src/Ryujinx.Graphics.Nvdec.Vp9/Types/MvClassType.cs @@ -14,4 +14,4 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types Class9, /* (512, 1024] integer pel */ Class10 /* (1024,2048] integer pel */ } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Graphics.Nvdec.Vp9/Types/MvJointType.cs b/src/Ryujinx.Graphics.Nvdec.Vp9/Types/MvJointType.cs index 499c50c68..a9dca4644 100644 --- a/src/Ryujinx.Graphics.Nvdec.Vp9/Types/MvJointType.cs +++ b/src/Ryujinx.Graphics.Nvdec.Vp9/Types/MvJointType.cs @@ -7,4 +7,4 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types Hzvnz, /* Hor zero, vert nonzero */ Hnzvnz /* Both components nonzero */ } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Graphics.Nvdec.Vp9/Types/MvRef.cs b/src/Ryujinx.Graphics.Nvdec.Vp9/Types/MvRef.cs index 06b082800..1d32a0927 100644 --- a/src/Ryujinx.Graphics.Nvdec.Vp9/Types/MvRef.cs +++ b/src/Ryujinx.Graphics.Nvdec.Vp9/Types/MvRef.cs @@ -7,4 +7,4 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types public Array2 Mv; public Array2 RefFrame; } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Graphics.Nvdec.Vp9/Types/PartitionType.cs b/src/Ryujinx.Graphics.Nvdec.Vp9/Types/PartitionType.cs index 8042071e4..c47557abf 100644 --- a/src/Ryujinx.Graphics.Nvdec.Vp9/Types/PartitionType.cs +++ b/src/Ryujinx.Graphics.Nvdec.Vp9/Types/PartitionType.cs @@ -9,4 +9,4 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types PartitionTypes, PartitionInvalid = PartitionTypes, } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Graphics.Nvdec.Vp9/Types/PlaneType.cs b/src/Ryujinx.Graphics.Nvdec.Vp9/Types/PlaneType.cs index ced1646e9..1b50010a2 100644 --- a/src/Ryujinx.Graphics.Nvdec.Vp9/Types/PlaneType.cs +++ b/src/Ryujinx.Graphics.Nvdec.Vp9/Types/PlaneType.cs @@ -1,4 +1,4 @@ -namespace Ryujinx.Graphics.Nvdec.Vp9.Types +namespace Ryujinx.Graphics.Nvdec.Vp9.Types { internal enum PlaneType { @@ -6,4 +6,4 @@ Uv, PlaneTypes } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Graphics.Nvdec.Vp9/Types/Position.cs b/src/Ryujinx.Graphics.Nvdec.Vp9/Types/Position.cs index d055f225e..cee2fbe83 100644 --- a/src/Ryujinx.Graphics.Nvdec.Vp9/Types/Position.cs +++ b/src/Ryujinx.Graphics.Nvdec.Vp9/Types/Position.cs @@ -11,4 +11,4 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types Col = col; } } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Graphics.Nvdec.Vp9/Types/PredictionMode.cs b/src/Ryujinx.Graphics.Nvdec.Vp9/Types/PredictionMode.cs index a0f15905d..2d9750af9 100644 --- a/src/Ryujinx.Graphics.Nvdec.Vp9/Types/PredictionMode.cs +++ b/src/Ryujinx.Graphics.Nvdec.Vp9/Types/PredictionMode.cs @@ -1,4 +1,4 @@ -namespace Ryujinx.Graphics.Nvdec.Vp9.Types +namespace Ryujinx.Graphics.Nvdec.Vp9.Types { internal enum PredictionMode { @@ -18,4 +18,4 @@ NewMv, MbModeCount } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Graphics.Nvdec.Vp9/Types/RefBuffer.cs b/src/Ryujinx.Graphics.Nvdec.Vp9/Types/RefBuffer.cs index 4b45f2c02..dc4444e6e 100644 --- a/src/Ryujinx.Graphics.Nvdec.Vp9/Types/RefBuffer.cs +++ b/src/Ryujinx.Graphics.Nvdec.Vp9/Types/RefBuffer.cs @@ -8,4 +8,4 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types public Surface Buf; public ScaleFactors Sf; } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Graphics.Nvdec.Vp9/Types/RefCntBuffer.cs b/src/Ryujinx.Graphics.Nvdec.Vp9/Types/RefCntBuffer.cs index 47febf38d..2f654b6f7 100644 --- a/src/Ryujinx.Graphics.Nvdec.Vp9/Types/RefCntBuffer.cs +++ b/src/Ryujinx.Graphics.Nvdec.Vp9/Types/RefCntBuffer.cs @@ -1,4 +1,4 @@ -namespace Ryujinx.Graphics.Nvdec.Vp9.Types +namespace Ryujinx.Graphics.Nvdec.Vp9.Types { internal struct RefCntBuffer { @@ -9,4 +9,4 @@ public VpxCodecFrameBuffer RawFrameBuffer; public Surface Buf; } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Graphics.Nvdec.Vp9/Types/ReferenceMode.cs b/src/Ryujinx.Graphics.Nvdec.Vp9/Types/ReferenceMode.cs index a678f8181..aee5fccc9 100644 --- a/src/Ryujinx.Graphics.Nvdec.Vp9/Types/ReferenceMode.cs +++ b/src/Ryujinx.Graphics.Nvdec.Vp9/Types/ReferenceMode.cs @@ -1,4 +1,4 @@ -namespace Ryujinx.Graphics.Nvdec.Vp9.Types +namespace Ryujinx.Graphics.Nvdec.Vp9.Types { internal enum ReferenceMode { @@ -7,4 +7,4 @@ Select, ReferenceModes } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Graphics.Nvdec.Vp9/Types/ScaleFactors.cs b/src/Ryujinx.Graphics.Nvdec.Vp9/Types/ScaleFactors.cs index 212571311..e3f73d761 100644 --- a/src/Ryujinx.Graphics.Nvdec.Vp9/Types/ScaleFactors.cs +++ b/src/Ryujinx.Graphics.Nvdec.Vp9/Types/ScaleFactors.cs @@ -1,4 +1,4 @@ -using Ryujinx.Common.Memory; +using Ryujinx.Common.Memory; using System.Runtime.CompilerServices; using static Ryujinx.Graphics.Nvdec.Vp9.Dsp.Convolve; using static Ryujinx.Graphics.Nvdec.Vp9.Dsp.Filter; @@ -123,18 +123,18 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types public int XStepQ4; public int YStepQ4; - public int ScaleValueX(int val) + public readonly int ScaleValueX(int val) { return IsScaled() ? ScaledX(val) : val; } - public int ScaleValueY(int val) + public readonly int ScaleValueY(int val) { return IsScaled() ? ScaledY(val) : val; } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public unsafe void InterPredict( + public readonly unsafe void InterPredict( int horiz, int vert, int avg, @@ -182,7 +182,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public unsafe void HighbdInterPredict( + public readonly unsafe void HighbdInterPredict( int horiz, int vert, int avg, @@ -231,12 +231,12 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types } } - private int ScaledX(int val) + private readonly int ScaledX(int val) { return (int)(((long)val * XScaleFp) >> RefScaleShift); } - private int ScaledY(int val) + private readonly int ScaledY(int val) { return (int)(((long)val * YScaleFp) >> RefScaleShift); } @@ -258,12 +258,12 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types return res; } - public bool IsValidScale() + public readonly bool IsValidScale() { return XScaleFp != RefInvalidScale && YScaleFp != RefInvalidScale; } - public bool IsScaled() + public readonly bool IsScaled() { return IsValidScale() && (XScaleFp != RefNoScale || YScaleFp != RefNoScale); } @@ -291,4 +291,4 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types YStepQ4 = ScaledY(16); } } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Graphics.Nvdec.Vp9/Types/SegLvlFeatures.cs b/src/Ryujinx.Graphics.Nvdec.Vp9/Types/SegLvlFeatures.cs index 21d57d1d7..d14cff2c8 100644 --- a/src/Ryujinx.Graphics.Nvdec.Vp9/Types/SegLvlFeatures.cs +++ b/src/Ryujinx.Graphics.Nvdec.Vp9/Types/SegLvlFeatures.cs @@ -1,4 +1,4 @@ -namespace Ryujinx.Graphics.Nvdec.Vp9.Types +namespace Ryujinx.Graphics.Nvdec.Vp9.Types { internal enum SegLvlFeatures { @@ -8,4 +8,4 @@ Skip, // Optional Segment (0,0) + skip mode Max // Number of features supported } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Graphics.Nvdec.Vp9/Types/Segmentation.cs b/src/Ryujinx.Graphics.Nvdec.Vp9/Types/Segmentation.cs index 726476d96..c34545791 100644 --- a/src/Ryujinx.Graphics.Nvdec.Vp9/Types/Segmentation.cs +++ b/src/Ryujinx.Graphics.Nvdec.Vp9/Types/Segmentation.cs @@ -1,4 +1,4 @@ -using Ryujinx.Common.Memory; +using Ryujinx.Common.Memory; using Ryujinx.Graphics.Video; using System; using System.Diagnostics; @@ -161,4 +161,4 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types } } } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Graphics.Nvdec.Vp9/Types/Surface.cs b/src/Ryujinx.Graphics.Nvdec.Vp9/Types/Surface.cs index 33741f85f..42ba0af3d 100644 --- a/src/Ryujinx.Graphics.Nvdec.Vp9/Types/Surface.cs +++ b/src/Ryujinx.Graphics.Nvdec.Vp9/Types/Surface.cs @@ -1,4 +1,4 @@ -using Ryujinx.Common.Memory; +using Ryujinx.Common.Memory; using Ryujinx.Graphics.Nvdec.Vp9.Common; using Ryujinx.Graphics.Video; using System.Diagnostics; @@ -26,7 +26,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types public readonly unsafe Plane UPlane => new((nint)UBuffer.ToPointer(), UBuffer.Length); public readonly unsafe Plane VPlane => new((nint)VBuffer.ToPointer(), VBuffer.Length); - public FrameField Field => FrameField.Progressive; + public readonly FrameField Field => FrameField.Progressive; public int Width { get; private set; } public int Height { get; private set; } @@ -43,10 +43,10 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types public int FrameSize { get; private set; } public int Border { get; private set; } - public int YCropWidth => Width; - public int YCropHeight => Height; - public int UvCropWidth => UvWidth; - public int UvCropHeight => UvHeight; + public readonly int YCropWidth => Width; + public readonly int YCropHeight => Height; + public readonly int UvCropWidth => UvWidth; + public readonly int UvCropHeight => UvHeight; public ArrayPtr BufferAlloc; public int BufferAllocSz; @@ -119,7 +119,6 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types VpxGetFrameBufferCbFnT cb, Ptr cbPriv) { - int byteAlign = byteAlignment == 0 ? 1 : byteAlignment; // TODO: Is it safe to ignore the alignment? int alignedWidth = (width + 7) & ~7; int alignedHeight = (height + 7) & ~7; int yStride = (alignedWidth + (2 * border) + 31) & ~31; @@ -135,8 +134,6 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types ulong frameSize = (ulong)(1 + (useHighbitdepth ? 1 : 0)) * (yplaneSize + (2 * uvplaneSize)); - ArrayPtr buf = ArrayPtr.Null; - // frame_size is stored in buffer_alloc_sz, which is an int. If it won't // fit, fail early. if (frameSize > int.MaxValue) @@ -211,7 +208,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types SubsamplingX = ssX; SubsamplingY = ssY; - buf = BufferAlloc; + ArrayPtr buf = BufferAlloc; if (useHighbitdepth) { // Store uint16 addresses when using 16bit framebuffers @@ -231,7 +228,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types return 0; } - public void Dispose() + public readonly void Dispose() { Marshal.FreeHGlobal(_pointer); } diff --git a/src/Ryujinx.Graphics.Nvdec.Vp9/Types/TileInfo.cs b/src/Ryujinx.Graphics.Nvdec.Vp9/Types/TileInfo.cs index 7d4350d3c..a32f55c72 100644 --- a/src/Ryujinx.Graphics.Nvdec.Vp9/Types/TileInfo.cs +++ b/src/Ryujinx.Graphics.Nvdec.Vp9/Types/TileInfo.cs @@ -83,4 +83,4 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types Debug.Assert(minLog2TileCols <= maxLog2TileCols); } } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Graphics.Nvdec.Vp9/Types/TxMode.cs b/src/Ryujinx.Graphics.Nvdec.Vp9/Types/TxMode.cs index d6a4fb843..47dad305c 100644 --- a/src/Ryujinx.Graphics.Nvdec.Vp9/Types/TxMode.cs +++ b/src/Ryujinx.Graphics.Nvdec.Vp9/Types/TxMode.cs @@ -1,4 +1,4 @@ -namespace Ryujinx.Graphics.Nvdec.Vp9.Types +namespace Ryujinx.Graphics.Nvdec.Vp9.Types { public enum TxMode { @@ -9,4 +9,4 @@ TxModeSelect, // Transform specified for each block TxModes } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Graphics.Nvdec.Vp9/Types/TxSize.cs b/src/Ryujinx.Graphics.Nvdec.Vp9/Types/TxSize.cs index 72908a00c..cfc51317a 100644 --- a/src/Ryujinx.Graphics.Nvdec.Vp9/Types/TxSize.cs +++ b/src/Ryujinx.Graphics.Nvdec.Vp9/Types/TxSize.cs @@ -1,4 +1,4 @@ -namespace Ryujinx.Graphics.Nvdec.Vp9.Types +namespace Ryujinx.Graphics.Nvdec.Vp9.Types { public enum TxSize { @@ -8,4 +8,4 @@ Tx32X32, // 32x32 transform TxSizes } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Graphics.Nvdec.Vp9/Types/TxType.cs b/src/Ryujinx.Graphics.Nvdec.Vp9/Types/TxType.cs index 60c5c9a44..95ef538f2 100644 --- a/src/Ryujinx.Graphics.Nvdec.Vp9/Types/TxType.cs +++ b/src/Ryujinx.Graphics.Nvdec.Vp9/Types/TxType.cs @@ -1,4 +1,4 @@ -namespace Ryujinx.Graphics.Nvdec.Vp9.Types +namespace Ryujinx.Graphics.Nvdec.Vp9.Types { internal enum TxType { @@ -8,4 +8,4 @@ AdstAdst, // ADST in both directions TxTypes } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Graphics.Nvdec.Vp9/Types/Vp9Common.cs b/src/Ryujinx.Graphics.Nvdec.Vp9/Types/Vp9Common.cs index 5669e8574..3fc31127a 100644 --- a/src/Ryujinx.Graphics.Nvdec.Vp9/Types/Vp9Common.cs +++ b/src/Ryujinx.Graphics.Nvdec.Vp9/Types/Vp9Common.cs @@ -1,4 +1,4 @@ -using Ryujinx.Common.Memory; +using Ryujinx.Common.Memory; using Ryujinx.Graphics.Nvdec.Vp9.Common; using Ryujinx.Graphics.Nvdec.Vp9.Dsp; using Ryujinx.Graphics.Video; @@ -148,7 +148,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types public ArrayPtr AboveSegContext; public ArrayPtr AboveContext; - public bool FrameIsIntraOnly() + public readonly bool FrameIsIntraOnly() { return FrameType == FrameType.KeyFrame || IntraOnly; } @@ -166,12 +166,12 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types return false; } - public ref Surface GetFrameNewBuffer() + public readonly ref Surface GetFrameNewBuffer() { return ref BufferPool.Value.FrameBufs[NewFbIdx].Buf; } - public int GetFreeFb() + public readonly int GetFreeFb() { ref Array12 frameBufs = ref BufferPool.Value.FrameBufs; @@ -233,7 +233,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types allocator.Allocate((tileCols * tileRows) + (maxThreads > 1 ? maxThreads : 0)); } - public void FreeTileWorkerData(MemoryAllocator allocator) + public readonly void FreeTileWorkerData(MemoryAllocator allocator) { allocator.Free(TileWorkerData); } @@ -357,7 +357,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types } } - private void SetPartitionProbs(ref MacroBlockD xd) + private readonly void SetPartitionProbs(ref MacroBlockD xd) { xd.PartitionProbs = FrameIsIntraOnly() ? new ArrayPtr>(ref Fc.Value.KfPartitionProb[0], 16) @@ -429,7 +429,6 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types { ref Vp9EntropyProbs fc = ref Fc.Value; - if (ReferenceMode == ReferenceMode.Select) { for (int i = 0; i < Constants.CompInterContexts; ++i) @@ -490,7 +489,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types } } - public void InitMvProbs() + public readonly void InitMvProbs() { Fc.Value.Joints[0] = 32; Fc.Value.Joints[1] = 64; @@ -684,11 +683,10 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types public void SetupTileInfo(ref ReadBitBuffer rb) { - int minLog2TileCols = 0, maxLog2TileCols = 0, maxOnes; - TileInfo.GetTileNBits(MiCols, out minLog2TileCols, out maxLog2TileCols); + TileInfo.GetTileNBits(MiCols, out int minLog2TileCols, out int maxLog2TileCols); // columns - maxOnes = maxLog2TileCols - minLog2TileCols; + int maxOnes = maxLog2TileCols - minLog2TileCols; Log2TileCols = minLog2TileCols; while (maxOnes-- != 0 && rb.ReadBit() != 0) { @@ -725,7 +723,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types if (ColorSpace != VpxColorSpace.Srgb) { ColorRange = (VpxColorRange)rb.ReadBit(); - if (Profile == BitstreamProfile.Profile1 || Profile == BitstreamProfile.Profile3) + if (Profile is BitstreamProfile.Profile1 or BitstreamProfile.Profile3) { SubsamplingX = rb.ReadBit(); SubsamplingY = rb.ReadBit(); @@ -748,7 +746,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types else { ColorRange = VpxColorRange.Full; - if (Profile == BitstreamProfile.Profile1 || Profile == BitstreamProfile.Profile3) + if (Profile is BitstreamProfile.Profile1 or BitstreamProfile.Profile3) { // Note if colorspace is SRGB then 4:4:4 chroma sampling is assumed. // 4:2:2 or 4:4:0 chroma sampling is not allowed. @@ -988,7 +986,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types } } - public void DefaultCoefProbs() + public readonly void DefaultCoefProbs() { Entropy.CopyProbs(ref Fc.Value.CoefProbs[(int)TxSize.Tx4X4], Entropy.DefaultCoefProbs4X4); Entropy.CopyProbs(ref Fc.Value.CoefProbs[(int)TxSize.Tx8X8], Entropy.DefaultCoefProbs8X8); @@ -996,4 +994,4 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types Entropy.CopyProbs(ref Fc.Value.CoefProbs[(int)TxSize.Tx32X32], Entropy.DefaultCoefProbs32X32); } } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Graphics.Nvdec.Vp9/Types/Vp9Decoder.cs b/src/Ryujinx.Graphics.Nvdec.Vp9/Types/Vp9Decoder.cs index 11c121cfe..4df8ef549 100644 --- a/src/Ryujinx.Graphics.Nvdec.Vp9/Types/Vp9Decoder.cs +++ b/src/Ryujinx.Graphics.Nvdec.Vp9/Types/Vp9Decoder.cs @@ -1,4 +1,4 @@ -using Ryujinx.Common.Memory; +using Ryujinx.Common.Memory; using Ryujinx.Graphics.Nvdec.Vp9.Common; using Ryujinx.Graphics.Video; using System.Diagnostics; @@ -279,9 +279,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types ArrayPtr dataStart = data; CodecErr res; Array8 frameSizes = new(); - int frameCount = 0; - res = Decoder.ParseSuperframeIndex(data, (ulong)data.Length, ref frameSizes, out frameCount); + res = Decoder.ParseSuperframeIndex(data, (ulong)data.Length, ref frameSizes, out int frameCount); if (res != CodecErr.Ok) { return res; @@ -407,4 +406,4 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types return CodecErr.Ok; } } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Graphics.Nvdec.Vp9/Types/VpxCodecFrameBuffer.cs b/src/Ryujinx.Graphics.Nvdec.Vp9/Types/VpxCodecFrameBuffer.cs index 358de79dd..6883dfad9 100644 --- a/src/Ryujinx.Graphics.Nvdec.Vp9/Types/VpxCodecFrameBuffer.cs +++ b/src/Ryujinx.Graphics.Nvdec.Vp9/Types/VpxCodecFrameBuffer.cs @@ -1,4 +1,4 @@ -using Ryujinx.Common.Memory; +using Ryujinx.Common.Memory; namespace Ryujinx.Graphics.Nvdec.Vp9.Types { @@ -7,4 +7,4 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types public ArrayPtr Data; public Ptr Priv; } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Graphics.Nvdec.Vp9/Types/VpxColorRange.cs b/src/Ryujinx.Graphics.Nvdec.Vp9/Types/VpxColorRange.cs index 9f8c7c53d..4f32abb94 100644 --- a/src/Ryujinx.Graphics.Nvdec.Vp9/Types/VpxColorRange.cs +++ b/src/Ryujinx.Graphics.Nvdec.Vp9/Types/VpxColorRange.cs @@ -1,4 +1,4 @@ -namespace Ryujinx.Graphics.Nvdec.Vp9.Types +namespace Ryujinx.Graphics.Nvdec.Vp9.Types { internal enum VpxColorRange { @@ -8,4 +8,4 @@ // YUV/RGB [0..255] Full } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Graphics.Nvdec.Vp9/Types/VpxColorSpace.cs b/src/Ryujinx.Graphics.Nvdec.Vp9/Types/VpxColorSpace.cs index a1706c0d0..fa69c16a5 100644 --- a/src/Ryujinx.Graphics.Nvdec.Vp9/Types/VpxColorSpace.cs +++ b/src/Ryujinx.Graphics.Nvdec.Vp9/Types/VpxColorSpace.cs @@ -1,4 +1,4 @@ -namespace Ryujinx.Graphics.Nvdec.Vp9.Types +namespace Ryujinx.Graphics.Nvdec.Vp9.Types { internal enum VpxColorSpace { @@ -26,4 +26,4 @@ // sRGB Srgb } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Graphics.OpenGL/Debugger.cs b/src/Ryujinx.Graphics.OpenGL/Debugger.cs index c700b3b7c..8a94bcc87 100644 --- a/src/Ryujinx.Graphics.OpenGL/Debugger.cs +++ b/src/Ryujinx.Graphics.OpenGL/Debugger.cs @@ -84,6 +84,7 @@ namespace Ryujinx.Graphics.OpenGL { Logger.Debug?.Print(LogClass.Gpu, $"{type} {severity}: {msg}", "GLDEBUG"); } + break; } } diff --git a/src/Ryujinx.Graphics.OpenGL/FormatTable.cs b/src/Ryujinx.Graphics.OpenGL/FormatTable.cs index 4cf4dc760..bca79cb97 100644 --- a/src/Ryujinx.Graphics.OpenGL/FormatTable.cs +++ b/src/Ryujinx.Graphics.OpenGL/FormatTable.cs @@ -228,14 +228,14 @@ namespace Ryujinx.Graphics.OpenGL public static bool IsPackedDepthStencil(Format format) { - return format == Format.D24UnormS8Uint || - format == Format.D32FloatS8Uint || - format == Format.S8UintD24Unorm; + return format is Format.D24UnormS8Uint or + Format.D32FloatS8Uint or + Format.S8UintD24Unorm; } public static bool IsDepthOnly(Format format) { - return format == Format.D16Unorm || format == Format.D32Float || format == Format.X8UintD24Unorm; + return format is Format.D16Unorm or Format.D32Float or Format.X8UintD24Unorm; } } } diff --git a/src/Ryujinx.Graphics.OpenGL/HwCapabilities.cs b/src/Ryujinx.Graphics.OpenGL/HwCapabilities.cs index cf0b0645c..71186807e 100644 --- a/src/Ryujinx.Graphics.OpenGL/HwCapabilities.cs +++ b/src/Ryujinx.Graphics.OpenGL/HwCapabilities.cs @@ -43,13 +43,13 @@ namespace Ryujinx.Graphics.OpenGL private static readonly Lazy _gpuVendor = new(GetGpuVendor); - private static bool IsIntel => _gpuVendor.Value == GpuVendor.IntelWindows || _gpuVendor.Value == GpuVendor.IntelUnix; + private static bool IsIntel => _gpuVendor.Value is GpuVendor.IntelWindows or GpuVendor.IntelUnix; public static GpuVendor Vendor => _gpuVendor.Value; private static readonly Lazy _maxSupportedAnisotropy = new(GL.GetFloat((GetPName)All.MaxTextureMaxAnisotropy)); - public static bool UsePersistentBufferForFlush => _gpuVendor.Value == GpuVendor.AmdWindows || _gpuVendor.Value == GpuVendor.Nvidia; + public static bool UsePersistentBufferForFlush => _gpuVendor.Value is GpuVendor.AmdWindows or GpuVendor.Nvidia; public static bool SupportsAlphaToCoverageDitherControl => _supportsAlphaToCoverageDitherControl.Value; public static bool SupportsAstcCompression => _supportsAstcCompression.Value; @@ -73,7 +73,7 @@ namespace Ryujinx.Graphics.OpenGL public static bool SupportsTextureShadowLod => _supportsTextureShadowLod.Value; public static bool SupportsViewportSwizzle => _supportsViewportSwizzle.Value; - public static bool SupportsMismatchingViewFormat => _gpuVendor.Value != GpuVendor.AmdWindows && _gpuVendor.Value != GpuVendor.IntelWindows; + public static bool SupportsMismatchingViewFormat => _gpuVendor.Value is not GpuVendor.AmdWindows and not GpuVendor.IntelWindows; public static bool SupportsNonConstantTextureOffset => _gpuVendor.Value == GpuVendor.Nvidia; public static bool RequiresSyncFlush => _gpuVendor.Value == GpuVendor.AmdWindows || IsIntel; @@ -117,11 +117,11 @@ namespace Ryujinx.Graphics.OpenGL return renderer.Contains("mesa") ? GpuVendor.IntelUnix : GpuVendor.IntelWindows; } - else if (vendor == "ati technologies inc." || vendor == "advanced micro devices, inc.") + else if (vendor is "ati technologies inc." or "advanced micro devices, inc.") { return GpuVendor.AmdWindows; } - else if (vendor == "amd" || vendor == "x.org") + else if (vendor is "amd" or "x.org") { return GpuVendor.AmdUnix; } diff --git a/src/Ryujinx.Graphics.OpenGL/Image/TextureCopy.cs b/src/Ryujinx.Graphics.OpenGL/Image/TextureCopy.cs index e08da7013..3d1e47339 100644 --- a/src/Ryujinx.Graphics.OpenGL/Image/TextureCopy.cs +++ b/src/Ryujinx.Graphics.OpenGL/Image/TextureCopy.cs @@ -290,7 +290,7 @@ namespace Ryujinx.Graphics.OpenGL.Image private static FramebufferAttachment AttachmentForFormat(Format format) { - if (format == Format.D24UnormS8Uint || format == Format.D32FloatS8Uint) + if (format is Format.D24UnormS8Uint or Format.D32FloatS8Uint) { return FramebufferAttachment.DepthStencilAttachment; } diff --git a/src/Ryujinx.Graphics.OpenGL/Image/TextureView.cs b/src/Ryujinx.Graphics.OpenGL/Image/TextureView.cs index 84bb86a2d..fcd004dd6 100644 --- a/src/Ryujinx.Graphics.OpenGL/Image/TextureView.cs +++ b/src/Ryujinx.Graphics.OpenGL/Image/TextureView.cs @@ -358,7 +358,7 @@ namespace Ryujinx.Graphics.OpenGL.Image PixelFormat pixelFormat = format.PixelFormat; PixelType pixelType = format.PixelType; - if (target == TextureTarget.TextureCubeMap || target == TextureTarget.TextureCubeMapArray) + if (target is TextureTarget.TextureCubeMap or TextureTarget.TextureCubeMapArray) { target = TextureTarget.TextureCubeMapPositiveX + (layer % 6); } @@ -568,6 +568,7 @@ namespace Ryujinx.Graphics.OpenGL.Image format.PixelType, data); } + break; case Target.Texture1DArray: @@ -597,6 +598,7 @@ namespace Ryujinx.Graphics.OpenGL.Image format.PixelType, data); } + break; case Target.Texture2D: @@ -626,6 +628,7 @@ namespace Ryujinx.Graphics.OpenGL.Image format.PixelType, data); } + break; case Target.Texture2DArray: @@ -661,6 +664,7 @@ namespace Ryujinx.Graphics.OpenGL.Image format.PixelType, data); } + break; case Target.Cubemap: @@ -690,6 +694,7 @@ namespace Ryujinx.Graphics.OpenGL.Image format.PixelType, data); } + break; } } @@ -756,6 +761,7 @@ namespace Ryujinx.Graphics.OpenGL.Image format.PixelType, data); } + break; case Target.Texture1DArray: @@ -786,6 +792,7 @@ namespace Ryujinx.Graphics.OpenGL.Image format.PixelType, data); } + break; case Target.Texture2DArray: @@ -821,6 +828,7 @@ namespace Ryujinx.Graphics.OpenGL.Image format.PixelType, data); } + break; case Target.Cubemap: @@ -855,6 +863,7 @@ namespace Ryujinx.Graphics.OpenGL.Image data + faceOffset); } } + break; } diff --git a/src/Ryujinx.Graphics.OpenGL/Queries/BufferedQuery.cs b/src/Ryujinx.Graphics.OpenGL/Queries/BufferedQuery.cs index a5acd8dce..f39829923 100644 --- a/src/Ryujinx.Graphics.OpenGL/Queries/BufferedQuery.cs +++ b/src/Ryujinx.Graphics.OpenGL/Queries/BufferedQuery.cs @@ -31,6 +31,7 @@ namespace Ryujinx.Graphics.OpenGL.Queries long defaultValue = DefaultValue; GL.BufferStorage(BufferTarget.QueryBuffer, sizeof(long), (nint)(&defaultValue), BufferStorageFlags.MapReadBit | BufferStorageFlags.MapWriteBit | BufferStorageFlags.MapPersistentBit); } + _bufferMap = GL.MapBufferRange(BufferTarget.QueryBuffer, nint.Zero, sizeof(long), BufferAccessMask.MapReadBit | BufferAccessMask.MapWriteBit | BufferAccessMask.MapPersistentBit); } diff --git a/src/Ryujinx.Graphics.OpenGL/Queries/CounterQueue.cs b/src/Ryujinx.Graphics.OpenGL/Queries/CounterQueue.cs index 88cdec983..0249440b4 100644 --- a/src/Ryujinx.Graphics.OpenGL/Queries/CounterQueue.cs +++ b/src/Ryujinx.Graphics.OpenGL/Queries/CounterQueue.cs @@ -172,6 +172,7 @@ namespace Ryujinx.Graphics.OpenGL.Queries { return; // If not blocking, then return when we encounter an event that is not ready yet. } + _events.Dequeue(); } } diff --git a/src/Ryujinx.Graphics.OpenGL/ResourcePool.cs b/src/Ryujinx.Graphics.OpenGL/ResourcePool.cs index 352728813..ef6571fb9 100644 --- a/src/Ryujinx.Graphics.OpenGL/ResourcePool.cs +++ b/src/Ryujinx.Graphics.OpenGL/ResourcePool.cs @@ -108,6 +108,7 @@ namespace Ryujinx.Graphics.OpenGL texture.View.Dispose(); } } + _textures.Clear(); } } diff --git a/src/Ryujinx.Graphics.OpenGL/Sync.cs b/src/Ryujinx.Graphics.OpenGL/Sync.cs index 9fd7db9d1..a809a22f0 100644 --- a/src/Ryujinx.Graphics.OpenGL/Sync.cs +++ b/src/Ryujinx.Graphics.OpenGL/Sync.cs @@ -27,7 +27,6 @@ namespace Ryujinx.Graphics.OpenGL Handle = GL.FenceSync(SyncCondition.SyncGpuCommandsComplete, WaitSyncFlags.None), }; - if (HwCapabilities.RequiresSyncFlush) { // Force commands to flush up to the syncpoint. diff --git a/src/Ryujinx.Graphics.OpenGL/VertexArray.cs b/src/Ryujinx.Graphics.OpenGL/VertexArray.cs index bd8e9eafa..2480b6af2 100644 --- a/src/Ryujinx.Graphics.OpenGL/VertexArray.cs +++ b/src/Ryujinx.Graphics.OpenGL/VertexArray.cs @@ -104,8 +104,8 @@ namespace Ryujinx.Graphics.OpenGL int offset = attrib.Offset; int size = fmtInfo.Components; - bool isFloat = fmtInfo.PixelType == PixelType.Float || - fmtInfo.PixelType == PixelType.HalfFloat; + bool isFloat = fmtInfo.PixelType is PixelType.Float or + PixelType.HalfFloat; if (isFloat || fmtInfo.Normalized || fmtInfo.Scaled) { diff --git a/src/Ryujinx.Graphics.OpenGL/Window.cs b/src/Ryujinx.Graphics.OpenGL/Window.cs index 2813e03bc..bb4df0c06 100644 --- a/src/Ryujinx.Graphics.OpenGL/Window.cs +++ b/src/Ryujinx.Graphics.OpenGL/Window.cs @@ -340,6 +340,7 @@ namespace Ryujinx.Graphics.OpenGL _antiAliasing?.Dispose(); _antiAliasing = new SmaaPostProcessingEffect(_renderer, quality); } + break; } } @@ -371,6 +372,7 @@ namespace Ryujinx.Graphics.OpenGL _scalingFilter?.Dispose(); _scalingFilter = new FsrScalingFilter(_renderer); } + _isLinear = false; _scalingFilter.Level = _scalingFilterLevel; @@ -382,6 +384,7 @@ namespace Ryujinx.Graphics.OpenGL _scalingFilter?.Dispose(); _scalingFilter = new AreaScalingFilter(_renderer); } + _isLinear = false; RecreateUpscalingTexture(); diff --git a/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/Declarations.cs b/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/Declarations.cs index 335222cee..e0d7cdc4b 100644 --- a/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/Declarations.cs +++ b/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/Declarations.cs @@ -629,9 +629,9 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl } else { - return stage == ShaderStage.TessellationControl || - stage == ShaderStage.TessellationEvaluation || - stage == ShaderStage.Geometry; + return stage is ShaderStage.TessellationControl or + ShaderStage.TessellationEvaluation or + ShaderStage.Geometry; } } diff --git a/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGen.cs b/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGen.cs index 9e7f64b0e..939b57aa7 100644 --- a/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGen.cs +++ b/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGen.cs @@ -74,7 +74,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions { builder.Append(GenerateLoadOrStore(context, operation, isStore: false)); - AggregateType dstType = operation.Inst == Instruction.AtomicMaxS32 || operation.Inst == Instruction.AtomicMinS32 + AggregateType dstType = operation.Inst is Instruction.AtomicMaxS32 or Instruction.AtomicMinS32 ? AggregateType.S32 : AggregateType.U32; diff --git a/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGenMemory.cs b/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGenMemory.cs index 634f9364a..32c930557 100644 --- a/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGenMemory.cs +++ b/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGenMemory.cs @@ -595,6 +595,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions varName = $"gl_out[{expr}].{varName}"; } } + break; default: diff --git a/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstType.cs b/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstType.cs index 56985ae08..43ff12168 100644 --- a/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstType.cs +++ b/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstType.cs @@ -4,7 +4,6 @@ using System.Diagnostics.CodeAnalysis; namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions { [Flags] - [SuppressMessage("Design", "CA1069: Enums values should not be duplicated")] enum InstType { OpNullary = Op | 0, diff --git a/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/IoMap.cs b/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/IoMap.cs index caa6ef642..8c45c0b67 100644 --- a/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/IoMap.cs +++ b/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/IoMap.cs @@ -79,9 +79,9 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions } else { - return stage == ShaderStage.TessellationControl || - stage == ShaderStage.TessellationEvaluation || - stage == ShaderStage.Geometry; + return stage is ShaderStage.TessellationControl or + ShaderStage.TessellationEvaluation or + ShaderStage.Geometry; } } diff --git a/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/NumberFormatter.cs b/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/NumberFormatter.cs index 28e44c900..b32e28e04 100644 --- a/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/NumberFormatter.cs +++ b/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/NumberFormatter.cs @@ -83,7 +83,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl public static string FormatInt(int value) { - if (value <= MaxDecimal && value >= -MaxDecimal) + if (value is <= MaxDecimal and >= (-MaxDecimal)) { return value.ToString(CultureInfo.InvariantCulture); } @@ -93,7 +93,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl public static string FormatUint(uint value) { - if (value <= MaxDecimal && value >= 0) + if (value is <= MaxDecimal and >= 0) { return value.ToString(CultureInfo.InvariantCulture) + "u"; } diff --git a/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/OperandManager.cs b/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/OperandManager.cs index a350b089c..6c20cb0c8 100644 --- a/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/OperandManager.cs +++ b/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/OperandManager.cs @@ -97,8 +97,8 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl } IoVariable ioVariable = (IoVariable)varId.Value; - bool isOutput = operation.StorageKind == StorageKind.Output || operation.StorageKind == StorageKind.OutputPerPatch; - bool isPerPatch = operation.StorageKind == StorageKind.InputPerPatch || operation.StorageKind == StorageKind.OutputPerPatch; + bool isOutput = operation.StorageKind is StorageKind.Output or StorageKind.OutputPerPatch; + bool isPerPatch = operation.StorageKind is StorageKind.InputPerPatch or StorageKind.OutputPerPatch; int location = 0; int component = 0; diff --git a/src/Ryujinx.Graphics.Shader/CodeGen/Spirv/Instructions.cs b/src/Ryujinx.Graphics.Shader/CodeGen/Spirv/Instructions.cs index 39b27a3e1..27b5c21c0 100644 --- a/src/Ryujinx.Graphics.Shader/CodeGen/Spirv/Instructions.cs +++ b/src/Ryujinx.Graphics.Shader/CodeGen/Spirv/Instructions.cs @@ -1695,6 +1695,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv varType = context.Properties.SharedMemories[bindingId.Value].Type & AggregateType.ElementTypeMask; baseObj = context.SharedMemories[bindingId.Value]; } + break; case StorageKind.Input: diff --git a/src/Ryujinx.Graphics.Shader/CodeGen/Spirv/IoMap.cs b/src/Ryujinx.Graphics.Shader/CodeGen/Spirv/IoMap.cs index 7b4e14ff0..1fd8a731a 100644 --- a/src/Ryujinx.Graphics.Shader/CodeGen/Spirv/IoMap.cs +++ b/src/Ryujinx.Graphics.Shader/CodeGen/Spirv/IoMap.cs @@ -104,9 +104,9 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv } else { - return stage == ShaderStage.TessellationControl || - stage == ShaderStage.TessellationEvaluation || - stage == ShaderStage.Geometry; + return stage is ShaderStage.TessellationControl or + ShaderStage.TessellationEvaluation or + ShaderStage.Geometry; } } diff --git a/src/Ryujinx.Graphics.Shader/CodeGen/Spirv/SpirvGenerator.cs b/src/Ryujinx.Graphics.Shader/CodeGen/Spirv/SpirvGenerator.cs index db4de586a..e1561446b 100644 --- a/src/Ryujinx.Graphics.Shader/CodeGen/Spirv/SpirvGenerator.cs +++ b/src/Ryujinx.Graphics.Shader/CodeGen/Spirv/SpirvGenerator.cs @@ -89,8 +89,8 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv context.AddCapability(Capability.GeometryShaderPassthroughNV); } } - else if (parameters.Definitions.Stage == ShaderStage.TessellationControl || - parameters.Definitions.Stage == ShaderStage.TessellationEvaluation) + else if (parameters.Definitions.Stage is ShaderStage.TessellationControl or + ShaderStage.TessellationEvaluation) { context.AddCapability(Capability.Tessellation); } diff --git a/src/Ryujinx.Graphics.Shader/Decoders/Decoder.cs b/src/Ryujinx.Graphics.Shader/Decoders/Decoder.cs index 72e934a39..ac1f24218 100644 --- a/src/Ryujinx.Graphics.Shader/Decoders/Decoder.cs +++ b/src/Ryujinx.Graphics.Shader/Decoders/Decoder.cs @@ -392,7 +392,7 @@ namespace Ryujinx.Graphics.Shader.Decoders if (perPatch) { - if (attr >= AttributeConsts.UserAttributePerPatchBase && attr < AttributeConsts.UserAttributePerPatchEnd) + if (attr is >= AttributeConsts.UserAttributePerPatchBase and < AttributeConsts.UserAttributePerPatchEnd) { int userAttr = attr - AttributeConsts.UserAttributePerPatchBase; int index = userAttr / 16; @@ -407,7 +407,7 @@ namespace Ryujinx.Graphics.Shader.Decoders } } } - else if (attr >= AttributeConsts.UserAttributeBase && attr < AttributeConsts.UserAttributeEnd) + else if (attr is >= AttributeConsts.UserAttributeBase and < AttributeConsts.UserAttributeEnd) { int userAttr = attr - AttributeConsts.UserAttributeBase; int index = userAttr / 16; @@ -436,16 +436,18 @@ namespace Ryujinx.Graphics.Shader.Decoders switch (attr) { case AttributeConsts.Layer: - if (definitions.Stage != ShaderStage.Compute && definitions.Stage != ShaderStage.Fragment) + if (definitions.Stage is not ShaderStage.Compute and not ShaderStage.Fragment) { context.SetUsedFeature(FeatureFlags.RtLayer); } + break; case AttributeConsts.ViewportIndex: if (definitions.Stage != ShaderStage.Fragment) { context.SetUsedFeature(FeatureFlags.ViewportIndex); } + break; case AttributeConsts.ClipDistance0: case AttributeConsts.ClipDistance1: @@ -459,12 +461,14 @@ namespace Ryujinx.Graphics.Shader.Decoders { context.SetClipDistanceWritten((attr - AttributeConsts.ClipDistance0) / 4); } + break; case AttributeConsts.ViewportMask: if (definitions.Stage != ShaderStage.Fragment) { context.SetUsedFeature(FeatureFlags.ViewportMask); } + break; } } @@ -478,12 +482,14 @@ namespace Ryujinx.Graphics.Shader.Decoders { context.SetUsedFeature(FeatureFlags.FragCoordXY); } + break; case AttributeConsts.InstanceId: if (definitions.Stage == ShaderStage.Vertex) { context.SetUsedFeature(FeatureFlags.InstanceId); } + break; } } @@ -879,7 +885,7 @@ namespace Ryujinx.Graphics.Shader.Decoders public static bool IsPopBranch(InstName name) { - return name == InstName.Brk || name == InstName.Cont || name == InstName.Sync; + return name is InstName.Brk or InstName.Cont or InstName.Sync; } private static MergeType GetMergeTypeFromPush(InstName name) diff --git a/src/Ryujinx.Graphics.Shader/Instructions/AttributeMap.cs b/src/Ryujinx.Graphics.Shader/Instructions/AttributeMap.cs index 572cc513d..b89502e16 100644 --- a/src/Ryujinx.Graphics.Shader/Instructions/AttributeMap.cs +++ b/src/Ryujinx.Graphics.Shader/Instructions/AttributeMap.cs @@ -1,6 +1,7 @@ using Ryujinx.Graphics.Shader.IntermediateRepresentation; using Ryujinx.Graphics.Shader.Translation; using System.Collections.Generic; +using System.Collections.ObjectModel; using static Ryujinx.Graphics.Shader.IntermediateRepresentation.OperandHelper; namespace Ryujinx.Graphics.Shader.Instructions @@ -46,8 +47,8 @@ namespace Ryujinx.Graphics.Shader.Instructions } } - private static readonly IReadOnlyDictionary _attributes; - private static readonly IReadOnlyDictionary _attributesPerPatch; + private static readonly ReadOnlyDictionary _attributes; + private static readonly ReadOnlyDictionary _attributesPerPatch; static AttributeMap() { @@ -55,7 +56,7 @@ namespace Ryujinx.Graphics.Shader.Instructions _attributesPerPatch = CreatePerPatchMap(); } - private static IReadOnlyDictionary CreateMap() + private static ReadOnlyDictionary CreateMap() { Dictionary map = new(); @@ -79,10 +80,10 @@ namespace Ryujinx.Graphics.Shader.Instructions Add(map, 0x3a0, AggregateType.Array | AggregateType.S32, IoVariable.ViewportMask, StagesMask.Fragment, StagesMask.VertexTessellationGeometry); Add(map, 0x3fc, AggregateType.Bool, IoVariable.FrontFacing, StagesMask.Fragment, StagesMask.None); - return map; + return map.AsReadOnly(); } - private static IReadOnlyDictionary CreatePerPatchMap() + private static ReadOnlyDictionary CreatePerPatchMap() { Dictionary map = new(); @@ -90,7 +91,7 @@ namespace Ryujinx.Graphics.Shader.Instructions Add(map, 0x010, AggregateType.Vector2 | AggregateType.FP32, IoVariable.TessellationLevelInner, StagesMask.TessellationEvaluation, StagesMask.TessellationControl); Add(map, 0x018, AggregateType.Vector4 | AggregateType.FP32, IoVariable.UserDefined, StagesMask.TessellationEvaluation, StagesMask.TessellationControl, 31, 0x200); - return map; + return map.AsReadOnly(); } private static void Add( @@ -326,9 +327,9 @@ namespace Ryujinx.Graphics.Shader.Instructions return false; } - return stage == ShaderStage.TessellationControl || - stage == ShaderStage.TessellationEvaluation || - stage == ShaderStage.Geometry; + return stage is ShaderStage.TessellationControl or + ShaderStage.TessellationEvaluation or + ShaderStage.Geometry; } public static bool HasInvocationId(ShaderStage stage, bool isOutput) diff --git a/src/Ryujinx.Graphics.Shader/Instructions/InstEmitAttribute.cs b/src/Ryujinx.Graphics.Shader/Instructions/InstEmitAttribute.cs index 89b7e9831..2b6647cd2 100644 --- a/src/Ryujinx.Graphics.Shader/Instructions/InstEmitAttribute.cs +++ b/src/Ryujinx.Graphics.Shader/Instructions/InstEmitAttribute.cs @@ -164,7 +164,7 @@ namespace Ryujinx.Graphics.Shader.Instructions { isFixedFunc = TryFixedFuncToUserAttributeIpa(context, op.Imm10, out res); - if (op.Imm10 >= AttributeConsts.UserAttributeBase && op.Imm10 < AttributeConsts.UserAttributeEnd) + if (op.Imm10 is >= AttributeConsts.UserAttributeBase and < AttributeConsts.UserAttributeEnd) { int index = (op.Imm10 - AttributeConsts.UserAttributeBase) >> 4; @@ -173,7 +173,7 @@ namespace Ryujinx.Graphics.Shader.Instructions res = context.FPMultiply(res, context.Load(StorageKind.Input, IoVariable.FragmentCoord, null, Const(3))); } } - else if (op.Imm10 == AttributeConsts.PositionX || op.Imm10 == AttributeConsts.PositionY) + else if (op.Imm10 is AttributeConsts.PositionX or AttributeConsts.PositionY) { // FragCoord X/Y must be divided by the render target scale, if resolution scaling is active, // because the shader code is not expecting scaled values. @@ -296,19 +296,19 @@ namespace Ryujinx.Graphics.Shader.Instructions private static bool HasPrimitiveVertex(int attr) { - return attr != AttributeConsts.PrimitiveId && - attr != AttributeConsts.TessCoordX && - attr != AttributeConsts.TessCoordY; + return attr is not AttributeConsts.PrimitiveId and + not AttributeConsts.TessCoordX and + not AttributeConsts.TessCoordY; } private static bool CanLoadOutput(int attr) { - return attr != AttributeConsts.TessCoordX && attr != AttributeConsts.TessCoordY; + return attr is not AttributeConsts.TessCoordX and not AttributeConsts.TessCoordY; } private static bool TryFixedFuncToUserAttributeIpa(EmitterContext context, int attr, out Operand selectedAttr) { - if (attr >= AttributeConsts.FrontColorDiffuseR && attr < AttributeConsts.BackColorDiffuseR) + if (attr is >= AttributeConsts.FrontColorDiffuseR and < AttributeConsts.BackColorDiffuseR) { // TODO: If two sided rendering is enabled, then this should return // FrontColor if the fragment is front facing, and back color otherwise. @@ -321,12 +321,12 @@ namespace Ryujinx.Graphics.Shader.Instructions selectedAttr = GenerateIpaLoad(context, FixedFuncToUserAttribute(context.TranslatorContext, attr, isOutput: false)); return true; } - else if (attr >= AttributeConsts.BackColorDiffuseR && attr < AttributeConsts.ClipDistance0) + else if (attr is >= AttributeConsts.BackColorDiffuseR and < AttributeConsts.ClipDistance0) { selectedAttr = ConstF(((attr >> 2) & 3) == 3 ? 1f : 0f); return true; } - else if (attr >= AttributeConsts.TexCoordBase && attr < AttributeConsts.TexCoordEnd) + else if (attr is >= AttributeConsts.TexCoordBase and < AttributeConsts.TexCoordEnd) { selectedAttr = GenerateIpaLoad(context, FixedFuncToUserAttribute(context.TranslatorContext, attr, isOutput: false)); return true; @@ -355,11 +355,11 @@ namespace Ryujinx.Graphics.Shader.Instructions { attr = FixedFuncToUserAttribute(translatorContext, attr, AttributeConsts.FogCoord, fixedStartAttr, isOutput); } - else if (attr >= AttributeConsts.FrontColorDiffuseR && attr < AttributeConsts.ClipDistance0) + else if (attr is >= AttributeConsts.FrontColorDiffuseR and < AttributeConsts.ClipDistance0) { attr = FixedFuncToUserAttribute(translatorContext, attr, AttributeConsts.FrontColorDiffuseR, fixedStartAttr + 1, isOutput); } - else if (attr >= AttributeConsts.TexCoordBase && attr < AttributeConsts.TexCoordEnd) + else if (attr is >= AttributeConsts.TexCoordBase and < AttributeConsts.TexCoordEnd) { attr = FixedFuncToUserAttribute(translatorContext, attr, AttributeConsts.TexCoordBase, fixedStartAttr + 5, isOutput); } diff --git a/src/Ryujinx.Graphics.Shader/Instructions/InstEmitConversion.cs b/src/Ryujinx.Graphics.Shader/Instructions/InstEmitConversion.cs index 198c9077a..4b917c1eb 100644 --- a/src/Ryujinx.Graphics.Shader/Instructions/InstEmitConversion.cs +++ b/src/Ryujinx.Graphics.Shader/Instructions/InstEmitConversion.cs @@ -179,8 +179,8 @@ namespace Ryujinx.Graphics.Shader.Instructions Instruction fpType = srcType.ToInstFPType(); - bool isSignedInt = dstType == IDstFmt.S16 || dstType == IDstFmt.S32 || dstType == IDstFmt.S64; - bool isSmallInt = dstType == IDstFmt.U16 || dstType == IDstFmt.S16; + bool isSignedInt = dstType is IDstFmt.S16 or IDstFmt.S32 or IDstFmt.S64; + bool isSmallInt = dstType is IDstFmt.U16 or IDstFmt.S16; Operand srcB = context.FPAbsNeg(src, absolute, negate, fpType); @@ -242,15 +242,15 @@ namespace Ryujinx.Graphics.Shader.Instructions bool negate) { bool isSignedInt = - srcType == ISrcFmt.S8 || - srcType == ISrcFmt.S16 || - srcType == ISrcFmt.S32 || - srcType == ISrcFmt.S64; + srcType is ISrcFmt.S8 or + ISrcFmt.S16 or + ISrcFmt.S32 or + ISrcFmt.S64; bool isSmallInt = - srcType == ISrcFmt.U16 || - srcType == ISrcFmt.S16 || - srcType == ISrcFmt.U8 || - srcType == ISrcFmt.S8; + srcType is ISrcFmt.U16 or + ISrcFmt.S16 or + ISrcFmt.U8 or + ISrcFmt.S8; // TODO: Handle S/U64. @@ -258,7 +258,7 @@ namespace Ryujinx.Graphics.Shader.Instructions if (isSmallInt) { - int size = srcType == ISrcFmt.U16 || srcType == ISrcFmt.S16 ? 16 : 8; + int size = srcType is ISrcFmt.U16 or ISrcFmt.S16 ? 16 : 8; srcB = isSignedInt ? context.BitfieldExtractS32(srcB, Const((int)byteSelection * 8), Const(size)) @@ -302,22 +302,22 @@ namespace Ryujinx.Graphics.Shader.Instructions } bool srcIsSignedInt = - srcType == ISrcDstFmt.S8 || - srcType == ISrcDstFmt.S16 || - srcType == ISrcDstFmt.S32; + srcType is ISrcDstFmt.S8 or + ISrcDstFmt.S16 or + ISrcDstFmt.S32; bool dstIsSignedInt = - dstType == ISrcDstFmt.S8 || - dstType == ISrcDstFmt.S16 || - dstType == ISrcDstFmt.S32; + dstType is ISrcDstFmt.S8 or + ISrcDstFmt.S16 or + ISrcDstFmt.S32; bool srcIsSmallInt = - srcType == ISrcDstFmt.U16 || - srcType == ISrcDstFmt.S16 || - srcType == ISrcDstFmt.U8 || - srcType == ISrcDstFmt.S8; + srcType is ISrcDstFmt.U16 or + ISrcDstFmt.S16 or + ISrcDstFmt.U8 or + ISrcDstFmt.S8; if (srcIsSmallInt) { - int size = srcType == ISrcDstFmt.U16 || srcType == ISrcDstFmt.S16 ? 16 : 8; + int size = srcType is ISrcDstFmt.U16 or ISrcDstFmt.S16 ? 16 : 8; src = srcIsSignedInt ? context.BitfieldExtractS32(src, Const((int)byteSelection * 8), Const(size)) diff --git a/src/Ryujinx.Graphics.Shader/Instructions/InstEmitFloatComparison.cs b/src/Ryujinx.Graphics.Shader/Instructions/InstEmitFloatComparison.cs index 314ab917c..e70afd74c 100644 --- a/src/Ryujinx.Graphics.Shader/Instructions/InstEmitFloatComparison.cs +++ b/src/Ryujinx.Graphics.Shader/Instructions/InstEmitFloatComparison.cs @@ -534,7 +534,7 @@ namespace Ryujinx.Graphics.Shader.Instructions { res = Const(IrConsts.False); } - else if (cond == FComp.Nan || cond == FComp.Num) + else if (cond is FComp.Nan or FComp.Num) { res = context.BitwiseOr(context.IsNan(srcA, fpType), context.IsNan(srcB, fpType)); diff --git a/src/Ryujinx.Graphics.Shader/Instructions/InstEmitMemory.cs b/src/Ryujinx.Graphics.Shader/Instructions/InstEmitMemory.cs index 3fcb821d3..154ed24fc 100644 --- a/src/Ryujinx.Graphics.Shader/Instructions/InstEmitMemory.cs +++ b/src/Ryujinx.Graphics.Shader/Instructions/InstEmitMemory.cs @@ -73,7 +73,7 @@ namespace Ryujinx.Graphics.Shader.Instructions Operand slot = Const(op.CbufSlot); Operand srcA = GetSrcReg(context, op.SrcA); - if (op.AddressMode == AddressMode.Is || op.AddressMode == AddressMode.Isl) + if (op.AddressMode is AddressMode.Is or AddressMode.Isl) { slot = context.IAdd(slot, context.BitfieldExtractU32(srcA, Const(16), Const(16))); srcA = context.BitwiseAnd(srcA, Const(0xffff)); @@ -213,7 +213,7 @@ namespace Ryujinx.Graphics.Shader.Instructions switch (op) { case AtomOp.Add: - if (type == AtomSize.S32 || type == AtomSize.U32) + if (type is AtomSize.S32 or AtomSize.U32) { res = context.AtomicAdd(storageKind, e0, e1, value); } @@ -221,6 +221,7 @@ namespace Ryujinx.Graphics.Shader.Instructions { context.TranslatorContext.GpuAccessor.Log($"Invalid reduction type: {type}."); } + break; case AtomOp.Min: if (type == AtomSize.S32) @@ -235,6 +236,7 @@ namespace Ryujinx.Graphics.Shader.Instructions { context.TranslatorContext.GpuAccessor.Log($"Invalid reduction type: {type}."); } + break; case AtomOp.Max: if (type == AtomSize.S32) @@ -249,9 +251,10 @@ namespace Ryujinx.Graphics.Shader.Instructions { context.TranslatorContext.GpuAccessor.Log($"Invalid reduction type: {type}."); } + break; case AtomOp.And: - if (type == AtomSize.S32 || type == AtomSize.U32) + if (type is AtomSize.S32 or AtomSize.U32) { res = context.AtomicAnd(storageKind, e0, e1, value); } @@ -259,9 +262,10 @@ namespace Ryujinx.Graphics.Shader.Instructions { context.TranslatorContext.GpuAccessor.Log($"Invalid reduction type: {type}."); } + break; case AtomOp.Or: - if (type == AtomSize.S32 || type == AtomSize.U32) + if (type is AtomSize.S32 or AtomSize.U32) { res = context.AtomicOr(storageKind, e0, e1, value); } @@ -269,9 +273,10 @@ namespace Ryujinx.Graphics.Shader.Instructions { context.TranslatorContext.GpuAccessor.Log($"Invalid reduction type: {type}."); } + break; case AtomOp.Xor: - if (type == AtomSize.S32 || type == AtomSize.U32) + if (type is AtomSize.S32 or AtomSize.U32) { res = context.AtomicXor(storageKind, e0, e1, value); } @@ -279,9 +284,10 @@ namespace Ryujinx.Graphics.Shader.Instructions { context.TranslatorContext.GpuAccessor.Log($"Invalid reduction type: {type}."); } + break; case AtomOp.Exch: - if (type == AtomSize.S32 || type == AtomSize.U32) + if (type is AtomSize.S32 or AtomSize.U32) { res = context.AtomicSwap(storageKind, e0, e1, value); } @@ -289,6 +295,7 @@ namespace Ryujinx.Graphics.Shader.Instructions { context.TranslatorContext.GpuAccessor.Log($"Invalid reduction type: {type}."); } + break; default: context.TranslatorContext.GpuAccessor.Log($"Invalid atomic operation: {op}."); diff --git a/src/Ryujinx.Graphics.Shader/Instructions/InstEmitMove.cs b/src/Ryujinx.Graphics.Shader/Instructions/InstEmitMove.cs index 944039d65..df84c38f1 100644 --- a/src/Ryujinx.Graphics.Shader/Instructions/InstEmitMove.cs +++ b/src/Ryujinx.Graphics.Shader/Instructions/InstEmitMove.cs @@ -92,14 +92,14 @@ namespace Ryujinx.Graphics.Shader.Instructions break; case SReg.InvocationInfo: - if (context.TranslatorContext.Definitions.Stage != ShaderStage.Compute && context.TranslatorContext.Definitions.Stage != ShaderStage.Fragment) + if (context.TranslatorContext.Definitions.Stage is not ShaderStage.Compute and not ShaderStage.Fragment) { // Note: Lowest 8-bits seems to contain some primitive index, // but it seems to be NVIDIA implementation specific as it's only used // to calculate ISBE offsets, so we can just keep it as zero. - if (context.TranslatorContext.Definitions.Stage == ShaderStage.TessellationControl || - context.TranslatorContext.Definitions.Stage == ShaderStage.TessellationEvaluation) + if (context.TranslatorContext.Definitions.Stage is ShaderStage.TessellationControl or + ShaderStage.TessellationEvaluation) { src = context.ShiftLeft(context.Load(StorageKind.Input, IoVariable.PatchVertices), Const(16)); } @@ -112,6 +112,7 @@ namespace Ryujinx.Graphics.Shader.Instructions { src = Const(0); } + break; case SReg.TId: diff --git a/src/Ryujinx.Graphics.Shader/Instructions/InstEmitShift.cs b/src/Ryujinx.Graphics.Shader/Instructions/InstEmitShift.cs index 7e2145c37..9c7899940 100644 --- a/src/Ryujinx.Graphics.Shader/Instructions/InstEmitShift.cs +++ b/src/Ryujinx.Graphics.Shader/Instructions/InstEmitShift.cs @@ -115,7 +115,7 @@ namespace Ryujinx.Graphics.Shader.Instructions bool left, bool writeCC) { - bool isLongShift = maxShift == MaxShift.U64 || maxShift == MaxShift.S64; + bool isLongShift = maxShift is MaxShift.U64 or MaxShift.S64; bool signedShift = maxShift == MaxShift.S64; int maxShiftConst = isLongShift ? 64 : 32; diff --git a/src/Ryujinx.Graphics.Shader/Instructions/InstEmitSurface.cs b/src/Ryujinx.Graphics.Shader/Instructions/InstEmitSurface.cs index 946dcc02e..e9f930179 100644 --- a/src/Ryujinx.Graphics.Shader/Instructions/InstEmitSurface.cs +++ b/src/Ryujinx.Graphics.Shader/Instructions/InstEmitSurface.cs @@ -258,7 +258,7 @@ namespace Ryujinx.Graphics.Shader.Instructions } // TODO: FP and 64-bit formats. - TextureFormat format = size == SuatomSize.Sd32 || size == SuatomSize.Sd64 + TextureFormat format = size is SuatomSize.Sd32 or SuatomSize.Sd64 ? (isBindless ? TextureFormat.Unknown : ShaderProperties.GetTextureFormatAtomic(context.TranslatorContext.GpuAccessor, imm)) : GetTextureFormat(size); @@ -537,7 +537,7 @@ namespace Ryujinx.Graphics.Shader.Instructions } // TODO: FP and 64-bit formats. - TextureFormat format = size == SuatomSize.Sd32 || size == SuatomSize.Sd64 + TextureFormat format = size is SuatomSize.Sd32 or SuatomSize.Sd64 ? (isBindless ? TextureFormat.Unknown : ShaderProperties.GetTextureFormatAtomic(context.TranslatorContext.GpuAccessor, imm)) : GetTextureFormat(size); diff --git a/src/Ryujinx.Graphics.Shader/Instructions/InstEmitTexture.cs b/src/Ryujinx.Graphics.Shader/Instructions/InstEmitTexture.cs index 7499f12d8..19b22e03b 100644 --- a/src/Ryujinx.Graphics.Shader/Instructions/InstEmitTexture.cs +++ b/src/Ryujinx.Graphics.Shader/Instructions/InstEmitTexture.cs @@ -284,7 +284,7 @@ namespace Ryujinx.Graphics.Shader.Instructions flags |= TextureFlags.Offset; } - if (lodMode == Lod.Lb || lodMode == Lod.Lba) + if (lodMode is Lod.Lb or Lod.Lba) { sourcesList.Add(lodValue); @@ -504,6 +504,7 @@ namespace Ryujinx.Graphics.Shader.Instructions sourcesList.Add(ConstF(0)); } + break; case TldsTarget.Texture1DLodLevel: @@ -694,10 +695,10 @@ namespace Ryujinx.Graphics.Shader.Instructions } bool isArray = - dimensions == TexDim.Array1d || - dimensions == TexDim.Array2d || - dimensions == TexDim.Array3d || - dimensions == TexDim.ArrayCube; + dimensions is TexDim.Array1d or + TexDim.Array2d or + TexDim.Array3d or + TexDim.ArrayCube; Operand arrayIndex = isArray ? Ra() : null; @@ -736,7 +737,7 @@ namespace Ryujinx.Graphics.Shader.Instructions Operand[] packedOffs = new Operand[2]; - bool hasAnyOffset = offset == TexOffset.Aoffi || offset == TexOffset.Ptp; + bool hasAnyOffset = offset is TexOffset.Aoffi or TexOffset.Ptp; packedOffs[0] = hasAnyOffset ? Rb() : null; packedOffs[1] = offset == TexOffset.Ptp ? Rb() : null; @@ -849,10 +850,10 @@ namespace Ryujinx.Graphics.Shader.Instructions int coordsCount = type.GetDimensions(); bool isArray = - dimensions == TexDim.Array1d || - dimensions == TexDim.Array2d || - dimensions == TexDim.Array3d || - dimensions == TexDim.ArrayCube; + dimensions is TexDim.Array1d or + TexDim.Array2d or + TexDim.Array3d or + TexDim.ArrayCube; Operand arrayIndex = isArray ? Ra() : null; @@ -993,10 +994,10 @@ namespace Ryujinx.Graphics.Shader.Instructions Operand packedParams = Ra(); bool isArray = - dimensions == TexDim.Array1d || - dimensions == TexDim.Array2d || - dimensions == TexDim.Array3d || - dimensions == TexDim.ArrayCube; + dimensions is TexDim.Array1d or + TexDim.Array2d or + TexDim.Array3d or + TexDim.ArrayCube; if (isArray) { @@ -1143,6 +1144,7 @@ namespace Ryujinx.Graphics.Shader.Instructions context.Copy(d, context.TextureQuerySize(type, flags, setAndBinding, compIndex, sources)); } } + break; case TexQuery.TexHeaderTextureType: @@ -1174,6 +1176,7 @@ namespace Ryujinx.Graphics.Shader.Instructions context.Copy(d, context.TextureQuerySamples(type, flags, setAndBinding, sources)); } } + break; default: diff --git a/src/Ryujinx.Graphics.Shader/IntermediateRepresentation/Instruction.cs b/src/Ryujinx.Graphics.Shader/IntermediateRepresentation/Instruction.cs index 273a38a5b..f63a8c4be 100644 --- a/src/Ryujinx.Graphics.Shader/IntermediateRepresentation/Instruction.cs +++ b/src/Ryujinx.Graphics.Shader/IntermediateRepresentation/Instruction.cs @@ -179,19 +179,19 @@ namespace Ryujinx.Graphics.Shader.IntermediateRepresentation public static bool IsTextureQuery(this Instruction inst) { inst &= Instruction.Mask; - return inst == Instruction.Lod || inst == Instruction.TextureQuerySamples || inst == Instruction.TextureQuerySize; + return inst is Instruction.Lod or Instruction.TextureQuerySamples or Instruction.TextureQuerySize; } public static bool IsImage(this Instruction inst) { inst &= Instruction.Mask; - return inst == Instruction.ImageAtomic || inst == Instruction.ImageLoad || inst == Instruction.ImageStore; + return inst is Instruction.ImageAtomic or Instruction.ImageLoad or Instruction.ImageStore; } public static bool IsImageStore(this Instruction inst) { inst &= Instruction.Mask; - return inst == Instruction.ImageAtomic || inst == Instruction.ImageStore; + return inst is Instruction.ImageAtomic or Instruction.ImageStore; } } } diff --git a/src/Ryujinx.Graphics.Shader/IntermediateRepresentation/StorageKind.cs b/src/Ryujinx.Graphics.Shader/IntermediateRepresentation/StorageKind.cs index 669c12816..2b39e85ea 100644 --- a/src/Ryujinx.Graphics.Shader/IntermediateRepresentation/StorageKind.cs +++ b/src/Ryujinx.Graphics.Shader/IntermediateRepresentation/StorageKind.cs @@ -24,22 +24,22 @@ namespace Ryujinx.Graphics.Shader.IntermediateRepresentation { public static bool IsInputOrOutput(this StorageKind storageKind) { - return storageKind == StorageKind.Input || - storageKind == StorageKind.InputPerPatch || - storageKind == StorageKind.Output || - storageKind == StorageKind.OutputPerPatch; + return storageKind is StorageKind.Input or + StorageKind.InputPerPatch or + StorageKind.Output or + StorageKind.OutputPerPatch; } public static bool IsOutput(this StorageKind storageKind) { - return storageKind == StorageKind.Output || - storageKind == StorageKind.OutputPerPatch; + return storageKind is StorageKind.Output or + StorageKind.OutputPerPatch; } public static bool IsPerPatch(this StorageKind storageKind) { - return storageKind == StorageKind.InputPerPatch || - storageKind == StorageKind.OutputPerPatch; + return storageKind is StorageKind.InputPerPatch or + StorageKind.OutputPerPatch; } } } diff --git a/src/Ryujinx.Graphics.Shader/IntermediateRepresentation/TextureFlags.cs b/src/Ryujinx.Graphics.Shader/IntermediateRepresentation/TextureFlags.cs index 51ff09cf8..61e6ecf5a 100644 --- a/src/Ryujinx.Graphics.Shader/IntermediateRepresentation/TextureFlags.cs +++ b/src/Ryujinx.Graphics.Shader/IntermediateRepresentation/TextureFlags.cs @@ -4,7 +4,6 @@ using System.Diagnostics.CodeAnalysis; namespace Ryujinx.Graphics.Shader.IntermediateRepresentation { [Flags] - [SuppressMessage("Design", "CA1069: Enums values should not be duplicated")] enum TextureFlags { None = 0, diff --git a/src/Ryujinx.Graphics.Shader/ShaderStage.cs b/src/Ryujinx.Graphics.Shader/ShaderStage.cs index 2522b4fc1..faea5c357 100644 --- a/src/Ryujinx.Graphics.Shader/ShaderStage.cs +++ b/src/Ryujinx.Graphics.Shader/ShaderStage.cs @@ -21,7 +21,7 @@ namespace Ryujinx.Graphics.Shader /// True if the shader stage supports render scale, false otherwise public static bool SupportsRenderScale(this ShaderStage stage) { - return stage == ShaderStage.Vertex || stage == ShaderStage.Fragment || stage == ShaderStage.Compute; + return stage is ShaderStage.Vertex or ShaderStage.Fragment or ShaderStage.Compute; } /// @@ -31,10 +31,10 @@ namespace Ryujinx.Graphics.Shader /// True if the shader stage is vertex, tessellation or geometry, false otherwise public static bool IsVtg(this ShaderStage stage) { - return stage == ShaderStage.Vertex || - stage == ShaderStage.TessellationControl || - stage == ShaderStage.TessellationEvaluation || - stage == ShaderStage.Geometry; + return stage is ShaderStage.Vertex or + ShaderStage.TessellationControl or + ShaderStage.TessellationEvaluation or + ShaderStage.Geometry; } } } diff --git a/src/Ryujinx.Graphics.Shader/StructuredIr/GotoElimination.cs b/src/Ryujinx.Graphics.Shader/StructuredIr/GotoElimination.cs index 687e5942d..e2e52586a 100644 --- a/src/Ryujinx.Graphics.Shader/StructuredIr/GotoElimination.cs +++ b/src/Ryujinx.Graphics.Shader/StructuredIr/GotoElimination.cs @@ -102,8 +102,8 @@ namespace Ryujinx.Graphics.Shader.StructuredIr return false; } - IAstNode block; - IAstNode other; + AstNode block; + AstNode other; int blockLvl, otherLvl; @@ -441,7 +441,7 @@ namespace Ryujinx.Graphics.Shader.StructuredIr return path.ToArray(); } - private static int Level(IAstNode node) + private static int Level(AstNode node) { int level = 0; diff --git a/src/Ryujinx.Graphics.Shader/StructuredIr/InstructionInfo.cs b/src/Ryujinx.Graphics.Shader/StructuredIr/InstructionInfo.cs index 72d0e9896..b2ddf6ab7 100644 --- a/src/Ryujinx.Graphics.Shader/StructuredIr/InstructionInfo.cs +++ b/src/Ryujinx.Graphics.Shader/StructuredIr/InstructionInfo.cs @@ -150,11 +150,11 @@ namespace Ryujinx.Graphics.Shader.StructuredIr { // TODO: Return correct type depending on source index, // that can improve the decompiler output. - if (inst == Instruction.ImageLoad || - inst == Instruction.ImageStore || - inst == Instruction.ImageAtomic || - inst == Instruction.Lod || - inst == Instruction.TextureSample) + if (inst is Instruction.ImageLoad or + Instruction.ImageStore or + Instruction.ImageAtomic or + Instruction.Lod or + Instruction.TextureSample) { return AggregateType.FP32; } diff --git a/src/Ryujinx.Graphics.Shader/StructuredIr/ShaderProperties.cs b/src/Ryujinx.Graphics.Shader/StructuredIr/ShaderProperties.cs index f56d7bff3..f0f22c056 100644 --- a/src/Ryujinx.Graphics.Shader/StructuredIr/ShaderProperties.cs +++ b/src/Ryujinx.Graphics.Shader/StructuredIr/ShaderProperties.cs @@ -87,7 +87,7 @@ namespace Ryujinx.Graphics.Shader.StructuredIr private static bool FormatSupportsAtomic(TextureFormat format) { - return format == TextureFormat.R32Sint || format == TextureFormat.R32Uint; + return format is TextureFormat.R32Sint or TextureFormat.R32Uint; } public static TextureFormat GetTextureFormatAtomic(IGpuAccessor gpuAccessor, int handle, int cbufSlot = -1) diff --git a/src/Ryujinx.Graphics.Shader/StructuredIr/StructuredProgram.cs b/src/Ryujinx.Graphics.Shader/StructuredIr/StructuredProgram.cs index 824aea195..63bd820dc 100644 --- a/src/Ryujinx.Graphics.Shader/StructuredIr/StructuredProgram.cs +++ b/src/Ryujinx.Graphics.Shader/StructuredIr/StructuredProgram.cs @@ -83,7 +83,7 @@ namespace Ryujinx.Graphics.Shader.StructuredIr Instruction inst = operation.Inst; StorageKind storageKind = operation.StorageKind; - if (inst == Instruction.Load || inst == Instruction.Store) + if (inst is Instruction.Load or Instruction.Store) { if (storageKind.IsInputOrOutput()) { diff --git a/src/Ryujinx.Graphics.Shader/TextureHandle.cs b/src/Ryujinx.Graphics.Shader/TextureHandle.cs index 3aaceac48..d2132172d 100644 --- a/src/Ryujinx.Graphics.Shader/TextureHandle.cs +++ b/src/Ryujinx.Graphics.Shader/TextureHandle.cs @@ -110,8 +110,8 @@ namespace Ryujinx.Graphics.Shader samplerHandle = samplerWordOffset; } - if (handleType == TextureHandleType.SeparateSamplerId || - handleType == TextureHandleType.SeparateConstantSamplerHandle) + if (handleType is TextureHandleType.SeparateSamplerId or + TextureHandleType.SeparateConstantSamplerHandle) { samplerHandle <<= 20; } diff --git a/src/Ryujinx.Graphics.Shader/Translation/AggregateType.cs b/src/Ryujinx.Graphics.Shader/Translation/AggregateType.cs index 108fcb94f..496fbc235 100644 --- a/src/Ryujinx.Graphics.Shader/Translation/AggregateType.cs +++ b/src/Ryujinx.Graphics.Shader/Translation/AggregateType.cs @@ -4,7 +4,6 @@ using System.Diagnostics.CodeAnalysis; namespace Ryujinx.Graphics.Shader.Translation { [Flags] - [SuppressMessage("Design", "CA1069: Enums values should not be duplicated")] enum AggregateType { Invalid, diff --git a/src/Ryujinx.Graphics.Shader/Translation/ControlFlowGraph.cs b/src/Ryujinx.Graphics.Shader/Translation/ControlFlowGraph.cs index e14044256..1df45a478 100644 --- a/src/Ryujinx.Graphics.Shader/Translation/ControlFlowGraph.cs +++ b/src/Ryujinx.Graphics.Shader/Translation/ControlFlowGraph.cs @@ -110,9 +110,9 @@ namespace Ryujinx.Graphics.Shader.Translation currentBlock.Operations.AddLast(operation); } - needsNewBlock = operation.Inst == Instruction.Branch || - operation.Inst == Instruction.BranchIfTrue || - operation.Inst == Instruction.BranchIfFalse; + needsNewBlock = operation.Inst is Instruction.Branch or + Instruction.BranchIfTrue or + Instruction.BranchIfFalse; if (needsNewBlock) { diff --git a/src/Ryujinx.Graphics.Shader/Translation/HelperFunctionManager.cs b/src/Ryujinx.Graphics.Shader/Translation/HelperFunctionManager.cs index ef2f8759d..ec181bb09 100644 --- a/src/Ryujinx.Graphics.Shader/Translation/HelperFunctionManager.cs +++ b/src/Ryujinx.Graphics.Shader/Translation/HelperFunctionManager.cs @@ -470,6 +470,5 @@ namespace Ryujinx.Graphics.Shader.Translation return oldValue; } - } } diff --git a/src/Ryujinx.Graphics.Shader/Translation/Optimizations/ConstantFolding.cs b/src/Ryujinx.Graphics.Shader/Translation/Optimizations/ConstantFolding.cs index 3941303b1..345e83c82 100644 --- a/src/Ryujinx.Graphics.Shader/Translation/Optimizations/ConstantFolding.cs +++ b/src/Ryujinx.Graphics.Shader/Translation/Optimizations/ConstantFolding.cs @@ -167,6 +167,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations operation.TurnIntoCopy(Cbuf(cbufSlot, cbufOffset)); } } + break; case Instruction.Maximum: diff --git a/src/Ryujinx.Graphics.Shader/Translation/Optimizations/GlobalToStorage.cs b/src/Ryujinx.Graphics.Shader/Translation/Optimizations/GlobalToStorage.cs index 4805fb1ca..55628c88b 100644 --- a/src/Ryujinx.Graphics.Shader/Translation/Optimizations/GlobalToStorage.cs +++ b/src/Ryujinx.Graphics.Shader/Translation/Optimizations/GlobalToStorage.cs @@ -91,7 +91,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations return functionId; } - public bool TryGetFunctionId(Operation baseOp, bool isMultiTarget, IReadOnlyList targetCbs, out int functionId) + public bool TryGetFunctionId(Operation baseOp, bool isMultiTarget, List targetCbs, out int functionId) { foreach (Entry entry in _entries) { @@ -281,19 +281,19 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations private static bool IsGlobalMemory(StorageKind storageKind) { - return storageKind == StorageKind.GlobalMemory || - storageKind == StorageKind.GlobalMemoryS8 || - storageKind == StorageKind.GlobalMemoryS16 || - storageKind == StorageKind.GlobalMemoryU8 || - storageKind == StorageKind.GlobalMemoryU16; + return storageKind is StorageKind.GlobalMemory or + StorageKind.GlobalMemoryS8 or + StorageKind.GlobalMemoryS16 or + StorageKind.GlobalMemoryU8 or + StorageKind.GlobalMemoryU16; } private static bool IsSmallInt(StorageKind storageKind) { - return storageKind == StorageKind.GlobalMemoryS8 || - storageKind == StorageKind.GlobalMemoryS16 || - storageKind == StorageKind.GlobalMemoryU8 || - storageKind == StorageKind.GlobalMemoryU16; + return storageKind is StorageKind.GlobalMemoryS8 or + StorageKind.GlobalMemoryS16 or + StorageKind.GlobalMemoryU8 or + StorageKind.GlobalMemoryU16; } private static LinkedListNode ReplaceGlobalMemoryWithStorage( @@ -865,6 +865,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations return context.IMaximumS32(memValue, value); }); } + break; case Instruction.AtomicMaxU32: resultValue = context.AtomicMaxU32(StorageKind.StorageBuffer, binding, Const(0), wordOffset, value); @@ -881,6 +882,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations return context.IMinimumS32(memValue, value); }); } + break; case Instruction.AtomicMinU32: resultValue = context.AtomicMinU32(StorageKind.StorageBuffer, binding, Const(0), wordOffset, value); @@ -1100,7 +1102,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations { baseOffset = null; - if (operation.Inst == Instruction.Load || operation.Inst == Instruction.Store) + if (operation.Inst is Instruction.Load or Instruction.Store) { if (operation.StorageKind == StorageKind.SharedMemory) { diff --git a/src/Ryujinx.Graphics.Shader/Translation/Optimizations/Simplification.cs b/src/Ryujinx.Graphics.Shader/Translation/Optimizations/Simplification.cs index 097c8aa88..282c136e1 100644 --- a/src/Ryujinx.Graphics.Shader/Translation/Optimizations/Simplification.cs +++ b/src/Ryujinx.Graphics.Shader/Translation/Optimizations/Simplification.cs @@ -25,6 +25,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations { TryEliminateBinaryOpCommutative(operation, 0); } + break; case Instruction.BitwiseOr: diff --git a/src/Ryujinx.Graphics.Shader/Translation/Optimizations/Utils.cs b/src/Ryujinx.Graphics.Shader/Translation/Optimizations/Utils.cs index 6ec90fa3c..449886e11 100644 --- a/src/Ryujinx.Graphics.Shader/Translation/Optimizations/Utils.cs +++ b/src/Ryujinx.Graphics.Shader/Translation/Optimizations/Utils.cs @@ -45,7 +45,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations return x == y || x.Type == OperandType.Constant || x.Type == OperandType.ConstantBuffer; } - private static bool AreAllSourcesEqual(INode node, INode otherNode) + private static bool AreAllSourcesEqual(Operation node, Operation otherNode) { if (node.SourcesCount != otherNode.SourcesCount) { @@ -96,7 +96,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations private static bool IsConditionalBranch(Instruction inst) { - return inst == Instruction.BranchIfFalse || inst == Instruction.BranchIfTrue; + return inst is Instruction.BranchIfFalse or Instruction.BranchIfTrue; } private static bool IsSameCondition(Operand currentCondition, Operand queryCondition) diff --git a/src/Ryujinx.Graphics.Shader/Translation/Optimizations/XmadOptimizer.cs b/src/Ryujinx.Graphics.Shader/Translation/Optimizations/XmadOptimizer.cs index 3cae50fd8..91073164d 100644 --- a/src/Ryujinx.Graphics.Shader/Translation/Optimizations/XmadOptimizer.cs +++ b/src/Ryujinx.Graphics.Shader/Translation/Optimizations/XmadOptimizer.cs @@ -9,7 +9,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations { for (LinkedListNode node = block.Operations.First; node != null; node = node.Next) { - if (!(node.Value is Operation operation)) + if (node.Value is not Operation operation) { continue; } @@ -56,14 +56,14 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations Operand src1 = operation.GetSource(0); Operand src2 = operation.GetSource(1); - if (!(src2.AsgOp is Operation addOp) || addOp.Inst != Instruction.Add) + if (src2.AsgOp is not Operation addOp || addOp.Inst != Instruction.Add) { return false; } Operand lowTimesLowResult = GetCopySource(addOp.GetSource(0)); - if (!(lowTimesLowResult.AsgOp is Operation lowTimesLowOp)) + if (lowTimesLowResult.AsgOp is not Operation lowTimesLowOp) { return false; } @@ -75,7 +75,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations Operand lowTimesHighResult = GetCopySource(GetShifted16Source(addOp.GetSource(1), Instruction.ShiftLeft)); - if (!(lowTimesHighResult.AsgOp is Operation lowTimesHighOp)) + if (lowTimesHighResult.AsgOp is not Operation lowTimesHighOp) { return false; } @@ -85,7 +85,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations return false; } - if (!(src1.AsgOp is Operation highTimesHighOp)) + if (src1.AsgOp is not Operation highTimesHighOp) { return false; } @@ -114,7 +114,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations Operand lowTimesLowResult = GetCopySource(src2); - if (!(lowTimesLowResult.AsgOp is Operation lowTimesLowOp)) + if (lowTimesLowResult.AsgOp is not Operation lowTimesLowOp) { return false; } @@ -126,7 +126,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations Operand highTimesLowResult = src1; - if (!(highTimesLowResult.AsgOp is Operation highTimesLowOp)) + if (highTimesLowResult.AsgOp is not Operation highTimesLowOp) { return false; } @@ -151,7 +151,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations if (operation.Inst == Instruction.Add) { - if (!(operation.GetSource(0).AsgOp is Operation mulOp)) + if (operation.GetSource(0).AsgOp is not Operation mulOp) { return false; } @@ -200,7 +200,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations mulResult = GetCopySource(mulResult); - if (!(mulResult.AsgOp is Operation mulOp) || mulOp.Inst != Instruction.Multiply) + if (mulResult.AsgOp is not Operation mulOp || mulOp.Inst != Instruction.Multiply) { return false; } @@ -237,7 +237,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations Operand mulResult = operation.GetSource(0); - if (!(mulResult.AsgOp is Operation mulOp) || mulOp.Inst != Instruction.Multiply) + if (mulResult.AsgOp is not Operation mulOp || mulOp.Inst != Instruction.Multiply) { return false; } @@ -271,7 +271,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations Operand mulResult = operation.GetSource(0); - if (!(mulResult.AsgOp is Operation mulOp) || mulOp.Inst != Instruction.Multiply) + if (mulResult.AsgOp is not Operation mulOp || mulOp.Inst != Instruction.Multiply) { return false; } @@ -291,7 +291,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations private static Operand GetMasked16Source(Operand value) { - if (!(value.AsgOp is Operation maskOp)) + if (value.AsgOp is not Operation maskOp) { return null; } @@ -306,7 +306,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations private static Operand GetShifted16Source(Operand value, Instruction shiftInst) { - if (!(value.AsgOp is Operation shiftOp)) + if (value.AsgOp is not Operation shiftOp) { return null; } diff --git a/src/Ryujinx.Graphics.Shader/Translation/ShaderHeader.cs b/src/Ryujinx.Graphics.Shader/Translation/ShaderHeader.cs index 39f01b1ce..0fcdff691 100644 --- a/src/Ryujinx.Graphics.Shader/Translation/ShaderHeader.cs +++ b/src/Ryujinx.Graphics.Shader/Translation/ShaderHeader.cs @@ -33,10 +33,12 @@ namespace Ryujinx.Graphics.Shader.Translation { return X; } + if (Y != PixelImap.Unused) { return Y; } + if (Z != PixelImap.Unused) { return Z; diff --git a/src/Ryujinx.Graphics.Shader/Translation/Transforms/GeometryToCompute.cs b/src/Ryujinx.Graphics.Shader/Translation/Transforms/GeometryToCompute.cs index 0013cf0eb..573acc942 100644 --- a/src/Ryujinx.Graphics.Shader/Translation/Transforms/GeometryToCompute.cs +++ b/src/Ryujinx.Graphics.Shader/Translation/Transforms/GeometryToCompute.cs @@ -91,6 +91,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Transforms context.GpuAccessor.Log($"Invalid output \"{(IoVariable)operation.GetSource(0).Value}\"."); } } + break; case Instruction.Store: if (operation.StorageKind == StorageKind.Output) @@ -110,6 +111,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Transforms context.GpuAccessor.Log($"Invalid output \"{(IoVariable)operation.GetSource(0).Value}\"."); } } + break; } diff --git a/src/Ryujinx.Graphics.Shader/Translation/Transforms/VertexToCompute.cs b/src/Ryujinx.Graphics.Shader/Translation/Transforms/VertexToCompute.cs index ebff0d59c..2f85a33d1 100644 --- a/src/Ryujinx.Graphics.Shader/Translation/Transforms/VertexToCompute.cs +++ b/src/Ryujinx.Graphics.Shader/Translation/Transforms/VertexToCompute.cs @@ -97,6 +97,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Transforms newNode = CopyMasked(context.ResourceManager, newNode, location, component, dest, temp); } } + break; case IoVariable.GlobalId: case IoVariable.SubgroupEqMask: diff --git a/src/Ryujinx.Graphics.Shader/Translation/TranslatorContext.cs b/src/Ryujinx.Graphics.Shader/Translation/TranslatorContext.cs index a579433f9..dd1325f8a 100644 --- a/src/Ryujinx.Graphics.Shader/Translation/TranslatorContext.cs +++ b/src/Ryujinx.Graphics.Shader/Translation/TranslatorContext.cs @@ -385,7 +385,7 @@ namespace Ryujinx.Graphics.Shader.Translation { StructureType tfeDataStruct = new(new StructureField[] { - new StructureField(AggregateType.Array | AggregateType.U32, "data", 0) + new(AggregateType.Array | AggregateType.U32, "data", 0) }); for (int i = 0; i < ResourceReservations.TfeBuffersCount; i++) @@ -404,7 +404,7 @@ namespace Ryujinx.Graphics.Shader.Translation StructureType vertexOutputStruct = new(new StructureField[] { - new StructureField(AggregateType.Array | AggregateType.FP32, "data", 0) + new(AggregateType.Array | AggregateType.FP32, "data", 0) }); int vertexOutputSbBinding = resourceManager.Reservations.VertexOutputStorageBufferBinding; @@ -441,7 +441,7 @@ namespace Ryujinx.Graphics.Shader.Translation StructureType geometryIbOutputStruct = new(new StructureField[] { - new StructureField(AggregateType.Array | AggregateType.U32, "data", 0) + new(AggregateType.Array | AggregateType.U32, "data", 0) }); int geometryIbOutputSbBinding = resourceManager.Reservations.GeometryIndexOutputStorageBufferBinding; @@ -501,7 +501,7 @@ namespace Ryujinx.Graphics.Shader.Translation StructureType vertexInputStruct = new(new StructureField[] { - new StructureField(AggregateType.Array | AggregateType.FP32, "data", 0) + new(AggregateType.Array | AggregateType.FP32, "data", 0) }); int vertexDataSbBinding = reservations.VertexOutputStorageBufferBinding; diff --git a/src/Ryujinx.Graphics.Texture/Astc/AstcDecoder.cs b/src/Ryujinx.Graphics.Texture/Astc/AstcDecoder.cs index d6974596d..1053f6f18 100644 --- a/src/Ryujinx.Graphics.Texture/Astc/AstcDecoder.cs +++ b/src/Ryujinx.Graphics.Texture/Astc/AstcDecoder.cs @@ -480,6 +480,7 @@ namespace Ryujinx.Graphics.Texture.Astc { Debug.Assert(colorEndpointMode[i] < 16); } + Debug.Assert(bitStream.BitsLeft == texelParams.GetPackedBitSize()); // Decode both color data and texel weight data @@ -1032,7 +1033,6 @@ namespace Ryujinx.Graphics.Texture.Astc break; } - case 1: { Span val = ReadUintColorValues(2, colorValues, ref colorValuesPosition); @@ -1295,7 +1295,6 @@ namespace Ryujinx.Graphics.Texture.Astc break; } - case 4: { c = 22; @@ -1389,6 +1388,7 @@ namespace Ryujinx.Graphics.Texture.Astc default: throw new AstcDecoderException("Unsupported quint encoding for color values."); } + break; } } @@ -1574,7 +1574,7 @@ namespace Ryujinx.Graphics.Texture.Astc r |= (modeBits & 0xC) >> 1; } - Debug.Assert(2 <= r && r <= 7); + Debug.Assert(r is >= 2 and <= 7); // Determine width & height switch (layout) diff --git a/src/Ryujinx.Graphics.Texture/Astc/Bits.cs b/src/Ryujinx.Graphics.Texture/Astc/Bits.cs index bedc14f78..2cc29acc3 100644 --- a/src/Ryujinx.Graphics.Texture/Astc/Bits.cs +++ b/src/Ryujinx.Graphics.Texture/Astc/Bits.cs @@ -52,6 +52,7 @@ namespace Ryujinx.Graphics.Texture.Astc comp = numberBits - newShift; numberBits = newShift; } + retValue <<= numberBits; retValue |= tempValue >> comp; resLength += numberBits; diff --git a/src/Ryujinx.Graphics.Texture/Astc/IntegerEncoded.cs b/src/Ryujinx.Graphics.Texture/Astc/IntegerEncoded.cs index 4d3e8c5b5..61ab2f571 100644 --- a/src/Ryujinx.Graphics.Texture/Astc/IntegerEncoded.cs +++ b/src/Ryujinx.Graphics.Texture/Astc/IntegerEncoded.cs @@ -52,6 +52,7 @@ namespace Ryujinx.Graphics.Texture.Astc { totalBits += (numberVals * 7 + 2) / 3; } + return totalBits; } diff --git a/src/Ryujinx.Graphics.Texture/Encoders/BC7Encoder.cs b/src/Ryujinx.Graphics.Texture/Encoders/BC7Encoder.cs index e5462b046..4154ef83d 100644 --- a/src/Ryujinx.Graphics.Texture/Encoders/BC7Encoder.cs +++ b/src/Ryujinx.Graphics.Texture/Encoders/BC7Encoder.cs @@ -153,7 +153,7 @@ namespace Ryujinx.Graphics.Texture.Encoders int selectedPartition = 0; - if (selectedMode == 1 || selectedMode == 7) + if (selectedMode is 1 or 7) { int partitionSelectionLowestError = int.MaxValue; @@ -180,7 +180,7 @@ namespace Ryujinx.Graphics.Texture.Encoders for (int m = 0; m < 8; m++) { - for (int r = 0; r < (m == 4 || m == 5 ? 4 : 1); r++) + for (int r = 0; r < (m is 4 or 5 ? 4 : 1); r++) { for (int im = 0; im < (m == 4 ? 2 : 1); im++) { diff --git a/src/Ryujinx.Graphics.Texture/LayoutConverter.cs b/src/Ryujinx.Graphics.Texture/LayoutConverter.cs index 5426af205..143c36259 100644 --- a/src/Ryujinx.Graphics.Texture/LayoutConverter.cs +++ b/src/Ryujinx.Graphics.Texture/LayoutConverter.cs @@ -79,6 +79,7 @@ namespace Ryujinx.Graphics.Texture outPtr += outStrideGap; } } + return true; } @@ -229,8 +230,10 @@ namespace Ryujinx.Graphics.Texture } } } + outOffs += stride * h * d * layers; } + return true; } @@ -245,6 +248,7 @@ namespace Ryujinx.Graphics.Texture _ => throw new NotSupportedException($"Unable to convert ${bytesPerPixel} bpp pixel format."), }; } + return outputOwner; } @@ -350,6 +354,7 @@ namespace Ryujinx.Graphics.Texture inPtr += inStrideGap; } } + return true; } @@ -493,8 +498,10 @@ namespace Ryujinx.Graphics.Texture } } } + inOffs += stride * h * d * layers; } + return true; } diff --git a/src/Ryujinx.Graphics.Texture/OffsetCalculator.cs b/src/Ryujinx.Graphics.Texture/OffsetCalculator.cs index e519341e6..10399ff16 100644 --- a/src/Ryujinx.Graphics.Texture/OffsetCalculator.cs +++ b/src/Ryujinx.Graphics.Texture/OffsetCalculator.cs @@ -115,7 +115,6 @@ namespace Ryujinx.Graphics.Texture _stride == other._stride && _bytesPerPixel == other._bytesPerPixel; - return !other._isLinear && _layoutConverter.LayoutMatches(other._layoutConverter); } } diff --git a/src/Ryujinx.Graphics.Texture/Utils/BC67Utils.cs b/src/Ryujinx.Graphics.Texture/Utils/BC67Utils.cs index f548684a4..ebf5e6a70 100644 --- a/src/Ryujinx.Graphics.Texture/Utils/BC67Utils.cs +++ b/src/Ryujinx.Graphics.Texture/Utils/BC67Utils.cs @@ -1172,7 +1172,7 @@ namespace Ryujinx.Graphics.Texture.Utils [MethodImpl(MethodImplOptions.AggressiveInlining)] public static RgbaColor32 Interpolate(RgbaColor32 color1, RgbaColor32 color2, int weightIndex, int indexBitCount) { - Debug.Assert(indexBitCount >= 2 && indexBitCount <= 4); + Debug.Assert(indexBitCount is >= 2 and <= 4); int weight = (((weightIndex << 7) / ((1 << indexBitCount) - 1)) + 1) >> 1; @@ -1191,8 +1191,8 @@ namespace Ryujinx.Graphics.Texture.Utils int colorIndexBitCount, int alphaIndexBitCount) { - Debug.Assert(colorIndexBitCount >= 2 && colorIndexBitCount <= 4); - Debug.Assert(alphaIndexBitCount >= 2 && alphaIndexBitCount <= 4); + Debug.Assert(colorIndexBitCount is >= 2 and <= 4); + Debug.Assert(alphaIndexBitCount is >= 2 and <= 4); int colorWeight = BC67Tables.Weights[colorIndexBitCount - 2][colorWeightIndex]; int alphaWeight = BC67Tables.Weights[alphaIndexBitCount - 2][alphaWeightIndex]; diff --git a/src/Ryujinx.Graphics.Vic/Image/SurfaceReader.cs b/src/Ryujinx.Graphics.Vic/Image/SurfaceReader.cs index 83f00f345..2c6ff0511 100644 --- a/src/Ryujinx.Graphics.Vic/Image/SurfaceReader.cs +++ b/src/Ryujinx.Graphics.Vic/Image/SurfaceReader.cs @@ -397,6 +397,7 @@ namespace Ryujinx.Graphics.Vic.Image { Scaler.DeinterlaceBob(buffer.Data, w, stride, isTopField); } + break; default: Logger.Error?.Print(LogClass.Vic, $"Unsupported deinterlace mode \"{config.DeinterlaceMode}\"."); diff --git a/src/Ryujinx.Graphics.Vic/Types/FrameFormat.cs b/src/Ryujinx.Graphics.Vic/Types/FrameFormat.cs index b8f821631..d76fcd9e0 100644 --- a/src/Ryujinx.Graphics.Vic/Types/FrameFormat.cs +++ b/src/Ryujinx.Graphics.Vic/Types/FrameFormat.cs @@ -54,8 +54,8 @@ namespace Ryujinx.Graphics.Vic.Types public static bool IsInterlacedBottomFirst(this FrameFormat frameFormat) { - return frameFormat == FrameFormat.InterlacedBottomFieldFirst || - frameFormat == FrameFormat.SubPicInterlacedBottomFieldFirst; + return frameFormat is FrameFormat.InterlacedBottomFieldFirst or + FrameFormat.SubPicInterlacedBottomFieldFirst; } public static bool IsTopField(this FrameFormat frameFormat, bool isLuma) diff --git a/src/Ryujinx.Graphics.Video/Vp9PictureInfo.cs b/src/Ryujinx.Graphics.Video/Vp9PictureInfo.cs index 09f6e6664..b9604181a 100644 --- a/src/Ryujinx.Graphics.Video/Vp9PictureInfo.cs +++ b/src/Ryujinx.Graphics.Video/Vp9PictureInfo.cs @@ -38,4 +38,4 @@ namespace Ryujinx.Graphics.Video public Vp9EntropyProbs Entropy; public Vp9BackwardUpdates BackwardUpdateCounts; } -} \ No newline at end of file +} diff --git a/src/Ryujinx.Graphics.Vulkan/BufferHolder.cs b/src/Ryujinx.Graphics.Vulkan/BufferHolder.cs index 3b2fce34a..1e54e8ece 100644 --- a/src/Ryujinx.Graphics.Vulkan/BufferHolder.cs +++ b/src/Ryujinx.Graphics.Vulkan/BufferHolder.cs @@ -289,7 +289,7 @@ namespace Ryujinx.Graphics.Vulkan if (_pendingData != null) { _mirrors.Clear(); - }; + } } public void ClearMirrors(CommandBufferScoped cbs, int offset, int size) @@ -309,7 +309,7 @@ namespace Ryujinx.Graphics.Vulkan { _gd.PipelineInternal.Rebind(_buffer, offset, size); } - }; + } } public void UseMirrors() diff --git a/src/Ryujinx.Graphics.Vulkan/BufferMirrorRangeList.cs b/src/Ryujinx.Graphics.Vulkan/BufferMirrorRangeList.cs index b643e55f1..3cffb08c9 100644 --- a/src/Ryujinx.Graphics.Vulkan/BufferMirrorRangeList.cs +++ b/src/Ryujinx.Graphics.Vulkan/BufferMirrorRangeList.cs @@ -172,7 +172,7 @@ namespace Ryujinx.Graphics.Vulkan { return null; } - + List result = null; int index = BinarySearch(list, offset, size); diff --git a/src/Ryujinx.Graphics.Vulkan/DescriptorSetTemplate.cs b/src/Ryujinx.Graphics.Vulkan/DescriptorSetTemplate.cs index 02d3ae88f..3b70a841a 100644 --- a/src/Ryujinx.Graphics.Vulkan/DescriptorSetTemplate.cs +++ b/src/Ryujinx.Graphics.Vulkan/DescriptorSetTemplate.cs @@ -194,12 +194,12 @@ namespace Ryujinx.Graphics.Vulkan private static bool IsBufferType(ResourceType type) { - return type == ResourceType.UniformBuffer || type == ResourceType.StorageBuffer; + return type is ResourceType.UniformBuffer or ResourceType.StorageBuffer; } private static bool IsBufferTextureType(ResourceType type) { - return type == ResourceType.BufferTexture || type == ResourceType.BufferImage; + return type is ResourceType.BufferTexture or ResourceType.BufferImage; } public unsafe void Dispose() diff --git a/src/Ryujinx.Graphics.Vulkan/DescriptorSetUpdater.cs b/src/Ryujinx.Graphics.Vulkan/DescriptorSetUpdater.cs index 406f33304..a0a238e38 100644 --- a/src/Ryujinx.Graphics.Vulkan/DescriptorSetUpdater.cs +++ b/src/Ryujinx.Graphics.Vulkan/DescriptorSetUpdater.cs @@ -235,7 +235,7 @@ namespace Ryujinx.Graphics.Vulkan // Check stage bindings - _uniformMirrored.Union(_uniformSet).SignalSet((int binding, int count) => + _uniformMirrored.Union(_uniformSet).SignalSet((binding, count) => { for (int i = 0; i < count; i++) { @@ -257,7 +257,7 @@ namespace Ryujinx.Graphics.Vulkan } }); - _storageMirrored.Union(_storageSet).SignalSet((int binding, int count) => + _storageMirrored.Union(_storageSet).SignalSet((binding, count) => { for (int i = 0; i < count; i++) { @@ -348,16 +348,16 @@ namespace Ryujinx.Graphics.Vulkan if (segment.IsArray) { - if (segment.Type == ResourceType.Texture || - segment.Type == ResourceType.Sampler || - segment.Type == ResourceType.TextureAndSampler || - segment.Type == ResourceType.BufferTexture) + if (segment.Type is ResourceType.Texture or + ResourceType.Sampler or + ResourceType.TextureAndSampler or + ResourceType.BufferTexture) { ref ArrayRef arrayRef = ref _textureArrayExtraRefs[setIndex - PipelineBase.DescriptorSetLayouts]; PipelineStageFlags stageFlags = arrayRef.Stage.ConvertToPipelineStageFlags(); arrayRef.Array?.QueueWriteToReadBarriers(cbs, stageFlags); } - else if (segment.Type == ResourceType.Image || segment.Type == ResourceType.BufferImage) + else if (segment.Type is ResourceType.Image or ResourceType.BufferImage) { ref ArrayRef arrayRef = ref _imageArrayExtraRefs[setIndex - PipelineBase.DescriptorSetLayouts]; PipelineStageFlags stageFlags = arrayRef.Stage.ConvertToPipelineStageFlags(); @@ -1072,7 +1072,7 @@ namespace Ryujinx.Graphics.Vulkan private void Initialize(CommandBufferScoped cbs, int setIndex, DescriptorSetCollection dsc) { // We don't support clearing texture descriptors currently. - if (setIndex != PipelineBase.UniformSetIndex && setIndex != PipelineBase.StorageSetIndex) + if (setIndex is not PipelineBase.UniformSetIndex and not PipelineBase.StorageSetIndex) { return; } @@ -1102,10 +1102,10 @@ namespace Ryujinx.Graphics.Vulkan { DescriptorSet[] sets = null; - if (segment.Type == ResourceType.Texture || - segment.Type == ResourceType.Sampler || - segment.Type == ResourceType.TextureAndSampler || - segment.Type == ResourceType.BufferTexture) + if (segment.Type is ResourceType.Texture or + ResourceType.Sampler or + ResourceType.TextureAndSampler or + ResourceType.BufferTexture) { sets = _textureArrayExtraRefs[setIndex - PipelineBase.DescriptorSetLayouts].Array.GetDescriptorSets( _device, @@ -1116,7 +1116,7 @@ namespace Ryujinx.Graphics.Vulkan _dummyTexture, _dummySampler); } - else if (segment.Type == ResourceType.Image || segment.Type == ResourceType.BufferImage) + else if (segment.Type is ResourceType.Image or ResourceType.BufferImage) { sets = _imageArrayExtraRefs[setIndex - PipelineBase.DescriptorSetLayouts].Array.GetDescriptorSets( _device, diff --git a/src/Ryujinx.Graphics.Vulkan/FenceHelper.cs b/src/Ryujinx.Graphics.Vulkan/FenceHelper.cs index 6649af7f5..9d682bab2 100644 --- a/src/Ryujinx.Graphics.Vulkan/FenceHelper.cs +++ b/src/Ryujinx.Graphics.Vulkan/FenceHelper.cs @@ -24,6 +24,7 @@ namespace Ryujinx.Graphics.Vulkan { // Keep waiting while the fence is not signaled. } + result.ThrowOnError(); } } diff --git a/src/Ryujinx.Graphics.Vulkan/FormatCapabilities.cs b/src/Ryujinx.Graphics.Vulkan/FormatCapabilities.cs index 18e5472db..0657638c9 100644 --- a/src/Ryujinx.Graphics.Vulkan/FormatCapabilities.cs +++ b/src/Ryujinx.Graphics.Vulkan/FormatCapabilities.cs @@ -222,14 +222,14 @@ namespace Ryujinx.Graphics.Vulkan public static bool IsD24S8(Format format) { - return format == Format.D24UnormS8Uint || format == Format.S8UintD24Unorm || format == Format.X8UintD24Unorm; + return format is Format.D24UnormS8Uint or Format.S8UintD24Unorm or Format.X8UintD24Unorm; } private static bool IsRGB16IntFloat(Format format) { - return format == Format.R16G16B16Float || - format == Format.R16G16B16Sint || - format == Format.R16G16B16Uint; + return format is Format.R16G16B16Float or + Format.R16G16B16Sint or + Format.R16G16B16Uint; } } } diff --git a/src/Ryujinx.Graphics.Vulkan/HelperShader.cs b/src/Ryujinx.Graphics.Vulkan/HelperShader.cs index 8c7c074f4..194179410 100644 --- a/src/Ryujinx.Graphics.Vulkan/HelperShader.cs +++ b/src/Ryujinx.Graphics.Vulkan/HelperShader.cs @@ -33,29 +33,29 @@ namespace Ryujinx.Graphics.Vulkan private readonly PipelineHelperShader _pipeline; private readonly ISampler _samplerLinear; private readonly ISampler _samplerNearest; - private readonly IProgram _programColorBlit; - private readonly IProgram _programColorBlitMs; - private readonly IProgram _programColorBlitClearAlpha; - private readonly IProgram _programColorClearF; - private readonly IProgram _programColorClearSI; - private readonly IProgram _programColorClearUI; - private readonly IProgram _programDepthStencilClear; - private readonly IProgram _programStrideChange; - private readonly IProgram _programConvertD32S8ToD24S8; - private readonly IProgram _programConvertIndexBuffer; - private readonly IProgram _programConvertIndirectData; - private readonly IProgram _programColorCopyShortening; - private readonly IProgram _programColorCopyToNonMs; - private readonly IProgram _programColorCopyWidening; - private readonly IProgram _programColorDrawToMs; - private readonly IProgram _programDepthBlit; - private readonly IProgram _programDepthBlitMs; - private readonly IProgram _programDepthDrawToMs; - private readonly IProgram _programDepthDrawToNonMs; - private readonly IProgram _programStencilBlit; - private readonly IProgram _programStencilBlitMs; - private readonly IProgram _programStencilDrawToMs; - private readonly IProgram _programStencilDrawToNonMs; + private readonly ShaderCollection _programColorBlit; + private readonly ShaderCollection _programColorBlitMs; + private readonly ShaderCollection _programColorBlitClearAlpha; + private readonly ShaderCollection _programColorClearF; + private readonly ShaderCollection _programColorClearSI; + private readonly ShaderCollection _programColorClearUI; + private readonly ShaderCollection _programDepthStencilClear; + private readonly ShaderCollection _programStrideChange; + private readonly ShaderCollection _programConvertD32S8ToD24S8; + private readonly ShaderCollection _programConvertIndexBuffer; + private readonly ShaderCollection _programConvertIndirectData; + private readonly ShaderCollection _programColorCopyShortening; + private readonly ShaderCollection _programColorCopyToNonMs; + private readonly ShaderCollection _programColorCopyWidening; + private readonly ShaderCollection _programColorDrawToMs; + private readonly ShaderCollection _programDepthBlit; + private readonly ShaderCollection _programDepthBlitMs; + private readonly ShaderCollection _programDepthDrawToMs; + private readonly ShaderCollection _programDepthDrawToNonMs; + private readonly ShaderCollection _programStencilBlit; + private readonly ShaderCollection _programStencilBlitMs; + private readonly ShaderCollection _programStencilDrawToMs; + private readonly ShaderCollection _programStencilDrawToNonMs; public HelperShader(VulkanRenderer gd, Device device) { diff --git a/src/Ryujinx.Graphics.Vulkan/MoltenVK/MVKInitialization.cs b/src/Ryujinx.Graphics.Vulkan/MoltenVK/MVKInitialization.cs index c3efcc8da..c1c59939e 100644 --- a/src/Ryujinx.Graphics.Vulkan/MoltenVK/MVKInitialization.cs +++ b/src/Ryujinx.Graphics.Vulkan/MoltenVK/MVKInitialization.cs @@ -40,6 +40,7 @@ namespace Ryujinx.Graphics.Vulkan.MoltenVK path = path[..^VulkanLib.Length] + "libMoltenVK.dylib"; return [path]; } + return []; } diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs b/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs index 49fe133dd..eac47e60e 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs @@ -1548,7 +1548,7 @@ namespace Ryujinx.Graphics.Vulkan } return false; - } + } [MethodImpl(MethodImplOptions.AggressiveInlining)] private bool UpdateFeedbackLoop() diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs b/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs index b6105589e..3ed87206f 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs @@ -192,14 +192,14 @@ namespace Ryujinx.Graphics.Vulkan private readonly void RecordFeedbackLoop(ExtAttachmentFeedbackLoopDynamicState api, CommandBuffer commandBuffer) { - ImageAspectFlags aspects = (_feedbackLoopAspects & FeedbackLoopAspects.Color) != 0 ? ImageAspectFlags.ColorBit : 0; + ImageAspectFlags aspects = (_feedbackLoopAspects & FeedbackLoopAspects.Color) != 0 ? ImageAspectFlags.ColorBit : 0; - if ((_feedbackLoopAspects & FeedbackLoopAspects.Depth) != 0) - { - aspects |= ImageAspectFlags.DepthBit | ImageAspectFlags.StencilBit; - } + if ((_feedbackLoopAspects & FeedbackLoopAspects.Depth) != 0) + { + aspects |= ImageAspectFlags.DepthBit | ImageAspectFlags.StencilBit; + } - api.CmdSetAttachmentFeedbackLoopEnable(commandBuffer, aspects); + api.CmdSetAttachmentFeedbackLoopEnable(commandBuffer, aspects); } } } diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineState.cs b/src/Ryujinx.Graphics.Vulkan/PipelineState.cs index eec3b8395..fa815d96c 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineState.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineState.cs @@ -433,11 +433,11 @@ namespace Ryujinx.Graphics.Vulkan } else { - topologySupportsRestart = Topology == PrimitiveTopology.LineStrip || - Topology == PrimitiveTopology.TriangleStrip || - Topology == PrimitiveTopology.TriangleFan || - Topology == PrimitiveTopology.LineStripWithAdjacency || - Topology == PrimitiveTopology.TriangleStripWithAdjacency; + topologySupportsRestart = Topology is PrimitiveTopology.LineStrip or + PrimitiveTopology.TriangleStrip or + PrimitiveTopology.TriangleFan or + PrimitiveTopology.LineStripWithAdjacency or + PrimitiveTopology.TriangleStripWithAdjacency; } primitiveRestartEnable &= topologySupportsRestart; diff --git a/src/Ryujinx.Graphics.Vulkan/Queries/BufferedQuery.cs b/src/Ryujinx.Graphics.Vulkan/Queries/BufferedQuery.cs index 5377c8a1e..4763007f4 100644 --- a/src/Ryujinx.Graphics.Vulkan/Queries/BufferedQuery.cs +++ b/src/Ryujinx.Graphics.Vulkan/Queries/BufferedQuery.cs @@ -105,6 +105,7 @@ namespace Ryujinx.Graphics.Vulkan.Queries bool isOcclusion = _type == CounterType.SamplesPassed; _pipeline.BeginQuery(this, _queryPool, needsReset, isOcclusion, isOcclusion && resetSequence != null); } + _resetSequence = null; } @@ -211,6 +212,7 @@ namespace Ryujinx.Graphics.Vulkan.Queries { _api.DestroyQueryPool(_device, _queryPool, null); } + _queryPool = default; } } diff --git a/src/Ryujinx.Graphics.Vulkan/Queries/CounterQueue.cs b/src/Ryujinx.Graphics.Vulkan/Queries/CounterQueue.cs index 24b0e7787..84e75bec0 100644 --- a/src/Ryujinx.Graphics.Vulkan/Queries/CounterQueue.cs +++ b/src/Ryujinx.Graphics.Vulkan/Queries/CounterQueue.cs @@ -198,6 +198,7 @@ namespace Ryujinx.Graphics.Vulkan.Queries { return; // If not blocking, then return when we encounter an event that is not ready yet. } + _events.Dequeue(); } } diff --git a/src/Ryujinx.Graphics.Vulkan/SamplerHolder.cs b/src/Ryujinx.Graphics.Vulkan/SamplerHolder.cs index eae003686..600f0fafc 100644 --- a/src/Ryujinx.Graphics.Vulkan/SamplerHolder.cs +++ b/src/Ryujinx.Graphics.Vulkan/SamplerHolder.cs @@ -20,7 +20,7 @@ namespace Ryujinx.Graphics.Vulkan float minLod = info.MinLod; float maxLod = info.MaxLod; - if (info.MinFilter == MinFilter.Nearest || info.MinFilter == MinFilter.Linear) + if (info.MinFilter is MinFilter.Nearest or MinFilter.Linear) { minLod = 0; maxLod = 0.25f; diff --git a/src/Ryujinx.Graphics.Vulkan/ShaderCollection.cs b/src/Ryujinx.Graphics.Vulkan/ShaderCollection.cs index 78cd15a39..c7bb1ba59 100644 --- a/src/Ryujinx.Graphics.Vulkan/ShaderCollection.cs +++ b/src/Ryujinx.Graphics.Vulkan/ShaderCollection.cs @@ -182,7 +182,7 @@ namespace Ryujinx.Graphics.Vulkan return false; } } - + //Prevent the sum of descriptors from exceeding MaxPushDescriptors int totalDescriptors = 0; foreach (ResourceDescriptor desc in layout.Sets.First().Descriptors) @@ -190,6 +190,7 @@ namespace Ryujinx.Graphics.Vulkan if (!reserved.Contains(desc.Binding)) totalDescriptors += desc.Count; } + if (totalDescriptors > gd.Capabilities.MaxPushDescriptors) return false; @@ -391,7 +392,7 @@ namespace Ryujinx.Graphics.Vulkan return templates; } - private PipelineStageFlags GetPipelineStages(ResourceStages stages) + private static PipelineStageFlags GetPipelineStages(ResourceStages stages) { PipelineStageFlags result = 0; @@ -428,7 +429,7 @@ namespace Ryujinx.Graphics.Vulkan return result; } - private (PipelineStageFlags Buffer, PipelineStageFlags Texture) BuildIncoherentStages(ReadOnlyCollection setUsages) + private static (PipelineStageFlags Buffer, PipelineStageFlags Texture) BuildIncoherentStages(ReadOnlyCollection setUsages) { PipelineStageFlags buffer = PipelineStageFlags.None; PipelineStageFlags texture = PipelineStageFlags.None; diff --git a/src/Ryujinx.Graphics.Vulkan/TextureStorage.cs b/src/Ryujinx.Graphics.Vulkan/TextureStorage.cs index 190ada27b..3dc605891 100644 --- a/src/Ryujinx.Graphics.Vulkan/TextureStorage.cs +++ b/src/Ryujinx.Graphics.Vulkan/TextureStorage.cs @@ -98,7 +98,7 @@ namespace Ryujinx.Graphics.Vulkan ImageCreateFlags flags = ImageCreateFlags.CreateMutableFormatBit | ImageCreateFlags.CreateExtendedUsageBit; // This flag causes mipmapped texture arrays to break on AMD GCN, so for that copy dependencies are forced for aliasing as cube. - bool isCube = info.Target == Target.Cubemap || info.Target == Target.CubemapArray; + bool isCube = info.Target is Target.Cubemap or Target.CubemapArray; bool cubeCompatible = gd.IsAmdGcn ? isCube : (info.Width == info.Height && layers >= 6); if (type == ImageType.Type2D && cubeCompatible) @@ -336,7 +336,7 @@ namespace Ryujinx.Graphics.Vulkan public static SampleCountFlags ConvertToSampleCountFlags(SampleCountFlags supportedSampleCounts, uint samples) { - if (samples == 0 || samples > (uint)SampleCountFlags.Count64Bit) + if (samples is 0 or > ((uint)SampleCountFlags.Count64Bit)) { return SampleCountFlags.Count1Bit; } diff --git a/src/Ryujinx.Graphics.Vulkan/TextureView.cs b/src/Ryujinx.Graphics.Vulkan/TextureView.cs index 7583b7e5c..1cbb7c6e1 100644 --- a/src/Ryujinx.Graphics.Vulkan/TextureView.cs +++ b/src/Ryujinx.Graphics.Vulkan/TextureView.cs @@ -78,9 +78,9 @@ namespace Ryujinx.Graphics.Vulkan ComponentSwizzle swizzleB = info.SwizzleB.Convert(); ComponentSwizzle swizzleA = info.SwizzleA.Convert(); - if (info.Format == Format.R5G5B5A1Unorm || - info.Format == Format.R5G5B5X1Unorm || - info.Format == Format.R5G6B5Unorm) + if (info.Format is Format.R5G5B5A1Unorm or + Format.R5G5B5X1Unorm or + Format.R5G6B5Unorm) { (swizzleB, swizzleR) = (swizzleR, swizzleB); } diff --git a/src/Ryujinx.Graphics.Vulkan/VulkanRenderer.cs b/src/Ryujinx.Graphics.Vulkan/VulkanRenderer.cs index 1dc55ca0a..32c22dd2a 100644 --- a/src/Ryujinx.Graphics.Vulkan/VulkanRenderer.cs +++ b/src/Ryujinx.Graphics.Vulkan/VulkanRenderer.cs @@ -360,11 +360,11 @@ namespace Ryujinx.Graphics.Vulkan IsAmdWindows = Vendor == Vendor.Amd && OperatingSystem.IsWindows(); IsIntelWindows = Vendor == Vendor.Intel && OperatingSystem.IsWindows(); IsTBDR = - Vendor == Vendor.Apple || - Vendor == Vendor.Qualcomm || - Vendor == Vendor.ARM || - Vendor == Vendor.Broadcom || - Vendor == Vendor.ImgTec; + Vendor is Vendor.Apple or + Vendor.Qualcomm or + Vendor.ARM or + Vendor.Broadcom or + Vendor.ImgTec; GpuVendor = VendorUtils.GetNameFromId(properties.VendorID); GpuDriver = hasDriverProperties && !OperatingSystem.IsMacOS() ? @@ -378,7 +378,7 @@ namespace Ryujinx.Graphics.Vulkan GpuVersion = $"Vulkan v{ParseStandardVulkanVersion(properties.ApiVersion)}, Driver v{ParseDriverVersion(ref properties)}"; IsAmdGcn = !IsMoltenVk && Vendor == Vendor.Amd && Patterns.AmdGcn.IsMatch(GpuRenderer); - + IsAmdRdna3 = Vendor == Vendor.Amd && (Patterns.AmdRdna3.IsMatch(GpuRenderer) // ROG Ally (X) Device IDs || properties.DeviceID is 0x15BF or 0x15C8); @@ -903,7 +903,7 @@ namespace Ryujinx.Graphics.Vulkan gpuInfoMessage = gpuInfoMessage.Prepend(GpuVendor); Logger.Notice.Print(LogClass.Gpu, gpuInfoMessage); - + Logger.Notice.Print(LogClass.Gpu, $"GPU Memory: {GetTotalGPUMemory() / (1024 * 1024)} MiB"); } diff --git a/src/Ryujinx.Graphics.Vulkan/Window.cs b/src/Ryujinx.Graphics.Vulkan/Window.cs index ab39cbd7d..b67b0dbfa 100644 --- a/src/Ryujinx.Graphics.Vulkan/Window.cs +++ b/src/Ryujinx.Graphics.Vulkan/Window.cs @@ -544,6 +544,7 @@ namespace Ryujinx.Graphics.Vulkan _effect?.Dispose(); _effect = new SmaaPostProcessingEffect(_gd, _device, quality); } + break; } } @@ -575,6 +576,7 @@ namespace Ryujinx.Graphics.Vulkan _scalingFilter?.Dispose(); _scalingFilter = new AreaScalingFilter(_gd, _device); } + break; } } diff --git a/src/Ryujinx.HLE.Generators/IpcServiceGenerator.cs b/src/Ryujinx.HLE.Generators/IpcServiceGenerator.cs index 4de100cf8..cdd062826 100644 --- a/src/Ryujinx.HLE.Generators/IpcServiceGenerator.cs +++ b/src/Ryujinx.HLE.Generators/IpcServiceGenerator.cs @@ -59,7 +59,7 @@ namespace Ryujinx.HLE.Generators generator.LeaveScope(); generator.LeaveScope(); - generator.AppendLine("#nullable disable"); + generator.AppendLine("#nullable disable"); context.AddSource($"IUserInterface.g.cs", generator.ToString()); } diff --git a/src/Ryujinx.HLE/FileSystem/ContentManager.cs b/src/Ryujinx.HLE/FileSystem/ContentManager.cs index 1c2a7351d..6ce19efee 100644 --- a/src/Ryujinx.HLE/FileSystem/ContentManager.cs +++ b/src/Ryujinx.HLE/FileSystem/ContentManager.cs @@ -111,10 +111,12 @@ namespace Ryujinx.HLE.FileSystem { continue; } + if (!ContentPath.TryGetRealPath(contentPathString, out string contentDirectory)) { continue; } + string registeredDirectory = Path.Combine(contentDirectory, "registered"); Directory.CreateDirectory(registeredDirectory); @@ -464,6 +466,7 @@ namespace Ryujinx.HLE.FileSystem { InstallFromZip(archive, temporaryDirectory); } + break; case ".xci": Xci xci = new(_virtualFileSystem.KeySet, file.AsStorage()); @@ -476,7 +479,7 @@ namespace Ryujinx.HLE.FileSystem FinishInstallation(temporaryDirectory, registeredDirectory); } - public void InstallKeys(string keysSource, string installDirectory) + public static void InstallKeys(string keysSource, string installDirectory) { if (Directory.Exists(keysSource)) { @@ -505,6 +508,7 @@ namespace Ryujinx.HLE.FileSystem { InstallKeysFromZip(archive, installDirectory); } + break; case ".keys": VerifyKeysFile(keysSource); @@ -515,13 +519,14 @@ namespace Ryujinx.HLE.FileSystem } } - private void InstallKeysFromZip(ZipArchive archive, string installDirectory) + private static void InstallKeysFromZip(ZipArchive archive, string installDirectory) { string temporaryDirectory = Path.Combine(installDirectory, "temp"); if (Directory.Exists(temporaryDirectory)) { Directory.Delete(temporaryDirectory, true); } + Directory.CreateDirectory(temporaryDirectory); foreach (ZipArchiveEntry entry in archive.Entries) { @@ -541,6 +546,7 @@ namespace Ryujinx.HLE.FileSystem } } } + Directory.Delete(temporaryDirectory, true); } @@ -567,7 +573,7 @@ namespace Ryujinx.HLE.FileSystem { Nca nca = new(_virtualFileSystem.KeySet, OpenPossibleFragmentedFile(filesystem, entry.FullPath, OpenMode.Read).AsStorage()); - SaveNca(nca, entry.Name.Remove(entry.Name.IndexOf('.')), temporaryDirectory); + SaveNca(nca, entry.Name[..entry.Name.IndexOf('.')], temporaryDirectory); } } @@ -641,7 +647,7 @@ namespace Ryujinx.HLE.FileSystem return file.Release(); } - private static Stream GetZipStream(ZipArchiveEntry entry) + private static MemoryStream GetZipStream(ZipArchiveEntry entry) { MemoryStream dest = MemoryStreamManager.Shared.GetStream(); @@ -1016,7 +1022,7 @@ namespace Ryujinx.HLE.FileSystem return null; } - public void VerifyKeysFile(string filePath) + public static void VerifyKeysFile(string filePath) { // Verify the keys file format refers to https://github.com/Thealexbarney/LibHac/blob/master/KEYS.md string genericPattern = @"^[a-z0-9_]+ = [a-z0-9]+$"; @@ -1028,7 +1034,7 @@ namespace Ryujinx.HLE.FileSystem string fileName = Path.GetFileName(filePath); string[] lines = File.ReadAllLines(filePath); - bool verified = false; + bool verified; switch (fileName) { case "prod.keys": @@ -1046,18 +1052,20 @@ namespace Ryujinx.HLE.FileSystem default: throw new FormatException($"Keys file name \"{fileName}\" not supported. Only \"prod.keys\", \"title.keys\", \"console.keys\", \"dev.keys\" are supported."); } + if (!verified) { throw new FormatException($"Invalid \"{filePath}\" file format."); } - } else + } + else { throw new FileNotFoundException($"Keys file not found at \"{filePath}\"."); } return; - - bool VerifyKeys(string[] lines, string regex) + + static bool VerifyKeys(string[] lines, string regex) { foreach (string line in lines) { @@ -1066,11 +1074,12 @@ namespace Ryujinx.HLE.FileSystem return false; } } + return true; } } - - public bool AreKeysAlredyPresent(string pathToCheck) + + public static bool AreKeysAlredyPresent(string pathToCheck) { string[] fileNames = ["prod.keys", "title.keys", "console.keys", "dev.keys"]; foreach (string file in fileNames) @@ -1080,6 +1089,7 @@ namespace Ryujinx.HLE.FileSystem return true; } } + return false; } } diff --git a/src/Ryujinx.HLE/FileSystem/EncryptedFileSystemCreator.cs b/src/Ryujinx.HLE/FileSystem/EncryptedFileSystemCreator.cs index d9f7d5dcf..e6d76cec9 100644 --- a/src/Ryujinx.HLE/FileSystem/EncryptedFileSystemCreator.cs +++ b/src/Ryujinx.HLE/FileSystem/EncryptedFileSystemCreator.cs @@ -12,7 +12,7 @@ namespace Ryujinx.HLE.FileSystem ref readonly SharedRef baseFileSystem, IEncryptedFileSystemCreator.KeyId idIndex, in EncryptionSeed encryptionSeed) { - if (idIndex < IEncryptedFileSystemCreator.KeyId.Save || idIndex > IEncryptedFileSystemCreator.KeyId.CustomStorage) + if (idIndex is < IEncryptedFileSystemCreator.KeyId.Save or > IEncryptedFileSystemCreator.KeyId.CustomStorage) { return ResultFs.InvalidArgument.Log(); } diff --git a/src/Ryujinx.HLE/FileSystem/VirtualFileSystem.cs b/src/Ryujinx.HLE/FileSystem/VirtualFileSystem.cs index 067b7d4a8..4e0fdf554 100644 --- a/src/Ryujinx.HLE/FileSystem/VirtualFileSystem.cs +++ b/src/Ryujinx.HLE/FileSystem/VirtualFileSystem.cs @@ -392,7 +392,7 @@ namespace Ryujinx.HLE.FileSystem private static Result CreateSaveDataDirectory(HorizonClient hos, in SaveDataInfo info) { - if (info.SpaceId != SaveDataSpaceId.User && info.SpaceId != SaveDataSpaceId.System) + if (info.SpaceId is not SaveDataSpaceId.User and not SaveDataSpaceId.System) { return Result.Success; } diff --git a/src/Ryujinx.HLE/HOS/Applets/Browser/BrowserApplet.cs b/src/Ryujinx.HLE/HOS/Applets/Browser/BrowserApplet.cs index 488eca291..c8bbfc4b4 100644 --- a/src/Ryujinx.HLE/HOS/Applets/Browser/BrowserApplet.cs +++ b/src/Ryujinx.HLE/HOS/Applets/Browser/BrowserApplet.cs @@ -1,3 +1,4 @@ +using Microsoft.IO; using Ryujinx.Common; using Ryujinx.Common.Logging; using Ryujinx.Common.Memory; @@ -63,7 +64,7 @@ namespace Ryujinx.HLE.HOS.Applets.Browser private static byte[] BuildResponseOld(WebCommonReturnValue result) { - using MemoryStream stream = MemoryStreamManager.Shared.GetStream(); + using RecyclableMemoryStream stream = MemoryStreamManager.Shared.GetStream(); using BinaryWriter writer = new(stream); writer.WriteStruct(result); @@ -71,7 +72,7 @@ namespace Ryujinx.HLE.HOS.Applets.Browser } private byte[] BuildResponseNew(List outputArguments) { - using MemoryStream stream = MemoryStreamManager.Shared.GetStream(); + using RecyclableMemoryStream stream = MemoryStreamManager.Shared.GetStream(); using BinaryWriter writer = new(stream); writer.WriteStruct(new WebArgHeader { diff --git a/src/Ryujinx.HLE/HOS/Applets/Cabinet/CabinetApplet.cs b/src/Ryujinx.HLE/HOS/Applets/Cabinet/CabinetApplet.cs index 04843deb0..d8f665504 100644 --- a/src/Ryujinx.HLE/HOS/Applets/Cabinet/CabinetApplet.cs +++ b/src/Ryujinx.HLE/HOS/Applets/Cabinet/CabinetApplet.cs @@ -1,8 +1,8 @@ using Ryujinx.Common.Logging; using Ryujinx.Common.Memory; using Ryujinx.HLE.HOS.Services.Am.AppletAE; -using Ryujinx.HLE.HOS.Services.Hid.HidServer; using Ryujinx.HLE.HOS.Services.Hid; +using Ryujinx.HLE.HOS.Services.Hid.HidServer; using Ryujinx.HLE.HOS.Services.Nfc.Nfp; using Ryujinx.HLE.HOS.Services.Nfc.Nfp.NfpManager; using System; @@ -75,7 +75,7 @@ namespace Ryujinx.HLE.HOS.Applets.Cabinet return ResultCode.Success; } - private void StartFormatter(ref StartParamForAmiiboSettings startParam) + private static void StartFormatter(ref StartParamForAmiiboSettings startParam) { // Initialize RegisterInfo startParam.RegisterInfo = new RegisterInfo(); @@ -109,6 +109,7 @@ namespace Ryujinx.HLE.HOS.Applets.Cabinet } } } + VirtualAmiibo.UpdateNickName(amiiboId, newName); } @@ -154,9 +155,9 @@ namespace Ryujinx.HLE.HOS.Applets.Cabinet public unsafe struct ReturnValueForAmiiboSettings { public byte AmiiboSettingsReturnFlag; - private byte Padding1; - private byte Padding2; - private byte Padding3; + private readonly byte Padding1; + private readonly byte Padding2; + private readonly byte Padding3; public DeviceHandle DeviceHandle; public TagInfo TagInfo; public RegisterInfo RegisterInfo; diff --git a/src/Ryujinx.HLE/HOS/Applets/Controller/ControllerApplet.cs b/src/Ryujinx.HLE/HOS/Applets/Controller/ControllerApplet.cs index 3a7b29ab5..6b11f2cdd 100644 --- a/src/Ryujinx.HLE/HOS/Applets/Controller/ControllerApplet.cs +++ b/src/Ryujinx.HLE/HOS/Applets/Controller/ControllerApplet.cs @@ -1,3 +1,4 @@ +using Microsoft.IO; using Ryujinx.Common.Logging; using Ryujinx.Common.Memory; using Ryujinx.HLE.HOS.Services.Am.AppletAE; @@ -119,7 +120,7 @@ namespace Ryujinx.HLE.HOS.Applets private static byte[] BuildResponse(ControllerSupportResultInfo result) { - using MemoryStream stream = MemoryStreamManager.Shared.GetStream(); + using RecyclableMemoryStream stream = MemoryStreamManager.Shared.GetStream(); using BinaryWriter writer = new(stream); writer.Write(MemoryMarshal.AsBytes(MemoryMarshal.CreateReadOnlySpan(ref result, Unsafe.SizeOf()))); @@ -129,7 +130,7 @@ namespace Ryujinx.HLE.HOS.Applets private static byte[] BuildResponse() { - using MemoryStream stream = MemoryStreamManager.Shared.GetStream(); + using RecyclableMemoryStream stream = MemoryStreamManager.Shared.GetStream(); using BinaryWriter writer = new(stream); writer.Write((ulong)ResultCode.Success); diff --git a/src/Ryujinx.HLE/HOS/Applets/Dummy/DummyApplet.cs b/src/Ryujinx.HLE/HOS/Applets/Dummy/DummyApplet.cs index a581e1864..6fedff4dc 100644 --- a/src/Ryujinx.HLE/HOS/Applets/Dummy/DummyApplet.cs +++ b/src/Ryujinx.HLE/HOS/Applets/Dummy/DummyApplet.cs @@ -1,3 +1,4 @@ +using Microsoft.IO; using Ryujinx.Common.Memory; using Ryujinx.HLE.HOS.Services.Am.AppletAE; using System; @@ -9,14 +10,14 @@ namespace Ryujinx.HLE.HOS.Applets.Dummy { private readonly Horizon _system; private AppletSession _normalSession; - + public event EventHandler AppletStateChanged; - + public DummyApplet(Horizon system) { _system = system; } - + public ResultCode Start(AppletSession normalSession, AppletSession interactiveSession) { _normalSession = normalSession; @@ -25,10 +26,10 @@ namespace Ryujinx.HLE.HOS.Applets.Dummy _system.ReturnFocus(); return ResultCode.Success; } - + private static byte[] BuildResponse() { - using MemoryStream stream = MemoryStreamManager.Shared.GetStream(); + using RecyclableMemoryStream stream = MemoryStreamManager.Shared.GetStream(); using BinaryWriter writer = new(stream); writer.Write((ulong)ResultCode.Success); return stream.ToArray(); diff --git a/src/Ryujinx.HLE/HOS/Applets/Error/ErrorApplet.cs b/src/Ryujinx.HLE/HOS/Applets/Error/ErrorApplet.cs index 47bfadc4c..4c54b4666 100644 --- a/src/Ryujinx.HLE/HOS/Applets/Error/ErrorApplet.cs +++ b/src/Ryujinx.HLE/HOS/Applets/Error/ErrorApplet.cs @@ -159,7 +159,7 @@ namespace Ryujinx.HLE.HOS.Applets.Error string[] buttons = GetButtonsText(module, description, "DlgBtn"); (uint Module, uint Description) errorCodeTuple = (module, uint.Parse(description.ToString("0000"))); - + bool showDetails = _horizon.Device.UIHandler.DisplayErrorAppletDialog($"Error Code: {module}-{description:0000}", "\n" + message, buttons, errorCodeTuple); if (showDetails) { diff --git a/src/Ryujinx.HLE/HOS/Applets/PlayerSelect/PlayerSelectApplet.cs b/src/Ryujinx.HLE/HOS/Applets/PlayerSelect/PlayerSelectApplet.cs index cf99b0e7a..69bff74a5 100644 --- a/src/Ryujinx.HLE/HOS/Applets/PlayerSelect/PlayerSelectApplet.cs +++ b/src/Ryujinx.HLE/HOS/Applets/PlayerSelect/PlayerSelectApplet.cs @@ -1,3 +1,4 @@ +using Microsoft.IO; using Ryujinx.Common.Memory; using Ryujinx.HLE.HOS.Services.Account.Acc; using Ryujinx.HLE.HOS.Services.Am.AppletAE; @@ -26,7 +27,7 @@ namespace Ryujinx.HLE.HOS.Applets { _normalSession = normalSession; _interactiveSession = interactiveSession; - + UserProfile selected = _system.Device.UIHandler.ShowPlayerSelectDialog(); if (selected == null) { @@ -40,6 +41,7 @@ namespace Ryujinx.HLE.HOS.Applets { _normalSession.Push(BuildResponse(selected)); } + AppletStateChanged?.Invoke(this, null); _system.ReturnFocus(); @@ -47,9 +49,9 @@ namespace Ryujinx.HLE.HOS.Applets return ResultCode.Success; } - private byte[] BuildResponse(UserProfile selectedUser) + private static byte[] BuildResponse(UserProfile selectedUser) { - using MemoryStream stream = MemoryStreamManager.Shared.GetStream(); + using RecyclableMemoryStream stream = MemoryStreamManager.Shared.GetStream(); using BinaryWriter writer = new(stream); writer.Write((ulong)PlayerSelectResult.Success); @@ -58,22 +60,22 @@ namespace Ryujinx.HLE.HOS.Applets return stream.ToArray(); } - - private byte[] BuildGuestResponse() + + private static byte[] BuildGuestResponse() { - using MemoryStream stream = MemoryStreamManager.Shared.GetStream(); + using RecyclableMemoryStream stream = MemoryStreamManager.Shared.GetStream(); using BinaryWriter writer = new(stream); - + writer.Write(new byte()); return stream.ToArray(); } - - private byte[] BuildResponse() + + private static byte[] BuildResponse() { - using MemoryStream stream = MemoryStreamManager.Shared.GetStream(); + using RecyclableMemoryStream stream = MemoryStreamManager.Shared.GetStream(); using BinaryWriter writer = new(stream); - + writer.Write((ulong)PlayerSelectResult.Failure); return stream.ToArray(); diff --git a/src/Ryujinx.HLE/HOS/Applets/SoftwareKeyboard/SoftwareKeyboardApplet.cs b/src/Ryujinx.HLE/HOS/Applets/SoftwareKeyboard/SoftwareKeyboardApplet.cs index 7e88db51d..58871a069 100644 --- a/src/Ryujinx.HLE/HOS/Applets/SoftwareKeyboard/SoftwareKeyboardApplet.cs +++ b/src/Ryujinx.HLE/HOS/Applets/SoftwareKeyboard/SoftwareKeyboardApplet.cs @@ -147,19 +147,19 @@ namespace Ryujinx.HLE.HOS.Applets private bool IsKeyboardActive() { - return _backgroundState >= InlineKeyboardState.Appearing && _backgroundState < InlineKeyboardState.Disappearing; + return _backgroundState is >= InlineKeyboardState.Appearing and < InlineKeyboardState.Disappearing; } private bool InputModeControllerEnabled() { - return _inputMode == KeyboardInputMode.ControllerAndKeyboard || - _inputMode == KeyboardInputMode.ControllerOnly; + return _inputMode is KeyboardInputMode.ControllerAndKeyboard or + KeyboardInputMode.ControllerOnly; } private bool InputModeTypingEnabled() { - return _inputMode == KeyboardInputMode.ControllerAndKeyboard || - _inputMode == KeyboardInputMode.KeyboardOnly; + return _inputMode is KeyboardInputMode.ControllerAndKeyboard or + KeyboardInputMode.KeyboardOnly; } private void AdvanceInputMode() @@ -365,6 +365,7 @@ namespace Ryujinx.HLE.HOS.Applets } } } + _interactiveSession.Push(InlineResponses.ReleasedUserWordInfo(_backgroundState)); break; case InlineKeyboardRequest.SetCustomizeDic: @@ -378,6 +379,7 @@ namespace Ryujinx.HLE.HOS.Applets { _keyboardBackgroundDic = reader.ReadStruct(); } + break; case InlineKeyboardRequest.SetCustomizedDictionaries: // Read the custom dictionaries data. @@ -390,6 +392,7 @@ namespace Ryujinx.HLE.HOS.Applets { _keyboardBackgroundDictSet = reader.ReadStruct(); } + break; case InlineKeyboardRequest.Calc: // The Calc request is used to communicate configuration changes and commands to the keyboard. diff --git a/src/Ryujinx.HLE/HOS/Applets/SoftwareKeyboard/SoftwareKeyboardRendererBase.cs b/src/Ryujinx.HLE/HOS/Applets/SoftwareKeyboard/SoftwareKeyboardRendererBase.cs index 11f527285..5c9885639 100644 --- a/src/Ryujinx.HLE/HOS/Applets/SoftwareKeyboard/SoftwareKeyboardRendererBase.cs +++ b/src/Ryujinx.HLE/HOS/Applets/SoftwareKeyboard/SoftwareKeyboardRendererBase.cs @@ -198,6 +198,7 @@ namespace Ryujinx.HLE.HOS.Applets.SoftwareKeyboard { return; } + SKCanvas canvas = _surface.Canvas; canvas.Clear(SKColors.Transparent); diff --git a/src/Ryujinx.HLE/HOS/ArmProcessContextFactory.cs b/src/Ryujinx.HLE/HOS/ArmProcessContextFactory.cs index 08d929bf0..759780c42 100644 --- a/src/Ryujinx.HLE/HOS/ArmProcessContextFactory.cs +++ b/src/Ryujinx.HLE/HOS/ArmProcessContextFactory.cs @@ -110,6 +110,7 @@ namespace Ryujinx.HLE.HOS MemoryManagerHostMapped memoryManagerHostMapped = new(addressSpace, mode == MemoryManagerMode.HostMappedUnsafe, invalidAccessHandler); processContext = new ArmProcessContext(pid, cpuEngine, _gpu, memoryManagerHostMapped, addressSpace.AddressSpaceSize, for64Bit); } + break; default: diff --git a/src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Demangler.cs b/src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Demangler.cs index 9413ed9ff..5424342fb 100644 --- a/src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Demangler.cs +++ b/src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Demangler.cs @@ -210,7 +210,6 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler return true; } - // ::= # non-dependent type name, dependent type name, or dependent typename-specifier // ::= Ts # dependent elaborated type specifier using 'struct' or 'class' // ::= Tu # dependent elaborated type specifier using 'union' @@ -252,7 +251,7 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler // ::= Do # non-throwing exception-specification (e.g., noexcept, throw()) // ::= DO E # computed (instantiation-dependent) noexcept // ::= Dw + E # dynamic exception specification with instantiation-dependent types - private BaseNode ParseFunctionType() + private FunctionType ParseFunctionType() { Cv cvQualifiers = ParseCvQualifiers(); @@ -347,7 +346,7 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler // ::= A _ // ::= A [] _ - private BaseNode ParseArrayType() + private ArrayType ParseArrayType() { if (!ConsumeIf("A")) { @@ -570,6 +569,7 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler default: return null; } + break; case 'F': result = ParseFunctionType(); @@ -582,7 +582,7 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler return null; case 'T': // might just be a class enum type - if (Peek(1) == 's' || Peek(1) == 'u' || Peek(1) == 'e') + if (Peek(1) is 's' or 'u' or 'e') { result = ParseClassEnumType(); break; @@ -604,6 +604,7 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler result = new NameTypeWithTemplateArguments(result, templateArguments); } + break; case 'P': _position++; @@ -680,6 +681,7 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler result = new NameTypeWithTemplateArguments(substitution, templateArgument); break; } + return substitution; } else @@ -691,6 +693,7 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler result = ParseClassEnumType(); break; } + if (result != null) { _substitutionList.Add(result); @@ -723,6 +726,7 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler return new SpecialName("guard variable for ", name); } + return null; } @@ -848,10 +852,12 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler { qualifiers |= Cv.Restricted; } + if (ConsumeIf("V")) { qualifiers |= Cv.Volatile; } + if (ConsumeIf("K")) { qualifiers |= Cv.Const; @@ -860,7 +866,6 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler return qualifiers; } - // ::= R # & ref-qualifier // ::= O # && ref-qualifier private SimpleReferenceType ParseRefQualifiers() @@ -874,6 +879,7 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler { result = Reference.LValue; } + return new SimpleReferenceType(result, null); } @@ -945,7 +951,7 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler } // ::= - private BaseNode ParseSourceName() + private NameType ParseSourceName() { int length = ParsePositiveNumber(); if (Count() < length || length <= 0) @@ -1131,6 +1137,7 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler _position += 2; return new NameType("operator[]"); } + return null; case 'l': switch (Peek(1)) @@ -1244,6 +1251,7 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler _position += 2; return new NameType("operator?"); } + return null; case 'r': switch (Peek(1)) @@ -1269,6 +1277,7 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler _position += 2; return new NameType("operator<=>"); } + return null; case 'v': // TODO: ::= v # vendor extended operator @@ -1311,6 +1320,7 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler // TODO: ABI Tags // throw new Exception("ABI Tags not implemented"); } + return result; } @@ -1320,7 +1330,7 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler // ::= D0 # deleting destructor // ::= D1 # complete object destructor // ::= D2 # base object destructor - private BaseNode ParseCtorDtorName(NameParserContext context, BaseNode prev) + private CtorDtorNameType ParseCtorDtorName(NameParserContext context, BaseNode prev) { if (prev.Type == NodeType.SpecialSubstitution && prev is SpecialSubstitution substitution) { @@ -1332,7 +1342,7 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler bool isInherited = ConsumeIf("I"); char ctorDtorType = Peek(); - if (ctorDtorType != '1' && ctorDtorType != '2' && ctorDtorType != '3') + if (ctorDtorType is not '1' and not '2' and not '3') { return null; } @@ -1355,7 +1365,7 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler if (ConsumeIf("D")) { char c = Peek(); - if (c != '0' && c != '1' && c != '2') + if (c is not '0' and not '1' and not '2') { return null; } @@ -1377,7 +1387,7 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler // ::= fp _ # L == 0, second and later parameters // ::= fL p _ # L > 0, first parameter // ::= fL p _ # L > 0, second and later parameters - private BaseNode ParseFunctionParameter() + private FunctionParameter ParseFunctionParameter() { if (ConsumeIf("fp")) { @@ -1422,7 +1432,7 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler // ::= fR // ::= fl // ::= fr - private BaseNode ParseFoldExpression() + private FoldExpression ParseFoldExpression() { if (!ConsumeIf("f")) { @@ -1430,8 +1440,8 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler } char foldKind = Peek(); - bool hasInitializer = foldKind == 'L' || foldKind == 'R'; - bool isLeftFold = foldKind == 'l' || foldKind == 'L'; + bool hasInitializer = foldKind is 'L' or 'R'; + bool isLeftFold = foldKind is 'l' or 'L'; if (!isLeftFold && !(foldKind == 'r' || foldKind == 'R')) { @@ -1568,10 +1578,9 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler return new FoldExpression(isLeftFold, operatorName, new PackedTemplateParameterExpansion(expression), initializer); } - // ::= cv # type (expression), conversion with one argument // ::= cv _ * E # type (expr-list), conversion with other than one argument - private BaseNode ParseConversionExpression() + private ConversionExpression ParseConversionExpression() { if (!ConsumeIf("cv")) { @@ -1616,7 +1625,7 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler return new ConversionExpression(type, new NodeArray(expressions)); } - private BaseNode ParseBinaryExpression(string name) + private BinaryExpression ParseBinaryExpression(string name) { BaseNode leftPart = ParseExpression(); if (leftPart == null) @@ -1633,7 +1642,7 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler return new BinaryExpression(leftPart, name, rightPart); } - private BaseNode ParsePrefixExpression(string name) + private PrefixExpression ParsePrefixExpression(string name) { BaseNode expression = ParseExpression(); if (expression == null) @@ -1644,7 +1653,6 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler return new PrefixExpression(name, expression); } - // ::= // ::= di # .name = expr // ::= dx # [expr] = expr @@ -1720,7 +1728,7 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler // ::= [gs] na * _ # new[] (expr-list) type (init) // // ::= pi * E # parenthesized initialization - private BaseNode ParseNewExpression() + private NewExpression ParseNewExpression() { bool isGlobal = ConsumeIf("gs"); bool isArray = Peek(1) == 'a'; @@ -1771,7 +1779,6 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler return new NewExpression(new NodeArray(expressions), typeNode, new NodeArray(initializers), isGlobal, isArray); } - // ::= // ::= // ::= @@ -1872,6 +1879,7 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler return new EnclosedExpression("alignof (", expression, ")"); } + return null; case 'c': switch (Peek(1)) @@ -1910,6 +1918,7 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler names.Add(expression); } + return new CallExpression(callee, names); case 'm': _position += 2; @@ -1920,6 +1929,7 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler case 'v': return ParseConversionExpression(); } + return null; case 'd': BaseNode leftNode; @@ -2001,6 +2011,7 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler _position += 2; return ParseBinaryExpression("/="); } + return null; case 'e': switch (Peek(1)) @@ -2015,6 +2026,7 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler _position += 2; return ParseBinaryExpression("=="); } + return null; case 'g': switch (Peek(1)) @@ -2026,6 +2038,7 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler _position += 2; return ParseBinaryExpression(">"); } + return null; case 'i': switch (Peek(1)) @@ -2059,8 +2072,10 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler bracedExpressions.Add(expression); } + return new InitListExpression(null, bracedExpressions); } + return null; case 'l': switch (Peek(1)) @@ -2078,6 +2093,7 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler _position += 2; return ParseBinaryExpression("<"); } + return null; case 'm': switch (Peek(1)) @@ -2109,6 +2125,7 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler return new PostfixExpression(expression, "--"); } + return null; case 'n': switch (Peek(1)) @@ -2136,6 +2153,7 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler return new EnclosedExpression("noexcept (", expression, ")"); } + return null; case 'o': switch (Peek(1)) @@ -2152,6 +2170,7 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler _position += 2; return ParseBinaryExpression("|="); } + return null; case 'p': switch (Peek(1)) @@ -2196,6 +2215,7 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler return new MemberExpression(leftNode, "->", rightNode); } + return null; case 'q': if (Peek(1) == 'u') @@ -2221,6 +2241,7 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler return new ConditionalExpression(condition, leftNode, rightNode); } + return null; case 'r': switch (Peek(1)) @@ -2253,6 +2274,7 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler _position += 2; return ParseBinaryExpression(">>="); } + return null; case 's': switch (Peek(1)) @@ -2324,6 +2346,7 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler return new EnclosedExpression("sizeof...(", sizeofParamNode, ")"); } + return null; case 'P': _position += 2; @@ -2338,8 +2361,10 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler arguments.Add(argument); } + return new EnclosedExpression("sizeof...(", new NodeArray(arguments), ")"); } + return null; case 't': switch (Peek(1)) @@ -2379,6 +2404,7 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler bracedExpressions.Add(expression); } + return new InitListExpression(typeNode, bracedExpressions); case 'r': _position += 2; @@ -2393,6 +2419,7 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler return new ThrowExpression(expression); } + return null; } @@ -2404,7 +2431,7 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler return null; } - private BaseNode ParseIntegerLiteral(string literalName) + private IntegerLiteral ParseIntegerLiteral(string literalName) { string number = ParseNumber(true); if (number == null || number.Length == 0 || !ConsumeIf("E")) @@ -2499,6 +2526,7 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler return encoding; } } + return null; case 'T': return null; @@ -2521,7 +2549,7 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler // ::= Dt E # decltype of an id-expression or class member access (C++0x) // ::= DT E # decltype of an expression (C++0x) - private BaseNode ParseDecltype() + private EnclosedExpression ParseDecltype() { if (!ConsumeIf("D") || (!ConsumeIf("t") && !ConsumeIf("T"))) { @@ -2579,6 +2607,7 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler _forwardTemplateReferenceList.Add(forwardTemplateReference); return forwardTemplateReference; } + if (index >= _templateParamList.Count) { return null; @@ -2588,7 +2617,7 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler } // ::= I + E - private BaseNode ParseTemplateArguments(bool hasContext = false) + private TemplateArguments ParseTemplateArguments(bool hasContext = false) { if (!ConsumeIf("I")) { @@ -2605,7 +2634,7 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler { if (hasContext) { - List templateParamListTemp = new(_templateParamList); + List templateParamListTemp = [.. _templateParamList]; BaseNode templateArgument = ParseTemplateArgument(); _templateParamList = templateParamListTemp; if (templateArgument == null) @@ -2618,6 +2647,7 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler { templateArgument = new PackedTemplateParameter(((NodeArray)templateArgument).Nodes); } + _templateParamList.Add(templateArgument); } else @@ -2631,10 +2661,10 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler args.Add(templateArgument); } } + return new TemplateArguments(args); } - // ::= # type or template // ::= X E # expression // ::= # simple expressions @@ -2670,6 +2700,7 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler templateArguments.Add(templateArgument); } + return new NodeArray(templateArguments, NodeType.PackedTemplateArgument); // default: @@ -2685,7 +2716,6 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler public bool CtorDtorConversion; } - // ::= [ ] # T:: or T:: // ::= # decltype(p):: // ::= @@ -2713,6 +2743,7 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler _substitutionList.Add(declType); return declType; } + return ParseSubstitution(); } @@ -2735,12 +2766,13 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler return new NameTypeWithTemplateArguments(sourceName, templateArguments); } + return sourceName; } // ::= # e.g., ~T or ~decltype(f()) // ::= # e.g., ~A<2*N> - private BaseNode ParseDestructorName() + private DtorName ParseDestructorName() { BaseNode node; if (char.IsDigit(Peek())) @@ -2751,6 +2783,7 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler { node = ParseUnresolvedType(); } + if (node == null) { return null; @@ -2794,6 +2827,7 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler return new NameTypeWithTemplateArguments(operatorName, templateArguments); } + return operatorName; } @@ -2955,6 +2989,7 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler return new StdQualifiedName(unresolvedName); } + return ParseUnresolvedName(context); } @@ -2998,6 +3033,7 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler continue; } + char c = Peek(); // TODO: template args @@ -3098,10 +3134,12 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler { return null; } + result = CreateNameNode(result, unqualifiedName, context); _substitutionList.Add(result); } + if (result == null || _substitutionList.Count == 0) { return null; @@ -3127,6 +3165,7 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler { Consume(); } + ConsumeIf("_"); } } @@ -3134,7 +3173,7 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler // ::= Z E [] // ::= Z E s [] // ::= Z Ed [ ] _ - private BaseNode ParseLocalName(NameParserContext context) + private LocalName ParseLocalName(NameParserContext context) { if (!ConsumeIf("Z")) { @@ -3329,6 +3368,7 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler { return encoding; } + return null; } else @@ -3338,6 +3378,7 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler { return type; } + return null; } } diff --git a/src/Ryujinx.HLE/HOS/Horizon.cs b/src/Ryujinx.HLE/HOS/Horizon.cs index 7af8711c7..5063b4329 100644 --- a/src/Ryujinx.HLE/HOS/Horizon.cs +++ b/src/Ryujinx.HLE/HOS/Horizon.cs @@ -345,6 +345,7 @@ namespace Ryujinx.HLE.HOS VirtualAmiibo.ApplicationBytes = []; VirtualAmiibo.InputBin = string.Empty; } + if (NfpDevices[nfpDeviceId].State == NfpDeviceState.SearchingForTag) { NfpDevices[nfpDeviceId].State = NfpDeviceState.TagFound; @@ -359,6 +360,7 @@ namespace Ryujinx.HLE.HOS { VirtualAmiibo.ApplicationBytes = []; } + byte[] encryptedData = File.ReadAllBytes(path); VirtualAmiiboFile newFile = AmiiboBinReader.ReadBinFile(encryptedData); if (SearchingForAmiibo(out int nfpDeviceId)) @@ -495,6 +497,7 @@ namespace Ryujinx.HLE.HOS TickSource.Resume(); } } + IsPaused = pause; } } diff --git a/src/Ryujinx.HLE/HOS/Kernel/Ipc/KServerSession.cs b/src/Ryujinx.HLE/HOS/Kernel/Ipc/KServerSession.cs index 6c1586cb9..edc3d819e 100644 --- a/src/Ryujinx.HLE/HOS/Kernel/Ipc/KServerSession.cs +++ b/src/Ryujinx.HLE/HOS/Kernel/Ipc/KServerSession.cs @@ -981,7 +981,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc { return KernelResult.OutOfResource; } - else if (recvListType == 1 || recvListType == 2) + else if (recvListType is 1 or 2) { ulong recvListBaseAddr; ulong recvListEndAddr; diff --git a/src/Ryujinx.HLE/HOS/Kernel/Memory/KCodeMemory.cs b/src/Ryujinx.HLE/HOS/Kernel/Memory/KCodeMemory.cs index e6d96d803..967aa6c0f 100644 --- a/src/Ryujinx.HLE/HOS/Kernel/Memory/KCodeMemory.cs +++ b/src/Ryujinx.HLE/HOS/Kernel/Memory/KCodeMemory.cs @@ -86,7 +86,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory return KernelResult.InvalidState; } - Debug.Assert(permission == KMemoryPermission.Read || permission == KMemoryPermission.ReadAndExecute); + Debug.Assert(permission is KMemoryPermission.Read or KMemoryPermission.ReadAndExecute); Result result = Owner.MemoryManager.MapPages(address, _pageList, MemoryState.CodeReadOnly, permission); diff --git a/src/Ryujinx.HLE/HOS/Kernel/Memory/KPageTableBase.cs b/src/Ryujinx.HLE/HOS/Kernel/Memory/KPageTableBase.cs index db190e6a9..ee1b4a7be 100644 --- a/src/Ryujinx.HLE/HOS/Kernel/Memory/KPageTableBase.cs +++ b/src/Ryujinx.HLE/HOS/Kernel/Memory/KPageTableBase.cs @@ -253,6 +253,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory AliasRegionExtraSize = addrSpaceEnd / 8; aliasRegion.Size += AliasRegionExtraSize; } + break; default: diff --git a/src/Ryujinx.HLE/HOS/Kernel/Process/HleProcessDebugger.cs b/src/Ryujinx.HLE/HOS/Kernel/Process/HleProcessDebugger.cs index bb12bd384..c4a9835cc 100644 --- a/src/Ryujinx.HLE/HOS/Kernel/Process/HleProcessDebugger.cs +++ b/src/Ryujinx.HLE/HOS/Kernel/Process/HleProcessDebugger.cs @@ -138,6 +138,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process { sb.AppendLine($"\tX[{i:d2}]:\t{GetReg(i)}"); } + sb.AppendLine($"\tFP:\t{GetReg(29)}"); sb.AppendLine($"\tLR:\t{GetReg(30)}"); sb.AppendLine($"\tSP:\t{GetReg(31)}"); @@ -235,6 +236,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process { info.SubName = Demangler.Parse(info.SubName); } + info.SubOffset = info.Offset - symbol.Value; } else diff --git a/src/Ryujinx.HLE/HOS/Kernel/Process/KProcess.cs b/src/Ryujinx.HLE/HOS/Kernel/Process/KProcess.cs index 32dca1512..478b4e864 100644 --- a/src/Ryujinx.HLE/HOS/Kernel/Process/KProcess.cs +++ b/src/Ryujinx.HLE/HOS/Kernel/Process/KProcess.cs @@ -128,7 +128,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process Pid = KernelContext.NewKipId(); - if (Pid == 0 || Pid >= KernelConstants.InitialProcessId) + if (Pid is 0 or >= KernelConstants.InitialProcessId) { throw new InvalidOperationException($"Invalid KIP Id {Pid}."); } @@ -231,7 +231,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process Pid = KernelContext.NewProcessId(); - if (Pid == ulong.MaxValue || Pid < KernelConstants.InitialProcessId) + if (Pid is ulong.MaxValue or < KernelConstants.InitialProcessId) { throw new InvalidOperationException($"Invalid Process Id {Pid}."); } @@ -309,7 +309,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process return KernelResult.InvalidCombination; } - if (requiredKernelVersionMajor != KernelVersionMajor && requiredKernelVersionMajor < 3) + if (requiredKernelVersionMajor is not KernelVersionMajor and < 3) { return KernelResult.InvalidCombination; } @@ -461,7 +461,6 @@ namespace Ryujinx.HLE.HOS.Kernel.Process Result result = Result.Success; - if (_fullTlsPages.TryGetValue(tlsPageAddr, out KTlsPageInfo pageInfo)) { // TLS page was full, free slot and move to free pages tree. @@ -509,7 +508,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process return result; } - private void GenerateRandomEntropy() + private static void GenerateRandomEntropy() { // TODO. } @@ -882,10 +881,10 @@ namespace Ryujinx.HLE.HOS.Kernel.Process { if (State >= ProcessState.Started) { - if (State == ProcessState.Started || - State == ProcessState.Crashed || - State == ProcessState.Attached || - State == ProcessState.DebugSuspended) + if (State is ProcessState.Started or + ProcessState.Crashed or + ProcessState.Attached or + ProcessState.DebugSuspended) { SetState(ProcessState.Exiting); @@ -925,9 +924,9 @@ namespace Ryujinx.HLE.HOS.Kernel.Process { if (State >= ProcessState.Started) { - if (State == ProcessState.Started || - State == ProcessState.Attached || - State == ProcessState.DebugSuspended) + if (State is ProcessState.Started or + ProcessState.Attached or + ProcessState.DebugSuspended) { SetState(ProcessState.Exiting); @@ -1090,7 +1089,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process { KernelContext.CriticalSection.Enter(); - if (State != ProcessState.Exiting && State != ProcessState.Exited) + if (State is not ProcessState.Exiting and not ProcessState.Exited) { if (pause) { diff --git a/src/Ryujinx.HLE/HOS/Kernel/Process/ProcessCreationFlags.cs b/src/Ryujinx.HLE/HOS/Kernel/Process/ProcessCreationFlags.cs index 1b62a29d4..6ca54355e 100644 --- a/src/Ryujinx.HLE/HOS/Kernel/Process/ProcessCreationFlags.cs +++ b/src/Ryujinx.HLE/HOS/Kernel/Process/ProcessCreationFlags.cs @@ -4,7 +4,6 @@ using System.Diagnostics.CodeAnalysis; namespace Ryujinx.HLE.HOS.Kernel.Process { [Flags] - [SuppressMessage("Design", "CA1069: Enums values should not be duplicated")] enum ProcessCreationFlags { Is64Bit = 1 << 0, diff --git a/src/Ryujinx.HLE/HOS/Kernel/SupervisorCall/Syscall.cs b/src/Ryujinx.HLE/HOS/Kernel/SupervisorCall/Syscall.cs index 9bcaf9538..c67220617 100644 --- a/src/Ryujinx.HLE/HOS/Kernel/SupervisorCall/Syscall.cs +++ b/src/Ryujinx.HLE/HOS/Kernel/SupervisorCall/Syscall.cs @@ -150,7 +150,7 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall return handleTable.GenerateHandle(process, out handle); } - public Result StartProcess(int handle, int priority, int cpuCore, ulong mainThreadStackSize) + public static Result StartProcess(int handle, int priority, int cpuCore, ulong mainThreadStackSize) { KProcess process = KernelStatic.GetCurrentProcess().HandleTable.GetObject(handle); @@ -1071,7 +1071,7 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall return result; } - public Result QueryMemory(out MemoryInfo info, out ulong pageInfo, ulong address) + public static Result QueryMemory(out MemoryInfo info, out ulong pageInfo, ulong address) { KProcess process = KernelStatic.GetCurrentProcess(); @@ -1199,7 +1199,7 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall return KernelResult.InvalidMemState; } - if (permission > KMemoryPermission.ReadAndWrite || permission == KMemoryPermission.Write) + if (permission is > KMemoryPermission.ReadAndWrite or KMemoryPermission.Write) { return KernelResult.InvalidPermission; } @@ -1261,7 +1261,7 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall return KernelResult.InvalidMemState; } - if (permission > KMemoryPermission.ReadAndWrite || permission == KMemoryPermission.Write) + if (permission is > KMemoryPermission.ReadAndWrite or KMemoryPermission.Write) { return KernelResult.InvalidPermission; } @@ -1485,7 +1485,7 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall return KernelResult.InvalidMemRange; } - if (permission != KMemoryPermission.Read && permission != KMemoryPermission.ReadAndExecute) + if (permission is not KMemoryPermission.Read and not KMemoryPermission.ReadAndExecute) { return KernelResult.InvalidPermission; } @@ -1540,10 +1540,10 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall return KernelResult.InvalidSize; } - if (permission != KMemoryPermission.None && - permission != KMemoryPermission.Read && - permission != KMemoryPermission.ReadAndWrite && - permission != KMemoryPermission.ReadAndExecute) + if (permission is not KMemoryPermission.None and + not KMemoryPermission.Read and + not KMemoryPermission.ReadAndWrite and + not KMemoryPermission.ReadAndExecute) { return KernelResult.InvalidPermission; } @@ -2009,6 +2009,7 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall { value = process.MemoryManager.GetMmUsedPages() * KPageTableBase.PageSize; } + break; case InfoType.ProgramId: @@ -2040,12 +2041,14 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall { value = 0; } + break; case InfoType.AliasRegionExtraSize: value = process.MemoryManager.AliasRegionExtraSize; break; } + break; } @@ -2093,6 +2096,7 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall value = (uint)resLimHandle; } + break; } @@ -2134,7 +2138,7 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall case InfoType.ThreadTickCount: { - if (subId < -1 || subId > 3) + if (subId is < (-1) or > 3) { return KernelResult.InvalidCombination; } @@ -2174,6 +2178,7 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall value = (ulong)KTimeManager.ConvertHostTicksToTicks(totalTimeRunning); } + break; } diff --git a/src/Ryujinx.HLE/HOS/Kernel/Threading/KCriticalSection.cs b/src/Ryujinx.HLE/HOS/Kernel/Threading/KCriticalSection.cs index b3fe5f1b6..172f67cca 100644 --- a/src/Ryujinx.HLE/HOS/Kernel/Threading/KCriticalSection.cs +++ b/src/Ryujinx.HLE/HOS/Kernel/Threading/KCriticalSection.cs @@ -6,7 +6,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading { private readonly KernelContext _context; private int _recursionCount; - + // type is not Lock due to Monitor class usage public object Lock { get; } = new(); diff --git a/src/Ryujinx.HLE/HOS/Kernel/Threading/KScheduler.cs b/src/Ryujinx.HLE/HOS/Kernel/Threading/KScheduler.cs index 19f1b8be0..7471702c3 100644 --- a/src/Ryujinx.HLE/HOS/Kernel/Threading/KScheduler.cs +++ b/src/Ryujinx.HLE/HOS/Kernel/Threading/KScheduler.cs @@ -46,10 +46,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading _currentThread = null; - if (_srcCoresHighestPrioThreads == null) - { - _srcCoresHighestPrioThreads = new int[CpuCoresCount]; - } + _srcCoresHighestPrioThreads ??= new int[CpuCoresCount]; } private static int PreemptionPriorities(int index) diff --git a/src/Ryujinx.HLE/HOS/Kernel/Threading/KThread.cs b/src/Ryujinx.HLE/HOS/Kernel/Threading/KThread.cs index f1745eb44..b5a14ad5b 100644 --- a/src/Ryujinx.HLE/HOS/Kernel/Threading/KThread.cs +++ b/src/Ryujinx.HLE/HOS/Kernel/Threading/KThread.cs @@ -537,7 +537,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading ThreadSchedState lowNibble = SchedFlags & ThreadSchedState.LowMask; - if (lowNibble != ThreadSchedState.Paused && lowNibble != ThreadSchedState.Running) + if (lowNibble is not ThreadSchedState.Paused and not ThreadSchedState.Running) { KernelContext.CriticalSection.Leave(); diff --git a/src/Ryujinx.HLE/HOS/ModLoader.cs b/src/Ryujinx.HLE/HOS/ModLoader.cs index 6d6da6240..4df929f35 100644 --- a/src/Ryujinx.HLE/HOS/ModLoader.cs +++ b/src/Ryujinx.HLE/HOS/ModLoader.cs @@ -500,6 +500,7 @@ namespace Ryujinx.HLE.HOS { AddFiles(fs, mod.Name, mod.Path.FullName, fileSet, builder); } + count++; } @@ -516,6 +517,7 @@ namespace Ryujinx.HLE.HOS { AddFiles(fs, mod.Name, mod.Path.FullName, fileSet, builder); } + count++; } @@ -547,7 +549,7 @@ namespace Ryujinx.HLE.HOS return newStorage; } - private static void AddFiles(IFileSystem fs, string modName, string rootPath, ISet fileSet, RomFsBuilder builder) + private static void AddFiles(IFileSystem fs, string modName, string rootPath, HashSet fileSet, RomFsBuilder builder) { foreach (DirectoryEntryEx entry in fs.EnumerateEntries() .AsParallel() @@ -644,16 +646,11 @@ namespace Ryujinx.HLE.HOS modLoadResult.Replaces[1 << i] = true; - using (FileStream stream = nsoFile.OpenRead()) - { - nsos[i] = new NsoExecutable(stream.AsStorage(), nsoName); - Logger.Info?.Print(LogClass.ModLoader, $"NSO '{nsoName}' replaced"); - using (MD5 md5 = MD5.Create()) - { - stream.Seek(0, SeekOrigin.Begin); - tempHash += BitConverter.ToString(md5.ComputeHash(stream)).Replace("-", "").ToLowerInvariant(); - } - } + using FileStream stream = nsoFile.OpenRead(); + nsos[i] = new NsoExecutable(stream.AsStorage(), nsoName); + Logger.Info?.Print(LogClass.ModLoader, $"NSO '{nsoName}' replaced"); + stream.Seek(0, SeekOrigin.Begin); + tempHash += Convert.ToHexStringLower(MD5.HashData(stream)); } modLoadResult.Stubs[1 << i] |= File.Exists(Path.Combine(mod.Path.FullName, nsoName + StubExtension)); @@ -687,10 +684,7 @@ namespace Ryujinx.HLE.HOS if (!string.IsNullOrEmpty(tempHash)) { - using (MD5 md5 = MD5.Create()) - { - modLoadResult.Hash += BitConverter.ToString(md5.ComputeHash(tempHash.ToBytes())).Replace("-", string.Empty).ToLowerInvariant(); - } + modLoadResult.Hash += Convert.ToHexStringLower(MD5.HashData(tempHash.ToBytes())); } return modLoadResult; diff --git a/src/Ryujinx.HLE/HOS/Services/Account/Acc/AccountManager.cs b/src/Ryujinx.HLE/HOS/Services/Account/Acc/AccountManager.cs index 7364b2d40..7643c109d 100644 --- a/src/Ryujinx.HLE/HOS/Services/Account/Acc/AccountManager.cs +++ b/src/Ryujinx.HLE/HOS/Services/Account/Acc/AccountManager.cs @@ -56,6 +56,7 @@ namespace Ryujinx.HLE.HOS.Services.Account.Acc Logger.Warning?.Print(LogClass.Application, $"The command line specified profile named '{initialProfileName}' was not found"); } } + OpenUser(commandLineUserProfileOverride.IsNull ? _accountSaveDataManager.LastOpened : commandLineUserProfileOverride); } } diff --git a/src/Ryujinx.HLE/HOS/Services/Am/AppletAE/Storage/StorageHelper.cs b/src/Ryujinx.HLE/HOS/Services/Am/AppletAE/Storage/StorageHelper.cs index 6c23720ee..d96877362 100644 --- a/src/Ryujinx.HLE/HOS/Services/Am/AppletAE/Storage/StorageHelper.cs +++ b/src/Ryujinx.HLE/HOS/Services/Am/AppletAE/Storage/StorageHelper.cs @@ -1,3 +1,4 @@ +using Microsoft.IO; using Ryujinx.Common.Memory; using Ryujinx.HLE.HOS.Services.Account.Acc; using System.IO; @@ -11,7 +12,7 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.Storage public static byte[] MakeLaunchParams(UserProfile userProfile) { // Size needs to be at least 0x88 bytes otherwise application errors. - using MemoryStream ms = MemoryStreamManager.Shared.GetStream(); + using RecyclableMemoryStream ms = MemoryStreamManager.Shared.GetStream(); BinaryWriter writer = new(ms); ms.SetLength(0x88); diff --git a/src/Ryujinx.HLE/HOS/Services/Caps/CaptureManager.cs b/src/Ryujinx.HLE/HOS/Services/Caps/CaptureManager.cs index 2dd86b436..3caea0f6c 100644 --- a/src/Ryujinx.HLE/HOS/Services/Caps/CaptureManager.cs +++ b/src/Ryujinx.HLE/HOS/Services/Caps/CaptureManager.cs @@ -103,7 +103,7 @@ namespace Ryujinx.HLE.HOS.Services.Caps }; // NOTE: The hex hash is a HMAC-SHA256 (first 32 bytes) using a hardcoded secret key over the titleId, we can simulate it by hashing the titleId instead. - string hash = Convert.ToHexString(SHA256.HashData(BitConverter.GetBytes(titleId))).Remove(0x20); + string hash = Convert.ToHexString(SHA256.HashData(BitConverter.GetBytes(titleId)))[..0x20]; string folderPath = Path.Combine(_sdCardPath, "Nintendo", "Album", currentDateTime.Year.ToString("00"), currentDateTime.Month.ToString("00"), currentDateTime.Day.ToString("00")); string filePath = GenerateFilePath(folderPath, applicationAlbumEntry, currentDateTime, hash); diff --git a/src/Ryujinx.HLE/HOS/Services/Caps/IAlbumApplicationService.cs b/src/Ryujinx.HLE/HOS/Services/Caps/IAlbumApplicationService.cs index 5fbba310f..754a44025 100644 --- a/src/Ryujinx.HLE/HOS/Services/Caps/IAlbumApplicationService.cs +++ b/src/Ryujinx.HLE/HOS/Services/Caps/IAlbumApplicationService.cs @@ -50,7 +50,7 @@ namespace Ryujinx.HLE.HOS.Services.Caps MemoryHelper.FillWithZeros(context.Memory, applicationAlbumFileEntryPosition, (int)applicationAlbumFileEntrySize); - if (contentType > ContentType.Unknown || contentType == ContentType.ExtraMovie) + if (contentType is > ContentType.Unknown or ContentType.ExtraMovie) { resultCode = ResultCode.InvalidContentType; } diff --git a/src/Ryujinx.HLE/HOS/Services/Caps/IScreenShotApplicationService.cs b/src/Ryujinx.HLE/HOS/Services/Caps/IScreenShotApplicationService.cs index 0dad46c14..0723b57cc 100644 --- a/src/Ryujinx.HLE/HOS/Services/Caps/IScreenShotApplicationService.cs +++ b/src/Ryujinx.HLE/HOS/Services/Caps/IScreenShotApplicationService.cs @@ -60,7 +60,6 @@ namespace Ryujinx.HLE.HOS.Services.Caps ulong screenshotDataPosition = context.Request.SendBuff[1].Position; ulong screenshotDataSize = context.Request.SendBuff[1].Size; - // TODO: Parse the application data: At 0x00 it's UserData (Size of 0x400), at 0x404 it's a uint UserDataSize (Always empty for now). _ = context.Memory.GetSpan(applicationDataPosition, (int)applicationDataSize).ToArray(); @@ -89,7 +88,6 @@ namespace Ryujinx.HLE.HOS.Services.Caps ulong screenshotDataPosition = context.Request.SendBuff[1].Position; ulong screenshotDataSize = context.Request.SendBuff[1].Size; - // TODO: Parse the UserIdList. _ = context.Memory.GetSpan(userIdListPosition, (int)userIdListSize).ToArray(); diff --git a/src/Ryujinx.HLE/HOS/Services/Fs/FileSystemProxy/IFileSystem.cs b/src/Ryujinx.HLE/HOS/Services/Fs/FileSystemProxy/IFileSystem.cs index 0ed56ea4e..168dfc37a 100644 --- a/src/Ryujinx.HLE/HOS/Services/Fs/FileSystemProxy/IFileSystem.cs +++ b/src/Ryujinx.HLE/HOS/Services/Fs/FileSystemProxy/IFileSystem.cs @@ -134,7 +134,7 @@ namespace Ryujinx.HLE.HOS.Services.Fs.FileSystemProxy ref readonly Path name = ref FileSystemProxyHelper.GetSfPath(context); using SharedRef dir = new(); - Result result = _fileSystem.Get.OpenDirectory(ref dir.Ref, name, mode); + Result result = _fileSystem.Get.OpenDirectory(ref dir.Ref, in name, mode); if (result.IsSuccess()) { diff --git a/src/Ryujinx.HLE/HOS/Services/Fs/FileSystemProxy/IStorage.cs b/src/Ryujinx.HLE/HOS/Services/Fs/FileSystemProxy/IStorage.cs index 04dc6c688..a485ebe63 100644 --- a/src/Ryujinx.HLE/HOS/Services/Fs/FileSystemProxy/IStorage.cs +++ b/src/Ryujinx.HLE/HOS/Services/Fs/FileSystemProxy/IStorage.cs @@ -16,7 +16,7 @@ namespace Ryujinx.HLE.HOS.Services.Fs.FileSystemProxy { _baseStorage = SharedRef.CreateMove(ref baseStorage); } - + private const string Xc2JpTitleId = "0100f3400332c000"; private const string Xc2GlobalTitleId = "0100e95004038000"; private static bool IsXc2 => TitleIDs.CurrentApplication.Value.OrDefault() is Xc2GlobalTitleId or Xc2JpTitleId; @@ -41,7 +41,7 @@ namespace Ryujinx.HLE.HOS.Services.Fs.FileSystemProxy using WritableRegion region = context.Memory.GetWritableRegion(bufferAddress, (int)bufferLen, true); Result result = _baseStorage.Get.Read((long)offset, new OutBuffer(region.Memory.Span), (long)size); - + if (context.Device.DirtyHacks.IsEnabled(DirtyHack.Xc2MenuSoftlockFix) && IsXc2) { // Add a load-bearing sleep to avoid XC2 softlock diff --git a/src/Ryujinx.HLE/HOS/Services/Fs/IFileSystemProxy.cs b/src/Ryujinx.HLE/HOS/Services/Fs/IFileSystemProxy.cs index dcd55d579..08ede2b5b 100644 --- a/src/Ryujinx.HLE/HOS/Services/Fs/IFileSystemProxy.cs +++ b/src/Ryujinx.HLE/HOS/Services/Fs/IFileSystemProxy.cs @@ -753,7 +753,7 @@ namespace Ryujinx.HLE.HOS.Services.Fs public ResultCode OpenCloudBackupWorkStorageFileSystem(ServiceCtx context) { CloudBackupWorkStorageId storageId = (CloudBackupWorkStorageId)context.RequestData.ReadInt32(); - + Logger.Stub?.PrintStub(LogClass.ServiceFs, new { storageId }); throw new NotImplementedException(); // reimplementing behavior from LibHac 0.19.0 } @@ -1232,9 +1232,9 @@ namespace Ryujinx.HLE.HOS.Services.Fs { BisPartitionId partitionId = (BisPartitionId)context.RequestData.ReadInt32(); ref readonly FspPath path = ref FileSystemProxyHelper.GetFspPath(context); - + Logger.Stub?.PrintStub(LogClass.ServiceFs, new { partitionId, path }); - + throw new NotImplementedException(); // reimplementing behavior from LibHac 0.19.0 } diff --git a/src/Ryujinx.HLE/HOS/Services/Hid/HidServer/HidUtils.cs b/src/Ryujinx.HLE/HOS/Services/Hid/HidServer/HidUtils.cs index 8e2e854fb..d314d0567 100644 --- a/src/Ryujinx.HLE/HOS/Services/Hid/HidServer/HidUtils.cs +++ b/src/Ryujinx.HLE/HOS/Services/Hid/HidServer/HidUtils.cs @@ -42,9 +42,9 @@ namespace Ryujinx.HLE.HOS.Services.Hid.HidServer public static bool IsValidNpadIdType(NpadIdType npadIdType) { - return (npadIdType >= NpadIdType.Player1 && npadIdType <= NpadIdType.Player8) || - npadIdType == NpadIdType.Handheld || - npadIdType == NpadIdType.Unknown; + return npadIdType is >= NpadIdType.Player1 and <= NpadIdType.Player8 or + NpadIdType.Handheld or + NpadIdType.Unknown; } } } diff --git a/src/Ryujinx.HLE/HOS/Services/Hid/IHidServer.cs b/src/Ryujinx.HLE/HOS/Services/Hid/IHidServer.cs index 21288429f..0d2fcaa2a 100644 --- a/src/Ryujinx.HLE/HOS/Services/Hid/IHidServer.cs +++ b/src/Ryujinx.HLE/HOS/Services/Hid/IHidServer.cs @@ -130,7 +130,7 @@ namespace Ryujinx.HLE.HOS.Services.Hid return ResultCode.Success; } - + [CommandCmif(26)] // ActivateDebugMouse(nn::applet::AppletResourceUserId) public ResultCode ActivateDebugMouse(ServiceCtx context) @@ -702,7 +702,7 @@ namespace Ryujinx.HLE.HOS.Services.Hid return ResultCode.Success; } - + [CommandCmif(92)] // SetGestureOutputRanges(pid, ushort Unknown0) public ResultCode SetGestureOutputRanges(ServiceCtx context) @@ -1161,59 +1161,54 @@ namespace Ryujinx.HLE.HOS.Services.Hid NpadStyleIndex deviceType = (NpadStyleIndex)deviceHandle.DeviceType; NpadIdType npadIdType = (NpadIdType)deviceHandle.PlayerId; - if (deviceType < NpadStyleIndex.System || deviceType >= NpadStyleIndex.FullKey) + if (!HidUtils.IsValidNpadIdType(npadIdType)) { - if (!HidUtils.IsValidNpadIdType(npadIdType)) - { - return ResultCode.InvalidNpadIdType; - } - - if (deviceHandle.Position > 1) - { - return ResultCode.InvalidDeviceIndex; - } - - VibrationDeviceType vibrationDeviceType = VibrationDeviceType.None; - - if (Enum.IsDefined(deviceType)) - { - vibrationDeviceType = VibrationDeviceType.LinearResonantActuator; - } - else if ((uint)deviceType == 8) - { - vibrationDeviceType = VibrationDeviceType.GcErm; - } - - VibrationDevicePosition vibrationDevicePosition = VibrationDevicePosition.None; - - if (vibrationDeviceType == VibrationDeviceType.LinearResonantActuator) - { - if (deviceHandle.Position == 0) - { - vibrationDevicePosition = VibrationDevicePosition.Left; - } - else if (deviceHandle.Position == 1) - { - vibrationDevicePosition = VibrationDevicePosition.Right; - } - else - { - throw new InvalidOperationException($"{nameof(deviceHandle.Position)} contains an invalid value: {deviceHandle.Position}"); - } - } - - VibrationDeviceValue deviceInfo = new() - { - DeviceType = vibrationDeviceType, - Position = vibrationDevicePosition, - }; - - context.ResponseData.WriteStruct(deviceInfo); - - return ResultCode.Success; + return ResultCode.InvalidNpadIdType; } - return ResultCode.InvalidNpadDeviceType; + if (deviceHandle.Position > 1) + { + return ResultCode.InvalidDeviceIndex; + } + + VibrationDeviceType vibrationDeviceType = VibrationDeviceType.None; + + if (Enum.IsDefined(deviceType)) + { + vibrationDeviceType = VibrationDeviceType.LinearResonantActuator; + } + else if ((uint)deviceType == 8) + { + vibrationDeviceType = VibrationDeviceType.GcErm; + } + + VibrationDevicePosition vibrationDevicePosition = VibrationDevicePosition.None; + + if (vibrationDeviceType == VibrationDeviceType.LinearResonantActuator) + { + if (deviceHandle.Position == 0) + { + vibrationDevicePosition = VibrationDevicePosition.Left; + } + else if (deviceHandle.Position == 1) + { + vibrationDevicePosition = VibrationDevicePosition.Right; + } + else + { + throw new InvalidOperationException($"{nameof(deviceHandle.Position)} contains an invalid value: {deviceHandle.Position}"); + } + } + + VibrationDeviceValue deviceInfo = new() + { + DeviceType = vibrationDeviceType, + Position = vibrationDevicePosition, + }; + + context.ResponseData.WriteStruct(deviceInfo); + + return ResultCode.Success; } [CommandCmif(201)] diff --git a/src/Ryujinx.HLE/HOS/Services/Hid/IHidbusServer.cs b/src/Ryujinx.HLE/HOS/Services/Hid/IHidbusServer.cs index d6531cc18..5082bddc2 100644 --- a/src/Ryujinx.HLE/HOS/Services/Hid/IHidbusServer.cs +++ b/src/Ryujinx.HLE/HOS/Services/Hid/IHidbusServer.cs @@ -10,9 +10,7 @@ namespace Ryujinx.HLE.HOS.Services.Hid [CommandCmif(1)] // GetBusHandle(nn::hid::NpadIdType, nn::hidbus::BusType, nn::applet::AppletResourceUserId) -> (bool HasHandle, nn::hidbus::BusHandle) -#pragma warning disable CA1822 // Mark member as static public ResultCode GetBusHandle(ServiceCtx context) -#pragma warning restore CA1822 { NpadIdType npadIdType = (NpadIdType)context.RequestData.ReadInt32(); context.RequestData.BaseStream.Position += 4; // Padding diff --git a/src/Ryujinx.HLE/HOS/Services/Hid/Irs/IIrSensorServer.cs b/src/Ryujinx.HLE/HOS/Services/Hid/Irs/IIrSensorServer.cs index 28caf4459..8a30ce066 100644 --- a/src/Ryujinx.HLE/HOS/Services/Hid/Irs/IIrSensorServer.cs +++ b/src/Ryujinx.HLE/HOS/Services/Hid/Irs/IIrSensorServer.cs @@ -172,9 +172,9 @@ namespace Ryujinx.HLE.HOS.Services.Hid.Irs { NpadIdType npadIdType = (NpadIdType)context.RequestData.ReadUInt32(); - if (npadIdType > NpadIdType.Player8 && - npadIdType != NpadIdType.Unknown && - npadIdType != NpadIdType.Handheld) + if (npadIdType is > NpadIdType.Player8 and + not NpadIdType.Unknown and + not NpadIdType.Handheld) { return ResultCode.NpadIdOutOfRange; } diff --git a/src/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/SharedMemory.cs b/src/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/SharedMemory.cs index 59d8f4489..7f3e564fb 100644 --- a/src/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/SharedMemory.cs +++ b/src/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/SharedMemory.cs @@ -45,7 +45,7 @@ namespace Ryujinx.HLE.HOS.Services.Hid.Types.SharedMemory /// [FieldOffset(0x9A00)] public Array10 Npads; - + /// /// Debug mouse. /// diff --git a/src/Ryujinx.HLE/HOS/Services/IpcService.cs b/src/Ryujinx.HLE/HOS/Services/IpcService.cs index de58bb178..4c354ebc6 100644 --- a/src/Ryujinx.HLE/HOS/Services/IpcService.cs +++ b/src/Ryujinx.HLE/HOS/Services/IpcService.cs @@ -26,17 +26,17 @@ namespace Ryujinx.HLE.HOS.Services public IpcService(ServerBase server = null, bool registerTipc = false) { Stopwatch sw = Stopwatch.StartNew(); - + CmifCommands = GetType() .GetMethods(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public) .SelectMany(methodInfo => methodInfo.GetCustomAttributes() .Select(command => (command.Id, methodInfo))) .ToDictionary(command => command.Id, command => command.methodInfo); - + sw.Stop(); - + Logger.Debug?.Print( - LogClass.Emulation, + LogClass.Emulation, $"{CmifCommands.Count} Cmif commands loaded in {sw.ElapsedTicks} ticks ({Stopwatch.Frequency} tps).", GetType().AsPrettyString() ); @@ -50,16 +50,16 @@ namespace Ryujinx.HLE.HOS.Services .SelectMany(methodInfo => methodInfo.GetCustomAttributes() .Select(command => (command.Id, methodInfo))) .ToDictionary(command => command.Id, command => command.methodInfo); - + sw.Stop(); - + Logger.Debug?.Print( - LogClass.Emulation, + LogClass.Emulation, $"{TipcCommands.Count} Tipc commands loaded in {sw.ElapsedTicks} ticks ({Stopwatch.Frequency} tps).", GetType().AsPrettyString() ); } - + Server = server; _parent = this; @@ -202,7 +202,6 @@ namespace Ryujinx.HLE.HOS.Services { string serviceName; - serviceName = (this is not DummyService dummyService) ? GetType().FullName : dummyService.ServiceName; Logger.Warning?.Print(LogClass.KernelIpc, $"Missing service {serviceName}: {commandId} ignored"); diff --git a/src/Ryujinx.HLE/HOS/Services/Ldn/UserServiceCreator/IUserLocalCommunicationService.cs b/src/Ryujinx.HLE/HOS/Services/Ldn/UserServiceCreator/IUserLocalCommunicationService.cs index ef898a611..62a86ad91 100644 --- a/src/Ryujinx.HLE/HOS/Services/Ldn/UserServiceCreator/IUserLocalCommunicationService.cs +++ b/src/Ryujinx.HLE/HOS/Services/Ldn/UserServiceCreator/IUserLocalCommunicationService.cs @@ -175,7 +175,7 @@ namespace Ryujinx.HLE.HOS.Services.Ldn.UserServiceCreator // NOTE: Return ResultCode.InvalidArgument if ip_address and subnet_mask are null, doesn't occur in our case. - if (_state == NetworkState.AccessPointCreated || _state == NetworkState.StationConnected) + if (_state is NetworkState.AccessPointCreated or NetworkState.StationConnected) { ProxyConfig config = _state switch { @@ -522,7 +522,7 @@ namespace Ryujinx.HLE.HOS.Services.Ldn.UserServiceCreator return _nifmResultCode; } - if (_state == NetworkState.AccessPoint || _state == NetworkState.AccessPointCreated) + if (_state is NetworkState.AccessPoint or NetworkState.AccessPointCreated) { DestroyNetworkImpl(DisconnectReason.DestroyedByUser); } @@ -698,12 +698,12 @@ namespace Ryujinx.HLE.HOS.Services.Ldn.UserServiceCreator return _nifmResultCode; } - if (bufferSize == 0 || bufferSize > LdnConst.AdvertiseDataSizeMax) + if (bufferSize is 0 or > LdnConst.AdvertiseDataSizeMax) { return ResultCode.InvalidArgument; } - if (_state == NetworkState.AccessPoint || _state == NetworkState.AccessPointCreated) + if (_state is NetworkState.AccessPoint or NetworkState.AccessPointCreated) { byte[] advertiseData = new byte[bufferSize]; @@ -733,7 +733,7 @@ namespace Ryujinx.HLE.HOS.Services.Ldn.UserServiceCreator return ResultCode.InvalidArgument; } - if (_state == NetworkState.AccessPoint || _state == NetworkState.AccessPointCreated) + if (_state is NetworkState.AccessPoint or NetworkState.AccessPointCreated) { return _accessPoint.SetStationAcceptPolicy(acceptPolicy); } @@ -807,7 +807,7 @@ namespace Ryujinx.HLE.HOS.Services.Ldn.UserServiceCreator return _nifmResultCode; } - if (_state == NetworkState.Station || _state == NetworkState.StationConnected) + if (_state is NetworkState.Station or NetworkState.StationConnected) { DisconnectImpl(DisconnectReason.DisconnectedByUser); } @@ -1089,13 +1089,14 @@ namespace Ryujinx.HLE.HOS.Services.Ldn.UserServiceCreator case MultiplayerMode.LdnRyu: try { - string ldnServer = context.Device.Configuration.MultiplayerLdnServer + string ldnServer = context.Device.Configuration.MultiplayerLdnServer ?? throw new InvalidOperationException("Cannot initialize RyuLDN with a null Multiplayer server."); if (!IPAddress.TryParse(ldnServer, out IPAddress ipAddress)) { ipAddress = Dns.GetHostEntry(ldnServer).AddressList[0]; } + NetworkClient = new LdnMasterProxyClient(ipAddress.ToString(), SharedConstants.LanPlayPort, context.Device.Configuration); } catch (Exception ex) @@ -1104,6 +1105,7 @@ namespace Ryujinx.HLE.HOS.Services.Ldn.UserServiceCreator Logger.Error?.Print(LogClass.ServiceLdn, ex.Message); NetworkClient = new LdnDisabledClient(); } + break; case MultiplayerMode.LdnMitm: NetworkClient = new LdnMitmClient(context.Device.Configuration); diff --git a/src/Ryujinx.HLE/HOS/Services/Ldn/UserServiceCreator/LdnMitm/LanProtocol.cs b/src/Ryujinx.HLE/HOS/Services/Ldn/UserServiceCreator/LdnMitm/LanProtocol.cs index 14142cc4e..a6470d94a 100644 --- a/src/Ryujinx.HLE/HOS/Services/Ldn/UserServiceCreator/LdnMitm/LanProtocol.cs +++ b/src/Ryujinx.HLE/HOS/Services/Ldn/UserServiceCreator/LdnMitm/LanProtocol.cs @@ -59,6 +59,7 @@ namespace Ryujinx.HLE.HOS.Services.Ldn.UserServiceCreator.LdnMitm { Scan?.Invoke(endPoint, LanPacketType.ScanResponse, SpanHelpers.AsSpan(ref _discovery.NetworkInfo).ToArray()); } + break; case LanPacketType.ScanResponse: // UDP diff --git a/src/Ryujinx.HLE/HOS/Services/Ldn/UserServiceCreator/LdnRyu/LdnMasterProxyClient.cs b/src/Ryujinx.HLE/HOS/Services/Ldn/UserServiceCreator/LdnRyu/LdnMasterProxyClient.cs index 91af49d14..f93b1c4cc 100644 --- a/src/Ryujinx.HLE/HOS/Services/Ldn/UserServiceCreator/LdnRyu/LdnMasterProxyClient.cs +++ b/src/Ryujinx.HLE/HOS/Services/Ldn/UserServiceCreator/LdnRyu/LdnMasterProxyClient.cs @@ -179,8 +179,6 @@ namespace Ryujinx.HLE.HOS.Services.Ldn.UserServiceCreator.LdnRyu _error.Set(); } - - private void HandleInitialize(LdnHeader header, InitializeMessage initialize) { InitializeMemory = initialize; diff --git a/src/Ryujinx.HLE/HOS/Services/Ldn/UserServiceCreator/LdnRyu/Proxy/LdnProxy.cs b/src/Ryujinx.HLE/HOS/Services/Ldn/UserServiceCreator/LdnRyu/Proxy/LdnProxy.cs index fa9cbda67..06d46aadc 100644 --- a/src/Ryujinx.HLE/HOS/Services/Ldn/UserServiceCreator/LdnRyu/Proxy/LdnProxy.cs +++ b/src/Ryujinx.HLE/HOS/Services/Ldn/UserServiceCreator/LdnRyu/Proxy/LdnProxy.cs @@ -47,6 +47,7 @@ namespace Ryujinx.HLE.HOS.Services.Ldn.UserServiceCreator.LdnRyu.Proxy { Logger.Error?.PrintMsg(LogClass.ServiceLdn, "Tcp proxy networking is untested. Please report this game so that it can be tested."); } + return domain == AddressFamily.InterNetwork && (protocol == ProtocolType.Tcp || protocol == ProtocolType.Udp); } diff --git a/src/Ryujinx.HLE/HOS/Services/Ldn/UserServiceCreator/LdnRyu/Proxy/LdnProxySocket.cs b/src/Ryujinx.HLE/HOS/Services/Ldn/UserServiceCreator/LdnRyu/Proxy/LdnProxySocket.cs index e792bb91e..4cdb8e8b8 100644 --- a/src/Ryujinx.HLE/HOS/Services/Ldn/UserServiceCreator/LdnRyu/Proxy/LdnProxySocket.cs +++ b/src/Ryujinx.HLE/HOS/Services/Ldn/UserServiceCreator/LdnRyu/Proxy/LdnProxySocket.cs @@ -115,7 +115,6 @@ namespace Ryujinx.HLE.HOS.Services.Ldn.UserServiceCreator.LdnRyu.Proxy return _receiveQueue.Count > 0; } } - } } public bool Writable => Connected || ProtocolType == ProtocolType.Udp; @@ -256,6 +255,7 @@ namespace Ryujinx.HLE.HOS.Services.Ldn.UserServiceCreator.LdnRyu.Proxy { _proxy.ReturnEphemeralPort(ProtocolType, (ushort)((IPEndPoint)LocalEndPoint).Port); } + IPEndPoint asIPEndpoint = (IPEndPoint)localEP; if (asIPEndpoint.Port == 0) { diff --git a/src/Ryujinx.HLE/HOS/Services/Ldn/UserServiceCreator/LdnRyu/Proxy/P2pProxyServer.cs b/src/Ryujinx.HLE/HOS/Services/Ldn/UserServiceCreator/LdnRyu/Proxy/P2pProxyServer.cs index 5e2f59d18..58830c1ce 100644 --- a/src/Ryujinx.HLE/HOS/Services/Ldn/UserServiceCreator/LdnRyu/Proxy/P2pProxyServer.cs +++ b/src/Ryujinx.HLE/HOS/Services/Ldn/UserServiceCreator/LdnRyu/Proxy/P2pProxyServer.cs @@ -156,7 +156,7 @@ namespace Ryujinx.HLE.HOS.Services.Ldn.UserServiceCreator.LdnRyu.Proxy if (_publicPort != 0) { _ = Executor.ExecuteAfterDelayAsync( - PortLeaseRenew.Seconds(), + PortLeaseRenew.Seconds(), _disposedCancellation.Token, RefreshLease); } diff --git a/src/Ryujinx.HLE/HOS/Services/Loader/ResultCode.cs b/src/Ryujinx.HLE/HOS/Services/Loader/ResultCode.cs index 6744563d9..18b267e91 100644 --- a/src/Ryujinx.HLE/HOS/Services/Loader/ResultCode.cs +++ b/src/Ryujinx.HLE/HOS/Services/Loader/ResultCode.cs @@ -2,7 +2,6 @@ using System.Diagnostics.CodeAnalysis; namespace Ryujinx.HLE.HOS.Services.Loader { - [SuppressMessage("Design", "CA1069: Enums values should not be duplicated")] enum ResultCode { ModuleId = 9, diff --git a/src/Ryujinx.HLE/HOS/Services/Mii/MiiDatabaseManager.cs b/src/Ryujinx.HLE/HOS/Services/Mii/MiiDatabaseManager.cs index 23a52d908..356d42a85 100644 --- a/src/Ryujinx.HLE/HOS/Services/Mii/MiiDatabaseManager.cs +++ b/src/Ryujinx.HLE/HOS/Services/Mii/MiiDatabaseManager.cs @@ -124,7 +124,6 @@ namespace Ryujinx.HLE.HOS.Services.Mii } if (_isTestModeEnabled) -#pragma warning disable CS0162 { result = _horizonClient.Fs.CreateSystemSaveData(saveDataId, 0x10000, 0x10000, SaveDataFlags.KeepAfterResettingSystemSaveDataWithoutUserSaveData); @@ -133,7 +132,6 @@ namespace Ryujinx.HLE.HOS.Services.Mii return result; } } -#pragma warning restore CS0162 else { result = _horizonClient.Fs.CreateSystemSaveData(saveDataId, SystemProgramId.Ns.Value, 0x10000, @@ -155,6 +153,7 @@ namespace Ryujinx.HLE.HOS.Services.Mii { _mountCounter++; } + return result; } diff --git a/src/Ryujinx.HLE/HOS/Services/Mii/Types/CharInfo.cs b/src/Ryujinx.HLE/HOS/Services/Mii/Types/CharInfo.cs index 63f44694f..8da856947 100644 --- a/src/Ryujinx.HLE/HOS/Services/Mii/Types/CharInfo.cs +++ b/src/Ryujinx.HLE/HOS/Services/Mii/Types/CharInfo.cs @@ -76,202 +76,252 @@ namespace Ryujinx.HLE.HOS.Services.Mii.Types { return 50; } + if (!Nickname.IsValid()) { return 51; } + if ((byte)FontRegion > 3) { return 23; } + if (FavoriteColor > 11) { return 22; } + if (Gender > Gender.Max) { return 24; } + if ((sbyte)Height < 0) { return 32; } + if ((sbyte)Build < 0) { return 3; } + if (Type > 1) { return 53; } + if (RegionMove > 3) { return 49; } + if (FacelineType > FacelineType.Max) { return 21; } + if (FacelineColor > FacelineColor.Max) { return 18; } + if (FacelineWrinkle > FacelineWrinkle.Max) { return 20; } + if (FacelineMake > FacelineMake.Max) { return 19; } + if (HairType > HairType.Max) { return 31; } + if (HairColor > CommonColor.Max) { return 29; } + if (HairFlip > HairFlip.Max) { return 30; } + if (EyeType > EyeType.Max) { return 8; } + if (EyeColor > CommonColor.Max) { return 5; } + if (EyeScale > 7) { return 7; } + if (EyeAspect > 6) { return 4; } + if (EyeRotate > 7) { return 6; } + if (EyeX > 12) { return 9; } + if (EyeY > 18) { return 10; } + if (EyebrowType > EyebrowType.Max) { return 15; } + if (EyebrowColor > CommonColor.Max) { return 12; } + if (EyebrowScale > 8) { return 14; } + if (EyebrowAspect > 6) { return 11; } + if (EyebrowRotate > 11) { return 13; } + if (EyebrowX > 12) { return 16; } + if (EyebrowY - 3 > 15) { return 17; } + if (NoseType > NoseType.Max) { return 47; } + if (NoseScale > 8) { return 46; } + if (NoseY > 18) { return 48; } + if (MouthType > MouthType.Max) { return 40; } + if (MouthColor > CommonColor.Max) { return 38; } + if (MouthScale > 8) { return 39; } + if (MouthAspect > 6) { return 37; } + if (MouthY > 18) { return 41; } + if (BeardColor > CommonColor.Max) { return 1; } + if (BeardType > BeardType.Max) { return 2; } + if (MustacheType > MustacheType.Max) { return 43; } + if (MustacheScale > 8) { return 42; } + if (MustacheY > 16) { return 44; } + if (GlassType > GlassType.Max) { return 27; } + if (GlassColor > CommonColor.Max) { return 25; } + if (GlassScale > 7) { return 26; } + if (GlassY > 20) { return 28; } + if (MoleType > MoleType.Max) { return 34; } + if (MoleScale > 8) { return 33; } + if (MoleX > 16) { return 35; } + if (MoleY >= 31) { return 36; diff --git a/src/Ryujinx.HLE/HOS/Services/Nfc/AmiiboDecryption/AmiiboBinReader.cs b/src/Ryujinx.HLE/HOS/Services/Nfc/AmiiboDecryption/AmiiboBinReader.cs index 44d164eba..0e11493d5 100644 --- a/src/Ryujinx.HLE/HOS/Services/Nfc/AmiiboDecryption/AmiiboBinReader.cs +++ b/src/Ryujinx.HLE/HOS/Services/Nfc/AmiiboDecryption/AmiiboBinReader.cs @@ -27,14 +27,12 @@ namespace Ryujinx.HLE.HOS.Services.Nfc.AmiiboDecryption return new VirtualAmiiboFile(); } - byte[] initialCounter = new byte[16]; - - const int totalPages = 135; - const int pageSize = 4; - const int totalBytes = totalPages * pageSize; - if (fileBytes.Length == 532) { + int totalPages = 135; + int pageSize = 4; + int totalBytes = totalPages * pageSize; + // add 8 bytes to the end of the file byte[] newFileBytes = new byte[totalBytes]; Array.Copy(fileBytes, newFileBytes, fileBytes.Length); @@ -54,7 +52,6 @@ namespace Ryujinx.HLE.HOS.Services.Nfc.AmiiboDecryption byte[] writeCounter = new byte[2]; byte[] appId = new byte[8]; byte[] settingsBytes = new byte[2]; - byte formData = 0; byte[] applicationAreas = new byte[216]; byte[] dataFull = amiiboDump.GetData(); Logger.Debug?.Print(LogClass.ServiceNfp, $"Data Full Length: {dataFull.Length}"); @@ -94,7 +91,6 @@ namespace Ryujinx.HLE.HOS.Services.Nfc.AmiiboDecryption // Bytes 0 and 1 are amiibo ID, byte 2 is set ID, byte 3 is form data Array.Copy(pageData, 0, amiiboID, 0, 2); setID[0] = pageData[2]; - formData = pageData[3]; break; case 64: case 65: @@ -145,6 +141,7 @@ namespace Ryujinx.HLE.HOS.Services.Nfc.AmiiboDecryption { VirtualAmiibo.ApplicationBytes = applicationAreas; } + VirtualAmiibo.NickName = nickName; return virtualAmiiboFile; } @@ -161,6 +158,7 @@ namespace Ryujinx.HLE.HOS.Services.Nfc.AmiiboDecryption Logger.Error?.Print(LogClass.ServiceNfp, $"Error reading file: {ex.Message}"); return false; } + string keyRetailBinPath = GetKeyRetailBinPath(); if (string.IsNullOrEmpty(keyRetailBinPath)) { @@ -207,6 +205,7 @@ namespace Ryujinx.HLE.HOS.Services.Nfc.AmiiboDecryption Logger.Error?.Print(LogClass.ServiceNfp, "Failed to encrypt data correctly."); return false; } + inputFile = inputFile.Replace("_modified", string.Empty); // Save the encrypted data to file or return it for saving externally string outputFilePath = Path.Combine(Path.GetDirectoryName(inputFile), Path.GetFileNameWithoutExtension(inputFile) + "_modified.bin"); @@ -235,6 +234,7 @@ namespace Ryujinx.HLE.HOS.Services.Nfc.AmiiboDecryption Logger.Error?.Print(LogClass.ServiceNfp, $"Error reading file: {ex.Message}"); return false; } + string keyRetailBinPath = GetKeyRetailBinPath(); if (string.IsNullOrEmpty(keyRetailBinPath)) { @@ -259,6 +259,7 @@ namespace Ryujinx.HLE.HOS.Services.Nfc.AmiiboDecryption Logger.Error?.Print(LogClass.ServiceNfp, "Invalid tag data length. Expected 540 bytes."); return false; } + byte[] encryptedData = amiiboDecryptor.EncryptAmiiboDump(oldData).GetData(); if (encryptedData == null || encryptedData.Length != readBytes.Length) @@ -266,6 +267,7 @@ namespace Ryujinx.HLE.HOS.Services.Nfc.AmiiboDecryption Logger.Error?.Print(LogClass.ServiceNfp, "Failed to encrypt data correctly."); return false; } + inputFile = inputFile.Replace("_modified", string.Empty); // Save the encrypted data to file or return it for saving externally string outputFilePath = Path.Combine(Path.GetDirectoryName(inputFile), Path.GetFileNameWithoutExtension(inputFile) + "_modified.bin"); @@ -316,6 +318,7 @@ namespace Ryujinx.HLE.HOS.Services.Nfc.AmiiboDecryption else crc >>= 1; } + table[i] = crc; } @@ -325,6 +328,7 @@ namespace Ryujinx.HLE.HOS.Services.Nfc.AmiiboDecryption byte index = (byte)((result & 0xFF) ^ b); result = (result >> 8) ^ table[index]; } + return ~result; } @@ -335,17 +339,17 @@ namespace Ryujinx.HLE.HOS.Services.Nfc.AmiiboDecryption public static bool HasAmiiboKeyFile => File.Exists(GetKeyRetailBinPath()); - - public static DateTime DateTimeFromTag(ushort value) + + public static DateTime DateTimeFromTag(ushort dateTimeTag) { try { - int day = value & 0x1F; - int month = (value >> 5) & 0x0F; - int year = (value >> 9) & 0x7F; + int day = dateTimeTag & 0x1F; + int month = (dateTimeTag >> 5) & 0x0F; + int year = (dateTimeTag >> 9) & 0x7F; if (day == 0 || month == 0 || month > 12 || day > DateTime.DaysInMonth(2000 + year, month)) - throw new ArgumentOutOfRangeException(); + throw new ArgumentOutOfRangeException(nameof(dateTimeTag), "Invalid date in tag."); return new DateTime(2000 + year, month, day); } diff --git a/src/Ryujinx.HLE/HOS/Services/Nfc/AmiiboDecryption/AmiiboDump.cs b/src/Ryujinx.HLE/HOS/Services/Nfc/AmiiboDecryption/AmiiboDump.cs index 9873ae1be..5f8d0faaa 100644 --- a/src/Ryujinx.HLE/HOS/Services/Nfc/AmiiboDecryption/AmiiboDump.cs +++ b/src/Ryujinx.HLE/HOS/Services/Nfc/AmiiboDecryption/AmiiboDump.cs @@ -7,11 +7,11 @@ namespace Ryujinx.HLE.HOS.Services.Nfc.AmiiboDecryption { public class AmiiboDump { - private AmiiboMasterKey dataMasterKey; - private AmiiboMasterKey tagMasterKey; + private readonly AmiiboMasterKey dataMasterKey; + private readonly AmiiboMasterKey tagMasterKey; private bool isLocked; - private byte[] data; + private readonly byte[] data; private byte[] hmacTagKey; private byte[] hmacDataKey; private byte[] aesKey; @@ -49,6 +49,7 @@ namespace Ryujinx.HLE.HOS.Services.Nfc.AmiiboDecryption { extract[i] = 0x00; } + seed.AddRange(extract.Take(append)); // Add the magic bytes @@ -70,6 +71,7 @@ namespace Ryujinx.HLE.HOS.Services.Nfc.AmiiboDecryption { paddedUser[i] = (byte)(user[i] ^ key.XorPad[i]); } + seed.AddRange(paddedUser); byte[] seedBytes = seed.ToArray(); @@ -134,9 +136,8 @@ namespace Ryujinx.HLE.HOS.Services.Nfc.AmiiboDecryption private void DeriveKeysAndCipher() { - byte[] discard; // Derive HMAC Tag Key - this.hmacTagKey = DeriveKey(this.tagMasterKey, false, out discard, out discard); + this.hmacTagKey = DeriveKey(this.tagMasterKey, false, out _, out _); // Derive HMAC Data Key and AES Key/IV this.hmacDataKey = DeriveKey(this.dataMasterKey, true, out aesKey, out aesIv); @@ -182,27 +183,25 @@ namespace Ryujinx.HLE.HOS.Services.Nfc.AmiiboDecryption byte[] counter = new byte[blockSize]; Array.Copy(iv, counter, blockSize); - using (ICryptoTransform encryptor = aes.CreateEncryptor()) + using ICryptoTransform encryptor = aes.CreateEncryptor(); + byte[] encryptedCounter = new byte[blockSize]; + + for (int i = 0; i < data.Length; i += blockSize) { - byte[] encryptedCounter = new byte[blockSize]; + // Encrypt the counter + encryptor.TransformBlock(counter, 0, blockSize, encryptedCounter, 0); - for (int i = 0; i < data.Length; i += blockSize) + // Determine the number of bytes to process in this block + int blockLength = Math.Min(blockSize, data.Length - i); + + // XOR the encrypted counter with the plaintext/ciphertext block + for (int j = 0; j < blockLength; j++) { - // Encrypt the counter - encryptor.TransformBlock(counter, 0, blockSize, encryptedCounter, 0); - - // Determine the number of bytes to process in this block - int blockLength = Math.Min(blockSize, data.Length - i); - - // XOR the encrypted counter with the plaintext/ciphertext block - for (int j = 0; j < blockLength; j++) - { - output[i + j] = (byte)(data[i + j] ^ encryptedCounter[j]); - } - - // Increment the counter - IncrementCounter(counter); + output[i + j] = (byte)(data[i + j] ^ encryptedCounter[j]); } + + // Increment the counter + IncrementCounter(counter); } } diff --git a/src/Ryujinx.HLE/HOS/Services/Nfc/Nfp/NfpManager/INfp.cs b/src/Ryujinx.HLE/HOS/Services/Nfc/Nfp/NfpManager/INfp.cs index 3256684f4..ca833e33d 100644 --- a/src/Ryujinx.HLE/HOS/Services/Nfc/Nfp/NfpManager/INfp.cs +++ b/src/Ryujinx.HLE/HOS/Services/Nfc/Nfp/NfpManager/INfp.cs @@ -145,6 +145,7 @@ namespace Ryujinx.HLE.HOS.Services.Nfc.Nfp break; } } + _cancelTokenSource = new CancellationTokenSource(); Task.Run(() => { @@ -196,6 +197,7 @@ namespace Ryujinx.HLE.HOS.Services.Nfc.Nfp break; } } + return ResultCode.Success; } @@ -601,7 +603,7 @@ namespace Ryujinx.HLE.HOS.Services.Nfc.Nfp } else { - if (context.Device.System.NfpDevices[i].State == NfpDeviceState.TagMounted || context.Device.System.NfpDevices[i].State == NfpDeviceState.TagFound) + if (context.Device.System.NfpDevices[i].State is NfpDeviceState.TagMounted or NfpDeviceState.TagFound) { byte[] uuid = VirtualAmiibo.GenerateUuid(context.Device.System.NfpDevices[i].AmiiboId, context.Device.System.NfpDevices[i].UseRandomUuid); @@ -877,6 +879,7 @@ namespace Ryujinx.HLE.HOS.Services.Nfc.Nfp return ResultCode.Success; } } + return ResultCode.DeviceNotFound; } @@ -972,7 +975,7 @@ namespace Ryujinx.HLE.HOS.Services.Nfc.Nfp { // TODO: Find the differencies between IUser and ISystem/IDebug. - if (_permissionLevel == NfpPermissionLevel.Debug || _permissionLevel == NfpPermissionLevel.System) + if (_permissionLevel is NfpPermissionLevel.Debug or NfpPermissionLevel.System) { return GetRegisterInfo(context); } diff --git a/src/Ryujinx.HLE/HOS/Services/Nfc/Nfp/VirtualAmiibo.cs b/src/Ryujinx.HLE/HOS/Services/Nfc/Nfp/VirtualAmiibo.cs index 7e3e4c0a2..63e7eb211 100644 --- a/src/Ryujinx.HLE/HOS/Services/Nfc/Nfp/VirtualAmiibo.cs +++ b/src/Ryujinx.HLE/HOS/Services/Nfc/Nfp/VirtualAmiibo.cs @@ -75,6 +75,7 @@ namespace Ryujinx.HLE.HOS.Services.Nfc.Nfp nickname = NickName; NickName = string.Empty; } + UtilityImpl utilityImpl = new(tickSource); CharInfo charInfo = new(); @@ -109,6 +110,7 @@ namespace Ryujinx.HLE.HOS.Services.Nfc.Nfp AmiiboBinReader.SaveBinFile(InputBin, virtualAmiiboFile.NickName); return; } + SaveAmiiboFile(virtualAmiiboFile); } @@ -139,6 +141,7 @@ namespace Ryujinx.HLE.HOS.Services.Nfc.Nfp ApplicationBytes = []; return bytes; } + VirtualAmiiboFile virtualAmiiboFile = LoadAmiiboFile(amiiboId); foreach (VirtualAmiiboApplicationArea applicationArea in virtualAmiiboFile.ApplicationAreas) @@ -179,6 +182,7 @@ namespace Ryujinx.HLE.HOS.Services.Nfc.Nfp AmiiboBinReader.SaveBinFile(InputBin, applicationAreaData); return; } + VirtualAmiiboFile virtualAmiiboFile = LoadAmiiboFile(amiiboId); if (virtualAmiiboFile.ApplicationAreas.Any(item => item.ApplicationAreaId == OpenedApplicationAreaId)) @@ -246,6 +250,7 @@ namespace Ryujinx.HLE.HOS.Services.Nfc.Nfp return true; } + return File.Exists(Path.Join(AppDataManager.BaseDirPath, "system", "amiibo", $"{virtualAmiiboFile.AmiiboId}.json")); } } diff --git a/src/Ryujinx.HLE/HOS/Services/Nv/NvDrvServices/NvHostChannel/NvHostChannelDeviceFile.cs b/src/Ryujinx.HLE/HOS/Services/Nv/NvDrvServices/NvHostChannel/NvHostChannelDeviceFile.cs index f81c2edef..a114bd3e0 100644 --- a/src/Ryujinx.HLE/HOS/Services/Nv/NvDrvServices/NvHostChannel/NvHostChannelDeviceFile.cs +++ b/src/Ryujinx.HLE/HOS/Services/Nv/NvDrvServices/NvHostChannel/NvHostChannelDeviceFile.cs @@ -400,7 +400,7 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostChannel private NvInternalResult SetTimeslice(ref uint timeslice) { - if (timeslice < 1000 || timeslice > 50000) + if (timeslice is < 1000 or > 50000) { return NvInternalResult.InvalidInput; } @@ -562,7 +562,7 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostChannel private static Host1xContext GetHost1XContext(GpuContext gpu, ulong pid) { - return _host1xContextRegistry.GetOrAdd(pid, (ulong key) => new Host1xContext(gpu, key)); + return _host1xContextRegistry.GetOrAdd(pid, key => new Host1xContext(gpu, key)); } public static void Destroy() diff --git a/src/Ryujinx.HLE/HOS/Services/Nv/NvDrvServices/NvHostCtrl/NvHostCtrlDeviceFile.cs b/src/Ryujinx.HLE/HOS/Services/Nv/NvDrvServices/NvHostCtrl/NvHostCtrlDeviceFile.cs index 471bca73c..6c5dd312f 100644 --- a/src/Ryujinx.HLE/HOS/Services/Nv/NvDrvServices/NvHostCtrl/NvHostCtrlDeviceFile.cs +++ b/src/Ryujinx.HLE/HOS/Services/Nv/NvDrvServices/NvHostCtrl/NvHostCtrlDeviceFile.cs @@ -66,6 +66,7 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostCtrl { configArgument.CopyTo(arguments); } + break; case 0x1c: result = CallIoctlMethod(EventSignal, arguments); @@ -224,7 +225,6 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostCtrl return result; } - } private NvInternalResult EventUnregister(ref uint userEventId) @@ -243,9 +243,9 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostCtrl return NvInternalResult.Success; } - if (hostEvent.State == NvHostEventState.Available || - hostEvent.State == NvHostEventState.Cancelled || - hostEvent.State == NvHostEventState.Signaled) + if (hostEvent.State is NvHostEventState.Available or + NvHostEventState.Cancelled or + NvHostEventState.Signaled) { _events[userEventId].CloseEvent(Context); _events[userEventId] = null; @@ -392,9 +392,9 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostCtrl { lock (hostEvent.Lock) { - if (hostEvent.State == NvHostEventState.Available || - hostEvent.State == NvHostEventState.Signaled || - hostEvent.State == NvHostEventState.Cancelled) + if (hostEvent.State is NvHostEventState.Available or + NvHostEventState.Signaled or + NvHostEventState.Cancelled) { bool timedOut = hostEvent.Wait(_device.Gpu, fence); @@ -456,9 +456,9 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostCtrl if (Event != null) { - if (Event.State == NvHostEventState.Available || - Event.State == NvHostEventState.Signaled || - Event.State == NvHostEventState.Cancelled) + if (Event.State is NvHostEventState.Available or + NvHostEventState.Signaled or + NvHostEventState.Cancelled) { eventIndex = index; diff --git a/src/Ryujinx.HLE/HOS/Services/Nv/NvMemoryAllocator.cs b/src/Ryujinx.HLE/HOS/Services/Nv/NvMemoryAllocator.cs index 3b8840a3d..a5b218b3f 100644 --- a/src/Ryujinx.HLE/HOS/Services/Nv/NvMemoryAllocator.cs +++ b/src/Ryujinx.HLE/HOS/Services/Nv/NvMemoryAllocator.cs @@ -124,6 +124,7 @@ namespace Ryujinx.HLE.HOS.Services.Nv { targetPrevAddress = InvalidAddress; } + node = node.Previous; _tree.Remove(prevAddress); _list.Remove(_dictionary[prevAddress]); @@ -151,6 +152,7 @@ namespace Ryujinx.HLE.HOS.Services.Nv { targetNextAddress = InvalidAddress; } + _tree.Remove(nextAddress); _list.Remove(_dictionary[nextAddress]); _dictionary.Remove(nextAddress); @@ -212,6 +214,7 @@ namespace Ryujinx.HLE.HOS.Services.Nv Logger.Debug?.Print(LogClass.ServiceNv, $"Target address was invalid, set to ceiling of 0x{address:X}; resulted in 0x{targetAddress:X}"); } } + while (address < AddressSpaceSize) { if (targetAddress != InvalidAddress) @@ -278,6 +281,7 @@ namespace Ryujinx.HLE.HOS.Services.Nv } } } + Logger.Debug?.Print(LogClass.ServiceNv, $"No suitable address range found; returning: 0x{InvalidAddress:X}."); freeAddressStartPosition = InvalidAddress; } @@ -303,6 +307,7 @@ namespace Ryujinx.HLE.HOS.Services.Nv return !(gpuVa >= floorAddress && ((gpuVa + size) <= _tree.Get(floorAddress))); } } + return true; } #endregion diff --git a/src/Ryujinx.HLE/HOS/Services/Pctl/ParentalControlServiceFactory/IParentalControlService.cs b/src/Ryujinx.HLE/HOS/Services/Pctl/ParentalControlServiceFactory/IParentalControlService.cs index c6e89b417..c36482e41 100644 --- a/src/Ryujinx.HLE/HOS/Services/Pctl/ParentalControlServiceFactory/IParentalControlService.cs +++ b/src/Ryujinx.HLE/HOS/Services/Pctl/ParentalControlServiceFactory/IParentalControlService.cs @@ -61,7 +61,7 @@ namespace Ryujinx.HLE.HOS.Services.Pctl.ParentalControlServiceFactory { _ratingAge[i] = Convert.ToInt32(context.Device.Processes.ActiveApplication.ApplicationControlProperties.RatingAge[i]); } - + _parentalControlFlag = context.Device.Processes.ActiveApplication.ApplicationControlProperties.ParentalControlFlag; } } @@ -180,7 +180,6 @@ namespace Ryujinx.HLE.HOS.Services.Pctl.ParentalControlServiceFactory #pragma warning disable // Remove unnecessary value assignment bool stereoVisionRestriction = false; -#pragma warning restore IDE0059 if (_stereoVisionRestrictionConfigurable) { diff --git a/src/Ryujinx.HLE/HOS/Services/Ro/IRoInterface.cs b/src/Ryujinx.HLE/HOS/Services/Ro/IRoInterface.cs index 17d0b96ef..873782d87 100644 --- a/src/Ryujinx.HLE/HOS/Services/Ro/IRoInterface.cs +++ b/src/Ryujinx.HLE/HOS/Services/Ro/IRoInterface.cs @@ -259,6 +259,7 @@ namespace Ryujinx.HLE.HOS.Services.Ro return baseAddress + size + GuardPagesSize <= memInfo.Address + memInfo.Size; } } + return false; } @@ -313,7 +314,7 @@ namespace Ryujinx.HLE.HOS.Services.Ro return ResultCode.Success; } - private Result SetNroMemoryPermissions(KProcess process, IExecutable relocatableObject, ulong baseAddress) + private Result SetNroMemoryPermissions(KProcess process, NroExecutable relocatableObject, ulong baseAddress) { ulong textStart = baseAddress + relocatableObject.TextOffset; ulong roStart = baseAddress + relocatableObject.RoOffset; diff --git a/src/Ryujinx.HLE/HOS/Services/Sdb/Pl/SharedFontManager.cs b/src/Ryujinx.HLE/HOS/Services/Sdb/Pl/SharedFontManager.cs index 83e93ec31..f5d3f161d 100644 --- a/src/Ryujinx.HLE/HOS/Services/Sdb/Pl/SharedFontManager.cs +++ b/src/Ryujinx.HLE/HOS/Services/Sdb/Pl/SharedFontManager.cs @@ -5,6 +5,7 @@ using LibHac.FsSystem; using LibHac.Ncm; using LibHac.Tools.FsSystem; using LibHac.Tools.FsSystem.NcaUtils; +using Microsoft.IO; using Ryujinx.Common.Memory; using Ryujinx.HLE.Exceptions; using Ryujinx.HLE.FileSystem; @@ -161,7 +162,7 @@ namespace Ryujinx.HLE.HOS.Services.Sdb.Pl static uint KXor(uint data) => data ^ FontKey; using BinaryReader reader = new(bfttfStream); - using MemoryStream ttfStream = MemoryStreamManager.Shared.GetStream(); + using RecyclableMemoryStream ttfStream = MemoryStreamManager.Shared.GetStream(); using BinaryWriter output = new(ttfStream); if (KXor(reader.ReadUInt32()) != BFTTFMagic) diff --git a/src/Ryujinx.HLE/HOS/Services/ServerBase.cs b/src/Ryujinx.HLE/HOS/Services/ServerBase.cs index 0fd5ab670..dcc01bf38 100644 --- a/src/Ryujinx.HLE/HOS/Services/ServerBase.cs +++ b/src/Ryujinx.HLE/HOS/Services/ServerBase.cs @@ -25,7 +25,7 @@ namespace Ryujinx.HLE.HOS.Services // not large enough. private const int PointerBufferSize = 0x8000; - private static uint[] _defaultCapabilities => [ + private static uint[] DefaultCapabilities => [ (((uint)KScheduler.CpuCoresCount - 1) << 24) + (((uint)KScheduler.CpuCoresCount - 1) << 16) + 0x63F7u, 0x1FFFFFCF, 0x207FFFEF, @@ -47,10 +47,10 @@ namespace Ryujinx.HLE.HOS.Services private readonly Dictionary _sessions = new(); private readonly Dictionary> _ports = new(); - private readonly MemoryStream _requestDataStream; + private readonly RecyclableMemoryStream _requestDataStream; private readonly BinaryReader _requestDataReader; - private readonly MemoryStream _responseDataStream; + private readonly RecyclableMemoryStream _responseDataStream; private readonly BinaryWriter _responseDataWriter; private int _isDisposed = 0; @@ -81,7 +81,7 @@ namespace Ryujinx.HLE.HOS.Services ProcessCreationInfo creationInfo = new("Service", 1, 0, 0x8000000, 1, Flags, 0, 0); - KernelStatic.StartInitialProcess(context, creationInfo, _defaultCapabilities, 44, Main); + KernelStatic.StartInitialProcess(context, creationInfo, DefaultCapabilities, 44, Main); } private void AddPort(int serverPortHandle, Func objectFactory) @@ -353,8 +353,8 @@ namespace Ryujinx.HLE.HOS.Services _requestDataStream.Write(request.RawData); _requestDataStream.Position = 0; - if (request.Type == IpcMessageType.CmifRequest || - request.Type == IpcMessageType.CmifRequestWithContext) + if (request.Type is IpcMessageType.CmifRequest or + IpcMessageType.CmifRequestWithContext) { response.Type = IpcMessageType.CmifResponse; @@ -374,8 +374,8 @@ namespace Ryujinx.HLE.HOS.Services response.RawData = _responseDataStream.ToArray(); } - else if (request.Type == IpcMessageType.CmifControl || - request.Type == IpcMessageType.CmifControlWithContext) + else if (request.Type is IpcMessageType.CmifControl or + IpcMessageType.CmifControlWithContext) { #pragma warning disable IDE0059 // Remove unnecessary value assignment uint magic = (uint)_requestDataReader.ReadUInt64(); @@ -425,7 +425,7 @@ namespace Ryujinx.HLE.HOS.Services throw new NotImplementedException(cmdId.ToString()); } } - else if (request.Type == IpcMessageType.CmifCloseSession || request.Type == IpcMessageType.TipcCloseSession) + else if (request.Type is IpcMessageType.CmifCloseSession or IpcMessageType.TipcCloseSession) { DestroySession(serverSessionHandle); shouldReply = false; diff --git a/src/Ryujinx.HLE/HOS/Services/Settings/ISettingsServer.cs b/src/Ryujinx.HLE/HOS/Services/Settings/ISettingsServer.cs index abb9b6d8e..fef994bf8 100644 --- a/src/Ryujinx.HLE/HOS/Services/Settings/ISettingsServer.cs +++ b/src/Ryujinx.HLE/HOS/Services/Settings/ISettingsServer.cs @@ -63,7 +63,7 @@ namespace Ryujinx.HLE.HOS.Services.Settings RegionCode regionCode = (RegionCode)context.Device.System.State.DesiredRegionCode; - if (regionCode < RegionCode.Min || regionCode > RegionCode.Max) + if (regionCode is < RegionCode.Min or > RegionCode.Max) { regionCode = RegionCode.USA; } diff --git a/src/Ryujinx.HLE/HOS/Services/Sm/IUserInterface.cs b/src/Ryujinx.HLE/HOS/Services/Sm/IUserInterface.cs index af511af29..f19eeebfc 100644 --- a/src/Ryujinx.HLE/HOS/Services/Sm/IUserInterface.cs +++ b/src/Ryujinx.HLE/HOS/Services/Sm/IUserInterface.cs @@ -242,7 +242,7 @@ namespace Ryujinx.HLE.HOS.Services.Sm { byte chr = context.RequestData.ReadByte(); - if (chr >= 0x20 && chr < 0x7f) + if (chr is >= 0x20 and < 0x7f) { nameBuilder.Append((char)chr); } diff --git a/src/Ryujinx.HLE/HOS/Services/Sockets/Bsd/IClient.cs b/src/Ryujinx.HLE/HOS/Services/Sockets/Bsd/IClient.cs index d4beb066c..a23bd3a11 100644 --- a/src/Ryujinx.HLE/HOS/Services/Sockets/Bsd/IClient.cs +++ b/src/Ryujinx.HLE/HOS/Services/Sockets/Bsd/IClient.cs @@ -38,6 +38,7 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd { Logger.Warning?.Print(LogClass.ServiceBsd, $"Operation failed with error {errorCode}."); } + result = -1; } @@ -102,7 +103,7 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd } LinuxError errno = LinuxError.SUCCESS; - ISocket newBsdSocket; + ManagedSocket newBsdSocket; try { @@ -412,7 +413,7 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd { static bool IsUnexpectedLinuxError(LinuxError error) { - return error != LinuxError.SUCCESS && error != LinuxError.ETIMEDOUT; + return error is not LinuxError.SUCCESS and not LinuxError.ETIMEDOUT; } // Hybrid approach @@ -817,7 +818,7 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd { Logger.Warning?.PrintMsg(LogClass.ServiceBsd, $"Invalid socket fd '{socketFd}'."); } - + return WriteBsdResult(context, 0, errno); } @@ -933,7 +934,7 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd { errno = LinuxError.EINVAL; - if (how >= 0 && how <= 2) + if (how is >= 0 and <= 2) { errno = socket.Shutdown((BsdSocketShutdownFlags)how); } @@ -950,7 +951,7 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd LinuxError errno = LinuxError.EINVAL; - if (how >= 0 && how <= 2) + if (how is >= 0 and <= 2) { errno = _context.ShutdownAllSockets((BsdSocketShutdownFlags)how); } @@ -1057,7 +1058,6 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd return WriteBsdResult(context, newSockFd, errno); } - [CommandCmif(29)] // 7.0.0+ // RecvMMsg(u32 fd, u32 vlen, u32 flags, u32 reserved, nn::socket::TimeVal timeout) -> (i32 ret, u32 bsd_errno, buffer message); public ResultCode RecvMMsg(ServiceCtx context) diff --git a/src/Ryujinx.HLE/HOS/Services/Sockets/Bsd/Impl/EventFileDescriptorPollManager.cs b/src/Ryujinx.HLE/HOS/Services/Sockets/Bsd/Impl/EventFileDescriptorPollManager.cs index 99e3abdf8..627e9838b 100644 --- a/src/Ryujinx.HLE/HOS/Services/Sockets/Bsd/Impl/EventFileDescriptorPollManager.cs +++ b/src/Ryujinx.HLE/HOS/Services/Sockets/Bsd/Impl/EventFileDescriptorPollManager.cs @@ -45,6 +45,7 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd.Impl isValidEvent = true; } + if (evnt.Data.InputEvents.HasFlag(PollEventTypeMask.Output)) { waiters.Add(socket.WriteEvent); @@ -91,7 +92,6 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd.Impl outputEvents |= PollEventTypeMask.Output; } - if (outputEvents != 0) { evnt.Data.OutputEvents = outputEvents; diff --git a/src/Ryujinx.HLE/HOS/Services/Sockets/Bsd/Impl/ManagedSocket.cs b/src/Ryujinx.HLE/HOS/Services/Sockets/Bsd/Impl/ManagedSocket.cs index 3c367660a..684e06598 100644 --- a/src/Ryujinx.HLE/HOS/Services/Sockets/Bsd/Impl/ManagedSocket.cs +++ b/src/Ryujinx.HLE/HOS/Services/Sockets/Bsd/Impl/ManagedSocket.cs @@ -109,6 +109,7 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd.Impl { Logger.Warning?.Print(LogClass.ServiceBsd, $"Socket Exception: {exception}"); } + return WinSockHelper.ConvertError((WsaError)exception.ErrorCode); } } @@ -128,6 +129,7 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd.Impl { Logger.Warning?.Print(LogClass.ServiceBsd, $"Socket Exception: {exception}"); } + return WinSockHelper.ConvertError((WsaError)exception.ErrorCode); } } @@ -148,6 +150,7 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd.Impl { Logger.Info?.PrintMsg(LogClass.ServiceBsd, $"Connecting to: {ProtocolType}/***:{remoteEndPoint.Port}"); } + try { Socket.Connect(remoteEndPoint); @@ -166,6 +169,7 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd.Impl { Logger.Warning?.Print(LogClass.ServiceBsd, $"Socket Exception: {exception}"); } + return WinSockHelper.ConvertError((WsaError)exception.ErrorCode); } } @@ -200,6 +204,7 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd.Impl { Logger.Warning?.Print(LogClass.ServiceBsd, $"Socket Exception: {exception}"); } + return WinSockHelper.ConvertError((WsaError)exception.ErrorCode); } } @@ -223,6 +228,7 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd.Impl { Logger.Warning?.Print(LogClass.ServiceBsd, $"Socket Exception: {exception}"); } + return WinSockHelper.ConvertError((WsaError)exception.ErrorCode); } } @@ -259,6 +265,7 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd.Impl { Logger.Warning?.Print(LogClass.ServiceBsd, $"Socket Exception: {exception}"); } + receiveSize = -1; result = WinSockHelper.ConvertError((WsaError)exception.ErrorCode); @@ -314,6 +321,7 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd.Impl { Logger.Warning?.Print(LogClass.ServiceBsd, $"Socket Exception: {exception}"); } + receiveSize = -1; result = WinSockHelper.ConvertError((WsaError)exception.ErrorCode); @@ -341,6 +349,7 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd.Impl { Logger.Warning?.Print(LogClass.ServiceBsd, $"Socket Exception: {exception}"); } + sendSize = -1; return WinSockHelper.ConvertError((WsaError)exception.ErrorCode); @@ -361,6 +370,7 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd.Impl { Logger.Warning?.Print(LogClass.ServiceBsd, $"Socket Exception: {exception}"); } + sendSize = -1; return WinSockHelper.ConvertError((WsaError)exception.ErrorCode); @@ -402,6 +412,7 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd.Impl { Logger.Warning?.Print(LogClass.ServiceBsd, $"Socket Exception: {exception}"); } + return WinSockHelper.ConvertError((WsaError)exception.ErrorCode); } } @@ -452,6 +463,7 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd.Impl { Logger.Warning?.Print(LogClass.ServiceBsd, $"Socket Exception: {exception}"); } + return WinSockHelper.ConvertError((WsaError)exception.ErrorCode); } } @@ -480,7 +492,7 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd.Impl return true; } - private static IList> ConvertMessagesToBuffer(BsdMMsgHdr message) + private static ArraySegment[] ConvertMessagesToBuffer(BsdMMsgHdr message) { int segmentCount = 0; int index = 0; @@ -588,6 +600,7 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd.Impl { Logger.Warning?.Print(LogClass.ServiceBsd, $"Socket Exception: {exception}"); } + return WinSockHelper.ConvertError((WsaError)exception.ErrorCode); } } @@ -630,6 +643,7 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd.Impl { Logger.Warning?.Print(LogClass.ServiceBsd, $"Socket Exception: {exception}"); } + return WinSockHelper.ConvertError((WsaError)exception.ErrorCode); } } diff --git a/src/Ryujinx.HLE/HOS/Services/Sockets/Bsd/Impl/WSAError.cs b/src/Ryujinx.HLE/HOS/Services/Sockets/Bsd/Impl/WSAError.cs index cd8e530c7..92a013d19 100644 --- a/src/Ryujinx.HLE/HOS/Services/Sockets/Bsd/Impl/WSAError.cs +++ b/src/Ryujinx.HLE/HOS/Services/Sockets/Bsd/Impl/WSAError.cs @@ -2,7 +2,6 @@ using System.Diagnostics.CodeAnalysis; namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd.Impl { - [SuppressMessage("ReSharper", "InconsistentNaming")] enum WsaError { /* diff --git a/src/Ryujinx.HLE/HOS/Services/Sockets/Bsd/Proxy/SocketHelpers.cs b/src/Ryujinx.HLE/HOS/Services/Sockets/Bsd/Proxy/SocketHelpers.cs index 660803714..e6d5f849b 100644 --- a/src/Ryujinx.HLE/HOS/Services/Sockets/Bsd/Proxy/SocketHelpers.cs +++ b/src/Ryujinx.HLE/HOS/Services/Sockets/Bsd/Proxy/SocketHelpers.cs @@ -36,7 +36,7 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd.Proxy throw new NotImplementedException(); } }); - }; + } FilterSockets(readEvents, readDefault, (socket) => socket.Readable); FilterSockets(writeEvents, writeDefault, (socket) => socket.Writable); @@ -77,6 +77,7 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd.Proxy { Logger.Info?.PrintMsg(LogClass.ServiceBsd, $"Opening socket using host networking stack"); } + return new DefaultSocket(domain, type, protocol, lanInterfaceId); } } diff --git a/src/Ryujinx.HLE/HOS/Services/Sockets/Bsd/Types/BsdSocketOption.cs b/src/Ryujinx.HLE/HOS/Services/Sockets/Bsd/Types/BsdSocketOption.cs index 5bc3e81f4..c275f3ba5 100644 --- a/src/Ryujinx.HLE/HOS/Services/Sockets/Bsd/Types/BsdSocketOption.cs +++ b/src/Ryujinx.HLE/HOS/Services/Sockets/Bsd/Types/BsdSocketOption.cs @@ -2,7 +2,6 @@ using System.Diagnostics.CodeAnalysis; namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd.Types { - [SuppressMessage("Design", "CA1069: Enums values should not be duplicated")] enum BsdSocketOption { SoDebug = 0x1, diff --git a/src/Ryujinx.HLE/HOS/Services/Sockets/Bsd/Types/LinuxError.cs b/src/Ryujinx.HLE/HOS/Services/Sockets/Bsd/Types/LinuxError.cs index aaeee44d1..1219d1476 100644 --- a/src/Ryujinx.HLE/HOS/Services/Sockets/Bsd/Types/LinuxError.cs +++ b/src/Ryujinx.HLE/HOS/Services/Sockets/Bsd/Types/LinuxError.cs @@ -2,7 +2,6 @@ using System.Diagnostics.CodeAnalysis; namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd.Types { - [SuppressMessage("ReSharper", "InconsistentNaming")] enum LinuxError { SUCCESS = 0, diff --git a/src/Ryujinx.HLE/HOS/Services/Sockets/Nsd/IManager.cs b/src/Ryujinx.HLE/HOS/Services/Sockets/Nsd/IManager.cs index 0c1fa3a9f..9e13a005c 100644 --- a/src/Ryujinx.HLE/HOS/Services/Sockets/Nsd/IManager.cs +++ b/src/Ryujinx.HLE/HOS/Services/Sockets/Nsd/IManager.cs @@ -14,10 +14,7 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Nsd class IManager : IpcService { public static readonly NsdSettings NsdSettings; -#pragma warning disable IDE0052 // Remove unread private member private readonly FqdnResolver _fqdnResolver; -#pragma warning restore IDE0052 - private readonly bool _isInitialized = false; public IManager(ServiceCtx context) diff --git a/src/Ryujinx.HLE/HOS/Services/Sockets/Nsd/Manager/FqdnResolver.cs b/src/Ryujinx.HLE/HOS/Services/Sockets/Nsd/Manager/FqdnResolver.cs index 3ff48b883..2666bfa6d 100644 --- a/src/Ryujinx.HLE/HOS/Services/Sockets/Nsd/Manager/FqdnResolver.cs +++ b/src/Ryujinx.HLE/HOS/Services/Sockets/Nsd/Manager/FqdnResolver.cs @@ -24,10 +24,10 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Nsd.Manager public static ResultCode Resolve(string address, out string resolvedAddress) { - if (address == "api.sect.srv.nintendo.net" || - address == "ctest.cdn.nintendo.net" || - address == "ctest.cdn.n.nintendoswitch.cn" || - address == "unknown.dummy.nintendo.net") + if (address is "api.sect.srv.nintendo.net" or + "ctest.cdn.nintendo.net" or + "ctest.cdn.n.nintendoswitch.cn" or + "unknown.dummy.nintendo.net") { resolvedAddress = address; } diff --git a/src/Ryujinx.HLE/HOS/Services/Spl/IGeneralInterface.cs b/src/Ryujinx.HLE/HOS/Services/Spl/IGeneralInterface.cs index ade67b9c0..301d415a0 100644 --- a/src/Ryujinx.HLE/HOS/Services/Spl/IGeneralInterface.cs +++ b/src/Ryujinx.HLE/HOS/Services/Spl/IGeneralInterface.cs @@ -84,6 +84,7 @@ namespace Ryujinx.HLE.HOS.Services.Spl { configValue = (ulong)DramId.IcosaSamsung4GiB; } + break; case ConfigItem.SecurityEngineInterruptNumber: return SmcResult.NotImplemented; diff --git a/src/Ryujinx.HLE/HOS/Services/Ssl/ISslService.cs b/src/Ryujinx.HLE/HOS/Services/Ssl/ISslService.cs index 17fde279c..8f38f293f 100644 --- a/src/Ryujinx.HLE/HOS/Services/Ssl/ISslService.cs +++ b/src/Ryujinx.HLE/HOS/Services/Ssl/ISslService.cs @@ -124,7 +124,7 @@ namespace Ryujinx.HLE.HOS.Services.Ssl return ResultCode.Success; } - + [CommandCmif(100)] // CreateContextForSystem(u64 pid, nn::ssl::sf::SslVersion, u64) public ResultCode CreateContextForSystem(ServiceCtx context) @@ -132,23 +132,23 @@ namespace Ryujinx.HLE.HOS.Services.Ssl ulong pid = context.RequestData.ReadUInt64(); SslVersion sslVersion = (SslVersion)context.RequestData.ReadUInt32(); ulong pidPlaceholder = context.RequestData.ReadUInt64(); - + Logger.Stub?.PrintStub(LogClass.ServiceSsl, new { pid, sslVersion, pidPlaceholder }); return ResultCode.Success; } - + [CommandCmif(101)] // SetThreadCoreMask(u64 mask) public ResultCode SetThreadCoreMask(ServiceCtx context) { ulong mask = context.RequestData.ReadUInt64(); - + Logger.Stub?.PrintStub(LogClass.ServiceSsl, new { mask }); return ResultCode.Success; } - + [CommandCmif(102)] // GetThreadCoreMask() -> u64 public ResultCode GetThreadCoreMask(ServiceCtx context) @@ -157,7 +157,7 @@ namespace Ryujinx.HLE.HOS.Services.Ssl return ResultCode.Success; } - + [CommandCmif(103)] // VerifySignature(buffer<0x5> unknownInput1, buffer<0x5> unknownInput2, buffer<0x5> unknownInput3, buffer unknown1) public ResultCode VerifySignature(ServiceCtx context) diff --git a/src/Ryujinx.HLE/HOS/Services/Ssl/SslService/ISslConnection.cs b/src/Ryujinx.HLE/HOS/Services/Ssl/SslService/ISslConnection.cs index 92e73f9f1..623990a58 100644 --- a/src/Ryujinx.HLE/HOS/Services/Ssl/SslService/ISslConnection.cs +++ b/src/Ryujinx.HLE/HOS/Services/Ssl/SslService/ISslConnection.cs @@ -21,7 +21,7 @@ namespace Ryujinx.HLE.HOS.Services.Ssl.SslService private SessionCacheMode _sessionCacheMode; private string _hostName; - private ISslConnectionBase _connection; + private SslManagedSocketConnection _connection; private BsdContext _bsdContext; private readonly ulong _processId; @@ -296,7 +296,6 @@ namespace Ryujinx.HLE.HOS.Services.Ssl.SslService using WritableRegion region = context.Memory.GetWritableRegion(context.Request.ReceiveBuff[0].Position, (int)context.Request.ReceiveBuff[0].Size); - // TODO: Better error management. result = _connection.Peek(out int peekCount, region.Memory); diff --git a/src/Ryujinx.HLE/HOS/Services/SurfaceFlinger/BufferQueueConsumer.cs b/src/Ryujinx.HLE/HOS/Services/SurfaceFlinger/BufferQueueConsumer.cs index 74afa989d..68560240b 100644 --- a/src/Ryujinx.HLE/HOS/Services/SurfaceFlinger/BufferQueueConsumer.cs +++ b/src/Ryujinx.HLE/HOS/Services/SurfaceFlinger/BufferQueueConsumer.cs @@ -336,7 +336,7 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger public Status SetMaxAcquiredBufferCount(int maxAcquiredBufferCount) { - if (maxAcquiredBufferCount < 0 || maxAcquiredBufferCount > BufferSlotArray.MaxAcquiredBuffers) + if (maxAcquiredBufferCount is < 0 or > BufferSlotArray.MaxAcquiredBuffers) { return Status.BadValue; } diff --git a/src/Ryujinx.HLE/HOS/Services/SurfaceFlinger/BufferQueueCore.cs b/src/Ryujinx.HLE/HOS/Services/SurfaceFlinger/BufferQueueCore.cs index 770149489..8399c6d67 100644 --- a/src/Ryujinx.HLE/HOS/Services/SurfaceFlinger/BufferQueueCore.cs +++ b/src/Ryujinx.HLE/HOS/Services/SurfaceFlinger/BufferQueueCore.cs @@ -126,7 +126,7 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger { BufferState state = Slots[slot].BufferState; - if (state == BufferState.Queued || state == BufferState.Dequeued) + if (state is BufferState.Queued or BufferState.Dequeued) { maxBufferCount = slot + 1; } diff --git a/src/Ryujinx.HLE/HOS/Services/SurfaceFlinger/BufferQueueProducer.cs b/src/Ryujinx.HLE/HOS/Services/SurfaceFlinger/BufferQueueProducer.cs index ae61d0bf7..9afb26c65 100644 --- a/src/Ryujinx.HLE/HOS/Services/SurfaceFlinger/BufferQueueProducer.cs +++ b/src/Ryujinx.HLE/HOS/Services/SurfaceFlinger/BufferQueueProducer.cs @@ -636,6 +636,7 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger status = Status.Success; } + break; } } @@ -758,7 +759,6 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger return Status.BadValue; } - if (maxBufferCount < Core.MaxBufferCountCached) { for (int slot = maxBufferCount; slot < Core.MaxBufferCountCached; slot++) @@ -791,6 +791,7 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger { freeSlot = slot; } + break; default: break; diff --git a/src/Ryujinx.HLE/HOS/Services/SurfaceFlinger/Status.cs b/src/Ryujinx.HLE/HOS/Services/SurfaceFlinger/Status.cs index 14f80fa90..0c69bf573 100644 --- a/src/Ryujinx.HLE/HOS/Services/SurfaceFlinger/Status.cs +++ b/src/Ryujinx.HLE/HOS/Services/SurfaceFlinger/Status.cs @@ -2,7 +2,6 @@ using System.Diagnostics.CodeAnalysis; namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger { - [SuppressMessage("Design", "CA1069: Enums values should not be duplicated")] enum Status { Success = 0, diff --git a/src/Ryujinx.HLE/HOS/Services/SurfaceFlinger/SurfaceFlinger.cs b/src/Ryujinx.HLE/HOS/Services/SurfaceFlinger/SurfaceFlinger.cs index 294192363..8acc4d756 100644 --- a/src/Ryujinx.HLE/HOS/Services/SurfaceFlinger/SurfaceFlinger.cs +++ b/src/Ryujinx.HLE/HOS/Services/SurfaceFlinger/SurfaceFlinger.cs @@ -189,7 +189,7 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger return Vi.ResultCode.InvalidValue; } - if (layer.State != LayerState.ManagedClosed && layer.State != LayerState.ManagedOpened) + if (layer.State is not LayerState.ManagedClosed and not LayerState.ManagedOpened) { Logger.Error?.Print(LogClass.SurfaceFlinger, $"Failed to destroy managed layer {layerId} (permission denied)"); @@ -393,7 +393,7 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger PostFrameBuffer(layer, item); } - else if (acquireStatus != Status.NoBufferAvailaible && acquireStatus != Status.InvalidOperation) + else if (acquireStatus is not Status.NoBufferAvailaible and not Status.InvalidOperation) { throw new InvalidOperationException(); } @@ -421,8 +421,8 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger Format format = ConvertColorFormat(item.GraphicBuffer.Object.Buffer.Surfaces[0].ColorFormat); byte bytesPerPixel = - format == Format.B5G6R5Unorm || - format == Format.R4G4B4A4Unorm ? (byte)2 : (byte)4; + format is Format.B5G6R5Unorm or + Format.R4G4B4A4Unorm ? (byte)2 : (byte)4; int gobBlocksInY = 1 << item.GraphicBuffer.Object.Buffer.Surfaces[0].BlockHeightLog2; diff --git a/src/Ryujinx.HLE/HOS/Services/SurfaceFlinger/Types/AndroidFence.cs b/src/Ryujinx.HLE/HOS/Services/SurfaceFlinger/Types/AndroidFence.cs index ebc6501ae..42dd4ed26 100644 --- a/src/Ryujinx.HLE/HOS/Services/SurfaceFlinger/Types/AndroidFence.cs +++ b/src/Ryujinx.HLE/HOS/Services/SurfaceFlinger/Types/AndroidFence.cs @@ -49,7 +49,6 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger Logger.Error?.Print(LogClass.SurfaceFlinger, "Android fence didn't signal in 3000 ms"); Wait(gpuContext, Timeout.InfiniteTimeSpan); } - } public bool Wait(GpuContext gpuContext, TimeSpan timeout) diff --git a/src/Ryujinx.HLE/HOS/Services/SurfaceFlinger/Types/Color/ColorFormat.cs b/src/Ryujinx.HLE/HOS/Services/SurfaceFlinger/Types/Color/ColorFormat.cs index 2512393c5..b26fb15d1 100644 --- a/src/Ryujinx.HLE/HOS/Services/SurfaceFlinger/Types/Color/ColorFormat.cs +++ b/src/Ryujinx.HLE/HOS/Services/SurfaceFlinger/Types/Color/ColorFormat.cs @@ -2,7 +2,6 @@ using System.Diagnostics.CodeAnalysis; namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger { - [SuppressMessage("Design", "CA1069: Enums values should not be duplicated")] enum ColorFormat : ulong { #pragma warning disable IDE0055 // Disable formatting diff --git a/src/Ryujinx.HLE/HOS/Services/Time/Clock/Types/ClockSnapshot.cs b/src/Ryujinx.HLE/HOS/Services/Time/Clock/Types/ClockSnapshot.cs index 4383fc823..7d918f5e3 100644 --- a/src/Ryujinx.HLE/HOS/Services/Time/Clock/Types/ClockSnapshot.cs +++ b/src/Ryujinx.HLE/HOS/Services/Time/Clock/Types/ClockSnapshot.cs @@ -26,7 +26,6 @@ namespace Ryujinx.HLE.HOS.Services.Time.Clock public byte Type; public ushort Unknown; - [StructLayout(LayoutKind.Sequential, Pack = 1, Size = Size)] private struct LocationNameStorageHolder { diff --git a/src/Ryujinx.HLE/HOS/Services/Time/ResultCode.cs b/src/Ryujinx.HLE/HOS/Services/Time/ResultCode.cs index 74a57f20b..ded2c3175 100644 --- a/src/Ryujinx.HLE/HOS/Services/Time/ResultCode.cs +++ b/src/Ryujinx.HLE/HOS/Services/Time/ResultCode.cs @@ -2,7 +2,6 @@ using System.Diagnostics.CodeAnalysis; namespace Ryujinx.HLE.HOS.Services.Time { - [SuppressMessage("Design", "CA1069: Enums values should not be duplicated")] public enum ResultCode { ModuleId = 116, diff --git a/src/Ryujinx.HLE/HOS/Services/Time/TimeZone/TimeZone.cs b/src/Ryujinx.HLE/HOS/Services/Time/TimeZone/TimeZone.cs index 819599171..dfacc8170 100644 --- a/src/Ryujinx.HLE/HOS/Services/Time/TimeZone/TimeZone.cs +++ b/src/Ryujinx.HLE/HOS/Services/Time/TimeZone/TimeZone.cs @@ -222,7 +222,6 @@ namespace Ryujinx.HLE.HOS.Services.Time.TimeZone { seconds = 0; - bool isValid = GetNum(name, ref namePosition, out int num, 0, HoursPerDays * DaysPerWeek - 1); if (!isValid) { @@ -264,6 +263,7 @@ namespace Ryujinx.HLE.HOS.Services.Time.TimeZone seconds += num; } } + return true; } @@ -486,7 +486,7 @@ namespace Ryujinx.HLE.HOS.Services.Time.TimeZone return false; } - if (name[namePosition] != '\0' && name[namePosition] != ',' && name[namePosition] != ';') + if (name[namePosition] is not (byte)'\0' and not (byte)',' and not (byte)';') { bool isValid = GetOffset(name.ToArray(), ref namePosition, ref dstOffset); @@ -506,7 +506,7 @@ namespace Ryujinx.HLE.HOS.Services.Time.TimeZone namePosition = 0; } - if (name[namePosition] == ',' || name[namePosition] == ';') + if (name[namePosition] is (byte)',' or (byte)';') { namePosition++; @@ -744,6 +744,7 @@ namespace Ryujinx.HLE.HOS.Services.Time.TimeZone { outRules.Chars[charsPosition + i] = destName[i]; } + outRules.Chars[charsPosition + destLen] = 0; } @@ -763,6 +764,7 @@ namespace Ryujinx.HLE.HOS.Services.Time.TimeZone { value += SecondsPerDay; } + break; case RuleType.DayOfYear: @@ -923,7 +925,6 @@ namespace Ryujinx.HLE.HOS.Services.Time.TimeZone return false; } - if (streamLength < (timeCount * TimeTypeSize + timeCount + typeCount * 6 @@ -1051,7 +1052,6 @@ namespace Ryujinx.HLE.HOS.Services.Time.TimeZone outRules.Ttis[i].IsGMT = p[0] != 0; p = p[1..]; } - } long position = (workBuffer.Length - p.Length); @@ -1554,7 +1554,7 @@ namespace Ryujinx.HLE.HOS.Services.Time.TimeZone int savedSeconds; - if (calendarTime.Second >= 0 && calendarTime.Second < SecondsPerMinute) + if (calendarTime.Second is >= 0 and < SecondsPerMinute) { savedSeconds = 0; } diff --git a/src/Ryujinx.HLE/HOS/Services/Time/TimeZone/TimeZoneContentManager.cs b/src/Ryujinx.HLE/HOS/Services/Time/TimeZone/TimeZoneContentManager.cs index 7ca367106..764fb5104 100644 --- a/src/Ryujinx.HLE/HOS/Services/Time/TimeZone/TimeZoneContentManager.cs +++ b/src/Ryujinx.HLE/HOS/Services/Time/TimeZone/TimeZoneContentManager.cs @@ -152,7 +152,6 @@ namespace Ryujinx.HLE.HOS.Services.Time.TimeZone TimeZone.ParseTimeZoneBinary(ref tzRule, tzif.Get.AsStream()); - TimeTypeInfo ttInfo; if (tzRule.TimeCount > 0) // Find the current transition period { @@ -164,6 +163,7 @@ namespace Ryujinx.HLE.HOS.Services.Time.TimeZone fin = i; } } + ttInfo = tzRule.Ttis[tzRule.Types[fin]]; } else if (tzRule.TypeCount >= 1) // Otherwise, use the first offset in TTInfo diff --git a/src/Ryujinx.HLE/HOS/Services/Vi/RootService/ApplicationDisplayService/IManagerDisplayService.cs b/src/Ryujinx.HLE/HOS/Services/Vi/RootService/ApplicationDisplayService/IManagerDisplayService.cs index 3a08cdd78..0e5d103d1 100644 --- a/src/Ryujinx.HLE/HOS/Services/Vi/RootService/ApplicationDisplayService/IManagerDisplayService.cs +++ b/src/Ryujinx.HLE/HOS/Services/Vi/RootService/ApplicationDisplayService/IManagerDisplayService.cs @@ -4,9 +4,7 @@ namespace Ryujinx.HLE.HOS.Services.Vi.RootService.ApplicationDisplayService { class IManagerDisplayService : IpcService { -#pragma warning disable IDE0052 // Remove unread private member private readonly IApplicationDisplayService _applicationDisplayService; -#pragma warning restore IDE0052 public IManagerDisplayService(IApplicationDisplayService applicationDisplayService) { diff --git a/src/Ryujinx.HLE/HOS/Services/Vi/RootService/ApplicationDisplayService/ISystemDisplayService.cs b/src/Ryujinx.HLE/HOS/Services/Vi/RootService/ApplicationDisplayService/ISystemDisplayService.cs index 12ac2cf4a..507290692 100644 --- a/src/Ryujinx.HLE/HOS/Services/Vi/RootService/ApplicationDisplayService/ISystemDisplayService.cs +++ b/src/Ryujinx.HLE/HOS/Services/Vi/RootService/ApplicationDisplayService/ISystemDisplayService.cs @@ -4,9 +4,7 @@ namespace Ryujinx.HLE.HOS.Services.Vi.RootService.ApplicationDisplayService { class ISystemDisplayService : IpcService { -#pragma warning disable IDE0052 // Remove unread private member private readonly IApplicationDisplayService _applicationDisplayService; -#pragma warning restore IDE0052 public ISystemDisplayService(IApplicationDisplayService applicationDisplayService) { diff --git a/src/Ryujinx.HLE/HOS/Services/Vi/RootService/IApplicationDisplayService.cs b/src/Ryujinx.HLE/HOS/Services/Vi/RootService/IApplicationDisplayService.cs index 9fe247e8a..99c640aa0 100644 --- a/src/Ryujinx.HLE/HOS/Services/Vi/RootService/IApplicationDisplayService.cs +++ b/src/Ryujinx.HLE/HOS/Services/Vi/RootService/IApplicationDisplayService.cs @@ -148,7 +148,7 @@ namespace Ryujinx.HLE.HOS.Services.Vi.RootService { byte chr = context.RequestData.ReadByte(); - if (chr >= 0x20 && chr < 0x7f) + if (chr is >= 0x20 and < 0x7f) { nameBuilder.Append((char)chr); } @@ -346,7 +346,7 @@ namespace Ryujinx.HLE.HOS.Services.Vi.RootService return ResultCode.InvalidArguments; } - if (scalingMode != SourceScalingMode.ScaleToWindow && scalingMode != SourceScalingMode.PreserveAspectRatio) + if (scalingMode is not SourceScalingMode.ScaleToWindow and not SourceScalingMode.PreserveAspectRatio) { // Invalid scaling mode specified. return ResultCode.InvalidScalingMode; diff --git a/src/Ryujinx.HLE/HOS/Tamper/AtmosphereCompiler.cs b/src/Ryujinx.HLE/HOS/Tamper/AtmosphereCompiler.cs index c5b228fc8..ec41e9bd5 100644 --- a/src/Ryujinx.HLE/HOS/Tamper/AtmosphereCompiler.cs +++ b/src/Ryujinx.HLE/HOS/Tamper/AtmosphereCompiler.cs @@ -55,7 +55,7 @@ namespace Ryujinx.HLE.HOS.Tamper return null; } - private ITamperProgram CompileImpl(string name, IEnumerable rawInstructions) + private AtmosphereProgram CompileImpl(string name, IEnumerable rawInstructions) { CompilationContext context = new(_exeAddress, _heapAddress, _aliasAddress, _aslrAddress, _process); context.BlockStack.Push(new OperationBlock(null)); diff --git a/src/Ryujinx.HLE/HOS/TamperMachine.cs b/src/Ryujinx.HLE/HOS/TamperMachine.cs index d9f4fb157..9b565b034 100644 --- a/src/Ryujinx.HLE/HOS/TamperMachine.cs +++ b/src/Ryujinx.HLE/HOS/TamperMachine.cs @@ -86,7 +86,7 @@ namespace Ryujinx.HLE.HOS private static bool IsProcessValid(ITamperedProcess process) { - return process.State != ProcessState.Crashed && process.State != ProcessState.Exiting && process.State != ProcessState.Exited; + return process.State is not ProcessState.Crashed and not ProcessState.Exiting and not ProcessState.Exited; } private void TamperRunner() @@ -173,7 +173,7 @@ namespace Ryujinx.HLE.HOS // Look for the input of the player one or the handheld. foreach (GamepadInput input in gamepadInputs) { - if (input.PlayerId == PlayerIndex.Player1 || input.PlayerId == PlayerIndex.Handheld) + if (input.PlayerId is PlayerIndex.Player1 or PlayerIndex.Handheld) { Volatile.Write(ref _pressedKeys, (long)input.Buttons); diff --git a/src/Ryujinx.HLE/HleConfiguration.cs b/src/Ryujinx.HLE/HleConfiguration.cs index 39745ff53..10c2a1f30 100644 --- a/src/Ryujinx.HLE/HleConfiguration.cs +++ b/src/Ryujinx.HLE/HleConfiguration.cs @@ -102,7 +102,7 @@ namespace Ryujinx.HLE /// Control if the Profiled Translation Cache (PTC) should be used. ///
internal readonly bool EnablePtc; - + /// /// Control the arbitrary scalar applied to emulated CPU tick timing. /// @@ -193,7 +193,7 @@ namespace Ryujinx.HLE /// An action called when HLE force a refresh of output after docked mode changed. ///
public Action RefreshInputConfig { internal get; set; } - + /// /// The desired hacky workarounds. /// diff --git a/src/Ryujinx.HLE/Loaders/Elf/ElfDynamicTag.cs b/src/Ryujinx.HLE/Loaders/Elf/ElfDynamicTag.cs index 6505e17dd..9b6eb014e 100644 --- a/src/Ryujinx.HLE/Loaders/Elf/ElfDynamicTag.cs +++ b/src/Ryujinx.HLE/Loaders/Elf/ElfDynamicTag.cs @@ -2,8 +2,6 @@ using System.Diagnostics.CodeAnalysis; namespace Ryujinx.HLE.Loaders.Elf { - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("Design", "CA1069: Enums values should not be duplicated")] enum ElfDynamicTag { DT_NULL = 0, diff --git a/src/Ryujinx.HLE/Loaders/Elf/ElfSymbol.cs b/src/Ryujinx.HLE/Loaders/Elf/ElfSymbol.cs index 1ed61b2cb..e3ade80ba 100644 --- a/src/Ryujinx.HLE/Loaders/Elf/ElfSymbol.cs +++ b/src/Ryujinx.HLE/Loaders/Elf/ElfSymbol.cs @@ -8,8 +8,8 @@ namespace Ryujinx.HLE.Loaders.Elf public ElfSymbolBinding Binding { get; private set; } public ElfSymbolVisibility Visibility { get; private set; } - public readonly bool IsFuncOrObject => Type == ElfSymbolType.SttFunc || Type == ElfSymbolType.SttObject; - public readonly bool IsGlobalOrWeak => Binding == ElfSymbolBinding.StbGlobal || Binding == ElfSymbolBinding.StbWeak; + public readonly bool IsFuncOrObject => Type is ElfSymbolType.SttFunc or ElfSymbolType.SttObject; + public readonly bool IsGlobalOrWeak => Binding is ElfSymbolBinding.StbGlobal or ElfSymbolBinding.StbWeak; public int ShIdx { get; private set; } public ulong Value { get; private set; } diff --git a/src/Ryujinx.HLE/Loaders/Mods/IPSwitchPatcher.cs b/src/Ryujinx.HLE/Loaders/Mods/IPSwitchPatcher.cs index b6b2c9759..70058fb43 100644 --- a/src/Ryujinx.HLE/Loaders/Mods/IPSwitchPatcher.cs +++ b/src/Ryujinx.HLE/Loaders/Mods/IPSwitchPatcher.cs @@ -94,15 +94,15 @@ namespace Ryujinx.HLE.Loaders.Mods static int ParseHexByte(byte c) { - if (c >= '0' && c <= '9') + if (c is >= (byte)'0' and <= (byte)'9') { return c - '0'; } - else if (c >= 'A' && c <= 'F') + else if (c is >= (byte)'A' and <= (byte)'F') { return c - 'A' + 10; } - else if (c >= 'a' && c <= 'f') + else if (c is >= (byte)'a' and <= (byte)'f') { return c - 'a' + 10; } diff --git a/src/Ryujinx.HLE/Loaders/Mods/MemPatch.cs b/src/Ryujinx.HLE/Loaders/Mods/MemPatch.cs index f601c7749..d007861e9 100644 --- a/src/Ryujinx.HLE/Loaders/Mods/MemPatch.cs +++ b/src/Ryujinx.HLE/Loaders/Mods/MemPatch.cs @@ -76,7 +76,7 @@ namespace Ryujinx.HLE.Loaders.Mods Logger.Warning?.Print(LogClass.ModLoader, $"Attempted to patch protected memory ({patchOffset:x} is within protected boundary of {protectedOffset:x})."); continue; } - + if (patchOffset > memory.Length) { Logger.Warning?.Print(LogClass.ModLoader, $"Attempted to patch out of bounds memory (offset {patchOffset} ({patchOffset:x}) exceeds memory buffer length {memory.Length})."); diff --git a/src/Ryujinx.HLE/Loaders/Processes/ProcessLoader.cs b/src/Ryujinx.HLE/Loaders/Processes/ProcessLoader.cs index 16dc1ae82..48b5b724c 100644 --- a/src/Ryujinx.HLE/Loaders/Processes/ProcessLoader.cs +++ b/src/Ryujinx.HLE/Loaders/Processes/ProcessLoader.cs @@ -34,7 +34,7 @@ namespace Ryujinx.HLE.Loaders.Processes if (!_processesByPid.TryGetValue(_latestPid, out ProcessResult value)) throw new RyujinxException( $"The HLE Process map did not have a process with ID {_latestPid}. Are you missing firmware?"); - + return value; } } @@ -159,7 +159,7 @@ namespace Ryujinx.HLE.Loaders.Processes return false; } - + public bool LoadNxo(string path) { BlitStruct nacpData = new(1); @@ -172,7 +172,7 @@ namespace Ryujinx.HLE.Loaders.Processes // Load executable. IExecutable executable; - if (Path.GetExtension(path).ToLower() == ".nro") + if (Path.GetExtension(path).Equals(".nro", StringComparison.OrdinalIgnoreCase)) { FileStream input = new(path, FileMode.Open); NroExecutable nro = new(input.AsStorage()); diff --git a/src/Ryujinx.HLE/PerformanceStatistics.cs b/src/Ryujinx.HLE/PerformanceStatistics.cs index 9363ff2d3..84b9eb05b 100644 --- a/src/Ryujinx.HLE/PerformanceStatistics.cs +++ b/src/Ryujinx.HLE/PerformanceStatistics.cs @@ -7,7 +7,7 @@ namespace Ryujinx.HLE public class PerformanceStatistics { private readonly Switch _device; - + private const int FrameTypeGame = 0; private const int PercentTypeFifo = 0; @@ -33,7 +33,7 @@ namespace Ryujinx.HLE public PerformanceStatistics(Switch device) { _device = device; - + _frameRate = new double[1]; _accumulatedFrameTime = new double[1]; _previousFrameTime = new double[1]; @@ -165,7 +165,7 @@ namespace Ryujinx.HLE { return 1000 / _frameRate[FrameTypeGame]; } - + public string FormatFifoPercent() { double fifoPercent = GetFifoPercent(); diff --git a/src/Ryujinx.HLE/StructHelpers.cs b/src/Ryujinx.HLE/StructHelpers.cs index a9a00c2d7..dc9c6d727 100644 --- a/src/Ryujinx.HLE/StructHelpers.cs +++ b/src/Ryujinx.HLE/StructHelpers.cs @@ -1,4 +1,4 @@ -using LibHac.Common; +using LibHac.Common; using LibHac.Ns; using System; using System.Text; @@ -11,13 +11,13 @@ namespace Ryujinx.HLE { // https://switchbrew.org/wiki/NACP const int OffsetOfDisplayVersion = 0x3060; - + // https://switchbrew.org/wiki/NACP#ApplicationTitle const int TotalApplicationTitles = 0x10; const int SizeOfApplicationTitle = 0x300; const int OffsetOfApplicationPublisherStrings = 0x200; - - + + BlitStruct nacpData = new(1); // name and publisher buffer @@ -27,7 +27,7 @@ namespace Ryujinx.HLE Encoding.ASCII.GetBytes(name).AsSpan().CopyTo(nacpData.ByteSpan[(i * SizeOfApplicationTitle)..]); "Ryujinx"u8.CopyTo(nacpData.ByteSpan[(i * SizeOfApplicationTitle + OffsetOfApplicationPublisherStrings)..]); } - + // version buffer Encoding.ASCII.GetBytes(version).AsSpan().CopyTo(nacpData.ByteSpan[OffsetOfDisplayVersion..]); diff --git a/src/Ryujinx.HLE/Switch.cs b/src/Ryujinx.HLE/Switch.cs index e52b3df15..bdcbe82c7 100644 --- a/src/Ryujinx.HLE/Switch.cs +++ b/src/Ryujinx.HLE/Switch.cs @@ -20,7 +20,7 @@ namespace Ryujinx.HLE public class Switch : IDisposable { public static Switch Shared { get; private set; } - + public HleConfiguration Configuration { get; } public IHardwareDeviceDriver AudioDeviceDriver { get; } public MemoryBlock Memory { get; } @@ -35,7 +35,7 @@ namespace Ryujinx.HLE get => System?.TickSource?.TickScalar ?? ITickSource.RealityTickScalar; set => System.TickSource.TickScalar = value; } - + public ProcessLoader Processes { get; } public PerformanceStatistics Statistics { get; } public Hid Hid { get; } diff --git a/src/Ryujinx.HLE/UI/IHostUIHandler.cs b/src/Ryujinx.HLE/UI/IHostUIHandler.cs index 3748eef39..b5c5cb168 100644 --- a/src/Ryujinx.HLE/UI/IHostUIHandler.cs +++ b/src/Ryujinx.HLE/UI/IHostUIHandler.cs @@ -62,8 +62,8 @@ namespace Ryujinx.HLE.UI /// Gets fonts and colors used by the host. ///
IHostUITheme HostUITheme { get; } - - + + /// /// Displays the player select dialog and returns the selected profile. /// diff --git a/src/Ryujinx.HLE/Utilities/PartitionFileSystemUtils.cs b/src/Ryujinx.HLE/Utilities/PartitionFileSystemUtils.cs index 671bcaa06..e65fac438 100644 --- a/src/Ryujinx.HLE/Utilities/PartitionFileSystemUtils.cs +++ b/src/Ryujinx.HLE/Utilities/PartitionFileSystemUtils.cs @@ -16,7 +16,7 @@ namespace Ryujinx.HLE.Utilities IFileSystem partitionFileSystem; - if (Path.GetExtension(path).ToLower() == ".xci") + if (Path.GetExtension(path).Equals(".xci", System.StringComparison.OrdinalIgnoreCase)) { partitionFileSystem = new Xci(fileSystem.KeySet, file.AsStorage()).OpenPartition(XciPartitionType.Secure); } diff --git a/src/Ryujinx.Horizon.Common/ResultNames.cs b/src/Ryujinx.Horizon.Common/ResultNames.cs index 25d04b308..15e372c35 100644 --- a/src/Ryujinx.Horizon.Common/ResultNames.cs +++ b/src/Ryujinx.Horizon.Common/ResultNames.cs @@ -1,11 +1,12 @@ using System.Collections.Generic; +using System.Collections.ObjectModel; namespace Ryujinx.Horizon.Common { static class ResultNames { // Reference: https://github.com/Thealexbarney/LibHac/blob/master/build/CodeGen/results.csv - private static readonly IReadOnlyDictionary _names = new Dictionary() + private static readonly ReadOnlyDictionary _names = new Dictionary() { { 0x0, "Success" }, { 0xE01, "OutOfSessions" }, @@ -1691,7 +1692,7 @@ namespace Ryujinx.Horizon.Common { 0x823AC, "InvalidPackage1SectionSize" }, { 0x825AC, "InvalidPackage1MarikoBodySize" }, { 0x827AC, "InvalidPackage1Pk11Size" }, - }; + }.AsReadOnly(); public static bool TryGet(int errorCode, out string name) { diff --git a/src/Ryujinx.Horizon.Generators/Hipc/HipcGenerator.cs b/src/Ryujinx.Horizon.Generators/Hipc/HipcGenerator.cs index b68e05681..2786c45aa 100644 --- a/src/Ryujinx.Horizon.Generators/Hipc/HipcGenerator.cs +++ b/src/Ryujinx.Horizon.Generators/Hipc/HipcGenerator.cs @@ -102,7 +102,7 @@ namespace Ryujinx.Horizon.Generators.Hipc private static string GetNamespaceName(SyntaxNode syntaxNode) { - while (syntaxNode != null && !(syntaxNode is NamespaceDeclarationSyntax)) + while (syntaxNode is not null and not NamespaceDeclarationSyntax) { syntaxNode = syntaxNode.Parent; } @@ -162,7 +162,7 @@ namespace Ryujinx.Horizon.Generators.Hipc arg = $"new CommandArg({bufferFlags})"; } } - else if (argType == CommandArgType.InArgument || argType == CommandArgType.OutArgument) + else if (argType is CommandArgType.InArgument or CommandArgType.OutArgument) { string alignment = GetTypeAlignmentExpression(compilation, parameter.Type); @@ -353,6 +353,7 @@ namespace Ryujinx.Horizon.Generators.Hipc value = $"CommandSerialization.GetRef<{canonicalTypeName}>(processor.GetBufferRange({index}))"; isNonSpanBuffer = true; } + break; } @@ -470,7 +471,7 @@ namespace Ryujinx.Horizon.Generators.Hipc { if (outObjectsCount != 0) { - generator.AppendLine($"processor.SetOutObjects(ref context, {ResponseVariableName}, {OutObjectsVariableName});"); + generator.AppendLine($"HipcCommandProcessor.SetOutObjects(ref context, {ResponseVariableName}, {OutObjectsVariableName});"); } if (buffersCount != 0) diff --git a/src/Ryujinx.Horizon.Kernel.Generators/SyscallGenerator.cs b/src/Ryujinx.Horizon.Kernel.Generators/SyscallGenerator.cs index b4063eda2..2a09001db 100644 --- a/src/Ryujinx.Horizon.Kernel.Generators/SyscallGenerator.cs +++ b/src/Ryujinx.Horizon.Kernel.Generators/SyscallGenerator.cs @@ -492,12 +492,12 @@ namespace Ryujinx.Horizon.Kernel.Generators private static bool Is32BitInteger(string canonicalTypeName) { - return canonicalTypeName == TypeSystemInt32 || canonicalTypeName == TypeSystemUInt32; + return canonicalTypeName is TypeSystemInt32 or TypeSystemUInt32; } private static bool Is64BitInteger(string canonicalTypeName) { - return canonicalTypeName == TypeSystemInt64 || canonicalTypeName == TypeSystemUInt64; + return canonicalTypeName is TypeSystemInt64 or TypeSystemUInt64; } private static string GenerateCastFromUInt64(string value, string canonicalTargetTypeName, string targetTypeName) diff --git a/src/Ryujinx.Horizon.Kernel.Generators/SyscallSyntaxReceiver.cs b/src/Ryujinx.Horizon.Kernel.Generators/SyscallSyntaxReceiver.cs index abeea4020..1351bdfeb 100644 --- a/src/Ryujinx.Horizon.Kernel.Generators/SyscallSyntaxReceiver.cs +++ b/src/Ryujinx.Horizon.Kernel.Generators/SyscallSyntaxReceiver.cs @@ -16,7 +16,7 @@ namespace Ryujinx.Horizon.Kernel.Generators public void OnVisitSyntaxNode(SyntaxNode syntaxNode) { - if (!(syntaxNode is ClassDeclarationSyntax classDeclaration) || classDeclaration.AttributeLists.Count == 0) + if (syntaxNode is not ClassDeclarationSyntax classDeclaration || classDeclaration.AttributeLists.Count == 0) { return; } diff --git a/src/Ryujinx.Horizon/HorizonStatic.cs b/src/Ryujinx.Horizon/HorizonStatic.cs index a936a5a2d..b0343a2cd 100644 --- a/src/Ryujinx.Horizon/HorizonStatic.cs +++ b/src/Ryujinx.Horizon/HorizonStatic.cs @@ -8,14 +8,14 @@ namespace Ryujinx.Horizon { public static class HorizonStatic { - internal static void HandlePlayReport(PlayReport report) => + internal static void HandlePlayReport(PlayReport report) => new Thread(() => PlayReport?.Invoke(report)) { - Name = "HLE.PlayReportEvent", + Name = "HLE.PlayReportEvent", IsBackground = true, Priority = ThreadPriority.AboveNormal }.Start(); - + public static event Action PlayReport; [field: ThreadStatic] diff --git a/src/Ryujinx.Horizon/Prepo/Ipc/PrepoService.cs b/src/Ryujinx.Horizon/Prepo/Ipc/PrepoService.cs index 0ca851e6e..8336adb18 100644 --- a/src/Ryujinx.Horizon/Prepo/Ipc/PrepoService.cs +++ b/src/Ryujinx.Horizon/Prepo/Ipc/PrepoService.cs @@ -131,7 +131,7 @@ namespace Ryujinx.Horizon.Prepo.Ipc { enabled = false; - if (_permissionLevel == PrepoServicePermissionLevel.User || _permissionLevel == PrepoServicePermissionLevel.System) + if (_permissionLevel is PrepoServicePermissionLevel.User or PrepoServicePermissionLevel.System) { enabled = _userAgreementCheckEnabled; @@ -148,7 +148,7 @@ namespace Ryujinx.Horizon.Prepo.Ipc [CmifCommand(40101)] // 2.0.0+ public Result SetUserAgreementCheckEnabled(bool enabled) { - if (_permissionLevel == PrepoServicePermissionLevel.User || _permissionLevel == PrepoServicePermissionLevel.System) + if (_permissionLevel is PrepoServicePermissionLevel.User or PrepoServicePermissionLevel.System) { _userAgreementCheckEnabled = enabled; @@ -188,17 +188,17 @@ namespace Ryujinx.Horizon.Prepo.Ipc { return PrepoResult.InvalidBufferSize; } - + StringBuilder builder = new(); MessagePackObject deserializedReport = MessagePackSerializer.UnpackMessagePackObject(reportBuffer.ToArray()); PlayReport playReport = new() { - Kind = playReportKind, + Kind = playReportKind, Room = gameRoom, ReportData = deserializedReport }; - + builder.AppendLine(); builder.AppendLine("PlayReport log:"); builder.AppendLine($" Kind: {playReportKind}"); @@ -225,7 +225,7 @@ namespace Ryujinx.Horizon.Prepo.Ipc _arp.GetApplicationLaunchProperty(out ApplicationLaunchProperty applicationLaunchProperty, applicationInstanceId).AbortOnFailure(); playReport.Version = applicationLaunchProperty.Version; - + builder.AppendLine($" ApplicationVersion: {applicationLaunchProperty.Version}"); if (!userId.IsNull) @@ -236,7 +236,7 @@ namespace Ryujinx.Horizon.Prepo.Ipc builder.AppendLine($" Room: {gameRoom}"); builder.AppendLine($" Report: {MessagePackObjectFormatter.Format(deserializedReport)}"); - + HorizonStatic.HandlePlayReport(playReport); Logger.Info?.Print(LogClass.ServicePrepo, builder.ToString()); diff --git a/src/Ryujinx.Horizon/Prepo/Types/PlayReport.cs b/src/Ryujinx.Horizon/Prepo/Types/PlayReport.cs index e896219d5..54106eaea 100644 --- a/src/Ryujinx.Horizon/Prepo/Types/PlayReport.cs +++ b/src/Ryujinx.Horizon/Prepo/Types/PlayReport.cs @@ -1,4 +1,4 @@ -using MsgPack; +using MsgPack; using Ryujinx.Horizon.Sdk.Account; using Ryujinx.Horizon.Sdk.Ncm; @@ -9,13 +9,13 @@ namespace Ryujinx.Horizon.Prepo.Types public PlayReportKind Kind { get; init; } public string Room { get; init; } public MessagePackObject ReportData { get; init; } - + public ApplicationId? AppId; public ulong? Pid; public uint Version; public Uid? UserId; } - + public enum PlayReportKind { Normal, diff --git a/src/Ryujinx.Horizon/Sdk/Audio/Detail/AudioDevice.cs b/src/Ryujinx.Horizon/Sdk/Audio/Detail/AudioDevice.cs index 2d3aa7ba9..583a04de3 100644 --- a/src/Ryujinx.Horizon/Sdk/Audio/Detail/AudioDevice.cs +++ b/src/Ryujinx.Horizon/Sdk/Audio/Detail/AudioDevice.cs @@ -121,7 +121,7 @@ namespace Ryujinx.Horizon.Sdk.Audio.Detail if (!_isUsbDeviceSupported && device.IsUsbDevice()) { - device = _registry.DefaultDevice; + device = VirtualDeviceSessionRegistry.DefaultDevice; } if (name.Length > 0) @@ -147,7 +147,7 @@ namespace Ryujinx.Horizon.Sdk.Audio.Detail if (!_isUsbDeviceSupported && device.IsUsbDevice()) { - device = _registry.DefaultDevice; + device = VirtualDeviceSessionRegistry.DefaultDevice; } channelCount = (int)device.ChannelCount; diff --git a/src/Ryujinx.Horizon/Sdk/Audio/Detail/AudioInManager.cs b/src/Ryujinx.Horizon/Sdk/Audio/Detail/AudioInManager.cs index b190cb8ae..64394b251 100644 --- a/src/Ryujinx.Horizon/Sdk/Audio/Detail/AudioInManager.cs +++ b/src/Ryujinx.Horizon/Sdk/Audio/Detail/AudioInManager.cs @@ -22,7 +22,7 @@ namespace Ryujinx.Horizon.Sdk.Audio.Detail [CmifCommand(0)] public Result ListAudioIns(out int count, [Buffer(HipcBufferFlags.Out | HipcBufferFlags.MapAlias)] Span names) { - string[] deviceNames = _impl.ListAudioIns(filtered: false); + string[] deviceNames = AudioInputManager.ListAudioIns(filtered: false); count = 0; @@ -94,7 +94,7 @@ namespace Ryujinx.Horizon.Sdk.Audio.Detail [CmifCommand(4)] // 3.0.0+ public Result ListAudioInsAutoFiltered(out int count, [Buffer(HipcBufferFlags.Out | HipcBufferFlags.AutoSelect)] Span names) { - string[] deviceNames = _impl.ListAudioIns(filtered: true); + string[] deviceNames = AudioInputManager.ListAudioIns(filtered: true); count = 0; diff --git a/src/Ryujinx.Horizon/Sdk/Audio/Detail/AudioOutManager.cs b/src/Ryujinx.Horizon/Sdk/Audio/Detail/AudioOutManager.cs index facfbbc03..37e51b042 100644 --- a/src/Ryujinx.Horizon/Sdk/Audio/Detail/AudioOutManager.cs +++ b/src/Ryujinx.Horizon/Sdk/Audio/Detail/AudioOutManager.cs @@ -22,7 +22,7 @@ namespace Ryujinx.Horizon.Sdk.Audio.Detail [CmifCommand(0)] public Result ListAudioOuts(out int count, [Buffer(HipcBufferFlags.Out | HipcBufferFlags.MapAlias)] Span names) { - string[] deviceNames = _impl.ListAudioOuts(); + string[] deviceNames = AudioOutputManager.ListAudioOuts(); count = 0; diff --git a/src/Ryujinx.Horizon/Sdk/Codec/Detail/HardwareOpusDecoderManager.cs b/src/Ryujinx.Horizon/Sdk/Codec/Detail/HardwareOpusDecoderManager.cs index d74e50a61..9c981b765 100644 --- a/src/Ryujinx.Horizon/Sdk/Codec/Detail/HardwareOpusDecoderManager.cs +++ b/src/Ryujinx.Horizon/Sdk/Codec/Detail/HardwareOpusDecoderManager.cs @@ -229,7 +229,7 @@ namespace Ryujinx.Horizon.Sdk.Codec.Detail return GetWorkBufferSizeForMultiStreamExImpl(out size, in parameter, fromDsp: true); } - private Result GetWorkBufferSizeExImpl(out int size, in HardwareOpusDecoderParameterInternalEx parameter, bool fromDsp) + private static Result GetWorkBufferSizeExImpl(out int size, in HardwareOpusDecoderParameterInternalEx parameter, bool fromDsp) { size = 0; @@ -253,7 +253,7 @@ namespace Ryujinx.Horizon.Sdk.Codec.Detail return Result.Success; } - private Result GetWorkBufferSizeForMultiStreamExImpl(out int size, in HardwareOpusMultiStreamDecoderParameterInternalEx parameter, bool fromDsp) + private static Result GetWorkBufferSizeForMultiStreamExImpl(out int size, in HardwareOpusMultiStreamDecoderParameterInternalEx parameter, bool fromDsp) { size = 0; @@ -305,7 +305,7 @@ namespace Ryujinx.Horizon.Sdk.Codec.Detail { const int SilkDecoderSize = 0x2160; - if (channelsCount < 1 || channelsCount > 2) + if (channelsCount is < 1 or > 2) { return 0; } @@ -351,12 +351,12 @@ namespace Ryujinx.Horizon.Sdk.Codec.Detail private static bool IsValidChannelCount(int channelsCount) { - return channelsCount > 0 && channelsCount <= 2; + return channelsCount is > 0 and <= 2; } private static bool IsValidMultiChannelCount(int channelsCount) { - return channelsCount > 0 && channelsCount <= 255; + return channelsCount is > 0 and <= 255; } private static bool IsValidSampleRate(int sampleRate) diff --git a/src/Ryujinx.Horizon/Sdk/Ngc/Detail/ContentsReader.cs b/src/Ryujinx.Horizon/Sdk/Ngc/Detail/ContentsReader.cs index d3ed37e78..0f84a2c62 100644 --- a/src/Ryujinx.Horizon/Sdk/Ngc/Detail/ContentsReader.cs +++ b/src/Ryujinx.Horizon/Sdk/Ngc/Detail/ContentsReader.cs @@ -47,6 +47,7 @@ namespace Ryujinx.Horizon.Sdk.Ngc.Detail { path = $"{MountName}:/ac_{regionIndex}_not_b_nx"; } + break; case AcType.AcB1: if (regionIndex < 0) @@ -57,6 +58,7 @@ namespace Ryujinx.Horizon.Sdk.Ngc.Detail { path = $"{MountName}:/ac_{regionIndex}_b1_nx"; } + break; case AcType.AcB2: if (regionIndex < 0) @@ -67,6 +69,7 @@ namespace Ryujinx.Horizon.Sdk.Ngc.Detail { path = $"{MountName}:/ac_{regionIndex}_b2_nx"; } + break; case AcType.AcSimilarForm: path = $"{MountName}:/ac_similar_form_nx"; diff --git a/src/Ryujinx.Horizon/Sdk/Ngc/Detail/ProfanityFilterBase.cs b/src/Ryujinx.Horizon/Sdk/Ngc/Detail/ProfanityFilterBase.cs index 9f3c6b449..3046be228 100644 --- a/src/Ryujinx.Horizon/Sdk/Ngc/Detail/ProfanityFilterBase.cs +++ b/src/Ryujinx.Horizon/Sdk/Ngc/Detail/ProfanityFilterBase.cs @@ -8,7 +8,6 @@ namespace Ryujinx.Horizon.Sdk.Ngc.Detail { abstract class ProfanityFilterBase { -#pragma warning disable IDE0230 // Use UTF-8 string literal private static readonly byte[][] _wordSeparators = [ [0x0D], @@ -92,7 +91,6 @@ namespace Ryujinx.Horizon.Sdk.Ngc.Detail [0xEF, 0xBC, 0x8D], [0xEF, 0xBC, 0xBD] ]; -#pragma warning restore IDE0230 private enum SignFilterStep { @@ -115,7 +113,7 @@ namespace Ryujinx.Horizon.Sdk.Ngc.Detail { break; } - else if (word[index] == '@' || word[index] == '\uFF20') + else if (word[index] is '@' or '\uFF20') { return true; } @@ -142,6 +140,7 @@ namespace Ryujinx.Horizon.Sdk.Ngc.Detail step = SignFilterStep.DetectEmailUserAtSign; matchStart = index; } + break; case SignFilterStep.DetectEmailUserAtSign: bool hasMatch = false; @@ -205,6 +204,7 @@ namespace Ryujinx.Horizon.Sdk.Ngc.Detail { index = domainIndex - 1; } + break; } } @@ -232,7 +232,7 @@ namespace Ryujinx.Horizon.Sdk.Ngc.Detail text[startOffset] = 0xc1; text[startOffset + 1] = 0xc1; } - else if (maskMode == MaskMode.Overwrite || maskMode == MaskMode.ReplaceByOneCharacter) + else if (maskMode is MaskMode.Overwrite or MaskMode.ReplaceByOneCharacter) { text[startOffset] = 0xc0; text[startOffset + 1] = 0xc0; @@ -312,7 +312,7 @@ namespace Ryujinx.Horizon.Sdk.Ngc.Detail } else if ((character & 0x80) != 0) { - if (character >= 0xc2 && character < 0xe0) + if (character is >= 0xc2 and < 0xe0) { characterByteLength = 2; } @@ -621,7 +621,7 @@ namespace Ryujinx.Horizon.Sdk.Ngc.Detail if ((character & 0x80) != 0) { - if (character >= 0xc2 && character < 0xe0) + if (character is >= 0xc2 and < 0xe0) { characterByteLength = 2; } @@ -751,7 +751,7 @@ namespace Ryujinx.Horizon.Sdk.Ngc.Detail if ((character & 0x80) != 0 || character == 0) { - if (character >= 0xc2 && character < 0xe0) + if (character is >= 0xc2 and < 0xe0) { characterByteLength = 2; } diff --git a/src/Ryujinx.Horizon/Sdk/OsTypes/Impl/InterProcessEvent.cs b/src/Ryujinx.Horizon/Sdk/OsTypes/Impl/InterProcessEvent.cs index 4da4ee86c..c45239b14 100644 --- a/src/Ryujinx.Horizon/Sdk/OsTypes/Impl/InterProcessEvent.cs +++ b/src/Ryujinx.Horizon/Sdk/OsTypes/Impl/InterProcessEvent.cs @@ -33,6 +33,7 @@ namespace Ryujinx.Horizon.Sdk.OsTypes.Impl { InterProcessEventImpl.Close(ipEvent.ReadableHandle); } + ipEvent.ReadableHandleManaged = false; } @@ -42,6 +43,7 @@ namespace Ryujinx.Horizon.Sdk.OsTypes.Impl { InterProcessEventImpl.Close(ipEvent.WritableHandle); } + ipEvent.WritableHandleManaged = false; } } diff --git a/src/Ryujinx.Horizon/Sdk/OsTypes/Impl/MultiWaitImpl.cs b/src/Ryujinx.Horizon/Sdk/OsTypes/Impl/MultiWaitImpl.cs index 2fbcfdc88..d723e5322 100644 --- a/src/Ryujinx.Horizon/Sdk/OsTypes/Impl/MultiWaitImpl.cs +++ b/src/Ryujinx.Horizon/Sdk/OsTypes/Impl/MultiWaitImpl.cs @@ -124,6 +124,7 @@ namespace Ryujinx.Horizon.Sdk.OsTypes.Impl { return null; } + break; case WaitCancelled: lock (_lock) @@ -133,6 +134,7 @@ namespace Ryujinx.Horizon.Sdk.OsTypes.Impl return _signaledHolder; } } + break; default: lock (_lock) diff --git a/src/Ryujinx.Horizon/Sdk/Sf/Cmif/ServiceDispatchTableBase.cs b/src/Ryujinx.Horizon/Sdk/Sf/Cmif/ServiceDispatchTableBase.cs index f2292feff..df1472560 100644 --- a/src/Ryujinx.Horizon/Sdk/Sf/Cmif/ServiceDispatchTableBase.cs +++ b/src/Ryujinx.Horizon/Sdk/Sf/Cmif/ServiceDispatchTableBase.cs @@ -62,8 +62,8 @@ namespace Ryujinx.Horizon.Sdk.Sf.Cmif Result commandResult = commandHandler.Invoke(ref outHeader, ref context, inMessageRawData); - if (commandResult.Module == SfResult.ModuleId || - commandResult.Module == HipcResult.ModuleId) + if (commandResult.Module is SfResult.ModuleId or + HipcResult.ModuleId) { Logger.Warning?.Print(LogClass.KernelIpc, $"{commandHandler.MethodName} returned error {commandResult}"); } diff --git a/src/Ryujinx.Horizon/Sdk/Sf/Hipc/ServerSessionManager.cs b/src/Ryujinx.Horizon/Sdk/Sf/Hipc/ServerSessionManager.cs index f51e0811e..ca13e611e 100644 --- a/src/Ryujinx.Horizon/Sdk/Sf/Hipc/ServerSessionManager.cs +++ b/src/Ryujinx.Horizon/Sdk/Sf/Hipc/ServerSessionManager.cs @@ -206,6 +206,7 @@ namespace Ryujinx.Horizon.Sdk.Sf.Hipc { return MemoryMarshal.Cast(inMessage)[3]; } + break; } diff --git a/src/Ryujinx.Horizon/Sdk/Sf/HipcCommandProcessor.cs b/src/Ryujinx.Horizon/Sdk/Sf/HipcCommandProcessor.cs index b553115eb..ec0acbdea 100644 --- a/src/Ryujinx.Horizon/Sdk/Sf/HipcCommandProcessor.cs +++ b/src/Ryujinx.Horizon/Sdk/Sf/HipcCommandProcessor.cs @@ -82,6 +82,7 @@ namespace Ryujinx.Horizon.Sdk.Sf _outMapAliasBuffersCount++; } } + break; case CommandArgType.InCopyHandle: _inCopyHandlesCount++; @@ -386,9 +387,7 @@ namespace Ryujinx.Horizon.Sdk.Sf outRawData = MemoryMarshal.Cast(response.DataWords); } -#pragma warning disable CA1822 // Mark member as static - public void SetOutObjects(ref ServiceDispatchContext context, HipcMessageData response, Span objects) -#pragma warning restore CA1822 + public static void SetOutObjects(ref ServiceDispatchContext context, HipcMessageData response, Span objects) { if (objects.Length == 0) { diff --git a/src/Ryujinx.Input.SDL2/SDL2Gamepad.cs b/src/Ryujinx.Input.SDL2/SDL2Gamepad.cs index 6f1b79d38..4b868efeb 100644 --- a/src/Ryujinx.Input.SDL2/SDL2Gamepad.cs +++ b/src/Ryujinx.Input.SDL2/SDL2Gamepad.cs @@ -86,7 +86,7 @@ namespace Ryujinx.Input.SDL2 Id = driverId; Features = GetFeaturesFlag(); _triggerThreshold = 0.0f; - + // Enable motion tracking if (Features.HasFlag(GamepadFeaturesFlag.Motion)) { @@ -104,12 +104,13 @@ namespace Ryujinx.Input.SDL2 public void SetLed(uint packedRgb) { - if (!Features.HasFlag(GamepadFeaturesFlag.Led)) return; + if (!Features.HasFlag(GamepadFeaturesFlag.Led)) + return; byte red = packedRgb > 0 ? (byte)(packedRgb >> 16) : (byte)0; byte green = packedRgb > 0 ? (byte)(packedRgb >> 8) : (byte)0; byte blue = packedRgb > 0 ? (byte)(packedRgb % 256) : (byte)0; - + if (SDL_GameControllerSetLED(_gamepadHandle, red, green, blue) != 0) Logger.Debug?.Print(LogClass.Hid, "LED setting failed; probably in the middle of disconnecting."); } @@ -155,6 +156,7 @@ namespace Ryujinx.Input.SDL2 public void Dispose() { Dispose(true); + GC.SuppressFinalize(this); } public void SetTriggerThreshold(float triggerThreshold) @@ -223,7 +225,7 @@ namespace Ryujinx.Input.SDL2 private static Vector3 RadToDegree(Vector3 rad) => rad * (180 / MathF.PI); private static Vector3 GsToMs2(Vector3 gs) => gs / SDL_STANDARD_GRAVITY; - + public void SetConfiguration(InputConfig configuration) { lock (_userMappingLock) @@ -236,11 +238,11 @@ namespace Ryujinx.Input.SDL2 (this as IGamepad).ClearLed(); else if (_configuration.Led.UseRainbow) SetLed((uint)Rainbow.Color.ToArgb()); - + if (!_configuration.Led.TurnOffLed && !_configuration.Led.UseRainbow) SetLed(_configuration.Led.LedColor); } - + _buttonsUserMapping.Clear(); // First update sticks @@ -290,7 +292,6 @@ namespace Ryujinx.Input.SDL2 if (_buttonsUserMapping.Count == 0) return rawState; - // ReSharper disable once ForeachCanBePartlyConvertedToQueryUsingAnotherGetEnumerator foreach (ButtonMappingEntry entry in _buttonsUserMapping) { @@ -336,6 +337,7 @@ namespace Ryujinx.Input.SDL2 else return _configuration.RightJoyconStick; } + return null; } diff --git a/src/Ryujinx.Input.SDL2/SDL2GamepadDriver.cs b/src/Ryujinx.Input.SDL2/SDL2GamepadDriver.cs index dfcc9e213..5b3756fb6 100644 --- a/src/Ryujinx.Input.SDL2/SDL2GamepadDriver.cs +++ b/src/Ryujinx.Input.SDL2/SDL2GamepadDriver.cs @@ -60,7 +60,7 @@ namespace Ryujinx.Input.SDL2 } // Remove the first 4 char of the guid (CRC part) to make it stable - string guidString = "0000" + guid.ToString().Substring(4); + string guidString = $"0000{guid.ToString()[4..]}"; string id; @@ -89,7 +89,7 @@ namespace Ryujinx.Input.SDL2 private void HandleJoyStickDisconnected(int joystickInstanceId) { bool joyConPairDisconnected = false; - + if (!_gamepadsInstanceIdsMapping.Remove(joystickInstanceId, out string id)) return; @@ -113,7 +113,7 @@ namespace Ryujinx.Input.SDL2 private void HandleJoyStickConnected(int joystickDeviceId, int joystickInstanceId) { bool joyConPairConnected = false; - + if (SDL_IsGameController(joystickDeviceId) == SDL_bool.SDL_TRUE) { if (_gamepadsInstanceIdsMapping.ContainsKey(joystickInstanceId)) @@ -138,7 +138,7 @@ namespace Ryujinx.Input.SDL2 _gamepadsIds.Insert(joystickDeviceId, id); else _gamepadsIds.Add(id); - + if (SDL2JoyConPair.IsCombinable(_gamepadsIds)) { _gamepadsIds.Remove(SDL2JoyConPair.Id); @@ -155,14 +155,13 @@ namespace Ryujinx.Input.SDL2 } } } - + private void HandleJoyBatteryUpdated(int joystickDeviceId, SDL_JoystickPowerLevel powerLevel) { Logger.Info?.Print(LogClass.Hid, $"{SDL_GameControllerNameForIndex(joystickDeviceId)} power level: {powerLevel}"); } - protected virtual void Dispose(bool disposing) { if (disposing) @@ -200,7 +199,7 @@ namespace Ryujinx.Input.SDL2 return SDL2JoyConPair.GetGamepad(_gamepadsIds); } } - + int joystickIndex = GetJoystickIndexByGamepadId(id); if (joystickIndex == -1) @@ -214,10 +213,10 @@ namespace Ryujinx.Input.SDL2 { return null; } - + if (SDL_GameControllerName(gamepadHandle).StartsWith(SDL2JoyCon.Prefix)) { - return new SDL2JoyCon(gamepadHandle, id); + return new SDL2JoyCon(gamepadHandle, id); } return new SDL2Gamepad(gamepadHandle, id); diff --git a/src/Ryujinx.Input.SDL2/SDL2JoyCon.cs b/src/Ryujinx.Input.SDL2/SDL2JoyCon.cs index 246a9ed8d..0c00c1899 100644 --- a/src/Ryujinx.Input.SDL2/SDL2JoyCon.cs +++ b/src/Ryujinx.Input.SDL2/SDL2JoyCon.cs @@ -1,4 +1,4 @@ -using Ryujinx.Common.Configuration.Hid; +using Ryujinx.Common.Configuration.Hid; using Ryujinx.Common.Configuration.Hid.Controller; using Ryujinx.Common.Logging; using System; @@ -20,7 +20,7 @@ namespace Ryujinx.Input.SDL2 private StandardControllerInputConfig _configuration; - private readonly Dictionary _leftButtonsDriverMapping = new() + private readonly Dictionary _leftButtonsDriverMapping = new() { { GamepadButtonInputId.LeftStick , SDL_GameControllerButton.SDL_CONTROLLER_BUTTON_LEFTSTICK }, {GamepadButtonInputId.DpadUp ,SDL_GameControllerButton.SDL_CONTROLLER_BUTTON_Y}, @@ -33,7 +33,7 @@ namespace Ryujinx.Input.SDL2 {GamepadButtonInputId.SingleRightTrigger0,SDL_GameControllerButton.SDL_CONTROLLER_BUTTON_RIGHTSHOULDER}, {GamepadButtonInputId.SingleLeftTrigger0,SDL_GameControllerButton.SDL_CONTROLLER_BUTTON_LEFTSHOULDER}, }; - private readonly Dictionary _rightButtonsDriverMapping = new() + private readonly Dictionary _rightButtonsDriverMapping = new() { {GamepadButtonInputId.RightStick,SDL_GameControllerButton.SDL_CONTROLLER_BUTTON_LEFTSTICK}, {GamepadButtonInputId.A,SDL_GameControllerButton.SDL_CONTROLLER_BUTTON_B}, @@ -155,7 +155,6 @@ namespace Ryujinx.Input.SDL2 Dispose(true); } - public void SetTriggerThreshold(float triggerThreshold) { @@ -212,7 +211,8 @@ namespace Ryujinx.Input.SDL2 Vector3 value = _joyConType switch { JoyConType.Left => new Vector3(-values[2], values[1], values[0]), - JoyConType.Right => new Vector3(values[2], values[1], -values[0]) + JoyConType.Right => new Vector3(values[2], values[1], -values[0]), + _ => throw new NotSupportedException($"Unsupported JoyCon type: {_joyConType}") }; return inputId switch @@ -240,7 +240,6 @@ namespace Ryujinx.Input.SDL2 _stickUserMapping[(int)StickInputId.Left] = (StickInputId)_configuration.LeftJoyconStick.Joystick; _stickUserMapping[(int)StickInputId.Right] = (StickInputId)_configuration.RightJoyconStick.Joystick; - switch (_joyConType) { case JoyConType.Left: @@ -268,9 +267,9 @@ namespace Ryujinx.Input.SDL2 _buttonsUserMapping.Add(new ButtonMappingEntry(GamepadButtonInputId.SingleLeftTrigger1, (GamepadButtonInputId)_configuration.RightJoycon.ButtonSl)); break; default: - throw new ArgumentOutOfRangeException(); + throw new NotSupportedException($"Unsupported JoyCon type: {_joyConType}"); } - + SetTriggerThreshold(_configuration.TriggerThreshold); } } @@ -294,7 +293,6 @@ namespace Ryujinx.Input.SDL2 if (_buttonsUserMapping.Count == 0) return rawState; - // ReSharper disable once ForeachCanBePartlyConvertedToQueryUsingAnotherGetEnumerator foreach (ButtonMappingEntry entry in _buttonsUserMapping) { @@ -318,7 +316,6 @@ namespace Ryujinx.Input.SDL2 return result; } - private static float ConvertRawStickValue(short value) { const float ConvertRate = 1.0f / (short.MaxValue + 0.5f); @@ -348,7 +345,6 @@ namespace Ryujinx.Input.SDL2 return null; } - public (float, float) GetStick(StickInputId inputId) { if (inputId == StickInputId.Unbound) @@ -358,7 +354,7 @@ namespace Ryujinx.Input.SDL2 { return (0.0f, 0.0f); } - + (short stickX, short stickY) = GetStickXY(); float resultX = ConvertRawStickValue(stickX); @@ -399,7 +395,7 @@ namespace Ryujinx.Input.SDL2 SDL_GameControllerGetAxis(_gamepadHandle, SDL_GameControllerAxis.SDL_CONTROLLER_AXIS_LEFTX), SDL_GameControllerGetAxis(_gamepadHandle, SDL_GameControllerAxis.SDL_CONTROLLER_AXIS_LEFTY)); } - + public bool IsPressed(GamepadButtonInputId inputId) { if (!_buttonsDriverMapping.TryGetValue(inputId, out var button)) diff --git a/src/Ryujinx.Input.SDL2/SDL2JoyConPair.cs b/src/Ryujinx.Input.SDL2/SDL2JoyConPair.cs index e3280ccb4..a1e13aa45 100644 --- a/src/Ryujinx.Input.SDL2/SDL2JoyConPair.cs +++ b/src/Ryujinx.Input.SDL2/SDL2JoyConPair.cs @@ -1,4 +1,4 @@ -using Ryujinx.Common.Configuration.Hid; +using Ryujinx.Common.Configuration.Hid; using Ryujinx.Common.Configuration.Hid.Controller; using System; using System.Collections.Generic; @@ -10,15 +10,6 @@ namespace Ryujinx.Input.SDL2 { internal class SDL2JoyConPair(IGamepad left, IGamepad right) : IGamepad { - private StandardControllerInputConfig _configuration; - - private readonly StickInputId[] _stickUserMapping = - [ - StickInputId.Unbound, - StickInputId.Left, - StickInputId.Right - ]; - public GamepadFeaturesFlag Features => (left?.Features ?? GamepadFeaturesFlag.None) | (right?.Features ?? GamepadFeaturesFlag.None); @@ -138,7 +129,6 @@ namespace Ryujinx.Input.SDL2 return null; } - return new SDL2JoyConPair(new SDL2JoyCon(leftGamepadHandle, gamepadsIds[leftIndex]), new SDL2JoyCon(rightGamepadHandle, gamepadsIds[rightIndex])); } diff --git a/src/Ryujinx.Input.SDL2/SDL2Keyboard.cs b/src/Ryujinx.Input.SDL2/SDL2Keyboard.cs index 6f4f839a5..1cbf4d35c 100644 --- a/src/Ryujinx.Input.SDL2/SDL2Keyboard.cs +++ b/src/Ryujinx.Input.SDL2/SDL2Keyboard.cs @@ -195,7 +195,7 @@ namespace Ryujinx.Input.SDL2 [MethodImpl(MethodImplOptions.AggressiveInlining)] private static int ToSDL2Scancode(Key key) { - if (key >= Key.Unknown && key <= Key.Menu) + if (key is >= Key.Unknown and <= Key.Menu) { return -1; } diff --git a/src/Ryujinx.Input.SDL2/SDL2MouseDriver.cs b/src/Ryujinx.Input.SDL2/SDL2MouseDriver.cs index 7a9679901..a1f6c1d7b 100644 --- a/src/Ryujinx.Input.SDL2/SDL2MouseDriver.cs +++ b/src/Ryujinx.Input.SDL2/SDL2MouseDriver.cs @@ -106,7 +106,7 @@ namespace Ryujinx.Input.SDL2 case SDL_EventType.SDL_MOUSEBUTTONUP: uint rawButton = evnt.button.button; - if (rawButton > 0 && rawButton <= (int)MouseButton.Count) + if (rawButton is > 0 and <= ((int)MouseButton.Count)) { PressedButtons[(int)DriverButtonToMouseButton(rawButton)] = evnt.type == SDL_EventType.SDL_MOUSEBUTTONDOWN; diff --git a/src/Ryujinx.Input/GamepadFeaturesFlag.cs b/src/Ryujinx.Input/GamepadFeaturesFlag.cs index 52e8519d1..8d3cda426 100644 --- a/src/Ryujinx.Input/GamepadFeaturesFlag.cs +++ b/src/Ryujinx.Input/GamepadFeaturesFlag.cs @@ -24,7 +24,7 @@ namespace Ryujinx.Input /// Also named sixaxis ///
Motion, - + /// /// The LED on the back of modern PlayStation controllers (DualSense & DualShock 4). /// diff --git a/src/Ryujinx.Input/GamepadStateSnapshot.cs b/src/Ryujinx.Input/GamepadStateSnapshot.cs index ed1bf5fe8..bf38b7c8a 100644 --- a/src/Ryujinx.Input/GamepadStateSnapshot.cs +++ b/src/Ryujinx.Input/GamepadStateSnapshot.cs @@ -32,7 +32,6 @@ namespace Ryujinx.Input [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool IsPressed(GamepadButtonInputId inputId) => _buttonsState[(int)inputId]; - /// /// Set the state of a given button. /// diff --git a/src/Ryujinx.Input/IGamepadDriver.cs b/src/Ryujinx.Input/IGamepadDriver.cs index 25b2295db..50548c979 100644 --- a/src/Ryujinx.Input/IGamepadDriver.cs +++ b/src/Ryujinx.Input/IGamepadDriver.cs @@ -34,7 +34,7 @@ namespace Ryujinx.Input /// The unique id of the gamepad /// An instance of associated to the gamepad id given or null if not found IGamepad GetGamepad(string id); - + /// /// Returns an of the connected gamepads. /// diff --git a/src/Ryujinx.Input/Motion/CemuHook/Client.cs b/src/Ryujinx.Input/Motion/CemuHook/Client.cs index d07ae6431..21e31a76e 100644 --- a/src/Ryujinx.Input/Motion/CemuHook/Client.cs +++ b/src/Ryujinx.Input/Motion/CemuHook/Client.cs @@ -1,3 +1,4 @@ +using Microsoft.IO; using Ryujinx.Common; using Ryujinx.Common.Configuration.Hid; using Ryujinx.Common.Configuration.Hid.Controller; @@ -367,6 +368,7 @@ namespace Ryujinx.Input.Motion.CemuHook RemoveClient(clientId); } } + break; } } @@ -380,7 +382,7 @@ namespace Ryujinx.Input.Motion.CemuHook Header header = GenerateHeader(clientId); - using MemoryStream stream = MemoryStreamManager.Shared.GetStream(); + using RecyclableMemoryStream stream = MemoryStreamManager.Shared.GetStream(); using BinaryWriter writer = new(stream); writer.WriteStruct(header); @@ -419,7 +421,7 @@ namespace Ryujinx.Input.Motion.CemuHook Header header = GenerateHeader(clientId); - using MemoryStream stream = MemoryStreamManager.Shared.GetStream(); + using RecyclableMemoryStream stream = MemoryStreamManager.Shared.GetStream(); using BinaryWriter writer = new(stream); writer.WriteStruct(header); diff --git a/src/Ryujinx.Input/MotionInputId.cs b/src/Ryujinx.Input/MotionInputId.cs index 9835e70b7..c3768da96 100644 --- a/src/Ryujinx.Input/MotionInputId.cs +++ b/src/Ryujinx.Input/MotionInputId.cs @@ -21,7 +21,7 @@ namespace Ryujinx.Input /// /// Values are in degrees Gyroscope, - + /// /// Second accelerometer. /// diff --git a/src/Ryujinx.Memory/Tracking/IMultiRegionHandle.cs b/src/Ryujinx.Memory/Tracking/IMultiRegionHandle.cs index 62b58344d..c4fd15f7e 100644 --- a/src/Ryujinx.Memory/Tracking/IMultiRegionHandle.cs +++ b/src/Ryujinx.Memory/Tracking/IMultiRegionHandle.cs @@ -23,7 +23,6 @@ namespace Ryujinx.Memory.Tracking /// Action to perform for modified regions void QueryModified(Action modifiedAction); - /// /// Check if part of the region has been modified within a given range, and perform an action for each. /// The range is aligned to the level of granularity of the contained handles. diff --git a/src/Ryujinx.Memory/Tracking/MultiRegionHandle.cs b/src/Ryujinx.Memory/Tracking/MultiRegionHandle.cs index a9b79ab3e..20d2a07ef 100644 --- a/src/Ryujinx.Memory/Tracking/MultiRegionHandle.cs +++ b/src/Ryujinx.Memory/Tracking/MultiRegionHandle.cs @@ -282,6 +282,7 @@ namespace Ryujinx.Memory.Tracking modifiedAction(rgStart, rgSize); rgSize = 0; } + rgStart = handle.RealAddress; } diff --git a/src/Ryujinx.Memory/Tracking/RegionHandle.cs b/src/Ryujinx.Memory/Tracking/RegionHandle.cs index b938c6ea9..f0edee3fc 100644 --- a/src/Ryujinx.Memory/Tracking/RegionHandle.cs +++ b/src/Ryujinx.Memory/Tracking/RegionHandle.cs @@ -177,7 +177,7 @@ namespace Ryujinx.Memory.Tracking InitializeRegions(); } - private List GetGuestRegions(MemoryTracking tracking, ulong address, ulong size, RegionFlags flags) + private static List GetGuestRegions(MemoryTracking tracking, ulong address, ulong size, RegionFlags flags) { ulong guestAddress; ulong guestSize; @@ -305,6 +305,7 @@ namespace Ryujinx.Memory.Tracking { OnDirty?.Invoke(); } + Parent?.SignalWrite(); } } diff --git a/src/Ryujinx.Memory/Tracking/SmartMultiRegionHandle.cs b/src/Ryujinx.Memory/Tracking/SmartMultiRegionHandle.cs index 1e44c0916..ccd60e8da 100644 --- a/src/Ryujinx.Memory/Tracking/SmartMultiRegionHandle.cs +++ b/src/Ryujinx.Memory/Tracking/SmartMultiRegionHandle.cs @@ -110,6 +110,7 @@ namespace Ryujinx.Memory.Tracking { splitLow.RegisterAction(signal); } + _handles[handleIndex] = splitLow; RegionHandle splitHigh = _tracking.BeginTracking(address + size, handle.Size - size, _id); @@ -118,6 +119,7 @@ namespace Ryujinx.Memory.Tracking { splitHigh.RegisterAction(signal); } + _handles[splitIndex] = splitHigh; } @@ -136,6 +138,7 @@ namespace Ryujinx.Memory.Tracking SplitHandle(i, startHandle); return; // The remainer of this handle should be filled in later on. } + break; } } @@ -201,6 +204,7 @@ namespace Ryujinx.Memory.Tracking modifiedAction(rgStart, rgSize); rgSize = 0; } + rgStart = handle.EndAddress; } @@ -255,6 +259,7 @@ namespace Ryujinx.Memory.Tracking modifiedAction(rgStart, rgSize); rgSize = 0; } + rgStart = handle.EndAddress; } diff --git a/src/Ryujinx.Memory/Tracking/VirtualRegion.cs b/src/Ryujinx.Memory/Tracking/VirtualRegion.cs index f9267d85b..b86631db2 100644 --- a/src/Ryujinx.Memory/Tracking/VirtualRegion.cs +++ b/src/Ryujinx.Memory/Tracking/VirtualRegion.cs @@ -98,6 +98,7 @@ namespace Ryujinx.Memory.Tracking return result; } } + return result; } @@ -142,7 +143,7 @@ namespace Ryujinx.Memory.Tracking Size = splitAddress - Address; // The new region inherits all of our parents. - newRegion.Handles = new List(Handles); + newRegion.Handles = [.. Handles]; foreach (RegionHandle parent in Handles) { parent.AddChild(newRegion); diff --git a/src/Ryujinx.Memory/VirtualMemoryManagerBase.cs b/src/Ryujinx.Memory/VirtualMemoryManagerBase.cs index eb5d66829..9c49286b9 100644 --- a/src/Ryujinx.Memory/VirtualMemoryManagerBase.cs +++ b/src/Ryujinx.Memory/VirtualMemoryManagerBase.cs @@ -400,6 +400,5 @@ namespace Ryujinx.Memory } } } - } } diff --git a/src/Ryujinx.SDL2.Common/SDL2Driver.cs b/src/Ryujinx.SDL2.Common/SDL2Driver.cs index 70453e549..df11966bc 100644 --- a/src/Ryujinx.SDL2.Common/SDL2Driver.cs +++ b/src/Ryujinx.SDL2.Common/SDL2Driver.cs @@ -32,12 +32,11 @@ namespace Ryujinx.SDL2.Common private Thread _worker; private const uint SDL_JOYBATTERYUPDATED = 1543; - + public event Action OnJoyStickConnected; public event Action OnJoystickDisconnected; - - public event Action OnJoyBatteryUpdated; + public event Action OnJoyBatteryUpdated; private ConcurrentDictionary> _registeredWindowHandlers; @@ -66,7 +65,6 @@ namespace Ryujinx.SDL2.Common SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_JOY_CONS, "1"); SDL_SetHint(SDL_HINT_VIDEO_ALLOW_SCREENSAVER, "1"); - // NOTE: As of SDL2 2.24.0, joycons are combined by default but the motion source only come from one of them. // We disable this behavior for now. SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_COMBINE_JOY_CONS, "0"); diff --git a/src/Ryujinx.Tests.Memory/MultiRegionTrackingTests.cs b/src/Ryujinx.Tests.Memory/MultiRegionTrackingTests.cs index c9ac4dc94..b35de3a82 100644 --- a/src/Ryujinx.Tests.Memory/MultiRegionTrackingTests.cs +++ b/src/Ryujinx.Tests.Memory/MultiRegionTrackingTests.cs @@ -400,6 +400,8 @@ namespace Ryujinx.Tests.Memory Assert.AreEqual(singlePages[2], combinedHandles.ElementAt(10)); } + static readonly bool[] _expectedPagesModified = [true, false, false]; + [Test] public void PreciseAction() { @@ -409,7 +411,11 @@ namespace Ryujinx.Tests.Memory PreparePages(granular, 3, PageSize * 3); // Add a precise action to the second and third handle in the multiregion. - granular.RegisterPreciseAction(PageSize * 4, PageSize * 2, (_, _, _) => { actionTriggered = true; return true; }); + granular.RegisterPreciseAction(PageSize * 4, PageSize * 2, (_, _, _) => + { + actionTriggered = true; + return true; + }); // Precise write to first handle in the multiregion. _tracking.VirtualMemoryEvent(PageSize * 3, PageSize, true, precise: true); @@ -433,7 +439,7 @@ namespace Ryujinx.Tests.Memory Assert.IsTrue(actionTriggered); // Action triggered. // Precise writes are ignored on two later handles due to the action returning true. - Assert.AreEqual(pagesModified, new bool[] { true, false, false }); + Assert.AreEqual(pagesModified, _expectedPagesModified); } } } diff --git a/src/Ryujinx.Tests.Memory/TrackingTests.cs b/src/Ryujinx.Tests.Memory/TrackingTests.cs index 675179ede..ac661924e 100644 --- a/src/Ryujinx.Tests.Memory/TrackingTests.cs +++ b/src/Ryujinx.Tests.Memory/TrackingTests.cs @@ -329,6 +329,7 @@ namespace Ryujinx.Tests.Memory { _tracking.VirtualMemoryEvent((ulong)random.Next(PageSize), 4, false); } + Interlocked.Increment(ref signalThreadsDone); }); } diff --git a/src/Ryujinx.Tests.Unicorn/Ryujinx.Tests.Unicorn.csproj b/src/Ryujinx.Tests.Unicorn/Ryujinx.Tests.Unicorn.csproj index f9f42416f..00fe473c5 100644 --- a/src/Ryujinx.Tests.Unicorn/Ryujinx.Tests.Unicorn.csproj +++ b/src/Ryujinx.Tests.Unicorn/Ryujinx.Tests.Unicorn.csproj @@ -1,4 +1,4 @@ - + true @@ -7,7 +7,7 @@ - false + true diff --git a/src/Ryujinx.Tests/Audio/Renderer/Server/PoolMapperTests.cs b/src/Ryujinx.Tests/Audio/Renderer/Server/PoolMapperTests.cs index d7879d627..941afae6f 100644 --- a/src/Ryujinx.Tests/Audio/Renderer/Server/PoolMapperTests.cs +++ b/src/Ryujinx.Tests/Audio/Renderer/Server/PoolMapperTests.cs @@ -85,7 +85,6 @@ namespace Ryujinx.Tests.Audio.Renderer.Server memoryPoolStateArray[i].SetCpuAddress(CpuAddress + (ulong)i * CpuSize, CpuSize); } - AddressInfo addressInfo = AddressInfo.Create(); PoolMapper poolMapper = new(DummyProcessHandle, true); diff --git a/src/Ryujinx.Tests/Cpu/CpuTest.cs b/src/Ryujinx.Tests/Cpu/CpuTest.cs index 6f749463e..c01a9e4e8 100644 --- a/src/Ryujinx.Tests/Cpu/CpuTest.cs +++ b/src/Ryujinx.Tests/Cpu/CpuTest.cs @@ -13,11 +13,8 @@ namespace Ryujinx.Tests.Cpu public class CpuTest { protected static readonly ulong Size = MemoryBlock.GetPageSize(); -#pragma warning disable CA2211 // Non-constant fields should not be visible - protected static ulong CodeBaseAddress = Size; - protected static ulong DataBaseAddress = CodeBaseAddress + Size; -#pragma warning restore CA2211 - + protected static ulong CodeBaseAddress { get; set; } = Size; + protected static ulong DataBaseAddress { get; set; } = CodeBaseAddress + Size; private static readonly bool _ignoreFpcrFz = false; private static readonly bool _ignoreFpcrDn = false; diff --git a/src/Ryujinx.Tests/Cpu/CpuTest32.cs b/src/Ryujinx.Tests/Cpu/CpuTest32.cs index d4c8156d7..e742c1713 100644 --- a/src/Ryujinx.Tests/Cpu/CpuTest32.cs +++ b/src/Ryujinx.Tests/Cpu/CpuTest32.cs @@ -13,11 +13,8 @@ namespace Ryujinx.Tests.Cpu public class CpuTest32 { protected static readonly uint Size = (uint)MemoryBlock.GetPageSize(); -#pragma warning disable CA2211 // Non-constant fields should not be visible - protected static uint CodeBaseAddress = Size; - protected static uint DataBaseAddress = CodeBaseAddress + Size; -#pragma warning restore CA2211 - + protected static uint CodeBaseAddress { get; set; } = Size; + protected static uint DataBaseAddress { get; set; } = CodeBaseAddress + Size; private uint _currAddress; private MemoryBlock _ram; @@ -421,6 +418,7 @@ namespace Ryujinx.Tests.Cpu { ManageFpTolerances(fpTolerances); } + Assert.That(V128ToSimdValue(_context.GetV(1)), Is.EqualTo(_unicornEmu.Q[1]), "V1"); Assert.That(V128ToSimdValue(_context.GetV(2)), Is.EqualTo(_unicornEmu.Q[2]), "V2"); Assert.That(V128ToSimdValue(_context.GetV(3)), Is.EqualTo(_unicornEmu.Q[3]), "V3"); diff --git a/src/Ryujinx.Tests/Cpu/CpuTestAluRs32.cs b/src/Ryujinx.Tests/Cpu/CpuTestAluRs32.cs index a6f8976c6..48480f58b 100644 --- a/src/Ryujinx.Tests/Cpu/CpuTestAluRs32.cs +++ b/src/Ryujinx.Tests/Cpu/CpuTestAluRs32.cs @@ -35,7 +35,6 @@ namespace Ryujinx.Tests.Cpu } #endregion - [Test, Pairwise] public void Adc_Adcs_Rsc_Rscs_Sbc_Sbcs([ValueSource(nameof(_Adc_Adcs_Rsc_Rscs_Sbc_Sbcs_))] uint opcode, [Values(0u, 13u)] uint rd, diff --git a/src/Ryujinx.Tests/Cpu/CpuTestBf32.cs b/src/Ryujinx.Tests/Cpu/CpuTestBf32.cs index 197171b8d..2006ae5f8 100644 --- a/src/Ryujinx.Tests/Cpu/CpuTestBf32.cs +++ b/src/Ryujinx.Tests/Cpu/CpuTestBf32.cs @@ -65,6 +65,7 @@ namespace Ryujinx.Tests.Cpu { widthm1 -= (lsb + widthm1) - 31; } + uint opcode = 0xe7e00050u; // UBFX R0, R0, #0, #1 opcode |= ((rd & 0xf) << 12); opcode |= ((rn & 0xf) << 0); @@ -90,6 +91,7 @@ namespace Ryujinx.Tests.Cpu { widthm1 -= (lsb + widthm1) - 31; } + uint opcode = 0xe7a00050u; // SBFX R0, R0, #0, #1 opcode |= ((rd & 0xf) << 12); opcode |= ((rn & 0xf) << 0); diff --git a/src/Ryujinx.Tests/Cpu/CpuTestMisc32.cs b/src/Ryujinx.Tests/Cpu/CpuTestMisc32.cs index e984a1584..4921193a2 100644 --- a/src/Ryujinx.Tests/Cpu/CpuTestMisc32.cs +++ b/src/Ryujinx.Tests/Cpu/CpuTestMisc32.cs @@ -90,16 +90,19 @@ namespace Ryujinx.Tests.Cpu { Opcode(0xEEE10A10); // VMSR FPSCR, R0 } + Opcode(0xEEB48A4A); // VCMP.F32 S16, S20 if (mode2) { Opcode(0xEEF10A10); // VMRS R0, FPSCR Opcode(0xE200020F); // AND R0, #0xF0000000 // R0 &= "Fpsr.Nzcv". } + if (mode3) { Opcode(0xEEF1FA10); // VMRS APSR_NZCV, FPSCR } + Opcode(0xE12FFF1E); // BX LR ExecuteOpcodes(); diff --git a/src/Ryujinx.Tests/Cpu/CpuTestSimdMemory32.cs b/src/Ryujinx.Tests/Cpu/CpuTestSimdMemory32.cs index 9bc24b300..04310dbbe 100644 --- a/src/Ryujinx.Tests/Cpu/CpuTestSimdMemory32.cs +++ b/src/Ryujinx.Tests/Cpu/CpuTestSimdMemory32.cs @@ -267,6 +267,7 @@ namespace Ryujinx.Tests.Cpu opcode |= ((sd & 0x10) << 18); opcode |= ((sd & 0xf) << 12); } + opcode |= imm & 0xff; SingleOpcode(opcode, r0: _testOffset); @@ -302,6 +303,7 @@ namespace Ryujinx.Tests.Cpu opcode |= ((sd & 0x10) << 18); opcode |= ((sd & 0xf) << 12); } + opcode |= imm & 0xff; (V128 vec1, V128 vec2, _, _) = GenerateTestVectors(); diff --git a/src/Ryujinx.Tests/Cpu/CpuTestSimdMov32.cs b/src/Ryujinx.Tests/Cpu/CpuTestSimdMov32.cs index 3956115d1..17e8f4d40 100644 --- a/src/Ryujinx.Tests/Cpu/CpuTestSimdMov32.cs +++ b/src/Ryujinx.Tests/Cpu/CpuTestSimdMov32.cs @@ -459,6 +459,7 @@ namespace Ryujinx.Tests.Cpu { opcode |= 1 << 6; } + opcode |= (vm & 0x10) << 1; opcode |= (vm & 0xf); opcode |= (vd & 0x10) << 18; @@ -511,6 +512,7 @@ namespace Ryujinx.Tests.Cpu { return; // Undefined. } + opcode |= (vm & 0x10) << 1; opcode |= (vm & 0xf); opcode |= (vd & 0x10) << 18; diff --git a/src/Ryujinx.Tests/Cpu/CpuTestSimdRegElem.cs b/src/Ryujinx.Tests/Cpu/CpuTestSimdRegElem.cs index 810c617f0..4d765fe1d 100644 --- a/src/Ryujinx.Tests/Cpu/CpuTestSimdRegElem.cs +++ b/src/Ryujinx.Tests/Cpu/CpuTestSimdRegElem.cs @@ -82,7 +82,6 @@ namespace Ryujinx.Tests.Cpu } #endregion - [Test, Pairwise] public void Mla_Mls_Mul_Sqdmulh_Sqrdmulh_Ve_4H_8H([ValueSource(nameof(_Mla_Mls_Mul_Sqdmulh_Sqrdmulh_Ve_4H_8H_))] uint opcodes, [Values(0u)] uint rd, diff --git a/src/Ryujinx.Tests/Cpu/CpuTestT32Flow.cs b/src/Ryujinx.Tests/Cpu/CpuTestT32Flow.cs index 01159afc6..b73072207 100644 --- a/src/Ryujinx.Tests/Cpu/CpuTestT32Flow.cs +++ b/src/Ryujinx.Tests/Cpu/CpuTestT32Flow.cs @@ -100,6 +100,7 @@ namespace Ryujinx.Tests.Cpu { ThumbOpcode(0xe7fe); } + ThumbOpcode(0x4670); // label: MOV R0, LR ThumbOpcode(0x2100); // MOVS R1, #0 ThumbOpcode(0x468e); // MOV LR, R1 diff --git a/src/Ryujinx.Tests/Cpu/CpuTestThumb.cs b/src/Ryujinx.Tests/Cpu/CpuTestThumb.cs index 4e90fdeac..1f00c663d 100644 --- a/src/Ryujinx.Tests/Cpu/CpuTestThumb.cs +++ b/src/Ryujinx.Tests/Cpu/CpuTestThumb.cs @@ -111,6 +111,7 @@ namespace Ryujinx.Tests.Cpu Assert.That(GetContext().GetPstateFlag(PState.CFlag), Is.EqualTo(w1 >= imm)); Assert.That(GetContext().GetPstateFlag(PState.VFlag), Is.EqualTo((overflow >> 31) != 0)); } + break; case 2: Assert.That(GetContext().GetX(1), Is.EqualTo((w1 + imm) & 0xffffffffu)); @@ -166,6 +167,7 @@ namespace Ryujinx.Tests.Cpu Assert.That(GetContext().GetPstateFlag(PState.NFlag), Is.EqualTo((result >> 31) != 0)); Assert.That(GetContext().GetPstateFlag(PState.ZFlag), Is.EqualTo(result == 0)); } + break; case 9: Assert.That(GetContext().GetX(1), Is.EqualTo((uint)-w2)); @@ -180,6 +182,7 @@ namespace Ryujinx.Tests.Cpu Assert.That(GetContext().GetPstateFlag(PState.CFlag), Is.EqualTo(w1 >= w2)); Assert.That(GetContext().GetPstateFlag(PState.VFlag), Is.EqualTo((overflow >> 31) != 0)); } + break; case 11: Assert.That(GetContext().GetX(1), Is.EqualTo(w1)); @@ -191,6 +194,7 @@ namespace Ryujinx.Tests.Cpu Assert.That(GetContext().GetPstateFlag(PState.CFlag), Is.EqualTo(result < w1)); Assert.That(GetContext().GetPstateFlag(PState.VFlag), Is.EqualTo((overflow >> 31) != 0)); } + break; case 12: Assert.That(GetContext().GetX(1), Is.EqualTo(w1 | w2)); @@ -244,6 +248,7 @@ namespace Ryujinx.Tests.Cpu Assert.That(GetContext().GetPstateFlag(PState.CFlag), Is.EqualTo(w1 >= w2)); Assert.That(GetContext().GetPstateFlag(PState.VFlag), Is.EqualTo((overflow >> 31) != 0)); } + break; case 2: Assert.That(GetContext().GetX((int)rd), Is.EqualTo(w2)); diff --git a/src/Ryujinx.Tests/Cpu/EnvironmentTests.cs b/src/Ryujinx.Tests/Cpu/EnvironmentTests.cs index da4997e26..d67f22160 100644 --- a/src/Ryujinx.Tests/Cpu/EnvironmentTests.cs +++ b/src/Ryujinx.Tests/Cpu/EnvironmentTests.cs @@ -12,15 +12,13 @@ namespace Ryujinx.Tests.Cpu { internal class EnvironmentTests { -#pragma warning disable IDE0052 // Remove unread private member private static Translator _translator; -#pragma warning restore IDE0052 private static void EnsureTranslator() { // Create a translator, as one is needed to register the signal handler or emit methods. _translator ??= new Translator( - new JitMemoryAllocator(), + new JitMemoryAllocator(), new MockMemoryManager(), AddressTable.CreateForArm(true, MemoryManagerType.SoftwarePageTable)); } diff --git a/src/Ryujinx.Tests/Memory/PartialUnmaps.cs b/src/Ryujinx.Tests/Memory/PartialUnmaps.cs index e723a3c74..92b994279 100644 --- a/src/Ryujinx.Tests/Memory/PartialUnmaps.cs +++ b/src/Ryujinx.Tests/Memory/PartialUnmaps.cs @@ -14,6 +14,7 @@ using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; +using System.Runtime.Versioning; using System.Threading; namespace Ryujinx.Tests.Memory @@ -57,8 +58,8 @@ namespace Ryujinx.Tests.Memory { // Create a translator, as one is needed to register the signal handler or emit methods. _translator ??= new Translator( - new JitMemoryAllocator(), - new MockMemoryManager(), + new JitMemoryAllocator(), + new MockMemoryManager(), AddressTable.CreateForArm(true, MemoryManagerType.SoftwarePageTable)); } @@ -289,7 +290,7 @@ namespace Ryujinx.Tests.Memory [Test] // Only test in Windows, as this is only used on Windows and uses Windows APIs for trimming. [Platform("Win")] - [SuppressMessage("Interoperability", "CA1416: Validate platform compatibility")] + [SupportedOSPlatform("windows")] public void ThreadLocalMap() { PartialUnmapState.Reset(); diff --git a/src/Ryujinx.Tests/Ryujinx.Tests.csproj b/src/Ryujinx.Tests/Ryujinx.Tests.csproj index daa2b4287..2ac6410ef 100644 --- a/src/Ryujinx.Tests/Ryujinx.Tests.csproj +++ b/src/Ryujinx.Tests/Ryujinx.Tests.csproj @@ -1,4 +1,4 @@ - + Exe @@ -13,7 +13,7 @@ - false + true True diff --git a/src/Ryujinx.Tests/TreeDictionaryTests.cs b/src/Ryujinx.Tests/TreeDictionaryTests.cs index ea9fb0731..61ea88d7c 100644 --- a/src/Ryujinx.Tests/TreeDictionaryTests.cs +++ b/src/Ryujinx.Tests/TreeDictionaryTests.cs @@ -84,6 +84,7 @@ namespace Ryujinx.Tests.Collections { Console.WriteLine($"{node.Key} -> {node.Value}"); } + Assert.AreEqual(list.Count, dictionary.Count); Assert.AreEqual(list[0].Key, 4); Assert.AreEqual(list[1].Key, 2); @@ -118,6 +119,7 @@ namespace Ryujinx.Tests.Collections { Console.WriteLine($"{node.Key} -> {node.Value}"); } + Assert.AreEqual(list[0].Key, 4); Assert.AreEqual(list[1].Key, 2); Assert.AreEqual(list[2].Key, 10); @@ -149,6 +151,7 @@ namespace Ryujinx.Tests.Collections { Console.WriteLine($"{node.Key} -> {node.Value}"); } + Assert.AreEqual(list[0].Key, 4); Assert.AreEqual(list[1].Key, 2); Assert.AreEqual(list[2].Key, 9); @@ -224,7 +227,6 @@ namespace Ryujinx.Tests.Collections Assert.AreEqual(list[4].Value, 4); - // Assure that none of the nodes locations have been modified. Assert.AreEqual(list[0].Key, 4); Assert.AreEqual(list[1].Key, 2); diff --git a/src/Ryujinx.UI.LocaleGenerator/LocaleGenerator.cs b/src/Ryujinx.UI.LocaleGenerator/LocaleGenerator.cs index a3d16c660..4de92ee4a 100644 --- a/src/Ryujinx.UI.LocaleGenerator/LocaleGenerator.cs +++ b/src/Ryujinx.UI.LocaleGenerator/LocaleGenerator.cs @@ -26,6 +26,7 @@ namespace Ryujinx.UI.LocaleGenerator { enumSourceBuilder.AppendLine($" {line},"); } + enumSourceBuilder.AppendLine("}"); spc.AddSource("LocaleKeys", enumSourceBuilder.ToString()); diff --git a/src/Ryujinx/Common/ApplicationHelper.cs b/src/Ryujinx/Common/ApplicationHelper.cs index 0b81e8cff..afdab3af5 100644 --- a/src/Ryujinx/Common/ApplicationHelper.cs +++ b/src/Ryujinx/Common/ApplicationHelper.cs @@ -13,10 +13,10 @@ using LibHac.Tools.Fs; using LibHac.Tools.FsSystem; using LibHac.Tools.FsSystem.NcaUtils; using Ryujinx.Ava.Common.Locale; -using Ryujinx.Ava.UI.Windows; -using Ryujinx.Ava.UI.Helpers; -using Ryujinx.Ava.Utilities; using Ryujinx.Ava.Systems.Configuration; +using Ryujinx.Ava.UI.Helpers; +using Ryujinx.Ava.UI.Windows; +using Ryujinx.Ava.Utilities; using Ryujinx.Common.Helper; using Ryujinx.Common.Logging; using Ryujinx.HLE.FileSystem; @@ -292,7 +292,7 @@ namespace Ryujinx.Ava.Common }; extractorThread.Start(); } - + public static void ExtractAoc(string destination, string updateFilePath, string updateName) { CancellationTokenSource cancellationToken = new(); @@ -416,12 +416,12 @@ namespace Ryujinx.Ava.Common Title = LocaleManager.Instance[LocaleKeys.FolderDialogExtractTitle] }); - if (!result.HasValue) return; - + if (!result.HasValue) + return; + ExtractAoc(result.Value.Path.LocalPath, updateFilePath, updateName); } - public static async Task ExtractSection(IStorageProvider storageProvider, NcaSectionType ncaSectionType, string titleFilePath, string titleName, int programIndex = 0) { Optional result = await storageProvider.OpenSingleFolderPickerAsync(new FolderPickerOpenOptions @@ -429,7 +429,8 @@ namespace Ryujinx.Ava.Common Title = LocaleManager.Instance[LocaleKeys.FolderDialogExtractTitle] }); - if (!result.HasValue) return; + if (!result.HasValue) + return; ExtractSection(result.Value.Path.LocalPath, ncaSectionType, titleFilePath, titleName, programIndex); } diff --git a/src/Ryujinx/Common/LocaleManager.cs b/src/Ryujinx/Common/LocaleManager.cs index e6648fd7e..e5538603f 100644 --- a/src/Ryujinx/Common/LocaleManager.cs +++ b/src/Ryujinx/Common/LocaleManager.cs @@ -1,7 +1,7 @@ using Gommon; using Ryujinx.Ava.Systems; -using Ryujinx.Ava.UI.ViewModels; using Ryujinx.Ava.Systems.Configuration; +using Ryujinx.Ava.UI.ViewModels; using Ryujinx.Common; using Ryujinx.Common.Utilities; using System; @@ -49,7 +49,7 @@ namespace Ryujinx.Ava.Common.Locale { string localeLanguageCode = !string.IsNullOrEmpty(ConfigurationState.Instance.UI.LanguageCode.Value) ? ConfigurationState.Instance.UI.LanguageCode.Value : CultureInfo.CurrentCulture.Name.Replace('-', '_'); - + LoadLanguage(localeLanguageCode); // Save whatever we ended up with. @@ -64,8 +64,8 @@ namespace Ryujinx.Ava.Common.Locale public static string GetUnformatted(LocaleKeys key) => Instance.Get(key); public string Get(LocaleKeys key) => - _localeStrings.TryGetValue(key, out string value) - ? value + _localeStrings.TryGetValue(key, out string value) + ? value : key.ToString(); public string this[LocaleKeys key] @@ -89,7 +89,7 @@ namespace Ryujinx.Ava.Common.Locale return value; } - + return key.ToString(); // If the locale text doesn't exist return the key. } set @@ -116,7 +116,7 @@ namespace Ryujinx.Ava.Common.Locale OnPropertyChanged("Translation"); } - + public string UpdateAndGetDynamicValue(LocaleKeys key, params object[] values) { SetDynamicValues(key, values); @@ -162,8 +162,8 @@ namespace Ryujinx.Ava.Common.Locale if (locale.Translations.Count < _localeData.Value.Languages.Count) { throw new Exception($"Locale key {{{locale.ID}}} is missing languages! Has {locale.Translations.Count} translations, expected {_localeData.Value.Languages.Count}!"); - } - + } + if (locale.Translations.Count > _localeData.Value.Languages.Count) { throw new Exception($"Locale key {{{locale.ID}}} has too many languages! Has {locale.Translations.Count} translations, expected {_localeData.Value.Languages.Count}!"); @@ -175,7 +175,7 @@ namespace Ryujinx.Ava.Common.Locale string str = locale.Translations.TryGetValue(languageCode, out string val) && !string.IsNullOrEmpty(val) ? val : locale.Translations[DefaultLanguageCode]; - + if (string.IsNullOrEmpty(str)) { throw new Exception($"Locale key '{locale.ID}' has no valid translations for desired language {languageCode}! {DefaultLanguageCode} is an empty string or null"); diff --git a/src/Ryujinx/Common/Markup/BasicMarkupExtension.cs b/src/Ryujinx/Common/Markup/BasicMarkupExtension.cs index 364c08c0b..d55e3c9a7 100644 --- a/src/Ryujinx/Common/Markup/BasicMarkupExtension.cs +++ b/src/Ryujinx/Common/Markup/BasicMarkupExtension.cs @@ -1,4 +1,4 @@ -using Avalonia.Data.Core; +using Avalonia.Data.Core; using Avalonia.Markup.Xaml; using Avalonia.Markup.Xaml.MarkupExtensions; using Avalonia.Markup.Xaml.MarkupExtensions.CompiledBindings; @@ -27,7 +27,7 @@ namespace Ryujinx.Ava.Common.Markup Setter as Action, typeof(T)); - public override object ProvideValue(IServiceProvider serviceProvider) + public override object ProvideValue(IServiceProvider serviceProvider) => new CompiledBindingExtension( new CompiledBindingPathBuilder() .Property(PropertyInfo, PropertyInfoAccessorFactory.CreateInpcPropertyAccessor) diff --git a/src/Ryujinx/Common/Markup/MarkupExtensions.cs b/src/Ryujinx/Common/Markup/MarkupExtensions.cs index 2c8290847..b2ed01517 100644 --- a/src/Ryujinx/Common/Markup/MarkupExtensions.cs +++ b/src/Ryujinx/Common/Markup/MarkupExtensions.cs @@ -9,32 +9,32 @@ namespace Ryujinx.Ava.Common.Markup public override string Name => "Icon"; protected override Icon Value => new() { Value = iconString }; } - + internal class SpinningIconExtension(string iconString) : BasicMarkupExtension { public override string Name => "SIcon"; protected override Icon Value => new() { Value = iconString, Animation = IconAnimation.Spin }; } - + internal class LocaleExtension(LocaleKeys key) : BasicMarkupExtension { public override string Name => "Translation"; protected override string Value => LocaleManager.Instance[key]; - protected override void ConfigureBindingExtension(CompiledBindingExtension bindingExtension) + protected override void ConfigureBindingExtension(CompiledBindingExtension bindingExtension) => bindingExtension.Source = LocaleManager.Instance; } - + internal class WindowTitleExtension(LocaleKeys key, bool includeVersion) : BasicMarkupExtension { public WindowTitleExtension(LocaleKeys key) : this(key, true) { } - + public override string Name => "WindowTitleTranslation"; protected override string Value => RyujinxApp.FormatTitle(key, includeVersion); - protected override void ConfigureBindingExtension(CompiledBindingExtension bindingExtension) + protected override void ConfigureBindingExtension(CompiledBindingExtension bindingExtension) => bindingExtension.Source = LocaleManager.Instance; } } diff --git a/src/Ryujinx/Common/Models/Github/GithubReleasesJsonResponse.cs b/src/Ryujinx/Common/Models/Github/GithubReleasesJsonResponse.cs index dee912e1c..af00121fe 100644 --- a/src/Ryujinx/Common/Models/Github/GithubReleasesJsonResponse.cs +++ b/src/Ryujinx/Common/Models/Github/GithubReleasesJsonResponse.cs @@ -5,7 +5,7 @@ namespace Ryujinx.Ava.Common.Models.Github public class GithubReleasesJsonResponse { public string Name { get; set; } - + public string TagName { get; set; } public List Assets { get; set; } } diff --git a/src/Ryujinx/Common/Models/XCITrimmerFileModel.cs b/src/Ryujinx/Common/Models/XCITrimmerFileModel.cs index cddc5de22..233ac2b6d 100644 --- a/src/Ryujinx/Common/Models/XCITrimmerFileModel.cs +++ b/src/Ryujinx/Common/Models/XCITrimmerFileModel.cs @@ -34,8 +34,8 @@ namespace Ryujinx.Ava.Common.Models { get { - return ProcessingOutcome != XCIFileTrimmer.OperationOutcome.Undetermined && - ProcessingOutcome != XCIFileTrimmer.OperationOutcome.Successful; + return ProcessingOutcome is not XCIFileTrimmer.OperationOutcome.Undetermined and + not XCIFileTrimmer.OperationOutcome.Successful; } } @@ -43,10 +43,10 @@ namespace Ryujinx.Ava.Common.Models { if (obj == null) return false; - + return this.Path == obj.Path; } - + public override int GetHashCode() { return this.Path.GetHashCode(); diff --git a/src/Ryujinx/Common/XCITrimmerLog.cs b/src/Ryujinx/Common/XCITrimmerLog.cs index 751831a66..3f840abba 100644 --- a/src/Ryujinx/Common/XCITrimmerLog.cs +++ b/src/Ryujinx/Common/XCITrimmerLog.cs @@ -23,7 +23,7 @@ namespace Ryujinx.Ava.Common }); } } - + internal class TrimmerWindow : Ryujinx.Common.Logging.XCIFileTrimmerLog { private readonly XciTrimmerViewModel _viewModel; diff --git a/src/Ryujinx/Headless/HeadlessRyujinx.Init.cs b/src/Ryujinx/Headless/HeadlessRyujinx.Init.cs index a2f5af24c..f15d24e8a 100644 --- a/src/Ryujinx/Headless/HeadlessRyujinx.Init.cs +++ b/src/Ryujinx/Headless/HeadlessRyujinx.Init.cs @@ -52,7 +52,7 @@ namespace Ryujinx.Headless // Logging system information. Program.PrintSystemInfo(); } - + private static InputConfig HandlePlayerConfiguration(string inputProfileName, string inputId, PlayerIndex index) { if (inputId == null) @@ -280,7 +280,7 @@ namespace Ryujinx.Headless return config; } - + private static IRenderer CreateRenderer(Options options, WindowBase window) { if (options.GraphicsBackend == GraphicsBackend.Vulkan && window is VulkanWindow vulkanWindow) @@ -295,7 +295,7 @@ namespace Ryujinx.Headless foreach (DeviceInfo device in devices) { - if (device.Vendor.ToLowerInvariant() == preferredGpuVendor) + if (device.Vendor.Equals(preferredGpuVendor, StringComparison.OrdinalIgnoreCase)) { preferredGpuId = device.Id; break; @@ -312,7 +312,7 @@ namespace Ryujinx.Headless return new OpenGLRenderer(); } - + private static Switch InitializeEmulationContext(WindowBase window, IRenderer renderer, Options options) => new( new HleConfiguration( diff --git a/src/Ryujinx/Headless/HeadlessRyujinx.cs b/src/Ryujinx/Headless/HeadlessRyujinx.cs index 288b6ecce..9a06482f9 100644 --- a/src/Ryujinx/Headless/HeadlessRyujinx.cs +++ b/src/Ryujinx/Headless/HeadlessRyujinx.cs @@ -86,23 +86,23 @@ namespace Ryujinx.Headless .WithNotParsed(errors => { Logger.Error?.PrintMsg(LogClass.Application, "Error parsing command-line arguments:"); - + errors.ForEach(err => Logger.Error?.PrintMsg(LogClass.Application, $" - {err.Tag}")); }); } - + public static void ReloadConfig(string customConfigPath = null) { string localConfigurationPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, ReleaseInformation.ConfigName); string appDataConfigurationPath = Path.Combine(AppDataManager.BaseDirPath, ReleaseInformation.ConfigName); string configurationPath = null; - + // Now load the configuration as the other subsystems are now registered if (customConfigPath != null && File.Exists(customConfigPath)) { configurationPath = customConfigPath; - } + } else if (File.Exists(localConfigurationPath)) { configurationPath = localConfigurationPath; @@ -150,10 +150,10 @@ namespace Ryujinx.Headless } AppDataManager.Initialize(option.BaseDataDir); - + if (useLastUsedProfile && AccountSaveDataManager.GetLastUsedUser().TryGet(out UserProfile profile)) option.UserProfile = profile.Name; - + // Check if keys exists. if (!File.Exists(Path.Combine(AppDataManager.KeysDirPath, "prod.keys"))) { @@ -162,12 +162,12 @@ namespace Ryujinx.Headless Logger.Error?.Print(LogClass.Application, "Keys not found"); } } - + ReloadConfig(); if (!option.DisableMainInputConfig) option.InheritMainConfigInput(originalArgs, ConfigurationState.Instance); - + _virtualFileSystem = VirtualFileSystem.CreateInstance(); _libHacHorizonManager = new LibHacHorizonManager(); @@ -228,9 +228,9 @@ namespace Ryujinx.Headless _inputConfiguration ??= []; _enableKeyboard = option.EnableKeyboard; _enableMouse = option.EnableMouse; - + LoadPlayerConfiguration(option.InputProfile1Name, option.InputId1, PlayerIndex.Player1); - LoadPlayerConfiguration(option.InputProfile2Name, option.InputId2, PlayerIndex.Player2); + LoadPlayerConfiguration(option.InputProfile2Name, option.InputId2, PlayerIndex.Player2); LoadPlayerConfiguration(option.InputProfile3Name, option.InputId3, PlayerIndex.Player3); LoadPlayerConfiguration(option.InputProfile4Name, option.InputId4, PlayerIndex.Player4); LoadPlayerConfiguration(option.InputProfile5Name, option.InputId5, PlayerIndex.Player5); @@ -238,7 +238,7 @@ namespace Ryujinx.Headless LoadPlayerConfiguration(option.InputProfile7Name, option.InputId7, PlayerIndex.Player7); LoadPlayerConfiguration(option.InputProfile8Name, option.InputId8, PlayerIndex.Player8); LoadPlayerConfiguration(option.InputProfileHandheldName, option.InputIdHandheld, PlayerIndex.Handheld); - + if (_inputConfiguration.Count == 0) { return; @@ -286,7 +286,7 @@ namespace Ryujinx.Headless GraphicsConfig.EnableMacroHLE = !option.DisableMacroHLE; DriverUtilities.InitDriverConfig(option.BackendThreading == BackendThreading.Off); - + if (_inputConfiguration.OfType() .Any(ic => ic?.Led?.UseRainbow ?? false)) Rainbow.Enable(); @@ -306,10 +306,11 @@ namespace Ryujinx.Headless try { _inputManager.Dispose(); - } catch {} + } + catch { } return; - + void LoadPlayerConfiguration(string inputProfileName, string inputId, PlayerIndex index) { if (index == PlayerIndex.Handheld && _inputConfiguration.Count > 0) @@ -317,7 +318,7 @@ namespace Ryujinx.Headless Logger.Info?.Print(LogClass.Configuration, "Skipping handheld configuration as there are already other players configured."); return; } - + InputConfig inputConfig = option.InheritedInputConfigs[index] ?? HandlePlayerConfiguration(inputProfileName, inputId, index); if (inputConfig != null) @@ -454,6 +455,7 @@ namespace Ryujinx.Headless return false; } + break; case ".nca": Logger.Info?.Print(LogClass.Application, "Loading as NCA."); @@ -464,6 +466,7 @@ namespace Ryujinx.Headless return false; } + break; case ".nsp": case ".pfs0": @@ -475,6 +478,7 @@ namespace Ryujinx.Headless return false; } + break; default: Logger.Info?.Print(LogClass.Application, "Loading as Homebrew."); @@ -495,6 +499,7 @@ namespace Ryujinx.Headless return false; } + break; } } diff --git a/src/Ryujinx/Headless/Options.cs b/src/Ryujinx/Headless/Options.cs index 162758afa..49050005c 100644 --- a/src/Ryujinx/Headless/Options.cs +++ b/src/Ryujinx/Headless/Options.cs @@ -24,7 +24,7 @@ namespace Ryujinx.Headless if (NeedsOverride(nameof(EnableKeyboard))) EnableKeyboard = configurationState.Hid.EnableKeyboard; - + if (NeedsOverride(nameof(EnableMouse))) EnableMouse = configurationState.Hid.EnableMouse; @@ -39,40 +39,40 @@ namespace Ryujinx.Headless if (NeedsOverride(nameof(DisableFsIntegrityChecks))) DisableFsIntegrityChecks = !configurationState.System.EnableFsIntegrityChecks; - + if (NeedsOverride(nameof(FsGlobalAccessLogMode))) FsGlobalAccessLogMode = configurationState.System.FsGlobalAccessLogMode; - + if (NeedsOverride(nameof(VSyncMode))) VSyncMode = configurationState.Graphics.VSyncMode; - + if (NeedsOverride(nameof(CustomVSyncInterval))) CustomVSyncInterval = configurationState.Graphics.CustomVSyncInterval; - + if (NeedsOverride(nameof(DisableShaderCache))) DisableShaderCache = !configurationState.Graphics.EnableShaderCache; if (NeedsOverride(nameof(EnableTextureRecompression))) EnableTextureRecompression = configurationState.Graphics.EnableTextureRecompression; - + if (NeedsOverride(nameof(DisableDockedMode))) DisableDockedMode = !configurationState.System.EnableDockedMode; if (NeedsOverride(nameof(SystemLanguage))) SystemLanguage = configurationState.System.Language.Value.ToHLE(); - + if (NeedsOverride(nameof(SystemRegion))) SystemRegion = configurationState.System.Region.Value.ToHLE(); - + if (NeedsOverride(nameof(SystemTimeZone))) SystemTimeZone = configurationState.System.TimeZone; - + if (NeedsOverride(nameof(SystemTimeOffset))) SystemTimeOffset = configurationState.System.SystemTimeOffset; - + if (NeedsOverride(nameof(MemoryManagerMode))) MemoryManagerMode = configurationState.System.MemoryManagerMode; - + if (NeedsOverride(nameof(AudioVolume))) AudioVolume = configurationState.System.AudioVolume; @@ -81,28 +81,28 @@ namespace Ryujinx.Headless if (NeedsOverride(nameof(MultiplayerLanInterfaceId))) MultiplayerLanInterfaceId = configurationState.Multiplayer.LanInterfaceId; - + if (NeedsOverride(nameof(DisableFileLog))) DisableFileLog = !configurationState.Logger.EnableFileLog; - + if (NeedsOverride(nameof(LoggingEnableDebug))) LoggingEnableDebug = configurationState.Logger.EnableDebug; - + if (NeedsOverride(nameof(LoggingDisableStub))) LoggingDisableStub = !configurationState.Logger.EnableStub; - + if (NeedsOverride(nameof(LoggingDisableInfo))) LoggingDisableInfo = !configurationState.Logger.EnableInfo; - + if (NeedsOverride(nameof(LoggingDisableWarning))) LoggingDisableWarning = !configurationState.Logger.EnableWarn; - + if (NeedsOverride(nameof(LoggingDisableError))) LoggingDisableError = !configurationState.Logger.EnableError; - + if (NeedsOverride(nameof(LoggingEnableTrace))) LoggingEnableTrace = configurationState.Logger.EnableTrace; - + if (NeedsOverride(nameof(LoggingDisableGuest))) LoggingDisableGuest = !configurationState.Logger.EnableGuest; @@ -114,40 +114,40 @@ namespace Ryujinx.Headless if (NeedsOverride(nameof(ResScale))) ResScale = configurationState.Graphics.ResScale; - + if (NeedsOverride(nameof(MaxAnisotropy))) MaxAnisotropy = configurationState.Graphics.MaxAnisotropy; - + if (NeedsOverride(nameof(AspectRatio))) AspectRatio = configurationState.Graphics.AspectRatio; - + if (NeedsOverride(nameof(BackendThreading))) BackendThreading = configurationState.Graphics.BackendThreading; - + if (NeedsOverride(nameof(DisableMacroHLE))) DisableMacroHLE = !configurationState.Graphics.EnableMacroHLE; - + if (NeedsOverride(nameof(GraphicsShadersDumpPath))) GraphicsShadersDumpPath = configurationState.Graphics.ShadersDumpPath; - + if (NeedsOverride(nameof(GraphicsBackend))) GraphicsBackend = configurationState.Graphics.GraphicsBackend; - + if (NeedsOverride(nameof(AntiAliasing))) AntiAliasing = configurationState.Graphics.AntiAliasing; - + if (NeedsOverride(nameof(ScalingFilter))) ScalingFilter = configurationState.Graphics.ScalingFilter; - + if (NeedsOverride(nameof(ScalingFilterLevel))) ScalingFilterLevel = configurationState.Graphics.ScalingFilterLevel; if (NeedsOverride(nameof(DramSize))) DramSize = configurationState.System.DramSize; - + if (NeedsOverride(nameof(IgnoreMissingServices))) IgnoreMissingServices = configurationState.System.IgnoreMissingServices; - + if (NeedsOverride(nameof(IgnoreControllerApplet))) IgnoreControllerApplet = configurationState.System.IgnoreControllerApplet; @@ -155,7 +155,7 @@ namespace Ryujinx.Headless SkipUserProfilesManager = configurationState.System.SkipUserProfilesManager; return; - + bool NeedsOverride(string argKey) => originalArgs.None(arg => arg.TrimStart('-').EqualsIgnoreCase(OptionName(argKey))); } @@ -182,18 +182,18 @@ namespace Ryujinx.Headless } return; - + bool NeedsOverride(string argKey) => originalArgs.None(arg => arg.TrimStart('-').EqualsIgnoreCase(OptionName(argKey))); } private static string OptionName(string propertyName) => typeof(Options)!.GetProperty(propertyName)!.GetCustomAttribute()!.LongName; - + // General - + [Option("use-main-config", Required = false, Default = false, HelpText = "Use the settings from what was configured via the UI.")] public bool InheritConfig { get; set; } - + [Option("disable-main-input-config", Required = false, Default = false, HelpText = "Do not use the input-related settings from what was configured via the UI.")] public bool DisableMainInputConfig { get; set; } @@ -416,7 +416,7 @@ namespace Ryujinx.Headless [Option("ignore-missing-services", Required = false, Default = false, HelpText = "Enable ignoring missing services.")] public bool IgnoreMissingServices { get; set; } - + [Option("ignore-controller-applet", Required = false, Default = false, HelpText = "Enable ignoring the controller applet when your game loses connection to your controller.")] public bool IgnoreControllerApplet { get; set; } diff --git a/src/Ryujinx/Headless/Windows/OpenGLWindow.cs b/src/Ryujinx/Headless/Windows/OpenGLWindow.cs index 117fe5780..02f24f218 100644 --- a/src/Ryujinx/Headless/Windows/OpenGLWindow.cs +++ b/src/Ryujinx/Headless/Windows/OpenGLWindow.cs @@ -108,7 +108,7 @@ namespace Ryujinx.Headless } } } - + private SDL2OpenGLContext _openGLContext; public OpenGLWindow( diff --git a/src/Ryujinx/Headless/Windows/WindowBase.cs b/src/Ryujinx/Headless/Windows/WindowBase.cs index 081998a00..14b090264 100644 --- a/src/Ryujinx/Headless/Windows/WindowBase.cs +++ b/src/Ryujinx/Headless/Windows/WindowBase.cs @@ -226,6 +226,7 @@ namespace Ryujinx.Headless Renderer?.Window.SetSize(Width, Height); MouseDriver.SetClientSize(Width, Height); } + break; case SDL_WindowEventID.SDL_WINDOWEVENT_CLOSE: @@ -488,8 +489,9 @@ namespace Ryujinx.Headless public bool DisplayMessageDialog(ControllerAppletUIArgs args) { - if (_ignoreControllerApplet) return false; - + if (_ignoreControllerApplet) + return false; + string playerCount = args.PlayerCountMin == args.PlayerCountMax ? $"exactly {args.PlayerCountMin}" : $"{args.PlayerCountMin}-{args.PlayerCountMax}"; string message = $"Application requests {playerCount} {"player".ToQuantity(args.PlayerCountMin + args.PlayerCountMax, ShowQuantityAs.None)} with:\n\n" @@ -558,7 +560,7 @@ namespace Ryujinx.Headless SDL2Driver.Instance.Dispose(); } } - + public UserProfile ShowPlayerSelectDialog() { return AccountSaveDataManager.GetLastUsedUser(); diff --git a/src/Ryujinx/Input/AvaloniaKeyboardDriver.cs b/src/Ryujinx/Input/AvaloniaKeyboardDriver.cs index 89b2c29ce..5fbfb1bbf 100644 --- a/src/Ryujinx/Input/AvaloniaKeyboardDriver.cs +++ b/src/Ryujinx/Input/AvaloniaKeyboardDriver.cs @@ -86,7 +86,7 @@ namespace Ryujinx.Ava.Input internal bool IsPressed(Key key) { - if (key == Key.Unbound || key == Key.Unknown) + if (key is Key.Unbound or Key.Unknown) { return false; } diff --git a/src/Ryujinx/Program.cs b/src/Ryujinx/Program.cs index 016cc348a..94a65b731 100644 --- a/src/Ryujinx/Program.cs +++ b/src/Ryujinx/Program.cs @@ -6,11 +6,11 @@ using Projektanker.Icons.Avalonia; using Projektanker.Icons.Avalonia.FontAwesome; using Projektanker.Icons.Avalonia.MaterialDesign; using Ryujinx.Ava.Systems; +using Ryujinx.Ava.Systems.Configuration; +using Ryujinx.Ava.Systems.Configuration.System; using Ryujinx.Ava.UI.Helpers; using Ryujinx.Ava.UI.Windows; using Ryujinx.Ava.Utilities; -using Ryujinx.Ava.Systems.Configuration; -using Ryujinx.Ava.Systems.Configuration.System; using Ryujinx.Ava.Utilities.SystemInfo; using Ryujinx.Common; using Ryujinx.Common.Configuration; @@ -47,7 +47,7 @@ namespace Ryujinx.Ava public static int Main(string[] args) { Version = ReleaseInformation.Version; - + if (OperatingSystem.IsWindows() && !OperatingSystem.IsWindowsVersionAtLeast(10, 0, 19041)) { _ = MessageBoxA(nint.Zero, "You are running an outdated version of Windows.\n\nRyujinx supports Windows 10 version 20H1 and newer.\n", $"Ryujinx {Version}", MbIconwarning); @@ -55,7 +55,7 @@ namespace Ryujinx.Ava } PreviewerDetached = true; - + if (args.Length > 0 && args[0] is "--no-gui" or "nogui") { HeadlessRyujinx.Entrypoint(args[1..]); @@ -63,7 +63,7 @@ namespace Ryujinx.Ava } Initialize(args); - + LoggerAdapter.Register(); IconProvider.Current @@ -115,11 +115,10 @@ namespace Ryujinx.Ava AppDomain.CurrentDomain.UnhandledException += (sender, e) => ProcessUnhandledException(sender, e.ExceptionObject as Exception, e.IsTerminating); TaskScheduler.UnobservedTaskException += (sender, e) - => ProcessUnhandledException(sender, e.Exception, false); + => ProcessUnhandledException(sender, e.Exception, false); AppDomain.CurrentDomain.ProcessExit += (_, _) => Exit(); - // Setup base data directory. AppDataManager.Initialize(CommandLineState.BaseDirPathArg); @@ -191,7 +190,6 @@ namespace Ryujinx.Ava string localConfigurationPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, ReleaseInformation.ConfigName); string appDataConfigurationPath = Path.Combine(AppDataManager.BaseDirPath, ReleaseInformation.ConfigName); - // Now load the configuration as the other subsystems are now registered if (File.Exists(localConfigurationPath)) { @@ -257,7 +255,6 @@ namespace Ryujinx.Ava if (CommandLineState.OverrideDockedMode.HasValue) ConfigurationState.Instance.System.EnableDockedMode.Value = CommandLineState.OverrideDockedMode.Value; - // Check if HideCursor was overridden. if (CommandLineState.OverrideHideCursor is not null) ConfigurationState.Instance.HideCursor.Value = CommandLineState.OverrideHideCursor.ToLower() switch @@ -307,13 +304,11 @@ namespace Ryujinx.Ava Logger.Notice.Print(LogClass.Application, $".NET Runtime: {RuntimeInformation.FrameworkDescription}"); SystemInfo.Gather().Print(); - Logger.Notice.Print(LogClass.Application, $"Logs Enabled: { - Logger.GetEnabledLevels() + Logger.Notice.Print(LogClass.Application, $"Logs Enabled: {Logger.GetEnabledLevels() .FormatCollection( - x => x.ToString(), - separator: ", ", - emptyCollectionFallback: "") - }"); + x => x.ToString(), + separator: ", ", + emptyCollectionFallback: "")}"); Logger.Notice.Print(LogClass.Application, AppDataManager.Mode == AppDataManager.LaunchMode.Custom @@ -345,8 +340,8 @@ namespace Ryujinx.Ava else log.PrintMsg(LogClass.Application, message); } - - + + if (isTerminating) Exit(); } diff --git a/src/Ryujinx/Systems/AppHost.cs b/src/Ryujinx/Systems/AppHost.cs index c20b89b5e..d8cf729e3 100644 --- a/src/Ryujinx/Systems/AppHost.cs +++ b/src/Ryujinx/Systems/AppHost.cs @@ -15,14 +15,14 @@ using Ryujinx.Audio.Integration; using Ryujinx.Ava.Common; using Ryujinx.Ava.Common.Locale; using Ryujinx.Ava.Input; +using Ryujinx.Ava.Systems.AppLibrary; +using Ryujinx.Ava.Systems.Configuration; using Ryujinx.Ava.UI.Helpers; using Ryujinx.Ava.UI.Models; using Ryujinx.Ava.UI.Renderer; using Ryujinx.Ava.UI.ViewModels; using Ryujinx.Ava.UI.Windows; using Ryujinx.Ava.Utilities; -using Ryujinx.Ava.Systems.AppLibrary; -using Ryujinx.Ava.Systems.Configuration; using Ryujinx.Common; using Ryujinx.Common.Configuration; using Ryujinx.Common.Configuration.Multiplayer; @@ -307,7 +307,7 @@ namespace Ryujinx.Ava.Systems Device.VSyncMode = e.NewValue; Device.UpdateVSyncInterval(); } - + _renderer.Window?.ChangeVSyncMode(e.NewValue); _viewModel.UpdateVSyncIntervalPicker(); @@ -319,7 +319,7 @@ namespace Ryujinx.Ava.Systems bool customVSyncIntervalEnabled = ConfigurationState.Instance.Graphics.EnableCustomVSyncInterval.Value; UpdateVSyncMode(this, new ReactiveEventArgs( - oldVSyncMode, + oldVSyncMode, oldVSyncMode.Next(customVSyncIntervalEnabled)) ); } @@ -480,7 +480,7 @@ namespace Ryujinx.Ava.Systems _renderingThread.Start(); _viewModel.Volume = ConfigurationState.Instance.System.AudioVolume.Value; - + Rainbow.Enable(); MainLoop(); @@ -575,7 +575,7 @@ namespace Ryujinx.Ava.Systems } DiscordIntegrationModule.GuestAppStartedAt = null; - + Rainbow.Disable(); Rainbow.Reset(); @@ -610,7 +610,6 @@ namespace Ryujinx.Ava.Systems if (Device.Processes != null) MainWindowViewModel.UpdateGameMetadata(Device.Processes.ActiveApplication.ProgramIdText); - ConfigurationState.Instance.System.IgnoreMissingServices.Event -= UpdateIgnoreMissingServicesState; ConfigurationState.Instance.Graphics.AspectRatio.Event -= UpdateAspectRatioState; ConfigurationState.Instance.System.EnableDockedMode.Event -= UpdateDockedModeState; @@ -667,7 +666,7 @@ namespace Ryujinx.Ava.Systems public async Task LoadGuestApplication(BlitStruct? customNacpData = null) { DiscordIntegrationModule.GuestAppStartedAt = Timestamps.Now; - + InitEmulatedSwitch(); MainWindow.UpdateGraphicsConfig(); @@ -751,7 +750,7 @@ namespace Ryujinx.Ava.Systems { romFsFiles = Directory.GetFiles(ApplicationPath, "*.romfs"); } - + Logger.Notice.Print(LogClass.Application, $"Loading unpacked content archive from '{ApplicationPath}'."); if (romFsFiles.Length > 0) @@ -780,7 +779,7 @@ namespace Ryujinx.Ava.Systems else if (File.Exists(ApplicationPath)) { Logger.Notice.Print(LogClass.Application, $"Loading content archive from '{ApplicationPath}'."); - + switch (Path.GetExtension(ApplicationPath).ToLowerInvariant()) { case ".xci": @@ -857,7 +856,7 @@ namespace Ryujinx.Ava.Systems return false; } - + ApplicationLibrary.LoadAndSaveMetaData(Device.Processes.ActiveApplication.ProgramIdText, appMetadata => appMetadata.UpdatePreGame() ); @@ -1077,7 +1076,7 @@ namespace Ryujinx.Ava.Systems }); (RendererHost.EmbeddedWindow as EmbeddedWindowOpenGL)?.MakeCurrent(true); - + // Reload settings when the game is turned off // (resets custom settings if there were any) Program.ReloadConfig(); @@ -1160,7 +1159,7 @@ namespace Ryujinx.Ava.Systems { if (_displayCount is 0 && _renderer.ProgramCount is 0) return; - + // If there is a mismatch between total program compile and previous count // this means new shaders have been compiled and should be displayed. if (_renderer.ProgramCount != _previousCount) @@ -1233,7 +1232,7 @@ namespace Ryujinx.Ava.Systems { Device.ToggleTurbo(); } - + switch (currentHotkeyState) { case KeyboardHotkeyState.ToggleVSyncMode: @@ -1250,6 +1249,7 @@ namespace Ryujinx.Ava.Systems { Device.ToggleTurbo(); } + break; case KeyboardHotkeyState.Screenshot: ScreenshotRequested = true; @@ -1266,6 +1266,7 @@ namespace Ryujinx.Ava.Systems { Pause(); } + break; case KeyboardHotkeyState.ToggleMute: if (Device.IsAudioMuted()) diff --git a/src/Ryujinx/Systems/AppLibrary/ApplicationData.cs b/src/Ryujinx/Systems/AppLibrary/ApplicationData.cs index 9e288e9a1..5656d6e73 100644 --- a/src/Ryujinx/Systems/AppLibrary/ApplicationData.cs +++ b/src/Ryujinx/Systems/AppLibrary/ApplicationData.cs @@ -9,8 +9,8 @@ using LibHac.Tools.Fs; using LibHac.Tools.FsSystem; using LibHac.Tools.FsSystem.NcaUtils; using Ryujinx.Ava.Common.Locale; -using Ryujinx.Ava.Utilities; using Ryujinx.Ava.Systems.PlayReport; +using Ryujinx.Ava.Utilities; using Ryujinx.Common.Logging; using Ryujinx.HLE.FileSystem; using Ryujinx.HLE.Loaders.Processes.Extensions; @@ -37,13 +37,13 @@ namespace Ryujinx.Ava.Systems.AppLibrary _id = value; Compatibility = CompatibilityDatabase.Find(value); - RichPresenceSpec = PlayReports.Analyzer.TryGetSpec(IdString, out GameSpec gameSpec) - ? gameSpec + RichPresenceSpec = PlayReports.Analyzer.TryGetSpec(IdString, out GameSpec gameSpec) + ? gameSpec : default(Optional); } } public Optional RichPresenceSpec { get; set; } - + public string Developer { get; set; } = "Unknown"; public string Version { get; set; } = "0"; public int PlayerCount { get; set; } @@ -53,7 +53,7 @@ namespace Ryujinx.Ava.Systems.AppLibrary public bool HasRichPresenceAsset => DiscordIntegrationModule.HasAssetImage(IdString); public bool HasDynamicRichPresenceSupport => RichPresenceSpec.HasValue; - + public TimeSpan TimePlayed { get; set; } public DateTime? LastPlayed { get; set; } public string FileExtension { get; set; } @@ -70,22 +70,22 @@ namespace Ryujinx.Ava.Systems.AppLibrary public string LastPlayedString => ValueFormatUtils.FormatDateTime(LastPlayed)?.Replace(" ", "\n"); public string FileSizeString => ValueFormatUtils.FormatFileSize(FileSize); - + public Optional Compatibility { get; private set; } - + public bool HasPlayabilityInfo => Compatibility.HasValue; public string LocalizedStatus => Compatibility.Convert(x => x.LocalizedStatus); public bool HasCompatibilityLabels => !FormattedCompatibilityLabels.Equals(string.Empty); - + public string FormattedCompatibilityLabels => Compatibility.Convert(x => x.FormattedIssueLabels).OrElse(string.Empty); - + public LocaleKeys? PlayabilityStatus => Compatibility.Convert(x => x.Status).OrElse(null); public string LocalizedStatusTooltip => - Compatibility.Convert(x => + Compatibility.Convert(x => #pragma warning disable CS8509 // It is exhaustive for all possible values this can contain. LocaleManager.Instance[x.Status switch #pragma warning restore CS8509 @@ -97,7 +97,7 @@ namespace Ryujinx.Ava.Systems.AppLibrary LocaleKeys.CompatibilityListNothing => LocaleKeys.CompatibilityListNothingTooltip, }] ).OrElse(string.Empty); - + [JsonIgnore] public string IdString => Id.ToString("x16"); @@ -112,7 +112,7 @@ namespace Ryujinx.Ava.Systems.AppLibrary Logger.Error?.Print(LogClass.Application, $"File \"{titleFilePath}\" does not exist."); return string.Empty; } - + using FileStream file = new(titleFilePath, FileMode.Open, FileAccess.Read); Nca mainNca = null; diff --git a/src/Ryujinx/Systems/AppLibrary/ApplicationLibrary.cs b/src/Ryujinx/Systems/AppLibrary/ApplicationLibrary.cs index 9ac484768..b5367ffee 100644 --- a/src/Ryujinx/Systems/AppLibrary/ApplicationLibrary.cs +++ b/src/Ryujinx/Systems/AppLibrary/ApplicationLibrary.cs @@ -12,9 +12,9 @@ using LibHac.Tools.Fs; using LibHac.Tools.FsSystem; using LibHac.Tools.FsSystem.NcaUtils; using Ryujinx.Ava.Common.Models; -using Ryujinx.Ava.Utilities; using Ryujinx.Ava.Systems.Configuration; using Ryujinx.Ava.Systems.Configuration.System; +using Ryujinx.Ava.Utilities; using Ryujinx.Common; using Ryujinx.Common.Configuration; using Ryujinx.Common.Configuration.Multiplayer; @@ -151,7 +151,7 @@ namespace Ryujinx.Ava.Systems.AppLibrary if (!DownloadableContents.Keys.FindFirst(x => x.TitleId == id).TryGet(out DownloadableContentModel dlcData)) return id.ToString("X16"); - + string name = Path.GetFileNameWithoutExtension(dlcData.FileName)!; int idx = name.IndexOf('['); if (idx != -1) @@ -167,28 +167,28 @@ namespace Ryujinx.Ava.Systems.AppLibrary return appData.HasValue; } - + public bool FindUpdate(ulong id, out TitleUpdateModel foundData) { - Gommon.Optional appData = + Gommon.Optional appData = TitleUpdates.Keys.FindFirst(x => x.TitleId == id); foundData = appData.HasValue ? appData.Value : null; return appData.HasValue; } - + public TitleUpdateModel[] FindUpdatesFor(ulong id) => TitleUpdates.Keys.Where(x => x.TitleIdBase == (id & ~0x1FFFUL)).ToArray(); - + public (TitleUpdateModel TitleUpdate, bool IsSelected)[] FindUpdateConfigurationFor(ulong id) => TitleUpdates.Items.Where(x => x.TitleUpdate.TitleIdBase == (id & ~0x1FFFUL)).ToArray(); - + public DownloadableContentModel[] FindDlcsFor(ulong id) => DownloadableContents.Keys.Where(x => x.TitleIdBase == (id & ~0x1FFFUL)).ToArray(); - + public (DownloadableContentModel Dlc, bool IsEnabled)[] FindDlcConfigurationFor(ulong id) => DownloadableContents.Items.Where(x => x.Dlc.TitleIdBase == (id & ~0x1FFFUL)).ToArray(); - + public bool HasDlcs(ulong id) => DownloadableContents.Keys.Any(x => x.TitleIdBase == (id & ~0x1FFFUL)); @@ -260,8 +260,8 @@ namespace Ryujinx.Ava.Systems.AppLibrary } } - return isExeFs - ? GetApplicationFromExeFs(pfs, filePath) + return isExeFs + ? GetApplicationFromExeFs(pfs, filePath) : null; } @@ -529,7 +529,7 @@ namespace Ryujinx.Ava.Systems.AppLibrary if (data.Id != 0) { ApplicationMetadata appMetadata = LoadAndSaveMetaData(data.IdString, appMetadata => - { + { appMetadata.Title = data.Name; // Only do the migration if time_played has a value and timespan_played hasn't been updated yet. @@ -550,10 +550,9 @@ namespace Ryujinx.Ava.Systems.AppLibrary // Migration successful: deleting last_played from the metadata file. appMetadata.LastPlayedOld = default; } - } }); - + data.Favorite = appMetadata.Favorite; data.TimePlayed = appMetadata.TimePlayed; data.LastPlayed = appMetadata.LastPlayed; @@ -788,7 +787,6 @@ namespace Ryujinx.Ava.Systems.AppLibrary } } - // Loops through applications list, creating a struct and then firing an event containing the struct for each application foreach (string applicationPath in applicationPaths) { @@ -848,9 +846,9 @@ namespace Ryujinx.Ava.Systems.AppLibrary public Task RefreshTotalTimePlayedAsync() { TotalTimePlayed = Gommon.Optional.None; - + TimeSpan temporary = TimeSpan.Zero; - + foreach (var installedApplication in Applications.Items) { temporary += LoadAndSaveMetaData(installedApplication.IdString).TimePlayed; @@ -872,7 +870,7 @@ namespace Ryujinx.Ava.Systems.AppLibrary { ldnWebHost = SharedConstants.DefaultLanPlayWebHost; } - + using HttpClient httpClient = new(); string ldnGameDataArrayString = await httpClient.GetStringAsync($"https://{ldnWebHost}/api/public_games"); LdnGameData[] ldnGameDataArray = JsonHelper.Deserialize(ldnGameDataArrayString, _ldnDataSerializerContext.IEnumerableLdnGameData).ToArray(); @@ -884,7 +882,7 @@ namespace Ryujinx.Ava.Systems.AppLibrary Logger.Warning?.Print(LogClass.Application, $"Failed to fetch the public games JSON from the API. Player and game count in the game list will be unavailable.\n{ex.Message}"); } } - + LdnGameDataReceived?.Invoke(LdnGameDataReceivedEventArgs.Empty); } @@ -1148,7 +1146,8 @@ namespace Ryujinx.Ava.Systems.AppLibrary private bool AddAndAutoSelectUpdate(TitleUpdateModel update) { - if (update == null) return false; + if (update == null) + return false; DynamicData.Kernel.Optional<(TitleUpdateModel TitleUpdate, bool IsSelected)> currentlySelected = TitleUpdates.Items.FirstOrOptional(it => it.TitleUpdate.TitleIdBase == update.TitleIdBase && it.IsSelected); @@ -1157,7 +1156,7 @@ namespace Ryujinx.Ava.Systems.AppLibrary currentlySelected.Value.TitleUpdate.Version < update.Version; _titleUpdates.AddOrUpdate((update, shouldSelect)); - + if (currentlySelected.HasValue && shouldSelect) { _titleUpdates.AddOrUpdate((currentlySelected.Value.TitleUpdate, false)); @@ -1557,7 +1556,7 @@ namespace Ryujinx.Ava.Systems.AppLibrary if (!savedUpdateLookup.Contains(update)) { bool shouldSelect = false; - if (!selectedUpdate.HasValue || selectedUpdate.Value.Item1.Version < update.Version) + if (!selectedUpdate.HasValue || selectedUpdate.Value.Update.Version < update.Version) { shouldSelect = true; if (selectedUpdate.HasValue) diff --git a/src/Ryujinx/Systems/AppLibrary/LdnGameData.cs b/src/Ryujinx/Systems/AppLibrary/LdnGameData.cs index 895aec222..e5e7abc42 100644 --- a/src/Ryujinx/Systems/AppLibrary/LdnGameData.cs +++ b/src/Ryujinx/Systems/AppLibrary/LdnGameData.cs @@ -30,7 +30,7 @@ namespace Ryujinx.Ava.Systems.AppLibrary public class Array { private readonly LdnGameData[] _ldnDatas; - + internal Array(IEnumerable receivedData) { _ldnDatas = receivedData.ToArray(); @@ -43,7 +43,7 @@ namespace Ryujinx.Ava.Systems.AppLibrary public static class LdnGameDataHelper { - public static LdnGameData.Array Where(this LdnGameData[] unfilteredDatas, ref ApplicationControlProperty acp) + public static LdnGameData.Array Where(this LdnGameData[] unfilteredDatas, ref ApplicationControlProperty acp) => LdnGameData.GetArrayForApp(unfilteredDatas, ref acp); } } diff --git a/src/Ryujinx/Systems/AppLibrary/LdnGameDataReceivedEventArgs.cs b/src/Ryujinx/Systems/AppLibrary/LdnGameDataReceivedEventArgs.cs index 21d24ff2d..8b207c6bd 100644 --- a/src/Ryujinx/Systems/AppLibrary/LdnGameDataReceivedEventArgs.cs +++ b/src/Ryujinx/Systems/AppLibrary/LdnGameDataReceivedEventArgs.cs @@ -5,13 +5,13 @@ namespace Ryujinx.Ava.Systems.AppLibrary public class LdnGameDataReceivedEventArgs : EventArgs { public static new readonly LdnGameDataReceivedEventArgs Empty = new(null); - + public LdnGameDataReceivedEventArgs(LdnGameData[] ldnData) { LdnData = ldnData ?? []; } - - + + public LdnGameData[] LdnData { get; set; } } } diff --git a/src/Ryujinx/Systems/CompatibilityDatabase.cs b/src/Ryujinx/Systems/CompatibilityDatabase.cs index bfc7ba903..1a780a785 100644 --- a/src/Ryujinx/Systems/CompatibilityDatabase.cs +++ b/src/Ryujinx/Systems/CompatibilityDatabase.cs @@ -1,4 +1,4 @@ -using Gommon; +using Gommon; using Humanizer; using nietras.SeparatedValues; using Ryujinx.Ava.Common.Locale; @@ -28,26 +28,26 @@ namespace Ryujinx.Ava.Systems .Enumerate(row => new CompatibilityEntry(ref columnIndices, row)) .OrderBy(it => it.GameName) .ToArray(); - + Logger.Debug?.Print(LogClass.UI, "Compatibility CSV loaded.", "LoadCompatibility"); } private static CompatibilityEntry[] _entries; - - public static CompatibilityEntry[] Entries + + public static CompatibilityEntry[] Entries { get { if (_entries == null) Load(); - + return _entries; } } public static CompatibilityEntry Find(string titleId) => Entries.FirstOrDefault(x => x.TitleId.HasValue && x.TitleId.Value.EqualsIgnoreCase(titleId)); - + public static CompatibilityEntry Find(ulong titleId) => Find(titleId.ToString("X16")); } @@ -57,10 +57,10 @@ namespace Ryujinx.Ava.Systems public CompatibilityEntry(ref ColumnIndices indices, SepReader.Row row) { string titleIdRow = ColStr(row[indices.TitleId]); - TitleId = !string.IsNullOrEmpty(titleIdRow) - ? titleIdRow + TitleId = !string.IsNullOrEmpty(titleIdRow) + ? titleIdRow : default(Optional); - + GameName = ColStr(row[indices.GameName]); Labels = ColStr(row[indices.Labels]).Split(';'); @@ -78,10 +78,10 @@ namespace Ryujinx.Ava.Systems LastUpdated = dt; return; - - string ColStr(SepReader.Col col) => col.ToString().Trim('"'); + + static string ColStr(SepReader.Col col) => col.ToString().Trim('"'); } - + public string GameName { get; } public Optional TitleId { get; } public string[] Labels { get; } @@ -97,12 +97,12 @@ namespace Ryujinx.Ava.Systems LocaleKeys.CompatibilityListNothing => LocaleKeys.CompatibilityListNothingTooltip, _ => null }; - + public DateTime LastUpdated { get; } public string LocalizedLastUpdated => LocaleManager.FormatDynamicValue(LocaleKeys.CompatibilityListLastUpdated, LastUpdated.Humanize()); - + public string LocalizedStatus => LocaleManager.Instance[Status!.Value]; public string LocalizedStatusDescription => LocaleManager.Instance[StatusDescription!.Value]; public string FormattedTitleId => TitleId @@ -117,9 +117,7 @@ namespace Ryujinx.Ava.Systems new StringBuilder("CompatibilityEntry: {") .Append($"{nameof(GameName)}=\"{GameName}\", ") .Append($"{nameof(TitleId)}={TitleId}, ") - .Append($"{nameof(Labels)}={ - Labels.FormatCollection(it => $"\"{it}\"", separator: ", ", prefix: "[", suffix: "]") - }, ") + .Append($"{nameof(Labels)}={Labels.FormatCollection(it => $"\"{it}\"", separator: ", ", prefix: "[", suffix: "]")}, ") .Append($"{nameof(Status)}=\"{Status}\", ") .Append($"{nameof(LastUpdated)}=\"{LastUpdated}\"") .Append('}') @@ -169,7 +167,7 @@ namespace Ryujinx.Ava.Systems _ => null }; } - + public struct ColumnIndices(Func, int> getIndex) { private const string TitleIdCol = "\"title_id\""; @@ -177,7 +175,7 @@ namespace Ryujinx.Ava.Systems private const string LabelsCol = "\"labels\""; private const string StatusCol = "\"status\""; private const string LastUpdatedCol = "\"last_updated\""; - + public readonly int TitleId = getIndex(TitleIdCol); public readonly int GameName = getIndex(GameNameCol); public readonly int Labels = getIndex(LabelsCol); diff --git a/src/Ryujinx/Systems/Configuration/ConfigurationFileFormat.cs b/src/Ryujinx/Systems/Configuration/ConfigurationFileFormat.cs index c5bbe3da8..432ff593a 100644 --- a/src/Ryujinx/Systems/Configuration/ConfigurationFileFormat.cs +++ b/src/Ryujinx/Systems/Configuration/ConfigurationFileFormat.cs @@ -111,7 +111,7 @@ namespace Ryujinx.Ava.Systems.Configuration /// Enables printing FS access log messages /// public bool LoggingEnableFsAccessLog { get; set; } - + /// /// Enables log messages from Avalonia /// @@ -146,7 +146,7 @@ namespace Ryujinx.Ava.Systems.Configuration /// Change System Time Offset in seconds /// public long SystemTimeOffset { get; set; } - + /// /// Instead of setting the time via configuration, use the values provided by the system. /// @@ -166,12 +166,12 @@ namespace Ryujinx.Ava.Systems.Configuration /// DEPRECATED: Checks for updates when Ryujinx starts when enabled /// public bool CheckUpdatesOnStart { get; set; } - + /// /// Checks for updates when Ryujinx starts when enabled, either prompting when an update is found or just showing a notification. /// public UpdaterType UpdateCheckerType { get; set; } - + /// /// How the emulator should behave when you click off/on the window. /// @@ -263,7 +263,7 @@ namespace Ryujinx.Ava.Systems.Configuration /// Enables or disables low-power profiled translation cache persistency loading /// public bool EnableLowPowerPtc { get; set; } - + /// /// Clock tick scalar, in percent points (100 = 1.0). /// @@ -398,7 +398,7 @@ namespace Ryujinx.Ava.Systems.Configuration /// Enable or disable mouse support (Independent from controllers binding) /// public bool EnableMouse { get; set; } - + /// /// Enable/disable the ability to control Ryujinx when it's not the currently focused window. /// @@ -413,7 +413,7 @@ namespace Ryujinx.Ava.Systems.Configuration /// Input configurations /// public List InputConfig { get; set; } - + /// /// The speed of spectrum cycling for the Rainbow LED feature. /// @@ -458,17 +458,17 @@ namespace Ryujinx.Ava.Systems.Configuration /// Uses Hypervisor over JIT if available /// public bool UseHypervisor { get; set; } - + /// /// Show toggles for dirty hacks in the UI. /// public bool ShowDirtyHacks { get; set; } - + /// /// The packed values of the enabled dirty hacks. /// public ulong[] DirtyHacks { get; set; } - + /// /// Loads a configuration file from disk /// diff --git a/src/Ryujinx/Systems/Configuration/ConfigurationState.Migration.cs b/src/Ryujinx/Systems/Configuration/ConfigurationState.Migration.cs index 5843b5963..b5c7abd57 100644 --- a/src/Ryujinx/Systems/Configuration/ConfigurationState.Migration.cs +++ b/src/Ryujinx/Systems/Configuration/ConfigurationState.Migration.cs @@ -33,18 +33,18 @@ namespace Ryujinx.Ava.Systems.Configuration foreach ((int newVersion, Action migratorFunction) in _migrations.OrderBy(x => x.Key)) { - if (cff.Version >= newVersion) + if (cff.Version >= newVersion) continue; - RyuLogger.Warning?.Print(LogClass.Application, + RyuLogger.Warning?.Print(LogClass.Application, $"Outdated configuration version {cff.Version}, migrating to version {newVersion}."); - + migratorFunction(cff); configurationFileUpdated = true; } - - + + EnableDiscordIntegration.Value = cff.EnableDiscordIntegration; UpdateCheckerType.Value = shouldLoadFromFile ? cff.UpdateCheckerType : UpdateCheckerType.Value; // Get from global config only FocusLostActionType.Value = cff.FocusLostActionType; @@ -53,7 +53,7 @@ namespace Ryujinx.Ava.Systems.Configuration ShowOldUI.Value = shouldLoadFromFile ? cff.ShowTitleBar : ShowOldUI.Value; // Get from global config only EnableHardwareAcceleration.Value = shouldLoadFromFile ? cff.EnableHardwareAcceleration : EnableHardwareAcceleration.Value; // Get from global config only HideCursor.Value = cff.HideCursor; - + Logger.EnableFileLog.Value = cff.EnableFileLog; Logger.EnableDebug.Value = cff.LoggingEnableDebug; Logger.EnableStub.Value = cff.LoggingEnableStub; @@ -65,7 +65,7 @@ namespace Ryujinx.Ava.Systems.Configuration Logger.EnableFsAccessLog.Value = cff.LoggingEnableFsAccessLog; Logger.FilteredClasses.Value = cff.LoggingFilteredClasses; Logger.GraphicsDebugLevel.Value = cff.LoggingGraphicsDebugLevel; - + Graphics.ResScale.Value = cff.ResScale; Graphics.ResScaleCustom.Value = cff.ResScaleCustom; Graphics.MaxAnisotropy.Value = cff.MaxAnisotropy; @@ -84,7 +84,7 @@ namespace Ryujinx.Ava.Systems.Configuration Graphics.EnableTextureRecompression.Value = cff.EnableTextureRecompression; Graphics.EnableMacroHLE.Value = cff.EnableMacroHLE; Graphics.EnableColorSpacePassthrough.Value = cff.EnableColorSpacePassthrough; - + System.Language.Value = cff.SystemLanguage; System.Region.Value = cff.SystemRegion; System.TimeZone.Value = cff.SystemTimeZone; @@ -142,10 +142,9 @@ namespace Ryujinx.Ava.Systems.Configuration UI.WindowStartup.WindowPositionY.Value = shouldLoadFromFile ? cff.WindowStartup.WindowPositionY : UI.WindowStartup.WindowPositionY.Value; UI.WindowStartup.WindowMaximized.Value = shouldLoadFromFile ? cff.WindowStartup.WindowMaximized : UI.WindowStartup.WindowMaximized.Value; - Hid.EnableKeyboard.Value = cff.EnableKeyboard; Hid.EnableMouse.Value = cff.EnableMouse; - Hid.DisableInputWhenOutOfFocus.Value = shouldLoadFromFile ? cff.DisableInputWhenOutOfFocus: Hid.DisableInputWhenOutOfFocus.Value; // Get from global config only + Hid.DisableInputWhenOutOfFocus.Value = shouldLoadFromFile ? cff.DisableInputWhenOutOfFocus : Hid.DisableInputWhenOutOfFocus.Value; // Get from global config only Hid.Hotkeys.Value = shouldLoadFromFile ? cff.Hotkeys : Hid.Hotkeys.Value; // Get from global config only Hid.InputConfig.Value = cff.InputConfig ?? []; Hid.RainbowSpeed.Value = cff.RainbowSpeed; @@ -155,14 +154,14 @@ namespace Ryujinx.Ava.Systems.Configuration Multiplayer.DisableP2p.Value = cff.MultiplayerDisableP2p; Multiplayer.LdnPassphrase.Value = cff.MultiplayerLdnPassphrase; Multiplayer.LdnServer.Value = cff.LdnServer; - - { - Hacks.ShowDirtyHacks.Value = shouldLoadFromFile ? cff.ShowDirtyHacks: Hacks.ShowDirtyHacks.Value; // Get from global config only - DirtyHacks hacks = new (cff.DirtyHacks ?? []); + { + Hacks.ShowDirtyHacks.Value = shouldLoadFromFile ? cff.ShowDirtyHacks : Hacks.ShowDirtyHacks.Value; // Get from global config only + + DirtyHacks hacks = new(cff.DirtyHacks ?? []); Hacks.Xc2MenuSoftlockFix.Value = hacks.IsEnabled(DirtyHack.Xc2MenuSoftlockFix); - + } if (configurationFileUpdated) @@ -172,7 +171,7 @@ namespace Ryujinx.Ava.Systems.Configuration RyuLogger.Notice.Print(LogClass.Application, $"Configuration file updated to version {ConfigurationFileFormat.CurrentVersion}"); } } - + private static readonly Dictionary> _migrations = Collections.NewDictionary>( (2, static cff => cff.SystemRegion = Region.USA), @@ -184,13 +183,15 @@ namespace Ryujinx.Ava.Systems.Configuration { cff.ColumnSort = new ColumnSort { SortColumnId = 0, SortAscending = false }; cff.Hotkeys = new KeyboardHotkeys { ToggleVSyncMode = Key.F1 }; - }), + } + ), (10, static cff => cff.AudioBackend = AudioBackend.OpenAl), (11, static cff => { cff.ResScale = 1; cff.ResScaleCustom = 1.0f; - }), + } + ), (12, static cff => cff.LoggingGraphicsDebugLevel = GraphicsDebugLevel.None), // 13 -> LDN1 (14, static cff => cff.CheckUpdatesOnStart = true), @@ -205,7 +206,8 @@ namespace Ryujinx.Ava.Systems.Configuration cff.MultiplayerMode = MultiplayerMode.Disabled; cff.MultiplayerLanInterfaceId = "0"; - }), + } + ), (22, static cff => cff.HideCursor = HideCursorMode.Never), (24, static cff => { @@ -260,14 +262,17 @@ namespace Ryujinx.Ava.Systems.Configuration }, } ]; - }), + } + ), (26, static cff => cff.MemoryManagerMode = MemoryManagerMode.HostMappedUnsafe), (27, static cff => cff.EnableMouse = false), (29, static cff => cff.Hotkeys = new KeyboardHotkeys { - ToggleVSyncMode = Key.F1, Screenshot = Key.F8, ShowUI = Key.F4 + ToggleVSyncMode = Key.F1, + Screenshot = Key.F8, + ShowUI = Key.F4 }), (30, static cff => { @@ -275,10 +280,13 @@ namespace Ryujinx.Ava.Systems.Configuration { config.Rumble = new RumbleConfigController { - EnableRumble = false, StrongRumble = 1f, WeakRumble = 1f, + EnableRumble = false, + StrongRumble = 1f, + WeakRumble = 1f, }; } - }), + } + ), (31, static cff => cff.BackendThreading = BackendThreading.Auto), (32, static cff => cff.Hotkeys = new KeyboardHotkeys { @@ -299,7 +307,8 @@ namespace Ryujinx.Ava.Systems.Configuration }; cff.AudioVolume = 1; - }), + } + ), (34, static cff => cff.EnableInternetAccess = false), (35, static cff => { @@ -309,7 +318,8 @@ namespace Ryujinx.Ava.Systems.Configuration config.RangeLeft = 1.0f; config.RangeRight = 1.0f; } - }), + } + ), (36, static cff => cff.LoggingEnableTrace = false), (37, static cff => cff.ShowConsole = true), @@ -320,7 +330,8 @@ namespace Ryujinx.Ava.Systems.Configuration cff.ShowNames = true; cff.GridSize = 2; cff.LanguageCode = "en_US"; - }), + } + ), (39, static cff => cff.Hotkeys = new KeyboardHotkeys { @@ -353,7 +364,8 @@ namespace Ryujinx.Ava.Systems.Configuration cff.AntiAliasing = AntiAliasing.None; cff.ScalingFilter = ScalingFilter.Bilinear; cff.ScalingFilterLevel = 80; - }), + } + ), (45, static cff => cff.ShownFileTypes = new ShownFileTypes { @@ -381,7 +393,8 @@ namespace Ryujinx.Ava.Systems.Configuration { AppDataManager.FixMacOSConfigurationFolders(); } - }), + } + ), (50, static cff => cff.EnableHardwareAcceleration = true), (51, static cff => cff.RememberWindowState = true), (52, static cff => cff.AutoloadDirs = []), @@ -410,7 +423,8 @@ namespace Ryujinx.Ava.Systems.Configuration }; cff.CustomVSyncInterval = 120; - }), + } + ), // 58 migration accidentally got skipped, but it worked with no issues somehow lol (59, static cff => { @@ -420,7 +434,8 @@ namespace Ryujinx.Ava.Systems.Configuration // This was accidentally enabled by default when it was PRed. That is not what we want, // so as a compromise users who want to use it will simply need to re-enable it once after updating. cff.IgnoreApplet = false; - }), + } + ), (60, static cff => cff.StartNoUI = false), (61, static cff => { @@ -434,7 +449,8 @@ namespace Ryujinx.Ava.Systems.Configuration LedColor = new Color(255, 5, 1, 253).ToUInt32() }; } - }), + } + ), (62, static cff => cff.RainbowSpeed = 1f), (63, static cff => cff.MatchSystemTime = false), (64, static cff => cff.LoggingEnableAvalonia = false), @@ -460,7 +476,8 @@ namespace Ryujinx.Ava.Systems.Configuration TurboMode = Key.Unbound, TurboModeWhileHeld = false }; - }), + } + ), (69, static cff => cff.SkipUserProfiles = false) ); } diff --git a/src/Ryujinx/Systems/Configuration/ConfigurationState.Model.cs b/src/Ryujinx/Systems/Configuration/ConfigurationState.Model.cs index 3c5fac1cb..500e001a6 100644 --- a/src/Ryujinx/Systems/Configuration/ConfigurationState.Model.cs +++ b/src/Ryujinx/Systems/Configuration/ConfigurationState.Model.cs @@ -256,7 +256,7 @@ namespace Ryujinx.Ava.Systems.Configuration /// Enables printing FS access log messages /// public ReactiveObject EnableFsAccessLog { get; private set; } - + /// /// Enables log messages from Avalonia /// @@ -320,7 +320,7 @@ namespace Ryujinx.Ava.Systems.Configuration /// System Time Offset in Seconds /// public ReactiveObject SystemTimeOffset { get; private set; } - + /// /// Instead of setting the time via configuration, use the values provided by the system. /// @@ -335,7 +335,7 @@ namespace Ryujinx.Ava.Systems.Configuration /// Enables or disables persistent profiled translation cache /// public ReactiveObject EnablePtc { get; private set; } - + /// /// Clock tick scalar, in percent points (100 = 1.0). /// @@ -389,7 +389,7 @@ namespace Ryujinx.Ava.Systems.Configuration /// Enable or disable ignoring missing services /// public ReactiveObject IgnoreMissingServices { get; private set; } - + /// /// Ignore Controller Applet /// @@ -423,7 +423,7 @@ namespace Ryujinx.Ava.Systems.Configuration EnablePtc.LogChangesToValue(nameof(EnablePtc)); EnableLowPowerPtc = new ReactiveObject(); EnableLowPowerPtc.LogChangesToValue(nameof(EnableLowPowerPtc)); - EnableLowPowerPtc.Event += (_, evnt) + EnableLowPowerPtc.Event += (_, evnt) => Optimizations.LowPower = evnt.NewValue; TickScalar = new ReactiveObject(); TickScalar.LogChangesToValue(nameof(TickScalar)); @@ -473,7 +473,7 @@ namespace Ryujinx.Ava.Systems.Configuration /// Enable or disable mouse support (Independent from controllers binding) /// public ReactiveObject EnableMouse { get; private set; } - + /// /// Enable/disable the ability to control Ryujinx when it's not the currently focused window. /// @@ -490,7 +490,7 @@ namespace Ryujinx.Ava.Systems.Configuration /// TODO: Implement a ReactiveList class. /// public ReactiveObject> InputConfig { get; private set; } - + /// /// The speed of spectrum cycling for the Rainbow LED feature. /// @@ -676,8 +676,8 @@ namespace Ryujinx.Ava.Systems.Configuration public string GetLdnServer() { string ldnServer = LdnServer; - return string.IsNullOrEmpty(ldnServer) - ? SharedConstants.DefaultLanPlayHost + return string.IsNullOrEmpty(ldnServer) + ? SharedConstants.DefaultLanPlayHost : ldnServer; } @@ -701,9 +701,9 @@ namespace Ryujinx.Ava.Systems.Configuration /// Show toggles for dirty hacks in the UI. /// public ReactiveObject ShowDirtyHacks { get; private set; } - + public ReactiveObject Xc2MenuSoftlockFix { get; private set; } - + public ReactiveObject DisableNifmIsAnyInternetRequestAccepted { get; private set; } public HacksSection() @@ -717,15 +717,15 @@ namespace Ryujinx.Ava.Systems.Configuration private void HackChanged(object sender, ReactiveEventArgs rxe) { - if (!ShowDirtyHacks) + if (!ShowDirtyHacks) return; - + string newHacks = EnabledHacks.Select(x => x.Hack) .JoinToString(", "); if (newHacks != _lastHackCollection) { - RyuLogger.Info?.Print(LogClass.Configuration, + RyuLogger.Info?.Print(LogClass.Configuration, $"EnabledDirtyHacks set to: [{newHacks}]", "LogValueChange"); _lastHackCollection = newHacks; @@ -739,13 +739,13 @@ namespace Ryujinx.Ava.Systems.Configuration get { List enabledHacks = []; - + if (Xc2MenuSoftlockFix) Apply(DirtyHack.Xc2MenuSoftlockFix); - + if (DisableNifmIsAnyInternetRequestAccepted) Apply(DirtyHack.NifmServiceDisableIsAnyInternetRequestAccepted); - + return enabledHacks.ToArray(); void Apply(DirtyHack hack, int value = 0) @@ -790,7 +790,7 @@ namespace Ryujinx.Ava.Systems.Configuration /// The Multiplayer section /// public MultiplayerSection Multiplayer { get; private set; } - + /// /// The Dirty Hacks section /// @@ -800,12 +800,12 @@ namespace Ryujinx.Ava.Systems.Configuration /// Enables or disables Discord Rich Presence /// public ReactiveObject EnableDiscordIntegration { get; private set; } - + /// /// Checks for updates when Ryujinx starts when enabled, either prompting when an update is found or just showing a notification. /// public ReactiveObject UpdateCheckerType { get; private set; } - + /// /// How the emulator should behave when you click off/on the window. /// @@ -865,8 +865,8 @@ namespace Ryujinx.Ava.Systems.Configuration System.EnablePtc, System.TickScalar, System.EnableInternetAccess, - System.EnableFsIntegrityChecks - ? IntegrityCheckLevel.ErrorOnInvalid + System.EnableFsIntegrityChecks + ? IntegrityCheckLevel.ErrorOnInvalid : IntegrityCheckLevel.None, System.FsGlobalAccessLogMode, System.MatchSystemTime diff --git a/src/Ryujinx/Systems/Configuration/FileTypes.cs b/src/Ryujinx/Systems/Configuration/FileTypes.cs index 70517683b..92c6550f4 100644 --- a/src/Ryujinx/Systems/Configuration/FileTypes.cs +++ b/src/Ryujinx/Systems/Configuration/FileTypes.cs @@ -13,7 +13,7 @@ namespace Ryujinx.Ava.Systems.Configuration NRO, NSO } - + public static class FileTypesExtensions { /// diff --git a/src/Ryujinx/Systems/Configuration/LoggerModule.cs b/src/Ryujinx/Systems/Configuration/LoggerModule.cs index 941556c43..e3d08ab8c 100644 --- a/src/Ryujinx/Systems/Configuration/LoggerModule.cs +++ b/src/Ryujinx/Systems/Configuration/LoggerModule.cs @@ -10,23 +10,23 @@ namespace Ryujinx.Ava.Systems.Configuration { public static void Initialize() { - ConfigurationState.Instance.Logger.EnableDebug.Event += + ConfigurationState.Instance.Logger.EnableDebug.Event += (_, e) => Logger.SetEnable(LogLevel.Debug, e.NewValue); - ConfigurationState.Instance.Logger.EnableStub.Event += + ConfigurationState.Instance.Logger.EnableStub.Event += (_, e) => Logger.SetEnable(LogLevel.Stub, e.NewValue); - ConfigurationState.Instance.Logger.EnableInfo.Event += + ConfigurationState.Instance.Logger.EnableInfo.Event += (_, e) => Logger.SetEnable(LogLevel.Info, e.NewValue); - ConfigurationState.Instance.Logger.EnableWarn.Event += + ConfigurationState.Instance.Logger.EnableWarn.Event += (_, e) => Logger.SetEnable(LogLevel.Warning, e.NewValue); - ConfigurationState.Instance.Logger.EnableError.Event += + ConfigurationState.Instance.Logger.EnableError.Event += (_, e) => Logger.SetEnable(LogLevel.Error, e.NewValue); - ConfigurationState.Instance.Logger.EnableTrace.Event += + ConfigurationState.Instance.Logger.EnableTrace.Event += (_, e) => Logger.SetEnable(LogLevel.Trace, e.NewValue); - ConfigurationState.Instance.Logger.EnableGuest.Event += + ConfigurationState.Instance.Logger.EnableGuest.Event += (_, e) => Logger.SetEnable(LogLevel.Guest, e.NewValue); ConfigurationState.Instance.Logger.EnableFsAccessLog.Event += (_, e) => Logger.SetEnable(LogLevel.AccessLog, e.NewValue); - + ConfigurationState.Instance.Logger.FilteredClasses.Event += (_, e) => { bool noFilter = e.NewValue.Length == 0; diff --git a/src/Ryujinx/Systems/Configuration/System/Region.cs b/src/Ryujinx/Systems/Configuration/System/Region.cs index 0089f073c..0c86093cc 100644 --- a/src/Ryujinx/Systems/Configuration/System/Region.cs +++ b/src/Ryujinx/Systems/Configuration/System/Region.cs @@ -14,7 +14,7 @@ namespace Ryujinx.Ava.Systems.Configuration.System Korea, Taiwan, } - + public static class RegionEnumHelper { public static Region ToUI(this HLE.HOS.SystemState.RegionCode hleRegion) diff --git a/src/Ryujinx/Systems/Configuration/UI/FocusLostType.cs b/src/Ryujinx/Systems/Configuration/UI/FocusLostType.cs index 2d0341022..9e22f3dca 100644 --- a/src/Ryujinx/Systems/Configuration/UI/FocusLostType.cs +++ b/src/Ryujinx/Systems/Configuration/UI/FocusLostType.cs @@ -1,4 +1,4 @@ -using Ryujinx.Common.Utilities; +using Ryujinx.Common.Utilities; using System.Text.Json.Serialization; namespace Ryujinx.Ava.Systems.Configuration.UI diff --git a/src/Ryujinx/Systems/Configuration/UI/UpdaterType.cs b/src/Ryujinx/Systems/Configuration/UI/UpdaterType.cs index 06cf35d10..bc2696780 100644 --- a/src/Ryujinx/Systems/Configuration/UI/UpdaterType.cs +++ b/src/Ryujinx/Systems/Configuration/UI/UpdaterType.cs @@ -1,4 +1,4 @@ -using Ryujinx.Common.Utilities; +using Ryujinx.Common.Utilities; using System.Text.Json.Serialization; namespace Ryujinx.Ava.Systems.Configuration.UI diff --git a/src/Ryujinx/Systems/DiscordIntegrationModule.cs b/src/Ryujinx/Systems/DiscordIntegrationModule.cs index f658aa9ec..5b61340b6 100644 --- a/src/Ryujinx/Systems/DiscordIntegrationModule.cs +++ b/src/Ryujinx/Systems/DiscordIntegrationModule.cs @@ -1,9 +1,9 @@ using DiscordRPC; using Gommon; -using Ryujinx.Ava.Utilities; using Ryujinx.Ava.Systems.AppLibrary; using Ryujinx.Ava.Systems.Configuration; using Ryujinx.Ava.Systems.PlayReport; +using Ryujinx.Ava.Utilities; using Ryujinx.Common; using Ryujinx.Common.Logging; using Ryujinx.HLE; @@ -42,7 +42,8 @@ namespace Ryujinx.Ava.Systems { Assets = new Assets { - LargeImageKey = "ryujinx", LargeImageText = TruncateToByteLength(_description) + LargeImageKey = "ryujinx", + LargeImageText = TruncateToByteLength(_description) }, Details = "Main Menu", State = "Idling", @@ -122,14 +123,18 @@ namespace Ryujinx.Ava.Systems private static void HandlePlayReport(Horizon.Prepo.Types.PlayReport playReport) { - if (_discordClient is null) return; - if (!TitleIDs.CurrentApplication.Value.HasValue) return; - if (_discordPresencePlaying is null) return; + if (_discordClient is null) + return; + if (!TitleIDs.CurrentApplication.Value.HasValue) + return; + if (_discordPresencePlaying is null) + return; FormattedValue formattedValue = PlayReports.Analyzer.Format(TitleIDs.CurrentApplication.Value, _currentApp, playReport); - if (!formattedValue.Handled) return; + if (!formattedValue.Handled) + return; _discordPresencePlaying.Details = TruncateToByteLength( formattedValue.Reset diff --git a/src/Ryujinx/Systems/PlayReport/Analyzer.cs b/src/Ryujinx/Systems/PlayReport/Analyzer.cs index d4198cdcf..42f74bc63 100644 --- a/src/Ryujinx/Systems/PlayReport/Analyzer.cs +++ b/src/Ryujinx/Systems/PlayReport/Analyzer.cs @@ -1,4 +1,4 @@ -using Gommon; +using Gommon; using Ryujinx.Ava.Systems.AppLibrary; using Ryujinx.Common.Logging; using System; @@ -71,14 +71,12 @@ namespace Ryujinx.Ava.Systems.PlayReport return AddSpec(transform(GameSpec.Create(tids))); Logger.Notice.PrintMsg(LogClass.Application, - $"Tried to add a {nameof(GameSpec)} with a non-hexadecimal title ID value. Input: '{ - tids.FormatCollection( + $"Tried to add a {nameof(GameSpec)} with a non-hexadecimal title ID value. Input: '{tids.FormatCollection( x => x, separator: ", ", prefix: "[", suffix: "]" - ) - }'"); + )}'"); return this; } @@ -95,14 +93,12 @@ namespace Ryujinx.Ava.Systems.PlayReport return AddSpec(GameSpec.Create(tids).Apply(transform)); Logger.Notice.PrintMsg(LogClass.Application, - $"Tried to add a {nameof(GameSpec)} with a non-hexadecimal title ID value. Input: '{ - tids.FormatCollection( + $"Tried to add a {nameof(GameSpec)} with a non-hexadecimal title ID value. Input: '{tids.FormatCollection( x => x, separator: ", ", prefix: "[", suffix: "]" - ) - }'"); + )}'"); return this; } @@ -117,7 +113,6 @@ namespace Ryujinx.Ava.Systems.PlayReport return this; } - /// /// Runs the configured for the specified game title ID. /// @@ -133,7 +128,7 @@ namespace Ryujinx.Ava.Systems.PlayReport { if (!playReport.ReportData.IsDictionary) return FormattedValue.Unhandled; - + if (!TryGetSpec(runningGameId, out GameSpec spec)) return FormattedValue.Unhandled; diff --git a/src/Ryujinx/Systems/PlayReport/Delegates.cs b/src/Ryujinx/Systems/PlayReport/Delegates.cs index b3496ec4d..bca70a7fa 100644 --- a/src/Ryujinx/Systems/PlayReport/Delegates.cs +++ b/src/Ryujinx/Systems/PlayReport/Delegates.cs @@ -1,4 +1,4 @@ -namespace Ryujinx.Ava.Systems.PlayReport +namespace Ryujinx.Ava.Systems.PlayReport { /// /// The delegate type that powers single value formatters.
diff --git a/src/Ryujinx/Systems/PlayReport/MatchedValues.cs b/src/Ryujinx/Systems/PlayReport/MatchedValues.cs index 025130758..9fbd01b4b 100644 --- a/src/Ryujinx/Systems/PlayReport/MatchedValues.cs +++ b/src/Ryujinx/Systems/PlayReport/MatchedValues.cs @@ -1,4 +1,4 @@ -using MsgPack; +using MsgPack; using Ryujinx.Ava.Systems.AppLibrary; using System.Collections.Generic; @@ -10,12 +10,12 @@ namespace Ryujinx.Ava.Systems.PlayReport { Matched = matched; } - + /// /// The currently running application's . /// public ApplicationMetadata Application { get; init; } - + /// /// The entire play report. /// @@ -26,7 +26,7 @@ namespace Ryujinx.Ava.Systems.PlayReport ///
public T Matched { get; init; } } - + /// /// The input data to a , /// containing the currently running application's , @@ -65,7 +65,7 @@ namespace Ryujinx.Ava.Systems.PlayReport public SparseMultiValue(Dictionary matched) : base(matched) { } - + public SparseMultiValue(Dictionary matched) : base(Value.ConvertPackedObjectMap(matched)) { } diff --git a/src/Ryujinx/Systems/PlayReport/PlayReports.Formatters.cs b/src/Ryujinx/Systems/PlayReport/PlayReports.Formatters.cs index 5c5fb40f4..dacf3ef0e 100644 --- a/src/Ryujinx/Systems/PlayReport/PlayReports.Formatters.cs +++ b/src/Ryujinx/Systems/PlayReport/PlayReports.Formatters.cs @@ -1,4 +1,4 @@ -using Gommon; +using Gommon; using Humanizer; using System; using System.Buffers.Binary; @@ -19,7 +19,7 @@ namespace Ryujinx.Ava.Systems.PlayReport < -201d => "Exploring the Depths", _ => "Roaming Hyrule" }; - + private static FormattedValue SkywardSwordHD_Rupees(SingleValue value) => "rupee".ToQuantity(value.Matched.IntValue); @@ -59,13 +59,13 @@ namespace Ryujinx.Ava.Systems.PlayReport "Race" => "Racing", _ => FormattedValue.ForceReset }; - + private static FormattedValue PokemonSV(MultiValue values) { - + string playStatus = values.Matched[0].BoxedValue is 0 ? "Playing Alone" : "Playing in a group"; - - FormattedValue locations = values.Matched[1].ToString() switch + + FormattedValue locations = values.Matched[1].ToString() switch { // Base Game Locations "a_w01" => "South Area One", @@ -97,8 +97,8 @@ namespace Ryujinx.Ava.Systems.PlayReport //TODO DLC Locations _ => FormattedValue.ForceReset }; - - return$"{playStatus} in {locations}"; + + return $"{playStatus} in {locations}"; } private static FormattedValue SuperSmashBrosUltimate_Mode(SparseMultiValue values) @@ -121,7 +121,7 @@ namespace Ryujinx.Ava.Systems.PlayReport if (values.Matched.ContainsKey("is_created")) { - return "Edited a Custom Stage!"; + return "Edited a Custom Stage!"; } if (values.Matched.ContainsKey("adv_slot")) @@ -179,97 +179,97 @@ namespace Ryujinx.Ava.Systems.PlayReport private static string SuperSmashBrosUltimate_Character(Value value) => BinaryPrimitives.ReverseEndianness( BitConverter.ToInt64(((MsgPack.MessagePackExtendedTypeObject)value.BoxedValue).GetBody(), 0)) switch - { - 0x0 => "Mario", - 0x1 => "Donkey Kong", - 0x2 => "Link", - 0x3 => "Samus", - 0x4 => "Dark Samus", - 0x5 => "Yoshi", - 0x6 => "Kirby", - 0x7 => "Fox", - 0x8 => "Pikachu", - 0x9 => "Luigi", - 0xA => "Ness", - 0xB => "Captain Falcon", - 0xC => "Jigglypuff", - 0xD => "Peach", - 0xE => "Daisy", - 0xF => "Bowser", - 0x10 => "Ice Climbers", - 0x11 => "Sheik", - 0x12 => "Zelda", - 0x13 => "Dr. Mario", - 0x14 => "Pichu", - 0x15 => "Falco", - 0x16 => "Marth", - 0x17 => "Lucina", - 0x18 => "Young Link", - 0x19 => "Ganondorf", - 0x1A => "Mewtwo", - 0x1B => "Roy", - 0x1C => "Chrom", - 0x1D => "Mr Game & Watch", - 0x1E => "Meta Knight", - 0x1F => "Pit", - 0x20 => "Dark Pit", - 0x21 => "Zero Suit Samus", - 0x22 => "Wario", - 0x23 => "Snake", - 0x24 => "Ike", - 0x25 => "Pokémon Trainer", - 0x26 => "Diddy Kong", - 0x27 => "Lucas", - 0x28 => "Sonic", - 0x29 => "King Dedede", - 0x2A => "Olimar", - 0x2B => "Lucario", - 0x2C => "R.O.B.", - 0x2D => "Toon Link", - 0x2E => "Wolf", - 0x2F => "Villager", - 0x30 => "Mega Man", - 0x31 => "Wii Fit Trainer", - 0x32 => "Rosalina & Luma", - 0x33 => "Little Mac", - 0x34 => "Greninja", - 0x35 => "Palutena", - 0x36 => "Pac-Man", - 0x37 => "Robin", - 0x38 => "Shulk", - 0x39 => "Bowser Jr.", - 0x3A => "Duck Hunt", - 0x3B => "Ryu", - 0x3C => "Ken", - 0x3D => "Cloud", - 0x3E => "Corrin", - 0x3F => "Bayonetta", - 0x40 => "Richter", - 0x41 => "Inkling", - 0x42 => "Ridley", - 0x43 => "King K. Rool", - 0x44 => "Simon", - 0x45 => "Isabelle", - 0x46 => "Incineroar", - 0x47 => "Mii Brawler", - 0x48 => "Mii Swordfighter", - 0x49 => "Mii Gunner", - 0x4A => "Piranha Plant", - 0x4B => "Joker", - 0x4C => "Hero", - 0x4D => "Banjo", - 0x4E => "Terry", - 0x4F => "Byleth", - 0x50 => "Min Min", - 0x51 => "Steve", - 0x52 => "Sephiroth", - 0x53 => "Pyra/Mythra", - 0x54 => "Kazuya", - 0x55 => "Sora", - 0xFE => "Random", - 0xFF => "Scripted Entity", - _ => "Unknown" - }; + { + 0x0 => "Mario", + 0x1 => "Donkey Kong", + 0x2 => "Link", + 0x3 => "Samus", + 0x4 => "Dark Samus", + 0x5 => "Yoshi", + 0x6 => "Kirby", + 0x7 => "Fox", + 0x8 => "Pikachu", + 0x9 => "Luigi", + 0xA => "Ness", + 0xB => "Captain Falcon", + 0xC => "Jigglypuff", + 0xD => "Peach", + 0xE => "Daisy", + 0xF => "Bowser", + 0x10 => "Ice Climbers", + 0x11 => "Sheik", + 0x12 => "Zelda", + 0x13 => "Dr. Mario", + 0x14 => "Pichu", + 0x15 => "Falco", + 0x16 => "Marth", + 0x17 => "Lucina", + 0x18 => "Young Link", + 0x19 => "Ganondorf", + 0x1A => "Mewtwo", + 0x1B => "Roy", + 0x1C => "Chrom", + 0x1D => "Mr Game & Watch", + 0x1E => "Meta Knight", + 0x1F => "Pit", + 0x20 => "Dark Pit", + 0x21 => "Zero Suit Samus", + 0x22 => "Wario", + 0x23 => "Snake", + 0x24 => "Ike", + 0x25 => "Pokémon Trainer", + 0x26 => "Diddy Kong", + 0x27 => "Lucas", + 0x28 => "Sonic", + 0x29 => "King Dedede", + 0x2A => "Olimar", + 0x2B => "Lucario", + 0x2C => "R.O.B.", + 0x2D => "Toon Link", + 0x2E => "Wolf", + 0x2F => "Villager", + 0x30 => "Mega Man", + 0x31 => "Wii Fit Trainer", + 0x32 => "Rosalina & Luma", + 0x33 => "Little Mac", + 0x34 => "Greninja", + 0x35 => "Palutena", + 0x36 => "Pac-Man", + 0x37 => "Robin", + 0x38 => "Shulk", + 0x39 => "Bowser Jr.", + 0x3A => "Duck Hunt", + 0x3B => "Ryu", + 0x3C => "Ken", + 0x3D => "Cloud", + 0x3E => "Corrin", + 0x3F => "Bayonetta", + 0x40 => "Richter", + 0x41 => "Inkling", + 0x42 => "Ridley", + 0x43 => "King K. Rool", + 0x44 => "Simon", + 0x45 => "Isabelle", + 0x46 => "Incineroar", + 0x47 => "Mii Brawler", + 0x48 => "Mii Swordfighter", + 0x49 => "Mii Gunner", + 0x4A => "Piranha Plant", + 0x4B => "Joker", + 0x4C => "Hero", + 0x4D => "Banjo", + 0x4E => "Terry", + 0x4F => "Byleth", + 0x50 => "Min Min", + 0x51 => "Steve", + 0x52 => "Sephiroth", + 0x53 => "Pyra/Mythra", + 0x54 => "Kazuya", + 0x55 => "Sora", + 0xFE => "Random", + 0xFF => "Scripted Entity", + _ => "Unknown" + }; private static string SuperSmashBrosUltimate_PlayerListing(SparseMultiValue values) { @@ -295,16 +295,14 @@ namespace Ryujinx.Ava.Systems.PlayReport players = players.OrderBy(p => p.Rank ?? int.MaxValue).ToList(); return players.Count > 4 - ? $"{players.Count} Players - { - players.Take(3) + ? $"{players.Count} Players - {players.Take(3) .Select(p => $"{p.Character}({p.PlayerNumber}){RankMedal(p.Rank)}") - .JoinToString(", ") - }" + .JoinToString(", ")}" : players .Select(p => $"{p.Character}({p.PlayerNumber}){RankMedal(p.Rank)}") .JoinToString(", "); - string RankMedal(int? rank) => rank switch + static string RankMedal(int? rank) => rank switch { 0 => "🥇", 1 => "🥈", @@ -371,7 +369,7 @@ namespace Ryujinx.Ava.Systems.PlayReport "m_9417_e" => Playing("Zero Wing"), #endregion - + #region Nintendo 64 "n_1653_e" or "n_1653_p" => Playing("1080º ™ Snowboarding"), diff --git a/src/Ryujinx/Systems/PlayReport/PlayReports.cs b/src/Ryujinx/Systems/PlayReport/PlayReports.cs index e42ca185c..628194b19 100644 --- a/src/Ryujinx/Systems/PlayReport/PlayReports.cs +++ b/src/Ryujinx/Systems/PlayReport/PlayReports.cs @@ -1,4 +1,4 @@ -using System; +using System; namespace Ryujinx.Ava.Systems.PlayReport { diff --git a/src/Ryujinx/Systems/PlayReport/Specs.cs b/src/Ryujinx/Systems/PlayReport/Specs.cs index 2dd1c02ac..27ad6d868 100644 --- a/src/Ryujinx/Systems/PlayReport/Specs.cs +++ b/src/Ryujinx/Systems/PlayReport/Specs.cs @@ -1,4 +1,4 @@ -using MsgPack; +using MsgPack; using Ryujinx.Ava.Systems.AppLibrary; using System; using System.Collections.Generic; @@ -36,9 +36,8 @@ namespace Ryujinx.Ava.Systems.PlayReport : null; return this; } - - public List ValueFormatters { get; } = []; + public List ValueFormatters { get; } = []; /// /// Add a value formatter to the current @@ -66,7 +65,9 @@ namespace Ryujinx.Ava.Systems.PlayReport SingleValueFormatter valueFormatter ) => AddValueFormatter(new FormatterSpec { - Priority = priority, ReportKeys = [reportKey], Formatter = valueFormatter + Priority = priority, + ReportKeys = [reportKey], + Formatter = valueFormatter }); /// @@ -95,7 +96,9 @@ namespace Ryujinx.Ava.Systems.PlayReport MultiValueFormatter valueFormatter ) => AddValueFormatter(new MultiFormatterSpec { - Priority = priority, ReportKeys = reportKeys, Formatter = valueFormatter + Priority = priority, + ReportKeys = reportKeys, + Formatter = valueFormatter }); /// @@ -130,7 +133,9 @@ namespace Ryujinx.Ava.Systems.PlayReport SparseMultiValueFormatter valueFormatter ) => AddValueFormatter(new SparseMultiFormatterSpec { - Priority = priority, ReportKeys = reportKeys, Formatter = valueFormatter + Priority = priority, + ReportKeys = reportKeys, + Formatter = valueFormatter }); private GameSpec AddValueFormatter(T formatterSpec) where T : FormatterSpecBase diff --git a/src/Ryujinx/Systems/PlayReport/Value.cs b/src/Ryujinx/Systems/PlayReport/Value.cs index 1c738c213..9edbc42f1 100644 --- a/src/Ryujinx/Systems/PlayReport/Value.cs +++ b/src/Ryujinx/Systems/PlayReport/Value.cs @@ -1,4 +1,4 @@ -using MsgPack; +using MsgPack; using System; using System.Collections.Generic; using System.Linq; @@ -130,7 +130,7 @@ namespace Ryujinx.Ava.Systems.PlayReport /// A delegate singleton you can use to always return in a . /// public static readonly MultiValueFormatter MultiAlwaysResets = _ => ForceReset; - + /// /// A delegate singleton you can use to always return in a . /// @@ -142,14 +142,14 @@ namespace Ryujinx.Ava.Systems.PlayReport /// /// The string to always return for this delegate instance. public static SingleValueFormatter SingleAlwaysReturns(string formattedValue) => _ => formattedValue; - + /// /// A delegate factory you can use to always return the specified /// in a . /// /// The string to always return for this delegate instance. public static MultiValueFormatter MultiAlwaysReturns(string formattedValue) => _ => formattedValue; - + /// /// A delegate factory you can use to always return the specified /// in a . diff --git a/src/Ryujinx/Systems/Rebooter.cs b/src/Ryujinx/Systems/Rebooter.cs index 4b149e9e3..ac22dfb15 100644 --- a/src/Ryujinx/Systems/Rebooter.cs +++ b/src/Ryujinx/Systems/Rebooter.cs @@ -15,7 +15,6 @@ namespace Ryujinx.Ava.Systems private static readonly string _updateDir = Path.Combine(Path.GetTempPath(), "Ryujinx", "update"); - public static void RebootAppWithGame(string gamePath, List args) { _ = Reboot(gamePath, args); @@ -37,10 +36,9 @@ namespace Ryujinx.Ava.Systems if (shouldRestart) { - List arguments = CommandLineState.Arguments.ToList(); string executableDirectory = AppDomain.CurrentDomain.BaseDirectory; - var dialogTask = taskDialog.ShowAsync(true); + _ = taskDialog.ShowAsync(true); await Task.Delay(500); // Find the process name. diff --git a/src/Ryujinx/Systems/Updater.cs b/src/Ryujinx/Systems/Updater.cs index ee57906a7..b74b6eaa8 100644 --- a/src/Ryujinx/Systems/Updater.cs +++ b/src/Ryujinx/Systems/Updater.cs @@ -32,9 +32,9 @@ namespace Ryujinx.Ava.Systems internal static class Updater { private static ReleaseChannels.Channel? _currentReleaseChannel; - + private const string GitHubApiUrl = "https://api.github.com"; - + private static readonly GithubReleasesJsonSerializerContext _serializerContext = new(JsonHelper.GetDefaultSerializerOptions()); private static readonly string _homeDir = AppDomain.CurrentDomain.BaseDirectory; @@ -43,10 +43,10 @@ namespace Ryujinx.Ava.Systems 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; @@ -68,14 +68,14 @@ namespace Ryujinx.Ava.Systems return default; } - + Logger.Info?.Print(LogClass.Application, "Checking for updates."); - + // Get latest version number from GitHub API try { using HttpClient jsonClient = ConstructHttpClient(); - + if (_currentReleaseChannel == null) { ReleaseChannels releaseChannels = await ReleaseInformation.GetReleaseChannelsAsync(jsonClient); @@ -84,7 +84,7 @@ namespace Ryujinx.Ava.Systems ? releaseChannels.Canary : releaseChannels.Stable; } - + string fetchedJson = await jsonClient.GetStringAsync(_currentReleaseChannel.Value.GetLatestReleaseApiUrl()); GithubReleasesJsonResponse fetched = JsonHelper.Deserialize(fetchedJson, _serializerContext.GithubReleasesJsonResponse); _buildVer = fetched.TagName; @@ -108,7 +108,7 @@ namespace Ryujinx.Ava.Systems OpenHelper.OpenUrl(ReleaseInformation.GetChangelogForVersion(currentVersion, _currentReleaseChannel.Value)); } } - + Logger.Info?.Print(LogClass.Application, "Up to date."); _running = false; @@ -134,7 +134,7 @@ namespace Ryujinx.Ava.Systems OpenHelper.OpenUrl(ReleaseInformation.GetChangelogForVersion(currentVersion, _currentReleaseChannel.Value)); } } - + Logger.Info?.Print(LogClass.Application, "Up to date."); _running = false; @@ -169,7 +169,7 @@ namespace Ryujinx.Ava.Systems return (currentVersion, newVersion); } - + public static async Task BeginUpdateAsync(bool showVersionUpToDate = false) { if (_running) @@ -181,7 +181,8 @@ namespace Ryujinx.Ava.Systems Optional<(Version, Version)> versionTuple = await CheckVersionAsync(showVersionUpToDate); - if (_running is false || !versionTuple.HasValue) return; + if (_running is false || !versionTuple.HasValue) + return; (Version currentVersion, Version newVersion) = versionTuple.Value; @@ -198,7 +199,7 @@ namespace Ryujinx.Ava.Systems OpenHelper.OpenUrl(ReleaseInformation.GetChangelogForVersion(currentVersion, _currentReleaseChannel.Value)); } } - + Logger.Info?.Print(LogClass.Application, "Up to date."); _running = false; @@ -229,9 +230,9 @@ namespace Ryujinx.Ava.Systems string newVersionString = ReleaseInformation.IsCanaryBuild ? $"Canary {currentVersion} -> Canary {newVersion}" : $"{currentVersion} -> {newVersion}"; - + Logger.Info?.Print(LogClass.Application, $"Version found: {newVersionString}"); - + RequestUserToUpdate: // Show a message asking the user if they want to update UserResult shouldUpdate = await ContentDialogHelper.CreateUpdaterChoiceDialog( @@ -442,8 +443,8 @@ namespace Ryujinx.Ava.Systems // On macOS, ensure that we remove the quarantine bit to prevent Gatekeeper from blocking execution. if (OperatingSystem.IsMacOS()) { - using Process xattrProcess = Process.Start("xattr", - [ "-d", "com.apple.quarantine", updateFile ]); + using Process xattrProcess = Process.Start("xattr", + ["-d", "com.apple.quarantine", updateFile]); xattrProcess.WaitForExit(); } @@ -491,7 +492,7 @@ namespace Ryujinx.Ava.Systems using HttpResponseMessage response = client.GetAsync(downloadUrl, HttpCompletionOption.ResponseHeadersRead).Result; using Stream remoteFileStream = response.Content.ReadAsStreamAsync().Result; - using Stream updateFileStream = File.Open(updateFile, FileMode.Create); + using FileStream updateFileStream = File.Open(updateFile, FileMode.Create); long totalBytes = response.Content.Headers.ContentLength.Value; long bytesWritten = 0; @@ -538,7 +539,7 @@ namespace Ryujinx.Ava.Systems [SupportedOSPlatform("macos")] private static void ExtractTarGzipFile(TaskDialog taskDialog, string archivePath, string outputDirectoryPath) { - using Stream inStream = File.OpenRead(archivePath); + using FileStream inStream = File.OpenRead(archivePath); using GZipInputStream gzipStream = new(inStream); using TarInputStream tarStream = new(gzipStream, Encoding.ASCII); @@ -781,7 +782,7 @@ namespace Ryujinx.Ava.Systems public static void CleanupUpdate() => Directory.GetFiles(_homeDir, "*.ryuold", SearchOption.AllDirectories) .ForEach(File.Delete); - + private static string BuildPlatformExtension() { if (RunningPlatform.IsMacOS) @@ -800,7 +801,7 @@ namespace Ryujinx.Ava.Systems Architecture.X64 => "x64", _ => throw new PlatformNotSupportedException($"Unknown architecture {Enum.GetName(RunningPlatform.Architecture)}."), }; - + string fileExtension = RunningPlatform.CurrentOS switch #pragma warning restore CS8509 { diff --git a/src/Ryujinx/UI/Applet/AvaHostUIHandler.cs b/src/Ryujinx/UI/Applet/AvaHostUIHandler.cs index 18252f337..38670e5d5 100644 --- a/src/Ryujinx/UI/Applet/AvaHostUIHandler.cs +++ b/src/Ryujinx/UI/Applet/AvaHostUIHandler.cs @@ -3,11 +3,11 @@ using Avalonia.Threading; using FluentAvalonia.UI.Controls; using Gommon; using Ryujinx.Ava.Common.Locale; +using Ryujinx.Ava.Systems.Configuration; using Ryujinx.Ava.UI.Controls; using Ryujinx.Ava.UI.Helpers; using Ryujinx.Ava.UI.ViewModels; using Ryujinx.Ava.UI.Windows; -using Ryujinx.Ava.Systems.Configuration; using Ryujinx.Common; using Ryujinx.HLE; using Ryujinx.HLE.HOS.Applets; @@ -179,11 +179,13 @@ namespace Ryujinx.Ava.UI.Applet try { _parent.ViewModel.AppHost.NpadManager.BlockInputUpdates(); - SoftwareKeyboardUIArgs args = new(); - args.KeyboardMode = KeyboardMode.Default; - args.InitialText = "Ryujinx"; - args.StringLengthMin = 1; - args.StringLengthMax = 25; + SoftwareKeyboardUIArgs args = new() + { + KeyboardMode = KeyboardMode.Default, + InitialText = "Ryujinx", + StringLengthMin = 1, + StringLengthMax = 25 + }; (UserResult result, string userInput) = await SwkbdAppletDialog.ShowInputDialog(LocaleManager.Instance[LocaleKeys.CabinetDialog], args); if (result == UserResult.Ok) @@ -220,7 +222,6 @@ namespace Ryujinx.Ava.UI.Applet dialogCloseEvent.WaitOne(); } - public void ExecuteProgram(Switch device, ProgramSpecifyKind kind, ulong value) { device.Configuration.UserChannelPersistence.ExecuteProgram(kind, value); @@ -240,7 +241,9 @@ namespace Ryujinx.Ava.UI.Applet { ErrorAppletWindow msgDialog = new(_parent, buttons, message) { - Title = title, WindowStartupLocation = WindowStartupLocation.CenterScreen, Width = 400 + Title = title, + WindowStartupLocation = WindowStartupLocation.CenterScreen, + Width = 400 }; object response = await msgDialog.Run(); @@ -291,7 +294,8 @@ namespace Ryujinx.Ava.UI.Applet profiles.Add(new Models.UserProfile(guest, nav)); ProfileSelectorDialogViewModel viewModel = new() { - Profiles = profiles, SelectedUserId = _parent.AccountManager.LastOpenedUser.UserId + Profiles = profiles, + SelectedUserId = _parent.AccountManager.LastOpenedUser.UserId }; (selected, _) = await ProfileSelectorDialog.ShowInputDialog(viewModel); diff --git a/src/Ryujinx/UI/Applet/ProfileSelectorDialog.axaml.cs b/src/Ryujinx/UI/Applet/ProfileSelectorDialog.axaml.cs index 606a865a1..838a2f10a 100644 --- a/src/Ryujinx/UI/Applet/ProfileSelectorDialog.axaml.cs +++ b/src/Ryujinx/UI/Applet/ProfileSelectorDialog.axaml.cs @@ -21,10 +21,10 @@ namespace Ryujinx.Ava.UI.Applet public ProfileSelectorDialog(ProfileSelectorDialogViewModel viewModel) { DataContext = ViewModel = viewModel; - + InitializeComponent(); } - + private void Grid_PointerEntered(object sender, PointerEventArgs e) { if (sender is Grid { DataContext: UserProfile profile }) @@ -61,7 +61,7 @@ namespace Ryujinx.Ava.UI.Applet if (item is UserProfile originalItem) { UserProfileSft profile = new(originalItem.UserId, originalItem.Name, originalItem.Image); - + if (profile.UserId == ViewModel.SelectedUserId) { profile.AccountState = AccountState.Open; @@ -98,13 +98,13 @@ namespace Ryujinx.Ava.UI.Applet UserId result = UserId.Null; bool input = false; - + contentDialog.Closed += Handler; await ContentDialogHelper.ShowAsync(contentDialog); return (result, input); - + void Handler(ContentDialog sender, ContentDialogClosedEventArgs eventArgs) { if (eventArgs.Result == ContentDialogResult.Primary) diff --git a/src/Ryujinx/UI/Controls/ApplicationContextMenu.axaml.cs b/src/Ryujinx/UI/Controls/ApplicationContextMenu.axaml.cs index 1f9f6c691..c54cd390c 100644 --- a/src/Ryujinx/UI/Controls/ApplicationContextMenu.axaml.cs +++ b/src/Ryujinx/UI/Controls/ApplicationContextMenu.axaml.cs @@ -7,12 +7,12 @@ using LibHac.Tools.FsSystem.NcaUtils; using Ryujinx.Ava.Common; using Ryujinx.Ava.Common.Locale; using Ryujinx.Ava.Common.Models; +using Ryujinx.Ava.Systems.AppLibrary; using Ryujinx.Ava.UI.Helpers; using Ryujinx.Ava.UI.ViewModels; +using Ryujinx.Ava.UI.Views.Dialog; using Ryujinx.Ava.UI.Windows; using Ryujinx.Ava.Utilities; -using Ryujinx.Ava.Systems.AppLibrary; -using Ryujinx.Ava.UI.Views.Dialog; using Ryujinx.Common.Configuration; using Ryujinx.Common.Helper; using Ryujinx.HLE.HOS; diff --git a/src/Ryujinx/UI/Controls/MiniVerticalSeparator.cs b/src/Ryujinx/UI/Controls/MiniVerticalSeparator.cs index 7888879f5..7b802e165 100644 --- a/src/Ryujinx/UI/Controls/MiniVerticalSeparator.cs +++ b/src/Ryujinx/UI/Controls/MiniVerticalSeparator.cs @@ -1,4 +1,4 @@ -using Avalonia; +using Avalonia; using Avalonia.Controls; using Avalonia.Media; diff --git a/src/Ryujinx/UI/Controls/NavigationDialogHost.axaml.cs b/src/Ryujinx/UI/Controls/NavigationDialogHost.axaml.cs index 12c6a9daf..fb0bd5e82 100644 --- a/src/Ryujinx/UI/Controls/NavigationDialogHost.axaml.cs +++ b/src/Ryujinx/UI/Controls/NavigationDialogHost.axaml.cs @@ -154,12 +154,12 @@ namespace Ryujinx.Ava.UI.Controls if (profile == null) { - _ = Dispatcher.UIThread.InvokeAsync(async () + _ = Dispatcher.UIThread.InvokeAsync(async () => await ContentDialogHelper.CreateErrorDialog( LocaleManager.Instance[LocaleKeys.DialogUserProfileDeletionWarningMessage])); return; - } + } AccountManager.OpenUser(profile.UserId); } diff --git a/src/Ryujinx/UI/Controls/RyujinxControl.cs b/src/Ryujinx/UI/Controls/RyujinxControl.cs index 748d7ed94..f63f3f537 100644 --- a/src/Ryujinx/UI/Controls/RyujinxControl.cs +++ b/src/Ryujinx/UI/Controls/RyujinxControl.cs @@ -1,4 +1,4 @@ -using Avalonia.Controls; +using Avalonia.Controls; using Gommon; using Ryujinx.Ava.UI.ViewModels; using System; diff --git a/src/Ryujinx/UI/Controls/RyujinxLogo.cs b/src/Ryujinx/UI/Controls/RyujinxLogo.cs index 89b89f311..e1908fc2b 100644 --- a/src/Ryujinx/UI/Controls/RyujinxLogo.cs +++ b/src/Ryujinx/UI/Controls/RyujinxLogo.cs @@ -1,4 +1,4 @@ -using Avalonia; +using Avalonia; using Avalonia.Controls; using Avalonia.Media.Imaging; using Ryujinx.Ava.Systems.Configuration; @@ -15,7 +15,7 @@ namespace Ryujinx.Ava.UI.Controls public static readonly Bitmap Bitmap = new(Assembly.GetAssembly(typeof(MainWindowViewModel))! .GetManifestResourceStream("Ryujinx.Assets.UIImages.Logo_Ryujinx_AntiAlias.png")!); - + public RyujinxLogo() { Margin = new Thickness(7, 7, 7, 0); diff --git a/src/Ryujinx/UI/Helpers/AvaloniaListExtensions.cs b/src/Ryujinx/UI/Helpers/AvaloniaListExtensions.cs index f4a5dc0c1..60251a70f 100644 --- a/src/Ryujinx/UI/Helpers/AvaloniaListExtensions.cs +++ b/src/Ryujinx/UI/Helpers/AvaloniaListExtensions.cs @@ -59,4 +59,4 @@ namespace Ryujinx.Ava.UI.Helpers } } } -} \ No newline at end of file +} diff --git a/src/Ryujinx/UI/Helpers/Commands.cs b/src/Ryujinx/UI/Helpers/Commands.cs index 7a65c61a1..7ca35e885 100644 --- a/src/Ryujinx/UI/Helpers/Commands.cs +++ b/src/Ryujinx/UI/Helpers/Commands.cs @@ -1,4 +1,4 @@ -using CommunityToolkit.Mvvm.Input; +using CommunityToolkit.Mvvm.Input; using System; using System.Threading.Tasks; @@ -11,7 +11,7 @@ namespace Ryujinx.Ava.UI.Helpers => new(action); public static RelayCommand CreateConditional(Func canExecute, Action action) => new(action, canExecute); - + public static RelayCommand Create(Action action) => new(action); public static RelayCommand CreateConditional(Predicate canExecute, Action action) @@ -23,7 +23,7 @@ namespace Ryujinx.Ava.UI.Helpers => new(action, AsyncRelayCommandOptions.AllowConcurrentExecutions); public static AsyncRelayCommand CreateSilentFail(Func action) => new(action, AsyncRelayCommandOptions.FlowExceptionsToTaskScheduler); - + public static AsyncRelayCommand Create(Func action) => new(action, AsyncRelayCommandOptions.None); public static AsyncRelayCommand CreateConcurrent(Func action) @@ -37,7 +37,7 @@ namespace Ryujinx.Ava.UI.Helpers => new(action, canExecute, AsyncRelayCommandOptions.AllowConcurrentExecutions); public static AsyncRelayCommand CreateSilentFailConditional(Func canExecute, Func action) => new(action, canExecute, AsyncRelayCommandOptions.FlowExceptionsToTaskScheduler); - + public static AsyncRelayCommand CreateConditional(Predicate canExecute, Func action) => new(action, canExecute, AsyncRelayCommandOptions.None); public static AsyncRelayCommand CreateConcurrentConditional(Predicate canExecute, Func action) diff --git a/src/Ryujinx/UI/Helpers/ContentDialogHelper.cs b/src/Ryujinx/UI/Helpers/ContentDialogHelper.cs index a93b2894e..e8730913c 100644 --- a/src/Ryujinx/UI/Helpers/ContentDialogHelper.cs +++ b/src/Ryujinx/UI/Helpers/ContentDialogHelper.cs @@ -23,13 +23,13 @@ namespace Ryujinx.Ava.UI.Helpers private static ContentDialogOverlayWindow _contentDialogOverlayWindow; public static ContentDialog ApplyStyles( - this ContentDialog contentDialog, - double closeButtonWidth = 80, + this ContentDialog contentDialog, + double closeButtonWidth = 80, HorizontalAlignment buttonSpaceAlignment = HorizontalAlignment.Right) { Style closeButton = new(x => x.Name("CloseButton")); closeButton.Setters.Add(new Setter(Layoutable.WidthProperty, closeButtonWidth)); - + Style closeButtonParent = new(x => x.Name("CommandSpace")); closeButtonParent.Setters.Add(new Setter(Layoutable.HorizontalAlignmentProperty, buttonSpaceAlignment)); @@ -281,7 +281,7 @@ namespace Ryujinx.Ava.UI.Helpers string.Empty, LocaleManager.Instance[LocaleKeys.InputDialogOk], (int)Symbol.Important); - + internal static async Task CreateUpdaterUpToDateInfoDialog(string primary, string secondaryText) => await ShowTextDialog( LocaleManager.Instance[LocaleKeys.DialogUpdaterTitle], @@ -339,7 +339,7 @@ namespace Ryujinx.Ava.UI.Helpers return response == UserResult.Yes; } - + internal static async Task CreateUpdaterChoiceDialog(string title, string primary, string secondaryText) { if (_isChoiceDialogOpen) @@ -403,7 +403,7 @@ namespace Ryujinx.Ava.UI.Helpers Position = parent.PointToScreen(new Point()), ShowInTaskbar = false, }; - + #if DEBUG _contentDialogOverlayWindow.AttachDevTools(new KeyGesture(Key.F12, KeyModifiers.Control)); #endif @@ -480,7 +480,7 @@ namespace Ryujinx.Ava.UI.Helpers await dialogWindow.ShowDialog(_contentDialogOverlayWindow ?? mainWindow ?? GetMainWindow()); } - private static Window GetMainWindow() + private static MainWindow GetMainWindow() { if (Application.Current?.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime al) { diff --git a/src/Ryujinx/UI/Helpers/Converters/DownloadableContentLabelConverter.cs b/src/Ryujinx/UI/Helpers/Converters/DownloadableContentLabelConverter.cs index 7ed26050c..8053c1b65 100644 --- a/src/Ryujinx/UI/Helpers/Converters/DownloadableContentLabelConverter.cs +++ b/src/Ryujinx/UI/Helpers/Converters/DownloadableContentLabelConverter.cs @@ -37,6 +37,5 @@ namespace Ryujinx.Ava.UI.Helpers { throw new NotImplementedException(); } - } } diff --git a/src/Ryujinx/UI/Helpers/Converters/KeyValueConverter.cs b/src/Ryujinx/UI/Helpers/Converters/KeyValueConverter.cs index e7a157892..d153adc74 100644 --- a/src/Ryujinx/UI/Helpers/Converters/KeyValueConverter.cs +++ b/src/Ryujinx/UI/Helpers/Converters/KeyValueConverter.cs @@ -150,6 +150,7 @@ namespace Ryujinx.Ava.UI.Helpers { keyString = key.ToString(); } + break; case GamepadInputId gamepadInputId: if (_gamepadInputIdMap.TryGetValue(gamepadInputId, out localeKey)) @@ -160,6 +161,7 @@ namespace Ryujinx.Ava.UI.Helpers { keyString = gamepadInputId.ToString(); } + break; case StickInputId stickInputId: if (_stickInputIdMap.TryGetValue(stickInputId, out localeKey)) @@ -170,6 +172,7 @@ namespace Ryujinx.Ava.UI.Helpers { keyString = stickInputId.ToString(); } + break; } diff --git a/src/Ryujinx/UI/Helpers/Converters/MultiplayerInfoConverter.cs b/src/Ryujinx/UI/Helpers/Converters/MultiplayerInfoConverter.cs index 1dca0d164..28552d611 100644 --- a/src/Ryujinx/UI/Helpers/Converters/MultiplayerInfoConverter.cs +++ b/src/Ryujinx/UI/Helpers/Converters/MultiplayerInfoConverter.cs @@ -17,7 +17,7 @@ namespace Ryujinx.Ava.UI.Helpers { if (value is not ApplicationData { HasLdnGames: true } applicationData) return ""; - + return new StringBuilder() .AppendLine( LocaleManager.Instance[LocaleKeys.GameListHeaderHostedGames] diff --git a/src/Ryujinx/UI/Helpers/Converters/PlayabilityStatusConverter.cs b/src/Ryujinx/UI/Helpers/Converters/PlayabilityStatusConverter.cs index c8082ec62..dce42fa29 100644 --- a/src/Ryujinx/UI/Helpers/Converters/PlayabilityStatusConverter.cs +++ b/src/Ryujinx/UI/Helpers/Converters/PlayabilityStatusConverter.cs @@ -1,4 +1,4 @@ -using Avalonia.Data.Converters; +using Avalonia.Data.Converters; using Avalonia.Media; using Gommon; using Ryujinx.Ava.Common.Locale; @@ -15,8 +15,8 @@ namespace Ryujinx.Ava.UI.Helpers public object Convert(object value, Type _, object __, CultureInfo ___) => value.Cast() switch { - LocaleKeys.CompatibilityListNothing or - LocaleKeys.CompatibilityListBoots or + LocaleKeys.CompatibilityListNothing or + LocaleKeys.CompatibilityListBoots or LocaleKeys.CompatibilityListMenus => Brushes.Red, LocaleKeys.CompatibilityListIngame => Brushes.DarkOrange, _ => Brushes.ForestGreen diff --git a/src/Ryujinx/UI/Helpers/Converters/XCITrimmerFileStatusConverter.cs b/src/Ryujinx/UI/Helpers/Converters/XCITrimmerFileStatusConverter.cs index c3fb1fe95..9a0e9fcbf 100644 --- a/src/Ryujinx/UI/Helpers/Converters/XCITrimmerFileStatusConverter.cs +++ b/src/Ryujinx/UI/Helpers/Converters/XCITrimmerFileStatusConverter.cs @@ -31,7 +31,7 @@ namespace Ryujinx.Ava.UI.Helpers } return app.PercentageProgress != null ? String.Empty : - app.ProcessingOutcome != OperationOutcome.Successful && app.ProcessingOutcome != OperationOutcome.Undetermined ? LocaleManager.Instance[LocaleKeys.TitleXCIStatusFailedLabel] : + app.ProcessingOutcome is not OperationOutcome.Successful and not OperationOutcome.Undetermined ? LocaleManager.Instance[LocaleKeys.TitleXCIStatusFailedLabel] : app.Trimmable & app.Untrimmable ? LocaleManager.Instance[LocaleKeys.TitleXCIStatusPartialLabel] : app.Trimmable ? LocaleManager.Instance[LocaleKeys.TitleXCIStatusTrimmableLabel] : app.Untrimmable ? LocaleManager.Instance[LocaleKeys.TitleXCIStatusUntrimmableLabel] : diff --git a/src/Ryujinx/UI/Helpers/Converters/XCITrimmerFileStatusDetailConverter.cs b/src/Ryujinx/UI/Helpers/Converters/XCITrimmerFileStatusDetailConverter.cs index e12d4efd9..b83fe485d 100644 --- a/src/Ryujinx/UI/Helpers/Converters/XCITrimmerFileStatusDetailConverter.cs +++ b/src/Ryujinx/UI/Helpers/Converters/XCITrimmerFileStatusDetailConverter.cs @@ -30,7 +30,7 @@ namespace Ryujinx.Ava.UI.Helpers } return app.PercentageProgress != null ? null : - app.ProcessingOutcome != OperationOutcome.Successful && app.ProcessingOutcome != OperationOutcome.Undetermined ? app.ProcessingOutcome.ToLocalisedText() : + app.ProcessingOutcome is not OperationOutcome.Successful and not OperationOutcome.Undetermined ? app.ProcessingOutcome.ToLocalisedText() : null; } diff --git a/src/Ryujinx/UI/Helpers/IconColorPicker.cs b/src/Ryujinx/UI/Helpers/IconColorPicker.cs index b6ee8bbbf..f73f58c17 100644 --- a/src/Ryujinx/UI/Helpers/IconColorPicker.cs +++ b/src/Ryujinx/UI/Helpers/IconColorPicker.cs @@ -31,7 +31,6 @@ namespace Ryujinx.Ava.UI.Helpers { SKColor color = GetColor(image); - // We don't want colors that are too dark. // If the color is too dark, make it brighter by reducing the range // and adding a constant color. diff --git a/src/Ryujinx/UI/Helpers/LoggerAdapter.cs b/src/Ryujinx/UI/Helpers/LoggerAdapter.cs index 902d3966f..c9d1c79c2 100644 --- a/src/Ryujinx/UI/Helpers/LoggerAdapter.cs +++ b/src/Ryujinx/UI/Helpers/LoggerAdapter.cs @@ -15,19 +15,20 @@ namespace Ryujinx.Ava.UI.Helpers internal class LoggerAdapter : ILogSink { - private static bool _avaloniaLogsEnabled = ConfigurationState.Instance.Logger.EnableAvaloniaLog; - + private static bool _avaloniaLogsEnabled = ConfigurationState.Instance.Logger.EnableAvaloniaLog; + public static void Register() { AvaLogger.Sink = new LoggerAdapter(); - ConfigurationState.Instance.Logger.EnableAvaloniaLog.Event + ConfigurationState.Instance.Logger.EnableAvaloniaLog.Event += (_, e) => _avaloniaLogsEnabled = e.NewValue; } private static RyuLogger.Log? GetLog(AvaLogLevel level, string area) { - if (!_avaloniaLogsEnabled) return null; - + if (!_avaloniaLogsEnabled) + return null; + return level switch { AvaLogLevel.Verbose => RyuLogger.Debug, diff --git a/src/Ryujinx/UI/Helpers/NotificationHelper.cs b/src/Ryujinx/UI/Helpers/NotificationHelper.cs index d4d898687..dfc5844d5 100644 --- a/src/Ryujinx/UI/Helpers/NotificationHelper.cs +++ b/src/Ryujinx/UI/Helpers/NotificationHelper.cs @@ -64,7 +64,7 @@ namespace Ryujinx.Ava.UI.Helpers public static void ShowError(string message) => ShowError( - LocaleManager.Instance[LocaleKeys.DialogErrorTitle], + LocaleManager.Instance[LocaleKeys.DialogErrorTitle], $"{LocaleManager.Instance[LocaleKeys.DialogErrorMessage]}\n\n{message}" ); @@ -73,8 +73,8 @@ namespace Ryujinx.Ava.UI.Helpers title, text, NotificationType.Information, - waitingExit, - onClick, + waitingExit, + onClick, onClose); public static void ShowSuccess(string title, string text, bool waitingExit = false, Action onClick = null, Action onClose = null) => @@ -82,8 +82,8 @@ namespace Ryujinx.Ava.UI.Helpers title, text, NotificationType.Success, - waitingExit, - onClick, + waitingExit, + onClick, onClose); public static void ShowWarning(string title, string text, bool waitingExit = false, Action onClick = null, Action onClose = null) => @@ -91,8 +91,8 @@ namespace Ryujinx.Ava.UI.Helpers title, text, NotificationType.Warning, - waitingExit, - onClick, + waitingExit, + onClick, onClose); public static void ShowError(string title, string text, bool waitingExit = false, Action onClick = null, Action onClose = null) => @@ -100,8 +100,8 @@ namespace Ryujinx.Ava.UI.Helpers title, text, NotificationType.Error, - waitingExit, - onClick, + waitingExit, + onClick, onClose); } } diff --git a/src/Ryujinx/UI/Helpers/Win32NativeInterop.cs b/src/Ryujinx/UI/Helpers/Win32NativeInterop.cs index 48f98f44a..d7466e95b 100644 --- a/src/Ryujinx/UI/Helpers/Win32NativeInterop.cs +++ b/src/Ryujinx/UI/Helpers/Win32NativeInterop.cs @@ -28,7 +28,6 @@ namespace Ryujinx.Ava.UI.Helpers IdcArrow = 32512, } - [SuppressMessage("Design", "CA1069: Enums values should not be duplicated")] public enum WindowsMessages : uint { NcHitTest = 0x0084, diff --git a/src/Ryujinx/UI/Helpers/XCITrimmerOperationOutcomeHelper.cs b/src/Ryujinx/UI/Helpers/XCITrimmerOperationOutcomeHelper.cs index 93489f806..1a0e126c8 100644 --- a/src/Ryujinx/UI/Helpers/XCITrimmerOperationOutcomeHelper.cs +++ b/src/Ryujinx/UI/Helpers/XCITrimmerOperationOutcomeHelper.cs @@ -33,4 +33,4 @@ namespace Ryujinx.Ava.UI.Helpers } } } -} \ No newline at end of file +} diff --git a/src/Ryujinx/UI/Models/Input/GamepadInputConfig.cs b/src/Ryujinx/UI/Models/Input/GamepadInputConfig.cs index 5ebfe4654..526e63afe 100644 --- a/src/Ryujinx/UI/Models/Input/GamepadInputConfig.cs +++ b/src/Ryujinx/UI/Models/Input/GamepadInputConfig.cs @@ -46,21 +46,21 @@ namespace Ryujinx.Ava.UI.Models.Input [ObservableProperty] private GamepadInputId _buttonMinus; [ObservableProperty] private GamepadInputId _buttonPlus; - + [ObservableProperty] private GamepadInputId _buttonA; [ObservableProperty] private GamepadInputId _buttonB; [ObservableProperty] private GamepadInputId _buttonX; [ObservableProperty] private GamepadInputId _buttonY; - + [ObservableProperty] private GamepadInputId _buttonZl; [ObservableProperty] private GamepadInputId _buttonZr; - + [ObservableProperty] private GamepadInputId _buttonL; [ObservableProperty] private GamepadInputId _buttonR; - + [ObservableProperty] private GamepadInputId _leftButtonSl; [ObservableProperty] private GamepadInputId _leftButtonSr; - + [ObservableProperty] private GamepadInputId _rightButtonSl; [ObservableProperty] private GamepadInputId _rightButtonSr; @@ -73,17 +73,17 @@ namespace Ryujinx.Ava.UI.Models.Input [ObservableProperty] private float _triggerThreshold; [ObservableProperty] private bool _enableMotion; - + [ObservableProperty] private bool _enableRumble; - + [ObservableProperty] private bool _enableLedChanging; - + [ObservableProperty] private Color _ledColor; - + public bool ShowLedColorPicker => !TurnOffLed && !UseRainbowLed; - + private bool _turnOffLed; - + public bool TurnOffLed { get => _turnOffLed; @@ -94,9 +94,9 @@ namespace Ryujinx.Ava.UI.Models.Input OnPropertyChanged(nameof(ShowLedColorPicker)); } } - + private bool _useRainbowLed; - + public bool UseRainbowLed { get => _useRainbowLed; @@ -183,7 +183,7 @@ namespace Ryujinx.Ava.UI.Models.Input WeakRumble = controllerInput.Rumble.WeakRumble; StrongRumble = controllerInput.Rumble.StrongRumble; } - + if (controllerInput.Led != null) { EnableLedChanging = controllerInput.Led.EnableLed; @@ -204,7 +204,7 @@ namespace Ryujinx.Ava.UI.Models.Input StandardControllerInputConfig config = new() { Id = Id, - Name = Name, + Name = Name, Backend = InputBackendType.GamepadSDL2, PlayerIndex = PlayerIndex, ControllerType = ControllerType, diff --git a/src/Ryujinx/UI/Models/Input/KeyboardInputConfig.cs b/src/Ryujinx/UI/Models/Input/KeyboardInputConfig.cs index a115aa0f2..0213d72fe 100644 --- a/src/Ryujinx/UI/Models/Input/KeyboardInputConfig.cs +++ b/src/Ryujinx/UI/Models/Input/KeyboardInputConfig.cs @@ -29,24 +29,24 @@ namespace Ryujinx.Ava.UI.Models.Input [ObservableProperty] private Key _dpadDown; [ObservableProperty] private Key _dpadLeft; [ObservableProperty] private Key _dpadRight; - + [ObservableProperty] private Key _buttonMinus; [ObservableProperty] private Key _buttonPlus; - + [ObservableProperty] private Key _buttonA; [ObservableProperty] private Key _buttonB; [ObservableProperty] private Key _buttonX; [ObservableProperty] private Key _buttonY; - + [ObservableProperty] private Key _buttonL; [ObservableProperty] private Key _buttonR; - + [ObservableProperty] private Key _buttonZl; [ObservableProperty] private Key _buttonZr; - + [ObservableProperty] private Key _leftButtonSl; [ObservableProperty] private Key _leftButtonSr; - + [ObservableProperty] private Key _rightButtonSl; [ObservableProperty] private Key _rightButtonSr; diff --git a/src/Ryujinx/UI/Models/Input/StickVisualizer.cs b/src/Ryujinx/UI/Models/Input/StickVisualizer.cs index b7e9ec331..f88f4ea72 100644 --- a/src/Ryujinx/UI/Models/Input/StickVisualizer.cs +++ b/src/Ryujinx/UI/Models/Input/StickVisualizer.cs @@ -96,9 +96,9 @@ namespace Ryujinx.Ava.UI.Models.Input public float UiStickRightX => ClampVector(UiStickRight).Item1; public float UiStickRightY => ClampVector(UiStickRight).Item2; - public int UiStickCircumference => DrawStickCircumference; - public int UiCanvasSize => DrawStickCanvasSize; - public int UiStickBorderSize => DrawStickBorderSize; + public static int UiStickCircumference => DrawStickCircumference; + public static int UiCanvasSize => DrawStickCanvasSize; + public static int UiStickBorderSize => DrawStickBorderSize; public float? UiDeadzoneLeft => _gamepadConfig?.DeadzoneLeft * DrawStickCanvasSize - DrawStickCircumference; public float? UiDeadzoneRight => _gamepadConfig?.DeadzoneRight * DrawStickCanvasSize - DrawStickCircumference; @@ -158,14 +158,17 @@ namespace Ryujinx.Ava.UI.Models.Input { leftBuffer.Item1 += 1; } + if (snapshot.IsPressed((Key)KeyboardConfig.LeftStickLeft)) { leftBuffer.Item1 -= 1; } + if (snapshot.IsPressed((Key)KeyboardConfig.LeftStickUp)) { leftBuffer.Item2 += 1; } + if (snapshot.IsPressed((Key)KeyboardConfig.LeftStickDown)) { leftBuffer.Item2 -= 1; @@ -175,14 +178,17 @@ namespace Ryujinx.Ava.UI.Models.Input { rightBuffer.Item1 += 1; } + if (snapshot.IsPressed((Key)KeyboardConfig.RightStickLeft)) { rightBuffer.Item1 -= 1; } + if (snapshot.IsPressed((Key)KeyboardConfig.RightStickUp)) { rightBuffer.Item2 += 1; } + if (snapshot.IsPressed((Key)KeyboardConfig.RightStickDown)) { rightBuffer.Item2 -= 1; @@ -191,6 +197,7 @@ namespace Ryujinx.Ava.UI.Models.Input UiStickLeft = leftBuffer; UiStickRight = rightBuffer; } + break; case DeviceType.Controller: @@ -201,6 +208,7 @@ namespace Ryujinx.Ava.UI.Models.Input leftBuffer = controller.GetStick((StickInputId)GamepadConfig.LeftJoystick); rightBuffer = controller.GetStick((StickInputId)GamepadConfig.RightJoystick); } + break; case DeviceType.None: diff --git a/src/Ryujinx/UI/Models/ModModel.cs b/src/Ryujinx/UI/Models/ModModel.cs index 3b3cbbbc9..91804d365 100644 --- a/src/Ryujinx/UI/Models/ModModel.cs +++ b/src/Ryujinx/UI/Models/ModModel.cs @@ -12,7 +12,7 @@ namespace Ryujinx.Ava.UI.Models public string Path { get; } public string Name { get; } - public string FormattedName => + public string FormattedName => InSd && ulong.TryParse(Name, NumberStyles.HexNumber, null, out ulong applicationId) ? $"Atmosphère: {RyujinxApp.MainWindow.ApplicationLibrary.GetNameForApplicationId(applicationId)}" : Name; diff --git a/src/Ryujinx/UI/Models/SaveModel.cs b/src/Ryujinx/UI/Models/SaveModel.cs index 1a4718ddf..d245ed4d9 100644 --- a/src/Ryujinx/UI/Models/SaveModel.cs +++ b/src/Ryujinx/UI/Models/SaveModel.cs @@ -1,9 +1,9 @@ using Gommon; using LibHac.Fs; using LibHac.Ncm; +using Ryujinx.Ava.Systems.AppLibrary; using Ryujinx.Ava.UI.ViewModels; using Ryujinx.Ava.Utilities; -using Ryujinx.Ava.Systems.AppLibrary; using Ryujinx.HLE.FileSystem; using System.IO; using System.Linq; diff --git a/src/Ryujinx/UI/Models/StatusUpdatedEventArgs.cs b/src/Ryujinx/UI/Models/StatusUpdatedEventArgs.cs index 9755aad46..bda998bd8 100644 --- a/src/Ryujinx/UI/Models/StatusUpdatedEventArgs.cs +++ b/src/Ryujinx/UI/Models/StatusUpdatedEventArgs.cs @@ -23,10 +23,10 @@ namespace Ryujinx.Ava.UI.Models ShaderCount = shaderCount; } - public override bool Equals(object obj) { - if (obj is not StatusUpdatedEventArgs suea) return false; + if (obj is not StatusUpdatedEventArgs suea) + return false; return VSyncMode == suea.VSyncMode && VolumeStatus == suea.VolumeStatus && @@ -37,7 +37,7 @@ namespace Ryujinx.Ava.UI.Models ShaderCount == suea.ShaderCount; } - public override int GetHashCode() + public override int GetHashCode() => HashCode.Combine(VSyncMode, VolumeStatus, AspectRatio, DockedMode, FifoStatus, GameStatus, ShaderCount); } } diff --git a/src/Ryujinx/UI/Renderer/EmbeddedWindow.cs b/src/Ryujinx/UI/Renderer/EmbeddedWindow.cs index 7b642bb9d..e360d42f7 100644 --- a/src/Ryujinx/UI/Renderer/EmbeddedWindow.cs +++ b/src/Ryujinx/UI/Renderer/EmbeddedWindow.cs @@ -115,7 +115,7 @@ namespace Ryujinx.Ava.UI.Renderer } [SupportedOSPlatform("linux")] - private IPlatformHandle CreateLinux(IPlatformHandle control) + private PlatformHandle CreateLinux(IPlatformHandle control) { if (ConfigurationState.Instance.Graphics.GraphicsBackend.Value == GraphicsBackend.Vulkan) { @@ -134,7 +134,7 @@ namespace Ryujinx.Ava.UI.Renderer } [SupportedOSPlatform("windows")] - IPlatformHandle CreateWin32(IPlatformHandle control) + PlatformHandle CreateWin32(IPlatformHandle control) { _className = "NativeWindow-" + Guid.NewGuid(); @@ -171,7 +171,7 @@ namespace Ryujinx.Ava.UI.Renderer } [SupportedOSPlatform("macos")] - IPlatformHandle CreateMacOS() + PlatformHandle CreateMacOS() { // Create a new CAMetalLayer. ObjectiveC.Object layerObject = new("CAMetalLayer"); @@ -215,11 +215,9 @@ namespace Ryujinx.Ava.UI.Renderer } [SupportedOSPlatform("macos")] -#pragma warning disable CA1822 // Mark member as static - void DestroyMacOS() + static void DestroyMacOS() { // TODO } -#pragma warning restore CA1822 } } diff --git a/src/Ryujinx/UI/Renderer/RendererHost.cs b/src/Ryujinx/UI/Renderer/RendererHost.cs index fd7124f2b..9d24fbbad 100644 --- a/src/Ryujinx/UI/Renderer/RendererHost.cs +++ b/src/Ryujinx/UI/Renderer/RendererHost.cs @@ -1,4 +1,4 @@ -using Avalonia; +using Avalonia; using Avalonia.Controls; using Avalonia.Media; using Ryujinx.Ava.Systems.Configuration; @@ -36,8 +36,8 @@ namespace Ryujinx.Ava.UI.Renderer EmbeddedWindowOpenGL => GraphicsBackend.OpenGl, _ => throw new NotImplementedException() }; - - + + private void Initialize() { EmbeddedWindow.WindowCreated += CurrentWindow_WindowCreated; diff --git a/src/Ryujinx/UI/RyujinxApp.axaml.cs b/src/Ryujinx/UI/RyujinxApp.axaml.cs index 2f460f2b3..34c2d96ca 100644 --- a/src/Ryujinx/UI/RyujinxApp.axaml.cs +++ b/src/Ryujinx/UI/RyujinxApp.axaml.cs @@ -8,11 +8,11 @@ using Avalonia.Threading; using FluentAvalonia.UI.Windowing; using Gommon; using Ryujinx.Ava.Common.Locale; +using Ryujinx.Ava.Systems.Configuration; using Ryujinx.Ava.UI.Helpers; +using Ryujinx.Ava.UI.Views.Dialog; using Ryujinx.Ava.UI.Windows; using Ryujinx.Ava.Utilities; -using Ryujinx.Ava.Systems.Configuration; -using Ryujinx.Ava.UI.Views.Dialog; using Ryujinx.Common; using Ryujinx.Common.Logging; using System; @@ -23,7 +23,7 @@ namespace Ryujinx.Ava public class RyujinxApp : Application { public static event Action ThemeChanged; - + internal static string FormatTitle(LocaleKeys? windowTitleKey = null, bool includeVersion = true) => windowTitleKey is null ? $"{FullAppName}{(includeVersion ? $" {Program.Version}" : string.Empty)}" @@ -34,7 +34,7 @@ namespace Ryujinx.Ava public static MainWindow MainWindow => Current! .ApplicationLifetime.Cast() .MainWindow.Cast(); - + public static IClassicDesktopStyleApplicationLifetime AppLifetime => Current! .ApplicationLifetime.Cast(); @@ -48,7 +48,6 @@ namespace Ryujinx.Ava public static void SetTaskbarProgressValue(ulong current, ulong total) => MainWindow.PlatformFeatures.SetTaskBarProgressBarValue(current, total); public static void SetTaskbarProgressValue(long current, long total) => SetTaskbarProgressValue(Convert.ToUInt64(current), Convert.ToUInt64(total)); - public override void Initialize() { Name = FormatTitle(); diff --git a/src/Ryujinx/UI/ViewModels/AboutWindowViewModel.cs b/src/Ryujinx/UI/ViewModels/AboutWindowViewModel.cs index e3225d19d..727294992 100644 --- a/src/Ryujinx/UI/ViewModels/AboutWindowViewModel.cs +++ b/src/Ryujinx/UI/ViewModels/AboutWindowViewModel.cs @@ -14,7 +14,7 @@ namespace Ryujinx.Ava.UI.ViewModels [ObservableProperty] private Bitmap _gitLabLogo; [ObservableProperty] private Bitmap _discordLogo; [ObservableProperty] private string _version; - + public string Developers => "GreemDev, LotP"; public string FormerDevelopers => LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.AboutPageDeveloperListMore, "gdkchan, Ac_K, marysaka, rip in peri peri, LDj3SNuD, emmaus, Thealexbarney, GoffyDude, TSRBerry, IsaacMarovitz"); @@ -37,9 +37,9 @@ namespace Ryujinx.Ava.UI.ViewModels private void UpdateLogoTheme(string theme) { bool isDarkTheme = theme == "Dark" || (theme == "Auto" && RyujinxApp.DetectSystemTheme() == ThemeVariant.Dark); - + string themeName = isDarkTheme ? "Dark" : "Light"; - + DiscordLogo = LoadBitmap(LogoPathFormat.Format("Discord", themeName)); GitLabLogo = LoadBitmap(LogoPathFormat.Format("GitLab", themeName)); } @@ -49,10 +49,10 @@ namespace Ryujinx.Ava.UI.ViewModels public void Dispose() { RyujinxApp.ThemeChanged -= Ryujinx_ThemeChanged; - + GitLabLogo.Dispose(); DiscordLogo.Dispose(); - + GC.SuppressFinalize(this); } } diff --git a/src/Ryujinx/UI/ViewModels/ApplicationDataViewModel.cs b/src/Ryujinx/UI/ViewModels/ApplicationDataViewModel.cs index 4bffcb7d3..431503e71 100644 --- a/src/Ryujinx/UI/ViewModels/ApplicationDataViewModel.cs +++ b/src/Ryujinx/UI/ViewModels/ApplicationDataViewModel.cs @@ -1,4 +1,4 @@ -using Gommon; +using Gommon; using Ryujinx.Ava.Common.Locale; using Ryujinx.Ava.Systems.AppLibrary; using Ryujinx.Ava.Systems.PlayReport; @@ -20,8 +20,8 @@ namespace Ryujinx.Ava.UI.ViewModels public string FormattedDeveloper => LocaleManager.Instance[LocaleKeys.GameListHeaderDeveloper].Format(AppData.Developer); public string FormattedFileExtension => LocaleManager.Instance[LocaleKeys.GameListHeaderFileExtension].Format(AppData.FileExtension); public string FormattedFileSize => LocaleManager.Instance[LocaleKeys.GameListHeaderFileSize].Format(AppData.FileSizeString); - - public string FormattedLdnInfo => + + public string FormattedLdnInfo => $"{LocaleManager.Instance[LocaleKeys.GameListHeaderHostedGames].Format(AppData.GameCount)}" + $"\n" + $"{LocaleManager.Instance[LocaleKeys.GameListHeaderPlayerCount].Format(AppData.PlayerCount)}"; diff --git a/src/Ryujinx/UI/ViewModels/CompatibilityViewModel.cs b/src/Ryujinx/UI/ViewModels/CompatibilityViewModel.cs index 1965fee69..9aa2f468c 100644 --- a/src/Ryujinx/UI/ViewModels/CompatibilityViewModel.cs +++ b/src/Ryujinx/UI/ViewModels/CompatibilityViewModel.cs @@ -1,4 +1,4 @@ -using Gommon; +using Gommon; using Ryujinx.Ava.Systems; using Ryujinx.Ava.Systems.AppLibrary; using System; @@ -19,15 +19,15 @@ namespace Ryujinx.Ava.UI.ViewModels x.TitleId.Check(tid => _ownedGameTitleIds.ContainsIgnoreCase(tid))) : _currentEntries; - public CompatibilityViewModel() {} - + public CompatibilityViewModel() { } + private void AppCountUpdated(object _, ApplicationCountUpdatedEventArgs __) => _ownedGameTitleIds = _appLibrary.Applications.Keys.Select(x => x.ToString("X16")).ToArray(); public CompatibilityViewModel(ApplicationLibrary appLibrary) { _appLibrary = appLibrary; - + AppCountUpdated(null, null); _appLibrary.ApplicationCountUpdated += AppCountUpdated; @@ -38,7 +38,7 @@ namespace Ryujinx.Ava.UI.ViewModels GC.SuppressFinalize(this); _appLibrary.ApplicationCountUpdated -= AppCountUpdated; } - + private bool _onlyShowOwnedGames = true; public bool OnlyShowOwnedGames @@ -69,9 +69,7 @@ namespace Ryujinx.Ava.UI.ViewModels private void SetEntries(IEnumerable entries) { -#pragma warning disable MVVMTK0034 _currentEntries = entries.ToList(); -#pragma warning restore MVVMTK0034 OnPropertyChanged(nameof(CurrentEntries)); } } diff --git a/src/Ryujinx/UI/ViewModels/DlcSelectViewModel.cs b/src/Ryujinx/UI/ViewModels/DlcSelectViewModel.cs index e236ac737..643614d6e 100644 --- a/src/Ryujinx/UI/ViewModels/DlcSelectViewModel.cs +++ b/src/Ryujinx/UI/ViewModels/DlcSelectViewModel.cs @@ -1,4 +1,4 @@ -using CommunityToolkit.Mvvm.ComponentModel; +using CommunityToolkit.Mvvm.ComponentModel; using Ryujinx.Ava.Common.Models; using Ryujinx.Ava.Systems.AppLibrary; using System.Linq; @@ -8,10 +8,10 @@ namespace Ryujinx.Ava.UI.ViewModels public partial class DlcSelectViewModel : BaseModel { [ObservableProperty] private DownloadableContentModel[] _dlcs; - #nullable enable +#nullable enable [ObservableProperty] private DownloadableContentModel? _selectedDlc; - #nullable disable - +#nullable disable + public DlcSelectViewModel(ulong titleId, ApplicationLibrary appLibrary) { _dlcs = appLibrary.FindDlcsFor(titleId) diff --git a/src/Ryujinx/UI/ViewModels/DownloadableContentManagerViewModel.cs b/src/Ryujinx/UI/ViewModels/DownloadableContentManagerViewModel.cs index dc1e928f1..c048b481c 100644 --- a/src/Ryujinx/UI/ViewModels/DownloadableContentManagerViewModel.cs +++ b/src/Ryujinx/UI/ViewModels/DownloadableContentManagerViewModel.cs @@ -6,8 +6,8 @@ using DynamicData; using FluentAvalonia.UI.Controls; using Ryujinx.Ava.Common.Locale; using Ryujinx.Ava.Common.Models; -using Ryujinx.Ava.UI.Helpers; using Ryujinx.Ava.Systems.AppLibrary; +using Ryujinx.Ava.UI.Helpers; using System.Collections.Generic; using System.Collections.ObjectModel; using System.IO; @@ -103,7 +103,7 @@ namespace Ryujinx.Ava.UI.ViewModels // NOTE(jpr): this works around a bug where calling _views.Clear also clears SelectedDownloadableContents for // some reason. so we save the items here and add them back after DownloadableContentModel[] items = SelectedDownloadableContents.ToArray(); - + Views.Clear(); Views.AddRange(view); @@ -119,7 +119,7 @@ namespace Ryujinx.Ava.UI.ViewModels { if (arg is DownloadableContentModel content) { - return string.IsNullOrWhiteSpace(_search) || content.FileName.ToLower().Contains(_search.ToLower()) || content.TitleIdStr.ToLower().Contains(_search.ToLower()); + return string.IsNullOrWhiteSpace(_search) || content.FileName.Contains(_search, System.StringComparison.OrdinalIgnoreCase) || content.TitleIdStr.Contains(_search, System.StringComparison.OrdinalIgnoreCase); } return false; @@ -253,12 +253,12 @@ namespace Ryujinx.Ava.UI.ViewModels return Dispatcher.UIThread.InvokeAsync(async () => { await ContentDialogHelper.ShowTextDialog( - LocaleManager.Instance[LocaleKeys.DialogConfirmationTitle], - msg, - string.Empty, - string.Empty, - string.Empty, - LocaleManager.Instance[LocaleKeys.InputDialogOk], + LocaleManager.Instance[LocaleKeys.DialogConfirmationTitle], + msg, + string.Empty, + string.Empty, + string.Empty, + LocaleManager.Instance[LocaleKeys.InputDialogOk], (int)Symbol.Checkmark); }); } diff --git a/src/Ryujinx/UI/ViewModels/Input/ControllerInputViewModel.cs b/src/Ryujinx/UI/ViewModels/Input/ControllerInputViewModel.cs index 84e4ba5d7..61d3ffd59 100644 --- a/src/Ryujinx/UI/ViewModels/Input/ControllerInputViewModel.cs +++ b/src/Ryujinx/UI/ViewModels/Input/ControllerInputViewModel.cs @@ -33,7 +33,7 @@ namespace Ryujinx.Ava.UI.ViewModels.Input OnPropertyChanged(); } } - + private bool _isLeft; public bool IsLeft { @@ -59,11 +59,11 @@ namespace Ryujinx.Ava.UI.ViewModels.Input } public bool HasSides => IsLeft ^ IsRight; - + [ObservableProperty] private SvgImage _image; - + public InputViewModel ParentModel { get; } - + public ControllerInputViewModel(InputViewModel model, GamepadInputConfig config, StickVisualizer visualizer) { ParentModel = model; @@ -79,7 +79,7 @@ namespace Ryujinx.Ava.UI.ViewModels.Input else { Rainbow.Reset(); - + if (Config.TurnOffLed) ParentModel.SelectedGamepad.ClearLed(); else @@ -91,17 +91,17 @@ namespace Ryujinx.Ava.UI.ViewModels.Input } public async void ShowMotionConfig() - { + { await MotionInputView.Show(this); ParentModel.IsModified = true; } public async void ShowRumbleConfig() - { + { await RumbleInputView.Show(this); ParentModel.IsModified = true; } - + public async void ShowLedConfig() { await LedInputView.Show(this); diff --git a/src/Ryujinx/UI/ViewModels/Input/InputViewModel.cs b/src/Ryujinx/UI/ViewModels/Input/InputViewModel.cs index 5b353a2c8..830fe689a 100644 --- a/src/Ryujinx/UI/ViewModels/Input/InputViewModel.cs +++ b/src/Ryujinx/UI/ViewModels/Input/InputViewModel.cs @@ -6,11 +6,11 @@ using CommunityToolkit.Mvvm.ComponentModel; using Gommon; using Ryujinx.Ava.Common.Locale; using Ryujinx.Ava.Input; +using Ryujinx.Ava.Systems.Configuration; using Ryujinx.Ava.UI.Helpers; using Ryujinx.Ava.UI.Models; using Ryujinx.Ava.UI.Models.Input; using Ryujinx.Ava.UI.Windows; -using Ryujinx.Ava.Systems.Configuration; using Ryujinx.Common; using Ryujinx.Common.Configuration; using Ryujinx.Common.Configuration.Hid; @@ -67,12 +67,12 @@ namespace Ryujinx.Ava.UI.ViewModels.Input private set { Rainbow.Reset(); - + _selectedGamepad = value; if (ConfigViewModel is ControllerInputViewModel { Config.UseRainbowLed: true }) Rainbow.Updated += (ref Color color) => _selectedGamepad.SetLed((uint)color.ToArgb()); - + OnPropertiesChanged(nameof(HasLed), nameof(CanClearLed)); } } @@ -101,7 +101,7 @@ namespace Ryujinx.Ava.UI.ViewModels.Input public bool IsModified { get => _isModified; - set + set { _isModified = value; OnPropertyChanged(); @@ -149,11 +149,11 @@ namespace Ryujinx.Ava.UI.ViewModels.Input set { if (IsModified) - { + { _playerIdChoose = value; return; } - + IsModified = false; _playerId = value; _isChangeTrackingActive = false; @@ -163,6 +163,7 @@ namespace Ryujinx.Ava.UI.ViewModels.Input _playerId = PlayerIndex.Player1; } + _isLoaded = false; LoadConfiguration(); LoadDevice(); @@ -216,11 +217,11 @@ namespace Ryujinx.Ava.UI.ViewModels.Input IsLeft = false; break; } - + LoadInputDriver(); LoadProfiles(); } - + OnPropertyChanged(); NotifyChanges(); } @@ -287,7 +288,6 @@ namespace Ryujinx.Ava.UI.ViewModels.Input } } - public InputConfig Config { get; set; } public InputViewModel(UserControl owner) : this() @@ -348,7 +348,6 @@ namespace Ryujinx.Ava.UI.ViewModels.Input { ConfigViewModel = new ControllerInputViewModel(this, new GamepadInputConfig(controllerInputConfig), VisualStick); } - } private void FindPairedDeviceInConfigFile() @@ -356,7 +355,7 @@ namespace Ryujinx.Ava.UI.ViewModels.Input // This function allows you to output a message about the device configuration found in the file // NOTE: if the configuration is found, we display the message "Waiting for controller connection", // but only if the id gamepad belongs to the selected player - + NotificationIsVisible = Config != null && Devices.FirstOrDefault(d => d.Id == Config.Id).Id != Config.Id && Config.PlayerIndex == PlayerId; if (NotificationIsVisible) { @@ -369,10 +368,8 @@ namespace Ryujinx.Ava.UI.ViewModels.Input NotificationText = $"{LocaleManager.Instance[LocaleKeys.ControllerSettingsWaitingConnectDevice].Format(Config.Name, Config.Id)}"; } } - } - private void MarkAsChanged() { //If tracking is active, then allow changing the modifier @@ -383,7 +380,6 @@ namespace Ryujinx.Ava.UI.ViewModels.Input } } - public void UnlinkDevice() { // "Disabled" mode is available after unbinding the device @@ -392,7 +388,6 @@ namespace Ryujinx.Ava.UI.ViewModels.Input IsModified = true; } - public void LoadDevice() { if (Config == null || Config.Backend == InputBackendType.Invalid) @@ -479,10 +474,10 @@ namespace Ryujinx.Ava.UI.ViewModels.Input LoadDevices(); IsModified = true; - RevertChanges(); + RevertChanges(); _isChangeTrackingActive = true;// Enable configuration change tracking - + } private string GetCurrentGamepadId() @@ -557,6 +552,7 @@ namespace Ryujinx.Ava.UI.ViewModels.Input { return $"{GetShortGamepadName(gamepad.Name)} ({controllerNumber})"; } + string GetUniqueGamepadName(IGamepad gamepad, ref int controllerNumber) { string name = GetGamepadName(gamepad, controllerNumber); @@ -565,6 +561,7 @@ namespace Ryujinx.Ava.UI.ViewModels.Input controllerNumber++; name = GetGamepadName(gamepad, controllerNumber); } + return name; } @@ -790,7 +787,7 @@ namespace Ryujinx.Ava.UI.ViewModels.Input } public void LoadProfileButton() - { + { LoadProfile(); IsModified = true; } @@ -824,6 +821,7 @@ namespace Ryujinx.Ava.UI.ViewModels.Input { ProfilesList.RemoveAt(index); } + return; } @@ -860,58 +858,57 @@ namespace Ryujinx.Ava.UI.ViewModels.Input public async void SaveProfile() { - - if (Device == 0) - { - return; - } - - if (ConfigViewModel == null) - { - return; - } - - if (ProfileName == LocaleManager.Instance[LocaleKeys.ControllerSettingsProfileDefault]) - { - await ContentDialogHelper.CreateErrorDialog(LocaleManager.Instance[LocaleKeys.DialogProfileDefaultProfileOverwriteErrorMessage]); - return; - } - else - { - bool validFileName = ProfileName.IndexOfAny(Path.GetInvalidFileNameChars()) == -1; + if (Device == 0) + { + return; + } - if (validFileName) - { - string path = Path.Combine(GetProfileBasePath(), ProfileName + ".json"); + if (ConfigViewModel == null) + { + return; + } - InputConfig config = null; + if (ProfileName == LocaleManager.Instance[LocaleKeys.ControllerSettingsProfileDefault]) + { + await ContentDialogHelper.CreateErrorDialog(LocaleManager.Instance[LocaleKeys.DialogProfileDefaultProfileOverwriteErrorMessage]); - if (IsKeyboard) - { - config = (ConfigViewModel as KeyboardInputViewModel).Config.GetConfig(); - } - else if (IsController) - { - config = (ConfigViewModel as ControllerInputViewModel).Config.GetConfig(); - } + return; + } + else + { + bool validFileName = ProfileName.IndexOfAny(Path.GetInvalidFileNameChars()) == -1; - config.ControllerType = Controllers[_controller].Type; + if (validFileName) + { + string path = Path.Combine(GetProfileBasePath(), ProfileName + ".json"); - string jsonString = JsonHelper.Serialize(config, _serializerContext.InputConfig); + InputConfig config = null; - await File.WriteAllTextAsync(path, jsonString); + if (IsKeyboard) + { + config = (ConfigViewModel as KeyboardInputViewModel).Config.GetConfig(); + } + else if (IsController) + { + config = (ConfigViewModel as ControllerInputViewModel).Config.GetConfig(); + } - LoadProfiles(); + config.ControllerType = Controllers[_controller].Type; - ProfileChoose = ProfileName; // Show new profile - } - else - { - await ContentDialogHelper.CreateErrorDialog(LocaleManager.Instance[LocaleKeys.DialogProfileInvalidProfileNameErrorMessage]); - } - } - + string jsonString = JsonHelper.Serialize(config, _serializerContext.InputConfig); + + await File.WriteAllTextAsync(path, jsonString); + + LoadProfiles(); + + ProfileChoose = ProfileName; // Show new profile + } + else + { + await ContentDialogHelper.CreateErrorDialog(LocaleManager.Instance[LocaleKeys.DialogProfileInvalidProfileNameErrorMessage]); + } + } } public async void RemoveProfile() @@ -947,7 +944,7 @@ namespace Ryujinx.Ava.UI.ViewModels.Input { LoadConfiguration(); // configuration preload is required if the paired gamepad was disconnected but was changed to another gamepad Device = Devices.ToList().FindIndex(d => d.Id == RevertDeviceId); - + LoadDevice(); LoadConfiguration(); @@ -957,7 +954,7 @@ namespace Ryujinx.Ava.UI.ViewModels.Input public void Save() { - + if (!IsModified) { return; //If the input settings were not touched, then do nothing @@ -967,7 +964,7 @@ namespace Ryujinx.Ava.UI.ViewModels.Input RevertDeviceId = Devices[Device].Id; // Remember selected device after saving - List newConfig = []; + List newConfig = []; newConfig.AddRange(ConfigurationState.Instance.Hid.InputConfig.Value); diff --git a/src/Ryujinx/UI/ViewModels/Input/LedInputViewModel.cs b/src/Ryujinx/UI/ViewModels/Input/LedInputViewModel.cs index effd07904..71c404c21 100644 --- a/src/Ryujinx/UI/ViewModels/Input/LedInputViewModel.cs +++ b/src/Ryujinx/UI/ViewModels/Input/LedInputViewModel.cs @@ -1,9 +1,9 @@ -using Avalonia.Media; +using Avalonia.Media; using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.Input; using Humanizer; -using Ryujinx.Ava.UI.Helpers; using Ryujinx.Ava.Systems.Configuration; +using Ryujinx.Ava.UI.Helpers; using System.Globalization; namespace Ryujinx.Ava.UI.ViewModels.Input @@ -11,22 +11,23 @@ namespace Ryujinx.Ava.UI.ViewModels.Input public partial class LedInputViewModel : BaseModel { public required InputViewModel ParentModel { get; init; } - + public RelayCommand LedDisabledChanged => Commands.Create(() => { - if (!EnableLedChanging) return; + if (!EnableLedChanging) + return; if (TurnOffLed) ParentModel.SelectedGamepad.ClearLed(); else ParentModel.SelectedGamepad.SetLed(LedColor.ToUInt32()); }); - + [ObservableProperty] private bool _enableLedChanging; [ObservableProperty] private Color _ledColor; public string RainbowSpeedText => RainbowSpeed.ToString(CultureInfo.CurrentCulture).Truncate(4, string.Empty); - + public float RainbowSpeed { get => ConfigurationState.Instance.Hid.RainbowSpeed; @@ -37,11 +38,11 @@ namespace Ryujinx.Ava.UI.ViewModels.Input OnPropertyChanged(nameof(RainbowSpeedText)); } } - + public bool ShowLedColorPicker => !TurnOffLed && !UseRainbowLed; - + private bool _turnOffLed; - + public bool TurnOffLed { get => _turnOffLed; @@ -52,9 +53,9 @@ namespace Ryujinx.Ava.UI.ViewModels.Input OnPropertyChanged(nameof(ShowLedColorPicker)); } } - + private bool _useRainbowLed; - + public bool UseRainbowLed { get => _useRainbowLed; diff --git a/src/Ryujinx/UI/ViewModels/MainWindowViewModel.cs b/src/Ryujinx/UI/ViewModels/MainWindowViewModel.cs index 020d96794..845ab2894 100644 --- a/src/Ryujinx/UI/ViewModels/MainWindowViewModel.cs +++ b/src/Ryujinx/UI/ViewModels/MainWindowViewModel.cs @@ -20,15 +20,15 @@ using Ryujinx.Ava.Common.Locale; using Ryujinx.Ava.Common.Models; using Ryujinx.Ava.Input; using Ryujinx.Ava.Systems; +using Ryujinx.Ava.Systems.AppLibrary; +using Ryujinx.Ava.Systems.Configuration; using Ryujinx.Ava.UI.Controls; using Ryujinx.Ava.UI.Helpers; using Ryujinx.Ava.UI.Models; using Ryujinx.Ava.UI.Models.Generic; using Ryujinx.Ava.UI.Renderer; -using Ryujinx.Ava.UI.Windows; -using Ryujinx.Ava.Systems.AppLibrary; -using Ryujinx.Ava.Systems.Configuration; using Ryujinx.Ava.UI.Views.Dialog; +using Ryujinx.Ava.UI.Windows; using Ryujinx.Ava.Utilities; using Ryujinx.Common; using Ryujinx.Common.Configuration; @@ -86,9 +86,9 @@ namespace Ryujinx.Ava.UI.ViewModels [ObservableProperty] private Brush _progressBarForegroundColor; [ObservableProperty] private Brush _progressBarBackgroundColor; [ObservableProperty] private Brush _vSyncModeColor; - #nullable enable +#nullable enable [ObservableProperty] private byte[]? _selectedIcon; - #nullable disable +#nullable disable [ObservableProperty] private int _statusBarProgressMaximum; [ObservableProperty] private int _statusBarProgressValue; [ObservableProperty] private string _statusBarProgressStatusText; @@ -118,7 +118,7 @@ namespace Ryujinx.Ava.UI.ViewModels if (Updater.CanUpdate(true)) await Updater.BeginUpdateAsync(true); }); - + private bool _showTotalTimePlayed; private bool _showLoadProgress; private bool _isGameRunning; @@ -140,7 +140,7 @@ namespace Ryujinx.Ava.UI.ViewModels private int _customVSyncIntervalPercentageProxy; private ApplicationData _listSelectedApplication; private ApplicationData _gridSelectedApplication; - + // Key is Title ID public SafeDictionary LdnData = []; @@ -157,9 +157,7 @@ namespace Ryujinx.Ava.UI.ViewModels .Sort(GetComparer()) .OnItemAdded(_ => OnPropertyChanged(nameof(AppsObservableList))) .OnItemRemoved(_ => OnPropertyChanged(nameof(AppsObservableList))) -#pragma warning disable MVVMTK0034 // Event to update is fired below .Bind(out _appsObservableList); -#pragma warning restore MVVMTK0034 _rendererWaitEvent = new AutoResetEvent(false); @@ -205,7 +203,7 @@ namespace Ryujinx.Ava.UI.ViewModels #if DEBUG topLevel.AttachDevTools(new KeyGesture(Avalonia.Input.Key.F12, KeyModifiers.Control)); #endif - + Window.ApplicationLibrary.TotalTimePlayedRecalculated += TotalTimePlayed_Recalculated; } @@ -327,7 +325,7 @@ namespace Ryujinx.Ava.UI.ViewModels OnPropertyChanged(); } } - + public ApplicationData ListSelectedApplication { get => _listSelectedApplication; @@ -335,13 +333,11 @@ namespace Ryujinx.Ava.UI.ViewModels { _listSelectedApplication = value; -#pragma warning disable MVVMTK0034 - if (_listSelectedApplication != null && _listAppContextMenu == null) + if (_listSelectedApplication != null && ListAppContextMenu == null) ListAppContextMenu = new ApplicationContextMenu(); - else if (_listSelectedApplication == null && _listAppContextMenu != null) + else if (_listSelectedApplication == null && ListAppContextMenu != null) ListAppContextMenu = null!; -#pragma warning restore MVVMTK0034 OnPropertyChanged(); } @@ -354,13 +350,11 @@ namespace Ryujinx.Ava.UI.ViewModels { _gridSelectedApplication = value; -#pragma warning disable MVVMTK0034 - if (_gridSelectedApplication != null && _gridAppContextMenu == null) + if (_gridSelectedApplication != null && GridAppContextMenu == null) GridAppContextMenu = new ApplicationContextMenu(); - else if (_gridSelectedApplication == null && _gridAppContextMenu != null) + else if (_gridSelectedApplication == null && GridAppContextMenu != null) GridAppContextMenu = null!; -#pragma warning restore MVVMTK0034 - + OnPropertyChanged(); } } @@ -380,7 +374,7 @@ namespace Ryujinx.Ava.UI.ViewModels { ListSelectedApplication = value; GridSelectedApplication = value; - } + } } public bool HasCompatibilityEntry => SelectedApplication.HasPlayabilityInfo; @@ -395,7 +389,7 @@ namespace Ryujinx.Ava.UI.ViewModels public bool OpenBcatSaveDirectoryEnabled => SelectedApplication.HasControlHolder && SelectedApplication.ControlHolder.Value.BcatDeliveryCacheStorageSize > 0; - public bool ShowCustomVSyncIntervalPicker + public bool ShowCustomVSyncIntervalPicker => _isGameRunning && AppHost.Device.VSyncMode == VSyncMode.Custom; public void UpdateVSyncIntervalPicker() @@ -416,6 +410,7 @@ namespace Ryujinx.Ava.UI.ViewModels AppHost.Device.CustomVSyncInterval = newInterval; AppHost.Device.UpdateVSyncInterval(); } + OnPropertyChanged((nameof(CustomVSyncInterval))); OnPropertyChanged((nameof(CustomVSyncIntervalPercentageText))); } @@ -447,6 +442,7 @@ namespace Ryujinx.Ava.UI.ViewModels AppHost.Device.CustomVSyncInterval = value; AppHost.Device.UpdateVSyncInterval(); } + OnPropertyChanged(nameof(CustomVSyncIntervalPercentageProxy)); OnPropertyChanged(nameof(CustomVSyncIntervalPercentageText)); OnPropertyChanged(); @@ -579,7 +575,7 @@ namespace Ryujinx.Ava.UI.ViewModels public bool ShowNames { - get => ConfigurationState.Instance.UI.ShowNames && ConfigurationState.Instance.UI.GridSize > 1; + get => ConfigurationState.Instance.UI.ShowNames && ConfigurationState.Instance.UI.GridSize > 1; set { ConfigurationState.Instance.UI.ShowNames.Value = value; @@ -762,7 +758,7 @@ namespace Ryujinx.Ava.UI.ViewModels #region PrivateMethods - private static IComparer CreateComparer(bool ascending, Func selector) => + private static SortExpressionComparer CreateComparer(bool ascending, Func selector) => ascending ? SortExpressionComparer.Ascending(selector) : SortExpressionComparer.Descending(selector); @@ -791,15 +787,13 @@ namespace Ryujinx.Ava.UI.ViewModels private void RefreshGrid() { - Applications.ToObservableChangeSet() + var appsList = Applications.ToObservableChangeSet() .Filter(Filter) .Sort(GetComparer()) -#pragma warning disable MVVMTK0034 - .Bind(out _appsObservableList) -#pragma warning restore MVVMTK0034 + .Bind(out var apps) .AsObservableList(); - OnPropertyChanged(nameof(AppsObservableList)); + AppsObservableList = apps; } private bool Filter(object arg) @@ -874,10 +868,10 @@ namespace Ryujinx.Ava.UI.ViewModels string message = LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.DialogFirmwareInstallerFirmwareInstallSuccessMessage, firmwareVersion.VersionString); await ContentDialogHelper.CreateInfoDialog( - dialogTitle, - message, - LocaleManager.Instance[LocaleKeys.InputDialogOk], - string.Empty, + dialogTitle, + message, + LocaleManager.Instance[LocaleKeys.InputDialogOk], + string.Empty, LocaleManager.Instance[LocaleKeys.RyujinxInfo]); Logger.Info?.Print(LogClass.Application, message); @@ -996,7 +990,7 @@ namespace Ryujinx.Ava.UI.ViewModels waitingDialog.Close(); string message = ex.Message; - if(ex is FormatException) + if (ex is FormatException) { message = LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.DialogKeysInstallerKeysNotFoundErrorMessage, filename); } @@ -1054,6 +1048,7 @@ namespace Ryujinx.Ava.UI.ViewModels CacheLoadStatus = string.Empty; break; } + break; case ShaderCacheLoadingState shaderCacheState: CacheLoadStatus = $"{current} / {total}"; @@ -1074,6 +1069,7 @@ namespace Ryujinx.Ava.UI.ViewModels CacheLoadStatus = string.Empty; break; } + break; default: throw new ArgumentException($"Unknown Progress Handler type {typeof(T)}"); @@ -1110,7 +1106,7 @@ namespace Ryujinx.Ava.UI.ViewModels _rendererWaitEvent.WaitOne(); AppHost?.Start(); - + AppHost?.DisposeContext(); } @@ -1190,11 +1186,11 @@ namespace Ryujinx.Ava.UI.ViewModels { await ContentDialogHelper.ShowTextDialog( LocaleManager.Instance[numAdded > 0 || numRemoved > 0 ? LocaleKeys.RyujinxConfirm : LocaleKeys.RyujinxInfo], - msg, - string.Empty, - string.Empty, - string.Empty, - LocaleManager.Instance[LocaleKeys.InputDialogOk], + msg, + string.Empty, + string.Empty, + string.Empty, + LocaleManager.Instance[LocaleKeys.InputDialogOk], (int)Symbol.Checkmark); }); } @@ -1388,7 +1384,7 @@ namespace Ryujinx.Ava.UI.ViewModels return; } - + OpenHelper.OpenFolder(screenshotsDir); } @@ -1578,15 +1574,11 @@ namespace Ryujinx.Ava.UI.ViewModels public bool InitializeUserConfig(ApplicationData application) { - // Code where conditions will be met before loading the user configuration (Global Config) - BackendThreading backendThreadingValue = ConfigurationState.Instance.Graphics.BackendThreading.Value; + // Code where conditions will be met before loading the user configuration (Global Config) string BackendThreadingInit = Program.BackendThreadingArg; - if (BackendThreadingInit is null) - { - BackendThreadingInit = ConfigurationState.Instance.Graphics.BackendThreading.Value.ToString(); - } - + BackendThreadingInit ??= ConfigurationState.Instance.Graphics.BackendThreading.Value.ToString(); + // If a configuration is found in the "/games/xxxxxxxxxxxxxx" folder, the program will load the user setting. string idGame = application.IdBaseString; if (ConfigurationFileFormat.TryLoad(Program.GetDirGameUserConfig(idGame), out ConfigurationFileFormat configurationFileFormat)) @@ -1599,13 +1591,13 @@ namespace Ryujinx.Ava.UI.ViewModels if (ConfigurationState.Instance.Graphics.BackendThreading.Value.ToString() != BackendThreadingInit) { - List Arguments = new List + List Arguments = new() { "--bt", ConfigurationState.Instance.Graphics.BackendThreading.Value.ToString() // BackendThreading }; Rebooter.RebootAppWithGame(application.Path, Arguments); - + return true; } @@ -1635,7 +1627,7 @@ namespace Ryujinx.Ava.UI.ViewModels #if RELEASE await PerformanceCheck(); #endif - + Logger.RestartTime(); SelectedIcon ??= ApplicationLibrary.GetApplicationIcon(application.Path, ConfigurationState.Instance.System.Language, application.Id); @@ -1680,7 +1672,7 @@ namespace Ryujinx.Ava.UI.ViewModels Thread gameThread = new(InitializeGame) { Name = "GUI.WindowThread" }; gameThread.Start(); - + } public void SwitchToRenderer(bool startFullscreen) => @@ -1801,7 +1793,6 @@ namespace Ryujinx.Ava.UI.ViewModels } } - public void ToggleFullscreen() { if (Environment.TickCount64 - LastFullscreenToggle < HotKeyPressDelayMs) @@ -1963,7 +1954,7 @@ namespace Ryujinx.Ava.UI.ViewModels #endregion #region Context Menu commands - + public static AsyncRelayCommand RunApplication { get; } = Commands.CreateConditional(vm => vm?.SelectedApplication != null, viewModel => viewModel.LoadApplication(viewModel.SelectedApplication)); @@ -1982,7 +1973,7 @@ namespace Ryujinx.Ava.UI.ViewModels viewModel.RefreshView(); } ); - + public static RelayCommand CreateApplicationShortcut { get; } = Commands.CreateConditional(vm => vm?.SelectedApplication != null, viewModel => ShortcutHelper.CreateAppShortcut( @@ -1991,7 +1982,7 @@ namespace Ryujinx.Ava.UI.ViewModels viewModel.SelectedApplication.IdString, viewModel.SelectedApplication.Icon )); - + public static AsyncRelayCommand EditGameConfiguration { get; } = Commands.CreateConditional(vm => vm?.SelectedApplication != null, async viewModel => @@ -2058,7 +2049,7 @@ namespace Ryujinx.Ava.UI.ViewModels viewModel.SelectedApplication.Path ) )); - + public static AsyncRelayCommand OpenModManager { get; } = Commands.CreateConditional(vm => vm?.SelectedApplication != null, viewModel => ModManagerView.Show( @@ -2086,11 +2077,11 @@ namespace Ryujinx.Ava.UI.ViewModels OpenHelper.OpenFolder(titleModsPath); }); - + public static AsyncRelayCommand TrimXci { get; } = Commands.CreateConditional(vm => vm?.SelectedApplication != null, viewModel => viewModel.TrimXCIFile(viewModel.SelectedApplication.Path)); - + public static AsyncRelayCommand PurgePtcCache { get; } = Commands.CreateConditional(vm => vm?.SelectedApplication != null, async viewModel => @@ -2280,7 +2271,7 @@ namespace Ryujinx.Ava.UI.ViewModels OpenHelper.OpenFolder(shaderCacheDir); }); - + public static AsyncRelayCommand ExtractApplicationExeFs { get; } = Commands.CreateConditional(vm => vm?.SelectedApplication != null, async viewModel => @@ -2350,7 +2341,7 @@ namespace Ryujinx.Ava.UI.ViewModels png.SaveTo(fileStream); }); - + #endregion } } diff --git a/src/Ryujinx/UI/ViewModels/ModManagerViewModel.cs b/src/Ryujinx/UI/ViewModels/ModManagerViewModel.cs index 081ca0912..1d65ba336 100644 --- a/src/Ryujinx/UI/ViewModels/ModManagerViewModel.cs +++ b/src/Ryujinx/UI/ViewModels/ModManagerViewModel.cs @@ -5,9 +5,9 @@ using CommunityToolkit.Mvvm.ComponentModel; using DynamicData; using Gommon; using Ryujinx.Ava.Common.Locale; +using Ryujinx.Ava.Systems.AppLibrary; using Ryujinx.Ava.UI.Helpers; using Ryujinx.Ava.UI.Models; -using Ryujinx.Ava.Systems.AppLibrary; using Ryujinx.Common.Configuration; using Ryujinx.Common.Logging; using Ryujinx.Common.Utilities; @@ -131,12 +131,10 @@ namespace Ryujinx.Ava.UI.ViewModels .Filter(Filter) .Bind(out ReadOnlyObservableCollection view).AsObservableList(); -#pragma warning disable MVVMTK0034 // Event to update is fired below - _views.Clear(); - _views.AddRange(view); -#pragma warning restore MVVMTK0034 + Views.Clear(); + Views.AddRange(view); - SelectedMods = new(Views.Where(x => x.Enabled)); + SelectedMods = [.. Views.Where(x => x.Enabled)]; OnPropertyChanged(nameof(ModCount)); OnPropertyChanged(nameof(Views)); @@ -147,7 +145,7 @@ namespace Ryujinx.Ava.UI.ViewModels { if (arg is ModModel content) { - return string.IsNullOrWhiteSpace(_search) || content.Name.ToLower().Contains(_search.ToLower()); + return string.IsNullOrWhiteSpace(_search) || content.Name.Contains(_search, StringComparison.OrdinalIgnoreCase); } return false; @@ -215,6 +213,7 @@ namespace Ryujinx.Ava.UI.ViewModels Mods.Remove(model); OnPropertyChanged(nameof(ModCount)); } + Sort(); } @@ -312,7 +311,7 @@ namespace Ryujinx.Ava.UI.ViewModels public void EnableAll() { - SelectedMods = new(Mods); + SelectedMods = [.. Mods]; } public void DisableAll() diff --git a/src/Ryujinx/UI/ViewModels/SettingsHacksViewModel.cs b/src/Ryujinx/UI/ViewModels/SettingsHacksViewModel.cs index 022b7481e..230887e34 100644 --- a/src/Ryujinx/UI/ViewModels/SettingsHacksViewModel.cs +++ b/src/Ryujinx/UI/ViewModels/SettingsHacksViewModel.cs @@ -1,4 +1,4 @@ -using CommunityToolkit.Mvvm.ComponentModel; +using CommunityToolkit.Mvvm.ComponentModel; using Gommon; using Ryujinx.Ava.Systems.Configuration; @@ -8,8 +8,8 @@ namespace Ryujinx.Ava.UI.ViewModels { private readonly SettingsViewModel _baseViewModel; - public SettingsHacksViewModel() {} - + public SettingsHacksViewModel() { } + public SettingsHacksViewModel(SettingsViewModel settingsVm) { _baseViewModel = settingsVm; @@ -17,20 +17,20 @@ namespace Ryujinx.Ava.UI.ViewModels [ObservableProperty] private bool _xc2MenuSoftlockFix = ConfigurationState.Instance.Hacks.Xc2MenuSoftlockFix; [ObservableProperty] private bool _nifmDisableIsAnyInternetRequestAccepted = ConfigurationState.Instance.Hacks.DisableNifmIsAnyInternetRequestAccepted; - + public static string Xc2MenuFixTooltip { get; } = Lambda.String(sb => { sb.AppendLine( "This hack applies a 2ms delay (via 'Thread.Sleep(2)') every time the game tries to read data from the emulated Switch filesystem.") .AppendLine(); - + sb.AppendLine("From the issue on GitHub:").AppendLine(); sb.Append( "When clicking very fast from game main menu to 2nd submenu, " + "there is a low chance that the game will softlock, " + "the submenu won't show up, while background music is still there."); }); - + public static string NifmDisableIsAnyInternetRequestAcceptedTooltip { get; } = Lambda.String(sb => { sb.AppendLine( diff --git a/src/Ryujinx/UI/ViewModels/SettingsViewModel.cs b/src/Ryujinx/UI/ViewModels/SettingsViewModel.cs index 9b540088b..6b6f07a7b 100644 --- a/src/Ryujinx/UI/ViewModels/SettingsViewModel.cs +++ b/src/Ryujinx/UI/ViewModels/SettingsViewModel.cs @@ -9,12 +9,12 @@ using Ryujinx.Audio.Backends.OpenAL; using Ryujinx.Audio.Backends.SDL2; using Ryujinx.Audio.Backends.SoundIo; using Ryujinx.Ava.Common.Locale; -using Ryujinx.Ava.UI.Helpers; -using Ryujinx.Ava.UI.Models.Input; -using Ryujinx.Ava.UI.Windows; using Ryujinx.Ava.Systems.Configuration; using Ryujinx.Ava.Systems.Configuration.System; using Ryujinx.Ava.Systems.Configuration.UI; +using Ryujinx.Ava.UI.Helpers; +using Ryujinx.Ava.UI.Models.Input; +using Ryujinx.Ava.UI.Windows; using Ryujinx.Common.Configuration; using Ryujinx.Common.Configuration.Multiplayer; using Ryujinx.Common.GraphicsDriver; @@ -72,10 +72,10 @@ namespace Ryujinx.Ava.UI.ViewModels public SettingsHacksViewModel DirtyHacks { get; } private readonly bool _isGameRunning; - private Bitmap _gameIcon; - private string _gameTitle; - private string _gamePath; - private string _gameId; + private readonly Bitmap _gameIcon; + private readonly string _gameTitle; + private readonly string _gamePath; + private readonly string _gameId; public bool IsGameRunning => _isGameRunning; public Bitmap GameIcon => _gameIcon; public string GamePath => _gamePath; @@ -142,9 +142,9 @@ namespace Ryujinx.Ava.UI.ViewModels public bool EnableKeyboard { get; set; } public bool EnableMouse { get; set; } public bool DisableInputWhenOutOfFocus { get; set; } - + public int FocusLostActionType { get; set; } - + public VSyncMode VSyncMode { get => _vSyncMode; @@ -188,6 +188,7 @@ namespace Ryujinx.Ava.UI.ViewModels { VSyncMode = VSyncMode.Custom; } + OnPropertyChanged(); } } @@ -201,15 +202,15 @@ namespace Ryujinx.Ava.UI.ViewModels int newPercent = (int)((value / 60f) * 100); _customVSyncIntervalPercentageProxy = newPercent; OnPropertiesChanged( - nameof(CustomVSyncIntervalPercentageProxy), + nameof(CustomVSyncIntervalPercentageProxy), nameof(CustomVSyncIntervalPercentageText)); OnPropertyChanged(); } } public bool EnablePptc { get; set; } public bool EnableLowPowerPptc { get; set; } - - + + public long TurboMultiplier { get => _turboModeMultiplier; @@ -218,13 +219,13 @@ namespace Ryujinx.Ava.UI.ViewModels if (_turboModeMultiplier != value) { _turboModeMultiplier = value; - + OnPropertyChanged(); OnPropertyChanged((nameof(TurboMultiplierPercentageText))); } } } - + public string TurboMultiplierPercentageText => $"{TurboMultiplier}%"; public bool EnableInternetAccess { get; set; } @@ -345,7 +346,7 @@ namespace Ryujinx.Ava.UI.ViewModels public AvaloniaList NetworkInterfaceList { - get => new(_networkInterfaces.Keys); + get => [.. _networkInterfaces.Keys]; } public HotkeyConfig KeyboardHotkey { get; set; } @@ -374,39 +375,37 @@ namespace Ryujinx.Ava.UI.ViewModels { _virtualFileSystem = virtualFileSystem; _contentManager = contentManager; - + if (Program.PreviewerDetached) { Task.Run(LoadTimeZones); - + DirtyHacks = new SettingsHacksViewModel(this); } } public SettingsViewModel( - VirtualFileSystem virtualFileSystem, + VirtualFileSystem virtualFileSystem, ContentManager contentManager, bool gameRunning, string gamePath, - string gameName, - string gameId, - byte[] gameIconData, + string gameName, + string gameId, + byte[] gameIconData, bool enableToLoadCustomConfig) : this(enableToLoadCustomConfig) { _virtualFileSystem = virtualFileSystem; _contentManager = contentManager; - + if (gameIconData != null && gameIconData.Length > 0) { - using (var ms = new MemoryStream(gameIconData)) - { - _gameIcon = new Bitmap(ms); - } + using var ms = new MemoryStream(gameIconData); + _gameIcon = new Bitmap(ms); } _isGameRunning = gameRunning; _gamePath = gamePath; - _gameTitle = gameName; + _gameTitle = gameName; _gameId = gameId; if (enableToLoadCustomConfig) // During the game. If there is no user config, then load the global config window @@ -414,7 +413,7 @@ namespace Ryujinx.Ava.UI.ViewModels string gameDir = Program.GetDirGameUserConfig(gameId, false, true); if (ConfigurationFileFormat.TryLoad(gameDir, out ConfigurationFileFormat configurationFileFormat)) { - ConfigurationState.Instance.Load(configurationFileFormat, gameDir, gameId); + ConfigurationState.Instance.Load(configurationFileFormat, gameDir, gameId); } LoadCurrentConfiguration(); // Needed to load custom configuration @@ -443,8 +442,8 @@ namespace Ryujinx.Ava.UI.ViewModels { Task.Run(LoadAvailableGpus); - // if (!noLoadGlobalConfig)// Default is false, but loading custom config avoids double call - LoadCurrentConfiguration(); + // if (!noLoadGlobalConfig)// Default is false, but loading custom config avoids double call + LoadCurrentConfiguration(); DirtyHacks = new SettingsHacksViewModel(this); } @@ -811,7 +810,7 @@ namespace Ryujinx.Ava.UI.ViewModels public void DeleteConfigGame() { - string gameDir = Program.GetDirGameUserConfig(GameId,false,false); + string gameDir = Program.GetDirGameUserConfig(GameId, false, false); if (File.Exists(gameDir)) { @@ -839,8 +838,9 @@ namespace Ryujinx.Ava.UI.ViewModels public AsyncRelayCommand ResetButton => Commands.Create(async () => { - if (!WantsToReset) return; - + if (!WantsToReset) + return; + CloseWindow?.Invoke(); ConfigurationState.Instance.LoadDefault(); ConfigurationState.Instance.ToFileFormat().SaveConfig(Program.ConfigurationPath); diff --git a/src/Ryujinx/UI/ViewModels/TitleUpdateViewModel.cs b/src/Ryujinx/UI/ViewModels/TitleUpdateViewModel.cs index 7ecfc1c87..74876774e 100644 --- a/src/Ryujinx/UI/ViewModels/TitleUpdateViewModel.cs +++ b/src/Ryujinx/UI/ViewModels/TitleUpdateViewModel.cs @@ -5,8 +5,8 @@ using CommunityToolkit.Mvvm.ComponentModel; using FluentAvalonia.UI.Controls; using Ryujinx.Ava.Common.Locale; using Ryujinx.Ava.Common.Models; -using Ryujinx.Ava.UI.Helpers; using Ryujinx.Ava.Systems.AppLibrary; +using Ryujinx.Ava.UI.Helpers; using System.Collections.Generic; using System.IO; using System.Linq; @@ -178,17 +178,17 @@ namespace Ryujinx.Ava.UI.ViewModels ApplicationLibrary.SaveTitleUpdatesForGame(ApplicationData, updates); } - private Task ShowNewUpdatesAddedDialog(int numAdded) + private Task ShowNewUpdatesAddedDialog(int numAdded) { string msg = string.Format(LocaleManager.Instance[LocaleKeys.UpdateWindowUpdateAddedMessage], numAdded); - return Dispatcher.UIThread.InvokeAsync(async () => + return Dispatcher.UIThread.InvokeAsync(async () => await ContentDialogHelper.ShowTextDialog( - LocaleManager.Instance[LocaleKeys.DialogConfirmationTitle], - msg, - string.Empty, - string.Empty, - string.Empty, - LocaleManager.Instance[LocaleKeys.InputDialogOk], + LocaleManager.Instance[LocaleKeys.DialogConfirmationTitle], + msg, + string.Empty, + string.Empty, + string.Empty, + LocaleManager.Instance[LocaleKeys.InputDialogOk], (int)Symbol.Checkmark )); } diff --git a/src/Ryujinx/UI/ViewModels/UserFirmwareAvatarSelectorViewModel.cs b/src/Ryujinx/UI/ViewModels/UserFirmwareAvatarSelectorViewModel.cs index 6b4d7795d..8c6a71038 100644 --- a/src/Ryujinx/UI/ViewModels/UserFirmwareAvatarSelectorViewModel.cs +++ b/src/Ryujinx/UI/ViewModels/UserFirmwareAvatarSelectorViewModel.cs @@ -128,7 +128,7 @@ namespace Ryujinx.Ava.UI.ViewModels } } - private static byte[] DecompressYaz0(Stream stream) + private static byte[] DecompressYaz0(MemoryStream stream) { using BinaryReader reader = new(stream); diff --git a/src/Ryujinx/UI/ViewModels/UserSaveManagerViewModel.cs b/src/Ryujinx/UI/ViewModels/UserSaveManagerViewModel.cs index 0b3f89556..894af8c6c 100644 --- a/src/Ryujinx/UI/ViewModels/UserSaveManagerViewModel.cs +++ b/src/Ryujinx/UI/ViewModels/UserSaveManagerViewModel.cs @@ -43,10 +43,8 @@ namespace Ryujinx.Ava.UI.ViewModels .Sort(GetComparer()) .Bind(out ReadOnlyObservableCollection view).AsObservableList(); -#pragma warning disable MVVMTK0034 - _views.Clear(); - _views.AddRange(view); -#pragma warning restore MVVMTK0034 + Views.Clear(); + Views.AddRange(view); OnPropertyChanged(nameof(Views)); } @@ -54,13 +52,13 @@ namespace Ryujinx.Ava.UI.ViewModels { if (arg is SaveModel save) { - return string.IsNullOrWhiteSpace(Search) || save.Title.ToLower().Contains(Search.ToLower()); + return string.IsNullOrWhiteSpace(Search) || save.Title.Contains(Search, System.StringComparison.OrdinalIgnoreCase); } return false; } - private IComparer GetComparer() + private SortExpressionComparer GetComparer() { return SortIndex switch { diff --git a/src/Ryujinx/UI/ViewModels/XciTrimmerViewModel.cs b/src/Ryujinx/UI/ViewModels/XciTrimmerViewModel.cs index 2085ffe26..dab42fbf8 100644 --- a/src/Ryujinx/UI/ViewModels/XciTrimmerViewModel.cs +++ b/src/Ryujinx/UI/ViewModels/XciTrimmerViewModel.cs @@ -1,12 +1,12 @@ using Avalonia.Collections; +using Avalonia.Threading; using DynamicData; using Gommon; -using Avalonia.Threading; using Ryujinx.Ava.Common; using Ryujinx.Ava.Common.Locale; using Ryujinx.Ava.Common.Models; -using Ryujinx.Ava.UI.Helpers; using Ryujinx.Ava.Systems.AppLibrary; +using Ryujinx.Ava.UI.Helpers; using Ryujinx.Common.Utilities; using System.Collections.Generic; using System.Collections.ObjectModel; @@ -36,10 +36,10 @@ namespace Ryujinx.Ava.UI.ViewModels private readonly Ryujinx.Common.Logging.XCIFileTrimmerLog _logger; private ApplicationLibrary ApplicationLibrary => _mainWindowViewModel.ApplicationLibrary; private Optional _processingApplication = null; - private AvaloniaList _allXCIFiles = []; + private readonly AvaloniaList _allXCIFiles = []; private AvaloniaList _selectedXCIFiles = []; - private AvaloniaList _displayedXCIFiles = []; - private MainWindowViewModel _mainWindowViewModel; + private readonly AvaloniaList _displayedXCIFiles = []; + private readonly MainWindowViewModel _mainWindowViewModel; private CancellationTokenSource _cancellationTokenSource; private string _search; private ProcessingMode _processingMode; @@ -93,12 +93,12 @@ namespace Ryujinx.Ava.UI.ViewModels private void SortingChanged() { OnPropertiesChanged( - nameof(IsSortedByName), - nameof(IsSortedBySaved), - nameof(SortingAscending), - nameof(SortingField), + nameof(IsSortedByName), + nameof(IsSortedBySaved), + nameof(SortingAscending), + nameof(SortingField), nameof(SortingFieldName)); - + SortAndFilter(); } @@ -110,13 +110,13 @@ namespace Ryujinx.Ava.UI.ViewModels private void ApplicationsChanged() { OnPropertiesChanged( - nameof(AllXCIFiles), - nameof(Status), - nameof(PotentialSavings), - nameof(ActualSavings), - nameof(CanTrim), + nameof(AllXCIFiles), + nameof(Status), + nameof(PotentialSavings), + nameof(ActualSavings), + nameof(CanTrim), nameof(CanUntrim)); - + DisplayedChanged(); SortAndFilter(); } @@ -124,9 +124,9 @@ namespace Ryujinx.Ava.UI.ViewModels private void SelectionChanged(bool displayedChanged = true) { OnPropertiesChanged( - nameof(Status), - nameof(CanTrim), - nameof(CanUntrim), + nameof(Status), + nameof(CanTrim), + nameof(CanUntrim), nameof(SelectedXCIFiles)); if (displayedChanged) @@ -136,10 +136,10 @@ namespace Ryujinx.Ava.UI.ViewModels private void ProcessingChanged() { OnPropertiesChanged( - nameof(Processing), - nameof(Cancel), - nameof(Status), - nameof(CanTrim), + nameof(Processing), + nameof(Cancel), + nameof(Status), + nameof(CanTrim), nameof(CanUntrim)); } @@ -245,8 +245,8 @@ namespace Ryujinx.Ava.UI.ViewModels if (arg is XCITrimmerFileModel content) { return string.IsNullOrWhiteSpace(_search) - || content.Name.ToLower().Contains(_search.ToLower()) - || content.Path.ToLower().Contains(_search.ToLower()); + || content.Name.Contains(_search, System.StringComparison.OrdinalIgnoreCase) + || content.Path.Contains(_search, System.StringComparison.OrdinalIgnoreCase); } return false; @@ -254,7 +254,7 @@ namespace Ryujinx.Ava.UI.ViewModels private class CompareXCITrimmerFiles : IComparer { - private XciTrimmerViewModel _viewModel; + private readonly XciTrimmerViewModel _viewModel; public CompareXCITrimmerFiles(XciTrimmerViewModel ViewModel) { diff --git a/src/Ryujinx/UI/Views/Dialog/AboutView.axaml.cs b/src/Ryujinx/UI/Views/Dialog/AboutView.axaml.cs index ce86156b9..8cfb18d15 100644 --- a/src/Ryujinx/UI/Views/Dialog/AboutView.axaml.cs +++ b/src/Ryujinx/UI/Views/Dialog/AboutView.axaml.cs @@ -22,7 +22,7 @@ namespace Ryujinx.Ava.UI.Views.Dialog public static async Task Show() { using AboutWindowViewModel viewModel = new(); - + ContentDialog contentDialog = new() { PrimaryButtonText = string.Empty, diff --git a/src/Ryujinx/UI/Views/Dialog/ApplicationDataView.axaml.cs b/src/Ryujinx/UI/Views/Dialog/ApplicationDataView.axaml.cs index 730128eb0..8f6be58a9 100644 --- a/src/Ryujinx/UI/Views/Dialog/ApplicationDataView.axaml.cs +++ b/src/Ryujinx/UI/Views/Dialog/ApplicationDataView.axaml.cs @@ -1,14 +1,14 @@ -using Avalonia.Controls; +using Avalonia.Controls; using Avalonia.Input.Platform; using Avalonia.Interactivity; using Avalonia.Layout; using FluentAvalonia.UI.Controls; using Ryujinx.Ava.Common.Locale; +using Ryujinx.Ava.Systems.AppLibrary; using Ryujinx.Ava.UI.Controls; using Ryujinx.Ava.UI.Helpers; using Ryujinx.Ava.UI.ViewModels; using Ryujinx.Ava.UI.Windows; -using Ryujinx.Ava.Systems.AppLibrary; using System.Linq; using System.Threading.Tasks; @@ -30,12 +30,12 @@ namespace Ryujinx.Ava.UI.Views.Dialog await ContentDialogHelper.ShowAsync(contentDialog.ApplyStyles(160, HorizontalAlignment.Center)); } - + public ApplicationDataView() { InitializeComponent(); } - + private async void PlayabilityStatus_OnClick(object sender, RoutedEventArgs e) { if (sender is not Button { Content: TextBlock playabilityLabel }) @@ -43,7 +43,7 @@ namespace Ryujinx.Ava.UI.Views.Dialog if (RyujinxApp.AppLifetime.Windows.TryGetFirst(x => x is ContentDialogOverlayWindow, out Window window)) window.Close(ContentDialogResult.None); - + await CompatibilityListWindow.Show((string)playabilityLabel.Tag); } @@ -54,15 +54,15 @@ namespace Ryujinx.Ava.UI.Views.Dialog if (!RyujinxApp.IsClipboardAvailable(out IClipboard clipboard)) return; - + ApplicationData appData = RyujinxApp.MainWindow.ViewModel.Applications.FirstOrDefault(it => it.IdString == idText.Text); if (appData is null) return; - + await clipboard.SetTextAsync(appData.IdString); - + NotificationHelper.ShowInformation( - "Copied Title ID", + "Copied Title ID", $"{appData.Name} ({appData.IdString})"); } } diff --git a/src/Ryujinx/UI/Views/Dialog/DlcSelectView.axaml.cs b/src/Ryujinx/UI/Views/Dialog/DlcSelectView.axaml.cs index fcd7dd353..8390b7403 100644 --- a/src/Ryujinx/UI/Views/Dialog/DlcSelectView.axaml.cs +++ b/src/Ryujinx/UI/Views/Dialog/DlcSelectView.axaml.cs @@ -1,10 +1,10 @@ -using FluentAvalonia.UI.Controls; +using FluentAvalonia.UI.Controls; using Ryujinx.Ava.Common.Locale; using Ryujinx.Ava.Common.Models; +using Ryujinx.Ava.Systems.AppLibrary; using Ryujinx.Ava.UI.Controls; using Ryujinx.Ava.UI.Helpers; using Ryujinx.Ava.UI.ViewModels; -using Ryujinx.Ava.Systems.AppLibrary; using System.Threading.Tasks; namespace Ryujinx.Ava.UI.Views.Dialog diff --git a/src/Ryujinx/UI/Views/Dialog/DownloadableContentManagerView.axaml.cs b/src/Ryujinx/UI/Views/Dialog/DownloadableContentManagerView.axaml.cs index 71461b81e..408e8892d 100644 --- a/src/Ryujinx/UI/Views/Dialog/DownloadableContentManagerView.axaml.cs +++ b/src/Ryujinx/UI/Views/Dialog/DownloadableContentManagerView.axaml.cs @@ -4,9 +4,9 @@ using Avalonia.Styling; using FluentAvalonia.UI.Controls; using Ryujinx.Ava.Common.Locale; using Ryujinx.Ava.Common.Models; -using Ryujinx.Ava.UI.ViewModels; using Ryujinx.Ava.Systems.AppLibrary; using Ryujinx.Ava.UI.Controls; +using Ryujinx.Ava.UI.ViewModels; using Ryujinx.Common.Helper; using System.Threading.Tasks; diff --git a/src/Ryujinx/UI/Views/Dialog/ModManagerView.axaml.cs b/src/Ryujinx/UI/Views/Dialog/ModManagerView.axaml.cs index 8735e2911..31e4323b7 100644 --- a/src/Ryujinx/UI/Views/Dialog/ModManagerView.axaml.cs +++ b/src/Ryujinx/UI/Views/Dialog/ModManagerView.axaml.cs @@ -3,11 +3,11 @@ using Avalonia.Interactivity; using Avalonia.Styling; using FluentAvalonia.UI.Controls; using Ryujinx.Ava.Common.Locale; +using Ryujinx.Ava.Systems.AppLibrary; +using Ryujinx.Ava.UI.Controls; using Ryujinx.Ava.UI.Helpers; using Ryujinx.Ava.UI.Models; using Ryujinx.Ava.UI.ViewModels; -using Ryujinx.Ava.Systems.AppLibrary; -using Ryujinx.Ava.UI.Controls; using Ryujinx.Common.Helper; using System.Threading.Tasks; using Button = Avalonia.Controls.Button; diff --git a/src/Ryujinx/UI/Views/Dialog/TitleUpdateManagerView.axaml.cs b/src/Ryujinx/UI/Views/Dialog/TitleUpdateManagerView.axaml.cs index bfff33592..3c745f3cb 100644 --- a/src/Ryujinx/UI/Views/Dialog/TitleUpdateManagerView.axaml.cs +++ b/src/Ryujinx/UI/Views/Dialog/TitleUpdateManagerView.axaml.cs @@ -4,9 +4,9 @@ using Avalonia.Styling; using FluentAvalonia.UI.Controls; using Ryujinx.Ava.Common.Locale; using Ryujinx.Ava.Common.Models; -using Ryujinx.Ava.UI.ViewModels; using Ryujinx.Ava.Systems.AppLibrary; using Ryujinx.Ava.UI.Controls; +using Ryujinx.Ava.UI.ViewModels; using Ryujinx.Common.Helper; using System.Threading.Tasks; diff --git a/src/Ryujinx/UI/Views/Input/ControllerInputView.axaml.cs b/src/Ryujinx/UI/Views/Input/ControllerInputView.axaml.cs index 87b2e7717..02e6e99c9 100644 --- a/src/Ryujinx/UI/Views/Input/ControllerInputView.axaml.cs +++ b/src/Ryujinx/UI/Views/Input/ControllerInputView.axaml.cs @@ -64,7 +64,7 @@ namespace Ryujinx.Ava.UI.Views.Input }; if (!float.IsNaN(_changeSlider) && _changeSlider != (float)check.Value) - { + { FlagInputConfigChanged(); _changeSlider = (float)check.Value; @@ -83,7 +83,6 @@ namespace Ryujinx.Ava.UI.Views.Input } } - private void Button_IsCheckedChanged(object sender, RoutedEventArgs e) { if (sender is ToggleButton button) @@ -104,7 +103,7 @@ namespace Ryujinx.Ava.UI.Views.Input this.Focus(NavigationMethod.Pointer); PointerPressed += MouseClick; - + ControllerInputViewModel viewModel = (DataContext as ControllerInputViewModel); IKeyboard keyboard = @@ -225,8 +224,8 @@ namespace Ryujinx.Ava.UI.Views.Input PointerPressed -= MouseClick; } - private IButtonAssigner CreateButtonAssigner(bool forStick) => - new GamepadButtonAssigner( + private GamepadButtonAssigner CreateButtonAssigner(bool forStick) => + new( ViewModel.ParentModel.SelectedGamepad, (ViewModel.ParentModel.Config as StandardControllerInputConfig).TriggerThreshold, forStick); @@ -234,11 +233,12 @@ namespace Ryujinx.Ava.UI.Views.Input protected override void OnDetachedFromVisualTree(VisualTreeAttachmentEventArgs e) { base.OnDetachedFromVisualTree(e); - + foreach (IGamepad gamepad in RyujinxApp.MainWindow.InputManager.GamepadDriver.GetGamepads()) { gamepad?.ClearLed(); } + _currentAssigner?.Cancel(); _currentAssigner = null; } diff --git a/src/Ryujinx/UI/Views/Input/InputView.axaml.cs b/src/Ryujinx/UI/Views/Input/InputView.axaml.cs index ae7a45530..b77eb4088 100644 --- a/src/Ryujinx/UI/Views/Input/InputView.axaml.cs +++ b/src/Ryujinx/UI/Views/Input/InputView.axaml.cs @@ -46,7 +46,6 @@ namespace Ryujinx.Ava.UI.Views.Input LocaleManager.Instance[LocaleKeys.Cancel], LocaleManager.Instance[LocaleKeys.RyujinxConfirm]); - if (result == UserResult.Yes) { ViewModel.Save(); @@ -61,14 +60,14 @@ namespace Ryujinx.Ava.UI.Views.Input ViewModel.IsModified = true; ViewModel.PlayerId = ((PlayerModel)e.AddedItems[0])!.Id; } + return; } ViewModel.IsModified = false; ViewModel.PlayerId = ViewModel.PlayerIdChoose; - - } - + + } } private void ComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e) diff --git a/src/Ryujinx/UI/Views/Input/KeyboardInputView.axaml.cs b/src/Ryujinx/UI/Views/Input/KeyboardInputView.axaml.cs index 6e105181f..668e1220c 100644 --- a/src/Ryujinx/UI/Views/Input/KeyboardInputView.axaml.cs +++ b/src/Ryujinx/UI/Views/Input/KeyboardInputView.axaml.cs @@ -9,8 +9,8 @@ using Ryujinx.Ava.UI.Helpers; using Ryujinx.Ava.UI.ViewModels.Input; using Ryujinx.Input; using Ryujinx.Input.Assigner; -using System.Collections.Generic; using System; +using System.Collections.Generic; using Button = Ryujinx.Input.Button; using Key = Ryujinx.Common.Configuration.Hid.Key; @@ -45,9 +45,9 @@ namespace Ryujinx.Ava.UI.Views.Input private void Button_IsCheckedChanged(object sender, RoutedEventArgs e) { - if (sender is not ToggleButton button) + if (sender is not ToggleButton button) return; - + if (button.IsChecked is true) { if (_currentAssigner != null && button == _currentAssigner.ToggledButton) @@ -65,7 +65,7 @@ namespace Ryujinx.Ava.UI.Views.Input IKeyboard keyboard = (IKeyboard)ViewModel.ParentModel.AvaloniaKeyboardDriver.GetGamepad("0"); // Open Avalonia keyboard for cancel operations. - IButtonAssigner assigner = + IButtonAssigner assigner = new KeyboardKeyAssigner((IKeyboard)ViewModel.ParentModel.SelectedGamepad); _currentAssigner.ButtonAssigned += (_, be) => @@ -205,7 +205,7 @@ namespace Ryujinx.Ava.UI.Views.Input if (_currentAssigner != null) { - Dictionary buttonActions = new Dictionary + Dictionary buttonActions = new() { { "ButtonZl", () => ViewModel.Config.ButtonZl = Key.Unbound }, { "ButtonL", () => ViewModel.Config.ButtonL = Key.Unbound }, diff --git a/src/Ryujinx/UI/Views/Input/LedInputView.axaml.cs b/src/Ryujinx/UI/Views/Input/LedInputView.axaml.cs index 916ada37e..cc1166dd7 100644 --- a/src/Ryujinx/UI/Views/Input/LedInputView.axaml.cs +++ b/src/Ryujinx/UI/Views/Input/LedInputView.axaml.cs @@ -1,4 +1,4 @@ -using Avalonia; +using Avalonia; using FluentAvalonia.UI.Controls; using Ryujinx.Ava.Common.Locale; using Ryujinx.Ava.UI.Controls; @@ -20,27 +20,32 @@ namespace Ryujinx.UI.Views.Input LedColor = viewModel.Config.LedColor, UseRainbowLed = viewModel.Config.UseRainbowLed, }; - + InitializeComponent(); } - + private void ColorPickerButton_OnColorChanged(ColorPickerButton sender, ColorButtonColorChangedEventArgs args) { - if (!args.NewColor.HasValue) return; - if (!ViewModel.EnableLedChanging) return; - if (ViewModel.TurnOffLed) return; - + if (!args.NewColor.HasValue) + return; + if (!ViewModel.EnableLedChanging) + return; + if (ViewModel.TurnOffLed) + return; + ViewModel.ParentModel.SelectedGamepad.SetLed(args.NewColor.Value.ToUInt32()); } private void ColorPickerButton_OnAttachedToVisualTree(object sender, VisualTreeAttachmentEventArgs e) { - if (!ViewModel.EnableLedChanging) return; - if (ViewModel.TurnOffLed) return; - + if (!ViewModel.EnableLedChanging) + return; + if (ViewModel.TurnOffLed) + return; + ViewModel.ParentModel.SelectedGamepad.SetLed(ViewModel.LedColor.ToUInt32()); } - + public static async Task Show(ControllerInputViewModel viewModel) { LedInputView content = new(viewModel); diff --git a/src/Ryujinx/UI/Views/Main/MainMenuBarView.axaml.cs b/src/Ryujinx/UI/Views/Main/MainMenuBarView.axaml.cs index 5534ab8e7..113f2e63a 100644 --- a/src/Ryujinx/UI/Views/Main/MainMenuBarView.axaml.cs +++ b/src/Ryujinx/UI/Views/Main/MainMenuBarView.axaml.cs @@ -6,14 +6,14 @@ using Gommon; using LibHac.Common; using LibHac.Ns; using Ryujinx.Ava.Common.Locale; +using Ryujinx.Ava.Systems.AppLibrary; +using Ryujinx.Ava.Systems.Configuration; using Ryujinx.Ava.UI.Controls; using Ryujinx.Ava.UI.Helpers; using Ryujinx.Ava.UI.ViewModels; +using Ryujinx.Ava.UI.Views.Dialog; using Ryujinx.Ava.UI.Windows; using Ryujinx.Ava.Utilities; -using Ryujinx.Ava.Systems.AppLibrary; -using Ryujinx.Ava.Systems.Configuration; -using Ryujinx.Ava.UI.Views.Dialog; using Ryujinx.Common; using Ryujinx.Common.Helper; using Ryujinx.Common.Utilities; @@ -52,13 +52,13 @@ namespace Ryujinx.Ava.UI.Views.Main UpdateMenuItem.Command = MainWindowViewModel.UpdateCommand; - FaqMenuItem.Command = - SetupGuideMenuItem.Command = + FaqMenuItem.Command = + SetupGuideMenuItem.Command = LdnGuideMenuItem.Command = Commands.Create(OpenHelper.OpenUrl); - - WindowSize720PMenuItem.Command = - WindowSize1080PMenuItem.Command = - WindowSize1440PMenuItem.Command = + + WindowSize720PMenuItem.Command = + WindowSize1080PMenuItem.Command = + WindowSize1440PMenuItem.Command = WindowSize2160PMenuItem.Command = Commands.Create(ChangeWindowSize); } @@ -95,7 +95,7 @@ namespace Ryujinx.Ava.UI.Views.Main { string tr = locales.Locales[index].Translations[language]; languageName = string.IsNullOrEmpty(tr) - ? language + ? language : tr; } @@ -134,7 +134,7 @@ namespace Ryujinx.Ava.UI.Views.Main await StyleableAppWindow.ShowAsync(Window.SettingsWindow); } else - { + { bool customConfigExists = File.Exists(Program.GetDirGameUserConfig(ViewModel.SelectedApplication.IdString)); if (!ViewModel.IsGameRunning || !customConfigExists) @@ -157,12 +157,12 @@ namespace Ryujinx.Ava.UI.Views.Main } public AppletMetadata MiiApplet => new(ViewModel.ContentManager, "miiEdit", 0x0100000000001009); - + public async Task OpenMiiApplet() { - if (!MiiApplet.CanStart(out ApplicationData appData, out BlitStruct nacpData)) + if (!MiiApplet.CanStart(out ApplicationData appData, out BlitStruct nacpData)) return; - + await ViewModel.LoadApplication(appData, ViewModel.IsFullScreen || ViewModel.StartGamesInFullscreen, nacpData); } @@ -217,7 +217,7 @@ namespace Ryujinx.Ava.UI.Views.Main private void ChangeWindowSize(string resolution) { (int resolutionWidth, int resolutionHeight) = resolution.Split(' ', 2) - .Into(parts => + .Into(parts => (int.Parse(parts[0]), int.Parse(parts[1])) ); @@ -237,6 +237,6 @@ namespace Ryujinx.Ava.UI.Views.Main } public void CloseWindow() => Window.Close(); - + } } diff --git a/src/Ryujinx/UI/Views/Main/MainStatusBarView.axaml.cs b/src/Ryujinx/UI/Views/Main/MainStatusBarView.axaml.cs index 8341dd92a..ca80d3bf8 100644 --- a/src/Ryujinx/UI/Views/Main/MainStatusBarView.axaml.cs +++ b/src/Ryujinx/UI/Views/Main/MainStatusBarView.axaml.cs @@ -3,10 +3,10 @@ using Avalonia.Input; using Avalonia.Interactivity; using Avalonia.Threading; using Ryujinx.Ava.Common.Locale; +using Ryujinx.Ava.Systems.Configuration; using Ryujinx.Ava.UI.Controls; using Ryujinx.Ava.UI.ViewModels; using Ryujinx.Ava.UI.Windows; -using Ryujinx.Ava.Systems.Configuration; using Ryujinx.Common; using Ryujinx.Common.Configuration; using Ryujinx.Common.Logging; diff --git a/src/Ryujinx/UI/Views/Misc/ApplicationGridView.axaml.cs b/src/Ryujinx/UI/Views/Misc/ApplicationGridView.axaml.cs index c1cf7a66b..4b4e08d3d 100644 --- a/src/Ryujinx/UI/Views/Misc/ApplicationGridView.axaml.cs +++ b/src/Ryujinx/UI/Views/Misc/ApplicationGridView.axaml.cs @@ -1,10 +1,10 @@ using Avalonia.Controls; using Avalonia.Input; using Avalonia.Interactivity; +using Ryujinx.Ava.Systems.AppLibrary; using Ryujinx.Ava.UI.Controls; using Ryujinx.Ava.UI.Helpers; using Ryujinx.Ava.UI.ViewModels; -using Ryujinx.Ava.Systems.AppLibrary; using System; namespace Ryujinx.Ava.UI.Views.Misc diff --git a/src/Ryujinx/UI/Views/Misc/ApplicationListView.axaml.cs b/src/Ryujinx/UI/Views/Misc/ApplicationListView.axaml.cs index aa87a8c9a..a3e1c438d 100644 --- a/src/Ryujinx/UI/Views/Misc/ApplicationListView.axaml.cs +++ b/src/Ryujinx/UI/Views/Misc/ApplicationListView.axaml.cs @@ -2,10 +2,10 @@ using Avalonia.Controls; using Avalonia.Input; using Avalonia.Input.Platform; using Avalonia.Interactivity; +using Ryujinx.Ava.Systems.AppLibrary; using Ryujinx.Ava.UI.Controls; using Ryujinx.Ava.UI.Helpers; using Ryujinx.Ava.UI.ViewModels; -using Ryujinx.Ava.Systems.AppLibrary; using Ryujinx.Ava.UI.Windows; using System; using System.Linq; @@ -30,7 +30,7 @@ namespace Ryujinx.Ava.UI.Views.Misc if (sender is ListBox { SelectedItem: ApplicationData selected }) RaiseEvent(new ApplicationOpenedEventArgs(selected, ApplicationOpenedEvent)); } - + private async void PlayabilityStatus_OnClick(object sender, RoutedEventArgs e) { if (sender is not Button { Content: TextBlock playabilityLabel }) @@ -46,15 +46,15 @@ namespace Ryujinx.Ava.UI.Views.Misc if (!RyujinxApp.IsClipboardAvailable(out IClipboard clipboard)) return; - + ApplicationData appData = ViewModel.Applications.FirstOrDefault(it => it.IdString == idText.Text); if (appData is null) return; - + await clipboard.SetTextAsync(appData.IdString); - + NotificationHelper.ShowInformation( - "Copied Title ID", + "Copied Title ID", $"{appData.Name} ({appData.IdString})"); } } diff --git a/src/Ryujinx/UI/Views/Settings/SettingsHotkeysView.axaml.cs b/src/Ryujinx/UI/Views/Settings/SettingsHotkeysView.axaml.cs index cadf0e1d6..b9a5462b2 100644 --- a/src/Ryujinx/UI/Views/Settings/SettingsHotkeysView.axaml.cs +++ b/src/Ryujinx/UI/Views/Settings/SettingsHotkeysView.axaml.cs @@ -10,8 +10,8 @@ using Ryujinx.Ava.UI.Helpers; using Ryujinx.Ava.UI.ViewModels; using Ryujinx.Input; using Ryujinx.Input.Assigner; -using System.Collections.Generic; using System; +using System.Collections.Generic; using Button = Ryujinx.Input.Button; using Key = Ryujinx.Common.Configuration.Hid.Key; @@ -20,7 +20,7 @@ namespace Ryujinx.Ava.UI.Views.Settings public partial class SettingsHotkeysView : RyujinxControl { private ButtonKeyAssigner _currentAssigner; - private readonly IGamepadDriver _avaloniaKeyboardDriver; + private readonly AvaloniaKeyboardDriver _avaloniaKeyboardDriver; public SettingsHotkeysView() { @@ -56,7 +56,7 @@ namespace Ryujinx.Ava.UI.Views.Settings { DeleteBind(); } - + _currentAssigner?.Cancel(shouldUnbind); PointerPressed -= MouseClick; @@ -69,7 +69,7 @@ namespace Ryujinx.Ava.UI.Views.Settings if (_currentAssigner != null) { - Dictionary buttonActions = new Dictionary + Dictionary buttonActions = new() { { "ToggleVSyncMode", () => viewModel.KeyboardHotkey.ToggleVSyncMode = Key.Unbound }, { "Screenshot", () => viewModel.KeyboardHotkey.Screenshot = Key.Unbound }, diff --git a/src/Ryujinx/UI/Views/Settings/SettingsUIView.axaml.cs b/src/Ryujinx/UI/Views/Settings/SettingsUIView.axaml.cs index fb839a473..f0742a579 100644 --- a/src/Ryujinx/UI/Views/Settings/SettingsUIView.axaml.cs +++ b/src/Ryujinx/UI/Views/Settings/SettingsUIView.axaml.cs @@ -32,7 +32,7 @@ namespace Ryujinx.Ava.UI.Views.Settings if (!string.IsNullOrWhiteSpace(path) && Directory.Exists(path) && !directories.Contains(path)) { directories.Add(path); - + addDirBox.Clear(); ViewModel.GameListNeedsRefresh = true; @@ -44,7 +44,7 @@ namespace Ryujinx.Ava.UI.Views.Settings if (folder.HasValue) { directories.Add(folder.Value.Path.LocalPath); - + ViewModel.GameListNeedsRefresh = true; } } diff --git a/src/Ryujinx/UI/Views/User/UserEditorView.axaml.cs b/src/Ryujinx/UI/Views/User/UserEditorView.axaml.cs index eb1cf58bb..62add2393 100644 --- a/src/Ryujinx/UI/Views/User/UserEditorView.axaml.cs +++ b/src/Ryujinx/UI/Views/User/UserEditorView.axaml.cs @@ -17,7 +17,7 @@ namespace Ryujinx.Ava.UI.Views.User private NavigationDialogHost _parent; private UserProfile _profile; private bool _isNewUser; - + public static uint MaxProfileNameLength => 0x20; public bool IsDeletable => _profile.UserId != AccountManager.DefaultUserId; diff --git a/src/Ryujinx/UI/Views/User/UserProfileImageSelectorView.axaml.cs b/src/Ryujinx/UI/Views/User/UserProfileImageSelectorView.axaml.cs index ae8ebec1a..3a5b7c6b7 100644 --- a/src/Ryujinx/UI/Views/User/UserProfileImageSelectorView.axaml.cs +++ b/src/Ryujinx/UI/Views/User/UserProfileImageSelectorView.axaml.cs @@ -54,6 +54,7 @@ namespace Ryujinx.Ava.UI.Views.User { _parent.GoBack(); } + break; } } diff --git a/src/Ryujinx/UI/Views/User/UserSaveManagerView.axaml.cs b/src/Ryujinx/UI/Views/User/UserSaveManagerView.axaml.cs index edbbd595b..7571888b8 100644 --- a/src/Ryujinx/UI/Views/User/UserSaveManagerView.axaml.cs +++ b/src/Ryujinx/UI/Views/User/UserSaveManagerView.axaml.cs @@ -130,7 +130,7 @@ namespace Ryujinx.Ava.UI.Views.User UserResult result = await ContentDialogHelper.CreateConfirmationDialog(LocaleManager.Instance[LocaleKeys.DeleteUserSave], LocaleManager.Instance[LocaleKeys.IrreversibleActionNote], LocaleManager.Instance[LocaleKeys.InputDialogYes], - LocaleManager.Instance[LocaleKeys.InputDialogNo], + LocaleManager.Instance[LocaleKeys.InputDialogNo], string.Empty); if (result == UserResult.Yes) diff --git a/src/Ryujinx/UI/Windows/CheatWindow.axaml.cs b/src/Ryujinx/UI/Windows/CheatWindow.axaml.cs index a9b42be1f..297be728c 100644 --- a/src/Ryujinx/UI/Windows/CheatWindow.axaml.cs +++ b/src/Ryujinx/UI/Windows/CheatWindow.axaml.cs @@ -1,8 +1,8 @@ using Avalonia.Collections; using Ryujinx.Ava.Common.Locale; -using Ryujinx.Ava.UI.Models; using Ryujinx.Ava.Systems.AppLibrary; using Ryujinx.Ava.Systems.Configuration; +using Ryujinx.Ava.UI.Models; using Ryujinx.HLE.FileSystem; using Ryujinx.HLE.HOS; using System.Collections.Generic; @@ -35,7 +35,7 @@ namespace Ryujinx.Ava.UI.Windows { MinWidth = 500; MinHeight = 650; - + LoadedCheats = []; Heading = LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.CheatWindowHeading, titleName, titleId.ToUpper()); diff --git a/src/Ryujinx/UI/Windows/CompatibilityListWindow.axaml.cs b/src/Ryujinx/UI/Windows/CompatibilityListWindow.axaml.cs index a2b98f8f8..b3442b7ee 100644 --- a/src/Ryujinx/UI/Windows/CompatibilityListWindow.axaml.cs +++ b/src/Ryujinx/UI/Windows/CompatibilityListWindow.axaml.cs @@ -1,4 +1,4 @@ -using Avalonia.Controls; +using Avalonia.Controls; using Ryujinx.Ava.Common.Locale; using Ryujinx.Ava.Systems.Configuration; using Ryujinx.Ava.UI.ViewModels; @@ -11,7 +11,7 @@ namespace Ryujinx.Ava.UI.Windows public static async Task Show(string titleId = null) { using CompatibilityViewModel compatWindow = new(RyujinxApp.MainWindow.ViewModel.ApplicationLibrary); - + await ShowAsync(new CompatibilityListWindow { DataContext = compatWindow, @@ -23,9 +23,9 @@ namespace Ryujinx.Ava.UI.Windows public CompatibilityListWindow() : base(useCustomTitleBar: true, 37) { Title = RyujinxApp.FormatTitle(LocaleKeys.CompatibilityListTitle); - + InitializeComponent(); - + FlushControls.IsVisible = !ConfigurationState.Instance.ShowOldUI; NormalControls.IsVisible = ConfigurationState.Instance.ShowOldUI; } @@ -39,7 +39,7 @@ namespace Ryujinx.Ava.UI.Windows if (sender is not TextBox searchBox) return; - + cvm.Search(searchBox.Text); } } diff --git a/src/Ryujinx/UI/Windows/GameSpecificSettingsWindow.axaml.cs b/src/Ryujinx/UI/Windows/GameSpecificSettingsWindow.axaml.cs index 0d172ff59..fb4767712 100644 --- a/src/Ryujinx/UI/Windows/GameSpecificSettingsWindow.axaml.cs +++ b/src/Ryujinx/UI/Windows/GameSpecificSettingsWindow.axaml.cs @@ -5,7 +5,6 @@ using Ryujinx.Ava.UI.ViewModels; using System; using System.Linq; - namespace Ryujinx.Ava.UI.Windows { public partial class GameSpecificSettingsWindow : StyleableAppWindow @@ -17,7 +16,7 @@ namespace Ryujinx.Ava.UI.Windows Title = string.Format(LocaleManager.Instance[LocaleKeys.SettingsWithInfo], viewModel.SelectedApplication.Name, viewModel.SelectedApplication.IdString); DataContext = ViewModel = new SettingsViewModel( - viewModel.VirtualFileSystem, + viewModel.VirtualFileSystem, viewModel.ContentManager, viewModel.IsGameRunning, viewModel.SelectedApplication.Path, @@ -38,7 +37,6 @@ namespace Ryujinx.Ava.UI.Windows InputPage.InputView?.SaveCurrentProfile(); } - private void Load() { Pages.Children.Clear(); @@ -48,7 +46,7 @@ namespace Ryujinx.Ava.UI.Windows private void NavPanelOnSelectionChanged(object sender, NavigationViewSelectionChangedEventArgs e) { - + if (e.SelectedItem is NavigationViewItem navItem && navItem.Tag is not null) { switch (navItem.Tag.ToString()) @@ -87,7 +85,7 @@ namespace Ryujinx.Ava.UI.Windows default: throw new NotImplementedException(); } - } + } } protected override void OnClosing(WindowClosingEventArgs e) diff --git a/src/Ryujinx/UI/Windows/MainWindow.axaml.cs b/src/Ryujinx/UI/Windows/MainWindow.axaml.cs index 6ba2ac725..a2d7ff657 100644 --- a/src/Ryujinx/UI/Windows/MainWindow.axaml.cs +++ b/src/Ryujinx/UI/Windows/MainWindow.axaml.cs @@ -13,13 +13,13 @@ using Ryujinx.Ava.Common; using Ryujinx.Ava.Common.Locale; using Ryujinx.Ava.Input; using Ryujinx.Ava.Systems; +using Ryujinx.Ava.Systems.AppLibrary; +using Ryujinx.Ava.Systems.Configuration; +using Ryujinx.Ava.Systems.Configuration.UI; using Ryujinx.Ava.UI.Applet; using Ryujinx.Ava.UI.Helpers; using Ryujinx.Ava.UI.ViewModels; using Ryujinx.Ava.Utilities; -using Ryujinx.Ava.Systems.AppLibrary; -using Ryujinx.Ava.Systems.Configuration; -using Ryujinx.Ava.Systems.Configuration.UI; using Ryujinx.Common; using Ryujinx.Common.Helper; using Ryujinx.Common.Logging; @@ -92,9 +92,9 @@ namespace Ryujinx.Ava.UI.Windows // NOTE: Height of MenuBar and StatusBar is not usable here, since it would still be 0 at this point. StatusBarHeight = StatusBarView.StatusBar.MinHeight; MenuBarHeight = MenuBar.MinHeight; - + TitleBar.Height = MenuBarHeight; - + // Correctly size window when 'TitleBar' is enabled (Nov. 14, 2024) TitleBarHeight = (ConfigurationState.Instance.ShowOldUI ? TitleBar.Height : 0); @@ -135,7 +135,7 @@ namespace Ryujinx.Ava.UI.Windows base.OnApplyTemplate(e); NotificationHelper.SetNotificationManager(this); - + Executor.ExecuteBackgroundAsync(async () => { await ShowIntelMacWarningAsync(); @@ -145,7 +145,7 @@ namespace Ryujinx.Ava.UI.Windows if ((firmwarePath.ExistsAsFile && firmwarePath.Extension is "xci" or "zip") || firmwarePath.ExistsAsDirectory) { - await Dispatcher.UIThread.InvokeAsync(() => + await Dispatcher.UIThread.InvokeAsync(() => ViewModel.HandleFirmwareInstallation(firmwarePath)); CommandLineState.FirmwareToInstallPathArg = null; } @@ -191,10 +191,10 @@ namespace Ryujinx.Ava.UI.Windows ref ApplicationControlProperty controlHolder = ref application.ControlHolder.Value; ViewModel.LdnData[application.IdString] = e.LdnData.Where(ref controlHolder); - + UpdateApplicationWithLdnData(application); } - + ViewModel.RefreshView(); }); } @@ -230,7 +230,7 @@ namespace Ryujinx.Ava.UI.Windows _deferLoad = true; _launchPath = launchPathArg; _launchApplicationId = launchApplicationId; - _startFullscreen = startFullscreenArg; + _startFullscreen = startFullscreenArg; } public void SwitchToGameControl(bool startFullscreen = false) @@ -330,6 +330,7 @@ namespace Ryujinx.Ava.UI.Windows { Logger.Error?.Print(LogClass.Application, $"Unable to change vm.max_map_count. Process exited with code: {rc}"); } + break; case UserResult.No: rc = LinuxHelper.RunPkExec($"echo \"vm.max_map_count = {LinuxHelper.RecommendedVmMaxMapCount}\" > {LinuxHelper.SysCtlConfigPath} && sysctl -p {LinuxHelper.SysCtlConfigPath}"); @@ -341,6 +342,7 @@ namespace Ryujinx.Ava.UI.Windows { Logger.Error?.Print(LogClass.Application, $"Unable to write new value for vm.max_map_count to config. Process exited with code: {rc}"); } + break; } } @@ -421,6 +423,7 @@ namespace Ryujinx.Ava.UI.Windows { Dispatcher.UIThread.Post(() => RyujinxApp.MainWindow.ViewModel.UpdateAvailable = versions.Current < versions.Incoming); } + break; } } @@ -430,7 +433,7 @@ namespace Ryujinx.Ava.UI.Windows StatusBarView.VolumeStatus.Click += VolumeStatus_CheckedChanged; ApplicationGrid.DataContext = ApplicationList.DataContext = ViewModel; - + ApplicationGrid.ApplicationOpened += Application_Opened; ApplicationList.ApplicationOpened += Application_Opened; } @@ -717,7 +720,7 @@ namespace Ryujinx.Ava.UI.Windows ShowNewContentAddedDialog(dlcLoaded, dlcRemoved, updatesLoaded, updatesRemoved); } - + Executor.ExecuteBackgroundAsync(ApplicationLibrary.RefreshTotalTimePlayedAsync); _isLoading = false; @@ -729,7 +732,7 @@ namespace Ryujinx.Ava.UI.Windows applicationLibraryThread.Start(); } - private void ShowNewContentAddedDialog(int numDlcAdded, int numDlcRemoved, int numUpdatesAdded, int numUpdatesRemoved) + private static void ShowNewContentAddedDialog(int numDlcAdded, int numDlcRemoved, int numUpdatesAdded, int numUpdatesRemoved) { string[] messages = [ @@ -749,10 +752,10 @@ namespace Ryujinx.Ava.UI.Windows await ContentDialogHelper.ShowTextDialog( LocaleManager.Instance[LocaleKeys.DialogConfirmationTitle], msg, - string.Empty, - string.Empty, - string.Empty, - LocaleManager.Instance[LocaleKeys.InputDialogOk], + string.Empty, + string.Empty, + string.Empty, + LocaleManager.Instance[LocaleKeys.InputDialogOk], (int)Symbol.Checkmark); }); } @@ -761,20 +764,22 @@ namespace Ryujinx.Ava.UI.Windows public static async Task ShowIntelMacWarningAsync() { - if (_intelMacWarningShown) return; - + if (_intelMacWarningShown) + return; + await Dispatcher.UIThread.InvokeAsync(async () => await ContentDialogHelper.CreateWarningDialog( "Intel Mac Warning", "Intel Macs are not supported and will not work properly.\nIf you continue, do not come to our Discord asking for support;\nand do not report bugs on the GitHub. They will be closed.")); _intelMacWarningShown = true; } - + private void InputElement_OnGotFocus(object sender, GotFocusEventArgs e) { - if (ViewModel.AppHost is null) return; - - if (!_focusLoss.Active) + if (ViewModel.AppHost is null) + return; + + if (!_focusLoss.Active) return; switch (_focusLoss.Type) @@ -798,9 +803,9 @@ namespace Ryujinx.Ava.UI.Windows _focusLoss = default; return; } - + ViewModel.AppHost.Device.SetVolume(ViewModel.VolumeBeforeMute); - + _focusLoss = default; break; } @@ -808,10 +813,10 @@ namespace Ryujinx.Ava.UI.Windows { if (!ViewModel.AppHost.Device.IsAudioMuted()) goto case FocusLostType.BlockInput; - + ViewModel.AppHost.Device.SetVolume(ViewModel.VolumeBeforeMute); ViewModel.AppHost.NpadManager.UnblockInputUpdates(); - + _focusLoss = default; break; } @@ -822,15 +827,15 @@ namespace Ryujinx.Ava.UI.Windows _focusLoss = default; return; } - + ViewModel.AppHost.Resume(); - + _focusLoss = default; break; } } } - + private (FocusLostType Type, bool Active) _focusLoss; private void InputElement_OnLostFocus(object sender, RoutedEventArgs e) @@ -838,7 +843,8 @@ namespace Ryujinx.Ava.UI.Windows if (ConfigurationState.Instance.FocusLostActionType.Value is FocusLostType.DoNothing) return; - if (ViewModel.AppHost is null) return; + if (ViewModel.AppHost is null) + return; switch (ConfigurationState.Instance.FocusLostActionType.Value) { @@ -846,7 +852,7 @@ namespace Ryujinx.Ava.UI.Windows { if (ViewModel.AppHost.NpadManager.InputUpdatesBlocked) return; - + ViewModel.AppHost.NpadManager.BlockInputUpdates(); _focusLoss = (FocusLostType.BlockInput, ViewModel.AppHost.NpadManager.InputUpdatesBlocked); break; @@ -876,7 +882,7 @@ namespace Ryujinx.Ava.UI.Windows { if (ViewModel.AppHost.Device.System.IsPaused) return; - + ViewModel.AppHost.Pause(); _focusLoss = (FocusLostType.PauseEmulation, ViewModel.AppHost.Device.System.IsPaused); break; diff --git a/src/Ryujinx/UI/Windows/SettingsWindow.axaml.cs b/src/Ryujinx/UI/Windows/SettingsWindow.axaml.cs index f68ec7279..81c00e4ac 100644 --- a/src/Ryujinx/UI/Windows/SettingsWindow.axaml.cs +++ b/src/Ryujinx/UI/Windows/SettingsWindow.axaml.cs @@ -33,7 +33,7 @@ namespace Ryujinx.Ava.UI.Windows Height = ConfigurationState.Instance.ShowOldUI ? 906 : 954; // nav panel is put on top with custom title bar so account for new height - + Load(); } @@ -111,12 +111,12 @@ namespace Ryujinx.Ava.UI.Windows protected override void OnClosing(WindowClosingEventArgs e) { HotkeysPage.Dispose(); - + foreach (IGamepad gamepad in RyujinxApp.MainWindow.InputManager.GamepadDriver.GetGamepads()) { gamepad?.ClearLed(); } - + InputPage.Dispose(); base.OnClosing(e); } diff --git a/src/Ryujinx/UI/Windows/StyleableWindow.cs b/src/Ryujinx/UI/Windows/StyleableWindow.cs index c5f753402..066440382 100644 --- a/src/Ryujinx/UI/Windows/StyleableWindow.cs +++ b/src/Ryujinx/UI/Windows/StyleableWindow.cs @@ -17,11 +17,11 @@ namespace Ryujinx.Ava.UI.Windows public static async Task ShowAsync(StyleableAppWindow appWindow, Window owner = null) { #if DEBUG - appWindow.AttachDevTools(new KeyGesture(Key.F12, KeyModifiers.Control)); + appWindow.AttachDevTools(new KeyGesture(Key.F12, KeyModifiers.Control)); #endif await appWindow.ShowDialog(owner ?? RyujinxApp.MainWindow); } - + protected StyleableAppWindow(bool useCustomTitleBar = false, double? titleBarHeight = null) { WindowStartupLocation = WindowStartupLocation.CenterOwner; @@ -34,7 +34,7 @@ namespace Ryujinx.Ava.UI.Windows { TitleBar.ExtendsContentIntoTitleBar = !ConfigurationState.Instance.ShowOldUI; TitleBar.TitleBarHitTestType = ConfigurationState.Instance.ShowOldUI ? TitleBarHitTestType.Simple : TitleBarHitTestType.Complex; - + if (TitleBar.ExtendsContentIntoTitleBar && titleBarHeight != null) TitleBar.Height = titleBarHeight.Value; } @@ -60,7 +60,7 @@ namespace Ryujinx.Ava.UI.Windows public static async Task ShowAsync(StyleableWindow window, Window owner = null) { #if DEBUG - window.AttachDevTools(new KeyGesture(Key.F12, KeyModifiers.Control)); + window.AttachDevTools(new KeyGesture(Key.F12, KeyModifiers.Control)); #endif await window.ShowDialog(owner ?? RyujinxApp.MainWindow); } diff --git a/src/Ryujinx/Utilities/AppletMetadata.cs b/src/Ryujinx/Utilities/AppletMetadata.cs index 3dee3a94d..42b8227dd 100644 --- a/src/Ryujinx/Utilities/AppletMetadata.cs +++ b/src/Ryujinx/Utilities/AppletMetadata.cs @@ -1,4 +1,4 @@ -using LibHac.Common; +using LibHac.Common; using LibHac.Ncm; using LibHac.Ns; using LibHac.Tools.FsSystem.NcaUtils; @@ -38,17 +38,17 @@ namespace Ryujinx.Ava.Utilities out BlitStruct appControl) { contentManager ??= _contentManager; - if (contentManager == null) + if (contentManager == null) goto BadData; string contentPath = GetContentPath(contentManager); - if (string.IsNullOrEmpty(contentPath)) + if (string.IsNullOrEmpty(contentPath)) goto BadData; appData = new() { Name = Name, Id = ProgramId, Path = contentPath }; appControl = StructHelpers.CreateCustomNacpData(Name, Version); return true; - + BadData: appData = null; appControl = new BlitStruct(0); diff --git a/src/Ryujinx/Utilities/CommandLineState.cs b/src/Ryujinx/Utilities/CommandLineState.cs index 33017756d..d7d113ebe 100644 --- a/src/Ryujinx/Utilities/CommandLineState.cs +++ b/src/Ryujinx/Utilities/CommandLineState.cs @@ -14,9 +14,9 @@ namespace Ryujinx.Ava.Utilities public static string OverrideBackendThreading { get; private set; } public static string OverrideBackendThreadingAfterReboot { get; private set; } public static string OverridePPTC { get; private set; } - public static string OverrideMemoryManagerMode { get; private set; } - public static string OverrideSystemRegion { get; private set; } - public static string OverrideSystemLanguage { get; private set; } + public static string OverrideMemoryManagerMode { get; private set; } + public static string OverrideSystemRegion { get; private set; } + public static string OverrideSystemLanguage { get; private set; } public static string OverrideHideCursor { get; private set; } public static string BaseDirPathArg { get; private set; } public static FilePath FirmwareToInstallPathArg { get; set; } @@ -26,7 +26,6 @@ namespace Ryujinx.Ava.Utilities public static bool StartFullscreenArg { get; private set; } public static bool HideAvailableUpdates { get; private set; } - public static void ParseArguments(string[] args) { List arguments = []; @@ -36,9 +35,9 @@ namespace Ryujinx.Ava.Utilities { string arg = args[i]; - if (arg.Contains("-") || arg.Contains("--")) + if (arg.Contains('-') || arg.Contains("--")) { - CountArguments++; + CountArguments++; } switch (arg) diff --git a/src/Ryujinx/Utilities/SetupValidator.cs b/src/Ryujinx/Utilities/SetupValidator.cs index 0bd3a348d..f4809484a 100644 --- a/src/Ryujinx/Utilities/SetupValidator.cs +++ b/src/Ryujinx/Utilities/SetupValidator.cs @@ -31,7 +31,7 @@ namespace Ryujinx.Ava.Utilities firmwareVersion = null; } - return error == UserError.NoFirmware && Path.GetExtension(baseApplicationPath).ToLowerInvariant() == ".xci" && firmwareVersion != null; + return error == UserError.NoFirmware && Path.GetExtension(baseApplicationPath).Equals(".xci", StringComparison.OrdinalIgnoreCase) && firmwareVersion != null; } public static bool TryFixStartApplication(ContentManager contentManager, string baseApplicationPath, UserError error, out UserError outError) @@ -94,7 +94,7 @@ namespace Ryujinx.Ava.Utilities error = UserError.Success; return true; } - + return IsFirmwareValid(contentManager, out error); } diff --git a/src/Ryujinx/Utilities/StorageProviderExtensions.cs b/src/Ryujinx/Utilities/StorageProviderExtensions.cs index 502b4a541..1efabfbaa 100644 --- a/src/Ryujinx/Utilities/StorageProviderExtensions.cs +++ b/src/Ryujinx/Utilities/StorageProviderExtensions.cs @@ -1,4 +1,4 @@ -using Avalonia.Platform.Storage; +using Avalonia.Platform.Storage; using Gommon; using System.Collections.Generic; using System.Linq; @@ -15,7 +15,7 @@ namespace Ryujinx.Ava.Utilities public static async Task> OpenSingleFilePickerAsync(this IStorageProvider storageProvider, FilePickerOpenOptions openOptions = null) => await storageProvider.OpenFilePickerAsync(FixOpenOptions(openOptions, false)) .Then(files => files.FindFirst()); - + public static async Task>> OpenMultiFolderPickerAsync(this IStorageProvider storageProvider, FolderPickerOpenOptions openOptions = null) => await storageProvider.OpenFolderPickerAsync(FixOpenOptions(openOptions, true)) .Then(folders => folders.Count > 0 ? Optional.Of(folders) : default); @@ -23,24 +23,24 @@ namespace Ryujinx.Ava.Utilities public static async Task>> OpenMultiFilePickerAsync(this IStorageProvider storageProvider, FilePickerOpenOptions openOptions = null) => await storageProvider.OpenFilePickerAsync(FixOpenOptions(openOptions, true)) .Then(files => files.Count > 0 ? Optional.Of(files) : default); - + private static FilePickerOpenOptions FixOpenOptions(this FilePickerOpenOptions openOptions, bool allowMultiple) { if (openOptions is null) return new FilePickerOpenOptions { AllowMultiple = allowMultiple }; openOptions.AllowMultiple = allowMultiple; - + return openOptions; } - + private static FolderPickerOpenOptions FixOpenOptions(this FolderPickerOpenOptions openOptions, bool allowMultiple) { if (openOptions is null) return new FolderPickerOpenOptions { AllowMultiple = allowMultiple }; openOptions.AllowMultiple = allowMultiple; - + return openOptions; } } diff --git a/src/Ryujinx/Utilities/TitleHelper.cs b/src/Ryujinx/Utilities/TitleHelper.cs index d255838b8..5e0916c27 100644 --- a/src/Ryujinx/Utilities/TitleHelper.cs +++ b/src/Ryujinx/Utilities/TitleHelper.cs @@ -14,7 +14,7 @@ namespace Ryujinx.Ava.Utilities string titleIdSection = $" ({activeProcess.ProgramIdText.ToUpper()})"; string titleArchSection = activeProcess.Is64Bit ? " (64-bit)" : " (32-bit)"; - string appTitle = customTitlebar + string appTitle = customTitlebar ? $"Ryujinx {applicationVersion}\n{titleNameSection.Trim()}\n{titleVersionSection.Trim()}\n{titleIdSection.Trim()}{titleArchSection}" : $"Ryujinx {applicationVersion} -{titleNameSection}{titleVersionSection}{titleIdSection}{titleArchSection}"; diff --git a/src/Ryujinx/Utilities/ValueFormatUtils.cs b/src/Ryujinx/Utilities/ValueFormatUtils.cs index 535518409..39723f511 100644 --- a/src/Ryujinx/Utilities/ValueFormatUtils.cs +++ b/src/Ryujinx/Utilities/ValueFormatUtils.cs @@ -51,22 +51,22 @@ namespace Ryujinx.Ava.Utilities { if (!timeSpan.HasValue || timeSpan.Value.TotalSeconds < 1) return string.Empty; - + if (timeSpan.Value.TotalSeconds < 60) - return timeSpan.Value.Humanize(1, - countEmptyUnits: false, + return timeSpan.Value.Humanize(1, + countEmptyUnits: false, maxUnit: TimeUnit.Second, minUnit: TimeUnit.Second); if (timeSpan.Value.TotalMinutes < 60) - return timeSpan.Value.Humanize(1, - countEmptyUnits: false, + return timeSpan.Value.Humanize(1, + countEmptyUnits: false, maxUnit: TimeUnit.Minute, minUnit: TimeUnit.Minute); - - return timeSpan.Value.Humanize(1, - countEmptyUnits: false, - maxUnit: TimeUnit.Hour, + + return timeSpan.Value.Humanize(1, + countEmptyUnits: false, + maxUnit: TimeUnit.Hour, minUnit: TimeUnit.Hour); } diff --git a/src/Spv.Generator/Autogenerated/CoreGrammar.cs b/src/Spv.Generator/Autogenerated/CoreGrammar.cs index 9982fdfa8..086e783fb 100644 --- a/src/Spv.Generator/Autogenerated/CoreGrammar.cs +++ b/src/Spv.Generator/Autogenerated/CoreGrammar.cs @@ -85,10 +85,12 @@ namespace Spv.Generator { result.AddOperand(file); } + if (source != null) { result.AddOperand(source); } + AddDebug(result); return result; @@ -414,6 +416,7 @@ namespace Spv.Generator { result.AddOperand(accessQualifier); } + AddTypeDeclaration(result, forceIdAllocation); return result; @@ -696,6 +699,7 @@ namespace Spv.Generator { result.AddOperand(initializer); } + return result; } @@ -720,6 +724,7 @@ namespace Spv.Generator { result.AddOperand(memoryAccess); } + AddToFunctionDefinitions(result); return result; @@ -735,6 +740,7 @@ namespace Spv.Generator { result.AddOperand(memoryAccess); } + AddToFunctionDefinitions(result); return result; @@ -750,10 +756,12 @@ namespace Spv.Generator { result.AddOperand(memoryAccess0); } + if (memoryAccess1 != (MemoryAccessMask)int.MaxValue) { result.AddOperand(memoryAccess1); } + AddToFunctionDefinitions(result); return result; @@ -770,10 +778,12 @@ namespace Spv.Generator { result.AddOperand(memoryAccess0); } + if (memoryAccess1 != (MemoryAccessMask)int.MaxValue) { result.AddOperand(memoryAccess1); } + AddToFunctionDefinitions(result); return result; @@ -984,10 +994,12 @@ namespace Spv.Generator { result.AddOperand(imageOperands); } + if (imageOperands != (ImageOperandsMask)int.MaxValue) { result.AddOperand(imageOperandIds); } + AddToFunctionDefinitions(result); return result; @@ -1004,6 +1016,7 @@ namespace Spv.Generator { result.AddOperand(imageOperandIds); } + AddToFunctionDefinitions(result); return result; @@ -1020,10 +1033,12 @@ namespace Spv.Generator { result.AddOperand(imageOperands); } + if (imageOperands != (ImageOperandsMask)int.MaxValue) { result.AddOperand(imageOperandIds); } + AddToFunctionDefinitions(result); return result; @@ -1041,6 +1056,7 @@ namespace Spv.Generator { result.AddOperand(imageOperandIds); } + AddToFunctionDefinitions(result); return result; @@ -1056,10 +1072,12 @@ namespace Spv.Generator { result.AddOperand(imageOperands); } + if (imageOperands != (ImageOperandsMask)int.MaxValue) { result.AddOperand(imageOperandIds); } + AddToFunctionDefinitions(result); return result; @@ -1076,6 +1094,7 @@ namespace Spv.Generator { result.AddOperand(imageOperandIds); } + AddToFunctionDefinitions(result); return result; @@ -1092,10 +1111,12 @@ namespace Spv.Generator { result.AddOperand(imageOperands); } + if (imageOperands != (ImageOperandsMask)int.MaxValue) { result.AddOperand(imageOperandIds); } + AddToFunctionDefinitions(result); return result; @@ -1113,6 +1134,7 @@ namespace Spv.Generator { result.AddOperand(imageOperandIds); } + AddToFunctionDefinitions(result); return result; @@ -1128,10 +1150,12 @@ namespace Spv.Generator { result.AddOperand(imageOperands); } + if (imageOperands != (ImageOperandsMask)int.MaxValue) { result.AddOperand(imageOperandIds); } + AddToFunctionDefinitions(result); return result; @@ -1148,10 +1172,12 @@ namespace Spv.Generator { result.AddOperand(imageOperands); } + if (imageOperands != (ImageOperandsMask)int.MaxValue) { result.AddOperand(imageOperandIds); } + AddToFunctionDefinitions(result); return result; @@ -1168,10 +1194,12 @@ namespace Spv.Generator { result.AddOperand(imageOperands); } + if (imageOperands != (ImageOperandsMask)int.MaxValue) { result.AddOperand(imageOperandIds); } + AddToFunctionDefinitions(result); return result; @@ -1187,10 +1215,12 @@ namespace Spv.Generator { result.AddOperand(imageOperands); } + if (imageOperands != (ImageOperandsMask)int.MaxValue) { result.AddOperand(imageOperandIds); } + AddToFunctionDefinitions(result); return result; @@ -1207,10 +1237,12 @@ namespace Spv.Generator { result.AddOperand(imageOperands); } + if (imageOperands != (ImageOperandsMask)int.MaxValue) { result.AddOperand(imageOperandIds); } + AddToFunctionDefinitions(result); return result; @@ -1308,10 +1340,12 @@ namespace Spv.Generator { result.AddOperand(imageOperands); } + if (imageOperands != (ImageOperandsMask)int.MaxValue) { result.AddOperand(imageOperandIds); } + AddToFunctionDefinitions(result); return result; @@ -1328,6 +1362,7 @@ namespace Spv.Generator { result.AddOperand(imageOperandIds); } + AddToFunctionDefinitions(result); return result; @@ -1344,10 +1379,12 @@ namespace Spv.Generator { result.AddOperand(imageOperands); } + if (imageOperands != (ImageOperandsMask)int.MaxValue) { result.AddOperand(imageOperandIds); } + AddToFunctionDefinitions(result); return result; @@ -1365,6 +1402,7 @@ namespace Spv.Generator { result.AddOperand(imageOperandIds); } + AddToFunctionDefinitions(result); return result; @@ -1380,10 +1418,12 @@ namespace Spv.Generator { result.AddOperand(imageOperands); } + if (imageOperands != (ImageOperandsMask)int.MaxValue) { result.AddOperand(imageOperandIds); } + AddToFunctionDefinitions(result); return result; @@ -1400,6 +1440,7 @@ namespace Spv.Generator { result.AddOperand(imageOperandIds); } + AddToFunctionDefinitions(result); return result; @@ -1416,10 +1457,12 @@ namespace Spv.Generator { result.AddOperand(imageOperands); } + if (imageOperands != (ImageOperandsMask)int.MaxValue) { result.AddOperand(imageOperandIds); } + AddToFunctionDefinitions(result); return result; @@ -1437,6 +1480,7 @@ namespace Spv.Generator { result.AddOperand(imageOperandIds); } + AddToFunctionDefinitions(result); return result; @@ -1452,10 +1496,12 @@ namespace Spv.Generator { result.AddOperand(imageOperands); } + if (imageOperands != (ImageOperandsMask)int.MaxValue) { result.AddOperand(imageOperandIds); } + AddToFunctionDefinitions(result); return result; @@ -1472,10 +1518,12 @@ namespace Spv.Generator { result.AddOperand(imageOperands); } + if (imageOperands != (ImageOperandsMask)int.MaxValue) { result.AddOperand(imageOperandIds); } + AddToFunctionDefinitions(result); return result; @@ -1492,10 +1540,12 @@ namespace Spv.Generator { result.AddOperand(imageOperands); } + if (imageOperands != (ImageOperandsMask)int.MaxValue) { result.AddOperand(imageOperandIds); } + AddToFunctionDefinitions(result); return result; @@ -1521,10 +1571,12 @@ namespace Spv.Generator { result.AddOperand(imageOperands); } + if (imageOperands != (ImageOperandsMask)int.MaxValue) { result.AddOperand(imageOperandIds); } + AddToFunctionDefinitions(result); return result; @@ -1542,10 +1594,12 @@ namespace Spv.Generator { result.AddOperand(imageOperands); } + if (imageOperands != (ImageOperandsMask)int.MaxValue) { result.AddOperand(imageOperandIds); } + AddToFunctionDefinitions(result); return result; @@ -4302,6 +4356,7 @@ namespace Spv.Generator { result.AddOperand(clusterSize); } + AddToFunctionDefinitions(result); return result; @@ -4318,6 +4373,7 @@ namespace Spv.Generator { result.AddOperand(clusterSize); } + AddToFunctionDefinitions(result); return result; @@ -4334,6 +4390,7 @@ namespace Spv.Generator { result.AddOperand(clusterSize); } + AddToFunctionDefinitions(result); return result; @@ -4350,6 +4407,7 @@ namespace Spv.Generator { result.AddOperand(clusterSize); } + AddToFunctionDefinitions(result); return result; @@ -4366,6 +4424,7 @@ namespace Spv.Generator { result.AddOperand(clusterSize); } + AddToFunctionDefinitions(result); return result; @@ -4382,6 +4441,7 @@ namespace Spv.Generator { result.AddOperand(clusterSize); } + AddToFunctionDefinitions(result); return result; @@ -4398,6 +4458,7 @@ namespace Spv.Generator { result.AddOperand(clusterSize); } + AddToFunctionDefinitions(result); return result; @@ -4414,6 +4475,7 @@ namespace Spv.Generator { result.AddOperand(clusterSize); } + AddToFunctionDefinitions(result); return result; @@ -4430,6 +4492,7 @@ namespace Spv.Generator { result.AddOperand(clusterSize); } + AddToFunctionDefinitions(result); return result; @@ -4446,6 +4509,7 @@ namespace Spv.Generator { result.AddOperand(clusterSize); } + AddToFunctionDefinitions(result); return result; @@ -4462,6 +4526,7 @@ namespace Spv.Generator { result.AddOperand(clusterSize); } + AddToFunctionDefinitions(result); return result; @@ -4478,6 +4543,7 @@ namespace Spv.Generator { result.AddOperand(clusterSize); } + AddToFunctionDefinitions(result); return result; @@ -4494,6 +4560,7 @@ namespace Spv.Generator { result.AddOperand(clusterSize); } + AddToFunctionDefinitions(result); return result; @@ -4510,6 +4577,7 @@ namespace Spv.Generator { result.AddOperand(clusterSize); } + AddToFunctionDefinitions(result); return result; @@ -4526,6 +4594,7 @@ namespace Spv.Generator { result.AddOperand(clusterSize); } + AddToFunctionDefinitions(result); return result; @@ -4542,6 +4611,7 @@ namespace Spv.Generator { result.AddOperand(clusterSize); } + AddToFunctionDefinitions(result); return result; @@ -4877,6 +4947,7 @@ namespace Spv.Generator { result.AddOperand(memoryAccess); } + AddToFunctionDefinitions(result); return result; @@ -4894,6 +4965,7 @@ namespace Spv.Generator { result.AddOperand(memoryAccess); } + AddToFunctionDefinitions(result); return result; @@ -5311,6 +5383,5 @@ namespace Spv.Generator return result; } - } } diff --git a/src/Spv.Generator/Autogenerated/GlslStd450Grammar.cs b/src/Spv.Generator/Autogenerated/GlslStd450Grammar.cs index fa01e94c0..394935f5a 100644 --- a/src/Spv.Generator/Autogenerated/GlslStd450Grammar.cs +++ b/src/Spv.Generator/Autogenerated/GlslStd450Grammar.cs @@ -434,6 +434,5 @@ namespace Spv.Generator { return ExtInst(resultType, AddExtInstImport("GLSL.std.450"), 81, x, minVal, maxVal); } - } } diff --git a/src/Spv.Generator/Autogenerated/OpenClGrammar.cs b/src/Spv.Generator/Autogenerated/OpenClGrammar.cs index 03eb5ccbd..50d548708 100644 --- a/src/Spv.Generator/Autogenerated/OpenClGrammar.cs +++ b/src/Spv.Generator/Autogenerated/OpenClGrammar.cs @@ -836,6 +836,5 @@ namespace Spv.Generator { return ExtInst(resultType, AddExtInstImport("OpenCL.std"), 185, ptr, numelements); } - } } diff --git a/src/Spv.Generator/Module.cs b/src/Spv.Generator/Module.cs index cb63633be..b2cbb254d 100644 --- a/src/Spv.Generator/Module.cs +++ b/src/Spv.Generator/Module.cs @@ -208,11 +208,11 @@ namespace Spv.Generator private void AddConstant(Instruction constant) { - Debug.Assert(constant.Opcode == Op.OpConstant || - constant.Opcode == Op.OpConstantFalse || - constant.Opcode == Op.OpConstantTrue || - constant.Opcode == Op.OpConstantNull || - constant.Opcode == Op.OpConstantComposite); + Debug.Assert(constant.Opcode is Op.OpConstant or + Op.OpConstantFalse or + Op.OpConstantTrue or + Op.OpConstantNull or + Op.OpConstantComposite); ConstantKey key = new(constant); @@ -337,7 +337,7 @@ namespace Spv.Generator declarations.AddRange(_typeDeclarationsList); declarations.AddRange(_globals); declarations.AddRange(_constants.Values); - declarations.Sort((Instruction x, Instruction y) => x.Id.CompareTo(y.Id)); + declarations.Sort((x, y) => x.Id.CompareTo(y.Id)); // 9. foreach (Instruction declaration in declarations) From af2575b40e6a5be038d37b8af95a58268b78a05f Mon Sep 17 00:00:00 2001 From: LotP <22-lotp@users.noreply.git.ryujinx.app> Date: Sun, 1 Jun 2025 01:28:21 -0500 Subject: [PATCH 045/105] Update LibHac See merge request ryubing/ryujinx!45 --- Directory.Packages.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Directory.Packages.props b/Directory.Packages.props index 37dcd292a..68d5b1f27 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -40,7 +40,7 @@ - + From 379e9ab6222c381e14d4d3e6ce27138261d334de Mon Sep 17 00:00:00 2001 From: GreemDev Date: Tue, 3 Jun 2025 04:04:41 -0500 Subject: [PATCH 046/105] stable release test workflow for gitlab releases --- .github/workflows/debug_release.yml | 215 ++++++++++++++++++++++++++++ 1 file changed, 215 insertions(+) create mode 100644 .github/workflows/debug_release.yml diff --git a/.github/workflows/debug_release.yml b/.github/workflows/debug_release.yml new file mode 100644 index 000000000..ce97bec7e --- /dev/null +++ b/.github/workflows/debug_release.yml @@ -0,0 +1,215 @@ +name: Release job (Debug) + +on: + workflow_dispatch: + inputs: {} + +concurrency: release + +env: + POWERSHELL_TELEMETRY_OPTOUT: 1 + DOTNET_CLI_TELEMETRY_OPTOUT: 1 + RYUJINX_BASE_VERSION: "1.3" + RYUJINX_TARGET_RELEASE_CHANNEL_NAME: "release" + RELEASE: 1 + +jobs: + release: + name: Release for ${{ matrix.platform.name }} + runs-on: ${{ matrix.platform.os }} + strategy: + matrix: + platform: + - { name: win-x64, os: windows-latest, zip_os_name: win_x64 } + #- { name: win-arm64, os: windows-latest, zip_os_name: win_arm64 } + - { name: linux-x64, os: ubuntu-latest, zip_os_name: linux_x64 } + - { name: linux-arm64, os: ubuntu-latest, zip_os_name: linux_arm64 } + steps: + - uses: actions/checkout@v4 + + - uses: actions/setup-dotnet@v4 + with: + global-json-file: global.json + + - name: Overwrite csc problem matcher + run: echo "::add-matcher::.github/csc.json" + + - name: Get version info + id: version_info + run: | + echo "build_version=${{ env.RYUJINX_BASE_VERSION }}.$((${{ github.run_number }} + 10))" >> $GITHUB_OUTPUT + echo "prev_build_version=${{ env.RYUJINX_BASE_VERSION }}.$((${{ github.run_number }} - 1))" >> $GITHUB_OUTPUT + echo "git_short_hash=$(git rev-parse --short "${{ github.sha }}")" >> $GITHUB_OUTPUT + shell: bash + + - name: Configure for release + run: | + sed -r --in-place 's/\%\%RYUJINX_BUILD_VERSION\%\%/${{ steps.version_info.outputs.build_version }}/g;' src/Ryujinx.Common/ReleaseInformation.cs + sed -r --in-place 's/\%\%RYUJINX_BUILD_GIT_HASH\%\%/${{ steps.version_info.outputs.git_short_hash }}/g;' src/Ryujinx.Common/ReleaseInformation.cs + sed -r --in-place 's/\%\%RYUJINX_TARGET_RELEASE_CHANNEL_NAME\%\%/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_NAME }}/g;' src/Ryujinx.Common/ReleaseInformation.cs + sed -r --in-place 's/\%\%RYUJINX_CONFIG_FILE_NAME\%\%/Config\.json/g;' src/Ryujinx.Common/ReleaseInformation.cs + shell: bash + + - name: Create output dir + run: "mkdir release_output" + + - name: Publish + run: | + dotnet publish -c Release -r "${{ matrix.platform.name }}" -o ./publish -p:Version="${{ steps.version_info.outputs.build_version }}" -p:SourceRevisionId="${{ steps.version_info.outputs.git_short_hash }}" -p:DebugType=embedded src/Ryujinx --self-contained + + - name: Packing Windows builds + if: matrix.platform.os == 'windows-latest' + run: | + pushd publish + rm libarmeilleure-jitsupport.dylib + 7z a ../release_output/ryujinx-${{ steps.version_info.outputs.build_version }}-${{ matrix.platform.zip_os_name }}.zip ../publish + popd + + gh release download -R GreemDev/GLI -O gli.exe -p 'GitLabCli-win_x64.exe' + + ./gli.exe --access-token=${{ secrets.GITLAB_TOKEN }} --project=ryubing/ryujinx --command=UploadGenericPackage "ryubing|${{ steps.version_info.outputs.build_version }}|release_output/ryujinx-${{ steps.version_info.outputs.build_version }}-${{ matrix.platform.zip_os_name }}.zip" + shell: bash + + - name: Packing Linux builds + if: matrix.platform.os == 'ubuntu-latest' + run: | + pushd publish + rm libarmeilleure-jitsupport.dylib + chmod +x Ryujinx.sh Ryujinx + tar -czvf ../release_output/ryujinx-${{ steps.version_info.outputs.build_version }}-${{ matrix.platform.zip_os_name }}.tar.gz ../publish + popd + + 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 + + gli --access-token=${{ secrets.GITLAB_TOKEN }} --project=ryubing/ryujinx --command=UploadGenericPackage "ryubing|${{ steps.version_info.outputs.build_version }}|release_output/ryujinx-${{ steps.version_info.outputs.build_version }}-${{ matrix.platform.zip_os_name }}.tar.gz" + shell: bash + + - name: Build AppImage (Linux) + if: matrix.platform.os == 'ubuntu-latest' + run: | + BUILD_VERSION="${{ steps.version_info.outputs.build_version }}" + PLATFORM_NAME="${{ matrix.platform.name }}" + + sudo apt install -y zsync desktop-file-utils appstream + + mkdir -p tools + export PATH="$PATH:$(readlink -f tools)" + + # Setup appimagetool + wget -q -O tools/appimagetool "https://github.com/AppImage/appimagetool/releases/download/continuous/appimagetool-x86_64.AppImage" + chmod +x tools/appimagetool + chmod +x distribution/linux/appimage/build-appimage.sh + + # Explicitly set $ARCH for appimagetool ($ARCH_NAME is for the file name) + if [ "$PLATFORM_NAME" = "linux-x64" ]; then + ARCH_NAME=x64 + export ARCH=x86_64 + elif [ "$PLATFORM_NAME" = "linux-arm64" ]; then + ARCH_NAME=arm64 + export ARCH=aarch64 + else + echo "Unexpected PLATFORM_NAME "$PLATFORM_NAME"" + exit 1 + fi + + export UFLAG="gh-releases-zsync|${{ github.repository_owner }}|${{ github.event.repository.name }}|latest|*-$ARCH_NAME.AppImage.zsync" + BUILDDIR=publish OUTDIR=publish_appimage distribution/linux/appimage/build-appimage.sh + + pushd publish_appimage + mv Ryujinx.AppImage ../release_output/ryujinx-$BUILD_VERSION-$ARCH_NAME.AppImage + mv Ryujinx.AppImage.zsync ../release_output/ryujinx-$BUILD_VERSION-$ARCH_NAME.AppImage.zsync + popd + + gli --access-token=${{ secrets.GITLAB_TOKEN }} --project=ryubing/ryujinx --command=UploadGenericPackage "ryubing|${{ steps.version_info.outputs.build_version }}|release_output/ryujinx-$BUILD_VERSION-$ARCH_NAME.AppImage" + gli --access-token=${{ secrets.GITLAB_TOKEN }} --project=ryubing/ryujinx --command=UploadGenericPackage "ryubing|${{ steps.version_info.outputs.build_version }}|release_output/ryujinx-$BUILD_VERSION-$ARCH_NAME.AppImage.zsync" + shell: bash + + macos_release: + name: Release MacOS universal + runs-on: ubuntu-24.04 + steps: + - uses: actions/checkout@v4 + + - uses: actions/setup-dotnet@v4 + with: + global-json-file: global.json + + - name: Setup LLVM 17 + run: | + wget https://apt.llvm.org/llvm.sh + chmod +x llvm.sh + sudo ./llvm.sh 17 + + - 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: Install rcodesign + run: | + mkdir -p $HOME/.bin + gh release download -R indygreg/apple-platform-rs -O apple-codesign.tar.gz -p 'apple-codesign-*-x86_64-unknown-linux-musl.tar.gz' + tar -xzvf apple-codesign.tar.gz --wildcards '*/rcodesign' --strip-components=1 + rm apple-codesign.tar.gz + mv rcodesign $HOME/.bin/ + echo "$HOME/.bin" >> $GITHUB_PATH + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Get version info + id: version_info + run: | + echo "build_version=${{ env.RYUJINX_BASE_VERSION }}.$((${{ github.run_number }} + 10))" >> $GITHUB_OUTPUT + echo "prev_build_version=${{ env.RYUJINX_BASE_VERSION }}.$((${{ github.run_number }} - 1))" >> $GITHUB_OUTPUT + echo "git_short_hash=$(git rev-parse --short "${{ github.sha }}")" >> $GITHUB_OUTPUT + + - name: Configure for release + run: | + sed -r --in-place 's/\%\%RYUJINX_BUILD_VERSION\%\%/${{ steps.version_info.outputs.build_version }}/g;' src/Ryujinx.Common/ReleaseInformation.cs + sed -r --in-place 's/\%\%RYUJINX_BUILD_GIT_HASH\%\%/${{ steps.version_info.outputs.git_short_hash }}/g;' src/Ryujinx.Common/ReleaseInformation.cs + sed -r --in-place 's/\%\%RYUJINX_TARGET_RELEASE_CHANNEL_NAME\%\%/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_NAME }}/g;' src/Ryujinx.Common/ReleaseInformation.cs + sed -r --in-place 's/\%\%RYUJINX_CONFIG_FILE_NAME\%\%/Config\.json/g;' src/Ryujinx.Common/ReleaseInformation.cs + shell: bash + + - name: Publish macOS Ryujinx + run: | + ./distribution/macos/create_macos_build_ava.sh . publish_tmp_ava publish ./distribution/macos/entitlements.xml "${{ steps.version_info.outputs.build_version }}" "${{ steps.version_info.outputs.git_short_hash }}" Release 0 + gli --access-token=${{ secrets.GITLAB_TOKEN }} --project=ryubing/ryujinx --command=UploadGenericPackage "ryubing|${{ steps.version_info.outputs.build_version }}|publish_ava/ryujinx-${{ steps.version_info.outputs.build_version }}-macos_universal.app.tar.gz" + + create_gitlab_release: + name: Create GitLab Release + runs-on: ubuntu-24.04 + needs: + - macos_release + - release + steps: + - name: Get version info + id: version_info + run: | + echo "build_version=${{ env.RYUJINX_BASE_VERSION }}.$((${{ github.run_number }} + 10))" >> $GITHUB_OUTPUT + echo "prev_build_version=${{ env.RYUJINX_BASE_VERSION }}.$((${{ github.run_number }} - 1))" >> $GITHUB_OUTPUT + echo "git_short_hash=$(git rev-parse --short "${{ github.sha }}")" >> $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 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 }}|test|THIS IS NOT INTENDED FOR END USER USAGE" From 8f5102aa2a3599c16824c9e50738fd0ab4bd2e66 Mon Sep 17 00:00:00 2001 From: GreemDev Date: Tue, 3 Jun 2025 18:28:59 -0500 Subject: [PATCH 047/105] infra: Add functionality to the CI to upload artifacts to this GitLab and make releases based on all files uploaded. See merge request ryubing/ryujinx!48 --- .github/workflows/canary.yml | 79 +++++++- .github/workflows/debug_release.yml | 33 +-- .github/workflows/release.yml | 82 ++++++-- src/Ryujinx.Common/ReleaseInformation.cs | 52 +---- .../GitLab/GitLabReleaseAssetJsonResponse.cs | 20 ++ .../GitLab/GitLabReleasesJsonResponse.cs | 19 ++ src/Ryujinx/Systems/Updater/Updater.GitHub.cs | 190 ++++++++++++++++++ src/Ryujinx/Systems/Updater/Updater.GitLab.cs | 138 +++++++++++++ src/Ryujinx/Systems/{ => Updater}/Updater.cs | 139 +++---------- src/Ryujinx/UI/Windows/MainWindow.axaml.cs | 2 +- 10 files changed, 558 insertions(+), 196 deletions(-) create mode 100644 src/Ryujinx/Common/Models/GitLab/GitLabReleaseAssetJsonResponse.cs create mode 100644 src/Ryujinx/Common/Models/GitLab/GitLabReleasesJsonResponse.cs create mode 100644 src/Ryujinx/Systems/Updater/Updater.GitHub.cs create mode 100644 src/Ryujinx/Systems/Updater/Updater.GitLab.cs rename src/Ryujinx/Systems/{ => Updater}/Updater.cs (83%) diff --git a/.github/workflows/canary.yml b/.github/workflows/canary.yml index de3dd6892..b0678724a 100644 --- a/.github/workflows/canary.yml +++ b/.github/workflows/canary.yml @@ -79,7 +79,7 @@ jobs: matrix: platform: - { name: win-x64, os: windows-latest, zip_os_name: win_x64 } - - { name: win-arm64, os: windows-latest, zip_os_name: win_arm64 } + #- { name: win-arm64, os: windows-latest, zip_os_name: win_arm64 } - { name: linux-x64, os: ubuntu-latest, zip_os_name: linux_x64 } - { name: linux-arm64, os: ubuntu-latest, zip_os_name: linux_arm64 } steps: @@ -91,6 +91,16 @@ 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 @@ -106,7 +116,7 @@ jobs: sed -r --in-place 's/\%\%RYUJINX_BUILD_GIT_HASH\%\%/${{ steps.version_info.outputs.git_short_hash }}/g;' src/Ryujinx.Common/ReleaseInformation.cs sed -r --in-place 's/\%\%RYUJINX_TARGET_RELEASE_CHANNEL_NAME\%\%/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_NAME }}/g;' src/Ryujinx.Common/ReleaseInformation.cs sed -r --in-place 's/\%\%RYUJINX_CONFIG_FILE_NAME\%\%/Config\.json/g;' src/Ryujinx.Common/ReleaseInformation.cs - sed -r --in-place '/^Name=Ryujinx$/s/Name=Ryujinx/Name=Ryujinx-Canary/' distribution/linux/Ryujinx.desktop + sed -r --in-place '/^Name=Ryujinx$/s/Name=Ryujinx/Name=Ryujinx-Canary/' distribution/linux/Ryujinx.desktop shell: bash - name: Create output dir @@ -123,7 +133,24 @@ jobs: rm libarmeilleure-jitsupport.dylib 7z a ../release_output/ryujinx-canary-${{ steps.version_info.outputs.build_version }}-${{ matrix.platform.zip_os_name }}.zip ../publish popd + + gh release download -R GreemDev/GLI -O gli.exe -p 'GitLabCli-win_x64.exe' + + ./gli.exe --access-token=${{ secrets.GITLAB_TOKEN }} --project=ryubing/canary --command=UploadGenericPackage "Ryubing-Canary|${{ steps.version_info.outputs.build_version }}|release_output/ryujinx-canary-${{ steps.version_info.outputs.build_version }}-${{ matrix.platform.zip_os_name }}.zip" shell: bash + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Install GitLabCli + if: matrix.platform.os == 'ubuntu-latest' + 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: Packing Linux builds if: matrix.platform.os == 'ubuntu-latest' @@ -133,6 +160,8 @@ jobs: chmod +x Ryujinx.sh Ryujinx tar -czvf ../release_output/ryujinx-canary-${{ steps.version_info.outputs.build_version }}-${{ matrix.platform.zip_os_name }}.tar.gz ../publish popd + + gli --access-token=${{ secrets.GITLAB_TOKEN }} --project=ryubing/canary --command=UploadGenericPackage "Ryubing-Canary|${{ steps.version_info.outputs.build_version }}|release_output/ryujinx-canary-${{ steps.version_info.outputs.build_version }}-${{ matrix.platform.zip_os_name }}.tar.gz" shell: bash - name: Build AppImage (Linux) @@ -169,7 +198,10 @@ jobs: pushd publish_appimage mv Ryujinx.AppImage ../release_output/ryujinx-canary-$BUILD_VERSION-$ARCH_NAME.AppImage mv Ryujinx.AppImage.zsync ../release_output/ryujinx-canary-$BUILD_VERSION-$ARCH_NAME.AppImage.zsync - popd + popd + + 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 @@ -214,6 +246,16 @@ jobs: wget https://apt.llvm.org/llvm.sh chmod +x llvm.sh sudo ./llvm.sh 17 + + - 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: Install rcodesign run: | @@ -246,6 +288,7 @@ jobs: - name: Publish macOS Ryujinx run: | ./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 @@ -260,3 +303,33 @@ jobs: 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: + - 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 + echo "git_short_hash=$(git rev-parse --short "${{ github.sha }}")" >> $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 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 }})**" diff --git a/.github/workflows/debug_release.yml b/.github/workflows/debug_release.yml index ce97bec7e..b166adb61 100644 --- a/.github/workflows/debug_release.yml +++ b/.github/workflows/debug_release.yml @@ -67,8 +67,21 @@ jobs: gh release download -R GreemDev/GLI -O gli.exe -p 'GitLabCli-win_x64.exe' - ./gli.exe --access-token=${{ secrets.GITLAB_TOKEN }} --project=ryubing/ryujinx --command=UploadGenericPackage "ryubing|${{ steps.version_info.outputs.build_version }}|release_output/ryujinx-${{ steps.version_info.outputs.build_version }}-${{ matrix.platform.zip_os_name }}.zip" + ./gli.exe --access-token=${{ secrets.GITLAB_TOKEN }} --project=ryubing/ryujinx --command=UploadGenericPackage "Ryubing|${{ steps.version_info.outputs.build_version }}|release_output/ryujinx-${{ steps.version_info.outputs.build_version }}-${{ matrix.platform.zip_os_name }}.zip" shell: bash + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Install GitLabCli + if: matrix.platform.os == 'ubuntu-latest' + 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: Packing Linux builds if: matrix.platform.os == 'ubuntu-latest' @@ -79,13 +92,7 @@ jobs: tar -czvf ../release_output/ryujinx-${{ steps.version_info.outputs.build_version }}-${{ matrix.platform.zip_os_name }}.tar.gz ../publish popd - 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 - - gli --access-token=${{ secrets.GITLAB_TOKEN }} --project=ryubing/ryujinx --command=UploadGenericPackage "ryubing|${{ steps.version_info.outputs.build_version }}|release_output/ryujinx-${{ steps.version_info.outputs.build_version }}-${{ matrix.platform.zip_os_name }}.tar.gz" + gli --access-token=${{ secrets.GITLAB_TOKEN }} --project=ryubing/ryujinx --command=UploadGenericPackage "Ryubing|${{ steps.version_info.outputs.build_version }}|release_output/ryujinx-${{ steps.version_info.outputs.build_version }}-${{ matrix.platform.zip_os_name }}.tar.gz" shell: bash - name: Build AppImage (Linux) @@ -124,8 +131,8 @@ jobs: mv Ryujinx.AppImage.zsync ../release_output/ryujinx-$BUILD_VERSION-$ARCH_NAME.AppImage.zsync popd - gli --access-token=${{ secrets.GITLAB_TOKEN }} --project=ryubing/ryujinx --command=UploadGenericPackage "ryubing|${{ steps.version_info.outputs.build_version }}|release_output/ryujinx-$BUILD_VERSION-$ARCH_NAME.AppImage" - gli --access-token=${{ secrets.GITLAB_TOKEN }} --project=ryubing/ryujinx --command=UploadGenericPackage "ryubing|${{ steps.version_info.outputs.build_version }}|release_output/ryujinx-$BUILD_VERSION-$ARCH_NAME.AppImage.zsync" + gli --access-token=${{ secrets.GITLAB_TOKEN }} --project=ryubing/ryujinx --command=UploadGenericPackage "Ryubing|${{ steps.version_info.outputs.build_version }}|release_output/ryujinx-$BUILD_VERSION-$ARCH_NAME.AppImage" + gli --access-token=${{ secrets.GITLAB_TOKEN }} --project=ryubing/ryujinx --command=UploadGenericPackage "Ryubing|${{ steps.version_info.outputs.build_version }}|release_output/ryujinx-$BUILD_VERSION-$ARCH_NAME.AppImage.zsync" shell: bash macos_release: @@ -183,7 +190,7 @@ jobs: - name: Publish macOS Ryujinx run: | ./distribution/macos/create_macos_build_ava.sh . publish_tmp_ava publish ./distribution/macos/entitlements.xml "${{ steps.version_info.outputs.build_version }}" "${{ steps.version_info.outputs.git_short_hash }}" Release 0 - gli --access-token=${{ secrets.GITLAB_TOKEN }} --project=ryubing/ryujinx --command=UploadGenericPackage "ryubing|${{ steps.version_info.outputs.build_version }}|publish_ava/ryujinx-${{ steps.version_info.outputs.build_version }}-macos_universal.app.tar.gz" + gli --access-token=${{ secrets.GITLAB_TOKEN }} --project=ryubing/ryujinx --command=UploadGenericPackage "Ryubing|${{ steps.version_info.outputs.build_version }}|publish/ryujinx-${{ steps.version_info.outputs.build_version }}-macos_universal.app.tar.gz" create_gitlab_release: name: Create GitLab Release @@ -192,6 +199,8 @@ jobs: - macos_release - release steps: + - uses: actions/checkout@v4 + - name: Get version info id: version_info run: | @@ -212,4 +221,4 @@ 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 }}|test|THIS IS NOT INTENDED FOR END USER USAGE" + 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 }}|test|THIS IS NOT INTENDED FOR END USER USAGE" diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 85c494dcb..4c443b969 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -24,19 +24,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 "${{ steps.version_info.outputs.build_version }}|master" - name: Create release uses: ncipollo/release-action@v1 @@ -66,7 +53,7 @@ jobs: matrix: platform: - { name: win-x64, os: windows-latest, zip_os_name: win_x64 } - - { name: win-arm64, os: windows-latest, zip_os_name: win_arm64 } + #- { name: win-arm64, os: windows-latest, zip_os_name: win_arm64 } - { name: linux-x64, os: ubuntu-latest, zip_os_name: linux_x64 } - { name: linux-arm64, os: ubuntu-latest, zip_os_name: linux_arm64 } steps: @@ -109,7 +96,24 @@ jobs: rm libarmeilleure-jitsupport.dylib 7z a ../release_output/ryujinx-${{ steps.version_info.outputs.build_version }}-${{ matrix.platform.zip_os_name }}.zip ../publish popd + + gh release download -R GreemDev/GLI -O gli.exe -p 'GitLabCli-win_x64.exe' + + ./gli.exe --access-token=${{ secrets.GITLAB_TOKEN }} --project=ryubing/ryujinx --command=UploadGenericPackage "Ryubing|${{ steps.version_info.outputs.build_version }}|release_output/ryujinx-${{ steps.version_info.outputs.build_version }}-${{ matrix.platform.zip_os_name }}.zip" shell: bash + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Install GitLabCli + if: matrix.platform.os == 'ubuntu-latest' + 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: Packing Linux builds if: matrix.platform.os == 'ubuntu-latest' @@ -119,7 +123,11 @@ jobs: chmod +x Ryujinx.sh Ryujinx tar -czvf ../release_output/ryujinx-${{ steps.version_info.outputs.build_version }}-${{ matrix.platform.zip_os_name }}.tar.gz ../publish popd + + gli --access-token=${{ secrets.GITLAB_TOKEN }} --project=ryubing/ryujinx --command=UploadGenericPackage "Ryubing|${{ steps.version_info.outputs.build_version }}|release_output/ryujinx-${{ steps.version_info.outputs.build_version }}-${{ matrix.platform.zip_os_name }}.tar.gz" shell: bash + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - name: Build AppImage (Linux) if: matrix.platform.os == 'ubuntu-latest' @@ -156,6 +164,9 @@ jobs: mv Ryujinx.AppImage ../release_output/ryujinx-$BUILD_VERSION-$ARCH_NAME.AppImage mv Ryujinx.AppImage.zsync ../release_output/ryujinx-$BUILD_VERSION-$ARCH_NAME.AppImage.zsync popd + + gli --access-token=${{ secrets.GITLAB_TOKEN }} --project=ryubing/ryujinx --command=UploadGenericPackage "Ryubing|${{ steps.version_info.outputs.build_version }}|release_output/ryujinx-$BUILD_VERSION-$ARCH_NAME.AppImage" + gli --access-token=${{ secrets.GITLAB_TOKEN }} --project=ryubing/ryujinx --command=UploadGenericPackage "Ryubing|${{ steps.version_info.outputs.build_version }}|release_output/ryujinx-$BUILD_VERSION-$ARCH_NAME.AppImage.zsync" shell: bash - name: Pushing new release @@ -197,6 +208,16 @@ jobs: wget https://apt.llvm.org/llvm.sh chmod +x llvm.sh sudo ./llvm.sh 17 + + - 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: Install rcodesign run: | @@ -227,6 +248,7 @@ jobs: - name: Publish macOS Ryujinx run: | ./distribution/macos/create_macos_build_ava.sh . publish_tmp_ava publish ./distribution/macos/entitlements.xml "${{ steps.version_info.outputs.build_version }}" "${{ steps.version_info.outputs.git_short_hash }}" Release 0 + gli --access-token=${{ secrets.GITLAB_TOKEN }} --project=ryubing/ryujinx --command=UploadGenericPackage "Ryubing|${{ steps.version_info.outputs.build_version }}|publish/ryujinx-${{ steps.version_info.outputs.build_version }}-macos_universal.app.tar.gz" - name: Pushing new release uses: ncipollo/release-action@v1 @@ -241,3 +263,35 @@ jobs: owner: ${{ secrets.RC_OWNER }} repo: ${{ secrets.RC_STABLE_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: | + 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 + echo "git_short_hash=$(git rev-parse --short "${{ github.sha }}")" >> $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 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 }})**" diff --git a/src/Ryujinx.Common/ReleaseInformation.cs b/src/Ryujinx.Common/ReleaseInformation.cs index 66971364c..a5beb1009 100644 --- a/src/Ryujinx.Common/ReleaseInformation.cs +++ b/src/Ryujinx.Common/ReleaseInformation.cs @@ -32,59 +32,11 @@ namespace Ryujinx.Common public static string Version => IsValid ? BuildVersion : Assembly.GetEntryAssembly()!.GetCustomAttribute()?.InformationalVersion; - public static string GetChangelogUrl(Version currentVersion, Version newVersion, ReleaseChannels.Channel releaseChannel) => + public static string GetChangelogUrl(Version currentVersion, Version newVersion) => IsCanaryBuild ? $"https://git.ryujinx.app/ryubing/ryujinx/-/compare/Canary-{currentVersion}...Canary-{newVersion}" - : GetChangelogForVersion(newVersion, releaseChannel); - - public static string GetChangelogForVersion(Version version, ReleaseChannels.Channel releaseChannel) => - $"https://github.com/{releaseChannel}/releases/{version}"; - - public static async Task GetReleaseChannelsAsync(HttpClient httpClient) - { - ReleaseChannelPair releaseChannelPair = await httpClient.GetFromJsonAsync("https://ryujinx.app/api/release-channels", ReleaseChannelPairContext.Default.ReleaseChannelPair); - return new ReleaseChannels(releaseChannelPair); - } + : $"https://git.ryujinx.app/ryubing/ryujinx/-/releases/{newVersion}"; } - public readonly struct ReleaseChannels - { - internal ReleaseChannels(ReleaseChannelPair channelPair) - { - Stable = new Channel(channelPair.Stable); - Canary = new Channel(channelPair.Canary); - } - public readonly Channel Stable; - public readonly Channel Canary; - - public readonly struct Channel - { - public Channel(string raw) - { - string[] parts = raw.Split('/'); - Owner = parts[0]; - Repo = parts[1]; - } - - public readonly string Owner; - public readonly string Repo; - - public override string ToString() => $"{Owner}/{Repo}"; - - public string GetLatestReleaseApiUrl() => - $"https://api.github.com/repos/{ToString()}/releases/latest"; - } - } - - [JsonSerializable(typeof(ReleaseChannelPair))] - partial class ReleaseChannelPairContext : JsonSerializerContext; - - class ReleaseChannelPair - { - [JsonPropertyName("stable")] - public string Stable { get; set; } - [JsonPropertyName("canary")] - public string Canary { get; set; } - } } diff --git a/src/Ryujinx/Common/Models/GitLab/GitLabReleaseAssetJsonResponse.cs b/src/Ryujinx/Common/Models/GitLab/GitLabReleaseAssetJsonResponse.cs new file mode 100644 index 000000000..a5b4bb619 --- /dev/null +++ b/src/Ryujinx/Common/Models/GitLab/GitLabReleaseAssetJsonResponse.cs @@ -0,0 +1,20 @@ +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 new file mode 100644 index 000000000..8d229a5f1 --- /dev/null +++ b/src/Ryujinx/Common/Models/GitLab/GitLabReleasesJsonResponse.cs @@ -0,0 +1,19 @@ +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.GitHub.cs b/src/Ryujinx/Systems/Updater/Updater.GitHub.cs new file mode 100644 index 000000000..9d67e5351 --- /dev/null +++ b/src/Ryujinx/Systems/Updater/Updater.GitHub.cs @@ -0,0 +1,190 @@ +using Gommon; +using Ryujinx.Ava.Common.Locale; +using Ryujinx.Ava.Common.Models.Github; +using Ryujinx.Ava.UI.Helpers; +using Ryujinx.Common; +using Ryujinx.Common.Helper; +using Ryujinx.Common.Logging; +using Ryujinx.Common.Utilities; +using System; +using System.Net.Http; +using System.Net.Http.Json; +using System.Text.Json.Serialization; +using System.Threading.Tasks; + +namespace Ryujinx.Ava.Systems +{ + internal static partial class Updater + { + private static GitHubReleaseChannels.Channel? _currentGitHubReleaseChannel; + + private static async Task> CheckGitHubVersionAsync(bool showVersionUpToDate = false) + { + if (!Version.TryParse(Program.Version, out Version currentVersion)) + { + Logger.Error?.Print(LogClass.Application, $"Failed to convert the current {RyujinxApp.FullAppName} version!"); + + await ContentDialogHelper.CreateWarningDialog( + LocaleManager.Instance[LocaleKeys.DialogUpdaterConvertFailedMessage], + LocaleManager.Instance[LocaleKeys.DialogUpdaterCancelUpdateMessage]); + + _running = false; + + return default; + } + + Logger.Info?.Print(LogClass.Application, "Checking for updates from GitHub."); + + // Get latest version number from GitHub API + try + { + using HttpClient jsonClient = ConstructHttpClient(); + + if (_currentGitHubReleaseChannel == null) + { + GitHubReleaseChannels releaseChannels = await GitHubReleaseChannels.GetAsync(jsonClient); + + _currentGitHubReleaseChannel = ReleaseInformation.IsCanaryBuild + ? releaseChannels.Canary + : releaseChannels.Stable; + + Logger.Info?.Print(LogClass.Application, $"Loaded GitHub release channel for '{(ReleaseInformation.IsCanaryBuild ? "canary" : "stable")}'"); + + _changelogUrlFormat = _currentGitHubReleaseChannel.Value.UrlFormat; + } + + string fetchedJson = await jsonClient.GetStringAsync(_currentGitHubReleaseChannel.Value.GetLatestReleaseApiUrl()); + GithubReleasesJsonResponse fetched = JsonHelper.Deserialize(fetchedJson, _ghSerializerContext.GithubReleasesJsonResponse); + _buildVer = fetched.TagName; + + foreach (GithubReleaseAssetJsonResponse asset in fetched.Assets) + { + if (asset.Name.StartsWith("ryujinx") && asset.Name.EndsWith(_platformExt)) + { + _buildUrl = asset.BrowserDownloadUrl; + + if (asset.State != "uploaded") + { + if (showVersionUpToDate) + { + UserResult userResult = await ContentDialogHelper.CreateUpdaterUpToDateInfoDialog( + LocaleManager.Instance[LocaleKeys.DialogUpdaterAlreadyOnLatestVersionMessage], + string.Empty); + + if (userResult is UserResult.Ok) + { + OpenHelper.OpenUrl(_changelogUrlFormat.Format(currentVersion)); + } + } + + Logger.Info?.Print(LogClass.Application, "Up to date."); + + _running = false; + + return default; + } + + break; + } + } + + // If build not done, assume no new update are available. + if (_buildUrl is null) + { + if (showVersionUpToDate) + { + UserResult userResult = await ContentDialogHelper.CreateUpdaterUpToDateInfoDialog( + LocaleManager.Instance[LocaleKeys.DialogUpdaterAlreadyOnLatestVersionMessage], + string.Empty); + + if (userResult is UserResult.Ok) + { + OpenHelper.OpenUrl(_changelogUrlFormat.Format(currentVersion)); + } + } + + Logger.Info?.Print(LogClass.Application, "Up to date."); + + _running = false; + + return default; + } + } + catch (Exception exception) + { + Logger.Error?.Print(LogClass.Application, exception.Message); + + await ContentDialogHelper.CreateErrorDialog( + LocaleManager.Instance[LocaleKeys.DialogUpdaterFailedToGetVersionMessage]); + + _running = false; + + return default; + } + + if (!Version.TryParse(_buildVer, out Version newVersion)) + { + Logger.Error?.Print(LogClass.Application, $"Failed to convert the received {RyujinxApp.FullAppName} version from GitHub!"); + + await ContentDialogHelper.CreateWarningDialog( + LocaleManager.Instance[LocaleKeys.DialogUpdaterConvertFailedGithubMessage], + LocaleManager.Instance[LocaleKeys.DialogUpdaterCancelUpdateMessage]); + + _running = false; + + return default; + } + + return (currentVersion, newVersion); + } + } + + public readonly struct GitHubReleaseChannels + { + public static async Task GetAsync(HttpClient httpClient) + { + ReleaseChannelPair releaseChannelPair = await httpClient.GetFromJsonAsync("https://ryujinx.app/api/release-channels", ReleaseChannelPairContext.Default.ReleaseChannelPair); + return new GitHubReleaseChannels(releaseChannelPair); + } + + internal GitHubReleaseChannels(ReleaseChannelPair channelPair) + { + Stable = new Channel(channelPair.Stable); + Canary = new Channel(channelPair.Canary); + } + + public readonly Channel Stable; + public readonly Channel Canary; + + public readonly struct Channel + { + public Channel(string raw) + { + string[] parts = raw.Split('/'); + Owner = parts[0]; + Repo = parts[1]; + } + + public readonly string Owner; + public readonly string Repo; + + public string UrlFormat => $"https://github.com/{ToString()}/releases/{{0}}"; + + public override string ToString() => $"{Owner}/{Repo}"; + + public string GetLatestReleaseApiUrl() => + $"https://api.github.com/repos/{ToString()}/releases/latest"; + } + } + + [JsonSerializable(typeof(ReleaseChannelPair))] + partial class ReleaseChannelPairContext : JsonSerializerContext; + + class ReleaseChannelPair + { + [JsonPropertyName("stable")] + public string Stable { get; set; } + [JsonPropertyName("canary")] + public string Canary { get; set; } + } +} diff --git a/src/Ryujinx/Systems/Updater/Updater.GitLab.cs b/src/Ryujinx/Systems/Updater/Updater.GitLab.cs new file mode 100644 index 000000000..6e5e914e0 --- /dev/null +++ b/src/Ryujinx/Systems/Updater/Updater.GitLab.cs @@ -0,0 +1,138 @@ +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.Text.Json.Serialization; +using System.Threading.Tasks; + +namespace Ryujinx.Ava.Systems +{ + internal static partial class Updater + { + private static GitLabReleaseChannels.ChannelType _currentGitLabReleaseChannel; + + private static async Task> CheckGitLabVersionAsync(bool showVersionUpToDate = false) + { + if (!Version.TryParse(Program.Version, out Version currentVersion)) + { + Logger.Error?.Print(LogClass.Application, + $"Failed to convert the current {RyujinxApp.FullAppName} version!"); + + await ContentDialogHelper.CreateWarningDialog( + LocaleManager.Instance[LocaleKeys.DialogUpdaterConvertFailedMessage], + LocaleManager.Instance[LocaleKeys.DialogUpdaterCancelUpdateMessage]); + + _running = false; + + return default; + } + + Logger.Info?.Print(LogClass.Application, "Checking for updates from https://git.ryujinx.app."); + + // 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); + + if (_currentGitLabReleaseChannel == null) + { + GitLabReleaseChannels releaseChannels = await GitLabReleaseChannels.GetAsync(jsonClient); + + _currentGitLabReleaseChannel = ReleaseInformation.IsCanaryBuild + ? releaseChannels.Canary + : releaseChannels.Stable; + + Logger.Info?.Print(LogClass.Application, $"Loaded GitLab release channel for '{(ReleaseInformation.IsCanaryBuild ? "canary" : "stable")}'"); + + _changelogUrlFormat = _currentGitLabReleaseChannel.UrlFormat; + } + + 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 are available. + if (_buildUrl is null) + { + if (showVersionUpToDate) + { + UserResult userResult = await ContentDialogHelper.CreateUpdaterUpToDateInfoDialog( + LocaleManager.Instance[LocaleKeys.DialogUpdaterAlreadyOnLatestVersionMessage], + string.Empty); + + if (userResult is UserResult.Ok) + { + OpenHelper.OpenUrl(_changelogUrlFormat.Format(currentVersion)); + } + } + + Logger.Info?.Print(LogClass.Application, "Up to date."); + + _running = false; + + return default; + } + + + if (!Version.TryParse(_buildVer, out Version newVersion)) + { + Logger.Error?.Print(LogClass.Application, + $"Failed to convert the received {RyujinxApp.FullAppName} version from GitLab!"); + + await ContentDialogHelper.CreateWarningDialog( + LocaleManager.Instance[LocaleKeys.DialogUpdaterConvertFailedGithubMessage], + LocaleManager.Instance[LocaleKeys.DialogUpdaterCancelUpdateMessage]); + + _running = false; + + return default; + } + + return (currentVersion, newVersion); + } + + [JsonSerializable(typeof(GitLabReleaseChannels))] + partial class GitLabReleaseChannelPairContext : JsonSerializerContext; + + public class GitLabReleaseChannels + { + 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("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/{Id}/releases/permalink/latest"; + } + } + } +} diff --git a/src/Ryujinx/Systems/Updater.cs b/src/Ryujinx/Systems/Updater/Updater.cs similarity index 83% rename from src/Ryujinx/Systems/Updater.cs rename to src/Ryujinx/Systems/Updater/Updater.cs index b74b6eaa8..c4e8a8cc6 100644 --- a/src/Ryujinx/Systems/Updater.cs +++ b/src/Ryujinx/Systems/Updater/Updater.cs @@ -6,6 +6,7 @@ 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; @@ -29,13 +30,11 @@ using System.Threading.Tasks; namespace Ryujinx.Ava.Systems { - internal static class Updater + internal static partial class Updater { - private static ReleaseChannels.Channel? _currentReleaseChannel; - - private const string GitHubApiUrl = "https://api.github.com"; - - private static readonly GithubReleasesJsonSerializerContext _serializerContext = new(JsonHelper.GetDefaultSerializerOptions()); + private static readonly GithubReleasesJsonSerializerContext _ghSerializerContext = new(JsonHelper.GetDefaultSerializerOptions()); + private static readonly GitLabReleasesJsonSerializerContext _glSerializerContext = new(JsonHelper.GetDefaultSerializerOptions()); + private static readonly string _homeDir = AppDomain.CurrentDomain.BaseDirectory; private static readonly string _updateDir = Path.Combine(Path.GetTempPath(), "Ryujinx", "update"); @@ -53,123 +52,28 @@ namespace Ryujinx.Ava.Systems private static bool _running; private static readonly string[] _windowsDependencyDirs = []; + + private static string _changelogUrlFormat = null; - public static async Task> CheckVersionAsync(bool showVersionUpToDate = false) + public static async Task> CheckForUpdateAsync(bool showVersionUpToDate = false) { - if (!Version.TryParse(Program.Version, out Version currentVersion)) - { - Logger.Error?.Print(LogClass.Application, $"Failed to convert the current {RyujinxApp.FullAppName} version!"); + Optional<(Version, Version)> versionTuple; - await ContentDialogHelper.CreateWarningDialog( - LocaleManager.Instance[LocaleKeys.DialogUpdaterConvertFailedMessage], - LocaleManager.Instance[LocaleKeys.DialogUpdaterCancelUpdateMessage]); - - _running = false; - - return default; - } - - Logger.Info?.Print(LogClass.Application, "Checking for updates."); - - // Get latest version number from GitHub API try { - using HttpClient jsonClient = ConstructHttpClient(); - - if (_currentReleaseChannel == null) - { - ReleaseChannels releaseChannels = await ReleaseInformation.GetReleaseChannelsAsync(jsonClient); - - _currentReleaseChannel = ReleaseInformation.IsCanaryBuild - ? releaseChannels.Canary - : releaseChannels.Stable; - } - - string fetchedJson = await jsonClient.GetStringAsync(_currentReleaseChannel.Value.GetLatestReleaseApiUrl()); - GithubReleasesJsonResponse fetched = JsonHelper.Deserialize(fetchedJson, _serializerContext.GithubReleasesJsonResponse); - _buildVer = fetched.TagName; - - foreach (GithubReleaseAssetJsonResponse asset in fetched.Assets) - { - if (asset.Name.StartsWith("ryujinx") && asset.Name.EndsWith(_platformExt)) - { - _buildUrl = asset.BrowserDownloadUrl; - - if (asset.State != "uploaded") - { - if (showVersionUpToDate) - { - UserResult userResult = await ContentDialogHelper.CreateUpdaterUpToDateInfoDialog( - LocaleManager.Instance[LocaleKeys.DialogUpdaterAlreadyOnLatestVersionMessage], - string.Empty); - - if (userResult is UserResult.Ok) - { - OpenHelper.OpenUrl(ReleaseInformation.GetChangelogForVersion(currentVersion, _currentReleaseChannel.Value)); - } - } - - Logger.Info?.Print(LogClass.Application, "Up to date."); - - _running = false; - - return default; - } - - break; - } - } - - // If build not done, assume no new update are available. - if (_buildUrl is null) - { - if (showVersionUpToDate) - { - UserResult userResult = await ContentDialogHelper.CreateUpdaterUpToDateInfoDialog( - LocaleManager.Instance[LocaleKeys.DialogUpdaterAlreadyOnLatestVersionMessage], - string.Empty); - - if (userResult is UserResult.Ok) - { - OpenHelper.OpenUrl(ReleaseInformation.GetChangelogForVersion(currentVersion, _currentReleaseChannel.Value)); - } - } - - Logger.Info?.Print(LogClass.Application, "Up to date."); - - _running = false; - - return default; - } + versionTuple = await CheckGitLabVersionAsync(showVersionUpToDate); } - catch (Exception exception) + catch (Exception e) { - Logger.Error?.Print(LogClass.Application, exception.Message); - - await ContentDialogHelper.CreateErrorDialog( - LocaleManager.Instance[LocaleKeys.DialogUpdaterFailedToGetVersionMessage]); - - _running = false; - - return default; + Logger.Error?.PrintMsg(LogClass.Application, "Update checking from GitLab failed; falling back to GitHub."); + Logger.Error?.PrintMsg(LogClass.Application, e.Message); + versionTuple = await CheckGitHubVersionAsync(showVersionUpToDate); } - if (!Version.TryParse(_buildVer, out Version newVersion)) - { - Logger.Error?.Print(LogClass.Application, $"Failed to convert the received {RyujinxApp.FullAppName} version from GitHub!"); - - await ContentDialogHelper.CreateWarningDialog( - LocaleManager.Instance[LocaleKeys.DialogUpdaterConvertFailedGithubMessage], - LocaleManager.Instance[LocaleKeys.DialogUpdaterCancelUpdateMessage]); - - _running = false; - - return default; - } - - return (currentVersion, newVersion); + return versionTuple; } - + + public static async Task BeginUpdateAsync(bool showVersionUpToDate = false) { if (_running) @@ -179,7 +83,7 @@ namespace Ryujinx.Ava.Systems _running = true; - Optional<(Version, Version)> versionTuple = await CheckVersionAsync(showVersionUpToDate); + Optional<(Version, Version)> versionTuple = await CheckForUpdateAsync(showVersionUpToDate); if (_running is false || !versionTuple.HasValue) return; @@ -196,7 +100,7 @@ namespace Ryujinx.Ava.Systems if (userResult is UserResult.Ok) { - OpenHelper.OpenUrl(ReleaseInformation.GetChangelogForVersion(currentVersion, _currentReleaseChannel.Value)); + OpenHelper.OpenUrl(_changelogUrlFormat.Format(currentVersion)); } } @@ -212,6 +116,9 @@ namespace Ryujinx.Ava.Systems try { buildSizeClient.DefaultRequestHeaders.Add("Range", "bytes=0-0"); + + // GitLab instance is located in Ukraine. Connection times will vary across the world. + buildSizeClient.Timeout = TimeSpan.FromSeconds(10); HttpResponseMessage message = await buildSizeClient.GetAsync(new Uri(_buildUrl), HttpCompletionOption.ResponseHeadersRead); @@ -247,7 +154,7 @@ namespace Ryujinx.Ava.Systems break; // Secondary button maps to no, which in this case is the show changelog button. case UserResult.No: - OpenHelper.OpenUrl(ReleaseInformation.GetChangelogUrl(currentVersion, newVersion, _currentReleaseChannel.Value)); + OpenHelper.OpenUrl(ReleaseInformation.GetChangelogUrl(currentVersion, newVersion)); goto RequestUserToUpdate; default: _running = false; diff --git a/src/Ryujinx/UI/Windows/MainWindow.axaml.cs b/src/Ryujinx/UI/Windows/MainWindow.axaml.cs index a2d7ff657..23a3f26f9 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.CheckVersionAsync()).TryGet(out (Version Current, Version Incoming) versions)) + if ((await Updater.CheckForUpdateAsync()).TryGet(out (Version Current, Version Incoming) versions)) { Dispatcher.UIThread.Post(() => RyujinxApp.MainWindow.ViewModel.UpdateAvailable = versions.Current < versions.Incoming); } From d688fed7d20a297657b364d3cfbd71352e7deea9 Mon Sep 17 00:00:00 2001 From: GreemDev Date: Tue, 3 Jun 2025 18:38:22 -0500 Subject: [PATCH 048/105] missed the projects/ API endpoint part --- src/Ryujinx/Systems/Updater/Updater.GitLab.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Ryujinx/Systems/Updater/Updater.GitLab.cs b/src/Ryujinx/Systems/Updater/Updater.GitLab.cs index 6e5e914e0..cd3a3f411 100644 --- a/src/Ryujinx/Systems/Updater/Updater.GitLab.cs +++ b/src/Ryujinx/Systems/Updater/Updater.GitLab.cs @@ -131,7 +131,7 @@ namespace Ryujinx.Ava.Systems public override string ToString() => $"{Group}/{Project}"; public string GetLatestReleaseApiUrl() => - $"https://git.ryujinx.app/api/v4/{Id}/releases/permalink/latest"; + $"https://git.ryujinx.app/api/v4/projects/{Id}/releases/permalink/latest"; } } } 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 049/105] 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 050/105] 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 051/105] 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 052/105] 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 053/105] 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 054/105] 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 055/105] 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 056/105] 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 057/105] 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 058/105] 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 059/105] 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 060/105] 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 061/105] 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 062/105] 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 063/105] 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 064/105] 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 065/105] 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 066/105] 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 067/105] 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 068/105] 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 069/105] 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 070/105] 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 @@ +