From 7870423671cba17c8aad9bb93a67c84bda441366 Mon Sep 17 00:00:00 2001
From: TSRBerry <20988865+TSRBerry@users.noreply.github.com>
Date: Fri, 17 Mar 2023 12:55:19 +0100
Subject: [PATCH] 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
---
 Ryujinx.HLE/HOS/Horizon.cs                    |   4 +-
 Ryujinx.HLE/HOS/Kernel/KernelConstants.cs     |   4 +-
 Ryujinx.HLE/HOS/Kernel/KernelStatic.cs        |   2 +-
 .../Kernel/Process/CapabilityExtensions.cs    |  22 ++++
 .../HOS/Kernel/Process/CapabilityType.cs      |  19 +++
 .../HOS/Kernel/Process/KHandleTable.cs        |   6 +-
 Ryujinx.HLE/HOS/Kernel/Process/KProcess.cs    |  12 +-
 .../Kernel/Process/KProcessCapabilities.cs    | 109 ++++++++++--------
 .../Kernel/Process/ProcessCreationFlags.cs    |   5 +-
 .../HOS/Kernel/SupervisorCall/Syscall.cs      |   4 +-
 Ryujinx.HLE/HOS/ProgramLoader.cs              |   8 +-
 Ryujinx.HLE/HOS/Services/ServerBase.cs        |   2 +-
 .../Loaders/Executables/KipExecutable.cs      |   6 +-
 13 files changed, 128 insertions(+), 75 deletions(-)
 create mode 100644 Ryujinx.HLE/HOS/Kernel/Process/CapabilityExtensions.cs
 create mode 100644 Ryujinx.HLE/HOS/Kernel/Process/CapabilityType.cs

diff --git a/Ryujinx.HLE/HOS/Horizon.cs b/Ryujinx.HLE/HOS/Horizon.cs
index 9908cbba84..2b77a7c2e6 100644
--- a/Ryujinx.HLE/HOS/Horizon.cs
+++ b/Ryujinx.HLE/HOS/Horizon.cs
@@ -338,7 +338,7 @@ namespace Ryujinx.HLE.HOS
 
                 ProcessCreationInfo creationInfo = new ProcessCreationInfo("Service", 1, 0, 0x8000000, 1, flags, 0, 0);
 
-                int[] defaultCapabilities = new int[]
+                uint[] defaultCapabilities = new uint[]
                 {
                     0x030363F7,
                     0x1FFFFFCF,
@@ -552,4 +552,4 @@ namespace Ryujinx.HLE.HOS
             IsPaused = pause;
         }
     }
-}
+}
\ No newline at end of file
diff --git a/Ryujinx.HLE/HOS/Kernel/KernelConstants.cs b/Ryujinx.HLE/HOS/Kernel/KernelConstants.cs
index 3817b0aa37..28db750c76 100644
--- a/Ryujinx.HLE/HOS/Kernel/KernelConstants.cs
+++ b/Ryujinx.HLE/HOS/Kernel/KernelConstants.cs
@@ -7,6 +7,8 @@ namespace Ryujinx.HLE.HOS.Kernel
         public const int InitialKipId = 1;
         public const int InitialProcessId = 0x51;
 
+        public const int SupervisorCallCount = 0xC0;
+
         public const int MemoryBlockAllocatorSize = 0x2710;
 
         public const ulong UserSlabHeapBase = DramMemoryMap.SlabHeapBase;
@@ -15,4 +17,4 @@ namespace Ryujinx.HLE.HOS.Kernel
 
         public const ulong CounterFrequency = 19200000;
     }
-}
+}
\ No newline at end of file
diff --git a/Ryujinx.HLE/HOS/Kernel/KernelStatic.cs b/Ryujinx.HLE/HOS/Kernel/KernelStatic.cs
index 21d7d90c4e..c66f4b578f 100644
--- a/Ryujinx.HLE/HOS/Kernel/KernelStatic.cs
+++ b/Ryujinx.HLE/HOS/Kernel/KernelStatic.cs
@@ -18,7 +18,7 @@ namespace Ryujinx.HLE.HOS.Kernel
         public static Result StartInitialProcess(
             KernelContext context,
             ProcessCreationInfo creationInfo,
-            ReadOnlySpan<int> capabilities,
+            ReadOnlySpan<uint> capabilities,
             int mainThreadPriority,
             ThreadStart customThreadStart)
         {
diff --git a/Ryujinx.HLE/HOS/Kernel/Process/CapabilityExtensions.cs b/Ryujinx.HLE/HOS/Kernel/Process/CapabilityExtensions.cs
new file mode 100644
index 0000000000..66d56fe31b
--- /dev/null
+++ b/Ryujinx.HLE/HOS/Kernel/Process/CapabilityExtensions.cs
@@ -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());
+        }
+    }
+}
\ No newline at end of file
diff --git a/Ryujinx.HLE/HOS/Kernel/Process/CapabilityType.cs b/Ryujinx.HLE/HOS/Kernel/Process/CapabilityType.cs
new file mode 100644
index 0000000000..51d92316d1
--- /dev/null
+++ b/Ryujinx.HLE/HOS/Kernel/Process/CapabilityType.cs
@@ -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
+    }
+}
\ No newline at end of file
diff --git a/Ryujinx.HLE/HOS/Kernel/Process/KHandleTable.cs b/Ryujinx.HLE/HOS/Kernel/Process/KHandleTable.cs
index c15ebef5cb..50f04e90ca 100644
--- a/Ryujinx.HLE/HOS/Kernel/Process/KHandleTable.cs
+++ b/Ryujinx.HLE/HOS/Kernel/Process/KHandleTable.cs
@@ -19,7 +19,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
 
         private int _activeSlotsCount;
 
-        private int _size;
+        private uint _size;
 
         private ushort _idCounter;
 
@@ -28,9 +28,9 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
             _context = context;
         }
 
-        public Result Initialize(int size)
+        public Result Initialize(uint size)
         {
-            if ((uint)size > 1024)
+            if (size > 1024)
             {
                 return KernelResult.OutOfMemory;
             }
diff --git a/Ryujinx.HLE/HOS/Kernel/Process/KProcess.cs b/Ryujinx.HLE/HOS/Kernel/Process/KProcess.cs
index 8d9cd242f7..21e89944ec 100644
--- a/Ryujinx.HLE/HOS/Kernel/Process/KProcess.cs
+++ b/Ryujinx.HLE/HOS/Kernel/Process/KProcess.cs
@@ -16,11 +16,11 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
 {
     class KProcess : KSynchronizationObject
     {
-        public const int KernelVersionMajor = 10;
-        public const int KernelVersionMinor = 4;
-        public const int KernelVersionRevision = 0;
+        public const uint KernelVersionMajor = 10;
+        public const uint KernelVersionMinor = 4;
+        public const uint KernelVersionRevision = 0;
 
-        public const int KernelVersionPacked =
+        public const uint KernelVersionPacked =
             (KernelVersionMajor << 19) |
             (KernelVersionMinor << 15) |
             (KernelVersionRevision << 0);
@@ -119,7 +119,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
 
         public Result InitializeKip(
             ProcessCreationInfo creationInfo,
-            ReadOnlySpan<int> capabilities,
+            ReadOnlySpan<uint> capabilities,
             KPageList pageList,
             KResourceLimit resourceLimit,
             MemoryRegion memRegion,
@@ -190,7 +190,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
 
         public Result Initialize(
             ProcessCreationInfo creationInfo,
-            ReadOnlySpan<int> capabilities,
+            ReadOnlySpan<uint> capabilities,
             KResourceLimit resourceLimit,
             MemoryRegion memRegion,
             IProcessContextFactory contextFactory,
diff --git a/Ryujinx.HLE/HOS/Kernel/Process/KProcessCapabilities.cs b/Ryujinx.HLE/HOS/Kernel/Process/KProcessCapabilities.cs
index ef55a165fd..c99e311231 100644
--- a/Ryujinx.HLE/HOS/Kernel/Process/KProcessCapabilities.cs
+++ b/Ryujinx.HLE/HOS/Kernel/Process/KProcessCapabilities.cs
@@ -1,4 +1,3 @@
-using Ryujinx.HLE.HOS.Kernel.Common;
 using Ryujinx.HLE.HOS.Kernel.Memory;
 using Ryujinx.HLE.HOS.Kernel.Threading;
 using Ryujinx.Horizon.Common;
@@ -9,48 +8,49 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
 {
     class KProcessCapabilities
     {
-        public byte[] SvcAccessMask { get; private set; }
-        public byte[] IrqAccessMask { get; private set; }
+        public byte[] SvcAccessMask { get; }
+        public byte[] IrqAccessMask { get; }
 
         public ulong AllowedCpuCoresMask    { get; private set; }
         public ulong AllowedThreadPriosMask { get; private set; }
 
-        public int DebuggingFlags       { get; private set; }
-        public int HandleTableSize      { get; private set; }
-        public int KernelReleaseVersion { get; private set; }
-        public int ApplicationType      { get; private set; }
+        public uint DebuggingFlags       { get; private set; }
+        public uint HandleTableSize      { get; private set; }
+        public uint KernelReleaseVersion { get; private set; }
+        public uint ApplicationType      { get; private set; }
 
         public KProcessCapabilities()
         {
-            SvcAccessMask = new byte[0x10];
+            // length / number of bits of the underlying type
+            SvcAccessMask = new byte[KernelConstants.SupervisorCallCount / 8];
             IrqAccessMask = new byte[0x80];
         }
 
-        public Result InitializeForKernel(ReadOnlySpan<int> capabilities, KPageTableBase memoryManager)
+        public Result InitializeForKernel(ReadOnlySpan<uint> capabilities, KPageTableBase memoryManager)
         {
             AllowedCpuCoresMask    = 0xf;
             AllowedThreadPriosMask = ulong.MaxValue;
-            DebuggingFlags        &= ~3;
+            DebuggingFlags        &= ~3u;
             KernelReleaseVersion   = KProcess.KernelVersionPacked;
 
             return Parse(capabilities, memoryManager);
         }
 
-        public Result InitializeForUser(ReadOnlySpan<int> capabilities, KPageTableBase memoryManager)
+        public Result InitializeForUser(ReadOnlySpan<uint> capabilities, KPageTableBase 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 mask1 = 0;
 
             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);
 
@@ -66,7 +66,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
                         return KernelResult.InvalidCombination;
                     }
 
-                    int prevCap = cap;
+                    uint prevCap = cap;
 
                     cap = capabilities[++index];
 
@@ -85,8 +85,8 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
                         return KernelResult.InvalidSize;
                     }
 
-                    long address = ((long)(uint)prevCap << 5) & 0xffffff000;
-                    long size    = ((long)(uint)cap     << 5) & 0xfffff000;
+                    long address = ((long)prevCap << 5) & 0xffffff000;
+                    long size    = ((long)cap     << 5) & 0xfffff000;
 
                     if (((ulong)(address + size - 1) >> 36) != 0)
                     {
@@ -118,20 +118,20 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
             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;
             }
-            else if (code == 0)
+            else if (code == CapabilityType.Padding)
             {
                 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.
             if (((mask0 & codeMask) & 0x1e008) != 0)
@@ -143,23 +143,23 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
 
             switch (code)
             {
-                case 8:
+                case CapabilityType.CorePriority:
                 {
                     if (AllowedCpuCoresMask != 0 || AllowedThreadPriosMask != 0)
                     {
                         return KernelResult.InvalidCapability;
                     }
 
-                    int lowestCpuCore  = (cap >> 16) & 0xff;
-                    int highestCpuCore = (cap >> 24) & 0xff;
+                    uint lowestCpuCore  = (cap >> 16) & 0xff;
+                    uint highestCpuCore = (cap >> 24) & 0xff;
 
                     if (lowestCpuCore > highestCpuCore)
                     {
                         return KernelResult.InvalidCombination;
                     }
 
-                    int highestThreadPrio = (cap >>  4) & 0x3f;
-                    int lowestThreadPrio  = (cap >> 10) & 0x3f;
+                    uint highestThreadPrio = (cap >>  4) & 0x3f;
+                    uint lowestThreadPrio  = (cap >> 10) & 0x3f;
 
                     if (lowestThreadPrio > highestThreadPrio)
                     {
@@ -177,9 +177,9 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
                     break;
                 }
 
-                case 0x10:
+                case CapabilityType.SyscallMask:
                 {
-                    int slot = (cap >> 29) & 7;
+                    int slot = ((int)cap >> 29) & 7;
 
                     int svcSlotMask = 1 << slot;
 
@@ -190,7 +190,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
 
                     mask1 |= svcSlotMask;
 
-                    int svcMask = (cap >> 5) & 0xffffff;
+                    uint svcMask = (cap >> 5) & 0xffffff;
 
                     int baseSvc = slot * 24;
 
@@ -203,7 +203,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
 
                         int svcId = baseSvc + index;
 
-                        if (svcId > 0x7f)
+                        if (svcId >= KernelConstants.SupervisorCallCount)
                         {
                             return KernelResult.MaximumExceeded;
                         }
@@ -214,20 +214,27 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
                     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);
 
                     break;
                 }
 
-                case 0x800:
+                case CapabilityType.MapRegion:
+                {
+                    // TODO: Implement capabilities for MapRegion
+
+                    break;
+                }
+
+                case CapabilityType.InterruptPair:
                 {
                     // TODO: GIC distributor check.
-                    int irq0 = (cap >> 12) & 0x3ff;
-                    int irq1 = (cap >> 22) & 0x3ff;
+                    int irq0 = ((int)cap >> 12) & 0x3ff;
+                    int irq1 = ((int)cap >> 22) & 0x3ff;
 
                     if (irq0 != 0x3ff)
                     {
@@ -242,11 +249,11 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
                     break;
                 }
 
-                case 0x2000:
+                case CapabilityType.ProgramType:
                 {
-                    int applicationType = cap >> 14;
+                    uint applicationType = (cap >> 14);
 
-                    if ((uint)applicationType > 7)
+                    if (applicationType > 7)
                     {
                         return KernelResult.ReservedValue;
                     }
@@ -256,7 +263,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
                     break;
                 }
 
-                case 0x4000:
+                case CapabilityType.KernelVersion:
                 {
                     // Note: This check is bugged on kernel too, we are just replicating the bug here.
                     if ((KernelReleaseVersion >> 17) != 0 || cap < 0x80000)
@@ -269,11 +276,11 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
                     break;
                 }
 
-                case 0x8000:
+                case CapabilityType.HandleTable:
                 {
-                    int handleTableSize = cap >> 26;
+                    uint handleTableSize = cap >> 26;
 
-                    if ((uint)handleTableSize > 0x3ff)
+                    if (handleTableSize > 0x3ff)
                     {
                         return KernelResult.ReservedValue;
                     }
@@ -283,16 +290,16 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
                     break;
                 }
 
-                case 0x10000:
+                case CapabilityType.DebugFlags:
                 {
-                    int debuggingFlags = cap >> 19;
+                    uint debuggingFlags = cap >> 19;
 
-                    if ((uint)debuggingFlags > 3)
+                    if (debuggingFlags > 3)
                     {
                         return KernelResult.ReservedValue;
                     }
 
-                    DebuggingFlags &= ~3;
+                    DebuggingFlags &= ~3u;
                     DebuggingFlags |= debuggingFlags;
 
                     break;
@@ -304,18 +311,18 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
             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)
             {
                 return ulong.MaxValue;
             }
 
-            ulong mask = (1UL << range) - 1;
+            ulong mask = (1UL << (int)range) - 1;
 
-            return mask << min;
+            return mask << (int)min;
         }
     }
 }
\ No newline at end of file
diff --git a/Ryujinx.HLE/HOS/Kernel/Process/ProcessCreationFlags.cs b/Ryujinx.HLE/HOS/Kernel/Process/ProcessCreationFlags.cs
index a34481e55e..a79978ac43 100644
--- a/Ryujinx.HLE/HOS/Kernel/Process/ProcessCreationFlags.cs
+++ b/Ryujinx.HLE/HOS/Kernel/Process/ProcessCreationFlags.cs
@@ -1,5 +1,8 @@
-namespace Ryujinx.HLE.HOS.Kernel.Process
+using System;
+
+namespace Ryujinx.HLE.HOS.Kernel.Process
 {
+    [Flags]
     enum ProcessCreationFlags
     {
         Is64Bit = 1 << 0,
diff --git a/Ryujinx.HLE/HOS/Kernel/SupervisorCall/Syscall.cs b/Ryujinx.HLE/HOS/Kernel/SupervisorCall/Syscall.cs
index e23274ebca..eef78e186f 100644
--- a/Ryujinx.HLE/HOS/Kernel/SupervisorCall/Syscall.cs
+++ b/Ryujinx.HLE/HOS/Kernel/SupervisorCall/Syscall.cs
@@ -54,7 +54,7 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
         public Result CreateProcess(
             out int handle,
             ProcessCreationInfo info,
-            ReadOnlySpan<int> capabilities,
+            ReadOnlySpan<uint> capabilities,
             IProcessContextFactory contextFactory,
             ThreadStart customThreadStart = null)
         {
@@ -3002,4 +3002,4 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
             return (address & 3) != 0;
         }
     }
-}
+}
\ No newline at end of file
diff --git a/Ryujinx.HLE/HOS/ProgramLoader.cs b/Ryujinx.HLE/HOS/ProgramLoader.cs
index 158ab701fe..4ebcb7e7dc 100644
--- a/Ryujinx.HLE/HOS/ProgramLoader.cs
+++ b/Ryujinx.HLE/HOS/ProgramLoader.cs
@@ -80,7 +80,7 @@ namespace Ryujinx.HLE.HOS
 
             ulong codeBaseAddress = kip.Is64BitAddressSpace ? 0x8000000UL : 0x200000UL;
 
-            ulong codeAddress = codeBaseAddress + (ulong)kip.TextOffset;
+            ulong codeAddress = codeBaseAddress + kip.TextOffset;
 
             ProcessCreationFlags flags = 0;
 
@@ -231,13 +231,13 @@ namespace Ryujinx.HLE.HOS
 
                 nsoSize = BitUtils.AlignUp<uint>(nsoSize, KPageTableBase.PageSize);
 
-                nsoBase[index] = codeStart + (ulong)codeSize;
+                nsoBase[index] = codeStart + codeSize;
 
                 codeSize += nsoSize;
 
                 if (arguments != null && argsSize == 0)
                 {
-                    argsStart = (ulong)codeSize;
+                    argsStart = codeSize;
 
                     argsSize = (uint)BitUtils.AlignDown(arguments.Length * 2 + ArgsTotalSize - 1, KPageTableBase.PageSize);
 
@@ -318,7 +318,7 @@ namespace Ryujinx.HLE.HOS
 
             result = process.Initialize(
                 creationInfo,
-                MemoryMarshal.Cast<byte, int>(npdm.KernelCapabilityData).ToArray(),
+                MemoryMarshal.Cast<byte, uint>(npdm.KernelCapabilityData),
                 resourceLimit,
                 memoryRegion,
                 processContextFactory);
diff --git a/Ryujinx.HLE/HOS/Services/ServerBase.cs b/Ryujinx.HLE/HOS/Services/ServerBase.cs
index 50f6c99e66..d4382a6433 100644
--- a/Ryujinx.HLE/HOS/Services/ServerBase.cs
+++ b/Ryujinx.HLE/HOS/Services/ServerBase.cs
@@ -19,7 +19,7 @@ namespace Ryujinx.HLE.HOS.Services
         // not large enough.
         private const int PointerBufferSize = 0x8000;
 
-        private readonly static int[] DefaultCapabilities = new int[]
+        private readonly static uint[] DefaultCapabilities = new uint[]
         {
             0x030363F7,
             0x1FFFFFCF,
diff --git a/Ryujinx.HLE/Loaders/Executables/KipExecutable.cs b/Ryujinx.HLE/Loaders/Executables/KipExecutable.cs
index 2073a7e2d8..ad2b681cd7 100644
--- a/Ryujinx.HLE/Loaders/Executables/KipExecutable.cs
+++ b/Ryujinx.HLE/Loaders/Executables/KipExecutable.cs
@@ -22,7 +22,7 @@ namespace Ryujinx.HLE.Loaders.Executables
         public uint DataSize { get; }
         public uint BssSize  { get; }
 
-        public int[] Capabilities       { get; }
+        public uint[] Capabilities      { get; }
         public bool UsesSecureMemory    { get; }
         public bool Is64BitAddressSpace { get; }
         public bool Is64Bit             { get; }
@@ -57,11 +57,11 @@ namespace Ryujinx.HLE.Loaders.Executables
             Version     = reader.Version;
             Name        = reader.Name.ToString();
 
-            Capabilities = new int[32];
+            Capabilities = new uint[32];
 
             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();