misc: chore: Fix numerous NullReferenceExceptions, InvalidOperationExceptions

This commit is contained in:
KeatonTheBot 2025-06-17 17:17:31 -05:00
parent a90db3464d
commit d2a532f971
90 changed files with 667 additions and 533 deletions

View file

@ -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;

View file

@ -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);

View file

@ -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;

View file

@ -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)

View file

@ -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();

View file

@ -27,7 +27,7 @@ namespace Ryujinx.Common.Configuration.Hid
{
string propertyName = tempReader.GetString();
if (propertyName.Equals("backend"))
if (propertyName is "backend")
{
tempReader.Read();

View file

@ -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;

View file

@ -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;

View file

@ -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)

View file

@ -135,7 +135,10 @@ namespace Ryujinx.Cpu.Jit
offset += (int)copySize;
}
return new ReadOnlySequence<byte>(first, 0, last, (int)(size - last.RunningIndex));
if (last != null)
{
return new ReadOnlySequence<byte>(first, 0, last, (int)(size - last.RunningIndex));
}
}
catch (InvalidMemoryRegionException)
{
@ -146,6 +149,8 @@ namespace Ryujinx.Cpu.Jit
return ReadOnlySequence<byte>.Empty;
}
return default;
}
/// <inheritdoc/>

View file

@ -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
{

View file

@ -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);

View file

@ -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))!);
}
/// <summary>
@ -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);

View file

@ -173,24 +173,27 @@ namespace Ryujinx.Graphics.Gpu.Image
/// </summary>
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;
}
/// <summary>

View file

@ -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;

View file

@ -372,7 +372,7 @@ namespace Ryujinx.Graphics.Gpu.Memory
if (rangeCount == -1)
{
_migrationTarget.WaitForAndFlushRanges(address, size);
_migrationTarget?.WaitForAndFlushRanges(address, size);
return;
}

View file

@ -481,7 +481,7 @@ namespace Ryujinx.Graphics.Gpu.Shader.DiskCache
}
int offset = Unsafe.SizeOf<TocHeader>() + programIndex * Unsafe.SizeOf<OffsetAndSize>();
if (offset + Unsafe.SizeOf<OffsetAndSize>() > tocFileStream.Length)
if (tocFileStream != null && offset + Unsafe.SizeOf<OffsetAndSize>() > 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);

View file

@ -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))

View file

@ -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)
{

View file

@ -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)
{

View file

@ -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);

View file

@ -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);

View file

@ -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);

View file

@ -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);

View file

@ -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
{

View file

@ -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)
{

View file

@ -34,7 +34,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations
operation.Dest = null;
LinkedListNode<INode> newNode = node.List.AddBefore(node, new Operation(Instruction.Call, 0, floatValue, callArgs));
LinkedListNode<INode> 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<INode> newNode = node.List.AddBefore(node, new Operation(Instruction.Call, 0, (Operand)null, callArgs));
LinkedListNode<INode> newNode = node.List?.AddBefore(node, new Operation(Instruction.Call, 0, (Operand)null, callArgs));
Utils.DeleteNode(node, operation);

View file

@ -305,7 +305,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations
LinkedListNode<INode> 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<INode> newNode = node.List.AddBefore(node, storageOp);
node.List?.AddBefore(node, shiftOp);
LinkedListNode<INode> 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<INode> newNode = node.List.AddBefore(node, callOp);
LinkedListNode<INode> newNode = node.List?.AddBefore(node, callOp);
if (returnsValue)
{

View file

@ -189,7 +189,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations
public static void DeleteNode(LinkedListNode<INode> node, Operation operation)
{
node.List.Remove(node);
node.List?.Remove(node);
for (int srcIndex = 0; srcIndex < operation.SourcesCount; srcIndex++)
{

View file

@ -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
{

View file

@ -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;
}

View file

@ -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<INode> 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<INode> 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<INode> GenerateInvocationId(LinkedListNode<INode> node, Operand dest)
{
return node.List.AddBefore(node, new Operation(
return node.List?.AddBefore(node, new Operation(
Instruction.Load,
StorageKind.Input,
dest,

View file

@ -48,7 +48,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Transforms
Operand[] callArgs = [Const(functionId), byteOffset, value];
LinkedListNode<INode> newNode = node.List.AddBefore(node, new Operation(Instruction.Call, 0, result, callArgs));
LinkedListNode<INode> newNode = node.List?.AddBefore(node, new Operation(Instruction.Call, 0, result, callArgs));
Utils.DeleteNode(node, operation);

View file

@ -47,7 +47,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Transforms
Operand[] callArgs = [Const(functionId), byteOffset, value];
LinkedListNode<INode> newNode = node.List.AddBefore(node, new Operation(Instruction.Call, 0, (Operand)null, callArgs));
LinkedListNode<INode> newNode = node.List?.AddBefore(node, new Operation(Instruction.Call, 0, (Operand)null, callArgs));
Utils.DeleteNode(node, operation);

View file

@ -42,7 +42,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Transforms
Operand[] callArgs = [Const(functionId), value, index, mask, valid];
LinkedListNode<INode> newNode = node.List.AddBefore(node, new Operation(Instruction.Call, 0, result, callArgs));
LinkedListNode<INode> newNode = node.List?.AddBefore(node, new Operation(Instruction.Call, 0, result, callArgs));
Utils.DeleteNode(node, operation);

View file

@ -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<INode> textureSizeNode = node.List.AddBefore(node, new TextureOperation(
LinkedListNode<INode> 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;
}

View file

@ -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;
}

View file

@ -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<INode> CopySignExtendedNormalized(LinkedListNode<INode> 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<INode> GenerateInstanceIndexLoad(ResourceManager resourceManager, LinkedListNode<INode> 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<INode> GenerateVertexIdVertexRateLoad(ResourceManager resourceManager, LinkedListNode<INode> 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<INode> GenerateVertexIdInstanceRateLoad(ResourceManager resourceManager, LinkedListNode<INode> 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<INode> GenerateInstanceIdLoad(LinkedListNode<INode> 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)

View file

@ -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();

View file

@ -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();

View file

@ -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();

View file

@ -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);");
}

View file

@ -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))
{

View file

@ -551,7 +551,7 @@ namespace Ryujinx.HLE.FileSystem
new DirectoryInfo(registeredDirectory).Delete(true);
}
Directory.Move(temporaryDirectory, registeredDirectory);
Directory.Move(temporaryDirectory, registeredDirectory ?? string.Empty);
LoadEntries();
}

View file

@ -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

View file

@ -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();
}

View file

@ -1369,44 +1369,50 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
LinkedListNode<KPageNode> 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;
}
}
}

View file

@ -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<T>(address + offset);
if (_pageList.Nodes.First != null)
{
ulong address = _pageList.Nodes.First.Value.Address - DramMemoryMap.DramBase;
return ref _context.Memory.GetRef<T>(address + offset);
}
}
throw new NotImplementedException("Non-contiguous shared memory is not yet supported.");

View file

@ -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)

View file

@ -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.");
}

View file

@ -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

View file

@ -147,20 +147,26 @@ namespace Ryujinx.Horizon.Kernel.Generators
List<SyscallIdAndName> 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));
}
}
}
}

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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
{

View file

@ -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 [];
}
/// <exception cref="Ryujinx.HLE.Exceptions.InvalidNpdmException">The npdm file doesn't contain valid data.</exception>
@ -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")
{

View file

@ -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}");
}

View file

@ -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)]

View file

@ -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();

View file

@ -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);

View file

@ -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();

View file

@ -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);
}
}
}

View file

@ -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;
}
}
}

View file

@ -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)

View file

@ -52,8 +52,8 @@ namespace Ryujinx.Ava.UI.Models
if (InGameList)
{
Icon = appData.Icon;
Title = appData.Name;
Icon = appData?.Icon;
Title = appData?.Name;
}
else
{

View file

@ -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)
{

View file

@ -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");
}

View file

@ -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)}");
}
}
}

View file

@ -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();

View file

@ -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();
}

View file

@ -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);

View file

@ -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);

View file

@ -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();

View file

@ -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;
}

View file

@ -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);

View file

@ -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;
}
}
}
}

View file

@ -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<Key>();
break;
case "ButtonL":
viewModel.Config.ButtonL = buttonValue.AsHidType<Key>();
break;
case "ButtonMinus":
viewModel.Config.ButtonMinus = buttonValue.AsHidType<Key>();
break;
case "LeftStickButton":
viewModel.Config.LeftStickButton = buttonValue.AsHidType<Key>();
break;
case "LeftStickUp":
viewModel.Config.LeftStickUp = buttonValue.AsHidType<Key>();
break;
case "LeftStickDown":
viewModel.Config.LeftStickDown = buttonValue.AsHidType<Key>();
break;
case "LeftStickRight":
viewModel.Config.LeftStickRight = buttonValue.AsHidType<Key>();
break;
case "LeftStickLeft":
viewModel.Config.LeftStickLeft = buttonValue.AsHidType<Key>();
break;
case "DpadUp":
viewModel.Config.DpadUp = buttonValue.AsHidType<Key>();
break;
case "DpadDown":
viewModel.Config.DpadDown = buttonValue.AsHidType<Key>();
break;
case "DpadLeft":
viewModel.Config.DpadLeft = buttonValue.AsHidType<Key>();
break;
case "DpadRight":
viewModel.Config.DpadRight = buttonValue.AsHidType<Key>();
break;
case "LeftButtonSr":
viewModel.Config.LeftButtonSr = buttonValue.AsHidType<Key>();
break;
case "LeftButtonSl":
viewModel.Config.LeftButtonSl = buttonValue.AsHidType<Key>();
break;
case "RightButtonSr":
viewModel.Config.RightButtonSr = buttonValue.AsHidType<Key>();
break;
case "RightButtonSl":
viewModel.Config.RightButtonSl = buttonValue.AsHidType<Key>();
break;
case "ButtonZr":
viewModel.Config.ButtonZr = buttonValue.AsHidType<Key>();
break;
case "ButtonR":
viewModel.Config.ButtonR = buttonValue.AsHidType<Key>();
break;
case "ButtonPlus":
viewModel.Config.ButtonPlus = buttonValue.AsHidType<Key>();
break;
case "ButtonA":
viewModel.Config.ButtonA = buttonValue.AsHidType<Key>();
break;
case "ButtonB":
viewModel.Config.ButtonB = buttonValue.AsHidType<Key>();
break;
case "ButtonX":
viewModel.Config.ButtonX = buttonValue.AsHidType<Key>();
break;
case "ButtonY":
viewModel.Config.ButtonY = buttonValue.AsHidType<Key>();
break;
case "RightStickButton":
viewModel.Config.RightStickButton = buttonValue.AsHidType<Key>();
break;
case "RightStickUp":
viewModel.Config.RightStickUp = buttonValue.AsHidType<Key>();
break;
case "RightStickDown":
viewModel.Config.RightStickDown = buttonValue.AsHidType<Key>();
break;
case "RightStickRight":
viewModel.Config.RightStickRight = buttonValue.AsHidType<Key>();
break;
case "RightStickLeft":
viewModel.Config.RightStickLeft = buttonValue.AsHidType<Key>();
break;
}
}
};
var buttonValue = e.ButtonValue.Value;
viewModel.ParentModel.IsModified = true;
_currentAssigner.GetInputAndAssign(assigner, keyboard);
switch (button.Name)
{
case "ButtonZl":
viewModel.Config.ButtonZl = buttonValue.AsHidType<Key>();
break;
case "ButtonL":
viewModel.Config.ButtonL = buttonValue.AsHidType<Key>();
break;
case "ButtonMinus":
viewModel.Config.ButtonMinus = buttonValue.AsHidType<Key>();
break;
case "LeftStickButton":
viewModel.Config.LeftStickButton = buttonValue.AsHidType<Key>();
break;
case "LeftStickUp":
viewModel.Config.LeftStickUp = buttonValue.AsHidType<Key>();
break;
case "LeftStickDown":
viewModel.Config.LeftStickDown = buttonValue.AsHidType<Key>();
break;
case "LeftStickRight":
viewModel.Config.LeftStickRight = buttonValue.AsHidType<Key>();
break;
case "LeftStickLeft":
viewModel.Config.LeftStickLeft = buttonValue.AsHidType<Key>();
break;
case "DpadUp":
viewModel.Config.DpadUp = buttonValue.AsHidType<Key>();
break;
case "DpadDown":
viewModel.Config.DpadDown = buttonValue.AsHidType<Key>();
break;
case "DpadLeft":
viewModel.Config.DpadLeft = buttonValue.AsHidType<Key>();
break;
case "DpadRight":
viewModel.Config.DpadRight = buttonValue.AsHidType<Key>();
break;
case "LeftButtonSr":
viewModel.Config.LeftButtonSr = buttonValue.AsHidType<Key>();
break;
case "LeftButtonSl":
viewModel.Config.LeftButtonSl = buttonValue.AsHidType<Key>();
break;
case "RightButtonSr":
viewModel.Config.RightButtonSr = buttonValue.AsHidType<Key>();
break;
case "RightButtonSl":
viewModel.Config.RightButtonSl = buttonValue.AsHidType<Key>();
break;
case "ButtonZr":
viewModel.Config.ButtonZr = buttonValue.AsHidType<Key>();
break;
case "ButtonR":
viewModel.Config.ButtonR = buttonValue.AsHidType<Key>();
break;
case "ButtonPlus":
viewModel.Config.ButtonPlus = buttonValue.AsHidType<Key>();
break;
case "ButtonA":
viewModel.Config.ButtonA = buttonValue.AsHidType<Key>();
break;
case "ButtonB":
viewModel.Config.ButtonB = buttonValue.AsHidType<Key>();
break;
case "ButtonX":
viewModel.Config.ButtonX = buttonValue.AsHidType<Key>();
break;
case "ButtonY":
viewModel.Config.ButtonY = buttonValue.AsHidType<Key>();
break;
case "RightStickButton":
viewModel.Config.RightStickButton = buttonValue.AsHidType<Key>();
break;
case "RightStickUp":
viewModel.Config.RightStickUp = buttonValue.AsHidType<Key>();
break;
case "RightStickDown":
viewModel.Config.RightStickDown = buttonValue.AsHidType<Key>();
break;
case "RightStickRight":
viewModel.Config.RightStickRight = buttonValue.AsHidType<Key>();
break;
case "RightStickLeft":
viewModel.Config.RightStickLeft = buttonValue.AsHidType<Key>();
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;
}

View file

@ -34,7 +34,7 @@ namespace Ryujinx.Ava.UI.Views.Main
{
if (sender is RadioButton button)
{
ViewModel.Sort(Enum.Parse<ApplicationSort>(button.Tag.ToString()));
ViewModel.Sort(Enum.Parse<ApplicationSort>(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");
}
}

View file

@ -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<Key>();
break;
case "Screenshot":
viewModel.KeyboardHotkey.Screenshot = buttonValue.AsHidType<Key>();
break;
case "ShowUI":
viewModel.KeyboardHotkey.ShowUI = buttonValue.AsHidType<Key>();
break;
case "Pause":
viewModel.KeyboardHotkey.Pause = buttonValue.AsHidType<Key>();
break;
case "ToggleMute":
viewModel.KeyboardHotkey.ToggleMute = buttonValue.AsHidType<Key>();
break;
case "ResScaleUp":
viewModel.KeyboardHotkey.ResScaleUp = buttonValue.AsHidType<Key>();
break;
case "ResScaleDown":
viewModel.KeyboardHotkey.ResScaleDown = buttonValue.AsHidType<Key>();
break;
case "VolumeUp":
viewModel.KeyboardHotkey.VolumeUp = buttonValue.AsHidType<Key>();
break;
case "VolumeDown":
viewModel.KeyboardHotkey.VolumeDown = buttonValue.AsHidType<Key>();
break;
case "CustomVSyncIntervalIncrement":
viewModel.KeyboardHotkey.CustomVSyncIntervalIncrement = buttonValue.AsHidType<Key>();
break;
case "CustomVSyncIntervalDecrement":
viewModel.KeyboardHotkey.CustomVSyncIntervalDecrement = buttonValue.AsHidType<Key>();
break;
switch (button.Name)
{
case "ToggleVSyncMode":
viewModel.KeyboardHotkey.ToggleVSyncMode = buttonValue.AsHidType<Key>();
break;
case "Screenshot":
viewModel.KeyboardHotkey.Screenshot = buttonValue.AsHidType<Key>();
break;
case "ShowUI":
viewModel.KeyboardHotkey.ShowUI = buttonValue.AsHidType<Key>();
break;
case "Pause":
viewModel.KeyboardHotkey.Pause = buttonValue.AsHidType<Key>();
break;
case "ToggleMute":
viewModel.KeyboardHotkey.ToggleMute = buttonValue.AsHidType<Key>();
break;
case "ResScaleUp":
viewModel.KeyboardHotkey.ResScaleUp = buttonValue.AsHidType<Key>();
break;
case "ResScaleDown":
viewModel.KeyboardHotkey.ResScaleDown = buttonValue.AsHidType<Key>();
break;
case "VolumeUp":
viewModel.KeyboardHotkey.VolumeUp = buttonValue.AsHidType<Key>();
break;
case "VolumeDown":
viewModel.KeyboardHotkey.VolumeDown = buttonValue.AsHidType<Key>();
break;
case "CustomVSyncIntervalIncrement":
viewModel.KeyboardHotkey.CustomVSyncIntervalIncrement = buttonValue.AsHidType<Key>();
break;
case "CustomVSyncIntervalDecrement":
viewModel.KeyboardHotkey.CustomVSyncIntervalDecrement = buttonValue.AsHidType<Key>();
break;
}
}
}
};

View file

@ -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<FilePickerFileType>

View file

@ -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();
}
}
}

View file

@ -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);

View file

@ -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)

View file

@ -494,7 +494,10 @@ namespace Ryujinx.Ava.UI.Windows
/// <summary>
/// Subscribe to the ColorValuesChanged event
/// </summary>
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);
}

View file

@ -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)

View file

@ -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)

View file

@ -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)

View file

@ -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)
{

View file

@ -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()

View file

@ -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()