<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://www.3dbrew.org/w/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=ForbiddenTempura</id>
	<title>3dbrew - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https://www.3dbrew.org/w/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=ForbiddenTempura"/>
	<link rel="alternate" type="text/html" href="https://www.3dbrew.org/wiki/Special:Contributions/ForbiddenTempura"/>
	<updated>2026-04-03T19:05:11Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.43.1</generator>
	<entry>
		<id>https://www.3dbrew.org/w/index.php?title=NCSD&amp;diff=22570</id>
		<title>NCSD</title>
		<link rel="alternate" type="text/html" href="https://www.3dbrew.org/w/index.php?title=NCSD&amp;diff=22570"/>
		<updated>2024-06-02T09:17:46Z</updated>

		<summary type="html">&lt;p&gt;ForbiddenTempura: /* InitialData */ Fix struct being too large caused by having redundant data&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:File formats]]&lt;br /&gt;
This page documents the format of NCSD.&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
There are two known specialisations of the NCSD container format. The CTR Cart Image (CCI) format and the 3DS&#039; raw [[Flash Filesystem#NAND structure|NAND format]]. CCI is the format of game ROM images.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;CTR System Update (CSU)&#039;&#039;&#039; is a variant of CCI, where the only difference is in the file extension. This is used with developer System Updates and associated [[3DS Development Unit Software|Tools]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
NCSD images start with a NCSD header, followed by up to a maximum of 8 [[NCCH]] partitions.&lt;br /&gt;
&lt;br /&gt;
For CCI images, the partitions are reserved as follows:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
!  [[NCCH]] Index&lt;br /&gt;
!  Reserved Use&lt;br /&gt;
|-&lt;br /&gt;
| 0&lt;br /&gt;
| Executable Content ([[NCCH#CXI|CXI]])&lt;br /&gt;
|-&lt;br /&gt;
| 1&lt;br /&gt;
| E-Manual ([[NCCH#CFA|CFA]])&lt;br /&gt;
|-&lt;br /&gt;
| 2&lt;br /&gt;
| [[Download Play]] Child container ([[NCCH#CFA|CFA]])&lt;br /&gt;
|-&lt;br /&gt;
| 6&lt;br /&gt;
| New3DS [[System_Update_CFA|Update Data]] ([[NCCH#CFA|CFA]])&lt;br /&gt;
|-&lt;br /&gt;
| 7&lt;br /&gt;
| [[System_Update_CFA|Update Data]] ([[NCCH#CFA|CFA]])&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The format of partitions can be determined from the partition FS flags (normally these are zero for CCI/CSU NCSD Images).&lt;br /&gt;
&lt;br /&gt;
== NCSD header ==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
!  Offset&lt;br /&gt;
!  Size&lt;br /&gt;
!  Description&lt;br /&gt;
|-&lt;br /&gt;
|  0x000&lt;br /&gt;
|  0x100&lt;br /&gt;
|  RSA-2048 SHA-256 signature of the NCSD header&lt;br /&gt;
|-&lt;br /&gt;
|  0x100&lt;br /&gt;
|  4&lt;br /&gt;
|  Magic Number &#039;NCSD&#039;&lt;br /&gt;
|-&lt;br /&gt;
|  0x104&lt;br /&gt;
|  4&lt;br /&gt;
|  Size of the NCSD image, in media units (1 media unit = 0x200 bytes)&lt;br /&gt;
|-&lt;br /&gt;
|  0x108&lt;br /&gt;
|  8&lt;br /&gt;
|  Media ID&lt;br /&gt;
|-&lt;br /&gt;
|  0x110&lt;br /&gt;
|  8&lt;br /&gt;
|  Partitions FS type (0=None, 1=Normal, 3=FIRM, 4=AGB_FIRM save)&lt;br /&gt;
|-&lt;br /&gt;
|  0x118&lt;br /&gt;
|  8&lt;br /&gt;
|  Partitions crypt type (each byte corresponds to a partition in the partition table)&lt;br /&gt;
|-&lt;br /&gt;
|  0x120&lt;br /&gt;
|  0x40=(4+4)*8&lt;br /&gt;
|  Offset &amp;amp; Length partition table, in media units&lt;br /&gt;
|-&lt;br /&gt;
|  0x160&lt;br /&gt;
|  0xA0&lt;br /&gt;
|  ...&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
For carts,&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
!  Offset&lt;br /&gt;
!  Size&lt;br /&gt;
!  Description&lt;br /&gt;
|-&lt;br /&gt;
|  0x160&lt;br /&gt;
|  0x20&lt;br /&gt;
|  Exheader SHA-256 hash&lt;br /&gt;
|-&lt;br /&gt;
|  0x180&lt;br /&gt;
|  0x4&lt;br /&gt;
|  Additional header size&lt;br /&gt;
|-&lt;br /&gt;
|  0x184&lt;br /&gt;
|  0x4&lt;br /&gt;
|  Sector zero offset&lt;br /&gt;
|-&lt;br /&gt;
|  0x188&lt;br /&gt;
|  8&lt;br /&gt;
|  Partition Flags (See Below)&lt;br /&gt;
|-&lt;br /&gt;
|  0x190&lt;br /&gt;
|  0x40=8*8&lt;br /&gt;
|  Partition ID table &lt;br /&gt;
|-&lt;br /&gt;
|  0x1D0&lt;br /&gt;
|  0x20&lt;br /&gt;
|  Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x1F0&lt;br /&gt;
| 0xE&lt;br /&gt;
| Reserved?&lt;br /&gt;
|-&lt;br /&gt;
| 0x1FE&lt;br /&gt;
| 0x1&lt;br /&gt;
| Support for this was implemented with [[9.6.0-24|9.6.0-X]] FIRM. Bit0=1 enables using bits 1-2, it&#039;s unknown what these two bits are actually used for(the value of these two bits get compared with some other value during NCSD verification/loading). This appears to enable a new, likely hardware-based, antipiracy check on cartridges.&lt;br /&gt;
|-&lt;br /&gt;
| 0x1FF&lt;br /&gt;
| 0x1&lt;br /&gt;
| Support for this was implemented with [[9.6.0-24|9.6.0-X]] FIRM, see below regarding save crypto.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
For NAND,&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
!  Offset&lt;br /&gt;
!  Size&lt;br /&gt;
!  Description&lt;br /&gt;
|-&lt;br /&gt;
|  0x160&lt;br /&gt;
|  0x5E&lt;br /&gt;
|  Unknown&lt;br /&gt;
|-&lt;br /&gt;
|  0x1BE&lt;br /&gt;
|  0x42&lt;br /&gt;
|  Encrypted MBR partition-table, for the TWL partitions(key-data used for this keyslot is console-unique).&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== NCSD Signature ===&lt;br /&gt;
The RSA public key used for gamecard NCSD is stored in [[Memory_layout|ITCM]]. The separate public key used for NAND NCSD is stored in Process9 .(ro)data instead of ITCM, and in [[Bootloader|boot ROM]].&lt;br /&gt;
&lt;br /&gt;
For the boot ROM check, sighax may be used to fake-sign NAND headers.  Process9&#039;s check will fail, however, unless patched.&lt;br /&gt;
&lt;br /&gt;
=== Partition Flags ===&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
!  Byte Index&lt;br /&gt;
!  Description&lt;br /&gt;
|-&lt;br /&gt;
| 0&lt;br /&gt;
| Backup Write Wait Time (The time to wait to write save to backup after the card is recognized (0-255 seconds)).NATIVE_FIRM loads this flag from the gamecard NCSD header starting with [[6.0.0-11]].&lt;br /&gt;
|-&lt;br /&gt;
| 3&lt;br /&gt;
| Media Card Device (1 = NOR Flash, 2 = None, 3 = BT) (SDK 3.X+)&lt;br /&gt;
|-&lt;br /&gt;
| 4&lt;br /&gt;
| Media Platform Index (1 = CTR)&lt;br /&gt;
|-&lt;br /&gt;
| 5&lt;br /&gt;
| Media Type Index (0 = Inner Device, 1 = Card1, 2 = Card2, 3 = Extended Device)&lt;br /&gt;
|-&lt;br /&gt;
| 6&lt;br /&gt;
| Media Unit Size i.e. u32 MediaUnitSize = 0x200*2^flags[6];&lt;br /&gt;
|-&lt;br /&gt;
| 7&lt;br /&gt;
| Media Card Device (1 = NOR Flash, 2 = None, 3 = BT) (Only SDK 2.X)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Partition Flags (In Terms of Save Crypto Determination) ===&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
!  Byte Index&lt;br /&gt;
!  Description&lt;br /&gt;
|-&lt;br /&gt;
| 1&lt;br /&gt;
| Starting with [[6.0.0-11]] NATIVE_FIRM will use this flag to determine the gamecard [[Savegames|savegame]] keyY method, when flag[3] is set. 0 = [[2.0.0-2]] hashed keyY, 1 = [[Savegames|new]] keyY method implemented with [[6.0.0-11]]. 0x0A = implemented with [[9.3.0-21|9.3.0-X]]. On Old3DS this is identical to the [[2.2.0-4]] crypto. On New3DS this is identical to the [[2.2.0-4]] crypto, except with New3DS-only gamecard savedata [[AES|keyslots]].&lt;br /&gt;
Starting with [[9.6.0-24|9.6.0-X]] FIRM, Process9 now sets &amp;lt;savecrypto_stateval&amp;gt; to partitionflag[1] + &amp;lt;the u8 value from NCSD+0x1FF&amp;gt;, instead of just setting it to partitionflag[1].&lt;br /&gt;
|-&lt;br /&gt;
| 3&lt;br /&gt;
| Support for this flag was implemented in NATIVE_FIRM with [[2.0.0-2]]. When this flag is set the hashed gamecard [[Savegames|savegame]] keyY method is used, this likely still uses the repeating-CTR however. With [[6.0.0-11]] the system will determine the gamecard savegame keyY method via flag[1], instead of just using the hashed keyY via this flag.&lt;br /&gt;
|-th&lt;br /&gt;
| 7&lt;br /&gt;
| This flag enables using the hashed gamecard [[Savegames|savegame]] keyY method, support for this flag was implemented in NATIVE_FIRM with [[2.2.0-4]]. All games with the NCSD image finalized since [[2.2.0-4]](and contains [[2.2.0-4]]+ in the system update partition) have this flag set, this flag also enables using new CTR method as well.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Starting with [[9.6.0-24|9.6.0-X]] FIRM, Process9 will just write val0 to a state field then return 0, instead of returning an error when the save crypto type isn&#039;t recognized. This was the *only* actual functionality change in the Old3DS Process9 function for gamecard savedata crypto init.&lt;br /&gt;
&lt;br /&gt;
== Card Info Header ==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
!  OFFSET&lt;br /&gt;
!  SIZE&lt;br /&gt;
!  DESCRIPTION&lt;br /&gt;
|-&lt;br /&gt;
|  0x200&lt;br /&gt;
|  4&lt;br /&gt;
|  CARD2: Writable Address In Media Units (For &#039;On-Chip&#039; Savedata). CARD1: Always 0xFFFFFFFF.&lt;br /&gt;
|-&lt;br /&gt;
|  0x204&lt;br /&gt;
|  4&lt;br /&gt;
|  Card Info Bitmask&lt;br /&gt;
|-&lt;br /&gt;
|  0x208&lt;br /&gt;
|  0xF8&lt;br /&gt;
|  Reserved&lt;br /&gt;
|-&lt;br /&gt;
|  0x300&lt;br /&gt;
|  4&lt;br /&gt;
|  Filled size of cartridge&lt;br /&gt;
|-&lt;br /&gt;
|  0x304&lt;br /&gt;
|  0xC&lt;br /&gt;
|  Reserved&lt;br /&gt;
|-&lt;br /&gt;
|  0x310&lt;br /&gt;
|  2&lt;br /&gt;
|  Title version&lt;br /&gt;
|-&lt;br /&gt;
|  0x312&lt;br /&gt;
|  2&lt;br /&gt;
|  Card revision&lt;br /&gt;
|-&lt;br /&gt;
|  0x314&lt;br /&gt;
|  0xC&lt;br /&gt;
|  Reserved&lt;br /&gt;
|-&lt;br /&gt;
|  0x320&lt;br /&gt;
|  8&lt;br /&gt;
|  Title ID of [[CVer]] in included update partition&lt;br /&gt;
|-&lt;br /&gt;
|  0x328&lt;br /&gt;
|  2&lt;br /&gt;
|  Version number of [[CVer]] in included update partition&lt;br /&gt;
|-&lt;br /&gt;
|  0x32A&lt;br /&gt;
|  0xCD6&lt;br /&gt;
|  Reserved&lt;br /&gt;
|-&lt;br /&gt;
|  0x1000&lt;br /&gt;
|  0x200&lt;br /&gt;
|  InitialData&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== InitialData ===&lt;br /&gt;
&lt;br /&gt;
This data is returned by [[Gamecards|16-byte cartridge command]] 0x82.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
!  OFFSET&lt;br /&gt;
!  SIZE&lt;br /&gt;
!  DESCRIPTION&lt;br /&gt;
|-&lt;br /&gt;
|  0x00&lt;br /&gt;
|  0x10&lt;br /&gt;
|  Seed (keyY used to decrypt the title key - keyX is keyslot 0x3B for production cards, or a key of all zeroes for development cards), consisting of the title ID (little-endian) followed by reserved data (normally all-zero)&lt;br /&gt;
|-&lt;br /&gt;
|  0x10&lt;br /&gt;
|  0x10&lt;br /&gt;
|  TitleKey (AES-CCM encrypted)&lt;br /&gt;
|-&lt;br /&gt;
|  0x20&lt;br /&gt;
|  0x10&lt;br /&gt;
|  AES-CCM MAC&lt;br /&gt;
|-&lt;br /&gt;
|  0x30&lt;br /&gt;
|  0xC&lt;br /&gt;
|  AES-CCM nonce&lt;br /&gt;
|-&lt;br /&gt;
|  0x3C&lt;br /&gt;
|  0xC4&lt;br /&gt;
|  Reserved (normally all-zero)&lt;br /&gt;
|-&lt;br /&gt;
|  0x100&lt;br /&gt;
|  0x100&lt;br /&gt;
|  NcchHeader (copy of the first NCCH header, excluding the RSA signature)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Development Card Info Header Extension ==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
!  OFFSET&lt;br /&gt;
!  SIZE&lt;br /&gt;
!  DESCRIPTION&lt;br /&gt;
|-&lt;br /&gt;
|  0x1200&lt;br /&gt;
|  0x200&lt;br /&gt;
|  CardDeviceReserved1&lt;br /&gt;
|-&lt;br /&gt;
|  0x1400&lt;br /&gt;
|  0x10&lt;br /&gt;
|  TitleKeyData&lt;br /&gt;
|-&lt;br /&gt;
|  0x1410&lt;br /&gt;
|  0x1BF0&lt;br /&gt;
|  CardDeviceReserved2&lt;br /&gt;
|-&lt;br /&gt;
|  0x3000&lt;br /&gt;
|  0x1000&lt;br /&gt;
|  TestData&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
TitleKeyData contains the decrypted version of the title key found in the InitialData. This field appears to be what development--and maybe production?--cards read to know what card encryption seed to use in the CTR protocol.&lt;br /&gt;
&lt;br /&gt;
The CardDeviceReserved areas have random-looking data whose purpose is unknown, other than perhaps to hide the TitleKey.&lt;br /&gt;
&lt;br /&gt;
Note that a particular flashcard vendor, namely Gateway, puts what many refer to as &amp;quot;private headers&amp;quot; at CardDeviceReserved1 in place of actual development card information. This header consists of:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
!  OFFSET&lt;br /&gt;
!  SIZE&lt;br /&gt;
!  DESCRIPTION&lt;br /&gt;
|-&lt;br /&gt;
|  0x0&lt;br /&gt;
|  0x40&lt;br /&gt;
|  Unique cartridge ID; only the first 0x10 bytes are meaningful, the rest are 0xff; obtainable using encrypted [[Gamecards|16-byte cartridge command]] 0xc6; the first 0x10 bytes can also be obtained in userland via [[Process_Services_PXI|pxi:ps9::GetRomId]]&lt;br /&gt;
|-&lt;br /&gt;
|  0x40&lt;br /&gt;
|  0x4&lt;br /&gt;
|  Cartridge ID1; obtainable using 8-byte cartridge command 0x90 or 16-byte cartridge command 0xa2&lt;br /&gt;
|-&lt;br /&gt;
|  0x44&lt;br /&gt;
|  0x4&lt;br /&gt;
|  Cartridge ID2; obtainable using 8-byte cartridge command 0xa0 or 16-byte cartridge command 0xa4&lt;br /&gt;
|-&lt;br /&gt;
|  0x48&lt;br /&gt;
|  0x8&lt;br /&gt;
|  Padding (all-0xff)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The legitimacy of the unique cartridge ID can be validated by online services.&lt;br /&gt;
&lt;br /&gt;
Some dumping tools, notably GodMode9 as of 2024-05-26, erroneously always write 0x00000000 into the position of the Cartridge ID2. This is presumably because the cartridge ID2 is always zero for retail carts.&lt;br /&gt;
&lt;br /&gt;
=== TestData ===&lt;br /&gt;
The test data is the same one encountered in development DS/DSi cartridges. Its layout is as follows:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
!  OFFSET&lt;br /&gt;
!  SIZE&lt;br /&gt;
!  DESCRIPTION&lt;br /&gt;
|-&lt;br /&gt;
|  0x0&lt;br /&gt;
|  0x8&lt;br /&gt;
|  The bytes FF 00 FF 00 AA 55 AA 55.&lt;br /&gt;
|-&lt;br /&gt;
|  0x8&lt;br /&gt;
|  0x1F8&lt;br /&gt;
|  An ascending byte sequence equal to the offset mod 256 (08 09 0A ... FE FF 00 01 ... FF).&lt;br /&gt;
|-&lt;br /&gt;
|  0x200&lt;br /&gt;
|  0x200&lt;br /&gt;
|  A descending byte sequence equal to 255 minus the offset mod 256 (FF FE FD ... 00 FF DE ... 00).&lt;br /&gt;
|-&lt;br /&gt;
|  0x400&lt;br /&gt;
|  0x200&lt;br /&gt;
|  Filled with 00 (0b00000000) bytes.&lt;br /&gt;
|-&lt;br /&gt;
|  0x600&lt;br /&gt;
|  0x200&lt;br /&gt;
|  Filled with FF (0b11111111) bytes.&lt;br /&gt;
|-&lt;br /&gt;
|  0x800&lt;br /&gt;
|  0x200&lt;br /&gt;
|  Filled with 0F (0b00001111) bytes.&lt;br /&gt;
|-&lt;br /&gt;
|  0xA00&lt;br /&gt;
|  0x200&lt;br /&gt;
|  Filled with F0 (0b11110000) bytes.&lt;br /&gt;
|-&lt;br /&gt;
|  0xC00&lt;br /&gt;
|  0x200&lt;br /&gt;
|  Filled with 55 (0b01010101) bytes.&lt;br /&gt;
|-&lt;br /&gt;
|  0xE00&lt;br /&gt;
|  0x1FF&lt;br /&gt;
|  Filled with AA (0b10101010) bytes.&lt;br /&gt;
|-&lt;br /&gt;
|  0xFFF&lt;br /&gt;
|  0x1&lt;br /&gt;
|  The final byte is 00 (0b00000000).&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Production cards always return FF when attempting to read 0x1200-0x3FFF. They probably actually have the same data as development cards, but there&#039;s no way to read it.&lt;br /&gt;
&lt;br /&gt;
== Tools ==&lt;br /&gt;
&lt;br /&gt;
[https://github.com/3dshax/ctr/tree/master/ctrtool ctrtool] - (CMD)(Windows/Linux) Parsing NCSD files&lt;br /&gt;
&lt;br /&gt;
[[3DSExplorer]] - (GUI)(Windows Only) Parsing NCSD files&lt;/div&gt;</summary>
		<author><name>ForbiddenTempura</name></author>
	</entry>
</feed>