Compare commits

..

8 Commits

Author SHA1 Message Date
59ddb26628 replace ByteMemoryPool usage in Ryujinx.Graphics (#7129)
* chore: replace `ByteMemoryPool` usage with `MemoryOwner<byte>`

* refactor: `PixelConverter.ConvertR4G4ToR4G4B4A4()` - rename old `outputSpan` to `outputSpanUInt16`, reuse same output `Span<byte>` as newly-freed name `outputSpan`

* eliminate temporary buffer allocations

* chore, perf: use MemoryOwner<byte> instead of IMemoryOwner<byte>
2024-08-03 19:50:53 +01:00
83fda10f6e Fix FileNotFoundException in TryGetApplicationsFromFile() and improve loading applications (#7145)
* Don't load files from hidden subdirectories

* Catch FileNotFoundException in TryGetApplicationsFromFile()

* Skip non-existent files and bad symlinks when loading applications
2024-08-03 19:46:59 +02:00
d97e995e59 Fix off-by-one on audio renderer PerformanceManager.GetNextEntry (#7139) 2024-07-31 22:22:11 -03:00
56b2f84702 Fix shader RegisterUsage pass only taking first operation dest into account (#7131)
* Fix shader RegisterUsage pass only taking first operation dest into account

* Shader cache version bump
2024-07-30 21:57:55 -03:00
698e36bbd2 Vulkan: Force topology to PatchList for Tessellation (#7102)
Vulkan spec states that input topology should always be PatchList when a tessellation pipeline is present. The AMD GPU on windows crashes so hard it BSODs the machine if this isn't the case, so it's forced here just in case.

I'm not sure what providing a different topology here would even do, as you'd think it would always be a patch list input.
2024-07-30 21:48:30 -03:00
6ce49a2dc7 Ava UI: Handle updates containing non numeric characters (#7043)
* Handle updates containing non numeric characters

Smh

Dont be stupid

* Use Berry’s method

* Thanks gdk

* Remove using
2024-07-25 16:44:33 -03:00
ccd330ba0f Vulkan: Add missing barriers for texture to buffer copy (#7092)
This barrier has always been missing, but it only became apparent when #7012 merged.

I also added some barriers in case the target buffer used here is used by other commands, though right now it isn't.

Fixes a regression where water would turn white on AMD GPUs with the proprietary driver. May fix other issues on this driver.
2024-07-25 16:34:30 -03:00
95d252b7b8 Update kernel GetInfo SVC for firmware 18.0.0 (#7075)
* Implement kernel GetInfo AliasRegionExtraSize

* Implement IsSvcPermitted

* Remove warning supressions that are no longer needed

* Remove useless cast
2024-07-22 12:46:04 -03:00
30 changed files with 274 additions and 290 deletions

View File

@ -18,16 +18,12 @@ namespace Ryujinx.Audio.Renderer.Server.Performance
if (version == 2) if (version == 2)
{ {
return (ulong)PerformanceManagerGeneric<PerformanceFrameHeaderVersion2, return (ulong)PerformanceManagerGeneric<PerformanceFrameHeaderVersion2, PerformanceEntryVersion2, PerformanceDetailVersion2>.GetRequiredBufferSizeForPerformanceMetricsPerFrame(ref parameter);
PerformanceEntryVersion2,
PerformanceDetailVersion2>.GetRequiredBufferSizeForPerformanceMetricsPerFrame(ref parameter);
} }
if (version == 1) if (version == 1)
{ {
return (ulong)PerformanceManagerGeneric<PerformanceFrameHeaderVersion1, return (ulong)PerformanceManagerGeneric<PerformanceFrameHeaderVersion1, PerformanceEntryVersion1, PerformanceDetailVersion1>.GetRequiredBufferSizeForPerformanceMetricsPerFrame(ref parameter);
PerformanceEntryVersion1,
PerformanceDetailVersion1>.GetRequiredBufferSizeForPerformanceMetricsPerFrame(ref parameter);
} }
throw new NotImplementedException($"Unknown Performance metrics data format version {version}"); throw new NotImplementedException($"Unknown Performance metrics data format version {version}");

View File

@ -234,7 +234,7 @@ namespace Ryujinx.Audio.Renderer.Server.Performance
{ {
performanceEntry = null; performanceEntry = null;
if (_entryDetailIndex > MaxFrameDetailCount) if (_entryDetailIndex >= MaxFrameDetailCount)
{ {
return false; return false;
} }
@ -245,7 +245,7 @@ namespace Ryujinx.Audio.Renderer.Server.Performance
EntryCountOffset = (uint)CurrentHeader.GetEntryCountOffset(), EntryCountOffset = (uint)CurrentHeader.GetEntryCountOffset(),
}; };
uint baseEntryOffset = (uint)(Unsafe.SizeOf<THeader>() + GetEntriesSize() + Unsafe.SizeOf<IPerformanceDetailEntry>() * _entryDetailIndex); uint baseEntryOffset = (uint)(Unsafe.SizeOf<THeader>() + GetEntriesSize() + Unsafe.SizeOf<TEntryDetail>() * _entryDetailIndex);
ref TEntryDetail entryDetail = ref EntriesDetail[_entryDetailIndex]; ref TEntryDetail entryDetail = ref EntriesDetail[_entryDetailIndex];

View File

@ -1,7 +1,6 @@
using Ryujinx.Common.Memory; using Ryujinx.Common.Memory;
using Ryujinx.Memory; using Ryujinx.Memory;
using System; using System;
using System.Buffers;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
@ -145,9 +144,9 @@ namespace Ryujinx.Graphics.Device
} }
else else
{ {
IMemoryOwner<byte> memoryOwner = ByteMemoryPool.Rent(size); MemoryOwner<byte> memoryOwner = MemoryOwner<byte>.Rent(size);
GetSpan(va, size).CopyTo(memoryOwner.Memory.Span); ReadImpl(va, memoryOwner.Span);
return new WritableRegion(this, va, memoryOwner, tracked: true); return new WritableRegion(this, va, memoryOwner, tracked: true);
} }

View File

@ -199,7 +199,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.InlineToMemory
if (target != null) if (target != null)
{ {
target.SynchronizeMemory(); target.SynchronizeMemory();
var dataCopy = ByteMemoryPool.RentCopy(data); var dataCopy = MemoryOwner<byte>.RentCopy(data);
target.SetData(dataCopy, 0, 0, new GAL.Rectangle<int>(_dstX, _dstY, _lineLengthIn / target.Info.FormatInfo.BytesPerPixel, _lineCount)); target.SetData(dataCopy, 0, 0, new GAL.Rectangle<int>(_dstX, _dstY, _lineLengthIn / target.Info.FormatInfo.BytesPerPixel, _lineCount));
target.SignalModified(); target.SignalModified();

View File

@ -1,4 +1,5 @@
using Ryujinx.Common.Logging; using Ryujinx.Common.Logging;
using Ryujinx.Common.Memory;
using Ryujinx.Graphics.GAL; using Ryujinx.Graphics.GAL;
using Ryujinx.Graphics.Gpu.Memory; using Ryujinx.Graphics.Gpu.Memory;
using Ryujinx.Graphics.Texture; using Ryujinx.Graphics.Texture;
@ -805,7 +806,7 @@ namespace Ryujinx.Graphics.Gpu.Image
sliceDepth, sliceDepth,
levels, levels,
layers, layers,
out IMemoryOwner<byte> decoded)) out MemoryOwner<byte> decoded))
{ {
string texInfo = $"{Info.Target} {Info.FormatInfo.Format} {Info.Width}x{Info.Height}x{Info.DepthOrLayers} levels {Info.Levels}"; string texInfo = $"{Info.Target} {Info.FormatInfo.Format} {Info.Width}x{Info.Height}x{Info.DepthOrLayers} levels {Info.Levels}";

View File

@ -2,7 +2,6 @@ using Ryujinx.Common.Memory;
using Ryujinx.Memory; using Ryujinx.Memory;
using Ryujinx.Memory.Range; using Ryujinx.Memory.Range;
using System; using System;
using System.Buffers;
using System.Collections.Generic; using System.Collections.Generic;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
@ -242,9 +241,9 @@ namespace Ryujinx.Graphics.Gpu.Memory
} }
else else
{ {
IMemoryOwner<byte> memoryOwner = ByteMemoryPool.Rent(size); MemoryOwner<byte> memoryOwner = MemoryOwner<byte>.Rent(size);
GetSpan(va, size).CopyTo(memoryOwner.Memory.Span); ReadImpl(va, memoryOwner.Span, tracked);
return new WritableRegion(this, va, memoryOwner, tracked); return new WritableRegion(this, va, memoryOwner, tracked);
} }

View File

@ -192,9 +192,9 @@ namespace Ryujinx.Graphics.Gpu.Memory
} }
else else
{ {
IMemoryOwner<byte> memoryOwner = ByteMemoryPool.Rent(range.GetSize()); MemoryOwner<byte> memoryOwner = MemoryOwner<byte>.Rent(checked((int)range.GetSize()));
Memory<byte> memory = memoryOwner.Memory; Span<byte> memorySpan = memoryOwner.Span;
int offset = 0; int offset = 0;
for (int i = 0; i < range.Count; i++) for (int i = 0; i < range.Count; i++)
@ -203,7 +203,7 @@ namespace Ryujinx.Graphics.Gpu.Memory
int size = (int)currentRange.Size; int size = (int)currentRange.Size;
if (currentRange.Address != MemoryManager.PteUnmapped) if (currentRange.Address != MemoryManager.PteUnmapped)
{ {
GetSpan(currentRange.Address, size).CopyTo(memory.Span.Slice(offset, size)); GetSpan(currentRange.Address, size).CopyTo(memorySpan.Slice(offset, size));
} }
offset += size; offset += size;
} }

View File

@ -22,7 +22,7 @@ namespace Ryujinx.Graphics.Gpu.Shader.DiskCache
private const ushort FileFormatVersionMajor = 1; private const ushort FileFormatVersionMajor = 1;
private const ushort FileFormatVersionMinor = 2; private const ushort FileFormatVersionMinor = 2;
private const uint FileFormatVersionPacked = ((uint)FileFormatVersionMajor << 16) | FileFormatVersionMinor; private const uint FileFormatVersionPacked = ((uint)FileFormatVersionMajor << 16) | FileFormatVersionMinor;
private const uint CodeGenVersion = 6921; private const uint CodeGenVersion = 7131;
private const string SharedTocFileName = "shared.toc"; private const string SharedTocFileName = "shared.toc";
private const string SharedDataFileName = "shared.data"; private const string SharedDataFileName = "shared.data";

View File

@ -1,6 +1,5 @@
using Ryujinx.Common.Memory; using Ryujinx.Common.Memory;
using System; using System;
using System.Buffers;
using System.Numerics; using System.Numerics;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Runtime.Intrinsics; using System.Runtime.Intrinsics;
@ -10,11 +9,11 @@ namespace Ryujinx.Graphics.OpenGL.Image
{ {
static class FormatConverter static class FormatConverter
{ {
public unsafe static IMemoryOwner<byte> ConvertS8D24ToD24S8(ReadOnlySpan<byte> data) public unsafe static MemoryOwner<byte> ConvertS8D24ToD24S8(ReadOnlySpan<byte> data)
{ {
IMemoryOwner<byte> outputMemory = ByteMemoryPool.Rent(data.Length); MemoryOwner<byte> outputMemory = MemoryOwner<byte>.Rent(data.Length);
Span<byte> output = outputMemory.Memory.Span; Span<byte> output = outputMemory.Span;
int start = 0; int start = 0;

View File

@ -155,9 +155,14 @@ namespace Ryujinx.Graphics.Shader.Translation
localInputs[block.Index] |= GetMask(register) & ~localOutputs[block.Index]; localInputs[block.Index] |= GetMask(register) & ~localOutputs[block.Index];
} }
if (operation.Dest != null && operation.Dest.Type == OperandType.Register) for (int dstIndex = 0; dstIndex < operation.DestsCount; dstIndex++)
{ {
localOutputs[block.Index] |= GetMask(operation.Dest.GetRegister()); Operand dest = operation.GetDest(dstIndex);
if (dest != null && dest.Type == OperandType.Register)
{
localOutputs[block.Index] |= GetMask(dest.GetRegister());
}
} }
} }
} }

View File

@ -1,7 +1,6 @@
using Ryujinx.Common.Memory; using Ryujinx.Common.Memory;
using Ryujinx.Common.Utilities; using Ryujinx.Common.Utilities;
using System; using System;
using System.Buffers;
using System.Diagnostics; using System.Diagnostics;
using System.Linq; using System.Linq;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
@ -293,9 +292,9 @@ namespace Ryujinx.Graphics.Texture.Astc
int depth, int depth,
int levels, int levels,
int layers, int layers,
out IMemoryOwner<byte> decoded) out MemoryOwner<byte> decoded)
{ {
decoded = ByteMemoryPool.Rent(QueryDecompressedSize(width, height, depth, levels, layers)); decoded = MemoryOwner<byte>.Rent(QueryDecompressedSize(width, height, depth, levels, layers));
AstcDecoder decoder = new(data, decoded.Memory, blockWidth, blockHeight, width, height, depth, levels, layers); AstcDecoder decoder = new(data, decoded.Memory, blockWidth, blockHeight, width, height, depth, levels, layers);

View File

@ -1,7 +1,6 @@
using Ryujinx.Common; using Ryujinx.Common;
using Ryujinx.Common.Memory; using Ryujinx.Common.Memory;
using System; using System;
using System.Buffers;
using System.Buffers.Binary; using System.Buffers.Binary;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Runtime.Intrinsics; using System.Runtime.Intrinsics;
@ -14,7 +13,7 @@ namespace Ryujinx.Graphics.Texture
private const int BlockWidth = 4; private const int BlockWidth = 4;
private const int BlockHeight = 4; private const int BlockHeight = 4;
public static IMemoryOwner<byte> DecodeBC1(ReadOnlySpan<byte> data, int width, int height, int depth, int levels, int layers) public static MemoryOwner<byte> DecodeBC1(ReadOnlySpan<byte> data, int width, int height, int depth, int levels, int layers)
{ {
int size = 0; int size = 0;
@ -23,12 +22,12 @@ namespace Ryujinx.Graphics.Texture
size += Math.Max(1, width >> l) * Math.Max(1, height >> l) * Math.Max(1, depth >> l) * layers * 4; size += Math.Max(1, width >> l) * Math.Max(1, height >> l) * Math.Max(1, depth >> l) * layers * 4;
} }
IMemoryOwner<byte> output = ByteMemoryPool.Rent(size); MemoryOwner<byte> output = MemoryOwner<byte>.Rent(size);
Span<byte> tile = stackalloc byte[BlockWidth * BlockHeight * 4]; Span<byte> tile = stackalloc byte[BlockWidth * BlockHeight * 4];
Span<uint> tileAsUint = MemoryMarshal.Cast<byte, uint>(tile); Span<uint> tileAsUint = MemoryMarshal.Cast<byte, uint>(tile);
Span<uint> outputAsUint = MemoryMarshal.Cast<byte, uint>(output.Memory.Span); Span<uint> outputAsUint = MemoryMarshal.Cast<byte, uint>(output.Span);
Span<Vector128<byte>> tileAsVector128 = MemoryMarshal.Cast<byte, Vector128<byte>>(tile); Span<Vector128<byte>> tileAsVector128 = MemoryMarshal.Cast<byte, Vector128<byte>>(tile);
@ -102,7 +101,7 @@ namespace Ryujinx.Graphics.Texture
return output; return output;
} }
public static IMemoryOwner<byte> DecodeBC2(ReadOnlySpan<byte> data, int width, int height, int depth, int levels, int layers) public static MemoryOwner<byte> DecodeBC2(ReadOnlySpan<byte> data, int width, int height, int depth, int levels, int layers)
{ {
int size = 0; int size = 0;
@ -111,12 +110,12 @@ namespace Ryujinx.Graphics.Texture
size += Math.Max(1, width >> l) * Math.Max(1, height >> l) * Math.Max(1, depth >> l) * layers * 4; size += Math.Max(1, width >> l) * Math.Max(1, height >> l) * Math.Max(1, depth >> l) * layers * 4;
} }
IMemoryOwner<byte> output = ByteMemoryPool.Rent(size); MemoryOwner<byte> output = MemoryOwner<byte>.Rent(size);
Span<byte> tile = stackalloc byte[BlockWidth * BlockHeight * 4]; Span<byte> tile = stackalloc byte[BlockWidth * BlockHeight * 4];
Span<uint> tileAsUint = MemoryMarshal.Cast<byte, uint>(tile); Span<uint> tileAsUint = MemoryMarshal.Cast<byte, uint>(tile);
Span<uint> outputAsUint = MemoryMarshal.Cast<byte, uint>(output.Memory.Span); Span<uint> outputAsUint = MemoryMarshal.Cast<byte, uint>(output.Span);
Span<Vector128<byte>> tileAsVector128 = MemoryMarshal.Cast<byte, Vector128<byte>>(tile); Span<Vector128<byte>> tileAsVector128 = MemoryMarshal.Cast<byte, Vector128<byte>>(tile);
@ -197,7 +196,7 @@ namespace Ryujinx.Graphics.Texture
return output; return output;
} }
public static IMemoryOwner<byte> DecodeBC3(ReadOnlySpan<byte> data, int width, int height, int depth, int levels, int layers) public static MemoryOwner<byte> DecodeBC3(ReadOnlySpan<byte> data, int width, int height, int depth, int levels, int layers)
{ {
int size = 0; int size = 0;
@ -206,13 +205,13 @@ namespace Ryujinx.Graphics.Texture
size += Math.Max(1, width >> l) * Math.Max(1, height >> l) * Math.Max(1, depth >> l) * layers * 4; size += Math.Max(1, width >> l) * Math.Max(1, height >> l) * Math.Max(1, depth >> l) * layers * 4;
} }
IMemoryOwner<byte> output = ByteMemoryPool.Rent(size); MemoryOwner<byte> output = MemoryOwner<byte>.Rent(size);
Span<byte> tile = stackalloc byte[BlockWidth * BlockHeight * 4]; Span<byte> tile = stackalloc byte[BlockWidth * BlockHeight * 4];
Span<byte> rPal = stackalloc byte[8]; Span<byte> rPal = stackalloc byte[8];
Span<uint> tileAsUint = MemoryMarshal.Cast<byte, uint>(tile); Span<uint> tileAsUint = MemoryMarshal.Cast<byte, uint>(tile);
Span<uint> outputAsUint = MemoryMarshal.Cast<byte, uint>(output.Memory.Span); Span<uint> outputAsUint = MemoryMarshal.Cast<byte, uint>(output.Span);
Span<Vector128<byte>> tileAsVector128 = MemoryMarshal.Cast<byte, Vector128<byte>>(tile); Span<Vector128<byte>> tileAsVector128 = MemoryMarshal.Cast<byte, Vector128<byte>>(tile);
@ -294,7 +293,7 @@ namespace Ryujinx.Graphics.Texture
return output; return output;
} }
public static IMemoryOwner<byte> DecodeBC4(ReadOnlySpan<byte> data, int width, int height, int depth, int levels, int layers, bool signed) public static MemoryOwner<byte> DecodeBC4(ReadOnlySpan<byte> data, int width, int height, int depth, int levels, int layers, bool signed)
{ {
int size = 0; int size = 0;
@ -306,8 +305,8 @@ namespace Ryujinx.Graphics.Texture
// Backends currently expect a stride alignment of 4 bytes, so output width must be aligned. // Backends currently expect a stride alignment of 4 bytes, so output width must be aligned.
int alignedWidth = BitUtils.AlignUp(width, 4); int alignedWidth = BitUtils.AlignUp(width, 4);
IMemoryOwner<byte> output = ByteMemoryPool.Rent(size); MemoryOwner<byte> output = MemoryOwner<byte>.Rent(size);
Span<byte> outputSpan = output.Memory.Span; Span<byte> outputSpan = output.Span;
ReadOnlySpan<ulong> data64 = MemoryMarshal.Cast<byte, ulong>(data); ReadOnlySpan<ulong> data64 = MemoryMarshal.Cast<byte, ulong>(data);
@ -402,7 +401,7 @@ namespace Ryujinx.Graphics.Texture
return output; return output;
} }
public static IMemoryOwner<byte> DecodeBC5(ReadOnlySpan<byte> data, int width, int height, int depth, int levels, int layers, bool signed) public static MemoryOwner<byte> DecodeBC5(ReadOnlySpan<byte> data, int width, int height, int depth, int levels, int layers, bool signed)
{ {
int size = 0; int size = 0;
@ -414,7 +413,7 @@ namespace Ryujinx.Graphics.Texture
// Backends currently expect a stride alignment of 4 bytes, so output width must be aligned. // Backends currently expect a stride alignment of 4 bytes, so output width must be aligned.
int alignedWidth = BitUtils.AlignUp(width, 2); int alignedWidth = BitUtils.AlignUp(width, 2);
IMemoryOwner<byte> output = ByteMemoryPool.Rent(size); MemoryOwner<byte> output = MemoryOwner<byte>.Rent(size);
ReadOnlySpan<ulong> data64 = MemoryMarshal.Cast<byte, ulong>(data); ReadOnlySpan<ulong> data64 = MemoryMarshal.Cast<byte, ulong>(data);
@ -423,7 +422,7 @@ namespace Ryujinx.Graphics.Texture
Span<byte> rPal = stackalloc byte[8]; Span<byte> rPal = stackalloc byte[8];
Span<byte> gPal = stackalloc byte[8]; Span<byte> gPal = stackalloc byte[8];
Span<ushort> outputAsUshort = MemoryMarshal.Cast<byte, ushort>(output.Memory.Span); Span<ushort> outputAsUshort = MemoryMarshal.Cast<byte, ushort>(output.Span);
Span<uint> rTileAsUint = MemoryMarshal.Cast<byte, uint>(rTile); Span<uint> rTileAsUint = MemoryMarshal.Cast<byte, uint>(rTile);
Span<uint> gTileAsUint = MemoryMarshal.Cast<byte, uint>(gTile); Span<uint> gTileAsUint = MemoryMarshal.Cast<byte, uint>(gTile);
@ -527,7 +526,7 @@ namespace Ryujinx.Graphics.Texture
return output; return output;
} }
public static IMemoryOwner<byte> DecodeBC6(ReadOnlySpan<byte> data, int width, int height, int depth, int levels, int layers, bool signed) public static MemoryOwner<byte> DecodeBC6(ReadOnlySpan<byte> data, int width, int height, int depth, int levels, int layers, bool signed)
{ {
int size = 0; int size = 0;
@ -536,8 +535,8 @@ namespace Ryujinx.Graphics.Texture
size += Math.Max(1, width >> l) * Math.Max(1, height >> l) * Math.Max(1, depth >> l) * layers * 8; size += Math.Max(1, width >> l) * Math.Max(1, height >> l) * Math.Max(1, depth >> l) * layers * 8;
} }
IMemoryOwner<byte> output = ByteMemoryPool.Rent(size); MemoryOwner<byte> output = MemoryOwner<byte>.Rent(size);
Span<byte> outputSpan = output.Memory.Span; Span<byte> outputSpan = output.Span;
int inputOffset = 0; int inputOffset = 0;
int outputOffset = 0; int outputOffset = 0;
@ -566,7 +565,7 @@ namespace Ryujinx.Graphics.Texture
return output; return output;
} }
public static IMemoryOwner<byte> DecodeBC7(ReadOnlySpan<byte> data, int width, int height, int depth, int levels, int layers) public static MemoryOwner<byte> DecodeBC7(ReadOnlySpan<byte> data, int width, int height, int depth, int levels, int layers)
{ {
int size = 0; int size = 0;
@ -575,8 +574,8 @@ namespace Ryujinx.Graphics.Texture
size += Math.Max(1, width >> l) * Math.Max(1, height >> l) * Math.Max(1, depth >> l) * layers * 4; size += Math.Max(1, width >> l) * Math.Max(1, height >> l) * Math.Max(1, depth >> l) * layers * 4;
} }
IMemoryOwner<byte> output = ByteMemoryPool.Rent(size); MemoryOwner<byte> output = MemoryOwner<byte>.Rent(size);
Span<byte> outputSpan = output.Memory.Span; Span<byte> outputSpan = output.Span;
int inputOffset = 0; int inputOffset = 0;
int outputOffset = 0; int outputOffset = 0;

View File

@ -2,7 +2,6 @@ using Ryujinx.Common;
using Ryujinx.Common.Memory; using Ryujinx.Common.Memory;
using Ryujinx.Graphics.Texture.Encoders; using Ryujinx.Graphics.Texture.Encoders;
using System; using System;
using System.Buffers;
namespace Ryujinx.Graphics.Texture namespace Ryujinx.Graphics.Texture
{ {
@ -11,7 +10,7 @@ namespace Ryujinx.Graphics.Texture
private const int BlockWidth = 4; private const int BlockWidth = 4;
private const int BlockHeight = 4; private const int BlockHeight = 4;
public static IMemoryOwner<byte> EncodeBC7(Memory<byte> data, int width, int height, int depth, int levels, int layers) public static MemoryOwner<byte> EncodeBC7(Memory<byte> data, int width, int height, int depth, int levels, int layers)
{ {
int size = 0; int size = 0;
@ -23,7 +22,7 @@ namespace Ryujinx.Graphics.Texture
size += w * h * 16 * Math.Max(1, depth >> l) * layers; size += w * h * 16 * Math.Max(1, depth >> l) * layers;
} }
IMemoryOwner<byte> output = ByteMemoryPool.Rent(size); MemoryOwner<byte> output = MemoryOwner<byte>.Rent(size);
Memory<byte> outputMemory = output.Memory; Memory<byte> outputMemory = output.Memory;
int imageBaseIOffs = 0; int imageBaseIOffs = 0;

View File

@ -1,7 +1,6 @@
using Ryujinx.Common; using Ryujinx.Common;
using Ryujinx.Common.Memory; using Ryujinx.Common.Memory;
using System; using System;
using System.Buffers;
using System.Buffers.Binary; using System.Buffers.Binary;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
@ -51,15 +50,15 @@ namespace Ryujinx.Graphics.Texture
new int[] { -3, -5, -7, -9, 2, 4, 6, 8 }, new int[] { -3, -5, -7, -9, 2, 4, 6, 8 },
}; };
public static IMemoryOwner<byte> DecodeRgb(ReadOnlySpan<byte> data, int width, int height, int depth, int levels, int layers) public static MemoryOwner<byte> DecodeRgb(ReadOnlySpan<byte> data, int width, int height, int depth, int levels, int layers)
{ {
ReadOnlySpan<ulong> dataUlong = MemoryMarshal.Cast<byte, ulong>(data); ReadOnlySpan<ulong> dataUlong = MemoryMarshal.Cast<byte, ulong>(data);
int inputOffset = 0; int inputOffset = 0;
IMemoryOwner<byte> output = ByteMemoryPool.Rent(CalculateOutputSize(width, height, depth, levels, layers)); MemoryOwner<byte> output = MemoryOwner<byte>.Rent(CalculateOutputSize(width, height, depth, levels, layers));
Span<uint> outputUint = MemoryMarshal.Cast<byte, uint>(output.Memory.Span); Span<uint> outputUint = MemoryMarshal.Cast<byte, uint>(output.Span);
Span<uint> tile = stackalloc uint[BlockWidth * BlockHeight]; Span<uint> tile = stackalloc uint[BlockWidth * BlockHeight];
int imageBaseOOffs = 0; int imageBaseOOffs = 0;
@ -113,15 +112,15 @@ namespace Ryujinx.Graphics.Texture
return output; return output;
} }
public static IMemoryOwner<byte> DecodePta(ReadOnlySpan<byte> data, int width, int height, int depth, int levels, int layers) public static MemoryOwner<byte> DecodePta(ReadOnlySpan<byte> data, int width, int height, int depth, int levels, int layers)
{ {
ReadOnlySpan<ulong> dataUlong = MemoryMarshal.Cast<byte, ulong>(data); ReadOnlySpan<ulong> dataUlong = MemoryMarshal.Cast<byte, ulong>(data);
int inputOffset = 0; int inputOffset = 0;
IMemoryOwner<byte> output = ByteMemoryPool.Rent(CalculateOutputSize(width, height, depth, levels, layers)); MemoryOwner<byte> output = MemoryOwner<byte>.Rent(CalculateOutputSize(width, height, depth, levels, layers));
Span<uint> outputUint = MemoryMarshal.Cast<byte, uint>(output.Memory.Span); Span<uint> outputUint = MemoryMarshal.Cast<byte, uint>(output.Span);
Span<uint> tile = stackalloc uint[BlockWidth * BlockHeight]; Span<uint> tile = stackalloc uint[BlockWidth * BlockHeight];
int imageBaseOOffs = 0; int imageBaseOOffs = 0;
@ -170,15 +169,15 @@ namespace Ryujinx.Graphics.Texture
return output; return output;
} }
public static IMemoryOwner<byte> DecodeRgba(ReadOnlySpan<byte> data, int width, int height, int depth, int levels, int layers) public static MemoryOwner<byte> DecodeRgba(ReadOnlySpan<byte> data, int width, int height, int depth, int levels, int layers)
{ {
ReadOnlySpan<ulong> dataUlong = MemoryMarshal.Cast<byte, ulong>(data); ReadOnlySpan<ulong> dataUlong = MemoryMarshal.Cast<byte, ulong>(data);
int inputOffset = 0; int inputOffset = 0;
IMemoryOwner<byte> output = ByteMemoryPool.Rent(CalculateOutputSize(width, height, depth, levels, layers)); MemoryOwner<byte> output = MemoryOwner<byte>.Rent(CalculateOutputSize(width, height, depth, levels, layers));
Span<uint> outputUint = MemoryMarshal.Cast<byte, uint>(output.Memory.Span); Span<uint> outputUint = MemoryMarshal.Cast<byte, uint>(output.Span);
Span<uint> tile = stackalloc uint[BlockWidth * BlockHeight]; Span<uint> tile = stackalloc uint[BlockWidth * BlockHeight];
int imageBaseOOffs = 0; int imageBaseOOffs = 0;

View File

@ -1,7 +1,6 @@
using Ryujinx.Common; using Ryujinx.Common;
using Ryujinx.Common.Memory; using Ryujinx.Common.Memory;
using System; using System;
using System.Buffers;
using System.Runtime.Intrinsics; using System.Runtime.Intrinsics;
using static Ryujinx.Graphics.Texture.BlockLinearConstants; using static Ryujinx.Graphics.Texture.BlockLinearConstants;
@ -95,7 +94,7 @@ namespace Ryujinx.Graphics.Texture
}; };
} }
public static IMemoryOwner<byte> ConvertBlockLinearToLinear( public static MemoryOwner<byte> ConvertBlockLinearToLinear(
int width, int width,
int height, int height,
int depth, int depth,
@ -121,8 +120,8 @@ namespace Ryujinx.Graphics.Texture
blockHeight, blockHeight,
bytesPerPixel); bytesPerPixel);
IMemoryOwner<byte> outputOwner = ByteMemoryPool.Rent(outSize); MemoryOwner<byte> outputOwner = MemoryOwner<byte>.Rent(outSize);
Span<byte> output = outputOwner.Memory.Span; Span<byte> output = outputOwner.Span;
int outOffs = 0; int outOffs = 0;
@ -249,7 +248,7 @@ namespace Ryujinx.Graphics.Texture
return outputOwner; return outputOwner;
} }
public static IMemoryOwner<byte> ConvertLinearStridedToLinear( public static MemoryOwner<byte> ConvertLinearStridedToLinear(
int width, int width,
int height, int height,
int blockWidth, int blockWidth,
@ -265,8 +264,8 @@ namespace Ryujinx.Graphics.Texture
int outStride = BitUtils.AlignUp(w * bytesPerPixel, HostStrideAlignment); int outStride = BitUtils.AlignUp(w * bytesPerPixel, HostStrideAlignment);
lineSize = Math.Min(lineSize, outStride); lineSize = Math.Min(lineSize, outStride);
IMemoryOwner<byte> output = ByteMemoryPool.Rent(h * outStride); MemoryOwner<byte> output = MemoryOwner<byte>.Rent(h * outStride);
Span<byte> outSpan = output.Memory.Span; Span<byte> outSpan = output.Span;
int outOffs = 0; int outOffs = 0;
int inOffs = 0; int inOffs = 0;

View File

@ -1,7 +1,6 @@
using Ryujinx.Common; using Ryujinx.Common;
using Ryujinx.Common.Memory; using Ryujinx.Common.Memory;
using System; using System;
using System.Buffers;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Runtime.Intrinsics; using System.Runtime.Intrinsics;
using System.Runtime.Intrinsics.X86; using System.Runtime.Intrinsics.X86;
@ -21,13 +20,14 @@ namespace Ryujinx.Graphics.Texture
return (remainder, outRemainder, length / stride); return (remainder, outRemainder, length / stride);
} }
public unsafe static IMemoryOwner<byte> ConvertR4G4ToR4G4B4A4(ReadOnlySpan<byte> data, int width) public unsafe static MemoryOwner<byte> ConvertR4G4ToR4G4B4A4(ReadOnlySpan<byte> data, int width)
{ {
IMemoryOwner<byte> output = ByteMemoryPool.Rent(data.Length * 2); MemoryOwner<byte> output = MemoryOwner<byte>.Rent(data.Length * 2);
Span<byte> outputSpan = output.Span;
(int remainder, int outRemainder, int height) = GetLineRemainders(data.Length, width, 1, 2); (int remainder, int outRemainder, int height) = GetLineRemainders(data.Length, width, 1, 2);
Span<ushort> outputSpan = MemoryMarshal.Cast<byte, ushort>(output.Memory.Span); Span<ushort> outputSpanUInt16 = MemoryMarshal.Cast<byte, ushort>(outputSpan);
if (remainder == 0) if (remainder == 0)
{ {
@ -38,7 +38,7 @@ namespace Ryujinx.Graphics.Texture
int sizeTrunc = data.Length & ~7; int sizeTrunc = data.Length & ~7;
start = sizeTrunc; start = sizeTrunc;
fixed (byte* inputPtr = data, outputPtr = output.Memory.Span) fixed (byte* inputPtr = data, outputPtr = outputSpan)
{ {
for (ulong offset = 0; offset < (ulong)sizeTrunc; offset += 8) for (ulong offset = 0; offset < (ulong)sizeTrunc; offset += 8)
{ {
@ -49,7 +49,7 @@ namespace Ryujinx.Graphics.Texture
for (int i = start; i < data.Length; i++) for (int i = start; i < data.Length; i++)
{ {
outputSpan[i] = data[i]; outputSpanUInt16[i] = data[i];
} }
} }
else else
@ -61,7 +61,7 @@ namespace Ryujinx.Graphics.Texture
{ {
for (int x = 0; x < width; x++) for (int x = 0; x < width; x++)
{ {
outputSpan[outOffset++] = data[offset++]; outputSpanUInt16[outOffset++] = data[offset++];
} }
offset += remainder; offset += remainder;
@ -72,16 +72,16 @@ namespace Ryujinx.Graphics.Texture
return output; return output;
} }
public static IMemoryOwner<byte> ConvertR5G6B5ToR8G8B8A8(ReadOnlySpan<byte> data, int width) public static MemoryOwner<byte> ConvertR5G6B5ToR8G8B8A8(ReadOnlySpan<byte> data, int width)
{ {
IMemoryOwner<byte> output = ByteMemoryPool.Rent(data.Length * 2); MemoryOwner<byte> output = MemoryOwner<byte>.Rent(data.Length * 2);
int offset = 0; int offset = 0;
int outOffset = 0; int outOffset = 0;
(int remainder, int outRemainder, int height) = GetLineRemainders(data.Length, width, 2, 4); (int remainder, int outRemainder, int height) = GetLineRemainders(data.Length, width, 2, 4);
ReadOnlySpan<ushort> inputSpan = MemoryMarshal.Cast<byte, ushort>(data); ReadOnlySpan<ushort> inputSpan = MemoryMarshal.Cast<byte, ushort>(data);
Span<uint> outputSpan = MemoryMarshal.Cast<byte, uint>(output.Memory.Span); Span<uint> outputSpan = MemoryMarshal.Cast<byte, uint>(output.Span);
for (int y = 0; y < height; y++) for (int y = 0; y < height; y++)
{ {
@ -109,16 +109,16 @@ namespace Ryujinx.Graphics.Texture
return output; return output;
} }
public static IMemoryOwner<byte> ConvertR5G5B5ToR8G8B8A8(ReadOnlySpan<byte> data, int width, bool forceAlpha) public static MemoryOwner<byte> ConvertR5G5B5ToR8G8B8A8(ReadOnlySpan<byte> data, int width, bool forceAlpha)
{ {
IMemoryOwner<byte> output = ByteMemoryPool.Rent(data.Length * 2); MemoryOwner<byte> output = MemoryOwner<byte>.Rent(data.Length * 2);
int offset = 0; int offset = 0;
int outOffset = 0; int outOffset = 0;
(int remainder, int outRemainder, int height) = GetLineRemainders(data.Length, width, 2, 4); (int remainder, int outRemainder, int height) = GetLineRemainders(data.Length, width, 2, 4);
ReadOnlySpan<ushort> inputSpan = MemoryMarshal.Cast<byte, ushort>(data); ReadOnlySpan<ushort> inputSpan = MemoryMarshal.Cast<byte, ushort>(data);
Span<uint> outputSpan = MemoryMarshal.Cast<byte, uint>(output.Memory.Span); Span<uint> outputSpan = MemoryMarshal.Cast<byte, uint>(output.Span);
for (int y = 0; y < height; y++) for (int y = 0; y < height; y++)
{ {
@ -146,16 +146,16 @@ namespace Ryujinx.Graphics.Texture
return output; return output;
} }
public static IMemoryOwner<byte> ConvertA1B5G5R5ToR8G8B8A8(ReadOnlySpan<byte> data, int width) public static MemoryOwner<byte> ConvertA1B5G5R5ToR8G8B8A8(ReadOnlySpan<byte> data, int width)
{ {
IMemoryOwner<byte> output = ByteMemoryPool.Rent(data.Length * 2); MemoryOwner<byte> output = MemoryOwner<byte>.Rent(data.Length * 2);
int offset = 0; int offset = 0;
int outOffset = 0; int outOffset = 0;
(int remainder, int outRemainder, int height) = GetLineRemainders(data.Length, width, 2, 4); (int remainder, int outRemainder, int height) = GetLineRemainders(data.Length, width, 2, 4);
ReadOnlySpan<ushort> inputSpan = MemoryMarshal.Cast<byte, ushort>(data); ReadOnlySpan<ushort> inputSpan = MemoryMarshal.Cast<byte, ushort>(data);
Span<uint> outputSpan = MemoryMarshal.Cast<byte, uint>(output.Memory.Span); Span<uint> outputSpan = MemoryMarshal.Cast<byte, uint>(output.Span);
for (int y = 0; y < height; y++) for (int y = 0; y < height; y++)
{ {
@ -183,16 +183,16 @@ namespace Ryujinx.Graphics.Texture
return output; return output;
} }
public static IMemoryOwner<byte> ConvertR4G4B4A4ToR8G8B8A8(ReadOnlySpan<byte> data, int width) public static MemoryOwner<byte> ConvertR4G4B4A4ToR8G8B8A8(ReadOnlySpan<byte> data, int width)
{ {
IMemoryOwner<byte> output = ByteMemoryPool.Rent(data.Length * 2); MemoryOwner<byte> output = MemoryOwner<byte>.Rent(data.Length * 2);
int offset = 0; int offset = 0;
int outOffset = 0; int outOffset = 0;
(int remainder, int outRemainder, int height) = GetLineRemainders(data.Length, width, 2, 4); (int remainder, int outRemainder, int height) = GetLineRemainders(data.Length, width, 2, 4);
ReadOnlySpan<ushort> inputSpan = MemoryMarshal.Cast<byte, ushort>(data); ReadOnlySpan<ushort> inputSpan = MemoryMarshal.Cast<byte, ushort>(data);
Span<uint> outputSpan = MemoryMarshal.Cast<byte, uint>(output.Memory.Span); Span<uint> outputSpan = MemoryMarshal.Cast<byte, uint>(output.Span);
for (int y = 0; y < height; y++) for (int y = 0; y < height; y++)
{ {

View File

@ -211,7 +211,7 @@ namespace Ryujinx.Graphics.Vulkan
public void Initialize() public void Initialize()
{ {
IMemoryOwner<byte> dummyTextureData = ByteMemoryPool.RentCleared(4); MemoryOwner<byte> dummyTextureData = MemoryOwner<byte>.RentCleared(4);
_dummyTexture.SetData(dummyTextureData); _dummyTexture.SetData(dummyTextureData);
} }

View File

@ -439,7 +439,7 @@ namespace Ryujinx.Graphics.Vulkan
{ {
SType = StructureType.PipelineInputAssemblyStateCreateInfo, SType = StructureType.PipelineInputAssemblyStateCreateInfo,
PrimitiveRestartEnable = primitiveRestartEnable, PrimitiveRestartEnable = primitiveRestartEnable,
Topology = Topology, Topology = HasTessellationControlShader ? PrimitiveTopology.PatchList : Topology,
}; };
var tessellationState = new PipelineTessellationStateCreateInfo var tessellationState = new PipelineTessellationStateCreateInfo

View File

@ -667,8 +667,36 @@ namespace Ryujinx.Graphics.Vulkan
if (PrepareOutputBuffer(cbs, hostSize, buffer, out VkBuffer copyToBuffer, out BufferHolder tempCopyHolder)) if (PrepareOutputBuffer(cbs, hostSize, buffer, out VkBuffer copyToBuffer, out BufferHolder tempCopyHolder))
{ {
// No barrier necessary, as this is a temporary copy buffer.
offset = 0; offset = 0;
} }
else
{
BufferHolder.InsertBufferBarrier(
_gd,
cbs.CommandBuffer,
copyToBuffer,
BufferHolder.DefaultAccessFlags,
AccessFlags.TransferWriteBit,
PipelineStageFlags.AllCommandsBit,
PipelineStageFlags.TransferBit,
offset,
outSize);
}
InsertImageBarrier(
_gd.Api,
cbs.CommandBuffer,
image,
TextureStorage.DefaultAccessMask,
AccessFlags.TransferReadBit,
PipelineStageFlags.AllCommandsBit,
PipelineStageFlags.TransferBit,
Info.Format.ConvertAspectFlags(),
FirstLayer + layer,
FirstLevel + level,
1,
1);
CopyFromOrToBuffer(cbs.CommandBuffer, copyToBuffer, image, hostSize, true, layer, level, 1, 1, singleSlice: true, offset, stride); CopyFromOrToBuffer(cbs.CommandBuffer, copyToBuffer, image, hostSize, true, layer, level, 1, 1, singleSlice: true, offset, stride);
@ -677,6 +705,19 @@ namespace Ryujinx.Graphics.Vulkan
CopyDataToOutputBuffer(cbs, tempCopyHolder, autoBuffer, hostSize, range.Offset); CopyDataToOutputBuffer(cbs, tempCopyHolder, autoBuffer, hostSize, range.Offset);
tempCopyHolder.Dispose(); tempCopyHolder.Dispose();
} }
else
{
BufferHolder.InsertBufferBarrier(
_gd,
cbs.CommandBuffer,
copyToBuffer,
AccessFlags.TransferWriteBit,
BufferHolder.DefaultAccessFlags,
PipelineStageFlags.TransferBit,
PipelineStageFlags.AllCommandsBit,
offset,
outSize);
}
} }
private ReadOnlySpan<byte> GetData(CommandBufferPool cbp, PersistentFlushBuffer flushBuffer) private ReadOnlySpan<byte> GetData(CommandBufferPool cbp, PersistentFlushBuffer flushBuffer)

View File

@ -1,10 +0,0 @@
namespace Ryujinx.HLE.HOS.Kernel.Memory
{
enum AddressSpaceType
{
Addr32Bits = 0,
Addr36Bits = 1,
Addr32BitsNoMap = 2,
Addr39Bits = 3,
}
}

View File

@ -58,11 +58,10 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
public ulong AslrRegionStart { get; private set; } public ulong AslrRegionStart { get; private set; }
public ulong AslrRegionEnd { get; private set; } public ulong AslrRegionEnd { get; private set; }
#pragma warning disable IDE0052 // Remove unread private member
private ulong _heapCapacity; private ulong _heapCapacity;
#pragma warning restore IDE0052
public ulong PhysicalMemoryUsage { get; private set; } public ulong PhysicalMemoryUsage { get; private set; }
public ulong AliasRegionExtraSize { get; private set; }
private readonly KMemoryBlockManager _blockManager; private readonly KMemoryBlockManager _blockManager;
@ -98,30 +97,21 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
_reservedAddressSpaceSize = reservedAddressSpaceSize; _reservedAddressSpaceSize = reservedAddressSpaceSize;
} }
private static readonly int[] _addrSpaceSizes = { 32, 36, 32, 39 };
public Result InitializeForProcess( public Result InitializeForProcess(
AddressSpaceType addrSpaceType, ProcessCreationFlags flags,
bool aslrEnabled,
bool fromBack, bool fromBack,
MemoryRegion memRegion, MemoryRegion memRegion,
ulong address, ulong address,
ulong size, ulong size,
KMemoryBlockSlabManager slabManager) KMemoryBlockSlabManager slabManager)
{ {
if ((uint)addrSpaceType > (uint)AddressSpaceType.Addr39Bits)
{
throw new ArgumentException($"AddressSpaceType bigger than {(uint)AddressSpaceType.Addr39Bits}: {(uint)addrSpaceType}", nameof(addrSpaceType));
}
_contextId = Context.ContextIdManager.GetId(); _contextId = Context.ContextIdManager.GetId();
ulong addrSpaceBase = 0; ulong addrSpaceBase = 0;
ulong addrSpaceSize = 1UL << _addrSpaceSizes[(int)addrSpaceType]; ulong addrSpaceSize = 1UL << GetAddressSpaceWidth(flags);
Result result = CreateUserAddressSpace( Result result = CreateUserAddressSpace(
addrSpaceType, flags,
aslrEnabled,
fromBack, fromBack,
addrSpaceBase, addrSpaceBase,
addrSpaceSize, addrSpaceSize,
@ -138,6 +128,22 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
return result; return result;
} }
private static int GetAddressSpaceWidth(ProcessCreationFlags flags)
{
switch (flags & ProcessCreationFlags.AddressSpaceMask)
{
case ProcessCreationFlags.AddressSpace32Bit:
case ProcessCreationFlags.AddressSpace32BitWithoutAlias:
return 32;
case ProcessCreationFlags.AddressSpace64BitDeprecated:
return 36;
case ProcessCreationFlags.AddressSpace64Bit:
return 39;
}
throw new ArgumentException($"Invalid process flags {flags}", nameof(flags));
}
private struct Region private struct Region
{ {
public ulong Start; public ulong Start;
@ -147,8 +153,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
} }
private Result CreateUserAddressSpace( private Result CreateUserAddressSpace(
AddressSpaceType addrSpaceType, ProcessCreationFlags flags,
bool aslrEnabled,
bool fromBack, bool fromBack,
ulong addrSpaceStart, ulong addrSpaceStart,
ulong addrSpaceEnd, ulong addrSpaceEnd,
@ -168,9 +173,11 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
ulong stackAndTlsIoStart; ulong stackAndTlsIoStart;
ulong stackAndTlsIoEnd; ulong stackAndTlsIoEnd;
switch (addrSpaceType) AliasRegionExtraSize = 0;
switch (flags & ProcessCreationFlags.AddressSpaceMask)
{ {
case AddressSpaceType.Addr32Bits: case ProcessCreationFlags.AddressSpace32Bit:
aliasRegion.Size = 0x40000000; aliasRegion.Size = 0x40000000;
heapRegion.Size = 0x40000000; heapRegion.Size = 0x40000000;
stackRegion.Size = 0; stackRegion.Size = 0;
@ -183,7 +190,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
stackAndTlsIoEnd = 0x40000000; stackAndTlsIoEnd = 0x40000000;
break; break;
case AddressSpaceType.Addr36Bits: case ProcessCreationFlags.AddressSpace64BitDeprecated:
aliasRegion.Size = 0x180000000; aliasRegion.Size = 0x180000000;
heapRegion.Size = 0x180000000; heapRegion.Size = 0x180000000;
stackRegion.Size = 0; stackRegion.Size = 0;
@ -196,7 +203,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
stackAndTlsIoEnd = 0x80000000; stackAndTlsIoEnd = 0x80000000;
break; break;
case AddressSpaceType.Addr32BitsNoMap: case ProcessCreationFlags.AddressSpace32BitWithoutAlias:
aliasRegion.Size = 0; aliasRegion.Size = 0;
heapRegion.Size = 0x80000000; heapRegion.Size = 0x80000000;
stackRegion.Size = 0; stackRegion.Size = 0;
@ -209,7 +216,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
stackAndTlsIoEnd = 0x40000000; stackAndTlsIoEnd = 0x40000000;
break; break;
case AddressSpaceType.Addr39Bits: case ProcessCreationFlags.AddressSpace64Bit:
if (_reservedAddressSpaceSize < addrSpaceEnd) if (_reservedAddressSpaceSize < addrSpaceEnd)
{ {
int addressSpaceWidth = (int)ulong.Log2(_reservedAddressSpaceSize); int addressSpaceWidth = (int)ulong.Log2(_reservedAddressSpaceSize);
@ -218,8 +225,8 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
heapRegion.Size = 0x180000000; heapRegion.Size = 0x180000000;
stackRegion.Size = 1UL << (addressSpaceWidth - 8); stackRegion.Size = 1UL << (addressSpaceWidth - 8);
tlsIoRegion.Size = 1UL << (addressSpaceWidth - 3); tlsIoRegion.Size = 1UL << (addressSpaceWidth - 3);
CodeRegionStart = BitUtils.AlignDown<ulong>(address, RegionAlignment); CodeRegionStart = BitUtils.AlignDown(address, RegionAlignment);
codeRegionSize = BitUtils.AlignUp<ulong>(endAddr, RegionAlignment) - CodeRegionStart; codeRegionSize = BitUtils.AlignUp(endAddr, RegionAlignment) - CodeRegionStart;
stackAndTlsIoStart = 0; stackAndTlsIoStart = 0;
stackAndTlsIoEnd = 0; stackAndTlsIoEnd = 0;
AslrRegionStart = 0x8000000; AslrRegionStart = 0x8000000;
@ -239,9 +246,16 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
stackAndTlsIoStart = 0; stackAndTlsIoStart = 0;
stackAndTlsIoEnd = 0; stackAndTlsIoEnd = 0;
} }
if (flags.HasFlag(ProcessCreationFlags.EnableAliasRegionExtraSize))
{
AliasRegionExtraSize = addrSpaceEnd / 8;
aliasRegion.Size += AliasRegionExtraSize;
}
break; break;
default: default:
throw new ArgumentException($"AddressSpaceType bigger than {(uint)AddressSpaceType.Addr39Bits}: {(uint)addrSpaceType}", nameof(addrSpaceType)); throw new ArgumentException($"Invalid process flags {flags}", nameof(flags));
} }
CodeRegionEnd = CodeRegionStart + codeRegionSize; CodeRegionEnd = CodeRegionStart + codeRegionSize;
@ -266,6 +280,8 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
ulong aslrMaxOffset = mapAvailableSize - mapTotalSize; ulong aslrMaxOffset = mapAvailableSize - mapTotalSize;
bool aslrEnabled = flags.HasFlag(ProcessCreationFlags.EnableAslr);
_aslrEnabled = aslrEnabled; _aslrEnabled = aslrEnabled;
AddrSpaceStart = addrSpaceStart; AddrSpaceStart = addrSpaceStart;
@ -725,7 +741,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
{ {
address = 0; address = 0;
if (size > HeapRegionEnd - HeapRegionStart) if (size > HeapRegionEnd - HeapRegionStart || size > _heapCapacity)
{ {
return KernelResult.OutOfMemory; return KernelResult.OutOfMemory;
} }

View File

@ -126,8 +126,6 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
_contextFactory = contextFactory ?? new ProcessContextFactory(); _contextFactory = contextFactory ?? new ProcessContextFactory();
_customThreadStart = customThreadStart; _customThreadStart = customThreadStart;
AddressSpaceType addrSpaceType = (AddressSpaceType)((int)(creationInfo.Flags & ProcessCreationFlags.AddressSpaceMask) >> (int)ProcessCreationFlags.AddressSpaceShift);
Pid = KernelContext.NewKipId(); Pid = KernelContext.NewKipId();
if (Pid == 0 || Pid >= KernelConstants.InitialProcessId) if (Pid == 0 || Pid >= KernelConstants.InitialProcessId)
@ -137,8 +135,6 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
InitializeMemoryManager(creationInfo.Flags); InitializeMemoryManager(creationInfo.Flags);
bool aslrEnabled = creationInfo.Flags.HasFlag(ProcessCreationFlags.EnableAslr);
ulong codeAddress = creationInfo.CodeAddress; ulong codeAddress = creationInfo.CodeAddress;
ulong codeSize = (ulong)creationInfo.CodePagesCount * KPageTableBase.PageSize; ulong codeSize = (ulong)creationInfo.CodePagesCount * KPageTableBase.PageSize;
@ -148,9 +144,8 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
: KernelContext.SmallMemoryBlockSlabManager; : KernelContext.SmallMemoryBlockSlabManager;
Result result = MemoryManager.InitializeForProcess( Result result = MemoryManager.InitializeForProcess(
addrSpaceType, creationInfo.Flags,
aslrEnabled, !creationInfo.Flags.HasFlag(ProcessCreationFlags.EnableAslr),
!aslrEnabled,
memRegion, memRegion,
codeAddress, codeAddress,
codeSize, codeSize,
@ -234,8 +229,6 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
: KernelContext.SmallMemoryBlockSlabManager; : KernelContext.SmallMemoryBlockSlabManager;
} }
AddressSpaceType addrSpaceType = (AddressSpaceType)((int)(creationInfo.Flags & ProcessCreationFlags.AddressSpaceMask) >> (int)ProcessCreationFlags.AddressSpaceShift);
Pid = KernelContext.NewProcessId(); Pid = KernelContext.NewProcessId();
if (Pid == ulong.MaxValue || Pid < KernelConstants.InitialProcessId) if (Pid == ulong.MaxValue || Pid < KernelConstants.InitialProcessId)
@ -245,16 +238,13 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
InitializeMemoryManager(creationInfo.Flags); InitializeMemoryManager(creationInfo.Flags);
bool aslrEnabled = creationInfo.Flags.HasFlag(ProcessCreationFlags.EnableAslr);
ulong codeAddress = creationInfo.CodeAddress; ulong codeAddress = creationInfo.CodeAddress;
ulong codeSize = codePagesCount * KPageTableBase.PageSize; ulong codeSize = codePagesCount * KPageTableBase.PageSize;
Result result = MemoryManager.InitializeForProcess( Result result = MemoryManager.InitializeForProcess(
addrSpaceType, creationInfo.Flags,
aslrEnabled, !creationInfo.Flags.HasFlag(ProcessCreationFlags.EnableAslr),
!aslrEnabled,
memRegion, memRegion,
codeAddress, codeAddress,
codeSize, codeSize,
@ -309,8 +299,8 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
private Result ParseProcessInfo(ProcessCreationInfo creationInfo) private Result ParseProcessInfo(ProcessCreationInfo creationInfo)
{ {
// Ensure that the current kernel version is equal or above to the minimum required. // Ensure that the current kernel version is equal or above to the minimum required.
uint requiredKernelVersionMajor = (uint)Capabilities.KernelReleaseVersion >> 19; uint requiredKernelVersionMajor = Capabilities.KernelReleaseVersion >> 19;
uint requiredKernelVersionMinor = ((uint)Capabilities.KernelReleaseVersion >> 15) & 0xf; uint requiredKernelVersionMinor = (Capabilities.KernelReleaseVersion >> 15) & 0xf;
if (KernelContext.EnableVersionChecks) if (KernelContext.EnableVersionChecks)
{ {
@ -519,12 +509,10 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
return result; return result;
} }
#pragma warning disable CA1822 // Mark member as static
private void GenerateRandomEntropy() private void GenerateRandomEntropy()
{ {
// TODO. // TODO.
} }
#pragma warning restore CA1822
public Result Start(int mainThreadPriority, ulong stackSize) public Result Start(int mainThreadPriority, ulong stackSize)
{ {
@ -1182,5 +1170,10 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
// TODO // TODO
return false; return false;
} }
public bool IsSvcPermitted(int svcId)
{
return Capabilities.IsSvcPermitted(svcId);
}
} }
} }

View File

@ -8,6 +8,8 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
{ {
class KProcessCapabilities class KProcessCapabilities
{ {
private const int SvcMaskElementBits = 8;
public byte[] SvcAccessMask { get; } public byte[] SvcAccessMask { get; }
public byte[] IrqAccessMask { get; } public byte[] IrqAccessMask { get; }
@ -22,7 +24,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
public KProcessCapabilities() public KProcessCapabilities()
{ {
// length / number of bits of the underlying type // length / number of bits of the underlying type
SvcAccessMask = new byte[KernelConstants.SupervisorCallCount / 8]; SvcAccessMask = new byte[KernelConstants.SupervisorCallCount / SvcMaskElementBits];
IrqAccessMask = new byte[0x80]; IrqAccessMask = new byte[0x80];
} }
@ -208,7 +210,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
return KernelResult.MaximumExceeded; return KernelResult.MaximumExceeded;
} }
SvcAccessMask[svcId / 8] |= (byte)(1 << (svcId & 7)); SvcAccessMask[svcId / SvcMaskElementBits] |= (byte)(1 << (svcId % SvcMaskElementBits));
} }
break; break;
@ -324,5 +326,13 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
return mask << (int)min; return mask << (int)min;
} }
public bool IsSvcPermitted(int svcId)
{
int index = svcId / SvcMaskElementBits;
int mask = 1 << (svcId % SvcMaskElementBits);
return (uint)svcId < KernelConstants.SupervisorCallCount && (SvcAccessMask[index] & mask) != 0;
}
} }
} }

View File

@ -29,6 +29,8 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
PoolPartitionMask = 0xf << PoolPartitionShift, PoolPartitionMask = 0xf << PoolPartitionShift,
OptimizeMemoryAllocation = 1 << 11, OptimizeMemoryAllocation = 1 << 11,
DisableDeviceAddressSpaceMerge = 1 << 12,
EnableAliasRegionExtraSize = 1 << 13,
All = All =
Is64Bit | Is64Bit |
@ -38,6 +40,8 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
IsApplication | IsApplication |
DeprecatedUseSecureMemory | DeprecatedUseSecureMemory |
PoolPartitionMask | PoolPartitionMask |
OptimizeMemoryAllocation, OptimizeMemoryAllocation |
DisableDeviceAddressSpaceMerge |
EnableAliasRegionExtraSize,
} }
} }

View File

@ -21,14 +21,17 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
SystemResourceSizeTotal, SystemResourceSizeTotal,
SystemResourceSizeUsed, SystemResourceSizeUsed,
ProgramId, ProgramId,
// NOTE: Added in 4.0.0, removed in 5.0.0. InitialProcessIdRange, // NOTE: Added in 4.0.0, removed in 5.0.0.
InitialProcessIdRange,
UserExceptionContextAddress, UserExceptionContextAddress,
TotalNonSystemMemorySize, TotalNonSystemMemorySize,
UsedNonSystemMemorySize, UsedNonSystemMemorySize,
IsApplication, IsApplication,
FreeThreadCount, FreeThreadCount,
ThreadTickCount, ThreadTickCount,
IsSvcPermitted,
IoRegionHint,
AliasRegionExtraSize,
MesosphereCurrentProcess = 65001, MesosphereCurrentProcess = 65001,
} }
} }

View File

@ -84,6 +84,17 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
return KernelResult.InvalidSize; return KernelResult.InvalidSize;
} }
if (info.Flags.HasFlag(ProcessCreationFlags.EnableAliasRegionExtraSize))
{
if ((info.Flags & ProcessCreationFlags.AddressSpaceMask) != ProcessCreationFlags.AddressSpace64Bit ||
info.SystemResourcePagesCount <= 0)
{
return KernelResult.InvalidState;
}
// TODO: Check that we are in debug mode.
}
if (info.Flags.HasFlag(ProcessCreationFlags.OptimizeMemoryAllocation) && if (info.Flags.HasFlag(ProcessCreationFlags.OptimizeMemoryAllocation) &&
!info.Flags.HasFlag(ProcessCreationFlags.IsApplication)) !info.Flags.HasFlag(ProcessCreationFlags.IsApplication))
{ {
@ -139,7 +150,6 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
return handleTable.GenerateHandle(process, out handle); return handleTable.GenerateHandle(process, out handle);
} }
#pragma warning disable CA1822 // Mark member as static
public Result StartProcess(int handle, int priority, int cpuCore, ulong mainThreadStackSize) public Result StartProcess(int handle, int priority, int cpuCore, ulong mainThreadStackSize)
{ {
KProcess process = KernelStatic.GetCurrentProcess().HandleTable.GetObject<KProcess>(handle); KProcess process = KernelStatic.GetCurrentProcess().HandleTable.GetObject<KProcess>(handle);
@ -172,17 +182,14 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
return Result.Success; return Result.Success;
} }
#pragma warning restore CA1822
[Svc(0x5f)] [Svc(0x5f)]
#pragma warning disable CA1822 // Mark member as static
public Result FlushProcessDataCache(int processHandle, ulong address, ulong size) public Result FlushProcessDataCache(int processHandle, ulong address, ulong size)
{ {
// FIXME: This needs to be implemented as ARMv7 doesn't have any way to do cache maintenance operations on EL0. // FIXME: This needs to be implemented as ARMv7 doesn't have any way to do cache maintenance operations on EL0.
// As we don't support (and don't actually need) to flush the cache, this is stubbed. // As we don't support (and don't actually need) to flush the cache, this is stubbed.
return Result.Success; return Result.Success;
} }
#pragma warning restore CA1822
// IPC // IPC
@ -256,7 +263,6 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
} }
[Svc(0x22)] [Svc(0x22)]
#pragma warning disable CA1822 // Mark member as static
public Result SendSyncRequestWithUserBuffer( public Result SendSyncRequestWithUserBuffer(
[PointerSized] ulong messagePtr, [PointerSized] ulong messagePtr,
[PointerSized] ulong messageSize, [PointerSized] ulong messageSize,
@ -306,7 +312,6 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
return result; return result;
} }
#pragma warning restore CA1822
[Svc(0x23)] [Svc(0x23)]
public Result SendAsyncRequestWithUserBuffer( public Result SendAsyncRequestWithUserBuffer(
@ -896,7 +901,6 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
} }
[Svc(2)] [Svc(2)]
#pragma warning disable CA1822 // Mark member as static
public Result SetMemoryPermission([PointerSized] ulong address, [PointerSized] ulong size, KMemoryPermission permission) public Result SetMemoryPermission([PointerSized] ulong address, [PointerSized] ulong size, KMemoryPermission permission)
{ {
if (!PageAligned(address)) if (!PageAligned(address))
@ -928,10 +932,8 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
return currentProcess.MemoryManager.SetMemoryPermission(address, size, permission); return currentProcess.MemoryManager.SetMemoryPermission(address, size, permission);
} }
#pragma warning restore CA1822
[Svc(3)] [Svc(3)]
#pragma warning disable CA1822 // Mark member as static
public Result SetMemoryAttribute( public Result SetMemoryAttribute(
[PointerSized] ulong address, [PointerSized] ulong address,
[PointerSized] ulong size, [PointerSized] ulong size,
@ -979,10 +981,8 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
return result; return result;
} }
#pragma warning restore CA1822
[Svc(4)] [Svc(4)]
#pragma warning disable CA1822 // Mark member as static
public Result MapMemory([PointerSized] ulong dst, [PointerSized] ulong src, [PointerSized] ulong size) public Result MapMemory([PointerSized] ulong dst, [PointerSized] ulong src, [PointerSized] ulong size)
{ {
if (!PageAligned(src | dst)) if (!PageAligned(src | dst))
@ -1018,10 +1018,8 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
return process.MemoryManager.Map(dst, src, size); return process.MemoryManager.Map(dst, src, size);
} }
#pragma warning restore CA1822
[Svc(5)] [Svc(5)]
#pragma warning disable CA1822 // Mark member as static
public Result UnmapMemory([PointerSized] ulong dst, [PointerSized] ulong src, [PointerSized] ulong size) public Result UnmapMemory([PointerSized] ulong dst, [PointerSized] ulong src, [PointerSized] ulong size)
{ {
if (!PageAligned(src | dst)) if (!PageAligned(src | dst))
@ -1057,7 +1055,6 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
return process.MemoryManager.Unmap(dst, src, size); return process.MemoryManager.Unmap(dst, src, size);
} }
#pragma warning restore CA1822
[Svc(6)] [Svc(6)]
public Result QueryMemory([PointerSized] ulong infoPtr, [PointerSized] out ulong pageInfo, [PointerSized] ulong address) public Result QueryMemory([PointerSized] ulong infoPtr, [PointerSized] out ulong pageInfo, [PointerSized] ulong address)
@ -1074,7 +1071,6 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
return result; return result;
} }
#pragma warning disable CA1822 // Mark member as static
public Result QueryMemory(out MemoryInfo info, out ulong pageInfo, ulong address) public Result QueryMemory(out MemoryInfo info, out ulong pageInfo, ulong address)
{ {
KProcess process = KernelStatic.GetCurrentProcess(); KProcess process = KernelStatic.GetCurrentProcess();
@ -1094,10 +1090,8 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
return Result.Success; return Result.Success;
} }
#pragma warning restore CA1822
[Svc(0x13)] [Svc(0x13)]
#pragma warning disable CA1822 // Mark member as static
public Result MapSharedMemory(int handle, [PointerSized] ulong address, [PointerSized] ulong size, KMemoryPermission permission) public Result MapSharedMemory(int handle, [PointerSized] ulong address, [PointerSized] ulong size, KMemoryPermission permission)
{ {
if (!PageAligned(address)) if (!PageAligned(address))
@ -1143,10 +1137,8 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
currentProcess, currentProcess,
permission); permission);
} }
#pragma warning restore CA1822
[Svc(0x14)] [Svc(0x14)]
#pragma warning disable CA1822 // Mark member as static
public Result UnmapSharedMemory(int handle, [PointerSized] ulong address, [PointerSized] ulong size) public Result UnmapSharedMemory(int handle, [PointerSized] ulong address, [PointerSized] ulong size)
{ {
if (!PageAligned(address)) if (!PageAligned(address))
@ -1186,7 +1178,6 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
size, size,
currentProcess); currentProcess);
} }
#pragma warning restore CA1822
[Svc(0x15)] [Svc(0x15)]
public Result CreateTransferMemory(out int handle, [PointerSized] ulong address, [PointerSized] ulong size, KMemoryPermission permission) public Result CreateTransferMemory(out int handle, [PointerSized] ulong address, [PointerSized] ulong size, KMemoryPermission permission)
@ -1253,7 +1244,6 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
} }
[Svc(0x51)] [Svc(0x51)]
#pragma warning disable CA1822 // Mark member as static
public Result MapTransferMemory(int handle, [PointerSized] ulong address, [PointerSized] ulong size, KMemoryPermission permission) public Result MapTransferMemory(int handle, [PointerSized] ulong address, [PointerSized] ulong size, KMemoryPermission permission)
{ {
if (!PageAligned(address)) if (!PageAligned(address))
@ -1299,10 +1289,8 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
currentProcess, currentProcess,
permission); permission);
} }
#pragma warning restore CA1822
[Svc(0x52)] [Svc(0x52)]
#pragma warning disable CA1822 // Mark member as static
public Result UnmapTransferMemory(int handle, [PointerSized] ulong address, [PointerSized] ulong size) public Result UnmapTransferMemory(int handle, [PointerSized] ulong address, [PointerSized] ulong size)
{ {
if (!PageAligned(address)) if (!PageAligned(address))
@ -1342,10 +1330,8 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
size, size,
currentProcess); currentProcess);
} }
#pragma warning restore CA1822
[Svc(0x2c)] [Svc(0x2c)]
#pragma warning disable CA1822 // Mark member as static
public Result MapPhysicalMemory([PointerSized] ulong address, [PointerSized] ulong size) public Result MapPhysicalMemory([PointerSized] ulong address, [PointerSized] ulong size)
{ {
if (!PageAligned(address)) if (!PageAligned(address))
@ -1380,10 +1366,8 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
return process.MemoryManager.MapPhysicalMemory(address, size); return process.MemoryManager.MapPhysicalMemory(address, size);
} }
#pragma warning restore CA1822
[Svc(0x2d)] [Svc(0x2d)]
#pragma warning disable CA1822 // Mark member as static
public Result UnmapPhysicalMemory([PointerSized] ulong address, [PointerSized] ulong size) public Result UnmapPhysicalMemory([PointerSized] ulong address, [PointerSized] ulong size)
{ {
if (!PageAligned(address)) if (!PageAligned(address))
@ -1418,7 +1402,6 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
return process.MemoryManager.UnmapPhysicalMemory(address, size); return process.MemoryManager.UnmapPhysicalMemory(address, size);
} }
#pragma warning restore CA1822
[Svc(0x4b)] [Svc(0x4b)]
public Result CreateCodeMemory(out int handle, [PointerSized] ulong address, [PointerSized] ulong size) public Result CreateCodeMemory(out int handle, [PointerSized] ulong address, [PointerSized] ulong size)
@ -1462,7 +1445,6 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
} }
[Svc(0x4c)] [Svc(0x4c)]
#pragma warning disable CA1822 // Mark member as static
public Result ControlCodeMemory( public Result ControlCodeMemory(
int handle, int handle,
CodeMemoryOperation op, CodeMemoryOperation op,
@ -1540,10 +1522,8 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
return KernelResult.InvalidEnumValue; return KernelResult.InvalidEnumValue;
} }
} }
#pragma warning restore CA1822
[Svc(0x73)] [Svc(0x73)]
#pragma warning disable CA1822 // Mark member as static
public Result SetProcessMemoryPermission( public Result SetProcessMemoryPermission(
int handle, int handle,
ulong src, ulong src,
@ -1584,10 +1564,8 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
return targetProcess.MemoryManager.SetProcessMemoryPermission(src, size, permission); return targetProcess.MemoryManager.SetProcessMemoryPermission(src, size, permission);
} }
#pragma warning restore CA1822
[Svc(0x74)] [Svc(0x74)]
#pragma warning disable CA1822 // Mark member as static
public Result MapProcessMemory( public Result MapProcessMemory(
[PointerSized] ulong dst, [PointerSized] ulong dst,
int handle, int handle,
@ -1643,10 +1621,8 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
return dstProcess.MemoryManager.MapPages(dst, pageList, MemoryState.ProcessMemory, KMemoryPermission.ReadAndWrite); return dstProcess.MemoryManager.MapPages(dst, pageList, MemoryState.ProcessMemory, KMemoryPermission.ReadAndWrite);
} }
#pragma warning restore CA1822
[Svc(0x75)] [Svc(0x75)]
#pragma warning disable CA1822 // Mark member as static
public Result UnmapProcessMemory( public Result UnmapProcessMemory(
[PointerSized] ulong dst, [PointerSized] ulong dst,
int handle, int handle,
@ -1691,10 +1667,8 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
return Result.Success; return Result.Success;
} }
#pragma warning restore CA1822
[Svc(0x77)] [Svc(0x77)]
#pragma warning disable CA1822 // Mark member as static
public Result MapProcessCodeMemory(int handle, ulong dst, ulong src, ulong size) public Result MapProcessCodeMemory(int handle, ulong dst, ulong src, ulong size)
{ {
if (!PageAligned(dst) || !PageAligned(src)) if (!PageAligned(dst) || !PageAligned(src))
@ -1731,10 +1705,8 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
return targetProcess.MemoryManager.MapProcessCodeMemory(dst, src, size); return targetProcess.MemoryManager.MapProcessCodeMemory(dst, src, size);
} }
#pragma warning restore CA1822
[Svc(0x78)] [Svc(0x78)]
#pragma warning disable CA1822 // Mark member as static
public Result UnmapProcessCodeMemory(int handle, ulong dst, ulong src, ulong size) public Result UnmapProcessCodeMemory(int handle, ulong dst, ulong src, ulong size)
{ {
if (!PageAligned(dst) || !PageAligned(src)) if (!PageAligned(dst) || !PageAligned(src))
@ -1771,7 +1743,6 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
return targetProcess.MemoryManager.UnmapProcessCodeMemory(dst, src, size); return targetProcess.MemoryManager.UnmapProcessCodeMemory(dst, src, size);
} }
#pragma warning restore CA1822
private static bool PageAligned(ulong address) private static bool PageAligned(ulong address)
{ {
@ -1781,7 +1752,6 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
// System // System
[Svc(0x7b)] [Svc(0x7b)]
#pragma warning disable CA1822 // Mark member as static
public Result TerminateProcess(int handle) public Result TerminateProcess(int handle)
{ {
KProcess process = KernelStatic.GetCurrentProcess(); KProcess process = KernelStatic.GetCurrentProcess();
@ -1810,15 +1780,12 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
return result; return result;
} }
#pragma warning restore CA1822
[Svc(7)] [Svc(7)]
#pragma warning disable CA1822 // Mark member as static
public void ExitProcess() public void ExitProcess()
{ {
KernelStatic.GetCurrentProcess().TerminateCurrentProcess(); KernelStatic.GetCurrentProcess().TerminateCurrentProcess();
} }
#pragma warning restore CA1822
[Svc(0x11)] [Svc(0x11)]
public Result SignalEvent(int handle) public Result SignalEvent(int handle)
@ -1911,7 +1878,6 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
} }
[Svc(0x26)] [Svc(0x26)]
#pragma warning disable CA1822 // Mark member as static
public void Break(ulong reason) public void Break(ulong reason)
{ {
KThread currentThread = KernelStatic.GetCurrentThread(); KThread currentThread = KernelStatic.GetCurrentThread();
@ -1937,10 +1903,8 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
Logger.Debug?.Print(LogClass.KernelSvc, "Debugger triggered."); Logger.Debug?.Print(LogClass.KernelSvc, "Debugger triggered.");
} }
} }
#pragma warning restore CA1822
[Svc(0x27)] [Svc(0x27)]
#pragma warning disable CA1822 // Mark member as static
public void OutputDebugString([PointerSized] ulong strPtr, [PointerSized] ulong size) public void OutputDebugString([PointerSized] ulong strPtr, [PointerSized] ulong size)
{ {
KProcess process = KernelStatic.GetCurrentProcess(); KProcess process = KernelStatic.GetCurrentProcess();
@ -1949,7 +1913,6 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
Logger.Warning?.Print(LogClass.KernelSvc, str); Logger.Warning?.Print(LogClass.KernelSvc, str);
} }
#pragma warning restore CA1822
[Svc(0x29)] [Svc(0x29)]
public Result GetInfo(out ulong value, InfoType id, int handle, long subId) public Result GetInfo(out ulong value, InfoType id, int handle, long subId)
@ -1978,6 +1941,7 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
case InfoType.UsedNonSystemMemorySize: case InfoType.UsedNonSystemMemorySize:
case InfoType.IsApplication: case InfoType.IsApplication:
case InfoType.FreeThreadCount: case InfoType.FreeThreadCount:
case InfoType.AliasRegionExtraSize:
{ {
if (subId != 0) if (subId != 0)
{ {
@ -2006,22 +1970,19 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
value = process.MemoryManager.AliasRegionStart; value = process.MemoryManager.AliasRegionStart;
break; break;
case InfoType.AliasRegionSize: case InfoType.AliasRegionSize:
value = (process.MemoryManager.AliasRegionEnd - value = process.MemoryManager.AliasRegionEnd - process.MemoryManager.AliasRegionStart;
process.MemoryManager.AliasRegionStart);
break; break;
case InfoType.HeapRegionAddress: case InfoType.HeapRegionAddress:
value = process.MemoryManager.HeapRegionStart; value = process.MemoryManager.HeapRegionStart;
break; break;
case InfoType.HeapRegionSize: case InfoType.HeapRegionSize:
value = (process.MemoryManager.HeapRegionEnd - value = process.MemoryManager.HeapRegionEnd - process.MemoryManager.HeapRegionStart;
process.MemoryManager.HeapRegionStart);
break; break;
case InfoType.TotalMemorySize: case InfoType.TotalMemorySize:
value = process.GetMemoryCapacity(); value = process.GetMemoryCapacity();
break; break;
case InfoType.UsedMemorySize: case InfoType.UsedMemorySize:
value = process.GetMemoryUsage(); value = process.GetMemoryUsage();
break; break;
@ -2029,7 +1990,6 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
case InfoType.AslrRegionAddress: case InfoType.AslrRegionAddress:
value = process.MemoryManager.GetAddrSpaceBaseAddr(); value = process.MemoryManager.GetAddrSpaceBaseAddr();
break; break;
case InfoType.AslrRegionSize: case InfoType.AslrRegionSize:
value = process.MemoryManager.GetAddrSpaceSize(); value = process.MemoryManager.GetAddrSpaceSize();
break; break;
@ -2038,20 +1998,17 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
value = process.MemoryManager.StackRegionStart; value = process.MemoryManager.StackRegionStart;
break; break;
case InfoType.StackRegionSize: case InfoType.StackRegionSize:
value = (process.MemoryManager.StackRegionEnd - value = process.MemoryManager.StackRegionEnd - process.MemoryManager.StackRegionStart;
process.MemoryManager.StackRegionStart);
break; break;
case InfoType.SystemResourceSizeTotal: case InfoType.SystemResourceSizeTotal:
value = process.PersonalMmHeapPagesCount * KPageTableBase.PageSize; value = process.PersonalMmHeapPagesCount * KPageTableBase.PageSize;
break; break;
case InfoType.SystemResourceSizeUsed: case InfoType.SystemResourceSizeUsed:
if (process.PersonalMmHeapPagesCount != 0) if (process.PersonalMmHeapPagesCount != 0)
{ {
value = process.MemoryManager.GetMmUsedPages() * KPageTableBase.PageSize; value = process.MemoryManager.GetMmUsedPages() * KPageTableBase.PageSize;
} }
break; break;
case InfoType.ProgramId: case InfoType.ProgramId:
@ -2065,7 +2022,6 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
case InfoType.TotalNonSystemMemorySize: case InfoType.TotalNonSystemMemorySize:
value = process.GetMemoryCapacityWithoutPersonalMmHeap(); value = process.GetMemoryCapacityWithoutPersonalMmHeap();
break; break;
case InfoType.UsedNonSystemMemorySize: case InfoType.UsedNonSystemMemorySize:
value = process.GetMemoryUsageWithoutPersonalMmHeap(); value = process.GetMemoryUsageWithoutPersonalMmHeap();
break; break;
@ -2084,10 +2040,12 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
{ {
value = 0; value = 0;
} }
break;
case InfoType.AliasRegionExtraSize:
value = process.MemoryManager.AliasRegionExtraSize;
break; break;
} }
break; break;
} }
@ -2104,7 +2062,6 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
} }
value = KernelStatic.GetCurrentProcess().Debug ? 1UL : 0UL; value = KernelStatic.GetCurrentProcess().Debug ? 1UL : 0UL;
break; break;
} }
@ -2136,7 +2093,6 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
value = (uint)resLimHandle; value = (uint)resLimHandle;
} }
break; break;
} }
@ -2155,7 +2111,6 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
} }
value = (ulong)KTimeManager.ConvertHostTicksToTicks(_context.Schedulers[currentCore].TotalIdleTimeTicks); value = (ulong)KTimeManager.ConvertHostTicksToTicks(_context.Schedulers[currentCore].TotalIdleTimeTicks);
break; break;
} }
@ -2174,7 +2129,6 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
KProcess currentProcess = KernelStatic.GetCurrentProcess(); KProcess currentProcess = KernelStatic.GetCurrentProcess();
value = currentProcess.RandomEntropy[subId]; value = currentProcess.RandomEntropy[subId];
break; break;
} }
@ -2220,7 +2174,22 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
value = (ulong)KTimeManager.ConvertHostTicksToTicks(totalTimeRunning); value = (ulong)KTimeManager.ConvertHostTicksToTicks(totalTimeRunning);
} }
break;
}
case InfoType.IsSvcPermitted:
{
if (handle != 0)
{
return KernelResult.InvalidHandle;
}
if (subId != 0x36)
{
return KernelResult.InvalidCombination;
}
value = KernelStatic.GetCurrentProcess().IsSvcPermitted((int)subId) ? 1UL : 0UL;
break; break;
} }
@ -2231,7 +2200,7 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
return KernelResult.InvalidHandle; return KernelResult.InvalidHandle;
} }
if ((ulong)subId != 0) if (subId != 0)
{ {
return KernelResult.InvalidCombination; return KernelResult.InvalidCombination;
} }
@ -2246,8 +2215,7 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
return result; return result;
} }
value = (ulong)outHandle; value = (uint)outHandle;
break; break;
} }
@ -2398,7 +2366,6 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
} }
[Svc(0x30)] [Svc(0x30)]
#pragma warning disable CA1822 // Mark member as static
public Result GetResourceLimitLimitValue(out long limitValue, int handle, LimitableResource resource) public Result GetResourceLimitLimitValue(out long limitValue, int handle, LimitableResource resource)
{ {
limitValue = 0; limitValue = 0;
@ -2419,10 +2386,8 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
return Result.Success; return Result.Success;
} }
#pragma warning restore CA1822
[Svc(0x31)] [Svc(0x31)]
#pragma warning disable CA1822 // Mark member as static
public Result GetResourceLimitCurrentValue(out long limitValue, int handle, LimitableResource resource) public Result GetResourceLimitCurrentValue(out long limitValue, int handle, LimitableResource resource)
{ {
limitValue = 0; limitValue = 0;
@ -2443,10 +2408,8 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
return Result.Success; return Result.Success;
} }
#pragma warning restore CA1822
[Svc(0x37)] [Svc(0x37)]
#pragma warning disable CA1822 // Mark member as static
public Result GetResourceLimitPeakValue(out long peak, int handle, LimitableResource resource) public Result GetResourceLimitPeakValue(out long peak, int handle, LimitableResource resource)
{ {
peak = 0; peak = 0;
@ -2467,7 +2430,6 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
return Result.Success; return Result.Success;
} }
#pragma warning restore CA1822
[Svc(0x7d)] [Svc(0x7d)]
public Result CreateResourceLimit(out int handle) public Result CreateResourceLimit(out int handle)
@ -2480,7 +2442,6 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
} }
[Svc(0x7e)] [Svc(0x7e)]
#pragma warning disable CA1822 // Mark member as static
public Result SetResourceLimitLimitValue(int handle, LimitableResource resource, long limitValue) public Result SetResourceLimitLimitValue(int handle, LimitableResource resource, long limitValue)
{ {
if (resource >= LimitableResource.Count) if (resource >= LimitableResource.Count)
@ -2497,7 +2458,6 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
return resourceLimit.SetLimitValue(resource, limitValue); return resourceLimit.SetLimitValue(resource, limitValue);
} }
#pragma warning restore CA1822
// Thread // Thread
@ -2577,7 +2537,6 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
} }
[Svc(9)] [Svc(9)]
#pragma warning disable CA1822 // Mark member as static
public Result StartThread(int handle) public Result StartThread(int handle)
{ {
KProcess process = KernelStatic.GetCurrentProcess(); KProcess process = KernelStatic.GetCurrentProcess();
@ -2604,17 +2563,14 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
return KernelResult.InvalidHandle; return KernelResult.InvalidHandle;
} }
} }
#pragma warning restore CA1822
[Svc(0xa)] [Svc(0xa)]
#pragma warning disable CA1822 // Mark member as static
public void ExitThread() public void ExitThread()
{ {
KThread currentThread = KernelStatic.GetCurrentThread(); KThread currentThread = KernelStatic.GetCurrentThread();
currentThread.Exit(); currentThread.Exit();
} }
#pragma warning restore CA1822
[Svc(0xb)] [Svc(0xb)]
public void SleepThread(long timeout) public void SleepThread(long timeout)
@ -2641,7 +2597,6 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
} }
[Svc(0xc)] [Svc(0xc)]
#pragma warning disable CA1822 // Mark member as static
public Result GetThreadPriority(out int priority, int handle) public Result GetThreadPriority(out int priority, int handle)
{ {
KProcess process = KernelStatic.GetCurrentProcess(); KProcess process = KernelStatic.GetCurrentProcess();
@ -2661,10 +2616,8 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
return KernelResult.InvalidHandle; return KernelResult.InvalidHandle;
} }
} }
#pragma warning restore CA1822
[Svc(0xd)] [Svc(0xd)]
#pragma warning disable CA1822 // Mark member as static
public Result SetThreadPriority(int handle, int priority) public Result SetThreadPriority(int handle, int priority)
{ {
// TODO: NPDM check. // TODO: NPDM check.
@ -2682,10 +2635,8 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
return Result.Success; return Result.Success;
} }
#pragma warning restore CA1822
[Svc(0xe)] [Svc(0xe)]
#pragma warning disable CA1822 // Mark member as static
public Result GetThreadCoreMask(out int preferredCore, out ulong affinityMask, int handle) public Result GetThreadCoreMask(out int preferredCore, out ulong affinityMask, int handle)
{ {
KProcess process = KernelStatic.GetCurrentProcess(); KProcess process = KernelStatic.GetCurrentProcess();
@ -2707,10 +2658,8 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
return KernelResult.InvalidHandle; return KernelResult.InvalidHandle;
} }
} }
#pragma warning restore CA1822
[Svc(0xf)] [Svc(0xf)]
#pragma warning disable CA1822 // Mark member as static
public Result SetThreadCoreMask(int handle, int preferredCore, ulong affinityMask) public Result SetThreadCoreMask(int handle, int preferredCore, ulong affinityMask)
{ {
KProcess currentProcess = KernelStatic.GetCurrentProcess(); KProcess currentProcess = KernelStatic.GetCurrentProcess();
@ -2758,18 +2707,14 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
return thread.SetCoreAndAffinityMask(preferredCore, affinityMask); return thread.SetCoreAndAffinityMask(preferredCore, affinityMask);
} }
#pragma warning restore CA1822
[Svc(0x10)] [Svc(0x10)]
#pragma warning disable CA1822 // Mark member as static
public int GetCurrentProcessorNumber() public int GetCurrentProcessorNumber()
{ {
return KernelStatic.GetCurrentThread().CurrentCore; return KernelStatic.GetCurrentThread().CurrentCore;
} }
#pragma warning restore CA1822
[Svc(0x25)] [Svc(0x25)]
#pragma warning disable CA1822 // Mark member as static
public Result GetThreadId(out ulong threadUid, int handle) public Result GetThreadId(out ulong threadUid, int handle)
{ {
KProcess process = KernelStatic.GetCurrentProcess(); KProcess process = KernelStatic.GetCurrentProcess();
@ -2789,10 +2734,8 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
return KernelResult.InvalidHandle; return KernelResult.InvalidHandle;
} }
} }
#pragma warning restore CA1822
[Svc(0x32)] [Svc(0x32)]
#pragma warning disable CA1822 // Mark member as static
public Result SetThreadActivity(int handle, bool pause) public Result SetThreadActivity(int handle, bool pause)
{ {
KProcess process = KernelStatic.GetCurrentProcess(); KProcess process = KernelStatic.GetCurrentProcess();
@ -2816,10 +2759,8 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
return thread.SetActivity(pause); return thread.SetActivity(pause);
} }
#pragma warning restore CA1822
[Svc(0x33)] [Svc(0x33)]
#pragma warning disable CA1822 // Mark member as static
public Result GetThreadContext3([PointerSized] ulong address, int handle) public Result GetThreadContext3([PointerSized] ulong address, int handle)
{ {
KProcess currentProcess = KernelStatic.GetCurrentProcess(); KProcess currentProcess = KernelStatic.GetCurrentProcess();
@ -2853,7 +2794,6 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
return result; return result;
} }
#pragma warning restore CA1822
// Thread synchronization // Thread synchronization
@ -2986,7 +2926,6 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
} }
[Svc(0x1a)] [Svc(0x1a)]
#pragma warning disable CA1822 // Mark member as static
public Result ArbitrateLock(int ownerHandle, [PointerSized] ulong mutexAddress, int requesterHandle) public Result ArbitrateLock(int ownerHandle, [PointerSized] ulong mutexAddress, int requesterHandle)
{ {
if (IsPointingInsideKernel(mutexAddress)) if (IsPointingInsideKernel(mutexAddress))
@ -3003,10 +2942,8 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
return currentProcess.AddressArbiter.ArbitrateLock(ownerHandle, mutexAddress, requesterHandle); return currentProcess.AddressArbiter.ArbitrateLock(ownerHandle, mutexAddress, requesterHandle);
} }
#pragma warning restore CA1822
[Svc(0x1b)] [Svc(0x1b)]
#pragma warning disable CA1822 // Mark member as static
public Result ArbitrateUnlock([PointerSized] ulong mutexAddress) public Result ArbitrateUnlock([PointerSized] ulong mutexAddress)
{ {
if (IsPointingInsideKernel(mutexAddress)) if (IsPointingInsideKernel(mutexAddress))
@ -3023,10 +2960,8 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
return currentProcess.AddressArbiter.ArbitrateUnlock(mutexAddress); return currentProcess.AddressArbiter.ArbitrateUnlock(mutexAddress);
} }
#pragma warning restore CA1822
[Svc(0x1c)] [Svc(0x1c)]
#pragma warning disable CA1822 // Mark member as static
public Result WaitProcessWideKeyAtomic( public Result WaitProcessWideKeyAtomic(
[PointerSized] ulong mutexAddress, [PointerSized] ulong mutexAddress,
[PointerSized] ulong condVarAddress, [PointerSized] ulong condVarAddress,
@ -3056,10 +2991,8 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
handle, handle,
timeout); timeout);
} }
#pragma warning restore CA1822
[Svc(0x1d)] [Svc(0x1d)]
#pragma warning disable CA1822 // Mark member as static
public Result SignalProcessWideKey([PointerSized] ulong address, int count) public Result SignalProcessWideKey([PointerSized] ulong address, int count)
{ {
KProcess currentProcess = KernelStatic.GetCurrentProcess(); KProcess currentProcess = KernelStatic.GetCurrentProcess();
@ -3068,10 +3001,8 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
return Result.Success; return Result.Success;
} }
#pragma warning restore CA1822
[Svc(0x34)] [Svc(0x34)]
#pragma warning disable CA1822 // Mark member as static
public Result WaitForAddress([PointerSized] ulong address, ArbitrationType type, int value, long timeout) public Result WaitForAddress([PointerSized] ulong address, ArbitrationType type, int value, long timeout)
{ {
if (IsPointingInsideKernel(address)) if (IsPointingInsideKernel(address))
@ -3102,10 +3033,8 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
_ => KernelResult.InvalidEnumValue, _ => KernelResult.InvalidEnumValue,
}; };
} }
#pragma warning restore CA1822
[Svc(0x35)] [Svc(0x35)]
#pragma warning disable CA1822 // Mark member as static
public Result SignalToAddress([PointerSized] ulong address, SignalType type, int value, int count) public Result SignalToAddress([PointerSized] ulong address, SignalType type, int value, int count)
{ {
if (IsPointingInsideKernel(address)) if (IsPointingInsideKernel(address))
@ -3131,17 +3060,14 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
_ => KernelResult.InvalidEnumValue, _ => KernelResult.InvalidEnumValue,
}; };
} }
#pragma warning restore CA1822
[Svc(0x36)] [Svc(0x36)]
#pragma warning disable CA1822 // Mark member as static
public Result SynchronizePreemptionState() public Result SynchronizePreemptionState()
{ {
KernelStatic.GetCurrentThread().SynchronizePreemptionState(); KernelStatic.GetCurrentThread().SynchronizePreemptionState();
return Result.Success; return Result.Success;
} }
#pragma warning restore CA1822
// Not actual syscalls, used by HLE services and such. // Not actual syscalls, used by HLE services and such.

View File

@ -9,5 +9,6 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostCtrlGpu.Types
public byte Sm0TpcIndex; public byte Sm0TpcIndex;
public byte Sm1GpcIndex; public byte Sm1GpcIndex;
public byte Sm1TpcIndex; public byte Sm1TpcIndex;
public uint Reserved;
} }
} }

View File

@ -266,8 +266,18 @@ namespace Ryujinx.UI.App.Common
public bool TryGetApplicationsFromFile(string applicationPath, out List<ApplicationData> applications) public bool TryGetApplicationsFromFile(string applicationPath, out List<ApplicationData> applications)
{ {
applications = []; applications = [];
long fileSize;
long fileSize = new FileInfo(applicationPath).Length; try
{
fileSize = new FileInfo(applicationPath).Length;
}
catch (FileNotFoundException)
{
Logger.Warning?.Print(LogClass.Application, $"The file was not found: '{applicationPath}'");
return false;
}
BlitStruct<ApplicationControlProperty> controlHolder = new(1); BlitStruct<ApplicationControlProperty> controlHolder = new(1);
@ -502,7 +512,13 @@ namespace Ryujinx.UI.App.Common
try try
{ {
IEnumerable<string> files = Directory.EnumerateFiles(appDir, "*", SearchOption.AllDirectories).Where(file => EnumerationOptions options = new()
{
RecurseSubdirectories = true,
IgnoreInaccessible = false,
};
IEnumerable<string> files = Directory.EnumerateFiles(appDir, "*", options).Where(file =>
{ {
return return
(Path.GetExtension(file).ToLower() is ".nsp" && ConfigurationState.Instance.UI.ShownFileTypes.NSP.Value) || (Path.GetExtension(file).ToLower() is ".nsp" && ConfigurationState.Instance.UI.ShownFileTypes.NSP.Value) ||
@ -521,14 +537,18 @@ namespace Ryujinx.UI.App.Common
} }
var fileInfo = new FileInfo(app); var fileInfo = new FileInfo(app);
string extension = fileInfo.Extension.ToLower();
if (!fileInfo.Attributes.HasFlag(FileAttributes.Hidden) && extension is ".nsp" or ".pfs0" or ".xci" or ".nca" or ".nro" or ".nso") try
{ {
var fullPath = fileInfo.ResolveLinkTarget(true)?.FullName ?? fileInfo.FullName; var fullPath = fileInfo.ResolveLinkTarget(true)?.FullName ?? fileInfo.FullName;
applicationPaths.Add(fullPath); applicationPaths.Add(fullPath);
numApplicationsFound++; numApplicationsFound++;
} }
catch (IOException exception)
{
Logger.Warning?.Print(LogClass.Application, $"Failed to resolve the full path to file: \"{app}\" Error: {exception}");
}
} }
} }
catch (UnauthorizedAccessException) catch (UnauthorizedAccessException)

View File

@ -1,21 +1,20 @@
using LibHac.Ns;
using Ryujinx.Ava.Common.Locale; using Ryujinx.Ava.Common.Locale;
namespace Ryujinx.Ava.UI.Models namespace Ryujinx.Ava.UI.Models
{ {
public class TitleUpdateModel public class TitleUpdateModel
{ {
public ApplicationControlProperty Control { get; } public uint Version { get; }
public string Path { get; } public string Path { get; }
public string Label { get; }
public string Label => LocaleManager.Instance.UpdateAndGetDynamicValue( public TitleUpdateModel(uint version, string displayVersion, string path)
System.IO.Path.GetExtension(Path)?.ToLower() == ".xci" ? LocaleKeys.TitleBundledUpdateVersionLabel : LocaleKeys.TitleUpdateVersionLabel,
Control.DisplayVersionString.ToString()
);
public TitleUpdateModel(ApplicationControlProperty control, string path)
{ {
Control = control; Version = version;
Label = LocaleManager.Instance.UpdateAndGetDynamicValue(
System.IO.Path.GetExtension(path)?.ToLower() == ".xci" ? LocaleKeys.TitleBundledUpdateVersionLabel : LocaleKeys.TitleUpdateVersionLabel,
displayVersion
);
Path = path; Path = path;
} }
} }

View File

@ -131,26 +131,11 @@ namespace Ryujinx.Ava.UI.ViewModels
public void SortUpdates() public void SortUpdates()
{ {
var list = TitleUpdates.ToList(); var sortedUpdates = TitleUpdates.OrderByDescending(update => update.Version);
list.Sort((first, second) =>
{
if (string.IsNullOrEmpty(first.Control.DisplayVersionString.ToString()))
{
return -1;
}
if (string.IsNullOrEmpty(second.Control.DisplayVersionString.ToString()))
{
return 1;
}
return Version.Parse(first.Control.DisplayVersionString.ToString()).CompareTo(Version.Parse(second.Control.DisplayVersionString.ToString())) * -1;
});
Views.Clear(); Views.Clear();
Views.Add(new BaseModel()); Views.Add(new BaseModel());
Views.AddRange(list); Views.AddRange(sortedUpdates);
if (SelectedUpdate == null) if (SelectedUpdate == null)
{ {
@ -204,7 +189,9 @@ namespace Ryujinx.Ava.UI.ViewModels
controlNca.OpenFileSystem(NcaSectionType.Data, IntegrityCheckLevel.None).OpenFile(ref nacpFile.Ref, "/control.nacp".ToU8Span(), OpenMode.Read).ThrowIfFailure(); controlNca.OpenFileSystem(NcaSectionType.Data, IntegrityCheckLevel.None).OpenFile(ref nacpFile.Ref, "/control.nacp".ToU8Span(), OpenMode.Read).ThrowIfFailure();
nacpFile.Get.Read(out _, 0, SpanHelpers.AsByteSpan(ref controlData), ReadOption.None).ThrowIfFailure(); nacpFile.Get.Read(out _, 0, SpanHelpers.AsByteSpan(ref controlData), ReadOption.None).ThrowIfFailure();
var update = new TitleUpdateModel(controlData, path); var displayVersion = controlData.DisplayVersionString.ToString();
var update = new TitleUpdateModel(content.Version.Version, displayVersion, path);
TitleUpdates.Add(update); TitleUpdates.Add(update);
if (selected) if (selected)