diff --git a/LibHac/Nacp.cs b/LibHac/Nacp.cs index 8dd7fe81..ade77bd7 100644 --- a/LibHac/Nacp.cs +++ b/LibHac/Nacp.cs @@ -5,7 +5,7 @@ namespace LibHac { public class Nacp { - public NacpLang[] Languages { get; } = new NacpLang[0x10]; + public NacpDescription[] Descriptions { get; } = new NacpDescription[0x10]; public string Isbn { get; } public byte StartupUserAccount { get; } public byte TouchScreenUsageMode { get; } @@ -54,20 +54,21 @@ namespace LibHac public byte RepairFlag { get; } public byte ProgramIndex { get; } - public long TotalSaveDataSize { get; } public long UserTotalSaveDataSize { get; } public long DeviceTotalSaveDataSize { get; } public Nacp() { } - public Nacp(BinaryReader reader) + public Nacp(Stream file) { - long start = reader.BaseStream.Position; + long start = file.Position; + + BinaryReader reader = new BinaryReader(file); for (int i = 0; i < 16; i++) { - Languages[i] = new NacpLang(reader); + Descriptions[i] = new NacpDescription(reader, i); } Isbn = reader.ReadUtf8Z(37); @@ -146,15 +147,18 @@ namespace LibHac } } - public class NacpLang + public class NacpDescription { public string Title { get; } public string Developer { get; } - public NacpLang() { } + public TitleLanguage Language; - public NacpLang(BinaryReader reader) + public NacpDescription() { } + + public NacpDescription(BinaryReader reader, int index) { + Language = (TitleLanguage)index; long start = reader.BaseStream.Position; Title = reader.ReadUtf8Z(); reader.BaseStream.Position = start + 0x200; @@ -162,4 +166,23 @@ namespace LibHac reader.BaseStream.Position = start + 0x300; } } + + public enum TitleLanguage + { + AmericanEnglish = 0, + BritishEnglish, + Japanese, + French, + German, + LatinAmericanSpanish, + Spanish, + Italian, + Dutch, + CanadianFrench, + Portuguese, + Russian, + Korean, + Taiwanese, + Chinese + } } diff --git a/LibHac/Npdm/Aci0.cs b/LibHac/Npdm/Aci0.cs new file mode 100644 index 00000000..53e856cd --- /dev/null +++ b/LibHac/Npdm/Aci0.cs @@ -0,0 +1,52 @@ +using System; +using System.IO; + +namespace LibHac.Npdm +{ + public class Aci0 + { + public string Magic; + public long TitleId { get; } + public int FsVersion { get; } + public ulong FsPermissionsBitmask { get; } + public ServiceAccessControl ServiceAccess { get; } + public KernelAccessControl KernelAccess { get; } + + public Aci0(Stream stream, int offset) + { + stream.Seek(offset, SeekOrigin.Begin); + + var reader = new BinaryReader(stream); + + Magic = reader.ReadAscii(0x4); + + if (Magic != "ACI0") + { + throw new Exception("ACI0 Stream doesn't contain ACI0 section!"); + } + + stream.Seek(0xc, SeekOrigin.Current); + + TitleId = reader.ReadInt64(); + + //Reserved. + stream.Seek(8, SeekOrigin.Current); + + int fsAccessHeaderOffset = reader.ReadInt32(); + int fsAccessHeaderSize = reader.ReadInt32(); + int serviceAccessControlOffset = reader.ReadInt32(); + int serviceAccessControlSize = reader.ReadInt32(); + int kernelAccessControlOffset = reader.ReadInt32(); + int kernelAccessControlSize = reader.ReadInt32(); + + var accessHeader = new FsAccessHeader(stream, offset + fsAccessHeaderOffset); + + FsVersion = accessHeader.Version; + FsPermissionsBitmask = accessHeader.PermissionsBitmask; + + ServiceAccess = new ServiceAccessControl(stream, offset + serviceAccessControlOffset, serviceAccessControlSize); + + KernelAccess = new KernelAccessControl(stream, offset + kernelAccessControlOffset, kernelAccessControlSize); + } + } +} diff --git a/LibHac/Npdm/Acid.cs b/LibHac/Npdm/Acid.cs new file mode 100644 index 00000000..870e7c30 --- /dev/null +++ b/LibHac/Npdm/Acid.cs @@ -0,0 +1,61 @@ +using System; +using System.IO; + +namespace LibHac.Npdm +{ + public class Acid + { + public string Magic; + public byte[] Rsa2048Signature { get; } + public byte[] Rsa2048Modulus { get; } + public int Unknown1 { get; } + public int Flags { get; } + + public long TitleIdRangeMin { get; } + public long TitleIdRangeMax { get; } + + public FsAccessControl FsAccess { get; } + public ServiceAccessControl ServiceAccess { get; } + public KernelAccessControl KernelAccess { get; } + + public Acid(Stream stream, int offset) + { + stream.Seek(offset, SeekOrigin.Begin); + + var reader = new BinaryReader(stream); + + Rsa2048Signature = reader.ReadBytes(0x100); + Rsa2048Modulus = reader.ReadBytes(0x100); + + Magic = reader.ReadAscii(0x4); + if (Magic != "ACID") + { + throw new Exception("ACID Stream doesn't contain ACID section!"); + } + + //Size field used with the above signature (?). + Unknown1 = reader.ReadInt32(); + + reader.ReadInt32(); + + //Bit0 must be 1 on retail, on devunit 0 is also allowed. Bit1 is unknown. + Flags = reader.ReadInt32(); + + TitleIdRangeMin = reader.ReadInt64(); + TitleIdRangeMax = reader.ReadInt64(); + + int fsAccessControlOffset = reader.ReadInt32(); + int fsAccessControlSize = reader.ReadInt32(); + int serviceAccessControlOffset = reader.ReadInt32(); + int serviceAccessControlSize = reader.ReadInt32(); + int kernelAccessControlOffset = reader.ReadInt32(); + int kernelAccessControlSize = reader.ReadInt32(); + + FsAccess = new FsAccessControl(stream, offset + fsAccessControlOffset); + + ServiceAccess = new ServiceAccessControl(stream, offset + serviceAccessControlOffset, serviceAccessControlSize); + + KernelAccess = new KernelAccessControl(stream, offset + kernelAccessControlOffset, kernelAccessControlSize); + } + } +} diff --git a/LibHac/Npdm/ApplicationType.cs b/LibHac/Npdm/ApplicationType.cs new file mode 100644 index 00000000..5719cb05 --- /dev/null +++ b/LibHac/Npdm/ApplicationType.cs @@ -0,0 +1,9 @@ +namespace LibHac.Npdm +{ + internal enum ApplicationType + { + SystemModule, + Application, + Applet + } +} diff --git a/LibHac/Npdm/FSAccessControl.cs b/LibHac/Npdm/FSAccessControl.cs new file mode 100644 index 00000000..92ec0c77 --- /dev/null +++ b/LibHac/Npdm/FSAccessControl.cs @@ -0,0 +1,28 @@ +using System.IO; + +namespace LibHac.Npdm +{ + public class FsAccessControl + { + public int Version { get; } + public ulong PermissionsBitmask { get; } + public int Unknown1 { get; } + public int Unknown2 { get; } + public int Unknown3 { get; } + public int Unknown4 { get; } + + public FsAccessControl(Stream stream, int offset) + { + stream.Seek(offset, SeekOrigin.Begin); + + var reader = new BinaryReader(stream); + + Version = reader.ReadInt32(); + PermissionsBitmask = reader.ReadUInt64(); + Unknown1 = reader.ReadInt32(); + Unknown2 = reader.ReadInt32(); + Unknown3 = reader.ReadInt32(); + Unknown4 = reader.ReadInt32(); + } + } +} diff --git a/LibHac/Npdm/FSAccessHeader.cs b/LibHac/Npdm/FSAccessHeader.cs new file mode 100644 index 00000000..d2663ee2 --- /dev/null +++ b/LibHac/Npdm/FSAccessHeader.cs @@ -0,0 +1,36 @@ +using System; +using System.IO; + +namespace LibHac.Npdm +{ + public class FsAccessHeader + { + public int Version { get; } + public ulong PermissionsBitmask { get; } + + public FsAccessHeader(Stream stream, int offset) + { + stream.Seek(offset, SeekOrigin.Begin); + + var reader = new BinaryReader(stream); + + Version = reader.ReadInt32(); + PermissionsBitmask = reader.ReadUInt64(); + + int dataSize = reader.ReadInt32(); + + if (dataSize != 0x1c) + { + throw new Exception("FsAccessHeader is corrupted!"); + } + + int contentOwnerIdSize = reader.ReadInt32(); + int dataAndContentOwnerIdSize = reader.ReadInt32(); + + if (dataAndContentOwnerIdSize != 0x1c) + { + throw new NotImplementedException("ContentOwnerId section is not implemented!"); + } + } + } +} diff --git a/LibHac/Npdm/FsPermissionBool.cs b/LibHac/Npdm/FsPermissionBool.cs new file mode 100644 index 00000000..755cdc75 --- /dev/null +++ b/LibHac/Npdm/FsPermissionBool.cs @@ -0,0 +1,33 @@ +namespace LibHac.Npdm +{ + 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 + } +} diff --git a/LibHac/Npdm/FsPermissionRw.cs b/LibHac/Npdm/FsPermissionRw.cs new file mode 100644 index 00000000..23955969 --- /dev/null +++ b/LibHac/Npdm/FsPermissionRw.cs @@ -0,0 +1,45 @@ +namespace LibHac.Npdm +{ + 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 + } +} diff --git a/LibHac/Npdm/KernelAccessControl.cs b/LibHac/Npdm/KernelAccessControl.cs new file mode 100644 index 00000000..adb09315 --- /dev/null +++ b/LibHac/Npdm/KernelAccessControl.cs @@ -0,0 +1,173 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; + +namespace LibHac.Npdm +{ + public class KernelAccessControl + { + public List Items { get; } + + public KernelAccessControl(Stream stream, int offset, int size) + { + stream.Seek(offset, SeekOrigin.Begin); + + var reader = new BinaryReader(stream); + + var items = new KernelAccessControlItem[size / 4]; + + for (int index = 0; index < size / 4; index++) + { + uint descriptor = reader.ReadUInt32(); + + //Ignore the descriptor. + if (descriptor == 0xffffffff) + { + continue; + } + + items[index] = new KernelAccessControlItem(); + + int lowBits = 0; + + while ((descriptor & 1) != 0) + { + descriptor >>= 1; + + lowBits++; + } + + descriptor >>= 1; + + switch (lowBits) + { + //Kernel flags. + case 3: + { + items[index].HasKernelFlags = true; + + items[index].HighestThreadPriority = (descriptor >> 0) & 0x3f; + items[index].LowestThreadPriority = (descriptor >> 6) & 0x3f; + items[index].LowestCpuId = (descriptor >> 12) & 0xff; + items[index].HighestCpuId = (descriptor >> 20) & 0xff; + + break; + } + + //Syscall mask. + case 4: + { + items[index].HasSvcFlags = true; + + items[index].AllowedSvcs = new bool[0x80]; + + int sysCallBase = (int)(descriptor >> 24) * 0x18; + + for (int sysCall = 0; sysCall < 0x18 && sysCallBase + sysCall < 0x80; sysCall++) + { + Items[index].AllowedSvcs[sysCallBase + sysCall] = (descriptor & 1) != 0; + + descriptor >>= 1; + } + + break; + } + + //Map IO/Normal. + case 6: + { + ulong address = (descriptor & 0xffffff) << 12; + bool isRo = (descriptor >> 24) != 0; + + if (index == size / 4 - 1) + { + throw new Exception("Invalid Kernel Access Control Descriptors!"); + } + + descriptor = reader.ReadUInt32(); + + if ((descriptor & 0x7f) != 0x3f) + { + throw new Exception("Invalid Kernel Access Control Descriptors!"); + } + + descriptor >>= 7; + + ulong mmioSize = (descriptor & 0xffffff) << 12; + bool isNormal = (descriptor >> 24) != 0; + + items[index].NormalMmio.Add(new KernelAccessControlMmio(address, mmioSize, isRo, isNormal)); + + index++; + + break; + } + + //Map Normal Page. + case 7: + { + ulong address = descriptor << 12; + + items[index].PageMmio.Add(new KernelAccessControlMmio(address, 0x1000, false, false)); + + break; + } + + //IRQ Pair. + case 11: + { + items[index].Irq.Add(new KernelAccessControlIrq( + (descriptor >> 0) & 0x3ff, + (descriptor >> 10) & 0x3ff)); + + break; + } + + //Application Type. + case 13: + { + items[index].HasApplicationType = true; + + items[index].ApplicationType = (int)descriptor & 7; + + break; + } + + //Kernel Release Version. + case 14: + { + items[index].HasKernelVersion = true; + + items[index].KernelVersionRelease = (int)descriptor; + + break; + } + + //Handle Table Size. + case 15: + { + items[index].HasHandleTableSize = true; + + items[index].HandleTableSize = (int)descriptor; + + break; + } + + //Debug Flags. + case 16: + { + items[index].HasDebugFlags = true; + + items[index].AllowDebug = ((descriptor >> 0) & 1) != 0; + items[index].ForceDebug = ((descriptor >> 1) & 1) != 0; + + break; + } + } + } + + Items = items.ToList(); + } + } +} diff --git a/LibHac/Npdm/KernelAccessControlIrq.cs b/LibHac/Npdm/KernelAccessControlIrq.cs new file mode 100644 index 00000000..aed2f980 --- /dev/null +++ b/LibHac/Npdm/KernelAccessControlIrq.cs @@ -0,0 +1,14 @@ +namespace LibHac.Npdm +{ + public struct KernelAccessControlIrq + { + public uint Irq0 { get; } + public uint Irq1 { get; } + + public KernelAccessControlIrq(uint irq0, uint irq1) + { + Irq0 = irq0; + Irq1 = irq1; + } + } +} \ No newline at end of file diff --git a/LibHac/Npdm/KernelAccessControlMmio.cs b/LibHac/Npdm/KernelAccessControlMmio.cs new file mode 100644 index 00000000..2aea07d1 --- /dev/null +++ b/LibHac/Npdm/KernelAccessControlMmio.cs @@ -0,0 +1,22 @@ +namespace LibHac.Npdm +{ + public struct KernelAccessControlMmio + { + public ulong Address { get; } + public ulong Size { get; private set; } + public bool IsRo { get; private set; } + public bool IsNormal { get; private set; } + + public KernelAccessControlMmio( + ulong address, + ulong size, + bool isro, + bool isnormal) + { + Address = address; + Size = size; + IsRo = isro; + IsNormal = isnormal; + } + } +} \ No newline at end of file diff --git a/LibHac/Npdm/KernelAccessItem.cs b/LibHac/Npdm/KernelAccessItem.cs new file mode 100644 index 00000000..3b7e2dc9 --- /dev/null +++ b/LibHac/Npdm/KernelAccessItem.cs @@ -0,0 +1,33 @@ +using System.Collections.Generic; + +namespace LibHac.Npdm +{ + public struct KernelAccessControlItem + { + public bool HasKernelFlags { get; set; } + public uint LowestThreadPriority { get; set; } + public uint HighestThreadPriority { get; set; } + public uint LowestCpuId { get; set; } + public uint HighestCpuId { get; set; } + + public bool HasSvcFlags { get; set; } + public bool[] AllowedSvcs { get; set; } + + public List NormalMmio { get; set; } + public List PageMmio { get; set; } + public List Irq { get; set; } + + public bool HasApplicationType { get; set; } + public int ApplicationType { get; set; } + + public bool HasKernelVersion { get; set; } + public int KernelVersionRelease { get; set; } + + public bool HasHandleTableSize { get; set; } + public int HandleTableSize { get; set; } + + public bool HasDebugFlags { get; set; } + public bool AllowDebug { get; set; } + public bool ForceDebug { get; set; } + } +} \ No newline at end of file diff --git a/LibHac/Npdm/Npdm.cs b/LibHac/Npdm/Npdm.cs new file mode 100644 index 00000000..a7318f93 --- /dev/null +++ b/LibHac/Npdm/Npdm.cs @@ -0,0 +1,76 @@ +using System; +using System.IO; + +namespace LibHac.Npdm +{ + //https://github.com/Ryujinx/Ryujinx/blob/master/Ryujinx.HLE/Loaders/Npdm/Npdm.cs + //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 + public class Npdm + { + public string Magic; + public bool Is64Bits { get; } + public int AddressSpaceWidth { get; } + public byte MainThreadPriority { get; } + public byte DefaultCpuId { get; } + public int SystemResourceSize { get; } + public int ProcessCategory { get; } + public int MainEntrypointStackSize { get; } + public string TitleName { get; } + public byte[] ProductCode { get; } + + public Aci0 Aci0 { get; } + public Acid AciD { get; } + + public Npdm(Stream stream) + { + var reader = new BinaryReader(stream); + + Magic = reader.ReadAscii(0x4); + + if (Magic != "META") + { + throw new Exception("NPDM Stream doesn't contain NPDM file!"); + } + + reader.ReadInt64(); + + //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(); + + MainThreadPriority = reader.ReadByte(); //(0-63). + DefaultCpuId = reader.ReadByte(); + + reader.ReadInt32(); + + //System resource size (max size as of 5.x: 534773760). + SystemResourceSize = Util.Swap32(reader.ReadInt32()); + + //ProcessCategory (0: regular title, 1: kernel built-in). Should be 0 here. + ProcessCategory = Util.Swap32(reader.ReadInt32()); + + //Main entrypoint stack size. + MainEntrypointStackSize = reader.ReadInt32(); + + TitleName = reader.ReadUtf8(0x10).Trim('\0'); + + ProductCode = reader.ReadBytes(0x10); + + stream.Seek(0x30, SeekOrigin.Current); + + int aci0Offset = reader.ReadInt32(); + int aci0Size = reader.ReadInt32(); + int acidOffset = reader.ReadInt32(); + int acidSize = reader.ReadInt32(); + + Aci0 = new Aci0(stream, aci0Offset); + AciD = new Acid(stream, acidOffset); + } + } +} diff --git a/LibHac/Npdm/ServiceAccessControl.cs b/LibHac/Npdm/ServiceAccessControl.cs new file mode 100644 index 00000000..1a11d225 --- /dev/null +++ b/LibHac/Npdm/ServiceAccessControl.cs @@ -0,0 +1,36 @@ +using System.Collections.Generic; +using System.IO; + +namespace LibHac.Npdm +{ + public class ServiceAccessControl + { + public Dictionary Services { get; } = new Dictionary(); + + public ServiceAccessControl(Stream stream, int offset, int size) + { + stream.Seek(offset, SeekOrigin.Begin); + + var reader = new BinaryReader(stream); + + int bytesRead = 0; + + while (bytesRead != size) + { + byte controlByte = reader.ReadByte(); + + if (controlByte == 0) + { + break; + } + + int length = ((controlByte & 0x07)) + 1; + bool registerAllowed = ((controlByte & 0x80) != 0); + + Services.Add(reader.ReadAscii(length), registerAllowed); + + bytesRead += length + 1; + } + } + } +} diff --git a/LibHac/Npdm/SvcName.cs b/LibHac/Npdm/SvcName.cs new file mode 100644 index 00000000..52d5db76 --- /dev/null +++ b/LibHac/Npdm/SvcName.cs @@ -0,0 +1,134 @@ +namespace LibHac.Npdm +{ + public enum SvcName + { + Reserved0, + SetHeapSize, + SetMemoryPermission, + SetMemoryAttribute, + MapMemory, + UnmapMemory, + QueryMemory, + ExitProcess, + CreateThread, + StartThread, + ExitThread, + SleepThread, + GetThreadPriority, + SetThreadPriority, + GetThreadCoreMask, + SetThreadCoreMask, + GetCurrentProcessorNumber, + SignalEvent, + ClearEvent, + MapSharedMemory, + UnmapSharedMemory, + CreateTransferMemory, + CloseHandle, + ResetSignal, + WaitSynchronization, + CancelSynchronization, + ArbitrateLock, + ArbitrateUnlock, + WaitProcessWideKeyAtomic, + SignalProcessWideKey, + GetSystemTick, + ConnectToNamedPort, + SendSyncRequestLight, + SendSyncRequest, + SendSyncRequestWithUserBuffer, + SendAsyncRequestWithUserBuffer, + GetProcessId, + GetThreadId, + Break, + OutputDebugString, + ReturnFromException, + GetInfo, + FlushEntireDataCache, + FlushDataCache, + MapPhysicalMemory, + UnmapPhysicalMemory, + GetFutureThreadInfo, + GetLastThreadInfo, + GetResourceLimitLimitValue, + GetResourceLimitCurrentValue, + SetThreadActivity, + GetThreadContext3, + WaitForAddress, + SignalToAddress, + Reserved1, + Reserved2, + Reserved3, + Reserved4, + Reserved5, + Reserved6, + DumpInfo, + DumpInfoNew, + Reserved7, + Reserved8, + CreateSession, + AcceptSession, + ReplyAndReceiveLight, + ReplyAndReceive, + ReplyAndReceiveWithUserBuffer, + CreateEvent, + Reserved9, + Reserved10, + MapPhysicalMemoryUnsafe, + UnmapPhysicalMemoryUnsafe, + SetUnsafeLimit, + CreateCodeMemory, + ControlCodeMemory, + SleepSystem, + ReadWriteRegister, + SetProcessActivity, + CreateSharedMemory, + MapTransferMemory, + UnmapTransferMemory, + CreateInterruptEvent, + QueryPhysicalAddress, + QueryIoMapping, + CreateDeviceAddressSpace, + AttachDeviceAddressSpace, + DetachDeviceAddressSpace, + MapDeviceAddressSpaceByForce, + MapDeviceAddressSpaceAligned, + MapDeviceAddressSpace, + UnmapDeviceAddressSpace, + InvalidateProcessDataCache, + StoreProcessDataCache, + FlushProcessDataCache, + DebugActiveProcess, + BreakDebugProcess, + TerminateDebugProcess, + GetDebugEvent, + ContinueDebugEvent, + GetProcessList, + GetThreadList, + GetDebugThreadContext, + SetDebugThreadContext, + QueryDebugProcessMemory, + ReadDebugProcessMemory, + WriteDebugProcessMemory, + SetHardwareBreakPoint, + GetDebugThreadParam, + Reserved11, + GetSystemInfo, + CreatePort, + ManageNamedPort, + ConnectToPort, + SetProcessMemoryPermission, + MapProcessMemory, + UnmapProcessMemory, + QueryProcessMemory, + MapProcessCodeMemory, + UnmapProcessCodeMemory, + CreateProcess, + StartProcess, + TerminateProcess, + GetProcessInfo, + CreateResourceLimit, + SetResourceLimitLimitValue, + CallSecureMonitor + } +} diff --git a/LibHac/SwitchFs.cs b/LibHac/SwitchFs.cs index 196c2379..19d9a4aa 100644 --- a/LibHac/SwitchFs.cs +++ b/LibHac/SwitchFs.cs @@ -189,16 +189,15 @@ namespace LibHac foreach (Title title in Titles.Values.Where(x => x.ControlNca != null)) { var romfs = new Romfs(title.ControlNca.OpenSection(0, false, IntegrityCheckLevel.ErrorOnInvalid)); - byte[] control = romfs.GetFile("/control.nacp"); + Stream control = romfs.OpenFile("/control.nacp"); - var reader = new BinaryReader(new MemoryStream(control)); - title.Control = new Nacp(reader); + title.Control = new Nacp(control); - foreach (NacpLang lang in title.Control.Languages) + foreach (NacpDescription desc in title.Control.Descriptions) { - if (!string.IsNullOrWhiteSpace(lang.Title)) + if (!string.IsNullOrWhiteSpace(desc.Title)) { - title.Name = lang.Title; + title.Name = desc.Title; break; } } diff --git a/LibHac/Util.cs b/LibHac/Util.cs index 2e7c5e2a..dea31b4f 100644 --- a/LibHac/Util.cs +++ b/LibHac/Util.cs @@ -409,6 +409,16 @@ namespace LibHac bool isOutOfRange = startIndex < 0 || startIndex > length || subLength < 0 || startIndex > length - subLength; return !isOutOfRange; } + + public static int Swap32(int value) + { + uint uintVal = (uint)value; + + return (int)(((uintVal >> 24) & 0x000000ff) | + ((uintVal >> 8) & 0x0000ff00) | + ((uintVal << 8) & 0x00ff0000) | + ((uintVal << 24) & 0xff000000)); + } } public class ByteArray128BitComparer : EqualityComparer