diff --git a/N3DS/ARM11KernelCapabilities.cs b/N3DS/ARM11KernelCapabilities.cs
index 75fbf92..6673a1a 100644
--- a/N3DS/ARM11KernelCapabilities.cs
+++ b/N3DS/ARM11KernelCapabilities.cs
@@ -1,9 +1,12 @@
-namespace SabreTools.Models.N3DS
+using System.Runtime.InteropServices;
+
+namespace SabreTools.Models.N3DS
{
///
/// The kernel capability descriptors are passed to svcCreateProcess.
///
///
+ [StructLayout(LayoutKind.Sequential)]
public sealed class ARM11KernelCapabilities
{
///
@@ -34,11 +37,15 @@
/// 13 Process has access to CPU core 2 (New3DS only)
///
/// TODO: Make enum for flag values
- public uint[]? Descriptors { get; set; }
+ /// 28 entries
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = 28)]
+ public uint[]? Descriptors;
///
/// Reserved
///
- public byte[]? Reserved { get; set; }
+ /// 0x10 bytes
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x10)]
+ public byte[]? Reserved;
}
}
diff --git a/N3DS/ARM11LocalSystemCapabilities.cs b/N3DS/ARM11LocalSystemCapabilities.cs
index 52ff297..270f04b 100644
--- a/N3DS/ARM11LocalSystemCapabilities.cs
+++ b/N3DS/ARM11LocalSystemCapabilities.cs
@@ -1,66 +1,81 @@
-namespace SabreTools.Models.N3DS
+using System.Runtime.InteropServices;
+
+namespace SabreTools.Models.N3DS
{
///
+ [StructLayout(LayoutKind.Sequential)]
public sealed class ARM11LocalSystemCapabilities
{
///
/// Program ID
///
- public ulong ProgramID { get; set; }
+ public ulong ProgramID;
///
/// Core version (The Title ID low of the required FIRM)
///
- public uint CoreVersion { get; set; }
+ public uint CoreVersion;
///
/// Flag1 (implemented starting from 8.0.0-18).
///
- public ARM11LSCFlag1 Flag1 { get; set; }
+ [MarshalAs(UnmanagedType.U1)]
+ public ARM11LSCFlag1 Flag1;
///
/// Flag2 (implemented starting from 8.0.0-18).
///
- public ARM11LSCFlag2 Flag2 { get; set; }
+ [MarshalAs(UnmanagedType.U1)]
+ public ARM11LSCFlag2 Flag2;
///
/// Flag0
///
- public ARM11LSCFlag0 Flag0 { get; set; }
+ [MarshalAs(UnmanagedType.U1)]
+ public ARM11LSCFlag0 Flag0;
///
/// Priority
///
- public byte Priority { get; set; }
+ public byte Priority;
///
/// Resource limit descriptors. The first byte here controls the maximum allowed CpuTime.
///
- public ushort[]? ResourceLimitDescriptors { get; set; }
+ /// 16 entries
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
+ public ushort[]? ResourceLimitDescriptors;
///
/// Storage info
///
- public StorageInfo? StorageInfo { get; set; }
+ public StorageInfo? StorageInfo;
///
/// Service access control
///
- public ulong[]? ServiceAccessControl { get; set; }
+ /// 32 entries
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)]
+ public ulong[]? ServiceAccessControl;
///
/// Extended service access control, support for this was implemented with 9.3.0-X.
///
- public ulong[]? ExtendedServiceAccessControl { get; set; }
+ /// 2 entries
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)]
+ public ulong[]? ExtendedServiceAccessControl;
///
/// Reserved
///
- public byte[]? Reserved { get; set; }
+ /// 0x0F bytes
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x0F)]
+ public byte[]? Reserved;
///
/// Resource limit category. (0 = APPLICATION, 1 = SYS_APPLET, 2 = LIB_APPLET, 3 = OTHER (sysmodules running under the BASE memregion))
///
- public ResourceLimitCategory ResourceLimitCategory { get; set; }
+ [MarshalAs(UnmanagedType.U1)]
+ public ResourceLimitCategory ResourceLimitCategory;
}
}
diff --git a/N3DS/ARM9AccessControl.cs b/N3DS/ARM9AccessControl.cs
index c9e863d..b93533d 100644
--- a/N3DS/ARM9AccessControl.cs
+++ b/N3DS/ARM9AccessControl.cs
@@ -1,17 +1,22 @@
-namespace SabreTools.Models.N3DS
+using System.Runtime.InteropServices;
+
+namespace SabreTools.Models.N3DS
{
///
+ [StructLayout(LayoutKind.Sequential)]
public sealed class ARM9AccessControl
{
///
/// Descriptors
///
- public byte[]? Descriptors { get; set; }
+ /// 15 bytes
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = 15)]
+ public byte[]? Descriptors;
///
/// 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.
///
- public byte DescriptorVersion { get; set; }
+ public byte DescriptorVersion;
}
}
diff --git a/N3DS/AccessControlInfo.cs b/N3DS/AccessControlInfo.cs
index 318fbd0..ae0dd1c 100644
--- a/N3DS/AccessControlInfo.cs
+++ b/N3DS/AccessControlInfo.cs
@@ -1,21 +1,24 @@
-namespace SabreTools.Models.N3DS
+using System.Runtime.InteropServices;
+
+namespace SabreTools.Models.N3DS
{
///
+ [StructLayout(LayoutKind.Sequential)]
public sealed class AccessControlInfo
{
///
/// ARM11 local system capabilities
///
- public ARM11LocalSystemCapabilities? ARM11LocalSystemCapabilities { get; set; }
+ public ARM11LocalSystemCapabilities? ARM11LocalSystemCapabilities;
///
/// ARM11 kernel capabilities
///
- public ARM11KernelCapabilities? ARM11KernelCapabilities { get; set; }
+ public ARM11KernelCapabilities? ARM11KernelCapabilities;
///
/// ARM9 access control
///
- public ARM9AccessControl? ARM9AccessControl { get; set; }
+ public ARM9AccessControl? ARM9AccessControl;
}
}
diff --git a/N3DS/CIAHeader.cs b/N3DS/CIAHeader.cs
index 2bb6adf..daa4983 100644
--- a/N3DS/CIAHeader.cs
+++ b/N3DS/CIAHeader.cs
@@ -1,51 +1,56 @@
+using System.Runtime.InteropServices;
+
namespace SabreTools.Models.N3DS
{
///
+ [StructLayout(LayoutKind.Sequential)]
public sealed class CIAHeader
{
///
/// Archive header size, usually 0x2020 bytes
///
- public uint HeaderSize { get; set; }
+ public uint HeaderSize;
///
/// Type
///
- public ushort Type { get; set; }
+ public ushort Type;
///
/// Version
///
- public ushort Version { get; set; }
+ public ushort Version;
///
/// Certificate chain size
///
- public uint CertificateChainSize { get; set; }
+ public uint CertificateChainSize;
///
/// Ticket size
///
- public uint TicketSize { get; set; }
+ public uint TicketSize;
///
/// TMD file size
///
- public uint TMDFileSize { get; set; }
+ public uint TMDFileSize;
///
/// Meta size (0 if no Meta data is present)
///
- public uint MetaSize { get; set; }
+ public uint MetaSize;
///
/// Content size
///
- public ulong ContentSize { get; set; }
+ public ulong ContentSize;
///
/// Content Index
///
- public byte[]? ContentIndex { get; set; }
+ /// 0x2000 bytes
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x2000)]
+ public byte[]? ContentIndex;
}
}
\ No newline at end of file
diff --git a/N3DS/CardInfoHeader.cs b/N3DS/CardInfoHeader.cs
index a56a523..329d677 100644
--- a/N3DS/CardInfoHeader.cs
+++ b/N3DS/CardInfoHeader.cs
@@ -1,61 +1,74 @@
+using System.Runtime.InteropServices;
+
namespace SabreTools.Models.N3DS
{
///
+ [StructLayout(LayoutKind.Sequential)]
public sealed class CardInfoHeader
{
///
/// CARD2: Writable Address In Media Units (For 'On-Chip' Savedata). CARD1: Always 0xFFFFFFFF.
///
- public uint WritableAddressMediaUnits { get; set; }
+ public uint WritableAddressMediaUnits;
///
/// Card Info Bitmask
///
- public uint CardInfoBitmask { get; set; }
+ public uint CardInfoBitmask;
///
/// Reserved
///
- public byte[]? Reserved1 { get; set; }
+ /// 0xF8 bytes
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = 0xF8)]
+ public byte[]? Reserved1;
///
/// Filled size of cartridge
///
- public uint FilledSize { get; set; }
+ public uint FilledSize;
///
/// Reserved
///
- public byte[]? Reserved2 { get; set; }
+ /// 0x0C bytes
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x0C)]
+ public byte[]? Reserved2;
///
/// Title version
///
- public ushort TitleVersion { get; set; }
+ public ushort TitleVersion;
///
/// Card revision
///
- public ushort CardRevision { get; set; }
+ public ushort CardRevision;
///
/// Reserved
///
- public byte[]? Reserved3 { get; set; }
+ /// 0x0C bytes
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x0C)]
+ public byte[]? Reserved3;
///
/// Title ID of CVer in included update partition
///
- public byte[]? CVerTitleID { get; set; }
+ /// 8 bytes
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
+ public byte[]? CVerTitleID;
///
/// Version number of CVer in included update partition
///
- public ushort CVerVersionNumber { get; set; }
+ public ushort CVerVersionNumber;
///
/// Reserved
///
- public byte[]? Reserved4 { get; set; }
+ /// 0xCD6 bytes
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = 0xCD6)]
+ public byte[]? Reserved4;
}
}
diff --git a/N3DS/CodeSetInfo.cs b/N3DS/CodeSetInfo.cs
index 42028be..075291a 100644
--- a/N3DS/CodeSetInfo.cs
+++ b/N3DS/CodeSetInfo.cs
@@ -1,21 +1,24 @@
-namespace SabreTools.Models.N3DS
+using System.Runtime.InteropServices;
+
+namespace SabreTools.Models.N3DS
{
///
+ [StructLayout(LayoutKind.Sequential)]
public sealed class CodeSetInfo
{
///
/// Address
///
- public uint Address { get; set; }
+ public uint Address;
///
/// Physical region size (in page-multiples)
///
- public uint PhysicalRegionSizeInPages { get; set; }
+ public uint PhysicalRegionSizeInPages;
///
/// Size (in bytes)
///
- public uint SizeInBytes { get; set; }
+ public uint SizeInBytes;
}
}
diff --git a/N3DS/ContentChunkRecord.cs b/N3DS/ContentChunkRecord.cs
index cdec186..5fd8b6d 100644
--- a/N3DS/ContentChunkRecord.cs
+++ b/N3DS/ContentChunkRecord.cs
@@ -1,3 +1,5 @@
+using System.Runtime.InteropServices;
+
namespace SabreTools.Models.N3DS
{
///
@@ -5,12 +7,13 @@ namespace SabreTools.Models.N3DS
/// (Determined by "Content Count" in the TMD Header).
///
///
+ [StructLayout(LayoutKind.Sequential)]
public sealed class ContentChunkRecord
{
///
/// Content id
///
- public uint ContentId { get; set; }
+ public uint ContentId;
///
/// Content index
@@ -18,21 +21,23 @@ namespace SabreTools.Models.N3DS
///
/// This does not apply to DLC.
///
- public ContentIndex ContentIndex { get; set; }
+ public ContentIndex ContentIndex;
///
/// Content type
///
- public TMDContentType ContentType { get; set; }
+ public TMDContentType ContentType;
///
/// Content size
///
- public ulong ContentSize { get; set; }
+ public ulong ContentSize;
///
/// SHA-256 hash
///
- public byte[]? SHA256Hash { get; set; }
+ /// 0x20 bytes
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x20)]
+ public byte[]? SHA256Hash;
}
}
\ No newline at end of file
diff --git a/N3DS/ContentInfoRecord.cs b/N3DS/ContentInfoRecord.cs
index 2cc2808..6f64b9f 100644
--- a/N3DS/ContentInfoRecord.cs
+++ b/N3DS/ContentInfoRecord.cs
@@ -1,24 +1,29 @@
+using System.Runtime.InteropServices;
+
namespace SabreTools.Models.N3DS
{
///
/// There are 64 of these records, usually only the first is used.
///
///
+ [StructLayout(LayoutKind.Sequential)]
public sealed class ContentInfoRecord
{
///
/// Content index offset
///
- public ushort ContentIndexOffset { get; set; }
+ public ushort ContentIndexOffset;
///
/// Content command count [k]
///
- public ushort ContentCommandCount { get; set; }
+ public ushort ContentCommandCount;
///
/// SHA-256 hash of the next k content records that have not been hashed yet
///
- public byte[]? UnhashedContentRecordsSHA256Hash { get; set; }
+ /// 0x20 bytes
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x20)]
+ public byte[]? UnhashedContentRecordsSHA256Hash;
}
}
\ No newline at end of file
diff --git a/N3DS/DevelopmentCardInfoHeader.cs b/N3DS/DevelopmentCardInfoHeader.cs
index e9fa121..816e522 100644
--- a/N3DS/DevelopmentCardInfoHeader.cs
+++ b/N3DS/DevelopmentCardInfoHeader.cs
@@ -1,31 +1,40 @@
+using System.Runtime.InteropServices;
+
namespace SabreTools.Models.N3DS
{
///
+ [StructLayout(LayoutKind.Sequential)]
public sealed class DevelopmentCardInfoHeader
{
///
/// InitialData
///
- public InitialData? InitialData { get; set; }
+ public InitialData? InitialData;
///
/// CardDeviceReserved1
///
- public byte[]? CardDeviceReserved1 { get; set; }
+ /// 0x200 bytes
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x200)]
+ public byte[]? CardDeviceReserved1;
///
/// TitleKey
///
- public byte[]? TitleKey { get; set; }
+ /// 0x10 bytes
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x10)]
+ public byte[]? TitleKey;
///
/// CardDeviceReserved2
///
- public byte[]? CardDeviceReserved2 { get; set; }
+ /// 0x1BF0 bytes
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x1BF0)]
+ public byte[]? CardDeviceReserved2;
///
/// TestData
///
- public TestData? TestData { get; set; }
+ public TestData? TestData;
}
}
diff --git a/N3DS/ExeFSFileHeader.cs b/N3DS/ExeFSFileHeader.cs
index dace6be..cdf8100 100644
--- a/N3DS/ExeFSFileHeader.cs
+++ b/N3DS/ExeFSFileHeader.cs
@@ -1,4 +1,6 @@
-namespace SabreTools.Models.N3DS
+using System.Runtime.InteropServices;
+
+namespace SabreTools.Models.N3DS
{
///
/// 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.)
///
///
+ [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public sealed class ExeFSFileHeader
{
///
/// File name
///
- public string? FileName { get; set; }
+ /// 8 bytes
+ [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 8)]
+ public string? FileName;
///
/// File offset
///
- public uint FileOffset { get; set; }
+ public uint FileOffset;
///
/// File size
///
- public uint FileSize { get; set; }
-
- ///
- /// SHA256 hash calculated over the entire file contents
- ///
- public byte[]? FileHash { get; set; }
+ public uint FileSize;
}
}
diff --git a/N3DS/ExeFSHeader.cs b/N3DS/ExeFSHeader.cs
index 742b9bd..98b3714 100644
--- a/N3DS/ExeFSHeader.cs
+++ b/N3DS/ExeFSHeader.cs
@@ -21,6 +21,7 @@
///
/// Reserved
///
+ /// 0x20 bytes
public byte[]? Reserved { get; set; }
///
diff --git a/N3DS/InitialData.cs b/N3DS/InitialData.cs
index 8a51441..065a743 100644
--- a/N3DS/InitialData.cs
+++ b/N3DS/InitialData.cs
@@ -1,36 +1,49 @@
+using System.Runtime.InteropServices;
+
namespace SabreTools.Models.N3DS
{
///
+ [StructLayout(LayoutKind.Sequential)]
public sealed class InitialData
{
///
/// Card seed keyY (first u64 is Media ID (same as first NCCH partitionId))
///
- public byte[]? CardSeedKeyY { get; set; }
+ /// 0x10 bytes
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x10)]
+ public byte[]? CardSeedKeyY;
///
/// Encrypted card seed (AES-CCM, keyslot 0x3B for retail cards, see CTRCARD_SECSEED)
///
- public byte[]? EncryptedCardSeed { get; set; }
+ /// 0x10 bytes
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x10)]
+ public byte[]? EncryptedCardSeed;
///
/// Card seed AES-MAC
///
- public byte[]? CardSeedAESMAC { get; set; }
+ /// 0x10 bytes
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x10)]
+ public byte[]? CardSeedAESMAC;
///
/// Card seed nonce
///
- public byte[]? CardSeedNonce { get; set; }
+ /// 0x0C bytes
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x0C)]
+ public byte[]? CardSeedNonce;
///
/// Reserved3
///
- public byte[]? Reserved { get; set; }
+ /// 0xC4 bytes
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = 0xC4)]
+ public byte[]? Reserved;
///
/// Copy of first NCCH header (excluding RSA signature)
///
- public NCCHHeader? BackupHeader { get; set; }
+ public NCCHHeader? BackupHeader;
}
}
diff --git a/N3DS/MetaData.cs b/N3DS/MetaData.cs
index 2a9bb08..f84545e 100644
--- a/N3DS/MetaData.cs
+++ b/N3DS/MetaData.cs
@@ -1,32 +1,43 @@
+using System.Runtime.InteropServices;
+
namespace SabreTools.Models.N3DS
{
///
+ [StructLayout(LayoutKind.Sequential)]
public sealed class MetaData
{
///
/// Title ID dependency list - Taken from the application's ExHeader
///
/// TODO: Determine numeric format of each entry
- public byte[]? TitleIDDependencyList { get; set; }
+ /// 0x180 bytes
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x180)]
+ public byte[]? TitleIDDependencyList;
///
/// Reserved
///
- public byte[]? Reserved1 { get; set; }
+ /// 0x180 bytes
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x180)]
+ public byte[]? Reserved1;
///
/// Core Version
///
- public uint CoreVersion { get; set; }
+ public uint CoreVersion;
///
/// Reserved
///
- public byte[]? Reserved2 { get; set; }
+ /// 0xFC bytes
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = 0xFC)]
+ public byte[]? Reserved2;
///
/// Icon Data(.ICN) - Taken from the application's ExeFS
///
- public byte[]? IconData { get; set; }
+ /// 0x36C0 bytes
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x36C0)]
+ public byte[]? IconData;
}
}
\ No newline at end of file
diff --git a/N3DS/NCCHExtendedHeader.cs b/N3DS/NCCHExtendedHeader.cs
index c7fd142..a9a00a7 100644
--- a/N3DS/NCCHExtendedHeader.cs
+++ b/N3DS/NCCHExtendedHeader.cs
@@ -1,36 +1,43 @@
-namespace SabreTools.Models.N3DS
+using System.Runtime.InteropServices;
+
+namespace SabreTools.Models.N3DS
{
///
/// 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.
///
///
+ [StructLayout(LayoutKind.Sequential)]
public sealed class NCCHExtendedHeader
{
///
/// SCI
///
- public SystemControlInfo? SCI { get; set; }
+ public SystemControlInfo? SCI;
///
/// ACI
///
- public AccessControlInfo? ACI { get; set; }
+ public AccessControlInfo? ACI;
///
/// AccessDesc signature (RSA-2048-SHA256)
///
- public byte[]? AccessDescSignature { get; set; }
+ /// 0x100 bytes
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x100)]
+ public byte[]? AccessDescSignature;
///
/// NCCH HDR RSA-2048 public key
///
- public byte[]? NCCHHDRPublicKey { get; set; }
+ /// 0x100 bytes
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x100)]
+ public byte[]? NCCHHDRPublicKey;
///
/// ACI (for limitation of first ACI)
///
- public AccessControlInfo? ACIForLimitations { get; set; }
+ public AccessControlInfo? ACIForLimitations;
}
}
diff --git a/N3DS/NCCHHeader.cs b/N3DS/NCCHHeader.cs
index 0add92c..cf41fd7 100644
--- a/N3DS/NCCHHeader.cs
+++ b/N3DS/NCCHHeader.cs
@@ -1,37 +1,44 @@
-namespace SabreTools.Models.N3DS
+using System.Runtime.InteropServices;
+
+namespace SabreTools.Models.N3DS
{
///
+ [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public sealed class NCCHHeader
{
///
/// RSA-2048 signature of the NCCH header, using SHA-256.
///
- public byte[]? RSA2048Signature { get; set; }
+ /// 0x100 bytes
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x100)]
+ public byte[]? RSA2048Signature;
///
/// Magic ID, always 'NCCH'
///
- public string? MagicID { get; set; }
+ /// 4 bytes
+ [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 4)]
+ public string? MagicID;
///
/// Content size, in media units (1 media unit = 0x200 bytes)
///
- public uint ContentSizeInMediaUnits { get; set; }
+ public uint ContentSizeInMediaUnits;
///
/// Partition ID
///
- public ulong PartitionId { get; set; }
+ public ulong PartitionId;
///
/// Maker code
///
- public ushort MakerCode { get; set; }
+ public ushort MakerCode;
///
/// Version
///
- public ushort Version { get; set; }
+ public ushort Version;
///
/// 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.
///
- public uint VerificationHash { get; set; }
+ public uint VerificationHash;
///
/// Program ID
///
- public byte[]? ProgramId { get; set; }
+ /// 8 bytes
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
+ public byte[]? ProgramId;
///
/// Reserved
///
- public byte[]? Reserved1 { get; set; }
+ /// 0x10 bytes
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x10)]
+ public byte[]? Reserved1;
///
/// Logo Region SHA-256 hash. (For applications built with SDK 5+) (Supported from firmware: 5.0.0-11)
///
- public byte[]? LogoRegionHash { get; set; }
+ /// 0x20 bytes
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x20)]
+ public byte[]? LogoRegionHash;
///
/// Product code
///
- public string? ProductCode { get; set; }
+ /// 0x10 bytes
+ [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 0x10)]
+ public string? ProductCode;
///
/// Extended header SHA-256 hash (SHA256 of 2x Alignment Size, beginning at 0x0 of ExHeader)
///
- public byte[]? ExtendedHeaderHash { get; set; }
+ /// 0x20 bytes
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x20)]
+ public byte[]? ExtendedHeaderHash;
///
/// Extended header size, in bytes
///
- public uint ExtendedHeaderSizeInBytes { get; set; }
+ public uint ExtendedHeaderSizeInBytes;
///
/// Reserved
///
- public byte[]? Reserved2 { get; set; }
+ public uint Reserved2;
///
/// Flags
///
- public NCCHHeaderFlags? Flags { get; set; }
+ public NCCHHeaderFlags? Flags;
///
/// Plain region offset, in media units
///
- public uint PlainRegionOffsetInMediaUnits { get; set; }
+ public uint PlainRegionOffsetInMediaUnits;
///
/// Plain region size, in media units
///
- public uint PlainRegionSizeInMediaUnits { get; set; }
+ public uint PlainRegionSizeInMediaUnits;
///
/// Logo Region offset, in media units (For applications built with SDK 5+) (Supported from firmware: 5.0.0-11)
///
- public uint LogoRegionOffsetInMediaUnits { get; set; }
+ public uint LogoRegionOffsetInMediaUnits;
///
/// Logo Region size, in media units (For applications built with SDK 5+) (Supported from firmware: 5.0.0-11)
///
- public uint LogoRegionSizeInMediaUnits { get; set; }
+ public uint LogoRegionSizeInMediaUnits;
///
/// ExeFS offset, in media units
///
- public uint ExeFSOffsetInMediaUnits { get; set; }
+ public uint ExeFSOffsetInMediaUnits;
///
/// ExeFS size, in media units
///
- public uint ExeFSSizeInMediaUnits { get; set; }
+ public uint ExeFSSizeInMediaUnits;
///
/// ExeFS hash region size, in media units
///
- public uint ExeFSHashRegionSizeInMediaUnits { get; set; }
+ public uint ExeFSHashRegionSizeInMediaUnits;
///
/// Reserved
///
- public byte[]? Reserved3 { get; set; }
+ public uint Reserved3;
///
/// RomFS offset, in media units
///
- public uint RomFSOffsetInMediaUnits { get; set; }
+ public uint RomFSOffsetInMediaUnits;
///
/// RomFS size, in media units
///
- public uint RomFSSizeInMediaUnits { get; set; }
+ public uint RomFSSizeInMediaUnits;
///
/// RomFS hash region size, in media units
///
- public uint RomFSHashRegionSizeInMediaUnits { get; set; }
+ public uint RomFSHashRegionSizeInMediaUnits;
///
/// Reserved
///
- public byte[]? Reserved4 { get; set; }
+ public uint Reserved4;
///
/// 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)
///
- public byte[]? ExeFSSuperblockHash { get; set; }
+ /// 0x20 bytes
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x20)]
+ public byte[]? ExeFSSuperblockHash;
///
/// 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)
///
- public byte[]? RomFSSuperblockHash { get; set; }
+ /// 0x20 bytes
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x20)]
+ public byte[]? RomFSSuperblockHash;
}
}
diff --git a/N3DS/NCCHHeaderFlags.cs b/N3DS/NCCHHeaderFlags.cs
index 6d9b816..266537b 100644
--- a/N3DS/NCCHHeaderFlags.cs
+++ b/N3DS/NCCHHeaderFlags.cs
@@ -1,49 +1,56 @@
-namespace SabreTools.Models.N3DS
+using System.Runtime.InteropServices;
+
+namespace SabreTools.Models.N3DS
{
///
+ [StructLayout(LayoutKind.Sequential)]
public sealed class NCCHHeaderFlags
{
///
/// Reserved
///
- public byte Reserved0 { get; set; }
+ public byte Reserved0;
///
/// Reserved
///
- public byte Reserved1 { get; set; }
+ public byte Reserved1;
///
/// Reserved
///
- public byte Reserved2 { get; set; }
+ public byte Reserved2;
///
/// Crypto Method: When this is non-zero, a NCCH crypto method using two keyslots is used.
///
- public CryptoMethod CryptoMethod { get; set; }
+ [MarshalAs(UnmanagedType.U1)]
+ public CryptoMethod CryptoMethod;
///
/// Content Platform: 1 = CTR, 2 = snake (New 3DS).
///
- public ContentPlatform ContentPlatform { get; set; }
+ [MarshalAs(UnmanagedType.U1)]
+ public ContentPlatform ContentPlatform;
///
/// 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.
///
- public ContentType MediaPlatformIndex { get; set; }
+ [MarshalAs(UnmanagedType.U1)]
+ public ContentType MediaPlatformIndex;
///
- /// Content Unit Size i.e. u32 ContentUnitSize = 0x200*2^flags[6] { get; set; }
+ /// Content Unit Size i.e. u32 ContentUnitSize = 0x200*2^flags[6];
///
- public byte ContentUnitSize { get; set; }
+ public byte ContentUnitSize;
///
/// Bit-masks: FixedCryptoKey = 0x1, NoMountRomFs = 0x2, NoCrypto = 0x4, using a new keyY
/// generator = 0x20(starting with FIRM 9.6.0-X).
///
- public BitMasks BitMasks { get; set; }
+ [MarshalAs(UnmanagedType.U1)]
+ public BitMasks BitMasks;
}
}
diff --git a/N3DS/PartitionTableEntry.cs b/N3DS/PartitionTableEntry.cs
index 8e0ac15..17cd573 100644
--- a/N3DS/PartitionTableEntry.cs
+++ b/N3DS/PartitionTableEntry.cs
@@ -1,19 +1,22 @@
-namespace SabreTools.Models.N3DS
+using System.Runtime.InteropServices;
+
+namespace SabreTools.Models.N3DS
{
///
/// Offset and Length partition table, in media units
///
///
+ [StructLayout(LayoutKind.Sequential)]
public sealed class PartitionTableEntry
{
///
/// Offset
///
- public uint Offset { get; set; }
+ public uint Offset;
///
/// Length
///
- public uint Length { get; set; }
+ public uint Length;
}
}
diff --git a/N3DS/RomFSHeader.cs b/N3DS/RomFSHeader.cs
index 01a743f..bfb7e55 100644
--- a/N3DS/RomFSHeader.cs
+++ b/N3DS/RomFSHeader.cs
@@ -1,4 +1,6 @@
-namespace SabreTools.Models.N3DS
+using System.Runtime.InteropServices;
+
+namespace SabreTools.Models.N3DS
{
///
/// RomFS (or Read-Only Filesystem) is part of the NCCH format, and is
@@ -6,91 +8,94 @@
///
///
/// TODO: Implement the other parts of the RomFS tree structure
+
+ [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public sealed class RomFSHeader
{
///
/// Magic "IVFC"
///
- public string? MagicString { get; set; }
+ [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 4)]
+ public string? MagicString;
///
/// Magic number 0x10000
///
- public uint MagicNumber { get; set; }
+ public uint MagicNumber;
///
/// Master hash size
///
- public uint MasterHashSize { get; set; }
+ public uint MasterHashSize;
///
/// Level 1 logical offset
///
- public ulong Level1LogicalOffset { get; set; }
+ public ulong Level1LogicalOffset;
///
/// Level 1 hashdata size
///
- public ulong Level1HashdataSize { get; set; }
+ public ulong Level1HashdataSize;
///
/// Level 1 block size, in log2
///
- public uint Level1BlockSizeLog2 { get; set; }
+ public uint Level1BlockSizeLog2;
///
/// Reserved
///
- public byte[]? Reserved1 { get; set; }
+ public uint Reserved1;
///
/// Level 2 logical offset
///
- public ulong Level2LogicalOffset { get; set; }
+ public ulong Level2LogicalOffset;
///
/// Level 2 hashdata size
///
- public ulong Level2HashdataSize { get; set; }
+ public ulong Level2HashdataSize;
///
/// Level 2 block size, in log2
///
- public uint Level2BlockSizeLog2 { get; set; }
+ public uint Level2BlockSizeLog2;
///
/// Reserved
///
- public byte[]? Reserved2 { get; set; }
+ public uint Reserved2;
///
/// Level 3 logical offset
///
- public ulong Level3LogicalOffset { get; set; }
+ public ulong Level3LogicalOffset;
///
/// Level 3 hashdata size
///
- public ulong Level3HashdataSize { get; set; }
+ public ulong Level3HashdataSize;
///
/// Level 3 block size, in log2
///
- public uint Level3BlockSizeLog2 { get; set; }
+ public uint Level3BlockSizeLog2;
///
/// Reserved
///
- public byte[]? Reserved3 { get; set; }
+ public uint Reserved3;
///
/// Reserved
///
- public byte[]? Reserved4 { get; set; }
+ public uint Reserved4;
///
/// Optional info size.
///
- public uint OptionalInfoSize { get; set; }
+ public uint OptionalInfoSize;
}
}
diff --git a/N3DS/StorageInfo.cs b/N3DS/StorageInfo.cs
index 483ae83..0a9f752 100644
--- a/N3DS/StorageInfo.cs
+++ b/N3DS/StorageInfo.cs
@@ -1,36 +1,46 @@
-namespace SabreTools.Models.N3DS
+using System.Runtime.InteropServices;
+
+namespace SabreTools.Models.N3DS
{
///
/// Used in FSReg:Register.
///
///
+ [StructLayout(LayoutKind.Sequential)]
public sealed class StorageInfo
{
///
/// Extdata ID
///
- public ulong ExtdataID { get; set; }
+ public ulong ExtdataID;
///
/// System savedata IDs
///
- public byte[]? SystemSavedataIDs { get; set; }
+ /// 8 bytes
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
+ public byte[]? SystemSavedataIDs;
///
/// Storage accessible unique IDs
///
- public byte[]? StorageAccessibleUniqueIDs { get; set; }
+ /// 8 bytes
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
+ public byte[]? StorageAccessibleUniqueIDs;
///
/// Filesystem access info
///
/// TODO: Create enum for the flag values
/// TODO: Combine with "other attributes"
- public byte[]? FileSystemAccessInfo { get; set; }
+ /// 7 bytes
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = 7)]
+ public byte[]? FileSystemAccessInfo;
///
/// Other attributes
///
- public StorageInfoOtherAttributes OtherAttributes { get; set; }
+ [MarshalAs(UnmanagedType.U1)]
+ public StorageInfoOtherAttributes OtherAttributes;
}
}
diff --git a/N3DS/SystemControlInfo.cs b/N3DS/SystemControlInfo.cs
index 0bf1653..abcbecf 100644
--- a/N3DS/SystemControlInfo.cs
+++ b/N3DS/SystemControlInfo.cs
@@ -1,66 +1,75 @@
-namespace SabreTools.Models.N3DS
+using System.Runtime.InteropServices;
+
+namespace SabreTools.Models.N3DS
{
///
+ [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public sealed class SystemControlInfo
{
///
/// Application title (default is "CtrApp")
///
- public string? ApplicationTitle { get; set; }
+ /// 8 bytes
+ [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 8)]
+ public string? ApplicationTitle;
///
/// Reserved
///
- public byte[]? Reserved1 { get; set; }
+ /// 5 bytes
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = 5)]
+ public byte[]? Reserved1;
///
/// Flag (bit 0: CompressExefsCode, bit 1: SDApplication)
///
- public byte Flag { get; set; }
+ public byte Flag;
///
/// Remaster version
///
- public ushort RemasterVersion { get; set; }
+ public ushort RemasterVersion;
///
/// Text code set info
///
- public CodeSetInfo? TextCodeSetInfo { get; set; }
+ public CodeSetInfo? TextCodeSetInfo;
///
/// Stack size
///
- public uint StackSize { get; set; }
+ public uint StackSize;
///
/// Read-only code set info
///
- public CodeSetInfo? ReadOnlyCodeSetInfo { get; set; }
+ public CodeSetInfo? ReadOnlyCodeSetInfo;
///
/// Reserved
///
- public byte[]? Reserved2 { get; set; }
+ public uint Reserved2;
///
/// Data code set info
///
- public CodeSetInfo? DataCodeSetInfo { get; set; }
+ public CodeSetInfo? DataCodeSetInfo;
///
/// BSS size
///
- public uint BSSSize { get; set; }
+ public uint BSSSize;
///
/// Dependency module (program ID) list
///
- public ulong[]? DependencyModuleList { get; set; }
+ /// 48 entries
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = 48)]
+ public ulong[]? DependencyModuleList;
///
/// SystemInfo
///
- public SystemInfo? SystemInfo { get; set; }
+ public SystemInfo? SystemInfo;
}
}
diff --git a/N3DS/SystemInfo.cs b/N3DS/SystemInfo.cs
index 51d2d84..8d43af6 100644
--- a/N3DS/SystemInfo.cs
+++ b/N3DS/SystemInfo.cs
@@ -1,21 +1,26 @@
-namespace SabreTools.Models.N3DS
+using System.Runtime.InteropServices;
+
+namespace SabreTools.Models.N3DS
{
///
+ [StructLayout(LayoutKind.Sequential)]
public sealed class SystemInfo
{
///
/// SaveData Size
///
- public ulong SaveDataSize { get; set; }
+ public ulong SaveDataSize;
///
/// Jump ID
///
- public ulong JumpID { get; set; }
+ public ulong JumpID;
///
/// Reserved
///
- public byte[]? Reserved { get; set; }
+ /// 0x30 bytes
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x30)]
+ public byte[]? Reserved;
}
}
diff --git a/N3DS/TestData.cs b/N3DS/TestData.cs
index 85feae4..6c8770b 100644
--- a/N3DS/TestData.cs
+++ b/N3DS/TestData.cs
@@ -1,59 +1,80 @@
+using System.Runtime.InteropServices;
+
namespace SabreTools.Models.N3DS
{
///
/// The test data is the same one encountered in development DS/DSi cartridges.
///
///
+ [StructLayout(LayoutKind.Sequential)]
public sealed class TestData
{
///
/// The bytes FF 00 FF 00 AA 55 AA 55.
///
- public byte[]? Signature { get; set; }
+ /// 8 bytes
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
+ public byte[]? Signature;
///
/// An ascending byte sequence equal to the offset mod 256 (08 09 0A ... FE FF 00 01 ... FF).
///
- public byte[]? AscendingByteSequence { get; set; }
+ /// 0x1F8 bytes
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x1F8)]
+ public byte[]? AscendingByteSequence;
///
/// A descending byte sequence equal to 255 minus the offset mod 256 (FF FE FD ... 00 FF DE ... 00).
///
- public byte[]? DescendingByteSequence { get; set; }
+ /// 0x200 bytes
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x200)]
+ public byte[]? DescendingByteSequence;
///
/// Filled with 00 (0b00000000) bytes.
///
- public byte[]? Filled00 { get; set; }
+ /// 0x200 bytes
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x200)]
+ public byte[]? Filled00;
///
/// Filled with FF (0b11111111) bytes.
///
- public byte[]? FilledFF { get; set; }
+ /// 0x200 bytes
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x200)]
+ public byte[]? FilledFF;
///
/// Filled with 0F (0b00001111) bytes.
///
- public byte[]? Filled0F { get; set; }
+ /// 0x200 bytes
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x200)]
+ public byte[]? Filled0F;
///
/// Filled with F0 (0b11110000) bytes.
///
- public byte[]? FilledF0 { get; set; }
+ /// 0x200 bytes
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x200)]
+ public byte[]? FilledF0;
///
/// Filled with 55 (0b01010101) bytes.
///
- public byte[]? Filled55 { get; set; }
+ /// 0x200 bytes
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x200)]
+ public byte[]? Filled55;
///
/// Filled with AA (0b10101010) bytes.
///
- public byte[]? FilledAA { get; set; }
+ /// 0x1FF bytes
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x1FF)]
+ public byte[]? FilledAA;
///
/// The final byte is 00 (0b00000000).
///
- public byte FinalByte { get; set; }
+ public byte FinalByte;
}
}