Compare commits

...

3 Commits

Author SHA1 Message Date
TSRBerry
7870423671 Update syscall capabilites to include SVCs from FW 15.0.0 (#4530)
* Add CapabilityType enum

* Add SupervisorCallCount

* kernel: Add CapabilityExtensions & Change type of capabilities to uint

* Remove private setter from Mask arrays

* Pass ReadOnlySpan directly & Remove redundant type casts
2023-03-17 12:55:19 +01:00
dependabot[bot]
b72916fbc1 nuget: bump UnicornEngine.Unicorn (#4543)
Bumps [UnicornEngine.Unicorn](https://github.com/unicorn-engine/unicorn) from 2.0.2-rc1-f7c841d to 2.0.2-rc1-fb78016.
- [Release notes](https://github.com/unicorn-engine/unicorn/releases)
- [Changelog](https://github.com/unicorn-engine/unicorn/blob/master/ChangeLog)
- [Commits](https://github.com/unicorn-engine/unicorn/commits)

---
updated-dependencies:
- dependency-name: UnicornEngine.Unicorn
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-03-17 12:50:52 +01:00
riperiperi
da073fce61 GPU: Fast path for adding one texture view to a group (#4528)
* GPU: Fast path for adding one texture view to a group

Texture group handles must store a list of their overlapping views, so they can be properly notified when a write is detected, and a few other things relating to texture readback. This is generally created when the group is established, with each handle looping over all views to find its overlaps. This whole process was also done when only a single view was added (and no handles were changed), however...

Sonic Frontiers had a huge cubemap array with 7350 faces (175 cubemaps * 6 faces * 7 levels), so iterating over both handles and existing views added up very fast. Since we are only adding a single view, we only need to _add_ that view to the existing overlaps, rather than recalculate them all.

This greatly improves performance during loading screens and a few seconds into gameplay on the "open zone" sections of Sonic Frontiers. May improve loading times or stutters on some other games.

Note that the current texture cache rules will cause these views to fall out of the cache, as there are more than the hard cap, so the cost will be repaid when reloading the open zone.

I also added some code to properly remove overlaps when texture views are removed, since it seems that was missing.

This can be improved further by only iterating handles that overlap the view (filter by range), but so can a few places in TextureGroup, so better to do all at once. The full generation of overlaps could probably be improved in a similar way.

I recommend testing a few games to make sure nothing breaks.

* Address feedback
2023-03-14 17:33:44 -03:00
17 changed files with 201 additions and 82 deletions

View File

@@ -46,7 +46,7 @@
<PackageVersion Include="System.IdentityModel.Tokens.Jwt" Version="6.27.0" /> <PackageVersion Include="System.IdentityModel.Tokens.Jwt" Version="6.27.0" />
<PackageVersion Include="System.IO.Hashing" Version="7.0.0" /> <PackageVersion Include="System.IO.Hashing" Version="7.0.0" />
<PackageVersion Include="System.Management" Version="7.0.0" /> <PackageVersion Include="System.Management" Version="7.0.0" />
<PackageVersion Include="UnicornEngine.Unicorn" Version="2.0.2-rc1-f7c841d" /> <PackageVersion Include="UnicornEngine.Unicorn" Version="2.0.2-rc1-fb78016" />
<PackageVersion Include="XamlNameReferenceGenerator" Version="1.5.1" /> <PackageVersion Include="XamlNameReferenceGenerator" Version="1.5.1" />
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@@ -360,7 +360,7 @@ namespace Ryujinx.Graphics.Gpu.Image
texture._viewStorage = this; texture._viewStorage = this;
Group.UpdateViews(_views); Group.UpdateViews(_views, texture);
if (texture.Group != null && texture.Group != Group) if (texture.Group != null && texture.Group != Group)
{ {
@@ -384,6 +384,8 @@ namespace Ryujinx.Graphics.Gpu.Image
{ {
_views.Remove(texture); _views.Remove(texture);
Group.RemoveView(texture);
texture._viewStorage = texture; texture._viewStorage = texture;
DecrementReferenceCount(); DecrementReferenceCount();

View File

@@ -989,7 +989,8 @@ namespace Ryujinx.Graphics.Gpu.Image
/// Update the views in this texture group, rebuilding the memory tracking if required. /// Update the views in this texture group, rebuilding the memory tracking if required.
/// </summary> /// </summary>
/// <param name="views">The views list of the storage texture</param> /// <param name="views">The views list of the storage texture</param>
public void UpdateViews(List<Texture> views) /// <param name="texture">The texture that has been added, if that is the only change, otherwise null</param>
public void UpdateViews(List<Texture> views, Texture texture)
{ {
// This is saved to calculate overlapping views for each handle. // This is saved to calculate overlapping views for each handle.
_views = views; _views = views;
@@ -1027,17 +1028,44 @@ namespace Ryujinx.Graphics.Gpu.Image
if (!regionsRebuilt) if (!regionsRebuilt)
{ {
// Must update the overlapping views on all handles, but only if they were not just recreated. if (texture != null)
foreach (TextureGroupHandle handle in _handles)
{ {
handle.RecalculateOverlaps(this, views); int offset = FindOffset(texture);
foreach (TextureGroupHandle handle in _handles)
{
handle.AddOverlap(offset, texture);
}
}
else
{
// Must update the overlapping views on all handles, but only if they were not just recreated.
foreach (TextureGroupHandle handle in _handles)
{
handle.RecalculateOverlaps(this, views);
}
} }
} }
SignalAllDirty(); SignalAllDirty();
} }
/// <summary>
/// Removes a view from the group, removing it from all overlap lists.
/// </summary>
/// <param name="view">View to remove from the group</param>
public void RemoveView(Texture view)
{
int offset = FindOffset(view);
foreach (TextureGroupHandle handle in _handles)
{
handle.RemoveOverlap(offset, view);
}
}
/// <summary> /// <summary>
/// Inherit handle state from an old set of handles, such as modified and dirty flags. /// Inherit handle state from an old set of handles, such as modified and dirty flags.
/// </summary> /// </summary>

View File

@@ -159,6 +159,42 @@ namespace Ryujinx.Graphics.Gpu.Image
} }
} }
/// <summary>
/// Adds a single texture view as an overlap if its range overlaps.
/// </summary>
/// <param name="offset">The offset of the view in the group</param>
/// <param name="view">The texture to add as an overlap</param>
public void AddOverlap(int offset, Texture view)
{
// Overlaps can be accessed from the memory tracking signal handler, so access must be atomic.
if (OverlapsWith(offset, (int)view.Size))
{
lock (Overlaps)
{
Overlaps.Add(view);
}
}
}
/// <summary>
/// Removes a single texture view as an overlap if its range overlaps.
/// </summary>
/// <param name="offset">The offset of the view in the group</param>
/// <param name="view">The texture to add as an overlap</param>
public void RemoveOverlap(int offset, Texture view)
{
// Overlaps can be accessed from the memory tracking signal handler, so access must be atomic.
if (OverlapsWith(offset, (int)view.Size))
{
lock (Overlaps)
{
Overlaps.Remove(view);
}
}
}
/// <summary> /// <summary>
/// Registers a sync action to happen for this handle, and an interim flush action on the tracking handle. /// Registers a sync action to happen for this handle, and an interim flush action on the tracking handle.
/// </summary> /// </summary>

View File

@@ -338,7 +338,7 @@ namespace Ryujinx.HLE.HOS
ProcessCreationInfo creationInfo = new ProcessCreationInfo("Service", 1, 0, 0x8000000, 1, flags, 0, 0); ProcessCreationInfo creationInfo = new ProcessCreationInfo("Service", 1, 0, 0x8000000, 1, flags, 0, 0);
int[] defaultCapabilities = new int[] uint[] defaultCapabilities = new uint[]
{ {
0x030363F7, 0x030363F7,
0x1FFFFFCF, 0x1FFFFFCF,
@@ -552,4 +552,4 @@ namespace Ryujinx.HLE.HOS
IsPaused = pause; IsPaused = pause;
} }
} }
} }

View File

@@ -7,6 +7,8 @@ namespace Ryujinx.HLE.HOS.Kernel
public const int InitialKipId = 1; public const int InitialKipId = 1;
public const int InitialProcessId = 0x51; public const int InitialProcessId = 0x51;
public const int SupervisorCallCount = 0xC0;
public const int MemoryBlockAllocatorSize = 0x2710; public const int MemoryBlockAllocatorSize = 0x2710;
public const ulong UserSlabHeapBase = DramMemoryMap.SlabHeapBase; public const ulong UserSlabHeapBase = DramMemoryMap.SlabHeapBase;
@@ -15,4 +17,4 @@ namespace Ryujinx.HLE.HOS.Kernel
public const ulong CounterFrequency = 19200000; public const ulong CounterFrequency = 19200000;
} }
} }

View File

@@ -18,7 +18,7 @@ namespace Ryujinx.HLE.HOS.Kernel
public static Result StartInitialProcess( public static Result StartInitialProcess(
KernelContext context, KernelContext context,
ProcessCreationInfo creationInfo, ProcessCreationInfo creationInfo,
ReadOnlySpan<int> capabilities, ReadOnlySpan<uint> capabilities,
int mainThreadPriority, int mainThreadPriority,
ThreadStart customThreadStart) ThreadStart customThreadStart)
{ {

View File

@@ -0,0 +1,22 @@
using System.Numerics;
namespace Ryujinx.HLE.HOS.Kernel.Process
{
static class CapabilityExtensions
{
public static CapabilityType GetCapabilityType(this uint cap)
{
return (CapabilityType)(((cap + 1) & ~cap) - 1);
}
public static uint GetFlag(this CapabilityType type)
{
return (uint)type + 1;
}
public static uint GetId(this CapabilityType type)
{
return (uint)BitOperations.TrailingZeroCount(type.GetFlag());
}
}
}

View File

@@ -0,0 +1,19 @@
namespace Ryujinx.HLE.HOS.Kernel.Process
{
enum CapabilityType : uint
{
CorePriority = (1u << 3) - 1,
SyscallMask = (1u << 4) - 1,
MapRange = (1u << 6) - 1,
MapIoPage = (1u << 7) - 1,
MapRegion = (1u << 10) - 1,
InterruptPair = (1u << 11) - 1,
ProgramType = (1u << 13) - 1,
KernelVersion = (1u << 14) - 1,
HandleTable = (1u << 15) - 1,
DebugFlags = (1u << 16) - 1,
Invalid = 0u,
Padding = ~0u
}
}

View File

@@ -19,7 +19,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
private int _activeSlotsCount; private int _activeSlotsCount;
private int _size; private uint _size;
private ushort _idCounter; private ushort _idCounter;
@@ -28,9 +28,9 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
_context = context; _context = context;
} }
public Result Initialize(int size) public Result Initialize(uint size)
{ {
if ((uint)size > 1024) if (size > 1024)
{ {
return KernelResult.OutOfMemory; return KernelResult.OutOfMemory;
} }

View File

@@ -16,11 +16,11 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
{ {
class KProcess : KSynchronizationObject class KProcess : KSynchronizationObject
{ {
public const int KernelVersionMajor = 10; public const uint KernelVersionMajor = 10;
public const int KernelVersionMinor = 4; public const uint KernelVersionMinor = 4;
public const int KernelVersionRevision = 0; public const uint KernelVersionRevision = 0;
public const int KernelVersionPacked = public const uint KernelVersionPacked =
(KernelVersionMajor << 19) | (KernelVersionMajor << 19) |
(KernelVersionMinor << 15) | (KernelVersionMinor << 15) |
(KernelVersionRevision << 0); (KernelVersionRevision << 0);
@@ -119,7 +119,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
public Result InitializeKip( public Result InitializeKip(
ProcessCreationInfo creationInfo, ProcessCreationInfo creationInfo,
ReadOnlySpan<int> capabilities, ReadOnlySpan<uint> capabilities,
KPageList pageList, KPageList pageList,
KResourceLimit resourceLimit, KResourceLimit resourceLimit,
MemoryRegion memRegion, MemoryRegion memRegion,
@@ -190,7 +190,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
public Result Initialize( public Result Initialize(
ProcessCreationInfo creationInfo, ProcessCreationInfo creationInfo,
ReadOnlySpan<int> capabilities, ReadOnlySpan<uint> capabilities,
KResourceLimit resourceLimit, KResourceLimit resourceLimit,
MemoryRegion memRegion, MemoryRegion memRegion,
IProcessContextFactory contextFactory, IProcessContextFactory contextFactory,

View File

@@ -1,4 +1,3 @@
using Ryujinx.HLE.HOS.Kernel.Common;
using Ryujinx.HLE.HOS.Kernel.Memory; using Ryujinx.HLE.HOS.Kernel.Memory;
using Ryujinx.HLE.HOS.Kernel.Threading; using Ryujinx.HLE.HOS.Kernel.Threading;
using Ryujinx.Horizon.Common; using Ryujinx.Horizon.Common;
@@ -9,48 +8,49 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
{ {
class KProcessCapabilities class KProcessCapabilities
{ {
public byte[] SvcAccessMask { get; private set; } public byte[] SvcAccessMask { get; }
public byte[] IrqAccessMask { get; private set; } public byte[] IrqAccessMask { get; }
public ulong AllowedCpuCoresMask { get; private set; } public ulong AllowedCpuCoresMask { get; private set; }
public ulong AllowedThreadPriosMask { get; private set; } public ulong AllowedThreadPriosMask { get; private set; }
public int DebuggingFlags { get; private set; } public uint DebuggingFlags { get; private set; }
public int HandleTableSize { get; private set; } public uint HandleTableSize { get; private set; }
public int KernelReleaseVersion { get; private set; } public uint KernelReleaseVersion { get; private set; }
public int ApplicationType { get; private set; } public uint ApplicationType { get; private set; }
public KProcessCapabilities() public KProcessCapabilities()
{ {
SvcAccessMask = new byte[0x10]; // length / number of bits of the underlying type
SvcAccessMask = new byte[KernelConstants.SupervisorCallCount / 8];
IrqAccessMask = new byte[0x80]; IrqAccessMask = new byte[0x80];
} }
public Result InitializeForKernel(ReadOnlySpan<int> capabilities, KPageTableBase memoryManager) public Result InitializeForKernel(ReadOnlySpan<uint> capabilities, KPageTableBase memoryManager)
{ {
AllowedCpuCoresMask = 0xf; AllowedCpuCoresMask = 0xf;
AllowedThreadPriosMask = ulong.MaxValue; AllowedThreadPriosMask = ulong.MaxValue;
DebuggingFlags &= ~3; DebuggingFlags &= ~3u;
KernelReleaseVersion = KProcess.KernelVersionPacked; KernelReleaseVersion = KProcess.KernelVersionPacked;
return Parse(capabilities, memoryManager); return Parse(capabilities, memoryManager);
} }
public Result InitializeForUser(ReadOnlySpan<int> capabilities, KPageTableBase memoryManager) public Result InitializeForUser(ReadOnlySpan<uint> capabilities, KPageTableBase memoryManager)
{ {
return Parse(capabilities, memoryManager); return Parse(capabilities, memoryManager);
} }
private Result Parse(ReadOnlySpan<int> capabilities, KPageTableBase memoryManager) private Result Parse(ReadOnlySpan<uint> capabilities, KPageTableBase memoryManager)
{ {
int mask0 = 0; int mask0 = 0;
int mask1 = 0; int mask1 = 0;
for (int index = 0; index < capabilities.Length; index++) for (int index = 0; index < capabilities.Length; index++)
{ {
int cap = capabilities[index]; uint cap = capabilities[index];
if (((cap + 1) & ~cap) != 0x40) if (cap.GetCapabilityType() != CapabilityType.MapRange)
{ {
Result result = ParseCapability(cap, ref mask0, ref mask1, memoryManager); Result result = ParseCapability(cap, ref mask0, ref mask1, memoryManager);
@@ -66,7 +66,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
return KernelResult.InvalidCombination; return KernelResult.InvalidCombination;
} }
int prevCap = cap; uint prevCap = cap;
cap = capabilities[++index]; cap = capabilities[++index];
@@ -85,8 +85,8 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
return KernelResult.InvalidSize; return KernelResult.InvalidSize;
} }
long address = ((long)(uint)prevCap << 5) & 0xffffff000; long address = ((long)prevCap << 5) & 0xffffff000;
long size = ((long)(uint)cap << 5) & 0xfffff000; long size = ((long)cap << 5) & 0xfffff000;
if (((ulong)(address + size - 1) >> 36) != 0) if (((ulong)(address + size - 1) >> 36) != 0)
{ {
@@ -118,20 +118,20 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
return Result.Success; return Result.Success;
} }
private Result ParseCapability(int cap, ref int mask0, ref int mask1, KPageTableBase memoryManager) private Result ParseCapability(uint cap, ref int mask0, ref int mask1, KPageTableBase memoryManager)
{ {
int code = (cap + 1) & ~cap; CapabilityType code = cap.GetCapabilityType();
if (code == 1) if (code == CapabilityType.Invalid)
{ {
return KernelResult.InvalidCapability; return KernelResult.InvalidCapability;
} }
else if (code == 0) else if (code == CapabilityType.Padding)
{ {
return Result.Success; return Result.Success;
} }
int codeMask = 1 << (32 - BitOperations.LeadingZeroCount((uint)code + 1)); int codeMask = 1 << (32 - BitOperations.LeadingZeroCount(code.GetFlag() + 1));
// Check if the property was already set. // Check if the property was already set.
if (((mask0 & codeMask) & 0x1e008) != 0) if (((mask0 & codeMask) & 0x1e008) != 0)
@@ -143,23 +143,23 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
switch (code) switch (code)
{ {
case 8: case CapabilityType.CorePriority:
{ {
if (AllowedCpuCoresMask != 0 || AllowedThreadPriosMask != 0) if (AllowedCpuCoresMask != 0 || AllowedThreadPriosMask != 0)
{ {
return KernelResult.InvalidCapability; return KernelResult.InvalidCapability;
} }
int lowestCpuCore = (cap >> 16) & 0xff; uint lowestCpuCore = (cap >> 16) & 0xff;
int highestCpuCore = (cap >> 24) & 0xff; uint highestCpuCore = (cap >> 24) & 0xff;
if (lowestCpuCore > highestCpuCore) if (lowestCpuCore > highestCpuCore)
{ {
return KernelResult.InvalidCombination; return KernelResult.InvalidCombination;
} }
int highestThreadPrio = (cap >> 4) & 0x3f; uint highestThreadPrio = (cap >> 4) & 0x3f;
int lowestThreadPrio = (cap >> 10) & 0x3f; uint lowestThreadPrio = (cap >> 10) & 0x3f;
if (lowestThreadPrio > highestThreadPrio) if (lowestThreadPrio > highestThreadPrio)
{ {
@@ -177,9 +177,9 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
break; break;
} }
case 0x10: case CapabilityType.SyscallMask:
{ {
int slot = (cap >> 29) & 7; int slot = ((int)cap >> 29) & 7;
int svcSlotMask = 1 << slot; int svcSlotMask = 1 << slot;
@@ -190,7 +190,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
mask1 |= svcSlotMask; mask1 |= svcSlotMask;
int svcMask = (cap >> 5) & 0xffffff; uint svcMask = (cap >> 5) & 0xffffff;
int baseSvc = slot * 24; int baseSvc = slot * 24;
@@ -203,7 +203,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
int svcId = baseSvc + index; int svcId = baseSvc + index;
if (svcId > 0x7f) if (svcId >= KernelConstants.SupervisorCallCount)
{ {
return KernelResult.MaximumExceeded; return KernelResult.MaximumExceeded;
} }
@@ -214,20 +214,27 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
break; break;
} }
case 0x80: case CapabilityType.MapIoPage:
{ {
long address = ((long)(uint)cap << 4) & 0xffffff000; long address = ((long)cap << 4) & 0xffffff000;
memoryManager.MapIoMemory(address, KPageTableBase.PageSize, KMemoryPermission.ReadAndWrite); memoryManager.MapIoMemory(address, KPageTableBase.PageSize, KMemoryPermission.ReadAndWrite);
break; break;
} }
case 0x800: case CapabilityType.MapRegion:
{
// TODO: Implement capabilities for MapRegion
break;
}
case CapabilityType.InterruptPair:
{ {
// TODO: GIC distributor check. // TODO: GIC distributor check.
int irq0 = (cap >> 12) & 0x3ff; int irq0 = ((int)cap >> 12) & 0x3ff;
int irq1 = (cap >> 22) & 0x3ff; int irq1 = ((int)cap >> 22) & 0x3ff;
if (irq0 != 0x3ff) if (irq0 != 0x3ff)
{ {
@@ -242,11 +249,11 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
break; break;
} }
case 0x2000: case CapabilityType.ProgramType:
{ {
int applicationType = cap >> 14; uint applicationType = (cap >> 14);
if ((uint)applicationType > 7) if (applicationType > 7)
{ {
return KernelResult.ReservedValue; return KernelResult.ReservedValue;
} }
@@ -256,7 +263,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
break; break;
} }
case 0x4000: case CapabilityType.KernelVersion:
{ {
// Note: This check is bugged on kernel too, we are just replicating the bug here. // Note: This check is bugged on kernel too, we are just replicating the bug here.
if ((KernelReleaseVersion >> 17) != 0 || cap < 0x80000) if ((KernelReleaseVersion >> 17) != 0 || cap < 0x80000)
@@ -269,11 +276,11 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
break; break;
} }
case 0x8000: case CapabilityType.HandleTable:
{ {
int handleTableSize = cap >> 26; uint handleTableSize = cap >> 26;
if ((uint)handleTableSize > 0x3ff) if (handleTableSize > 0x3ff)
{ {
return KernelResult.ReservedValue; return KernelResult.ReservedValue;
} }
@@ -283,16 +290,16 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
break; break;
} }
case 0x10000: case CapabilityType.DebugFlags:
{ {
int debuggingFlags = cap >> 19; uint debuggingFlags = cap >> 19;
if ((uint)debuggingFlags > 3) if (debuggingFlags > 3)
{ {
return KernelResult.ReservedValue; return KernelResult.ReservedValue;
} }
DebuggingFlags &= ~3; DebuggingFlags &= ~3u;
DebuggingFlags |= debuggingFlags; DebuggingFlags |= debuggingFlags;
break; break;
@@ -304,18 +311,18 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
return Result.Success; return Result.Success;
} }
private static ulong GetMaskFromMinMax(int min, int max) private static ulong GetMaskFromMinMax(uint min, uint max)
{ {
int range = max - min + 1; uint range = max - min + 1;
if (range == 64) if (range == 64)
{ {
return ulong.MaxValue; return ulong.MaxValue;
} }
ulong mask = (1UL << range) - 1; ulong mask = (1UL << (int)range) - 1;
return mask << min; return mask << (int)min;
} }
} }
} }

View File

@@ -1,5 +1,8 @@
namespace Ryujinx.HLE.HOS.Kernel.Process using System;
namespace Ryujinx.HLE.HOS.Kernel.Process
{ {
[Flags]
enum ProcessCreationFlags enum ProcessCreationFlags
{ {
Is64Bit = 1 << 0, Is64Bit = 1 << 0,

View File

@@ -54,7 +54,7 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
public Result CreateProcess( public Result CreateProcess(
out int handle, out int handle,
ProcessCreationInfo info, ProcessCreationInfo info,
ReadOnlySpan<int> capabilities, ReadOnlySpan<uint> capabilities,
IProcessContextFactory contextFactory, IProcessContextFactory contextFactory,
ThreadStart customThreadStart = null) ThreadStart customThreadStart = null)
{ {
@@ -3002,4 +3002,4 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
return (address & 3) != 0; return (address & 3) != 0;
} }
} }
} }

View File

@@ -80,7 +80,7 @@ namespace Ryujinx.HLE.HOS
ulong codeBaseAddress = kip.Is64BitAddressSpace ? 0x8000000UL : 0x200000UL; ulong codeBaseAddress = kip.Is64BitAddressSpace ? 0x8000000UL : 0x200000UL;
ulong codeAddress = codeBaseAddress + (ulong)kip.TextOffset; ulong codeAddress = codeBaseAddress + kip.TextOffset;
ProcessCreationFlags flags = 0; ProcessCreationFlags flags = 0;
@@ -231,13 +231,13 @@ namespace Ryujinx.HLE.HOS
nsoSize = BitUtils.AlignUp<uint>(nsoSize, KPageTableBase.PageSize); nsoSize = BitUtils.AlignUp<uint>(nsoSize, KPageTableBase.PageSize);
nsoBase[index] = codeStart + (ulong)codeSize; nsoBase[index] = codeStart + codeSize;
codeSize += nsoSize; codeSize += nsoSize;
if (arguments != null && argsSize == 0) if (arguments != null && argsSize == 0)
{ {
argsStart = (ulong)codeSize; argsStart = codeSize;
argsSize = (uint)BitUtils.AlignDown(arguments.Length * 2 + ArgsTotalSize - 1, KPageTableBase.PageSize); argsSize = (uint)BitUtils.AlignDown(arguments.Length * 2 + ArgsTotalSize - 1, KPageTableBase.PageSize);
@@ -318,7 +318,7 @@ namespace Ryujinx.HLE.HOS
result = process.Initialize( result = process.Initialize(
creationInfo, creationInfo,
MemoryMarshal.Cast<byte, int>(npdm.KernelCapabilityData).ToArray(), MemoryMarshal.Cast<byte, uint>(npdm.KernelCapabilityData),
resourceLimit, resourceLimit,
memoryRegion, memoryRegion,
processContextFactory); processContextFactory);

View File

@@ -19,7 +19,7 @@ namespace Ryujinx.HLE.HOS.Services
// not large enough. // not large enough.
private const int PointerBufferSize = 0x8000; private const int PointerBufferSize = 0x8000;
private readonly static int[] DefaultCapabilities = new int[] private readonly static uint[] DefaultCapabilities = new uint[]
{ {
0x030363F7, 0x030363F7,
0x1FFFFFCF, 0x1FFFFFCF,

View File

@@ -22,7 +22,7 @@ namespace Ryujinx.HLE.Loaders.Executables
public uint DataSize { get; } public uint DataSize { get; }
public uint BssSize { get; } public uint BssSize { get; }
public int[] Capabilities { get; } public uint[] Capabilities { get; }
public bool UsesSecureMemory { get; } public bool UsesSecureMemory { get; }
public bool Is64BitAddressSpace { get; } public bool Is64BitAddressSpace { get; }
public bool Is64Bit { get; } public bool Is64Bit { get; }
@@ -57,11 +57,11 @@ namespace Ryujinx.HLE.Loaders.Executables
Version = reader.Version; Version = reader.Version;
Name = reader.Name.ToString(); Name = reader.Name.ToString();
Capabilities = new int[32]; Capabilities = new uint[32];
for (int index = 0; index < Capabilities.Length; index++) for (int index = 0; index < Capabilities.Length; index++)
{ {
Capabilities[index] = (int)reader.Capabilities[index]; Capabilities[index] = reader.Capabilities[index];
} }
reader.GetSegmentSize(KipReader.SegmentType.Data, out int uncompressedSize).ThrowIfFailure(); reader.GetSegmentSize(KipReader.SegmentType.Data, out int uncompressedSize).ThrowIfFailure();