From d2a532f971c0fde68d63b86a5724a068a5156d76 Mon Sep 17 00:00:00 2001 From: KeatonTheBot Date: Tue, 17 Jun 2025 17:17:31 -0500 Subject: [PATCH] misc: chore: Fix numerous NullReferenceExceptions, InvalidOperationExceptions --- .../Dsp/Command/CircularBufferSinkCommand.cs | 6 +- .../Collections/IntervalTree.cs | 7 +- .../Collections/TreeDictionary.cs | 7 +- .../Configuration/AppDataManager.cs | 4 +- .../JsonMotionConfigControllerConverter.cs | 2 +- .../Hid/JsonInputConfigConverter.cs | 2 +- src/Ryujinx.Common/Logging/Logger.cs | 2 +- src/Ryujinx.Cpu/AddressTable.cs | 27 +-- .../Jit/HostTracked/AddressSpacePartition.cs | 7 +- .../Jit/MemoryManagerHostTracked.cs | 7 +- .../Arm32/Target/Arm64/InstEmitMemory.cs | 2 +- .../Multithreading/ThreadedRenderer.cs | 2 +- .../Engine/MME/MacroJitCompiler.cs | 6 +- .../Image/AutoDeleteCache.cs | 33 +-- src/Ryujinx.Graphics.Gpu/Image/PoolCache.cs | 3 +- .../Memory/BufferModifiedRangeList.cs | 2 +- .../Shader/DiskCache/DiskCacheHostStorage.cs | 4 +- .../Shader/ShaderSpecializationState.cs | 7 +- .../FFmpegContext.cs | 2 +- src/Ryujinx.Graphics.OpenGL/Debugger.cs | 2 +- .../Effects/AreaScalingFilter.cs | 2 +- .../Effects/FsrScalingFilter.cs | 73 ++++--- .../Effects/FxaaPostProcessingEffect.cs | 2 +- .../Effects/SmaaPostProcessingEffect.cs | 6 +- .../IntermediateRepresentation/BasicBlock.cs | 5 +- .../Optimizations/BindlessToArray.cs | 2 +- .../Optimizations/DoubleToFloat.cs | 4 +- .../Optimizations/GlobalToStorage.cs | 14 +- .../Translation/Optimizations/Utils.cs | 2 +- .../Translation/RegisterUsage.cs | 15 +- .../Transforms/DrawParametersReplace.cs | 2 +- .../Transforms/GeometryToCompute.cs | 62 +++--- .../Transforms/SharedAtomicSignedCas.cs | 2 +- .../Transforms/SharedStoreSmallIntCas.cs | 2 +- .../Translation/Transforms/ShufflePass.cs | 2 +- .../Translation/Transforms/TexturePass.cs | 30 +-- .../Transforms/VectorComponentSelect.cs | 6 +- .../Translation/Transforms/VertexToCompute.cs | 50 ++--- .../Effects/FsrScalingFilter.cs | 2 +- .../Effects/FxaaPostProcessingEffect.cs | 2 +- .../Effects/SmaaPostProcessingEffect.cs | 10 +- .../IpcServiceGenerator.cs | 10 +- .../ServiceNotImplementedException.cs | 2 +- src/Ryujinx.HLE/FileSystem/ContentManager.cs | 2 +- .../SoftwareKeyboard/InlineResponses.cs | 8 +- src/Ryujinx.HLE/HOS/Kernel/Ipc/KServerPort.cs | 5 +- .../HOS/Kernel/Memory/KPageTableBase.cs | 68 +++--- .../HOS/Kernel/Memory/SharedMemoryStorage.cs | 7 +- .../HOS/Kernel/Threading/KPriorityQueue.cs | 2 +- .../HOS/Kernel/Threading/KThread.cs | 2 +- .../Hipc/HipcGenerator.cs | 109 +++++----- .../SyscallGenerator.cs | 30 +-- src/Ryujinx.Horizon/Arp/Ipc/Reader.cs | 6 +- src/Ryujinx.Input/HLE/NpadController.cs | 6 +- src/Ryujinx.Input/HLE/NpadManager.cs | 7 +- .../App/ApplicationLibrary.cs | 13 +- .../Helper/FileAssociationHelper.cs | 2 +- .../SystemInfo/WindowsSystemInfo.cs | 4 +- src/Ryujinx/App.axaml.cs | 4 +- src/Ryujinx/Modules/Updater/Updater.cs | 70 +++--- .../Applet/AvaloniaDynamicTextInputHandler.cs | 12 +- .../Controls/ApplicationContextMenu.axaml.cs | 9 +- .../UI/Controls/ApplicationGridView.axaml.cs | 2 +- .../UI/Controls/ApplicationListView.axaml.cs | 2 +- src/Ryujinx/UI/Models/SaveModel.cs | 4 +- src/Ryujinx/UI/Models/UserProfile.cs | 2 +- src/Ryujinx/UI/Renderer/EmbeddedWindow.cs | 7 +- .../ViewModels/AppListFavoriteComparable.cs | 2 +- .../DownloadableContentManagerViewModel.cs | 4 +- .../UI/ViewModels/Input/InputViewModel.cs | 18 +- .../UI/ViewModels/MainWindowViewModel.cs | 4 +- .../UI/ViewModels/ModManagerViewModel.cs | 4 +- .../UI/ViewModels/TitleUpdateViewModel.cs | 4 +- .../UI/ViewModels/XCITrimmerViewModel.cs | 6 +- .../Views/Input/ControllerInputView.axaml.cs | 18 +- src/Ryujinx/UI/Views/Input/InputView.axaml.cs | 5 +- .../UI/Views/Input/KeyboardInputView.axaml.cs | 201 +++++++++--------- .../UI/Views/Main/MainViewControls.axaml.cs | 4 +- .../Settings/SettingsHotkeysView.axaml.cs | 73 ++++--- .../UserProfileImageSelectorView.axaml.cs | 2 +- .../UI/Views/User/UserSelectorView.axaml.cs | 2 +- src/Ryujinx/UI/Windows/CheatWindow.axaml.cs | 2 +- .../DownloadableContentManagerWindow.axaml.cs | 4 +- src/Ryujinx/UI/Windows/MainWindow.axaml.cs | 7 +- .../UI/Windows/ModManagerWindow.axaml.cs | 4 +- .../UI/Windows/TitleUpdateWindow.axaml.cs | 4 +- .../UI/Windows/XCITrimmerWindow.axaml.cs | 2 +- src/Spv.Generator/Instruction.cs | 2 +- src/Spv.Generator/LiteralInteger.cs | 2 +- src/Spv.Generator/LiteralString.cs | 2 +- 90 files changed, 667 insertions(+), 533 deletions(-) diff --git a/src/Ryujinx.Audio/Renderer/Dsp/Command/CircularBufferSinkCommand.cs b/src/Ryujinx.Audio/Renderer/Dsp/Command/CircularBufferSinkCommand.cs index 59ef70932..0545f0292 100644 --- a/src/Ryujinx.Audio/Renderer/Dsp/Command/CircularBufferSinkCommand.cs +++ b/src/Ryujinx.Audio/Renderer/Dsp/Command/CircularBufferSinkCommand.cs @@ -59,7 +59,11 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command for (int y = 0; y < context.SampleCount; y++) { - context.MemoryManager.Write(targetOffset + (ulong)y * TargetChannelCount, PcmHelper.Saturate(inputBuffer[y])); + if (inputBuffer != null) + { + context.MemoryManager.Write(targetOffset + (ulong)y * TargetChannelCount, + PcmHelper.Saturate(inputBuffer[y])); + } } currentOffset += context.SampleCount * TargetChannelCount; diff --git a/src/Ryujinx.Common/Collections/IntervalTree.cs b/src/Ryujinx.Common/Collections/IntervalTree.cs index 695487dda..251c84ac2 100644 --- a/src/Ryujinx.Common/Collections/IntervalTree.cs +++ b/src/Ryujinx.Common/Collections/IntervalTree.cs @@ -318,13 +318,16 @@ namespace Ryujinx.Common.Collections { Root = newNode; } - else if (start.CompareTo(parent.Start) < 0) + else if (parent != null && start.CompareTo(parent.Start) < 0) { parent.Left = newNode; } else { - parent.Right = newNode; + if (parent != null) + { + parent.Right = newNode; + } } PropagateIncrease(newNode); diff --git a/src/Ryujinx.Common/Collections/TreeDictionary.cs b/src/Ryujinx.Common/Collections/TreeDictionary.cs index 18f48188a..9d15ba367 100644 --- a/src/Ryujinx.Common/Collections/TreeDictionary.cs +++ b/src/Ryujinx.Common/Collections/TreeDictionary.cs @@ -279,13 +279,16 @@ namespace Ryujinx.Common.Collections { Root = newNode; } - else if (key.CompareTo(parent.Key) < 0) + else if (parent != null && key.CompareTo(parent.Key) < 0) { parent.Left = newNode; } else { - parent.Right = newNode; + if (parent != null) + { + parent.Right = newNode; + } } Count++; return newNode; diff --git a/src/Ryujinx.Common/Configuration/AppDataManager.cs b/src/Ryujinx.Common/Configuration/AppDataManager.cs index deaa03def..2c20fd07b 100644 --- a/src/Ryujinx.Common/Configuration/AppDataManager.cs +++ b/src/Ryujinx.Common/Configuration/AppDataManager.cs @@ -273,7 +273,7 @@ namespace Ryujinx.Common.Configuration { FileSystemInfo resolvedDirectoryInfo = Directory.ResolveLinkTarget(correctApplicationDataDirectoryPath, true); - string resolvedPath = resolvedDirectoryInfo.FullName; + string resolvedPath = resolvedDirectoryInfo?.FullName; Logger.Error?.Print(LogClass.Application, $"Please manually move your Ryujinx data from {resolvedPath} to {correctApplicationDataDirectoryPath}, and remove the symlink."); } catch (Exception symlinkException) @@ -297,7 +297,7 @@ namespace Ryujinx.Common.Configuration { FileSystemInfo resolvedDirectoryInfo = Directory.ResolveLinkTarget(correctApplicationDataDirectoryPath, true); - string resolvedPath = resolvedDirectoryInfo.FullName; + string resolvedPath = resolvedDirectoryInfo?.FullName; Logger.Error?.Print(LogClass.Application, $"Please manually move your Ryujinx data from {resolvedPath} to {correctApplicationDataDirectoryPath}, and remove the symlink."); } catch (Exception symlinkException) diff --git a/src/Ryujinx.Common/Configuration/Hid/Controller/Motion/JsonMotionConfigControllerConverter.cs b/src/Ryujinx.Common/Configuration/Hid/Controller/Motion/JsonMotionConfigControllerConverter.cs index 40f067aea..6bd6538ee 100644 --- a/src/Ryujinx.Common/Configuration/Hid/Controller/Motion/JsonMotionConfigControllerConverter.cs +++ b/src/Ryujinx.Common/Configuration/Hid/Controller/Motion/JsonMotionConfigControllerConverter.cs @@ -25,7 +25,7 @@ namespace Ryujinx.Common.Configuration.Hid.Controller.Motion { string propertyName = tempReader.GetString(); - if (propertyName.Equals("motion_backend")) + if (propertyName is "motion_backend") { tempReader.Read(); diff --git a/src/Ryujinx.Common/Configuration/Hid/JsonInputConfigConverter.cs b/src/Ryujinx.Common/Configuration/Hid/JsonInputConfigConverter.cs index 6c2a69b88..39c2260ea 100644 --- a/src/Ryujinx.Common/Configuration/Hid/JsonInputConfigConverter.cs +++ b/src/Ryujinx.Common/Configuration/Hid/JsonInputConfigConverter.cs @@ -27,7 +27,7 @@ namespace Ryujinx.Common.Configuration.Hid { string propertyName = tempReader.GetString(); - if (propertyName.Equals("backend")) + if (propertyName is "backend") { tempReader.Read(); diff --git a/src/Ryujinx.Common/Logging/Logger.cs b/src/Ryujinx.Common/Logging/Logger.cs index b2b46905e..4f9f2d41d 100644 --- a/src/Ryujinx.Common/Logging/Logger.cs +++ b/src/Ryujinx.Common/Logging/Logger.cs @@ -24,7 +24,7 @@ namespace Ryujinx.Common.Logging public readonly struct Log { private static readonly string _homeDir = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile); - private static readonly string _homeDirRedacted = Path.Combine(Directory.GetParent(_homeDir).FullName, "[redacted]"); + private static readonly string _homeDirRedacted = Path.Combine(Directory.GetParent(_homeDir)?.FullName ?? string.Empty, "[redacted]"); internal readonly LogLevel Level; diff --git a/src/Ryujinx.Cpu/AddressTable.cs b/src/Ryujinx.Cpu/AddressTable.cs index aaba642c6..594663fbc 100644 --- a/src/Ryujinx.Cpu/AddressTable.cs +++ b/src/Ryujinx.Cpu/AddressTable.cs @@ -258,23 +258,26 @@ namespace ARMeilleure.Common for (int i = 0; i < Levels.Length - 1; i++) { ref AddressTableLevel level = ref Levels[i]; - ref TEntry* nextPage = ref page[level.GetValue(address)]; - - if (nextPage == null || nextPage == _fillBottomLevelPtr) + if (page != null) { - ref AddressTableLevel nextLevel = ref Levels[i + 1]; + ref TEntry* nextPage = ref page[level.GetValue(address)]; - if (i == Levels.Length - 2) + if (nextPage == null || nextPage == _fillBottomLevelPtr) { - nextPage = (TEntry*)Allocate(1 << nextLevel.Length, Fill, leaf: true); - } - else - { - nextPage = (TEntry*)Allocate(1 << nextLevel.Length, GetFillValue(i), leaf: false); + ref AddressTableLevel nextLevel = ref Levels[i + 1]; + + if (i == Levels.Length - 2) + { + nextPage = (TEntry*)Allocate(1 << nextLevel.Length, Fill, leaf: true); + } + else + { + nextPage = (TEntry*)Allocate(1 << nextLevel.Length, GetFillValue(i), leaf: false); + } } + + page = (TEntry**)nextPage; } - - page = (TEntry**)nextPage; } return (TEntry*)page; diff --git a/src/Ryujinx.Cpu/Jit/HostTracked/AddressSpacePartition.cs b/src/Ryujinx.Cpu/Jit/HostTracked/AddressSpacePartition.cs index 224c5edc3..25a1aab58 100644 --- a/src/Ryujinx.Cpu/Jit/HostTracked/AddressSpacePartition.cs +++ b/src/Ryujinx.Cpu/Jit/HostTracked/AddressSpacePartition.cs @@ -388,7 +388,12 @@ namespace Ryujinx.Cpu.Jit.HostTracked _treeLock.ExitReadLock(); } - return (_backingMemory, _firstPagePa.Value); + if (_firstPagePa != null) + { + return (_backingMemory, _firstPagePa.Value); + } + + return (null, 0); } public PrivateRange GetPrivateAllocation(ulong va) diff --git a/src/Ryujinx.Cpu/Jit/MemoryManagerHostTracked.cs b/src/Ryujinx.Cpu/Jit/MemoryManagerHostTracked.cs index 2849a03d8..5dc9129ac 100644 --- a/src/Ryujinx.Cpu/Jit/MemoryManagerHostTracked.cs +++ b/src/Ryujinx.Cpu/Jit/MemoryManagerHostTracked.cs @@ -135,7 +135,10 @@ namespace Ryujinx.Cpu.Jit offset += (int)copySize; } - return new ReadOnlySequence(first, 0, last, (int)(size - last.RunningIndex)); + if (last != null) + { + return new ReadOnlySequence(first, 0, last, (int)(size - last.RunningIndex)); + } } catch (InvalidMemoryRegionException) { @@ -146,6 +149,8 @@ namespace Ryujinx.Cpu.Jit return ReadOnlySequence.Empty; } + + return default; } /// diff --git a/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitMemory.cs b/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitMemory.cs index d8caee6e7..09d49e445 100644 --- a/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitMemory.cs +++ b/src/Ryujinx.Cpu/LightningJit/Arm32/Target/Arm64/InstEmitMemory.cs @@ -872,7 +872,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64 if (unscaled) { - writeInstUnscaled(rt, tempRegister.Operand, offs); + writeInstUnscaled?.Invoke(rt, tempRegister.Operand, offs); } else { diff --git a/src/Ryujinx.Graphics.GAL/Multithreading/ThreadedRenderer.cs b/src/Ryujinx.Graphics.GAL/Multithreading/ThreadedRenderer.cs index 6375d290c..4537ba40b 100644 --- a/src/Ryujinx.Graphics.GAL/Multithreading/ThreadedRenderer.cs +++ b/src/Ryujinx.Graphics.GAL/Multithreading/ThreadedRenderer.cs @@ -126,7 +126,7 @@ namespace Ryujinx.Graphics.GAL.Multithreading if (Volatile.Read(ref _interruptAction) != null) { - _interruptAction(); + _interruptAction?.Invoke(); _interruptRun.Set(); Interlocked.Exchange(ref _interruptAction, null); diff --git a/src/Ryujinx.Graphics.Gpu/Engine/MME/MacroJitCompiler.cs b/src/Ryujinx.Graphics.Gpu/Engine/MME/MacroJitCompiler.cs index ea8bb2d61..d77294638 100644 --- a/src/Ryujinx.Graphics.Gpu/Engine/MME/MacroJitCompiler.cs +++ b/src/Ryujinx.Graphics.Gpu/Engine/MME/MacroJitCompiler.cs @@ -297,7 +297,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.MME EmitLoadGprA(opCode); EmitLoadImm(opCode); _ilGen.Emit(OpCodes.Add); - _ilGen.Emit(OpCodes.Call, typeof(MacroJitContext).GetMethod(nameof(MacroJitContext.Read))); + _ilGen.Emit(OpCodes.Call, typeof(MacroJitContext).GetMethod(nameof(MacroJitContext.Read))!); break; default: @@ -457,7 +457,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.MME private void EmitFetchParam() { _ilGen.Emit(OpCodes.Ldarg_0); - _ilGen.Emit(OpCodes.Call, typeof(MacroJitContext).GetMethod(nameof(MacroJitContext.FetchParam))); + _ilGen.Emit(OpCodes.Call, typeof(MacroJitContext).GetMethod(nameof(MacroJitContext.FetchParam))!); } /// @@ -508,7 +508,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.MME { _ilGen.Emit(OpCodes.Ldarg_1); _ilGen.Emit(OpCodes.Ldloc_S, _methAddr); - _ilGen.Emit(OpCodes.Call, typeof(MacroJitContext).GetMethod(nameof(MacroJitContext.Send))); + _ilGen.Emit(OpCodes.Call, typeof(MacroJitContext).GetMethod(nameof(MacroJitContext.Send))!); _ilGen.Emit(OpCodes.Ldloc_S, _methAddr); _ilGen.Emit(OpCodes.Ldloc_S, _methIncr); _ilGen.Emit(OpCodes.Add); diff --git a/src/Ryujinx.Graphics.Gpu/Image/AutoDeleteCache.cs b/src/Ryujinx.Graphics.Gpu/Image/AutoDeleteCache.cs index 08fafd1cf..3a694db34 100644 --- a/src/Ryujinx.Graphics.Gpu/Image/AutoDeleteCache.cs +++ b/src/Ryujinx.Graphics.Gpu/Image/AutoDeleteCache.cs @@ -173,24 +173,27 @@ namespace Ryujinx.Graphics.Gpu.Image /// private void RemoveLeastUsedTexture() { - Texture oldestTexture = _textures.First.Value; - - _totalSize -= oldestTexture.Size; - - if (!oldestTexture.CheckModified(false)) + if (_textures.First != null) { - // The texture must be flushed if it falls out of the auto delete cache. - // Flushes out of the auto delete cache do not trigger write tracking, - // as it is expected that other overlapping textures exist that have more up-to-date contents. + Texture oldestTexture = _textures.First.Value; - oldestTexture.Group.SynchronizeDependents(oldestTexture); - oldestTexture.FlushModified(false); + _totalSize -= oldestTexture.Size; + + if (!oldestTexture.CheckModified(false)) + { + // The texture must be flushed if it falls out of the auto delete cache. + // Flushes out of the auto delete cache do not trigger write tracking, + // as it is expected that other overlapping textures exist that have more up-to-date contents. + + oldestTexture.Group.SynchronizeDependents(oldestTexture); + oldestTexture.FlushModified(false); + } + + _textures.RemoveFirst(); + + oldestTexture.DecrementReferenceCount(); + oldestTexture.CacheNode = null; } - - _textures.RemoveFirst(); - - oldestTexture.DecrementReferenceCount(); - oldestTexture.CacheNode = null; } /// diff --git a/src/Ryujinx.Graphics.Gpu/Image/PoolCache.cs b/src/Ryujinx.Graphics.Gpu/Image/PoolCache.cs index b9aa37fed..066611494 100644 --- a/src/Ryujinx.Graphics.Gpu/Image/PoolCache.cs +++ b/src/Ryujinx.Graphics.Gpu/Image/PoolCache.cs @@ -67,7 +67,8 @@ namespace Ryujinx.Graphics.Gpu.Image public T FindOrCreate(GpuChannel channel, ulong address, int maximumId, TextureBindingsArrayCache bindingsArrayCache) { // Remove old entries from the cache, if possible. - while (_pools.Count > MaxCapacity && (_currentTimestamp - _pools.First.Value.CacheTimestamp) >= MinDeltaForRemoval) + while (_pools.Count > MaxCapacity && _pools.First != null && + (_currentTimestamp - _pools.First.Value.CacheTimestamp) >= MinDeltaForRemoval) { T oldestPool = _pools.First.Value; diff --git a/src/Ryujinx.Graphics.Gpu/Memory/BufferModifiedRangeList.cs b/src/Ryujinx.Graphics.Gpu/Memory/BufferModifiedRangeList.cs index f246f64a9..7a125ca9c 100644 --- a/src/Ryujinx.Graphics.Gpu/Memory/BufferModifiedRangeList.cs +++ b/src/Ryujinx.Graphics.Gpu/Memory/BufferModifiedRangeList.cs @@ -372,7 +372,7 @@ namespace Ryujinx.Graphics.Gpu.Memory if (rangeCount == -1) { - _migrationTarget.WaitForAndFlushRanges(address, size); + _migrationTarget?.WaitForAndFlushRanges(address, size); return; } diff --git a/src/Ryujinx.Graphics.Gpu/Shader/DiskCache/DiskCacheHostStorage.cs b/src/Ryujinx.Graphics.Gpu/Shader/DiskCache/DiskCacheHostStorage.cs index c36fc0ada..640058d12 100644 --- a/src/Ryujinx.Graphics.Gpu/Shader/DiskCache/DiskCacheHostStorage.cs +++ b/src/Ryujinx.Graphics.Gpu/Shader/DiskCache/DiskCacheHostStorage.cs @@ -481,7 +481,7 @@ namespace Ryujinx.Graphics.Gpu.Shader.DiskCache } int offset = Unsafe.SizeOf() + programIndex * Unsafe.SizeOf(); - if (offset + Unsafe.SizeOf() > tocFileStream.Length) + if (tocFileStream != null && offset + Unsafe.SizeOf() > tocFileStream.Length) { return (null, null); } @@ -491,7 +491,7 @@ namespace Ryujinx.Graphics.Gpu.Shader.DiskCache throw new DiskCacheLoadException(DiskCacheLoadResult.FileCorruptedGeneric); } - tocFileStream.Seek(offset, SeekOrigin.Begin); + tocFileStream?.Seek(offset, SeekOrigin.Begin); BinarySerializer tocReader = new(tocFileStream); diff --git a/src/Ryujinx.Graphics.Gpu/Shader/ShaderSpecializationState.cs b/src/Ryujinx.Graphics.Gpu/Shader/ShaderSpecializationState.cs index 1230c0580..5944519f3 100644 --- a/src/Ryujinx.Graphics.Gpu/Shader/ShaderSpecializationState.cs +++ b/src/Ryujinx.Graphics.Gpu/Shader/ShaderSpecializationState.cs @@ -991,8 +991,11 @@ namespace Ryujinx.Graphics.Gpu.Shader if (hasPipelineState) { - ProgramPipelineState pipelineState = PipelineState.Value; - dataWriter.WriteWithMagicAndSize(ref pipelineState, PgpsMagic); + if (PipelineState != null) + { + ProgramPipelineState pipelineState = PipelineState.Value; + dataWriter.WriteWithMagicAndSize(ref pipelineState, PgpsMagic); + } } if (_queriedState.HasFlag(QueriedStateFlags.TransformFeedback)) diff --git a/src/Ryujinx.Graphics.Nvdec.FFmpeg/FFmpegContext.cs b/src/Ryujinx.Graphics.Nvdec.FFmpeg/FFmpegContext.cs index 0767cc9d6..489e96355 100644 --- a/src/Ryujinx.Graphics.Nvdec.FFmpeg/FFmpegContext.cs +++ b/src/Ryujinx.Graphics.Nvdec.FFmpeg/FFmpegContext.cs @@ -91,7 +91,7 @@ namespace Ryujinx.Graphics.Nvdec.FFmpeg FFmpegApi.av_log_format_line(ptr, level, format, vl, lineBuffer, lineSize, &printPrefix); - string line = Marshal.PtrToStringAnsi((IntPtr)lineBuffer).Trim(); + string line = Marshal.PtrToStringAnsi((IntPtr)lineBuffer)?.Trim(); switch (level) { diff --git a/src/Ryujinx.Graphics.OpenGL/Debugger.cs b/src/Ryujinx.Graphics.OpenGL/Debugger.cs index 7606bdbfd..afff460e2 100644 --- a/src/Ryujinx.Graphics.OpenGL/Debugger.cs +++ b/src/Ryujinx.Graphics.OpenGL/Debugger.cs @@ -59,7 +59,7 @@ namespace Ryujinx.Graphics.OpenGL IntPtr message, IntPtr userParam) { - string msg = Marshal.PtrToStringUTF8(message).Replace('\n', ' '); + string msg = Marshal.PtrToStringUTF8(message)?.Replace('\n', ' '); switch (type) { diff --git a/src/Ryujinx.Graphics.OpenGL/Effects/AreaScalingFilter.cs b/src/Ryujinx.Graphics.OpenGL/Effects/AreaScalingFilter.cs index 9971b5814..f615f1522 100644 --- a/src/Ryujinx.Graphics.OpenGL/Effects/AreaScalingFilter.cs +++ b/src/Ryujinx.Graphics.OpenGL/Effects/AreaScalingFilter.cs @@ -94,7 +94,7 @@ namespace Ryujinx.Graphics.OpenGL.Effects GL.UseProgram(previousProgram); GL.MemoryBarrier(MemoryBarrierFlags.ShaderImageAccessBarrierBit); - (_renderer.Pipeline as Pipeline).RestoreImages1And2(); + (_renderer.Pipeline as Pipeline)?.RestoreImages1And2(); GL.ActiveTexture(TextureUnit.Texture0); GL.BindTexture(TextureTarget.Texture2D, previousTextureBinding); diff --git a/src/Ryujinx.Graphics.OpenGL/Effects/FsrScalingFilter.cs b/src/Ryujinx.Graphics.OpenGL/Effects/FsrScalingFilter.cs index 0522e28e0..514e8c8c2 100644 --- a/src/Ryujinx.Graphics.OpenGL/Effects/FsrScalingFilter.cs +++ b/src/Ryujinx.Graphics.OpenGL/Effects/FsrScalingFilter.cs @@ -125,48 +125,53 @@ namespace Ryujinx.Graphics.OpenGL.Effects GL.ActiveTexture(TextureUnit.Texture0); int previousTextureBinding = GL.GetInteger(GetPName.TextureBinding2D); - GL.BindImageTexture(0, textureView.Handle, 0, false, 0, TextureAccess.ReadWrite, SizedInternalFormat.Rgba8); + if (textureView != null) + { + GL.BindImageTexture(0, textureView.Handle, 0, false, 0, TextureAccess.ReadWrite, + SizedInternalFormat.Rgba8); - int threadGroupWorkRegionDim = 16; - int dispatchX = (width + (threadGroupWorkRegionDim - 1)) / threadGroupWorkRegionDim; - int dispatchY = (height + (threadGroupWorkRegionDim - 1)) / threadGroupWorkRegionDim; + int threadGroupWorkRegionDim = 16; + int dispatchX = (width + (threadGroupWorkRegionDim - 1)) / threadGroupWorkRegionDim; + int dispatchY = (height + (threadGroupWorkRegionDim - 1)) / threadGroupWorkRegionDim; - // Scaling pass - float srcWidth = Math.Abs(source.X2 - source.X1); - float srcHeight = Math.Abs(source.Y2 - source.Y1); - float scaleX = srcWidth / view.Width; - float scaleY = srcHeight / view.Height; - GL.UseProgram(_scalingShaderProgram); - view.Bind(0); - GL.Uniform1(_inputUniform, 0); - GL.Uniform1(_outputUniform, 0); - GL.Uniform1(_srcX0Uniform, (float)source.X1); - GL.Uniform1(_srcX1Uniform, (float)source.X2); - GL.Uniform1(_srcY0Uniform, (float)source.Y1); - GL.Uniform1(_srcY1Uniform, (float)source.Y2); - GL.Uniform1(_dstX0Uniform, (float)destination.X1); - GL.Uniform1(_dstX1Uniform, (float)destination.X2); - GL.Uniform1(_dstY0Uniform, (float)destination.Y1); - GL.Uniform1(_dstY1Uniform, (float)destination.Y2); - GL.Uniform1(_scaleXUniform, scaleX); - GL.Uniform1(_scaleYUniform, scaleY); - GL.DispatchCompute(dispatchX, dispatchY, 1); + // Scaling pass + float srcWidth = Math.Abs(source.X2 - source.X1); + float srcHeight = Math.Abs(source.Y2 - source.Y1); + float scaleX = srcWidth / view.Width; + float scaleY = srcHeight / view.Height; + GL.UseProgram(_scalingShaderProgram); + view.Bind(0); + GL.Uniform1(_inputUniform, 0); + GL.Uniform1(_outputUniform, 0); + GL.Uniform1(_srcX0Uniform, (float)source.X1); + GL.Uniform1(_srcX1Uniform, (float)source.X2); + GL.Uniform1(_srcY0Uniform, (float)source.Y1); + GL.Uniform1(_srcY1Uniform, (float)source.Y2); + GL.Uniform1(_dstX0Uniform, (float)destination.X1); + GL.Uniform1(_dstX1Uniform, (float)destination.X2); + GL.Uniform1(_dstY0Uniform, (float)destination.Y1); + GL.Uniform1(_dstY1Uniform, (float)destination.Y2); + GL.Uniform1(_scaleXUniform, scaleX); + GL.Uniform1(_scaleYUniform, scaleY); + GL.DispatchCompute(dispatchX, dispatchY, 1); - GL.MemoryBarrier(MemoryBarrierFlags.ShaderImageAccessBarrierBit); + GL.MemoryBarrier(MemoryBarrierFlags.ShaderImageAccessBarrierBit); - // Sharpening Pass - GL.UseProgram(_sharpeningShaderProgram); - GL.BindImageTexture(0, destinationTexture.Handle, 0, false, 0, TextureAccess.ReadWrite, SizedInternalFormat.Rgba8); - textureView.Bind(0); - GL.Uniform1(_inputUniform, 0); - GL.Uniform1(_outputUniform, 0); - GL.Uniform1(_sharpeningUniform, 1.5f - (Level * 0.01f * 1.5f)); - GL.DispatchCompute(dispatchX, dispatchY, 1); + // Sharpening Pass + GL.UseProgram(_sharpeningShaderProgram); + GL.BindImageTexture(0, destinationTexture.Handle, 0, false, 0, TextureAccess.ReadWrite, + SizedInternalFormat.Rgba8); + textureView.Bind(0); + GL.Uniform1(_inputUniform, 0); + GL.Uniform1(_outputUniform, 0); + GL.Uniform1(_sharpeningUniform, 1.5f - (Level * 0.01f * 1.5f)); + GL.DispatchCompute(dispatchX, dispatchY, 1); + } GL.UseProgram(previousProgram); GL.MemoryBarrier(MemoryBarrierFlags.ShaderImageAccessBarrierBit); - (_renderer.Pipeline as Pipeline).RestoreImages1And2(); + (_renderer.Pipeline as Pipeline)?.RestoreImages1And2(); GL.ActiveTexture(TextureUnit.Texture0); GL.BindTexture(TextureTarget.Texture2D, previousTextureBinding); diff --git a/src/Ryujinx.Graphics.OpenGL/Effects/FxaaPostProcessingEffect.cs b/src/Ryujinx.Graphics.OpenGL/Effects/FxaaPostProcessingEffect.cs index 4e92efe6d..4229bb3f8 100644 --- a/src/Ryujinx.Graphics.OpenGL/Effects/FxaaPostProcessingEffect.cs +++ b/src/Ryujinx.Graphics.OpenGL/Effects/FxaaPostProcessingEffect.cs @@ -68,7 +68,7 @@ namespace Ryujinx.Graphics.OpenGL.Effects GL.UseProgram(previousProgram); GL.MemoryBarrier(MemoryBarrierFlags.ShaderImageAccessBarrierBit); - (_renderer.Pipeline as Pipeline).RestoreImages1And2(); + (_renderer.Pipeline as Pipeline)?.RestoreImages1And2(); GL.ActiveTexture(TextureUnit.Texture0); GL.BindTexture(TextureTarget.Texture2D, previousTextureBinding); diff --git a/src/Ryujinx.Graphics.OpenGL/Effects/SmaaPostProcessingEffect.cs b/src/Ryujinx.Graphics.OpenGL/Effects/SmaaPostProcessingEffect.cs index d58326367..29df60292 100644 --- a/src/Ryujinx.Graphics.OpenGL/Effects/SmaaPostProcessingEffect.cs +++ b/src/Ryujinx.Graphics.OpenGL/Effects/SmaaPostProcessingEffect.cs @@ -222,8 +222,8 @@ namespace Ryujinx.Graphics.OpenGL.Effects.Smaa GL.BindImageTexture(0, blendOutput.Handle, 0, false, 0, TextureAccess.ReadWrite, SizedInternalFormat.Rgba8); GL.UseProgram(_blendShaderPrograms[Quality]); edgeOutput.Bind(0); - areaTexture.Bind(1); - searchTexture.Bind(2); + areaTexture?.Bind(1); + searchTexture?.Bind(2); GL.Uniform1(_inputUniform, 0); GL.Uniform1(_outputUniform, 0); GL.Uniform1(_samplerAreaUniform, 1); @@ -243,7 +243,7 @@ namespace Ryujinx.Graphics.OpenGL.Effects.Smaa GL.DispatchCompute(dispatchX, dispatchY, 1); GL.MemoryBarrier(MemoryBarrierFlags.ShaderImageAccessBarrierBit); - (_renderer.Pipeline as Pipeline).RestoreImages1And2(); + (_renderer.Pipeline as Pipeline)?.RestoreImages1And2(); GL.UseProgram(previousProgram); diff --git a/src/Ryujinx.Graphics.Shader/IntermediateRepresentation/BasicBlock.cs b/src/Ryujinx.Graphics.Shader/IntermediateRepresentation/BasicBlock.cs index d3eae3108..cc45f7264 100644 --- a/src/Ryujinx.Graphics.Shader/IntermediateRepresentation/BasicBlock.cs +++ b/src/Ryujinx.Graphics.Shader/IntermediateRepresentation/BasicBlock.cs @@ -65,7 +65,10 @@ namespace Ryujinx.Graphics.Shader.IntermediateRepresentation if (lastOp is Operation operation && IsControlFlowInst(operation.Inst)) { - Operations.AddBefore(Operations.Last, node); + if (Operations.Last != null) + { + Operations.AddBefore(Operations.Last, node); + } } else { diff --git a/src/Ryujinx.Graphics.Shader/Translation/Optimizations/BindlessToArray.cs b/src/Ryujinx.Graphics.Shader/Translation/Optimizations/BindlessToArray.cs index 1e0b3b645..a6970c94f 100644 --- a/src/Ryujinx.Graphics.Shader/Translation/Optimizations/BindlessToArray.cs +++ b/src/Ryujinx.Graphics.Shader/Translation/Optimizations/BindlessToArray.cs @@ -158,7 +158,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations } } - if (handleAsgOp.Inst != Instruction.Load || + if (handleAsgOp is not { Inst: Instruction.Load } || handleAsgOp.StorageKind != StorageKind.ConstantBuffer || handleAsgOp.SourcesCount != 4) { diff --git a/src/Ryujinx.Graphics.Shader/Translation/Optimizations/DoubleToFloat.cs b/src/Ryujinx.Graphics.Shader/Translation/Optimizations/DoubleToFloat.cs index 208ca3935..29ee9833a 100644 --- a/src/Ryujinx.Graphics.Shader/Translation/Optimizations/DoubleToFloat.cs +++ b/src/Ryujinx.Graphics.Shader/Translation/Optimizations/DoubleToFloat.cs @@ -34,7 +34,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations operation.Dest = null; - LinkedListNode newNode = node.List.AddBefore(node, new Operation(Instruction.Call, 0, floatValue, callArgs)); + LinkedListNode newNode = node.List?.AddBefore(node, new Operation(Instruction.Call, 0, floatValue, callArgs)); Utils.DeleteNode(node, operation); @@ -53,7 +53,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations Operand[] callArgs = [Const(functionId), operation.GetSource(0), resultLow, resultHigh]; - LinkedListNode newNode = node.List.AddBefore(node, new Operation(Instruction.Call, 0, (Operand)null, callArgs)); + LinkedListNode newNode = node.List?.AddBefore(node, new Operation(Instruction.Call, 0, (Operand)null, callArgs)); Utils.DeleteNode(node, operation); diff --git a/src/Ryujinx.Graphics.Shader/Translation/Optimizations/GlobalToStorage.cs b/src/Ryujinx.Graphics.Shader/Translation/Optimizations/GlobalToStorage.cs index 96898afb7..d30672f3f 100644 --- a/src/Ryujinx.Graphics.Shader/Translation/Optimizations/GlobalToStorage.cs +++ b/src/Ryujinx.Graphics.Shader/Translation/Optimizations/GlobalToStorage.cs @@ -305,7 +305,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations LinkedListNode node) { Operation operation = node.Value as Operation; - Operand globalAddress = operation.GetSource(0); + Operand globalAddress = operation?.GetSource(0); SearchResult result = FindUniqueBaseAddressCb(gtsContext, block, globalAddress, needsOffset: true); if (result.Found) @@ -331,8 +331,8 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations Operation maskOp = new(Instruction.BitwiseAnd, baseAddressMasked, baseAddress, Const(-alignment)); Operation subOp = new(Instruction.Subtract, hostOffset, globalAddress, baseAddressMasked); - node.List.AddBefore(node, maskOp); - node.List.AddBefore(node, subOp); + node.List?.AddBefore(node, maskOp); + node.List?.AddBefore(node, subOp); offset = hostOffset; } @@ -342,7 +342,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations Operation addOp = new(Instruction.Add, newOffset, offset, Const(result.ConstOffset)); - node.List.AddBefore(node, addOp); + node.List?.AddBefore(node, addOp); offset = newOffset; } @@ -441,8 +441,8 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations Operation shiftOp = new(Instruction.ShiftRightU32, wordOffset, offset, Const(2)); Operation storageOp = new(operation.Inst, StorageKind.StorageBuffer, operation.Dest, sources); - node.List.AddBefore(node, shiftOp); - LinkedListNode newNode = node.List.AddBefore(node, storageOp); + node.List?.AddBefore(node, shiftOp); + LinkedListNode newNode = node.List?.AddBefore(node, storageOp); Utils.DeleteNode(node, operation); @@ -483,7 +483,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations Operation callOp = new(Instruction.Call, returnValue, sources); - LinkedListNode newNode = node.List.AddBefore(node, callOp); + LinkedListNode newNode = node.List?.AddBefore(node, callOp); if (returnsValue) { diff --git a/src/Ryujinx.Graphics.Shader/Translation/Optimizations/Utils.cs b/src/Ryujinx.Graphics.Shader/Translation/Optimizations/Utils.cs index 6ec90fa3c..bc02d57ac 100644 --- a/src/Ryujinx.Graphics.Shader/Translation/Optimizations/Utils.cs +++ b/src/Ryujinx.Graphics.Shader/Translation/Optimizations/Utils.cs @@ -189,7 +189,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations public static void DeleteNode(LinkedListNode node, Operation operation) { - node.List.Remove(node); + node.List?.Remove(node); for (int srcIndex = 0; srcIndex < operation.SourcesCount; srcIndex++) { diff --git a/src/Ryujinx.Graphics.Shader/Translation/RegisterUsage.cs b/src/Ryujinx.Graphics.Shader/Translation/RegisterUsage.cs index 1290bab99..a63f9092a 100644 --- a/src/Ryujinx.Graphics.Shader/Translation/RegisterUsage.cs +++ b/src/Ryujinx.Graphics.Shader/Translation/RegisterUsage.cs @@ -141,7 +141,7 @@ namespace Ryujinx.Graphics.Shader.Translation { Operation operation = node.Value as Operation; - for (int srcIndex = 0; srcIndex < operation.SourcesCount; srcIndex++) + for (int srcIndex = 0; srcIndex < operation?.SourcesCount; srcIndex++) { Operand source = operation.GetSource(srcIndex); @@ -155,7 +155,7 @@ namespace Ryujinx.Graphics.Shader.Translation localInputs[block.Index] |= GetMask(register) & ~localOutputs[block.Index]; } - for (int dstIndex = 0; dstIndex < operation.DestsCount; dstIndex++) + for (int dstIndex = 0; dstIndex < operation?.DestsCount; dstIndex++) { Operand dest = operation.GetDest(dstIndex); @@ -296,7 +296,7 @@ namespace Ryujinx.Graphics.Shader.Translation { Operation operation = node.Value as Operation; - if (operation.Inst == Instruction.Call) + if (operation?.Inst == Instruction.Call) { Operand funcId = operation.GetSource(0); @@ -333,7 +333,7 @@ namespace Ryujinx.Graphics.Shader.Translation return false; } - return block.Operations.First.Value is Operation operation && operation.Inst == inst; + return block.Operations.First?.Value is Operation operation && operation.Inst == inst; } private static bool EndsWith(BasicBlock block, Instruction inst) @@ -343,7 +343,7 @@ namespace Ryujinx.Graphics.Shader.Translation return false; } - return block.Operations.Last.Value is Operation operation && operation.Inst == inst; + return block.Operations.Last?.Value is Operation operation && operation.Inst == inst; } private static RegisterMask GetMask(Register register) @@ -445,7 +445,10 @@ namespace Ryujinx.Graphics.Shader.Translation if (node == null) { - node = block.Operations.AddBefore(block.Operations.Last, copyOp); + if (block.Operations.Last != null) + { + node = block.Operations.AddBefore(block.Operations.Last, copyOp); + } } else { diff --git a/src/Ryujinx.Graphics.Shader/Translation/Transforms/DrawParametersReplace.cs b/src/Ryujinx.Graphics.Shader/Translation/Transforms/DrawParametersReplace.cs index 9e73013db..b14f4e390 100644 --- a/src/Ryujinx.Graphics.Shader/Translation/Transforms/DrawParametersReplace.cs +++ b/src/Ryujinx.Graphics.Shader/Translation/Transforms/DrawParametersReplace.cs @@ -36,7 +36,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Transforms Operand GenerateLoad(IoVariable ioVariable) { Operand value = Local(); - node.List.AddBefore(node, new Operation(Instruction.Load, StorageKind.Input, value, Const((int)ioVariable))); + node.List?.AddBefore(node, new Operation(Instruction.Load, StorageKind.Input, value, Const((int)ioVariable))); return value; } diff --git a/src/Ryujinx.Graphics.Shader/Translation/Transforms/GeometryToCompute.cs b/src/Ryujinx.Graphics.Shader/Translation/Transforms/GeometryToCompute.cs index 0013cf0eb..14e226f84 100644 --- a/src/Ryujinx.Graphics.Shader/Translation/Transforms/GeometryToCompute.cs +++ b/src/Ryujinx.Graphics.Shader/Translation/Transforms/GeometryToCompute.cs @@ -45,7 +45,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Transforms Operand vertexElemOffset = GenerateVertexOffset(context.ResourceManager, node, inputOffset, primVertex); - newNode = node.List.AddBefore(node, new Operation( + newNode = node.List?.AddBefore(node, new Operation( Instruction.Load, StorageKind.StorageBuffer, operation.Dest, @@ -80,7 +80,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Transforms { if (TryGetOffset(context.ResourceManager, operation, StorageKind.Output, out int outputOffset)) { - newNode = node.List.AddBefore(node, new Operation( + newNode = node.List?.AddBefore(node, new Operation( Instruction.Load, StorageKind.LocalMemory, operation.Dest, @@ -99,7 +99,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Transforms { Operand value = operation.GetSource(operation.SourcesCount - 1); - newNode = node.List.AddBefore(node, new Operation( + newNode = node.List?.AddBefore(node, new Operation( Instruction.Store, StorageKind.LocalMemory, (Operand)null, @@ -134,7 +134,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Transforms definitions.MaxOutputVertices * definitions.ThreadsPerInputPrimitive, definitions.ThreadsPerInputPrimitive); Operand outputBaseVertex = Local(); - node.List.AddBefore(node, new Operation(Instruction.Add, outputBaseVertex, new[] { baseVertexOffset, outputPrimVertex })); + node.List?.AddBefore(node, new Operation(Instruction.Add, outputBaseVertex, new[] { baseVertexOffset, outputPrimVertex })); Operand outputPrimIndex = IncrementLocalMemory(node, resourceManager.LocalGeometryOutputIndexCountMemoryId); Operand baseIndexOffset = GenerateBaseOffset( @@ -143,16 +143,16 @@ namespace Ryujinx.Graphics.Shader.Translation.Transforms definitions.GetGeometryOutputIndexBufferStride(), definitions.ThreadsPerInputPrimitive); Operand outputBaseIndex = Local(); - node.List.AddBefore(node, new Operation(Instruction.Add, outputBaseIndex, new[] { baseIndexOffset, outputPrimIndex })); + node.List?.AddBefore(node, new Operation(Instruction.Add, outputBaseIndex, new[] { baseIndexOffset, outputPrimIndex })); - node.List.AddBefore(node, new Operation( + node.List?.AddBefore(node, new Operation( Instruction.Store, StorageKind.StorageBuffer, null, new[] { Const(ibOutputBinding), Const(0), outputBaseIndex, outputBaseVertex })); Operand baseOffset = Local(); - node.List.AddBefore(node, new Operation(Instruction.Multiply, baseOffset, new[] { outputBaseVertex, Const(stride) })); + node.List?.AddBefore(node, new Operation(Instruction.Multiply, baseOffset, new[] { outputBaseVertex, Const(stride) })); LinkedListNode newNode = node; @@ -163,7 +163,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Transforms if (offset > 0) { vertexOffset = Local(); - node.List.AddBefore(node, new Operation(Instruction.Add, vertexOffset, new[] { baseOffset, Const(offset) })); + node.List?.AddBefore(node, new Operation(Instruction.Add, vertexOffset, new[] { baseOffset, Const(offset) })); } else { @@ -171,13 +171,13 @@ namespace Ryujinx.Graphics.Shader.Translation.Transforms } Operand value = Local(); - node.List.AddBefore(node, new Operation( + node.List?.AddBefore(node, new Operation( Instruction.Load, StorageKind.LocalMemory, value, new[] { Const(resourceManager.LocalVertexDataMemoryId), Const(offset) })); - newNode = node.List.AddBefore(node, new Operation( + newNode = node.List?.AddBefore(node, new Operation( Instruction.Store, StorageKind.StorageBuffer, null, @@ -198,9 +198,9 @@ namespace Ryujinx.Graphics.Shader.Translation.Transforms definitions.GetGeometryOutputIndexBufferStride(), definitions.ThreadsPerInputPrimitive); Operand outputBaseIndex = Local(); - node.List.AddBefore(node, new Operation(Instruction.Add, outputBaseIndex, new[] { baseIndexOffset, outputPrimIndex })); + node.List?.AddBefore(node, new Operation(Instruction.Add, outputBaseIndex, new[] { baseIndexOffset, outputPrimIndex })); - return node.List.AddBefore(node, new Operation( + return node.List?.AddBefore(node, new Operation( Instruction.Store, StorageKind.StorageBuffer, null, @@ -213,16 +213,16 @@ namespace Ryujinx.Graphics.Shader.Translation.Transforms GeneratePrimitiveId(resourceManager, node, primitiveId); Operand baseOffset = Local(); - node.List.AddBefore(node, new Operation(Instruction.Multiply, baseOffset, new[] { primitiveId, Const(stride) })); + node.List?.AddBefore(node, new Operation(Instruction.Multiply, baseOffset, new[] { primitiveId, Const(stride) })); Operand invocationId = Local(); GenerateInvocationId(node, invocationId); Operand invocationOffset = Local(); - node.List.AddBefore(node, new Operation(Instruction.Multiply, invocationOffset, new[] { invocationId, Const(stride / threadsPerInputPrimitive) })); + node.List?.AddBefore(node, new Operation(Instruction.Multiply, invocationOffset, new[] { invocationId, Const(stride / threadsPerInputPrimitive) })); Operand combinedOffset = Local(); - node.List.AddBefore(node, new Operation(Instruction.Add, combinedOffset, new[] { baseOffset, invocationOffset })); + node.List?.AddBefore(node, new Operation(Instruction.Add, combinedOffset, new[] { baseOffset, invocationOffset })); return combinedOffset; } @@ -230,16 +230,16 @@ namespace Ryujinx.Graphics.Shader.Translation.Transforms private static Operand IncrementLocalMemory(LinkedListNode node, int memoryId) { Operand oldValue = Local(); - node.List.AddBefore(node, new Operation( + node.List?.AddBefore(node, new Operation( Instruction.Load, StorageKind.LocalMemory, oldValue, new[] { Const(memoryId) })); Operand newValue = Local(); - node.List.AddBefore(node, new Operation(Instruction.Add, newValue, new[] { oldValue, Const(1) })); + node.List?.AddBefore(node, new Operation(Instruction.Add, newValue, new[] { oldValue, Const(1) })); - node.List.AddBefore(node, new Operation(Instruction.Store, StorageKind.LocalMemory, null, new[] { Const(memoryId), newValue })); + node.List?.AddBefore(node, new Operation(Instruction.Store, StorageKind.LocalMemory, null, new[] { Const(memoryId), newValue })); return oldValue; } @@ -253,34 +253,34 @@ namespace Ryujinx.Graphics.Shader.Translation.Transforms int vertexInfoCbBinding = resourceManager.Reservations.VertexInfoConstantBufferBinding; Operand vertexCount = Local(); - node.List.AddBefore(node, new Operation( + node.List?.AddBefore(node, new Operation( Instruction.Load, StorageKind.ConstantBuffer, vertexCount, new[] { Const(vertexInfoCbBinding), Const((int)VertexInfoBufferField.VertexCounts), Const(0) })); Operand primInputVertex = Local(); - node.List.AddBefore(node, new Operation( + node.List?.AddBefore(node, new Operation( Instruction.Load, StorageKind.LocalMemory, primInputVertex, new[] { Const(resourceManager.LocalTopologyRemapMemoryId), primVertex })); Operand instanceIndex = Local(); - node.List.AddBefore(node, new Operation( + node.List?.AddBefore(node, new Operation( Instruction.Load, StorageKind.Input, instanceIndex, new[] { Const((int)IoVariable.GlobalId), Const(1) })); Operand baseVertex = Local(); - node.List.AddBefore(node, new Operation(Instruction.Multiply, baseVertex, new[] { instanceIndex, vertexCount })); + node.List?.AddBefore(node, new Operation(Instruction.Multiply, baseVertex, new[] { instanceIndex, vertexCount })); Operand vertexIndex = Local(); - node.List.AddBefore(node, new Operation(Instruction.Add, vertexIndex, new[] { baseVertex, primInputVertex })); + node.List?.AddBefore(node, new Operation(Instruction.Add, vertexIndex, new[] { baseVertex, primInputVertex })); Operand vertexBaseOffset = Local(); - node.List.AddBefore(node, new Operation( + node.List?.AddBefore(node, new Operation( Instruction.Multiply, vertexBaseOffset, new[] { vertexIndex, Const(resourceManager.Reservations.InputSizePerInvocation) })); @@ -291,7 +291,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Transforms { vertexElemOffset = Local(); - node.List.AddBefore(node, new Operation(Instruction.Add, vertexElemOffset, new[] { vertexBaseOffset, Const(elementOffset) })); + node.List?.AddBefore(node, new Operation(Instruction.Add, vertexElemOffset, new[] { vertexBaseOffset, Const(elementOffset) })); } else { @@ -306,35 +306,35 @@ namespace Ryujinx.Graphics.Shader.Translation.Transforms int vertexInfoCbBinding = resourceManager.Reservations.VertexInfoConstantBufferBinding; Operand vertexCount = Local(); - node.List.AddBefore(node, new Operation( + node.List?.AddBefore(node, new Operation( Instruction.Load, StorageKind.ConstantBuffer, vertexCount, new[] { Const(vertexInfoCbBinding), Const((int)VertexInfoBufferField.VertexCounts), Const(0) })); Operand vertexIndex = Local(); - node.List.AddBefore(node, new Operation( + node.List?.AddBefore(node, new Operation( Instruction.Load, StorageKind.Input, vertexIndex, new[] { Const((int)IoVariable.GlobalId), Const(0) })); Operand instanceIndex = Local(); - node.List.AddBefore(node, new Operation( + node.List?.AddBefore(node, new Operation( Instruction.Load, StorageKind.Input, instanceIndex, new[] { Const((int)IoVariable.GlobalId), Const(1) })); Operand baseVertex = Local(); - node.List.AddBefore(node, new Operation(Instruction.Multiply, baseVertex, new[] { instanceIndex, vertexCount })); + node.List?.AddBefore(node, new Operation(Instruction.Multiply, baseVertex, new[] { instanceIndex, vertexCount })); - return node.List.AddBefore(node, new Operation(Instruction.Add, dest, new[] { baseVertex, vertexIndex })); + return node.List?.AddBefore(node, new Operation(Instruction.Add, dest, new[] { baseVertex, vertexIndex })); } private static LinkedListNode GenerateInvocationId(LinkedListNode node, Operand dest) { - return node.List.AddBefore(node, new Operation( + return node.List?.AddBefore(node, new Operation( Instruction.Load, StorageKind.Input, dest, diff --git a/src/Ryujinx.Graphics.Shader/Translation/Transforms/SharedAtomicSignedCas.cs b/src/Ryujinx.Graphics.Shader/Translation/Transforms/SharedAtomicSignedCas.cs index c556e8149..0db9d09a7 100644 --- a/src/Ryujinx.Graphics.Shader/Translation/Transforms/SharedAtomicSignedCas.cs +++ b/src/Ryujinx.Graphics.Shader/Translation/Transforms/SharedAtomicSignedCas.cs @@ -48,7 +48,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Transforms Operand[] callArgs = [Const(functionId), byteOffset, value]; - LinkedListNode newNode = node.List.AddBefore(node, new Operation(Instruction.Call, 0, result, callArgs)); + LinkedListNode newNode = node.List?.AddBefore(node, new Operation(Instruction.Call, 0, result, callArgs)); Utils.DeleteNode(node, operation); diff --git a/src/Ryujinx.Graphics.Shader/Translation/Transforms/SharedStoreSmallIntCas.cs b/src/Ryujinx.Graphics.Shader/Translation/Transforms/SharedStoreSmallIntCas.cs index 2852a61ad..0afcf9e98 100644 --- a/src/Ryujinx.Graphics.Shader/Translation/Transforms/SharedStoreSmallIntCas.cs +++ b/src/Ryujinx.Graphics.Shader/Translation/Transforms/SharedStoreSmallIntCas.cs @@ -47,7 +47,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Transforms Operand[] callArgs = [Const(functionId), byteOffset, value]; - LinkedListNode newNode = node.List.AddBefore(node, new Operation(Instruction.Call, 0, (Operand)null, callArgs)); + LinkedListNode newNode = node.List?.AddBefore(node, new Operation(Instruction.Call, 0, (Operand)null, callArgs)); Utils.DeleteNode(node, operation); diff --git a/src/Ryujinx.Graphics.Shader/Translation/Transforms/ShufflePass.cs b/src/Ryujinx.Graphics.Shader/Translation/Transforms/ShufflePass.cs index 9cb361e6c..1b53573c3 100644 --- a/src/Ryujinx.Graphics.Shader/Translation/Transforms/ShufflePass.cs +++ b/src/Ryujinx.Graphics.Shader/Translation/Transforms/ShufflePass.cs @@ -42,7 +42,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Transforms Operand[] callArgs = [Const(functionId), value, index, mask, valid]; - LinkedListNode newNode = node.List.AddBefore(node, new Operation(Instruction.Call, 0, result, callArgs)); + LinkedListNode newNode = node.List?.AddBefore(node, new Operation(Instruction.Call, 0, result, callArgs)); Utils.DeleteNode(node, operation); diff --git a/src/Ryujinx.Graphics.Shader/Translation/Transforms/TexturePass.cs b/src/Ryujinx.Graphics.Shader/Translation/Transforms/TexturePass.cs index 808692559..b026c0415 100644 --- a/src/Ryujinx.Graphics.Shader/Translation/Transforms/TexturePass.cs +++ b/src/Ryujinx.Graphics.Shader/Translation/Transforms/TexturePass.cs @@ -79,7 +79,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Transforms callArgs = [Const(functionId), texOp.GetSource(coordsIndex + index), Const(samplerIndex)]; } - node.List.AddBefore(node, new Operation(Instruction.Call, 0, scaledCoord, callArgs)); + node.List?.AddBefore(node, new Operation(Instruction.Call, 0, scaledCoord, callArgs)); texOp.SetSource(coordsIndex + index, scaledCoord); } @@ -130,7 +130,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Transforms Operand[] callArgs = [Const(functionId), dest, Const(samplerIndex)]; - node.List.AddAfter(node, new Operation(Instruction.Call, 0, unscaledSize, callArgs)); + node.List?.AddAfter(node, new Operation(Instruction.Call, 0, unscaledSize, callArgs)); } } @@ -178,7 +178,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Transforms Operand[] texSizeSources = [Const(0)]; - LinkedListNode textureSizeNode = node.List.AddBefore(node, new TextureOperation( + LinkedListNode textureSizeNode = node.List?.AddBefore(node, new TextureOperation( Instruction.TextureQuerySize, texOp.Type, texOp.Format, @@ -195,7 +195,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Transforms Operand coordNormalized = Local(); - node.List.AddBefore(node, new Operation(Instruction.FP32 | Instruction.Divide, coordNormalized, source, GenerateI2f(node, coordSize))); + node.List?.AddBefore(node, new Operation(Instruction.FP32 | Instruction.Divide, coordNormalized, source, GenerateI2f(node, coordSize))); texOp.SetSource(index, coordNormalized); @@ -248,7 +248,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Transforms texSizeSources = [Const(0)]; } - node.List.AddBefore(node, new TextureOperation( + node.List?.AddBefore(node, new TextureOperation( Instruction.TextureQuerySize, texOp.Type, texOp.Format, @@ -259,18 +259,18 @@ namespace Ryujinx.Graphics.Shader.Translation.Transforms [coordSize], texSizeSources)); - node.List.AddBefore(node, new Operation( + node.List?.AddBefore(node, new Operation( Instruction.FP32 | Instruction.Multiply, scaledSize, GenerateI2f(node, coordSize), ConstF((float)(1 << (gatherBiasPrecision + 1))))); - node.List.AddBefore(node, new Operation(Instruction.FP32 | Instruction.Divide, bias, ConstF(1f), scaledSize)); + node.List?.AddBefore(node, new Operation(Instruction.FP32 | Instruction.Divide, bias, ConstF(1f), scaledSize)); Operand source = texOp.GetSource(coordsIndex + index); Operand coordBiased = Local(); - node.List.AddBefore(node, new Operation(Instruction.FP32 | Instruction.Add, coordBiased, source, bias)); + node.List?.AddBefore(node, new Operation(Instruction.FP32 | Instruction.Add, coordBiased, source, bias)); texOp.SetSource(coordsIndex + index, coordBiased); } @@ -573,7 +573,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Transforms texSizeSources = [Const(0)]; } - node.List.AddBefore(node, new TextureOperation( + node.List?.AddBefore(node, new TextureOperation( Instruction.TextureQuerySize, texOp.Type, texOp.Format, @@ -604,7 +604,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Transforms { lod = Local(); - node.List.AddBefore(node, new TextureOperation( + node.List?.AddBefore(node, new TextureOperation( Instruction.Lod, texOp.Type, texOp.Format, @@ -635,7 +635,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Transforms texSizeSources = [GenerateF2i(node, lod)]; } - node.List.AddBefore(node, new TextureOperation( + node.List?.AddBefore(node, new TextureOperation( Instruction.TextureQuerySize, texOp.Type, texOp.Format, @@ -692,8 +692,8 @@ namespace Ryujinx.Graphics.Shader.Translation.Transforms Operation convOp = new(Instruction.ConvertS32ToFP32, Local(), dest); Operation normOp = new(Instruction.FP32 | Instruction.Multiply, Local(), convOp.Dest, ConstF(1f / maxPositive)); - node = node.List.AddAfter(node, convOp); - node = node.List.AddAfter(node, normOp); + node = node?.List?.AddAfter(node, convOp); + node = node?.List?.AddAfter(node, normOp); foreach (INode useOp in uses) { @@ -720,7 +720,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Transforms { Operand res = Local(); - node.List.AddBefore(node, new Operation(Instruction.ConvertS32ToFP32, res, value)); + node.List?.AddBefore(node, new Operation(Instruction.ConvertS32ToFP32, res, value)); return res; } @@ -729,7 +729,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Transforms { Operand res = Local(); - node.List.AddBefore(node, new Operation(Instruction.ConvertFP32ToS32, res, value)); + node.List?.AddBefore(node, new Operation(Instruction.ConvertFP32ToS32, res, value)); return res; } diff --git a/src/Ryujinx.Graphics.Shader/Translation/Transforms/VectorComponentSelect.cs b/src/Ryujinx.Graphics.Shader/Translation/Transforms/VectorComponentSelect.cs index e55f4355d..d7e3fd111 100644 --- a/src/Ryujinx.Graphics.Shader/Translation/Transforms/VectorComponentSelect.cs +++ b/src/Ryujinx.Graphics.Shader/Translation/Transforms/VectorComponentSelect.cs @@ -67,7 +67,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Transforms Operation loadOp = new(Instruction.Load, StorageKind.ConstantBuffer, value, inputs); - node.List.AddBefore(node, loadOp); + node.List?.AddBefore(node, loadOp); if (i == 0) { @@ -81,8 +81,8 @@ namespace Ryujinx.Graphics.Shader.Translation.Transforms Operation compareOp = new(Instruction.CompareEqual, isCurrentIndex, new Operand[] { elemIndex, Const(i) }); Operation selectOp = new(Instruction.ConditionalSelect, selection, new Operand[] { isCurrentIndex, value, result }); - node.List.AddBefore(node, compareOp); - node.List.AddBefore(node, selectOp); + node.List?.AddBefore(node, compareOp); + node.List?.AddBefore(node, selectOp); result = selection; } diff --git a/src/Ryujinx.Graphics.Shader/Translation/Transforms/VertexToCompute.cs b/src/Ryujinx.Graphics.Shader/Translation/Transforms/VertexToCompute.cs index ebff0d59c..57239a367 100644 --- a/src/Ryujinx.Graphics.Shader/Translation/Transforms/VertexToCompute.cs +++ b/src/Ryujinx.Graphics.Shader/Translation/Transforms/VertexToCompute.cs @@ -58,7 +58,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Transforms Operand temp = needsSextNorm ? Local() : dest; Operand vertexElemOffset = GenerateVertexOffset(context.ResourceManager, node, location, 0); - newNode = node.List.AddBefore(node, new TextureOperation( + newNode = node.List?.AddBefore(node, new TextureOperation( Instruction.TextureSample, SamplerType.TextureBuffer, TextureFormat.Unknown, @@ -81,7 +81,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Transforms Operand temp = component > 0 ? Local() : dest; Operand vertexElemOffset = GenerateVertexOffset(context.ResourceManager, node, location, component); - newNode = node.List.AddBefore(node, new TextureOperation( + newNode = node.List?.AddBefore(node, new TextureOperation( Instruction.TextureSample, SamplerType.TextureBuffer, TextureFormat.Unknown, @@ -116,7 +116,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Transforms { if (TryGetOutputOffset(context.ResourceManager, operation, out int outputOffset)) { - newNode = node.List.AddBefore(node, new Operation( + newNode = node.List?.AddBefore(node, new Operation( Instruction.Load, StorageKind.LocalMemory, operation.Dest, @@ -133,7 +133,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Transforms { Operand value = operation.GetSource(operation.SourcesCount - 1); - newNode = node.List.AddBefore(node, new Operation( + newNode = node.List?.AddBefore(node, new Operation( Instruction.Store, StorageKind.LocalMemory, (Operand)null, @@ -164,37 +164,37 @@ namespace Ryujinx.Graphics.Shader.Translation.Transforms GenerateVertexIdInstanceRateLoad(resourceManager, node, vertexIdIr); Operand attributeOffset = Local(); - node.List.AddBefore(node, new Operation( + node.List?.AddBefore(node, new Operation( Instruction.Load, StorageKind.ConstantBuffer, attributeOffset, new[] { Const(vertexInfoCbBinding), Const((int)VertexInfoBufferField.VertexOffsets), Const(location), Const(0) })); Operand isInstanceRate = Local(); - node.List.AddBefore(node, new Operation( + node.List?.AddBefore(node, new Operation( Instruction.Load, StorageKind.ConstantBuffer, isInstanceRate, new[] { Const(vertexInfoCbBinding), Const((int)VertexInfoBufferField.VertexOffsets), Const(location), Const(1) })); Operand vertexId = Local(); - node.List.AddBefore(node, new Operation( + node.List?.AddBefore(node, new Operation( Instruction.ConditionalSelect, vertexId, new[] { isInstanceRate, vertexIdIr, vertexIdVr })); Operand vertexStride = Local(); - node.List.AddBefore(node, new Operation( + node.List?.AddBefore(node, new Operation( Instruction.Load, StorageKind.ConstantBuffer, vertexStride, new[] { Const(vertexInfoCbBinding), Const((int)VertexInfoBufferField.VertexStrides), Const(location), Const(0) })); Operand vertexBaseOffset = Local(); - node.List.AddBefore(node, new Operation(Instruction.Multiply, vertexBaseOffset, new[] { vertexId, vertexStride })); + node.List?.AddBefore(node, new Operation(Instruction.Multiply, vertexBaseOffset, new[] { vertexId, vertexStride })); Operand vertexOffset = Local(); - node.List.AddBefore(node, new Operation(Instruction.Add, vertexOffset, new[] { attributeOffset, vertexBaseOffset })); + node.List?.AddBefore(node, new Operation(Instruction.Add, vertexOffset, new[] { attributeOffset, vertexBaseOffset })); Operand vertexElemOffset; @@ -202,7 +202,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Transforms { vertexElemOffset = Local(); - node.List.AddBefore(node, new Operation(Instruction.Add, vertexElemOffset, new[] { vertexOffset, Const(component) })); + node.List?.AddBefore(node, new Operation(Instruction.Add, vertexElemOffset, new[] { vertexOffset, Const(component) })); } else { @@ -215,13 +215,13 @@ namespace Ryujinx.Graphics.Shader.Translation.Transforms private static LinkedListNode CopySignExtendedNormalized(LinkedListNode node, int bits, bool normalize, Operand dest, Operand src) { Operand leftShifted = Local(); - node = node.List.AddAfter(node, new Operation( + node = node.List?.AddAfter(node, new Operation( Instruction.ShiftLeft, leftShifted, new[] { src, Const(32 - bits) })); Operand rightShifted = normalize ? Local() : dest; - node = node.List.AddAfter(node, new Operation( + node = node?.List?.AddAfter(node, new Operation( Instruction.ShiftRightS32, rightShifted, new[] { leftShifted, Const(32 - bits) })); @@ -229,8 +229,8 @@ namespace Ryujinx.Graphics.Shader.Translation.Transforms if (normalize) { Operand asFloat = Local(); - node = node.List.AddAfter(node, new Operation(Instruction.ConvertS32ToFP32, asFloat, new[] { rightShifted })); - node = node.List.AddAfter(node, new Operation( + node = node?.List?.AddAfter(node, new Operation(Instruction.ConvertS32ToFP32, asFloat, new[] { rightShifted })); + node = node?.List?.AddAfter(node, new Operation( Instruction.FP32 | Instruction.Multiply, dest, new[] { asFloat, ConstF(1f / (1 << (bits - 1))) })); @@ -249,13 +249,13 @@ namespace Ryujinx.Graphics.Shader.Translation.Transforms { Operand componentExists = Local(); int vertexInfoCbBinding = resourceManager.Reservations.VertexInfoConstantBufferBinding; - node = node.List.AddAfter(node, new Operation( + node = node.List?.AddAfter(node, new Operation( Instruction.Load, StorageKind.ConstantBuffer, componentExists, new[] { Const(vertexInfoCbBinding), Const((int)VertexInfoBufferField.VertexStrides), Const(location), Const(component) })); - return node.List.AddAfter(node, new Operation( + return node?.List?.AddAfter(node, new Operation( Instruction.ConditionalSelect, dest, new[] { componentExists, src, ConstF(component == 3 ? 1f : 0f) })); @@ -265,7 +265,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Transforms { int vertexInfoCbBinding = resourceManager.Reservations.VertexInfoConstantBufferBinding; - return node.List.AddBefore(node, new Operation( + return node.List?.AddBefore(node, new Operation( Instruction.Load, StorageKind.ConstantBuffer, dest, @@ -276,7 +276,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Transforms { int vertexInfoCbBinding = resourceManager.Reservations.VertexInfoConstantBufferBinding; - return node.List.AddBefore(node, new Operation( + return node.List?.AddBefore(node, new Operation( Instruction.Load, StorageKind.ConstantBuffer, dest, @@ -291,7 +291,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Transforms GenerateBaseVertexLoad(resourceManager, node, baseVertex); GenerateVertexIdVertexRateLoad(resourceManager, node, vertexId); - return node.List.AddBefore(node, new Operation(Instruction.Add, dest, new[] { baseVertex, vertexId })); + return node.List?.AddBefore(node, new Operation(Instruction.Add, dest, new[] { baseVertex, vertexId })); } private static LinkedListNode GenerateInstanceIndexLoad(ResourceManager resourceManager, LinkedListNode node, Operand dest) @@ -301,34 +301,34 @@ namespace Ryujinx.Graphics.Shader.Translation.Transforms GenerateBaseInstanceLoad(resourceManager, node, baseInstance); - node.List.AddBefore(node, new Operation( + node.List?.AddBefore(node, new Operation( Instruction.Load, StorageKind.Input, instanceId, new[] { Const((int)IoVariable.GlobalId), Const(1) })); - return node.List.AddBefore(node, new Operation(Instruction.Add, dest, new[] { baseInstance, instanceId })); + return node.List?.AddBefore(node, new Operation(Instruction.Add, dest, new[] { baseInstance, instanceId })); } private static LinkedListNode GenerateVertexIdVertexRateLoad(ResourceManager resourceManager, LinkedListNode node, Operand dest) { Operand[] sources = [Const(resourceManager.LocalVertexIndexVertexRateMemoryId)]; - return node.List.AddBefore(node, new Operation(Instruction.Load, StorageKind.LocalMemory, dest, sources)); + return node.List?.AddBefore(node, new Operation(Instruction.Load, StorageKind.LocalMemory, dest, sources)); } private static LinkedListNode GenerateVertexIdInstanceRateLoad(ResourceManager resourceManager, LinkedListNode node, Operand dest) { Operand[] sources = [Const(resourceManager.LocalVertexIndexInstanceRateMemoryId)]; - return node.List.AddBefore(node, new Operation(Instruction.Load, StorageKind.LocalMemory, dest, sources)); + return node.List?.AddBefore(node, new Operation(Instruction.Load, StorageKind.LocalMemory, dest, sources)); } private static LinkedListNode GenerateInstanceIdLoad(LinkedListNode node, Operand dest) { Operand[] sources = [Const((int)IoVariable.GlobalId), Const(1)]; - return node.List.AddBefore(node, new Operation(Instruction.Load, StorageKind.Input, dest, sources)); + return node.List?.AddBefore(node, new Operation(Instruction.Load, StorageKind.Input, dest, sources)); } private static bool TryGetOutputOffset(ResourceManager resourceManager, Operation operation, out int outputOffset) diff --git a/src/Ryujinx.Graphics.Vulkan/Effects/FsrScalingFilter.cs b/src/Ryujinx.Graphics.Vulkan/Effects/FsrScalingFilter.cs index 50a50f74e..360f33778 100644 --- a/src/Ryujinx.Graphics.Vulkan/Effects/FsrScalingFilter.cs +++ b/src/Ryujinx.Graphics.Vulkan/Effects/FsrScalingFilter.cs @@ -152,7 +152,7 @@ namespace Ryujinx.Graphics.Vulkan.Effects int dispatchY = (height + (threadGroupWorkRegionDim - 1)) / threadGroupWorkRegionDim; _pipeline.SetUniformBuffers([new BufferAssignment(2, buffer.Range)]); - _pipeline.SetImage(ShaderStage.Compute, 0, _intermediaryTexture.GetView(FormatTable.ConvertRgba8SrgbToUnorm(view.Info.Format))); + _pipeline.SetImage(ShaderStage.Compute, 0, _intermediaryTexture?.GetView(FormatTable.ConvertRgba8SrgbToUnorm(view.Info.Format))); _pipeline.DispatchCompute(dispatchX, dispatchY, 1); _pipeline.ComputeBarrier(); diff --git a/src/Ryujinx.Graphics.Vulkan/Effects/FxaaPostProcessingEffect.cs b/src/Ryujinx.Graphics.Vulkan/Effects/FxaaPostProcessingEffect.cs index af4d84aac..fff05b121 100644 --- a/src/Ryujinx.Graphics.Vulkan/Effects/FxaaPostProcessingEffect.cs +++ b/src/Ryujinx.Graphics.Vulkan/Effects/FxaaPostProcessingEffect.cs @@ -74,7 +74,7 @@ namespace Ryujinx.Graphics.Vulkan.Effects var dispatchX = BitUtils.DivRoundUp(view.Width, IPostProcessingEffect.LocalGroupSize); var dispatchY = BitUtils.DivRoundUp(view.Height, IPostProcessingEffect.LocalGroupSize); - _pipeline.SetImage(ShaderStage.Compute, 0, _texture.GetView(FormatTable.ConvertRgba8SrgbToUnorm(view.Info.Format))); + _pipeline.SetImage(ShaderStage.Compute, 0, _texture?.GetView(FormatTable.ConvertRgba8SrgbToUnorm(view.Info.Format))); _pipeline.DispatchCompute(dispatchX, dispatchY, 1); _pipeline.ComputeBarrier(); diff --git a/src/Ryujinx.Graphics.Vulkan/Effects/SmaaPostProcessingEffect.cs b/src/Ryujinx.Graphics.Vulkan/Effects/SmaaPostProcessingEffect.cs index 28343cda1..29d2edf19 100644 --- a/src/Ryujinx.Graphics.Vulkan/Effects/SmaaPostProcessingEffect.cs +++ b/src/Ryujinx.Graphics.Vulkan/Effects/SmaaPostProcessingEffect.cs @@ -177,8 +177,8 @@ namespace Ryujinx.Graphics.Vulkan.Effects _areaTexture = _renderer.CreateTexture(areaInfo) as TextureView; _searchTexture = _renderer.CreateTexture(searchInfo) as TextureView; - _areaTexture.SetData(areaTexture); - _searchTexture.SetData(searchTexture); + _areaTexture?.SetData(areaTexture); + _searchTexture?.SetData(searchTexture); } public TextureView Run(TextureView view, CommandBufferScoped cbs, int width, int height) @@ -216,7 +216,7 @@ namespace Ryujinx.Graphics.Vulkan.Effects buffer.Holder.SetDataUnchecked(buffer.Offset, resolutionBuffer); _pipeline.SetUniformBuffers([new BufferAssignment(2, buffer.Range)]); - _pipeline.SetImage(ShaderStage.Compute, 0, _edgeOutputTexture.GetView(FormatTable.ConvertRgba8SrgbToUnorm(view.Info.Format))); + _pipeline.SetImage(ShaderStage.Compute, 0, _edgeOutputTexture?.GetView(FormatTable.ConvertRgba8SrgbToUnorm(view.Info.Format))); _pipeline.DispatchCompute(dispatchX, dispatchY, 1); _pipeline.ComputeBarrier(); @@ -226,7 +226,7 @@ namespace Ryujinx.Graphics.Vulkan.Effects _pipeline.SetTextureAndSampler(ShaderStage.Compute, 1, _edgeOutputTexture, _samplerLinear); _pipeline.SetTextureAndSampler(ShaderStage.Compute, 3, _areaTexture, _samplerLinear); _pipeline.SetTextureAndSampler(ShaderStage.Compute, 4, _searchTexture, _samplerLinear); - _pipeline.SetImage(ShaderStage.Compute, 0, _blendOutputTexture.GetView(FormatTable.ConvertRgba8SrgbToUnorm(view.Info.Format))); + _pipeline.SetImage(ShaderStage.Compute, 0, _blendOutputTexture?.GetView(FormatTable.ConvertRgba8SrgbToUnorm(view.Info.Format))); _pipeline.DispatchCompute(dispatchX, dispatchY, 1); _pipeline.ComputeBarrier(); @@ -235,7 +235,7 @@ namespace Ryujinx.Graphics.Vulkan.Effects _pipeline.Specialize(_specConstants); _pipeline.SetTextureAndSampler(ShaderStage.Compute, 3, _blendOutputTexture, _samplerLinear); _pipeline.SetTextureAndSampler(ShaderStage.Compute, 1, view, _samplerLinear); - _pipeline.SetImage(ShaderStage.Compute, 0, _outputTexture.GetView(FormatTable.ConvertRgba8SrgbToUnorm(view.Info.Format))); + _pipeline.SetImage(ShaderStage.Compute, 0, _outputTexture?.GetView(FormatTable.ConvertRgba8SrgbToUnorm(view.Info.Format))); _pipeline.DispatchCompute(dispatchX, dispatchY, 1); _pipeline.ComputeBarrier(); diff --git a/src/Ryujinx.HLE.Generators/IpcServiceGenerator.cs b/src/Ryujinx.HLE.Generators/IpcServiceGenerator.cs index 07ded7edd..8126eef1f 100644 --- a/src/Ryujinx.HLE.Generators/IpcServiceGenerator.cs +++ b/src/Ryujinx.HLE.Generators/IpcServiceGenerator.cs @@ -28,15 +28,15 @@ namespace Ryujinx.HLE.Generators continue; var constructors = className.ChildNodes().Where(x => x.IsKind(SyntaxKind.ConstructorDeclaration)).Select(y => y as ConstructorDeclarationSyntax); - if (!constructors.Any(x => x.ParameterList.Parameters.Count >= 1)) + if (!constructors.Any(x => x != null && x.ParameterList.Parameters.Count >= 1)) continue; - if (constructors.Where(x => x.ParameterList.Parameters.Count >= 1).FirstOrDefault().ParameterList.Parameters[0].Type.ToString() == "ServiceCtx") + if (constructors.FirstOrDefault(x => x != null && x.ParameterList.Parameters.Count >= 1).ParameterList.Parameters[0].Type.ToString() == "ServiceCtx") { generator.EnterScope($"if (type == typeof({GetFullName(className, context)}))"); - if (constructors.Any(x => x.ParameterList.Parameters.Count == 2)) + if (constructors.Any(x => x != null && x.ParameterList.Parameters.Count == 2)) { - var type = constructors.Where(x => x.ParameterList.Parameters.Count == 2).FirstOrDefault().ParameterList.Parameters[1].Type; + var type = constructors.FirstOrDefault(x => x != null && x.ParameterList.Parameters.Count == 2).ParameterList.Parameters[1].Type; var model = context.Compilation.GetSemanticModel(type.SyntaxTree); var typeSymbol = model.GetSymbolInfo(type).Symbol as INamedTypeSymbol; var fullName = typeSymbol?.ToString(); @@ -45,7 +45,7 @@ namespace Ryujinx.HLE.Generators generator.LeaveScope(); } - if (constructors.Any(x => x.ParameterList.Parameters.Count == 1)) + if (constructors.Any(x => x != null && x.ParameterList.Parameters.Count == 1)) { generator.AppendLine($"return new {GetFullName(className, context)}(context);"); } diff --git a/src/Ryujinx.HLE/Exceptions/ServiceNotImplementedException.cs b/src/Ryujinx.HLE/Exceptions/ServiceNotImplementedException.cs index 9c276b932..ac260d196 100644 --- a/src/Ryujinx.HLE/Exceptions/ServiceNotImplementedException.cs +++ b/src/Ryujinx.HLE/Exceptions/ServiceNotImplementedException.cs @@ -147,7 +147,7 @@ namespace Ryujinx.HLE.Exceptions while ((frame = trace.GetFrame(i++)) != null) { var method = frame.GetMethod(); - var declType = method.DeclaringType; + var declType = method?.DeclaringType; if (typeof(IpcService).IsAssignableFrom(declType)) { diff --git a/src/Ryujinx.HLE/FileSystem/ContentManager.cs b/src/Ryujinx.HLE/FileSystem/ContentManager.cs index 3e93a8ee1..d63234509 100644 --- a/src/Ryujinx.HLE/FileSystem/ContentManager.cs +++ b/src/Ryujinx.HLE/FileSystem/ContentManager.cs @@ -551,7 +551,7 @@ namespace Ryujinx.HLE.FileSystem new DirectoryInfo(registeredDirectory).Delete(true); } - Directory.Move(temporaryDirectory, registeredDirectory); + Directory.Move(temporaryDirectory, registeredDirectory ?? string.Empty); LoadEntries(); } diff --git a/src/Ryujinx.HLE/HOS/Applets/SoftwareKeyboard/InlineResponses.cs b/src/Ryujinx.HLE/HOS/Applets/SoftwareKeyboard/InlineResponses.cs index 46e541a9e..db167e262 100644 --- a/src/Ryujinx.HLE/HOS/Applets/SoftwareKeyboard/InlineResponses.cs +++ b/src/Ryujinx.HLE/HOS/Applets/SoftwareKeyboard/InlineResponses.cs @@ -31,8 +31,12 @@ namespace Ryujinx.HLE.HOS.Applets.SoftwareKeyboard } } - writer.Write(bytes); - writer.Seek((int)maxSize - bytes.Length, SeekOrigin.Current); + if (bytes != null) + { + writer.Write(bytes); + writer.Seek((int)maxSize - bytes.Length, SeekOrigin.Current); + } + writer.Write((uint)text.Length); // String size return (uint)text.Length; // Return the cursor position at the end of the text diff --git a/src/Ryujinx.HLE/HOS/Kernel/Ipc/KServerPort.cs b/src/Ryujinx.HLE/HOS/Kernel/Ipc/KServerPort.cs index d4e0dbfb5..b32070c1a 100644 --- a/src/Ryujinx.HLE/HOS/Kernel/Ipc/KServerPort.cs +++ b/src/Ryujinx.HLE/HOS/Kernel/Ipc/KServerPort.cs @@ -62,7 +62,10 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc if (list.Count != 0) { - session = list.First.Value; + if (list.First != null) + { + session = list.First.Value; + } list.RemoveFirst(); } diff --git a/src/Ryujinx.HLE/HOS/Kernel/Memory/KPageTableBase.cs b/src/Ryujinx.HLE/HOS/Kernel/Memory/KPageTableBase.cs index b4eafab11..38afa377a 100644 --- a/src/Ryujinx.HLE/HOS/Kernel/Memory/KPageTableBase.cs +++ b/src/Ryujinx.HLE/HOS/Kernel/Memory/KPageTableBase.cs @@ -1369,44 +1369,50 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory LinkedListNode pageListNode = pageList.Nodes.First; - KPageNode pageNode = pageListNode.Value; - - ulong srcPa = pageNode.Address; - ulong srcPaPages = pageNode.PagesCount; - - foreach (KMemoryInfo info in IterateOverRange(address, endAddr)) + if (pageListNode != null) { - if (info.State != MemoryState.Unmapped) + KPageNode pageNode = pageListNode.Value; + + ulong srcPa = pageNode.Address; + ulong srcPaPages = pageNode.PagesCount; + + foreach (KMemoryInfo info in IterateOverRange(address, endAddr)) { - continue; - } - - ulong blockSize = GetSizeInRange(info, address, endAddr); - - ulong dstVaPages = blockSize / PageSize; - - ulong dstVa = GetAddrInRange(info, address); - - while (dstVaPages > 0) - { - if (srcPaPages == 0) + if (info.State != MemoryState.Unmapped) { - pageListNode = pageListNode.Next; - - pageNode = pageListNode.Value; - - srcPa = pageNode.Address; - srcPaPages = pageNode.PagesCount; + continue; } - ulong currentPagesCount = Math.Min(srcPaPages, dstVaPages); + ulong blockSize = GetSizeInRange(info, address, endAddr); - MapPages(dstVa, currentPagesCount, srcPa, KMemoryPermission.ReadAndWrite, MemoryMapFlags.Private); + ulong dstVaPages = blockSize / PageSize; - dstVa += currentPagesCount * PageSize; - srcPa += currentPagesCount * PageSize; - srcPaPages -= currentPagesCount; - dstVaPages -= currentPagesCount; + ulong dstVa = GetAddrInRange(info, address); + + while (dstVaPages > 0) + { + if (srcPaPages == 0) + { + pageListNode = pageListNode?.Next; + + if (pageListNode != null) + { + pageNode = pageListNode.Value; + } + + srcPa = pageNode.Address; + srcPaPages = pageNode.PagesCount; + } + + ulong currentPagesCount = Math.Min(srcPaPages, dstVaPages); + + MapPages(dstVa, currentPagesCount, srcPa, KMemoryPermission.ReadAndWrite, MemoryMapFlags.Private); + + dstVa += currentPagesCount * PageSize; + srcPa += currentPagesCount * PageSize; + srcPaPages -= currentPagesCount; + dstVaPages -= currentPagesCount; + } } } diff --git a/src/Ryujinx.HLE/HOS/Kernel/Memory/SharedMemoryStorage.cs b/src/Ryujinx.HLE/HOS/Kernel/Memory/SharedMemoryStorage.cs index 54ccad0ab..10aad7fc5 100644 --- a/src/Ryujinx.HLE/HOS/Kernel/Memory/SharedMemoryStorage.cs +++ b/src/Ryujinx.HLE/HOS/Kernel/Memory/SharedMemoryStorage.cs @@ -34,8 +34,11 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory { if (_pageList.Nodes.Count == 1) { - ulong address = _pageList.Nodes.First.Value.Address - DramMemoryMap.DramBase; - return ref _context.Memory.GetRef(address + offset); + if (_pageList.Nodes.First != null) + { + ulong address = _pageList.Nodes.First.Value.Address - DramMemoryMap.DramBase; + return ref _context.Memory.GetRef(address + offset); + } } throw new NotImplementedException("Non-contiguous shared memory is not yet supported."); diff --git a/src/Ryujinx.HLE/HOS/Kernel/Threading/KPriorityQueue.cs b/src/Ryujinx.HLE/HOS/Kernel/Threading/KPriorityQueue.cs index 41674a3a5..08f18be92 100644 --- a/src/Ryujinx.HLE/HOS/Kernel/Threading/KPriorityQueue.cs +++ b/src/Ryujinx.HLE/HOS/Kernel/Threading/KPriorityQueue.cs @@ -253,7 +253,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading thread.SiblingsPerCore[core] = queue.AddLast(thread); - return queue.First.Value; + return queue.First?.Value; } public void Unschedule(int prio, int core, KThread thread) diff --git a/src/Ryujinx.HLE/HOS/Kernel/Threading/KThread.cs b/src/Ryujinx.HLE/HOS/Kernel/Threading/KThread.cs index cf522453f..20671e028 100644 --- a/src/Ryujinx.HLE/HOS/Kernel/Threading/KThread.cs +++ b/src/Ryujinx.HLE/HOS/Kernel/Threading/KThread.cs @@ -1302,7 +1302,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading { Owner?.RemoveThread(this); - if (_tlsAddress != 0 && Owner.FreeThreadLocalStorage(_tlsAddress) != Result.Success) + if (_tlsAddress != 0 && Owner?.FreeThreadLocalStorage(_tlsAddress) != Result.Success) { throw new InvalidOperationException("Unexpected failure freeing thread local storage."); } diff --git a/src/Ryujinx.Horizon.Generators/Hipc/HipcGenerator.cs b/src/Ryujinx.Horizon.Generators/Hipc/HipcGenerator.cs index ae3509b13..8187292ba 100644 --- a/src/Ryujinx.Horizon.Generators/Hipc/HipcGenerator.cs +++ b/src/Ryujinx.Horizon.Generators/Hipc/HipcGenerator.cs @@ -61,42 +61,45 @@ namespace Ryujinx.Horizon.Generators.Hipc { HipcSyntaxReceiver syntaxReceiver = (HipcSyntaxReceiver)context.SyntaxReceiver; - foreach (var commandInterface in syntaxReceiver.CommandInterfaces) + if (syntaxReceiver?.CommandInterfaces != null) { - if (!NeedsIServiceObjectImplementation(context.Compilation, commandInterface.ClassDeclarationSyntax)) + foreach (var commandInterface in syntaxReceiver.CommandInterfaces) { - continue; - } + if (!NeedsIServiceObjectImplementation(context.Compilation, commandInterface.ClassDeclarationSyntax)) + { + continue; + } - CodeGenerator generator = new CodeGenerator(); - string className = commandInterface.ClassDeclarationSyntax.Identifier.ToString(); + CodeGenerator generator = new CodeGenerator(); + string className = commandInterface.ClassDeclarationSyntax.Identifier.ToString(); - generator.AppendLine("using Ryujinx.Horizon.Common;"); - generator.AppendLine("using Ryujinx.Horizon.Sdk.Sf;"); - generator.AppendLine("using Ryujinx.Horizon.Sdk.Sf.Cmif;"); - generator.AppendLine("using Ryujinx.Horizon.Sdk.Sf.Hipc;"); - generator.AppendLine("using System;"); - generator.AppendLine("using System.Collections.Frozen;"); - generator.AppendLine("using System.Collections.Generic;"); - generator.AppendLine("using System.Runtime.CompilerServices;"); - generator.AppendLine("using System.Runtime.InteropServices;"); - generator.AppendLine(); - generator.EnterScope($"namespace {GetNamespaceName(commandInterface.ClassDeclarationSyntax)}"); - generator.EnterScope($"partial class {className}"); - - GenerateMethodTable(generator, context.Compilation, commandInterface); - - foreach (var method in commandInterface.CommandImplementations) - { + generator.AppendLine("using Ryujinx.Horizon.Common;"); + generator.AppendLine("using Ryujinx.Horizon.Sdk.Sf;"); + generator.AppendLine("using Ryujinx.Horizon.Sdk.Sf.Cmif;"); + generator.AppendLine("using Ryujinx.Horizon.Sdk.Sf.Hipc;"); + generator.AppendLine("using System;"); + generator.AppendLine("using System.Collections.Frozen;"); + generator.AppendLine("using System.Collections.Generic;"); + generator.AppendLine("using System.Runtime.CompilerServices;"); + generator.AppendLine("using System.Runtime.InteropServices;"); generator.AppendLine(); + generator.EnterScope($"namespace {GetNamespaceName(commandInterface.ClassDeclarationSyntax)}"); + generator.EnterScope($"partial class {className}"); - GenerateMethod(generator, context.Compilation, method); + GenerateMethodTable(generator, context.Compilation, commandInterface); + + foreach (var method in commandInterface.CommandImplementations) + { + generator.AppendLine(); + + GenerateMethod(generator, context.Compilation, method); + } + + generator.LeaveScope(); + generator.LeaveScope(); + + context.AddSource($"{GetNamespaceName(commandInterface.ClassDeclarationSyntax)}.{className}.g.cs", generator.ToString()); } - - generator.LeaveScope(); - generator.LeaveScope(); - - context.AddSource($"{GetNamespaceName(commandInterface.ClassDeclarationSyntax)}.{className}.g.cs", generator.ToString()); } } @@ -191,11 +194,15 @@ namespace Ryujinx.Horizon.Generators.Hipc { ISymbol symbol = compilation.GetSemanticModel(syntaxNode.SyntaxTree).GetDeclaredSymbol(syntaxNode); - foreach (var attribute in symbol.GetAttributes()) + if (symbol != null) { - if (attribute.AttributeClass.ToDisplayString() == attributeName && (uint)argIndex < (uint)attribute.ConstructorArguments.Length) + foreach (var attribute in symbol.GetAttributes()) { - yield return attribute.ConstructorArguments[argIndex].ToCSharpString(); + if (attribute.AttributeClass?.ToDisplayString() == attributeName && + (uint)argIndex < (uint)attribute.ConstructorArguments.Length) + { + yield return attribute.ConstructorArguments[argIndex].ToCSharpString(); + } } } } @@ -507,18 +514,21 @@ namespace Ryujinx.Horizon.Generators.Hipc { TypeInfo typeInfo = compilation.GetSemanticModel(syntaxNode.SyntaxTree).GetTypeInfo(syntaxNode); - return typeInfo.Type.ToDisplayString(); + return typeInfo.Type?.ToDisplayString(); } private static string GetCanonicalTypeName(Compilation compilation, SyntaxNode syntaxNode) { TypeInfo typeInfo = compilation.GetSemanticModel(syntaxNode.SyntaxTree).GetTypeInfo(syntaxNode); - string typeName = typeInfo.Type.ToDisplayString(); + string typeName = typeInfo.Type?.ToDisplayString(); - int genericArgsStartIndex = typeName.IndexOf('<'); - if (genericArgsStartIndex >= 0) + if (typeName != null) { - return typeName.Substring(0, genericArgsStartIndex); + int genericArgsStartIndex = typeName.IndexOf('<'); + if (genericArgsStartIndex >= 0) + { + return typeName.Substring(0, genericArgsStartIndex); + } } return typeName; @@ -528,7 +538,7 @@ namespace Ryujinx.Horizon.Generators.Hipc { TypeInfo typeInfo = compilation.GetSemanticModel(syntaxNode.SyntaxTree).GetTypeInfo(syntaxNode); - return typeInfo.Type.SpecialType; + return typeInfo.Type?.SpecialType ?? SpecialType.None; } private static string GetTypeAlignmentExpression(Compilation compilation, SyntaxNode syntaxNode) @@ -539,7 +549,7 @@ namespace Ryujinx.Horizon.Generators.Hipc // "special" types are primitive types aligned to their own length. // Otherwise, assume that the type is a custom struct, that either defines an explicit alignment // or has an alignment of 1 which is the lowest possible value. - if (typeInfo.Type.SpecialType == SpecialType.None) + if (typeInfo.Type is { SpecialType: SpecialType.None }) { string pack = GetTypeFirstNamedAttributeAgument(compilation, syntaxNode, TypeStructLayoutAttribute, "Pack"); @@ -547,7 +557,7 @@ namespace Ryujinx.Horizon.Generators.Hipc } else { - return $"Unsafe.SizeOf<{typeInfo.Type.ToDisplayString()}>()"; + return $"Unsafe.SizeOf<{typeInfo.Type?.ToDisplayString()}>()"; } } @@ -555,13 +565,13 @@ namespace Ryujinx.Horizon.Generators.Hipc { ISymbol symbol = compilation.GetSemanticModel(syntaxNode.SyntaxTree).GetTypeInfo(syntaxNode).Type; - foreach (var attribute in symbol.GetAttributes()) + if (symbol != null) { - if (attribute.AttributeClass.ToDisplayString() == attributeName) + foreach (var attribute in symbol.GetAttributes()) { - foreach (var kv in attribute.NamedArguments) + if (attribute.AttributeClass?.ToDisplayString() == attributeName) { - if (kv.Key == argName) + foreach (var kv in attribute.NamedArguments.Where(kv => kv.Key == argName)) { return kv.Value.ToCSharpString(); } @@ -664,7 +674,7 @@ namespace Ryujinx.Horizon.Generators.Hipc { TypeInfo typeInfo = compilation.GetSemanticModel(syntaxNode.SyntaxTree).GetTypeInfo(syntaxNode); - return typeInfo.Type.IsUnmanagedType; + return typeInfo.Type is { IsUnmanagedType: true }; } private static bool IsMemory(Compilation compilation, ParameterSyntax parameter) @@ -707,10 +717,11 @@ namespace Ryujinx.Horizon.Generators.Hipc private static bool IsObject(Compilation compilation, ParameterSyntax parameter) { SyntaxNode syntaxNode = parameter.Type; - TypeInfo typeInfo = compilation.GetSemanticModel(syntaxNode.SyntaxTree).GetTypeInfo(syntaxNode); + TypeInfo typeInfo = compilation.GetSemanticModel(syntaxNode!.SyntaxTree).GetTypeInfo(syntaxNode); - return typeInfo.Type.ToDisplayString() == TypeIServiceObject || - typeInfo.Type.AllInterfaces.Any(x => x.ToDisplayString() == TypeIServiceObject); + return typeInfo.Type != null && + (typeInfo.Type.ToDisplayString() == TypeIServiceObject || + typeInfo.Type.AllInterfaces.Any(x => x.ToDisplayString() == TypeIServiceObject)); } private static bool IsProcessId(Compilation compilation, ParameterSyntax parameter) @@ -781,7 +792,7 @@ namespace Ryujinx.Horizon.Generators.Hipc private static bool NeedsIServiceObjectImplementation(Compilation compilation, ClassDeclarationSyntax classDeclarationSyntax) { ITypeSymbol type = compilation.GetSemanticModel(classDeclarationSyntax.SyntaxTree).GetDeclaredSymbol(classDeclarationSyntax); - var serviceObjectInterface = type.AllInterfaces.FirstOrDefault(x => x.ToDisplayString() == TypeIServiceObject); + var serviceObjectInterface = type?.AllInterfaces.FirstOrDefault(x => x.ToDisplayString() == TypeIServiceObject); var interfaceMember = serviceObjectInterface?.GetMembers().FirstOrDefault(x => x.Name == "GetCommandHandlers"); // Return true only if the class implements IServiceObject but does not actually implement the method diff --git a/src/Ryujinx.Horizon.Kernel.Generators/SyscallGenerator.cs b/src/Ryujinx.Horizon.Kernel.Generators/SyscallGenerator.cs index 272d934de..28f616ed1 100644 --- a/src/Ryujinx.Horizon.Kernel.Generators/SyscallGenerator.cs +++ b/src/Ryujinx.Horizon.Kernel.Generators/SyscallGenerator.cs @@ -147,20 +147,26 @@ namespace Ryujinx.Horizon.Kernel.Generators List syscalls = []; - foreach (var method in syntaxReceiver.SvcImplementations) + if (syntaxReceiver != null) { - GenerateMethod32(generator, context.Compilation, method); - GenerateMethod64(generator, context.Compilation, method); - - foreach (AttributeSyntax attribute in method.AttributeLists.SelectMany(attributeList => - attributeList.Attributes.Where(attribute => - GetCanonicalTypeName(context.Compilation, attribute) == TypeSvcAttribute))) + foreach (var method in syntaxReceiver.SvcImplementations) { - syscalls.AddRange(from attributeArg in attribute.ArgumentList.Arguments - where attributeArg.Expression.Kind() == SyntaxKind.NumericLiteralExpression - select (LiteralExpressionSyntax)attributeArg.Expression - into numericLiteral - select new SyscallIdAndName((int)numericLiteral.Token.Value, method.Identifier.Text)); + GenerateMethod32(generator, context.Compilation, method); + GenerateMethod64(generator, context.Compilation, method); + + foreach (AttributeSyntax attribute in method.AttributeLists.SelectMany(attributeList => + attributeList.Attributes.Where(attribute => + GetCanonicalTypeName(context.Compilation, attribute) == TypeSvcAttribute))) + { + if (attribute.ArgumentList != null) + { + syscalls.AddRange(from attributeArg in attribute.ArgumentList.Arguments + where attributeArg.Expression.Kind() == SyntaxKind.NumericLiteralExpression + select (LiteralExpressionSyntax)attributeArg.Expression + into numericLiteral + select new SyscallIdAndName((int)numericLiteral.Token.Value, method.Identifier.Text)); + } + } } } diff --git a/src/Ryujinx.Horizon/Arp/Ipc/Reader.cs b/src/Ryujinx.Horizon/Arp/Ipc/Reader.cs index de99c2ade..1d07a1055 100644 --- a/src/Ryujinx.Horizon/Arp/Ipc/Reader.cs +++ b/src/Ryujinx.Horizon/Arp/Ipc/Reader.cs @@ -127,7 +127,11 @@ namespace Ryujinx.Horizon.Arp.Ipc return ArpResult.InvalidInstanceId; } - applicationCertificate = _applicationInstanceManager.Entries[applicationInstanceId].Certificate.Value; + ApplicationCertificate? certificate = _applicationInstanceManager.Entries[applicationInstanceId].Certificate; + if (certificate != null) + { + applicationCertificate = certificate.Value; + } return Result.Success; } diff --git a/src/Ryujinx.Input/HLE/NpadController.cs b/src/Ryujinx.Input/HLE/NpadController.cs index b03b5b83a..8e0bd0996 100644 --- a/src/Ryujinx.Input/HLE/NpadController.cs +++ b/src/Ryujinx.Input/HLE/NpadController.cs @@ -510,7 +510,7 @@ namespace Ryujinx.Input.HLE { var keyboard = KeyboardDriver.GetGamepad("0") as IKeyboard; - KeyboardStateSnapshot keyboardState = keyboard.GetKeyboardStateSnapshot(); + KeyboardStateSnapshot keyboardState = keyboard?.GetKeyboardStateSnapshot(); KeyboardInput hidKeyboard = new() { @@ -520,14 +520,14 @@ namespace Ryujinx.Input.HLE foreach (HLEKeyboardMappingEntry entry in _keyMapping) { - ulong value = keyboardState.IsPressed(entry.TargetKey) ? 1UL : 0UL; + ulong value = keyboardState != null && keyboardState.IsPressed(entry.TargetKey) ? 1UL : 0UL; hidKeyboard.Keys[entry.Target / 0x40] |= (value << (entry.Target % 0x40)); } foreach (HLEKeyboardMappingEntry entry in _keyModifierMapping) { - int value = keyboardState.IsPressed(entry.TargetKey) ? 1 : 0; + int value = keyboardState != null && keyboardState.IsPressed(entry.TargetKey) ? 1 : 0; hidKeyboard.Modifier |= value << entry.Target; } diff --git a/src/Ryujinx.Input/HLE/NpadManager.cs b/src/Ryujinx.Input/HLE/NpadManager.cs index 8824dade6..29711bf4e 100644 --- a/src/Ryujinx.Input/HLE/NpadManager.cs +++ b/src/Ryujinx.Input/HLE/NpadManager.cs @@ -304,9 +304,12 @@ namespace Ryujinx.Input.HLE buttons |= 1 << 4; } - var position = IMouse.GetScreenPosition(mouseInput.Position, mouse.ClientSize, aspectRatio); + if (mouse != null) + { + var position = IMouse.GetScreenPosition(mouseInput.Position, mouse.ClientSize, aspectRatio); - _device.Hid.Mouse.Update((int)position.X, (int)position.Y, buttons, (int)mouseInput.Scroll.X, (int)mouseInput.Scroll.Y, true); + _device.Hid.Mouse.Update((int)position.X, (int)position.Y, buttons, (int)mouseInput.Scroll.X, (int)mouseInput.Scroll.Y, true); + } } else { diff --git a/src/Ryujinx.UI.Common/App/ApplicationLibrary.cs b/src/Ryujinx.UI.Common/App/ApplicationLibrary.cs index 45ce09905..6376b51da 100644 --- a/src/Ryujinx.UI.Common/App/ApplicationLibrary.cs +++ b/src/Ryujinx.UI.Common/App/ApplicationLibrary.cs @@ -88,11 +88,16 @@ namespace Ryujinx.UI.App.Common private static byte[] GetResourceBytes(string resourceName) { Stream resourceStream = Assembly.GetCallingAssembly().GetManifestResourceStream(resourceName); - byte[] resourceByteArray = new byte[resourceStream.Length]; + if (resourceStream != null) + { + byte[] resourceByteArray = new byte[resourceStream.Length]; - resourceStream.ReadExactly(resourceByteArray); + resourceStream.ReadExactly(resourceByteArray); - return resourceByteArray; + return resourceByteArray; + } + + return []; } /// The npdm file doesn't contain valid data. @@ -1178,7 +1183,7 @@ namespace Ryujinx.UI.App.Common { string extension = Path.GetExtension(applicationPath)?.ToLower(); - using FileStream file = new(applicationPath, FileMode.Open, FileAccess.Read); + using FileStream file = new(applicationPath ?? string.Empty, FileMode.Open, FileAccess.Read); if (extension == ".nsp" || extension == ".pfs0" || extension == ".xci") { diff --git a/src/Ryujinx.UI.Common/Helper/FileAssociationHelper.cs b/src/Ryujinx.UI.Common/Helper/FileAssociationHelper.cs index ede506bfa..9a2d1243e 100644 --- a/src/Ryujinx.UI.Common/Helper/FileAssociationHelper.cs +++ b/src/Ryujinx.UI.Common/Helper/FileAssociationHelper.cs @@ -152,7 +152,7 @@ namespace Ryujinx.UI.Common.Helper Logger.Debug?.Print(LogClass.Application, $"Adding type association {ext}"); using var openCmd = key.CreateSubKey(@"shell\open\command"); - openCmd.SetValue("", $"\"{Environment.ProcessPath}\" \"%1\""); + openCmd?.SetValue("", $"\"{Environment.ProcessPath}\" \"%1\""); Logger.Debug?.Print(LogClass.Application, $"Added type association {ext}"); } diff --git a/src/Ryujinx.UI.Common/SystemInfo/WindowsSystemInfo.cs b/src/Ryujinx.UI.Common/SystemInfo/WindowsSystemInfo.cs index bf49c2a66..40130adba 100644 --- a/src/Ryujinx.UI.Common/SystemInfo/WindowsSystemInfo.cs +++ b/src/Ryujinx.UI.Common/SystemInfo/WindowsSystemInfo.cs @@ -36,11 +36,11 @@ namespace Ryujinx.UI.Common.SystemInfo { foreach (var cpuObj in cpuObjs) { - return cpuObj["Name"].ToString().Trim(); + return cpuObj["Name"].ToString()?.Trim(); } } - return Environment.GetEnvironmentVariable("PROCESSOR_IDENTIFIER").Trim(); + return Environment.GetEnvironmentVariable("PROCESSOR_IDENTIFIER")?.Trim(); } [StructLayout(LayoutKind.Sequential)] diff --git a/src/Ryujinx/App.axaml.cs b/src/Ryujinx/App.axaml.cs index cd4416aa1..a42306ef5 100644 --- a/src/Ryujinx/App.axaml.cs +++ b/src/Ryujinx/App.axaml.cs @@ -84,7 +84,7 @@ namespace Ryujinx.Ava if (result == UserResult.Yes) { var path = Environment.ProcessPath; - var proc = Process.Start(path, CommandLineState.Arguments); + var proc = Process.Start(path ?? string.Empty, CommandLineState.Arguments); desktop.Shutdown(); Environment.Exit(0); } @@ -144,7 +144,7 @@ namespace Ryujinx.Ava public static ThemeVariant DetectSystemTheme() { - if (Current is App app) + if (Current is App { PlatformSettings: not null } app) { var colorValues = app.PlatformSettings.GetColorValues(); diff --git a/src/Ryujinx/Modules/Updater/Updater.cs b/src/Ryujinx/Modules/Updater/Updater.cs index 36bdfd342..a8b0db9ef 100644 --- a/src/Ryujinx/Modules/Updater/Updater.cs +++ b/src/Ryujinx/Modules/Updater/Updater.cs @@ -192,7 +192,10 @@ namespace Ryujinx.Modules HttpResponseMessage message = await buildSizeClient.GetAsync(new Uri(_buildUrl), HttpCompletionOption.ResponseHeadersRead); - _buildSize = message.Content.Headers.ContentRange.Length.Value; + if (message.Content.Headers.ContentRange?.Length != null) + { + _buildSize = message.Content.Headers.ContentRange.Length.Value; + } } catch (Exception ex) { @@ -376,10 +379,14 @@ namespace Ryujinx.Modules client.DownloadProgressChanged += (_, args) => { - int index = (int)args.UserState; + if (args.UserState != null) + { + int index = (int)args.UserState; + + Interlocked.Add(ref totalProgressPercentage, -1 * progressPercentage[index]); + Interlocked.Exchange(ref progressPercentage[index], args.ProgressPercentage); + } - Interlocked.Add(ref totalProgressPercentage, -1 * progressPercentage[index]); - Interlocked.Exchange(ref progressPercentage[index], args.ProgressPercentage); Interlocked.Add(ref totalProgressPercentage, args.ProgressPercentage); taskDialog.SetProgressBarState(totalProgressPercentage / ConnectionCount, TaskDialogProgressState.Normal); @@ -387,18 +394,22 @@ namespace Ryujinx.Modules client.DownloadDataCompleted += (_, args) => { - int index = (int)args.UserState; - - if (args.Cancelled) + if (args.UserState != null) { - webClients[index].Dispose(); + int index = (int)args.UserState; - taskDialog.Hide(); + if (args.Cancelled) + { + webClients[index].Dispose(); - return; + taskDialog.Hide(); + + return; + } + + list[index] = args.Result; } - list[index] = args.Result; Interlocked.Increment(ref completedRequests); if (Equals(completedRequests, ConnectionCount)) @@ -465,25 +476,28 @@ namespace Ryujinx.Modules using Stream remoteFileStream = response.Content.ReadAsStreamAsync().Result; using Stream updateFileStream = File.Open(updateFile, FileMode.Create); - long totalBytes = response.Content.Headers.ContentLength.Value; - long byteWritten = 0; - - byte[] buffer = new byte[32 * 1024]; - - while (true) + if (response.Content.Headers.ContentLength != null) { - int readSize = remoteFileStream.Read(buffer); + long totalBytes = response.Content.Headers.ContentLength.Value; + long byteWritten = 0; - if (readSize == 0) + byte[] buffer = new byte[32 * 1024]; + + while (true) { - break; + int readSize = remoteFileStream.Read(buffer); + + if (readSize == 0) + { + break; + } + + byteWritten += readSize; + + taskDialog.SetProgressBarState(GetPercentage(byteWritten, totalBytes), TaskDialogProgressState.Normal); + + updateFileStream.Write(buffer, 0, readSize); } - - byteWritten += readSize; - - taskDialog.SetProgressBarState(GetPercentage(byteWritten, totalBytes), TaskDialogProgressState.Normal); - - updateFileStream.Write(buffer, 0, readSize); } InstallUpdate(taskDialog, updateFile); @@ -524,7 +538,7 @@ namespace Ryujinx.Modules string outPath = Path.Combine(outputDirectoryPath, tarEntry.Name); - Directory.CreateDirectory(Path.GetDirectoryName(outPath)); + Directory.CreateDirectory(Path.GetDirectoryName(outPath) ?? string.Empty); using FileStream outStream = File.OpenWrite(outPath); tarStream.CopyEntryContents(outStream); @@ -560,7 +574,7 @@ namespace Ryujinx.Modules string outPath = Path.Combine(outputDirectoryPath, zipEntry.Name); - Directory.CreateDirectory(Path.GetDirectoryName(outPath)); + Directory.CreateDirectory(Path.GetDirectoryName(outPath) ?? string.Empty); using Stream zipStream = zipFile.GetInputStream(zipEntry); using FileStream outStream = File.OpenWrite(outPath); diff --git a/src/Ryujinx/UI/Applet/AvaloniaDynamicTextInputHandler.cs b/src/Ryujinx/UI/Applet/AvaloniaDynamicTextInputHandler.cs index 0e7cfb8e6..5b5a96423 100644 --- a/src/Ryujinx/UI/Applet/AvaloniaDynamicTextInputHandler.cs +++ b/src/Ryujinx/UI/Applet/AvaloniaDynamicTextInputHandler.cs @@ -25,9 +25,9 @@ namespace Ryujinx.Ava.UI.Applet { _parent = parent; - (_parent.InputManager.KeyboardDriver as AvaloniaKeyboardDriver).KeyPressed += AvaloniaDynamicTextInputHandler_KeyPressed; - (_parent.InputManager.KeyboardDriver as AvaloniaKeyboardDriver).KeyRelease += AvaloniaDynamicTextInputHandler_KeyRelease; - (_parent.InputManager.KeyboardDriver as AvaloniaKeyboardDriver).TextInput += AvaloniaDynamicTextInputHandler_TextInput; + ((AvaloniaKeyboardDriver)_parent.InputManager.KeyboardDriver).KeyPressed += AvaloniaDynamicTextInputHandler_KeyPressed; + ((AvaloniaKeyboardDriver)_parent.InputManager.KeyboardDriver).KeyRelease += AvaloniaDynamicTextInputHandler_KeyRelease; + ((AvaloniaKeyboardDriver)_parent.InputManager.KeyboardDriver).TextInput += AvaloniaDynamicTextInputHandler_TextInput; _hiddenTextBox = _parent.HiddenTextBox; @@ -118,9 +118,9 @@ namespace Ryujinx.Ava.UI.Applet public void Dispose() { - (_parent.InputManager.KeyboardDriver as AvaloniaKeyboardDriver).KeyPressed -= AvaloniaDynamicTextInputHandler_KeyPressed; - (_parent.InputManager.KeyboardDriver as AvaloniaKeyboardDriver).KeyRelease -= AvaloniaDynamicTextInputHandler_KeyRelease; - (_parent.InputManager.KeyboardDriver as AvaloniaKeyboardDriver).TextInput -= AvaloniaDynamicTextInputHandler_TextInput; + ((AvaloniaKeyboardDriver)_parent.InputManager.KeyboardDriver).KeyPressed -= AvaloniaDynamicTextInputHandler_KeyPressed; + ((AvaloniaKeyboardDriver)_parent.InputManager.KeyboardDriver).KeyRelease -= AvaloniaDynamicTextInputHandler_KeyRelease; + ((AvaloniaKeyboardDriver)_parent.InputManager.KeyboardDriver).TextInput -= AvaloniaDynamicTextInputHandler_TextInput; _textChangedSubscription?.Dispose(); _selectionStartChangedSubscription?.Dispose(); diff --git a/src/Ryujinx/UI/Controls/ApplicationContextMenu.axaml.cs b/src/Ryujinx/UI/Controls/ApplicationContextMenu.axaml.cs index 94874e462..a939d6ad9 100644 --- a/src/Ryujinx/UI/Controls/ApplicationContextMenu.axaml.cs +++ b/src/Ryujinx/UI/Controls/ApplicationContextMenu.axaml.cs @@ -111,7 +111,7 @@ namespace Ryujinx.Ava.UI.Controls viewModel.VirtualFileSystem, viewModel.SelectedApplication.IdString, viewModel.SelectedApplication.Name, - viewModel.SelectedApplication.Path).ShowDialog(viewModel.TopLevel as Window); + viewModel.SelectedApplication.Path).ShowDialog((Window)viewModel.TopLevel); } } @@ -396,9 +396,12 @@ namespace Ryujinx.Ava.UI.Controls viewModel.SelectedApplication.Name); var iconFile = await result[0].CreateFileAsync(selectedApp.IdString + ".png"); - await using var fileStream = await iconFile.OpenWriteAsync(); + if (iconFile != null) + { + await using var fileStream = await iconFile.OpenWriteAsync(); - fileStream.Write(selectedApp.Icon); + fileStream.Write(selectedApp.Icon); + } } } diff --git a/src/Ryujinx/UI/Controls/ApplicationGridView.axaml.cs b/src/Ryujinx/UI/Controls/ApplicationGridView.axaml.cs index 38c59b757..cdb4581e3 100644 --- a/src/Ryujinx/UI/Controls/ApplicationGridView.axaml.cs +++ b/src/Ryujinx/UI/Controls/ApplicationGridView.axaml.cs @@ -37,7 +37,7 @@ namespace Ryujinx.Ava.UI.Controls private void SearchBox_OnKeyUp(object sender, KeyEventArgs args) { - (DataContext as MainWindowViewModel).SearchText = (sender as TextBox).Text; + (DataContext as MainWindowViewModel).SearchText = (sender as TextBox)?.Text; } } } diff --git a/src/Ryujinx/UI/Controls/ApplicationListView.axaml.cs b/src/Ryujinx/UI/Controls/ApplicationListView.axaml.cs index 4be72bb52..da029bbff 100644 --- a/src/Ryujinx/UI/Controls/ApplicationListView.axaml.cs +++ b/src/Ryujinx/UI/Controls/ApplicationListView.axaml.cs @@ -38,7 +38,7 @@ namespace Ryujinx.Ava.UI.Controls private void SearchBox_OnKeyUp(object sender, KeyEventArgs args) { - (DataContext as MainWindowViewModel).SearchText = (sender as TextBox).Text; + (DataContext as MainWindowViewModel).SearchText = (sender as TextBox)?.Text; } private async void IdString_OnClick(object sender, RoutedEventArgs e) diff --git a/src/Ryujinx/UI/Models/SaveModel.cs b/src/Ryujinx/UI/Models/SaveModel.cs index 181295b06..faeb16377 100644 --- a/src/Ryujinx/UI/Models/SaveModel.cs +++ b/src/Ryujinx/UI/Models/SaveModel.cs @@ -52,8 +52,8 @@ namespace Ryujinx.Ava.UI.Models if (InGameList) { - Icon = appData.Icon; - Title = appData.Name; + Icon = appData?.Icon; + Title = appData?.Name; } else { diff --git a/src/Ryujinx/UI/Models/UserProfile.cs b/src/Ryujinx/UI/Models/UserProfile.cs index 7a9237fe1..36d0678aa 100644 --- a/src/Ryujinx/UI/Models/UserProfile.cs +++ b/src/Ryujinx/UI/Models/UserProfile.cs @@ -88,7 +88,7 @@ namespace Ryujinx.Ava.UI.Models private void UpdateBackground() { var currentApplication = Avalonia.Application.Current; - currentApplication.Styles.TryGetResource("ControlFillColorSecondary", currentApplication.ActualThemeVariant, out object color); + currentApplication!.Styles.TryGetResource("ControlFillColorSecondary", currentApplication.ActualThemeVariant, out object color); if (color is not null) { diff --git a/src/Ryujinx/UI/Renderer/EmbeddedWindow.cs b/src/Ryujinx/UI/Renderer/EmbeddedWindow.cs index f9cc20f93..256f723b2 100644 --- a/src/Ryujinx/UI/Renderer/EmbeddedWindow.cs +++ b/src/Ryujinx/UI/Renderer/EmbeddedWindow.cs @@ -127,8 +127,11 @@ namespace Ryujinx.Ava.UI.Renderer X11Window = PlatformHelper.CreateOpenGLWindow(new FramebufferFormat(new ColorFormat(8, 8, 8, 0), 16, 0, ColorFormat.Zero, 0, 2, false), 0, 0, 100, 100) as GLXWindow; } - WindowHandle = X11Window.WindowHandle.RawHandle; - X11Display = X11Window.DisplayHandle.RawHandle; + if (X11Window != null) + { + WindowHandle = X11Window.WindowHandle.RawHandle; + X11Display = X11Window.DisplayHandle.RawHandle; + } return new PlatformHandle(WindowHandle, "X11"); } diff --git a/src/Ryujinx/UI/ViewModels/AppListFavoriteComparable.cs b/src/Ryujinx/UI/ViewModels/AppListFavoriteComparable.cs index e80984508..71a143494 100644 --- a/src/Ryujinx/UI/ViewModels/AppListFavoriteComparable.cs +++ b/src/Ryujinx/UI/ViewModels/AppListFavoriteComparable.cs @@ -37,7 +37,7 @@ namespace Ryujinx.Ava.UI.ViewModels return app.Favorite ? -1 : 1; } - throw new InvalidCastException($"Cannot cast {o.GetType()} to {nameof(AppListFavoriteComparable)}"); + throw new InvalidCastException($"Cannot cast {o?.GetType()} to {nameof(AppListFavoriteComparable)}"); } } } diff --git a/src/Ryujinx/UI/ViewModels/DownloadableContentManagerViewModel.cs b/src/Ryujinx/UI/ViewModels/DownloadableContentManagerViewModel.cs index e651baa22..7bcc4bdd2 100644 --- a/src/Ryujinx/UI/ViewModels/DownloadableContentManagerViewModel.cs +++ b/src/Ryujinx/UI/ViewModels/DownloadableContentManagerViewModel.cs @@ -92,9 +92,9 @@ namespace Ryujinx.Ava.UI.ViewModels _applicationData = applicationData; - if (Application.Current.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop) + if (Application.Current?.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop) { - _storageProvider = desktop.MainWindow.StorageProvider; + _storageProvider = desktop.MainWindow?.StorageProvider; } LoadDownloadableContents(); diff --git a/src/Ryujinx/UI/ViewModels/Input/InputViewModel.cs b/src/Ryujinx/UI/ViewModels/Input/InputViewModel.cs index 1c230914a..9730ef07e 100644 --- a/src/Ryujinx/UI/ViewModels/Input/InputViewModel.cs +++ b/src/Ryujinx/UI/ViewModels/Input/InputViewModel.cs @@ -254,10 +254,13 @@ namespace Ryujinx.Ava.UI.ViewModels.Input AvaloniaKeyboardDriver = new AvaloniaKeyboardDriver(owner); - _mainWindow.InputManager.GamepadDriver.OnGamepadConnected += HandleOnGamepadConnected; - _mainWindow.InputManager.GamepadDriver.OnGamepadDisconnected += HandleOnGamepadDisconnected; + if (_mainWindow != null) + { + _mainWindow.InputManager.GamepadDriver.OnGamepadConnected += HandleOnGamepadConnected; + _mainWindow.InputManager.GamepadDriver.OnGamepadDisconnected += HandleOnGamepadDisconnected; - _mainWindow.ViewModel.AppHost?.NpadManager.BlockInputUpdates(); + _mainWindow.ViewModel.AppHost?.NpadManager.BlockInputUpdates(); + } _isLoaded = false; @@ -783,11 +786,14 @@ namespace Ryujinx.Ava.UI.ViewModels.Input config = (ConfigViewModel as ControllerInputViewModel)?.Config.GetConfig(); } - config.ControllerType = Controllers[_controller].Type; + if (config != null) + { + config.ControllerType = Controllers[_controller].Type; - string jsonString = JsonHelper.Serialize(config, _serializerContext.InputConfig); + string jsonString = JsonHelper.Serialize(config, _serializerContext.InputConfig); - await File.WriteAllTextAsync(path, jsonString); + await File.WriteAllTextAsync(path, jsonString); + } LoadProfiles(); } diff --git a/src/Ryujinx/UI/ViewModels/MainWindowViewModel.cs b/src/Ryujinx/UI/ViewModels/MainWindowViewModel.cs index 3ef9b4e62..2df1f8231 100644 --- a/src/Ryujinx/UI/ViewModels/MainWindowViewModel.cs +++ b/src/Ryujinx/UI/ViewModels/MainWindowViewModel.cs @@ -1332,7 +1332,7 @@ namespace Ryujinx.Ava.UI.ViewModels } catch (MissingKeyException ex) { - if (Application.Current.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop) + if (Application.Current?.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop) { Logger.Error?.Print(LogClass.Application, ex.ToString()); @@ -1553,7 +1553,7 @@ namespace Ryujinx.Ava.UI.ViewModels { Dispatcher.UIThread.InvokeAsync(() => { - Application.Current.Styles.TryGetResource(args.VSyncMode, + Application.Current!.Styles.TryGetResource(args.VSyncMode, Application.Current.ActualThemeVariant, out object color); diff --git a/src/Ryujinx/UI/ViewModels/ModManagerViewModel.cs b/src/Ryujinx/UI/ViewModels/ModManagerViewModel.cs index 8012695fc..7d0876acf 100644 --- a/src/Ryujinx/UI/ViewModels/ModManagerViewModel.cs +++ b/src/Ryujinx/UI/ViewModels/ModManagerViewModel.cs @@ -279,7 +279,7 @@ namespace Ryujinx.Ava.UI.ViewModels foreach (var dir in directories) { - string dirToCreate = dir.Replace(directory.Parent.ToString(), destinationDir); + string dirToCreate = dir.Replace(directory.Parent?.ToString() ?? string.Empty, destinationDir); // Mod already exists if (Directory.Exists(dirToCreate)) @@ -302,7 +302,7 @@ namespace Ryujinx.Ava.UI.ViewModels foreach (var file in files) { - File.Copy(file, file.Replace(directory.Parent.ToString(), destinationDir), true); + File.Copy(file, file.Replace(directory.Parent?.ToString() ?? string.Empty, destinationDir), true); } LoadMods(_applicationId, _installedDlcIds); diff --git a/src/Ryujinx/UI/ViewModels/TitleUpdateViewModel.cs b/src/Ryujinx/UI/ViewModels/TitleUpdateViewModel.cs index a6be45eea..debfe6e3d 100644 --- a/src/Ryujinx/UI/ViewModels/TitleUpdateViewModel.cs +++ b/src/Ryujinx/UI/ViewModels/TitleUpdateViewModel.cs @@ -75,9 +75,9 @@ namespace Ryujinx.Ava.UI.ViewModels ApplicationData = applicationData; - if (Application.Current.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop) + if (Application.Current?.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop) { - StorageProvider = desktop.MainWindow.StorageProvider; + StorageProvider = desktop.MainWindow?.StorageProvider; } LoadUpdates(); diff --git a/src/Ryujinx/UI/ViewModels/XCITrimmerViewModel.cs b/src/Ryujinx/UI/ViewModels/XCITrimmerViewModel.cs index fbd491e07..918d392d6 100644 --- a/src/Ryujinx/UI/ViewModels/XCITrimmerViewModel.cs +++ b/src/Ryujinx/UI/ViewModels/XCITrimmerViewModel.cs @@ -268,7 +268,11 @@ namespace Ryujinx.Ava.UI.ViewModels result = String.Compare(x?.Name, y?.Name, StringComparison.Ordinal); break; case SortField.Saved: - result = x.PotentialSavingsB.CompareTo(y.PotentialSavingsB); + if (x != null && y != null) + { + result = x.PotentialSavingsB.CompareTo(y.PotentialSavingsB); + } + break; } diff --git a/src/Ryujinx/UI/Views/Input/ControllerInputView.axaml.cs b/src/Ryujinx/UI/Views/Input/ControllerInputView.axaml.cs index dcf8e3a3d..912dd45fe 100644 --- a/src/Ryujinx/UI/Views/Input/ControllerInputView.axaml.cs +++ b/src/Ryujinx/UI/Views/Input/ControllerInputView.axaml.cs @@ -70,8 +70,12 @@ namespace Ryujinx.Ava.UI.Views.Input { var viewModel = (DataContext as ControllerInputViewModel); - viewModel.ParentModel.IsModified = true; - _changeSlider = (float)check.Value; + if (viewModel != null) + { + viewModel.ParentModel.IsModified = true; + } + + _changeSlider = (float)check.Value; } } } @@ -82,9 +86,11 @@ namespace Ryujinx.Ava.UI.Views.Input { if ((bool)check.IsPointerOver) { + if (DataContext is ControllerInputViewModel viewModel) + { + viewModel.ParentModel.IsModified = true; + } - var viewModel = (DataContext as ControllerInputViewModel); - viewModel.ParentModel.IsModified = true; _currentAssigner?.Cancel(); _currentAssigner = null; } @@ -96,7 +102,7 @@ namespace Ryujinx.Ava.UI.Views.Input { if (sender is ToggleButton button ) { - if ((bool)button.IsChecked) + if (button.IsChecked != null && (bool)button.IsChecked) { if (_currentAssigner != null && button == _currentAssigner.ToggledButton) { @@ -233,7 +239,7 @@ namespace Ryujinx.Ava.UI.Views.Input var controllerInputViewModel = DataContext as ControllerInputViewModel; assigner = new GamepadButtonAssigner( - controllerInputViewModel.ParentModel.SelectedGamepad, + controllerInputViewModel?.ParentModel.SelectedGamepad, (controllerInputViewModel.ParentModel.Config as StandardControllerInputConfig).TriggerThreshold, forStick); diff --git a/src/Ryujinx/UI/Views/Input/InputView.axaml.cs b/src/Ryujinx/UI/Views/Input/InputView.axaml.cs index 5fda7ef6a..3803d7fc7 100644 --- a/src/Ryujinx/UI/Views/Input/InputView.axaml.cs +++ b/src/Ryujinx/UI/Views/Input/InputView.axaml.cs @@ -72,7 +72,10 @@ namespace Ryujinx.Ava.UI.Views.Input { ViewModel.IsModified = true; var player = (PlayerModel)e.AddedItems[0]; - ViewModel.PlayerId = player.Id; + if (player != null) + { + ViewModel.PlayerId = player.Id; + } } } } diff --git a/src/Ryujinx/UI/Views/Input/KeyboardInputView.axaml.cs b/src/Ryujinx/UI/Views/Input/KeyboardInputView.axaml.cs index f17c7496c..384e09df3 100644 --- a/src/Ryujinx/UI/Views/Input/KeyboardInputView.axaml.cs +++ b/src/Ryujinx/UI/Views/Input/KeyboardInputView.axaml.cs @@ -43,7 +43,7 @@ namespace Ryujinx.Ava.UI.Views.Input { if (sender is ToggleButton button) { - if ((bool)button.IsChecked) + if (button.IsChecked != null && (bool)button.IsChecked) { if (_currentAssigner != null && button == _currentAssigner.ToggledButton) { @@ -60,107 +60,110 @@ namespace Ryujinx.Ava.UI.Views.Input var viewModel = (DataContext as KeyboardInputViewModel); - IKeyboard keyboard = (IKeyboard)viewModel.ParentModel.AvaloniaKeyboardDriver.GetGamepad("0"); // Open Avalonia keyboard for cancel operations. - IButtonAssigner assigner = CreateButtonAssigner(); - - _currentAssigner.ButtonAssigned += (sender, e) => + if (viewModel != null) { - if (e.ButtonValue.HasValue) + IKeyboard keyboard = (IKeyboard)viewModel.ParentModel.AvaloniaKeyboardDriver.GetGamepad("0"); // Open Avalonia keyboard for cancel operations. + IButtonAssigner assigner = CreateButtonAssigner(); + + _currentAssigner.ButtonAssigned += (sender, e) => { - var buttonValue = e.ButtonValue.Value; - viewModel.ParentModel.IsModified = true; - - switch (button.Name) + if (e.ButtonValue.HasValue) { - case "ButtonZl": - viewModel.Config.ButtonZl = buttonValue.AsHidType(); - break; - case "ButtonL": - viewModel.Config.ButtonL = buttonValue.AsHidType(); - break; - case "ButtonMinus": - viewModel.Config.ButtonMinus = buttonValue.AsHidType(); - break; - case "LeftStickButton": - viewModel.Config.LeftStickButton = buttonValue.AsHidType(); - break; - case "LeftStickUp": - viewModel.Config.LeftStickUp = buttonValue.AsHidType(); - break; - case "LeftStickDown": - viewModel.Config.LeftStickDown = buttonValue.AsHidType(); - break; - case "LeftStickRight": - viewModel.Config.LeftStickRight = buttonValue.AsHidType(); - break; - case "LeftStickLeft": - viewModel.Config.LeftStickLeft = buttonValue.AsHidType(); - break; - case "DpadUp": - viewModel.Config.DpadUp = buttonValue.AsHidType(); - break; - case "DpadDown": - viewModel.Config.DpadDown = buttonValue.AsHidType(); - break; - case "DpadLeft": - viewModel.Config.DpadLeft = buttonValue.AsHidType(); - break; - case "DpadRight": - viewModel.Config.DpadRight = buttonValue.AsHidType(); - break; - case "LeftButtonSr": - viewModel.Config.LeftButtonSr = buttonValue.AsHidType(); - break; - case "LeftButtonSl": - viewModel.Config.LeftButtonSl = buttonValue.AsHidType(); - break; - case "RightButtonSr": - viewModel.Config.RightButtonSr = buttonValue.AsHidType(); - break; - case "RightButtonSl": - viewModel.Config.RightButtonSl = buttonValue.AsHidType(); - break; - case "ButtonZr": - viewModel.Config.ButtonZr = buttonValue.AsHidType(); - break; - case "ButtonR": - viewModel.Config.ButtonR = buttonValue.AsHidType(); - break; - case "ButtonPlus": - viewModel.Config.ButtonPlus = buttonValue.AsHidType(); - break; - case "ButtonA": - viewModel.Config.ButtonA = buttonValue.AsHidType(); - break; - case "ButtonB": - viewModel.Config.ButtonB = buttonValue.AsHidType(); - break; - case "ButtonX": - viewModel.Config.ButtonX = buttonValue.AsHidType(); - break; - case "ButtonY": - viewModel.Config.ButtonY = buttonValue.AsHidType(); - break; - case "RightStickButton": - viewModel.Config.RightStickButton = buttonValue.AsHidType(); - break; - case "RightStickUp": - viewModel.Config.RightStickUp = buttonValue.AsHidType(); - break; - case "RightStickDown": - viewModel.Config.RightStickDown = buttonValue.AsHidType(); - break; - case "RightStickRight": - viewModel.Config.RightStickRight = buttonValue.AsHidType(); - break; - case "RightStickLeft": - viewModel.Config.RightStickLeft = buttonValue.AsHidType(); - break; - } - } - }; + var buttonValue = e.ButtonValue.Value; + viewModel.ParentModel.IsModified = true; - _currentAssigner.GetInputAndAssign(assigner, keyboard); + switch (button.Name) + { + case "ButtonZl": + viewModel.Config.ButtonZl = buttonValue.AsHidType(); + break; + case "ButtonL": + viewModel.Config.ButtonL = buttonValue.AsHidType(); + break; + case "ButtonMinus": + viewModel.Config.ButtonMinus = buttonValue.AsHidType(); + break; + case "LeftStickButton": + viewModel.Config.LeftStickButton = buttonValue.AsHidType(); + break; + case "LeftStickUp": + viewModel.Config.LeftStickUp = buttonValue.AsHidType(); + break; + case "LeftStickDown": + viewModel.Config.LeftStickDown = buttonValue.AsHidType(); + break; + case "LeftStickRight": + viewModel.Config.LeftStickRight = buttonValue.AsHidType(); + break; + case "LeftStickLeft": + viewModel.Config.LeftStickLeft = buttonValue.AsHidType(); + break; + case "DpadUp": + viewModel.Config.DpadUp = buttonValue.AsHidType(); + break; + case "DpadDown": + viewModel.Config.DpadDown = buttonValue.AsHidType(); + break; + case "DpadLeft": + viewModel.Config.DpadLeft = buttonValue.AsHidType(); + break; + case "DpadRight": + viewModel.Config.DpadRight = buttonValue.AsHidType(); + break; + case "LeftButtonSr": + viewModel.Config.LeftButtonSr = buttonValue.AsHidType(); + break; + case "LeftButtonSl": + viewModel.Config.LeftButtonSl = buttonValue.AsHidType(); + break; + case "RightButtonSr": + viewModel.Config.RightButtonSr = buttonValue.AsHidType(); + break; + case "RightButtonSl": + viewModel.Config.RightButtonSl = buttonValue.AsHidType(); + break; + case "ButtonZr": + viewModel.Config.ButtonZr = buttonValue.AsHidType(); + break; + case "ButtonR": + viewModel.Config.ButtonR = buttonValue.AsHidType(); + break; + case "ButtonPlus": + viewModel.Config.ButtonPlus = buttonValue.AsHidType(); + break; + case "ButtonA": + viewModel.Config.ButtonA = buttonValue.AsHidType(); + break; + case "ButtonB": + viewModel.Config.ButtonB = buttonValue.AsHidType(); + break; + case "ButtonX": + viewModel.Config.ButtonX = buttonValue.AsHidType(); + break; + case "ButtonY": + viewModel.Config.ButtonY = buttonValue.AsHidType(); + break; + case "RightStickButton": + viewModel.Config.RightStickButton = buttonValue.AsHidType(); + break; + case "RightStickUp": + viewModel.Config.RightStickUp = buttonValue.AsHidType(); + break; + case "RightStickDown": + viewModel.Config.RightStickDown = buttonValue.AsHidType(); + break; + case "RightStickRight": + viewModel.Config.RightStickRight = buttonValue.AsHidType(); + break; + case "RightStickLeft": + viewModel.Config.RightStickLeft = buttonValue.AsHidType(); + break; + } + } + }; + + _currentAssigner.GetInputAndAssign(assigner, keyboard); + } } else { @@ -193,7 +196,7 @@ namespace Ryujinx.Ava.UI.Views.Input { IButtonAssigner assigner; - assigner = new KeyboardKeyAssigner((IKeyboard)(DataContext as KeyboardInputViewModel).ParentModel.SelectedGamepad); + assigner = new KeyboardKeyAssigner((IKeyboard)(DataContext as KeyboardInputViewModel)?.ParentModel.SelectedGamepad); return assigner; } diff --git a/src/Ryujinx/UI/Views/Main/MainViewControls.axaml.cs b/src/Ryujinx/UI/Views/Main/MainViewControls.axaml.cs index 02fd1bf5d..8a844345b 100644 --- a/src/Ryujinx/UI/Views/Main/MainViewControls.axaml.cs +++ b/src/Ryujinx/UI/Views/Main/MainViewControls.axaml.cs @@ -34,7 +34,7 @@ namespace Ryujinx.Ava.UI.Views.Main { if (sender is RadioButton button) { - ViewModel.Sort(Enum.Parse(button.Tag.ToString())); + ViewModel.Sort(Enum.Parse(button.Tag?.ToString() ?? string.Empty)); } } @@ -42,7 +42,7 @@ namespace Ryujinx.Ava.UI.Views.Main { if (sender is RadioButton button) { - ViewModel.Sort(button.Tag.ToString() != "Descending"); + ViewModel.Sort(button.Tag?.ToString() != "Descending"); } } diff --git a/src/Ryujinx/UI/Views/Settings/SettingsHotkeysView.axaml.cs b/src/Ryujinx/UI/Views/Settings/SettingsHotkeysView.axaml.cs index 35e67c12c..5740a895d 100644 --- a/src/Ryujinx/UI/Views/Settings/SettingsHotkeysView.axaml.cs +++ b/src/Ryujinx/UI/Views/Settings/SettingsHotkeysView.axaml.cs @@ -46,7 +46,7 @@ namespace Ryujinx.Ava.UI.Views.Settings { if (sender is ToggleButton button) { - if ((bool)button.IsChecked) + if (button.IsChecked != null && (bool)button.IsChecked) { if (_currentAssigner != null && button == _currentAssigner.ToggledButton) { @@ -69,41 +69,44 @@ namespace Ryujinx.Ava.UI.Views.Settings var viewModel = (DataContext) as SettingsViewModel; var buttonValue = e.ButtonValue.Value; - switch (button.Name) + if (viewModel != null) { - case "ToggleVSyncMode": - viewModel.KeyboardHotkey.ToggleVSyncMode = buttonValue.AsHidType(); - break; - case "Screenshot": - viewModel.KeyboardHotkey.Screenshot = buttonValue.AsHidType(); - break; - case "ShowUI": - viewModel.KeyboardHotkey.ShowUI = buttonValue.AsHidType(); - break; - case "Pause": - viewModel.KeyboardHotkey.Pause = buttonValue.AsHidType(); - break; - case "ToggleMute": - viewModel.KeyboardHotkey.ToggleMute = buttonValue.AsHidType(); - break; - case "ResScaleUp": - viewModel.KeyboardHotkey.ResScaleUp = buttonValue.AsHidType(); - break; - case "ResScaleDown": - viewModel.KeyboardHotkey.ResScaleDown = buttonValue.AsHidType(); - break; - case "VolumeUp": - viewModel.KeyboardHotkey.VolumeUp = buttonValue.AsHidType(); - break; - case "VolumeDown": - viewModel.KeyboardHotkey.VolumeDown = buttonValue.AsHidType(); - break; - case "CustomVSyncIntervalIncrement": - viewModel.KeyboardHotkey.CustomVSyncIntervalIncrement = buttonValue.AsHidType(); - break; - case "CustomVSyncIntervalDecrement": - viewModel.KeyboardHotkey.CustomVSyncIntervalDecrement = buttonValue.AsHidType(); - break; + switch (button.Name) + { + case "ToggleVSyncMode": + viewModel.KeyboardHotkey.ToggleVSyncMode = buttonValue.AsHidType(); + break; + case "Screenshot": + viewModel.KeyboardHotkey.Screenshot = buttonValue.AsHidType(); + break; + case "ShowUI": + viewModel.KeyboardHotkey.ShowUI = buttonValue.AsHidType(); + break; + case "Pause": + viewModel.KeyboardHotkey.Pause = buttonValue.AsHidType(); + break; + case "ToggleMute": + viewModel.KeyboardHotkey.ToggleMute = buttonValue.AsHidType(); + break; + case "ResScaleUp": + viewModel.KeyboardHotkey.ResScaleUp = buttonValue.AsHidType(); + break; + case "ResScaleDown": + viewModel.KeyboardHotkey.ResScaleDown = buttonValue.AsHidType(); + break; + case "VolumeUp": + viewModel.KeyboardHotkey.VolumeUp = buttonValue.AsHidType(); + break; + case "VolumeDown": + viewModel.KeyboardHotkey.VolumeDown = buttonValue.AsHidType(); + break; + case "CustomVSyncIntervalIncrement": + viewModel.KeyboardHotkey.CustomVSyncIntervalIncrement = buttonValue.AsHidType(); + break; + case "CustomVSyncIntervalDecrement": + viewModel.KeyboardHotkey.CustomVSyncIntervalDecrement = buttonValue.AsHidType(); + break; + } } } }; diff --git a/src/Ryujinx/UI/Views/User/UserProfileImageSelectorView.axaml.cs b/src/Ryujinx/UI/Views/User/UserProfileImageSelectorView.axaml.cs index 9faf14cb4..43f3d234a 100644 --- a/src/Ryujinx/UI/Views/User/UserProfileImageSelectorView.axaml.cs +++ b/src/Ryujinx/UI/Views/User/UserProfileImageSelectorView.axaml.cs @@ -64,7 +64,7 @@ namespace Ryujinx.Ava.UI.Views.User private async void Import_OnClick(object sender, RoutedEventArgs e) { var window = this.GetVisualRoot() as Window; - var result = await window.StorageProvider.OpenFilePickerAsync(new FilePickerOpenOptions + var result = await window?.StorageProvider.OpenFilePickerAsync(new FilePickerOpenOptions { AllowMultiple = false, FileTypeFilter = new List diff --git a/src/Ryujinx/UI/Views/User/UserSelectorView.axaml.cs b/src/Ryujinx/UI/Views/User/UserSelectorView.axaml.cs index fa3383aa9..d132f9941 100644 --- a/src/Ryujinx/UI/Views/User/UserSelectorView.axaml.cs +++ b/src/Ryujinx/UI/Views/User/UserSelectorView.axaml.cs @@ -123,7 +123,7 @@ namespace Ryujinx.Ava.UI.Views.User private void Close(object sender, RoutedEventArgs e) { - ((ContentDialog)_parent.Parent).Hide(); + ((ContentDialog)_parent.Parent)?.Hide(); } } } diff --git a/src/Ryujinx/UI/Windows/CheatWindow.axaml.cs b/src/Ryujinx/UI/Windows/CheatWindow.axaml.cs index 4d9cd9bfe..3a155594c 100644 --- a/src/Ryujinx/UI/Windows/CheatWindow.axaml.cs +++ b/src/Ryujinx/UI/Windows/CheatWindow.axaml.cs @@ -120,7 +120,7 @@ namespace Ryujinx.Ava.UI.Windows } } - Directory.CreateDirectory(Path.GetDirectoryName(_enabledCheatsPath)); + Directory.CreateDirectory(Path.GetDirectoryName(_enabledCheatsPath) ?? string.Empty); File.WriteAllLines(_enabledCheatsPath, enabledCheats); diff --git a/src/Ryujinx/UI/Windows/DownloadableContentManagerWindow.axaml.cs b/src/Ryujinx/UI/Windows/DownloadableContentManagerWindow.axaml.cs index 14e20b6fc..89da05e5a 100644 --- a/src/Ryujinx/UI/Windows/DownloadableContentManagerWindow.axaml.cs +++ b/src/Ryujinx/UI/Windows/DownloadableContentManagerWindow.axaml.cs @@ -53,12 +53,12 @@ namespace Ryujinx.Ava.UI.Windows private void SaveAndClose(object sender, RoutedEventArgs routedEventArgs) { ViewModel.Save(); - ((ContentDialog)Parent).Hide(); + ((ContentDialog)Parent)?.Hide(); } private void Close(object sender, RoutedEventArgs e) { - ((ContentDialog)Parent).Hide(); + ((ContentDialog)Parent)?.Hide(); } private void RemoveDLC(object sender, RoutedEventArgs e) diff --git a/src/Ryujinx/UI/Windows/MainWindow.axaml.cs b/src/Ryujinx/UI/Windows/MainWindow.axaml.cs index 2241f5985..49dffd062 100644 --- a/src/Ryujinx/UI/Windows/MainWindow.axaml.cs +++ b/src/Ryujinx/UI/Windows/MainWindow.axaml.cs @@ -494,7 +494,10 @@ namespace Ryujinx.Ava.UI.Windows /// /// Subscribe to the ColorValuesChanged event /// - PlatformSettings.ColorValuesChanged += OnPlatformColorValuesChanged; + if (PlatformSettings != null) + { + PlatformSettings.ColorValuesChanged += OnPlatformColorValuesChanged; + } ViewModel.Initialize( ContentManager, @@ -578,7 +581,7 @@ namespace Ryujinx.Ava.UI.Windows var volumeSplitButton = sender as ToggleSplitButton; if (ViewModel.IsGameRunning) { - if (!volumeSplitButton.IsChecked) + if (volumeSplitButton is not { IsChecked: true }) { ViewModel.AppHost.Device.SetVolume(ViewModel.VolumeBeforeMute); } diff --git a/src/Ryujinx/UI/Windows/ModManagerWindow.axaml.cs b/src/Ryujinx/UI/Windows/ModManagerWindow.axaml.cs index dab966362..4558719cd 100644 --- a/src/Ryujinx/UI/Windows/ModManagerWindow.axaml.cs +++ b/src/Ryujinx/UI/Windows/ModManagerWindow.axaml.cs @@ -53,12 +53,12 @@ namespace Ryujinx.Ava.UI.Windows private void SaveAndClose(object sender, RoutedEventArgs e) { ViewModel.Save(); - ((ContentDialog)Parent).Hide(); + ((ContentDialog)Parent)?.Hide(); } private void Close(object sender, RoutedEventArgs e) { - ((ContentDialog)Parent).Hide(); + ((ContentDialog)Parent)?.Hide(); } private async void DeleteMod(object sender, RoutedEventArgs e) diff --git a/src/Ryujinx/UI/Windows/TitleUpdateWindow.axaml.cs b/src/Ryujinx/UI/Windows/TitleUpdateWindow.axaml.cs index 7d4925c4e..09a766477 100644 --- a/src/Ryujinx/UI/Windows/TitleUpdateWindow.axaml.cs +++ b/src/Ryujinx/UI/Windows/TitleUpdateWindow.axaml.cs @@ -50,14 +50,14 @@ namespace Ryujinx.Ava.UI.Windows private void Close(object sender, RoutedEventArgs e) { - ((ContentDialog)Parent).Hide(); + ((ContentDialog)Parent)?.Hide(); } public void Save(object sender, RoutedEventArgs e) { ViewModel.Save(); - ((ContentDialog)Parent).Hide(); + ((ContentDialog)Parent)?.Hide(); } private void OpenLocation(object sender, RoutedEventArgs e) diff --git a/src/Ryujinx/UI/Windows/XCITrimmerWindow.axaml.cs b/src/Ryujinx/UI/Windows/XCITrimmerWindow.axaml.cs index 580ebc9da..f338bd7e9 100644 --- a/src/Ryujinx/UI/Windows/XCITrimmerWindow.axaml.cs +++ b/src/Ryujinx/UI/Windows/XCITrimmerWindow.axaml.cs @@ -59,7 +59,7 @@ namespace Ryujinx.Ava.UI.Windows private void Close(object sender, RoutedEventArgs e) { - ((ContentDialog)Parent).Hide(); + ((ContentDialog)Parent)?.Hide(); } private void Cancel(Object sender, RoutedEventArgs e) diff --git a/src/Spv.Generator/Instruction.cs b/src/Spv.Generator/Instruction.cs index 5a8f17d47..88c75a465 100644 --- a/src/Spv.Generator/Instruction.cs +++ b/src/Spv.Generator/Instruction.cs @@ -162,7 +162,7 @@ namespace Spv.Generator public bool Equals(Instruction cmpObj) { - bool result = Type == cmpObj.Type && Id == cmpObj.Id; + bool result = cmpObj != null && Type == cmpObj.Type && Id == cmpObj.Id; if (result) { diff --git a/src/Spv.Generator/LiteralInteger.cs b/src/Spv.Generator/LiteralInteger.cs index 013ca3b94..a30d9bdbd 100644 --- a/src/Spv.Generator/LiteralInteger.cs +++ b/src/Spv.Generator/LiteralInteger.cs @@ -87,7 +87,7 @@ namespace Spv.Generator public bool Equals(LiteralInteger cmpObj) { - return Type == cmpObj.Type && _integerType == cmpObj._integerType && _data == cmpObj._data; + return cmpObj != null && Type == cmpObj.Type && _integerType == cmpObj._integerType && _data == cmpObj._data; } public override int GetHashCode() diff --git a/src/Spv.Generator/LiteralString.cs b/src/Spv.Generator/LiteralString.cs index ed20d0e8f..3781a2615 100644 --- a/src/Spv.Generator/LiteralString.cs +++ b/src/Spv.Generator/LiteralString.cs @@ -36,7 +36,7 @@ namespace Spv.Generator public bool Equals(LiteralString cmpObj) { - return Type == cmpObj.Type && _value.Equals(cmpObj._value); + return cmpObj != null && Type == cmpObj.Type && _value.Equals(cmpObj._value); } public override int GetHashCode()