Add layouts for some N3DS models

This commit is contained in:
Matt Nadareski
2024-04-23 20:09:39 -04:00
parent 089e13ca03
commit 9bebf95599
23 changed files with 364 additions and 181 deletions

View File

@@ -1,9 +1,12 @@
namespace SabreTools.Models.N3DS
using System.Runtime.InteropServices;
namespace SabreTools.Models.N3DS
{
/// <summary>
/// The kernel capability descriptors are passed to svcCreateProcess.
/// </summary>
/// <see href="https://www.3dbrew.org/wiki/NCCH/Extended_Header#ARM11_Kernel_Capabilities"/>
[StructLayout(LayoutKind.Sequential)]
public sealed class ARM11KernelCapabilities
{
/// <summary>
@@ -34,11 +37,15 @@
/// 13 Process has access to CPU core 2 (New3DS only)
/// </summary>
/// TODO: Make enum for flag values
public uint[]? Descriptors { get; set; }
/// <remarks>28 entries</remarks>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 28)]
public uint[]? Descriptors;
/// <summary>
/// Reserved
/// </summary>
public byte[]? Reserved { get; set; }
/// <remarks>0x10 bytes</remarks>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x10)]
public byte[]? Reserved;
}
}

View File

@@ -1,66 +1,81 @@
namespace SabreTools.Models.N3DS
using System.Runtime.InteropServices;
namespace SabreTools.Models.N3DS
{
/// <see href="https://www.3dbrew.org/wiki/NCCH/Extended_Header#ARM11_Local_System_Capabilities"/>
[StructLayout(LayoutKind.Sequential)]
public sealed class ARM11LocalSystemCapabilities
{
/// <summary>
/// Program ID
/// </summary>
public ulong ProgramID { get; set; }
public ulong ProgramID;
/// <summary>
/// Core version (The Title ID low of the required FIRM)
/// </summary>
public uint CoreVersion { get; set; }
public uint CoreVersion;
/// <summary>
/// Flag1 (implemented starting from 8.0.0-18).
/// </summary>
public ARM11LSCFlag1 Flag1 { get; set; }
[MarshalAs(UnmanagedType.U1)]
public ARM11LSCFlag1 Flag1;
/// <summary>
/// Flag2 (implemented starting from 8.0.0-18).
/// </summary>
public ARM11LSCFlag2 Flag2 { get; set; }
[MarshalAs(UnmanagedType.U1)]
public ARM11LSCFlag2 Flag2;
/// <summary>
/// Flag0
/// </summary>
public ARM11LSCFlag0 Flag0 { get; set; }
[MarshalAs(UnmanagedType.U1)]
public ARM11LSCFlag0 Flag0;
/// <summary>
/// Priority
/// </summary>
public byte Priority { get; set; }
public byte Priority;
/// <summary>
/// Resource limit descriptors. The first byte here controls the maximum allowed CpuTime.
/// </summary>
public ushort[]? ResourceLimitDescriptors { get; set; }
/// <remarks>16 entries</remarks>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
public ushort[]? ResourceLimitDescriptors;
/// <summary>
/// Storage info
/// </summary>
public StorageInfo? StorageInfo { get; set; }
public StorageInfo? StorageInfo;
/// <summary>
/// Service access control
/// </summary>
public ulong[]? ServiceAccessControl { get; set; }
/// <remarks>32 entries</remarks>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)]
public ulong[]? ServiceAccessControl;
/// <summary>
/// Extended service access control, support for this was implemented with 9.3.0-X.
/// </summary>
public ulong[]? ExtendedServiceAccessControl { get; set; }
/// <remarks>2 entries</remarks>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)]
public ulong[]? ExtendedServiceAccessControl;
/// <summary>
/// Reserved
/// </summary>
public byte[]? Reserved { get; set; }
/// <remarks>0x0F bytes</remarks>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x0F)]
public byte[]? Reserved;
/// <summary>
/// Resource limit category. (0 = APPLICATION, 1 = SYS_APPLET, 2 = LIB_APPLET, 3 = OTHER (sysmodules running under the BASE memregion))
/// </summary>
public ResourceLimitCategory ResourceLimitCategory { get; set; }
[MarshalAs(UnmanagedType.U1)]
public ResourceLimitCategory ResourceLimitCategory;
}
}

View File

@@ -1,17 +1,22 @@
namespace SabreTools.Models.N3DS
using System.Runtime.InteropServices;
namespace SabreTools.Models.N3DS
{
/// <see href="https://www.3dbrew.org/wiki/NCCH/Extended_Header#ARM9_Access_Control"/>
[StructLayout(LayoutKind.Sequential)]
public sealed class ARM9AccessControl
{
/// <summary>
/// Descriptors
/// </summary>
public byte[]? Descriptors { get; set; }
/// <remarks>15 bytes</remarks>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 15)]
public byte[]? Descriptors;
/// <summary>
/// ARM9 Descriptor Version. Originally this value had to be ≥ 2.
/// Starting with 9.3.0-X this value has to be either value 2 or value 3.
/// </summary>
public byte DescriptorVersion { get; set; }
public byte DescriptorVersion;
}
}

View File

@@ -1,21 +1,24 @@
namespace SabreTools.Models.N3DS
using System.Runtime.InteropServices;
namespace SabreTools.Models.N3DS
{
/// <see href="https://www.3dbrew.org/wiki/NCCH/Extended_Header#Access_Control_Info"/>
[StructLayout(LayoutKind.Sequential)]
public sealed class AccessControlInfo
{
/// <summary>
/// ARM11 local system capabilities
/// </summary>
public ARM11LocalSystemCapabilities? ARM11LocalSystemCapabilities { get; set; }
public ARM11LocalSystemCapabilities? ARM11LocalSystemCapabilities;
/// <summary>
/// ARM11 kernel capabilities
/// </summary>
public ARM11KernelCapabilities? ARM11KernelCapabilities { get; set; }
public ARM11KernelCapabilities? ARM11KernelCapabilities;
/// <summary>
/// ARM9 access control
/// </summary>
public ARM9AccessControl? ARM9AccessControl { get; set; }
public ARM9AccessControl? ARM9AccessControl;
}
}

View File

@@ -1,51 +1,56 @@
using System.Runtime.InteropServices;
namespace SabreTools.Models.N3DS
{
/// <see href="https://www.3dbrew.org/wiki/CIA#CIA_Header"/>
[StructLayout(LayoutKind.Sequential)]
public sealed class CIAHeader
{
/// <summary>
/// Archive header size, usually 0x2020 bytes
/// </summary>
public uint HeaderSize { get; set; }
public uint HeaderSize;
/// <summary>
/// Type
/// </summary>
public ushort Type { get; set; }
public ushort Type;
/// <summary>
/// Version
/// </summary>
public ushort Version { get; set; }
public ushort Version;
/// <summary>
/// Certificate chain size
/// </summary>
public uint CertificateChainSize { get; set; }
public uint CertificateChainSize;
/// <summary>
/// Ticket size
/// </summary>
public uint TicketSize { get; set; }
public uint TicketSize;
/// <summary>
/// TMD file size
/// </summary>
public uint TMDFileSize { get; set; }
public uint TMDFileSize;
/// <summary>
/// Meta size (0 if no Meta data is present)
/// </summary>
public uint MetaSize { get; set; }
public uint MetaSize;
/// <summary>
/// Content size
/// </summary>
public ulong ContentSize { get; set; }
public ulong ContentSize;
/// <summary>
/// Content Index
/// </summary>
public byte[]? ContentIndex { get; set; }
/// <remarks>0x2000 bytes</remarks>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x2000)]
public byte[]? ContentIndex;
}
}

View File

@@ -1,61 +1,74 @@
using System.Runtime.InteropServices;
namespace SabreTools.Models.N3DS
{
/// <see href="https://www.3dbrew.org/wiki/NCSD#Card_Info_Header"/>
[StructLayout(LayoutKind.Sequential)]
public sealed class CardInfoHeader
{
/// <summary>
/// CARD2: Writable Address In Media Units (For 'On-Chip' Savedata). CARD1: Always 0xFFFFFFFF.
/// </summary>
public uint WritableAddressMediaUnits { get; set; }
public uint WritableAddressMediaUnits;
/// <summary>
/// Card Info Bitmask
/// </summary>
public uint CardInfoBitmask { get; set; }
public uint CardInfoBitmask;
/// <summary>
/// Reserved
/// </summary>
public byte[]? Reserved1 { get; set; }
/// <remarks>0xF8 bytes</remarks>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 0xF8)]
public byte[]? Reserved1;
/// <summary>
/// Filled size of cartridge
/// </summary>
public uint FilledSize { get; set; }
public uint FilledSize;
/// <summary>
/// Reserved
/// </summary>
public byte[]? Reserved2 { get; set; }
/// <remarks>0x0C bytes</remarks>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x0C)]
public byte[]? Reserved2;
/// <summary>
/// Title version
/// </summary>
public ushort TitleVersion { get; set; }
public ushort TitleVersion;
/// <summary>
/// Card revision
/// </summary>
public ushort CardRevision { get; set; }
public ushort CardRevision;
/// <summary>
/// Reserved
/// </summary>
public byte[]? Reserved3 { get; set; }
/// <remarks>0x0C bytes</remarks>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x0C)]
public byte[]? Reserved3;
/// <summary>
/// Title ID of CVer in included update partition
/// </summary>
public byte[]? CVerTitleID { get; set; }
/// <remarks>8 bytes</remarks>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
public byte[]? CVerTitleID;
/// <summary>
/// Version number of CVer in included update partition
/// </summary>
public ushort CVerVersionNumber { get; set; }
public ushort CVerVersionNumber;
/// <summary>
/// Reserved
/// </summary>
public byte[]? Reserved4 { get; set; }
/// <remarks>0xCD6 bytes</remarks>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 0xCD6)]
public byte[]? Reserved4;
}
}

View File

@@ -1,21 +1,24 @@
namespace SabreTools.Models.N3DS
using System.Runtime.InteropServices;
namespace SabreTools.Models.N3DS
{
/// <see href="https://www.3dbrew.org/wiki/NCCH/Extended_Header#Code_Set_Info"/>
[StructLayout(LayoutKind.Sequential)]
public sealed class CodeSetInfo
{
/// <summary>
/// Address
/// </summary>
public uint Address { get; set; }
public uint Address;
/// <summary>
/// Physical region size (in page-multiples)
/// </summary>
public uint PhysicalRegionSizeInPages { get; set; }
public uint PhysicalRegionSizeInPages;
/// <summary>
/// Size (in bytes)
/// </summary>
public uint SizeInBytes { get; set; }
public uint SizeInBytes;
}
}

View File

@@ -1,3 +1,5 @@
using System.Runtime.InteropServices;
namespace SabreTools.Models.N3DS
{
/// <summary>
@@ -5,12 +7,13 @@ namespace SabreTools.Models.N3DS
/// (Determined by "Content Count" in the TMD Header).
/// </summary>
/// <see href="https://www.3dbrew.org/wiki/Title_metadata#Content_chunk_records"/>
[StructLayout(LayoutKind.Sequential)]
public sealed class ContentChunkRecord
{
/// <summary>
/// Content id
/// </summary>
public uint ContentId { get; set; }
public uint ContentId;
/// <summary>
/// Content index
@@ -18,21 +21,23 @@ namespace SabreTools.Models.N3DS
/// <remarks>
/// This does not apply to DLC.
/// </remarks>
public ContentIndex ContentIndex { get; set; }
public ContentIndex ContentIndex;
/// <summary>
/// Content type
/// </summary>
public TMDContentType ContentType { get; set; }
public TMDContentType ContentType;
/// <summary>
/// Content size
/// </summary>
public ulong ContentSize { get; set; }
public ulong ContentSize;
/// <summary>
/// SHA-256 hash
/// </summary>
public byte[]? SHA256Hash { get; set; }
/// <remarks>0x20 bytes</remarks>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x20)]
public byte[]? SHA256Hash;
}
}

View File

@@ -1,24 +1,29 @@
using System.Runtime.InteropServices;
namespace SabreTools.Models.N3DS
{
/// <summary>
/// There are 64 of these records, usually only the first is used.
/// </summary>
/// <see href="https://www.3dbrew.org/wiki/Title_metadata#Content_Info_Records"/>
[StructLayout(LayoutKind.Sequential)]
public sealed class ContentInfoRecord
{
/// <summary>
/// Content index offset
/// </summary>
public ushort ContentIndexOffset { get; set; }
public ushort ContentIndexOffset;
/// <summary>
/// Content command count [k]
/// </summary>
public ushort ContentCommandCount { get; set; }
public ushort ContentCommandCount;
/// <summary>
/// SHA-256 hash of the next k content records that have not been hashed yet
/// </summary>
public byte[]? UnhashedContentRecordsSHA256Hash { get; set; }
/// <remarks>0x20 bytes</remarks>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x20)]
public byte[]? UnhashedContentRecordsSHA256Hash;
}
}

View File

@@ -1,31 +1,40 @@
using System.Runtime.InteropServices;
namespace SabreTools.Models.N3DS
{
/// <see href="https://www.3dbrew.org/wiki/NCSD#Development_Card_Info_Header_Extension"/>
[StructLayout(LayoutKind.Sequential)]
public sealed class DevelopmentCardInfoHeader
{
/// <summary>
/// InitialData
/// </summary>
public InitialData? InitialData { get; set; }
public InitialData? InitialData;
/// <summary>
/// CardDeviceReserved1
/// </summary>
public byte[]? CardDeviceReserved1 { get; set; }
/// <remarks>0x200 bytes</remarks>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x200)]
public byte[]? CardDeviceReserved1;
/// <summary>
/// TitleKey
/// </summary>
public byte[]? TitleKey { get; set; }
/// <remarks>0x10 bytes</remarks>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x10)]
public byte[]? TitleKey;
/// <summary>
/// CardDeviceReserved2
/// </summary>
public byte[]? CardDeviceReserved2 { get; set; }
/// <remarks>0x1BF0 bytes</remarks>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x1BF0)]
public byte[]? CardDeviceReserved2;
/// <summary>
/// TestData
/// </summary>
public TestData? TestData { get; set; }
public TestData? TestData;
}
}

View File

@@ -1,4 +1,6 @@
namespace SabreTools.Models.N3DS
using System.Runtime.InteropServices;
namespace SabreTools.Models.N3DS
{
/// <summary>
/// There are a maximum of 10 file headers in the ExeFS format. (This maximum
@@ -8,26 +10,24 @@
/// the currently define size of 0x200 bytes.)
/// </summary>
/// <see href="https://www.3dbrew.org/wiki/ExeFS#File_headers"/>
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public sealed class ExeFSFileHeader
{
/// <summary>
/// File name
/// </summary>
public string? FileName { get; set; }
/// <remarks>8 bytes</remarks>
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 8)]
public string? FileName;
/// <summary>
/// File offset
/// </summary>
public uint FileOffset { get; set; }
public uint FileOffset;
/// <summary>
/// File size
/// </summary>
public uint FileSize { get; set; }
/// <summary>
/// SHA256 hash calculated over the entire file contents
/// </summary>
public byte[]? FileHash { get; set; }
public uint FileSize;
}
}

View File

@@ -21,6 +21,7 @@
/// <summary>
/// Reserved
/// </summary>
/// <remarks>0x20 bytes</remarks>
public byte[]? Reserved { get; set; }
/// <summary>

View File

@@ -1,36 +1,49 @@
using System.Runtime.InteropServices;
namespace SabreTools.Models.N3DS
{
/// <see href="https://www.3dbrew.org/wiki/NCSD#InitialData"/>
[StructLayout(LayoutKind.Sequential)]
public sealed class InitialData
{
/// <summary>
/// Card seed keyY (first u64 is Media ID (same as first NCCH partitionId))
/// </summary>
public byte[]? CardSeedKeyY { get; set; }
/// <remarks>0x10 bytes</remarks>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x10)]
public byte[]? CardSeedKeyY;
/// <summary>
/// Encrypted card seed (AES-CCM, keyslot 0x3B for retail cards, see CTRCARD_SECSEED)
/// </summary>
public byte[]? EncryptedCardSeed { get; set; }
/// <remarks>0x10 bytes</remarks>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x10)]
public byte[]? EncryptedCardSeed;
/// <summary>
/// Card seed AES-MAC
/// </summary>
public byte[]? CardSeedAESMAC { get; set; }
/// <remarks>0x10 bytes</remarks>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x10)]
public byte[]? CardSeedAESMAC;
/// <summary>
/// Card seed nonce
/// </summary>
public byte[]? CardSeedNonce { get; set; }
/// <remarks>0x0C bytes</remarks>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x0C)]
public byte[]? CardSeedNonce;
/// <summary>
/// Reserved3
/// </summary>
public byte[]? Reserved { get; set; }
/// <remarks>0xC4 bytes</remarks>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 0xC4)]
public byte[]? Reserved;
/// <summary>
/// Copy of first NCCH header (excluding RSA signature)
/// </summary>
public NCCHHeader? BackupHeader { get; set; }
public NCCHHeader? BackupHeader;
}
}

View File

@@ -1,32 +1,43 @@
using System.Runtime.InteropServices;
namespace SabreTools.Models.N3DS
{
/// <see href="https://www.3dbrew.org/wiki/CIA#Meta"/>
[StructLayout(LayoutKind.Sequential)]
public sealed class MetaData
{
/// <summary>
/// Title ID dependency list - Taken from the application's ExHeader
/// </summary>
/// TODO: Determine numeric format of each entry
public byte[]? TitleIDDependencyList { get; set; }
/// <remarks>0x180 bytes</remarks>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x180)]
public byte[]? TitleIDDependencyList;
/// <summary>
/// Reserved
/// </summary>
public byte[]? Reserved1 { get; set; }
/// <remarks>0x180 bytes</remarks>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x180)]
public byte[]? Reserved1;
/// <summary>
/// Core Version
/// </summary>
public uint CoreVersion { get; set; }
public uint CoreVersion;
/// <summary>
/// Reserved
/// </summary>
public byte[]? Reserved2 { get; set; }
/// <remarks>0xFC bytes</remarks>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 0xFC)]
public byte[]? Reserved2;
/// <summary>
/// Icon Data(.ICN) - Taken from the application's ExeFS
/// </summary>
public byte[]? IconData { get; set; }
/// <remarks>0x36C0 bytes</remarks>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x36C0)]
public byte[]? IconData;
}
}

View File

@@ -1,36 +1,43 @@
namespace SabreTools.Models.N3DS
using System.Runtime.InteropServices;
namespace SabreTools.Models.N3DS
{
/// <summary>
/// The exheader has two sections:
/// - The actual exheader data, containing System Control Info (SCI) and Access Control Info (ACI) { get; set; }
/// - The actual exheader data, containing System Control Info (SCI) and Access Control Info (ACI);
/// - A signed copy of NCCH HDR public key, and exheader ACI. This version of the ACI is used as limitation to the actual ACI.
/// </summary>
/// <see href="https://www.3dbrew.org/wiki/NCCH/Extended_Header"/>
[StructLayout(LayoutKind.Sequential)]
public sealed class NCCHExtendedHeader
{
/// <summary>
/// SCI
/// </summary>
public SystemControlInfo? SCI { get; set; }
public SystemControlInfo? SCI;
/// <summary>
/// ACI
/// </summary>
public AccessControlInfo? ACI { get; set; }
public AccessControlInfo? ACI;
/// <summary>
/// AccessDesc signature (RSA-2048-SHA256)
/// </summary>
public byte[]? AccessDescSignature { get; set; }
/// <remarks>0x100 bytes</remarks>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x100)]
public byte[]? AccessDescSignature;
/// <summary>
/// NCCH HDR RSA-2048 public key
/// </summary>
public byte[]? NCCHHDRPublicKey { get; set; }
/// <remarks>0x100 bytes</remarks>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x100)]
public byte[]? NCCHHDRPublicKey;
/// <summary>
/// ACI (for limitation of first ACI)
/// </summary>
public AccessControlInfo? ACIForLimitations { get; set; }
public AccessControlInfo? ACIForLimitations;
}
}

View File

@@ -1,37 +1,44 @@
namespace SabreTools.Models.N3DS
using System.Runtime.InteropServices;
namespace SabreTools.Models.N3DS
{
/// <see href="https://www.3dbrew.org/wiki/NCCH#NCCH_Header"/>
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public sealed class NCCHHeader
{
/// <summary>
/// RSA-2048 signature of the NCCH header, using SHA-256.
/// </summary>
public byte[]? RSA2048Signature { get; set; }
/// <remarks>0x100 bytes</remarks>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x100)]
public byte[]? RSA2048Signature;
/// <summary>
/// Magic ID, always 'NCCH'
/// </summary>
public string? MagicID { get; set; }
/// <remarks>4 bytes</remarks>
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 4)]
public string? MagicID;
/// <summary>
/// Content size, in media units (1 media unit = 0x200 bytes)
/// </summary>
public uint ContentSizeInMediaUnits { get; set; }
public uint ContentSizeInMediaUnits;
/// <summary>
/// Partition ID
/// </summary>
public ulong PartitionId { get; set; }
public ulong PartitionId;
/// <summary>
/// Maker code
/// </summary>
public ushort MakerCode { get; set; }
public ushort MakerCode;
/// <summary>
/// Version
/// </summary>
public ushort Version { get; set; }
public ushort Version;
/// <summary>
/// When ncchflag[7] = 0x20 starting with FIRM 9.6.0-X, this is compared with the first output u32 from a
@@ -39,118 +46,132 @@
/// [programID from NCCH + 0x118]. This hash is only used for verification of the content lock seed, and
/// is not the actual keyY.
/// </summary>
public uint VerificationHash { get; set; }
public uint VerificationHash;
/// <summary>
/// Program ID
/// </summary>
public byte[]? ProgramId { get; set; }
/// <remarks>8 bytes</remarks>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
public byte[]? ProgramId;
/// <summary>
/// Reserved
/// </summary>
public byte[]? Reserved1 { get; set; }
/// <remarks>0x10 bytes</remarks>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x10)]
public byte[]? Reserved1;
/// <summary>
/// Logo Region SHA-256 hash. (For applications built with SDK 5+) (Supported from firmware: 5.0.0-11)
/// </summary>
public byte[]? LogoRegionHash { get; set; }
/// <remarks>0x20 bytes</remarks>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x20)]
public byte[]? LogoRegionHash;
/// <summary>
/// Product code
/// </summary>
public string? ProductCode { get; set; }
/// <remarks>0x10 bytes</remarks>
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 0x10)]
public string? ProductCode;
/// <summary>
/// Extended header SHA-256 hash (SHA256 of 2x Alignment Size, beginning at 0x0 of ExHeader)
/// </summary>
public byte[]? ExtendedHeaderHash { get; set; }
/// <remarks>0x20 bytes</remarks>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x20)]
public byte[]? ExtendedHeaderHash;
/// <summary>
/// Extended header size, in bytes
/// </summary>
public uint ExtendedHeaderSizeInBytes { get; set; }
public uint ExtendedHeaderSizeInBytes;
/// <summary>
/// Reserved
/// </summary>
public byte[]? Reserved2 { get; set; }
public uint Reserved2;
/// <summary>
/// Flags
/// </summary>
public NCCHHeaderFlags? Flags { get; set; }
public NCCHHeaderFlags? Flags;
/// <summary>
/// Plain region offset, in media units
/// </summary>
public uint PlainRegionOffsetInMediaUnits { get; set; }
public uint PlainRegionOffsetInMediaUnits;
/// <summary>
/// Plain region size, in media units
/// </summary>
public uint PlainRegionSizeInMediaUnits { get; set; }
public uint PlainRegionSizeInMediaUnits;
/// <summary>
/// Logo Region offset, in media units (For applications built with SDK 5+) (Supported from firmware: 5.0.0-11)
/// </summary>
public uint LogoRegionOffsetInMediaUnits { get; set; }
public uint LogoRegionOffsetInMediaUnits;
/// <summary>
/// Logo Region size, in media units (For applications built with SDK 5+) (Supported from firmware: 5.0.0-11)
/// </summary>
public uint LogoRegionSizeInMediaUnits { get; set; }
public uint LogoRegionSizeInMediaUnits;
/// <summary>
/// ExeFS offset, in media units
/// </summary>
public uint ExeFSOffsetInMediaUnits { get; set; }
public uint ExeFSOffsetInMediaUnits;
/// <summary>
/// ExeFS size, in media units
/// </summary>
public uint ExeFSSizeInMediaUnits { get; set; }
public uint ExeFSSizeInMediaUnits;
/// <summary>
/// ExeFS hash region size, in media units
/// </summary>
public uint ExeFSHashRegionSizeInMediaUnits { get; set; }
public uint ExeFSHashRegionSizeInMediaUnits;
/// <summary>
/// Reserved
/// </summary>
public byte[]? Reserved3 { get; set; }
public uint Reserved3;
/// <summary>
/// RomFS offset, in media units
/// </summary>
public uint RomFSOffsetInMediaUnits { get; set; }
public uint RomFSOffsetInMediaUnits;
/// <summary>
/// RomFS size, in media units
/// </summary>
public uint RomFSSizeInMediaUnits { get; set; }
public uint RomFSSizeInMediaUnits;
/// <summary>
/// RomFS hash region size, in media units
/// </summary>
public uint RomFSHashRegionSizeInMediaUnits { get; set; }
public uint RomFSHashRegionSizeInMediaUnits;
/// <summary>
/// Reserved
/// </summary>
public byte[]? Reserved4 { get; set; }
public uint Reserved4;
/// <summary>
/// ExeFS superblock SHA-256 hash - (SHA-256 hash, starting at 0x0 of the ExeFS over the number of
/// media units specified in the ExeFS hash region size)
/// </summary>
public byte[]? ExeFSSuperblockHash { get; set; }
/// <remarks>0x20 bytes</remarks>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x20)]
public byte[]? ExeFSSuperblockHash;
/// <summary>
/// RomFS superblock SHA-256 hash - (SHA-256 hash, starting at 0x0 of the RomFS over the number
/// of media units specified in the RomFS hash region size)
/// </summary>
public byte[]? RomFSSuperblockHash { get; set; }
/// <remarks>0x20 bytes</remarks>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x20)]
public byte[]? RomFSSuperblockHash;
}
}

View File

@@ -1,49 +1,56 @@
namespace SabreTools.Models.N3DS
using System.Runtime.InteropServices;
namespace SabreTools.Models.N3DS
{
/// <see href="https://www.3dbrew.org/wiki/NCCH#NCCH_Flags"/>
[StructLayout(LayoutKind.Sequential)]
public sealed class NCCHHeaderFlags
{
/// <summary>
/// Reserved
/// </summary>
public byte Reserved0 { get; set; }
public byte Reserved0;
/// <summary>
/// Reserved
/// </summary>
public byte Reserved1 { get; set; }
public byte Reserved1;
/// <summary>
/// Reserved
/// </summary>
public byte Reserved2 { get; set; }
public byte Reserved2;
/// <summary>
/// Crypto Method: When this is non-zero, a NCCH crypto method using two keyslots is used.
/// </summary>
public CryptoMethod CryptoMethod { get; set; }
[MarshalAs(UnmanagedType.U1)]
public CryptoMethod CryptoMethod;
/// <summary>
/// Content Platform: 1 = CTR, 2 = snake (New 3DS).
/// </summary>
public ContentPlatform ContentPlatform { get; set; }
[MarshalAs(UnmanagedType.U1)]
public ContentPlatform ContentPlatform;
/// <summary>
/// Content Type Bit-masks: Data = 0x1, Executable = 0x2, SystemUpdate = 0x4, Manual = 0x8,
/// Child = (0x4|0x8), Trial = 0x10. When 'Data' is set, but not 'Executable', NCCH is a CFA.
/// Otherwise when 'Executable' is set, NCCH is a CXI.
/// </summary>
public ContentType MediaPlatformIndex { get; set; }
[MarshalAs(UnmanagedType.U1)]
public ContentType MediaPlatformIndex;
/// <summary>
/// Content Unit Size i.e. u32 ContentUnitSize = 0x200*2^flags[6] { get; set; }
/// Content Unit Size i.e. u32 ContentUnitSize = 0x200*2^flags[6];
/// </summary>
public byte ContentUnitSize { get; set; }
public byte ContentUnitSize;
/// <summary>
/// Bit-masks: FixedCryptoKey = 0x1, NoMountRomFs = 0x2, NoCrypto = 0x4, using a new keyY
/// generator = 0x20(starting with FIRM 9.6.0-X).
/// </summary>
public BitMasks BitMasks { get; set; }
[MarshalAs(UnmanagedType.U1)]
public BitMasks BitMasks;
}
}

View File

@@ -1,19 +1,22 @@
namespace SabreTools.Models.N3DS
using System.Runtime.InteropServices;
namespace SabreTools.Models.N3DS
{
/// <summary>
/// Offset and Length partition table, in media units
/// </summary>
/// <see href="https://www.3dbrew.org/wiki/NCSD#NCSD_header"/>
[StructLayout(LayoutKind.Sequential)]
public sealed class PartitionTableEntry
{
/// <summary>
/// Offset
/// </summary>
public uint Offset { get; set; }
public uint Offset;
/// <summary>
/// Length
/// </summary>
public uint Length { get; set; }
public uint Length;
}
}

View File

@@ -1,4 +1,6 @@
namespace SabreTools.Models.N3DS
using System.Runtime.InteropServices;
namespace SabreTools.Models.N3DS
{
/// <summary>
/// RomFS (or Read-Only Filesystem) is part of the NCCH format, and is
@@ -6,91 +8,94 @@
/// </summary>
/// <see href="https://www.3dbrew.org/wiki/RomFS"/>
/// TODO: Implement the other parts of the RomFS tree structure
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public sealed class RomFSHeader
{
/// <summary>
/// Magic "IVFC"
/// </summary>
public string? MagicString { get; set; }
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 4)]
public string? MagicString;
/// <summary>
/// Magic number 0x10000
/// </summary>
public uint MagicNumber { get; set; }
public uint MagicNumber;
/// <summary>
/// Master hash size
/// </summary>
public uint MasterHashSize { get; set; }
public uint MasterHashSize;
/// <summary>
/// Level 1 logical offset
/// </summary>
public ulong Level1LogicalOffset { get; set; }
public ulong Level1LogicalOffset;
/// <summary>
/// Level 1 hashdata size
/// </summary>
public ulong Level1HashdataSize { get; set; }
public ulong Level1HashdataSize;
/// <summary>
/// Level 1 block size, in log2
/// </summary>
public uint Level1BlockSizeLog2 { get; set; }
public uint Level1BlockSizeLog2;
/// <summary>
/// Reserved
/// </summary>
public byte[]? Reserved1 { get; set; }
public uint Reserved1;
/// <summary>
/// Level 2 logical offset
/// </summary>
public ulong Level2LogicalOffset { get; set; }
public ulong Level2LogicalOffset;
/// <summary>
/// Level 2 hashdata size
/// </summary>
public ulong Level2HashdataSize { get; set; }
public ulong Level2HashdataSize;
/// <summary>
/// Level 2 block size, in log2
/// </summary>
public uint Level2BlockSizeLog2 { get; set; }
public uint Level2BlockSizeLog2;
/// <summary>
/// Reserved
/// </summary>
public byte[]? Reserved2 { get; set; }
public uint Reserved2;
/// <summary>
/// Level 3 logical offset
/// </summary>
public ulong Level3LogicalOffset { get; set; }
public ulong Level3LogicalOffset;
/// <summary>
/// Level 3 hashdata size
/// </summary>
public ulong Level3HashdataSize { get; set; }
public ulong Level3HashdataSize;
/// <summary>
/// Level 3 block size, in log2
/// </summary>
public uint Level3BlockSizeLog2 { get; set; }
public uint Level3BlockSizeLog2;
/// <summary>
/// Reserved
/// </summary>
public byte[]? Reserved3 { get; set; }
public uint Reserved3;
/// <summary>
/// Reserved
/// </summary>
public byte[]? Reserved4 { get; set; }
public uint Reserved4;
/// <summary>
/// Optional info size.
/// </summary>
public uint OptionalInfoSize { get; set; }
public uint OptionalInfoSize;
}
}

View File

@@ -1,36 +1,46 @@
namespace SabreTools.Models.N3DS
using System.Runtime.InteropServices;
namespace SabreTools.Models.N3DS
{
/// <summary>
/// Used in FSReg:Register.
/// </summary>
/// <see href="https://www.3dbrew.org/wiki/NCCH/Extended_Header#Storage_Info"/>
[StructLayout(LayoutKind.Sequential)]
public sealed class StorageInfo
{
/// <summary>
/// Extdata ID
/// </summary>
public ulong ExtdataID { get; set; }
public ulong ExtdataID;
/// <summary>
/// System savedata IDs
/// </summary>
public byte[]? SystemSavedataIDs { get; set; }
/// <remarks>8 bytes</remarks>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
public byte[]? SystemSavedataIDs;
/// <summary>
/// Storage accessible unique IDs
/// </summary>
public byte[]? StorageAccessibleUniqueIDs { get; set; }
/// <remarks>8 bytes</remarks>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
public byte[]? StorageAccessibleUniqueIDs;
/// <summary>
/// Filesystem access info
/// </summary>
/// TODO: Create enum for the flag values
/// TODO: Combine with "other attributes"
public byte[]? FileSystemAccessInfo { get; set; }
/// <remarks>7 bytes</remarks>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 7)]
public byte[]? FileSystemAccessInfo;
/// <summary>
/// Other attributes
/// </summary>
public StorageInfoOtherAttributes OtherAttributes { get; set; }
[MarshalAs(UnmanagedType.U1)]
public StorageInfoOtherAttributes OtherAttributes;
}
}

View File

@@ -1,66 +1,75 @@
namespace SabreTools.Models.N3DS
using System.Runtime.InteropServices;
namespace SabreTools.Models.N3DS
{
/// <see href="https://www.3dbrew.org/wiki/NCCH/Extended_Header#System_Control_Info"/>
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public sealed class SystemControlInfo
{
/// <summary>
/// Application title (default is "CtrApp")
/// </summary>
public string? ApplicationTitle { get; set; }
/// <remarks>8 bytes</remarks>
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 8)]
public string? ApplicationTitle;
/// <summary>
/// Reserved
/// </summary>
public byte[]? Reserved1 { get; set; }
/// <remarks>5 bytes</remarks>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 5)]
public byte[]? Reserved1;
/// <summary>
/// Flag (bit 0: CompressExefsCode, bit 1: SDApplication)
/// </summary>
public byte Flag { get; set; }
public byte Flag;
/// <summary>
/// Remaster version
/// </summary>
public ushort RemasterVersion { get; set; }
public ushort RemasterVersion;
/// <summary>
/// Text code set info
/// </summary>
public CodeSetInfo? TextCodeSetInfo { get; set; }
public CodeSetInfo? TextCodeSetInfo;
/// <summary>
/// Stack size
/// </summary>
public uint StackSize { get; set; }
public uint StackSize;
/// <summary>
/// Read-only code set info
/// </summary>
public CodeSetInfo? ReadOnlyCodeSetInfo { get; set; }
public CodeSetInfo? ReadOnlyCodeSetInfo;
/// <summary>
/// Reserved
/// </summary>
public byte[]? Reserved2 { get; set; }
public uint Reserved2;
/// <summary>
/// Data code set info
/// </summary>
public CodeSetInfo? DataCodeSetInfo { get; set; }
public CodeSetInfo? DataCodeSetInfo;
/// <summary>
/// BSS size
/// </summary>
public uint BSSSize { get; set; }
public uint BSSSize;
/// <summary>
/// Dependency module (program ID) list
/// </summary>
public ulong[]? DependencyModuleList { get; set; }
/// <remarks>48 entries</remarks>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 48)]
public ulong[]? DependencyModuleList;
/// <summary>
/// SystemInfo
/// </summary>
public SystemInfo? SystemInfo { get; set; }
public SystemInfo? SystemInfo;
}
}

View File

@@ -1,21 +1,26 @@
namespace SabreTools.Models.N3DS
using System.Runtime.InteropServices;
namespace SabreTools.Models.N3DS
{
/// <see href="https://www.3dbrew.org/wiki/NCCH/Extended_Header#System_Info"/>
[StructLayout(LayoutKind.Sequential)]
public sealed class SystemInfo
{
/// <summary>
/// SaveData Size
/// </summary>
public ulong SaveDataSize { get; set; }
public ulong SaveDataSize;
/// <summary>
/// Jump ID
/// </summary>
public ulong JumpID { get; set; }
public ulong JumpID;
/// <summary>
/// Reserved
/// </summary>
public byte[]? Reserved { get; set; }
/// <remarks>0x30 bytes</remarks>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x30)]
public byte[]? Reserved;
}
}

View File

@@ -1,59 +1,80 @@
using System.Runtime.InteropServices;
namespace SabreTools.Models.N3DS
{
/// <summary>
/// The test data is the same one encountered in development DS/DSi cartridges.
/// </summary>
/// <see href="https://www.3dbrew.org/wiki/NCSD#TestData"/>
[StructLayout(LayoutKind.Sequential)]
public sealed class TestData
{
/// <summary>
/// The bytes FF 00 FF 00 AA 55 AA 55.
/// </summary>
public byte[]? Signature { get; set; }
/// <remarks>8 bytes</remarks>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
public byte[]? Signature;
/// <summary>
/// An ascending byte sequence equal to the offset mod 256 (08 09 0A ... FE FF 00 01 ... FF).
/// </summary>
public byte[]? AscendingByteSequence { get; set; }
/// <remarks>0x1F8 bytes</remarks>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x1F8)]
public byte[]? AscendingByteSequence;
/// <summary>
/// A descending byte sequence equal to 255 minus the offset mod 256 (FF FE FD ... 00 FF DE ... 00).
/// </summary>
public byte[]? DescendingByteSequence { get; set; }
/// <remarks>0x200 bytes</remarks>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x200)]
public byte[]? DescendingByteSequence;
/// <summary>
/// Filled with 00 (0b00000000) bytes.
/// </summary>
public byte[]? Filled00 { get; set; }
/// <remarks>0x200 bytes</remarks>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x200)]
public byte[]? Filled00;
/// <summary>
/// Filled with FF (0b11111111) bytes.
/// </summary>
public byte[]? FilledFF { get; set; }
/// <remarks>0x200 bytes</remarks>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x200)]
public byte[]? FilledFF;
/// <summary>
/// Filled with 0F (0b00001111) bytes.
/// </summary>
public byte[]? Filled0F { get; set; }
/// <remarks>0x200 bytes</remarks>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x200)]
public byte[]? Filled0F;
/// <summary>
/// Filled with F0 (0b11110000) bytes.
/// </summary>
public byte[]? FilledF0 { get; set; }
/// <remarks>0x200 bytes</remarks>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x200)]
public byte[]? FilledF0;
/// <summary>
/// Filled with 55 (0b01010101) bytes.
/// </summary>
public byte[]? Filled55 { get; set; }
/// <remarks>0x200 bytes</remarks>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x200)]
public byte[]? Filled55;
/// <summary>
/// Filled with AA (0b10101010) bytes.
/// </summary>
public byte[]? FilledAA { get; set; }
/// <remarks>0x1FF bytes</remarks>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x1FF)]
public byte[]? FilledAA;
/// <summary>
/// The final byte is 00 (0b00000000).
/// </summary>
public byte FinalByte { get; set; }
public byte FinalByte;
}
}