From f6632f06b3620de1f8305d55d9fb1d28095acb9f Mon Sep 17 00:00:00 2001 From: Ac_K Date: Sun, 17 Jun 2018 03:28:40 +0000 Subject: [PATCH] Implement NPDM files parser (Currently not used in Ryujinx) --- Ryujinx.HLE/Loaders/Npdm/ACI0.cs | 53 ++++ Ryujinx.HLE/Loaders/Npdm/ACID.cs | 65 +++++ Ryujinx.HLE/Loaders/Npdm/FSAccessControl.cs | 28 ++ Ryujinx.HLE/Loaders/Npdm/FSAccessHeader.cs | 37 +++ .../Loaders/Npdm/KernelAccessControl.cs | 211 +++++++++++++++ Ryujinx.HLE/Loaders/Npdm/Npdm.cs | 81 ++++++ Ryujinx.HLE/Loaders/Npdm/NpdmException.cs | 9 + Ryujinx.HLE/Loaders/Npdm/NpdmInfo.cs | 249 ++++++++++++++++++ .../Loaders/Npdm/ServiceAccessControl.cs | 36 +++ 9 files changed, 769 insertions(+) create mode 100644 Ryujinx.HLE/Loaders/Npdm/ACI0.cs create mode 100644 Ryujinx.HLE/Loaders/Npdm/ACID.cs create mode 100644 Ryujinx.HLE/Loaders/Npdm/FSAccessControl.cs create mode 100644 Ryujinx.HLE/Loaders/Npdm/FSAccessHeader.cs create mode 100644 Ryujinx.HLE/Loaders/Npdm/KernelAccessControl.cs create mode 100644 Ryujinx.HLE/Loaders/Npdm/Npdm.cs create mode 100644 Ryujinx.HLE/Loaders/Npdm/NpdmException.cs create mode 100644 Ryujinx.HLE/Loaders/Npdm/NpdmInfo.cs create mode 100644 Ryujinx.HLE/Loaders/Npdm/ServiceAccessControl.cs diff --git a/Ryujinx.HLE/Loaders/Npdm/ACI0.cs b/Ryujinx.HLE/Loaders/Npdm/ACI0.cs new file mode 100644 index 0000000000..32f897eff3 --- /dev/null +++ b/Ryujinx.HLE/Loaders/Npdm/ACI0.cs @@ -0,0 +1,53 @@ +using System; +using System.IO; + +namespace Ryujinx.HLE.Loaders.Npdm +{ + public 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 ACI0(Stream ACI0Stream, int Offset) + { + ACI0Stream.Seek(Offset, SeekOrigin.Begin); + + BinaryReader Reader = new BinaryReader(ACI0Stream); + + if (EndianSwap.Swap32(Reader.ReadInt32()) != 0x41434930) // ACI0 + { + 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 0000000000..92e9dc29e5 --- /dev/null +++ b/Ryujinx.HLE/Loaders/Npdm/ACID.cs @@ -0,0 +1,65 @@ +using System; +using System.IO; + +namespace Ryujinx.HLE.Loaders.Npdm +{ + public 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 ACID(Stream ACIDStream, int Offset) + { + ACIDStream.Seek(Offset, SeekOrigin.Begin); + + BinaryReader Reader = new BinaryReader(ACIDStream); + + RSA2048Signature = Reader.ReadBytes(0x100); + RSA2048Modulus = Reader.ReadBytes(0x100); + + if (EndianSwap.Swap32(Reader.ReadInt32()) != 0x41434944) // ACID + { + 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 0000000000..ca8eac2e76 --- /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 0000000000..0ba3af7341 --- /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 0000000000..0fa5e07890 --- /dev/null +++ b/Ryujinx.HLE/Loaders/Npdm/KernelAccessControl.cs @@ -0,0 +1,211 @@ +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 NormalMMIO; + public List PageMMIO; + public List 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; + Descriptor >>= 6; + Items[i].LowestThreadPriority = Descriptor & 0x3F; + Descriptor >>= 6; + Items[i].LowestCpuId = Descriptor & 0xFF; + Descriptor >>= 8; + Items[i].HighestCpuId = Descriptor & 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 0000000000..78d0cd6e33 --- /dev/null +++ b/Ryujinx.HLE/Loaders/Npdm/Npdm.cs @@ -0,0 +1,81 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Text; + +namespace Ryujinx.HLE.Loaders.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 Npdm(Stream NPDMStream) + { + BinaryReader Reader = new BinaryReader(NPDMStream); + + if (EndianSwap.Swap32(Reader.ReadInt32()) != 0x4D455441) // META + { + 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 0000000000..d87a6461da --- /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 0000000000..c3bc889d04 --- /dev/null +++ b/Ryujinx.HLE/Loaders/Npdm/NpdmInfo.cs @@ -0,0 +1,249 @@ +namespace Ryujinx.HLE.Loaders.Npdm +{ + public static class NpdmInfo + { + public 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 + }; + + public 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 + } + + public enum FSBoolPermissions : 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 + } + + public enum ApplicationTypes + { + SystemModule, + Application, + Applet + } + + public enum SVCs + { + 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 0000000000..803683f01d --- /dev/null +++ b/Ryujinx.HLE/Loaders/Npdm/ServiceAccessControl.cs @@ -0,0 +1,36 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Text; + +namespace Ryujinx.HLE.Loaders.Npdm +{ + public class ServiceAccessControl + { + public List> Services = new List>(); + + 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); + byte[] TempServiceName = Reader.ReadBytes(Length); + + Services.Add(Tuple.Create(Encoding.ASCII.GetString(TempServiceName, 0, TempServiceName.Length), RegisterAllowed)); + + ByteReaded += Length + 1; + } + } + } +}