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
This commit is contained in:
parent
3c4dafff3f
commit
4e430760b4
10 changed files with 753 additions and 0 deletions
56
Ryujinx.HLE/Loaders/Npdm/ACI0.cs
Normal file
56
Ryujinx.HLE/Loaders/Npdm/ACI0.cs
Normal file
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
68
Ryujinx.HLE/Loaders/Npdm/ACID.cs
Normal file
68
Ryujinx.HLE/Loaders/Npdm/ACID.cs
Normal file
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
28
Ryujinx.HLE/Loaders/Npdm/FSAccessControl.cs
Normal file
28
Ryujinx.HLE/Loaders/Npdm/FSAccessControl.cs
Normal file
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
37
Ryujinx.HLE/Loaders/Npdm/FSAccessHeader.cs
Normal file
37
Ryujinx.HLE/Loaders/Npdm/FSAccessHeader.cs
Normal file
|
@ -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!");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
208
Ryujinx.HLE/Loaders/Npdm/KernelAccessControl.cs
Normal file
208
Ryujinx.HLE/Loaders/Npdm/KernelAccessControl.cs
Normal file
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
87
Ryujinx.HLE/Loaders/Npdm/Npdm.cs
Normal file
87
Ryujinx.HLE/Loaders/Npdm/Npdm.cs
Normal file
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
9
Ryujinx.HLE/Loaders/Npdm/NpdmException.cs
Normal file
9
Ryujinx.HLE/Loaders/Npdm/NpdmException.cs
Normal file
|
@ -0,0 +1,9 @@
|
|||
using System;
|
||||
|
||||
namespace Ryujinx.HLE.Loaders.Npdm
|
||||
{
|
||||
public class InvalidNpdmException : Exception
|
||||
{
|
||||
public InvalidNpdmException(string ExMsg) : base(ExMsg) { }
|
||||
}
|
||||
}
|
215
Ryujinx.HLE/Loaders/Npdm/NpdmInfo.cs
Normal file
215
Ryujinx.HLE/Loaders/Npdm/NpdmInfo.cs
Normal file
|
@ -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
|
||||
};
|
||||
}
|
35
Ryujinx.HLE/Loaders/Npdm/ServiceAccessControl.cs
Normal file
35
Ryujinx.HLE/Loaders/Npdm/ServiceAccessControl.cs
Normal file
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Reference in a new issue