diff options
author | Ac_K <Acoustik666@gmail.com> | 2018-06-18 02:28:11 +0000 |
---|---|---|
committer | gdkchan <gab.dark.100@gmail.com> | 2018-06-17 23:28:11 -0300 |
commit | 4e430760b4f5b50284459ccdc6439af65ed5862c (patch) | |
tree | c5886c7f50a5dce05e055525f5a2cdd973f01062 | |
parent | 3c4dafff3fd37daf1a3ab5fab9357cfee46c9a6b (diff) |
Implement NPDM files parser (#169)
* Implement NPDM files parser
(Currently not used in Ryujinx)
* Add credits
* Add Swap32
* Update Npdm.cs
* Update ACI0.cs
* Update ACID.cs
* Update Npdm.cs
* Update EndianSwap.cs
* Update ACI0.cs
* Update ACID.cs
* Update KernelAccessControl.cs
* Update NpdmInfo.cs
* Update ServiceAccessControl.cs
* Update NpdmInfo.cs
-rw-r--r-- | Ryujinx.HLE/Loaders/Npdm/ACI0.cs | 56 | ||||
-rw-r--r-- | Ryujinx.HLE/Loaders/Npdm/ACID.cs | 68 | ||||
-rw-r--r-- | Ryujinx.HLE/Loaders/Npdm/FSAccessControl.cs | 28 | ||||
-rw-r--r-- | Ryujinx.HLE/Loaders/Npdm/FSAccessHeader.cs | 37 | ||||
-rw-r--r-- | Ryujinx.HLE/Loaders/Npdm/KernelAccessControl.cs | 208 | ||||
-rw-r--r-- | Ryujinx.HLE/Loaders/Npdm/Npdm.cs | 87 | ||||
-rw-r--r-- | Ryujinx.HLE/Loaders/Npdm/NpdmException.cs | 9 | ||||
-rw-r--r-- | Ryujinx.HLE/Loaders/Npdm/NpdmInfo.cs | 215 | ||||
-rw-r--r-- | Ryujinx.HLE/Loaders/Npdm/ServiceAccessControl.cs | 35 | ||||
-rw-r--r-- | Ryujinx.HLE/OsHle/Utilities/EndianSwap.cs | 10 |
10 files changed, 753 insertions, 0 deletions
diff --git a/Ryujinx.HLE/Loaders/Npdm/ACI0.cs b/Ryujinx.HLE/Loaders/Npdm/ACI0.cs new file mode 100644 index 00000000..1f1b810e --- /dev/null +++ b/Ryujinx.HLE/Loaders/Npdm/ACI0.cs @@ -0,0 +1,56 @@ +using Ryujinx.HLE.OsHle.Utilities;
+using System;
+using System.IO;
+
+namespace Ryujinx.HLE.Loaders.Npdm
+{
+ class ACI0
+ {
+ public string TitleId;
+
+ private int FSAccessHeaderOffset;
+ private int FSAccessHeaderSize;
+ private int ServiceAccessControlOffset;
+ private int ServiceAccessControlSize;
+ private int KernelAccessControlOffset;
+ private int KernelAccessControlSize;
+
+ public FSAccessHeader FSAccessHeader;
+ public ServiceAccessControl ServiceAccessControl;
+ public KernelAccessControl KernelAccessControl;
+
+ public const long ACI0Magic = 'A' << 0 | 'C' << 8 | 'I' << 16 | '0' << 24;
+
+ public ACI0(Stream ACI0Stream, int Offset)
+ {
+ ACI0Stream.Seek(Offset, SeekOrigin.Begin);
+
+ BinaryReader Reader = new BinaryReader(ACI0Stream);
+
+ if (Reader.ReadInt32() != ACI0Magic)
+ {
+ throw new InvalidNpdmException("ACI0 Stream doesn't contain ACI0 section!");
+ }
+
+ ACI0Stream.Seek(0x0C, SeekOrigin.Current);
+
+ byte[] TempTitleId = Reader.ReadBytes(8);
+ Array.Reverse(TempTitleId);
+ TitleId = BitConverter.ToString(TempTitleId).Replace("-", "");
+
+ // Reserved (Not currently used, potentially to be used for lowest title ID in future.)
+ ACI0Stream.Seek(0x08, SeekOrigin.Current);
+
+ FSAccessHeaderOffset = Reader.ReadInt32();
+ FSAccessHeaderSize = Reader.ReadInt32();
+ ServiceAccessControlOffset = Reader.ReadInt32();
+ ServiceAccessControlSize = Reader.ReadInt32();
+ KernelAccessControlOffset = Reader.ReadInt32();
+ KernelAccessControlSize = Reader.ReadInt32();
+
+ FSAccessHeader = new FSAccessHeader(ACI0Stream, Offset + FSAccessHeaderOffset, FSAccessHeaderSize);
+ ServiceAccessControl = new ServiceAccessControl(ACI0Stream, Offset + ServiceAccessControlOffset, ServiceAccessControlSize);
+ KernelAccessControl = new KernelAccessControl(ACI0Stream, Offset + KernelAccessControlOffset, KernelAccessControlSize);
+ }
+ }
+}
diff --git a/Ryujinx.HLE/Loaders/Npdm/ACID.cs b/Ryujinx.HLE/Loaders/Npdm/ACID.cs new file mode 100644 index 00000000..d0f0acdd --- /dev/null +++ b/Ryujinx.HLE/Loaders/Npdm/ACID.cs @@ -0,0 +1,68 @@ +using Ryujinx.HLE.OsHle.Utilities;
+using System;
+using System.IO;
+
+namespace Ryujinx.HLE.Loaders.Npdm
+{
+ class ACID
+ {
+ public byte[] RSA2048Signature;
+ public byte[] RSA2048Modulus;
+ public int Unknown1;
+ public int Flags;
+
+ public string TitleIdRangeMin;
+ public string TitleIdRangeMax;
+
+ private int FSAccessControlOffset;
+ private int FSAccessControlSize;
+ private int ServiceAccessControlOffset;
+ private int ServiceAccessControlSize;
+ private int KernelAccessControlOffset;
+ private int KernelAccessControlSize;
+
+ public FSAccessControl FSAccessControl;
+ public ServiceAccessControl ServiceAccessControl;
+ public KernelAccessControl KernelAccessControl;
+
+ public const long ACIDMagic = 'A' << 0 | 'C' << 8 | 'I' << 16 | 'D' << 24;
+
+ public ACID(Stream ACIDStream, int Offset)
+ {
+ ACIDStream.Seek(Offset, SeekOrigin.Begin);
+
+ BinaryReader Reader = new BinaryReader(ACIDStream);
+
+ RSA2048Signature = Reader.ReadBytes(0x100);
+ RSA2048Modulus = Reader.ReadBytes(0x100);
+
+ if (Reader.ReadInt32() != ACIDMagic)
+ {
+ throw new InvalidNpdmException("ACID Stream doesn't contain ACID section!");
+ }
+
+ Unknown1 = Reader.ReadInt32(); // Size field used with the above signature(?).
+ Reader.ReadInt32(); // Padding / Unused
+ Flags = Reader.ReadInt32(); // Bit0 must be 1 on retail, on devunit 0 is also allowed. Bit1 is unknown.
+
+ byte[] TempTitleIdRangeMin = Reader.ReadBytes(8);
+ Array.Reverse(TempTitleIdRangeMin);
+ TitleIdRangeMin = BitConverter.ToString(TempTitleIdRangeMin).Replace("-", "");
+
+ byte[] TempTitleIdRangeMax = Reader.ReadBytes(8);
+ Array.Reverse(TempTitleIdRangeMax);
+ TitleIdRangeMax = BitConverter.ToString(TempTitleIdRangeMax).Replace("-", "");
+
+ FSAccessControlOffset = Reader.ReadInt32();
+ FSAccessControlSize = Reader.ReadInt32();
+ ServiceAccessControlOffset = Reader.ReadInt32();
+ ServiceAccessControlSize = Reader.ReadInt32();
+ KernelAccessControlOffset = Reader.ReadInt32();
+ KernelAccessControlSize = Reader.ReadInt32();
+
+ FSAccessControl = new FSAccessControl(ACIDStream, Offset + FSAccessControlOffset, FSAccessControlSize);
+ ServiceAccessControl = new ServiceAccessControl(ACIDStream, Offset + ServiceAccessControlOffset, ServiceAccessControlSize);
+ KernelAccessControl = new KernelAccessControl(ACIDStream, Offset + KernelAccessControlOffset, KernelAccessControlSize);
+ }
+ }
+}
diff --git a/Ryujinx.HLE/Loaders/Npdm/FSAccessControl.cs b/Ryujinx.HLE/Loaders/Npdm/FSAccessControl.cs new file mode 100644 index 00000000..ca8eac2e --- /dev/null +++ b/Ryujinx.HLE/Loaders/Npdm/FSAccessControl.cs @@ -0,0 +1,28 @@ +using System.IO;
+
+namespace Ryujinx.HLE.Loaders.Npdm
+{
+ public class FSAccessControl
+ {
+ public int Version;
+ public ulong PermissionsBitmask;
+ public int Unknown1;
+ public int Unknown2;
+ public int Unknown3;
+ public int Unknown4;
+
+ public FSAccessControl(Stream FSAccessHeaderStream, int Offset, int Size)
+ {
+ FSAccessHeaderStream.Seek(Offset, SeekOrigin.Begin);
+
+ BinaryReader Reader = new BinaryReader(FSAccessHeaderStream);
+
+ Version = Reader.ReadInt32();
+ PermissionsBitmask = Reader.ReadUInt64();
+ Unknown1 = Reader.ReadInt32();
+ Unknown2 = Reader.ReadInt32();
+ Unknown3 = Reader.ReadInt32();
+ Unknown4 = Reader.ReadInt32();
+ }
+ }
+}
diff --git a/Ryujinx.HLE/Loaders/Npdm/FSAccessHeader.cs b/Ryujinx.HLE/Loaders/Npdm/FSAccessHeader.cs new file mode 100644 index 00000000..0ba3af73 --- /dev/null +++ b/Ryujinx.HLE/Loaders/Npdm/FSAccessHeader.cs @@ -0,0 +1,37 @@ +using System.IO;
+
+namespace Ryujinx.HLE.Loaders.Npdm
+{
+ public class FSAccessHeader
+ {
+ public int Version;
+ public ulong PermissionsBitmask;
+ public int DataSize;
+ public int ContentOwnerIDSize;
+ public int DataAndContentOwnerIDSize;
+
+ public FSAccessHeader(Stream FSAccessHeaderStream, int Offset, int Size)
+ {
+ FSAccessHeaderStream.Seek(Offset, SeekOrigin.Begin);
+
+ BinaryReader Reader = new BinaryReader(FSAccessHeaderStream);
+
+ Version = Reader.ReadInt32();
+ PermissionsBitmask = Reader.ReadUInt64();
+ DataSize = Reader.ReadInt32();
+
+ if (DataSize != 0x1C)
+ {
+ throw new InvalidNpdmException("FSAccessHeader is corrupted!");
+ }
+
+ ContentOwnerIDSize = Reader.ReadInt32();
+ DataAndContentOwnerIDSize = Reader.ReadInt32();
+
+ if (DataAndContentOwnerIDSize != 0x1C)
+ {
+ throw new InvalidNpdmException("ContentOwnerID section is not implemented!");
+ }
+ }
+ }
+}
diff --git a/Ryujinx.HLE/Loaders/Npdm/KernelAccessControl.cs b/Ryujinx.HLE/Loaders/Npdm/KernelAccessControl.cs new file mode 100644 index 00000000..46fad63e --- /dev/null +++ b/Ryujinx.HLE/Loaders/Npdm/KernelAccessControl.cs @@ -0,0 +1,208 @@ +using System.Collections.Generic;
+using System.IO;
+
+namespace Ryujinx.HLE.Loaders.Npdm
+{
+ public class KernelAccessControlIRQ
+ {
+ public uint IRQ0;
+ public uint IRQ1;
+ }
+
+ public class KernelAccessControlMMIO
+ {
+ public ulong Address;
+ public ulong Size;
+ public bool IsRO;
+ public bool IsNormal;
+ }
+
+ public class KernelAccessControlItems
+ {
+ public bool HasKernelFlags;
+ public uint LowestThreadPriority;
+ public uint HighestThreadPriority;
+ public uint LowestCpuId;
+ public uint HighestCpuId;
+
+ public bool HasSVCFlags;
+ public int[] SVCsAllowed;
+
+ public List<KernelAccessControlMMIO> NormalMMIO;
+ public List<KernelAccessControlMMIO> PageMMIO;
+ public List<KernelAccessControlIRQ> IRQ;
+
+ public bool HasApplicationType;
+ public int ApplicationType;
+
+ public bool HasKernelVersion;
+ public int KernelVersionRelease;
+
+ public bool HasHandleTableSize;
+ public int HandleTableSize;
+
+ public bool HasDebugFlags;
+ public bool AllowDebug;
+ public bool ForceDebug;
+ }
+
+ public class KernelAccessControl
+ {
+ public KernelAccessControlItems[] Items;
+
+ public KernelAccessControl(Stream FSAccessControlsStream, int Offset, int Size)
+ {
+ FSAccessControlsStream.Seek(Offset, SeekOrigin.Begin);
+
+ BinaryReader Reader = new BinaryReader(FSAccessControlsStream);
+
+ Items = new KernelAccessControlItems[Size / 4];
+
+ for (int i = 0; i < Size / 4; i++)
+ {
+ uint Descriptor = Reader.ReadUInt32();
+
+ if (Descriptor == 0xFFFFFFFF) //Ignore the descriptor
+ {
+ continue;
+ }
+
+ Items[i] = new KernelAccessControlItems();
+
+ int LowBits = 0;
+
+ while ((Descriptor & 1) != 0)
+ {
+ Descriptor >>= 1;
+ LowBits++;
+ }
+
+ Descriptor >>= 1;
+
+ switch (LowBits)
+ {
+ case 3: // Kernel flags
+ {
+ Items[i].HasKernelFlags = true;
+
+ Items[i].HighestThreadPriority = Descriptor & 0x3F;
+ Items[i].LowestThreadPriority = (Descriptor >> 6) & 0x3F;
+ Items[i].LowestCpuId = (Descriptor >> 12) & 0xFF;
+ Items[i].HighestCpuId = (Descriptor >> 20) & 0xFF;
+
+ break;
+ }
+
+ case 4: // Syscall mask
+ {
+ Items[i].HasSVCFlags = true;
+
+ Items[i].SVCsAllowed = new int[0x80];
+
+ int SysCallBase = (int)(Descriptor >> 24) * 0x18;
+
+ for (int SysCall = 0; SysCall < 0x18 && SysCallBase + SysCall < 0x80; SysCall++)
+ {
+ Items[i].SVCsAllowed[SysCallBase + SysCall] = (int)Descriptor & 1;
+ Descriptor >>= 1;
+ }
+
+ break;
+ }
+
+ case 6: // Map IO/Normal - Never tested.
+ {
+ KernelAccessControlMMIO TempNormalMMIO = new KernelAccessControlMMIO
+ {
+ Address = (Descriptor & 0xFFFFFF) << 12,
+ IsRO = (Descriptor >> 24) != 0
+ };
+
+ if (i == Size / 4 - 1)
+ {
+ throw new InvalidNpdmException("Invalid Kernel Access Control Descriptors!");
+ }
+
+ Descriptor = Reader.ReadUInt32();
+
+ if ((Descriptor & 0x7F) != 0x3F)
+ {
+ throw new InvalidNpdmException("Invalid Kernel Access Control Descriptors!");
+ }
+
+ Descriptor >>= 7;
+ TempNormalMMIO.Size = (Descriptor & 0xFFFFFF) << 12;
+ TempNormalMMIO.IsNormal = (Descriptor >> 24) != 0;
+
+ Items[i].NormalMMIO.Add(TempNormalMMIO);
+ i++;
+
+ break;
+ }
+
+ case 7: // Map Normal Page - Never tested.
+ {
+ KernelAccessControlMMIO TempPageMMIO = new KernelAccessControlMMIO
+ {
+ Address = Descriptor << 12,
+ Size = 0x1000,
+ IsRO = false,
+ IsNormal = false
+ };
+
+ Items[i].PageMMIO.Add(TempPageMMIO);
+
+ break;
+ }
+
+ case 11: // IRQ Pair - Never tested.
+ {
+ KernelAccessControlIRQ TempIRQ = new KernelAccessControlIRQ
+ {
+ IRQ0 = Descriptor & 0x3FF,
+ IRQ1 = (Descriptor >> 10) & 0x3FF
+ };
+
+ break;
+ }
+
+ case 13: // App Type
+ {
+ Items[i].HasApplicationType = true;
+ Items[i].ApplicationType = (int)Descriptor & 7;
+
+ break;
+ }
+
+ case 14: // Kernel Release Version
+ {
+ Items[i].HasKernelVersion = true;
+
+ Items[i].KernelVersionRelease = (int)Descriptor;
+
+ break;
+ }
+
+ case 15: // Handle Table Size
+ {
+ Items[i].HasHandleTableSize = true;
+
+ Items[i].HandleTableSize = (int)Descriptor;
+
+ break;
+ }
+
+ case 16: // Debug Flags
+ {
+ Items[i].HasDebugFlags = true;
+
+ Items[i].AllowDebug = (Descriptor & 1) != 0;
+ Items[i].ForceDebug = ((Descriptor >> 1) & 1) != 0;
+
+ break;
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/Ryujinx.HLE/Loaders/Npdm/Npdm.cs b/Ryujinx.HLE/Loaders/Npdm/Npdm.cs new file mode 100644 index 00000000..d255e668 --- /dev/null +++ b/Ryujinx.HLE/Loaders/Npdm/Npdm.cs @@ -0,0 +1,87 @@ +using Ryujinx.HLE.OsHle.Utilities;
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Text;
+
+namespace Ryujinx.HLE.Loaders.Npdm
+{
+ //https://github.com/SciresM/hactool/blob/master/npdm.c
+ //https://github.com/SciresM/hactool/blob/master/npdm.h
+ //http://switchbrew.org/index.php?title=NPDM
+ class Npdm
+ {
+ public bool Is64Bits;
+ public int AddressSpaceWidth;
+ public byte MainThreadPriority;
+ public byte DefaultCpuId;
+ public int SystemResourceSize;
+ public int ProcessCategory;
+ public int MainEntrypointStackSize;
+ public string TitleName;
+ public byte[] ProductCode;
+ public ulong FSPerms;
+
+ private int ACI0Offset;
+ private int ACI0Size;
+ private int ACIDOffset;
+ private int ACIDSize;
+
+ public ACI0 ACI0;
+ public ACID ACID;
+
+ public const long NpdmMagic = 'M' << 0 | 'E' << 8 | 'T' << 16 | 'A' << 24;
+
+ public Npdm(Stream NPDMStream)
+ {
+ BinaryReader Reader = new BinaryReader(NPDMStream);
+
+ if (Reader.ReadInt32() != NpdmMagic)
+ {
+ throw new InvalidNpdmException("NPDM Stream doesn't contain NPDM file!");
+ }
+
+ Reader.ReadInt64(); // Padding / Unused
+
+ // MmuFlags, bit0: 64-bit instructions, bits1-3: address space width (1=64-bit, 2=32-bit). Needs to be <= 0xF
+ byte MmuFlags = Reader.ReadByte();
+ Is64Bits = (MmuFlags & 1) != 0;
+ AddressSpaceWidth = (MmuFlags >> 1) & 7;
+
+ Reader.ReadByte(); // Padding / Unused
+
+ MainThreadPriority = Reader.ReadByte(); // (0-63)
+ DefaultCpuId = Reader.ReadByte();
+
+ Reader.ReadInt32(); // Padding / Unused
+
+ // System resource size (max size as of 5.x: 534773760). Unknown usage.
+ SystemResourceSize = EndianSwap.Swap32(Reader.ReadInt32());
+
+ // ProcessCategory (0: regular title, 1: kernel built-in). Should be 0 here.
+ ProcessCategory = EndianSwap.Swap32(Reader.ReadInt32());
+
+ // Main entrypoint stack size
+ // (Should(?) be page-aligned. In non-nspwn scenarios, values of 0 can also rarely break in Horizon.
+ // This might be something auto-adapting or a security feature of some sort ?)
+ MainEntrypointStackSize = Reader.ReadInt32();
+
+ byte[] TempTitleName = Reader.ReadBytes(0x10);
+ TitleName = Encoding.UTF8.GetString(TempTitleName, 0, TempTitleName.Length).Trim('\0');
+
+ ProductCode = Reader.ReadBytes(0x10); // Unknown value
+
+ NPDMStream.Seek(0x30, SeekOrigin.Current); // Skip reserved bytes
+
+ ACI0Offset = Reader.ReadInt32();
+ ACI0Size = Reader.ReadInt32();
+ ACIDOffset = Reader.ReadInt32();
+ ACIDSize = Reader.ReadInt32();
+
+ ACI0 = new ACI0(NPDMStream, ACI0Offset);
+ ACID = new ACID(NPDMStream, ACIDOffset);
+
+ FSPerms = ACI0.FSAccessHeader.PermissionsBitmask & ACID.FSAccessControl.PermissionsBitmask;
+ }
+ }
+}
diff --git a/Ryujinx.HLE/Loaders/Npdm/NpdmException.cs b/Ryujinx.HLE/Loaders/Npdm/NpdmException.cs new file mode 100644 index 00000000..d87a6461 --- /dev/null +++ b/Ryujinx.HLE/Loaders/Npdm/NpdmException.cs @@ -0,0 +1,9 @@ +using System;
+
+namespace Ryujinx.HLE.Loaders.Npdm
+{
+ public class InvalidNpdmException : Exception
+ {
+ public InvalidNpdmException(string ExMsg) : base(ExMsg) { }
+ }
+}
diff --git a/Ryujinx.HLE/Loaders/Npdm/NpdmInfo.cs b/Ryujinx.HLE/Loaders/Npdm/NpdmInfo.cs new file mode 100644 index 00000000..72e6b3e2 --- /dev/null +++ b/Ryujinx.HLE/Loaders/Npdm/NpdmInfo.cs @@ -0,0 +1,215 @@ +namespace Ryujinx.HLE.Loaders.Npdm
+{
+ enum FSPermissionRW : ulong
+ {
+ MountContentType2 = 0x8000000000000801,
+ MountContentType5 = 0x8000000000000801,
+ MountContentType3 = 0x8000000000000801,
+ MountContentType4 = 0x8000000000000801,
+ MountContentType6 = 0x8000000000000801,
+ MountContentType7 = 0x8000000000000801,
+ Unknown0x6 = 0x8000000000000000,
+ ContentStorageAccess = 0x8000000000000800,
+ ImageDirectoryAccess = 0x8000000000001000,
+ MountBisType28 = 0x8000000000000084,
+ MountBisType29 = 0x8000000000000080,
+ MountBisType30 = 0x8000000000008080,
+ MountBisType31 = 0x8000000000008080,
+ Unknown0xD = 0x8000000000000080,
+ SdCardAccess = 0xC000000000200000,
+ GameCardUser = 0x8000000000000010,
+ SaveDataAccess0 = 0x8000000000040020,
+ SystemSaveDataAccess0 = 0x8000000000000028,
+ SaveDataAccess1 = 0x8000000000000020,
+ SystemSaveDataAccess1 = 0x8000000000000020,
+ BisPartition0 = 0x8000000000010082,
+ BisPartition10 = 0x8000000000010080,
+ BisPartition20 = 0x8000000000010080,
+ BisPartition21 = 0x8000000000010080,
+ BisPartition22 = 0x8000000000010080,
+ BisPartition23 = 0x8000000000010080,
+ BisPartition24 = 0x8000000000010080,
+ BisPartition25 = 0x8000000000010080,
+ BisPartition26 = 0x8000000000000080,
+ BisPartition27 = 0x8000000000000084,
+ BisPartition28 = 0x8000000000000084,
+ BisPartition29 = 0x8000000000000080,
+ BisPartition30 = 0x8000000000000080,
+ BisPartition31 = 0x8000000000000080,
+ BisPartition32 = 0x8000000000000080,
+ Unknown0x23 = 0xC000000000200000,
+ GameCard_System = 0x8000000000000100,
+ MountContent_System = 0x8000000000100008,
+ HostAccess = 0xC000000000400000
+ };
+
+ enum FSPermissionBool : ulong
+ {
+ BisCache = 0x8000000000000080,
+ EraseMmc = 0x8000000000000080,
+ GameCardCertificate = 0x8000000000000010,
+ GameCardIdSet = 0x8000000000000010,
+ GameCardDriver = 0x8000000000000200,
+ GameCardAsic = 0x8000000000000200,
+ SaveDataCreate = 0x8000000000002020,
+ SaveDataDelete0 = 0x8000000000000060,
+ SystemSaveDataCreate0 = 0x8000000000000028,
+ SystemSaveDataCreate1 = 0x8000000000000020,
+ SaveDataDelete1 = 0x8000000000004028,
+ SaveDataIterators0 = 0x8000000000000060,
+ SaveDataIterators1 = 0x8000000000004020,
+ SaveThumbnails = 0x8000000000020000,
+ PosixTime = 0x8000000000000400,
+ SaveDataExtraData = 0x8000000000004060,
+ GlobalMode = 0x8000000000080000,
+ SpeedEmulation = 0x8000000000080000,
+ NULL = 0,
+ PaddingFiles = 0xC000000000800000,
+ SaveData_Debug = 0xC000000001000000,
+ SaveData_SystemManagement = 0xC000000002000000,
+ Unknown0x16 = 0x8000000004000000,
+ Unknown0x17 = 0x8000000008000000,
+ Unknown0x18 = 0x8000000010000000,
+ Unknown0x19 = 0x8000000000000800,
+ Unknown0x1A = 0x8000000000004020
+ }
+
+ enum NpdmApplicationType
+ {
+ SystemModule,
+ Application,
+ Applet
+ }
+
+ enum SvcName
+ {
+ svcUnknown0,
+ svcSetHeapSize,
+ svcSetMemoryPermission,
+ svcSetMemoryAttribute,
+ svcMapMemory,
+ svcUnmapMemory,
+ svcQueryMemory,
+ svcExitProcess,
+ svcCreateThread,
+ svcStartThread,
+ svcExitThread,
+ svcSleepThread,
+ svcGetThreadPriority,
+ svcSetThreadPriority,
+ svcGetThreadCoreMask,
+ svcSetThreadCoreMask,
+ svcGetCurrentProcessorNumber,
+ svcSignalEvent,
+ svcClearEvent,
+ svcMapSharedMemory,
+ svcUnmapSharedMemory,
+ svcCreateTransferMemory,
+ svcCloseHandle,
+ svcResetSignal,
+ svcWaitSynchronization,
+ svcCancelSynchronization,
+ svcArbitrateLock,
+ svcArbitrateUnlock,
+ svcWaitProcessWideKeyAtomic,
+ svcSignalProcessWideKey,
+ svcGetSystemTick,
+ svcConnectToNamedPort,
+ svcSendSyncRequestLight,
+ svcSendSyncRequest,
+ svcSendSyncRequestWithUserBuffer,
+ svcSendAsyncRequestWithUserBuffer,
+ svcGetProcessId,
+ svcGetThreadId,
+ svcBreak,
+ svcOutputDebugString,
+ svcReturnFromException,
+ svcGetInfo,
+ svcFlushEntireDataCache,
+ svcFlushDataCache,
+ svcMapPhysicalMemory,
+ svcUnmapPhysicalMemory,
+ svcGetFutureThreadInfo,
+ svcGetLastThreadInfo,
+ svcGetResourceLimitLimitValue,
+ svcGetResourceLimitCurrentValue,
+ svcSetThreadActivity,
+ svcGetThreadContext3,
+ svcWaitForAddress,
+ svcSignalToAddress,
+ svcUnknown1,
+ svcUnknown2,
+ svcUnknown3,
+ svcUnknown4,
+ svcUnknown5,
+ svcUnknown6,
+ svcDumpInfo,
+ svcDumpInfoNew,
+ svcUnknown7,
+ svcUnknown8,
+ svcCreateSession,
+ svcAcceptSession,
+ svcReplyAndReceiveLight,
+ svcReplyAndReceive,
+ svcReplyAndReceiveWithUserBuffer,
+ svcCreateEvent,
+ svcUnknown9,
+ svcUnknown10,
+ svcMapPhysicalMemoryUnsafe,
+ svcUnmapPhysicalMemoryUnsafe,
+ svcSetUnsafeLimit,
+ svcCreateCodeMemory,
+ svcControlCodeMemory,
+ svcSleepSystem,
+ svcReadWriteRegister,
+ svcSetProcessActivity,
+ svcCreateSharedMemory,
+ svcMapTransferMemory,
+ svcUnmapTransferMemory,
+ svcCreateInterruptEvent,
+ svcQueryPhysicalAddress,
+ svcQueryIoMapping,
+ svcCreateDeviceAddressSpace,
+ svcAttachDeviceAddressSpace,
+ svcDetachDeviceAddressSpace,
+ svcMapDeviceAddressSpaceByForce,
+ svcMapDeviceAddressSpaceAligned,
+ svcMapDeviceAddressSpace,
+ svcUnmapDeviceAddressSpace,
+ svcInvalidateProcessDataCache,
+ svcStoreProcessDataCache,
+ svcFlushProcessDataCache,
+ svcDebugActiveProcess,
+ svcBreakDebugProcess,
+ svcTerminateDebugProcess,
+ svcGetDebugEvent,
+ svcContinueDebugEvent,
+ svcGetProcessList,
+ svcGetThreadList,
+ svcGetDebugThreadContext,
+ svcSetDebugThreadContext,
+ svcQueryDebugProcessMemory,
+ svcReadDebugProcessMemory,
+ svcWriteDebugProcessMemory,
+ svcSetHardwareBreakPoint,
+ svcGetDebugThreadParam,
+ svcUnknown11,
+ svcGetSystemInfo,
+ svcCreatePort,
+ svcManageNamedPort,
+ svcConnectToPort,
+ svcSetProcessMemoryPermission,
+ svcMapProcessMemory,
+ svcUnmapProcessMemory,
+ svcQueryProcessMemory,
+ svcMapProcessCodeMemory,
+ svcUnmapProcessCodeMemory,
+ svcCreateProcess,
+ svcStartProcess,
+ svcTerminateProcess,
+ svcGetProcessInfo,
+ svcCreateResourceLimit,
+ svcSetResourceLimitLimitValue,
+ svcCallSecureMonitor
+ };
+}
diff --git a/Ryujinx.HLE/Loaders/Npdm/ServiceAccessControl.cs b/Ryujinx.HLE/Loaders/Npdm/ServiceAccessControl.cs new file mode 100644 index 00000000..fd33841a --- /dev/null +++ b/Ryujinx.HLE/Loaders/Npdm/ServiceAccessControl.cs @@ -0,0 +1,35 @@ +using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Text;
+
+namespace Ryujinx.HLE.Loaders.Npdm
+{
+ public class ServiceAccessControl
+ {
+ public List<(string, bool)> Services = new List<(string, bool)>();
+
+ public ServiceAccessControl(Stream ServiceAccessControlStream, int Offset, int Size)
+ {
+ ServiceAccessControlStream.Seek(Offset, SeekOrigin.Begin);
+
+ BinaryReader Reader = new BinaryReader(ServiceAccessControlStream);
+
+ int ByteReaded = 0;
+
+ while (ByteReaded != Size)
+ {
+ byte ControlByte = Reader.ReadByte();
+
+ if (ControlByte == 0x00) break;
+
+ int Length = ((ControlByte & 0x07)) + 1;
+ bool RegisterAllowed = ((ControlByte & 0x80) != 0);
+
+ Services.Add((Encoding.ASCII.GetString(Reader.ReadBytes(Length), 0, Length), RegisterAllowed));
+
+ ByteReaded += Length + 1;
+ }
+ }
+ }
+}
diff --git a/Ryujinx.HLE/OsHle/Utilities/EndianSwap.cs b/Ryujinx.HLE/OsHle/Utilities/EndianSwap.cs index 93fd38c8..46a2edcb 100644 --- a/Ryujinx.HLE/OsHle/Utilities/EndianSwap.cs +++ b/Ryujinx.HLE/OsHle/Utilities/EndianSwap.cs @@ -3,5 +3,15 @@ static class EndianSwap { public static short Swap16(short Value) => (short)(((Value >> 8) & 0xff) | (Value << 8)); + + public static int Swap32(int Value) + { + uint UintVal = (uint)Value; + + return (int)(((UintVal >> 24) & 0x000000ff) | + ((UintVal >> 8) & 0x0000ff00) | + ((UintVal << 8) & 0x00ff0000) | + ((UintVal << 24) & 0xff000000)); + } } } |