<?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=Wwylele</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=Wwylele"/>
	<link rel="alternate" type="text/html" href="https://www.3dbrew.org/wiki/Special:Contributions/Wwylele"/>
	<updated>2026-04-22T16:09:48Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.43.1</generator>
	<entry>
		<id>https://www.3dbrew.org/w/index.php?title=Inner_FAT&amp;diff=21157</id>
		<title>Inner FAT</title>
		<link rel="alternate" type="text/html" href="https://www.3dbrew.org/w/index.php?title=Inner_FAT&amp;diff=21157"/>
		<updated>2020-01-30T19:50:21Z</updated>

		<summary type="html">&lt;p&gt;Wwylele: /* Directory Hash Table &amp;amp;amp; File Hash Table */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This page describes a common FAT-like file system used in [[Savegames]], [[Extdata]] and [[Title Database]]. This file system format has several variants depending on which kind of data it stores. All the three kinds of data that use this file system structure also happen to use the [[DISA and DIFF]] container as well, but there is no direct relationship between the file system and the DISA/DIFF container. All data formats described here is in the inner data of the DISA/DIFF container (i.e. IVFC level 4). Please refer to the DISA/DIFF page for how to unwrap it first before trying to extract the file system.&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
&lt;br /&gt;
The file system consists of the following components:&lt;br /&gt;
* header&lt;br /&gt;
* directory hash table&lt;br /&gt;
* file hash table&lt;br /&gt;
* file allocation table&lt;br /&gt;
* directory entry table&lt;br /&gt;
* file entry table&lt;br /&gt;
* data region&lt;br /&gt;
&lt;br /&gt;
The file allocation table (FAT) forms several linked lists inside, each of which represents a &amp;quot;file&amp;quot; allocated in the data region. Please refer to the File Allocation Table section below for more detail. In some variants, the directory entry table and the file entry table are also allocated as two special &amp;quot;files&amp;quot; in the data region, managed by the FAT, while in others they are stand-alone tables located outside the data region.&lt;br /&gt;
&lt;br /&gt;
== Layout Variants ==&lt;br /&gt;
Four variants of the file system layout has been identified. A summary diagram:&lt;br /&gt;
&lt;br /&gt;
[[File:Inner-fat.png]]&lt;br /&gt;
&lt;br /&gt;
=== Savegame, &amp;lt;code&amp;gt;duplicate data = true&amp;lt;/code&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
Such savegame is a single DISA container that only has one partition which is always configured as external IVFC level 4 disabled (see [[DISA and DIFF|DISA]] format for details). All components are stored in this partition as&lt;br /&gt;
&lt;br /&gt;
* filesystem header at the beginning&lt;br /&gt;
* directory hash table&lt;br /&gt;
* file hash table&lt;br /&gt;
* file allocation table&lt;br /&gt;
* data region&lt;br /&gt;
** directory entry table is allocated inside data region&lt;br /&gt;
** file entry table as well&lt;br /&gt;
** all file data is also allocated here&lt;br /&gt;
&lt;br /&gt;
In this layout, all data is duplicated by DISA&#039;s DPFS tree, which is what the parameter &amp;lt;code&amp;gt;duplicate data&amp;lt;/code&amp;gt; implies.&lt;br /&gt;
&lt;br /&gt;
=== Savegame, &amp;lt;code&amp;gt;duplicate data = false&amp;lt;/code&amp;gt; === &lt;br /&gt;
Such savegame is a single DISA container that has two partitions. Partition A is always configured as external IVFC level 4 disabled, and partition B is configured as it enabled. Components are stored among the two partitions as&lt;br /&gt;
&lt;br /&gt;
* Partition A&lt;br /&gt;
** filesystem header at the beginning.&lt;br /&gt;
** directory hash table&lt;br /&gt;
** file hash table&lt;br /&gt;
** (stand-alone) file allocation table&lt;br /&gt;
** (stand-alone) directory entry table&lt;br /&gt;
** file entry table&lt;br /&gt;
* Partition B&lt;br /&gt;
** used as data region entirely, and only has file data allocated.&lt;br /&gt;
&lt;br /&gt;
In this layout, all file system metadata is duplicated by partition A DPFS tree, but file data is not as partition B has external IVFC level 4.&lt;br /&gt;
&lt;br /&gt;
=== Extdata ===&lt;br /&gt;
An extdata consists of several DIFF containers (device files), among which the special device file &amp;lt;code&amp;gt;00000000/00000001&amp;lt;/code&amp;gt; contains the inner FAT system, while other devices contains normal subfiles of the extdata. Please refer to [[Extdata]] for detail. The special file &amp;lt;code&amp;gt;00000000/00000001&amp;lt;/code&amp;gt; contists of the following components&lt;br /&gt;
&lt;br /&gt;
* filesystem header at the beginning&lt;br /&gt;
* directory hash table&lt;br /&gt;
* file hash table&lt;br /&gt;
* file allocation table (degenerate, because the data region only has two &amp;quot;files&amp;quot;: the directory entry table and the file entry table)&lt;br /&gt;
* data region&lt;br /&gt;
** directory entry table allocated inside data region&lt;br /&gt;
** file entry table as well&lt;br /&gt;
** normal subfiles are NOT in the data region. They are in their DIFF containers instead.&lt;br /&gt;
&lt;br /&gt;
The special file &amp;lt;code&amp;gt;00000000/00000001&amp;lt;/code&amp;gt; is configured as external IVFC level 4 disabled, and all other device files are configured as it enabled.&lt;br /&gt;
&lt;br /&gt;
=== Title database ===&lt;br /&gt;
All [[Title Database]] files are DIFF containers. Except for &amp;lt;code&amp;gt;certs.db&amp;lt;/code&amp;gt;, all of them uses this filesystem in the DIFF inner data, which consists of&lt;br /&gt;
&lt;br /&gt;
* database-specific pre-header at the beginning (See [[Title Database]])&lt;br /&gt;
* filesystem header&lt;br /&gt;
* directory Hash Table (degenerate and always has only one bucket, as there is only one directory for &amp;quot;root&amp;quot;)&lt;br /&gt;
* file Hash Table&lt;br /&gt;
* file allocation table&lt;br /&gt;
* data region&lt;br /&gt;
** directory entry table allocated inside data region (degenerate, as there is only one directory for &amp;quot;root&amp;quot;)&lt;br /&gt;
** file entry table as well&lt;br /&gt;
** title entries (title info or ticket) are allocated as normal files in the data region as well.&lt;br /&gt;
&lt;br /&gt;
== Filesystem Header ==&lt;br /&gt;
Offsets listed in the table below are all relative to the beginning of the header, while all &amp;quot;starting block index&amp;quot; are relative to the beginning of data region. This is especially important for title database, as the offsets doesn&#039;t count the pre header.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! Offset&lt;br /&gt;
! Length&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x00&lt;br /&gt;
| 4&lt;br /&gt;
| Magic (&amp;quot;SAVE&amp;quot; for savegame; &amp;quot;BDRI&amp;quot; for title database; &amp;quot;VSXE&amp;quot; for extdata)&lt;br /&gt;
|-&lt;br /&gt;
| 0x04&lt;br /&gt;
| 4&lt;br /&gt;
| Version (0x40000 for savegame; 0x30000 for title database and extdata)&lt;br /&gt;
|-&lt;br /&gt;
| 0x08&lt;br /&gt;
| 8&lt;br /&gt;
| Filesystem Information offset (Y, =0x20 for savegame and title database, =0x138 for extdata)&lt;br /&gt;
|-&lt;br /&gt;
| 0x10&lt;br /&gt;
| 8&lt;br /&gt;
| Filesystem image size in blocks (including pre header for title database)&lt;br /&gt;
|-&lt;br /&gt;
| 0x18&lt;br /&gt;
| 4&lt;br /&gt;
| Filesystem Image block size&lt;br /&gt;
|-&lt;br /&gt;
| 0x1C&lt;br /&gt;
| 4&lt;br /&gt;
| Padding&lt;br /&gt;
|-&lt;br /&gt;
| 0x20 &lt;br /&gt;
| 0x118 in total&lt;br /&gt;
| Below is additional data for extdata. Not present in savegame or title database&lt;br /&gt;
|-&lt;br /&gt;
| 0x20&lt;br /&gt;
| 8&lt;br /&gt;
| Unknown&lt;br /&gt;
|-&lt;br /&gt;
| 0x28&lt;br /&gt;
| 4&lt;br /&gt;
| &#039;Action&#039; made on most recently mounted Extdata image&lt;br /&gt;
|-&lt;br /&gt;
| 0x2C&lt;br /&gt;
| 4&lt;br /&gt;
| Unknown&lt;br /&gt;
|-&lt;br /&gt;
| 0x30&lt;br /&gt;
| 4&lt;br /&gt;
| ID of most recently mounted Extdata image&lt;br /&gt;
|-&lt;br /&gt;
| 0x34&lt;br /&gt;
| 4&lt;br /&gt;
| Unknown&lt;br /&gt;
|-&lt;br /&gt;
| 0x38&lt;br /&gt;
| 0x100&lt;br /&gt;
| Mount path, from most recently mounted Extdata image&lt;br /&gt;
|-&lt;br /&gt;
| Y &lt;br /&gt;
| 0x68 in total&lt;br /&gt;
| Below is Filesystem Information&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x00&lt;br /&gt;
| 4&lt;br /&gt;
| Unknown&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x04&lt;br /&gt;
| 4&lt;br /&gt;
| Data region block size&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x08&lt;br /&gt;
| 8&lt;br /&gt;
| Directory hash table offset&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x10&lt;br /&gt;
| 4&lt;br /&gt;
| Directory hash table bucket count (=1 for title database)&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x14&lt;br /&gt;
| 4&lt;br /&gt;
| Padding&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x18&lt;br /&gt;
| 8&lt;br /&gt;
| File hash table offset&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x20&lt;br /&gt;
| 4&lt;br /&gt;
| File hash table bucket count&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x24&lt;br /&gt;
| 4&lt;br /&gt;
| Padding&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x28&lt;br /&gt;
| 8&lt;br /&gt;
| File allocation table offset&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x30&lt;br /&gt;
| 4&lt;br /&gt;
| File allocation table entry count &lt;br /&gt;
(excluding the leading 0th entry. See below)&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x34&lt;br /&gt;
| 4&lt;br /&gt;
| Padding&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x38&lt;br /&gt;
| 8&lt;br /&gt;
| Data region offset &lt;br /&gt;
(0 for savegame &amp;lt;code&amp;gt;duplicate data = false&amp;lt;/code&amp;gt; layout, as the data region is in partition B for that layout)&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x40&lt;br /&gt;
| 4&lt;br /&gt;
| Data region block count &lt;br /&gt;
(= File allocation table entry count)&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x44&lt;br /&gt;
| 4&lt;br /&gt;
| Padding&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x48&lt;br /&gt;
| 8&lt;br /&gt;
| for savegame &amp;lt;code&amp;gt;duplicate data = false&amp;lt;/code&amp;gt; layout: directory entry table offset;&lt;br /&gt;
otherwise: u32 directory entry table starting block index + u32 directory entry table block count&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x50&lt;br /&gt;
| 4&lt;br /&gt;
| Maximum directory count, excluding the mandatory &amp;quot;root&amp;quot; directory &lt;br /&gt;
(=1 for title database, but that 1 free directory slot is never used)&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x54&lt;br /&gt;
| 4&lt;br /&gt;
| Padding&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x58&lt;br /&gt;
| 8&lt;br /&gt;
| for savegame &amp;lt;code&amp;gt;duplicate data = false&amp;lt;/code&amp;gt; layout: file entry table offset;&lt;br /&gt;
otherwise: u32 file entry table starting block index + u32 file entry table block count&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x60&lt;br /&gt;
| 4&lt;br /&gt;
| Maximum file count&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x64&lt;br /&gt;
| 4&lt;br /&gt;
| Padding&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
* For savegames, the file/directory bucket count &amp;amp; maximum count are specified by the parameters of [[FS:FormatSaveData]] or [[FS:CreateSystemSaveData]].&lt;br /&gt;
* For extdata, the maximum file/directory count are specified by the parameters of [[FS:CreateExtSaveData]]. The bucket count is likely calculated by the system.&lt;br /&gt;
* Directory &amp;amp; file entry tables are allocated in the data region as if they are two normal files (except for savegame &amp;lt;code&amp;gt;duplicate data = false&amp;lt;/code&amp;gt; layout). However, only continuous allocation has been observed, so directly reading block_count * block_size bytes from data_region + starting_block_index * block_size should be safe.&lt;br /&gt;
* For title database (except for ticket), the range specified for data region seems overflow the file end by 0x80 bytes, which is exactly the size of the pre header. This makes it as if the data region offset should be relative to the pre header instead of the BDRI header. However, further investigation on the directory/file table allocated inside the data region shows that the data region offset is indeed relative to the BDRI header. It might be a bug in 3DS that the title database files miss 0x80-byte space at the end.&lt;br /&gt;
&lt;br /&gt;
== Directory Entry Table ==&lt;br /&gt;
&lt;br /&gt;
The directory entry table is an array of the entry type shown below. It describes the directory hierarchy of the file system. There are two variants of the directory entry type, and a dummy entry type.&lt;br /&gt;
&lt;br /&gt;
=== Savegame/Extdata Variant===&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! Offset&lt;br /&gt;
! Length&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x00&lt;br /&gt;
| 4&lt;br /&gt;
| Parent directory index. 0 for root&lt;br /&gt;
|-&lt;br /&gt;
| 0x04&lt;br /&gt;
| 16&lt;br /&gt;
| ASCII directory name in. All zero for root&lt;br /&gt;
|-&lt;br /&gt;
| 0x14&lt;br /&gt;
| 4&lt;br /&gt;
| Next sibling directory index. 0 if this is the last one&lt;br /&gt;
|-&lt;br /&gt;
| 0x18&lt;br /&gt;
| 4&lt;br /&gt;
| First subdirectory index. 0 if not exists&lt;br /&gt;
|-&lt;br /&gt;
| 0x1C&lt;br /&gt;
| 4&lt;br /&gt;
| First file index in file entry table. 0 for empty directory&lt;br /&gt;
|-&lt;br /&gt;
| 0x20&lt;br /&gt;
| 4&lt;br /&gt;
| Padding / zero?&lt;br /&gt;
|-&lt;br /&gt;
| 0x24&lt;br /&gt;
| 4&lt;br /&gt;
| Index of the next directory in the same hash table bucket. 0 if this is the last one&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Title Database Variant===&lt;br /&gt;
Because title database only has one directory for &amp;quot;root&amp;quot;, its directory entry table degenerates into many zeros whose structure is not recognizable. The size of one entry here is guessed.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! Offset&lt;br /&gt;
! Length&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x00&lt;br /&gt;
| 4&lt;br /&gt;
| Parent directory index = 0 for root&lt;br /&gt;
|-&lt;br /&gt;
| 0x04&lt;br /&gt;
| 4&lt;br /&gt;
| Next sibling directory index = 0 because this is the last one&lt;br /&gt;
|-&lt;br /&gt;
| 0x08&lt;br /&gt;
| 4&lt;br /&gt;
| First subdirectory index = 0 because there is no subdirectory&lt;br /&gt;
|-&lt;br /&gt;
| 0x0C&lt;br /&gt;
| 4&lt;br /&gt;
| First file index in file entry table. 0 for empty directory&lt;br /&gt;
|-&lt;br /&gt;
| 0x10&lt;br /&gt;
| 12&lt;br /&gt;
| Padding / zero?&lt;br /&gt;
|-&lt;br /&gt;
| 0x1C&lt;br /&gt;
| 4&lt;br /&gt;
| Index of the next directory in the same hash table bucket = 0 because there is no other directory&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Dummy Entry===&lt;br /&gt;
There are also some dummy entries in the array&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! Offset&lt;br /&gt;
! Length&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x00&lt;br /&gt;
| 4&lt;br /&gt;
| Current Total entry count&lt;br /&gt;
|-&lt;br /&gt;
| 0x04&lt;br /&gt;
| 4&lt;br /&gt;
| Maximum entry count = maximum directory count + 2&lt;br /&gt;
|-&lt;br /&gt;
| 0x08&lt;br /&gt;
| 28/20&lt;br /&gt;
| Padding / All zero&lt;br /&gt;
|-&lt;br /&gt;
| 0x24/0x1C&lt;br /&gt;
| 4&lt;br /&gt;
| Index of the next dummy entry. 0 if this is the last one&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The 0-th entry of the array is always a dummy entry, which functions as the head of the dummy entry linked list. The 1-st entry of the array is always the root. Therefore maximum entry count is two more than maximum directory count. Dummy entries are left there when deleting directories, and reserved for future use.&lt;br /&gt;
&lt;br /&gt;
== File Entry Table ==&lt;br /&gt;
&lt;br /&gt;
The file entry table is an array of the entry type shown below. It contains information for each file. There are three variants of the file entry type, and a dummy entry type.&lt;br /&gt;
&lt;br /&gt;
=== Savegame Variant ===&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! Offset&lt;br /&gt;
! Length&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x00&lt;br /&gt;
| 4&lt;br /&gt;
| Parent directory index in directory entry table&lt;br /&gt;
|-&lt;br /&gt;
| 0x04&lt;br /&gt;
| 16&lt;br /&gt;
| ASCII file name&lt;br /&gt;
|-&lt;br /&gt;
| 0x14&lt;br /&gt;
| 4&lt;br /&gt;
| Next sibling file index. 0 if this is the last one&lt;br /&gt;
|-&lt;br /&gt;
| 0x18&lt;br /&gt;
| 4&lt;br /&gt;
| Padding&lt;br /&gt;
|-&lt;br /&gt;
| 0x1C&lt;br /&gt;
| 4&lt;br /&gt;
| First block index in data region. 0x80000000 if the file is just created and has no data.&lt;br /&gt;
|-&lt;br /&gt;
| 0x20&lt;br /&gt;
| 8&lt;br /&gt;
| File Size&lt;br /&gt;
|-&lt;br /&gt;
| 0x28&lt;br /&gt;
| 4&lt;br /&gt;
| Padding?&lt;br /&gt;
|-&lt;br /&gt;
| 0x2C&lt;br /&gt;
| 4&lt;br /&gt;
| Index of the next file in the same hash table bucket. 0 if this is the last one&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Extdata Variant ===&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! Offset&lt;br /&gt;
! Length&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x00&lt;br /&gt;
| 4&lt;br /&gt;
| Parent directory index in directory entry table&lt;br /&gt;
|-&lt;br /&gt;
| 0x04&lt;br /&gt;
| 16&lt;br /&gt;
| ASCII file name&lt;br /&gt;
|-&lt;br /&gt;
| 0x14&lt;br /&gt;
| 4&lt;br /&gt;
| Next sibling file index. 0 if this is the last one&lt;br /&gt;
|-&lt;br /&gt;
| 0x18&lt;br /&gt;
| 4&lt;br /&gt;
| Padding&lt;br /&gt;
|-&lt;br /&gt;
| 0x1C&lt;br /&gt;
| 4&lt;br /&gt;
| Always 0x80000000&lt;br /&gt;
|-&lt;br /&gt;
| 0x20&lt;br /&gt;
| 8&lt;br /&gt;
| Unique identifier. See [[Extdata]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x28&lt;br /&gt;
| 4&lt;br /&gt;
| Padding?&lt;br /&gt;
|-&lt;br /&gt;
| 0x2C&lt;br /&gt;
| 4&lt;br /&gt;
| Index of the next file in the same hash table bucket. 0 if this is the last one&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Title database Variant ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! Offset&lt;br /&gt;
! Length&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x00&lt;br /&gt;
| 4&lt;br /&gt;
| Parent directory index in directory entry table&lt;br /&gt;
|-&lt;br /&gt;
| 0x04&lt;br /&gt;
| 8&lt;br /&gt;
| Title ID&lt;br /&gt;
|-&lt;br /&gt;
| 0x0C&lt;br /&gt;
| 4&lt;br /&gt;
| Next sibling file index. 0 if this is the last one&lt;br /&gt;
|-&lt;br /&gt;
| 0x10&lt;br /&gt;
| 4&lt;br /&gt;
| Padding&lt;br /&gt;
|-&lt;br /&gt;
| 0x14&lt;br /&gt;
| 4&lt;br /&gt;
| First block index in data region.&lt;br /&gt;
|-&lt;br /&gt;
| 0x18&lt;br /&gt;
| 8&lt;br /&gt;
| File size&lt;br /&gt;
|-&lt;br /&gt;
| 0x20&lt;br /&gt;
| 8&lt;br /&gt;
| Padding?&lt;br /&gt;
|-&lt;br /&gt;
| 0x28&lt;br /&gt;
| 4&lt;br /&gt;
| Index of the next file in the same hash table bucket. 0 if this is the last one&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Dummy Entry ===&lt;br /&gt;
Like directory entry table, file entry table also has some dummy entries:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! Offset&lt;br /&gt;
! Length&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x00&lt;br /&gt;
| 4&lt;br /&gt;
| Current total entry count&lt;br /&gt;
|-&lt;br /&gt;
| 0x04&lt;br /&gt;
| 4&lt;br /&gt;
| Maximum entry count = maximum file count + 1&lt;br /&gt;
|-&lt;br /&gt;
| 0x08&lt;br /&gt;
| 36/32&lt;br /&gt;
| Padding / All zero&lt;br /&gt;
|-&lt;br /&gt;
| 0x2C/0x28&lt;br /&gt;
| 4&lt;br /&gt;
| Index of the next dummy entry. 0 if this is the last one&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The 0-th entry of the array is always a dummy entry, which functions as the head of the dummy entry linked list. Therefore maximum entry count is one more than maximum file count. Dummy entries are left there when deleting files, and reserved for future use.&lt;br /&gt;
&lt;br /&gt;
== Directory Hash Table &amp;amp;amp; File Hash Table ==&lt;br /&gt;
&lt;br /&gt;
This is a u32 array of size = bucket count, each of which is an index to the directory / file entry table. The directory / file name is hashed and its entry index is put to the corresponding bucket. If there is already a directory/file entry in the bucket, then it appends to the linked list formed by &amp;lt;code&amp;gt;Index of the next directory/file in the same hash table bucket&amp;lt;/code&amp;gt; field in the directory/file entry table. i.e. this is a hash table using separate chaining with linked lists&lt;br /&gt;
&lt;br /&gt;
The hash function takes the parent index and the ASCII name (or title ID for title database) as key. The function is equivalent to&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;uint32_t GetBucket(&lt;br /&gt;
    uint8_t name[16 or 8], // For savegame/extdata, this takes all 16 bytes including trailing zeros; For title database, this is the 8-byte title ID&lt;br /&gt;
    uint32_t parent_dir_index,&lt;br /&gt;
    uint32_t bucket_count&lt;br /&gt;
) {&lt;br /&gt;
    uint32_t hash = parent_dir_index ^ 0x091A2B3C;&lt;br /&gt;
    for (int i = 0; i &amp;amp;lt; 4 or 2; ++i) {&lt;br /&gt;
        hash = (hash &amp;amp;gt;&amp;amp;gt; 1) | (hash &amp;amp;lt;&amp;amp;lt; 31);&lt;br /&gt;
        hash ^= (uint32_t)name[i * 4]&lt;br /&gt;
        hash ^= (uint32_t)name[i * 4 + 1] &amp;amp;lt;&amp;amp;lt; 8&lt;br /&gt;
        hash ^= (uint32_t)name[i * 4 + 2] &amp;amp;lt;&amp;amp;lt; 16&lt;br /&gt;
        hash ^= (uint32_t)name[i * 4 + 3] &amp;amp;lt;&amp;amp;lt; 24&lt;br /&gt;
    }&lt;br /&gt;
    return hash % bucket_count;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== File Allocation Table ==&lt;br /&gt;
&lt;br /&gt;
The file allocation table is an array of a 8-byte entry shown below. The array size is actually &#039;&#039;one larger than&#039;&#039; the size recorded in the filesystem header. Each entry corresponds to a block in the data region (the block size is defined in filesystem header). However, the 0th entry corresponds to nothing, so the corresponding block index is off by one. e.g. entry 31 in this table corresponds to block 30 in the data region.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! Offset&lt;br /&gt;
! Length&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x00&lt;br /&gt;
| 4&lt;br /&gt;
| bit[0:30]: Index U; bit[31]: Flag U&lt;br /&gt;
|-&lt;br /&gt;
| 0x04&lt;br /&gt;
| 4&lt;br /&gt;
| bit[0:30]: Index V; bit[31]: Flag V&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Entries in this table forms several chains, representing how blocks in the data region should be linked together. However, unlike normal FAT systems, which uses chains of entries, 3DS savegames use chain of &#039;&#039;nodes&#039;&#039;. Each node spans one or multiple entries.&lt;br /&gt;
&lt;br /&gt;
One node spanning &amp;lt;code&amp;gt;n&amp;lt;/code&amp;gt; entries starting from &amp;lt;code&amp;gt;FAT[k]&amp;lt;/code&amp;gt; is in the following format:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;FAT[k + 0]:&lt;br /&gt;
    Index_U = index of the first entry of the previous node. 0 if this is the first node.&lt;br /&gt;
    Index_V = index of the first entry of the next node. 0 if this is the last node.&lt;br /&gt;
    Flag_U set if this is the first node.&lt;br /&gt;
    Flag_V set if this node has multiple entries.&lt;br /&gt;
&lt;br /&gt;
FAT[k + 1]:&lt;br /&gt;
    Index_U = k (the first entry index of this node)&lt;br /&gt;
    Index_V = k + n - 1 (the last entry index of this node)&lt;br /&gt;
    Flag_U always set&lt;br /&gt;
    Flag_V always clear&lt;br /&gt;
&lt;br /&gt;
FAT[k + 2] ~ FAT[k + n - 2]:&lt;br /&gt;
    All these entries are uninitialized&lt;br /&gt;
&lt;br /&gt;
FAT[k + n - 1]:&lt;br /&gt;
    Index_U = k&lt;br /&gt;
    Index_V = k + n - 1&lt;br /&gt;
    Flag_U always set&lt;br /&gt;
    Flag_V always clear&lt;br /&gt;
    (Same values as FAT[k + 1])&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* Note: all indices above are entry indices (block index + 1)&lt;br /&gt;
&lt;br /&gt;
All free blocks that are not allocated to any files also form a node chain in the allocation table. The head index of this &amp;amp;quot;free chain&amp;amp;quot; is recorded in &amp;lt;code&amp;gt;FAT[0].Index_V&amp;lt;/code&amp;gt;. Other fields of &amp;lt;code&amp;gt;FAT[0]&amp;lt;/code&amp;gt; are all zero&lt;br /&gt;
&lt;br /&gt;
Here is an example: &lt;br /&gt;
&lt;br /&gt;
[[File:Disa-fat.png]]&lt;br /&gt;
&lt;br /&gt;
For extdata, because only two &amp;quot;files&amp;quot; (directory and file entry tables) are allocated in the data region, and their size never changes once the extdata is created, they are guaranteed continuous in the data region, and the FAT degenerates to two big nodes. Therefore, instead of going through FAT, the offset and size of directory / file entry table can be found directly by offset = entry_table_starting block * data_region_block_size + data_region_offset and size = entry_table_block_count * data_region_block_size.&lt;/div&gt;</summary>
		<author><name>Wwylele</name></author>
	</entry>
	<entry>
		<id>https://www.3dbrew.org/w/index.php?title=RomFS&amp;diff=21155</id>
		<title>RomFS</title>
		<link rel="alternate" type="text/html" href="https://www.3dbrew.org/w/index.php?title=RomFS&amp;diff=21155"/>
		<updated>2020-01-24T14:58:39Z</updated>

		<summary type="html">&lt;p&gt;Wwylele: Undo revision 21154 by Marius851000 (talk) This is not true. I opened one of RomFS of an official game I have. The root directory has the &amp;quot;Offset of first Child Directory&amp;quot; = 0x18, implying the root directory entry located at offset 0 is 0x18 bytes, which would contain the &amp;quot;Name Length&amp;quot; field. The said field also has value 0 as expected.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=== Overview ===&lt;br /&gt;
RomFS (or Read-Only Filesystem) is part of the [[NCCH]] format, and is used as external file storage.&lt;br /&gt;
&lt;br /&gt;
RomFS can be used:&lt;br /&gt;
&lt;br /&gt;
*in conjunction with the [[ExeFS]] of a NCCH&lt;br /&gt;
&lt;br /&gt;
*to contain the game manual accessible from the [[Home Menu]]&lt;br /&gt;
&lt;br /&gt;
*to contain the [[Download Play#Broadcasted application data|DLP Child CIA]])&lt;br /&gt;
&lt;br /&gt;
*or to contain game cartridge update data&lt;br /&gt;
&lt;br /&gt;
(There may be more implementations in the future)&lt;br /&gt;
&lt;br /&gt;
=== Format ===&lt;br /&gt;
&lt;br /&gt;
The RomFS is wrapped inside a IVFC hash-tree container, and the actual data is structured like a node-based tree, starting at the root level directory node, moving down to other directory and file nodes. Each directory node  has pointers to child directory nodes and siblings, together with a pointer to the first file node for that directory. Each file node has pointers to their next file node, together with information about the actual file data.&lt;br /&gt;
&lt;br /&gt;
The RomFS IVFC hash-tree header is 0x5C bytes long and is structured 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;
!  START&lt;br /&gt;
!  SIZE&lt;br /&gt;
!  DESCRIPTION&lt;br /&gt;
|-&lt;br /&gt;
|  0x00&lt;br /&gt;
|  0x4&lt;br /&gt;
|  Magic &amp;quot;IVFC&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| 0x04&lt;br /&gt;
| 0x4&lt;br /&gt;
| Magic number 0x10000&lt;br /&gt;
|-&lt;br /&gt;
| 0x08&lt;br /&gt;
| 0x4&lt;br /&gt;
| Master hash size&lt;br /&gt;
|-&lt;br /&gt;
| 0x0C&lt;br /&gt;
| 0x8&lt;br /&gt;
| Level 1 logical offset&lt;br /&gt;
|-&lt;br /&gt;
| 0x14&lt;br /&gt;
| 0x8&lt;br /&gt;
| Level 1 hashdata size&lt;br /&gt;
|-&lt;br /&gt;
| 0x1C&lt;br /&gt;
| 0x4&lt;br /&gt;
| Level 1 block size, in log2&lt;br /&gt;
|-&lt;br /&gt;
| 0x20&lt;br /&gt;
| 0x4&lt;br /&gt;
| Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x24&lt;br /&gt;
| 0x8&lt;br /&gt;
| Level 2 logical offset&lt;br /&gt;
|-&lt;br /&gt;
| 0x2C&lt;br /&gt;
| 0x8&lt;br /&gt;
| Level 2 hashdata size&lt;br /&gt;
|-&lt;br /&gt;
| 0x34&lt;br /&gt;
| 0x4&lt;br /&gt;
| Level 2 block size, in log2.&lt;br /&gt;
|-&lt;br /&gt;
| 0x38&lt;br /&gt;
| 0x4&lt;br /&gt;
| Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x3C&lt;br /&gt;
| 0x8&lt;br /&gt;
| Level 3 logical offset&lt;br /&gt;
|-&lt;br /&gt;
| 0x44&lt;br /&gt;
| 0x8&lt;br /&gt;
| Level 3 hashdata size&lt;br /&gt;
|-&lt;br /&gt;
| 0x4C&lt;br /&gt;
| 0x4&lt;br /&gt;
| Level 3 block size, in log2.&lt;br /&gt;
|-&lt;br /&gt;
| 0x50&lt;br /&gt;
| 0x4&lt;br /&gt;
| Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x54&lt;br /&gt;
| 0x4&lt;br /&gt;
| Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x58&lt;br /&gt;
| 0x4&lt;br /&gt;
| Optional info size.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Level 3 Format ===&lt;br /&gt;
&lt;br /&gt;
The Level 3 partition of a RomFS consists of a header specifying offsets to four tables, followed by filedata (aligned to 16-bytes). Though their size varies by RomFS contents, the tables are always sequential and in the same order, 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;
!  START&lt;br /&gt;
!  SIZE&lt;br /&gt;
!  DESCRIPTION&lt;br /&gt;
|-&lt;br /&gt;
|  0x0&lt;br /&gt;
|  0x28&lt;br /&gt;
|  Header&lt;br /&gt;
|-&lt;br /&gt;
|  0x28&lt;br /&gt;
|  Varies&lt;br /&gt;
|  Directory HashKey Table&lt;br /&gt;
|-&lt;br /&gt;
|  Varies&lt;br /&gt;
|  Varies&lt;br /&gt;
|  Directory Metadata Table&lt;br /&gt;
|-&lt;br /&gt;
|  Varies&lt;br /&gt;
|  Varies&lt;br /&gt;
|  File HashKey Table&lt;br /&gt;
|-&lt;br /&gt;
|  Varies&lt;br /&gt;
|  Varies&lt;br /&gt;
|  File Metadata Table&lt;br /&gt;
|-&lt;br /&gt;
|  Varies&lt;br /&gt;
|  Varies&lt;br /&gt;
|  File Data&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Level 3 Header Format ===&lt;br /&gt;
&lt;br /&gt;
RomFS Header data is always 0x28 bytes long, and follows this layout (offsets are from the start of the header):&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
!  START&lt;br /&gt;
!  SIZE&lt;br /&gt;
!  DESCRIPTION&lt;br /&gt;
|-&lt;br /&gt;
|  0x0&lt;br /&gt;
|  0x4&lt;br /&gt;
|  Header Length&lt;br /&gt;
|-&lt;br /&gt;
|  0x4&lt;br /&gt;
|  0x4&lt;br /&gt;
|  Directory Hash Table Offset&lt;br /&gt;
|-&lt;br /&gt;
|  0x8&lt;br /&gt;
|  0x4&lt;br /&gt;
|  Directory Hash Table Length&lt;br /&gt;
|-&lt;br /&gt;
|  0xC&lt;br /&gt;
|  0x4&lt;br /&gt;
|  Directory Metadata Table Offset&lt;br /&gt;
|-&lt;br /&gt;
|  0x10&lt;br /&gt;
|  0x4&lt;br /&gt;
|  Directory Metadata Table Length&lt;br /&gt;
|-&lt;br /&gt;
|  0x14&lt;br /&gt;
|  0x4&lt;br /&gt;
|  File Hash Table Offset&lt;br /&gt;
|-&lt;br /&gt;
|  0x18&lt;br /&gt;
|  0x4&lt;br /&gt;
|  File Hash Table Length&lt;br /&gt;
|-&lt;br /&gt;
|  0x1C&lt;br /&gt;
|  0x4&lt;br /&gt;
|  File Metadata Table Offset&lt;br /&gt;
|-&lt;br /&gt;
|  0x20&lt;br /&gt;
|  0x4&lt;br /&gt;
|  File Metadata Table Length&lt;br /&gt;
|-&lt;br /&gt;
|  0x24&lt;br /&gt;
|  0x4&lt;br /&gt;
|  File Data Offset&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Directory Metadata Structure ===&lt;br /&gt;
&lt;br /&gt;
When a RomFS is built, directories are added recursively starting with the root. When a directory is added, all of its files are added to the File Metadata Table, then all of its subdirectories (if any), are added to the table. If any of the directory&#039;s subdirectories have their own subdirectories, the current directory&#039;s subdirectories are all added before the subdirectories&#039; subdirectories are added.&lt;br /&gt;
&lt;br /&gt;
A Metadata entry for a directory has the following structure (all values are initialized to 0xFFFFFFFF, and remain that way when unused):&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
!  START&lt;br /&gt;
!  SIZE&lt;br /&gt;
!  DESCRIPTION&lt;br /&gt;
|-&lt;br /&gt;
|  0x0&lt;br /&gt;
|  0x4&lt;br /&gt;
|  Offset of Parent Directory (self if Root)&lt;br /&gt;
|-&lt;br /&gt;
|  0x4&lt;br /&gt;
|  0x4&lt;br /&gt;
|  Offset of next Sibling Directory&lt;br /&gt;
|-&lt;br /&gt;
|  0x8&lt;br /&gt;
|  0x4&lt;br /&gt;
|  Offset of first Child Directory (Subdirectory)&lt;br /&gt;
|-&lt;br /&gt;
|  0xC&lt;br /&gt;
|  0x4&lt;br /&gt;
|  Offset of first File (in File Metadata Table)&lt;br /&gt;
|-&lt;br /&gt;
|  0x10&lt;br /&gt;
|  0x4&lt;br /&gt;
|  Offset of next Directory in the same Hash Table bucket&lt;br /&gt;
|-&lt;br /&gt;
|  0x14&lt;br /&gt;
|  0x4&lt;br /&gt;
|  Name Length&lt;br /&gt;
|-&lt;br /&gt;
|  0x18&lt;br /&gt;
|  Name Length (rounded up to multiple of 4)&lt;br /&gt;
|  Directory Name (Unicode)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== File Metadata Structure ===&lt;br /&gt;
&lt;br /&gt;
A Metadata entry for a file has the following structure (all values are initialized to 0xFFFFFFFF, and remain that way when unused):&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
!  START&lt;br /&gt;
!  SIZE&lt;br /&gt;
!  DESCRIPTION&lt;br /&gt;
|-&lt;br /&gt;
|  0x0&lt;br /&gt;
|  0x4&lt;br /&gt;
|  Offset of Containing Directory (within Directory Metadata Table)&lt;br /&gt;
|-&lt;br /&gt;
|  0x4&lt;br /&gt;
|  0x4&lt;br /&gt;
|  Offset of next Sibling File&lt;br /&gt;
|-&lt;br /&gt;
|  0x8&lt;br /&gt;
|  0x8&lt;br /&gt;
|  Offset of File&#039;s Data&lt;br /&gt;
|-&lt;br /&gt;
|  0x10&lt;br /&gt;
|  0x8&lt;br /&gt;
|  Length of File&#039;s Data&lt;br /&gt;
|-&lt;br /&gt;
|  0x18&lt;br /&gt;
|  0x4&lt;br /&gt;
|  Offset of next File in the same Hash Table bucket&lt;br /&gt;
|-&lt;br /&gt;
|  0x1C&lt;br /&gt;
|  0x4&lt;br /&gt;
|  Name Length&lt;br /&gt;
|-&lt;br /&gt;
|  0x20&lt;br /&gt;
|  Name Length (rounded up to multiple of 4)&lt;br /&gt;
|  File Name (Unicode)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Hash Table Structure ===&lt;br /&gt;
&lt;br /&gt;
For both files and directories, a [https://en.wikipedia.org/wiki/Hash_table#Collision_resolution separate chaining hash table] is created for quick lookup.&lt;br /&gt;
&lt;br /&gt;
A hash table consists of a number of buckets, all initialized to 0xFFFFFFFF. The size of the table is dependent on the number of entries in the relevant MetaData table (it&#039;s probably intended to always be the smallest prime number greater than or equal to the number of entries, but the implementation was lazy), illustrated by the following code (C#):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
		public static byte[] GetHashTableLength(uint numEntries)&lt;br /&gt;
		{&lt;br /&gt;
			uint count = numEntries;&lt;br /&gt;
			if (numEntries &amp;lt; 3)&lt;br /&gt;
				count = 3;&lt;br /&gt;
			else if (numEntries &amp;lt; 19)&lt;br /&gt;
				count |= 1;&lt;br /&gt;
			else&lt;br /&gt;
			{&lt;br /&gt;
				while (count % 2 == 0 &lt;br /&gt;
					|| count % 3 == 0 &lt;br /&gt;
					|| count % 5 == 0 &lt;br /&gt;
					|| count % 7 == 0 &lt;br /&gt;
					|| count % 11 == 0 &lt;br /&gt;
					|| count % 13 == 0 &lt;br /&gt;
					|| count % 17 == 0)&lt;br /&gt;
				{&lt;br /&gt;
					count++;&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
			return count;&lt;br /&gt;
		}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The hash function is based off directory/file name (byte array taken from Metadata entry) and Parent Directory&#039;s offset (C#):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
		public static uint CalcPathHash(byte[] Name, uint ParentOffset)&lt;br /&gt;
		{&lt;br /&gt;
			uint hash = ParentOffset ^ 123456789;&lt;br /&gt;
			for (int i = 0; i &amp;lt; Name.Length; i += 2)&lt;br /&gt;
			{&lt;br /&gt;
				hash = (hash &amp;gt;&amp;gt; 5) | (hash &amp;lt;&amp;lt; 27);&lt;br /&gt;
				hash ^= (ushort)((Name[i]) | (Name[i + 1] &amp;lt;&amp;lt; 8));&lt;br /&gt;
			}&lt;br /&gt;
			return hash;&lt;br /&gt;
		}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Each directory/file is put into the &#039;&#039;i&#039;&#039;th bucket, where &#039;&#039;i&#039;&#039; is the hash taken modulus of bucket count. The directories/files in the same bucket form a linked list, with the value in hash table as the offset to the head element. When creating the hash table, a latter added directory/file is always added as the head element of the linked list.&lt;/div&gt;</summary>
		<author><name>Wwylele</name></author>
	</entry>
	<entry>
		<id>https://www.3dbrew.org/w/index.php?title=DISA_and_DIFF&amp;diff=21144</id>
		<title>DISA and DIFF</title>
		<link rel="alternate" type="text/html" href="https://www.3dbrew.org/w/index.php?title=DISA_and_DIFF&amp;diff=21144"/>
		<updated>2020-01-02T05:21:18Z</updated>

		<summary type="html">&lt;p&gt;Wwylele: /* Summary diagram */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This page describes DISA and DIFF format as the underlying container of [[Savegames]], [[Extdata]] and [[Title Database]]. For further format specification of the inner data, please refer to their own page.&lt;br /&gt;
&lt;br /&gt;
All data in this page is little-endian. All &amp;quot;unused / padding&amp;quot; fields can contain uninitialized data unless otherwise specified.&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
&lt;br /&gt;
DISA and DIFF are two container formats. They are very similar and are used for various purposes in 3DS. Here is a summary table of their usage, the CMAC type and the AES key slot used (the meaning of these is explained in the next section):&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! Usage&lt;br /&gt;
! Media&lt;br /&gt;
! Container format&lt;br /&gt;
! [[#AES CMAC|CMAC type]]&lt;br /&gt;
! CMAC [[AES Registers|Keyslot]]&lt;br /&gt;
|-&lt;br /&gt;
| [[Savegames]]&lt;br /&gt;
| Gamecard&lt;br /&gt;
| DISA&lt;br /&gt;
| [[#CTR-NOR0|CTR-NOR0]]&lt;br /&gt;
| 0x19 / 0x33&lt;br /&gt;
|-&lt;br /&gt;
| [[Savegames]]&lt;br /&gt;
| [[SD Filesystem|SD]]&lt;br /&gt;
| DISA&lt;br /&gt;
| [[#CTR-SIGN|CTR-SIGN]]&lt;br /&gt;
| 0x30&lt;br /&gt;
|-&lt;br /&gt;
| [[System SaveData]]&lt;br /&gt;
| [[Flash Filesystem|NAND]]&lt;br /&gt;
| DISA&lt;br /&gt;
| [[#CTR-SYS0|CTR-SYS0]]&lt;br /&gt;
| 0x30&lt;br /&gt;
|-&lt;br /&gt;
| [[Extdata|Private Extdata]]&lt;br /&gt;
| [[SD Filesystem|SD]]&lt;br /&gt;
| DIFF&lt;br /&gt;
| [[#CTR-EXT0|CTR-EXT0]]&lt;br /&gt;
| 0x30&lt;br /&gt;
|-&lt;br /&gt;
| [[Extdata|Shared Extdata]]&lt;br /&gt;
| [[Flash Filesystem|NAND]]&lt;br /&gt;
| DIFF&lt;br /&gt;
| [[#CTR-EXT0|CTR-EXT0]]&lt;br /&gt;
| 0x30&lt;br /&gt;
|-&lt;br /&gt;
| [[Title Database]]&lt;br /&gt;
| [[SD Filesystem|SD]]&lt;br /&gt;
| DIFF&lt;br /&gt;
| [[#CTR-9DB0|CTR-9DB0]]&lt;br /&gt;
| 0x30&lt;br /&gt;
|-&lt;br /&gt;
| [[Title Database]]&lt;br /&gt;
| [[Flash Filesystem|NAND]]&lt;br /&gt;
| DIFF&lt;br /&gt;
| [[#CTR-9DB0|CTR-9DB0]]&lt;br /&gt;
| 0x0B&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Encryption ==&lt;br /&gt;
&lt;br /&gt;
DISA and DIFF formats don&#039;t have their own encryption specification. They follow the encryption method defined by their media:&lt;br /&gt;
&lt;br /&gt;
* Gamecard savegames have special wear leveling + encryption layers. See [[Savegames]] for detail.&lt;br /&gt;
* Files on SD follow [[SD Filesystem|the general SD filesystem encryption rule]].&lt;br /&gt;
* Files on NAND are in cleartext, after decrypting [[Flash Filesystem|the NAND partition encryption]].&lt;br /&gt;
&lt;br /&gt;
== Format ==&lt;br /&gt;
&lt;br /&gt;
A DISA / DIFF file consists of the following components:&lt;br /&gt;
&lt;br /&gt;
* 0x100-byte AES CMAC&lt;br /&gt;
* 0x100-byte Header&lt;br /&gt;
* Secondary partition table&lt;br /&gt;
** Contains one or two partition descriptors, depending on the number of partitions.&lt;br /&gt;
* Primary partition table&lt;br /&gt;
** Same layout as the secondary one&lt;br /&gt;
* Partition A&lt;br /&gt;
* Partition B (optional)&lt;br /&gt;
** can only exist for DISA.&lt;br /&gt;
&lt;br /&gt;
== AES CMAC ==&lt;br /&gt;
&lt;br /&gt;
The AES CMAC is located at the beginning of the DISA / DIFF image, and it is 0x10 long. The rest 0xF0 bytes before the header are unused.&lt;br /&gt;
&lt;br /&gt;
The key used for the AES CMAC is generated by the [[AES Registers|hardware key engine]]. See the keyslot it uses in the table above.&lt;br /&gt;
&lt;br /&gt;
The data being authenticated by the AES CMAC is a 0x20-byte SHA-256 hash of a data block. The data block has different content formats among CMAC types. All types of data block contain a copy or a hash of the header, which is the start of the the rest of the verification chain, so the AES CMAC effectively authenticates the whole save image. Each type of data block is explained below.&lt;br /&gt;
&lt;br /&gt;
=== CTR-NOR0 ===&lt;br /&gt;
&lt;br /&gt;
This CMAC type is used for gamecard savegames. It is 0x28-byte long.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! Offset&lt;br /&gt;
! Length&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x00&lt;br /&gt;
| 8&lt;br /&gt;
| Magic &amp;amp;quot;CTR-NOR0&amp;amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| 0x8&lt;br /&gt;
| 0x20&lt;br /&gt;
| SHA-256 of the following 0x108-byte block&lt;br /&gt;
 {| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! Offset&lt;br /&gt;
! Length&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x00&lt;br /&gt;
| 8&lt;br /&gt;
| Magic &amp;amp;quot;CTR-SAV0&amp;amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| 0x08&lt;br /&gt;
| 0x100&lt;br /&gt;
| Copy of the DISA header&lt;br /&gt;
|}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== CTR-SIGN ===&lt;br /&gt;
&lt;br /&gt;
This CMAC type is used for SD savegames. It is 0x30-byte long.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! Offset&lt;br /&gt;
! Length&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x00&lt;br /&gt;
| 8&lt;br /&gt;
| Magic &amp;amp;quot;CTR-SIGN&amp;amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| 0x08&lt;br /&gt;
| 8&lt;br /&gt;
| Title ID&lt;br /&gt;
|-&lt;br /&gt;
| 0x10&lt;br /&gt;
| 0x20&lt;br /&gt;
| SHA-256 of the following 0x108-byte block&lt;br /&gt;
 {| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! Offset&lt;br /&gt;
! Length&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x00&lt;br /&gt;
| 8&lt;br /&gt;
| Magic &amp;amp;quot;CTR-SAV0&amp;amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| 0x08&lt;br /&gt;
| 0x100&lt;br /&gt;
| Copy of the DISA header&lt;br /&gt;
|}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== CTR-SYS0 ===&lt;br /&gt;
&lt;br /&gt;
This CMAC type is used for NAND system save. It is 0x110-byte long.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! Offset&lt;br /&gt;
! Length&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x00&lt;br /&gt;
| 8&lt;br /&gt;
| Magic &amp;amp;quot;CTR-SYS0&amp;amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| 0x08&lt;br /&gt;
| 8&lt;br /&gt;
| Save ID. The higher word is always zero&lt;br /&gt;
|-&lt;br /&gt;
| 0x10&lt;br /&gt;
| 0x100&lt;br /&gt;
| Copy of the DISA header&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== CTR-EXT0 ===&lt;br /&gt;
&lt;br /&gt;
This CMAC type is used for extdata. It is 0x11C-byte long.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! Offset&lt;br /&gt;
! Length&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x00&lt;br /&gt;
| 8&lt;br /&gt;
| Magic &amp;amp;quot;CTR-EXT0&amp;amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| 0x08&lt;br /&gt;
| 8&lt;br /&gt;
| Extdata ID&lt;br /&gt;
|-&lt;br /&gt;
| 0x10&lt;br /&gt;
| 4&lt;br /&gt;
| 0 for Quota.dat, 1 otherwise&lt;br /&gt;
|-&lt;br /&gt;
| 0x14&lt;br /&gt;
| 4&lt;br /&gt;
| ID in the device file name. 0 for Quota.dat&lt;br /&gt;
|-&lt;br /&gt;
| 0x18&lt;br /&gt;
| 4&lt;br /&gt;
| ID in the device directory name that the file is in. 0 for Quota.dat&lt;br /&gt;
|-&lt;br /&gt;
| 0x1C&lt;br /&gt;
| 0x100&lt;br /&gt;
| Copy of the DIFF header&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== CTR-9DB0 ===&lt;br /&gt;
&lt;br /&gt;
This CMAC type is used for title database. It is 0x10C-byte long.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! Offset&lt;br /&gt;
! Length&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x00&lt;br /&gt;
| 8&lt;br /&gt;
| Magic &amp;amp;quot;CTR-9DB0&amp;amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| 0x08&lt;br /&gt;
| 4&lt;br /&gt;
| Database ID. Each .db file has its own ID&lt;br /&gt;
|-&lt;br /&gt;
| 0x0C&lt;br /&gt;
| 0x100&lt;br /&gt;
| Copy of the DIFF header&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Header ==&lt;br /&gt;
&lt;br /&gt;
The header located at offset 0x100 defines the rest components of the file (partitions and their tables). All offsets in the header are relative to the beginning of the DISA/DIFF file, except for partition descriptor offsets, which are relative to the beginning of the (active) partition table. DISA and DIFF have different header format.&lt;br /&gt;
&lt;br /&gt;
=== DISA header ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! Offset&lt;br /&gt;
! Length&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x00&lt;br /&gt;
| 4&lt;br /&gt;
| Magic &amp;amp;quot;DISA&amp;amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| 0x04&lt;br /&gt;
| 4&lt;br /&gt;
| Magic 0x40000&lt;br /&gt;
|-&lt;br /&gt;
| 0x08&lt;br /&gt;
| 4&lt;br /&gt;
| Partition count, 1 or 2&lt;br /&gt;
|-&lt;br /&gt;
| 0x0C&lt;br /&gt;
| 4&lt;br /&gt;
| Padding&lt;br /&gt;
|-&lt;br /&gt;
| 0x10&lt;br /&gt;
| 8&lt;br /&gt;
| Secondary partition table offset&lt;br /&gt;
|-&lt;br /&gt;
| 0x18&lt;br /&gt;
| 8&lt;br /&gt;
| Primary partition table offset&lt;br /&gt;
|-&lt;br /&gt;
| 0x20&lt;br /&gt;
| 8&lt;br /&gt;
| Partition table size&lt;br /&gt;
|-&lt;br /&gt;
| 0x28&lt;br /&gt;
| 8&lt;br /&gt;
| Partition A descriptor offset in the partition table&lt;br /&gt;
|-&lt;br /&gt;
| 0x30&lt;br /&gt;
| 8&lt;br /&gt;
| Partition A descriptor size&lt;br /&gt;
|-&lt;br /&gt;
| 0x38&lt;br /&gt;
| 8&lt;br /&gt;
| Partition B descriptor offset in the partition table&lt;br /&gt;
|-&lt;br /&gt;
| 0x40&lt;br /&gt;
| 8&lt;br /&gt;
| Partition B descriptor size&lt;br /&gt;
|-&lt;br /&gt;
| 0x48&lt;br /&gt;
| 8&lt;br /&gt;
| Partition A offset&lt;br /&gt;
|-&lt;br /&gt;
| 0x50&lt;br /&gt;
| 8&lt;br /&gt;
| Partition A size&lt;br /&gt;
|-&lt;br /&gt;
| 0x58&lt;br /&gt;
| 8&lt;br /&gt;
| Partition B offset&lt;br /&gt;
|-&lt;br /&gt;
| 0x60&lt;br /&gt;
| 8&lt;br /&gt;
| Partition B size&lt;br /&gt;
|-&lt;br /&gt;
| 0x68&lt;br /&gt;
| 1&lt;br /&gt;
| Active partition table, 0 = primary, 1 = secondary&lt;br /&gt;
|-&lt;br /&gt;
| 0x69&lt;br /&gt;
| 3&lt;br /&gt;
| Padding&lt;br /&gt;
|-&lt;br /&gt;
| 0x6C&lt;br /&gt;
| 0x20&lt;br /&gt;
| SHA-256 over the active partition table&lt;br /&gt;
|-&lt;br /&gt;
| 0x8C&lt;br /&gt;
| 0x74&lt;br /&gt;
| Unused&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Note:&lt;br /&gt;
&lt;br /&gt;
* When the partition count is 1, there is no partition B and all of its related fields are zero.&lt;br /&gt;
&lt;br /&gt;
=== DIFF header ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! Offset&lt;br /&gt;
! Length&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x00&lt;br /&gt;
| 4&lt;br /&gt;
| Magic &amp;amp;quot;DIFF&amp;amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| 0x04&lt;br /&gt;
| 4&lt;br /&gt;
| Magic 0x30000&lt;br /&gt;
|-&lt;br /&gt;
| 0x08&lt;br /&gt;
| 8&lt;br /&gt;
| Secondary partition table/descriptor offset&lt;br /&gt;
|-&lt;br /&gt;
| 0x10&lt;br /&gt;
| 8&lt;br /&gt;
| Primary partition table/descriptor offset&lt;br /&gt;
|-&lt;br /&gt;
| 0x18&lt;br /&gt;
| 8&lt;br /&gt;
| Partition table/descriptor size&lt;br /&gt;
|-&lt;br /&gt;
| 0x20&lt;br /&gt;
| 8&lt;br /&gt;
| Partition (A) offset&lt;br /&gt;
|-&lt;br /&gt;
| 0x28&lt;br /&gt;
| 8&lt;br /&gt;
| Partition (A) size&lt;br /&gt;
|-&lt;br /&gt;
| 0x30&lt;br /&gt;
| 4&lt;br /&gt;
| Active partition descriptor, 0 = primary, 1 = secondary&lt;br /&gt;
|-&lt;br /&gt;
| 0x34&lt;br /&gt;
| 0x20&lt;br /&gt;
| SHA-256 over the active partition table/descriptor&lt;br /&gt;
|-&lt;br /&gt;
| 0x54&lt;br /&gt;
| 8&lt;br /&gt;
| Unique identifier&lt;br /&gt;
|-&lt;br /&gt;
| 0x5C&lt;br /&gt;
| 0xA4&lt;br /&gt;
| Unused, might contain leftover data&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Note:&lt;br /&gt;
&lt;br /&gt;
* Since DIFF can only contain one partition, a partition table can only have one partition descriptor, so they become the same concept here.&lt;br /&gt;
* See [[Extdata]] for its usage of the unique identifier field. For title database files, this field is zero.&lt;br /&gt;
&lt;br /&gt;
== Partition table &amp;amp;amp; partition descriptor ==&lt;br /&gt;
&lt;br /&gt;
There are two partition tables, but only one of them is active. When operating on a DISA / DIFF file, 3DS FS alternately activate one of the two tables, presumably for data backup or atomic file writing. A newly created DISA / DIFF file may have entirely uninitialized data in the inactive partition table.&lt;br /&gt;
&lt;br /&gt;
One partition table contains one or two partition descriptors , each of which describes the layout of one partition. A partition descriptor contains the following components:&lt;br /&gt;
&lt;br /&gt;
* DIFI header&lt;br /&gt;
* IVFC descriptor&lt;br /&gt;
* DPFS descriptor&lt;br /&gt;
* Partition master hash&lt;br /&gt;
&lt;br /&gt;
=== DIFI header ===&lt;br /&gt;
&lt;br /&gt;
The DIFI header locates at the beginning of a partition descriptor. This header defines the rest components of the partition descriptor (IVFC descriptor, DPFS descriptor and partition master hash). All offsets are relative to the beginning of the partition descriptor, except for &amp;lt;code&amp;gt;External IVFC level 4 offset&amp;lt;/code&amp;gt;, which is relative to the beginning of the partition.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! Offset&lt;br /&gt;
! Length&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x00&lt;br /&gt;
| 4&lt;br /&gt;
| Magic &amp;amp;quot;DIFI&amp;amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| 0x04&lt;br /&gt;
| 4&lt;br /&gt;
| Magic 0x10000&lt;br /&gt;
|-&lt;br /&gt;
| 0x08&lt;br /&gt;
| 8&lt;br /&gt;
| IVFC descriptor offset&lt;br /&gt;
|-&lt;br /&gt;
| 0x10&lt;br /&gt;
| 8&lt;br /&gt;
| IVFC descriptor size&lt;br /&gt;
|-&lt;br /&gt;
| 0x18&lt;br /&gt;
| 8&lt;br /&gt;
| DPFS descriptor offset&lt;br /&gt;
|-&lt;br /&gt;
| 0x20&lt;br /&gt;
| 8&lt;br /&gt;
| DPFS descriptor size&lt;br /&gt;
|-&lt;br /&gt;
| 0x28&lt;br /&gt;
| 8&lt;br /&gt;
| Partition hash offset&lt;br /&gt;
|-&lt;br /&gt;
| 0x30&lt;br /&gt;
| 8&lt;br /&gt;
| Partition hash size&lt;br /&gt;
|-&lt;br /&gt;
| 0x38&lt;br /&gt;
| 1&lt;br /&gt;
| If none zero, enable external IVFC level 4.&lt;br /&gt;
|-&lt;br /&gt;
| 0x39&lt;br /&gt;
| 1&lt;br /&gt;
| DPFS tree level 1 selector&lt;br /&gt;
|-&lt;br /&gt;
| 0x3A&lt;br /&gt;
| 2&lt;br /&gt;
| Padding&lt;br /&gt;
|-&lt;br /&gt;
| 0x3C&lt;br /&gt;
| 8&lt;br /&gt;
| External IVFC level 4 offset (zero if external IVFC level 4 disabled)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Note:&lt;br /&gt;
&lt;br /&gt;
* The meaning of fields after 0x38 are explained in the section [[#Partition]]&lt;br /&gt;
&lt;br /&gt;
=== IVFC descriptor ===&lt;br /&gt;
&lt;br /&gt;
This header defines each level of IVFC tree (explained in the section [[#Partition]]). All offsets are relative to the beginning of DPFS level 3.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! Offset&lt;br /&gt;
! Length&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x00&lt;br /&gt;
| 4&lt;br /&gt;
| Magic &amp;amp;quot;IVFC&amp;amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| 0x04&lt;br /&gt;
| 4&lt;br /&gt;
| Magic 0x20000&lt;br /&gt;
|-&lt;br /&gt;
| 0x08&lt;br /&gt;
| 8&lt;br /&gt;
| Master hash size = partition master hash size in DIFI header&lt;br /&gt;
|-&lt;br /&gt;
| 0x10&lt;br /&gt;
| 8&lt;br /&gt;
| IVFC level 1 offset&lt;br /&gt;
|-&lt;br /&gt;
| 0x18&lt;br /&gt;
| 8&lt;br /&gt;
| IVFC level 1 size&lt;br /&gt;
|-&lt;br /&gt;
| 0x20&lt;br /&gt;
| 4&lt;br /&gt;
| IVFC level 1 block size in log2&lt;br /&gt;
|-&lt;br /&gt;
| 0x24&lt;br /&gt;
| 4&lt;br /&gt;
| Padding&lt;br /&gt;
|-&lt;br /&gt;
| 0x28&lt;br /&gt;
| 8&lt;br /&gt;
| IVFC level 2 offset&lt;br /&gt;
|-&lt;br /&gt;
| 0x30&lt;br /&gt;
| 8&lt;br /&gt;
| IVFC level 2 size&lt;br /&gt;
|-&lt;br /&gt;
| 0x38&lt;br /&gt;
| 4&lt;br /&gt;
| IVFC level 2 block size in log2&lt;br /&gt;
|-&lt;br /&gt;
| 0x3C&lt;br /&gt;
| 4&lt;br /&gt;
| Padding&lt;br /&gt;
|-&lt;br /&gt;
| 0x40&lt;br /&gt;
| 8&lt;br /&gt;
| IVFC level 3 offset&lt;br /&gt;
|-&lt;br /&gt;
| 0x48&lt;br /&gt;
| 8&lt;br /&gt;
| IVFC level 3 size&lt;br /&gt;
|-&lt;br /&gt;
| 0x50&lt;br /&gt;
| 4&lt;br /&gt;
| IVFC level 3 block size in log2&lt;br /&gt;
|-&lt;br /&gt;
| 0x54&lt;br /&gt;
| 4&lt;br /&gt;
| Padding&lt;br /&gt;
|-&lt;br /&gt;
| 0x58&lt;br /&gt;
| 8&lt;br /&gt;
| IVFC level 4 offset (unused if external IVFC level 4 enabled)&lt;br /&gt;
|-&lt;br /&gt;
| 0x60&lt;br /&gt;
| 8&lt;br /&gt;
| IVFC level 4 size&lt;br /&gt;
|-&lt;br /&gt;
| 0x68&lt;br /&gt;
| 4&lt;br /&gt;
| IVFC level 4 block size in log2&lt;br /&gt;
|-&lt;br /&gt;
| 0x6C&lt;br /&gt;
| 4&lt;br /&gt;
| Padding&lt;br /&gt;
|-&lt;br /&gt;
| 0x70&lt;br /&gt;
| 8&lt;br /&gt;
| IVFC descriptor size? The value is usually 0x78&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== DPFS descriptor ===&lt;br /&gt;
&lt;br /&gt;
This header defines each level of DPFS tree (explained in the section [[#Partition]]). All offsets are relative to the beginning of the partition.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! Offset&lt;br /&gt;
! Length&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x00&lt;br /&gt;
| 4&lt;br /&gt;
| Magic &amp;amp;quot;DPFS&amp;amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| 0x04&lt;br /&gt;
| 4&lt;br /&gt;
| Magic 0x10000&lt;br /&gt;
|-&lt;br /&gt;
| 0x08&lt;br /&gt;
| 8&lt;br /&gt;
| DPFS level 1 offset&lt;br /&gt;
|-&lt;br /&gt;
| 0x10&lt;br /&gt;
| 8&lt;br /&gt;
| DPFS level 1 size&lt;br /&gt;
|-&lt;br /&gt;
| 0x18&lt;br /&gt;
| 4&lt;br /&gt;
| DPFS level 1 block size in log2 (unused?)&lt;br /&gt;
|-&lt;br /&gt;
| 0x1C&lt;br /&gt;
| 4&lt;br /&gt;
| Padding&lt;br /&gt;
|-&lt;br /&gt;
| 0x20&lt;br /&gt;
| 8&lt;br /&gt;
| DPFS level 2 offset&lt;br /&gt;
|-&lt;br /&gt;
| 0x28&lt;br /&gt;
| 8&lt;br /&gt;
| DPFS level 2 size&lt;br /&gt;
|-&lt;br /&gt;
| 0x30&lt;br /&gt;
| 4&lt;br /&gt;
| DPFS level 2 block size in log2&lt;br /&gt;
|-&lt;br /&gt;
| 0x34&lt;br /&gt;
| 4&lt;br /&gt;
| Padding&lt;br /&gt;
|-&lt;br /&gt;
| 0x38&lt;br /&gt;
| 8&lt;br /&gt;
| DPFS level 3 offset&lt;br /&gt;
|-&lt;br /&gt;
| 0x40&lt;br /&gt;
| 8&lt;br /&gt;
| DPFS level 3 size&lt;br /&gt;
|-&lt;br /&gt;
| 0x48&lt;br /&gt;
| 4&lt;br /&gt;
| DPFS level 3 block size in log2&lt;br /&gt;
|-&lt;br /&gt;
| 0x4C&lt;br /&gt;
| 4&lt;br /&gt;
| Padding&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Partition master hash ===&lt;br /&gt;
&lt;br /&gt;
This is a SHA-256 hash list over IVFC level 1. See [[#IVFC tree]] for explanation.&lt;br /&gt;
&lt;br /&gt;
== Partition ==&lt;br /&gt;
&lt;br /&gt;
A partition can have two types of layout. This is determined by the field DIFF + 0x38 (&amp;lt;code&amp;gt;Enable external IVFC level 4&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
The layout type 0 (external IVFC level 4 disabled) contains&lt;br /&gt;
&lt;br /&gt;
* DPFS level 1&lt;br /&gt;
* DPFS level 2&lt;br /&gt;
* DPFS level 3, and inside&lt;br /&gt;
** IVFC level 1&lt;br /&gt;
** IVFC level 2&lt;br /&gt;
** IVFC level 3&lt;br /&gt;
** IVFC level 4 (the actual content data)&lt;br /&gt;
&lt;br /&gt;
The layout type 1 (external IVFC level 4 enabled) contains&lt;br /&gt;
&lt;br /&gt;
* DPFS level 1&lt;br /&gt;
* DPFS level 2&lt;br /&gt;
* DPFS level 3, and inside&lt;br /&gt;
** IVFC level 1&lt;br /&gt;
** IVFC level 2&lt;br /&gt;
** IVFC level 3&lt;br /&gt;
* IVFC level 4 (the actual content data, note that this is out side DPFS level 3)&lt;br /&gt;
&lt;br /&gt;
=== DPFS tree ===&lt;br /&gt;
&lt;br /&gt;
Everything inside the DPFS tree comes in pairs, and at one time only one of a pair is active. The tree is probably designed for atomic writing: for a file writing operation, it writes to the inactive part, then commits the data by switching a bit to activate it.&lt;br /&gt;
&lt;br /&gt;
Each level of DPFS tree consists of a pair of chunks. The size of one chunk is defined as it in the DPFS descriptor, so the total size of a level is actually twice as large as the size recorded in the descriptor. For level 1 and 2, each chunk is a bit array, in which each bit corresponds to a block in the next level (the block size of the next level is also defined in the DPFS descriptor). This bit indicates which one of the pair in the next level is active for this block: 0 means the first one and 1 means the second one. The active chunk of level 1 is selected by &amp;lt;code&amp;gt;DPFS tree level 1 selector&amp;lt;/code&amp;gt; in the DIFI header. The bit array is encoded in u32 array, with MSB as the first bit of each 32 bits.&lt;br /&gt;
&lt;br /&gt;
To access data in level 3, one needs to check the bits in level 1 and level 2 to know which chunk of level 3 is active for the accessed location. For example, for a following configuration:&lt;br /&gt;
&lt;br /&gt;
* Level 1: size = 4 bytes = 32 bits&lt;br /&gt;
* Level 2: size = 0x380 bytes = 0x1C00 bits, block size = 0x80 bytes&lt;br /&gt;
* Level 3: size = 0x1B7F000, block size = 0x1000, block size = 0x1000 bytes&lt;br /&gt;
&lt;br /&gt;
if one want to read byte at 0x1234567 of level 3, the following calculation is performed:&lt;br /&gt;
&lt;br /&gt;
* get level 2 bit index &amp;lt;code&amp;gt;0x1234567 / 0x1000 = 0x1234&amp;lt;/code&amp;gt;, and its byte location &amp;lt;code&amp;gt;0x1234 / 8 = 0x246&amp;lt;/code&amp;gt;&lt;br /&gt;
* get level 1 bit index &amp;lt;code&amp;gt;0x246 / 0x80 = 4&amp;lt;/code&amp;gt;&lt;br /&gt;
* get &amp;lt;code&amp;gt;level1_selector&amp;lt;/code&amp;gt; from DIFI header&lt;br /&gt;
* read &amp;lt;code&amp;gt;level2_selector = Level1[level1_selector].bits[4]&amp;lt;/code&amp;gt;;&lt;br /&gt;
* read &amp;lt;code&amp;gt;level3_selector = Level2[level2_selector].bits[0x1234]&amp;lt;/code&amp;gt;;&lt;br /&gt;
* read &amp;lt;code&amp;gt;data = Level3[level3_selector].bytes[0x1234567]&amp;lt;/code&amp;gt; as the final data&lt;br /&gt;
* in the code above &amp;lt;code&amp;gt;Levelx[k]&amp;lt;/code&amp;gt; means the &amp;lt;code&amp;gt;k&amp;lt;/code&amp;gt;-th chunk in level &amp;lt;code&amp;gt;x&amp;lt;/code&amp;gt;, where &amp;lt;code&amp;gt;k = 0, 1&amp;lt;/code&amp;gt;. &amp;lt;code&amp;gt;.bits[n]&amp;lt;/code&amp;gt; is expanded to &amp;lt;code&amp;gt;(.u32_array[n / 32] &amp;amp;gt;&amp;amp;gt; (31 - n % 32)) &amp;amp;amp; 1&amp;lt;/code&amp;gt; as the bit array is encoded in u32 array.&lt;br /&gt;
&lt;br /&gt;
Effectively, the active data is scattered among the two level 3 chunk. One can assemble the whole active level 3 image following the same rule.&lt;br /&gt;
&lt;br /&gt;
=== IVFC tree ===&lt;br /&gt;
&lt;br /&gt;
The IVFC tree is used for data verification. It is very similar to the IVFC tree in [[RomFS]], except that it has an additional level here. For level 1, 2 and 3, each level is a list of SHA-256 hash, of which each corresponds to a block of the next level which is zero-padded to align the block size (the block size of the next level is defined in the IVFC descriptor).&lt;br /&gt;
&lt;br /&gt;
The partition master hash in the partition descriptor can be seen as IVFC level 0, which hashes level 1 following the same rule. The master hash is usually 0x20 long, consisting only one hash. This is because most DISA / DIFF files are not large enough to have multiple hashes on the top level, which isn&#039;t the case for some title database files.&lt;br /&gt;
&lt;br /&gt;
However, not all data is hashed - only ranges that have been written with valid data are properly hashed.&lt;br /&gt;
&lt;br /&gt;
Level 4 is the actual content of the partition, which is what the container format essentially contains.&lt;br /&gt;
&lt;br /&gt;
== Extracting content from a DISA / DIFF container ==&lt;br /&gt;
&lt;br /&gt;
* Find the active partition table and the partition(s).&lt;br /&gt;
* Unwrap DPFS tree of partition(s) by reconstructing active data.&lt;br /&gt;
* Unwrap IVFC tree. Either take out level 4 directly, or, better, verify all the hashes and poison the data that is not properly hashed.&lt;br /&gt;
* The IVFC level 4 is the inner content of the file. The format of it varies among different usage. Refer their own page for further extraction.&lt;br /&gt;
&lt;br /&gt;
== Chain of trust ==&lt;br /&gt;
&lt;br /&gt;
* AES CMAC verifies the header.&lt;br /&gt;
* The header verifies the active partition table via the table hash.&lt;br /&gt;
* In the partition table, each descriptor verifies level 1 of its IVFC tree via the master hash.&lt;br /&gt;
* Each IVFC level verifies the next level, until the level 4, which is the inner content.&lt;br /&gt;
&lt;br /&gt;
== Summary diagram ==&lt;br /&gt;
&lt;br /&gt;
[[File:Disa-diff.png]]&lt;/div&gt;</summary>
		<author><name>Wwylele</name></author>
	</entry>
	<entry>
		<id>https://www.3dbrew.org/w/index.php?title=File:Disa-diff.png&amp;diff=21143</id>
		<title>File:Disa-diff.png</title>
		<link rel="alternate" type="text/html" href="https://www.3dbrew.org/w/index.php?title=File:Disa-diff.png&amp;diff=21143"/>
		<updated>2020-01-02T05:20:28Z</updated>

		<summary type="html">&lt;p&gt;Wwylele: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Wwylele</name></author>
	</entry>
	<entry>
		<id>https://www.3dbrew.org/w/index.php?title=Inner_FAT&amp;diff=21142</id>
		<title>Inner FAT</title>
		<link rel="alternate" type="text/html" href="https://www.3dbrew.org/w/index.php?title=Inner_FAT&amp;diff=21142"/>
		<updated>2020-01-02T05:16:41Z</updated>

		<summary type="html">&lt;p&gt;Wwylele: Embed diagrams&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This page describes a common FAT-like file system used in [[Savegames]], [[Extdata]] and [[Title Database]]. This file system format has several variants depending on which kind of data it stores. All the three kinds of data that use this file system structure also happen to use the [[DISA and DIFF]] container as well, but there is no direct relationship between the file system and the DISA/DIFF container. All data formats described here is in the inner data of the DISA/DIFF container (i.e. IVFC level 4). Please refer to the DISA/DIFF page for how to unwrap it first before trying to extract the file system.&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
&lt;br /&gt;
The file system consists of the following components:&lt;br /&gt;
* header&lt;br /&gt;
* directory hash table&lt;br /&gt;
* file hash table&lt;br /&gt;
* file allocation table&lt;br /&gt;
* directory entry table&lt;br /&gt;
* file entry table&lt;br /&gt;
* data region&lt;br /&gt;
&lt;br /&gt;
The file allocation table (FAT) forms several linked lists inside, each of which represents a &amp;quot;file&amp;quot; allocated in the data region. Please refer to the File Allocation Table section below for more detail. In some variants, the directory entry table and the file entry table are also allocated as two special &amp;quot;files&amp;quot; in the data region, managed by the FAT, while in others they are stand-alone tables located outside the data region.&lt;br /&gt;
&lt;br /&gt;
== Layout Variants ==&lt;br /&gt;
Four variants of the file system layout has been identified. A summary diagram:&lt;br /&gt;
&lt;br /&gt;
[[File:Inner-fat.png]]&lt;br /&gt;
&lt;br /&gt;
=== Savegame, &amp;lt;code&amp;gt;duplicate data = true&amp;lt;/code&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
Such savegame is a single DISA container that only has one partition which is always configured as external IVFC level 4 disabled (see [[DISA and DIFF|DISA]] format for details). All components are stored in this partition as&lt;br /&gt;
&lt;br /&gt;
* filesystem header at the beginning&lt;br /&gt;
* directory hash table&lt;br /&gt;
* file hash table&lt;br /&gt;
* file allocation table&lt;br /&gt;
* data region&lt;br /&gt;
** directory entry table is allocated inside data region&lt;br /&gt;
** file entry table as well&lt;br /&gt;
** all file data is also allocated here&lt;br /&gt;
&lt;br /&gt;
In this layout, all data is duplicated by DISA&#039;s DPFS tree, which is what the parameter &amp;lt;code&amp;gt;duplicate data&amp;lt;/code&amp;gt; implies.&lt;br /&gt;
&lt;br /&gt;
=== Savegame, &amp;lt;code&amp;gt;duplicate data = false&amp;lt;/code&amp;gt; === &lt;br /&gt;
Such savegame is a single DISA container that has two partitions. Partition A is always configured as external IVFC level 4 disabled, and partition B is configured as it enabled. Components are stored among the two partitions as&lt;br /&gt;
&lt;br /&gt;
* Partition A&lt;br /&gt;
** filesystem header at the beginning.&lt;br /&gt;
** directory hash table&lt;br /&gt;
** file hash table&lt;br /&gt;
** (stand-alone) file allocation table&lt;br /&gt;
** (stand-alone) directory entry table&lt;br /&gt;
** file entry table&lt;br /&gt;
* Partition B&lt;br /&gt;
** used as data region entirely, and only has file data allocated.&lt;br /&gt;
&lt;br /&gt;
In this layout, all file system metadata is duplicated by partition A DPFS tree, but file data is not as partition B has external IVFC level 4.&lt;br /&gt;
&lt;br /&gt;
=== Extdata ===&lt;br /&gt;
An extdata consists of several DIFF containers (device files), among which the special device file &amp;lt;code&amp;gt;00000000/00000001&amp;lt;/code&amp;gt; contains the inner FAT system, while other devices contains normal subfiles of the extdata. Please refer to [[Extdata]] for detail. The special file &amp;lt;code&amp;gt;00000000/00000001&amp;lt;/code&amp;gt; contists of the following components&lt;br /&gt;
&lt;br /&gt;
* filesystem header at the beginning&lt;br /&gt;
* directory hash table&lt;br /&gt;
* file hash table&lt;br /&gt;
* file allocation table (degenerate, because the data region only has two &amp;quot;files&amp;quot;: the directory entry table and the file entry table)&lt;br /&gt;
* data region&lt;br /&gt;
** directory entry table allocated inside data region&lt;br /&gt;
** file entry table as well&lt;br /&gt;
** normal subfiles are NOT in the data region. They are in their DIFF containers instead.&lt;br /&gt;
&lt;br /&gt;
The special file &amp;lt;code&amp;gt;00000000/00000001&amp;lt;/code&amp;gt; is configured as external IVFC level 4 disabled, and all other device files are configured as it enabled.&lt;br /&gt;
&lt;br /&gt;
=== Title database ===&lt;br /&gt;
All [[Title Database]] files are DIFF containers. Except for &amp;lt;code&amp;gt;certs.db&amp;lt;/code&amp;gt;, all of them uses this filesystem in the DIFF inner data, which consists of&lt;br /&gt;
&lt;br /&gt;
* database-specific pre-header at the beginning (See [[Title Database]])&lt;br /&gt;
* filesystem header&lt;br /&gt;
* directory Hash Table (degenerate and always has only one bucket, as there is only one directory for &amp;quot;root&amp;quot;)&lt;br /&gt;
* file Hash Table&lt;br /&gt;
* file allocation table&lt;br /&gt;
* data region&lt;br /&gt;
** directory entry table allocated inside data region (degenerate, as there is only one directory for &amp;quot;root&amp;quot;)&lt;br /&gt;
** file entry table as well&lt;br /&gt;
** title entries (title info or ticket) are allocated as normal files in the data region as well.&lt;br /&gt;
&lt;br /&gt;
== Filesystem Header ==&lt;br /&gt;
Offsets listed in the table below are all relative to the beginning of the header, while all &amp;quot;starting block index&amp;quot; are relative to the beginning of data region. This is especially important for title database, as the offsets doesn&#039;t count the pre header.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! Offset&lt;br /&gt;
! Length&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x00&lt;br /&gt;
| 4&lt;br /&gt;
| Magic (&amp;quot;SAVE&amp;quot; for savegame; &amp;quot;BDRI&amp;quot; for title database; &amp;quot;VSXE&amp;quot; for extdata)&lt;br /&gt;
|-&lt;br /&gt;
| 0x04&lt;br /&gt;
| 4&lt;br /&gt;
| Version (0x40000 for savegame; 0x30000 for title database and extdata)&lt;br /&gt;
|-&lt;br /&gt;
| 0x08&lt;br /&gt;
| 8&lt;br /&gt;
| Filesystem Information offset (Y, =0x20 for savegame and title database, =0x138 for extdata)&lt;br /&gt;
|-&lt;br /&gt;
| 0x10&lt;br /&gt;
| 8&lt;br /&gt;
| Filesystem image size in blocks (including pre header for title database)&lt;br /&gt;
|-&lt;br /&gt;
| 0x18&lt;br /&gt;
| 4&lt;br /&gt;
| Filesystem Image block size&lt;br /&gt;
|-&lt;br /&gt;
| 0x1C&lt;br /&gt;
| 4&lt;br /&gt;
| Padding&lt;br /&gt;
|-&lt;br /&gt;
| 0x20 &lt;br /&gt;
| 0x118 in total&lt;br /&gt;
| Below is additional data for extdata. Not present in savegame or title database&lt;br /&gt;
|-&lt;br /&gt;
| 0x20&lt;br /&gt;
| 8&lt;br /&gt;
| Unknown&lt;br /&gt;
|-&lt;br /&gt;
| 0x28&lt;br /&gt;
| 4&lt;br /&gt;
| &#039;Action&#039; made on most recently mounted Extdata image&lt;br /&gt;
|-&lt;br /&gt;
| 0x2C&lt;br /&gt;
| 4&lt;br /&gt;
| Unknown&lt;br /&gt;
|-&lt;br /&gt;
| 0x30&lt;br /&gt;
| 4&lt;br /&gt;
| ID of most recently mounted Extdata image&lt;br /&gt;
|-&lt;br /&gt;
| 0x34&lt;br /&gt;
| 4&lt;br /&gt;
| Unknown&lt;br /&gt;
|-&lt;br /&gt;
| 0x38&lt;br /&gt;
| 0x100&lt;br /&gt;
| Mount path, from most recently mounted Extdata image&lt;br /&gt;
|-&lt;br /&gt;
| Y &lt;br /&gt;
| 0x68 in total&lt;br /&gt;
| Below is Filesystem Information&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x00&lt;br /&gt;
| 4&lt;br /&gt;
| Unknown&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x04&lt;br /&gt;
| 4&lt;br /&gt;
| Data region block size&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x08&lt;br /&gt;
| 8&lt;br /&gt;
| Directory hash table offset&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x10&lt;br /&gt;
| 4&lt;br /&gt;
| Directory hash table bucket count (=1 for title database)&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x14&lt;br /&gt;
| 4&lt;br /&gt;
| Padding&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x18&lt;br /&gt;
| 8&lt;br /&gt;
| File hash table offset&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x20&lt;br /&gt;
| 4&lt;br /&gt;
| File hash table bucket count&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x24&lt;br /&gt;
| 4&lt;br /&gt;
| Padding&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x28&lt;br /&gt;
| 8&lt;br /&gt;
| File allocation table offset&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x30&lt;br /&gt;
| 4&lt;br /&gt;
| File allocation table entry count &lt;br /&gt;
(excluding the leading 0th entry. See below)&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x34&lt;br /&gt;
| 4&lt;br /&gt;
| Padding&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x38&lt;br /&gt;
| 8&lt;br /&gt;
| Data region offset &lt;br /&gt;
(0 for savegame &amp;lt;code&amp;gt;duplicate data = false&amp;lt;/code&amp;gt; layout, as the data region is in partition B for that layout)&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x40&lt;br /&gt;
| 4&lt;br /&gt;
| Data region block count &lt;br /&gt;
(= File allocation table entry count)&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x44&lt;br /&gt;
| 4&lt;br /&gt;
| Padding&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x48&lt;br /&gt;
| 8&lt;br /&gt;
| for savegame &amp;lt;code&amp;gt;duplicate data = false&amp;lt;/code&amp;gt; layout: directory entry table offset;&lt;br /&gt;
otherwise: u32 directory entry table starting block index + u32 directory entry table block count&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x50&lt;br /&gt;
| 4&lt;br /&gt;
| Maximum directory count, excluding the mandatory &amp;quot;root&amp;quot; directory &lt;br /&gt;
(=1 for title database, but that 1 free directory slot is never used)&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x54&lt;br /&gt;
| 4&lt;br /&gt;
| Padding&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x58&lt;br /&gt;
| 8&lt;br /&gt;
| for savegame &amp;lt;code&amp;gt;duplicate data = false&amp;lt;/code&amp;gt; layout: file entry table offset;&lt;br /&gt;
otherwise: u32 file entry table starting block index + u32 file entry table block count&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x60&lt;br /&gt;
| 4&lt;br /&gt;
| Maximum file count&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x64&lt;br /&gt;
| 4&lt;br /&gt;
| Padding&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
* For savegames, the file/directory bucket count &amp;amp; maximum count are specified by the parameters of [[FS:FormatSaveData]] or [[FS:CreateSystemSaveData]].&lt;br /&gt;
* For extdata, the maximum file/directory count are specified by the parameters of [[FS:CreateExtSaveData]]. The bucket count is likely calculated by the system.&lt;br /&gt;
* Directory &amp;amp; file entry tables are allocated in the data region as if they are two normal files (except for savegame &amp;lt;code&amp;gt;duplicate data = false&amp;lt;/code&amp;gt; layout). However, only continuous allocation has been observed, so directly reading block_count * block_size bytes from data_region + starting_block_index * block_size should be safe.&lt;br /&gt;
* For title database (except for ticket), the range specified for data region seems overflow the file end by 0x80 bytes, which is exactly the size of the pre header. This makes it as if the data region offset should be relative to the pre header instead of the BDRI header. However, further investigation on the directory/file table allocated inside the data region shows that the data region offset is indeed relative to the BDRI header. It might be a bug in 3DS that the title database files miss 0x80-byte space at the end.&lt;br /&gt;
&lt;br /&gt;
== Directory Entry Table ==&lt;br /&gt;
&lt;br /&gt;
The directory entry table is an array of the entry type shown below. It describes the directory hierarchy of the file system. There are two variants of the directory entry type, and a dummy entry type.&lt;br /&gt;
&lt;br /&gt;
=== Savegame/Extdata Variant===&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! Offset&lt;br /&gt;
! Length&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x00&lt;br /&gt;
| 4&lt;br /&gt;
| Parent directory index. 0 for root&lt;br /&gt;
|-&lt;br /&gt;
| 0x04&lt;br /&gt;
| 16&lt;br /&gt;
| ASCII directory name in. All zero for root&lt;br /&gt;
|-&lt;br /&gt;
| 0x14&lt;br /&gt;
| 4&lt;br /&gt;
| Next sibling directory index. 0 if this is the last one&lt;br /&gt;
|-&lt;br /&gt;
| 0x18&lt;br /&gt;
| 4&lt;br /&gt;
| First subdirectory index. 0 if not exists&lt;br /&gt;
|-&lt;br /&gt;
| 0x1C&lt;br /&gt;
| 4&lt;br /&gt;
| First file index in file entry table. 0 for empty directory&lt;br /&gt;
|-&lt;br /&gt;
| 0x20&lt;br /&gt;
| 4&lt;br /&gt;
| Padding / zero?&lt;br /&gt;
|-&lt;br /&gt;
| 0x24&lt;br /&gt;
| 4&lt;br /&gt;
| Index of the next directory in the same hash table bucket. 0 if this is the last one&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Title Database Variant===&lt;br /&gt;
Because title database only has one directory for &amp;quot;root&amp;quot;, its directory entry table degenerates into many zeros whose structure is not recognizable. The size of one entry here is guessed.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! Offset&lt;br /&gt;
! Length&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x00&lt;br /&gt;
| 4&lt;br /&gt;
| Parent directory index = 0 for root&lt;br /&gt;
|-&lt;br /&gt;
| 0x04&lt;br /&gt;
| 4&lt;br /&gt;
| Next sibling directory index = 0 because this is the last one&lt;br /&gt;
|-&lt;br /&gt;
| 0x08&lt;br /&gt;
| 4&lt;br /&gt;
| First subdirectory index = 0 because there is no subdirectory&lt;br /&gt;
|-&lt;br /&gt;
| 0x0C&lt;br /&gt;
| 4&lt;br /&gt;
| First file index in file entry table. 0 for empty directory&lt;br /&gt;
|-&lt;br /&gt;
| 0x10&lt;br /&gt;
| 12&lt;br /&gt;
| Padding / zero?&lt;br /&gt;
|-&lt;br /&gt;
| 0x1C&lt;br /&gt;
| 4&lt;br /&gt;
| Index of the next directory in the same hash table bucket = 0 because there is no other directory&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Dummy Entry===&lt;br /&gt;
There are also some dummy entries in the array&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! Offset&lt;br /&gt;
! Length&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x00&lt;br /&gt;
| 4&lt;br /&gt;
| Current Total entry count&lt;br /&gt;
|-&lt;br /&gt;
| 0x04&lt;br /&gt;
| 4&lt;br /&gt;
| Maximum entry count = maximum directory count + 2&lt;br /&gt;
|-&lt;br /&gt;
| 0x08&lt;br /&gt;
| 28/20&lt;br /&gt;
| Padding / All zero&lt;br /&gt;
|-&lt;br /&gt;
| 0x24/0x1C&lt;br /&gt;
| 4&lt;br /&gt;
| Index of the next dummy entry. 0 if this is the last one&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The 0-th entry of the array is always a dummy entry, which functions as the head of the dummy entry linked list. The 1-st entry of the array is always the root. Therefore maximum entry count is two more than maximum directory count. Dummy entries are left there when deleting directories, and reserved for future use.&lt;br /&gt;
&lt;br /&gt;
== File Entry Table ==&lt;br /&gt;
&lt;br /&gt;
The file entry table is an array of the entry type shown below. It contains information for each file. There are three variants of the file entry type, and a dummy entry type.&lt;br /&gt;
&lt;br /&gt;
=== Savegame Variant ===&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! Offset&lt;br /&gt;
! Length&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x00&lt;br /&gt;
| 4&lt;br /&gt;
| Parent directory index in directory entry table&lt;br /&gt;
|-&lt;br /&gt;
| 0x04&lt;br /&gt;
| 16&lt;br /&gt;
| ASCII file name&lt;br /&gt;
|-&lt;br /&gt;
| 0x14&lt;br /&gt;
| 4&lt;br /&gt;
| Next sibling file index. 0 if this is the last one&lt;br /&gt;
|-&lt;br /&gt;
| 0x18&lt;br /&gt;
| 4&lt;br /&gt;
| Padding&lt;br /&gt;
|-&lt;br /&gt;
| 0x1C&lt;br /&gt;
| 4&lt;br /&gt;
| First block index in data region. 0x80000000 if the file is just created and has no data.&lt;br /&gt;
|-&lt;br /&gt;
| 0x20&lt;br /&gt;
| 8&lt;br /&gt;
| File Size&lt;br /&gt;
|-&lt;br /&gt;
| 0x28&lt;br /&gt;
| 4&lt;br /&gt;
| Padding?&lt;br /&gt;
|-&lt;br /&gt;
| 0x2C&lt;br /&gt;
| 4&lt;br /&gt;
| Index of the next file in the same hash table bucket. 0 if this is the last one&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Extdata Variant ===&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! Offset&lt;br /&gt;
! Length&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x00&lt;br /&gt;
| 4&lt;br /&gt;
| Parent directory index in directory entry table&lt;br /&gt;
|-&lt;br /&gt;
| 0x04&lt;br /&gt;
| 16&lt;br /&gt;
| ASCII file name&lt;br /&gt;
|-&lt;br /&gt;
| 0x14&lt;br /&gt;
| 4&lt;br /&gt;
| Next sibling file index. 0 if this is the last one&lt;br /&gt;
|-&lt;br /&gt;
| 0x18&lt;br /&gt;
| 4&lt;br /&gt;
| Padding&lt;br /&gt;
|-&lt;br /&gt;
| 0x1C&lt;br /&gt;
| 4&lt;br /&gt;
| Always 0x80000000&lt;br /&gt;
|-&lt;br /&gt;
| 0x20&lt;br /&gt;
| 8&lt;br /&gt;
| Unique identifier. See [[Extdata]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x28&lt;br /&gt;
| 4&lt;br /&gt;
| Padding?&lt;br /&gt;
|-&lt;br /&gt;
| 0x2C&lt;br /&gt;
| 4&lt;br /&gt;
| Index of the next file in the same hash table bucket. 0 if this is the last one&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Title database Variant ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! Offset&lt;br /&gt;
! Length&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x00&lt;br /&gt;
| 4&lt;br /&gt;
| Parent directory index in directory entry table&lt;br /&gt;
|-&lt;br /&gt;
| 0x04&lt;br /&gt;
| 8&lt;br /&gt;
| Title ID&lt;br /&gt;
|-&lt;br /&gt;
| 0x0C&lt;br /&gt;
| 4&lt;br /&gt;
| Next sibling file index. 0 if this is the last one&lt;br /&gt;
|-&lt;br /&gt;
| 0x10&lt;br /&gt;
| 4&lt;br /&gt;
| Padding&lt;br /&gt;
|-&lt;br /&gt;
| 0x14&lt;br /&gt;
| 4&lt;br /&gt;
| First block index in data region.&lt;br /&gt;
|-&lt;br /&gt;
| 0x18&lt;br /&gt;
| 8&lt;br /&gt;
| File size&lt;br /&gt;
|-&lt;br /&gt;
| 0x20&lt;br /&gt;
| 8&lt;br /&gt;
| Padding?&lt;br /&gt;
|-&lt;br /&gt;
| 0x28&lt;br /&gt;
| 4&lt;br /&gt;
| Index of the next file in the same hash table bucket. 0 if this is the last one&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Dummy Entry ===&lt;br /&gt;
Like directory entry table, file entry table also has some dummy entries:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! Offset&lt;br /&gt;
! Length&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x00&lt;br /&gt;
| 4&lt;br /&gt;
| Current total entry count&lt;br /&gt;
|-&lt;br /&gt;
| 0x04&lt;br /&gt;
| 4&lt;br /&gt;
| Maximum entry count = maximum file count + 1&lt;br /&gt;
|-&lt;br /&gt;
| 0x08&lt;br /&gt;
| 36/32&lt;br /&gt;
| Padding / All zero&lt;br /&gt;
|-&lt;br /&gt;
| 0x2C/0x28&lt;br /&gt;
| 4&lt;br /&gt;
| Index of the next dummy entry. 0 if this is the last one&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The 0-th entry of the array is always a dummy entry, which functions as the head of the dummy entry linked list. Therefore maximum entry count is one more than maximum file count. Dummy entries are left there when deleting files, and reserved for future use.&lt;br /&gt;
&lt;br /&gt;
== Directory Hash Table &amp;amp;amp; File Hash Table ==&lt;br /&gt;
&lt;br /&gt;
This is a u32 array of size = bucket count, each of which is an index to the directory / file entry table. The directory / file name is hashed and its entry index is put to the corresponding bucket. If there is already a directory/file entry in the bucket, then it appends to the linked list formed by &amp;lt;code&amp;gt;Index of the next directory/file in the same hash table bucket&amp;lt;/code&amp;gt; field in the directory/file entry table. i.e. this is a hash table using separate chaining with linked lists&lt;br /&gt;
&lt;br /&gt;
The hash function takes the parent index and the ASCII name (or title ID for title database) as key. The function is equivalent to&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;uint32_t GetBucket(&lt;br /&gt;
    char name[16 or 8], // For savegame/extdata, this takes all 16 bytes including trailing zeros; For title database, this is the 8-byte title ID&lt;br /&gt;
    uint32_t parent_dir_index,&lt;br /&gt;
    uint32_t bucket_count&lt;br /&gt;
) {&lt;br /&gt;
    uint32_t hash = parent_dir_index ^ 0x091A2B3C;&lt;br /&gt;
    for (int i = 0; i &amp;amp;lt; 4 or 2; ++i) {&lt;br /&gt;
        hash = (hash &amp;amp;gt;&amp;amp;gt; 1) | (hash &amp;amp;lt;&amp;amp;lt; 31);&lt;br /&gt;
        hash ^= (uint32_t)name[i * 4]&lt;br /&gt;
        hash ^= (uint32_t)name[i * 4 + 1] &amp;amp;lt;&amp;amp;lt; 8&lt;br /&gt;
        hash ^= (uint32_t)name[i * 4 + 2] &amp;amp;lt;&amp;amp;lt; 16&lt;br /&gt;
        hash ^= (uint32_t)name[i * 4 + 3] &amp;amp;lt;&amp;amp;lt; 24&lt;br /&gt;
    }&lt;br /&gt;
    return hash % bucket_count;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== File Allocation Table ==&lt;br /&gt;
&lt;br /&gt;
The file allocation table is an array of a 8-byte entry shown below. The array size is actually &#039;&#039;one larger than&#039;&#039; the size recorded in the filesystem header. Each entry corresponds to a block in the data region (the block size is defined in filesystem header). However, the 0th entry corresponds to nothing, so the corresponding block index is off by one. e.g. entry 31 in this table corresponds to block 30 in the data region.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! Offset&lt;br /&gt;
! Length&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x00&lt;br /&gt;
| 4&lt;br /&gt;
| bit[0:30]: Index U; bit[31]: Flag U&lt;br /&gt;
|-&lt;br /&gt;
| 0x04&lt;br /&gt;
| 4&lt;br /&gt;
| bit[0:30]: Index V; bit[31]: Flag V&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Entries in this table forms several chains, representing how blocks in the data region should be linked together. However, unlike normal FAT systems, which uses chains of entries, 3DS savegames use chain of &#039;&#039;nodes&#039;&#039;. Each node spans one or multiple entries.&lt;br /&gt;
&lt;br /&gt;
One node spanning &amp;lt;code&amp;gt;n&amp;lt;/code&amp;gt; entries starting from &amp;lt;code&amp;gt;FAT[k]&amp;lt;/code&amp;gt; is in the following format:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;FAT[k + 0]:&lt;br /&gt;
    Index_U = index of the first entry of the previous node. 0 if this is the first node.&lt;br /&gt;
    Index_V = index of the first entry of the next node. 0 if this is the last node.&lt;br /&gt;
    Flag_U set if this is the first node.&lt;br /&gt;
    Flag_V set if this node has multiple entries.&lt;br /&gt;
&lt;br /&gt;
FAT[k + 1]:&lt;br /&gt;
    Index_U = k (the first entry index of this node)&lt;br /&gt;
    Index_V = k + n - 1 (the last entry index of this node)&lt;br /&gt;
    Flag_U always set&lt;br /&gt;
    Flag_V always clear&lt;br /&gt;
&lt;br /&gt;
FAT[k + 2] ~ FAT[k + n - 2]:&lt;br /&gt;
    All these entries are uninitialized&lt;br /&gt;
&lt;br /&gt;
FAT[k + n - 1]:&lt;br /&gt;
    Index_U = k&lt;br /&gt;
    Index_V = k + n - 1&lt;br /&gt;
    Flag_U always set&lt;br /&gt;
    Flag_V always clear&lt;br /&gt;
    (Same values as FAT[k + 1])&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* Note: all indices above are entry indices (block index + 1)&lt;br /&gt;
&lt;br /&gt;
All free blocks that are not allocated to any files also form a node chain in the allocation table. The head index of this &amp;amp;quot;free chain&amp;amp;quot; is recorded in &amp;lt;code&amp;gt;FAT[0].Index_V&amp;lt;/code&amp;gt;. Other fields of &amp;lt;code&amp;gt;FAT[0]&amp;lt;/code&amp;gt; are all zero&lt;br /&gt;
&lt;br /&gt;
Here is an example: &lt;br /&gt;
&lt;br /&gt;
[[File:Disa-fat.png]]&lt;br /&gt;
&lt;br /&gt;
For extdata, because only two &amp;quot;files&amp;quot; (directory and file entry tables) are allocated in the data region, and their size never changes once the extdata is created, they are guaranteed continuous in the data region, and the FAT degenerates to two big nodes. Therefore, instead of going through FAT, the offset and size of directory / file entry table can be found directly by offset = entry_table_starting block * data_region_block_size + data_region_offset and size = entry_table_block_count * data_region_block_size.&lt;/div&gt;</summary>
		<author><name>Wwylele</name></author>
	</entry>
	<entry>
		<id>https://www.3dbrew.org/w/index.php?title=File:Disa-fat.png&amp;diff=21141</id>
		<title>File:Disa-fat.png</title>
		<link rel="alternate" type="text/html" href="https://www.3dbrew.org/w/index.php?title=File:Disa-fat.png&amp;diff=21141"/>
		<updated>2020-01-02T04:59:47Z</updated>

		<summary type="html">&lt;p&gt;Wwylele: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Wwylele</name></author>
	</entry>
	<entry>
		<id>https://www.3dbrew.org/w/index.php?title=File:Inner-fat.png&amp;diff=21140</id>
		<title>File:Inner-fat.png</title>
		<link rel="alternate" type="text/html" href="https://www.3dbrew.org/w/index.php?title=File:Inner-fat.png&amp;diff=21140"/>
		<updated>2020-01-02T00:41:14Z</updated>

		<summary type="html">&lt;p&gt;Wwylele: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Wwylele</name></author>
	</entry>
	<entry>
		<id>https://www.3dbrew.org/w/index.php?title=Savegames&amp;diff=21126</id>
		<title>Savegames</title>
		<link rel="alternate" type="text/html" href="https://www.3dbrew.org/w/index.php?title=Savegames&amp;diff=21126"/>
		<updated>2019-12-23T02:51:05Z</updated>

		<summary type="html">&lt;p&gt;Wwylele: /* Gamecard savegame Encryption */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This page describes the format and encryption of savegames contained in gamecards, SD and NAND. You can find savegames from various 3DS games on the [[Games]] page.&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
Savegames are stored in [[DISA and DIFF|DISA container format]]. Inside the DISA container, it forms a [[Inner FAT|FAT filesystem]]. &#039;&#039;&#039;Please refer to these pages for how to fully extract save files&#039;&#039;&#039;. This page only describes additional encryption wear leveling on top of the DISA container. These layers only apply to gamecard save games. SD savegames and NAND savegames are DISA containers in plaintext after decrypting the common SD/NAND encryption layer.&lt;br /&gt;
&lt;br /&gt;
== Gamecard savegame Encryption ==&lt;br /&gt;
&lt;br /&gt;
Gamecard encryption is AES-CTR applied on top of DISA container, but below the wear leveling layer (if exists). The same key Y used for encryption is also used for DISA CMAC signing. Several versions of encryption scheme have been introduced over the time.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
!  FW Introduced&lt;br /&gt;
!  Old3DS&lt;br /&gt;
!  [[AES#Keyslot|AES Keyslots]] (Encryotion / CMAC)&lt;br /&gt;
!  KeyY generation method&lt;br /&gt;
!  Repeating CTR&lt;br /&gt;
|-&lt;br /&gt;
| The initial version&lt;br /&gt;
| style=&amp;quot;background: #ccffbb&amp;quot; | Yes&lt;br /&gt;
| 0x37 / 0x33&lt;br /&gt;
| v1&lt;br /&gt;
| style=&amp;quot;background: #ccffbb&amp;quot; | Yes&lt;br /&gt;
|-&lt;br /&gt;
| [[2.0.0-2]]&lt;br /&gt;
| style=&amp;quot;background: #ccffbb&amp;quot; | Yes&lt;br /&gt;
| 0x37 / 0x33&lt;br /&gt;
| v2&lt;br /&gt;
| style=&amp;quot;background: #ccffbb&amp;quot; | Yes&lt;br /&gt;
|-&lt;br /&gt;
| [[2.2.0-4]]&lt;br /&gt;
| style=&amp;quot;background: #ccffbb&amp;quot; | Yes&lt;br /&gt;
| 0x37 / 0x33&lt;br /&gt;
| v2&lt;br /&gt;
| style=&amp;quot;background: #ffccbb&amp;quot; | No&lt;br /&gt;
|-&lt;br /&gt;
| [[6.0.0-11]]&lt;br /&gt;
| style=&amp;quot;background: #ccffbb&amp;quot; | Yes&lt;br /&gt;
| 0x37 / 0x33&lt;br /&gt;
| v3&lt;br /&gt;
| style=&amp;quot;background: #ffccbb&amp;quot; | No&lt;br /&gt;
|-&lt;br /&gt;
| [[9.6.0-24|9.6.0-X]]&lt;br /&gt;
| style=&amp;quot;background: #ffccbb&amp;quot; | No&lt;br /&gt;
| 0x1A / 0x19&lt;br /&gt;
| v2?&lt;br /&gt;
| style=&amp;quot;background: #ffccbb&amp;quot; | No&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Repeating CTR Fail ===&lt;br /&gt;
On the 3DS savegames are stored much like on the DS, that is on a FLASH chip in the gamecart. On the DS these savegames were stored in plain-text but on the 3DS a layer of encryption was added. This is AES-CTR, as the contents of several savegames exhibit the odd behavior that xor-ing certain parts of the savegame together will result in the plain-text appearing.&lt;br /&gt;
&lt;br /&gt;
The reason this works is because the stream cipher used has a period of 512 bytes. That is to say, it will repeat the same keystream after 512 bytes. The way you encrypt with a stream cipher is you XOR your data with the keystream as it is produced. Unfortunately, if your streamcipher repeats and you are encrypting a known plain-text (in our case, zeros) you are basically giving away your valuable keystream.&lt;br /&gt;
&lt;br /&gt;
So how do you use this to decrypt a savegame on a 3DS? First off, you chunk up the savegame into 512 byte chunks. Then, you bin these chunks by their contents, discarding any that contain only FF. Now look for the most common chunk. This is your keystream. Now XOR the keystream with your original savegame and you should have a fully decrypted savegame. XOR with the keystream again to produce an encrypted savegame.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== KeyY Generation methid ===&lt;br /&gt;
&lt;br /&gt;
The [[NCSD]] partition flags determine the method used to generate this keyY.&lt;br /&gt;
&lt;br /&gt;
==== v1 ====&lt;br /&gt;
&lt;br /&gt;
When all of the flags checked by the running NATIVE_FIRM are clear, the keyY is the following:&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;
| First 8-bytes from the plaintext [[NCCH#CXI|CXI]] accessdesc signature.&lt;br /&gt;
|-&lt;br /&gt;
| 0x8&lt;br /&gt;
| 0x4&lt;br /&gt;
| u32 CardID0 from [[Gamecards|gamecard]] plaintext-mode command 0x90, Process9 reads this with the [[NTRCARD]] hw. The actual cmdID used by Process9 is different since Process9 reads it with the gamecard in encrypted-mode.&lt;br /&gt;
|-&lt;br /&gt;
| 0xC&lt;br /&gt;
| 0x4&lt;br /&gt;
| u32 CardID1 from [[Gamecards|gamecard]] plaintext-mode command 0xA0, Process9 reads this with the [[NTRCARD]] hw. The actual cmdID used by Process9 is different since Process9 reads it with the gamecard in encrypted-mode.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== v2 ====&lt;br /&gt;
&lt;br /&gt;
Key Y is the first 0x10 bytes of SHA-256 calculated over the following data&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;
| 0x8&lt;br /&gt;
| First 8-bytes from the plaintext [[NCCH#CXI|CXI]] accessdesc signature.&lt;br /&gt;
|-&lt;br /&gt;
| 0x8&lt;br /&gt;
| 0x40&lt;br /&gt;
| read from a gamecard command(this 0x40-byte data is also read by [[Process_Services_PXI|GetRomId]], which is the gamecard-uniqueID)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
This keyY generation method was implemented with [[2.0.0-2]] via NCSD partition flag[3], however the proper CTR wasn&#039;t implemented for flag[7] until [[2.2.0-4]]. The hashed keyY flag[3] implemented with [[2.0.0-2]] was likely never used with retail gamecards.&lt;br /&gt;
&lt;br /&gt;
==== v3 ====&lt;br /&gt;
&lt;br /&gt;
[[6.0.0-11]] implemented support for generating the savegame keyY with a new method, this method is much more complex than previous keyY methods. This is enabled via new [[NCSD]] partition flags, all retail games which have the NCSD image finalized after the [[6.0.0-11]] release(and [[6.0.0-11]]+ in the system update partition) will have these flags set for using this new method.&lt;br /&gt;
&lt;br /&gt;
First, a SHA-256 hash is calculated over the following data&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;
| 0x8&lt;br /&gt;
| First 8-bytes from the plaintext [[NCCH#CXI|CXI]] accessdesc signature.&lt;br /&gt;
|-&lt;br /&gt;
| 0x8&lt;br /&gt;
| 0x40&lt;br /&gt;
| Same ID as [[Process_Services_PXI|GetRomId]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x48&lt;br /&gt;
| 0x8&lt;br /&gt;
| CXI Program ID&lt;br /&gt;
|-&lt;br /&gt;
| 0x50&lt;br /&gt;
| 0x20&lt;br /&gt;
| ExeFS:/.code hash from the decrypted [[ExeFS]] header&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Then an [[AES]]-CMAC is calculated over this hash. The output CMAC is used for keyY. The key slot for this CMAC is 0x2F.&lt;br /&gt;
&lt;br /&gt;
The 0x2F keyY used for calculating this AES-CMAC (not to be confused with the final keyY for decrypting/signing savegames) is initialized while NATIVE_FIRM is loading, this keyY is generated via the [[RSA]] engine. The RSA slot used here is slot0(key-data for slot0 is initialized by bootrom), this RSA slot0 key-data is overwritten during system boot. This RSA slot0 key-data gets overwritten with the RSA key-data used for verifying RSA signatures, every time Process9 verifies any RSA signatures except for [[NCCH|NCCH]] accessdesc signatures. Starting with [[7.0.0-13]] this key-init function used at boot is also used to initialize a separate keyslot used for the new [[NCCH]] encryption method.&lt;br /&gt;
&lt;br /&gt;
This [[FIRM|Process9]] key-init function first checks if a certain 0x10-byte block in the 0x01FF8000 region is all-zero. When all-zero it immediately returns, otherwise it clears that block then continues to do the key generation. This is likely for supporting launching a v6.0+ NATIVE_FIRM under this FIRM.&lt;br /&gt;
&lt;br /&gt;
== Gamecard wear leveling ==&lt;br /&gt;
&lt;br /&gt;
The 3DS employs a wear leveling scheme on the savegame FLASH chips(only used for CARD1 gamecards). This is done through the usage of blockmaps and a journal. The blockmap is located at offset 0 of the flash chip, and is immediately followed by the journal. The initial state is dictated by the blockmap, and the journal is then applied to that.&lt;br /&gt;
&lt;br /&gt;
There are two versions of wear leveling have been observed. V1 is used for 128KB and 512 KB CARD1 flash chips. V2 is used for 1MB CARD1 flash chips (uncommon. Pokemon Sun/Moon is an exampe).&lt;br /&gt;
&lt;br /&gt;
First, there are two 32-bit integers whose purposes are currently unknown. They generally increase the value as the savegame is written more times, so probably counter for how many times the journal became full and got flushed into the block map, and/or how many times &amp;lt;code&amp;gt;alloc_cnt&amp;lt;/code&amp;gt; has wrapped around. &lt;br /&gt;
&lt;br /&gt;
Then comes the actual blockmap. The block map contains entries of 10 bytes (V1) or 2 bytes (V2) with total number of &amp;lt;code&amp;gt;(flash_size / 0x1000 - 1)&amp;lt;/code&amp;gt;. &lt;br /&gt;
The blockmap entry is simple:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
struct blockmap_entry_v1 {&lt;br /&gt;
        uint8_t phys_sec; // when bit7 is set, block is initialized and has checksums, otherwise checksums are all zero&lt;br /&gt;
        uint8_t alloc_cnt;&lt;br /&gt;
        uint8_t chksums[8];&lt;br /&gt;
} __attribute__((__packed__));&lt;br /&gt;
&lt;br /&gt;
struct blockmap_entry_v2 {&lt;br /&gt;
        // Note that the phys_sec and alloc_cnt field are swapped in v2, &lt;br /&gt;
        // but the initialized bit is still on the first byte&lt;br /&gt;
        uint8_t alloc_cnt; // when bit7 is set, block is initialized&lt;br /&gt;
        uint8_t phys_sec; &lt;br /&gt;
        // v2 has no chksums&lt;br /&gt;
} __attribute__((__packed__));&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There&#039;s one entry per 0x1000-byte sector, counting from physical sector 1 (sector 0 contains the blockmap/journal).&lt;br /&gt;
&lt;br /&gt;
A 2-byte CRC16 follows the block map. For V1 it immediately follows the last block map entry. For V2 it is located at 0x3FE, and bytes before the CRC is padded with zero. The CRC16 checks all the bytes before it, including the two unknown integers, the block map, and the padding bytes for V2. The CRC standard used looks like CRC-16-IBM (modbus). Here is the code in Rust for it&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
fn crc16(data: &amp;amp;[u8]) -&amp;gt; u16 {&lt;br /&gt;
    let poly = 0xA001;&lt;br /&gt;
    let mut crc = 0xFFFFu16;&lt;br /&gt;
    for byte in data {&lt;br /&gt;
        crc ^= &amp;lt;u16&amp;gt;::from(*byte);&lt;br /&gt;
        for _ in 0..8 {&lt;br /&gt;
            let b = crc &amp;amp; 1 != 0;&lt;br /&gt;
            crc &amp;gt;&amp;gt;= 1;&lt;br /&gt;
            if b {&lt;br /&gt;
                crc ^= poly;&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    crc&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then comes the journal. The journal contains entries that describes how sectors should be remapped. The rest bytes before 0x1000 after all journal entries are padded with 0xFF&lt;br /&gt;
The journal entry structure is as follows:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
struct journal_entry_half {&lt;br /&gt;
        uint8_t virt_sec;       // Mapped to sector&lt;br /&gt;
        uint8_t prev_virt_sec;  // Physical sector previously mapped to&lt;br /&gt;
        uint8_t phys_sec;       // Mapped from sector&lt;br /&gt;
        uint8_t prev_phys_sec;  // Virtual sector previously mapped to&lt;br /&gt;
        uint8_t phys_realloc_cnt;       // Amount of times physical sector has been remapped&lt;br /&gt;
        uint8_t virt_realloc_cnt;       // Amount of times virtual sector has been remapped&lt;br /&gt;
        uint8_t chksums[8];     // Unused &amp;amp; uninitialized for V2&lt;br /&gt;
} __attribute__((__packed__));&lt;br /&gt;
&lt;br /&gt;
struct journal_entry{&lt;br /&gt;
        struct journal_entry_half entry;&lt;br /&gt;
        struct journal_entry_half dupe; // same data as `entry`. No idea what this is used fore&lt;br /&gt;
        uint32_t uninitialized;         // 0xFFFFFFFF in newer system&lt;br /&gt;
}__attribute__((__packed__));&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The checksums in the blockmap/journal entries work as follows:&lt;br /&gt;
* each byte is the checksum of an encrypted 0x200 bytes large block&lt;br /&gt;
* to calculate the checksum, a CRC16 of the block (same CRC16 algorithm as above) is calculated, and the two bytes of the CRC16 are XORed together to produce the 8bit checksum&lt;br /&gt;
&lt;br /&gt;
== Initialization ==&lt;br /&gt;
&lt;br /&gt;
When a save FLASH contains all xFFFF blocks it&#039;s assumed uninitialized by the game cartridges and it initializes default data in place, without prompting the user. The 0xFFFFFFFF blocks are uninitialized data. When creating a non-gamecard savegame and other images/files, it&#039;s initially all 0xFFFFFFFF until it&#039;s formatted where some of the blocks are overwritten with encrypted data.&lt;br /&gt;
&lt;br /&gt;
I got a new game SplinterCell3D-Pal and I downloaded the save and it was 128KB of 0xFF, except the first 0x10 bytes which were the letter &#039;Z&#039; (uppercase) --[[User:Elisherer|Elisherer]] 22:41, 15 October 2011 (CEST)&lt;br /&gt;
&lt;br /&gt;
== Fun Facts ==&lt;br /&gt;
&lt;br /&gt;
If you have facts that you found out by looking at the binary files please share them here:&lt;br /&gt;
&lt;br /&gt;
* From one save to another the game backups the last files that were in the partition and the entire image header in &amp;quot;random&amp;quot; locations.. --[[User:Elisherer|Elisherer]] 22:41, 15 October 2011 (CEST)&lt;br /&gt;
&lt;br /&gt;
== Tools ==&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/wwylele/save3ds save3ds] supports reading and modifying savegames, extdata and title database in FUSE filesystem or batch extracting/importing.&lt;br /&gt;
* [https://github.com/3dshax/3ds/tree/master/3dsfuse 3dsfuse] supports reading and modifying savegames. In the mounted FUSE filesystem, the /output.sav is the raw FLASH save-image. When the save was modified, a separate tool to update the CMAC must be used with /clean.sav, prior to writing output.sav to a gamecard. (This is an old tool that doesn&#039;t handle the savegame format correctly. --[[User:Wwylele|Wwylele]] ([[User talk:Wwylele|talk]]) 16:13, 2 December 2019 (CET))&lt;br /&gt;
* [[3DSExplorer]] supports reading of savegames, it doesn&#039;t support reading the new encrypted savegames and maybe in the future it will support modifying (some of the modyfing code is already implemented).&lt;br /&gt;
* [https://github.com/wwylele/3ds-save-tool wwylele&#039;s 3ds-save-tool] supports extracting files from savegames and extdata. It properly reconstructs data from the DPFS tree and extracts files in directories hierarchy.&lt;br /&gt;
&lt;br /&gt;
[[セーブデータ|Japanese]]&lt;/div&gt;</summary>
		<author><name>Wwylele</name></author>
	</entry>
	<entry>
		<id>https://www.3dbrew.org/w/index.php?title=Savegames&amp;diff=21125</id>
		<title>Savegames</title>
		<link rel="alternate" type="text/html" href="https://www.3dbrew.org/w/index.php?title=Savegames&amp;diff=21125"/>
		<updated>2019-12-22T18:30:24Z</updated>

		<summary type="html">&lt;p&gt;Wwylele: /* Gamecard savegame Encryption */ Add summary table for encryption&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This page describes the format and encryption of savegames contained in gamecards, SD and NAND. You can find savegames from various 3DS games on the [[Games]] page.&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
Savegames are stored in [[DISA and DIFF|DISA container format]]. Inside the DISA container, it forms a [[Inner FAT|FAT filesystem]]. &#039;&#039;&#039;Please refer to these pages for how to fully extract save files&#039;&#039;&#039;. This page only describes additional encryption wear leveling on top of the DISA container. These layers only apply to gamecard save games. SD savegames and NAND savegames are DISA containers in plaintext after decrypting the common SD/NAND encryption layer.&lt;br /&gt;
&lt;br /&gt;
== Gamecard savegame Encryption ==&lt;br /&gt;
&lt;br /&gt;
Gamecard encryption is AES-CTR applied on top of DISA container, but below the wear leveling layer (if exists). The same key Y used for encryption is also used for DISA CMAC signing. Several versions of encryption scheme have been introduced over the time.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
!  FW Introduced&lt;br /&gt;
!  Old3DS&lt;br /&gt;
!  [[AES#Keyslot|AES Keyslots]] (Encryotion / CMAC)&lt;br /&gt;
!  Key Y generation method&lt;br /&gt;
!  Repeating CTR&lt;br /&gt;
|-&lt;br /&gt;
| The initial version&lt;br /&gt;
| style=&amp;quot;background: #ccffbb&amp;quot; | Yes&lt;br /&gt;
| 0x37 / 0x33&lt;br /&gt;
| v1&lt;br /&gt;
| style=&amp;quot;background: #ccffbb&amp;quot; | Yes&lt;br /&gt;
|-&lt;br /&gt;
| [[2.0.0-2]]&lt;br /&gt;
| style=&amp;quot;background: #ccffbb&amp;quot; | Yes&lt;br /&gt;
| 0x37 / 0x33&lt;br /&gt;
| v2&lt;br /&gt;
| style=&amp;quot;background: #ccffbb&amp;quot; | Yes&lt;br /&gt;
|-&lt;br /&gt;
| [[2.2.0-4]]&lt;br /&gt;
| style=&amp;quot;background: #ccffbb&amp;quot; | Yes&lt;br /&gt;
| 0x37 / 0x33&lt;br /&gt;
| v2&lt;br /&gt;
| style=&amp;quot;background: #ffccbb&amp;quot; | No&lt;br /&gt;
|-&lt;br /&gt;
| [[6.0.0-11]]&lt;br /&gt;
| style=&amp;quot;background: #ccffbb&amp;quot; | Yes&lt;br /&gt;
| 0x37 / 0x33&lt;br /&gt;
| v3&lt;br /&gt;
| style=&amp;quot;background: #ffccbb&amp;quot; | No&lt;br /&gt;
|-&lt;br /&gt;
| [[9.6.0-24|9.6.0-X]]&lt;br /&gt;
| style=&amp;quot;background: #ffccbb&amp;quot; | No&lt;br /&gt;
| 0x1A / 0x19&lt;br /&gt;
| v2?&lt;br /&gt;
| style=&amp;quot;background: #ffccbb&amp;quot; | No&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Repeating CTR Fail ===&lt;br /&gt;
On the 3DS savegames are stored much like on the DS, that is on a FLASH chip in the gamecart. On the DS these savegames were stored in plain-text but on the 3DS a layer of encryption was added. This is AES-CTR, as the contents of several savegames exhibit the odd behavior that xor-ing certain parts of the savegame together will result in the plain-text appearing.&lt;br /&gt;
&lt;br /&gt;
The reason this works is because the stream cipher used has a period of 512 bytes. That is to say, it will repeat the same keystream after 512 bytes. The way you encrypt with a stream cipher is you XOR your data with the keystream as it is produced. Unfortunately, if your streamcipher repeats and you are encrypting a known plain-text (in our case, zeros) you are basically giving away your valuable keystream.&lt;br /&gt;
&lt;br /&gt;
So how do you use this to decrypt a savegame on a 3DS? First off, you chunk up the savegame into 512 byte chunks. Then, you bin these chunks by their contents, discarding any that contain only FF. Now look for the most common chunk. This is your keystream. Now XOR the keystream with your original savegame and you should have a fully decrypted savegame. XOR with the keystream again to produce an encrypted savegame.&lt;br /&gt;
&lt;br /&gt;
=== Savegame keyY ===&lt;br /&gt;
&lt;br /&gt;
All gamecard and SD savegames are encrypted with AES-CTR. The base CTR for gamecard savegames is all-zero. The gamecard savegame [[AES|keyslots]]&#039; keyY(these savegame keyslots use the hardware key-generator) is unique for each region and for each game. The [[NCSD]] partition flags determine the method used to generate this keyY. When the save [[NCSD]] flags checked by the running NATIVE_FIRM are all-zero, the system will use the repeating CTR, otherwise a proper CTR which never repeats within the image is used.&lt;br /&gt;
&lt;br /&gt;
The [[AES]]-CMAC (which uses a hardware key-generator keyslot, as mentioned above) at the the beginning of the savegame must match the calculated CMAC using the DISA/DIFF data, otherwise the savegame is considered corrupted(see below).&lt;br /&gt;
&lt;br /&gt;
When all of the flags checked by the running NATIVE_FIRM are clear, the keyY(original keyY method used with saves where the CTR repeats within the image) is the following:&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;
| First 8-bytes from the plaintext [[NCCH#CXI|CXI]] accessdesc signature.&lt;br /&gt;
|-&lt;br /&gt;
| 0x8&lt;br /&gt;
| 0x4&lt;br /&gt;
| u32 CardID0 from [[Gamecards|gamecard]] plaintext-mode command 0x90, Process9 reads this with the [[NTRCARD]] hw. The actual cmdID used by Process9 is different since Process9 reads it with the gamecard in encrypted-mode.&lt;br /&gt;
|-&lt;br /&gt;
| 0xC&lt;br /&gt;
| 0x4&lt;br /&gt;
| u32 CardID1 from [[Gamecards|gamecard]] plaintext-mode command 0xA0, Process9 reads this with the [[NTRCARD]] hw. The actual cmdID used by Process9 is different since Process9 reads it with the gamecard in encrypted-mode.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== [[2.0.0-2]] Hashed keyY and [[2.2.0-4]] Savegame Encryption ====&lt;br /&gt;
&lt;br /&gt;
When certain [[NCSD]] partition flags are set, a SHA-256 hash is calculated over the data from the CXI(same data used with the original plain keyY), and the 0x40-bytes read from a gamecard command(this 0x40-byte data is also read by [[Process_Services_PXI|GetRomId]], which is the gamecard-uniqueID). The first 0x10-bytes from this hash is used for the keyY. When flag[7] is set, the CTR will never repeat within the save image, unlike the original CTR-method. All games which had the retail NCSD image finalized after the [[2.2.0-4]] update(and contain [[2.2.0-4]]+ in the [[System Update CFA|System update partition]]), use this encryption method.&lt;br /&gt;
&lt;br /&gt;
This keyY generation method was implemented with [[2.0.0-2]] via NCSD partition flag[3], however the proper CTR wasn&#039;t implemented for flag[7] until [[2.2.0-4]]. The hashed keyY flag[3] implemented with [[2.0.0-2]] was likely never used with retail gamecards.&lt;br /&gt;
&lt;br /&gt;
==== [[6.0.0-11]] Savegame keyY ====&lt;br /&gt;
&lt;br /&gt;
[[6.0.0-11]] implemented support for generating the savegame keyY with a new method, this method is much more complex than previous keyY methods. This is enabled via new [[NCSD]] partition flags, all retail games which have the NCSD image finalized after the [[6.0.0-11]] release(and [[6.0.0-11]]+ in the system update partition) will have these flags set for using this new method.&lt;br /&gt;
&lt;br /&gt;
A SHA-256 hash is calculated over the same data used with the above hashed keyY method, after hashing the above data the following data is hashed: the CXI programID, and the ExeFS:/.code hash from the decrypted [[ExeFS]] header. An [[AES]]-CMAC (the keyslot used for this uses the hardware key-scrambler) is then calculated over this hash, the output CMAC is used for the savegame keyY.&lt;br /&gt;
&lt;br /&gt;
The keyY used for calculating this AES-CMAC is initialized while NATIVE_FIRM is loading, this keyY is generated via the [[RSA]] engine. The RSA slot used here is slot0(key-data for slot0 is initialized by bootrom), this RSA slot0 key-data is overwritten during system boot. This RSA slot0 key-data gets overwritten with the RSA key-data used for verifying RSA signatures, every time Process9 verifies any RSA signatures except for [[NCCH|NCCH]] accessdesc signatures. Starting with [[7.0.0-13]] this key-init function used at boot is also used to initialize a separate keyslot used for the new [[NCCH]] encryption method.&lt;br /&gt;
&lt;br /&gt;
This [[FIRM|Process9]] key-init function first checks if a certain 0x10-byte block in the 0x01FF8000 region is all-zero. When all-zero it immediately returns, otherwise it clears that block then continues to do the key generation. This is likely for supporting launching a v6.0+ NATIVE_FIRM under this FIRM.&lt;br /&gt;
&lt;br /&gt;
== Gamecard wear leveling ==&lt;br /&gt;
&lt;br /&gt;
The 3DS employs a wear leveling scheme on the savegame FLASH chips(only used for CARD1 gamecards). This is done through the usage of blockmaps and a journal. The blockmap is located at offset 0 of the flash chip, and is immediately followed by the journal. The initial state is dictated by the blockmap, and the journal is then applied to that.&lt;br /&gt;
&lt;br /&gt;
There are two versions of wear leveling have been observed. V1 is used for 128KB and 512 KB CARD1 flash chips. V2 is used for 1MB CARD1 flash chips (uncommon. Pokemon Sun/Moon is an exampe).&lt;br /&gt;
&lt;br /&gt;
First, there are two 32-bit integers whose purposes are currently unknown. They generally increase the value as the savegame is written more times, so probably counter for how many times the journal became full and got flushed into the block map, and/or how many times &amp;lt;code&amp;gt;alloc_cnt&amp;lt;/code&amp;gt; has wrapped around. &lt;br /&gt;
&lt;br /&gt;
Then comes the actual blockmap. The block map contains entries of 10 bytes (V1) or 2 bytes (V2) with total number of &amp;lt;code&amp;gt;(flash_size / 0x1000 - 1)&amp;lt;/code&amp;gt;. &lt;br /&gt;
The blockmap entry is simple:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
struct blockmap_entry_v1 {&lt;br /&gt;
        uint8_t phys_sec; // when bit7 is set, block is initialized and has checksums, otherwise checksums are all zero&lt;br /&gt;
        uint8_t alloc_cnt;&lt;br /&gt;
        uint8_t chksums[8];&lt;br /&gt;
} __attribute__((__packed__));&lt;br /&gt;
&lt;br /&gt;
struct blockmap_entry_v2 {&lt;br /&gt;
        // Note that the phys_sec and alloc_cnt field are swapped in v2, &lt;br /&gt;
        // but the initialized bit is still on the first byte&lt;br /&gt;
        uint8_t alloc_cnt; // when bit7 is set, block is initialized&lt;br /&gt;
        uint8_t phys_sec; &lt;br /&gt;
        // v2 has no chksums&lt;br /&gt;
} __attribute__((__packed__));&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There&#039;s one entry per 0x1000-byte sector, counting from physical sector 1 (sector 0 contains the blockmap/journal).&lt;br /&gt;
&lt;br /&gt;
A 2-byte CRC16 follows the block map. For V1 it immediately follows the last block map entry. For V2 it is located at 0x3FE, and bytes before the CRC is padded with zero. The CRC16 checks all the bytes before it, including the two unknown integers, the block map, and the padding bytes for V2. The CRC standard used looks like CRC-16-IBM (modbus). Here is the code in Rust for it&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
fn crc16(data: &amp;amp;[u8]) -&amp;gt; u16 {&lt;br /&gt;
    let poly = 0xA001;&lt;br /&gt;
    let mut crc = 0xFFFFu16;&lt;br /&gt;
    for byte in data {&lt;br /&gt;
        crc ^= &amp;lt;u16&amp;gt;::from(*byte);&lt;br /&gt;
        for _ in 0..8 {&lt;br /&gt;
            let b = crc &amp;amp; 1 != 0;&lt;br /&gt;
            crc &amp;gt;&amp;gt;= 1;&lt;br /&gt;
            if b {&lt;br /&gt;
                crc ^= poly;&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    crc&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then comes the journal. The journal contains entries that describes how sectors should be remapped. The rest bytes before 0x1000 after all journal entries are padded with 0xFF&lt;br /&gt;
The journal entry structure is as follows:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
struct journal_entry_half {&lt;br /&gt;
        uint8_t virt_sec;       // Mapped to sector&lt;br /&gt;
        uint8_t prev_virt_sec;  // Physical sector previously mapped to&lt;br /&gt;
        uint8_t phys_sec;       // Mapped from sector&lt;br /&gt;
        uint8_t prev_phys_sec;  // Virtual sector previously mapped to&lt;br /&gt;
        uint8_t phys_realloc_cnt;       // Amount of times physical sector has been remapped&lt;br /&gt;
        uint8_t virt_realloc_cnt;       // Amount of times virtual sector has been remapped&lt;br /&gt;
        uint8_t chksums[8];     // Unused &amp;amp; uninitialized for V2&lt;br /&gt;
} __attribute__((__packed__));&lt;br /&gt;
&lt;br /&gt;
struct journal_entry{&lt;br /&gt;
        struct journal_entry_half entry;&lt;br /&gt;
        struct journal_entry_half dupe; // same data as `entry`. No idea what this is used fore&lt;br /&gt;
        uint32_t uninitialized;         // 0xFFFFFFFF in newer system&lt;br /&gt;
}__attribute__((__packed__));&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The checksums in the blockmap/journal entries work as follows:&lt;br /&gt;
* each byte is the checksum of an encrypted 0x200 bytes large block&lt;br /&gt;
* to calculate the checksum, a CRC16 of the block (same CRC16 algorithm as above) is calculated, and the two bytes of the CRC16 are XORed together to produce the 8bit checksum&lt;br /&gt;
&lt;br /&gt;
== Initialization ==&lt;br /&gt;
&lt;br /&gt;
When a save FLASH contains all xFFFF blocks it&#039;s assumed uninitialized by the game cartridges and it initializes default data in place, without prompting the user. The 0xFFFFFFFF blocks are uninitialized data. When creating a non-gamecard savegame and other images/files, it&#039;s initially all 0xFFFFFFFF until it&#039;s formatted where some of the blocks are overwritten with encrypted data.&lt;br /&gt;
&lt;br /&gt;
I got a new game SplinterCell3D-Pal and I downloaded the save and it was 128KB of 0xFF, except the first 0x10 bytes which were the letter &#039;Z&#039; (uppercase) --[[User:Elisherer|Elisherer]] 22:41, 15 October 2011 (CEST)&lt;br /&gt;
&lt;br /&gt;
== Fun Facts ==&lt;br /&gt;
&lt;br /&gt;
If you have facts that you found out by looking at the binary files please share them here:&lt;br /&gt;
&lt;br /&gt;
* From one save to another the game backups the last files that were in the partition and the entire image header in &amp;quot;random&amp;quot; locations.. --[[User:Elisherer|Elisherer]] 22:41, 15 October 2011 (CEST)&lt;br /&gt;
&lt;br /&gt;
== Tools ==&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/wwylele/save3ds save3ds] supports reading and modifying savegames, extdata and title database in FUSE filesystem or batch extracting/importing.&lt;br /&gt;
* [https://github.com/3dshax/3ds/tree/master/3dsfuse 3dsfuse] supports reading and modifying savegames. In the mounted FUSE filesystem, the /output.sav is the raw FLASH save-image. When the save was modified, a separate tool to update the CMAC must be used with /clean.sav, prior to writing output.sav to a gamecard. (This is an old tool that doesn&#039;t handle the savegame format correctly. --[[User:Wwylele|Wwylele]] ([[User talk:Wwylele|talk]]) 16:13, 2 December 2019 (CET))&lt;br /&gt;
* [[3DSExplorer]] supports reading of savegames, it doesn&#039;t support reading the new encrypted savegames and maybe in the future it will support modifying (some of the modyfing code is already implemented).&lt;br /&gt;
* [https://github.com/wwylele/3ds-save-tool wwylele&#039;s 3ds-save-tool] supports extracting files from savegames and extdata. It properly reconstructs data from the DPFS tree and extracts files in directories hierarchy.&lt;br /&gt;
&lt;br /&gt;
[[セーブデータ|Japanese]]&lt;/div&gt;</summary>
		<author><name>Wwylele</name></author>
	</entry>
	<entry>
		<id>https://www.3dbrew.org/w/index.php?title=DISA_and_DIFF&amp;diff=21124</id>
		<title>DISA and DIFF</title>
		<link rel="alternate" type="text/html" href="https://www.3dbrew.org/w/index.php?title=DISA_and_DIFF&amp;diff=21124"/>
		<updated>2019-12-22T18:12:17Z</updated>

		<summary type="html">&lt;p&gt;Wwylele: /* AES CMAC */ Explicitly shows the nested hash block format&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This page describes DISA and DIFF format as the underlying container of [[Savegames]], [[Extdata]] and [[Title Database]]. For further format specification of the inner data, please refer to their own page.&lt;br /&gt;
&lt;br /&gt;
All data in this page is little-endian. All &amp;quot;unused / padding&amp;quot; fields can contain uninitialized data unless otherwise specified.&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
&lt;br /&gt;
DISA and DIFF are two container formats. They are very similar and are used for various purposes in 3DS. Here is a summary table of their usage, the CMAC type and the AES key slot used (the meaning of these is explained in the next section):&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! Usage&lt;br /&gt;
! Media&lt;br /&gt;
! Container format&lt;br /&gt;
! [[#AES CMAC|CMAC type]]&lt;br /&gt;
! CMAC [[AES Registers|Keyslot]]&lt;br /&gt;
|-&lt;br /&gt;
| [[Savegames]]&lt;br /&gt;
| Gamecard&lt;br /&gt;
| DISA&lt;br /&gt;
| [[#CTR-NOR0|CTR-NOR0]]&lt;br /&gt;
| 0x19 / 0x33&lt;br /&gt;
|-&lt;br /&gt;
| [[Savegames]]&lt;br /&gt;
| [[SD Filesystem|SD]]&lt;br /&gt;
| DISA&lt;br /&gt;
| [[#CTR-SIGN|CTR-SIGN]]&lt;br /&gt;
| 0x30&lt;br /&gt;
|-&lt;br /&gt;
| [[System SaveData]]&lt;br /&gt;
| [[Flash Filesystem|NAND]]&lt;br /&gt;
| DISA&lt;br /&gt;
| [[#CTR-SYS0|CTR-SYS0]]&lt;br /&gt;
| 0x30&lt;br /&gt;
|-&lt;br /&gt;
| [[Extdata|Private Extdata]]&lt;br /&gt;
| [[SD Filesystem|SD]]&lt;br /&gt;
| DIFF&lt;br /&gt;
| [[#CTR-EXT0|CTR-EXT0]]&lt;br /&gt;
| 0x30&lt;br /&gt;
|-&lt;br /&gt;
| [[Extdata|Shared Extdata]]&lt;br /&gt;
| [[Flash Filesystem|NAND]]&lt;br /&gt;
| DIFF&lt;br /&gt;
| [[#CTR-EXT0|CTR-EXT0]]&lt;br /&gt;
| 0x30&lt;br /&gt;
|-&lt;br /&gt;
| [[Title Database]]&lt;br /&gt;
| [[SD Filesystem|SD]]&lt;br /&gt;
| DIFF&lt;br /&gt;
| [[#CTR-9DB0|CTR-9DB0]]&lt;br /&gt;
| 0x30&lt;br /&gt;
|-&lt;br /&gt;
| [[Title Database]]&lt;br /&gt;
| [[Flash Filesystem|NAND]]&lt;br /&gt;
| DIFF&lt;br /&gt;
| [[#CTR-9DB0|CTR-9DB0]]&lt;br /&gt;
| 0x0B&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Encryption ==&lt;br /&gt;
&lt;br /&gt;
DISA and DIFF formats don&#039;t have their own encryption specification. They follow the encryption method defined by their media:&lt;br /&gt;
&lt;br /&gt;
* Gamecard savegames have special wear leveling + encryption layers. See [[Savegames]] for detail.&lt;br /&gt;
* Files on SD follow [[SD Filesystem|the general SD filesystem encryption rule]].&lt;br /&gt;
* Files on NAND are in cleartext, after decrypting [[Flash Filesystem|the NAND partition encryption]].&lt;br /&gt;
&lt;br /&gt;
== Format ==&lt;br /&gt;
&lt;br /&gt;
A DISA / DIFF file consists of the following components:&lt;br /&gt;
&lt;br /&gt;
* 0x100-byte AES CMAC&lt;br /&gt;
* 0x100-byte Header&lt;br /&gt;
* Secondary partition table&lt;br /&gt;
** Contains one or two partition descriptors, depending on the number of partitions.&lt;br /&gt;
* Primary partition table&lt;br /&gt;
** Same layout as the secondary one&lt;br /&gt;
* Partition A&lt;br /&gt;
* Partition B (optional)&lt;br /&gt;
** can only exist for DISA.&lt;br /&gt;
&lt;br /&gt;
== AES CMAC ==&lt;br /&gt;
&lt;br /&gt;
The AES CMAC is located at the beginning of the DISA / DIFF image, and it is 0x10 long. The rest 0xF0 bytes before the header are unused.&lt;br /&gt;
&lt;br /&gt;
The key used for the AES CMAC is generated by the [[AES Registers|hardware key engine]]. See the keyslot it uses in the table above.&lt;br /&gt;
&lt;br /&gt;
The data being authenticated by the AES CMAC is a 0x20-byte SHA-256 hash of a data block. The data block has different content formats among CMAC types. All types of data block contain a copy or a hash of the header, which is the start of the the rest of the verification chain, so the AES CMAC effectively authenticates the whole save image. Each type of data block is explained below.&lt;br /&gt;
&lt;br /&gt;
=== CTR-NOR0 ===&lt;br /&gt;
&lt;br /&gt;
This CMAC type is used for gamecard savegames. It is 0x28-byte long.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! Offset&lt;br /&gt;
! Length&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x00&lt;br /&gt;
| 8&lt;br /&gt;
| Magic &amp;amp;quot;CTR-NOR0&amp;amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| 0x8&lt;br /&gt;
| 0x20&lt;br /&gt;
| SHA-256 of the following 0x108-byte block&lt;br /&gt;
 {| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! Offset&lt;br /&gt;
! Length&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x00&lt;br /&gt;
| 8&lt;br /&gt;
| Magic &amp;amp;quot;CTR-SAV0&amp;amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| 0x08&lt;br /&gt;
| 0x100&lt;br /&gt;
| Copy of the DISA header&lt;br /&gt;
|}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== CTR-SIGN ===&lt;br /&gt;
&lt;br /&gt;
This CMAC type is used for SD savegames. It is 0x30-byte long.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! Offset&lt;br /&gt;
! Length&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x00&lt;br /&gt;
| 8&lt;br /&gt;
| Magic &amp;amp;quot;CTR-SIGN&amp;amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| 0x08&lt;br /&gt;
| 8&lt;br /&gt;
| Title ID&lt;br /&gt;
|-&lt;br /&gt;
| 0x10&lt;br /&gt;
| 0x20&lt;br /&gt;
| SHA-256 of the following 0x108-byte block&lt;br /&gt;
 {| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! Offset&lt;br /&gt;
! Length&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x00&lt;br /&gt;
| 8&lt;br /&gt;
| Magic &amp;amp;quot;CTR-SAV0&amp;amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| 0x08&lt;br /&gt;
| 0x100&lt;br /&gt;
| Copy of the DISA header&lt;br /&gt;
|}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== CTR-SYS0 ===&lt;br /&gt;
&lt;br /&gt;
This CMAC type is used for NAND system save. It is 0x110-byte long.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! Offset&lt;br /&gt;
! Length&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x00&lt;br /&gt;
| 8&lt;br /&gt;
| Magic &amp;amp;quot;CTR-SYS0&amp;amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| 0x08&lt;br /&gt;
| 8&lt;br /&gt;
| Save ID. The higher word is always zero&lt;br /&gt;
|-&lt;br /&gt;
| 0x10&lt;br /&gt;
| 0x100&lt;br /&gt;
| Copy of the DISA header&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== CTR-EXT0 ===&lt;br /&gt;
&lt;br /&gt;
This CMAC type is used for extdata. It is 0x11C-byte long.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! Offset&lt;br /&gt;
! Length&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x00&lt;br /&gt;
| 8&lt;br /&gt;
| Magic &amp;amp;quot;CTR-EXT0&amp;amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| 0x08&lt;br /&gt;
| 8&lt;br /&gt;
| Extdata ID&lt;br /&gt;
|-&lt;br /&gt;
| 0x10&lt;br /&gt;
| 4&lt;br /&gt;
| 0 for Quota.dat, 1 otherwise&lt;br /&gt;
|-&lt;br /&gt;
| 0x14&lt;br /&gt;
| 4&lt;br /&gt;
| ID in the device file name. 0 for Quota.dat&lt;br /&gt;
|-&lt;br /&gt;
| 0x18&lt;br /&gt;
| 4&lt;br /&gt;
| ID in the device directory name that the file is in. 0 for Quota.dat&lt;br /&gt;
|-&lt;br /&gt;
| 0x1C&lt;br /&gt;
| 0x100&lt;br /&gt;
| Copy of the DIFF header&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== CTR-9DB0 ===&lt;br /&gt;
&lt;br /&gt;
This CMAC type is used for title database. It is 0x10C-byte long.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! Offset&lt;br /&gt;
! Length&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x00&lt;br /&gt;
| 8&lt;br /&gt;
| Magic &amp;amp;quot;CTR-9DB0&amp;amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| 0x08&lt;br /&gt;
| 4&lt;br /&gt;
| Database ID. Each .db file has its own ID&lt;br /&gt;
|-&lt;br /&gt;
| 0x0C&lt;br /&gt;
| 0x100&lt;br /&gt;
| Copy of the DIFF header&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Header ==&lt;br /&gt;
&lt;br /&gt;
The header located at offset 0x100 defines the rest components of the file (partitions and their tables). All offsets in the header are relative to the beginning of the DISA/DIFF file, except for partition descriptor offsets, which are relative to the beginning of the (active) partition table. DISA and DIFF have different header format.&lt;br /&gt;
&lt;br /&gt;
=== DISA header ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! Offset&lt;br /&gt;
! Length&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x00&lt;br /&gt;
| 4&lt;br /&gt;
| Magic &amp;amp;quot;DISA&amp;amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| 0x04&lt;br /&gt;
| 4&lt;br /&gt;
| Magic 0x40000&lt;br /&gt;
|-&lt;br /&gt;
| 0x08&lt;br /&gt;
| 4&lt;br /&gt;
| Partition count, 1 or 2&lt;br /&gt;
|-&lt;br /&gt;
| 0x0C&lt;br /&gt;
| 4&lt;br /&gt;
| Padding&lt;br /&gt;
|-&lt;br /&gt;
| 0x10&lt;br /&gt;
| 8&lt;br /&gt;
| Secondary partition table offset&lt;br /&gt;
|-&lt;br /&gt;
| 0x18&lt;br /&gt;
| 8&lt;br /&gt;
| Primary partition table offset&lt;br /&gt;
|-&lt;br /&gt;
| 0x20&lt;br /&gt;
| 8&lt;br /&gt;
| Partition table size&lt;br /&gt;
|-&lt;br /&gt;
| 0x28&lt;br /&gt;
| 8&lt;br /&gt;
| Partition A descriptor offset in the partition table&lt;br /&gt;
|-&lt;br /&gt;
| 0x30&lt;br /&gt;
| 8&lt;br /&gt;
| Partition A descriptor size&lt;br /&gt;
|-&lt;br /&gt;
| 0x38&lt;br /&gt;
| 8&lt;br /&gt;
| Partition B descriptor offset in the partition table&lt;br /&gt;
|-&lt;br /&gt;
| 0x40&lt;br /&gt;
| 8&lt;br /&gt;
| Partition B descriptor size&lt;br /&gt;
|-&lt;br /&gt;
| 0x48&lt;br /&gt;
| 8&lt;br /&gt;
| Partition A offset&lt;br /&gt;
|-&lt;br /&gt;
| 0x50&lt;br /&gt;
| 8&lt;br /&gt;
| Partition A size&lt;br /&gt;
|-&lt;br /&gt;
| 0x58&lt;br /&gt;
| 8&lt;br /&gt;
| Partition B offset&lt;br /&gt;
|-&lt;br /&gt;
| 0x60&lt;br /&gt;
| 8&lt;br /&gt;
| Partition B size&lt;br /&gt;
|-&lt;br /&gt;
| 0x68&lt;br /&gt;
| 1&lt;br /&gt;
| Active partition table, 0 = primary, 1 = secondary&lt;br /&gt;
|-&lt;br /&gt;
| 0x69&lt;br /&gt;
| 3&lt;br /&gt;
| Padding&lt;br /&gt;
|-&lt;br /&gt;
| 0x6C&lt;br /&gt;
| 0x20&lt;br /&gt;
| SHA-256 over the active partition table&lt;br /&gt;
|-&lt;br /&gt;
| 0x8C&lt;br /&gt;
| 0x74&lt;br /&gt;
| Unused&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Note:&lt;br /&gt;
&lt;br /&gt;
* When the partition count is 1, there is no partition B and all of its related fields are zero.&lt;br /&gt;
&lt;br /&gt;
=== DIFF header ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! Offset&lt;br /&gt;
! Length&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x00&lt;br /&gt;
| 4&lt;br /&gt;
| Magic &amp;amp;quot;DIFF&amp;amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| 0x04&lt;br /&gt;
| 4&lt;br /&gt;
| Magic 0x30000&lt;br /&gt;
|-&lt;br /&gt;
| 0x08&lt;br /&gt;
| 8&lt;br /&gt;
| Secondary partition table/descriptor offset&lt;br /&gt;
|-&lt;br /&gt;
| 0x10&lt;br /&gt;
| 8&lt;br /&gt;
| Primary partition table/descriptor offset&lt;br /&gt;
|-&lt;br /&gt;
| 0x18&lt;br /&gt;
| 8&lt;br /&gt;
| Partition table/descriptor size&lt;br /&gt;
|-&lt;br /&gt;
| 0x20&lt;br /&gt;
| 8&lt;br /&gt;
| Partition (A) offset&lt;br /&gt;
|-&lt;br /&gt;
| 0x28&lt;br /&gt;
| 8&lt;br /&gt;
| Partition (A) size&lt;br /&gt;
|-&lt;br /&gt;
| 0x30&lt;br /&gt;
| 4&lt;br /&gt;
| Active partition descriptor, 0 = primary, 1 = secondary&lt;br /&gt;
|-&lt;br /&gt;
| 0x34&lt;br /&gt;
| 0x20&lt;br /&gt;
| SHA-256 over the active partition table/descriptor&lt;br /&gt;
|-&lt;br /&gt;
| 0x54&lt;br /&gt;
| 8&lt;br /&gt;
| Unique identifier&lt;br /&gt;
|-&lt;br /&gt;
| 0x5C&lt;br /&gt;
| 0xA4&lt;br /&gt;
| Unused, might contain leftover data&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Note:&lt;br /&gt;
&lt;br /&gt;
* Since DIFF can only contain one partition, a partition table can only have one partition descriptor, so they become the same concept here.&lt;br /&gt;
* See [[Extdata]] for its usage of the unique identifier field. For title database files, this field is zero.&lt;br /&gt;
&lt;br /&gt;
== Partition table &amp;amp;amp; partition descriptor ==&lt;br /&gt;
&lt;br /&gt;
There are two partition tables, but only one of them is active. When operating on a DISA / DIFF file, 3DS FS alternately activate one of the two tables, presumably for data backup or atomic file writing. A newly created DISA / DIFF file may have entirely uninitialized data in the inactive partition table.&lt;br /&gt;
&lt;br /&gt;
One partition table contains one or two partition descriptors , each of which describes the layout of one partition. A partition descriptor contains the following components:&lt;br /&gt;
&lt;br /&gt;
* DIFI header&lt;br /&gt;
* IVFC descriptor&lt;br /&gt;
* DPFS descriptor&lt;br /&gt;
* Partition master hash&lt;br /&gt;
&lt;br /&gt;
=== DIFI header ===&lt;br /&gt;
&lt;br /&gt;
The DIFI header locates at the beginning of a partition descriptor. This header defines the rest components of the partition descriptor (IVFC descriptor, DPFS descriptor and partition master hash). All offsets are relative to the beginning of the partition descriptor, except for &amp;lt;code&amp;gt;External IVFC level 4 offset&amp;lt;/code&amp;gt;, which is relative to the beginning of the partition.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! Offset&lt;br /&gt;
! Length&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x00&lt;br /&gt;
| 4&lt;br /&gt;
| Magic &amp;amp;quot;DIFI&amp;amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| 0x04&lt;br /&gt;
| 4&lt;br /&gt;
| Magic 0x10000&lt;br /&gt;
|-&lt;br /&gt;
| 0x08&lt;br /&gt;
| 8&lt;br /&gt;
| IVFC descriptor offset&lt;br /&gt;
|-&lt;br /&gt;
| 0x10&lt;br /&gt;
| 8&lt;br /&gt;
| IVFC descriptor size&lt;br /&gt;
|-&lt;br /&gt;
| 0x18&lt;br /&gt;
| 8&lt;br /&gt;
| DPFS descriptor offset&lt;br /&gt;
|-&lt;br /&gt;
| 0x20&lt;br /&gt;
| 8&lt;br /&gt;
| DPFS descriptor size&lt;br /&gt;
|-&lt;br /&gt;
| 0x28&lt;br /&gt;
| 8&lt;br /&gt;
| Partition hash offset&lt;br /&gt;
|-&lt;br /&gt;
| 0x30&lt;br /&gt;
| 8&lt;br /&gt;
| Partition hash size&lt;br /&gt;
|-&lt;br /&gt;
| 0x38&lt;br /&gt;
| 1&lt;br /&gt;
| If none zero, enable external IVFC level 4.&lt;br /&gt;
|-&lt;br /&gt;
| 0x39&lt;br /&gt;
| 1&lt;br /&gt;
| DPFS tree level 1 selector&lt;br /&gt;
|-&lt;br /&gt;
| 0x3A&lt;br /&gt;
| 2&lt;br /&gt;
| Padding&lt;br /&gt;
|-&lt;br /&gt;
| 0x3C&lt;br /&gt;
| 8&lt;br /&gt;
| External IVFC level 4 offset (zero if external IVFC level 4 disabled)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Note:&lt;br /&gt;
&lt;br /&gt;
* The meaning of fields after 0x38 are explained in the section [[#Partition]]&lt;br /&gt;
&lt;br /&gt;
=== IVFC descriptor ===&lt;br /&gt;
&lt;br /&gt;
This header defines each level of IVFC tree (explained in the section [[#Partition]]). All offsets are relative to the beginning of DPFS level 3.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! Offset&lt;br /&gt;
! Length&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x00&lt;br /&gt;
| 4&lt;br /&gt;
| Magic &amp;amp;quot;IVFC&amp;amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| 0x04&lt;br /&gt;
| 4&lt;br /&gt;
| Magic 0x20000&lt;br /&gt;
|-&lt;br /&gt;
| 0x08&lt;br /&gt;
| 8&lt;br /&gt;
| Master hash size = partition master hash size in DIFI header&lt;br /&gt;
|-&lt;br /&gt;
| 0x10&lt;br /&gt;
| 8&lt;br /&gt;
| IVFC level 1 offset&lt;br /&gt;
|-&lt;br /&gt;
| 0x18&lt;br /&gt;
| 8&lt;br /&gt;
| IVFC level 1 size&lt;br /&gt;
|-&lt;br /&gt;
| 0x20&lt;br /&gt;
| 4&lt;br /&gt;
| IVFC level 1 block size in log2&lt;br /&gt;
|-&lt;br /&gt;
| 0x24&lt;br /&gt;
| 4&lt;br /&gt;
| Padding&lt;br /&gt;
|-&lt;br /&gt;
| 0x28&lt;br /&gt;
| 8&lt;br /&gt;
| IVFC level 2 offset&lt;br /&gt;
|-&lt;br /&gt;
| 0x30&lt;br /&gt;
| 8&lt;br /&gt;
| IVFC level 2 size&lt;br /&gt;
|-&lt;br /&gt;
| 0x38&lt;br /&gt;
| 4&lt;br /&gt;
| IVFC level 2 block size in log2&lt;br /&gt;
|-&lt;br /&gt;
| 0x3C&lt;br /&gt;
| 4&lt;br /&gt;
| Padding&lt;br /&gt;
|-&lt;br /&gt;
| 0x40&lt;br /&gt;
| 8&lt;br /&gt;
| IVFC level 3 offset&lt;br /&gt;
|-&lt;br /&gt;
| 0x48&lt;br /&gt;
| 8&lt;br /&gt;
| IVFC level 3 size&lt;br /&gt;
|-&lt;br /&gt;
| 0x50&lt;br /&gt;
| 4&lt;br /&gt;
| IVFC level 3 block size in log2&lt;br /&gt;
|-&lt;br /&gt;
| 0x54&lt;br /&gt;
| 4&lt;br /&gt;
| Padding&lt;br /&gt;
|-&lt;br /&gt;
| 0x58&lt;br /&gt;
| 8&lt;br /&gt;
| IVFC level 4 offset (unused if external IVFC level 4 enabled)&lt;br /&gt;
|-&lt;br /&gt;
| 0x60&lt;br /&gt;
| 8&lt;br /&gt;
| IVFC level 4 size&lt;br /&gt;
|-&lt;br /&gt;
| 0x68&lt;br /&gt;
| 4&lt;br /&gt;
| IVFC level 4 block size in log2&lt;br /&gt;
|-&lt;br /&gt;
| 0x6C&lt;br /&gt;
| 4&lt;br /&gt;
| Padding&lt;br /&gt;
|-&lt;br /&gt;
| 0x70&lt;br /&gt;
| 8&lt;br /&gt;
| IVFC descriptor size? The value is usually 0x78&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== DPFS descriptor ===&lt;br /&gt;
&lt;br /&gt;
This header defines each level of DPFS tree (explained in the section [[#Partition]]). All offsets are relative to the beginning of the partition.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! Offset&lt;br /&gt;
! Length&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x00&lt;br /&gt;
| 4&lt;br /&gt;
| Magic &amp;amp;quot;DPFS&amp;amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| 0x04&lt;br /&gt;
| 4&lt;br /&gt;
| Magic 0x10000&lt;br /&gt;
|-&lt;br /&gt;
| 0x08&lt;br /&gt;
| 8&lt;br /&gt;
| DPFS level 1 offset&lt;br /&gt;
|-&lt;br /&gt;
| 0x10&lt;br /&gt;
| 8&lt;br /&gt;
| DPFS level 1 size&lt;br /&gt;
|-&lt;br /&gt;
| 0x18&lt;br /&gt;
| 4&lt;br /&gt;
| DPFS level 1 block size in log2 (unused?)&lt;br /&gt;
|-&lt;br /&gt;
| 0x1C&lt;br /&gt;
| 4&lt;br /&gt;
| Padding&lt;br /&gt;
|-&lt;br /&gt;
| 0x20&lt;br /&gt;
| 8&lt;br /&gt;
| DPFS level 2 offset&lt;br /&gt;
|-&lt;br /&gt;
| 0x28&lt;br /&gt;
| 8&lt;br /&gt;
| DPFS level 2 size&lt;br /&gt;
|-&lt;br /&gt;
| 0x30&lt;br /&gt;
| 4&lt;br /&gt;
| DPFS level 2 block size in log2&lt;br /&gt;
|-&lt;br /&gt;
| 0x34&lt;br /&gt;
| 4&lt;br /&gt;
| Padding&lt;br /&gt;
|-&lt;br /&gt;
| 0x38&lt;br /&gt;
| 8&lt;br /&gt;
| DPFS level 3 offset&lt;br /&gt;
|-&lt;br /&gt;
| 0x40&lt;br /&gt;
| 8&lt;br /&gt;
| DPFS level 3 size&lt;br /&gt;
|-&lt;br /&gt;
| 0x48&lt;br /&gt;
| 4&lt;br /&gt;
| DPFS level 3 block size in log2&lt;br /&gt;
|-&lt;br /&gt;
| 0x4C&lt;br /&gt;
| 4&lt;br /&gt;
| Padding&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Partition master hash ===&lt;br /&gt;
&lt;br /&gt;
This is a SHA-256 hash list over IVFC level 1. See [[#IVFC tree]] for explanation.&lt;br /&gt;
&lt;br /&gt;
== Partition ==&lt;br /&gt;
&lt;br /&gt;
A partition can have two types of layout. This is determined by the field DIFF + 0x38 (&amp;lt;code&amp;gt;Enable external IVFC level 4&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
The layout type 0 (external IVFC level 4 disabled) contains&lt;br /&gt;
&lt;br /&gt;
* DPFS level 1&lt;br /&gt;
* DPFS level 2&lt;br /&gt;
* DPFS level 3, and inside&lt;br /&gt;
** IVFC level 1&lt;br /&gt;
** IVFC level 2&lt;br /&gt;
** IVFC level 3&lt;br /&gt;
** IVFC level 4 (the actual content data)&lt;br /&gt;
&lt;br /&gt;
The layout type 1 (external IVFC level 4 enabled) contains&lt;br /&gt;
&lt;br /&gt;
* DPFS level 1&lt;br /&gt;
* DPFS level 2&lt;br /&gt;
* DPFS level 3, and inside&lt;br /&gt;
** IVFC level 1&lt;br /&gt;
** IVFC level 2&lt;br /&gt;
** IVFC level 3&lt;br /&gt;
* IVFC level 4 (the actual content data, note that this is out side DPFS level 3)&lt;br /&gt;
&lt;br /&gt;
=== DPFS tree ===&lt;br /&gt;
&lt;br /&gt;
Everything inside the DPFS tree comes in pairs, and at one time only one of a pair is active. The tree is probably designed for atomic writing: for a file writing operation, it writes to the inactive part, then commits the data by switching a bit to activate it.&lt;br /&gt;
&lt;br /&gt;
Each level of DPFS tree consists of a pair of chunks. The size of one chunk is defined as it in the DPFS descriptor, so the total size of a level is actually twice as large as the size recorded in the descriptor. For level 1 and 2, each chunk is a bit array, in which each bit corresponds to a block in the next level (the block size of the next level is also defined in the DPFS descriptor). This bit indicates which one of the pair in the next level is active for this block: 0 means the first one and 1 means the second one. The active chunk of level 1 is selected by &amp;lt;code&amp;gt;DPFS tree level 1 selector&amp;lt;/code&amp;gt; in the DIFI header. The bit array is encoded in u32 array, with MSB as the first bit of each 32 bits.&lt;br /&gt;
&lt;br /&gt;
To access data in level 3, one needs to check the bits in level 1 and level 2 to know which chunk of level 3 is active for the accessed location. For example, for a following configuration:&lt;br /&gt;
&lt;br /&gt;
* Level 1: size = 4 bytes = 32 bits&lt;br /&gt;
* Level 2: size = 0x380 bytes = 0x1C00 bits, block size = 0x80 bytes&lt;br /&gt;
* Level 3: size = 0x1B7F000, block size = 0x1000, block size = 0x1000 bytes&lt;br /&gt;
&lt;br /&gt;
if one want to read byte at 0x1234567 of level 3, the following calculation is performed:&lt;br /&gt;
&lt;br /&gt;
* get level 2 bit index &amp;lt;code&amp;gt;0x1234567 / 0x1000 = 0x1234&amp;lt;/code&amp;gt;, and its byte location &amp;lt;code&amp;gt;0x1234 / 8 = 0x246&amp;lt;/code&amp;gt;&lt;br /&gt;
* get level 1 bit index &amp;lt;code&amp;gt;0x246 / 0x80 = 4&amp;lt;/code&amp;gt;&lt;br /&gt;
* get &amp;lt;code&amp;gt;level1_selector&amp;lt;/code&amp;gt; from DIFI header&lt;br /&gt;
* read &amp;lt;code&amp;gt;level2_selector = Level1[level1_selector].bits[4]&amp;lt;/code&amp;gt;;&lt;br /&gt;
* read &amp;lt;code&amp;gt;level3_selector = Level2[level2_selector].bits[0x1234]&amp;lt;/code&amp;gt;;&lt;br /&gt;
* read &amp;lt;code&amp;gt;data = Level3[level3_selector].bytes[0x1234567]&amp;lt;/code&amp;gt; as the final data&lt;br /&gt;
* in the code above &amp;lt;code&amp;gt;Levelx[k]&amp;lt;/code&amp;gt; means the &amp;lt;code&amp;gt;k&amp;lt;/code&amp;gt;-th chunk in level &amp;lt;code&amp;gt;x&amp;lt;/code&amp;gt;, where &amp;lt;code&amp;gt;k = 0, 1&amp;lt;/code&amp;gt;. &amp;lt;code&amp;gt;.bits[n]&amp;lt;/code&amp;gt; is expanded to &amp;lt;code&amp;gt;(.u32_array[n / 32] &amp;amp;gt;&amp;amp;gt; (31 - n % 32)) &amp;amp;amp; 1&amp;lt;/code&amp;gt; as the bit array is encoded in u32 array.&lt;br /&gt;
&lt;br /&gt;
Effectively, the active data is scattered among the two level 3 chunk. One can assemble the whole active level 3 image following the same rule.&lt;br /&gt;
&lt;br /&gt;
=== IVFC tree ===&lt;br /&gt;
&lt;br /&gt;
The IVFC tree is used for data verification. It is very similar to the IVFC tree in [[RomFS]], except that it has an additional level here. For level 1, 2 and 3, each level is a list of SHA-256 hash, of which each corresponds to a block of the next level which is zero-padded to align the block size (the block size of the next level is defined in the IVFC descriptor).&lt;br /&gt;
&lt;br /&gt;
The partition master hash in the partition descriptor can be seen as IVFC level 0, which hashes level 1 following the same rule. The master hash is usually 0x20 long, consisting only one hash. This is because most DISA / DIFF files are not large enough to have multiple hashes on the top level, which isn&#039;t the case for some title database files.&lt;br /&gt;
&lt;br /&gt;
However, not all data is hashed - only ranges that have been written with valid data are properly hashed.&lt;br /&gt;
&lt;br /&gt;
Level 4 is the actual content of the partition, which is what the container format essentially contains.&lt;br /&gt;
&lt;br /&gt;
== Extracting content from a DISA / DIFF container ==&lt;br /&gt;
&lt;br /&gt;
* Find the active partition table and the partition(s).&lt;br /&gt;
* Unwrap DPFS tree of partition(s) by reconstructing active data.&lt;br /&gt;
* Unwrap IVFC tree. Either take out level 4 directly, or, better, verify all the hashes and poison the data that is not properly hashed.&lt;br /&gt;
* The IVFC level 4 is the inner content of the file. The format of it varies among different usage. Refer their own page for further extraction.&lt;br /&gt;
&lt;br /&gt;
== Chain of trust ==&lt;br /&gt;
&lt;br /&gt;
* AES CMAC verifies the header.&lt;br /&gt;
* The header verifies the active partition table via the table hash.&lt;br /&gt;
* In the partition table, each descriptor verifies level 1 of its IVFC tree via the master hash.&lt;br /&gt;
* Each IVFC level verifies the next level, until the level 4, which is the inner content.&lt;br /&gt;
&lt;br /&gt;
== Summary diagram ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
external link: https://i.imgur.com/BjwShJZ.png&lt;br /&gt;
* Please move this into 3dbrew when file uploading is fixed.&lt;/div&gt;</summary>
		<author><name>Wwylele</name></author>
	</entry>
	<entry>
		<id>https://www.3dbrew.org/w/index.php?title=Savegames&amp;diff=21114</id>
		<title>Savegames</title>
		<link rel="alternate" type="text/html" href="https://www.3dbrew.org/w/index.php?title=Savegames&amp;diff=21114"/>
		<updated>2019-12-02T14:13:50Z</updated>

		<summary type="html">&lt;p&gt;Wwylele: /* Tools */ Bump my tools to the top. Sorry for self-promotion, but it is better than the old one in anyway now.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This page describes the format and encryption of savegames contained in gamecards, SD and NAND. You can find savegames from various 3DS games on the [[Games]] page.&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
Savegames are stored in [[DISA and DIFF|DISA container format]]. Inside the DISA container, it forms a [[Inner FAT|FAT filesystem]]. &#039;&#039;&#039;Please refer to these pages for how to fully extract save files&#039;&#039;&#039;. This page only describes additional encryption wear leveling on top of the DISA container. These layers only apply to gamecard save games. SD savegames and NAND savegames are DISA containers in plaintext after decrypting the common SD/NAND encryption layer.&lt;br /&gt;
&lt;br /&gt;
== Gamecard savegame Encryption ==&lt;br /&gt;
&lt;br /&gt;
=== Repeating CTR Fail ===&lt;br /&gt;
On the 3DS savegames are stored much like on the DS, that is on a FLASH chip in the gamecart. On the DS these savegames were stored in plain-text but on the 3DS a layer of encryption was added. This is AES-CTR, as the contents of several savegames exhibit the odd behavior that xor-ing certain parts of the savegame together will result in the plain-text appearing.&lt;br /&gt;
&lt;br /&gt;
The reason this works is because the stream cipher used has a period of 512 bytes. That is to say, it will repeat the same keystream after 512 bytes. The way you encrypt with a stream cipher is you XOR your data with the keystream as it is produced. Unfortunately, if your streamcipher repeats and you are encrypting a known plain-text (in our case, zeros) you are basically giving away your valuable keystream.&lt;br /&gt;
&lt;br /&gt;
So how do you use this to decrypt a savegame on a 3DS? First off, you chunk up the savegame into 512 byte chunks. Then, you bin these chunks by their contents, discarding any that contain only FF. Now look for the most common chunk. This is your keystream. Now XOR the keystream with your original savegame and you should have a fully decrypted savegame. XOR with the keystream again to produce an encrypted savegame.&lt;br /&gt;
&lt;br /&gt;
=== Savegame keyY ===&lt;br /&gt;
&lt;br /&gt;
All gamecard and SD savegames are encrypted with AES-CTR. The base CTR for gamecard savegames is all-zero. The gamecard savegame [[AES|keyslots]]&#039; keyY(these savegame keyslots use the hardware key-generator) is unique for each region and for each game. The [[NCSD]] partition flags determine the method used to generate this keyY. When the save [[NCSD]] flags checked by the running NATIVE_FIRM are all-zero, the system will use the repeating CTR, otherwise a proper CTR which never repeats within the image is used.&lt;br /&gt;
&lt;br /&gt;
The [[AES]]-CMAC (which uses a hardware key-generator keyslot, as mentioned above) at the the beginning of the savegame must match the calculated CMAC using the DISA/DIFF data, otherwise the savegame is considered corrupted(see below).&lt;br /&gt;
&lt;br /&gt;
When all of the flags checked by the running NATIVE_FIRM are clear, the keyY(original keyY method used with saves where the CTR repeats within the image) is the following:&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;
| First 8-bytes from the plaintext [[NCCH#CXI|CXI]] accessdesc signature.&lt;br /&gt;
|-&lt;br /&gt;
| 0x8&lt;br /&gt;
| 0x4&lt;br /&gt;
| u32 CardID0 from [[Gamecards|gamecard]] plaintext-mode command 0x90, Process9 reads this with the [[NTRCARD]] hw. The actual cmdID used by Process9 is different since Process9 reads it with the gamecard in encrypted-mode.&lt;br /&gt;
|-&lt;br /&gt;
| 0xC&lt;br /&gt;
| 0x4&lt;br /&gt;
| u32 CardID1 from [[Gamecards|gamecard]] plaintext-mode command 0xA0, Process9 reads this with the [[NTRCARD]] hw. The actual cmdID used by Process9 is different since Process9 reads it with the gamecard in encrypted-mode.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== [[2.0.0-2]] Hashed keyY and [[2.2.0-4]] Savegame Encryption ====&lt;br /&gt;
&lt;br /&gt;
When certain [[NCSD]] partition flags are set, a SHA-256 hash is calculated over the data from the CXI(same data used with the original plain keyY), and the 0x40-bytes read from a gamecard command(this 0x40-byte data is also read by [[Process_Services_PXI|GetRomId]], which is the gamecard-uniqueID). The first 0x10-bytes from this hash is used for the keyY. When flag[7] is set, the CTR will never repeat within the save image, unlike the original CTR-method. All games which had the retail NCSD image finalized after the [[2.2.0-4]] update(and contain [[2.2.0-4]]+ in the [[System Update CFA|System update partition]]), use this encryption method.&lt;br /&gt;
&lt;br /&gt;
This keyY generation method was implemented with [[2.0.0-2]] via NCSD partition flag[3], however the proper CTR wasn&#039;t implemented for flag[7] until [[2.2.0-4]]. The hashed keyY flag[3] implemented with [[2.0.0-2]] was likely never used with retail gamecards.&lt;br /&gt;
&lt;br /&gt;
==== [[6.0.0-11]] Savegame keyY ====&lt;br /&gt;
&lt;br /&gt;
[[6.0.0-11]] implemented support for generating the savegame keyY with a new method, this method is much more complex than previous keyY methods. This is enabled via new [[NCSD]] partition flags, all retail games which have the NCSD image finalized after the [[6.0.0-11]] release(and [[6.0.0-11]]+ in the system update partition) will have these flags set for using this new method.&lt;br /&gt;
&lt;br /&gt;
A SHA-256 hash is calculated over the same data used with the above hashed keyY method, after hashing the above data the following data is hashed: the CXI programID, and the ExeFS:/.code hash from the decrypted [[ExeFS]] header. An [[AES]]-CMAC (the keyslot used for this uses the hardware key-scrambler) is then calculated over this hash, the output CMAC is used for the savegame keyY.&lt;br /&gt;
&lt;br /&gt;
The keyY used for calculating this AES-CMAC is initialized while NATIVE_FIRM is loading, this keyY is generated via the [[RSA]] engine. The RSA slot used here is slot0(key-data for slot0 is initialized by bootrom), this RSA slot0 key-data is overwritten during system boot. This RSA slot0 key-data gets overwritten with the RSA key-data used for verifying RSA signatures, every time Process9 verifies any RSA signatures except for [[NCCH|NCCH]] accessdesc signatures. Starting with [[7.0.0-13]] this key-init function used at boot is also used to initialize a separate keyslot used for the new [[NCCH]] encryption method.&lt;br /&gt;
&lt;br /&gt;
This [[FIRM|Process9]] key-init function first checks if a certain 0x10-byte block in the 0x01FF8000 region is all-zero. When all-zero it immediately returns, otherwise it clears that block then continues to do the key generation. This is likely for supporting launching a v6.0+ NATIVE_FIRM under this FIRM.&lt;br /&gt;
&lt;br /&gt;
== Gamecard wear leveling ==&lt;br /&gt;
&lt;br /&gt;
The 3DS employs a wear leveling scheme on the savegame FLASH chips(only used for CARD1 gamecards). This is done through the usage of blockmaps and a journal. The blockmap is located at offset 0 of the flash chip, and is immediately followed by the journal. The initial state is dictated by the blockmap, and the journal is then applied to that.&lt;br /&gt;
&lt;br /&gt;
There are two versions of wear leveling have been observed. V1 is used for 128KB and 512 KB CARD1 flash chips. V2 is used for 1MB CARD1 flash chips (uncommon. Pokemon Sun/Moon is an exampe).&lt;br /&gt;
&lt;br /&gt;
First, there are two 32-bit integers whose purposes are currently unknown. They generally increase the value as the savegame is written more times, so probably counter for how many times the journal became full and got flushed into the block map, and/or how many times &amp;lt;code&amp;gt;alloc_cnt&amp;lt;/code&amp;gt; has wrapped around. &lt;br /&gt;
&lt;br /&gt;
Then comes the actual blockmap. The block map contains entries of 10 bytes (V1) or 2 bytes (V2) with total number of &amp;lt;code&amp;gt;(flash_size / 0x1000 - 1)&amp;lt;/code&amp;gt;. &lt;br /&gt;
The blockmap entry is simple:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
struct blockmap_entry_v1 {&lt;br /&gt;
        uint8_t phys_sec; // when bit7 is set, block is initialized and has checksums, otherwise checksums are all zero&lt;br /&gt;
        uint8_t alloc_cnt;&lt;br /&gt;
        uint8_t chksums[8];&lt;br /&gt;
} __attribute__((__packed__));&lt;br /&gt;
&lt;br /&gt;
struct blockmap_entry_v2 {&lt;br /&gt;
        // Note that the phys_sec and alloc_cnt field are swapped in v2, &lt;br /&gt;
        // but the initialized bit is still on the first byte&lt;br /&gt;
        uint8_t alloc_cnt; // when bit7 is set, block is initialized&lt;br /&gt;
        uint8_t phys_sec; &lt;br /&gt;
        // v2 has no chksums&lt;br /&gt;
} __attribute__((__packed__));&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There&#039;s one entry per 0x1000-byte sector, counting from physical sector 1 (sector 0 contains the blockmap/journal).&lt;br /&gt;
&lt;br /&gt;
A 2-byte CRC16 follows the block map. For V1 it immediately follows the last block map entry. For V2 it is located at 0x3FE, and bytes before the CRC is padded with zero. The CRC16 checks all the bytes before it, including the two unknown integers, the block map, and the padding bytes for V2. The CRC standard used looks like CRC-16-IBM (modbus). Here is the code in Rust for it&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
fn crc16(data: &amp;amp;[u8]) -&amp;gt; u16 {&lt;br /&gt;
    let poly = 0xA001;&lt;br /&gt;
    let mut crc = 0xFFFFu16;&lt;br /&gt;
    for byte in data {&lt;br /&gt;
        crc ^= &amp;lt;u16&amp;gt;::from(*byte);&lt;br /&gt;
        for _ in 0..8 {&lt;br /&gt;
            let b = crc &amp;amp; 1 != 0;&lt;br /&gt;
            crc &amp;gt;&amp;gt;= 1;&lt;br /&gt;
            if b {&lt;br /&gt;
                crc ^= poly;&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    crc&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then comes the journal. The journal contains entries that describes how sectors should be remapped. The rest bytes before 0x1000 after all journal entries are padded with 0xFF&lt;br /&gt;
The journal entry structure is as follows:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
struct journal_entry_half {&lt;br /&gt;
        uint8_t virt_sec;       // Mapped to sector&lt;br /&gt;
        uint8_t prev_virt_sec;  // Physical sector previously mapped to&lt;br /&gt;
        uint8_t phys_sec;       // Mapped from sector&lt;br /&gt;
        uint8_t prev_phys_sec;  // Virtual sector previously mapped to&lt;br /&gt;
        uint8_t phys_realloc_cnt;       // Amount of times physical sector has been remapped&lt;br /&gt;
        uint8_t virt_realloc_cnt;       // Amount of times virtual sector has been remapped&lt;br /&gt;
        uint8_t chksums[8];     // Unused &amp;amp; uninitialized for V2&lt;br /&gt;
} __attribute__((__packed__));&lt;br /&gt;
&lt;br /&gt;
struct journal_entry{&lt;br /&gt;
        struct journal_entry_half entry;&lt;br /&gt;
        struct journal_entry_half dupe; // same data as `entry`. No idea what this is used fore&lt;br /&gt;
        uint32_t uninitialized;         // 0xFFFFFFFF in newer system&lt;br /&gt;
}__attribute__((__packed__));&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The checksums in the blockmap/journal entries work as follows:&lt;br /&gt;
* each byte is the checksum of an encrypted 0x200 bytes large block&lt;br /&gt;
* to calculate the checksum, a CRC16 of the block (same CRC16 algorithm as above) is calculated, and the two bytes of the CRC16 are XORed together to produce the 8bit checksum&lt;br /&gt;
&lt;br /&gt;
== Initialization ==&lt;br /&gt;
&lt;br /&gt;
When a save FLASH contains all xFFFF blocks it&#039;s assumed uninitialized by the game cartridges and it initializes default data in place, without prompting the user. The 0xFFFFFFFF blocks are uninitialized data. When creating a non-gamecard savegame and other images/files, it&#039;s initially all 0xFFFFFFFF until it&#039;s formatted where some of the blocks are overwritten with encrypted data.&lt;br /&gt;
&lt;br /&gt;
I got a new game SplinterCell3D-Pal and I downloaded the save and it was 128KB of 0xFF, except the first 0x10 bytes which were the letter &#039;Z&#039; (uppercase) --[[User:Elisherer|Elisherer]] 22:41, 15 October 2011 (CEST)&lt;br /&gt;
&lt;br /&gt;
== Fun Facts ==&lt;br /&gt;
&lt;br /&gt;
If you have facts that you found out by looking at the binary files please share them here:&lt;br /&gt;
&lt;br /&gt;
* From one save to another the game backups the last files that were in the partition and the entire image header in &amp;quot;random&amp;quot; locations.. --[[User:Elisherer|Elisherer]] 22:41, 15 October 2011 (CEST)&lt;br /&gt;
&lt;br /&gt;
== Tools ==&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/wwylele/save3ds save3ds] supports reading and modifying savegames, extdata and title database in FUSE filesystem or batch extracting/importing.&lt;br /&gt;
* [https://github.com/3dshax/3ds/tree/master/3dsfuse 3dsfuse] supports reading and modifying savegames. In the mounted FUSE filesystem, the /output.sav is the raw FLASH save-image. When the save was modified, a separate tool to update the CMAC must be used with /clean.sav, prior to writing output.sav to a gamecard. (This is an old tool that doesn&#039;t handle the savegame format correctly. --[[User:Wwylele|Wwylele]] ([[User talk:Wwylele|talk]]) 16:13, 2 December 2019 (CET))&lt;br /&gt;
* [[3DSExplorer]] supports reading of savegames, it doesn&#039;t support reading the new encrypted savegames and maybe in the future it will support modifying (some of the modyfing code is already implemented).&lt;br /&gt;
* [https://github.com/wwylele/3ds-save-tool wwylele&#039;s 3ds-save-tool] supports extracting files from savegames and extdata. It properly reconstructs data from the DPFS tree and extracts files in directories hierarchy.&lt;br /&gt;
&lt;br /&gt;
[[セーブデータ|Japanese]]&lt;/div&gt;</summary>
		<author><name>Wwylele</name></author>
	</entry>
	<entry>
		<id>https://www.3dbrew.org/w/index.php?title=Savegames&amp;diff=21113</id>
		<title>Savegames</title>
		<link rel="alternate" type="text/html" href="https://www.3dbrew.org/w/index.php?title=Savegames&amp;diff=21113"/>
		<updated>2019-12-02T14:06:26Z</updated>

		<summary type="html">&lt;p&gt;Wwylele: /* Gamecard wear leveling */ Update info for wear leveling V2&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This page describes the format and encryption of savegames contained in gamecards, SD and NAND. You can find savegames from various 3DS games on the [[Games]] page.&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
Savegames are stored in [[DISA and DIFF|DISA container format]]. Inside the DISA container, it forms a [[Inner FAT|FAT filesystem]]. &#039;&#039;&#039;Please refer to these pages for how to fully extract save files&#039;&#039;&#039;. This page only describes additional encryption wear leveling on top of the DISA container. These layers only apply to gamecard save games. SD savegames and NAND savegames are DISA containers in plaintext after decrypting the common SD/NAND encryption layer.&lt;br /&gt;
&lt;br /&gt;
== Gamecard savegame Encryption ==&lt;br /&gt;
&lt;br /&gt;
=== Repeating CTR Fail ===&lt;br /&gt;
On the 3DS savegames are stored much like on the DS, that is on a FLASH chip in the gamecart. On the DS these savegames were stored in plain-text but on the 3DS a layer of encryption was added. This is AES-CTR, as the contents of several savegames exhibit the odd behavior that xor-ing certain parts of the savegame together will result in the plain-text appearing.&lt;br /&gt;
&lt;br /&gt;
The reason this works is because the stream cipher used has a period of 512 bytes. That is to say, it will repeat the same keystream after 512 bytes. The way you encrypt with a stream cipher is you XOR your data with the keystream as it is produced. Unfortunately, if your streamcipher repeats and you are encrypting a known plain-text (in our case, zeros) you are basically giving away your valuable keystream.&lt;br /&gt;
&lt;br /&gt;
So how do you use this to decrypt a savegame on a 3DS? First off, you chunk up the savegame into 512 byte chunks. Then, you bin these chunks by their contents, discarding any that contain only FF. Now look for the most common chunk. This is your keystream. Now XOR the keystream with your original savegame and you should have a fully decrypted savegame. XOR with the keystream again to produce an encrypted savegame.&lt;br /&gt;
&lt;br /&gt;
=== Savegame keyY ===&lt;br /&gt;
&lt;br /&gt;
All gamecard and SD savegames are encrypted with AES-CTR. The base CTR for gamecard savegames is all-zero. The gamecard savegame [[AES|keyslots]]&#039; keyY(these savegame keyslots use the hardware key-generator) is unique for each region and for each game. The [[NCSD]] partition flags determine the method used to generate this keyY. When the save [[NCSD]] flags checked by the running NATIVE_FIRM are all-zero, the system will use the repeating CTR, otherwise a proper CTR which never repeats within the image is used.&lt;br /&gt;
&lt;br /&gt;
The [[AES]]-CMAC (which uses a hardware key-generator keyslot, as mentioned above) at the the beginning of the savegame must match the calculated CMAC using the DISA/DIFF data, otherwise the savegame is considered corrupted(see below).&lt;br /&gt;
&lt;br /&gt;
When all of the flags checked by the running NATIVE_FIRM are clear, the keyY(original keyY method used with saves where the CTR repeats within the image) is the following:&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;
| First 8-bytes from the plaintext [[NCCH#CXI|CXI]] accessdesc signature.&lt;br /&gt;
|-&lt;br /&gt;
| 0x8&lt;br /&gt;
| 0x4&lt;br /&gt;
| u32 CardID0 from [[Gamecards|gamecard]] plaintext-mode command 0x90, Process9 reads this with the [[NTRCARD]] hw. The actual cmdID used by Process9 is different since Process9 reads it with the gamecard in encrypted-mode.&lt;br /&gt;
|-&lt;br /&gt;
| 0xC&lt;br /&gt;
| 0x4&lt;br /&gt;
| u32 CardID1 from [[Gamecards|gamecard]] plaintext-mode command 0xA0, Process9 reads this with the [[NTRCARD]] hw. The actual cmdID used by Process9 is different since Process9 reads it with the gamecard in encrypted-mode.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== [[2.0.0-2]] Hashed keyY and [[2.2.0-4]] Savegame Encryption ====&lt;br /&gt;
&lt;br /&gt;
When certain [[NCSD]] partition flags are set, a SHA-256 hash is calculated over the data from the CXI(same data used with the original plain keyY), and the 0x40-bytes read from a gamecard command(this 0x40-byte data is also read by [[Process_Services_PXI|GetRomId]], which is the gamecard-uniqueID). The first 0x10-bytes from this hash is used for the keyY. When flag[7] is set, the CTR will never repeat within the save image, unlike the original CTR-method. All games which had the retail NCSD image finalized after the [[2.2.0-4]] update(and contain [[2.2.0-4]]+ in the [[System Update CFA|System update partition]]), use this encryption method.&lt;br /&gt;
&lt;br /&gt;
This keyY generation method was implemented with [[2.0.0-2]] via NCSD partition flag[3], however the proper CTR wasn&#039;t implemented for flag[7] until [[2.2.0-4]]. The hashed keyY flag[3] implemented with [[2.0.0-2]] was likely never used with retail gamecards.&lt;br /&gt;
&lt;br /&gt;
==== [[6.0.0-11]] Savegame keyY ====&lt;br /&gt;
&lt;br /&gt;
[[6.0.0-11]] implemented support for generating the savegame keyY with a new method, this method is much more complex than previous keyY methods. This is enabled via new [[NCSD]] partition flags, all retail games which have the NCSD image finalized after the [[6.0.0-11]] release(and [[6.0.0-11]]+ in the system update partition) will have these flags set for using this new method.&lt;br /&gt;
&lt;br /&gt;
A SHA-256 hash is calculated over the same data used with the above hashed keyY method, after hashing the above data the following data is hashed: the CXI programID, and the ExeFS:/.code hash from the decrypted [[ExeFS]] header. An [[AES]]-CMAC (the keyslot used for this uses the hardware key-scrambler) is then calculated over this hash, the output CMAC is used for the savegame keyY.&lt;br /&gt;
&lt;br /&gt;
The keyY used for calculating this AES-CMAC is initialized while NATIVE_FIRM is loading, this keyY is generated via the [[RSA]] engine. The RSA slot used here is slot0(key-data for slot0 is initialized by bootrom), this RSA slot0 key-data is overwritten during system boot. This RSA slot0 key-data gets overwritten with the RSA key-data used for verifying RSA signatures, every time Process9 verifies any RSA signatures except for [[NCCH|NCCH]] accessdesc signatures. Starting with [[7.0.0-13]] this key-init function used at boot is also used to initialize a separate keyslot used for the new [[NCCH]] encryption method.&lt;br /&gt;
&lt;br /&gt;
This [[FIRM|Process9]] key-init function first checks if a certain 0x10-byte block in the 0x01FF8000 region is all-zero. When all-zero it immediately returns, otherwise it clears that block then continues to do the key generation. This is likely for supporting launching a v6.0+ NATIVE_FIRM under this FIRM.&lt;br /&gt;
&lt;br /&gt;
== Gamecard wear leveling ==&lt;br /&gt;
&lt;br /&gt;
The 3DS employs a wear leveling scheme on the savegame FLASH chips(only used for CARD1 gamecards). This is done through the usage of blockmaps and a journal. The blockmap is located at offset 0 of the flash chip, and is immediately followed by the journal. The initial state is dictated by the blockmap, and the journal is then applied to that.&lt;br /&gt;
&lt;br /&gt;
There are two versions of wear leveling have been observed. V1 is used for 128KB and 512 KB CARD1 flash chips. V2 is used for 1MB CARD1 flash chips (uncommon. Pokemon Sun/Moon is an exampe).&lt;br /&gt;
&lt;br /&gt;
First, there are two 32-bit integers whose purposes are currently unknown. They generally increase the value as the savegame is written more times, so probably counter for how many times the journal became full and got flushed into the block map, and/or how many times &amp;lt;code&amp;gt;alloc_cnt&amp;lt;/code&amp;gt; has wrapped around. &lt;br /&gt;
&lt;br /&gt;
Then comes the actual blockmap. The block map contains entries of 10 bytes (V1) or 2 bytes (V2) with total number of &amp;lt;code&amp;gt;(flash_size / 0x1000 - 1)&amp;lt;/code&amp;gt;. &lt;br /&gt;
The blockmap entry is simple:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
struct blockmap_entry_v1 {&lt;br /&gt;
        uint8_t phys_sec; // when bit7 is set, block is initialized and has checksums, otherwise checksums are all zero&lt;br /&gt;
        uint8_t alloc_cnt;&lt;br /&gt;
        uint8_t chksums[8];&lt;br /&gt;
} __attribute__((__packed__));&lt;br /&gt;
&lt;br /&gt;
struct blockmap_entry_v2 {&lt;br /&gt;
        // Note that the phys_sec and alloc_cnt field are swapped in v2, &lt;br /&gt;
        // but the initialized bit is still on the first byte&lt;br /&gt;
        uint8_t alloc_cnt; // when bit7 is set, block is initialized&lt;br /&gt;
        uint8_t phys_sec; &lt;br /&gt;
        // v2 has no chksums&lt;br /&gt;
} __attribute__((__packed__));&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There&#039;s one entry per 0x1000-byte sector, counting from physical sector 1 (sector 0 contains the blockmap/journal).&lt;br /&gt;
&lt;br /&gt;
A 2-byte CRC16 follows the block map. For V1 it immediately follows the last block map entry. For V2 it is located at 0x3FE, and bytes before the CRC is padded with zero. The CRC16 checks all the bytes before it, including the two unknown integers, the block map, and the padding bytes for V2. The CRC standard used looks like CRC-16-IBM (modbus). Here is the code in Rust for it&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
fn crc16(data: &amp;amp;[u8]) -&amp;gt; u16 {&lt;br /&gt;
    let poly = 0xA001;&lt;br /&gt;
    let mut crc = 0xFFFFu16;&lt;br /&gt;
    for byte in data {&lt;br /&gt;
        crc ^= &amp;lt;u16&amp;gt;::from(*byte);&lt;br /&gt;
        for _ in 0..8 {&lt;br /&gt;
            let b = crc &amp;amp; 1 != 0;&lt;br /&gt;
            crc &amp;gt;&amp;gt;= 1;&lt;br /&gt;
            if b {&lt;br /&gt;
                crc ^= poly;&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    crc&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then comes the journal. The journal contains entries that describes how sectors should be remapped. The rest bytes before 0x1000 after all journal entries are padded with 0xFF&lt;br /&gt;
The journal entry structure is as follows:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
struct journal_entry_half {&lt;br /&gt;
        uint8_t virt_sec;       // Mapped to sector&lt;br /&gt;
        uint8_t prev_virt_sec;  // Physical sector previously mapped to&lt;br /&gt;
        uint8_t phys_sec;       // Mapped from sector&lt;br /&gt;
        uint8_t prev_phys_sec;  // Virtual sector previously mapped to&lt;br /&gt;
        uint8_t phys_realloc_cnt;       // Amount of times physical sector has been remapped&lt;br /&gt;
        uint8_t virt_realloc_cnt;       // Amount of times virtual sector has been remapped&lt;br /&gt;
        uint8_t chksums[8];     // Unused &amp;amp; uninitialized for V2&lt;br /&gt;
} __attribute__((__packed__));&lt;br /&gt;
&lt;br /&gt;
struct journal_entry{&lt;br /&gt;
        struct journal_entry_half entry;&lt;br /&gt;
        struct journal_entry_half dupe; // same data as `entry`. No idea what this is used fore&lt;br /&gt;
        uint32_t uninitialized;         // 0xFFFFFFFF in newer system&lt;br /&gt;
}__attribute__((__packed__));&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The checksums in the blockmap/journal entries work as follows:&lt;br /&gt;
* each byte is the checksum of an encrypted 0x200 bytes large block&lt;br /&gt;
* to calculate the checksum, a CRC16 of the block (same CRC16 algorithm as above) is calculated, and the two bytes of the CRC16 are XORed together to produce the 8bit checksum&lt;br /&gt;
&lt;br /&gt;
== Initialization ==&lt;br /&gt;
&lt;br /&gt;
When a save FLASH contains all xFFFF blocks it&#039;s assumed uninitialized by the game cartridges and it initializes default data in place, without prompting the user. The 0xFFFFFFFF blocks are uninitialized data. When creating a non-gamecard savegame and other images/files, it&#039;s initially all 0xFFFFFFFF until it&#039;s formatted where some of the blocks are overwritten with encrypted data.&lt;br /&gt;
&lt;br /&gt;
I got a new game SplinterCell3D-Pal and I downloaded the save and it was 128KB of 0xFF, except the first 0x10 bytes which were the letter &#039;Z&#039; (uppercase) --[[User:Elisherer|Elisherer]] 22:41, 15 October 2011 (CEST)&lt;br /&gt;
&lt;br /&gt;
== Fun Facts ==&lt;br /&gt;
&lt;br /&gt;
If you have facts that you found out by looking at the binary files please share them here:&lt;br /&gt;
&lt;br /&gt;
* From one save to another the game backups the last files that were in the partition and the entire image header in &amp;quot;random&amp;quot; locations.. --[[User:Elisherer|Elisherer]] 22:41, 15 October 2011 (CEST)&lt;br /&gt;
&lt;br /&gt;
== Tools ==&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/3dshax/3ds/tree/master/3dsfuse 3dsfuse] supports reading and modifying savegames. In the mounted FUSE filesystem, the /output.sav is the raw FLASH save-image. When the save was modified, a separate tool to update the CMAC must be used with /clean.sav, prior to writing output.sav to a gamecard.&lt;br /&gt;
* [[3DSExplorer]] supports reading of savegames, it doesn&#039;t support reading the new encrypted savegames and maybe in the future it will support modifying (some of the modyfing code is already implemented).&lt;br /&gt;
* [https://github.com/wwylele/3ds-save-tool wwylele&#039;s 3ds-save-tool] supports extracting files from savegames and extdata. It properly reconstructs data from the DPFS tree and extracts files in directories hierarchy.&lt;br /&gt;
* [https://github.com/wwylele/save3ds save3ds] similar to 3dsfuse, but supports savegame inner FS, proper DPFS handling, and automatic CMAC update. Mainly supports SD/NAND save/extdata. Cart save WIP&lt;br /&gt;
&lt;br /&gt;
[[セーブデータ|Japanese]]&lt;/div&gt;</summary>
		<author><name>Wwylele</name></author>
	</entry>
	<entry>
		<id>https://www.3dbrew.org/w/index.php?title=DISA_and_DIFF&amp;diff=21081</id>
		<title>DISA and DIFF</title>
		<link rel="alternate" type="text/html" href="https://www.3dbrew.org/w/index.php?title=DISA_and_DIFF&amp;diff=21081"/>
		<updated>2019-10-25T19:18:27Z</updated>

		<summary type="html">&lt;p&gt;Wwylele: Correct CMAC for cart save&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This page describes DISA and DIFF format as the underlying container of [[Savegames]], [[Extdata]] and [[Title Database]]. For further format specification of the inner data, please refer to their own page.&lt;br /&gt;
&lt;br /&gt;
All data in this page is little-endian. All &amp;quot;unused / padding&amp;quot; fields can contain uninitialized data unless otherwise specified.&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
&lt;br /&gt;
DISA and DIFF are two container formats. They are very similar and are used for various purposes in 3DS. Here is a summary table of their usage, the CMAC type and the AES key slot used (the meaning of these is explained in the next section):&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! Usage&lt;br /&gt;
! Media&lt;br /&gt;
! Container format&lt;br /&gt;
! [[#AES CMAC|CMAC type]]&lt;br /&gt;
! CMAC [[AES Registers|Keyslot]]&lt;br /&gt;
|-&lt;br /&gt;
| [[Savegames]]&lt;br /&gt;
| Gamecard&lt;br /&gt;
| DISA&lt;br /&gt;
| [[#CTR-NOR0|CTR-NOR0]]&lt;br /&gt;
| 0x19 / 0x33&lt;br /&gt;
|-&lt;br /&gt;
| [[Savegames]]&lt;br /&gt;
| [[SD Filesystem|SD]]&lt;br /&gt;
| DISA&lt;br /&gt;
| [[#CTR-SIGN|CTR-SIGN]]&lt;br /&gt;
| 0x30&lt;br /&gt;
|-&lt;br /&gt;
| [[System SaveData]]&lt;br /&gt;
| [[Flash Filesystem|NAND]]&lt;br /&gt;
| DISA&lt;br /&gt;
| [[#CTR-SYS0|CTR-SYS0]]&lt;br /&gt;
| 0x30&lt;br /&gt;
|-&lt;br /&gt;
| [[Extdata|Private Extdata]]&lt;br /&gt;
| [[SD Filesystem|SD]]&lt;br /&gt;
| DIFF&lt;br /&gt;
| [[#CTR-EXT0|CTR-EXT0]]&lt;br /&gt;
| 0x30&lt;br /&gt;
|-&lt;br /&gt;
| [[Extdata|Shared Extdata]]&lt;br /&gt;
| [[Flash Filesystem|NAND]]&lt;br /&gt;
| DIFF&lt;br /&gt;
| [[#CTR-EXT0|CTR-EXT0]]&lt;br /&gt;
| 0x30&lt;br /&gt;
|-&lt;br /&gt;
| [[Title Database]]&lt;br /&gt;
| [[SD Filesystem|SD]]&lt;br /&gt;
| DIFF&lt;br /&gt;
| [[#CTR-9DB0|CTR-9DB0]]&lt;br /&gt;
| 0x30&lt;br /&gt;
|-&lt;br /&gt;
| [[Title Database]]&lt;br /&gt;
| [[Flash Filesystem|NAND]]&lt;br /&gt;
| DIFF&lt;br /&gt;
| [[#CTR-9DB0|CTR-9DB0]]&lt;br /&gt;
| 0x0B&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Encryption ==&lt;br /&gt;
&lt;br /&gt;
DISA and DIFF formats don&#039;t have their own encryption specification. They follow the encryption method defined by their media:&lt;br /&gt;
&lt;br /&gt;
* Gamecard savegames have special wear leveling + encryption layers. See [[Savegames]] for detail.&lt;br /&gt;
* Files on SD follow [[SD Filesystem|the general SD filesystem encryption rule]].&lt;br /&gt;
* Files on NAND are in cleartext, after decrypting [[Flash Filesystem|the NAND partition encryption]].&lt;br /&gt;
&lt;br /&gt;
== Format ==&lt;br /&gt;
&lt;br /&gt;
A DISA / DIFF file consists of the following components:&lt;br /&gt;
&lt;br /&gt;
* 0x100-byte AES CMAC&lt;br /&gt;
* 0x100-byte Header&lt;br /&gt;
* Secondary partition table&lt;br /&gt;
** Contains one or two partition descriptors, depending on the number of partitions.&lt;br /&gt;
* Primary partition table&lt;br /&gt;
** Same layout as the secondary one&lt;br /&gt;
* Partition A&lt;br /&gt;
* Partition B (optional)&lt;br /&gt;
** can only exist for DISA.&lt;br /&gt;
&lt;br /&gt;
== AES CMAC ==&lt;br /&gt;
&lt;br /&gt;
The AES CMAC is located at the beginning of the DISA / DIFF image, and it is 0x10 long. The rest 0xF0 bytes before the header are unused.&lt;br /&gt;
&lt;br /&gt;
The key used for the AES CMAC is generated by the [[AES Registers|hardware key engine]]. See the keyslot it uses in the table above.&lt;br /&gt;
&lt;br /&gt;
The data being authenticated by the AES CMAC is a 0x20-byte SHA-256 hash of a data block. The data block has different content formats among CMAC types. All types of data block contain a copy or a hash of the header, which is the start of the the rest of the verification chain, so the AES CMAC effectively authenticates the whole save image. Each type of data block is explained below.&lt;br /&gt;
&lt;br /&gt;
=== CTR-NOR0 ===&lt;br /&gt;
&lt;br /&gt;
This CMAC type is used for gamecard savegames. It is 0x28-byte long.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! Offset&lt;br /&gt;
! Length&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x00&lt;br /&gt;
| 8&lt;br /&gt;
| Magic &amp;amp;quot;CTR-NOR0&amp;amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| 0x8&lt;br /&gt;
| 0x20&lt;br /&gt;
| SHA-256 of the following 0x108-byte block&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
| 0x00&lt;br /&gt;
| 8&lt;br /&gt;
| Magic &amp;amp;quot;CTR-SAV0&amp;amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| 0x08&lt;br /&gt;
| 0x100&lt;br /&gt;
| Copy of the DISA header&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== CTR-SIGN ===&lt;br /&gt;
&lt;br /&gt;
This CMAC type is used for SD savegames. It is 0x30-byte long.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! Offset&lt;br /&gt;
! Length&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x00&lt;br /&gt;
| 8&lt;br /&gt;
| Magic &amp;amp;quot;CTR-SIGN&amp;amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| 0x08&lt;br /&gt;
| 8&lt;br /&gt;
| Title ID&lt;br /&gt;
|-&lt;br /&gt;
| 0x10&lt;br /&gt;
| 0x20&lt;br /&gt;
| SHA-256 of the following 0x108-byte block&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
| 0x00&lt;br /&gt;
| 8&lt;br /&gt;
| Magic &amp;amp;quot;CTR-SAV0&amp;amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| 0x08&lt;br /&gt;
| 0x100&lt;br /&gt;
| Copy of the DISA header&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== CTR-SYS0 ===&lt;br /&gt;
&lt;br /&gt;
This CMAC type is used for NAND system save. It is 0x110-byte long.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! Offset&lt;br /&gt;
! Length&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x00&lt;br /&gt;
| 8&lt;br /&gt;
| Magic &amp;amp;quot;CTR-SYS0&amp;amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| 0x08&lt;br /&gt;
| 8&lt;br /&gt;
| Save ID. The higher word is always zero&lt;br /&gt;
|-&lt;br /&gt;
| 0x10&lt;br /&gt;
| 0x100&lt;br /&gt;
| Copy of the DISA header&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== CTR-EXT0 ===&lt;br /&gt;
&lt;br /&gt;
This CMAC type is used for extdata. It is 0x11C-byte long.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! Offset&lt;br /&gt;
! Length&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x00&lt;br /&gt;
| 8&lt;br /&gt;
| Magic &amp;amp;quot;CTR-EXT0&amp;amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| 0x08&lt;br /&gt;
| 8&lt;br /&gt;
| Extdata ID&lt;br /&gt;
|-&lt;br /&gt;
| 0x10&lt;br /&gt;
| 4&lt;br /&gt;
| 0 for Quota.dat, 1 otherwise&lt;br /&gt;
|-&lt;br /&gt;
| 0x14&lt;br /&gt;
| 4&lt;br /&gt;
| ID in the device file name. 0 for Quota.dat&lt;br /&gt;
|-&lt;br /&gt;
| 0x18&lt;br /&gt;
| 4&lt;br /&gt;
| ID in the device directory name that the file is in. 0 for Quota.dat&lt;br /&gt;
|-&lt;br /&gt;
| 0x1C&lt;br /&gt;
| 0x100&lt;br /&gt;
| Copy of the DIFF header&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== CTR-9DB0 ===&lt;br /&gt;
&lt;br /&gt;
This CMAC type is used for title database. It is 0x10C-byte long.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! Offset&lt;br /&gt;
! Length&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x00&lt;br /&gt;
| 8&lt;br /&gt;
| Magic &amp;amp;quot;CTR-9DB0&amp;amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| 0x08&lt;br /&gt;
| 4&lt;br /&gt;
| Database ID. Each .db file has its own ID&lt;br /&gt;
|-&lt;br /&gt;
| 0x0C&lt;br /&gt;
| 0x100&lt;br /&gt;
| Copy of the DIFF header&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Header ==&lt;br /&gt;
&lt;br /&gt;
The header located at offset 0x100 defines the rest components of the file (partitions and their tables). All offsets in the header are relative to the beginning of the DISA/DIFF file, except for partition descriptor offsets, which are relative to the beginning of the (active) partition table. DISA and DIFF have different header format.&lt;br /&gt;
&lt;br /&gt;
=== DISA header ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! Offset&lt;br /&gt;
! Length&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x00&lt;br /&gt;
| 4&lt;br /&gt;
| Magic &amp;amp;quot;DISA&amp;amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| 0x04&lt;br /&gt;
| 4&lt;br /&gt;
| Magic 0x40000&lt;br /&gt;
|-&lt;br /&gt;
| 0x08&lt;br /&gt;
| 4&lt;br /&gt;
| Partition count, 1 or 2&lt;br /&gt;
|-&lt;br /&gt;
| 0x0C&lt;br /&gt;
| 4&lt;br /&gt;
| Padding&lt;br /&gt;
|-&lt;br /&gt;
| 0x10&lt;br /&gt;
| 8&lt;br /&gt;
| Secondary partition table offset&lt;br /&gt;
|-&lt;br /&gt;
| 0x18&lt;br /&gt;
| 8&lt;br /&gt;
| Primary partition table offset&lt;br /&gt;
|-&lt;br /&gt;
| 0x20&lt;br /&gt;
| 8&lt;br /&gt;
| Partition table size&lt;br /&gt;
|-&lt;br /&gt;
| 0x28&lt;br /&gt;
| 8&lt;br /&gt;
| Partition A descriptor offset in the partition table&lt;br /&gt;
|-&lt;br /&gt;
| 0x30&lt;br /&gt;
| 8&lt;br /&gt;
| Partition A descriptor size&lt;br /&gt;
|-&lt;br /&gt;
| 0x38&lt;br /&gt;
| 8&lt;br /&gt;
| Partition B descriptor offset in the partition table&lt;br /&gt;
|-&lt;br /&gt;
| 0x40&lt;br /&gt;
| 8&lt;br /&gt;
| Partition B descriptor size&lt;br /&gt;
|-&lt;br /&gt;
| 0x48&lt;br /&gt;
| 8&lt;br /&gt;
| Partition A offset&lt;br /&gt;
|-&lt;br /&gt;
| 0x50&lt;br /&gt;
| 8&lt;br /&gt;
| Partition A size&lt;br /&gt;
|-&lt;br /&gt;
| 0x58&lt;br /&gt;
| 8&lt;br /&gt;
| Partition B offset&lt;br /&gt;
|-&lt;br /&gt;
| 0x60&lt;br /&gt;
| 8&lt;br /&gt;
| Partition B size&lt;br /&gt;
|-&lt;br /&gt;
| 0x68&lt;br /&gt;
| 1&lt;br /&gt;
| Active partition table, 0 = primary, 1 = secondary&lt;br /&gt;
|-&lt;br /&gt;
| 0x69&lt;br /&gt;
| 3&lt;br /&gt;
| Padding&lt;br /&gt;
|-&lt;br /&gt;
| 0x6C&lt;br /&gt;
| 0x20&lt;br /&gt;
| SHA-256 over the active partition table&lt;br /&gt;
|-&lt;br /&gt;
| 0x8C&lt;br /&gt;
| 0x74&lt;br /&gt;
| Unused&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Note:&lt;br /&gt;
&lt;br /&gt;
* When the partition count is 1, there is no partition B and all of its related fields are zero.&lt;br /&gt;
&lt;br /&gt;
=== DIFF header ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! Offset&lt;br /&gt;
! Length&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x00&lt;br /&gt;
| 4&lt;br /&gt;
| Magic &amp;amp;quot;DIFF&amp;amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| 0x04&lt;br /&gt;
| 4&lt;br /&gt;
| Magic 0x30000&lt;br /&gt;
|-&lt;br /&gt;
| 0x08&lt;br /&gt;
| 8&lt;br /&gt;
| Secondary partition table/descriptor offset&lt;br /&gt;
|-&lt;br /&gt;
| 0x10&lt;br /&gt;
| 8&lt;br /&gt;
| Primary partition table/descriptor offset&lt;br /&gt;
|-&lt;br /&gt;
| 0x18&lt;br /&gt;
| 8&lt;br /&gt;
| Partition table/descriptor size&lt;br /&gt;
|-&lt;br /&gt;
| 0x20&lt;br /&gt;
| 8&lt;br /&gt;
| Partition (A) offset&lt;br /&gt;
|-&lt;br /&gt;
| 0x28&lt;br /&gt;
| 8&lt;br /&gt;
| Partition (A) size&lt;br /&gt;
|-&lt;br /&gt;
| 0x30&lt;br /&gt;
| 4&lt;br /&gt;
| Active partition descriptor, 0 = primary, 1 = secondary&lt;br /&gt;
|-&lt;br /&gt;
| 0x34&lt;br /&gt;
| 0x20&lt;br /&gt;
| SHA-256 over the active partition table/descriptor&lt;br /&gt;
|-&lt;br /&gt;
| 0x54&lt;br /&gt;
| 8&lt;br /&gt;
| Unique identifier&lt;br /&gt;
|-&lt;br /&gt;
| 0x5C&lt;br /&gt;
| 0xA4&lt;br /&gt;
| Unused, might contain leftover data&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Note:&lt;br /&gt;
&lt;br /&gt;
* Since DIFF can only contain one partition, a partition table can only have one partition descriptor, so they become the same concept here.&lt;br /&gt;
* See [[Extdata]] for its usage of the unique identifier field. For title database files, this field is zero.&lt;br /&gt;
&lt;br /&gt;
== Partition table &amp;amp;amp; partition descriptor ==&lt;br /&gt;
&lt;br /&gt;
There are two partition tables, but only one of them is active. When operating on a DISA / DIFF file, 3DS FS alternately activate one of the two tables, presumably for data backup or atomic file writing. A newly created DISA / DIFF file may have entirely uninitialized data in the inactive partition table.&lt;br /&gt;
&lt;br /&gt;
One partition table contains one or two partition descriptors , each of which describes the layout of one partition. A partition descriptor contains the following components:&lt;br /&gt;
&lt;br /&gt;
* DIFI header&lt;br /&gt;
* IVFC descriptor&lt;br /&gt;
* DPFS descriptor&lt;br /&gt;
* Partition master hash&lt;br /&gt;
&lt;br /&gt;
=== DIFI header ===&lt;br /&gt;
&lt;br /&gt;
The DIFI header locates at the beginning of a partition descriptor. This header defines the rest components of the partition descriptor (IVFC descriptor, DPFS descriptor and partition master hash). All offsets are relative to the beginning of the partition descriptor, except for &amp;lt;code&amp;gt;External IVFC level 4 offset&amp;lt;/code&amp;gt;, which is relative to the beginning of the partition.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! Offset&lt;br /&gt;
! Length&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x00&lt;br /&gt;
| 4&lt;br /&gt;
| Magic &amp;amp;quot;DIFI&amp;amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| 0x04&lt;br /&gt;
| 4&lt;br /&gt;
| Magic 0x10000&lt;br /&gt;
|-&lt;br /&gt;
| 0x08&lt;br /&gt;
| 8&lt;br /&gt;
| IVFC descriptor offset&lt;br /&gt;
|-&lt;br /&gt;
| 0x10&lt;br /&gt;
| 8&lt;br /&gt;
| IVFC descriptor size&lt;br /&gt;
|-&lt;br /&gt;
| 0x18&lt;br /&gt;
| 8&lt;br /&gt;
| DPFS descriptor offset&lt;br /&gt;
|-&lt;br /&gt;
| 0x20&lt;br /&gt;
| 8&lt;br /&gt;
| DPFS descriptor size&lt;br /&gt;
|-&lt;br /&gt;
| 0x28&lt;br /&gt;
| 8&lt;br /&gt;
| Partition hash offset&lt;br /&gt;
|-&lt;br /&gt;
| 0x30&lt;br /&gt;
| 8&lt;br /&gt;
| Partition hash size&lt;br /&gt;
|-&lt;br /&gt;
| 0x38&lt;br /&gt;
| 1&lt;br /&gt;
| If none zero, enable external IVFC level 4.&lt;br /&gt;
|-&lt;br /&gt;
| 0x39&lt;br /&gt;
| 1&lt;br /&gt;
| DPFS tree level 1 selector&lt;br /&gt;
|-&lt;br /&gt;
| 0x3A&lt;br /&gt;
| 2&lt;br /&gt;
| Padding&lt;br /&gt;
|-&lt;br /&gt;
| 0x3C&lt;br /&gt;
| 8&lt;br /&gt;
| External IVFC level 4 offset (zero if external IVFC level 4 disabled)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Note:&lt;br /&gt;
&lt;br /&gt;
* The meaning of fields after 0x38 are explained in the section [[#Partition]]&lt;br /&gt;
&lt;br /&gt;
=== IVFC descriptor ===&lt;br /&gt;
&lt;br /&gt;
This header defines each level of IVFC tree (explained in the section [[#Partition]]). All offsets are relative to the beginning of DPFS level 3.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! Offset&lt;br /&gt;
! Length&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x00&lt;br /&gt;
| 4&lt;br /&gt;
| Magic &amp;amp;quot;IVFC&amp;amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| 0x04&lt;br /&gt;
| 4&lt;br /&gt;
| Magic 0x20000&lt;br /&gt;
|-&lt;br /&gt;
| 0x08&lt;br /&gt;
| 8&lt;br /&gt;
| Master hash size = partition master hash size in DIFI header&lt;br /&gt;
|-&lt;br /&gt;
| 0x10&lt;br /&gt;
| 8&lt;br /&gt;
| IVFC level 1 offset&lt;br /&gt;
|-&lt;br /&gt;
| 0x18&lt;br /&gt;
| 8&lt;br /&gt;
| IVFC level 1 size&lt;br /&gt;
|-&lt;br /&gt;
| 0x20&lt;br /&gt;
| 4&lt;br /&gt;
| IVFC level 1 block size in log2&lt;br /&gt;
|-&lt;br /&gt;
| 0x24&lt;br /&gt;
| 4&lt;br /&gt;
| Padding&lt;br /&gt;
|-&lt;br /&gt;
| 0x28&lt;br /&gt;
| 8&lt;br /&gt;
| IVFC level 2 offset&lt;br /&gt;
|-&lt;br /&gt;
| 0x30&lt;br /&gt;
| 8&lt;br /&gt;
| IVFC level 2 size&lt;br /&gt;
|-&lt;br /&gt;
| 0x38&lt;br /&gt;
| 4&lt;br /&gt;
| IVFC level 2 block size in log2&lt;br /&gt;
|-&lt;br /&gt;
| 0x3C&lt;br /&gt;
| 4&lt;br /&gt;
| Padding&lt;br /&gt;
|-&lt;br /&gt;
| 0x40&lt;br /&gt;
| 8&lt;br /&gt;
| IVFC level 3 offset&lt;br /&gt;
|-&lt;br /&gt;
| 0x48&lt;br /&gt;
| 8&lt;br /&gt;
| IVFC level 3 size&lt;br /&gt;
|-&lt;br /&gt;
| 0x50&lt;br /&gt;
| 4&lt;br /&gt;
| IVFC level 3 block size in log2&lt;br /&gt;
|-&lt;br /&gt;
| 0x54&lt;br /&gt;
| 4&lt;br /&gt;
| Padding&lt;br /&gt;
|-&lt;br /&gt;
| 0x58&lt;br /&gt;
| 8&lt;br /&gt;
| IVFC level 4 offset (unused if external IVFC level 4 enabled)&lt;br /&gt;
|-&lt;br /&gt;
| 0x60&lt;br /&gt;
| 8&lt;br /&gt;
| IVFC level 4 size&lt;br /&gt;
|-&lt;br /&gt;
| 0x68&lt;br /&gt;
| 4&lt;br /&gt;
| IVFC level 4 block size in log2&lt;br /&gt;
|-&lt;br /&gt;
| 0x6C&lt;br /&gt;
| 4&lt;br /&gt;
| Padding&lt;br /&gt;
|-&lt;br /&gt;
| 0x70&lt;br /&gt;
| 8&lt;br /&gt;
| IVFC descriptor size? The value is usually 0x78&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== DPFS descriptor ===&lt;br /&gt;
&lt;br /&gt;
This header defines each level of DPFS tree (explained in the section [[#Partition]]). All offsets are relative to the beginning of the partition.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! Offset&lt;br /&gt;
! Length&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x00&lt;br /&gt;
| 4&lt;br /&gt;
| Magic &amp;amp;quot;DPFS&amp;amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| 0x04&lt;br /&gt;
| 4&lt;br /&gt;
| Magic 0x10000&lt;br /&gt;
|-&lt;br /&gt;
| 0x08&lt;br /&gt;
| 8&lt;br /&gt;
| DPFS level 1 offset&lt;br /&gt;
|-&lt;br /&gt;
| 0x10&lt;br /&gt;
| 8&lt;br /&gt;
| DPFS level 1 size&lt;br /&gt;
|-&lt;br /&gt;
| 0x18&lt;br /&gt;
| 4&lt;br /&gt;
| DPFS level 1 block size in log2 (unused?)&lt;br /&gt;
|-&lt;br /&gt;
| 0x1C&lt;br /&gt;
| 4&lt;br /&gt;
| Padding&lt;br /&gt;
|-&lt;br /&gt;
| 0x20&lt;br /&gt;
| 8&lt;br /&gt;
| DPFS level 2 offset&lt;br /&gt;
|-&lt;br /&gt;
| 0x28&lt;br /&gt;
| 8&lt;br /&gt;
| DPFS level 2 size&lt;br /&gt;
|-&lt;br /&gt;
| 0x30&lt;br /&gt;
| 4&lt;br /&gt;
| DPFS level 2 block size in log2&lt;br /&gt;
|-&lt;br /&gt;
| 0x34&lt;br /&gt;
| 4&lt;br /&gt;
| Padding&lt;br /&gt;
|-&lt;br /&gt;
| 0x38&lt;br /&gt;
| 8&lt;br /&gt;
| DPFS level 3 offset&lt;br /&gt;
|-&lt;br /&gt;
| 0x40&lt;br /&gt;
| 8&lt;br /&gt;
| DPFS level 3 size&lt;br /&gt;
|-&lt;br /&gt;
| 0x48&lt;br /&gt;
| 4&lt;br /&gt;
| DPFS level 3 block size in log2&lt;br /&gt;
|-&lt;br /&gt;
| 0x4C&lt;br /&gt;
| 4&lt;br /&gt;
| Padding&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Partition master hash ===&lt;br /&gt;
&lt;br /&gt;
This is a SHA-256 hash list over IVFC level 1. See [[#IVFC tree]] for explanation.&lt;br /&gt;
&lt;br /&gt;
== Partition ==&lt;br /&gt;
&lt;br /&gt;
A partition can have two types of layout. This is determined by the field DIFF + 0x38 (&amp;lt;code&amp;gt;Enable external IVFC level 4&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
The layout type 0 (external IVFC level 4 disabled) contains&lt;br /&gt;
&lt;br /&gt;
* DPFS level 1&lt;br /&gt;
* DPFS level 2&lt;br /&gt;
* DPFS level 3, and inside&lt;br /&gt;
** IVFC level 1&lt;br /&gt;
** IVFC level 2&lt;br /&gt;
** IVFC level 3&lt;br /&gt;
** IVFC level 4 (the actual content data)&lt;br /&gt;
&lt;br /&gt;
The layout type 1 (external IVFC level 4 enabled) contains&lt;br /&gt;
&lt;br /&gt;
* DPFS level 1&lt;br /&gt;
* DPFS level 2&lt;br /&gt;
* DPFS level 3, and inside&lt;br /&gt;
** IVFC level 1&lt;br /&gt;
** IVFC level 2&lt;br /&gt;
** IVFC level 3&lt;br /&gt;
* IVFC level 4 (the actual content data, note that this is out side DPFS level 3)&lt;br /&gt;
&lt;br /&gt;
=== DPFS tree ===&lt;br /&gt;
&lt;br /&gt;
Everything inside the DPFS tree comes in pairs, and at one time only one of a pair is active. The tree is probably designed for atomic writing: for a file writing operation, it writes to the inactive part, then commits the data by switching a bit to activate it.&lt;br /&gt;
&lt;br /&gt;
Each level of DPFS tree consists of a pair of chunks. The size of one chunk is defined as it in the DPFS descriptor, so the total size of a level is actually twice as large as the size recorded in the descriptor. For level 1 and 2, each chunk is a bit array, in which each bit corresponds to a block in the next level (the block size of the next level is also defined in the DPFS descriptor). This bit indicates which one of the pair in the next level is active for this block: 0 means the first one and 1 means the second one. The active chunk of level 1 is selected by &amp;lt;code&amp;gt;DPFS tree level 1 selector&amp;lt;/code&amp;gt; in the DIFI header. The bit array is encoded in u32 array, with MSB as the first bit of each 32 bits.&lt;br /&gt;
&lt;br /&gt;
To access data in level 3, one needs to check the bits in level 1 and level 2 to know which chunk of level 3 is active for the accessed location. For example, for a following configuration:&lt;br /&gt;
&lt;br /&gt;
* Level 1: size = 4 bytes = 32 bits&lt;br /&gt;
* Level 2: size = 0x380 bytes = 0x1C00 bits, block size = 0x80 bytes&lt;br /&gt;
* Level 3: size = 0x1B7F000, block size = 0x1000, block size = 0x1000 bytes&lt;br /&gt;
&lt;br /&gt;
if one want to read byte at 0x1234567 of level 3, the following calculation is performed:&lt;br /&gt;
&lt;br /&gt;
* get level 2 bit index &amp;lt;code&amp;gt;0x1234567 / 0x1000 = 0x1234&amp;lt;/code&amp;gt;, and its byte location &amp;lt;code&amp;gt;0x1234 / 8 = 0x246&amp;lt;/code&amp;gt;&lt;br /&gt;
* get level 1 bit index &amp;lt;code&amp;gt;0x246 / 0x80 = 4&amp;lt;/code&amp;gt;&lt;br /&gt;
* get &amp;lt;code&amp;gt;level1_selector&amp;lt;/code&amp;gt; from DIFI header&lt;br /&gt;
* read &amp;lt;code&amp;gt;level2_selector = Level1[level1_selector].bits[4]&amp;lt;/code&amp;gt;;&lt;br /&gt;
* read &amp;lt;code&amp;gt;level3_selector = Level2[level2_selector].bits[0x1234]&amp;lt;/code&amp;gt;;&lt;br /&gt;
* read &amp;lt;code&amp;gt;data = Level3[level3_selector].bytes[0x1234567]&amp;lt;/code&amp;gt; as the final data&lt;br /&gt;
* in the code above &amp;lt;code&amp;gt;Levelx[k]&amp;lt;/code&amp;gt; means the &amp;lt;code&amp;gt;k&amp;lt;/code&amp;gt;-th chunk in level &amp;lt;code&amp;gt;x&amp;lt;/code&amp;gt;, where &amp;lt;code&amp;gt;k = 0, 1&amp;lt;/code&amp;gt;. &amp;lt;code&amp;gt;.bits[n]&amp;lt;/code&amp;gt; is expanded to &amp;lt;code&amp;gt;(.u32_array[n / 32] &amp;amp;gt;&amp;amp;gt; (31 - n % 32)) &amp;amp;amp; 1&amp;lt;/code&amp;gt; as the bit array is encoded in u32 array.&lt;br /&gt;
&lt;br /&gt;
Effectively, the active data is scattered among the two level 3 chunk. One can assemble the whole active level 3 image following the same rule.&lt;br /&gt;
&lt;br /&gt;
=== IVFC tree ===&lt;br /&gt;
&lt;br /&gt;
The IVFC tree is used for data verification. It is very similar to the IVFC tree in [[RomFS]], except that it has an additional level here. For level 1, 2 and 3, each level is a list of SHA-256 hash, of which each corresponds to a block of the next level which is zero-padded to align the block size (the block size of the next level is defined in the IVFC descriptor).&lt;br /&gt;
&lt;br /&gt;
The partition master hash in the partition descriptor can be seen as IVFC level 0, which hashes level 1 following the same rule. The master hash is usually 0x20 long, consisting only one hash. This is because most DISA / DIFF files are not large enough to have multiple hashes on the top level, which isn&#039;t the case for some title database files.&lt;br /&gt;
&lt;br /&gt;
However, not all data is hashed - only ranges that have been written with valid data are properly hashed.&lt;br /&gt;
&lt;br /&gt;
Level 4 is the actual content of the partition, which is what the container format essentially contains.&lt;br /&gt;
&lt;br /&gt;
== Extracting content from a DISA / DIFF container ==&lt;br /&gt;
&lt;br /&gt;
* Find the active partition table and the partition(s).&lt;br /&gt;
* Unwrap DPFS tree of partition(s) by reconstructing active data.&lt;br /&gt;
* Unwrap IVFC tree. Either take out level 4 directly, or, better, verify all the hashes and poison the data that is not properly hashed.&lt;br /&gt;
* The IVFC level 4 is the inner content of the file. The format of it varies among different usage. Refer their own page for further extraction.&lt;br /&gt;
&lt;br /&gt;
== Chain of trust ==&lt;br /&gt;
&lt;br /&gt;
* AES CMAC verifies the header.&lt;br /&gt;
* The header verifies the active partition table via the table hash.&lt;br /&gt;
* In the partition table, each descriptor verifies level 1 of its IVFC tree via the master hash.&lt;br /&gt;
* Each IVFC level verifies the next level, until the level 4, which is the inner content.&lt;br /&gt;
&lt;br /&gt;
== Summary diagram ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
external link: https://i.imgur.com/BjwShJZ.png&lt;br /&gt;
* Please move this into 3dbrew when file uploading is fixed.&lt;/div&gt;</summary>
		<author><name>Wwylele</name></author>
	</entry>
	<entry>
		<id>https://www.3dbrew.org/w/index.php?title=Savegames&amp;diff=21080</id>
		<title>Savegames</title>
		<link rel="alternate" type="text/html" href="https://www.3dbrew.org/w/index.php?title=Savegames&amp;diff=21080"/>
		<updated>2019-10-18T19:05:17Z</updated>

		<summary type="html">&lt;p&gt;Wwylele: /* Tools */ update my save tool&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This page describes the format and encryption of savegames contained in gamecards, SD and NAND. You can find savegames from various 3DS games on the [[Games]] page.&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
Savegames are stored in [[DISA and DIFF|DISA container format]]. Inside the DISA container, it forms a [[Inner FAT|FAT filesystem]]. &#039;&#039;&#039;Please refer to these pages for how to fully extract save files&#039;&#039;&#039;. This page only describes additional encryption wear leveling on top of the DISA container. These layers only apply to gamecard save games. SD savegames and NAND savegames are DISA containers in plaintext after decrypting the common SD/NAND encryption layer.&lt;br /&gt;
&lt;br /&gt;
== Gamecard savegame Encryption ==&lt;br /&gt;
&lt;br /&gt;
=== Repeating CTR Fail ===&lt;br /&gt;
On the 3DS savegames are stored much like on the DS, that is on a FLASH chip in the gamecart. On the DS these savegames were stored in plain-text but on the 3DS a layer of encryption was added. This is AES-CTR, as the contents of several savegames exhibit the odd behavior that xor-ing certain parts of the savegame together will result in the plain-text appearing.&lt;br /&gt;
&lt;br /&gt;
The reason this works is because the stream cipher used has a period of 512 bytes. That is to say, it will repeat the same keystream after 512 bytes. The way you encrypt with a stream cipher is you XOR your data with the keystream as it is produced. Unfortunately, if your streamcipher repeats and you are encrypting a known plain-text (in our case, zeros) you are basically giving away your valuable keystream.&lt;br /&gt;
&lt;br /&gt;
So how do you use this to decrypt a savegame on a 3DS? First off, you chunk up the savegame into 512 byte chunks. Then, you bin these chunks by their contents, discarding any that contain only FF. Now look for the most common chunk. This is your keystream. Now XOR the keystream with your original savegame and you should have a fully decrypted savegame. XOR with the keystream again to produce an encrypted savegame.&lt;br /&gt;
&lt;br /&gt;
=== Savegame keyY ===&lt;br /&gt;
&lt;br /&gt;
All gamecard and SD savegames are encrypted with AES-CTR. The base CTR for gamecard savegames is all-zero. The gamecard savegame [[AES|keyslots]]&#039; keyY(these savegame keyslots use the hardware key-generator) is unique for each region and for each game. The [[NCSD]] partition flags determine the method used to generate this keyY. When the save [[NCSD]] flags checked by the running NATIVE_FIRM are all-zero, the system will use the repeating CTR, otherwise a proper CTR which never repeats within the image is used.&lt;br /&gt;
&lt;br /&gt;
The [[AES]]-CMAC (which uses a hardware key-generator keyslot, as mentioned above) at the the beginning of the savegame must match the calculated CMAC using the DISA/DIFF data, otherwise the savegame is considered corrupted(see below).&lt;br /&gt;
&lt;br /&gt;
When all of the flags checked by the running NATIVE_FIRM are clear, the keyY(original keyY method used with saves where the CTR repeats within the image) is the following:&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;
| First 8-bytes from the plaintext [[NCCH#CXI|CXI]] accessdesc signature.&lt;br /&gt;
|-&lt;br /&gt;
| 0x8&lt;br /&gt;
| 0x4&lt;br /&gt;
| u32 CardID0 from [[Gamecards|gamecard]] plaintext-mode command 0x90, Process9 reads this with the [[NTRCARD]] hw. The actual cmdID used by Process9 is different since Process9 reads it with the gamecard in encrypted-mode.&lt;br /&gt;
|-&lt;br /&gt;
| 0xC&lt;br /&gt;
| 0x4&lt;br /&gt;
| u32 CardID1 from [[Gamecards|gamecard]] plaintext-mode command 0xA0, Process9 reads this with the [[NTRCARD]] hw. The actual cmdID used by Process9 is different since Process9 reads it with the gamecard in encrypted-mode.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== [[2.0.0-2]] Hashed keyY and [[2.2.0-4]] Savegame Encryption ====&lt;br /&gt;
&lt;br /&gt;
When certain [[NCSD]] partition flags are set, a SHA-256 hash is calculated over the data from the CXI(same data used with the original plain keyY), and the 0x40-bytes read from a gamecard command(this 0x40-byte data is also read by [[Process_Services_PXI|GetRomId]], which is the gamecard-uniqueID). The first 0x10-bytes from this hash is used for the keyY. When flag[7] is set, the CTR will never repeat within the save image, unlike the original CTR-method. All games which had the retail NCSD image finalized after the [[2.2.0-4]] update(and contain [[2.2.0-4]]+ in the [[System Update CFA|System update partition]]), use this encryption method.&lt;br /&gt;
&lt;br /&gt;
This keyY generation method was implemented with [[2.0.0-2]] via NCSD partition flag[3], however the proper CTR wasn&#039;t implemented for flag[7] until [[2.2.0-4]]. The hashed keyY flag[3] implemented with [[2.0.0-2]] was likely never used with retail gamecards.&lt;br /&gt;
&lt;br /&gt;
==== [[6.0.0-11]] Savegame keyY ====&lt;br /&gt;
&lt;br /&gt;
[[6.0.0-11]] implemented support for generating the savegame keyY with a new method, this method is much more complex than previous keyY methods. This is enabled via new [[NCSD]] partition flags, all retail games which have the NCSD image finalized after the [[6.0.0-11]] release(and [[6.0.0-11]]+ in the system update partition) will have these flags set for using this new method.&lt;br /&gt;
&lt;br /&gt;
A SHA-256 hash is calculated over the same data used with the above hashed keyY method, after hashing the above data the following data is hashed: the CXI programID, and the ExeFS:/.code hash from the decrypted [[ExeFS]] header. An [[AES]]-CMAC (the keyslot used for this uses the hardware key-scrambler) is then calculated over this hash, the output CMAC is used for the savegame keyY.&lt;br /&gt;
&lt;br /&gt;
The keyY used for calculating this AES-CMAC is initialized while NATIVE_FIRM is loading, this keyY is generated via the [[RSA]] engine. The RSA slot used here is slot0(key-data for slot0 is initialized by bootrom), this RSA slot0 key-data is overwritten during system boot. This RSA slot0 key-data gets overwritten with the RSA key-data used for verifying RSA signatures, every time Process9 verifies any RSA signatures except for [[NCCH|NCCH]] accessdesc signatures. Starting with [[7.0.0-13]] this key-init function used at boot is also used to initialize a separate keyslot used for the new [[NCCH]] encryption method.&lt;br /&gt;
&lt;br /&gt;
This [[FIRM|Process9]] key-init function first checks if a certain 0x10-byte block in the 0x01FF8000 region is all-zero. When all-zero it immediately returns, otherwise it clears that block then continues to do the key generation. This is likely for supporting launching a v6.0+ NATIVE_FIRM under this FIRM.&lt;br /&gt;
&lt;br /&gt;
== Gamecard wear leveling ==&lt;br /&gt;
&lt;br /&gt;
The 3DS employs a wear leveling scheme on the savegame FLASH chips(only used for CARD1 gamecards). This is done through the usage of blockmaps and a journal. The blockmap is located at offset 0 of the flash chip, and is immediately followed by the journal. The initial state is dictated by the blockmap, and the journal is then applied to that.&lt;br /&gt;
&lt;br /&gt;
First, there are 8 bytes whose purposes are currently unknown. Then comes the actual blockmap.&lt;br /&gt;
The blockmap structure is simple:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
struct header_entry {&lt;br /&gt;
        uint8_t phys_sec; // when bit7 is set, block has checksums, otherwise checksums are all zero&lt;br /&gt;
        uint8_t alloc_cnt;&lt;br /&gt;
        uint8_t chksums[8];&lt;br /&gt;
} __attribute__((__packed__));&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There&#039;s one entry per sector, counting from physical sector 1 (sector 0 contains the blockmap/journal).&lt;br /&gt;
&lt;br /&gt;
The 2 bytes that follow the blockmap are the CRC16 (with starting value 0xFFFF (like modbus)) of the first 8 bytes and the blockmap.&lt;br /&gt;
&lt;br /&gt;
Then comes the journal.&lt;br /&gt;
The journal structure is as follows:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
struct sector_entry {&lt;br /&gt;
        uint8_t virt_sec;       // Mapped to sector&lt;br /&gt;
        uint8_t prev_virt_sec;  // Physical sector previously mapped to&lt;br /&gt;
        uint8_t phys_sec;       // Mapped from sector&lt;br /&gt;
        uint8_t prev_phys_sec;  // Virtual sector previously mapped to&lt;br /&gt;
        uint8_t phys_realloc_cnt;       // Amount of times physical sector has been remapped&lt;br /&gt;
        uint8_t virt_realloc_cnt;       // Amount of times virtual sector has been remapped&lt;br /&gt;
        uint8_t chksums[8];&lt;br /&gt;
} __attribute__((__packed__));&lt;br /&gt;
&lt;br /&gt;
struct long_sector_entry{&lt;br /&gt;
        struct sector_entry sector;&lt;br /&gt;
        struct sector_entry dupe;&lt;br /&gt;
        uint32_t magic;&lt;br /&gt;
}__attribute__((__packed__));&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
With magic being a constant 0x080d6ce0.&lt;br /&gt;
&lt;br /&gt;
The checksums in the blockmap/journal entries work as follows:&lt;br /&gt;
* each byte is the checksum of an encrypted 0x200 bytes large block&lt;br /&gt;
* to calculate the checksum, a CRC16 of the block (with starting value 0xFFFF) is calculated, and the two bytes of the CRC16 are XORed together to produce the 8bit checksum&lt;br /&gt;
&lt;br /&gt;
== Initialization ==&lt;br /&gt;
&lt;br /&gt;
When a save FLASH contains all xFFFF blocks it&#039;s assumed uninitialized by the game cartridges and it initializes default data in place, without prompting the user. The 0xFFFFFFFF blocks are uninitialized data. When creating a non-gamecard savegame and other images/files, it&#039;s initially all 0xFFFFFFFF until it&#039;s formatted where some of the blocks are overwritten with encrypted data.&lt;br /&gt;
&lt;br /&gt;
I got a new game SplinterCell3D-Pal and I downloaded the save and it was 128KB of 0xFF, except the first 0x10 bytes which were the letter &#039;Z&#039; (uppercase) --[[User:Elisherer|Elisherer]] 22:41, 15 October 2011 (CEST)&lt;br /&gt;
&lt;br /&gt;
== Fun Facts ==&lt;br /&gt;
&lt;br /&gt;
If you have facts that you found out by looking at the binary files please share them here:&lt;br /&gt;
&lt;br /&gt;
* From one save to another the game backups the last files that were in the partition and the entire image header in &amp;quot;random&amp;quot; locations.. --[[User:Elisherer|Elisherer]] 22:41, 15 October 2011 (CEST)&lt;br /&gt;
&lt;br /&gt;
== Tools ==&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/3dshax/3ds/tree/master/3dsfuse 3dsfuse] supports reading and modifying savegames. In the mounted FUSE filesystem, the /output.sav is the raw FLASH save-image. When the save was modified, a separate tool to update the CMAC must be used with /clean.sav, prior to writing output.sav to a gamecard.&lt;br /&gt;
* [[3DSExplorer]] supports reading of savegames, it doesn&#039;t support reading the new encrypted savegames and maybe in the future it will support modifying (some of the modyfing code is already implemented).&lt;br /&gt;
* [https://github.com/wwylele/3ds-save-tool wwylele&#039;s 3ds-save-tool] supports extracting files from savegames and extdata. It properly reconstructs data from the DPFS tree and extracts files in directories hierarchy.&lt;br /&gt;
* [https://github.com/wwylele/save3ds save3ds] similar to 3dsfuse, but supports savegame inner FS, proper DPFS handling, and automatic CMAC update. Mainly supports SD/NAND save/extdata. Cart save WIP&lt;br /&gt;
&lt;br /&gt;
[[セーブデータ|Japanese]]&lt;/div&gt;</summary>
		<author><name>Wwylele</name></author>
	</entry>
	<entry>
		<id>https://www.3dbrew.org/w/index.php?title=FS:Obsoleted_2_0_FormatThisUserSaveData&amp;diff=20990</id>
		<title>FS:Obsoleted 2 0 FormatThisUserSaveData</title>
		<link rel="alternate" type="text/html" href="https://www.3dbrew.org/w/index.php?title=FS:Obsoleted_2_0_FormatThisUserSaveData&amp;diff=20990"/>
		<updated>2019-05-30T21:19:45Z</updated>

		<summary type="html">&lt;p&gt;Wwylele: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Request=&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
!  Index Word&lt;br /&gt;
!  Description&lt;br /&gt;
|-&lt;br /&gt;
| 0&lt;br /&gt;
| Header code [0x080F0180]&lt;br /&gt;
|-&lt;br /&gt;
| 1&lt;br /&gt;
| Size of a block. Only 0x200 and 0x1000 are accepted it seems.&lt;br /&gt;
|-&lt;br /&gt;
| 2&lt;br /&gt;
| Number of Directories&lt;br /&gt;
|-&lt;br /&gt;
| 3&lt;br /&gt;
| Number of Files&lt;br /&gt;
|-&lt;br /&gt;
| 4&lt;br /&gt;
| Directory Bucket Count&lt;br /&gt;
|-&lt;br /&gt;
| 5&lt;br /&gt;
| File Bucket Count&lt;br /&gt;
|-&lt;br /&gt;
| 6&lt;br /&gt;
| u8, 0 = don&#039;t duplicate data, 1 = duplicate data&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=Response=&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
!  Index Word&lt;br /&gt;
!  Description&lt;br /&gt;
|-&lt;br /&gt;
| 0&lt;br /&gt;
| Header code&lt;br /&gt;
|-&lt;br /&gt;
| 1&lt;br /&gt;
| Result code&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=Description=&lt;br /&gt;
This has been obsoleted. Prefer [[FS:FormatSaveData]].&lt;/div&gt;</summary>
		<author><name>Wwylele</name></author>
	</entry>
	<entry>
		<id>https://www.3dbrew.org/w/index.php?title=FS:FormatSaveData&amp;diff=20989</id>
		<title>FS:FormatSaveData</title>
		<link rel="alternate" type="text/html" href="https://www.3dbrew.org/w/index.php?title=FS:FormatSaveData&amp;diff=20989"/>
		<updated>2019-05-30T21:19:21Z</updated>

		<summary type="html">&lt;p&gt;Wwylele: /* Request */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Request=&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
!  Index Word&lt;br /&gt;
!  Description&lt;br /&gt;
|-&lt;br /&gt;
| 0&lt;br /&gt;
| Header code [0x084C0242]&lt;br /&gt;
|-&lt;br /&gt;
| 1&lt;br /&gt;
| [[Filesystem_services#ArchiveId|Archive ID]]. This must be either 0x4 (SaveData) or 0x567890B2, otherwise error 0xE0E046BE is returned.&lt;br /&gt;
|-&lt;br /&gt;
| 2&lt;br /&gt;
| [[Filesystem_services#PathType|Path Type]]&lt;br /&gt;
|-&lt;br /&gt;
| 3&lt;br /&gt;
| Path Size&lt;br /&gt;
|-&lt;br /&gt;
| 4&lt;br /&gt;
| Size of a block. Only 0x200 and 0x1000 are accepted it seems. The value of this word is hard-coded to 0x200 in official titles it appears.&lt;br /&gt;
|-&lt;br /&gt;
| 5&lt;br /&gt;
| Number of Directories&lt;br /&gt;
|-&lt;br /&gt;
| 6&lt;br /&gt;
| Max number of Files&lt;br /&gt;
|-&lt;br /&gt;
| 7&lt;br /&gt;
| Directory Bucket Count&lt;br /&gt;
|-&lt;br /&gt;
| 8&lt;br /&gt;
| File Bucket Count&lt;br /&gt;
|-&lt;br /&gt;
| 9&lt;br /&gt;
| u8, 0 = don&#039;t duplicate data, 1 = duplicate data&lt;br /&gt;
|-&lt;br /&gt;
| 10&lt;br /&gt;
| (PathSize &amp;lt;&amp;lt; 14) &amp;lt;nowiki&amp;gt;|&amp;lt;/nowiki&amp;gt; 2&lt;br /&gt;
|-&lt;br /&gt;
| 11&lt;br /&gt;
| Path Data Pointer&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=Response=&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
!  Index Word&lt;br /&gt;
!  Description&lt;br /&gt;
|-&lt;br /&gt;
| 0&lt;br /&gt;
| Header code&lt;br /&gt;
|-&lt;br /&gt;
| 1&lt;br /&gt;
| Result code&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=Description=&lt;br /&gt;
This clears the SaveData archive for the specified game, if the LowPath.Type is Empty then this will clear the SaveData for the current game. The target SaveData to format is determined by a Binary path, a game needs an exheader permission set in order to format the SaveData of another program.&lt;br /&gt;
&lt;br /&gt;
See [[RomFS#Hash_Table_Structure|here]] for an example of how bucket counts should be calculated.&lt;/div&gt;</summary>
		<author><name>Wwylele</name></author>
	</entry>
	<entry>
		<id>https://www.3dbrew.org/w/index.php?title=Extdata&amp;diff=20985</id>
		<title>Extdata</title>
		<link rel="alternate" type="text/html" href="https://www.3dbrew.org/w/index.php?title=Extdata&amp;diff=20985"/>
		<updated>2019-05-28T13:34:51Z</updated>

		<summary type="html">&lt;p&gt;Wwylele: /* Quota File */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This page describes the format and encryption of extdata, &amp;amp;quot;extra data&amp;amp;quot; stored on SD card and NAND, at:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;nand/data/&amp;amp;lt;ID&amp;amp;gt;/extdata/&amp;amp;lt;ExtdataID-High&amp;amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;sdmc/Nintendo 3DS/&amp;amp;lt;ID0&amp;amp;gt;/&amp;amp;lt;ID1&amp;amp;gt;/extdata/&amp;amp;lt;ExtdataID-High&amp;amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
ExtdataID-High is always 00000000 for SD, and always 00048000 for NAND. Regular apps can only mount SD extdata using the same extdataID which is stored in the CXI exheader. Therefore, regular apps which have the exheader extdataID set to zero can&#039;t use extdata. This restriction doesn&#039;t apply for shared extdata with extdataID high bitmask 0x48000 stored on NAND. System apps with a certain access right can mount arbitrary extdata. All NAND extdata is shared extdata, while all SD extdata is normal extdata.&lt;br /&gt;
&lt;br /&gt;
All data in this page is little-endian. All &amp;amp;quot;unused / padding&amp;amp;quot; fields can contain uninitialized data unless otherwise specified.&lt;br /&gt;
&lt;br /&gt;
= Format =&lt;br /&gt;
&lt;br /&gt;
To avoid confusion, the terms &#039;&#039;&#039;device directory / file&#039;&#039;&#039; and &#039;&#039;&#039;virtual directory / file&#039;&#039;&#039; are used with the following meanings:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Device directory / file&#039;&#039;&#039; are the real directory / file stored on SD / NAND that can be seen under path &amp;lt;code&amp;gt;nand/data/&amp;amp;lt;ID&amp;amp;gt;/extdata/&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;sdmc/Nintendo 3DS/&amp;amp;lt;ID0&amp;amp;gt;/&amp;amp;lt;ID1&amp;amp;gt;/extdata/&amp;lt;/code&amp;gt;.&lt;br /&gt;
* &#039;&#039;&#039;Virtual directory / file&#039;&#039;&#039; are directory / file stored inside extdata virtual file system, which can be seen by applications in the mounted extdata archives.&lt;br /&gt;
&lt;br /&gt;
An extdata consists of several device directories and files, which forms a file system consisting of multiple virtual directories and files.&lt;br /&gt;
&lt;br /&gt;
An extdata with ID &amp;lt;code&amp;gt;ExtdataId&amp;lt;/code&amp;gt; has the following device files:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;.../extdata/&amp;amp;lt;ExtdataID-High&amp;amp;gt;/&amp;amp;lt;ExtdataId-Low&amp;amp;gt;/Quota.dat&amp;lt;/code&amp;gt; (optional)&lt;br /&gt;
* &amp;lt;code&amp;gt;.../extdata/&amp;amp;lt;ExtdataID-High&amp;amp;gt;/&amp;amp;lt;ExtdataId-Low&amp;amp;gt;/&amp;amp;lt;SubDirID&amp;amp;gt;/&amp;amp;lt;SubFileID&amp;amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note:&lt;br /&gt;
&lt;br /&gt;
* All device files are [[DISA and DIFF|DIFF containers]]. &#039;&#039;&#039;All format description below is about the inner content of the containers&#039;&#039;&#039;. Please unwrap these files first according to the DIFF format description before reading them using the extdata format description below.&lt;br /&gt;
* &amp;lt;code&amp;gt;Quota.dat&amp;lt;/code&amp;gt; is only observed existing for NAND shared extdata.&lt;br /&gt;
* &amp;lt;code&amp;gt;&amp;amp;lt;SubDirID&amp;amp;gt;&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;&amp;amp;lt;SubFileID&amp;amp;gt;&amp;lt;/code&amp;gt; are 8-digit hex strings.&lt;br /&gt;
* Device file with &amp;lt;code&amp;gt;SubDirID = SubFileID = 00000000&amp;lt;/code&amp;gt; doesn&#039;t exist. Other ID combinations can exists.&lt;br /&gt;
* Device file with &amp;lt;code&amp;gt;SubDirID = 00000000&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;SubFileID = 00000001&amp;lt;/code&amp;gt; is the VSXE metadata file and must exist.&lt;br /&gt;
* Other files, besides &amp;lt;code&amp;gt;Quota.dat&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;00000000/00000001&amp;lt;/code&amp;gt;, are normal sub files, are these device files one-to-one correspond to virtual files. They contain raw virtual file data in the DIFF inner content.&lt;br /&gt;
* &amp;lt;code&amp;gt;SubDirID = 00000000&amp;lt;/code&amp;gt; is usually the only one device directory that can be seen. See [[#Device Directory Capacity]] for more information.&lt;br /&gt;
&lt;br /&gt;
== Quota File ==&lt;br /&gt;
&lt;br /&gt;
The inner data of &amp;lt;code&amp;gt;Quota.dat&amp;lt;/code&amp;gt; is 0x48 bytes with the following format. The file seems to limit the extdata total size.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! Offset&lt;br /&gt;
! Length&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x00&lt;br /&gt;
| 4&lt;br /&gt;
| Magic &amp;amp;quot;QUOT&amp;amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| 0x04&lt;br /&gt;
| 4&lt;br /&gt;
| Magic 0x30000&lt;br /&gt;
|-&lt;br /&gt;
| 0x08&lt;br /&gt;
| 4&lt;br /&gt;
| 0x1000, block size&lt;br /&gt;
|-&lt;br /&gt;
| 0x0C&lt;br /&gt;
| 4&lt;br /&gt;
| Always 126. Probably device directory capacity. See the [[#Device Directory Capacity]] more information.&lt;br /&gt;
|-&lt;br /&gt;
| 0x10&lt;br /&gt;
| 4&lt;br /&gt;
| Always 0?&lt;br /&gt;
|-&lt;br /&gt;
| 0x14&lt;br /&gt;
| 4&lt;br /&gt;
| Max number of blocks&lt;br /&gt;
|-&lt;br /&gt;
| 0x18&lt;br /&gt;
| 4&lt;br /&gt;
| Always 0? &lt;br /&gt;
|-&lt;br /&gt;
| 0x1C&lt;br /&gt;
| 4&lt;br /&gt;
| Free blocks remained&lt;br /&gt;
|-&lt;br /&gt;
| 0x20&lt;br /&gt;
| 4&lt;br /&gt;
| Always 0? &lt;br /&gt;
|-&lt;br /&gt;
| 0x24&lt;br /&gt;
| 4&lt;br /&gt;
| Always 0? &lt;br /&gt;
|-&lt;br /&gt;
| 0x28&lt;br /&gt;
| 4&lt;br /&gt;
| Free blocks remained + (blocks occupied by the recently mounted file, specified by the ID below (0 if recently deleted))&lt;br /&gt;
|-&lt;br /&gt;
| 0x2C&lt;br /&gt;
| 4&lt;br /&gt;
| Always 0? &lt;br /&gt;
|-&lt;br /&gt;
| 0x30&lt;br /&gt;
| 4&lt;br /&gt;
| ID of most recently mounted file. Same as the one in [[Inner_FAT#Filesystem Header]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x34&lt;br /&gt;
| 4&lt;br /&gt;
| Always 0?&lt;br /&gt;
|-&lt;br /&gt;
| 0x38&lt;br /&gt;
| 4&lt;br /&gt;
| Always 0?&lt;br /&gt;
|-&lt;br /&gt;
| 0x3C&lt;br /&gt;
| 4&lt;br /&gt;
| Always 0?&lt;br /&gt;
|-&lt;br /&gt;
| 0x40&lt;br /&gt;
| 4&lt;br /&gt;
| Size in bytes of most recently mounted file (device file size). 0 if recently deleted&lt;br /&gt;
|-&lt;br /&gt;
| 0x44&lt;br /&gt;
| 4&lt;br /&gt;
| Always 0?&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Device Directory Capacity ==&lt;br /&gt;
&lt;br /&gt;
A device directory in an extdata (a &amp;lt;code&amp;gt;&amp;amp;lt;SubDirID&amp;amp;gt;&amp;lt;/code&amp;gt; directory) seems to have a maximum number of device files it can contain. For SD extdata, this maximum number seems to be hard-coded as 126. For NAND extdata, the number is probably indicated by a field in Quota.dat, which is, again, always 126 as observed. 3DS FS tries to put all device files in the device directory &amp;lt;code&amp;gt;00000000&amp;lt;/code&amp;gt; if possible, and only when more than 126 files needed to add, a second device directory &amp;lt;code&amp;gt;00000001&amp;lt;/code&amp;gt; and so on are created. However, few extdata have such amount of files to store, so the behavior lacks of use cases to confirm.&lt;br /&gt;
&lt;br /&gt;
The number 126 is probably from some kind of other capacity of 128 with &amp;lt;code&amp;gt;&amp;amp;quot;.&amp;amp;quot;&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;&amp;amp;quot;..&amp;amp;quot;&amp;lt;/code&amp;gt; entries reserved. It is theorized that this is to keep a FAT directory table, with 0x20 bytes for each entry, in one 0x1000 cluster. The motivation is unclear.&lt;br /&gt;
&lt;br /&gt;
== VSXE Filesystem ==&lt;br /&gt;
&lt;br /&gt;
This is one variant of the [[Inner FAT|FAT filesystem]]. Please refer to its page for the description of the filesystem. In general, device file &amp;lt;code&amp;gt;00000000/00000001&amp;lt;/code&amp;gt; contains the metadata of the filesystem, while other device files (except for the Quota file) contains normal sub-files&lt;br /&gt;
&lt;br /&gt;
Each non-dummy file entry corresponds to a device file. The path to the device file is generated by the following computation:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;// See previous section about this capacity&lt;br /&gt;
const uint32_t device_dir_capacity = 126;&lt;br /&gt;
&lt;br /&gt;
// entry index is the index in the file entry table, with the first dummy entry as&lt;br /&gt;
// index = 0, which is never used for a real file.&lt;br /&gt;
// file_index = 1 is reserved for the VSXE Filesystem Metadata itself, so real files&lt;br /&gt;
// started from file_index = 2.&lt;br /&gt;
uint32_t file_index = entry_index + 1;&lt;br /&gt;
&lt;br /&gt;
uint32_t SubDirID = file_index / device_dir_capacity;&lt;br /&gt;
uint32_t SubFileID = file_index % pdevice_dir_capacity;&lt;br /&gt;
&lt;br /&gt;
char extdata_path[...]; // &amp;amp;quot;.../extdata/&amp;amp;lt;ExtdataID-High&amp;amp;gt;/&amp;amp;lt;ExtdataId-Low&amp;amp;gt;&amp;amp;quot;&lt;br /&gt;
char device_path[...]; // output path&lt;br /&gt;
sprintf(device_path, &amp;amp;quot;%s/%08x/%08x&amp;amp;quot;, extdata_path, SubDirID, SubFileID);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
When mounting extdata, the unique identifier is used to match the ID stored in subfile&#039;s [[DISA and DIFF#DIFF header|DIFF header]]. If the ID doesn&#039;t match, mounting will fail.&lt;br /&gt;
&lt;br /&gt;
== Virtual File System Structure ==&lt;br /&gt;
&lt;br /&gt;
When extdata is created, these are &#039;&#039;always&#039;&#039; created regardless of whether the title actually uses them.&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;/icon&amp;lt;/code&amp;gt; This virtual file contains the extdata icon displayed in data management. This icon can only be written to by titles when creating extdata, titles would have to recreate extdata to change the icon. This file can&#039;t be read directly, instead it is read via FS:ReadExtSaveDataIcon.&lt;br /&gt;
* &amp;lt;code&amp;gt;/user/&amp;lt;/code&amp;gt; This virtual directory contains the title&#039;s actual extdata files.&lt;br /&gt;
* &amp;lt;code&amp;gt;/boss/&amp;lt;/code&amp;gt; This virtual directory can contain SpotPass content. SpotPass content can only be downloaded to this &amp;lt;code&amp;gt;/boss&amp;lt;/code&amp;gt; virtual directory.&lt;br /&gt;
&lt;br /&gt;
User extdata and SpotPass extdata use separate mount points at &amp;lt;code&amp;gt;/user&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;/boss&amp;lt;/code&amp;gt;. Therefore one mount can&#039;t access the other virtual directory, and also can&#039;t access &amp;lt;code&amp;gt;/icon&amp;lt;/code&amp;gt;.(The title&#039;s SpotPass extdata can be mounted by the title itself, if it uses SpotPass)&lt;br /&gt;
&lt;br /&gt;
Other optional but notable directories include:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;/user/ExBanner&amp;lt;/code&amp;gt; This virtual directory can optionally store extended banners. When this is available, this banner is displayed instead of the CXI ExeFS banner. &amp;lt;code&amp;gt;COMMON.bin&amp;lt;/code&amp;gt; stores the common exbanner, while &amp;lt;code&amp;gt;&amp;amp;lt;regionlang_code&amp;amp;gt;.bin&amp;lt;/code&amp;gt; stores an optional separate region/language specific banner.(regionlang_code can be &amp;amp;quot;JPN_JP&amp;amp;quot;, &amp;amp;quot;USA_EN&amp;amp;quot;, etc)&lt;br /&gt;
&lt;br /&gt;
== SD Extdata ==&lt;br /&gt;
Usually the ExtdataID low is in the format &#039;00&amp;lt;Unique ID&amp;gt;&#039;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! JPN ExtdataID&lt;br /&gt;
! USA ExtdataID&lt;br /&gt;
! EUR ExtdataID&lt;br /&gt;
! Description&lt;br /&gt;
! Extdata images&lt;br /&gt;
|-&lt;br /&gt;
| 00000082&lt;br /&gt;
| 0000008f&lt;br /&gt;
| 00000098&lt;br /&gt;
| [[Home Menu]] extdata, this contains home-menu savedata and cached icons for applications.&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| 00000200&lt;br /&gt;
| 00000210&lt;br /&gt;
| 00000220&lt;br /&gt;
| [[System_Settings|System Settings]] extdata added with [[2.0.0-2]].&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| 00000207&lt;br /&gt;
| 00000217&lt;br /&gt;
| 00000227&lt;br /&gt;
| [[Mii Maker]], contains an ExBanner&lt;br /&gt;
| [https://dl.dropbox.com/u/20520664/extdata00000217.zip cleartext]&lt;br /&gt;
|-&lt;br /&gt;
| 00000208&lt;br /&gt;
| 00000218&lt;br /&gt;
| 00000228&lt;br /&gt;
| Streetpass Mii Plaza&lt;br /&gt;
| 11 mb big!&lt;br /&gt;
|-&lt;br /&gt;
| 00000209&lt;br /&gt;
| 00000219&lt;br /&gt;
| 00000229&lt;br /&gt;
| [[eShop]], contains store music in AAC format.&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| 0000020b&lt;br /&gt;
| 0000021b&lt;br /&gt;
| 0000022b&lt;br /&gt;
| Nintendo Zone&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| 0000020d&lt;br /&gt;
| 0000021d&lt;br /&gt;
| 0000022d&lt;br /&gt;
| Face Raiders, likely contains an ExBanner&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| 000002cc&lt;br /&gt;
| 000002cd&lt;br /&gt;
| 000002ce&lt;br /&gt;
| [[Home Menu]] theme&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| ?&lt;br /&gt;
| 000004aa&lt;br /&gt;
| 000004ab&lt;br /&gt;
| Nintendo Video Extra Data&lt;br /&gt;
This is where the video files are stored, and [[Nintendo_Video|includes]] the thumbnail, the description, and possibly some checksum info in each video file stored in the extdata images. There are always 9 files within the subdirectory &amp;quot;00000000&amp;quot; of this folder, even without any videos downloaded. The files are &amp;quot;00000001&amp;quot; - &amp;quot;00000009&amp;quot;, and &amp;quot;00000003&amp;quot; - &amp;quot;00000008&amp;quot; have the same filesize of 50.7 MB. It is possible to restore the older videos by overwriting all the files within this directory. Provided of course you have made a backup of the files before hand, by copying all the files within this directory to your computer. As far I&#039;m aware its not possible to mix and match the files in order to get certain videos in one grouping, ie. having all 3 Zelda orchestral recordings in one group of 4 Nintendo videos.&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
|00000306&lt;br /&gt;
|00000308&lt;br /&gt;
|00000307&lt;br /&gt;
|Mario Kart 7&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
| 0000030b&lt;br /&gt;
| 0000030d&lt;br /&gt;
| 0000030c&lt;br /&gt;
| Nintendogs + Cats&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| 00000326&lt;br /&gt;
| 00000326&lt;br /&gt;
| 00000326&lt;br /&gt;
| Pokédex 3D&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| 00000305&lt;br /&gt;
| 0000032d&lt;br /&gt;
| 0000033c&lt;br /&gt;
| Super Street Fighter IV 3D&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| 00000328&lt;br /&gt;
| 00000358&lt;br /&gt;
| 0000033b&lt;br /&gt;
| Ridge Racer 3D&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| ?&lt;br /&gt;
| 0000034d&lt;br /&gt;
| 00000402&lt;br /&gt;
| Samurai Warriors Chronicles&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| ?&lt;br /&gt;
| 0000034f&lt;br /&gt;
| 0000038a&lt;br /&gt;
| Dead or Alive Dimensions&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| 00000481&lt;br /&gt;
| N/A&lt;br /&gt;
| N/A&lt;br /&gt;
| Monster Hunter Tri G (Download-Quests)&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| ?&lt;br /&gt;
| 00000517&lt;br /&gt;
| 00000518&lt;br /&gt;
| Swapnote&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| 0000055d&lt;br /&gt;
| 0000055d&lt;br /&gt;
| 0000055d&lt;br /&gt;
| Pokémon X&amp;lt;br&amp;gt;Pokémon Y&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| ?&lt;br /&gt;
| 00000725&lt;br /&gt;
| 00000724&lt;br /&gt;
| Ambassador Certificate&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| ?&lt;br /&gt;
| ?&lt;br /&gt;
| 000007af&lt;br /&gt;
| New Super Mario Bros. 2&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| ?&lt;br /&gt;
| 00000863&lt;br /&gt;
| 00000864&lt;br /&gt;
| Animal Crossing: New Leaf&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| ?&lt;br /&gt;
| 00000a85&lt;br /&gt;
| 00000a86&lt;br /&gt;
| Professor Layton and the Miracle Mask&amp;lt;br&amp;gt;Professor Layton and the Azran Legacy&lt;br /&gt;
German Version ExtdataID is 00000a87&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| ?&lt;br /&gt;
| ?&lt;br /&gt;
| 00000b4f&lt;br /&gt;
| Fullblox / Crashmo&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| ?&lt;br /&gt;
| ?&lt;br /&gt;
| 00000ba9&lt;br /&gt;
| Pokémon Mystery Dungeon: Gates to Infinity&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| ?&lt;br /&gt;
| ?&lt;br /&gt;
| 00000c24&lt;br /&gt;
| Denpa men&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| 00000c73&lt;br /&gt;
| 00000c73&lt;br /&gt;
| 00000c73&lt;br /&gt;
| Save Data Transfer Tool&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| ?&lt;br /&gt;
| ?&lt;br /&gt;
| 00000d9a&lt;br /&gt;
| Donkey Kong Country™&amp;lt;br&amp;gt;Returns 3D: Trailer&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| ?&lt;br /&gt;
| ?&lt;br /&gt;
| 00000ea6&lt;br /&gt;
| Etrian Odyssey IV&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| ?&lt;br /&gt;
| 00000edf&lt;br /&gt;
| 00000ee0&lt;br /&gt;
| Super Smash Bros. for Nintendo 3DS&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| ?&lt;br /&gt;
| 00000f14&lt;br /&gt;
| 00000f1e&lt;br /&gt;
| Phoenix Wright: Ace Attorney - Dual Destinies&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| ?&lt;br /&gt;
| 00001007&lt;br /&gt;
| 00001005&lt;br /&gt;
| Professor Layton vs Phoenix Wright: Ace Attorney&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| ?&lt;br /&gt;
| ?&lt;br /&gt;
| 00001062&lt;br /&gt;
| Nintendo Pocket Football Club&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| ?&lt;br /&gt;
| ?&lt;br /&gt;
| 0000111c&lt;br /&gt;
| Yoshi&#039;s New Island&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| ?&lt;br /&gt;
| ?&lt;br /&gt;
| 00001131&lt;br /&gt;
| Fantasy Life&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| 000011c5&lt;br /&gt;
| 000011c5&lt;br /&gt;
| 000011c5&lt;br /&gt;
| Pokémon Omega Ruby&amp;lt;br&amp;gt;Pokémon Alpha Sapphire&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| ?&lt;br /&gt;
| ?&lt;br /&gt;
| 000012ca&lt;br /&gt;
| Mario vs. Donkey Kong: Tipping Stars&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| ?&lt;br /&gt;
| ?&lt;br /&gt;
| 00001499&lt;br /&gt;
| Korg DSN-12&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| ?&lt;br /&gt;
| ?&lt;br /&gt;
| 000014f2&lt;br /&gt;
| Animal Crossing: Happy Home Designer&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| 000014d1&lt;br /&gt;
| 000014d1&lt;br /&gt;
| 000014d1&lt;br /&gt;
| [[Home Menu]] badge&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| ?&lt;br /&gt;
| ?&lt;br /&gt;
| 00001632&lt;br /&gt;
| Fullblox / Stretchmo&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| ?&lt;br /&gt;
| ?&lt;br /&gt;
| 00001646&lt;br /&gt;
| Pokémon Rumble World&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| 00001648&lt;br /&gt;
| 00001648&lt;br /&gt;
| 00001648&lt;br /&gt;
| Pokémon Sun&amp;lt;br&amp;gt;Pokémon Moon&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| 0000165c&lt;br /&gt;
| 0000165c&lt;br /&gt;
| 0000165c&lt;br /&gt;
| [[Home Menu]] saved theme layouts&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| ?&lt;br /&gt;
| ?&lt;br /&gt;
| 00001678&lt;br /&gt;
| Yo-kai Watch&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| ?&lt;br /&gt;
| ?&lt;br /&gt;
| 000018fa&lt;br /&gt;
| Phoenix Wright: Ace Attorney - Spirit of Justice&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| ?&lt;br /&gt;
| ?&lt;br /&gt;
| 0000198f&lt;br /&gt;
| Animal Crossing: New Leaf - Welcome amiibo&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
| ?&lt;br /&gt;
| ?&lt;br /&gt;
| 00001a05&lt;br /&gt;
| Super Mario Maker&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| ?&lt;br /&gt;
| ?&lt;br /&gt;
| 00001a2e&lt;br /&gt;
| Swapdoodle&lt;br /&gt;
| &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== NAND Shared Extdata ==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
!  ExtdataID&lt;br /&gt;
!  Description&lt;br /&gt;
|-&lt;br /&gt;
| 0xe0000000&lt;br /&gt;
| Home Menu attempts to open this archive during boot, if [[FS:OpenArchive]] doesn&#039;t return an error Home Menu seems to then launch the [[System Transfer]] application. Home Menu doesn&#039;t actually use this archive at all except for checking whether it exists.&lt;br /&gt;
|-&lt;br /&gt;
|  0xf0000001&lt;br /&gt;
|  NAND JPEG/MPO files and phtcache.bin from the camera application are stored here. This also contains UploadData.dat.&lt;br /&gt;
|-&lt;br /&gt;
|  0xf0000002&lt;br /&gt;
|  NAND M4A files from the sound application are stored here&lt;br /&gt;
|-&lt;br /&gt;
|  0xf0000009&lt;br /&gt;
|  Used for [[BOSS_Services|SpotPass]] content storage for [[News_Services|notifications]].&lt;br /&gt;
|-&lt;br /&gt;
|  0xf000000b&lt;br /&gt;
|  Contains idb.dat, idbt.dat, gamecoin.dat, ubll.lst, CFL_DB.dat, and CFL_OldDB.dat. These files contain cleartext [[Mii_Maker|Miis]] and some data relating (including cached ICN data) to Play/Usage Records.&lt;br /&gt;
|-&lt;br /&gt;
|  0xf000000c&lt;br /&gt;
|  Contains bashotorya.dat and bashotorya2.dat.&lt;br /&gt;
|-&lt;br /&gt;
|  0xf000000d&lt;br /&gt;
|  Home Menu SpotPass content data [[BOSS_Services|storage]].&lt;br /&gt;
|-&lt;br /&gt;
|  0xf000000e&lt;br /&gt;
|  Contains [[VersionList|versionlist.dat]], used by Home Menu for the software update notification added with [[7.0.0-13]].&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Shared Extdata 0xf000000b gamecoin.dat ====&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;
| 0x4&lt;br /&gt;
| Magic number: 0x4F00&lt;br /&gt;
|-&lt;br /&gt;
| 0x4&lt;br /&gt;
| 0x2&lt;br /&gt;
| Total Play Coins&lt;br /&gt;
|-&lt;br /&gt;
| 0x6&lt;br /&gt;
| 0x2&lt;br /&gt;
| Total Play Coins obtained on the date stored below. When the below date does not match the current date, this field is reset to zero, then the date(and other fields) are updated. Once this value is &amp;gt;=10, no more Play Coins can be obtained until the current date changes.&lt;br /&gt;
|-&lt;br /&gt;
| 0x8&lt;br /&gt;
| 0x4&lt;br /&gt;
| Total step [[PTM:GetTotalStepCount|count]] at the time a new Play Coin was obtained.&lt;br /&gt;
|-&lt;br /&gt;
| 0xC&lt;br /&gt;
| 0x4&lt;br /&gt;
| Step count for the day the last Play Coin was obtained, for that day&#039;s step count(same as the step count displayed by home-menu when this file was updated).&lt;br /&gt;
|-&lt;br /&gt;
| 0x10&lt;br /&gt;
| 0x2&lt;br /&gt;
| Year&lt;br /&gt;
|-&lt;br /&gt;
| 0x12&lt;br /&gt;
| 0x1&lt;br /&gt;
| Month&lt;br /&gt;
|-&lt;br /&gt;
| 0x13&lt;br /&gt;
| 0x1&lt;br /&gt;
| Day&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The above date stores the last time new Play Coin(s) were obtained. The contents of this file is updated by home-menu. [[PTM:GetTotalStepCount]] is not checked constantly, after home-menu boot this is only checked when waking from sleep-mode. Each time home-menu updates the contents of this file, home-menu will set the Play Coin total to 300 if it&#039;s higher than the 300 Play Coin limit.&lt;br /&gt;
&lt;br /&gt;
[[Home Menu]] loads this file / opens this archive during [[Home Menu|startup]]. When accessing this file fails, like when the file/archive is corrupted(or at least on older system-versions), the result is a brick due to Home Menu using [[SVC|svcBreak]]. [[User:Yellows8|Yellows8]] bricked a 3DS this way due to corruption via invalid [[FSFile:Write]] flush flags. When opening this extdata archive(0xf000000b) fails, Home Menu executes svcBreak.&lt;br /&gt;
&lt;br /&gt;
==== Shared Extdata 0xf000000b ubll.lst ====&lt;br /&gt;
List of blocked users.&lt;br /&gt;
&lt;br /&gt;
Empty space is filled with 0xC-long sequences of 00 00 ... 07&lt;br /&gt;
&lt;br /&gt;
=== Tools ===&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/wwylele/3ds-save-tool 3ds-save-tool] - Extract/verifies extdata&lt;/div&gt;</summary>
		<author><name>Wwylele</name></author>
	</entry>
	<entry>
		<id>https://www.3dbrew.org/w/index.php?title=Extdata&amp;diff=20984</id>
		<title>Extdata</title>
		<link rel="alternate" type="text/html" href="https://www.3dbrew.org/w/index.php?title=Extdata&amp;diff=20984"/>
		<updated>2019-05-28T13:31:09Z</updated>

		<summary type="html">&lt;p&gt;Wwylele: /* Quota File */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This page describes the format and encryption of extdata, &amp;amp;quot;extra data&amp;amp;quot; stored on SD card and NAND, at:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;nand/data/&amp;amp;lt;ID&amp;amp;gt;/extdata/&amp;amp;lt;ExtdataID-High&amp;amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;sdmc/Nintendo 3DS/&amp;amp;lt;ID0&amp;amp;gt;/&amp;amp;lt;ID1&amp;amp;gt;/extdata/&amp;amp;lt;ExtdataID-High&amp;amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
ExtdataID-High is always 00000000 for SD, and always 00048000 for NAND. Regular apps can only mount SD extdata using the same extdataID which is stored in the CXI exheader. Therefore, regular apps which have the exheader extdataID set to zero can&#039;t use extdata. This restriction doesn&#039;t apply for shared extdata with extdataID high bitmask 0x48000 stored on NAND. System apps with a certain access right can mount arbitrary extdata. All NAND extdata is shared extdata, while all SD extdata is normal extdata.&lt;br /&gt;
&lt;br /&gt;
All data in this page is little-endian. All &amp;amp;quot;unused / padding&amp;amp;quot; fields can contain uninitialized data unless otherwise specified.&lt;br /&gt;
&lt;br /&gt;
= Format =&lt;br /&gt;
&lt;br /&gt;
To avoid confusion, the terms &#039;&#039;&#039;device directory / file&#039;&#039;&#039; and &#039;&#039;&#039;virtual directory / file&#039;&#039;&#039; are used with the following meanings:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Device directory / file&#039;&#039;&#039; are the real directory / file stored on SD / NAND that can be seen under path &amp;lt;code&amp;gt;nand/data/&amp;amp;lt;ID&amp;amp;gt;/extdata/&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;sdmc/Nintendo 3DS/&amp;amp;lt;ID0&amp;amp;gt;/&amp;amp;lt;ID1&amp;amp;gt;/extdata/&amp;lt;/code&amp;gt;.&lt;br /&gt;
* &#039;&#039;&#039;Virtual directory / file&#039;&#039;&#039; are directory / file stored inside extdata virtual file system, which can be seen by applications in the mounted extdata archives.&lt;br /&gt;
&lt;br /&gt;
An extdata consists of several device directories and files, which forms a file system consisting of multiple virtual directories and files.&lt;br /&gt;
&lt;br /&gt;
An extdata with ID &amp;lt;code&amp;gt;ExtdataId&amp;lt;/code&amp;gt; has the following device files:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;.../extdata/&amp;amp;lt;ExtdataID-High&amp;amp;gt;/&amp;amp;lt;ExtdataId-Low&amp;amp;gt;/Quota.dat&amp;lt;/code&amp;gt; (optional)&lt;br /&gt;
* &amp;lt;code&amp;gt;.../extdata/&amp;amp;lt;ExtdataID-High&amp;amp;gt;/&amp;amp;lt;ExtdataId-Low&amp;amp;gt;/&amp;amp;lt;SubDirID&amp;amp;gt;/&amp;amp;lt;SubFileID&amp;amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note:&lt;br /&gt;
&lt;br /&gt;
* All device files are [[DISA and DIFF|DIFF containers]]. &#039;&#039;&#039;All format description below is about the inner content of the containers&#039;&#039;&#039;. Please unwrap these files first according to the DIFF format description before reading them using the extdata format description below.&lt;br /&gt;
* &amp;lt;code&amp;gt;Quota.dat&amp;lt;/code&amp;gt; is only observed existing for NAND shared extdata.&lt;br /&gt;
* &amp;lt;code&amp;gt;&amp;amp;lt;SubDirID&amp;amp;gt;&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;&amp;amp;lt;SubFileID&amp;amp;gt;&amp;lt;/code&amp;gt; are 8-digit hex strings.&lt;br /&gt;
* Device file with &amp;lt;code&amp;gt;SubDirID = SubFileID = 00000000&amp;lt;/code&amp;gt; doesn&#039;t exist. Other ID combinations can exists.&lt;br /&gt;
* Device file with &amp;lt;code&amp;gt;SubDirID = 00000000&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;SubFileID = 00000001&amp;lt;/code&amp;gt; is the VSXE metadata file and must exist.&lt;br /&gt;
* Other files, besides &amp;lt;code&amp;gt;Quota.dat&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;00000000/00000001&amp;lt;/code&amp;gt;, are normal sub files, are these device files one-to-one correspond to virtual files. They contain raw virtual file data in the DIFF inner content.&lt;br /&gt;
* &amp;lt;code&amp;gt;SubDirID = 00000000&amp;lt;/code&amp;gt; is usually the only one device directory that can be seen. See [[#Device Directory Capacity]] for more information.&lt;br /&gt;
&lt;br /&gt;
== Quota File ==&lt;br /&gt;
&lt;br /&gt;
The inner data of &amp;lt;code&amp;gt;Quota.dat&amp;lt;/code&amp;gt; is 0x48 bytes with the following format. The file seems to limit the extdata total size.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! Offset&lt;br /&gt;
! Length&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x00&lt;br /&gt;
| 4&lt;br /&gt;
| Magic &amp;amp;quot;QUOT&amp;amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| 0x04&lt;br /&gt;
| 4&lt;br /&gt;
| Magic 0x30000&lt;br /&gt;
|-&lt;br /&gt;
| 0x08&lt;br /&gt;
| 4&lt;br /&gt;
| 0x1000, block size&lt;br /&gt;
|-&lt;br /&gt;
| 0x0C&lt;br /&gt;
| 4&lt;br /&gt;
| Always 126. Probably device directory capacity. See the [[#Device Directory Capacity]] more information.&lt;br /&gt;
|-&lt;br /&gt;
| 0x10&lt;br /&gt;
| 4&lt;br /&gt;
| Always 0?&lt;br /&gt;
|-&lt;br /&gt;
| 0x14&lt;br /&gt;
| 4&lt;br /&gt;
| Max number of blocks&lt;br /&gt;
|-&lt;br /&gt;
| 0x18&lt;br /&gt;
| 4&lt;br /&gt;
| Always 0? &lt;br /&gt;
|-&lt;br /&gt;
| 0x1C&lt;br /&gt;
| 4&lt;br /&gt;
| Free blocks remained&lt;br /&gt;
|-&lt;br /&gt;
| 0x20&lt;br /&gt;
| 4&lt;br /&gt;
| Always 0? &lt;br /&gt;
|-&lt;br /&gt;
| 0x24&lt;br /&gt;
| 4&lt;br /&gt;
| Always 0? &lt;br /&gt;
|-&lt;br /&gt;
| 0x28&lt;br /&gt;
| 4&lt;br /&gt;
| Free blocks remained + (blocks occupied by the recently mounted file, specified by the ID below (0 if recently deleted))&lt;br /&gt;
|-&lt;br /&gt;
| 0x2C&lt;br /&gt;
| 4&lt;br /&gt;
| Always 0? &lt;br /&gt;
|-&lt;br /&gt;
| 0x30&lt;br /&gt;
| 4&lt;br /&gt;
| ID of most recently mounted file. Same as the one in [[Inner_FAT#Filesystem Header]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x34&lt;br /&gt;
| 4&lt;br /&gt;
| Always 0?&lt;br /&gt;
|-&lt;br /&gt;
| 0x38&lt;br /&gt;
| 4&lt;br /&gt;
| Always 0?&lt;br /&gt;
|-&lt;br /&gt;
| 0x3C&lt;br /&gt;
| 4&lt;br /&gt;
| Always 0?&lt;br /&gt;
|-&lt;br /&gt;
| 0x40&lt;br /&gt;
| 4&lt;br /&gt;
| ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x44&lt;br /&gt;
| 4&lt;br /&gt;
| Always 0?&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Device Directory Capacity ==&lt;br /&gt;
&lt;br /&gt;
A device directory in an extdata (a &amp;lt;code&amp;gt;&amp;amp;lt;SubDirID&amp;amp;gt;&amp;lt;/code&amp;gt; directory) seems to have a maximum number of device files it can contain. For SD extdata, this maximum number seems to be hard-coded as 126. For NAND extdata, the number is probably indicated by a field in Quota.dat, which is, again, always 126 as observed. 3DS FS tries to put all device files in the device directory &amp;lt;code&amp;gt;00000000&amp;lt;/code&amp;gt; if possible, and only when more than 126 files needed to add, a second device directory &amp;lt;code&amp;gt;00000001&amp;lt;/code&amp;gt; and so on are created. However, few extdata have such amount of files to store, so the behavior lacks of use cases to confirm.&lt;br /&gt;
&lt;br /&gt;
The number 126 is probably from some kind of other capacity of 128 with &amp;lt;code&amp;gt;&amp;amp;quot;.&amp;amp;quot;&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;&amp;amp;quot;..&amp;amp;quot;&amp;lt;/code&amp;gt; entries reserved. It is theorized that this is to keep a FAT directory table, with 0x20 bytes for each entry, in one 0x1000 cluster. The motivation is unclear.&lt;br /&gt;
&lt;br /&gt;
== VSXE Filesystem ==&lt;br /&gt;
&lt;br /&gt;
This is one variant of the [[Inner FAT|FAT filesystem]]. Please refer to its page for the description of the filesystem. In general, device file &amp;lt;code&amp;gt;00000000/00000001&amp;lt;/code&amp;gt; contains the metadata of the filesystem, while other device files (except for the Quota file) contains normal sub-files&lt;br /&gt;
&lt;br /&gt;
Each non-dummy file entry corresponds to a device file. The path to the device file is generated by the following computation:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;// See previous section about this capacity&lt;br /&gt;
const uint32_t device_dir_capacity = 126;&lt;br /&gt;
&lt;br /&gt;
// entry index is the index in the file entry table, with the first dummy entry as&lt;br /&gt;
// index = 0, which is never used for a real file.&lt;br /&gt;
// file_index = 1 is reserved for the VSXE Filesystem Metadata itself, so real files&lt;br /&gt;
// started from file_index = 2.&lt;br /&gt;
uint32_t file_index = entry_index + 1;&lt;br /&gt;
&lt;br /&gt;
uint32_t SubDirID = file_index / device_dir_capacity;&lt;br /&gt;
uint32_t SubFileID = file_index % pdevice_dir_capacity;&lt;br /&gt;
&lt;br /&gt;
char extdata_path[...]; // &amp;amp;quot;.../extdata/&amp;amp;lt;ExtdataID-High&amp;amp;gt;/&amp;amp;lt;ExtdataId-Low&amp;amp;gt;&amp;amp;quot;&lt;br /&gt;
char device_path[...]; // output path&lt;br /&gt;
sprintf(device_path, &amp;amp;quot;%s/%08x/%08x&amp;amp;quot;, extdata_path, SubDirID, SubFileID);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
When mounting extdata, the unique identifier is used to match the ID stored in subfile&#039;s [[DISA and DIFF#DIFF header|DIFF header]]. If the ID doesn&#039;t match, mounting will fail.&lt;br /&gt;
&lt;br /&gt;
== Virtual File System Structure ==&lt;br /&gt;
&lt;br /&gt;
When extdata is created, these are &#039;&#039;always&#039;&#039; created regardless of whether the title actually uses them.&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;/icon&amp;lt;/code&amp;gt; This virtual file contains the extdata icon displayed in data management. This icon can only be written to by titles when creating extdata, titles would have to recreate extdata to change the icon. This file can&#039;t be read directly, instead it is read via FS:ReadExtSaveDataIcon.&lt;br /&gt;
* &amp;lt;code&amp;gt;/user/&amp;lt;/code&amp;gt; This virtual directory contains the title&#039;s actual extdata files.&lt;br /&gt;
* &amp;lt;code&amp;gt;/boss/&amp;lt;/code&amp;gt; This virtual directory can contain SpotPass content. SpotPass content can only be downloaded to this &amp;lt;code&amp;gt;/boss&amp;lt;/code&amp;gt; virtual directory.&lt;br /&gt;
&lt;br /&gt;
User extdata and SpotPass extdata use separate mount points at &amp;lt;code&amp;gt;/user&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;/boss&amp;lt;/code&amp;gt;. Therefore one mount can&#039;t access the other virtual directory, and also can&#039;t access &amp;lt;code&amp;gt;/icon&amp;lt;/code&amp;gt;.(The title&#039;s SpotPass extdata can be mounted by the title itself, if it uses SpotPass)&lt;br /&gt;
&lt;br /&gt;
Other optional but notable directories include:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;/user/ExBanner&amp;lt;/code&amp;gt; This virtual directory can optionally store extended banners. When this is available, this banner is displayed instead of the CXI ExeFS banner. &amp;lt;code&amp;gt;COMMON.bin&amp;lt;/code&amp;gt; stores the common exbanner, while &amp;lt;code&amp;gt;&amp;amp;lt;regionlang_code&amp;amp;gt;.bin&amp;lt;/code&amp;gt; stores an optional separate region/language specific banner.(regionlang_code can be &amp;amp;quot;JPN_JP&amp;amp;quot;, &amp;amp;quot;USA_EN&amp;amp;quot;, etc)&lt;br /&gt;
&lt;br /&gt;
== SD Extdata ==&lt;br /&gt;
Usually the ExtdataID low is in the format &#039;00&amp;lt;Unique ID&amp;gt;&#039;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! JPN ExtdataID&lt;br /&gt;
! USA ExtdataID&lt;br /&gt;
! EUR ExtdataID&lt;br /&gt;
! Description&lt;br /&gt;
! Extdata images&lt;br /&gt;
|-&lt;br /&gt;
| 00000082&lt;br /&gt;
| 0000008f&lt;br /&gt;
| 00000098&lt;br /&gt;
| [[Home Menu]] extdata, this contains home-menu savedata and cached icons for applications.&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| 00000200&lt;br /&gt;
| 00000210&lt;br /&gt;
| 00000220&lt;br /&gt;
| [[System_Settings|System Settings]] extdata added with [[2.0.0-2]].&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| 00000207&lt;br /&gt;
| 00000217&lt;br /&gt;
| 00000227&lt;br /&gt;
| [[Mii Maker]], contains an ExBanner&lt;br /&gt;
| [https://dl.dropbox.com/u/20520664/extdata00000217.zip cleartext]&lt;br /&gt;
|-&lt;br /&gt;
| 00000208&lt;br /&gt;
| 00000218&lt;br /&gt;
| 00000228&lt;br /&gt;
| Streetpass Mii Plaza&lt;br /&gt;
| 11 mb big!&lt;br /&gt;
|-&lt;br /&gt;
| 00000209&lt;br /&gt;
| 00000219&lt;br /&gt;
| 00000229&lt;br /&gt;
| [[eShop]], contains store music in AAC format.&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| 0000020b&lt;br /&gt;
| 0000021b&lt;br /&gt;
| 0000022b&lt;br /&gt;
| Nintendo Zone&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| 0000020d&lt;br /&gt;
| 0000021d&lt;br /&gt;
| 0000022d&lt;br /&gt;
| Face Raiders, likely contains an ExBanner&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| 000002cc&lt;br /&gt;
| 000002cd&lt;br /&gt;
| 000002ce&lt;br /&gt;
| [[Home Menu]] theme&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| ?&lt;br /&gt;
| 000004aa&lt;br /&gt;
| 000004ab&lt;br /&gt;
| Nintendo Video Extra Data&lt;br /&gt;
This is where the video files are stored, and [[Nintendo_Video|includes]] the thumbnail, the description, and possibly some checksum info in each video file stored in the extdata images. There are always 9 files within the subdirectory &amp;quot;00000000&amp;quot; of this folder, even without any videos downloaded. The files are &amp;quot;00000001&amp;quot; - &amp;quot;00000009&amp;quot;, and &amp;quot;00000003&amp;quot; - &amp;quot;00000008&amp;quot; have the same filesize of 50.7 MB. It is possible to restore the older videos by overwriting all the files within this directory. Provided of course you have made a backup of the files before hand, by copying all the files within this directory to your computer. As far I&#039;m aware its not possible to mix and match the files in order to get certain videos in one grouping, ie. having all 3 Zelda orchestral recordings in one group of 4 Nintendo videos.&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
|00000306&lt;br /&gt;
|00000308&lt;br /&gt;
|00000307&lt;br /&gt;
|Mario Kart 7&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
| 0000030b&lt;br /&gt;
| 0000030d&lt;br /&gt;
| 0000030c&lt;br /&gt;
| Nintendogs + Cats&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| 00000326&lt;br /&gt;
| 00000326&lt;br /&gt;
| 00000326&lt;br /&gt;
| Pokédex 3D&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| 00000305&lt;br /&gt;
| 0000032d&lt;br /&gt;
| 0000033c&lt;br /&gt;
| Super Street Fighter IV 3D&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| 00000328&lt;br /&gt;
| 00000358&lt;br /&gt;
| 0000033b&lt;br /&gt;
| Ridge Racer 3D&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| ?&lt;br /&gt;
| 0000034d&lt;br /&gt;
| 00000402&lt;br /&gt;
| Samurai Warriors Chronicles&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| ?&lt;br /&gt;
| 0000034f&lt;br /&gt;
| 0000038a&lt;br /&gt;
| Dead or Alive Dimensions&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| 00000481&lt;br /&gt;
| N/A&lt;br /&gt;
| N/A&lt;br /&gt;
| Monster Hunter Tri G (Download-Quests)&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| ?&lt;br /&gt;
| 00000517&lt;br /&gt;
| 00000518&lt;br /&gt;
| Swapnote&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| 0000055d&lt;br /&gt;
| 0000055d&lt;br /&gt;
| 0000055d&lt;br /&gt;
| Pokémon X&amp;lt;br&amp;gt;Pokémon Y&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| ?&lt;br /&gt;
| 00000725&lt;br /&gt;
| 00000724&lt;br /&gt;
| Ambassador Certificate&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| ?&lt;br /&gt;
| ?&lt;br /&gt;
| 000007af&lt;br /&gt;
| New Super Mario Bros. 2&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| ?&lt;br /&gt;
| 00000863&lt;br /&gt;
| 00000864&lt;br /&gt;
| Animal Crossing: New Leaf&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| ?&lt;br /&gt;
| 00000a85&lt;br /&gt;
| 00000a86&lt;br /&gt;
| Professor Layton and the Miracle Mask&amp;lt;br&amp;gt;Professor Layton and the Azran Legacy&lt;br /&gt;
German Version ExtdataID is 00000a87&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| ?&lt;br /&gt;
| ?&lt;br /&gt;
| 00000b4f&lt;br /&gt;
| Fullblox / Crashmo&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| ?&lt;br /&gt;
| ?&lt;br /&gt;
| 00000ba9&lt;br /&gt;
| Pokémon Mystery Dungeon: Gates to Infinity&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| ?&lt;br /&gt;
| ?&lt;br /&gt;
| 00000c24&lt;br /&gt;
| Denpa men&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| 00000c73&lt;br /&gt;
| 00000c73&lt;br /&gt;
| 00000c73&lt;br /&gt;
| Save Data Transfer Tool&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| ?&lt;br /&gt;
| ?&lt;br /&gt;
| 00000d9a&lt;br /&gt;
| Donkey Kong Country™&amp;lt;br&amp;gt;Returns 3D: Trailer&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| ?&lt;br /&gt;
| ?&lt;br /&gt;
| 00000ea6&lt;br /&gt;
| Etrian Odyssey IV&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| ?&lt;br /&gt;
| 00000edf&lt;br /&gt;
| 00000ee0&lt;br /&gt;
| Super Smash Bros. for Nintendo 3DS&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| ?&lt;br /&gt;
| 00000f14&lt;br /&gt;
| 00000f1e&lt;br /&gt;
| Phoenix Wright: Ace Attorney - Dual Destinies&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| ?&lt;br /&gt;
| 00001007&lt;br /&gt;
| 00001005&lt;br /&gt;
| Professor Layton vs Phoenix Wright: Ace Attorney&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| ?&lt;br /&gt;
| ?&lt;br /&gt;
| 00001062&lt;br /&gt;
| Nintendo Pocket Football Club&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| ?&lt;br /&gt;
| ?&lt;br /&gt;
| 0000111c&lt;br /&gt;
| Yoshi&#039;s New Island&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| ?&lt;br /&gt;
| ?&lt;br /&gt;
| 00001131&lt;br /&gt;
| Fantasy Life&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| 000011c5&lt;br /&gt;
| 000011c5&lt;br /&gt;
| 000011c5&lt;br /&gt;
| Pokémon Omega Ruby&amp;lt;br&amp;gt;Pokémon Alpha Sapphire&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| ?&lt;br /&gt;
| ?&lt;br /&gt;
| 000012ca&lt;br /&gt;
| Mario vs. Donkey Kong: Tipping Stars&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| ?&lt;br /&gt;
| ?&lt;br /&gt;
| 00001499&lt;br /&gt;
| Korg DSN-12&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| ?&lt;br /&gt;
| ?&lt;br /&gt;
| 000014f2&lt;br /&gt;
| Animal Crossing: Happy Home Designer&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| 000014d1&lt;br /&gt;
| 000014d1&lt;br /&gt;
| 000014d1&lt;br /&gt;
| [[Home Menu]] badge&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| ?&lt;br /&gt;
| ?&lt;br /&gt;
| 00001632&lt;br /&gt;
| Fullblox / Stretchmo&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| ?&lt;br /&gt;
| ?&lt;br /&gt;
| 00001646&lt;br /&gt;
| Pokémon Rumble World&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| 00001648&lt;br /&gt;
| 00001648&lt;br /&gt;
| 00001648&lt;br /&gt;
| Pokémon Sun&amp;lt;br&amp;gt;Pokémon Moon&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| 0000165c&lt;br /&gt;
| 0000165c&lt;br /&gt;
| 0000165c&lt;br /&gt;
| [[Home Menu]] saved theme layouts&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| ?&lt;br /&gt;
| ?&lt;br /&gt;
| 00001678&lt;br /&gt;
| Yo-kai Watch&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| ?&lt;br /&gt;
| ?&lt;br /&gt;
| 000018fa&lt;br /&gt;
| Phoenix Wright: Ace Attorney - Spirit of Justice&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| ?&lt;br /&gt;
| ?&lt;br /&gt;
| 0000198f&lt;br /&gt;
| Animal Crossing: New Leaf - Welcome amiibo&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
| ?&lt;br /&gt;
| ?&lt;br /&gt;
| 00001a05&lt;br /&gt;
| Super Mario Maker&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| ?&lt;br /&gt;
| ?&lt;br /&gt;
| 00001a2e&lt;br /&gt;
| Swapdoodle&lt;br /&gt;
| &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== NAND Shared Extdata ==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
!  ExtdataID&lt;br /&gt;
!  Description&lt;br /&gt;
|-&lt;br /&gt;
| 0xe0000000&lt;br /&gt;
| Home Menu attempts to open this archive during boot, if [[FS:OpenArchive]] doesn&#039;t return an error Home Menu seems to then launch the [[System Transfer]] application. Home Menu doesn&#039;t actually use this archive at all except for checking whether it exists.&lt;br /&gt;
|-&lt;br /&gt;
|  0xf0000001&lt;br /&gt;
|  NAND JPEG/MPO files and phtcache.bin from the camera application are stored here. This also contains UploadData.dat.&lt;br /&gt;
|-&lt;br /&gt;
|  0xf0000002&lt;br /&gt;
|  NAND M4A files from the sound application are stored here&lt;br /&gt;
|-&lt;br /&gt;
|  0xf0000009&lt;br /&gt;
|  Used for [[BOSS_Services|SpotPass]] content storage for [[News_Services|notifications]].&lt;br /&gt;
|-&lt;br /&gt;
|  0xf000000b&lt;br /&gt;
|  Contains idb.dat, idbt.dat, gamecoin.dat, ubll.lst, CFL_DB.dat, and CFL_OldDB.dat. These files contain cleartext [[Mii_Maker|Miis]] and some data relating (including cached ICN data) to Play/Usage Records.&lt;br /&gt;
|-&lt;br /&gt;
|  0xf000000c&lt;br /&gt;
|  Contains bashotorya.dat and bashotorya2.dat.&lt;br /&gt;
|-&lt;br /&gt;
|  0xf000000d&lt;br /&gt;
|  Home Menu SpotPass content data [[BOSS_Services|storage]].&lt;br /&gt;
|-&lt;br /&gt;
|  0xf000000e&lt;br /&gt;
|  Contains [[VersionList|versionlist.dat]], used by Home Menu for the software update notification added with [[7.0.0-13]].&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Shared Extdata 0xf000000b gamecoin.dat ====&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;
| 0x4&lt;br /&gt;
| Magic number: 0x4F00&lt;br /&gt;
|-&lt;br /&gt;
| 0x4&lt;br /&gt;
| 0x2&lt;br /&gt;
| Total Play Coins&lt;br /&gt;
|-&lt;br /&gt;
| 0x6&lt;br /&gt;
| 0x2&lt;br /&gt;
| Total Play Coins obtained on the date stored below. When the below date does not match the current date, this field is reset to zero, then the date(and other fields) are updated. Once this value is &amp;gt;=10, no more Play Coins can be obtained until the current date changes.&lt;br /&gt;
|-&lt;br /&gt;
| 0x8&lt;br /&gt;
| 0x4&lt;br /&gt;
| Total step [[PTM:GetTotalStepCount|count]] at the time a new Play Coin was obtained.&lt;br /&gt;
|-&lt;br /&gt;
| 0xC&lt;br /&gt;
| 0x4&lt;br /&gt;
| Step count for the day the last Play Coin was obtained, for that day&#039;s step count(same as the step count displayed by home-menu when this file was updated).&lt;br /&gt;
|-&lt;br /&gt;
| 0x10&lt;br /&gt;
| 0x2&lt;br /&gt;
| Year&lt;br /&gt;
|-&lt;br /&gt;
| 0x12&lt;br /&gt;
| 0x1&lt;br /&gt;
| Month&lt;br /&gt;
|-&lt;br /&gt;
| 0x13&lt;br /&gt;
| 0x1&lt;br /&gt;
| Day&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The above date stores the last time new Play Coin(s) were obtained. The contents of this file is updated by home-menu. [[PTM:GetTotalStepCount]] is not checked constantly, after home-menu boot this is only checked when waking from sleep-mode. Each time home-menu updates the contents of this file, home-menu will set the Play Coin total to 300 if it&#039;s higher than the 300 Play Coin limit.&lt;br /&gt;
&lt;br /&gt;
[[Home Menu]] loads this file / opens this archive during [[Home Menu|startup]]. When accessing this file fails, like when the file/archive is corrupted(or at least on older system-versions), the result is a brick due to Home Menu using [[SVC|svcBreak]]. [[User:Yellows8|Yellows8]] bricked a 3DS this way due to corruption via invalid [[FSFile:Write]] flush flags. When opening this extdata archive(0xf000000b) fails, Home Menu executes svcBreak.&lt;br /&gt;
&lt;br /&gt;
==== Shared Extdata 0xf000000b ubll.lst ====&lt;br /&gt;
List of blocked users.&lt;br /&gt;
&lt;br /&gt;
Empty space is filled with 0xC-long sequences of 00 00 ... 07&lt;br /&gt;
&lt;br /&gt;
=== Tools ===&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/wwylele/3ds-save-tool 3ds-save-tool] - Extract/verifies extdata&lt;/div&gt;</summary>
		<author><name>Wwylele</name></author>
	</entry>
	<entry>
		<id>https://www.3dbrew.org/w/index.php?title=Extdata&amp;diff=20983</id>
		<title>Extdata</title>
		<link rel="alternate" type="text/html" href="https://www.3dbrew.org/w/index.php?title=Extdata&amp;diff=20983"/>
		<updated>2019-05-28T12:46:52Z</updated>

		<summary type="html">&lt;p&gt;Wwylele: /* Quota File */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This page describes the format and encryption of extdata, &amp;amp;quot;extra data&amp;amp;quot; stored on SD card and NAND, at:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;nand/data/&amp;amp;lt;ID&amp;amp;gt;/extdata/&amp;amp;lt;ExtdataID-High&amp;amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;sdmc/Nintendo 3DS/&amp;amp;lt;ID0&amp;amp;gt;/&amp;amp;lt;ID1&amp;amp;gt;/extdata/&amp;amp;lt;ExtdataID-High&amp;amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
ExtdataID-High is always 00000000 for SD, and always 00048000 for NAND. Regular apps can only mount SD extdata using the same extdataID which is stored in the CXI exheader. Therefore, regular apps which have the exheader extdataID set to zero can&#039;t use extdata. This restriction doesn&#039;t apply for shared extdata with extdataID high bitmask 0x48000 stored on NAND. System apps with a certain access right can mount arbitrary extdata. All NAND extdata is shared extdata, while all SD extdata is normal extdata.&lt;br /&gt;
&lt;br /&gt;
All data in this page is little-endian. All &amp;amp;quot;unused / padding&amp;amp;quot; fields can contain uninitialized data unless otherwise specified.&lt;br /&gt;
&lt;br /&gt;
= Format =&lt;br /&gt;
&lt;br /&gt;
To avoid confusion, the terms &#039;&#039;&#039;device directory / file&#039;&#039;&#039; and &#039;&#039;&#039;virtual directory / file&#039;&#039;&#039; are used with the following meanings:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Device directory / file&#039;&#039;&#039; are the real directory / file stored on SD / NAND that can be seen under path &amp;lt;code&amp;gt;nand/data/&amp;amp;lt;ID&amp;amp;gt;/extdata/&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;sdmc/Nintendo 3DS/&amp;amp;lt;ID0&amp;amp;gt;/&amp;amp;lt;ID1&amp;amp;gt;/extdata/&amp;lt;/code&amp;gt;.&lt;br /&gt;
* &#039;&#039;&#039;Virtual directory / file&#039;&#039;&#039; are directory / file stored inside extdata virtual file system, which can be seen by applications in the mounted extdata archives.&lt;br /&gt;
&lt;br /&gt;
An extdata consists of several device directories and files, which forms a file system consisting of multiple virtual directories and files.&lt;br /&gt;
&lt;br /&gt;
An extdata with ID &amp;lt;code&amp;gt;ExtdataId&amp;lt;/code&amp;gt; has the following device files:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;.../extdata/&amp;amp;lt;ExtdataID-High&amp;amp;gt;/&amp;amp;lt;ExtdataId-Low&amp;amp;gt;/Quota.dat&amp;lt;/code&amp;gt; (optional)&lt;br /&gt;
* &amp;lt;code&amp;gt;.../extdata/&amp;amp;lt;ExtdataID-High&amp;amp;gt;/&amp;amp;lt;ExtdataId-Low&amp;amp;gt;/&amp;amp;lt;SubDirID&amp;amp;gt;/&amp;amp;lt;SubFileID&amp;amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note:&lt;br /&gt;
&lt;br /&gt;
* All device files are [[DISA and DIFF|DIFF containers]]. &#039;&#039;&#039;All format description below is about the inner content of the containers&#039;&#039;&#039;. Please unwrap these files first according to the DIFF format description before reading them using the extdata format description below.&lt;br /&gt;
* &amp;lt;code&amp;gt;Quota.dat&amp;lt;/code&amp;gt; is only observed existing for NAND shared extdata.&lt;br /&gt;
* &amp;lt;code&amp;gt;&amp;amp;lt;SubDirID&amp;amp;gt;&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;&amp;amp;lt;SubFileID&amp;amp;gt;&amp;lt;/code&amp;gt; are 8-digit hex strings.&lt;br /&gt;
* Device file with &amp;lt;code&amp;gt;SubDirID = SubFileID = 00000000&amp;lt;/code&amp;gt; doesn&#039;t exist. Other ID combinations can exists.&lt;br /&gt;
* Device file with &amp;lt;code&amp;gt;SubDirID = 00000000&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;SubFileID = 00000001&amp;lt;/code&amp;gt; is the VSXE metadata file and must exist.&lt;br /&gt;
* Other files, besides &amp;lt;code&amp;gt;Quota.dat&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;00000000/00000001&amp;lt;/code&amp;gt;, are normal sub files, are these device files one-to-one correspond to virtual files. They contain raw virtual file data in the DIFF inner content.&lt;br /&gt;
* &amp;lt;code&amp;gt;SubDirID = 00000000&amp;lt;/code&amp;gt; is usually the only one device directory that can be seen. See [[#Device Directory Capacity]] for more information.&lt;br /&gt;
&lt;br /&gt;
== Quota File ==&lt;br /&gt;
&lt;br /&gt;
The inner data of &amp;lt;code&amp;gt;Quota.dat&amp;lt;/code&amp;gt; is 0x48 bytes with the following format. The file seems to limit the extdata total size.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! Offset&lt;br /&gt;
! Length&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x00&lt;br /&gt;
| 4&lt;br /&gt;
| Magic &amp;amp;quot;QUOT&amp;amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| 0x04&lt;br /&gt;
| 4&lt;br /&gt;
| Magic 0x30000&lt;br /&gt;
|-&lt;br /&gt;
| 0x08&lt;br /&gt;
| 4&lt;br /&gt;
| 0x1000, block size&lt;br /&gt;
|-&lt;br /&gt;
| 0x0C&lt;br /&gt;
| 4&lt;br /&gt;
| Always 126. Probably device directory capacity. See the [[#Device Directory Capacity]] more information.&lt;br /&gt;
|-&lt;br /&gt;
| 0x10&lt;br /&gt;
| 4&lt;br /&gt;
| Always 0?&lt;br /&gt;
|-&lt;br /&gt;
| 0x14&lt;br /&gt;
| 4&lt;br /&gt;
| Max number of blocks&lt;br /&gt;
|-&lt;br /&gt;
| 0x18&lt;br /&gt;
| 4&lt;br /&gt;
| Always 0? &lt;br /&gt;
|-&lt;br /&gt;
| 0x1C&lt;br /&gt;
| 4&lt;br /&gt;
| Free blocks remained&lt;br /&gt;
|-&lt;br /&gt;
| 0x20&lt;br /&gt;
| 4&lt;br /&gt;
| Always 0? &lt;br /&gt;
|-&lt;br /&gt;
| 0x24&lt;br /&gt;
| 4&lt;br /&gt;
| Always 0? &lt;br /&gt;
|-&lt;br /&gt;
| 0x28&lt;br /&gt;
| 4&lt;br /&gt;
| Equal or greater than the free blocks number?&lt;br /&gt;
|-&lt;br /&gt;
| 0x2C&lt;br /&gt;
| 4&lt;br /&gt;
| Always 0? &lt;br /&gt;
|-&lt;br /&gt;
| 0x30&lt;br /&gt;
| 4&lt;br /&gt;
| ID of most recently mounted Extdata image. Same as the one in [[Inner_FAT#Filesystem Header]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x34&lt;br /&gt;
| 4&lt;br /&gt;
| Always 0?&lt;br /&gt;
|-&lt;br /&gt;
| 0x38&lt;br /&gt;
| 4&lt;br /&gt;
| Always 0?&lt;br /&gt;
|-&lt;br /&gt;
| 0x3C&lt;br /&gt;
| 4&lt;br /&gt;
| Always 0?&lt;br /&gt;
|-&lt;br /&gt;
| 0x40&lt;br /&gt;
| 4&lt;br /&gt;
| ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x44&lt;br /&gt;
| 4&lt;br /&gt;
| Always 0?&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Device Directory Capacity ==&lt;br /&gt;
&lt;br /&gt;
A device directory in an extdata (a &amp;lt;code&amp;gt;&amp;amp;lt;SubDirID&amp;amp;gt;&amp;lt;/code&amp;gt; directory) seems to have a maximum number of device files it can contain. For SD extdata, this maximum number seems to be hard-coded as 126. For NAND extdata, the number is probably indicated by a field in Quota.dat, which is, again, always 126 as observed. 3DS FS tries to put all device files in the device directory &amp;lt;code&amp;gt;00000000&amp;lt;/code&amp;gt; if possible, and only when more than 126 files needed to add, a second device directory &amp;lt;code&amp;gt;00000001&amp;lt;/code&amp;gt; and so on are created. However, few extdata have such amount of files to store, so the behavior lacks of use cases to confirm.&lt;br /&gt;
&lt;br /&gt;
The number 126 is probably from some kind of other capacity of 128 with &amp;lt;code&amp;gt;&amp;amp;quot;.&amp;amp;quot;&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;&amp;amp;quot;..&amp;amp;quot;&amp;lt;/code&amp;gt; entries reserved. It is theorized that this is to keep a FAT directory table, with 0x20 bytes for each entry, in one 0x1000 cluster. The motivation is unclear.&lt;br /&gt;
&lt;br /&gt;
== VSXE Filesystem ==&lt;br /&gt;
&lt;br /&gt;
This is one variant of the [[Inner FAT|FAT filesystem]]. Please refer to its page for the description of the filesystem. In general, device file &amp;lt;code&amp;gt;00000000/00000001&amp;lt;/code&amp;gt; contains the metadata of the filesystem, while other device files (except for the Quota file) contains normal sub-files&lt;br /&gt;
&lt;br /&gt;
Each non-dummy file entry corresponds to a device file. The path to the device file is generated by the following computation:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;// See previous section about this capacity&lt;br /&gt;
const uint32_t device_dir_capacity = 126;&lt;br /&gt;
&lt;br /&gt;
// entry index is the index in the file entry table, with the first dummy entry as&lt;br /&gt;
// index = 0, which is never used for a real file.&lt;br /&gt;
// file_index = 1 is reserved for the VSXE Filesystem Metadata itself, so real files&lt;br /&gt;
// started from file_index = 2.&lt;br /&gt;
uint32_t file_index = entry_index + 1;&lt;br /&gt;
&lt;br /&gt;
uint32_t SubDirID = file_index / device_dir_capacity;&lt;br /&gt;
uint32_t SubFileID = file_index % pdevice_dir_capacity;&lt;br /&gt;
&lt;br /&gt;
char extdata_path[...]; // &amp;amp;quot;.../extdata/&amp;amp;lt;ExtdataID-High&amp;amp;gt;/&amp;amp;lt;ExtdataId-Low&amp;amp;gt;&amp;amp;quot;&lt;br /&gt;
char device_path[...]; // output path&lt;br /&gt;
sprintf(device_path, &amp;amp;quot;%s/%08x/%08x&amp;amp;quot;, extdata_path, SubDirID, SubFileID);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
When mounting extdata, the unique identifier is used to match the ID stored in subfile&#039;s [[DISA and DIFF#DIFF header|DIFF header]]. If the ID doesn&#039;t match, mounting will fail.&lt;br /&gt;
&lt;br /&gt;
== Virtual File System Structure ==&lt;br /&gt;
&lt;br /&gt;
When extdata is created, these are &#039;&#039;always&#039;&#039; created regardless of whether the title actually uses them.&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;/icon&amp;lt;/code&amp;gt; This virtual file contains the extdata icon displayed in data management. This icon can only be written to by titles when creating extdata, titles would have to recreate extdata to change the icon. This file can&#039;t be read directly, instead it is read via FS:ReadExtSaveDataIcon.&lt;br /&gt;
* &amp;lt;code&amp;gt;/user/&amp;lt;/code&amp;gt; This virtual directory contains the title&#039;s actual extdata files.&lt;br /&gt;
* &amp;lt;code&amp;gt;/boss/&amp;lt;/code&amp;gt; This virtual directory can contain SpotPass content. SpotPass content can only be downloaded to this &amp;lt;code&amp;gt;/boss&amp;lt;/code&amp;gt; virtual directory.&lt;br /&gt;
&lt;br /&gt;
User extdata and SpotPass extdata use separate mount points at &amp;lt;code&amp;gt;/user&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;/boss&amp;lt;/code&amp;gt;. Therefore one mount can&#039;t access the other virtual directory, and also can&#039;t access &amp;lt;code&amp;gt;/icon&amp;lt;/code&amp;gt;.(The title&#039;s SpotPass extdata can be mounted by the title itself, if it uses SpotPass)&lt;br /&gt;
&lt;br /&gt;
Other optional but notable directories include:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;/user/ExBanner&amp;lt;/code&amp;gt; This virtual directory can optionally store extended banners. When this is available, this banner is displayed instead of the CXI ExeFS banner. &amp;lt;code&amp;gt;COMMON.bin&amp;lt;/code&amp;gt; stores the common exbanner, while &amp;lt;code&amp;gt;&amp;amp;lt;regionlang_code&amp;amp;gt;.bin&amp;lt;/code&amp;gt; stores an optional separate region/language specific banner.(regionlang_code can be &amp;amp;quot;JPN_JP&amp;amp;quot;, &amp;amp;quot;USA_EN&amp;amp;quot;, etc)&lt;br /&gt;
&lt;br /&gt;
== SD Extdata ==&lt;br /&gt;
Usually the ExtdataID low is in the format &#039;00&amp;lt;Unique ID&amp;gt;&#039;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! JPN ExtdataID&lt;br /&gt;
! USA ExtdataID&lt;br /&gt;
! EUR ExtdataID&lt;br /&gt;
! Description&lt;br /&gt;
! Extdata images&lt;br /&gt;
|-&lt;br /&gt;
| 00000082&lt;br /&gt;
| 0000008f&lt;br /&gt;
| 00000098&lt;br /&gt;
| [[Home Menu]] extdata, this contains home-menu savedata and cached icons for applications.&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| 00000200&lt;br /&gt;
| 00000210&lt;br /&gt;
| 00000220&lt;br /&gt;
| [[System_Settings|System Settings]] extdata added with [[2.0.0-2]].&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| 00000207&lt;br /&gt;
| 00000217&lt;br /&gt;
| 00000227&lt;br /&gt;
| [[Mii Maker]], contains an ExBanner&lt;br /&gt;
| [https://dl.dropbox.com/u/20520664/extdata00000217.zip cleartext]&lt;br /&gt;
|-&lt;br /&gt;
| 00000208&lt;br /&gt;
| 00000218&lt;br /&gt;
| 00000228&lt;br /&gt;
| Streetpass Mii Plaza&lt;br /&gt;
| 11 mb big!&lt;br /&gt;
|-&lt;br /&gt;
| 00000209&lt;br /&gt;
| 00000219&lt;br /&gt;
| 00000229&lt;br /&gt;
| [[eShop]], contains store music in AAC format.&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| 0000020b&lt;br /&gt;
| 0000021b&lt;br /&gt;
| 0000022b&lt;br /&gt;
| Nintendo Zone&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| 0000020d&lt;br /&gt;
| 0000021d&lt;br /&gt;
| 0000022d&lt;br /&gt;
| Face Raiders, likely contains an ExBanner&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| 000002cc&lt;br /&gt;
| 000002cd&lt;br /&gt;
| 000002ce&lt;br /&gt;
| [[Home Menu]] theme&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| ?&lt;br /&gt;
| 000004aa&lt;br /&gt;
| 000004ab&lt;br /&gt;
| Nintendo Video Extra Data&lt;br /&gt;
This is where the video files are stored, and [[Nintendo_Video|includes]] the thumbnail, the description, and possibly some checksum info in each video file stored in the extdata images. There are always 9 files within the subdirectory &amp;quot;00000000&amp;quot; of this folder, even without any videos downloaded. The files are &amp;quot;00000001&amp;quot; - &amp;quot;00000009&amp;quot;, and &amp;quot;00000003&amp;quot; - &amp;quot;00000008&amp;quot; have the same filesize of 50.7 MB. It is possible to restore the older videos by overwriting all the files within this directory. Provided of course you have made a backup of the files before hand, by copying all the files within this directory to your computer. As far I&#039;m aware its not possible to mix and match the files in order to get certain videos in one grouping, ie. having all 3 Zelda orchestral recordings in one group of 4 Nintendo videos.&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
|00000306&lt;br /&gt;
|00000308&lt;br /&gt;
|00000307&lt;br /&gt;
|Mario Kart 7&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
| 0000030b&lt;br /&gt;
| 0000030d&lt;br /&gt;
| 0000030c&lt;br /&gt;
| Nintendogs + Cats&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| 00000326&lt;br /&gt;
| 00000326&lt;br /&gt;
| 00000326&lt;br /&gt;
| Pokédex 3D&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| 00000305&lt;br /&gt;
| 0000032d&lt;br /&gt;
| 0000033c&lt;br /&gt;
| Super Street Fighter IV 3D&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| 00000328&lt;br /&gt;
| 00000358&lt;br /&gt;
| 0000033b&lt;br /&gt;
| Ridge Racer 3D&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| ?&lt;br /&gt;
| 0000034d&lt;br /&gt;
| 00000402&lt;br /&gt;
| Samurai Warriors Chronicles&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| ?&lt;br /&gt;
| 0000034f&lt;br /&gt;
| 0000038a&lt;br /&gt;
| Dead or Alive Dimensions&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| 00000481&lt;br /&gt;
| N/A&lt;br /&gt;
| N/A&lt;br /&gt;
| Monster Hunter Tri G (Download-Quests)&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| ?&lt;br /&gt;
| 00000517&lt;br /&gt;
| 00000518&lt;br /&gt;
| Swapnote&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| 0000055d&lt;br /&gt;
| 0000055d&lt;br /&gt;
| 0000055d&lt;br /&gt;
| Pokémon X&amp;lt;br&amp;gt;Pokémon Y&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| ?&lt;br /&gt;
| 00000725&lt;br /&gt;
| 00000724&lt;br /&gt;
| Ambassador Certificate&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| ?&lt;br /&gt;
| ?&lt;br /&gt;
| 000007af&lt;br /&gt;
| New Super Mario Bros. 2&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| ?&lt;br /&gt;
| 00000863&lt;br /&gt;
| 00000864&lt;br /&gt;
| Animal Crossing: New Leaf&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| ?&lt;br /&gt;
| 00000a85&lt;br /&gt;
| 00000a86&lt;br /&gt;
| Professor Layton and the Miracle Mask&amp;lt;br&amp;gt;Professor Layton and the Azran Legacy&lt;br /&gt;
German Version ExtdataID is 00000a87&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| ?&lt;br /&gt;
| ?&lt;br /&gt;
| 00000b4f&lt;br /&gt;
| Fullblox / Crashmo&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| ?&lt;br /&gt;
| ?&lt;br /&gt;
| 00000ba9&lt;br /&gt;
| Pokémon Mystery Dungeon: Gates to Infinity&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| ?&lt;br /&gt;
| ?&lt;br /&gt;
| 00000c24&lt;br /&gt;
| Denpa men&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| 00000c73&lt;br /&gt;
| 00000c73&lt;br /&gt;
| 00000c73&lt;br /&gt;
| Save Data Transfer Tool&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| ?&lt;br /&gt;
| ?&lt;br /&gt;
| 00000d9a&lt;br /&gt;
| Donkey Kong Country™&amp;lt;br&amp;gt;Returns 3D: Trailer&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| ?&lt;br /&gt;
| ?&lt;br /&gt;
| 00000ea6&lt;br /&gt;
| Etrian Odyssey IV&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| ?&lt;br /&gt;
| 00000edf&lt;br /&gt;
| 00000ee0&lt;br /&gt;
| Super Smash Bros. for Nintendo 3DS&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| ?&lt;br /&gt;
| 00000f14&lt;br /&gt;
| 00000f1e&lt;br /&gt;
| Phoenix Wright: Ace Attorney - Dual Destinies&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| ?&lt;br /&gt;
| 00001007&lt;br /&gt;
| 00001005&lt;br /&gt;
| Professor Layton vs Phoenix Wright: Ace Attorney&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| ?&lt;br /&gt;
| ?&lt;br /&gt;
| 00001062&lt;br /&gt;
| Nintendo Pocket Football Club&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| ?&lt;br /&gt;
| ?&lt;br /&gt;
| 0000111c&lt;br /&gt;
| Yoshi&#039;s New Island&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| ?&lt;br /&gt;
| ?&lt;br /&gt;
| 00001131&lt;br /&gt;
| Fantasy Life&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| 000011c5&lt;br /&gt;
| 000011c5&lt;br /&gt;
| 000011c5&lt;br /&gt;
| Pokémon Omega Ruby&amp;lt;br&amp;gt;Pokémon Alpha Sapphire&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| ?&lt;br /&gt;
| ?&lt;br /&gt;
| 000012ca&lt;br /&gt;
| Mario vs. Donkey Kong: Tipping Stars&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| ?&lt;br /&gt;
| ?&lt;br /&gt;
| 00001499&lt;br /&gt;
| Korg DSN-12&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| ?&lt;br /&gt;
| ?&lt;br /&gt;
| 000014f2&lt;br /&gt;
| Animal Crossing: Happy Home Designer&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| 000014d1&lt;br /&gt;
| 000014d1&lt;br /&gt;
| 000014d1&lt;br /&gt;
| [[Home Menu]] badge&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| ?&lt;br /&gt;
| ?&lt;br /&gt;
| 00001632&lt;br /&gt;
| Fullblox / Stretchmo&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| ?&lt;br /&gt;
| ?&lt;br /&gt;
| 00001646&lt;br /&gt;
| Pokémon Rumble World&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| 00001648&lt;br /&gt;
| 00001648&lt;br /&gt;
| 00001648&lt;br /&gt;
| Pokémon Sun&amp;lt;br&amp;gt;Pokémon Moon&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| 0000165c&lt;br /&gt;
| 0000165c&lt;br /&gt;
| 0000165c&lt;br /&gt;
| [[Home Menu]] saved theme layouts&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| ?&lt;br /&gt;
| ?&lt;br /&gt;
| 00001678&lt;br /&gt;
| Yo-kai Watch&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| ?&lt;br /&gt;
| ?&lt;br /&gt;
| 000018fa&lt;br /&gt;
| Phoenix Wright: Ace Attorney - Spirit of Justice&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| ?&lt;br /&gt;
| ?&lt;br /&gt;
| 0000198f&lt;br /&gt;
| Animal Crossing: New Leaf - Welcome amiibo&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
| ?&lt;br /&gt;
| ?&lt;br /&gt;
| 00001a05&lt;br /&gt;
| Super Mario Maker&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| ?&lt;br /&gt;
| ?&lt;br /&gt;
| 00001a2e&lt;br /&gt;
| Swapdoodle&lt;br /&gt;
| &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== NAND Shared Extdata ==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
!  ExtdataID&lt;br /&gt;
!  Description&lt;br /&gt;
|-&lt;br /&gt;
| 0xe0000000&lt;br /&gt;
| Home Menu attempts to open this archive during boot, if [[FS:OpenArchive]] doesn&#039;t return an error Home Menu seems to then launch the [[System Transfer]] application. Home Menu doesn&#039;t actually use this archive at all except for checking whether it exists.&lt;br /&gt;
|-&lt;br /&gt;
|  0xf0000001&lt;br /&gt;
|  NAND JPEG/MPO files and phtcache.bin from the camera application are stored here. This also contains UploadData.dat.&lt;br /&gt;
|-&lt;br /&gt;
|  0xf0000002&lt;br /&gt;
|  NAND M4A files from the sound application are stored here&lt;br /&gt;
|-&lt;br /&gt;
|  0xf0000009&lt;br /&gt;
|  Used for [[BOSS_Services|SpotPass]] content storage for [[News_Services|notifications]].&lt;br /&gt;
|-&lt;br /&gt;
|  0xf000000b&lt;br /&gt;
|  Contains idb.dat, idbt.dat, gamecoin.dat, ubll.lst, CFL_DB.dat, and CFL_OldDB.dat. These files contain cleartext [[Mii_Maker|Miis]] and some data relating (including cached ICN data) to Play/Usage Records.&lt;br /&gt;
|-&lt;br /&gt;
|  0xf000000c&lt;br /&gt;
|  Contains bashotorya.dat and bashotorya2.dat.&lt;br /&gt;
|-&lt;br /&gt;
|  0xf000000d&lt;br /&gt;
|  Home Menu SpotPass content data [[BOSS_Services|storage]].&lt;br /&gt;
|-&lt;br /&gt;
|  0xf000000e&lt;br /&gt;
|  Contains [[VersionList|versionlist.dat]], used by Home Menu for the software update notification added with [[7.0.0-13]].&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Shared Extdata 0xf000000b gamecoin.dat ====&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;
| 0x4&lt;br /&gt;
| Magic number: 0x4F00&lt;br /&gt;
|-&lt;br /&gt;
| 0x4&lt;br /&gt;
| 0x2&lt;br /&gt;
| Total Play Coins&lt;br /&gt;
|-&lt;br /&gt;
| 0x6&lt;br /&gt;
| 0x2&lt;br /&gt;
| Total Play Coins obtained on the date stored below. When the below date does not match the current date, this field is reset to zero, then the date(and other fields) are updated. Once this value is &amp;gt;=10, no more Play Coins can be obtained until the current date changes.&lt;br /&gt;
|-&lt;br /&gt;
| 0x8&lt;br /&gt;
| 0x4&lt;br /&gt;
| Total step [[PTM:GetTotalStepCount|count]] at the time a new Play Coin was obtained.&lt;br /&gt;
|-&lt;br /&gt;
| 0xC&lt;br /&gt;
| 0x4&lt;br /&gt;
| Step count for the day the last Play Coin was obtained, for that day&#039;s step count(same as the step count displayed by home-menu when this file was updated).&lt;br /&gt;
|-&lt;br /&gt;
| 0x10&lt;br /&gt;
| 0x2&lt;br /&gt;
| Year&lt;br /&gt;
|-&lt;br /&gt;
| 0x12&lt;br /&gt;
| 0x1&lt;br /&gt;
| Month&lt;br /&gt;
|-&lt;br /&gt;
| 0x13&lt;br /&gt;
| 0x1&lt;br /&gt;
| Day&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The above date stores the last time new Play Coin(s) were obtained. The contents of this file is updated by home-menu. [[PTM:GetTotalStepCount]] is not checked constantly, after home-menu boot this is only checked when waking from sleep-mode. Each time home-menu updates the contents of this file, home-menu will set the Play Coin total to 300 if it&#039;s higher than the 300 Play Coin limit.&lt;br /&gt;
&lt;br /&gt;
[[Home Menu]] loads this file / opens this archive during [[Home Menu|startup]]. When accessing this file fails, like when the file/archive is corrupted(or at least on older system-versions), the result is a brick due to Home Menu using [[SVC|svcBreak]]. [[User:Yellows8|Yellows8]] bricked a 3DS this way due to corruption via invalid [[FSFile:Write]] flush flags. When opening this extdata archive(0xf000000b) fails, Home Menu executes svcBreak.&lt;br /&gt;
&lt;br /&gt;
==== Shared Extdata 0xf000000b ubll.lst ====&lt;br /&gt;
List of blocked users.&lt;br /&gt;
&lt;br /&gt;
Empty space is filled with 0xC-long sequences of 00 00 ... 07&lt;br /&gt;
&lt;br /&gt;
=== Tools ===&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/wwylele/3ds-save-tool 3ds-save-tool] - Extract/verifies extdata&lt;/div&gt;</summary>
		<author><name>Wwylele</name></author>
	</entry>
	<entry>
		<id>https://www.3dbrew.org/w/index.php?title=DISA_and_DIFF&amp;diff=20974</id>
		<title>DISA and DIFF</title>
		<link rel="alternate" type="text/html" href="https://www.3dbrew.org/w/index.php?title=DISA_and_DIFF&amp;diff=20974"/>
		<updated>2019-05-26T13:35:47Z</updated>

		<summary type="html">&lt;p&gt;Wwylele: /* Partition table &amp;amp;amp; partition descriptor */ The padding doesn&amp;#039;t actually belongs to the descriptor, according to the descriptor size in the header&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This page describes DISA and DIFF format as the underlying container of [[Savegames]], [[Extdata]] and [[Title Database]]. For further format specification of the inner data, please refer to their own page.&lt;br /&gt;
&lt;br /&gt;
All data in this page is little-endian. All &amp;quot;unused / padding&amp;quot; fields can contain uninitialized data unless otherwise specified.&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
&lt;br /&gt;
DISA and DIFF are two container formats. They are very similar and are used for various purposes in 3DS. Here is a summary table of their usage, the CMAC type and the AES key slot used (the meaning of these is explained in the next section):&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! Usage&lt;br /&gt;
! Media&lt;br /&gt;
! Container format&lt;br /&gt;
! [[#AES CMAC|CMAC type]]&lt;br /&gt;
! CMAC [[AES Registers|Keyslot]]&lt;br /&gt;
|-&lt;br /&gt;
| [[Savegames]]&lt;br /&gt;
| Gamecard&lt;br /&gt;
| DISA&lt;br /&gt;
| [[#CTR-SAV0|CTR-SAV0]]&lt;br /&gt;
| 0x19&lt;br /&gt;
|-&lt;br /&gt;
| [[Savegames]]&lt;br /&gt;
| [[SD Filesystem|SD]]&lt;br /&gt;
| DISA&lt;br /&gt;
| [[#CTR-SIGN|CTR-SIGN]]&lt;br /&gt;
| 0x30&lt;br /&gt;
|-&lt;br /&gt;
| [[System SaveData]]&lt;br /&gt;
| [[Flash Filesystem|NAND]]&lt;br /&gt;
| DISA&lt;br /&gt;
| [[#CTR-SYS0|CTR-SYS0]]&lt;br /&gt;
| 0x30&lt;br /&gt;
|-&lt;br /&gt;
| [[Extdata|Private Extdata]]&lt;br /&gt;
| [[SD Filesystem|SD]]&lt;br /&gt;
| DIFF&lt;br /&gt;
| [[#CTR-EXT0|CTR-EXT0]]&lt;br /&gt;
| 0x30&lt;br /&gt;
|-&lt;br /&gt;
| [[Extdata|Shared Extdata]]&lt;br /&gt;
| [[Flash Filesystem|NAND]]&lt;br /&gt;
| DIFF&lt;br /&gt;
| [[#CTR-EXT0|CTR-EXT0]]&lt;br /&gt;
| 0x30&lt;br /&gt;
|-&lt;br /&gt;
| [[Title Database]]&lt;br /&gt;
| [[SD Filesystem|SD]]&lt;br /&gt;
| DIFF&lt;br /&gt;
| [[#CTR-9DB0|CTR-9DB0]]&lt;br /&gt;
| 0x30&lt;br /&gt;
|-&lt;br /&gt;
| [[Title Database]]&lt;br /&gt;
| [[Flash Filesystem|NAND]]&lt;br /&gt;
| DIFF&lt;br /&gt;
| [[#CTR-9DB0|CTR-9DB0]]&lt;br /&gt;
| 0x0B&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Encryption ==&lt;br /&gt;
&lt;br /&gt;
DISA and DIFF formats don&#039;t have their own encryption specification. They follow the encryption method defined by their media:&lt;br /&gt;
&lt;br /&gt;
* Gamecard savegames have special wear leveling + encryption layers. See [[Savegames]] for detail.&lt;br /&gt;
* Files on SD follow [[SD Filesystem|the general SD filesystem encryption rule]].&lt;br /&gt;
* Files on NAND are in cleartext, after decrypting [[Flash Filesystem|the NAND partition encryption]].&lt;br /&gt;
&lt;br /&gt;
== Format ==&lt;br /&gt;
&lt;br /&gt;
A DISA / DIFF file consists of the following components:&lt;br /&gt;
&lt;br /&gt;
* 0x100-byte AES CMAC&lt;br /&gt;
* 0x100-byte Header&lt;br /&gt;
* Secondary partition table&lt;br /&gt;
** Contains one or two partition descriptors, depending on the number of partitions.&lt;br /&gt;
* Primary partition table&lt;br /&gt;
** Same layout as the secondary one&lt;br /&gt;
* Partition A&lt;br /&gt;
* Partition B (optional)&lt;br /&gt;
** can only exist for DISA.&lt;br /&gt;
&lt;br /&gt;
== AES CMAC ==&lt;br /&gt;
&lt;br /&gt;
The AES CMAC is located at the beginning of the DISA / DIFF image, and it is 0x10 long. The rest 0xF0 bytes before the header are unused.&lt;br /&gt;
&lt;br /&gt;
The key used for the AES CMAC is generated by the [[AES Registers|hardware key engine]]. See the keyslot it uses in the table above.&lt;br /&gt;
&lt;br /&gt;
The data being authenticated by the AES CMAC is a 0x20-byte SHA-256 hash of a data block. The data block has different content formats among CMAC types. All types of data block contain a copy or a hash of the header, which is the start of the the rest of the verification chain, so the AES CMAC effectively authenticates the whole save image. Each type of data block is explained below.&lt;br /&gt;
&lt;br /&gt;
=== CTR-SAV0 ===&lt;br /&gt;
&lt;br /&gt;
This CMAC type is used for gamecard savegames. It is 0x28-byte long.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! Offset&lt;br /&gt;
! Length&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x00&lt;br /&gt;
| 8&lt;br /&gt;
| Magic &amp;amp;quot;CTR-SAV0&amp;amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| 0x8&lt;br /&gt;
| 0x20&lt;br /&gt;
| SHA-256 of the following 0x108-byte block&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
| 0x00&lt;br /&gt;
| 8&lt;br /&gt;
| Magic &amp;amp;quot;CTR-NOR0&amp;amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| 0x08&lt;br /&gt;
| 0x100&lt;br /&gt;
| Copy of the DISA header&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== CTR-SIGN ===&lt;br /&gt;
&lt;br /&gt;
This CMAC type is used for SD savegames. It is 0x30-byte long.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! Offset&lt;br /&gt;
! Length&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x00&lt;br /&gt;
| 8&lt;br /&gt;
| Magic &amp;amp;quot;CTR-SIGN&amp;amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| 0x08&lt;br /&gt;
| 8&lt;br /&gt;
| Title ID&lt;br /&gt;
|-&lt;br /&gt;
| 0x10&lt;br /&gt;
| 0x20&lt;br /&gt;
| SHA-256 of the following 0x108-byte block&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
| 0x00&lt;br /&gt;
| 8&lt;br /&gt;
| Magic &amp;amp;quot;CTR-SAV0&amp;amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| 0x08&lt;br /&gt;
| 0x100&lt;br /&gt;
| Copy of the DISA header&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== CTR-SYS0 ===&lt;br /&gt;
&lt;br /&gt;
This CMAC type is used for NAND system save. It is 0x110-byte long.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! Offset&lt;br /&gt;
! Length&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x00&lt;br /&gt;
| 8&lt;br /&gt;
| Magic &amp;amp;quot;CTR-SYS0&amp;amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| 0x08&lt;br /&gt;
| 8&lt;br /&gt;
| Save ID. The higher word is always zero&lt;br /&gt;
|-&lt;br /&gt;
| 0x10&lt;br /&gt;
| 0x100&lt;br /&gt;
| Copy of the DISA header&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== CTR-EXT0 ===&lt;br /&gt;
&lt;br /&gt;
This CMAC type is used for extdata. It is 0x11C-byte long.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! Offset&lt;br /&gt;
! Length&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x00&lt;br /&gt;
| 8&lt;br /&gt;
| Magic &amp;amp;quot;CTR-EXT0&amp;amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| 0x08&lt;br /&gt;
| 8&lt;br /&gt;
| Extdata ID&lt;br /&gt;
|-&lt;br /&gt;
| 0x10&lt;br /&gt;
| 4&lt;br /&gt;
| 0 for Quota.dat, 1 otherwise&lt;br /&gt;
|-&lt;br /&gt;
| 0x14&lt;br /&gt;
| 4&lt;br /&gt;
| ID in the device file name. 0 for Quota.dat&lt;br /&gt;
|-&lt;br /&gt;
| 0x18&lt;br /&gt;
| 4&lt;br /&gt;
| ID in the device directory name that the file is in. 0 for Quota.dat&lt;br /&gt;
|-&lt;br /&gt;
| 0x1C&lt;br /&gt;
| 0x100&lt;br /&gt;
| Copy of the DIFF header&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== CTR-9DB0 ===&lt;br /&gt;
&lt;br /&gt;
This CMAC type is used for title database. It is 0x10C-byte long.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! Offset&lt;br /&gt;
! Length&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x00&lt;br /&gt;
| 8&lt;br /&gt;
| Magic &amp;amp;quot;CTR-9DB0&amp;amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| 0x08&lt;br /&gt;
| 4&lt;br /&gt;
| Database ID. Each .db file has its own ID&lt;br /&gt;
|-&lt;br /&gt;
| 0x0C&lt;br /&gt;
| 0x100&lt;br /&gt;
| Copy of the DIFF header&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Header ==&lt;br /&gt;
&lt;br /&gt;
The header located at offset 0x100 defines the rest components of the file (partitions and their tables). All offsets in the header are relative to the beginning of the DISA/DIFF file, except for partition descriptor offsets, which are relative to the beginning of the (active) partition table. DISA and DIFF have different header format.&lt;br /&gt;
&lt;br /&gt;
=== DISA header ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! Offset&lt;br /&gt;
! Length&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x00&lt;br /&gt;
| 4&lt;br /&gt;
| Magic &amp;amp;quot;DISA&amp;amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| 0x04&lt;br /&gt;
| 4&lt;br /&gt;
| Magic 0x40000&lt;br /&gt;
|-&lt;br /&gt;
| 0x08&lt;br /&gt;
| 4&lt;br /&gt;
| Partition count, 1 or 2&lt;br /&gt;
|-&lt;br /&gt;
| 0x0C&lt;br /&gt;
| 4&lt;br /&gt;
| Padding&lt;br /&gt;
|-&lt;br /&gt;
| 0x10&lt;br /&gt;
| 8&lt;br /&gt;
| Secondary partition table offset&lt;br /&gt;
|-&lt;br /&gt;
| 0x18&lt;br /&gt;
| 8&lt;br /&gt;
| Primary partition table offset&lt;br /&gt;
|-&lt;br /&gt;
| 0x20&lt;br /&gt;
| 8&lt;br /&gt;
| Partition table size&lt;br /&gt;
|-&lt;br /&gt;
| 0x28&lt;br /&gt;
| 8&lt;br /&gt;
| Partition A descriptor offset in the partition table&lt;br /&gt;
|-&lt;br /&gt;
| 0x30&lt;br /&gt;
| 8&lt;br /&gt;
| Partition A descriptor size&lt;br /&gt;
|-&lt;br /&gt;
| 0x38&lt;br /&gt;
| 8&lt;br /&gt;
| Partition B descriptor offset in the partition table&lt;br /&gt;
|-&lt;br /&gt;
| 0x40&lt;br /&gt;
| 8&lt;br /&gt;
| Partition B descriptor size&lt;br /&gt;
|-&lt;br /&gt;
| 0x48&lt;br /&gt;
| 8&lt;br /&gt;
| Partition A offset&lt;br /&gt;
|-&lt;br /&gt;
| 0x50&lt;br /&gt;
| 8&lt;br /&gt;
| Partition A size&lt;br /&gt;
|-&lt;br /&gt;
| 0x58&lt;br /&gt;
| 8&lt;br /&gt;
| Partition B offset&lt;br /&gt;
|-&lt;br /&gt;
| 0x60&lt;br /&gt;
| 8&lt;br /&gt;
| Partition B size&lt;br /&gt;
|-&lt;br /&gt;
| 0x68&lt;br /&gt;
| 1&lt;br /&gt;
| Active partition table, 0 = primary, 1 = secondary&lt;br /&gt;
|-&lt;br /&gt;
| 0x69&lt;br /&gt;
| 3&lt;br /&gt;
| Padding&lt;br /&gt;
|-&lt;br /&gt;
| 0x6C&lt;br /&gt;
| 0x20&lt;br /&gt;
| SHA-256 over the active partition table&lt;br /&gt;
|-&lt;br /&gt;
| 0x8C&lt;br /&gt;
| 0x74&lt;br /&gt;
| Unused&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Note:&lt;br /&gt;
&lt;br /&gt;
* When the partition count is 1, there is no partition B and all of its related fields are zero.&lt;br /&gt;
&lt;br /&gt;
=== DIFF header ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! Offset&lt;br /&gt;
! Length&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x00&lt;br /&gt;
| 4&lt;br /&gt;
| Magic &amp;amp;quot;DIFF&amp;amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| 0x04&lt;br /&gt;
| 4&lt;br /&gt;
| Magic 0x30000&lt;br /&gt;
|-&lt;br /&gt;
| 0x08&lt;br /&gt;
| 8&lt;br /&gt;
| Secondary partition table/descriptor offset&lt;br /&gt;
|-&lt;br /&gt;
| 0x10&lt;br /&gt;
| 8&lt;br /&gt;
| Primary partition table/descriptor offset&lt;br /&gt;
|-&lt;br /&gt;
| 0x18&lt;br /&gt;
| 8&lt;br /&gt;
| Partition table/descriptor size&lt;br /&gt;
|-&lt;br /&gt;
| 0x20&lt;br /&gt;
| 8&lt;br /&gt;
| Partition (A) offset&lt;br /&gt;
|-&lt;br /&gt;
| 0x28&lt;br /&gt;
| 8&lt;br /&gt;
| Partition (A) size&lt;br /&gt;
|-&lt;br /&gt;
| 0x30&lt;br /&gt;
| 4&lt;br /&gt;
| Active partition descriptor, 0 = primary, 1 = secondary&lt;br /&gt;
|-&lt;br /&gt;
| 0x34&lt;br /&gt;
| 0x20&lt;br /&gt;
| SHA-256 over the active partition table/descriptor&lt;br /&gt;
|-&lt;br /&gt;
| 0x54&lt;br /&gt;
| 8&lt;br /&gt;
| Unique identifier&lt;br /&gt;
|-&lt;br /&gt;
| 0x5C&lt;br /&gt;
| 0xA4&lt;br /&gt;
| Unused, might contain leftover data&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Note:&lt;br /&gt;
&lt;br /&gt;
* Since DIFF can only contain one partition, a partition table can only have one partition descriptor, so they become the same concept here.&lt;br /&gt;
* See [[Extdata]] for its usage of the unique identifier field. For title database files, this field is zero.&lt;br /&gt;
&lt;br /&gt;
== Partition table &amp;amp;amp; partition descriptor ==&lt;br /&gt;
&lt;br /&gt;
There are two partition tables, but only one of them is active. When operating on a DISA / DIFF file, 3DS FS alternately activate one of the two tables, presumably for data backup or atomic file writing. A newly created DISA / DIFF file may have entirely uninitialized data in the inactive partition table.&lt;br /&gt;
&lt;br /&gt;
One partition table contains one or two partition descriptors , each of which describes the layout of one partition. A partition descriptor contains the following components:&lt;br /&gt;
&lt;br /&gt;
* DIFI header&lt;br /&gt;
* IVFC descriptor&lt;br /&gt;
* DPFS descriptor&lt;br /&gt;
* Partition master hash&lt;br /&gt;
&lt;br /&gt;
=== DIFI header ===&lt;br /&gt;
&lt;br /&gt;
The DIFI header locates at the beginning of a partition descriptor. This header defines the rest components of the partition descriptor (IVFC descriptor, DPFS descriptor and partition master hash). All offsets are relative to the beginning of the partition descriptor, except for &amp;lt;code&amp;gt;External IVFC level 4 offset&amp;lt;/code&amp;gt;, which is relative to the beginning of the partition.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! Offset&lt;br /&gt;
! Length&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x00&lt;br /&gt;
| 4&lt;br /&gt;
| Magic &amp;amp;quot;DIFI&amp;amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| 0x04&lt;br /&gt;
| 4&lt;br /&gt;
| Magic 0x10000&lt;br /&gt;
|-&lt;br /&gt;
| 0x08&lt;br /&gt;
| 8&lt;br /&gt;
| IVFC descriptor offset&lt;br /&gt;
|-&lt;br /&gt;
| 0x10&lt;br /&gt;
| 8&lt;br /&gt;
| IVFC descriptor size&lt;br /&gt;
|-&lt;br /&gt;
| 0x18&lt;br /&gt;
| 8&lt;br /&gt;
| DPFS descriptor offset&lt;br /&gt;
|-&lt;br /&gt;
| 0x20&lt;br /&gt;
| 8&lt;br /&gt;
| DPFS descriptor size&lt;br /&gt;
|-&lt;br /&gt;
| 0x28&lt;br /&gt;
| 8&lt;br /&gt;
| Partition hash offset&lt;br /&gt;
|-&lt;br /&gt;
| 0x30&lt;br /&gt;
| 8&lt;br /&gt;
| Partition hash size&lt;br /&gt;
|-&lt;br /&gt;
| 0x38&lt;br /&gt;
| 1&lt;br /&gt;
| If none zero, enable external IVFC level 4.&lt;br /&gt;
|-&lt;br /&gt;
| 0x39&lt;br /&gt;
| 1&lt;br /&gt;
| DPFS tree level 1 selector&lt;br /&gt;
|-&lt;br /&gt;
| 0x3A&lt;br /&gt;
| 2&lt;br /&gt;
| Padding&lt;br /&gt;
|-&lt;br /&gt;
| 0x3C&lt;br /&gt;
| 8&lt;br /&gt;
| External IVFC level 4 offset (zero if external IVFC level 4 disabled)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Note:&lt;br /&gt;
&lt;br /&gt;
* The meaning of fields after 0x38 are explained in the section [[#Partition]]&lt;br /&gt;
&lt;br /&gt;
=== IVFC descriptor ===&lt;br /&gt;
&lt;br /&gt;
This header defines each level of IVFC tree (explained in the section [[#Partition]]). All offsets are relative to the beginning of DPFS level 3.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! Offset&lt;br /&gt;
! Length&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x00&lt;br /&gt;
| 4&lt;br /&gt;
| Magic &amp;amp;quot;IVFC&amp;amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| 0x04&lt;br /&gt;
| 4&lt;br /&gt;
| Magic 0x20000&lt;br /&gt;
|-&lt;br /&gt;
| 0x08&lt;br /&gt;
| 8&lt;br /&gt;
| Master hash size = partition master hash size in DIFI header&lt;br /&gt;
|-&lt;br /&gt;
| 0x10&lt;br /&gt;
| 8&lt;br /&gt;
| IVFC level 1 offset&lt;br /&gt;
|-&lt;br /&gt;
| 0x18&lt;br /&gt;
| 8&lt;br /&gt;
| IVFC level 1 size&lt;br /&gt;
|-&lt;br /&gt;
| 0x20&lt;br /&gt;
| 4&lt;br /&gt;
| IVFC level 1 block size in log2&lt;br /&gt;
|-&lt;br /&gt;
| 0x24&lt;br /&gt;
| 4&lt;br /&gt;
| Padding&lt;br /&gt;
|-&lt;br /&gt;
| 0x28&lt;br /&gt;
| 8&lt;br /&gt;
| IVFC level 2 offset&lt;br /&gt;
|-&lt;br /&gt;
| 0x30&lt;br /&gt;
| 8&lt;br /&gt;
| IVFC level 2 size&lt;br /&gt;
|-&lt;br /&gt;
| 0x38&lt;br /&gt;
| 4&lt;br /&gt;
| IVFC level 2 block size in log2&lt;br /&gt;
|-&lt;br /&gt;
| 0x3C&lt;br /&gt;
| 4&lt;br /&gt;
| Padding&lt;br /&gt;
|-&lt;br /&gt;
| 0x40&lt;br /&gt;
| 8&lt;br /&gt;
| IVFC level 3 offset&lt;br /&gt;
|-&lt;br /&gt;
| 0x48&lt;br /&gt;
| 8&lt;br /&gt;
| IVFC level 3 size&lt;br /&gt;
|-&lt;br /&gt;
| 0x50&lt;br /&gt;
| 4&lt;br /&gt;
| IVFC level 3 block size in log2&lt;br /&gt;
|-&lt;br /&gt;
| 0x54&lt;br /&gt;
| 4&lt;br /&gt;
| Padding&lt;br /&gt;
|-&lt;br /&gt;
| 0x58&lt;br /&gt;
| 8&lt;br /&gt;
| IVFC level 4 offset (unused if external IVFC level 4 enabled)&lt;br /&gt;
|-&lt;br /&gt;
| 0x60&lt;br /&gt;
| 8&lt;br /&gt;
| IVFC level 4 size&lt;br /&gt;
|-&lt;br /&gt;
| 0x68&lt;br /&gt;
| 4&lt;br /&gt;
| IVFC level 4 block size in log2&lt;br /&gt;
|-&lt;br /&gt;
| 0x6C&lt;br /&gt;
| 4&lt;br /&gt;
| Padding&lt;br /&gt;
|-&lt;br /&gt;
| 0x70&lt;br /&gt;
| 8&lt;br /&gt;
| IVFC descriptor size? The value is usually 0x78&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== DPFS descriptor ===&lt;br /&gt;
&lt;br /&gt;
This header defines each level of DPFS tree (explained in the section [[#Partition]]). All offsets are relative to the beginning of the partition.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! Offset&lt;br /&gt;
! Length&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x00&lt;br /&gt;
| 4&lt;br /&gt;
| Magic &amp;amp;quot;DPFS&amp;amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| 0x04&lt;br /&gt;
| 4&lt;br /&gt;
| Magic 0x10000&lt;br /&gt;
|-&lt;br /&gt;
| 0x08&lt;br /&gt;
| 8&lt;br /&gt;
| DPFS level 1 offset&lt;br /&gt;
|-&lt;br /&gt;
| 0x10&lt;br /&gt;
| 8&lt;br /&gt;
| DPFS level 1 size&lt;br /&gt;
|-&lt;br /&gt;
| 0x18&lt;br /&gt;
| 4&lt;br /&gt;
| DPFS level 1 block size in log2 (unused?)&lt;br /&gt;
|-&lt;br /&gt;
| 0x1C&lt;br /&gt;
| 4&lt;br /&gt;
| Padding&lt;br /&gt;
|-&lt;br /&gt;
| 0x20&lt;br /&gt;
| 8&lt;br /&gt;
| DPFS level 2 offset&lt;br /&gt;
|-&lt;br /&gt;
| 0x28&lt;br /&gt;
| 8&lt;br /&gt;
| DPFS level 2 size&lt;br /&gt;
|-&lt;br /&gt;
| 0x30&lt;br /&gt;
| 4&lt;br /&gt;
| DPFS level 2 block size in log2&lt;br /&gt;
|-&lt;br /&gt;
| 0x34&lt;br /&gt;
| 4&lt;br /&gt;
| Padding&lt;br /&gt;
|-&lt;br /&gt;
| 0x38&lt;br /&gt;
| 8&lt;br /&gt;
| DPFS level 3 offset&lt;br /&gt;
|-&lt;br /&gt;
| 0x40&lt;br /&gt;
| 8&lt;br /&gt;
| DPFS level 3 size&lt;br /&gt;
|-&lt;br /&gt;
| 0x48&lt;br /&gt;
| 4&lt;br /&gt;
| DPFS level 3 block size in log2&lt;br /&gt;
|-&lt;br /&gt;
| 0x4C&lt;br /&gt;
| 4&lt;br /&gt;
| Padding&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Partition master hash ===&lt;br /&gt;
&lt;br /&gt;
This is a SHA-256 hash list over IVFC level 1. See [[#IVFC tree]] for explanation.&lt;br /&gt;
&lt;br /&gt;
== Partition ==&lt;br /&gt;
&lt;br /&gt;
A partition can have two types of layout. This is determined by the field DIFF + 0x38 (&amp;lt;code&amp;gt;Enable external IVFC level 4&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
The layout type 0 (external IVFC level 4 disabled) contains&lt;br /&gt;
&lt;br /&gt;
* DPFS level 1&lt;br /&gt;
* DPFS level 2&lt;br /&gt;
* DPFS level 3, and inside&lt;br /&gt;
** IVFC level 1&lt;br /&gt;
** IVFC level 2&lt;br /&gt;
** IVFC level 3&lt;br /&gt;
** IVFC level 4 (the actual content data)&lt;br /&gt;
&lt;br /&gt;
The layout type 1 (external IVFC level 4 enabled) contains&lt;br /&gt;
&lt;br /&gt;
* DPFS level 1&lt;br /&gt;
* DPFS level 2&lt;br /&gt;
* DPFS level 3, and inside&lt;br /&gt;
** IVFC level 1&lt;br /&gt;
** IVFC level 2&lt;br /&gt;
** IVFC level 3&lt;br /&gt;
* IVFC level 4 (the actual content data, note that this is out side DPFS level 3)&lt;br /&gt;
&lt;br /&gt;
=== DPFS tree ===&lt;br /&gt;
&lt;br /&gt;
Everything inside the DPFS tree comes in pairs, and at one time only one of a pair is active. The tree is probably designed for atomic writing: for a file writing operation, it writes to the inactive part, then commits the data by switching a bit to activate it.&lt;br /&gt;
&lt;br /&gt;
Each level of DPFS tree consists of a pair of chunks. The size of one chunk is defined as it in the DPFS descriptor, so the total size of a level is actually twice as large as the size recorded in the descriptor. For level 1 and 2, each chunk is a bit array, in which each bit corresponds to a block in the next level (the block size of the next level is also defined in the DPFS descriptor). This bit indicates which one of the pair in the next level is active for this block: 0 means the first one and 1 means the second one. The active chunk of level 1 is selected by &amp;lt;code&amp;gt;DPFS tree level 1 selector&amp;lt;/code&amp;gt; in the DIFI header. The bit array is encoded in u32 array, with MSB as the first bit of each 32 bits.&lt;br /&gt;
&lt;br /&gt;
To access data in level 3, one needs to check the bits in level 1 and level 2 to know which chunk of level 3 is active for the accessed location. For example, for a following configuration:&lt;br /&gt;
&lt;br /&gt;
* Level 1: size = 4 bytes = 32 bits&lt;br /&gt;
* Level 2: size = 0x380 bytes = 0x1C00 bits, block size = 0x80 bytes&lt;br /&gt;
* Level 3: size = 0x1B7F000, block size = 0x1000, block size = 0x1000 bytes&lt;br /&gt;
&lt;br /&gt;
if one want to read byte at 0x1234567 of level 3, the following calculation is performed:&lt;br /&gt;
&lt;br /&gt;
* get level 2 bit index &amp;lt;code&amp;gt;0x1234567 / 0x1000 = 0x1234&amp;lt;/code&amp;gt;, and its byte location &amp;lt;code&amp;gt;0x1234 / 8 = 0x246&amp;lt;/code&amp;gt;&lt;br /&gt;
* get level 1 bit index &amp;lt;code&amp;gt;0x246 / 0x80 = 4&amp;lt;/code&amp;gt;&lt;br /&gt;
* get &amp;lt;code&amp;gt;level1_selector&amp;lt;/code&amp;gt; from DIFI header&lt;br /&gt;
* read &amp;lt;code&amp;gt;level2_selector = Level1[level1_selector].bits[4]&amp;lt;/code&amp;gt;;&lt;br /&gt;
* read &amp;lt;code&amp;gt;level3_selector = Level2[level2_selector].bits[0x1234]&amp;lt;/code&amp;gt;;&lt;br /&gt;
* read &amp;lt;code&amp;gt;data = Level3[level3_selector].bytes[0x1234567]&amp;lt;/code&amp;gt; as the final data&lt;br /&gt;
* in the code above &amp;lt;code&amp;gt;Levelx[k]&amp;lt;/code&amp;gt; means the &amp;lt;code&amp;gt;k&amp;lt;/code&amp;gt;-th chunk in level &amp;lt;code&amp;gt;x&amp;lt;/code&amp;gt;, where &amp;lt;code&amp;gt;k = 0, 1&amp;lt;/code&amp;gt;. &amp;lt;code&amp;gt;.bits[n]&amp;lt;/code&amp;gt; is expanded to &amp;lt;code&amp;gt;(.u32_array[n / 32] &amp;amp;gt;&amp;amp;gt; (31 - n % 32)) &amp;amp;amp; 1&amp;lt;/code&amp;gt; as the bit array is encoded in u32 array.&lt;br /&gt;
&lt;br /&gt;
Effectively, the active data is scattered among the two level 3 chunk. One can assemble the whole active level 3 image following the same rule.&lt;br /&gt;
&lt;br /&gt;
=== IVFC tree ===&lt;br /&gt;
&lt;br /&gt;
The IVFC tree is used for data verification. It is very similar to the IVFC tree in [[RomFS]], except that it has an additional level here. For level 1, 2 and 3, each level is a list of SHA-256 hash, of which each corresponds to a block of the next level which is zero-padded to align the block size (the block size of the next level is defined in the IVFC descriptor).&lt;br /&gt;
&lt;br /&gt;
The partition master hash in the partition descriptor can be seen as IVFC level 0, which hashes level 1 following the same rule. The master hash is usually 0x20 long, consisting only one hash. This is because most DISA / DIFF files are not large enough to have multiple hashes on the top level, which isn&#039;t the case for some title database files.&lt;br /&gt;
&lt;br /&gt;
However, not all data is hashed - only ranges that have been written with valid data are properly hashed.&lt;br /&gt;
&lt;br /&gt;
Level 4 is the actual content of the partition, which is what the container format essentially contains.&lt;br /&gt;
&lt;br /&gt;
== Extracting content from a DISA / DIFF container ==&lt;br /&gt;
&lt;br /&gt;
* Find the active partition table and the partition(s).&lt;br /&gt;
* Unwrap DPFS tree of partition(s) by reconstructing active data.&lt;br /&gt;
* Unwrap IVFC tree. Either take out level 4 directly, or, better, verify all the hashes and poison the data that is not properly hashed.&lt;br /&gt;
* The IVFC level 4 is the inner content of the file. The format of it varies among different usage. Refer their own page for further extraction.&lt;br /&gt;
&lt;br /&gt;
== Chain of trust ==&lt;br /&gt;
&lt;br /&gt;
* AES CMAC verifies the header.&lt;br /&gt;
* The header verifies the active partition table via the table hash.&lt;br /&gt;
* In the partition table, each descriptor verifies level 1 of its IVFC tree via the master hash.&lt;br /&gt;
* Each IVFC level verifies the next level, until the level 4, which is the inner content.&lt;br /&gt;
&lt;br /&gt;
== Summary diagram ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
external link: https://i.imgur.com/BjwShJZ.png&lt;br /&gt;
* Please move this into 3dbrew when file uploading is fixed.&lt;/div&gt;</summary>
		<author><name>Wwylele</name></author>
	</entry>
	<entry>
		<id>https://www.3dbrew.org/w/index.php?title=Inner_FAT&amp;diff=20972</id>
		<title>Inner FAT</title>
		<link rel="alternate" type="text/html" href="https://www.3dbrew.org/w/index.php?title=Inner_FAT&amp;diff=20972"/>
		<updated>2019-05-23T01:16:31Z</updated>

		<summary type="html">&lt;p&gt;Wwylele: /* Filesystem Header */ Nintendo please&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This page describes a common FAT-like file system used in [[Savegames]], [[Extdata]] and [[Title Database]]. This file system format has several variants depending on which kind of data it stores. All the three kinds of data that use this file system structure also happen to use the [[DISA and DIFF]] container as well, but there is no direct relationship between the file system and the DISA/DIFF container. All data formats described here is in the inner data of the DISA/DIFF container (i.e. IVFC level 4). Please refer to the DISA/DIFF page for how to unwrap it first before trying to extract the file system.&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
&lt;br /&gt;
The file system consists of the following components:&lt;br /&gt;
* header&lt;br /&gt;
* directory hash table&lt;br /&gt;
* file hash table&lt;br /&gt;
* file allocation table&lt;br /&gt;
* directory entry table&lt;br /&gt;
* file entry table&lt;br /&gt;
* data region&lt;br /&gt;
&lt;br /&gt;
The file allocation table (FAT) forms several linked lists inside, each of which represents a &amp;quot;file&amp;quot; allocated in the data region. Please refer to the File Allocation Table section below for more detail. In some variants, the directory entry table and the file entry table are also allocated as two special &amp;quot;files&amp;quot; in the data region, managed by the FAT, while in others they are stand-alone tables located outside the data region.&lt;br /&gt;
&lt;br /&gt;
== Layout Variants ==&lt;br /&gt;
Four variants of the file system layout has been identified. A summary diagram can be found here: [https://github.com/wwylele/3ds-save-tool/raw/master/inner-fat.png]&lt;br /&gt;
&lt;br /&gt;
=== Savegame, &amp;lt;code&amp;gt;duplicate data = true&amp;lt;/code&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
Such savegame is a single DISA container that only has one partition which is always configured as external IVFC level 4 disabled (see [[DISA and DIFF|DISA]] format for details). All components are stored in this partition as&lt;br /&gt;
&lt;br /&gt;
* filesystem header at the beginning&lt;br /&gt;
* directory hash table&lt;br /&gt;
* file hash table&lt;br /&gt;
* file allocation table&lt;br /&gt;
* data region&lt;br /&gt;
** directory entry table is allocated inside data region&lt;br /&gt;
** file entry table as well&lt;br /&gt;
** all file data is also allocated here&lt;br /&gt;
&lt;br /&gt;
In this layout, all data is duplicated by DISA&#039;s DPFS tree, which is what the parameter &amp;lt;code&amp;gt;duplicate data&amp;lt;/code&amp;gt; implies.&lt;br /&gt;
&lt;br /&gt;
=== Savegame, &amp;lt;code&amp;gt;duplicate data = false&amp;lt;/code&amp;gt; === &lt;br /&gt;
Such savegame is a single DISA container that has two partitions. Partition A is always configured as external IVFC level 4 disabled, and partition B is configured as it enabled. Components are stored among the two partitions as&lt;br /&gt;
&lt;br /&gt;
* Partition A&lt;br /&gt;
** filesystem header at the beginning.&lt;br /&gt;
** directory hash table&lt;br /&gt;
** file hash table&lt;br /&gt;
** (stand-alone) file allocation table&lt;br /&gt;
** (stand-alone) directory entry table&lt;br /&gt;
** file entry table&lt;br /&gt;
* Partition B&lt;br /&gt;
** used as data region entirely, and only has file data allocated.&lt;br /&gt;
&lt;br /&gt;
In this layout, all file system metadata is duplicated by partition A DPFS tree, but file data is not as partition B has external IVFC level 4.&lt;br /&gt;
&lt;br /&gt;
=== Extdata ===&lt;br /&gt;
An extdata consists of several DIFF containers (device files), among which the special device file &amp;lt;code&amp;gt;00000000/00000001&amp;lt;/code&amp;gt; contains the inner FAT system, while other devices contains normal subfiles of the extdata. Please refer to [[Extdata]] for detail. The special file &amp;lt;code&amp;gt;00000000/00000001&amp;lt;/code&amp;gt; contists of the following components&lt;br /&gt;
&lt;br /&gt;
* filesystem header at the beginning&lt;br /&gt;
* directory hash table&lt;br /&gt;
* file hash table&lt;br /&gt;
* file allocation table (degenerate, because the data region only has two &amp;quot;files&amp;quot;: the directory entry table and the file entry table)&lt;br /&gt;
* data region&lt;br /&gt;
** directory entry table allocated inside data region&lt;br /&gt;
** file entry table as well&lt;br /&gt;
** normal subfiles are NOT in the data region. They are in their DIFF containers instead.&lt;br /&gt;
&lt;br /&gt;
=== Title database ===&lt;br /&gt;
All [[Title Database]] files are DIFF containers. Except for &amp;lt;code&amp;gt;certs.db&amp;lt;/code&amp;gt;, all of them uses this filesystem in the DIFF inner data, which consists of&lt;br /&gt;
&lt;br /&gt;
* database-specific pre-header at the beginning (See [[Title Database]])&lt;br /&gt;
* filesystem header&lt;br /&gt;
* directory Hash Table (degenerate and always has only one bucket, as there is only one directory for &amp;quot;root&amp;quot;)&lt;br /&gt;
* file Hash Table&lt;br /&gt;
* file allocation table&lt;br /&gt;
* data region&lt;br /&gt;
** directory entry table allocated inside data region (degenerate, as there is only one directory for &amp;quot;root&amp;quot;)&lt;br /&gt;
** file entry table as well&lt;br /&gt;
** title entries (title info or ticket) are allocated as normal files in the data region as well.&lt;br /&gt;
&lt;br /&gt;
== Filesystem Header ==&lt;br /&gt;
Offsets listed in the table below are all relative to the beginning of the header, while all &amp;quot;starting block index&amp;quot; are relative to the beginning of data region. This is especially important for title database, as the offsets doesn&#039;t count the pre header.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! Offset&lt;br /&gt;
! Length&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x00&lt;br /&gt;
| 4&lt;br /&gt;
| Magic (&amp;quot;SAVE&amp;quot; for savegame; &amp;quot;BDRI&amp;quot; for title database; &amp;quot;VSXE&amp;quot; for extdata)&lt;br /&gt;
|-&lt;br /&gt;
| 0x04&lt;br /&gt;
| 4&lt;br /&gt;
| Version (0x40000 for savegame; 0x30000 for title database and extdata)&lt;br /&gt;
|-&lt;br /&gt;
| 0x08&lt;br /&gt;
| 8&lt;br /&gt;
| Filesystem Information offset (Y, =0x20 for savegame and title database, =0x138 for extdata)&lt;br /&gt;
|-&lt;br /&gt;
| 0x10&lt;br /&gt;
| 8&lt;br /&gt;
| Filesystem image size in blocks (including pre header for title database)&lt;br /&gt;
|-&lt;br /&gt;
| 0x18&lt;br /&gt;
| 4&lt;br /&gt;
| Filesystem Image block size&lt;br /&gt;
|-&lt;br /&gt;
| 0x1C&lt;br /&gt;
| 4&lt;br /&gt;
| Padding&lt;br /&gt;
|-&lt;br /&gt;
| 0x20 &lt;br /&gt;
| 0x118 in total&lt;br /&gt;
| Below is additional data for extdata. Not present in savegame or title database&lt;br /&gt;
|-&lt;br /&gt;
| 0x20&lt;br /&gt;
| 8&lt;br /&gt;
| Unknown&lt;br /&gt;
|-&lt;br /&gt;
| 0x28&lt;br /&gt;
| 4&lt;br /&gt;
| &#039;Action&#039; made on most recently mounted Extdata image&lt;br /&gt;
|-&lt;br /&gt;
| 0x2C&lt;br /&gt;
| 4&lt;br /&gt;
| Unknown&lt;br /&gt;
|-&lt;br /&gt;
| 0x30&lt;br /&gt;
| 4&lt;br /&gt;
| ID of most recently mounted Extdata image&lt;br /&gt;
|-&lt;br /&gt;
| 0x34&lt;br /&gt;
| 4&lt;br /&gt;
| Unknown&lt;br /&gt;
|-&lt;br /&gt;
| 0x38&lt;br /&gt;
| 0x100&lt;br /&gt;
| Mount path, from most recently mounted Extdata image&lt;br /&gt;
|-&lt;br /&gt;
| Y &lt;br /&gt;
| 0x68 in total&lt;br /&gt;
| Below is Filesystem Information&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x00&lt;br /&gt;
| 4&lt;br /&gt;
| Unknown&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x04&lt;br /&gt;
| 4&lt;br /&gt;
| Data region block size&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x08&lt;br /&gt;
| 8&lt;br /&gt;
| Directory hash table offset&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x10&lt;br /&gt;
| 4&lt;br /&gt;
| Directory hash table bucket count (=1 for title database)&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x14&lt;br /&gt;
| 4&lt;br /&gt;
| Padding&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x18&lt;br /&gt;
| 8&lt;br /&gt;
| File hash table offset&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x20&lt;br /&gt;
| 4&lt;br /&gt;
| File hash table bucket count&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x24&lt;br /&gt;
| 4&lt;br /&gt;
| Padding&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x28&lt;br /&gt;
| 8&lt;br /&gt;
| File allocation table offset&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x30&lt;br /&gt;
| 4&lt;br /&gt;
| File allocation table entry count &lt;br /&gt;
(excluding the leading 0th entry. See below)&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x34&lt;br /&gt;
| 4&lt;br /&gt;
| Padding&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x38&lt;br /&gt;
| 8&lt;br /&gt;
| Data region offset &lt;br /&gt;
(0 for savegame &amp;lt;code&amp;gt;duplicate data = false&amp;lt;/code&amp;gt; layout, as the data region is in partition B for that layout)&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x40&lt;br /&gt;
| 4&lt;br /&gt;
| Data region block count &lt;br /&gt;
(= File allocation table entry count)&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x44&lt;br /&gt;
| 4&lt;br /&gt;
| Padding&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x48&lt;br /&gt;
| 8&lt;br /&gt;
| for savegame &amp;lt;code&amp;gt;duplicate data = false&amp;lt;/code&amp;gt; layout: directory entry table offset;&lt;br /&gt;
otherwise: u32 directory entry table starting block index + u32 directory entry table block count&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x50&lt;br /&gt;
| 4&lt;br /&gt;
| Maximum directory count, excluding the mandatory &amp;quot;root&amp;quot; directory &lt;br /&gt;
(=1 for title database, but that 1 free directory slot is never used)&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x54&lt;br /&gt;
| 4&lt;br /&gt;
| Padding&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x58&lt;br /&gt;
| 8&lt;br /&gt;
| for savegame &amp;lt;code&amp;gt;duplicate data = false&amp;lt;/code&amp;gt; layout: file entry table offset;&lt;br /&gt;
otherwise: u32 file entry table starting block index + u32 file entry table block count&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x60&lt;br /&gt;
| 4&lt;br /&gt;
| Maximum file count&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x64&lt;br /&gt;
| 4&lt;br /&gt;
| Padding&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
* For savegames, the file/directory bucket count &amp;amp; maximum count are specified by the parameters of [[FS:FormatSaveData]] or [[FS:CreateSystemSaveData]].&lt;br /&gt;
* For extdata, the maximum file/directory count are specified by the parameters of [[FS:CreateExtSaveData]]. The bucket count is likely calculated by the system.&lt;br /&gt;
* Directory &amp;amp; file entry tables are allocated in the data region as if they are two normal files (except for savegame &amp;lt;code&amp;gt;duplicate data = false&amp;lt;/code&amp;gt; layout). However, only continuous allocation has been observed, so directly reading block_count * block_size bytes from data_region + starting_block_index * block_size should be safe.&lt;br /&gt;
* For title database (except for ticket), the range specified for data region seems overflow the file end by 0x80 bytes, which is exactly the size of the pre header. This makes it as if the data region offset should be relative to the pre header instead of the BDRI header. However, further investigation on the directory/file table allocated inside the data region shows that the data region offset is indeed relative to the BDRI header. It might be a bug in 3DS that the title database files miss 0x80-byte space at the end.&lt;br /&gt;
&lt;br /&gt;
== Directory Entry Table ==&lt;br /&gt;
&lt;br /&gt;
The directory entry table is an array of the entry type shown below. It describes the directory hierarchy of the file system. There are two variants of the directory entry type, and a dummy entry type.&lt;br /&gt;
&lt;br /&gt;
=== Savegame/Extdata Variant===&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! Offset&lt;br /&gt;
! Length&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x00&lt;br /&gt;
| 4&lt;br /&gt;
| Parent directory index. 0 for root&lt;br /&gt;
|-&lt;br /&gt;
| 0x04&lt;br /&gt;
| 16&lt;br /&gt;
| ASCII directory name in. All zero for root&lt;br /&gt;
|-&lt;br /&gt;
| 0x14&lt;br /&gt;
| 4&lt;br /&gt;
| Next sibling directory index. 0 if this is the last one&lt;br /&gt;
|-&lt;br /&gt;
| 0x18&lt;br /&gt;
| 4&lt;br /&gt;
| First subdirectory index. 0 if not exists&lt;br /&gt;
|-&lt;br /&gt;
| 0x1C&lt;br /&gt;
| 4&lt;br /&gt;
| First file index in file entry table. 0 for empty directory&lt;br /&gt;
|-&lt;br /&gt;
| 0x20&lt;br /&gt;
| 4&lt;br /&gt;
| Padding / zero?&lt;br /&gt;
|-&lt;br /&gt;
| 0x24&lt;br /&gt;
| 4&lt;br /&gt;
| Index of the next directory in the same hash table bucket. 0 if this is the last one&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Title Database Variant===&lt;br /&gt;
Because title database only has one directory for &amp;quot;root&amp;quot;, its directory entry table degenerates into many zeros whose structure is not recognizable. The size of one entry here is guessed.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! Offset&lt;br /&gt;
! Length&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x00&lt;br /&gt;
| 4&lt;br /&gt;
| Parent directory index = 0 for root&lt;br /&gt;
|-&lt;br /&gt;
| 0x04&lt;br /&gt;
| 4&lt;br /&gt;
| Next sibling directory index = 0 because this is the last one&lt;br /&gt;
|-&lt;br /&gt;
| 0x08&lt;br /&gt;
| 4&lt;br /&gt;
| First subdirectory index = 0 because there is no subdirectory&lt;br /&gt;
|-&lt;br /&gt;
| 0x0C&lt;br /&gt;
| 4&lt;br /&gt;
| First file index in file entry table. 0 for empty directory&lt;br /&gt;
|-&lt;br /&gt;
| 0x10&lt;br /&gt;
| 12&lt;br /&gt;
| Padding / zero?&lt;br /&gt;
|-&lt;br /&gt;
| 0x1C&lt;br /&gt;
| 4&lt;br /&gt;
| Index of the next directory in the same hash table bucket = 0 because there is no other directory&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Dummy Entry===&lt;br /&gt;
There are also some dummy entries in the array&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! Offset&lt;br /&gt;
! Length&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x00&lt;br /&gt;
| 4&lt;br /&gt;
| Current Total entry count&lt;br /&gt;
|-&lt;br /&gt;
| 0x04&lt;br /&gt;
| 4&lt;br /&gt;
| Maximum entry count = maximum directory count + 2&lt;br /&gt;
|-&lt;br /&gt;
| 0x08&lt;br /&gt;
| 28/20&lt;br /&gt;
| Padding / All zero&lt;br /&gt;
|-&lt;br /&gt;
| 0x24/0x1C&lt;br /&gt;
| 4&lt;br /&gt;
| Index of the next dummy entry. 0 if this is the last one&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The 0-th entry of the array is always a dummy entry, which functions as the head of the dummy entry linked list. The 1-st entry of the array is always the root. Therefore maximum entry count is two more than maximum directory count. Dummy entries are left there when deleting directories, and reserved for future use.&lt;br /&gt;
&lt;br /&gt;
== File Entry Table ==&lt;br /&gt;
&lt;br /&gt;
The file entry table is an array of the entry type shown below. It contains information for each file. There are three variants of the file entry type, and a dummy entry type.&lt;br /&gt;
&lt;br /&gt;
=== Savegame Variant ===&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! Offset&lt;br /&gt;
! Length&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x00&lt;br /&gt;
| 4&lt;br /&gt;
| Parent directory index in directory entry table&lt;br /&gt;
|-&lt;br /&gt;
| 0x04&lt;br /&gt;
| 16&lt;br /&gt;
| ASCII file name&lt;br /&gt;
|-&lt;br /&gt;
| 0x14&lt;br /&gt;
| 4&lt;br /&gt;
| Next sibling file index. 0 if this is the last one&lt;br /&gt;
|-&lt;br /&gt;
| 0x18&lt;br /&gt;
| 4&lt;br /&gt;
| Padding&lt;br /&gt;
|-&lt;br /&gt;
| 0x1C&lt;br /&gt;
| 4&lt;br /&gt;
| First block index in data region. 0x80000000 if the file is just created and has no data.&lt;br /&gt;
|-&lt;br /&gt;
| 0x20&lt;br /&gt;
| 8&lt;br /&gt;
| File Size&lt;br /&gt;
|-&lt;br /&gt;
| 0x28&lt;br /&gt;
| 4&lt;br /&gt;
| Padding?&lt;br /&gt;
|-&lt;br /&gt;
| 0x2C&lt;br /&gt;
| 4&lt;br /&gt;
| Index of the next file in the same hash table bucket. 0 if this is the last one&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Extdata Variant ===&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! Offset&lt;br /&gt;
! Length&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x00&lt;br /&gt;
| 4&lt;br /&gt;
| Parent directory index in directory entry table&lt;br /&gt;
|-&lt;br /&gt;
| 0x04&lt;br /&gt;
| 16&lt;br /&gt;
| ASCII file name&lt;br /&gt;
|-&lt;br /&gt;
| 0x14&lt;br /&gt;
| 4&lt;br /&gt;
| Next sibling file index. 0 if this is the last one&lt;br /&gt;
|-&lt;br /&gt;
| 0x18&lt;br /&gt;
| 4&lt;br /&gt;
| Padding&lt;br /&gt;
|-&lt;br /&gt;
| 0x1C&lt;br /&gt;
| 4&lt;br /&gt;
| Always 0x80000000&lt;br /&gt;
|-&lt;br /&gt;
| 0x20&lt;br /&gt;
| 8&lt;br /&gt;
| Unique identifier. See [[Extdata]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x28&lt;br /&gt;
| 4&lt;br /&gt;
| Padding?&lt;br /&gt;
|-&lt;br /&gt;
| 0x2C&lt;br /&gt;
| 4&lt;br /&gt;
| Index of the next file in the same hash table bucket. 0 if this is the last one&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Title database Variant ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! Offset&lt;br /&gt;
! Length&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x00&lt;br /&gt;
| 4&lt;br /&gt;
| Parent directory index in directory entry table&lt;br /&gt;
|-&lt;br /&gt;
| 0x04&lt;br /&gt;
| 8&lt;br /&gt;
| Title ID&lt;br /&gt;
|-&lt;br /&gt;
| 0x0C&lt;br /&gt;
| 4&lt;br /&gt;
| Next sibling file index. 0 if this is the last one&lt;br /&gt;
|-&lt;br /&gt;
| 0x10&lt;br /&gt;
| 4&lt;br /&gt;
| Padding&lt;br /&gt;
|-&lt;br /&gt;
| 0x14&lt;br /&gt;
| 4&lt;br /&gt;
| First block index in data region.&lt;br /&gt;
|-&lt;br /&gt;
| 0x18&lt;br /&gt;
| 8&lt;br /&gt;
| File size&lt;br /&gt;
|-&lt;br /&gt;
| 0x20&lt;br /&gt;
| 8&lt;br /&gt;
| Padding?&lt;br /&gt;
|-&lt;br /&gt;
| 0x28&lt;br /&gt;
| 4&lt;br /&gt;
| Index of the next file in the same hash table bucket. 0 if this is the last one&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Dummy Entry ===&lt;br /&gt;
Like directory entry table, file entry table also has some dummy entries:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! Offset&lt;br /&gt;
! Length&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x00&lt;br /&gt;
| 4&lt;br /&gt;
| Current total entry count&lt;br /&gt;
|-&lt;br /&gt;
| 0x04&lt;br /&gt;
| 4&lt;br /&gt;
| Maximum entry count = maximum file count + 1&lt;br /&gt;
|-&lt;br /&gt;
| 0x08&lt;br /&gt;
| 36/32&lt;br /&gt;
| Padding / All zero&lt;br /&gt;
|-&lt;br /&gt;
| 0x2C/0x28&lt;br /&gt;
| 4&lt;br /&gt;
| Index of the next dummy entry. 0 if this is the last one&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The 0-th entry of the array is always a dummy entry, which functions as the head of the dummy entry linked list. Therefore maximum entry count is one more than maximum file count. Dummy entries are left there when deleting files, and reserved for future use.&lt;br /&gt;
&lt;br /&gt;
== Directory Hash Table &amp;amp;amp; File Hash Table ==&lt;br /&gt;
&lt;br /&gt;
This is a u32 array of size = bucket count, each of which is an index to the directory / file entry table. The directory / file name is hashed and its entry index is put to the corresponding bucket. If there is already a directory/file entry in the bucket, then it appends to the linked list formed by &amp;lt;code&amp;gt;Index of the next directory/file in the same hash table bucket&amp;lt;/code&amp;gt; field in the directory/file entry table. i.e. this is a hash table using separate chaining with linked lists&lt;br /&gt;
&lt;br /&gt;
The hash function takes the parent index and the ASCII name (or title ID for title database) as key. The function is equivalent to&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;uint32_t GetBucket(&lt;br /&gt;
    char name[16 or 8], // For savegame/extdata, this takes all 16 bytes including trailing zeros; For title database, this is the 8-byte title ID&lt;br /&gt;
    uint32_t parent_dir_index,&lt;br /&gt;
    uint32_t bucket_count&lt;br /&gt;
) {&lt;br /&gt;
    uint32_t hash = parent_dir_index ^ 0x091A2B3C;&lt;br /&gt;
    for (int i = 0; i &amp;amp;lt; 4 or 2; ++i) {&lt;br /&gt;
        hash = (hash &amp;amp;gt;&amp;amp;gt; 1) | (hash &amp;amp;lt;&amp;amp;lt; 31);&lt;br /&gt;
        hash ^= (uint32_t)name[i * 4]&lt;br /&gt;
        hash ^= (uint32_t)name[i * 4 + 1] &amp;amp;lt;&amp;amp;lt; 8&lt;br /&gt;
        hash ^= (uint32_t)name[i * 4 + 2] &amp;amp;lt;&amp;amp;lt; 16&lt;br /&gt;
        hash ^= (uint32_t)name[i * 4 + 3] &amp;amp;lt;&amp;amp;lt; 24&lt;br /&gt;
    }&lt;br /&gt;
    return hash % bucket_count;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== File Allocation Table ==&lt;br /&gt;
&lt;br /&gt;
The file allocation table is an array of a 8-byte entry shown below. The array size is actually &#039;&#039;one larger than&#039;&#039; the size recorded in the filesystem header. Each entry corresponds to a block in the data region (the block size is defined in filesystem header). However, the 0th entry corresponds to nothing, so the corresponding block index is off by one. e.g. entry 31 in this table corresponds to block 30 in the data region.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! Offset&lt;br /&gt;
! Length&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x00&lt;br /&gt;
| 4&lt;br /&gt;
| bit[0:30]: Index U; bit[31]: Flag U&lt;br /&gt;
|-&lt;br /&gt;
| 0x04&lt;br /&gt;
| 4&lt;br /&gt;
| bit[0:30]: Index V; bit[31]: Flag V&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Entries in this table forms several chains, representing how blocks in the data region should be linked together. However, unlike normal FAT systems, which uses chains of entries, 3DS savegames use chain of &#039;&#039;nodes&#039;&#039;. Each node spans one or multiple entries.&lt;br /&gt;
&lt;br /&gt;
One node spanning &amp;lt;code&amp;gt;n&amp;lt;/code&amp;gt; entries starting from &amp;lt;code&amp;gt;FAT[k]&amp;lt;/code&amp;gt; is in the following format:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;FAT[k + 0]:&lt;br /&gt;
    Index_U = index of the first entry of the previous node. 0 if this is the first node.&lt;br /&gt;
    Index_V = index of the first entry of the next node. 0 if this is the last node.&lt;br /&gt;
    Flag_U set if this is the first node.&lt;br /&gt;
    Flag_V set if this node has multiple entries.&lt;br /&gt;
&lt;br /&gt;
FAT[k + 1]:&lt;br /&gt;
    Index_U = k (the first entry index of this node)&lt;br /&gt;
    Index_V = k + n - 1 (the last entry index of this node)&lt;br /&gt;
    Flag_U always set&lt;br /&gt;
    Flag_V always clear&lt;br /&gt;
&lt;br /&gt;
FAT[k + 2] ~ FAT[k + n - 2]:&lt;br /&gt;
    All these entries are uninitialized&lt;br /&gt;
&lt;br /&gt;
FAT[k + n - 1]:&lt;br /&gt;
    Index_U = k&lt;br /&gt;
    Index_V = k + n - 1&lt;br /&gt;
    Flag_U always set&lt;br /&gt;
    Flag_V always clear&lt;br /&gt;
    (Same values as FAT[k + 1])&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* Note: all indices above are entry indices (block index + 1)&lt;br /&gt;
&lt;br /&gt;
All free blocks that are not allocated to any files also form a node chain in the allocation table. The head index of this &amp;amp;quot;free chain&amp;amp;quot; is recorded in &amp;lt;code&amp;gt;FAT[0].Index_V&amp;lt;/code&amp;gt;. Other fields of &amp;lt;code&amp;gt;FAT[0]&amp;lt;/code&amp;gt; are all zero&lt;br /&gt;
&lt;br /&gt;
Here is an example: [https://raw.githubusercontent.com/wwylele/3ds-save-tool/master/disa-fat.png]&lt;br /&gt;
&lt;br /&gt;
For extdata, because only two &amp;quot;files&amp;quot; (directory and file entry tables) are allocated in the data region, and their size never changes once the extdata is created, they are guaranteed continuous in the data region, and the FAT degenerates to two big nodes. Therefore, instead of going through FAT, the offset and size of directory / file entry table can be found directly by offset = entry_table_starting block * data_region_block_size + data_region_offset and size = entry_table_block_count * data_region_block_size.&lt;/div&gt;</summary>
		<author><name>Wwylele</name></author>
	</entry>
	<entry>
		<id>https://www.3dbrew.org/w/index.php?title=Inner_FAT&amp;diff=20967</id>
		<title>Inner FAT</title>
		<link rel="alternate" type="text/html" href="https://www.3dbrew.org/w/index.php?title=Inner_FAT&amp;diff=20967"/>
		<updated>2019-05-15T08:54:51Z</updated>

		<summary type="html">&lt;p&gt;Wwylele: /* Filesystem Header */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This page describes a common FAT-like file system used in [[Savegames]], [[Extdata]] and [[Title Database]]. This file system format has several variants depending on which kind of data it stores. All the three kinds of data that use this file system structure also happen to use the [[DISA and DIFF]] container as well, but there is no direct relationship between the file system and the DISA/DIFF container. All data formats described here is in the inner data of the DISA/DIFF container (i.e. IVFC level 4). Please refer to the DISA/DIFF page for how to unwrap it first before trying to extract the file system.&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
&lt;br /&gt;
The file system consists of the following components:&lt;br /&gt;
* header&lt;br /&gt;
* directory hash table&lt;br /&gt;
* file hash table&lt;br /&gt;
* file allocation table&lt;br /&gt;
* directory entry table&lt;br /&gt;
* file entry table&lt;br /&gt;
* data region&lt;br /&gt;
&lt;br /&gt;
The file allocation table (FAT) forms several linked lists inside, each of which represents a &amp;quot;file&amp;quot; allocated in the data region. Please refer to the File Allocation Table section below for more detail. In some variants, the directory entry table and the file entry table are also allocated as two special &amp;quot;files&amp;quot; in the data region, managed by the FAT, while in others they are stand-alone tables located outside the data region.&lt;br /&gt;
&lt;br /&gt;
== Layout Variants ==&lt;br /&gt;
Four variants of the file system layout has been identified. A summary diagram can be found here: [https://github.com/wwylele/3ds-save-tool/raw/master/inner-fat.png]&lt;br /&gt;
&lt;br /&gt;
=== Savegame, &amp;lt;code&amp;gt;duplicate data = true&amp;lt;/code&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
Such savegame is a single DISA container that only has one partition which is always configured as external IVFC level 4 disabled (see [[DISA and DIFF|DISA]] format for details). All components are stored in this partition as&lt;br /&gt;
&lt;br /&gt;
* filesystem header at the beginning&lt;br /&gt;
* directory hash table&lt;br /&gt;
* file hash table&lt;br /&gt;
* file allocation table&lt;br /&gt;
* data region&lt;br /&gt;
** directory entry table is allocated inside data region&lt;br /&gt;
** file entry table as well&lt;br /&gt;
** all file data is also allocated here&lt;br /&gt;
&lt;br /&gt;
In this layout, all data is duplicated by DISA&#039;s DPFS tree, which is what the parameter &amp;lt;code&amp;gt;duplicate data&amp;lt;/code&amp;gt; implies.&lt;br /&gt;
&lt;br /&gt;
=== Savegame, &amp;lt;code&amp;gt;duplicate data = false&amp;lt;/code&amp;gt; === &lt;br /&gt;
Such savegame is a single DISA container that has two partitions. Partition A is always configured as external IVFC level 4 disabled, and partition B is configured as it enabled. Components are stored among the two partitions as&lt;br /&gt;
&lt;br /&gt;
* Partition A&lt;br /&gt;
** filesystem header at the beginning.&lt;br /&gt;
** directory hash table&lt;br /&gt;
** file hash table&lt;br /&gt;
** (stand-alone) file allocation table&lt;br /&gt;
** (stand-alone) directory entry table&lt;br /&gt;
** file entry table&lt;br /&gt;
* Partition B&lt;br /&gt;
** used as data region entirely, and only has file data allocated.&lt;br /&gt;
&lt;br /&gt;
In this layout, all file system metadata is duplicated by partition A DPFS tree, but file data is not as partition B has external IVFC level 4.&lt;br /&gt;
&lt;br /&gt;
=== Extdata ===&lt;br /&gt;
An extdata consists of several DIFF containers (device files), among which the special device file &amp;lt;code&amp;gt;00000000/00000001&amp;lt;/code&amp;gt; contains the inner FAT system, while other devices contains normal subfiles of the extdata. Please refer to [[Extdata]] for detail. The special file &amp;lt;code&amp;gt;00000000/00000001&amp;lt;/code&amp;gt; contists of the following components&lt;br /&gt;
&lt;br /&gt;
* filesystem header at the beginning&lt;br /&gt;
* directory hash table&lt;br /&gt;
* file hash table&lt;br /&gt;
* file allocation table (degenerate, because the data region only has two &amp;quot;files&amp;quot;: the directory entry table and the file entry table)&lt;br /&gt;
* data region&lt;br /&gt;
** directory entry table allocated inside data region&lt;br /&gt;
** file entry table as well&lt;br /&gt;
** normal subfiles are NOT in the data region. They are in their DIFF containers instead.&lt;br /&gt;
&lt;br /&gt;
=== Title database ===&lt;br /&gt;
All [[Title Database]] files are DIFF containers. Except for &amp;lt;code&amp;gt;certs.db&amp;lt;/code&amp;gt;, all of them uses this filesystem in the DIFF inner data, which consists of&lt;br /&gt;
&lt;br /&gt;
* database-specific pre-header at the beginning (See [[Title Database]])&lt;br /&gt;
* filesystem header&lt;br /&gt;
* directory Hash Table (degenerate and always has only one bucket, as there is only one directory for &amp;quot;root&amp;quot;)&lt;br /&gt;
* file Hash Table&lt;br /&gt;
* file allocation table&lt;br /&gt;
* data region&lt;br /&gt;
** directory entry table allocated inside data region (degenerate, as there is only one directory for &amp;quot;root&amp;quot;)&lt;br /&gt;
** file entry table as well&lt;br /&gt;
** title entries (title info or ticket) are allocated as normal files in the data region as well.&lt;br /&gt;
&lt;br /&gt;
== Filesystem Header ==&lt;br /&gt;
Offsets listed in the table below are all relative to the beginning of the header, while all &amp;quot;starting block index&amp;quot; are relative to the beginning of data region. This is especially important for title database, as the offsets doesn&#039;t count the pre header.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! Offset&lt;br /&gt;
! Length&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x00&lt;br /&gt;
| 4&lt;br /&gt;
| Magic (&amp;quot;SAVE&amp;quot; for savegame; &amp;quot;BDRI&amp;quot; for title database; &amp;quot;VSXE&amp;quot; for extdata)&lt;br /&gt;
|-&lt;br /&gt;
| 0x04&lt;br /&gt;
| 4&lt;br /&gt;
| Version (0x40000 for savegame; 0x30000 for title database and extdata)&lt;br /&gt;
|-&lt;br /&gt;
| 0x08&lt;br /&gt;
| 8&lt;br /&gt;
| Filesystem Information offset (Y, =0x20 for savegame and title database, =0x138 for extdata)&lt;br /&gt;
|-&lt;br /&gt;
| 0x10&lt;br /&gt;
| 8&lt;br /&gt;
| Filesystem image size in blocks (including pre header for title database)&lt;br /&gt;
|-&lt;br /&gt;
| 0x18&lt;br /&gt;
| 4&lt;br /&gt;
| Filesystem Image block size&lt;br /&gt;
|-&lt;br /&gt;
| 0x1C&lt;br /&gt;
| 4&lt;br /&gt;
| Padding&lt;br /&gt;
|-&lt;br /&gt;
| 0x20 &lt;br /&gt;
| 0x118 in total&lt;br /&gt;
| Below is additional data for extdata. Not present in savegame or title database&lt;br /&gt;
|-&lt;br /&gt;
| 0x20&lt;br /&gt;
| 8&lt;br /&gt;
| Unknown&lt;br /&gt;
|-&lt;br /&gt;
| 0x28&lt;br /&gt;
| 4&lt;br /&gt;
| &#039;Action&#039; made on most recently mounted Extdata image&lt;br /&gt;
|-&lt;br /&gt;
| 0x2C&lt;br /&gt;
| 4&lt;br /&gt;
| Unknown&lt;br /&gt;
|-&lt;br /&gt;
| 0x30&lt;br /&gt;
| 4&lt;br /&gt;
| ID of most recently mounted Extdata image&lt;br /&gt;
|-&lt;br /&gt;
| 0x34&lt;br /&gt;
| 4&lt;br /&gt;
| Unknown&lt;br /&gt;
|-&lt;br /&gt;
| 0x38&lt;br /&gt;
| 0x100&lt;br /&gt;
| Mount path, from most recently mounted Extdata image&lt;br /&gt;
|-&lt;br /&gt;
| Y &lt;br /&gt;
| 0x68 in total&lt;br /&gt;
| Below is Filesystem Information&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x00&lt;br /&gt;
| 4&lt;br /&gt;
| Unknown&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x04&lt;br /&gt;
| 4&lt;br /&gt;
| Data region block size&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x08&lt;br /&gt;
| 8&lt;br /&gt;
| Directory hash table offset&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x10&lt;br /&gt;
| 4&lt;br /&gt;
| Directory hash table bucket count (=1 for title database)&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x14&lt;br /&gt;
| 4&lt;br /&gt;
| Padding&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x18&lt;br /&gt;
| 8&lt;br /&gt;
| File hash table offset&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x20&lt;br /&gt;
| 4&lt;br /&gt;
| File hash table bucket count&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x24&lt;br /&gt;
| 4&lt;br /&gt;
| Padding&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x28&lt;br /&gt;
| 8&lt;br /&gt;
| File allocation table offset&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x30&lt;br /&gt;
| 4&lt;br /&gt;
| File allocation table entry count &lt;br /&gt;
(excluding the leading 0th entry. See below)&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x34&lt;br /&gt;
| 4&lt;br /&gt;
| Padding&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x38&lt;br /&gt;
| 8&lt;br /&gt;
| Data region offset &lt;br /&gt;
(0 for savegame &amp;lt;code&amp;gt;duplicate data = false&amp;lt;/code&amp;gt; layout, as the data region is in partition B for that layout)&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x40&lt;br /&gt;
| 4&lt;br /&gt;
| Data region block count &lt;br /&gt;
(= File allocation table entry count)&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x44&lt;br /&gt;
| 4&lt;br /&gt;
| Padding&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x48&lt;br /&gt;
| 8&lt;br /&gt;
| for savegame &amp;lt;code&amp;gt;duplicate data = false&amp;lt;/code&amp;gt; layout: directory entry table offset;&lt;br /&gt;
otherwise: u32 directory entry table starting block index + u32 directory entry table block count&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x50&lt;br /&gt;
| 4&lt;br /&gt;
| Maximum directory count, excluding the mandatory &amp;quot;root&amp;quot; directory &lt;br /&gt;
(=1 for title database, but that 1 free directory slot is never used)&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x54&lt;br /&gt;
| 4&lt;br /&gt;
| Padding&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x58&lt;br /&gt;
| 8&lt;br /&gt;
| for savegame &amp;lt;code&amp;gt;duplicate data = false&amp;lt;/code&amp;gt; layout: file entry table offset;&lt;br /&gt;
otherwise: u32 file entry table starting block index + u32 file entry table block count&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x60&lt;br /&gt;
| 4&lt;br /&gt;
| Maximum file count&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x64&lt;br /&gt;
| 4&lt;br /&gt;
| Padding&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
* For savegames, the file/directory bucket count &amp;amp; maximum count are specified by the parameters of [[FS:FormatSaveData]] or [[FS:CreateSystemSaveData]].&lt;br /&gt;
* For extdata, the maximum file/directory count are specified by the parameters of [[FS:CreateExtSaveData]]. The bucket count is likely calculated by the system.&lt;br /&gt;
* Directory &amp;amp; file entry tables are allocated in the data region as if they are two normal files (except for savegame &amp;lt;code&amp;gt;duplicate data = false&amp;lt;/code&amp;gt; layout). However, only continuous allocation has been observed, so directly reading block_count * block_size bytes from data_region + starting_block_index * block_size should be safe.&lt;br /&gt;
&lt;br /&gt;
== Directory Entry Table ==&lt;br /&gt;
&lt;br /&gt;
The directory entry table is an array of the entry type shown below. It describes the directory hierarchy of the file system. There are two variants of the directory entry type, and a dummy entry type.&lt;br /&gt;
&lt;br /&gt;
=== Savegame/Extdata Variant===&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! Offset&lt;br /&gt;
! Length&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x00&lt;br /&gt;
| 4&lt;br /&gt;
| Parent directory index. 0 for root&lt;br /&gt;
|-&lt;br /&gt;
| 0x04&lt;br /&gt;
| 16&lt;br /&gt;
| ASCII directory name in. All zero for root&lt;br /&gt;
|-&lt;br /&gt;
| 0x14&lt;br /&gt;
| 4&lt;br /&gt;
| Next sibling directory index. 0 if this is the last one&lt;br /&gt;
|-&lt;br /&gt;
| 0x18&lt;br /&gt;
| 4&lt;br /&gt;
| First subdirectory index. 0 if not exists&lt;br /&gt;
|-&lt;br /&gt;
| 0x1C&lt;br /&gt;
| 4&lt;br /&gt;
| First file index in file entry table. 0 for empty directory&lt;br /&gt;
|-&lt;br /&gt;
| 0x20&lt;br /&gt;
| 4&lt;br /&gt;
| Padding / zero?&lt;br /&gt;
|-&lt;br /&gt;
| 0x24&lt;br /&gt;
| 4&lt;br /&gt;
| Index of the next directory in the same hash table bucket. 0 if this is the last one&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Title Database Variant===&lt;br /&gt;
Because title database only has one directory for &amp;quot;root&amp;quot;, its directory entry table degenerates into many zeros whose structure is not recognizable. The size of one entry here is guessed.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! Offset&lt;br /&gt;
! Length&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x00&lt;br /&gt;
| 4&lt;br /&gt;
| Parent directory index = 0 for root&lt;br /&gt;
|-&lt;br /&gt;
| 0x04&lt;br /&gt;
| 4&lt;br /&gt;
| Next sibling directory index = 0 because this is the last one&lt;br /&gt;
|-&lt;br /&gt;
| 0x08&lt;br /&gt;
| 4&lt;br /&gt;
| First subdirectory index = 0 because there is no subdirectory&lt;br /&gt;
|-&lt;br /&gt;
| 0x0C&lt;br /&gt;
| 4&lt;br /&gt;
| First file index in file entry table. 0 for empty directory&lt;br /&gt;
|-&lt;br /&gt;
| 0x10&lt;br /&gt;
| 12&lt;br /&gt;
| Padding / zero?&lt;br /&gt;
|-&lt;br /&gt;
| 0x1C&lt;br /&gt;
| 4&lt;br /&gt;
| Index of the next directory in the same hash table bucket = 0 because there is no other directory&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Dummy Entry===&lt;br /&gt;
There are also some dummy entries in the array&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! Offset&lt;br /&gt;
! Length&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x00&lt;br /&gt;
| 4&lt;br /&gt;
| Current Total entry count&lt;br /&gt;
|-&lt;br /&gt;
| 0x04&lt;br /&gt;
| 4&lt;br /&gt;
| Maximum entry count = maximum directory count + 2&lt;br /&gt;
|-&lt;br /&gt;
| 0x08&lt;br /&gt;
| 28/20&lt;br /&gt;
| Padding / All zero&lt;br /&gt;
|-&lt;br /&gt;
| 0x24/0x1C&lt;br /&gt;
| 4&lt;br /&gt;
| Index of the next dummy entry. 0 if this is the last one&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The 0-th entry of the array is always a dummy entry, which functions as the head of the dummy entry linked list. The 1-st entry of the array is always the root. Therefore maximum entry count is two more than maximum directory count. Dummy entries are left there when deleting directories, and reserved for future use.&lt;br /&gt;
&lt;br /&gt;
== File Entry Table ==&lt;br /&gt;
&lt;br /&gt;
The file entry table is an array of the entry type shown below. It contains information for each file. There are three variants of the file entry type, and a dummy entry type.&lt;br /&gt;
&lt;br /&gt;
=== Savegame Variant ===&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! Offset&lt;br /&gt;
! Length&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x00&lt;br /&gt;
| 4&lt;br /&gt;
| Parent directory index in directory entry table&lt;br /&gt;
|-&lt;br /&gt;
| 0x04&lt;br /&gt;
| 16&lt;br /&gt;
| ASCII file name&lt;br /&gt;
|-&lt;br /&gt;
| 0x14&lt;br /&gt;
| 4&lt;br /&gt;
| Next sibling file index. 0 if this is the last one&lt;br /&gt;
|-&lt;br /&gt;
| 0x18&lt;br /&gt;
| 4&lt;br /&gt;
| Padding&lt;br /&gt;
|-&lt;br /&gt;
| 0x1C&lt;br /&gt;
| 4&lt;br /&gt;
| First block index in data region. 0x80000000 if the file is just created and has no data.&lt;br /&gt;
|-&lt;br /&gt;
| 0x20&lt;br /&gt;
| 8&lt;br /&gt;
| File Size&lt;br /&gt;
|-&lt;br /&gt;
| 0x28&lt;br /&gt;
| 4&lt;br /&gt;
| Padding?&lt;br /&gt;
|-&lt;br /&gt;
| 0x2C&lt;br /&gt;
| 4&lt;br /&gt;
| Index of the next file in the same hash table bucket. 0 if this is the last one&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Extdata Variant ===&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! Offset&lt;br /&gt;
! Length&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x00&lt;br /&gt;
| 4&lt;br /&gt;
| Parent directory index in directory entry table&lt;br /&gt;
|-&lt;br /&gt;
| 0x04&lt;br /&gt;
| 16&lt;br /&gt;
| ASCII file name&lt;br /&gt;
|-&lt;br /&gt;
| 0x14&lt;br /&gt;
| 4&lt;br /&gt;
| Next sibling file index. 0 if this is the last one&lt;br /&gt;
|-&lt;br /&gt;
| 0x18&lt;br /&gt;
| 4&lt;br /&gt;
| Padding&lt;br /&gt;
|-&lt;br /&gt;
| 0x1C&lt;br /&gt;
| 4&lt;br /&gt;
| Always 0x80000000&lt;br /&gt;
|-&lt;br /&gt;
| 0x20&lt;br /&gt;
| 8&lt;br /&gt;
| Unique identifier. See [[Extdata]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x28&lt;br /&gt;
| 4&lt;br /&gt;
| Padding?&lt;br /&gt;
|-&lt;br /&gt;
| 0x2C&lt;br /&gt;
| 4&lt;br /&gt;
| Index of the next file in the same hash table bucket. 0 if this is the last one&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Title database Variant ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! Offset&lt;br /&gt;
! Length&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x00&lt;br /&gt;
| 4&lt;br /&gt;
| Parent directory index in directory entry table&lt;br /&gt;
|-&lt;br /&gt;
| 0x04&lt;br /&gt;
| 8&lt;br /&gt;
| Title ID&lt;br /&gt;
|-&lt;br /&gt;
| 0x0C&lt;br /&gt;
| 4&lt;br /&gt;
| Next sibling file index. 0 if this is the last one&lt;br /&gt;
|-&lt;br /&gt;
| 0x10&lt;br /&gt;
| 4&lt;br /&gt;
| Padding&lt;br /&gt;
|-&lt;br /&gt;
| 0x14&lt;br /&gt;
| 4&lt;br /&gt;
| First block index in data region.&lt;br /&gt;
|-&lt;br /&gt;
| 0x18&lt;br /&gt;
| 8&lt;br /&gt;
| File size&lt;br /&gt;
|-&lt;br /&gt;
| 0x20&lt;br /&gt;
| 8&lt;br /&gt;
| Padding?&lt;br /&gt;
|-&lt;br /&gt;
| 0x28&lt;br /&gt;
| 4&lt;br /&gt;
| Index of the next file in the same hash table bucket. 0 if this is the last one&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Dummy Entry ===&lt;br /&gt;
Like directory entry table, file entry table also has some dummy entries:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! Offset&lt;br /&gt;
! Length&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x00&lt;br /&gt;
| 4&lt;br /&gt;
| Current total entry count&lt;br /&gt;
|-&lt;br /&gt;
| 0x04&lt;br /&gt;
| 4&lt;br /&gt;
| Maximum entry count = maximum file count + 1&lt;br /&gt;
|-&lt;br /&gt;
| 0x08&lt;br /&gt;
| 36/32&lt;br /&gt;
| Padding / All zero&lt;br /&gt;
|-&lt;br /&gt;
| 0x2C/0x28&lt;br /&gt;
| 4&lt;br /&gt;
| Index of the next dummy entry. 0 if this is the last one&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The 0-th entry of the array is always a dummy entry, which functions as the head of the dummy entry linked list. Therefore maximum entry count is one more than maximum file count. Dummy entries are left there when deleting files, and reserved for future use.&lt;br /&gt;
&lt;br /&gt;
== Directory Hash Table &amp;amp;amp; File Hash Table ==&lt;br /&gt;
&lt;br /&gt;
This is a u32 array of size = bucket count, each of which is an index to the directory / file entry table. The directory / file name is hashed and its entry index is put to the corresponding bucket. If there is already a directory/file entry in the bucket, then it appends to the linked list formed by &amp;lt;code&amp;gt;Index of the next directory/file in the same hash table bucket&amp;lt;/code&amp;gt; field in the directory/file entry table. i.e. this is a hash table using separate chaining with linked lists&lt;br /&gt;
&lt;br /&gt;
The hash function takes the parent index and the ASCII name (or title ID for title database) as key. The function is equivalent to&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;uint32_t GetBucket(&lt;br /&gt;
    char name[16 or 8], // For savegame/extdata, this takes all 16 bytes including trailing zeros; For title database, this is the 8-byte title ID&lt;br /&gt;
    uint32_t parent_dir_index,&lt;br /&gt;
    uint32_t bucket_count&lt;br /&gt;
) {&lt;br /&gt;
    uint32_t hash = parent_dir_index ^ 0x091A2B3C;&lt;br /&gt;
    for (int i = 0; i &amp;amp;lt; 4 or 2; ++i) {&lt;br /&gt;
        hash = (hash &amp;amp;gt;&amp;amp;gt; 1) | (hash &amp;amp;lt;&amp;amp;lt; 31);&lt;br /&gt;
        hash ^= (uint32_t)name[i * 4]&lt;br /&gt;
        hash ^= (uint32_t)name[i * 4 + 1] &amp;amp;lt;&amp;amp;lt; 8&lt;br /&gt;
        hash ^= (uint32_t)name[i * 4 + 2] &amp;amp;lt;&amp;amp;lt; 16&lt;br /&gt;
        hash ^= (uint32_t)name[i * 4 + 3] &amp;amp;lt;&amp;amp;lt; 24&lt;br /&gt;
    }&lt;br /&gt;
    return hash % bucket_count;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== File Allocation Table ==&lt;br /&gt;
&lt;br /&gt;
The file allocation table is an array of a 8-byte entry shown below. The array size is actually &#039;&#039;one larger than&#039;&#039; the size recorded in the filesystem header. Each entry corresponds to a block in the data region (the block size is defined in filesystem header). However, the 0th entry corresponds to nothing, so the corresponding block index is off by one. e.g. entry 31 in this table corresponds to block 30 in the data region.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! Offset&lt;br /&gt;
! Length&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x00&lt;br /&gt;
| 4&lt;br /&gt;
| bit[0:30]: Index U; bit[31]: Flag U&lt;br /&gt;
|-&lt;br /&gt;
| 0x04&lt;br /&gt;
| 4&lt;br /&gt;
| bit[0:30]: Index V; bit[31]: Flag V&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Entries in this table forms several chains, representing how blocks in the data region should be linked together. However, unlike normal FAT systems, which uses chains of entries, 3DS savegames use chain of &#039;&#039;nodes&#039;&#039;. Each node spans one or multiple entries.&lt;br /&gt;
&lt;br /&gt;
One node spanning &amp;lt;code&amp;gt;n&amp;lt;/code&amp;gt; entries starting from &amp;lt;code&amp;gt;FAT[k]&amp;lt;/code&amp;gt; is in the following format:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;FAT[k + 0]:&lt;br /&gt;
    Index_U = index of the first entry of the previous node. 0 if this is the first node.&lt;br /&gt;
    Index_V = index of the first entry of the next node. 0 if this is the last node.&lt;br /&gt;
    Flag_U set if this is the first node.&lt;br /&gt;
    Flag_V set if this node has multiple entries.&lt;br /&gt;
&lt;br /&gt;
FAT[k + 1]:&lt;br /&gt;
    Index_U = k (the first entry index of this node)&lt;br /&gt;
    Index_V = k + n - 1 (the last entry index of this node)&lt;br /&gt;
    Flag_U always set&lt;br /&gt;
    Flag_V always clear&lt;br /&gt;
&lt;br /&gt;
FAT[k + 2] ~ FAT[k + n - 2]:&lt;br /&gt;
    All these entries are uninitialized&lt;br /&gt;
&lt;br /&gt;
FAT[k + n - 1]:&lt;br /&gt;
    Index_U = k&lt;br /&gt;
    Index_V = k + n - 1&lt;br /&gt;
    Flag_U always set&lt;br /&gt;
    Flag_V always clear&lt;br /&gt;
    (Same values as FAT[k + 1])&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* Note: all indices above are entry indices (block index + 1)&lt;br /&gt;
&lt;br /&gt;
All free blocks that are not allocated to any files also form a node chain in the allocation table. The head index of this &amp;amp;quot;free chain&amp;amp;quot; is recorded in &amp;lt;code&amp;gt;FAT[0].Index_V&amp;lt;/code&amp;gt;. Other fields of &amp;lt;code&amp;gt;FAT[0]&amp;lt;/code&amp;gt; are all zero&lt;br /&gt;
&lt;br /&gt;
Here is an example: [https://raw.githubusercontent.com/wwylele/3ds-save-tool/master/disa-fat.png]&lt;br /&gt;
&lt;br /&gt;
For extdata, because only two &amp;quot;files&amp;quot; (directory and file entry tables) are allocated in the data region, and their size never changes once the extdata is created, they are guaranteed continuous in the data region, and the FAT degenerates to two big nodes. Therefore, instead of going through FAT, the offset and size of directory / file entry table can be found directly by offset = entry_table_starting block * data_region_block_size + data_region_offset and size = entry_table_block_count * data_region_block_size.&lt;/div&gt;</summary>
		<author><name>Wwylele</name></author>
	</entry>
	<entry>
		<id>https://www.3dbrew.org/w/index.php?title=Inner_FAT&amp;diff=20950</id>
		<title>Inner FAT</title>
		<link rel="alternate" type="text/html" href="https://www.3dbrew.org/w/index.php?title=Inner_FAT&amp;diff=20950"/>
		<updated>2019-05-05T12:15:04Z</updated>

		<summary type="html">&lt;p&gt;Wwylele: /* Filesystem Header */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This page describes a common FAT-like file system used in [[Savegames]], [[Extdata]] and [[Title Database]]. This file system format has several variants depending on which kind of data it stores. All the three kinds of data that use this file system structure also happen to use the [[DISA and DIFF]] container as well, but there is no direct relationship between the file system and the DISA/DIFF container. All data formats described here is in the inner data of the DISA/DIFF container (i.e. IVFC level 4). Please refer to the DISA/DIFF page for how to unwrap it first before trying to extract the file system.&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
&lt;br /&gt;
The file system consists of the following components:&lt;br /&gt;
* header&lt;br /&gt;
* directory hash table&lt;br /&gt;
* file hash table&lt;br /&gt;
* file allocation table&lt;br /&gt;
* directory entry table&lt;br /&gt;
* file entry table&lt;br /&gt;
* data region&lt;br /&gt;
&lt;br /&gt;
The file allocation table (FAT) forms several linked lists inside, each of which represents a &amp;quot;file&amp;quot; allocated in the data region. Please refer to the File Allocation Table section below for more detail. In some variants, the directory entry table and the file entry table are also allocated as two special &amp;quot;files&amp;quot; in the data region, managed by the FAT, while in others they are stand-alone tables located outside the data region.&lt;br /&gt;
&lt;br /&gt;
== Layout Variants ==&lt;br /&gt;
Four variants of the file system layout has been identified. A summary diagram can be found here: [https://github.com/wwylele/3ds-save-tool/raw/master/inner-fat.png]&lt;br /&gt;
&lt;br /&gt;
=== Savegame, &amp;lt;code&amp;gt;duplicate data = true&amp;lt;/code&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
Such savegame is a single DISA container that only has one partition which is always configured as external IVFC level 4 disabled (see [[DISA and DIFF|DISA]] format for details). All components are stored in this partition as&lt;br /&gt;
&lt;br /&gt;
* filesystem header at the beginning&lt;br /&gt;
* directory hash table&lt;br /&gt;
* file hash table&lt;br /&gt;
* file allocation table&lt;br /&gt;
* data region&lt;br /&gt;
** directory entry table is allocated inside data region&lt;br /&gt;
** file entry table as well&lt;br /&gt;
** all file data is also allocated here&lt;br /&gt;
&lt;br /&gt;
In this layout, all data is duplicated by DISA&#039;s DPFS tree, which is what the parameter &amp;lt;code&amp;gt;duplicate data&amp;lt;/code&amp;gt; implies.&lt;br /&gt;
&lt;br /&gt;
=== Savegame, &amp;lt;code&amp;gt;duplicate data = false&amp;lt;/code&amp;gt; === &lt;br /&gt;
Such savegame is a single DISA container that has two partitions. Partition A is always configured as external IVFC level 4 disabled, and partition B is configured as it enabled. Components are stored among the two partitions as&lt;br /&gt;
&lt;br /&gt;
* Partition A&lt;br /&gt;
** filesystem header at the beginning.&lt;br /&gt;
** directory hash table&lt;br /&gt;
** file hash table&lt;br /&gt;
** (stand-alone) file allocation table&lt;br /&gt;
** (stand-alone) directory entry table&lt;br /&gt;
** file entry table&lt;br /&gt;
* Partition B&lt;br /&gt;
** used as data region entirely, and only has file data allocated.&lt;br /&gt;
&lt;br /&gt;
In this layout, all file system metadata is duplicated by partition A DPFS tree, but file data is not as partition B has external IVFC level 4.&lt;br /&gt;
&lt;br /&gt;
=== Extdata ===&lt;br /&gt;
An extdata consists of several DIFF containers (device files), among which the special device file &amp;lt;code&amp;gt;00000000/00000001&amp;lt;/code&amp;gt; contains the inner FAT system, while other devices contains normal subfiles of the extdata. Please refer to [[Extdata]] for detail. The special file &amp;lt;code&amp;gt;00000000/00000001&amp;lt;/code&amp;gt; contists of the following components&lt;br /&gt;
&lt;br /&gt;
* filesystem header at the beginning&lt;br /&gt;
* directory hash table&lt;br /&gt;
* file hash table&lt;br /&gt;
* file allocation table (degenerate, because the data region only has two &amp;quot;files&amp;quot;: the directory entry table and the file entry table)&lt;br /&gt;
* data region&lt;br /&gt;
** directory entry table allocated inside data region&lt;br /&gt;
** file entry table as well&lt;br /&gt;
** normal subfiles are NOT in the data region. They are in their DIFF containers instead.&lt;br /&gt;
&lt;br /&gt;
=== Title database ===&lt;br /&gt;
All [[Title Database]] files are DIFF containers. Except for &amp;lt;code&amp;gt;certs.db&amp;lt;/code&amp;gt;, all of them uses this filesystem in the DIFF inner data, which consists of&lt;br /&gt;
&lt;br /&gt;
* database-specific pre-header at the beginning (See [[Title Database]])&lt;br /&gt;
* filesystem header&lt;br /&gt;
* directory Hash Table (degenerate and always has only one bucket, as there is only one directory for &amp;quot;root&amp;quot;)&lt;br /&gt;
* file Hash Table&lt;br /&gt;
* file allocation table&lt;br /&gt;
* data region&lt;br /&gt;
** directory entry table allocated inside data region (degenerate, as there is only one directory for &amp;quot;root&amp;quot;)&lt;br /&gt;
** file entry table as well&lt;br /&gt;
** title entries (title info or ticket) are allocated as normal files in the data region as well.&lt;br /&gt;
&lt;br /&gt;
== Filesystem Header ==&lt;br /&gt;
Offsets listed in the table below are all relative to the beginning of the header, while all &amp;quot;starting block index&amp;quot; are relative to the beginning of data region. This is especially important for title database, as the offsets doesn&#039;t count the pre header.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! Offset&lt;br /&gt;
! Length&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x00&lt;br /&gt;
| 4&lt;br /&gt;
| Magic (&amp;quot;SAVE&amp;quot; for savegame; &amp;quot;BDRI&amp;quot; for title database; &amp;quot;VSXE&amp;quot; for extdata)&lt;br /&gt;
|-&lt;br /&gt;
| 0x04&lt;br /&gt;
| 4&lt;br /&gt;
| Version (0x40000 for savegame; 0x30000 for title database and extdata)&lt;br /&gt;
|-&lt;br /&gt;
| 0x08&lt;br /&gt;
| 8&lt;br /&gt;
| Filesystem Information offset (Y, =0x20 for savegame and title database, =0x138 for extdata)&lt;br /&gt;
|-&lt;br /&gt;
| 0x10&lt;br /&gt;
| 8&lt;br /&gt;
| Filesystem image size in blocks (including pre header for title database)&lt;br /&gt;
|-&lt;br /&gt;
| 0x18&lt;br /&gt;
| 4&lt;br /&gt;
| Filesystem Image block size&lt;br /&gt;
|-&lt;br /&gt;
| 0x1C&lt;br /&gt;
| 4&lt;br /&gt;
| Padding&lt;br /&gt;
|-&lt;br /&gt;
| 0x20 &lt;br /&gt;
| 0x118 in total&lt;br /&gt;
| Below is additional data for extdata. Not present in savegame or title database&lt;br /&gt;
|-&lt;br /&gt;
| 0x20&lt;br /&gt;
| 8&lt;br /&gt;
| Unknown&lt;br /&gt;
|-&lt;br /&gt;
| 0x28&lt;br /&gt;
| 4&lt;br /&gt;
| &#039;Action&#039; made on most recently mounted Extdata image&lt;br /&gt;
|-&lt;br /&gt;
| 0x2C&lt;br /&gt;
| 4&lt;br /&gt;
| Unknown&lt;br /&gt;
|-&lt;br /&gt;
| 0x30&lt;br /&gt;
| 4&lt;br /&gt;
| D of most recently mounted Extdata image&lt;br /&gt;
|-&lt;br /&gt;
| 0x34&lt;br /&gt;
| 4&lt;br /&gt;
| Unknown&lt;br /&gt;
|-&lt;br /&gt;
| 0x38&lt;br /&gt;
| 0x100&lt;br /&gt;
| Mount path, from most recently mounted Extdata image&lt;br /&gt;
|-&lt;br /&gt;
| Y &lt;br /&gt;
| 0x68 in total&lt;br /&gt;
| Below is Filesystem Information&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x00&lt;br /&gt;
| 4&lt;br /&gt;
| Unknown&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x04&lt;br /&gt;
| 4&lt;br /&gt;
| Data region block size&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x08&lt;br /&gt;
| 8&lt;br /&gt;
| Directory hash table offset&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x10&lt;br /&gt;
| 4&lt;br /&gt;
| Directory hash table bucket count (=1 for title database)&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x14&lt;br /&gt;
| 4&lt;br /&gt;
| Padding&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x18&lt;br /&gt;
| 8&lt;br /&gt;
| File hash table offset&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x20&lt;br /&gt;
| 4&lt;br /&gt;
| File hash table bucket count&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x24&lt;br /&gt;
| 4&lt;br /&gt;
| Padding&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x28&lt;br /&gt;
| 8&lt;br /&gt;
| File allocation table offset&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x30&lt;br /&gt;
| 4&lt;br /&gt;
| File allocation table entry count &lt;br /&gt;
(excluding the leading 0th entry. See below)&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x34&lt;br /&gt;
| 4&lt;br /&gt;
| Padding&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x38&lt;br /&gt;
| 8&lt;br /&gt;
| Data region offset &lt;br /&gt;
(0 for savegame &amp;lt;code&amp;gt;duplicate data = false&amp;lt;/code&amp;gt; layout, as the data region is in partition B for that layout)&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x40&lt;br /&gt;
| 4&lt;br /&gt;
| Data region block count &lt;br /&gt;
(= File allocation table entry count)&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x44&lt;br /&gt;
| 4&lt;br /&gt;
| Padding&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x48&lt;br /&gt;
| 8&lt;br /&gt;
| for savegame &amp;lt;code&amp;gt;duplicate data = false&amp;lt;/code&amp;gt; layout: directory entry table offset;&lt;br /&gt;
otherwise: u32 directory entry table starting block index + u32 directory entry table block count&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x50&lt;br /&gt;
| 4&lt;br /&gt;
| Maximum directory count, excluding the mandatory &amp;quot;root&amp;quot; directory &lt;br /&gt;
(=1 for title database, but that 1 free directory slot is never used)&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x54&lt;br /&gt;
| 4&lt;br /&gt;
| Padding&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x58&lt;br /&gt;
| 8&lt;br /&gt;
| for savegame &amp;lt;code&amp;gt;duplicate data = false&amp;lt;/code&amp;gt; layout: file entry table offset;&lt;br /&gt;
otherwise: u32 file entry table starting block index + u32 file entry table block count&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x60&lt;br /&gt;
| 4&lt;br /&gt;
| Maximum file count&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x64&lt;br /&gt;
| 4&lt;br /&gt;
| Padding&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
* For savegames, the file/directory bucket count &amp;amp; maximum count are specified by the parameters of [[FS:FormatSaveData]] or [[FS:CreateSystemSaveData]].&lt;br /&gt;
* For extdata, the maximum file/directory count are specified by the parameters of [[FS:CreateExtSaveData]]. The bucket count is likely calculated by the system.&lt;br /&gt;
* Directory &amp;amp; file entry tables are allocated in the data region as if they are two normal files (except for savegame &amp;lt;code&amp;gt;duplicate data = false&amp;lt;/code&amp;gt; layout). However, only continuous allocation has been observed, so directly reading block_count * block_size bytes from data_region + starting_block_index * block_size should be safe.&lt;br /&gt;
&lt;br /&gt;
== Directory Entry Table ==&lt;br /&gt;
&lt;br /&gt;
The directory entry table is an array of the entry type shown below. It describes the directory hierarchy of the file system. There are two variants of the directory entry type, and a dummy entry type.&lt;br /&gt;
&lt;br /&gt;
=== Savegame/Extdata Variant===&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! Offset&lt;br /&gt;
! Length&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x00&lt;br /&gt;
| 4&lt;br /&gt;
| Parent directory index. 0 for root&lt;br /&gt;
|-&lt;br /&gt;
| 0x04&lt;br /&gt;
| 16&lt;br /&gt;
| ASCII directory name in. All zero for root&lt;br /&gt;
|-&lt;br /&gt;
| 0x14&lt;br /&gt;
| 4&lt;br /&gt;
| Next sibling directory index. 0 if this is the last one&lt;br /&gt;
|-&lt;br /&gt;
| 0x18&lt;br /&gt;
| 4&lt;br /&gt;
| First subdirectory index. 0 if not exists&lt;br /&gt;
|-&lt;br /&gt;
| 0x1C&lt;br /&gt;
| 4&lt;br /&gt;
| First file index in file entry table. 0 for empty directory&lt;br /&gt;
|-&lt;br /&gt;
| 0x20&lt;br /&gt;
| 4&lt;br /&gt;
| Padding / zero?&lt;br /&gt;
|-&lt;br /&gt;
| 0x24&lt;br /&gt;
| 4&lt;br /&gt;
| Index of the next directory in the same hash table bucket. 0 if this is the last one&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Title Database Variant===&lt;br /&gt;
Because title database only has one directory for &amp;quot;root&amp;quot;, its directory entry table degenerates into many zeros whose structure is not recognizable. The size of one entry here is guessed.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! Offset&lt;br /&gt;
! Length&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x00&lt;br /&gt;
| 4&lt;br /&gt;
| Parent directory index = 0 for root&lt;br /&gt;
|-&lt;br /&gt;
| 0x04&lt;br /&gt;
| 4&lt;br /&gt;
| Next sibling directory index = 0 because this is the last one&lt;br /&gt;
|-&lt;br /&gt;
| 0x08&lt;br /&gt;
| 4&lt;br /&gt;
| First subdirectory index = 0 because there is no subdirectory&lt;br /&gt;
|-&lt;br /&gt;
| 0x0C&lt;br /&gt;
| 4&lt;br /&gt;
| First file index in file entry table. 0 for empty directory&lt;br /&gt;
|-&lt;br /&gt;
| 0x10&lt;br /&gt;
| 12&lt;br /&gt;
| Padding / zero?&lt;br /&gt;
|-&lt;br /&gt;
| 0x1C&lt;br /&gt;
| 4&lt;br /&gt;
| Index of the next directory in the same hash table bucket = 0 because there is no other directory&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Dummy Entry===&lt;br /&gt;
There are also some dummy entries in the array&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! Offset&lt;br /&gt;
! Length&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x00&lt;br /&gt;
| 4&lt;br /&gt;
| Current Total entry count&lt;br /&gt;
|-&lt;br /&gt;
| 0x04&lt;br /&gt;
| 4&lt;br /&gt;
| Maximum entry count = maximum directory count + 2&lt;br /&gt;
|-&lt;br /&gt;
| 0x08&lt;br /&gt;
| 28/20&lt;br /&gt;
| Padding / All zero&lt;br /&gt;
|-&lt;br /&gt;
| 0x24/0x1C&lt;br /&gt;
| 4&lt;br /&gt;
| Index of the next dummy entry. 0 if this is the last one&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The 0-th entry of the array is always a dummy entry, which functions as the head of the dummy entry linked list. The 1-st entry of the array is always the root. Therefore maximum entry count is two more than maximum directory count. Dummy entries are left there when deleting directories, and reserved for future use.&lt;br /&gt;
&lt;br /&gt;
== File Entry Table ==&lt;br /&gt;
&lt;br /&gt;
The file entry table is an array of the entry type shown below. It contains information for each file. There are three variants of the file entry type, and a dummy entry type.&lt;br /&gt;
&lt;br /&gt;
=== Savegame Variant ===&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! Offset&lt;br /&gt;
! Length&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x00&lt;br /&gt;
| 4&lt;br /&gt;
| Parent directory index in directory entry table&lt;br /&gt;
|-&lt;br /&gt;
| 0x04&lt;br /&gt;
| 16&lt;br /&gt;
| ASCII file name&lt;br /&gt;
|-&lt;br /&gt;
| 0x14&lt;br /&gt;
| 4&lt;br /&gt;
| Next sibling file index. 0 if this is the last one&lt;br /&gt;
|-&lt;br /&gt;
| 0x18&lt;br /&gt;
| 4&lt;br /&gt;
| Padding&lt;br /&gt;
|-&lt;br /&gt;
| 0x1C&lt;br /&gt;
| 4&lt;br /&gt;
| First block index in data region. 0x80000000 if the file is just created and has no data.&lt;br /&gt;
|-&lt;br /&gt;
| 0x20&lt;br /&gt;
| 8&lt;br /&gt;
| File Size&lt;br /&gt;
|-&lt;br /&gt;
| 0x28&lt;br /&gt;
| 4&lt;br /&gt;
| Padding?&lt;br /&gt;
|-&lt;br /&gt;
| 0x2C&lt;br /&gt;
| 4&lt;br /&gt;
| Index of the next file in the same hash table bucket. 0 if this is the last one&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Extdata Variant ===&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! Offset&lt;br /&gt;
! Length&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x00&lt;br /&gt;
| 4&lt;br /&gt;
| Parent directory index in directory entry table&lt;br /&gt;
|-&lt;br /&gt;
| 0x04&lt;br /&gt;
| 16&lt;br /&gt;
| ASCII file name&lt;br /&gt;
|-&lt;br /&gt;
| 0x14&lt;br /&gt;
| 4&lt;br /&gt;
| Next sibling file index. 0 if this is the last one&lt;br /&gt;
|-&lt;br /&gt;
| 0x18&lt;br /&gt;
| 4&lt;br /&gt;
| Padding&lt;br /&gt;
|-&lt;br /&gt;
| 0x1C&lt;br /&gt;
| 4&lt;br /&gt;
| Always 0x80000000&lt;br /&gt;
|-&lt;br /&gt;
| 0x20&lt;br /&gt;
| 8&lt;br /&gt;
| Unique identifier. See [[Extdata]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x28&lt;br /&gt;
| 4&lt;br /&gt;
| Padding?&lt;br /&gt;
|-&lt;br /&gt;
| 0x2C&lt;br /&gt;
| 4&lt;br /&gt;
| Index of the next file in the same hash table bucket. 0 if this is the last one&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Title database Variant ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! Offset&lt;br /&gt;
! Length&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x00&lt;br /&gt;
| 4&lt;br /&gt;
| Parent directory index in directory entry table&lt;br /&gt;
|-&lt;br /&gt;
| 0x04&lt;br /&gt;
| 8&lt;br /&gt;
| Title ID&lt;br /&gt;
|-&lt;br /&gt;
| 0x0C&lt;br /&gt;
| 4&lt;br /&gt;
| Next sibling file index. 0 if this is the last one&lt;br /&gt;
|-&lt;br /&gt;
| 0x10&lt;br /&gt;
| 4&lt;br /&gt;
| Padding&lt;br /&gt;
|-&lt;br /&gt;
| 0x14&lt;br /&gt;
| 4&lt;br /&gt;
| First block index in data region.&lt;br /&gt;
|-&lt;br /&gt;
| 0x18&lt;br /&gt;
| 8&lt;br /&gt;
| File size&lt;br /&gt;
|-&lt;br /&gt;
| 0x20&lt;br /&gt;
| 8&lt;br /&gt;
| Padding?&lt;br /&gt;
|-&lt;br /&gt;
| 0x28&lt;br /&gt;
| 4&lt;br /&gt;
| Index of the next file in the same hash table bucket. 0 if this is the last one&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Dummy Entry ===&lt;br /&gt;
Like directory entry table, file entry table also has some dummy entries:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! Offset&lt;br /&gt;
! Length&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x00&lt;br /&gt;
| 4&lt;br /&gt;
| Current total entry count&lt;br /&gt;
|-&lt;br /&gt;
| 0x04&lt;br /&gt;
| 4&lt;br /&gt;
| Maximum entry count = maximum file count + 1&lt;br /&gt;
|-&lt;br /&gt;
| 0x08&lt;br /&gt;
| 36/32&lt;br /&gt;
| Padding / All zero&lt;br /&gt;
|-&lt;br /&gt;
| 0x2C/0x28&lt;br /&gt;
| 4&lt;br /&gt;
| Index of the next dummy entry. 0 if this is the last one&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The 0-th entry of the array is always a dummy entry, which functions as the head of the dummy entry linked list. Therefore maximum entry count is one more than maximum file count. Dummy entries are left there when deleting files, and reserved for future use.&lt;br /&gt;
&lt;br /&gt;
== Directory Hash Table &amp;amp;amp; File Hash Table ==&lt;br /&gt;
&lt;br /&gt;
This is a u32 array of size = bucket count, each of which is an index to the directory / file entry table. The directory / file name is hashed and its entry index is put to the corresponding bucket. If there is already a directory/file entry in the bucket, then it appends to the linked list formed by &amp;lt;code&amp;gt;Index of the next directory/file in the same hash table bucket&amp;lt;/code&amp;gt; field in the directory/file entry table. i.e. this is a hash table using separate chaining with linked lists&lt;br /&gt;
&lt;br /&gt;
The hash function takes the parent index and the ASCII name (or title ID for title database) as key. The function is equivalent to&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;uint32_t GetBucket(&lt;br /&gt;
    char name[16 or 8], // For savegame/extdata, this takes all 16 bytes including trailing zeros; For title database, this is the 8-byte title ID&lt;br /&gt;
    uint32_t parent_dir_index,&lt;br /&gt;
    uint32_t bucket_count&lt;br /&gt;
) {&lt;br /&gt;
    uint32_t hash = parent_dir_index ^ 0x091A2B3C;&lt;br /&gt;
    for (int i = 0; i &amp;amp;lt; 4 or 2; ++i) {&lt;br /&gt;
        hash = (hash &amp;amp;gt;&amp;amp;gt; 1) | (hash &amp;amp;lt;&amp;amp;lt; 31);&lt;br /&gt;
        hash ^= (uint32_t)name[i * 4]&lt;br /&gt;
        hash ^= (uint32_t)name[i * 4 + 1] &amp;amp;lt;&amp;amp;lt; 8&lt;br /&gt;
        hash ^= (uint32_t)name[i * 4 + 2] &amp;amp;lt;&amp;amp;lt; 16&lt;br /&gt;
        hash ^= (uint32_t)name[i * 4 + 3] &amp;amp;lt;&amp;amp;lt; 24&lt;br /&gt;
    }&lt;br /&gt;
    return hash % bucket_count;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== File Allocation Table ==&lt;br /&gt;
&lt;br /&gt;
The file allocation table is an array of a 8-byte entry shown below. The array size is actually &#039;&#039;one larger than&#039;&#039; the size recorded in the filesystem header. Each entry corresponds to a block in the data region (the block size is defined in filesystem header). However, the 0th entry corresponds to nothing, so the corresponding block index is off by one. e.g. entry 31 in this table corresponds to block 30 in the data region.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! Offset&lt;br /&gt;
! Length&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x00&lt;br /&gt;
| 4&lt;br /&gt;
| bit[0:30]: Index U; bit[31]: Flag U&lt;br /&gt;
|-&lt;br /&gt;
| 0x04&lt;br /&gt;
| 4&lt;br /&gt;
| bit[0:30]: Index V; bit[31]: Flag V&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Entries in this table forms several chains, representing how blocks in the data region should be linked together. However, unlike normal FAT systems, which uses chains of entries, 3DS savegames use chain of &#039;&#039;nodes&#039;&#039;. Each node spans one or multiple entries.&lt;br /&gt;
&lt;br /&gt;
One node spanning &amp;lt;code&amp;gt;n&amp;lt;/code&amp;gt; entries starting from &amp;lt;code&amp;gt;FAT[k]&amp;lt;/code&amp;gt; is in the following format:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;FAT[k + 0]:&lt;br /&gt;
    Index_U = index of the first entry of the previous node. 0 if this is the first node.&lt;br /&gt;
    Index_V = index of the first entry of the next node. 0 if this is the last node.&lt;br /&gt;
    Flag_U set if this is the first node.&lt;br /&gt;
    Flag_V set if this node has multiple entries.&lt;br /&gt;
&lt;br /&gt;
FAT[k + 1]:&lt;br /&gt;
    Index_U = k (the first entry index of this node)&lt;br /&gt;
    Index_V = k + n - 1 (the last entry index of this node)&lt;br /&gt;
    Flag_U always set&lt;br /&gt;
    Flag_V always clear&lt;br /&gt;
&lt;br /&gt;
FAT[k + 2] ~ FAT[k + n - 2]:&lt;br /&gt;
    All these entries are uninitialized&lt;br /&gt;
&lt;br /&gt;
FAT[k + n - 1]:&lt;br /&gt;
    Index_U = k&lt;br /&gt;
    Index_V = k + n - 1&lt;br /&gt;
    Flag_U always set&lt;br /&gt;
    Flag_V always clear&lt;br /&gt;
    (Same values as FAT[k + 1])&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* Note: all indices above are entry indices (block index + 1)&lt;br /&gt;
&lt;br /&gt;
All free blocks that are not allocated to any files also form a node chain in the allocation table. The head index of this &amp;amp;quot;free chain&amp;amp;quot; is recorded in &amp;lt;code&amp;gt;FAT[0].Index_V&amp;lt;/code&amp;gt;. Other fields of &amp;lt;code&amp;gt;FAT[0]&amp;lt;/code&amp;gt; are all zero&lt;br /&gt;
&lt;br /&gt;
Here is an example: [https://raw.githubusercontent.com/wwylele/3ds-save-tool/master/disa-fat.png]&lt;br /&gt;
&lt;br /&gt;
For extdata, because only two &amp;quot;files&amp;quot; (directory and file entry tables) are allocated in the data region, and their size never changes once the extdata is created, they are guaranteed continuous in the data region, and the FAT degenerates to two big nodes. Therefore, instead of going through FAT, the offset and size of directory / file entry table can be found directly by offset = entry_table_starting block * data_region_block_size + data_region_offset and size = entry_table_block_count * data_region_block_size.&lt;/div&gt;</summary>
		<author><name>Wwylele</name></author>
	</entry>
	<entry>
		<id>https://www.3dbrew.org/w/index.php?title=Title_Database&amp;diff=20948</id>
		<title>Title Database</title>
		<link rel="alternate" type="text/html" href="https://www.3dbrew.org/w/index.php?title=Title_Database&amp;diff=20948"/>
		<updated>2019-05-03T20:03:21Z</updated>

		<summary type="html">&lt;p&gt;Wwylele: Migrate to Inner FAT&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;These files contain data relating to install/usage/management of installed 3DS titles. The database files are located at:&lt;br /&gt;
&lt;br /&gt;
* nand/dbs&lt;br /&gt;
* sdmc/Nintendo 3DS/&amp;lt;ID0&amp;gt;/&amp;lt;ID1&amp;gt;/dbs&lt;br /&gt;
&lt;br /&gt;
ID0 is the first 0x10-bytes from a SHA256 [[nand/private/movable.sed|hash]]. The installation of [[SD Filesystem|SD Card]] titles was introduced in the [[2.0.0-2]] update and the SD dbs files are encrypted by [[SD Filesystem|the general SD filesystem encryption rule]]. These files are [[DISA and DIFF|DIFF containers]]. These DIFF files do not use external IVFC level 4, so all database data is duplicated in the container. In this page only the inner content of the container is described.&lt;br /&gt;
&lt;br /&gt;
These files are only created on SD (via [[Application_Manager_Services|AM]]) if they don&#039;t exist when the [[eShop]] application is starting up, during network init etc (prior to showing the &amp;quot;system update required&amp;quot; dialog).&lt;br /&gt;
&lt;br /&gt;
These files are stored under this directory:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
!  Stored on SD card&lt;br /&gt;
!  Stored in CTR-NAND&lt;br /&gt;
!  Filename&lt;br /&gt;
!  [[DISA and DIFF#CTR-9DB0|CTR-9DB0]] ID&lt;br /&gt;
!  Description&lt;br /&gt;
|-&lt;br /&gt;
| No&lt;br /&gt;
| Yes&lt;br /&gt;
| ticket.db&lt;br /&gt;
| 0x0&lt;br /&gt;
| This contains the installed tickets (NAND and SD).&lt;br /&gt;
|-&lt;br /&gt;
| No&lt;br /&gt;
| Yes&lt;br /&gt;
| certs.db&lt;br /&gt;
| 0x1&lt;br /&gt;
| This contains the certificate chain used to verify TMDs and other certificates.&lt;br /&gt;
|-&lt;br /&gt;
| Yes&lt;br /&gt;
| Yes&lt;br /&gt;
| title.db&lt;br /&gt;
| 0x2&lt;br /&gt;
| Title database, this contains entries for all installed titles (TWL &amp;amp; CTR) on the 3DS (Each database is responsible for titles installed on its medium).&lt;br /&gt;
|-&lt;br /&gt;
| Yes&lt;br /&gt;
| Yes&lt;br /&gt;
| import.db&lt;br /&gt;
| 0x3&lt;br /&gt;
| This is an Import Database, it contains entries for titles (or versions of titles) not yet installed, ready for transferring to the title.db. (Automatic Update uses this, so completing the update takes seconds.)&lt;br /&gt;
|-&lt;br /&gt;
| No&lt;br /&gt;
| Yes&lt;br /&gt;
| tmp_t.db&lt;br /&gt;
| 0x4&lt;br /&gt;
| This is the temporary Title database containing one entry for the currently installed [[Download Play]] Child.&lt;br /&gt;
|-&lt;br /&gt;
| No&lt;br /&gt;
| Yes&lt;br /&gt;
| tmp_i.db&lt;br /&gt;
| 0x5&lt;br /&gt;
| Similar to import.db, except it&#039;s used in conjunction with tmp_t.db, for installing [[Download Play]] Children.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The inner content of the container consists of a pre-header with size of 0x80 identifying the Database Type, followed by a BDRI container. The offsets in the BDRI header are usually relative to the offset to the start of the BDRI header (0x80 in the file)&lt;br /&gt;
&lt;br /&gt;
== Pre Header ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Start&lt;br /&gt;
! Length&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x00&lt;br /&gt;
| 8&lt;br /&gt;
| Database Type &amp;quot;Magic&amp;quot; (see below)&lt;br /&gt;
|-&lt;br /&gt;
| 0x08&lt;br /&gt;
| 0x78&lt;br /&gt;
| Reserved&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
For ticket.db different pre header is used:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Start&lt;br /&gt;
! Length&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x00&lt;br /&gt;
| 4&lt;br /&gt;
| Database Type &amp;quot;Magic&amp;quot; (see below)&lt;br /&gt;
|-&lt;br /&gt;
| 0x04&lt;br /&gt;
| 0x04&lt;br /&gt;
| Unknown (always 0x00000001 ?)&lt;br /&gt;
|-&lt;br /&gt;
| 0x08&lt;br /&gt;
| 0x04&lt;br /&gt;
| Unknown&lt;br /&gt;
|-&lt;br /&gt;
| 0x0C&lt;br /&gt;
| 0x04&lt;br /&gt;
| Unknown (0x30 smaller than previous one)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Database Magic ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Database Type&lt;br /&gt;
! Magic&lt;br /&gt;
|-&lt;br /&gt;
| CTR-NAND ticket.db&lt;br /&gt;
| TICK&lt;br /&gt;
|-&lt;br /&gt;
| CTR-NAND import.db&lt;br /&gt;
| NANDIDB&lt;br /&gt;
|-&lt;br /&gt;
| CTR-NAND title.db&lt;br /&gt;
| NANDTDB&lt;br /&gt;
|-&lt;br /&gt;
| CTR-NAND tmp_i.db&lt;br /&gt;
| TEMPIDB&lt;br /&gt;
|-&lt;br /&gt;
| CTR-NAND tmp_t.db&lt;br /&gt;
| TEMPIDB&lt;br /&gt;
|-&lt;br /&gt;
| SD Card import.db&lt;br /&gt;
| TEMPTDB&lt;br /&gt;
|-&lt;br /&gt;
| SD Card title.db&lt;br /&gt;
| TEMPTDB&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== BDRI ==&lt;br /&gt;
&lt;br /&gt;
This is a variant of [[Inner FAT|FAT filesystem]]. It consists one &amp;quot;root&amp;quot; directory and multiple &amp;quot;files&amp;quot;. Each &amp;quot;file&amp;quot; is one title info entry described below.&lt;br /&gt;
&lt;br /&gt;
== Title Info Entry ==&lt;br /&gt;
&lt;br /&gt;
An entry contains information taken from both the application NCCH file(s) and TMD.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Start&lt;br /&gt;
! Length&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0&lt;br /&gt;
| 8&lt;br /&gt;
| Title Size&lt;br /&gt;
|-&lt;br /&gt;
| 0x8&lt;br /&gt;
| 4&lt;br /&gt;
| Title Type(usually 0x40)&lt;br /&gt;
|-&lt;br /&gt;
| 0xC&lt;br /&gt;
| 4&lt;br /&gt;
| Title Version&lt;br /&gt;
|-&lt;br /&gt;
| 0x10&lt;br /&gt;
| 4&lt;br /&gt;
| Flags_0&lt;br /&gt;
|-&lt;br /&gt;
| 0x14&lt;br /&gt;
| 4&lt;br /&gt;
| TMD Content ID&lt;br /&gt;
|-&lt;br /&gt;
| 0x18&lt;br /&gt;
| 4&lt;br /&gt;
| CMD Content ID&lt;br /&gt;
|-&lt;br /&gt;
| 0x1c&lt;br /&gt;
| 4&lt;br /&gt;
| Flags_1&lt;br /&gt;
|-&lt;br /&gt;
| 0x20&lt;br /&gt;
| 4&lt;br /&gt;
| ExtdataID low (zero if title doesn&#039;t use Extdata)&lt;br /&gt;
|-&lt;br /&gt;
| 0x24&lt;br /&gt;
| 4&lt;br /&gt;
| Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x28&lt;br /&gt;
| 8&lt;br /&gt;
| Flags_2&lt;br /&gt;
|-&lt;br /&gt;
| 0x30&lt;br /&gt;
| 0x10&lt;br /&gt;
| Product Code&lt;br /&gt;
|-&lt;br /&gt;
| 0x40&lt;br /&gt;
| 0x10&lt;br /&gt;
| Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 0x50&lt;br /&gt;
| 0x4&lt;br /&gt;
| Unknown&lt;br /&gt;
|-&lt;br /&gt;
| 0x54&lt;br /&gt;
| 0x2c&lt;br /&gt;
| Reserved&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
For ticket.db title info contains a small header and actual ticket data:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Start&lt;br /&gt;
! Length&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0&lt;br /&gt;
| 4&lt;br /&gt;
| Unknown (always 0x00000001?)&lt;br /&gt;
|-&lt;br /&gt;
| 0x4&lt;br /&gt;
| 4&lt;br /&gt;
| Ticket data size X (=0x530)&lt;br /&gt;
|-&lt;br /&gt;
| 0x8&lt;br /&gt;
| X&lt;br /&gt;
| [[Ticket|Ticket]] data&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Flags_0 ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Index&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0&lt;br /&gt;
| Electronic Manual&lt;br /&gt;
|-&lt;br /&gt;
| 1&lt;br /&gt;
| ?&lt;br /&gt;
|-&lt;br /&gt;
| 2&lt;br /&gt;
| ?&lt;br /&gt;
|-&lt;br /&gt;
| 3&lt;br /&gt;
| ?&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Flags_1 ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Index&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0&lt;br /&gt;
| SD Save Data&lt;br /&gt;
|-&lt;br /&gt;
| 1&lt;br /&gt;
| ?&lt;br /&gt;
|-&lt;br /&gt;
| 2&lt;br /&gt;
| ?&lt;br /&gt;
|-&lt;br /&gt;
| 3&lt;br /&gt;
| ?&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Flags_2 ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Index&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0&lt;br /&gt;
| DSiWare Related (Visibility on Home Menu/Export Flag?)&lt;br /&gt;
|-&lt;br /&gt;
| 1&lt;br /&gt;
| ?&lt;br /&gt;
|-&lt;br /&gt;
| 2&lt;br /&gt;
| ?&lt;br /&gt;
|-&lt;br /&gt;
| 3&lt;br /&gt;
| ?&lt;br /&gt;
|-&lt;br /&gt;
| 4&lt;br /&gt;
| Found with DSiWare Titles and titles with an &#039;Application&#039; Title ID&lt;br /&gt;
|-&lt;br /&gt;
| 5&lt;br /&gt;
| DSiWare Related (Visibility on Home Menu/Export Flag?)&lt;br /&gt;
|-&lt;br /&gt;
| 6&lt;br /&gt;
| ?&lt;br /&gt;
|-&lt;br /&gt;
| 7&lt;br /&gt;
| ?&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;NOTES:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
It is important to note the database doesn&#039;t contain a hash of the [[Title Data Structure|.cmd]]. So if a user has more than one valid set of [[Title Data Structure|application data]] for a given .cmd Content ID they can be manually interchanged without issue. Though renaming a .cmd file to match the Content ID which the title.db is expecting will result in an error, as the CTR for the per-console encryption layer changes depending on the file path, and the MAC of the .cmd is probably generated with the .cmd Content ID in mind.&lt;br /&gt;
&lt;br /&gt;
These NAND/SD /dbs images seem to be loaded by the ARM9 while NATIVE_FIRM is booting.&lt;br /&gt;
&lt;br /&gt;
Removing ticket.db from a New-3DS with signature checks disabled will not result in an unbootable system, however all icons except Slot-1 will disappear from Home. Applets can however still be used. Recovery can be accomplished via [[Hardware|hardmod]] or [[arm9loaderhax]] plus a known good backup of the file (or the whole partition or disk); Gamecard exploits were not tested, and Browserhax did not work.&lt;/div&gt;</summary>
		<author><name>Wwylele</name></author>
	</entry>
	<entry>
		<id>https://www.3dbrew.org/w/index.php?title=Inner_FAT&amp;diff=20947</id>
		<title>Inner FAT</title>
		<link rel="alternate" type="text/html" href="https://www.3dbrew.org/w/index.php?title=Inner_FAT&amp;diff=20947"/>
		<updated>2019-05-03T19:58:09Z</updated>

		<summary type="html">&lt;p&gt;Wwylele: /* Filesystem Header */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This page describes a common FAT-like file system used in [[Savegames]], [[Extdata]] and [[Title Database]]. This file system format has several variants depending on which kind of data it stores. All the three kinds of data that use this file system structure also happen to use the [[DISA and DIFF]] container as well, but there is no direct relationship between the file system and the DISA/DIFF container. All data formats described here is in the inner data of the DISA/DIFF container (i.e. IVFC level 4). Please refer to the DISA/DIFF page for how to unwrap it first before trying to extract the file system.&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
&lt;br /&gt;
The file system consists of the following components:&lt;br /&gt;
* header&lt;br /&gt;
* directory hash table&lt;br /&gt;
* file hash table&lt;br /&gt;
* file allocation table&lt;br /&gt;
* directory entry table&lt;br /&gt;
* file entry table&lt;br /&gt;
* data region&lt;br /&gt;
&lt;br /&gt;
The file allocation table (FAT) forms several linked lists inside, each of which represents a &amp;quot;file&amp;quot; allocated in the data region. Please refer to the File Allocation Table section below for more detail. In some variants, the directory entry table and the file entry table are also allocated as two special &amp;quot;files&amp;quot; in the data region, managed by the FAT, while in others they are stand-alone tables located outside the data region.&lt;br /&gt;
&lt;br /&gt;
== Layout Variants ==&lt;br /&gt;
Four variants of the file system layout has been identified. A summary diagram can be found here: [https://github.com/wwylele/3ds-save-tool/raw/master/inner-fat.png]&lt;br /&gt;
&lt;br /&gt;
=== Savegame, &amp;lt;code&amp;gt;duplicate data = true&amp;lt;/code&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
Such savegame is a single DISA container that only has one partition which is always configured as external IVFC level 4 disabled (see [[DISA and DIFF|DISA]] format for details). All components are stored in this partition as&lt;br /&gt;
&lt;br /&gt;
* filesystem header at the beginning&lt;br /&gt;
* directory hash table&lt;br /&gt;
* file hash table&lt;br /&gt;
* file allocation table&lt;br /&gt;
* data region&lt;br /&gt;
** directory entry table is allocated inside data region&lt;br /&gt;
** file entry table as well&lt;br /&gt;
** all file data is also allocated here&lt;br /&gt;
&lt;br /&gt;
In this layout, all data is duplicated by DISA&#039;s DPFS tree, which is what the parameter &amp;lt;code&amp;gt;duplicate data&amp;lt;/code&amp;gt; implies.&lt;br /&gt;
&lt;br /&gt;
=== Savegame, &amp;lt;code&amp;gt;duplicate data = false&amp;lt;/code&amp;gt; === &lt;br /&gt;
Such savegame is a single DISA container that has two partitions. Partition A is always configured as external IVFC level 4 disabled, and partition B is configured as it enabled. Components are stored among the two partitions as&lt;br /&gt;
&lt;br /&gt;
* Partition A&lt;br /&gt;
** filesystem header at the beginning.&lt;br /&gt;
** directory hash table&lt;br /&gt;
** file hash table&lt;br /&gt;
** (stand-alone) file allocation table&lt;br /&gt;
** (stand-alone) directory entry table&lt;br /&gt;
** file entry table&lt;br /&gt;
* Partition B&lt;br /&gt;
** used as data region entirely, and only has file data allocated.&lt;br /&gt;
&lt;br /&gt;
In this layout, all file system metadata is duplicated by partition A DPFS tree, but file data is not as partition B has external IVFC level 4.&lt;br /&gt;
&lt;br /&gt;
=== Extdata ===&lt;br /&gt;
An extdata consists of several DIFF containers (device files), among which the special device file &amp;lt;code&amp;gt;00000000/00000001&amp;lt;/code&amp;gt; contains the inner FAT system, while other devices contains normal subfiles of the extdata. Please refer to [[Extdata]] for detail. The special file &amp;lt;code&amp;gt;00000000/00000001&amp;lt;/code&amp;gt; contists of the following components&lt;br /&gt;
&lt;br /&gt;
* filesystem header at the beginning&lt;br /&gt;
* directory hash table&lt;br /&gt;
* file hash table&lt;br /&gt;
* file allocation table (degenerate, because the data region only has two &amp;quot;files&amp;quot;: the directory entry table and the file entry table)&lt;br /&gt;
* data region&lt;br /&gt;
** directory entry table allocated inside data region&lt;br /&gt;
** file entry table as well&lt;br /&gt;
** normal subfiles are NOT in the data region. They are in their DIFF containers instead.&lt;br /&gt;
&lt;br /&gt;
=== Title database ===&lt;br /&gt;
All [[Title Database]] files are DIFF containers. Except for &amp;lt;code&amp;gt;certs.db&amp;lt;/code&amp;gt;, all of them uses this filesystem in the DIFF inner data, which consists of&lt;br /&gt;
&lt;br /&gt;
* database-specific pre-header at the beginning (See [[Title Database]])&lt;br /&gt;
* filesystem header&lt;br /&gt;
* directory Hash Table (degenerate and always has only one bucket, as there is only one directory for &amp;quot;root&amp;quot;)&lt;br /&gt;
* file Hash Table&lt;br /&gt;
* file allocation table&lt;br /&gt;
* data region&lt;br /&gt;
** directory entry table allocated inside data region (degenerate, as there is only one directory for &amp;quot;root&amp;quot;)&lt;br /&gt;
** file entry table as well&lt;br /&gt;
** title entries (title info or ticket) are allocated as normal files in the data region as well.&lt;br /&gt;
&lt;br /&gt;
== Filesystem Header ==&lt;br /&gt;
Offsets listed in the table below are all relative to the beginning of the header, while all &amp;quot;starting block index&amp;quot; are relative to the beginning of data region. This is especially important for title database, as the offsets doesn&#039;t count the pre header.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! Offset&lt;br /&gt;
! Length&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x00&lt;br /&gt;
| 4&lt;br /&gt;
| Magic (&amp;quot;SAVE&amp;quot; for savegame; &amp;quot;BDRI&amp;quot; for title database; &amp;quot;VSXE&amp;quot; for extdata)&lt;br /&gt;
|-&lt;br /&gt;
| 0x04&lt;br /&gt;
| 4&lt;br /&gt;
| Version (0x40000 for savegame; 0x30000 for title database and extdata)&lt;br /&gt;
|-&lt;br /&gt;
| 0x08&lt;br /&gt;
| 8&lt;br /&gt;
| Filesystem Information offset (Y, =0x20 for savegame and title database, =0x138 for extdata)&lt;br /&gt;
|-&lt;br /&gt;
| 0x10&lt;br /&gt;
| 8&lt;br /&gt;
| Filesystem image size in blocks (including pre header for title database)&lt;br /&gt;
|-&lt;br /&gt;
| 0x18&lt;br /&gt;
| 4&lt;br /&gt;
| Filesystem Image block size&lt;br /&gt;
|-&lt;br /&gt;
| 0x1C&lt;br /&gt;
| 4&lt;br /&gt;
| Padding&lt;br /&gt;
|-&lt;br /&gt;
| 0x20 &lt;br /&gt;
| 0x118 in total&lt;br /&gt;
| Below is additional data for extdata. Not present in savegame or title database&lt;br /&gt;
|-&lt;br /&gt;
| 0x20&lt;br /&gt;
| 8&lt;br /&gt;
| Unknown&lt;br /&gt;
|-&lt;br /&gt;
| 0x28&lt;br /&gt;
| 4&lt;br /&gt;
| &#039;Action&#039; made on most recently mounted Extdata image&lt;br /&gt;
|-&lt;br /&gt;
| 0x2C&lt;br /&gt;
| 4&lt;br /&gt;
| Unknown&lt;br /&gt;
|-&lt;br /&gt;
| 0x30&lt;br /&gt;
| 4&lt;br /&gt;
| D of most recently mounted Extdata image&lt;br /&gt;
|-&lt;br /&gt;
| 0x34&lt;br /&gt;
| 4&lt;br /&gt;
| Unknown&lt;br /&gt;
|-&lt;br /&gt;
| 0x38&lt;br /&gt;
| 0x100&lt;br /&gt;
| Mount path, from most recently mounted Extdata image&lt;br /&gt;
|-&lt;br /&gt;
| Y &lt;br /&gt;
| 0x68 in total&lt;br /&gt;
| Below is Filesystem Information&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x00&lt;br /&gt;
| 4&lt;br /&gt;
| Unknown&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x04&lt;br /&gt;
| 4&lt;br /&gt;
| Data region block size&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x08&lt;br /&gt;
| 8&lt;br /&gt;
| Directory hash table offset&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x10&lt;br /&gt;
| 4&lt;br /&gt;
| Directory hash table bucket count (=1 for title database)&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x14&lt;br /&gt;
| 4&lt;br /&gt;
| Padding&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x18&lt;br /&gt;
| 8&lt;br /&gt;
| File hash table offset&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x20&lt;br /&gt;
| 4&lt;br /&gt;
| File hash table bucket count&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x24&lt;br /&gt;
| 4&lt;br /&gt;
| Padding&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x28&lt;br /&gt;
| 8&lt;br /&gt;
| File allocation table offset&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x30&lt;br /&gt;
| 4&lt;br /&gt;
| File allocation table entry count&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x34&lt;br /&gt;
| 4&lt;br /&gt;
| Padding&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x38&lt;br /&gt;
| 8&lt;br /&gt;
| Data region offset &lt;br /&gt;
(0 for savegame &amp;lt;code&amp;gt;duplicate data = false&amp;lt;/code&amp;gt; layout, as the data region is in partition B for that layout)&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x40&lt;br /&gt;
| 4&lt;br /&gt;
| Data region block count &lt;br /&gt;
(= number of file allocation table entries excluding the leading 0th entry. See below)&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x44&lt;br /&gt;
| 4&lt;br /&gt;
| Padding&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x48&lt;br /&gt;
| 8&lt;br /&gt;
| for savegame &amp;lt;code&amp;gt;duplicate data = false&amp;lt;/code&amp;gt; layout: directory entry table offset;&lt;br /&gt;
otherwise: u32 directory entry table starting block index + u32 directory entry table block count&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x50&lt;br /&gt;
| 4&lt;br /&gt;
| Maximum directory count, excluding the mandatory &amp;quot;root&amp;quot; directory &lt;br /&gt;
(=1 for title database, but that 1 free directory slot is never used)&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x54&lt;br /&gt;
| 4&lt;br /&gt;
| Padding&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x58&lt;br /&gt;
| 8&lt;br /&gt;
| for savegame &amp;lt;code&amp;gt;duplicate data = false&amp;lt;/code&amp;gt; layout: file entry table offset;&lt;br /&gt;
otherwise: u32 file entry table starting block index + u32 file entry table block count&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x60&lt;br /&gt;
| 4&lt;br /&gt;
| Maximum file count&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x64&lt;br /&gt;
| 4&lt;br /&gt;
| Padding&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
* For savegames, the file/directory bucket count &amp;amp; maximum count are specified by the parameters of [[FS:FormatSaveData]] or [[FS:CreateSystemSaveData]].&lt;br /&gt;
* For extdata, the maximum file/directory count are specified by the parameters of [[FS:CreateExtSaveData]]. The bucket count is likely calculated by the system.&lt;br /&gt;
* Directory &amp;amp; file entry tables are allocated in the data region as if they are two normal files (except for savegame &amp;lt;code&amp;gt;duplicate data = false&amp;lt;/code&amp;gt; layout). However, only continuous allocation has been observed, so directly reading block_count * block_size bytes from data_region + starting_block_index * block_size should be safe.&lt;br /&gt;
&lt;br /&gt;
== Directory Entry Table ==&lt;br /&gt;
&lt;br /&gt;
The directory entry table is an array of the entry type shown below. It describes the directory hierarchy of the file system. There are two variants of the directory entry type, and a dummy entry type.&lt;br /&gt;
&lt;br /&gt;
=== Savegame/Extdata Variant===&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! Offset&lt;br /&gt;
! Length&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x00&lt;br /&gt;
| 4&lt;br /&gt;
| Parent directory index. 0 for root&lt;br /&gt;
|-&lt;br /&gt;
| 0x04&lt;br /&gt;
| 16&lt;br /&gt;
| ASCII directory name in. All zero for root&lt;br /&gt;
|-&lt;br /&gt;
| 0x14&lt;br /&gt;
| 4&lt;br /&gt;
| Next sibling directory index. 0 if this is the last one&lt;br /&gt;
|-&lt;br /&gt;
| 0x18&lt;br /&gt;
| 4&lt;br /&gt;
| First subdirectory index. 0 if not exists&lt;br /&gt;
|-&lt;br /&gt;
| 0x1C&lt;br /&gt;
| 4&lt;br /&gt;
| First file index in file entry table. 0 for empty directory&lt;br /&gt;
|-&lt;br /&gt;
| 0x20&lt;br /&gt;
| 4&lt;br /&gt;
| Padding / zero?&lt;br /&gt;
|-&lt;br /&gt;
| 0x24&lt;br /&gt;
| 4&lt;br /&gt;
| Index of the next directory in the same hash table bucket. 0 if this is the last one&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Title Database Variant===&lt;br /&gt;
Because title database only has one directory for &amp;quot;root&amp;quot;, its directory entry table degenerates into many zeros whose structure is not recognizable. The size of one entry here is guessed.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! Offset&lt;br /&gt;
! Length&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x00&lt;br /&gt;
| 4&lt;br /&gt;
| Parent directory index = 0 for root&lt;br /&gt;
|-&lt;br /&gt;
| 0x04&lt;br /&gt;
| 4&lt;br /&gt;
| Next sibling directory index = 0 because this is the last one&lt;br /&gt;
|-&lt;br /&gt;
| 0x08&lt;br /&gt;
| 4&lt;br /&gt;
| First subdirectory index = 0 because there is no subdirectory&lt;br /&gt;
|-&lt;br /&gt;
| 0x0C&lt;br /&gt;
| 4&lt;br /&gt;
| First file index in file entry table. 0 for empty directory&lt;br /&gt;
|-&lt;br /&gt;
| 0x10&lt;br /&gt;
| 12&lt;br /&gt;
| Padding / zero?&lt;br /&gt;
|-&lt;br /&gt;
| 0x1C&lt;br /&gt;
| 4&lt;br /&gt;
| Index of the next directory in the same hash table bucket = 0 because there is no other directory&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Dummy Entry===&lt;br /&gt;
There are also some dummy entries in the array&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! Offset&lt;br /&gt;
! Length&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x00&lt;br /&gt;
| 4&lt;br /&gt;
| Current Total entry count&lt;br /&gt;
|-&lt;br /&gt;
| 0x04&lt;br /&gt;
| 4&lt;br /&gt;
| Maximum entry count = maximum directory count + 2&lt;br /&gt;
|-&lt;br /&gt;
| 0x08&lt;br /&gt;
| 28/20&lt;br /&gt;
| Padding / All zero&lt;br /&gt;
|-&lt;br /&gt;
| 0x24/0x1C&lt;br /&gt;
| 4&lt;br /&gt;
| Index of the next dummy entry. 0 if this is the last one&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The 0-th entry of the array is always a dummy entry, which functions as the head of the dummy entry linked list. The 1-st entry of the array is always the root. Therefore maximum entry count is two more than maximum directory count. Dummy entries are left there when deleting directories, and reserved for future use.&lt;br /&gt;
&lt;br /&gt;
== File Entry Table ==&lt;br /&gt;
&lt;br /&gt;
The file entry table is an array of the entry type shown below. It contains information for each file. There are three variants of the file entry type, and a dummy entry type.&lt;br /&gt;
&lt;br /&gt;
=== Savegame Variant ===&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! Offset&lt;br /&gt;
! Length&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x00&lt;br /&gt;
| 4&lt;br /&gt;
| Parent directory index in directory entry table&lt;br /&gt;
|-&lt;br /&gt;
| 0x04&lt;br /&gt;
| 16&lt;br /&gt;
| ASCII file name&lt;br /&gt;
|-&lt;br /&gt;
| 0x14&lt;br /&gt;
| 4&lt;br /&gt;
| Next sibling file index. 0 if this is the last one&lt;br /&gt;
|-&lt;br /&gt;
| 0x18&lt;br /&gt;
| 4&lt;br /&gt;
| Padding&lt;br /&gt;
|-&lt;br /&gt;
| 0x1C&lt;br /&gt;
| 4&lt;br /&gt;
| First block index in data region. 0x80000000 if the file is just created and has no data.&lt;br /&gt;
|-&lt;br /&gt;
| 0x20&lt;br /&gt;
| 8&lt;br /&gt;
| File Size&lt;br /&gt;
|-&lt;br /&gt;
| 0x28&lt;br /&gt;
| 4&lt;br /&gt;
| Padding?&lt;br /&gt;
|-&lt;br /&gt;
| 0x2C&lt;br /&gt;
| 4&lt;br /&gt;
| Index of the next file in the same hash table bucket. 0 if this is the last one&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Extdata Variant ===&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! Offset&lt;br /&gt;
! Length&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x00&lt;br /&gt;
| 4&lt;br /&gt;
| Parent directory index in directory entry table&lt;br /&gt;
|-&lt;br /&gt;
| 0x04&lt;br /&gt;
| 16&lt;br /&gt;
| ASCII file name&lt;br /&gt;
|-&lt;br /&gt;
| 0x14&lt;br /&gt;
| 4&lt;br /&gt;
| Next sibling file index. 0 if this is the last one&lt;br /&gt;
|-&lt;br /&gt;
| 0x18&lt;br /&gt;
| 4&lt;br /&gt;
| Padding&lt;br /&gt;
|-&lt;br /&gt;
| 0x1C&lt;br /&gt;
| 4&lt;br /&gt;
| Always 0x80000000&lt;br /&gt;
|-&lt;br /&gt;
| 0x20&lt;br /&gt;
| 8&lt;br /&gt;
| Unique identifier. See [[Extdata]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x28&lt;br /&gt;
| 4&lt;br /&gt;
| Padding?&lt;br /&gt;
|-&lt;br /&gt;
| 0x2C&lt;br /&gt;
| 4&lt;br /&gt;
| Index of the next file in the same hash table bucket. 0 if this is the last one&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Title database Variant ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! Offset&lt;br /&gt;
! Length&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x00&lt;br /&gt;
| 4&lt;br /&gt;
| Parent directory index in directory entry table&lt;br /&gt;
|-&lt;br /&gt;
| 0x04&lt;br /&gt;
| 8&lt;br /&gt;
| Title ID&lt;br /&gt;
|-&lt;br /&gt;
| 0x0C&lt;br /&gt;
| 4&lt;br /&gt;
| Next sibling file index. 0 if this is the last one&lt;br /&gt;
|-&lt;br /&gt;
| 0x10&lt;br /&gt;
| 4&lt;br /&gt;
| Padding&lt;br /&gt;
|-&lt;br /&gt;
| 0x14&lt;br /&gt;
| 4&lt;br /&gt;
| First block index in data region.&lt;br /&gt;
|-&lt;br /&gt;
| 0x18&lt;br /&gt;
| 8&lt;br /&gt;
| File size&lt;br /&gt;
|-&lt;br /&gt;
| 0x20&lt;br /&gt;
| 8&lt;br /&gt;
| Padding?&lt;br /&gt;
|-&lt;br /&gt;
| 0x28&lt;br /&gt;
| 4&lt;br /&gt;
| Index of the next file in the same hash table bucket. 0 if this is the last one&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Dummy Entry ===&lt;br /&gt;
Like directory entry table, file entry table also has some dummy entries:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! Offset&lt;br /&gt;
! Length&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x00&lt;br /&gt;
| 4&lt;br /&gt;
| Current total entry count&lt;br /&gt;
|-&lt;br /&gt;
| 0x04&lt;br /&gt;
| 4&lt;br /&gt;
| Maximum entry count = maximum file count + 1&lt;br /&gt;
|-&lt;br /&gt;
| 0x08&lt;br /&gt;
| 36/32&lt;br /&gt;
| Padding / All zero&lt;br /&gt;
|-&lt;br /&gt;
| 0x2C/0x28&lt;br /&gt;
| 4&lt;br /&gt;
| Index of the next dummy entry. 0 if this is the last one&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The 0-th entry of the array is always a dummy entry, which functions as the head of the dummy entry linked list. Therefore maximum entry count is one more than maximum file count. Dummy entries are left there when deleting files, and reserved for future use.&lt;br /&gt;
&lt;br /&gt;
== Directory Hash Table &amp;amp;amp; File Hash Table ==&lt;br /&gt;
&lt;br /&gt;
This is a u32 array of size = bucket count, each of which is an index to the directory / file entry table. The directory / file name is hashed and its entry index is put to the corresponding bucket. If there is already a directory/file entry in the bucket, then it appends to the linked list formed by &amp;lt;code&amp;gt;Index of the next directory/file in the same hash table bucket&amp;lt;/code&amp;gt; field in the directory/file entry table. i.e. this is a hash table using separate chaining with linked lists&lt;br /&gt;
&lt;br /&gt;
The hash function takes the parent index and the ASCII name (or title ID for title database) as key. The function is equivalent to&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;uint32_t GetBucket(&lt;br /&gt;
    char name[16 or 8], // For savegame/extdata, this takes all 16 bytes including trailing zeros; For title database, this is the 8-byte title ID&lt;br /&gt;
    uint32_t parent_dir_index,&lt;br /&gt;
    uint32_t bucket_count&lt;br /&gt;
) {&lt;br /&gt;
    uint32_t hash = parent_dir_index ^ 0x091A2B3C;&lt;br /&gt;
    for (int i = 0; i &amp;amp;lt; 4 or 2; ++i) {&lt;br /&gt;
        hash = (hash &amp;amp;gt;&amp;amp;gt; 1) | (hash &amp;amp;lt;&amp;amp;lt; 31);&lt;br /&gt;
        hash ^= (uint32_t)name[i * 4]&lt;br /&gt;
        hash ^= (uint32_t)name[i * 4 + 1] &amp;amp;lt;&amp;amp;lt; 8&lt;br /&gt;
        hash ^= (uint32_t)name[i * 4 + 2] &amp;amp;lt;&amp;amp;lt; 16&lt;br /&gt;
        hash ^= (uint32_t)name[i * 4 + 3] &amp;amp;lt;&amp;amp;lt; 24&lt;br /&gt;
    }&lt;br /&gt;
    return hash % bucket_count;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== File Allocation Table ==&lt;br /&gt;
&lt;br /&gt;
The file allocation table is an array of a 8-byte entry shown below. The array size is actually &#039;&#039;one larger than&#039;&#039; the size recorded in the filesystem header. Each entry corresponds to a block in the data region (the block size is defined in filesystem header). However, the 0th entry corresponds to nothing, so the corresponding block index is off by one. e.g. entry 31 in this table corresponds to block 30 in the data region.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! Offset&lt;br /&gt;
! Length&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x00&lt;br /&gt;
| 4&lt;br /&gt;
| bit[0:30]: Index U; bit[31]: Flag U&lt;br /&gt;
|-&lt;br /&gt;
| 0x04&lt;br /&gt;
| 4&lt;br /&gt;
| bit[0:30]: Index V; bit[31]: Flag V&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Entries in this table forms several chains, representing how blocks in the data region should be linked together. However, unlike normal FAT systems, which uses chains of entries, 3DS savegames use chain of &#039;&#039;nodes&#039;&#039;. Each node spans one or multiple entries.&lt;br /&gt;
&lt;br /&gt;
One node spanning &amp;lt;code&amp;gt;n&amp;lt;/code&amp;gt; entries starting from &amp;lt;code&amp;gt;FAT[k]&amp;lt;/code&amp;gt; is in the following format:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;FAT[k + 0]:&lt;br /&gt;
    Index_U = index of the first entry of the previous node. 0 if this is the first node.&lt;br /&gt;
    Index_V = index of the first entry of the next node. 0 if this is the last node.&lt;br /&gt;
    Flag_U set if this is the first node.&lt;br /&gt;
    Flag_V set if this node has multiple entries.&lt;br /&gt;
&lt;br /&gt;
FAT[k + 1]:&lt;br /&gt;
    Index_U = k (the first entry index of this node)&lt;br /&gt;
    Index_V = k + n - 1 (the last entry index of this node)&lt;br /&gt;
    Flag_U always set&lt;br /&gt;
    Flag_V always clear&lt;br /&gt;
&lt;br /&gt;
FAT[k + 2] ~ FAT[k + n - 2]:&lt;br /&gt;
    All these entries are uninitialized&lt;br /&gt;
&lt;br /&gt;
FAT[k + n - 1]:&lt;br /&gt;
    Index_U = k&lt;br /&gt;
    Index_V = k + n - 1&lt;br /&gt;
    Flag_U always set&lt;br /&gt;
    Flag_V always clear&lt;br /&gt;
    (Same values as FAT[k + 1])&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* Note: all indices above are entry indices (block index + 1)&lt;br /&gt;
&lt;br /&gt;
All free blocks that are not allocated to any files also form a node chain in the allocation table. The head index of this &amp;amp;quot;free chain&amp;amp;quot; is recorded in &amp;lt;code&amp;gt;FAT[0].Index_V&amp;lt;/code&amp;gt;. Other fields of &amp;lt;code&amp;gt;FAT[0]&amp;lt;/code&amp;gt; are all zero&lt;br /&gt;
&lt;br /&gt;
Here is an example: [https://raw.githubusercontent.com/wwylele/3ds-save-tool/master/disa-fat.png]&lt;br /&gt;
&lt;br /&gt;
For extdata, because only two &amp;quot;files&amp;quot; (directory and file entry tables) are allocated in the data region, and their size never changes once the extdata is created, they are guaranteed continuous in the data region, and the FAT degenerates to two big nodes. Therefore, instead of going through FAT, the offset and size of directory / file entry table can be found directly by offset = entry_table_starting block * data_region_block_size + data_region_offset and size = entry_table_block_count * data_region_block_size.&lt;/div&gt;</summary>
		<author><name>Wwylele</name></author>
	</entry>
	<entry>
		<id>https://www.3dbrew.org/w/index.php?title=Extdata&amp;diff=20946</id>
		<title>Extdata</title>
		<link rel="alternate" type="text/html" href="https://www.3dbrew.org/w/index.php?title=Extdata&amp;diff=20946"/>
		<updated>2019-05-03T19:52:51Z</updated>

		<summary type="html">&lt;p&gt;Wwylele: /* VSXE File System Metadata */ Migrate to Inner FAT&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This page describes the format and encryption of extdata, &amp;amp;quot;extra data&amp;amp;quot; stored on SD card and NAND, at:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;nand/data/&amp;amp;lt;ID&amp;amp;gt;/extdata/&amp;amp;lt;ExtdataID-High&amp;amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;sdmc/Nintendo 3DS/&amp;amp;lt;ID0&amp;amp;gt;/&amp;amp;lt;ID1&amp;amp;gt;/extdata/&amp;amp;lt;ExtdataID-High&amp;amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
ExtdataID-High is always 00000000 for SD, and always 00048000 for NAND. Regular apps can only mount SD extdata using the same extdataID which is stored in the CXI exheader. Therefore, regular apps which have the exheader extdataID set to zero can&#039;t use extdata. This restriction doesn&#039;t apply for shared extdata with extdataID high bitmask 0x48000 stored on NAND. System apps with a certain access right can mount arbitrary extdata. All NAND extdata is shared extdata, while all SD extdata is normal extdata.&lt;br /&gt;
&lt;br /&gt;
All data in this page is little-endian. All &amp;amp;quot;unused / padding&amp;amp;quot; fields can contain uninitialized data unless otherwise specified.&lt;br /&gt;
&lt;br /&gt;
= Format =&lt;br /&gt;
&lt;br /&gt;
To avoid confusion, the terms &#039;&#039;&#039;device directory / file&#039;&#039;&#039; and &#039;&#039;&#039;virtual directory / file&#039;&#039;&#039; are used with the following meanings:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Device directory / file&#039;&#039;&#039; are the real directory / file stored on SD / NAND that can be seen under path &amp;lt;code&amp;gt;nand/data/&amp;amp;lt;ID&amp;amp;gt;/extdata/&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;sdmc/Nintendo 3DS/&amp;amp;lt;ID0&amp;amp;gt;/&amp;amp;lt;ID1&amp;amp;gt;/extdata/&amp;lt;/code&amp;gt;.&lt;br /&gt;
* &#039;&#039;&#039;Virtual directory / file&#039;&#039;&#039; are directory / file stored inside extdata virtual file system, which can be seen by applications in the mounted extdata archives.&lt;br /&gt;
&lt;br /&gt;
An extdata consists of several device directories and files, which forms a file system consisting of multiple virtual directories and files.&lt;br /&gt;
&lt;br /&gt;
An extdata with ID &amp;lt;code&amp;gt;ExtdataId&amp;lt;/code&amp;gt; has the following device files:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;.../extdata/&amp;amp;lt;ExtdataID-High&amp;amp;gt;/&amp;amp;lt;ExtdataId-Low&amp;amp;gt;/Quota.dat&amp;lt;/code&amp;gt; (optional)&lt;br /&gt;
* &amp;lt;code&amp;gt;.../extdata/&amp;amp;lt;ExtdataID-High&amp;amp;gt;/&amp;amp;lt;ExtdataId-Low&amp;amp;gt;/&amp;amp;lt;SubDirID&amp;amp;gt;/&amp;amp;lt;SubFileID&amp;amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note:&lt;br /&gt;
&lt;br /&gt;
* All device files are [[DISA and DIFF|DIFF containers]]. &#039;&#039;&#039;All format description below is about the inner content of the containers&#039;&#039;&#039;. Please unwrap these files first according to the DIFF format description before reading them using the extdata format description below.&lt;br /&gt;
* &amp;lt;code&amp;gt;Quota.dat&amp;lt;/code&amp;gt; is only observed existing for NAND shared extdata.&lt;br /&gt;
* &amp;lt;code&amp;gt;&amp;amp;lt;SubDirID&amp;amp;gt;&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;&amp;amp;lt;SubFileID&amp;amp;gt;&amp;lt;/code&amp;gt; are 8-digit hex strings.&lt;br /&gt;
* Device file with &amp;lt;code&amp;gt;SubDirID = SubFileID = 00000000&amp;lt;/code&amp;gt; doesn&#039;t exist. Other ID combinations can exists.&lt;br /&gt;
* Device file with &amp;lt;code&amp;gt;SubDirID = 00000000&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;SubFileID = 00000001&amp;lt;/code&amp;gt; is the VSXE metadata file and must exist.&lt;br /&gt;
* Other files, besides &amp;lt;code&amp;gt;Quota.dat&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;00000000/00000001&amp;lt;/code&amp;gt;, are normal sub files, are these device files one-to-one correspond to virtual files. They contain raw virtual file data in the DIFF inner content.&lt;br /&gt;
* &amp;lt;code&amp;gt;SubDirID = 00000000&amp;lt;/code&amp;gt; is usually the only one device directory that can be seen. See [[#Device Directory Capacity]] for more information.&lt;br /&gt;
&lt;br /&gt;
== Quota File ==&lt;br /&gt;
&lt;br /&gt;
The inner data of &amp;lt;code&amp;gt;Quota.dat&amp;lt;/code&amp;gt; is 0x48 bytes with the following format. The exact function of this file is unclear.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! Offset&lt;br /&gt;
! Length&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x00&lt;br /&gt;
| 4&lt;br /&gt;
| Magic &amp;amp;quot;QUOT&amp;amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| 0x04&lt;br /&gt;
| 4&lt;br /&gt;
| Magic 0x30000&lt;br /&gt;
|-&lt;br /&gt;
| 0x08&lt;br /&gt;
| 4&lt;br /&gt;
| 0x1000, block size?&lt;br /&gt;
|-&lt;br /&gt;
| 0x0C&lt;br /&gt;
| 4&lt;br /&gt;
| Always 126. Probably device directory capacity. See the [[#Device Directory Capacity]] more information.&lt;br /&gt;
|-&lt;br /&gt;
| ...&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
| The meaning of other fields is unknown&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Device Directory Capacity ==&lt;br /&gt;
&lt;br /&gt;
A device directory in an extdata (a &amp;lt;code&amp;gt;&amp;amp;lt;SubDirID&amp;amp;gt;&amp;lt;/code&amp;gt; directory) seems to have a maximum number of device files it can contain. For SD extdata, this maximum number seems to be hard-coded as 126. For NAND extdata, the number is probably indicated by a field in Quota.dat, which is, again, always 126 as observed. 3DS FS tries to put all device files in the device directory &amp;lt;code&amp;gt;00000000&amp;lt;/code&amp;gt; if possible, and only when more than 126 files needed to add, a second device directory &amp;lt;code&amp;gt;00000001&amp;lt;/code&amp;gt; and so on are created. However, few extdata have such amount of files to store, so the behavior lacks of use cases to confirm.&lt;br /&gt;
&lt;br /&gt;
The number 126 is probably from some kind of other capacity of 128 with &amp;lt;code&amp;gt;&amp;amp;quot;.&amp;amp;quot;&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;&amp;amp;quot;..&amp;amp;quot;&amp;lt;/code&amp;gt; entries reserved. It is theorized that this is to keep a FAT directory table, with 0x20 bytes for each entry, in one 0x1000 cluster. The motivation is unclear.&lt;br /&gt;
&lt;br /&gt;
== VSXE Filesystem ==&lt;br /&gt;
&lt;br /&gt;
This is one variant of the [[Inner FAT|FAT filesystem]]. Please refer to its page for the description of the filesystem. In general, device file &amp;lt;code&amp;gt;00000000/00000001&amp;lt;/code&amp;gt; contains the metadata of the filesystem, while other device files (except for the Quota file) contains normal sub-files&lt;br /&gt;
&lt;br /&gt;
Each non-dummy file entry corresponds to a device file. The path to the device file is generated by the following computation:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;// See previous section about this capacity&lt;br /&gt;
const uint32_t device_dir_capacity = 126;&lt;br /&gt;
&lt;br /&gt;
// entry index is the index in the file entry table, with the first dummy entry as&lt;br /&gt;
// index = 0, which is never used for a real file.&lt;br /&gt;
// file_index = 1 is reserved for the VSXE Filesystem Metadata itself, so real files&lt;br /&gt;
// started from file_index = 2.&lt;br /&gt;
uint32_t file_index = entry_index + 1;&lt;br /&gt;
&lt;br /&gt;
uint32_t SubDirID = file_index / device_dir_capacity;&lt;br /&gt;
uint32_t SubFileID = file_index % pdevice_dir_capacity;&lt;br /&gt;
&lt;br /&gt;
char extdata_path[...]; // &amp;amp;quot;.../extdata/&amp;amp;lt;ExtdataID-High&amp;amp;gt;/&amp;amp;lt;ExtdataId-Low&amp;amp;gt;&amp;amp;quot;&lt;br /&gt;
char device_path[...]; // output path&lt;br /&gt;
sprintf(device_path, &amp;amp;quot;%s/%08x/%08x&amp;amp;quot;, extdata_path, SubDirID, SubFileID);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
When mounting extdata, the unique identifier is used to match the ID stored in subfile&#039;s [[DISA and DIFF#DIFF header|DIFF header]]. If the ID doesn&#039;t match, mounting will fail.&lt;br /&gt;
&lt;br /&gt;
== Virtual File System Structure ==&lt;br /&gt;
&lt;br /&gt;
When extdata is created, these are &#039;&#039;always&#039;&#039; created regardless of whether the title actually uses them.&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;/icon&amp;lt;/code&amp;gt; This virtual file contains the extdata icon displayed in data management. This icon can only be written to by titles when creating extdata, titles would have to recreate extdata to change the icon. This file can&#039;t be read directly, instead it is read via FS:ReadExtSaveDataIcon.&lt;br /&gt;
* &amp;lt;code&amp;gt;/user/&amp;lt;/code&amp;gt; This virtual directory contains the title&#039;s actual extdata files.&lt;br /&gt;
* &amp;lt;code&amp;gt;/boss/&amp;lt;/code&amp;gt; This virtual directory can contain SpotPass content. SpotPass content can only be downloaded to this &amp;lt;code&amp;gt;/boss&amp;lt;/code&amp;gt; virtual directory.&lt;br /&gt;
&lt;br /&gt;
User extdata and SpotPass extdata use separate mount points at &amp;lt;code&amp;gt;/user&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;/boss&amp;lt;/code&amp;gt;. Therefore one mount can&#039;t access the other virtual directory, and also can&#039;t access &amp;lt;code&amp;gt;/icon&amp;lt;/code&amp;gt;.(The title&#039;s SpotPass extdata can be mounted by the title itself, if it uses SpotPass)&lt;br /&gt;
&lt;br /&gt;
Other optional but notable directories include:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;/user/ExBanner&amp;lt;/code&amp;gt; This virtual directory can optionally store extended banners. When this is available, this banner is displayed instead of the CXI ExeFS banner. &amp;lt;code&amp;gt;COMMON.bin&amp;lt;/code&amp;gt; stores the common exbanner, while &amp;lt;code&amp;gt;&amp;amp;lt;regionlang_code&amp;amp;gt;.bin&amp;lt;/code&amp;gt; stores an optional separate region/language specific banner.(regionlang_code can be &amp;amp;quot;JPN_JP&amp;amp;quot;, &amp;amp;quot;USA_EN&amp;amp;quot;, etc)&lt;br /&gt;
&lt;br /&gt;
== SD Extdata ==&lt;br /&gt;
Usually the ExtdataID low is in the format &#039;00&amp;lt;Unique ID&amp;gt;&#039;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! JPN ExtdataID&lt;br /&gt;
! USA ExtdataID&lt;br /&gt;
! EUR ExtdataID&lt;br /&gt;
! Description&lt;br /&gt;
! Extdata images&lt;br /&gt;
|-&lt;br /&gt;
| 00000082&lt;br /&gt;
| 0000008f&lt;br /&gt;
| 00000098&lt;br /&gt;
| [[Home Menu]] extdata, this contains home-menu savedata and cached icons for applications.&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| 00000200&lt;br /&gt;
| 00000210&lt;br /&gt;
| 00000220&lt;br /&gt;
| [[System_Settings|System Settings]] extdata added with [[2.0.0-2]].&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| 00000207&lt;br /&gt;
| 00000217&lt;br /&gt;
| 00000227&lt;br /&gt;
| [[Mii Maker]], contains an ExBanner&lt;br /&gt;
| [https://dl.dropbox.com/u/20520664/extdata00000217.zip cleartext]&lt;br /&gt;
|-&lt;br /&gt;
| 00000208&lt;br /&gt;
| 00000218&lt;br /&gt;
| 00000228&lt;br /&gt;
| Streetpass Mii Plaza&lt;br /&gt;
| 11 mb big!&lt;br /&gt;
|-&lt;br /&gt;
| 00000209&lt;br /&gt;
| 00000219&lt;br /&gt;
| 00000229&lt;br /&gt;
| [[eShop]], contains store music in AAC format.&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| 0000020b&lt;br /&gt;
| 0000021b&lt;br /&gt;
| 0000022b&lt;br /&gt;
| Nintendo Zone&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| 0000020d&lt;br /&gt;
| 0000021d&lt;br /&gt;
| 0000022d&lt;br /&gt;
| Face Raiders, likely contains an ExBanner&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| 000002cc&lt;br /&gt;
| 000002cd&lt;br /&gt;
| 000002ce&lt;br /&gt;
| [[Home Menu]] theme&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| ?&lt;br /&gt;
| 000004aa&lt;br /&gt;
| 000004ab&lt;br /&gt;
| Nintendo Video Extra Data&lt;br /&gt;
This is where the video files are stored, and [[Nintendo_Video|includes]] the thumbnail, the description, and possibly some checksum info in each video file stored in the extdata images. There are always 9 files within the subdirectory &amp;quot;00000000&amp;quot; of this folder, even without any videos downloaded. The files are &amp;quot;00000001&amp;quot; - &amp;quot;00000009&amp;quot;, and &amp;quot;00000003&amp;quot; - &amp;quot;00000008&amp;quot; have the same filesize of 50.7 MB. It is possible to restore the older videos by overwriting all the files within this directory. Provided of course you have made a backup of the files before hand, by copying all the files within this directory to your computer. As far I&#039;m aware its not possible to mix and match the files in order to get certain videos in one grouping, ie. having all 3 Zelda orchestral recordings in one group of 4 Nintendo videos.&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
|00000306&lt;br /&gt;
|00000308&lt;br /&gt;
|00000307&lt;br /&gt;
|Mario Kart 7&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
| 0000030b&lt;br /&gt;
| 0000030d&lt;br /&gt;
| 0000030c&lt;br /&gt;
| Nintendogs + Cats&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| 00000326&lt;br /&gt;
| 00000326&lt;br /&gt;
| 00000326&lt;br /&gt;
| Pokédex 3D&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| 00000305&lt;br /&gt;
| 0000032d&lt;br /&gt;
| 0000033c&lt;br /&gt;
| Super Street Fighter IV 3D&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| 00000328&lt;br /&gt;
| 00000358&lt;br /&gt;
| 0000033b&lt;br /&gt;
| Ridge Racer 3D&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| ?&lt;br /&gt;
| 0000034d&lt;br /&gt;
| 00000402&lt;br /&gt;
| Samurai Warriors Chronicles&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| ?&lt;br /&gt;
| 0000034f&lt;br /&gt;
| 0000038a&lt;br /&gt;
| Dead or Alive Dimensions&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| 00000481&lt;br /&gt;
| N/A&lt;br /&gt;
| N/A&lt;br /&gt;
| Monster Hunter Tri G (Download-Quests)&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| ?&lt;br /&gt;
| 00000517&lt;br /&gt;
| 00000518&lt;br /&gt;
| Swapnote&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| 0000055d&lt;br /&gt;
| 0000055d&lt;br /&gt;
| 0000055d&lt;br /&gt;
| Pokémon X&amp;lt;br&amp;gt;Pokémon Y&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| ?&lt;br /&gt;
| 00000725&lt;br /&gt;
| 00000724&lt;br /&gt;
| Ambassador Certificate&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| ?&lt;br /&gt;
| ?&lt;br /&gt;
| 000007af&lt;br /&gt;
| New Super Mario Bros. 2&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| ?&lt;br /&gt;
| 00000863&lt;br /&gt;
| 00000864&lt;br /&gt;
| Animal Crossing: New Leaf&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| ?&lt;br /&gt;
| 00000a85&lt;br /&gt;
| 00000a86&lt;br /&gt;
| Professor Layton and the Miracle Mask&amp;lt;br&amp;gt;Professor Layton and the Azran Legacy&lt;br /&gt;
German Version ExtdataID is 00000a87&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| ?&lt;br /&gt;
| ?&lt;br /&gt;
| 00000b4f&lt;br /&gt;
| Fullblox / Crashmo&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| ?&lt;br /&gt;
| ?&lt;br /&gt;
| 00000ba9&lt;br /&gt;
| Pokémon Mystery Dungeon: Gates to Infinity&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| ?&lt;br /&gt;
| ?&lt;br /&gt;
| 00000c24&lt;br /&gt;
| Denpa men&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| 00000c73&lt;br /&gt;
| 00000c73&lt;br /&gt;
| 00000c73&lt;br /&gt;
| Save Data Transfer Tool&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| ?&lt;br /&gt;
| ?&lt;br /&gt;
| 00000d9a&lt;br /&gt;
| Donkey Kong Country™&amp;lt;br&amp;gt;Returns 3D: Trailer&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| ?&lt;br /&gt;
| ?&lt;br /&gt;
| 00000ea6&lt;br /&gt;
| Etrian Odyssey IV&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| ?&lt;br /&gt;
| 00000edf&lt;br /&gt;
| 00000ee0&lt;br /&gt;
| Super Smash Bros. for Nintendo 3DS&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| ?&lt;br /&gt;
| 00000f14&lt;br /&gt;
| 00000f1e&lt;br /&gt;
| Phoenix Wright: Ace Attorney - Dual Destinies&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| ?&lt;br /&gt;
| 00001007&lt;br /&gt;
| 00001005&lt;br /&gt;
| Professor Layton vs Phoenix Wright: Ace Attorney&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| ?&lt;br /&gt;
| ?&lt;br /&gt;
| 00001062&lt;br /&gt;
| Nintendo Pocket Football Club&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| ?&lt;br /&gt;
| ?&lt;br /&gt;
| 0000111c&lt;br /&gt;
| Yoshi&#039;s New Island&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| ?&lt;br /&gt;
| ?&lt;br /&gt;
| 00001131&lt;br /&gt;
| Fantasy Life&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| 000011c5&lt;br /&gt;
| 000011c5&lt;br /&gt;
| 000011c5&lt;br /&gt;
| Pokémon Omega Ruby&amp;lt;br&amp;gt;Pokémon Alpha Sapphire&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| ?&lt;br /&gt;
| ?&lt;br /&gt;
| 000012ca&lt;br /&gt;
| Mario vs. Donkey Kong: Tipping Stars&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| ?&lt;br /&gt;
| ?&lt;br /&gt;
| 00001499&lt;br /&gt;
| Korg DSN-12&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| ?&lt;br /&gt;
| ?&lt;br /&gt;
| 000014f2&lt;br /&gt;
| Animal Crossing: Happy Home Designer&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| 000014d1&lt;br /&gt;
| 000014d1&lt;br /&gt;
| 000014d1&lt;br /&gt;
| [[Home Menu]] badge&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| ?&lt;br /&gt;
| ?&lt;br /&gt;
| 00001632&lt;br /&gt;
| Fullblox / Stretchmo&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| ?&lt;br /&gt;
| ?&lt;br /&gt;
| 00001646&lt;br /&gt;
| Pokémon Rumble World&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| 00001648&lt;br /&gt;
| 00001648&lt;br /&gt;
| 00001648&lt;br /&gt;
| Pokémon Sun&amp;lt;br&amp;gt;Pokémon Moon&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| 0000165c&lt;br /&gt;
| 0000165c&lt;br /&gt;
| 0000165c&lt;br /&gt;
| [[Home Menu]] saved theme layouts&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| ?&lt;br /&gt;
| ?&lt;br /&gt;
| 00001678&lt;br /&gt;
| Yo-kai Watch&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| ?&lt;br /&gt;
| ?&lt;br /&gt;
| 000018fa&lt;br /&gt;
| Phoenix Wright: Ace Attorney - Spirit of Justice&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| ?&lt;br /&gt;
| ?&lt;br /&gt;
| 0000198f&lt;br /&gt;
| Animal Crossing: New Leaf - Welcome amiibo&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
| ?&lt;br /&gt;
| ?&lt;br /&gt;
| 00001a05&lt;br /&gt;
| Super Mario Maker&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| ?&lt;br /&gt;
| ?&lt;br /&gt;
| 00001a2e&lt;br /&gt;
| Swapdoodle&lt;br /&gt;
| &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== NAND Shared Extdata ==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
!  ExtdataID&lt;br /&gt;
!  Description&lt;br /&gt;
|-&lt;br /&gt;
| 0xe0000000&lt;br /&gt;
| Home Menu attempts to open this archive during boot, if [[FS:OpenArchive]] doesn&#039;t return an error Home Menu seems to then launch the [[System Transfer]] application. Home Menu doesn&#039;t actually use this archive at all except for checking whether it exists.&lt;br /&gt;
|-&lt;br /&gt;
|  0xf0000001&lt;br /&gt;
|  NAND JPEG/MPO files and phtcache.bin from the camera application are stored here. This also contains UploadData.dat.&lt;br /&gt;
|-&lt;br /&gt;
|  0xf0000002&lt;br /&gt;
|  NAND M4A files from the sound application are stored here&lt;br /&gt;
|-&lt;br /&gt;
|  0xf0000009&lt;br /&gt;
|  Used for [[BOSS_Services|SpotPass]] content storage for [[News_Services|notifications]].&lt;br /&gt;
|-&lt;br /&gt;
|  0xf000000b&lt;br /&gt;
|  Contains idb.dat, idbt.dat, gamecoin.dat, ubll.lst, CFL_DB.dat, and CFL_OldDB.dat. These files contain cleartext [[Mii_Maker|Miis]] and some data relating (including cached ICN data) to Play/Usage Records.&lt;br /&gt;
|-&lt;br /&gt;
|  0xf000000c&lt;br /&gt;
|  Contains bashotorya.dat and bashotorya2.dat.&lt;br /&gt;
|-&lt;br /&gt;
|  0xf000000d&lt;br /&gt;
|  Home Menu SpotPass content data [[BOSS_Services|storage]].&lt;br /&gt;
|-&lt;br /&gt;
|  0xf000000e&lt;br /&gt;
|  Contains [[VersionList|versionlist.dat]], used by Home Menu for the software update notification added with [[7.0.0-13]].&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Shared Extdata 0xf000000b gamecoin.dat ====&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;
| 0x4&lt;br /&gt;
| Magic number: 0x4F00&lt;br /&gt;
|-&lt;br /&gt;
| 0x4&lt;br /&gt;
| 0x2&lt;br /&gt;
| Total Play Coins&lt;br /&gt;
|-&lt;br /&gt;
| 0x6&lt;br /&gt;
| 0x2&lt;br /&gt;
| Total Play Coins obtained on the date stored below. When the below date does not match the current date, this field is reset to zero, then the date(and other fields) are updated. Once this value is &amp;gt;=10, no more Play Coins can be obtained until the current date changes.&lt;br /&gt;
|-&lt;br /&gt;
| 0x8&lt;br /&gt;
| 0x4&lt;br /&gt;
| Total step [[PTM:GetTotalStepCount|count]] at the time a new Play Coin was obtained.&lt;br /&gt;
|-&lt;br /&gt;
| 0xC&lt;br /&gt;
| 0x4&lt;br /&gt;
| Step count for the day the last Play Coin was obtained, for that day&#039;s step count(same as the step count displayed by home-menu when this file was updated).&lt;br /&gt;
|-&lt;br /&gt;
| 0x10&lt;br /&gt;
| 0x2&lt;br /&gt;
| Year&lt;br /&gt;
|-&lt;br /&gt;
| 0x12&lt;br /&gt;
| 0x1&lt;br /&gt;
| Month&lt;br /&gt;
|-&lt;br /&gt;
| 0x13&lt;br /&gt;
| 0x1&lt;br /&gt;
| Day&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The above date stores the last time new Play Coin(s) were obtained. The contents of this file is updated by home-menu. [[PTM:GetTotalStepCount]] is not checked constantly, after home-menu boot this is only checked when waking from sleep-mode. Each time home-menu updates the contents of this file, home-menu will set the Play Coin total to 300 if it&#039;s higher than the 300 Play Coin limit.&lt;br /&gt;
&lt;br /&gt;
[[Home Menu]] loads this file / opens this archive during [[Home Menu|startup]]. When accessing this file fails, like when the file/archive is corrupted(or at least on older system-versions), the result is a brick due to Home Menu using [[SVC|svcBreak]]. [[User:Yellows8|Yellows8]] bricked a 3DS this way due to corruption via invalid [[FSFile:Write]] flush flags. When opening this extdata archive(0xf000000b) fails, Home Menu executes svcBreak.&lt;br /&gt;
&lt;br /&gt;
==== Shared Extdata 0xf000000b ubll.lst ====&lt;br /&gt;
List of blocked users.&lt;br /&gt;
&lt;br /&gt;
Empty space is filled with 0xC-long sequences of 00 00 ... 07&lt;br /&gt;
&lt;br /&gt;
=== Tools ===&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/wwylele/3ds-save-tool 3ds-save-tool] - Extract/verifies extdata&lt;/div&gt;</summary>
		<author><name>Wwylele</name></author>
	</entry>
	<entry>
		<id>https://www.3dbrew.org/w/index.php?title=Savegames&amp;diff=20945</id>
		<title>Savegames</title>
		<link rel="alternate" type="text/html" href="https://www.3dbrew.org/w/index.php?title=Savegames&amp;diff=20945"/>
		<updated>2019-05-03T19:48:21Z</updated>

		<summary type="html">&lt;p&gt;Wwylele: Migrate file system doc&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This page describes the format and encryption of savegames contained in gamecards, SD and NAND. You can find savegames from various 3DS games on the [[Games]] page.&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
Savegames are stored in [[DISA and DIFF|DISA container format]]. Inside the DISA container, it forms a [[Inner FAT|FAT filesystem]]. &#039;&#039;&#039;Please refer to these pages for how to fully extract save files&#039;&#039;&#039;. This page only describes additional encryption wear leveling on top of the DISA container. These layers only apply to gamecard save games. SD savegames and NAND savegames are DISA containers in plaintext after decrypting the common SD/NAND encryption layer.&lt;br /&gt;
&lt;br /&gt;
== Gamecard savegame Encryption ==&lt;br /&gt;
&lt;br /&gt;
=== Repeating CTR Fail ===&lt;br /&gt;
On the 3DS savegames are stored much like on the DS, that is on a FLASH chip in the gamecart. On the DS these savegames were stored in plain-text but on the 3DS a layer of encryption was added. This is AES-CTR, as the contents of several savegames exhibit the odd behavior that xor-ing certain parts of the savegame together will result in the plain-text appearing.&lt;br /&gt;
&lt;br /&gt;
The reason this works is because the stream cipher used has a period of 512 bytes. That is to say, it will repeat the same keystream after 512 bytes. The way you encrypt with a stream cipher is you XOR your data with the keystream as it is produced. Unfortunately, if your streamcipher repeats and you are encrypting a known plain-text (in our case, zeros) you are basically giving away your valuable keystream.&lt;br /&gt;
&lt;br /&gt;
So how do you use this to decrypt a savegame on a 3DS? First off, you chunk up the savegame into 512 byte chunks. Then, you bin these chunks by their contents, discarding any that contain only FF. Now look for the most common chunk. This is your keystream. Now XOR the keystream with your original savegame and you should have a fully decrypted savegame. XOR with the keystream again to produce an encrypted savegame.&lt;br /&gt;
&lt;br /&gt;
=== Savegame keyY ===&lt;br /&gt;
&lt;br /&gt;
All gamecard and SD savegames are encrypted with AES-CTR. The base CTR for gamecard savegames is all-zero. The gamecard savegame [[AES|keyslots]]&#039; keyY(these savegame keyslots use the hardware key-generator) is unique for each region and for each game. The [[NCSD]] partition flags determine the method used to generate this keyY. When the save [[NCSD]] flags checked by the running NATIVE_FIRM are all-zero, the system will use the repeating CTR, otherwise a proper CTR which never repeats within the image is used.&lt;br /&gt;
&lt;br /&gt;
The [[AES]]-CMAC (which uses a hardware key-generator keyslot, as mentioned above) at the the beginning of the savegame must match the calculated CMAC using the DISA/DIFF data, otherwise the savegame is considered corrupted(see below).&lt;br /&gt;
&lt;br /&gt;
When all of the flags checked by the running NATIVE_FIRM are clear, the keyY(original keyY method used with saves where the CTR repeats within the image) is the following:&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;
| First 8-bytes from the plaintext [[NCCH#CXI|CXI]] accessdesc signature.&lt;br /&gt;
|-&lt;br /&gt;
| 0x8&lt;br /&gt;
| 0x4&lt;br /&gt;
| u32 CardID0 from [[Gamecards|gamecard]] plaintext-mode command 0x90, Process9 reads this with the [[NTRCARD]] hw. The actual cmdID used by Process9 is different since Process9 reads it with the gamecard in encrypted-mode.&lt;br /&gt;
|-&lt;br /&gt;
| 0xC&lt;br /&gt;
| 0x4&lt;br /&gt;
| u32 CardID1 from [[Gamecards|gamecard]] plaintext-mode command 0xA0, Process9 reads this with the [[NTRCARD]] hw. The actual cmdID used by Process9 is different since Process9 reads it with the gamecard in encrypted-mode.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== [[2.0.0-2]] Hashed keyY and [[2.2.0-4]] Savegame Encryption ====&lt;br /&gt;
&lt;br /&gt;
When certain [[NCSD]] partition flags are set, a SHA-256 hash is calculated over the data from the CXI(same data used with the original plain keyY), and the 0x40-bytes read from a gamecard command(this 0x40-byte data is also read by [[Process_Services_PXI|GetRomId]], which is the gamecard-uniqueID). The first 0x10-bytes from this hash is used for the keyY. When flag[7] is set, the CTR will never repeat within the save image, unlike the original CTR-method. All games which had the retail NCSD image finalized after the [[2.2.0-4]] update(and contain [[2.2.0-4]]+ in the [[System Update CFA|System update partition]]), use this encryption method.&lt;br /&gt;
&lt;br /&gt;
This keyY generation method was implemented with [[2.0.0-2]] via NCSD partition flag[3], however the proper CTR wasn&#039;t implemented for flag[7] until [[2.2.0-4]]. The hashed keyY flag[3] implemented with [[2.0.0-2]] was likely never used with retail gamecards.&lt;br /&gt;
&lt;br /&gt;
==== [[6.0.0-11]] Savegame keyY ====&lt;br /&gt;
&lt;br /&gt;
[[6.0.0-11]] implemented support for generating the savegame keyY with a new method, this method is much more complex than previous keyY methods. This is enabled via new [[NCSD]] partition flags, all retail games which have the NCSD image finalized after the [[6.0.0-11]] release(and [[6.0.0-11]]+ in the system update partition) will have these flags set for using this new method.&lt;br /&gt;
&lt;br /&gt;
A SHA-256 hash is calculated over the same data used with the above hashed keyY method, after hashing the above data the following data is hashed: the CXI programID, and the ExeFS:/.code hash from the decrypted [[ExeFS]] header. An [[AES]]-CMAC (the keyslot used for this uses the hardware key-scrambler) is then calculated over this hash, the output CMAC is used for the savegame keyY.&lt;br /&gt;
&lt;br /&gt;
The keyY used for calculating this AES-CMAC is initialized while NATIVE_FIRM is loading, this keyY is generated via the [[RSA]] engine. The RSA slot used here is slot0(key-data for slot0 is initialized by bootrom), this RSA slot0 key-data is overwritten during system boot. This RSA slot0 key-data gets overwritten with the RSA key-data used for verifying RSA signatures, every time Process9 verifies any RSA signatures except for [[NCCH|NCCH]] accessdesc signatures. Starting with [[7.0.0-13]] this key-init function used at boot is also used to initialize a separate keyslot used for the new [[NCCH]] encryption method.&lt;br /&gt;
&lt;br /&gt;
This [[FIRM|Process9]] key-init function first checks if a certain 0x10-byte block in the 0x01FF8000 region is all-zero. When all-zero it immediately returns, otherwise it clears that block then continues to do the key generation. This is likely for supporting launching a v6.0+ NATIVE_FIRM under this FIRM.&lt;br /&gt;
&lt;br /&gt;
== Gamecard wear leveling ==&lt;br /&gt;
&lt;br /&gt;
The 3DS employs a wear leveling scheme on the savegame FLASH chips(only used for CARD1 gamecards). This is done through the usage of blockmaps and a journal. The blockmap is located at offset 0 of the flash chip, and is immediately followed by the journal. The initial state is dictated by the blockmap, and the journal is then applied to that.&lt;br /&gt;
&lt;br /&gt;
First, there are 8 bytes whose purposes are currently unknown. Then comes the actual blockmap.&lt;br /&gt;
The blockmap structure is simple:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
struct header_entry {&lt;br /&gt;
        uint8_t phys_sec; // when bit7 is set, block has checksums, otherwise checksums are all zero&lt;br /&gt;
        uint8_t alloc_cnt;&lt;br /&gt;
        uint8_t chksums[8];&lt;br /&gt;
} __attribute__((__packed__));&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There&#039;s one entry per sector, counting from physical sector 1 (sector 0 contains the blockmap/journal).&lt;br /&gt;
&lt;br /&gt;
The 2 bytes that follow the blockmap are the CRC16 (with starting value 0xFFFF (like modbus)) of the first 8 bytes and the blockmap.&lt;br /&gt;
&lt;br /&gt;
Then comes the journal.&lt;br /&gt;
The journal structure is as follows:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
struct sector_entry {&lt;br /&gt;
        uint8_t virt_sec;       // Mapped to sector&lt;br /&gt;
        uint8_t prev_virt_sec;  // Physical sector previously mapped to&lt;br /&gt;
        uint8_t phys_sec;       // Mapped from sector&lt;br /&gt;
        uint8_t prev_phys_sec;  // Virtual sector previously mapped to&lt;br /&gt;
        uint8_t phys_realloc_cnt;       // Amount of times physical sector has been remapped&lt;br /&gt;
        uint8_t virt_realloc_cnt;       // Amount of times virtual sector has been remapped&lt;br /&gt;
        uint8_t chksums[8];&lt;br /&gt;
} __attribute__((__packed__));&lt;br /&gt;
&lt;br /&gt;
struct long_sector_entry{&lt;br /&gt;
        struct sector_entry sector;&lt;br /&gt;
        struct sector_entry dupe;&lt;br /&gt;
        uint32_t magic;&lt;br /&gt;
}__attribute__((__packed__));&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
With magic being a constant 0x080d6ce0.&lt;br /&gt;
&lt;br /&gt;
The checksums in the blockmap/journal entries work as follows:&lt;br /&gt;
* each byte is the checksum of an encrypted 0x200 bytes large block&lt;br /&gt;
* to calculate the checksum, a CRC16 of the block (with starting value 0xFFFF) is calculated, and the two bytes of the CRC16 are XORed together to produce the 8bit checksum&lt;br /&gt;
&lt;br /&gt;
== Initialization ==&lt;br /&gt;
&lt;br /&gt;
When a save FLASH contains all xFFFF blocks it&#039;s assumed uninitialized by the game cartridges and it initializes default data in place, without prompting the user. The 0xFFFFFFFF blocks are uninitialized data. When creating a non-gamecard savegame and other images/files, it&#039;s initially all 0xFFFFFFFF until it&#039;s formatted where some of the blocks are overwritten with encrypted data.&lt;br /&gt;
&lt;br /&gt;
I got a new game SplinterCell3D-Pal and I downloaded the save and it was 128KB of 0xFF, except the first 0x10 bytes which were the letter &#039;Z&#039; (uppercase) --[[User:Elisherer|Elisherer]] 22:41, 15 October 2011 (CEST)&lt;br /&gt;
&lt;br /&gt;
== Fun Facts ==&lt;br /&gt;
&lt;br /&gt;
If you have facts that you found out by looking at the binary files please share them here:&lt;br /&gt;
&lt;br /&gt;
* From one save to another the game backups the last files that were in the partition and the entire image header in &amp;quot;random&amp;quot; locations.. --[[User:Elisherer|Elisherer]] 22:41, 15 October 2011 (CEST)&lt;br /&gt;
&lt;br /&gt;
== Tools ==&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/3dshax/3ds/tree/master/3dsfuse 3dsfuse] supports reading and modifying savegames. In the mounted FUSE filesystem, the /output.sav is the raw FLASH save-image. When the save was modified, a separate tool to update the CMAC must be used with /clean.sav, prior to writing output.sav to a gamecard.&lt;br /&gt;
* [[3DSExplorer]] supports reading of savegames, it doesn&#039;t support reading the new encrypted savegames and maybe in the future it will support modifying (some of the modyfing code is already implemented).&lt;br /&gt;
* [https://github.com/wwylele/3ds-save-tool wwylele&#039;s 3ds-save-tool] supports extracting files from savegames and extdata. It properly reconstructs data from the DPFS tree and extracts files in directories hierarchy.&lt;br /&gt;
* [https://github.com/wwylele/3dsfuse-ex 3dsfuse-ex] similar to 3dsfuse, but supports savegame inner FS, proper DPFS handling, and automatic CMAC update. Still WIP.&lt;br /&gt;
&lt;br /&gt;
[[セーブデータ|Japanese]]&lt;/div&gt;</summary>
		<author><name>Wwylele</name></author>
	</entry>
	<entry>
		<id>https://www.3dbrew.org/w/index.php?title=Inner_FAT&amp;diff=20944</id>
		<title>Inner FAT</title>
		<link rel="alternate" type="text/html" href="https://www.3dbrew.org/w/index.php?title=Inner_FAT&amp;diff=20944"/>
		<updated>2019-05-03T19:39:59Z</updated>

		<summary type="html">&lt;p&gt;Wwylele: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This page describes a common FAT-like file system used in [[Savegames]], [[Extdata]] and [[Title Database]]. This file system format has several variants depending on which kind of data it stores. All the three kinds of data that use this file system structure also happen to use the [[DISA and DIFF]] container as well, but there is no direct relationship between the file system and the DISA/DIFF container. All data formats described here is in the inner data of the DISA/DIFF container (i.e. IVFC level 4). Please refer to the DISA/DIFF page for how to unwrap it first before trying to extract the file system.&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
&lt;br /&gt;
The file system consists of the following components:&lt;br /&gt;
* header&lt;br /&gt;
* directory hash table&lt;br /&gt;
* file hash table&lt;br /&gt;
* file allocation table&lt;br /&gt;
* directory entry table&lt;br /&gt;
* file entry table&lt;br /&gt;
* data region&lt;br /&gt;
&lt;br /&gt;
The file allocation table (FAT) forms several linked lists inside, each of which represents a &amp;quot;file&amp;quot; allocated in the data region. Please refer to the File Allocation Table section below for more detail. In some variants, the directory entry table and the file entry table are also allocated as two special &amp;quot;files&amp;quot; in the data region, managed by the FAT, while in others they are stand-alone tables located outside the data region.&lt;br /&gt;
&lt;br /&gt;
== Layout Variants ==&lt;br /&gt;
Four variants of the file system layout has been identified. A summary diagram can be found here: [https://github.com/wwylele/3ds-save-tool/raw/master/inner-fat.png]&lt;br /&gt;
&lt;br /&gt;
=== Savegame, &amp;lt;code&amp;gt;duplicate data = true&amp;lt;/code&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
Such savegame is a single DISA container that only has one partition which is always configured as external IVFC level 4 disabled (see [[DISA and DIFF|DISA]] format for details). All components are stored in this partition as&lt;br /&gt;
&lt;br /&gt;
* filesystem header at the beginning&lt;br /&gt;
* directory hash table&lt;br /&gt;
* file hash table&lt;br /&gt;
* file allocation table&lt;br /&gt;
* data region&lt;br /&gt;
** directory entry table is allocated inside data region&lt;br /&gt;
** file entry table as well&lt;br /&gt;
** all file data is also allocated here&lt;br /&gt;
&lt;br /&gt;
In this layout, all data is duplicated by DISA&#039;s DPFS tree, which is what the parameter &amp;lt;code&amp;gt;duplicate data&amp;lt;/code&amp;gt; implies.&lt;br /&gt;
&lt;br /&gt;
=== Savegame, &amp;lt;code&amp;gt;duplicate data = false&amp;lt;/code&amp;gt; === &lt;br /&gt;
Such savegame is a single DISA container that has two partitions. Partition A is always configured as external IVFC level 4 disabled, and partition B is configured as it enabled. Components are stored among the two partitions as&lt;br /&gt;
&lt;br /&gt;
* Partition A&lt;br /&gt;
** filesystem header at the beginning.&lt;br /&gt;
** directory hash table&lt;br /&gt;
** file hash table&lt;br /&gt;
** (stand-alone) file allocation table&lt;br /&gt;
** (stand-alone) directory entry table&lt;br /&gt;
** file entry table&lt;br /&gt;
* Partition B&lt;br /&gt;
** used as data region entirely, and only has file data allocated.&lt;br /&gt;
&lt;br /&gt;
In this layout, all file system metadata is duplicated by partition A DPFS tree, but file data is not as partition B has external IVFC level 4.&lt;br /&gt;
&lt;br /&gt;
=== Extdata ===&lt;br /&gt;
An extdata consists of several DIFF containers (device files), among which the special device file &amp;lt;code&amp;gt;00000000/00000001&amp;lt;/code&amp;gt; contains the inner FAT system, while other devices contains normal subfiles of the extdata. Please refer to [[Extdata]] for detail. The special file &amp;lt;code&amp;gt;00000000/00000001&amp;lt;/code&amp;gt; contists of the following components&lt;br /&gt;
&lt;br /&gt;
* filesystem header at the beginning&lt;br /&gt;
* directory hash table&lt;br /&gt;
* file hash table&lt;br /&gt;
* file allocation table (degenerate, because the data region only has two &amp;quot;files&amp;quot;: the directory entry table and the file entry table)&lt;br /&gt;
* data region&lt;br /&gt;
** directory entry table allocated inside data region&lt;br /&gt;
** file entry table as well&lt;br /&gt;
** normal subfiles are NOT in the data region. They are in their DIFF containers instead.&lt;br /&gt;
&lt;br /&gt;
=== Title database ===&lt;br /&gt;
All [[Title Database]] files are DIFF containers. Except for &amp;lt;code&amp;gt;certs.db&amp;lt;/code&amp;gt;, all of them uses this filesystem in the DIFF inner data, which consists of&lt;br /&gt;
&lt;br /&gt;
* database-specific pre-header at the beginning (See [[Title Database]])&lt;br /&gt;
* filesystem header&lt;br /&gt;
* directory Hash Table (degenerate and always has only one bucket, as there is only one directory for &amp;quot;root&amp;quot;)&lt;br /&gt;
* file Hash Table&lt;br /&gt;
* file allocation table&lt;br /&gt;
* data region&lt;br /&gt;
** directory entry table allocated inside data region (degenerate, as there is only one directory for &amp;quot;root&amp;quot;)&lt;br /&gt;
** file entry table as well&lt;br /&gt;
** title entries (title info or ticket) are allocated as normal files in the data region as well.&lt;br /&gt;
&lt;br /&gt;
== Filesystem Header ==&lt;br /&gt;
Offsets listed in the table below are all relative to the beginning of the header, while all &amp;quot;starting block index&amp;quot; are relative to the beginning of data region. This is especially important for title database, as the offsets doesn&#039;t count the pre header.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! Offset&lt;br /&gt;
! Length&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x00&lt;br /&gt;
| 4&lt;br /&gt;
| Magic (&amp;quot;SAVE&amp;quot; for savegame; &amp;quot;BDRI&amp;quot; for title database; &amp;quot;VSXE&amp;quot; for extdata)&lt;br /&gt;
|-&lt;br /&gt;
| 0x04&lt;br /&gt;
| 4&lt;br /&gt;
| Version (0x40000 for savegame; 0x30000 for title database and extdata)&lt;br /&gt;
|-&lt;br /&gt;
| 0x08&lt;br /&gt;
| 8&lt;br /&gt;
| Filesystem Information offset (Y, =0x20 for savegame and title database, =0x138 for extdata)&lt;br /&gt;
|-&lt;br /&gt;
| 0x10&lt;br /&gt;
| 8&lt;br /&gt;
| Filesystem image size in blocks&lt;br /&gt;
|-&lt;br /&gt;
| 0x18&lt;br /&gt;
| 4&lt;br /&gt;
| Filesystem Image block size&lt;br /&gt;
|-&lt;br /&gt;
| 0x1C&lt;br /&gt;
| 4&lt;br /&gt;
| Padding&lt;br /&gt;
|-&lt;br /&gt;
| 0x20 &lt;br /&gt;
| 0x118 in total&lt;br /&gt;
| Below is additional data for extdata. Not present in savegame or title database&lt;br /&gt;
|-&lt;br /&gt;
| 0x20&lt;br /&gt;
| 8&lt;br /&gt;
| Unknown&lt;br /&gt;
|-&lt;br /&gt;
| 0x28&lt;br /&gt;
| 4&lt;br /&gt;
| &#039;Action&#039; made on most recently mounted Extdata image&lt;br /&gt;
|-&lt;br /&gt;
| 0x2C&lt;br /&gt;
| 4&lt;br /&gt;
| Unknown&lt;br /&gt;
|-&lt;br /&gt;
| 0x30&lt;br /&gt;
| 4&lt;br /&gt;
| D of most recently mounted Extdata image&lt;br /&gt;
|-&lt;br /&gt;
| 0x34&lt;br /&gt;
| 4&lt;br /&gt;
| Unknown&lt;br /&gt;
|-&lt;br /&gt;
| 0x38&lt;br /&gt;
| 0x100&lt;br /&gt;
| Mount path, from most recently mounted Extdata image&lt;br /&gt;
|-&lt;br /&gt;
| Y &lt;br /&gt;
| 0x68 in total&lt;br /&gt;
| Below is Filesystem Information&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x00&lt;br /&gt;
| 4&lt;br /&gt;
| Unknown&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x04&lt;br /&gt;
| 4&lt;br /&gt;
| Data region block size&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x08&lt;br /&gt;
| 8&lt;br /&gt;
| Directory hash table offset&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x10&lt;br /&gt;
| 4&lt;br /&gt;
| Directory hash table bucket count (=1 for title database)&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x14&lt;br /&gt;
| 4&lt;br /&gt;
| Padding&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x18&lt;br /&gt;
| 8&lt;br /&gt;
| File hash table offset&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x20&lt;br /&gt;
| 4&lt;br /&gt;
| File hash table bucket count&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x24&lt;br /&gt;
| 4&lt;br /&gt;
| Padding&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x28&lt;br /&gt;
| 8&lt;br /&gt;
| File allocation table offset&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x30&lt;br /&gt;
| 4&lt;br /&gt;
| File allocation table entry count&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x34&lt;br /&gt;
| 4&lt;br /&gt;
| Padding&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x38&lt;br /&gt;
| 8&lt;br /&gt;
| Data region offset &lt;br /&gt;
(0 for savegame &amp;lt;code&amp;gt;duplicate data = false&amp;lt;/code&amp;gt; layout, as the data region is in partition B for that layout)&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x40&lt;br /&gt;
| 4&lt;br /&gt;
| Data region block count &lt;br /&gt;
(= number of file allocation table entries excluding the leading 0th entry. See below)&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x44&lt;br /&gt;
| 4&lt;br /&gt;
| Padding&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x48&lt;br /&gt;
| 8&lt;br /&gt;
| for savegame &amp;lt;code&amp;gt;duplicate data = false&amp;lt;/code&amp;gt; layout: directory entry table offset;&lt;br /&gt;
otherwise: u32 directory entry table starting block index + u32 directory entry table block count&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x50&lt;br /&gt;
| 4&lt;br /&gt;
| Maximum directory count, excluding the mandatory &amp;quot;root&amp;quot; directory &lt;br /&gt;
(=1 for title database, but that 1 free directory slot is never used)&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x54&lt;br /&gt;
| 4&lt;br /&gt;
| Padding&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x58&lt;br /&gt;
| 8&lt;br /&gt;
| for savegame &amp;lt;code&amp;gt;duplicate data = false&amp;lt;/code&amp;gt; layout: file entry table offset;&lt;br /&gt;
otherwise: u32 file entry table starting block index + u32 file entry table block count&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x60&lt;br /&gt;
| 4&lt;br /&gt;
| Maximum file count&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x64&lt;br /&gt;
| 4&lt;br /&gt;
| Padding&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
* For savegames, the file/directory bucket count &amp;amp; maximum count are specified by the parameters of [[FS:FormatSaveData]] or [[FS:CreateSystemSaveData]].&lt;br /&gt;
* For extdata, the maximum file/directory count are specified by the parameters of [[FS:CreateExtSaveData]]. The bucket count is likely calculated by the system.&lt;br /&gt;
* Directory &amp;amp; file entry tables are allocated in the data region as if they are two normal files (except for savegame &amp;lt;code&amp;gt;duplicate data = false&amp;lt;/code&amp;gt; layout). However, only continuous allocation has been observed, so directly reading block_count * block_size bytes from data_region + starting_block_index * block_size should be safe. &lt;br /&gt;
&lt;br /&gt;
== Directory Entry Table ==&lt;br /&gt;
&lt;br /&gt;
The directory entry table is an array of the entry type shown below. It describes the directory hierarchy of the file system. There are two variants of the directory entry type, and a dummy entry type.&lt;br /&gt;
&lt;br /&gt;
=== Savegame/Extdata Variant===&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! Offset&lt;br /&gt;
! Length&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x00&lt;br /&gt;
| 4&lt;br /&gt;
| Parent directory index. 0 for root&lt;br /&gt;
|-&lt;br /&gt;
| 0x04&lt;br /&gt;
| 16&lt;br /&gt;
| ASCII directory name in. All zero for root&lt;br /&gt;
|-&lt;br /&gt;
| 0x14&lt;br /&gt;
| 4&lt;br /&gt;
| Next sibling directory index. 0 if this is the last one&lt;br /&gt;
|-&lt;br /&gt;
| 0x18&lt;br /&gt;
| 4&lt;br /&gt;
| First subdirectory index. 0 if not exists&lt;br /&gt;
|-&lt;br /&gt;
| 0x1C&lt;br /&gt;
| 4&lt;br /&gt;
| First file index in file entry table. 0 for empty directory&lt;br /&gt;
|-&lt;br /&gt;
| 0x20&lt;br /&gt;
| 4&lt;br /&gt;
| Padding / zero?&lt;br /&gt;
|-&lt;br /&gt;
| 0x24&lt;br /&gt;
| 4&lt;br /&gt;
| Index of the next directory in the same hash table bucket. 0 if this is the last one&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Title Database Variant===&lt;br /&gt;
Because title database only has one directory for &amp;quot;root&amp;quot;, its directory entry table degenerates into many zeros whose structure is not recognizable. The size of one entry here is guessed.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! Offset&lt;br /&gt;
! Length&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x00&lt;br /&gt;
| 4&lt;br /&gt;
| Parent directory index = 0 for root&lt;br /&gt;
|-&lt;br /&gt;
| 0x04&lt;br /&gt;
| 4&lt;br /&gt;
| Next sibling directory index = 0 because this is the last one&lt;br /&gt;
|-&lt;br /&gt;
| 0x08&lt;br /&gt;
| 4&lt;br /&gt;
| First subdirectory index = 0 because there is no subdirectory&lt;br /&gt;
|-&lt;br /&gt;
| 0x0C&lt;br /&gt;
| 4&lt;br /&gt;
| First file index in file entry table. 0 for empty directory&lt;br /&gt;
|-&lt;br /&gt;
| 0x10&lt;br /&gt;
| 12&lt;br /&gt;
| Padding / zero?&lt;br /&gt;
|-&lt;br /&gt;
| 0x1C&lt;br /&gt;
| 4&lt;br /&gt;
| Index of the next directory in the same hash table bucket = 0 because there is no other directory&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Dummy Entry===&lt;br /&gt;
There are also some dummy entries in the array&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! Offset&lt;br /&gt;
! Length&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x00&lt;br /&gt;
| 4&lt;br /&gt;
| Current Total entry count&lt;br /&gt;
|-&lt;br /&gt;
| 0x04&lt;br /&gt;
| 4&lt;br /&gt;
| Maximum entry count = maximum directory count + 2&lt;br /&gt;
|-&lt;br /&gt;
| 0x08&lt;br /&gt;
| 28/20&lt;br /&gt;
| Padding / All zero&lt;br /&gt;
|-&lt;br /&gt;
| 0x24/0x1C&lt;br /&gt;
| 4&lt;br /&gt;
| Index of the next dummy entry. 0 if this is the last one&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The 0-th entry of the array is always a dummy entry, which functions as the head of the dummy entry linked list. The 1-st entry of the array is always the root. Therefore maximum entry count is two more than maximum directory count. Dummy entries are left there when deleting directories, and reserved for future use.&lt;br /&gt;
&lt;br /&gt;
== File Entry Table ==&lt;br /&gt;
&lt;br /&gt;
The file entry table is an array of the entry type shown below. It contains information for each file. There are three variants of the file entry type, and a dummy entry type.&lt;br /&gt;
&lt;br /&gt;
=== Savegame Variant ===&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! Offset&lt;br /&gt;
! Length&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x00&lt;br /&gt;
| 4&lt;br /&gt;
| Parent directory index in directory entry table&lt;br /&gt;
|-&lt;br /&gt;
| 0x04&lt;br /&gt;
| 16&lt;br /&gt;
| ASCII file name&lt;br /&gt;
|-&lt;br /&gt;
| 0x14&lt;br /&gt;
| 4&lt;br /&gt;
| Next sibling file index. 0 if this is the last one&lt;br /&gt;
|-&lt;br /&gt;
| 0x18&lt;br /&gt;
| 4&lt;br /&gt;
| Padding&lt;br /&gt;
|-&lt;br /&gt;
| 0x1C&lt;br /&gt;
| 4&lt;br /&gt;
| First block index in data region. 0x80000000 if the file is just created and has no data.&lt;br /&gt;
|-&lt;br /&gt;
| 0x20&lt;br /&gt;
| 8&lt;br /&gt;
| File Size&lt;br /&gt;
|-&lt;br /&gt;
| 0x28&lt;br /&gt;
| 4&lt;br /&gt;
| Padding?&lt;br /&gt;
|-&lt;br /&gt;
| 0x2C&lt;br /&gt;
| 4&lt;br /&gt;
| Index of the next file in the same hash table bucket. 0 if this is the last one&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Extdata Variant ===&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! Offset&lt;br /&gt;
! Length&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x00&lt;br /&gt;
| 4&lt;br /&gt;
| Parent directory index in directory entry table&lt;br /&gt;
|-&lt;br /&gt;
| 0x04&lt;br /&gt;
| 16&lt;br /&gt;
| ASCII file name&lt;br /&gt;
|-&lt;br /&gt;
| 0x14&lt;br /&gt;
| 4&lt;br /&gt;
| Next sibling file index. 0 if this is the last one&lt;br /&gt;
|-&lt;br /&gt;
| 0x18&lt;br /&gt;
| 4&lt;br /&gt;
| Padding&lt;br /&gt;
|-&lt;br /&gt;
| 0x1C&lt;br /&gt;
| 4&lt;br /&gt;
| Always 0x80000000&lt;br /&gt;
|-&lt;br /&gt;
| 0x20&lt;br /&gt;
| 8&lt;br /&gt;
| Unique identifier. See [[Extdata]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x28&lt;br /&gt;
| 4&lt;br /&gt;
| Padding?&lt;br /&gt;
|-&lt;br /&gt;
| 0x2C&lt;br /&gt;
| 4&lt;br /&gt;
| Index of the next file in the same hash table bucket. 0 if this is the last one&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Title database Variant ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! Offset&lt;br /&gt;
! Length&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x00&lt;br /&gt;
| 4&lt;br /&gt;
| Parent directory index in directory entry table&lt;br /&gt;
|-&lt;br /&gt;
| 0x04&lt;br /&gt;
| 8&lt;br /&gt;
| Title ID&lt;br /&gt;
|-&lt;br /&gt;
| 0x0C&lt;br /&gt;
| 4&lt;br /&gt;
| Next sibling file index. 0 if this is the last one&lt;br /&gt;
|-&lt;br /&gt;
| 0x10&lt;br /&gt;
| 4&lt;br /&gt;
| Padding&lt;br /&gt;
|-&lt;br /&gt;
| 0x14&lt;br /&gt;
| 4&lt;br /&gt;
| First block index in data region.&lt;br /&gt;
|-&lt;br /&gt;
| 0x18&lt;br /&gt;
| 8&lt;br /&gt;
| File size&lt;br /&gt;
|-&lt;br /&gt;
| 0x20&lt;br /&gt;
| 8&lt;br /&gt;
| Padding?&lt;br /&gt;
|-&lt;br /&gt;
| 0x28&lt;br /&gt;
| 4&lt;br /&gt;
| Index of the next file in the same hash table bucket. 0 if this is the last one&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Dummy Entry ===&lt;br /&gt;
Like directory entry table, file entry table also has some dummy entries:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! Offset&lt;br /&gt;
! Length&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x00&lt;br /&gt;
| 4&lt;br /&gt;
| Current total entry count&lt;br /&gt;
|-&lt;br /&gt;
| 0x04&lt;br /&gt;
| 4&lt;br /&gt;
| Maximum entry count = maximum file count + 1&lt;br /&gt;
|-&lt;br /&gt;
| 0x08&lt;br /&gt;
| 36/32&lt;br /&gt;
| Padding / All zero&lt;br /&gt;
|-&lt;br /&gt;
| 0x2C/0x28&lt;br /&gt;
| 4&lt;br /&gt;
| Index of the next dummy entry. 0 if this is the last one&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The 0-th entry of the array is always a dummy entry, which functions as the head of the dummy entry linked list. Therefore maximum entry count is one more than maximum file count. Dummy entries are left there when deleting files, and reserved for future use.&lt;br /&gt;
&lt;br /&gt;
== Directory Hash Table &amp;amp;amp; File Hash Table ==&lt;br /&gt;
&lt;br /&gt;
This is a u32 array of size = bucket count, each of which is an index to the directory / file entry table. The directory / file name is hashed and its entry index is put to the corresponding bucket. If there is already a directory/file entry in the bucket, then it appends to the linked list formed by &amp;lt;code&amp;gt;Index of the next directory/file in the same hash table bucket&amp;lt;/code&amp;gt; field in the directory/file entry table. i.e. this is a hash table using separate chaining with linked lists&lt;br /&gt;
&lt;br /&gt;
The hash function takes the parent index and the ASCII name (or title ID for title database) as key. The function is equivalent to&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;uint32_t GetBucket(&lt;br /&gt;
    char name[16 or 8], // For savegame/extdata, this takes all 16 bytes including trailing zeros; For title database, this is the 8-byte title ID&lt;br /&gt;
    uint32_t parent_dir_index,&lt;br /&gt;
    uint32_t bucket_count&lt;br /&gt;
) {&lt;br /&gt;
    uint32_t hash = parent_dir_index ^ 0x091A2B3C;&lt;br /&gt;
    for (int i = 0; i &amp;amp;lt; 4 or 2; ++i) {&lt;br /&gt;
        hash = (hash &amp;amp;gt;&amp;amp;gt; 1) | (hash &amp;amp;lt;&amp;amp;lt; 31);&lt;br /&gt;
        hash ^= (uint32_t)name[i * 4]&lt;br /&gt;
        hash ^= (uint32_t)name[i * 4 + 1] &amp;amp;lt;&amp;amp;lt; 8&lt;br /&gt;
        hash ^= (uint32_t)name[i * 4 + 2] &amp;amp;lt;&amp;amp;lt; 16&lt;br /&gt;
        hash ^= (uint32_t)name[i * 4 + 3] &amp;amp;lt;&amp;amp;lt; 24&lt;br /&gt;
    }&lt;br /&gt;
    return hash % bucket_count;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== File Allocation Table ==&lt;br /&gt;
&lt;br /&gt;
The file allocation table is an array of a 8-byte entry shown below. The array size is actually &#039;&#039;one larger than&#039;&#039; the size recorded in the filesystem header. Each entry corresponds to a block in the data region (the block size is defined in filesystem header). However, the 0th entry corresponds to nothing, so the corresponding block index is off by one. e.g. entry 31 in this table corresponds to block 30 in the data region.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! Offset&lt;br /&gt;
! Length&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x00&lt;br /&gt;
| 4&lt;br /&gt;
| bit[0:30]: Index U; bit[31]: Flag U&lt;br /&gt;
|-&lt;br /&gt;
| 0x04&lt;br /&gt;
| 4&lt;br /&gt;
| bit[0:30]: Index V; bit[31]: Flag V&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Entries in this table forms several chains, representing how blocks in the data region should be linked together. However, unlike normal FAT systems, which uses chains of entries, 3DS savegames use chain of &#039;&#039;nodes&#039;&#039;. Each node spans one or multiple entries.&lt;br /&gt;
&lt;br /&gt;
One node spanning &amp;lt;code&amp;gt;n&amp;lt;/code&amp;gt; entries starting from &amp;lt;code&amp;gt;FAT[k]&amp;lt;/code&amp;gt; is in the following format:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;FAT[k + 0]:&lt;br /&gt;
    Index_U = index of the first entry of the previous node. 0 if this is the first node.&lt;br /&gt;
    Index_V = index of the first entry of the next node. 0 if this is the last node.&lt;br /&gt;
    Flag_U set if this is the first node.&lt;br /&gt;
    Flag_V set if this node has multiple entries.&lt;br /&gt;
&lt;br /&gt;
FAT[k + 1]:&lt;br /&gt;
    Index_U = k (the first entry index of this node)&lt;br /&gt;
    Index_V = k + n - 1 (the last entry index of this node)&lt;br /&gt;
    Flag_U always set&lt;br /&gt;
    Flag_V always clear&lt;br /&gt;
&lt;br /&gt;
FAT[k + 2] ~ FAT[k + n - 2]:&lt;br /&gt;
    All these entries are uninitialized&lt;br /&gt;
&lt;br /&gt;
FAT[k + n - 1]:&lt;br /&gt;
    Index_U = k&lt;br /&gt;
    Index_V = k + n - 1&lt;br /&gt;
    Flag_U always set&lt;br /&gt;
    Flag_V always clear&lt;br /&gt;
    (Same values as FAT[k + 1])&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* Note: all indices above are entry indices (block index + 1)&lt;br /&gt;
&lt;br /&gt;
All free blocks that are not allocated to any files also form a node chain in the allocation table. The head index of this &amp;amp;quot;free chain&amp;amp;quot; is recorded in &amp;lt;code&amp;gt;FAT[0].Index_V&amp;lt;/code&amp;gt;. Other fields of &amp;lt;code&amp;gt;FAT[0]&amp;lt;/code&amp;gt; are all zero&lt;br /&gt;
&lt;br /&gt;
Here is an example: [https://raw.githubusercontent.com/wwylele/3ds-save-tool/master/disa-fat.png]&lt;br /&gt;
&lt;br /&gt;
For extdata, because only two &amp;quot;files&amp;quot; (directory and file entry tables) are allocated in the data region, and their size never changes once the extdata is created, they are guaranteed continuous in the data region, and the FAT degenerates to two big nodes. Therefore, instead of going through FAT, the offset and size of directory / file entry table can be found directly by offset = entry_table_starting block * data_region_block_size + data_region_offset and size = entry_table_block_count * data_region_block_size.&lt;/div&gt;</summary>
		<author><name>Wwylele</name></author>
	</entry>
	<entry>
		<id>https://www.3dbrew.org/w/index.php?title=Inner_FAT&amp;diff=20943</id>
		<title>Inner FAT</title>
		<link rel="alternate" type="text/html" href="https://www.3dbrew.org/w/index.php?title=Inner_FAT&amp;diff=20943"/>
		<updated>2019-05-03T19:27:52Z</updated>

		<summary type="html">&lt;p&gt;Wwylele: Merge hash table here&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This page describes a common FAT-like file system used in [[Savegames]], [[Extdata]] and [[Title Database]]. This file system format has several variants depending on which kind of data it stores. All the three kinds of data that use this file system structure also happen to use the [[DISA and DIFF]] container as well, but there is no direct relationship between the file system and the DISA/DIFF container. All data formats described here is in the inner data of the DISA/DIFF container (i.e. IVFC level 4). Please refer to the DISA/DIFF page for how to unwrap it first before trying to extract the file system.&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
&lt;br /&gt;
The file system consists of the following components:&lt;br /&gt;
* header&lt;br /&gt;
* directory hash table&lt;br /&gt;
* file hash table&lt;br /&gt;
* file allocation table&lt;br /&gt;
* directory entry table&lt;br /&gt;
* file entry table&lt;br /&gt;
* data region&lt;br /&gt;
&lt;br /&gt;
The file allocation table (FAT) forms several linked lists inside, each of which represents a &amp;quot;file&amp;quot; allocated in the data region. Please refer to the File Allocation Table section below for more detail. In some variants, the directory entry table and the file entry table are also allocated as two special &amp;quot;files&amp;quot; in the data region, managed by the FAT, while in others they are stand-alone tables located outside the data region.&lt;br /&gt;
&lt;br /&gt;
== Layout Variants ==&lt;br /&gt;
Four variants of the file system layout has been identified. A summary diagram can be found here: [https://github.com/wwylele/3ds-save-tool/raw/master/inner-fat.png]&lt;br /&gt;
&lt;br /&gt;
=== Savegame, &amp;lt;code&amp;gt;duplicate data = true&amp;lt;/code&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
Such savegame is a single DISA container that only has one partition which is always configured as external IVFC level 4 disabled (see [[DISA and DIFF|DISA]] format for details). All components are stored in this partition as&lt;br /&gt;
&lt;br /&gt;
* filesystem header at the beginning&lt;br /&gt;
* directory hash table&lt;br /&gt;
* file hash table&lt;br /&gt;
* file allocation table&lt;br /&gt;
* data region&lt;br /&gt;
** directory entry table is allocated inside data region&lt;br /&gt;
** file entry table as well&lt;br /&gt;
** all file data is also allocated here&lt;br /&gt;
&lt;br /&gt;
In this layout, all data is duplicated by DISA&#039;s DPFS tree, which is what the parameter &amp;lt;code&amp;gt;duplicate data&amp;lt;/code&amp;gt; implies.&lt;br /&gt;
&lt;br /&gt;
=== Savegame, &amp;lt;code&amp;gt;duplicate data = false&amp;lt;/code&amp;gt; === &lt;br /&gt;
Such savegame is a single DISA container that has two partitions. Partition A is always configured as external IVFC level 4 disabled, and partition B is configured as it enabled. Components are stored among the two partitions as&lt;br /&gt;
&lt;br /&gt;
* Partition A&lt;br /&gt;
** filesystem header at the beginning.&lt;br /&gt;
** directory hash table&lt;br /&gt;
** file hash table&lt;br /&gt;
** (stand-alone) file allocation table&lt;br /&gt;
** (stand-alone) directory entry table&lt;br /&gt;
** file entry table&lt;br /&gt;
* Partition B&lt;br /&gt;
** used as data region entirely, and only has file data allocated.&lt;br /&gt;
&lt;br /&gt;
In this layout, all file system metadata is duplicated by partition A DPFS tree, but file data is not as partition B has external IVFC level 4.&lt;br /&gt;
&lt;br /&gt;
=== Extdata ===&lt;br /&gt;
An extdata consists of several DIFF containers (device files), among which the special device file &amp;lt;code&amp;gt;00000000/00000001&amp;lt;/code&amp;gt; contains the inner FAT system, while other devices contains normal subfiles of the extdata. Please refer to [[Extdata]] for detail. The special file &amp;lt;code&amp;gt;00000000/00000001&amp;lt;/code&amp;gt; contists of the following components&lt;br /&gt;
&lt;br /&gt;
* filesystem header at the beginning&lt;br /&gt;
* directory hash table&lt;br /&gt;
* file hash table&lt;br /&gt;
* file allocation table (degenerate, because the data region only has two &amp;quot;files&amp;quot;: the directory entry table and the file entry table)&lt;br /&gt;
* data region&lt;br /&gt;
** directory entry table allocated inside data region&lt;br /&gt;
** file entry table as well&lt;br /&gt;
** normal subfiles are NOT in the data region. They are in their DIFF containers instead.&lt;br /&gt;
&lt;br /&gt;
=== Title database ===&lt;br /&gt;
All [[Title Database]] files are DIFF containers. Except for &amp;lt;code&amp;gt;certs.db&amp;lt;/code&amp;gt;, all of them uses this filesystem in the DIFF inner data, which consists of&lt;br /&gt;
&lt;br /&gt;
* database-specific pre-header at the beginning (See [[Title Database]])&lt;br /&gt;
* filesystem header&lt;br /&gt;
* directory Hash Table (degenerate and always has only one bucket, as there is only one directory for &amp;quot;root&amp;quot;)&lt;br /&gt;
* file Hash Table&lt;br /&gt;
* file allocation table&lt;br /&gt;
* data region&lt;br /&gt;
** directory entry table allocated inside data region (degenerate, as there is only one directory for &amp;quot;root&amp;quot;)&lt;br /&gt;
** file entry table as well&lt;br /&gt;
** title entries (title info or ticket) are allocated as normal files in the data region as well.&lt;br /&gt;
&lt;br /&gt;
== Filesystem Header ==&lt;br /&gt;
Offsets listed in the table below are all related to the beginning of the header. This is especially important for title database, as the offsets doesn&#039;t count the pre header there.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! Offset&lt;br /&gt;
! Length&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x00&lt;br /&gt;
| 4&lt;br /&gt;
| Magic (&amp;quot;SAVE&amp;quot; for savegame; &amp;quot;BDRI&amp;quot; for title database; &amp;quot;VSXE&amp;quot; for extdata)&lt;br /&gt;
|-&lt;br /&gt;
| 0x04&lt;br /&gt;
| 4&lt;br /&gt;
| Version (0x40000 for savegame; 0x30000 for title database and extdata)&lt;br /&gt;
|-&lt;br /&gt;
| 0x08&lt;br /&gt;
| 8&lt;br /&gt;
| Filesystem Information offset (Y, =0x20 for savegame and title database, =0x138 for extdata)&lt;br /&gt;
|-&lt;br /&gt;
| 0x10&lt;br /&gt;
| 8&lt;br /&gt;
| Filesystem image size in blocks&lt;br /&gt;
|-&lt;br /&gt;
| 0x18&lt;br /&gt;
| 4&lt;br /&gt;
| Filesystem Image block size&lt;br /&gt;
|-&lt;br /&gt;
| 0x1C&lt;br /&gt;
| 4&lt;br /&gt;
| Padding&lt;br /&gt;
|-&lt;br /&gt;
| 0x20 &lt;br /&gt;
| 0x118 in total&lt;br /&gt;
| Below is additional data for extdata. Not present in savegame or title database&lt;br /&gt;
|-&lt;br /&gt;
| 0x20&lt;br /&gt;
| 8&lt;br /&gt;
| Unknown&lt;br /&gt;
|-&lt;br /&gt;
| 0x28&lt;br /&gt;
| 4&lt;br /&gt;
| &#039;Action&#039; made on most recently mounted Extdata image&lt;br /&gt;
|-&lt;br /&gt;
| 0x2C&lt;br /&gt;
| 4&lt;br /&gt;
| Unknown&lt;br /&gt;
|-&lt;br /&gt;
| 0x30&lt;br /&gt;
| 4&lt;br /&gt;
| D of most recently mounted Extdata image&lt;br /&gt;
|-&lt;br /&gt;
| 0x34&lt;br /&gt;
| 4&lt;br /&gt;
| Unknown&lt;br /&gt;
|-&lt;br /&gt;
| 0x38&lt;br /&gt;
| 0x100&lt;br /&gt;
| Mount path, from most recently mounted Extdata image&lt;br /&gt;
|-&lt;br /&gt;
| Y &lt;br /&gt;
| 0x68 in total&lt;br /&gt;
| Below is Filesystem Information&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x00&lt;br /&gt;
| 4&lt;br /&gt;
| Unknown&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x04&lt;br /&gt;
| 4&lt;br /&gt;
| Data region block size&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x08&lt;br /&gt;
| 8&lt;br /&gt;
| Directory hash table offset&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x10&lt;br /&gt;
| 4&lt;br /&gt;
| Directory hash table bucket count (=1 for title database)&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x14&lt;br /&gt;
| 4&lt;br /&gt;
| Padding&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x18&lt;br /&gt;
| 8&lt;br /&gt;
| File hash table offset&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x20&lt;br /&gt;
| 4&lt;br /&gt;
| File hash table bucket count&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x24&lt;br /&gt;
| 4&lt;br /&gt;
| Padding&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x28&lt;br /&gt;
| 8&lt;br /&gt;
| File allocation table offset&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x30&lt;br /&gt;
| 4&lt;br /&gt;
| File allocation table entry count&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x34&lt;br /&gt;
| 4&lt;br /&gt;
| Padding&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x38&lt;br /&gt;
| 8&lt;br /&gt;
| Data region offset &lt;br /&gt;
(0 for savegame &amp;lt;code&amp;gt;duplicate data = false&amp;lt;/code&amp;gt; layout, as the data region is in partition B for that layout)&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x40&lt;br /&gt;
| 4&lt;br /&gt;
| Data region block count &lt;br /&gt;
(= number of file allocation table entries excluding the leading 0th entry. See below)&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x44&lt;br /&gt;
| 4&lt;br /&gt;
| Padding&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x48&lt;br /&gt;
| 8&lt;br /&gt;
| for savegame &amp;lt;code&amp;gt;duplicate data = false&amp;lt;/code&amp;gt; layout: directory entry table offset;&lt;br /&gt;
otherwise: u32 directory entry table starting block index + u32 directory entry table block count&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x50&lt;br /&gt;
| 4&lt;br /&gt;
| Maximum directory count, excluding the mandatory &amp;quot;root&amp;quot; directory &lt;br /&gt;
(=1 for title database, but that 1 free directory slot is never used)&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x54&lt;br /&gt;
| 4&lt;br /&gt;
| Padding&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x58&lt;br /&gt;
| 8&lt;br /&gt;
| for savegame &amp;lt;code&amp;gt;duplicate data = false&amp;lt;/code&amp;gt; layout: file entry table offset;&lt;br /&gt;
otherwise: u32 file entry table starting block index + u32 file entry table block count&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x60&lt;br /&gt;
| 4&lt;br /&gt;
| Maximum file count&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x64&lt;br /&gt;
| 4&lt;br /&gt;
| Padding&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Directory Entry Table ==&lt;br /&gt;
&lt;br /&gt;
The directory entry table is an array of the entry type shown below. It describes the directory hierarchy of the file system. There are two variants of the directory entry type, and a dummy entry type.&lt;br /&gt;
&lt;br /&gt;
=== Savegame/Extdata Variant===&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! Offset&lt;br /&gt;
! Length&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x00&lt;br /&gt;
| 4&lt;br /&gt;
| Parent directory index. 0 for root&lt;br /&gt;
|-&lt;br /&gt;
| 0x04&lt;br /&gt;
| 16&lt;br /&gt;
| ASCII directory name in. All zero for root&lt;br /&gt;
|-&lt;br /&gt;
| 0x14&lt;br /&gt;
| 4&lt;br /&gt;
| Next sibling directory index. 0 if this is the last one&lt;br /&gt;
|-&lt;br /&gt;
| 0x18&lt;br /&gt;
| 4&lt;br /&gt;
| First subdirectory index. 0 if not exists&lt;br /&gt;
|-&lt;br /&gt;
| 0x1C&lt;br /&gt;
| 4&lt;br /&gt;
| First file index in file entry table. 0 for empty directory&lt;br /&gt;
|-&lt;br /&gt;
| 0x20&lt;br /&gt;
| 4&lt;br /&gt;
| Padding / zero?&lt;br /&gt;
|-&lt;br /&gt;
| 0x24&lt;br /&gt;
| 4&lt;br /&gt;
| Index of the next directory in the same hash table bucket. 0 if this is the last one&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Title Database Variant===&lt;br /&gt;
Because title database only has one directory for &amp;quot;root&amp;quot;, its directory entry table degenerates into many zeros whose structure is not recognizable. The size of one entry here is guessed.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! Offset&lt;br /&gt;
! Length&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x00&lt;br /&gt;
| 4&lt;br /&gt;
| Parent directory index = 0 for root&lt;br /&gt;
|-&lt;br /&gt;
| 0x04&lt;br /&gt;
| 4&lt;br /&gt;
| Next sibling directory index = 0 because this is the last one&lt;br /&gt;
|-&lt;br /&gt;
| 0x08&lt;br /&gt;
| 4&lt;br /&gt;
| First subdirectory index = 0 because there is no subdirectory&lt;br /&gt;
|-&lt;br /&gt;
| 0x0C&lt;br /&gt;
| 4&lt;br /&gt;
| First file index in file entry table. 0 for empty directory&lt;br /&gt;
|-&lt;br /&gt;
| 0x10&lt;br /&gt;
| 12&lt;br /&gt;
| Padding / zero?&lt;br /&gt;
|-&lt;br /&gt;
| 0x1C&lt;br /&gt;
| 4&lt;br /&gt;
| Index of the next directory in the same hash table bucket = 0 because there is no other directory&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Dummy Entry===&lt;br /&gt;
There are also some dummy entries in the array&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! Offset&lt;br /&gt;
! Length&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x00&lt;br /&gt;
| 4&lt;br /&gt;
| Current Total entry count&lt;br /&gt;
|-&lt;br /&gt;
| 0x04&lt;br /&gt;
| 4&lt;br /&gt;
| Maximum entry count = maximum directory count + 2&lt;br /&gt;
|-&lt;br /&gt;
| 0x08&lt;br /&gt;
| 28/20&lt;br /&gt;
| Padding / All zero&lt;br /&gt;
|-&lt;br /&gt;
| 0x24/0x1C&lt;br /&gt;
| 4&lt;br /&gt;
| Index of the next dummy entry. 0 if this is the last one&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The 0-th entry of the array is always a dummy entry, which functions as the head of the dummy entry linked list. The 1-st entry of the array is always the root. Therefore maximum entry count is two more than maximum directory count. Dummy entries are left there when deleting directories, and reserved for future use.&lt;br /&gt;
&lt;br /&gt;
== File Entry Table ==&lt;br /&gt;
&lt;br /&gt;
The file entry table is an array of the entry type shown below. It contains information for each file. There are three variants of the file entry type, and a dummy entry type.&lt;br /&gt;
&lt;br /&gt;
=== Savegame Variant ===&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! Offset&lt;br /&gt;
! Length&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x00&lt;br /&gt;
| 4&lt;br /&gt;
| Parent directory index in directory entry table&lt;br /&gt;
|-&lt;br /&gt;
| 0x04&lt;br /&gt;
| 16&lt;br /&gt;
| ASCII file name&lt;br /&gt;
|-&lt;br /&gt;
| 0x14&lt;br /&gt;
| 4&lt;br /&gt;
| Next sibling file index. 0 if this is the last one&lt;br /&gt;
|-&lt;br /&gt;
| 0x18&lt;br /&gt;
| 4&lt;br /&gt;
| Padding&lt;br /&gt;
|-&lt;br /&gt;
| 0x1C&lt;br /&gt;
| 4&lt;br /&gt;
| First block index in data region. 0x80000000 if the file is just created and has no data.&lt;br /&gt;
|-&lt;br /&gt;
| 0x20&lt;br /&gt;
| 8&lt;br /&gt;
| File Size&lt;br /&gt;
|-&lt;br /&gt;
| 0x28&lt;br /&gt;
| 4&lt;br /&gt;
| Padding?&lt;br /&gt;
|-&lt;br /&gt;
| 0x2C&lt;br /&gt;
| 4&lt;br /&gt;
| Index of the next file in the same hash table bucket. 0 if this is the last one&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Extdata Variant ===&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! Offset&lt;br /&gt;
! Length&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x00&lt;br /&gt;
| 4&lt;br /&gt;
| Parent directory index in directory entry table&lt;br /&gt;
|-&lt;br /&gt;
| 0x04&lt;br /&gt;
| 16&lt;br /&gt;
| ASCII file name&lt;br /&gt;
|-&lt;br /&gt;
| 0x14&lt;br /&gt;
| 4&lt;br /&gt;
| Next sibling file index. 0 if this is the last one&lt;br /&gt;
|-&lt;br /&gt;
| 0x18&lt;br /&gt;
| 4&lt;br /&gt;
| Padding&lt;br /&gt;
|-&lt;br /&gt;
| 0x1C&lt;br /&gt;
| 4&lt;br /&gt;
| Always 0x80000000&lt;br /&gt;
|-&lt;br /&gt;
| 0x20&lt;br /&gt;
| 8&lt;br /&gt;
| Unique identifier&lt;br /&gt;
|-&lt;br /&gt;
| 0x28&lt;br /&gt;
| 4&lt;br /&gt;
| Padding?&lt;br /&gt;
|-&lt;br /&gt;
| 0x2C&lt;br /&gt;
| 4&lt;br /&gt;
| Index of the next file in the same hash table bucket. 0 if this is the last one&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Title database Variant ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! Offset&lt;br /&gt;
! Length&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x00&lt;br /&gt;
| 4&lt;br /&gt;
| Parent directory index in directory entry table&lt;br /&gt;
|-&lt;br /&gt;
| 0x04&lt;br /&gt;
| 8&lt;br /&gt;
| Title ID&lt;br /&gt;
|-&lt;br /&gt;
| 0x0C&lt;br /&gt;
| 4&lt;br /&gt;
| Next sibling file index. 0 if this is the last one&lt;br /&gt;
|-&lt;br /&gt;
| 0x10&lt;br /&gt;
| 4&lt;br /&gt;
| Padding&lt;br /&gt;
|-&lt;br /&gt;
| 0x14&lt;br /&gt;
| 4&lt;br /&gt;
| First block index in data region.&lt;br /&gt;
|-&lt;br /&gt;
| 0x18&lt;br /&gt;
| 8&lt;br /&gt;
| File size&lt;br /&gt;
|-&lt;br /&gt;
| 0x20&lt;br /&gt;
| 8&lt;br /&gt;
| Padding?&lt;br /&gt;
|-&lt;br /&gt;
| 0x28&lt;br /&gt;
| 4&lt;br /&gt;
| Index of the next file in the same hash table bucket. 0 if this is the last one&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Dummy Entry ===&lt;br /&gt;
Like directory entry table, file entry table also has some dummy entries:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! Offset&lt;br /&gt;
! Length&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x00&lt;br /&gt;
| 4&lt;br /&gt;
| Current total entry count&lt;br /&gt;
|-&lt;br /&gt;
| 0x04&lt;br /&gt;
| 4&lt;br /&gt;
| Maximum entry count = maximum file count + 1&lt;br /&gt;
|-&lt;br /&gt;
| 0x08&lt;br /&gt;
| 36/32&lt;br /&gt;
| Padding / All zero&lt;br /&gt;
|-&lt;br /&gt;
| 0x2C/0x28&lt;br /&gt;
| 4&lt;br /&gt;
| Index of the next dummy entry. 0 if this is the last one&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The 0-th entry of the array is always a dummy entry, which functions as the head of the dummy entry linked list. Therefore maximum entry count is one more than maximum file count. Dummy entries are left there when deleting files, and reserved for future use.&lt;br /&gt;
&lt;br /&gt;
== Directory Hash Table &amp;amp;amp; File Hash Table ==&lt;br /&gt;
&lt;br /&gt;
This is a u32 array of size = bucket count, each of which is an index to the directory / file entry table. The directory / file name is hashed and its entry index is put to the corresponding bucket. If there is already a directory/file entry in the bucket, then it appends to the linked list formed by &amp;lt;code&amp;gt;Index of the next directory/file in the same hash table bucket&amp;lt;/code&amp;gt; field in the directory/file entry table. i.e. this is a hash table using separate chaining with linked lists&lt;br /&gt;
&lt;br /&gt;
The hash function takes the parent index and the ASCII name (or title ID for title database) as key. The function is equivalent to&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;uint32_t GetBucket(&lt;br /&gt;
    char name[16 or 8], // For savegame/extdata, this takes all 16 bytes including trailing zeros; For title database, this is the 8-byte title ID&lt;br /&gt;
    uint32_t parent_dir_index,&lt;br /&gt;
    uint32_t bucket_count&lt;br /&gt;
) {&lt;br /&gt;
    uint32_t hash = parent_dir_index ^ 0x091A2B3C;&lt;br /&gt;
    for (int i = 0; i &amp;amp;lt; 4 or 2; ++i) {&lt;br /&gt;
        hash = (hash &amp;amp;gt;&amp;amp;gt; 1) | (hash &amp;amp;lt;&amp;amp;lt; 31);&lt;br /&gt;
        hash ^= (uint32_t)name[i * 4]&lt;br /&gt;
        hash ^= (uint32_t)name[i * 4 + 1] &amp;amp;lt;&amp;amp;lt; 8&lt;br /&gt;
        hash ^= (uint32_t)name[i * 4 + 2] &amp;amp;lt;&amp;amp;lt; 16&lt;br /&gt;
        hash ^= (uint32_t)name[i * 4 + 3] &amp;amp;lt;&amp;amp;lt; 24&lt;br /&gt;
    }&lt;br /&gt;
    return hash % bucket_count;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== File Allocation Table ==&lt;br /&gt;
&lt;br /&gt;
The file allocation table is an array of a 8-byte entry shown below. The array size is actually &#039;&#039;one larger than&#039;&#039; the size recorded in the filesystem header. Each entry corresponds to a block in the data region (the block size is defined in filesystem header). However, the 0th entry corresponds to nothing, so the corresponding block index is off by one. e.g. entry 31 in this table corresponds to block 30 in the data region.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! Offset&lt;br /&gt;
! Length&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x00&lt;br /&gt;
| 4&lt;br /&gt;
| bit[0:30]: Index U; bit[31]: Flag U&lt;br /&gt;
|-&lt;br /&gt;
| 0x04&lt;br /&gt;
| 4&lt;br /&gt;
| bit[0:30]: Index V; bit[31]: Flag V&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Entries in this table forms several chains, representing how blocks in the data region should be linked together. However, unlike normal FAT systems, which uses chains of entries, 3DS savegames use chain of &#039;&#039;nodes&#039;&#039;. Each node spans one or multiple entries.&lt;br /&gt;
&lt;br /&gt;
One node spanning &amp;lt;code&amp;gt;n&amp;lt;/code&amp;gt; entries starting from &amp;lt;code&amp;gt;FAT[k]&amp;lt;/code&amp;gt; is in the following format:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;FAT[k + 0]:&lt;br /&gt;
    Index_U = index of the first entry of the previous node. 0 if this is the first node.&lt;br /&gt;
    Index_V = index of the first entry of the next node. 0 if this is the last node.&lt;br /&gt;
    Flag_U set if this is the first node.&lt;br /&gt;
    Flag_V set if this node has multiple entries.&lt;br /&gt;
&lt;br /&gt;
FAT[k + 1]:&lt;br /&gt;
    Index_U = k (the first entry index of this node)&lt;br /&gt;
    Index_V = k + n - 1 (the last entry index of this node)&lt;br /&gt;
    Flag_U always set&lt;br /&gt;
    Flag_V always clear&lt;br /&gt;
&lt;br /&gt;
FAT[k + 2] ~ FAT[k + n - 2]:&lt;br /&gt;
    All these entries are uninitialized&lt;br /&gt;
&lt;br /&gt;
FAT[k + n - 1]:&lt;br /&gt;
    Index_U = k&lt;br /&gt;
    Index_V = k + n - 1&lt;br /&gt;
    Flag_U always set&lt;br /&gt;
    Flag_V always clear&lt;br /&gt;
    (Same values as FAT[k + 1])&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* Note: all indices above are entry indices (block index + 1)&lt;br /&gt;
&lt;br /&gt;
All free blocks that are not allocated to any files also form a node chain in the allocation table. The head index of this &amp;amp;quot;free chain&amp;amp;quot; is recorded in &amp;lt;code&amp;gt;FAT[0].Index_V&amp;lt;/code&amp;gt;. Other fields of &amp;lt;code&amp;gt;FAT[0]&amp;lt;/code&amp;gt; are all zero&lt;br /&gt;
&lt;br /&gt;
Here is an example: [https://raw.githubusercontent.com/wwylele/3ds-save-tool/master/disa-fat.png]&lt;br /&gt;
&lt;br /&gt;
For extdata, because only two &amp;quot;files&amp;quot; (directory and file entry tables) are allocated in the data region, and their size never changes once the extdata is created, they are guaranteed continuous in the data region, and the FAT degenerates to two big nodes. Therefore, instead of going through FAT, the offset and size of directory / file entry table can be found directly by offset = entry_table_starting block * data_region_block_size + data_region_offset and size = entry_table_block_count * data_region_block_size.&lt;/div&gt;</summary>
		<author><name>Wwylele</name></author>
	</entry>
	<entry>
		<id>https://www.3dbrew.org/w/index.php?title=Inner_FAT&amp;diff=20942</id>
		<title>Inner FAT</title>
		<link rel="alternate" type="text/html" href="https://www.3dbrew.org/w/index.php?title=Inner_FAT&amp;diff=20942"/>
		<updated>2019-05-03T19:21:22Z</updated>

		<summary type="html">&lt;p&gt;Wwylele: Merge file entry table here&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This page describes a common FAT-like file system used in [[Savegames]], [[Extdata]] and [[Title Database]]. This file system format has several variants depending on which kind of data it stores. All the three kinds of data that use this file system structure also happen to use the [[DISA and DIFF]] container as well, but there is no direct relationship between the file system and the DISA/DIFF container. All data formats described here is in the inner data of the DISA/DIFF container (i.e. IVFC level 4). Please refer to the DISA/DIFF page for how to unwrap it first before trying to extract the file system.&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
&lt;br /&gt;
The file system consists of the following components:&lt;br /&gt;
* header&lt;br /&gt;
* directory hash table&lt;br /&gt;
* file hash table&lt;br /&gt;
* file allocation table&lt;br /&gt;
* directory entry table&lt;br /&gt;
* file entry table&lt;br /&gt;
* data region&lt;br /&gt;
&lt;br /&gt;
The file allocation table (FAT) forms several linked lists inside, each of which represents a &amp;quot;file&amp;quot; allocated in the data region. Please refer to the File Allocation Table section below for more detail. In some variants, the directory entry table and the file entry table are also allocated as two special &amp;quot;files&amp;quot; in the data region, managed by the FAT, while in others they are stand-alone tables located outside the data region.&lt;br /&gt;
&lt;br /&gt;
== Layout Variants ==&lt;br /&gt;
Four variants of the file system layout has been identified. A summary diagram can be found here: [https://github.com/wwylele/3ds-save-tool/raw/master/inner-fat.png]&lt;br /&gt;
&lt;br /&gt;
=== Savegame, &amp;lt;code&amp;gt;duplicate data = true&amp;lt;/code&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
Such savegame is a single DISA container that only has one partition which is always configured as external IVFC level 4 disabled (see [[DISA and DIFF|DISA]] format for details). All components are stored in this partition as&lt;br /&gt;
&lt;br /&gt;
* filesystem header at the beginning&lt;br /&gt;
* directory hash table&lt;br /&gt;
* file hash table&lt;br /&gt;
* file allocation table&lt;br /&gt;
* data region&lt;br /&gt;
** directory entry table is allocated inside data region&lt;br /&gt;
** file entry table as well&lt;br /&gt;
** all file data is also allocated here&lt;br /&gt;
&lt;br /&gt;
In this layout, all data is duplicated by DISA&#039;s DPFS tree, which is what the parameter &amp;lt;code&amp;gt;duplicate data&amp;lt;/code&amp;gt; implies.&lt;br /&gt;
&lt;br /&gt;
=== Savegame, &amp;lt;code&amp;gt;duplicate data = false&amp;lt;/code&amp;gt; === &lt;br /&gt;
Such savegame is a single DISA container that has two partitions. Partition A is always configured as external IVFC level 4 disabled, and partition B is configured as it enabled. Components are stored among the two partitions as&lt;br /&gt;
&lt;br /&gt;
* Partition A&lt;br /&gt;
** filesystem header at the beginning.&lt;br /&gt;
** directory hash table&lt;br /&gt;
** file hash table&lt;br /&gt;
** (stand-alone) file allocation table&lt;br /&gt;
** (stand-alone) directory entry table&lt;br /&gt;
** file entry table&lt;br /&gt;
* Partition B&lt;br /&gt;
** used as data region entirely, and only has file data allocated.&lt;br /&gt;
&lt;br /&gt;
In this layout, all file system metadata is duplicated by partition A DPFS tree, but file data is not as partition B has external IVFC level 4.&lt;br /&gt;
&lt;br /&gt;
=== Extdata ===&lt;br /&gt;
An extdata consists of several DIFF containers (device files), among which the special device file &amp;lt;code&amp;gt;00000000/00000001&amp;lt;/code&amp;gt; contains the inner FAT system, while other devices contains normal subfiles of the extdata. Please refer to [[Extdata]] for detail. The special file &amp;lt;code&amp;gt;00000000/00000001&amp;lt;/code&amp;gt; contists of the following components&lt;br /&gt;
&lt;br /&gt;
* filesystem header at the beginning&lt;br /&gt;
* directory hash table&lt;br /&gt;
* file hash table&lt;br /&gt;
* file allocation table (degenerate, because the data region only has two &amp;quot;files&amp;quot;: the directory entry table and the file entry table)&lt;br /&gt;
* data region&lt;br /&gt;
** directory entry table allocated inside data region&lt;br /&gt;
** file entry table as well&lt;br /&gt;
** normal subfiles are NOT in the data region. They are in their DIFF containers instead.&lt;br /&gt;
&lt;br /&gt;
=== Title database ===&lt;br /&gt;
All [[Title Database]] files are DIFF containers. Except for &amp;lt;code&amp;gt;certs.db&amp;lt;/code&amp;gt;, all of them uses this filesystem in the DIFF inner data, which consists of&lt;br /&gt;
&lt;br /&gt;
* database-specific pre-header at the beginning (See [[Title Database]])&lt;br /&gt;
* filesystem header&lt;br /&gt;
* directory Hash Table (degenerate and always has only one bucket, as there is only one directory for &amp;quot;root&amp;quot;)&lt;br /&gt;
* file Hash Table&lt;br /&gt;
* file allocation table&lt;br /&gt;
* data region&lt;br /&gt;
** directory entry table allocated inside data region (degenerate, as there is only one directory for &amp;quot;root&amp;quot;)&lt;br /&gt;
** file entry table as well&lt;br /&gt;
** title entries (title info or ticket) are allocated as normal files in the data region as well.&lt;br /&gt;
&lt;br /&gt;
== Filesystem Header ==&lt;br /&gt;
Offsets listed in the table below are all related to the beginning of the header. This is especially important for title database, as the offsets doesn&#039;t count the pre header there.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! Offset&lt;br /&gt;
! Length&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x00&lt;br /&gt;
| 4&lt;br /&gt;
| Magic (&amp;quot;SAVE&amp;quot; for savegame; &amp;quot;BDRI&amp;quot; for title database; &amp;quot;VSXE&amp;quot; for extdata)&lt;br /&gt;
|-&lt;br /&gt;
| 0x04&lt;br /&gt;
| 4&lt;br /&gt;
| Version (0x40000 for savegame; 0x30000 for title database and extdata)&lt;br /&gt;
|-&lt;br /&gt;
| 0x08&lt;br /&gt;
| 8&lt;br /&gt;
| Filesystem Information offset (Y, =0x20 for savegame and title database, =0x138 for extdata)&lt;br /&gt;
|-&lt;br /&gt;
| 0x10&lt;br /&gt;
| 8&lt;br /&gt;
| Filesystem image size in blocks&lt;br /&gt;
|-&lt;br /&gt;
| 0x18&lt;br /&gt;
| 4&lt;br /&gt;
| Filesystem Image block size&lt;br /&gt;
|-&lt;br /&gt;
| 0x1C&lt;br /&gt;
| 4&lt;br /&gt;
| Padding&lt;br /&gt;
|-&lt;br /&gt;
| 0x20 &lt;br /&gt;
| 0x118 in total&lt;br /&gt;
| Below is additional data for extdata. Not present in savegame or title database&lt;br /&gt;
|-&lt;br /&gt;
| 0x20&lt;br /&gt;
| 8&lt;br /&gt;
| Unknown&lt;br /&gt;
|-&lt;br /&gt;
| 0x28&lt;br /&gt;
| 4&lt;br /&gt;
| &#039;Action&#039; made on most recently mounted Extdata image&lt;br /&gt;
|-&lt;br /&gt;
| 0x2C&lt;br /&gt;
| 4&lt;br /&gt;
| Unknown&lt;br /&gt;
|-&lt;br /&gt;
| 0x30&lt;br /&gt;
| 4&lt;br /&gt;
| D of most recently mounted Extdata image&lt;br /&gt;
|-&lt;br /&gt;
| 0x34&lt;br /&gt;
| 4&lt;br /&gt;
| Unknown&lt;br /&gt;
|-&lt;br /&gt;
| 0x38&lt;br /&gt;
| 0x100&lt;br /&gt;
| Mount path, from most recently mounted Extdata image&lt;br /&gt;
|-&lt;br /&gt;
| Y &lt;br /&gt;
| 0x68 in total&lt;br /&gt;
| Below is Filesystem Information&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x00&lt;br /&gt;
| 4&lt;br /&gt;
| Unknown&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x04&lt;br /&gt;
| 4&lt;br /&gt;
| Data region block size&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x08&lt;br /&gt;
| 8&lt;br /&gt;
| Directory hash table offset&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x10&lt;br /&gt;
| 4&lt;br /&gt;
| Directory hash table bucket count (=1 for title database)&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x14&lt;br /&gt;
| 4&lt;br /&gt;
| Padding&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x18&lt;br /&gt;
| 8&lt;br /&gt;
| File hash table offset&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x20&lt;br /&gt;
| 4&lt;br /&gt;
| File hash table bucket count&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x24&lt;br /&gt;
| 4&lt;br /&gt;
| Padding&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x28&lt;br /&gt;
| 8&lt;br /&gt;
| File allocation table offset&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x30&lt;br /&gt;
| 4&lt;br /&gt;
| File allocation table entry count&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x34&lt;br /&gt;
| 4&lt;br /&gt;
| Padding&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x38&lt;br /&gt;
| 8&lt;br /&gt;
| Data region offset &lt;br /&gt;
(0 for savegame &amp;lt;code&amp;gt;duplicate data = false&amp;lt;/code&amp;gt; layout, as the data region is in partition B for that layout)&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x40&lt;br /&gt;
| 4&lt;br /&gt;
| Data region block count &lt;br /&gt;
(= number of file allocation table entries excluding the leading 0th entry. See below)&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x44&lt;br /&gt;
| 4&lt;br /&gt;
| Padding&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x48&lt;br /&gt;
| 8&lt;br /&gt;
| for savegame &amp;lt;code&amp;gt;duplicate data = false&amp;lt;/code&amp;gt; layout: directory entry table offset;&lt;br /&gt;
otherwise: u32 directory entry table starting block index + u32 directory entry table block count&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x50&lt;br /&gt;
| 4&lt;br /&gt;
| Maximum directory count, excluding the mandatory &amp;quot;root&amp;quot; directory &lt;br /&gt;
(=1 for title database, but that 1 free directory slot is never used)&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x54&lt;br /&gt;
| 4&lt;br /&gt;
| Padding&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x58&lt;br /&gt;
| 8&lt;br /&gt;
| for savegame &amp;lt;code&amp;gt;duplicate data = false&amp;lt;/code&amp;gt; layout: file entry table offset;&lt;br /&gt;
otherwise: u32 file entry table starting block index + u32 file entry table block count&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x60&lt;br /&gt;
| 4&lt;br /&gt;
| Maximum file count&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x64&lt;br /&gt;
| 4&lt;br /&gt;
| Padding&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Directory Entry Table ==&lt;br /&gt;
&lt;br /&gt;
The directory entry table is an array of the entry type shown below. It describes the directory hierarchy of the file system. There are two variants of the directory entry type, and a dummy entry type.&lt;br /&gt;
&lt;br /&gt;
=== Savegame/Extdata Variant===&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! Offset&lt;br /&gt;
! Length&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x00&lt;br /&gt;
| 4&lt;br /&gt;
| Parent directory index. 0 for root&lt;br /&gt;
|-&lt;br /&gt;
| 0x04&lt;br /&gt;
| 16&lt;br /&gt;
| ASCII directory name in. All zero for root&lt;br /&gt;
|-&lt;br /&gt;
| 0x14&lt;br /&gt;
| 4&lt;br /&gt;
| Next sibling directory index. 0 if this is the last one&lt;br /&gt;
|-&lt;br /&gt;
| 0x18&lt;br /&gt;
| 4&lt;br /&gt;
| First subdirectory index. 0 if not exists&lt;br /&gt;
|-&lt;br /&gt;
| 0x1C&lt;br /&gt;
| 4&lt;br /&gt;
| First file index in file entry table. 0 for empty directory&lt;br /&gt;
|-&lt;br /&gt;
| 0x20&lt;br /&gt;
| 4&lt;br /&gt;
| Padding / zero?&lt;br /&gt;
|-&lt;br /&gt;
| 0x24&lt;br /&gt;
| 4&lt;br /&gt;
| Index of the next directory in the same hash table bucket. 0 if this is the last one&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Title Database Variant===&lt;br /&gt;
Because title database only has one directory for &amp;quot;root&amp;quot;, its directory entry table degenerates into many zeros whose structure is not recognizable. The size of one entry here is guessed.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! Offset&lt;br /&gt;
! Length&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x00&lt;br /&gt;
| 4&lt;br /&gt;
| Parent directory index = 0 for root&lt;br /&gt;
|-&lt;br /&gt;
| 0x04&lt;br /&gt;
| 4&lt;br /&gt;
| Next sibling directory index = 0 because this is the last one&lt;br /&gt;
|-&lt;br /&gt;
| 0x08&lt;br /&gt;
| 4&lt;br /&gt;
| First subdirectory index = 0 because there is no subdirectory&lt;br /&gt;
|-&lt;br /&gt;
| 0x0C&lt;br /&gt;
| 4&lt;br /&gt;
| First file index in file entry table. 0 for empty directory&lt;br /&gt;
|-&lt;br /&gt;
| 0x10&lt;br /&gt;
| 12&lt;br /&gt;
| Padding / zero?&lt;br /&gt;
|-&lt;br /&gt;
| 0x1C&lt;br /&gt;
| 4&lt;br /&gt;
| Index of the next directory in the same hash table bucket = 0 because there is no other directory&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Dummy Entry===&lt;br /&gt;
There are also some dummy entries in the array&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! Offset&lt;br /&gt;
! Length&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x00&lt;br /&gt;
| 4&lt;br /&gt;
| Current Total entry count&lt;br /&gt;
|-&lt;br /&gt;
| 0x04&lt;br /&gt;
| 4&lt;br /&gt;
| Maximum entry count = maximum directory count + 2&lt;br /&gt;
|-&lt;br /&gt;
| 0x08&lt;br /&gt;
| 28/20&lt;br /&gt;
| Padding / All zero&lt;br /&gt;
|-&lt;br /&gt;
| 0x24/0x1C&lt;br /&gt;
| 4&lt;br /&gt;
| Index of the next dummy entry. 0 if this is the last one&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The 0-th entry of the array is always a dummy entry, which functions as the head of the dummy entry linked list. The 1-st entry of the array is always the root. Therefore maximum entry count is two more than maximum directory count. Dummy entries are left there when deleting directories, and reserved for future use.&lt;br /&gt;
&lt;br /&gt;
== File Entry Table ==&lt;br /&gt;
&lt;br /&gt;
The file entry table is an array of the entry type shown below. It contains information for each file. There are three variants of the file entry type, and a dummy entry type.&lt;br /&gt;
&lt;br /&gt;
=== Savegame Variant ===&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! Offset&lt;br /&gt;
! Length&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x00&lt;br /&gt;
| 4&lt;br /&gt;
| Parent directory index in directory entry table&lt;br /&gt;
|-&lt;br /&gt;
| 0x04&lt;br /&gt;
| 16&lt;br /&gt;
| ASCII file name&lt;br /&gt;
|-&lt;br /&gt;
| 0x14&lt;br /&gt;
| 4&lt;br /&gt;
| Next sibling file index. 0 if this is the last one&lt;br /&gt;
|-&lt;br /&gt;
| 0x18&lt;br /&gt;
| 4&lt;br /&gt;
| Padding&lt;br /&gt;
|-&lt;br /&gt;
| 0x1C&lt;br /&gt;
| 4&lt;br /&gt;
| First block index in data region. 0x80000000 if the file is just created and has no data.&lt;br /&gt;
|-&lt;br /&gt;
| 0x20&lt;br /&gt;
| 8&lt;br /&gt;
| File Size&lt;br /&gt;
|-&lt;br /&gt;
| 0x28&lt;br /&gt;
| 4&lt;br /&gt;
| Padding?&lt;br /&gt;
|-&lt;br /&gt;
| 0x2C&lt;br /&gt;
| 4&lt;br /&gt;
| Index of the next file in the same hash table bucket. 0 if this is the last one&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Extdata Variant ===&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! Offset&lt;br /&gt;
! Length&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x00&lt;br /&gt;
| 4&lt;br /&gt;
| Parent directory index in directory entry table&lt;br /&gt;
|-&lt;br /&gt;
| 0x04&lt;br /&gt;
| 16&lt;br /&gt;
| ASCII file name&lt;br /&gt;
|-&lt;br /&gt;
| 0x14&lt;br /&gt;
| 4&lt;br /&gt;
| Next sibling file index. 0 if this is the last one&lt;br /&gt;
|-&lt;br /&gt;
| 0x18&lt;br /&gt;
| 4&lt;br /&gt;
| Padding&lt;br /&gt;
|-&lt;br /&gt;
| 0x1C&lt;br /&gt;
| 4&lt;br /&gt;
| Always 0x80000000&lt;br /&gt;
|-&lt;br /&gt;
| 0x20&lt;br /&gt;
| 8&lt;br /&gt;
| Unique identifier&lt;br /&gt;
|-&lt;br /&gt;
| 0x28&lt;br /&gt;
| 4&lt;br /&gt;
| Padding?&lt;br /&gt;
|-&lt;br /&gt;
| 0x2C&lt;br /&gt;
| 4&lt;br /&gt;
| Index of the next file in the same hash table bucket. 0 if this is the last one&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Title database Variant ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! Offset&lt;br /&gt;
! Length&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x00&lt;br /&gt;
| 4&lt;br /&gt;
| Parent directory index in directory entry table&lt;br /&gt;
|-&lt;br /&gt;
| 0x04&lt;br /&gt;
| 8&lt;br /&gt;
| Title ID&lt;br /&gt;
|-&lt;br /&gt;
| 0x0C&lt;br /&gt;
| 4&lt;br /&gt;
| Next sibling file index. 0 if this is the last one&lt;br /&gt;
|-&lt;br /&gt;
| 0x10&lt;br /&gt;
| 4&lt;br /&gt;
| Padding&lt;br /&gt;
|-&lt;br /&gt;
| 0x14&lt;br /&gt;
| 4&lt;br /&gt;
| First block index in data region.&lt;br /&gt;
|-&lt;br /&gt;
| 0x18&lt;br /&gt;
| 8&lt;br /&gt;
| File size&lt;br /&gt;
|-&lt;br /&gt;
| 0x20&lt;br /&gt;
| 8&lt;br /&gt;
| Padding?&lt;br /&gt;
|-&lt;br /&gt;
| 0x28&lt;br /&gt;
| 4&lt;br /&gt;
| Index of the next file in the same hash table bucket. 0 if this is the last one&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Dummy Entry ===&lt;br /&gt;
Like directory entry table, file entry table also has some dummy entries:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! Offset&lt;br /&gt;
! Length&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x00&lt;br /&gt;
| 4&lt;br /&gt;
| Current total entry count&lt;br /&gt;
|-&lt;br /&gt;
| 0x04&lt;br /&gt;
| 4&lt;br /&gt;
| Maximum entry count = maximum file count + 1&lt;br /&gt;
|-&lt;br /&gt;
| 0x08&lt;br /&gt;
| 36/32&lt;br /&gt;
| Padding / All zero&lt;br /&gt;
|-&lt;br /&gt;
| 0x2C/0x28&lt;br /&gt;
| 4&lt;br /&gt;
| Index of the next dummy entry. 0 if this is the last one&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The 0-th entry of the array is always a dummy entry, which functions as the head of the dummy entry linked list. Therefore maximum entry count is one more than maximum file count. Dummy entries are left there when deleting files, and reserved for future use.&lt;br /&gt;
&lt;br /&gt;
== File Allocation Table ==&lt;br /&gt;
&lt;br /&gt;
The file allocation table is an array of a 8-byte entry shown below. The array size is actually &#039;&#039;one larger than&#039;&#039; the size recorded in the filesystem header. Each entry corresponds to a block in the data region (the block size is defined in filesystem header). However, the 0th entry corresponds to nothing, so the corresponding block index is off by one. e.g. entry 31 in this table corresponds to block 30 in the data region.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! Offset&lt;br /&gt;
! Length&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x00&lt;br /&gt;
| 4&lt;br /&gt;
| bit[0:30]: Index U; bit[31]: Flag U&lt;br /&gt;
|-&lt;br /&gt;
| 0x04&lt;br /&gt;
| 4&lt;br /&gt;
| bit[0:30]: Index V; bit[31]: Flag V&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Entries in this table forms several chains, representing how blocks in the data region should be linked together. However, unlike normal FAT systems, which uses chains of entries, 3DS savegames use chain of &#039;&#039;nodes&#039;&#039;. Each node spans one or multiple entries.&lt;br /&gt;
&lt;br /&gt;
One node spanning &amp;lt;code&amp;gt;n&amp;lt;/code&amp;gt; entries starting from &amp;lt;code&amp;gt;FAT[k]&amp;lt;/code&amp;gt; is in the following format:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;FAT[k + 0]:&lt;br /&gt;
    Index_U = index of the first entry of the previous node. 0 if this is the first node.&lt;br /&gt;
    Index_V = index of the first entry of the next node. 0 if this is the last node.&lt;br /&gt;
    Flag_U set if this is the first node.&lt;br /&gt;
    Flag_V set if this node has multiple entries.&lt;br /&gt;
&lt;br /&gt;
FAT[k + 1]:&lt;br /&gt;
    Index_U = k (the first entry index of this node)&lt;br /&gt;
    Index_V = k + n - 1 (the last entry index of this node)&lt;br /&gt;
    Flag_U always set&lt;br /&gt;
    Flag_V always clear&lt;br /&gt;
&lt;br /&gt;
FAT[k + 2] ~ FAT[k + n - 2]:&lt;br /&gt;
    All these entries are uninitialized&lt;br /&gt;
&lt;br /&gt;
FAT[k + n - 1]:&lt;br /&gt;
    Index_U = k&lt;br /&gt;
    Index_V = k + n - 1&lt;br /&gt;
    Flag_U always set&lt;br /&gt;
    Flag_V always clear&lt;br /&gt;
    (Same values as FAT[k + 1])&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* Note: all indices above are entry indices (block index + 1)&lt;br /&gt;
&lt;br /&gt;
All free blocks that are not allocated to any files also form a node chain in the allocation table. The head index of this &amp;amp;quot;free chain&amp;amp;quot; is recorded in &amp;lt;code&amp;gt;FAT[0].Index_V&amp;lt;/code&amp;gt;. Other fields of &amp;lt;code&amp;gt;FAT[0]&amp;lt;/code&amp;gt; are all zero&lt;br /&gt;
&lt;br /&gt;
Here is an example: [https://raw.githubusercontent.com/wwylele/3ds-save-tool/master/disa-fat.png]&lt;br /&gt;
&lt;br /&gt;
For extdata, because only two &amp;quot;files&amp;quot; (directory and file entry tables) are allocated in the data region, and their size never changes once the extdata is created, they are guaranteed continuous in the data region, and the FAT degenerates to two big nodes. Therefore, instead of going through FAT, the offset and size of directory / file entry table can be found directly by offset = entry_table_starting block * data_region_block_size + data_region_offset and size = entry_table_block_count * data_region_block_size.&lt;/div&gt;</summary>
		<author><name>Wwylele</name></author>
	</entry>
	<entry>
		<id>https://www.3dbrew.org/w/index.php?title=Inner_FAT&amp;diff=20941</id>
		<title>Inner FAT</title>
		<link rel="alternate" type="text/html" href="https://www.3dbrew.org/w/index.php?title=Inner_FAT&amp;diff=20941"/>
		<updated>2019-05-03T19:11:44Z</updated>

		<summary type="html">&lt;p&gt;Wwylele: Merge directory entry table here&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This page describes a common FAT-like file system used in [[Savegames]], [[Extdata]] and [[Title Database]]. This file system format has several variants depending on which kind of data it stores. All the three kinds of data that use this file system structure also happen to use the [[DISA and DIFF]] container as well, but there is no direct relationship between the file system and the DISA/DIFF container. All data formats described here is in the inner data of the DISA/DIFF container (i.e. IVFC level 4). Please refer to the DISA/DIFF page for how to unwrap it first before trying to extract the file system.&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
&lt;br /&gt;
The file system consists of the following components:&lt;br /&gt;
* header&lt;br /&gt;
* directory hash table&lt;br /&gt;
* file hash table&lt;br /&gt;
* file allocation table&lt;br /&gt;
* directory entry table&lt;br /&gt;
* file entry table&lt;br /&gt;
* data region&lt;br /&gt;
&lt;br /&gt;
The file allocation table (FAT) forms several linked lists inside, each of which represents a &amp;quot;file&amp;quot; allocated in the data region. Please refer to the File Allocation Table section below for more detail. In some variants, the directory entry table and the file entry table are also allocated as two special &amp;quot;files&amp;quot; in the data region, managed by the FAT, while in others they are stand-alone tables located outside the data region.&lt;br /&gt;
&lt;br /&gt;
== Layout Variants ==&lt;br /&gt;
Four variants of the file system layout has been identified. A summary diagram can be found here: [https://github.com/wwylele/3ds-save-tool/raw/master/inner-fat.png]&lt;br /&gt;
&lt;br /&gt;
=== Savegame, &amp;lt;code&amp;gt;duplicate data = true&amp;lt;/code&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
Such savegame is a single DISA container that only has one partition which is always configured as external IVFC level 4 disabled (see [[DISA and DIFF|DISA]] format for details). All components are stored in this partition as&lt;br /&gt;
&lt;br /&gt;
* filesystem header at the beginning&lt;br /&gt;
* directory hash table&lt;br /&gt;
* file hash table&lt;br /&gt;
* file allocation table&lt;br /&gt;
* data region&lt;br /&gt;
** directory entry table is allocated inside data region&lt;br /&gt;
** file entry table as well&lt;br /&gt;
** all file data is also allocated here&lt;br /&gt;
&lt;br /&gt;
In this layout, all data is duplicated by DISA&#039;s DPFS tree, which is what the parameter &amp;lt;code&amp;gt;duplicate data&amp;lt;/code&amp;gt; implies.&lt;br /&gt;
&lt;br /&gt;
=== Savegame, &amp;lt;code&amp;gt;duplicate data = false&amp;lt;/code&amp;gt; === &lt;br /&gt;
Such savegame is a single DISA container that has two partitions. Partition A is always configured as external IVFC level 4 disabled, and partition B is configured as it enabled. Components are stored among the two partitions as&lt;br /&gt;
&lt;br /&gt;
* Partition A&lt;br /&gt;
** filesystem header at the beginning.&lt;br /&gt;
** directory hash table&lt;br /&gt;
** file hash table&lt;br /&gt;
** (stand-alone) file allocation table&lt;br /&gt;
** (stand-alone) directory entry table&lt;br /&gt;
** file entry table&lt;br /&gt;
* Partition B&lt;br /&gt;
** used as data region entirely, and only has file data allocated.&lt;br /&gt;
&lt;br /&gt;
In this layout, all file system metadata is duplicated by partition A DPFS tree, but file data is not as partition B has external IVFC level 4.&lt;br /&gt;
&lt;br /&gt;
=== Extdata ===&lt;br /&gt;
An extdata consists of several DIFF containers (device files), among which the special device file &amp;lt;code&amp;gt;00000000/00000001&amp;lt;/code&amp;gt; contains the inner FAT system, while other devices contains normal subfiles of the extdata. Please refer to [[Extdata]] for detail. The special file &amp;lt;code&amp;gt;00000000/00000001&amp;lt;/code&amp;gt; contists of the following components&lt;br /&gt;
&lt;br /&gt;
* filesystem header at the beginning&lt;br /&gt;
* directory hash table&lt;br /&gt;
* file hash table&lt;br /&gt;
* file allocation table (degenerate, because the data region only has two &amp;quot;files&amp;quot;: the directory entry table and the file entry table)&lt;br /&gt;
* data region&lt;br /&gt;
** directory entry table allocated inside data region&lt;br /&gt;
** file entry table as well&lt;br /&gt;
** normal subfiles are NOT in the data region. They are in their DIFF containers instead.&lt;br /&gt;
&lt;br /&gt;
=== Title database ===&lt;br /&gt;
All [[Title Database]] files are DIFF containers. Except for &amp;lt;code&amp;gt;certs.db&amp;lt;/code&amp;gt;, all of them uses this filesystem in the DIFF inner data, which consists of&lt;br /&gt;
&lt;br /&gt;
* database-specific pre-header at the beginning (See [[Title Database]])&lt;br /&gt;
* filesystem header&lt;br /&gt;
* directory Hash Table (degenerate and always has only one bucket, as there is only one directory for &amp;quot;root&amp;quot;)&lt;br /&gt;
* file Hash Table&lt;br /&gt;
* file allocation table&lt;br /&gt;
* data region&lt;br /&gt;
** directory entry table allocated inside data region (degenerate, as there is only one directory for &amp;quot;root&amp;quot;)&lt;br /&gt;
** file entry table as well&lt;br /&gt;
** title entries (title info or ticket) are allocated as normal files in the data region as well.&lt;br /&gt;
&lt;br /&gt;
== Filesystem Header ==&lt;br /&gt;
Offsets listed in the table below are all related to the beginning of the header. This is especially important for title database, as the offsets doesn&#039;t count the pre header there.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! Offset&lt;br /&gt;
! Length&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x00&lt;br /&gt;
| 4&lt;br /&gt;
| Magic (&amp;quot;SAVE&amp;quot; for savegame; &amp;quot;BDRI&amp;quot; for title database; &amp;quot;VSXE&amp;quot; for extdata)&lt;br /&gt;
|-&lt;br /&gt;
| 0x04&lt;br /&gt;
| 4&lt;br /&gt;
| Version (0x40000 for savegame; 0x30000 for title database and extdata)&lt;br /&gt;
|-&lt;br /&gt;
| 0x08&lt;br /&gt;
| 8&lt;br /&gt;
| Filesystem Information offset (Y, =0x20 for savegame and title database, =0x138 for extdata)&lt;br /&gt;
|-&lt;br /&gt;
| 0x10&lt;br /&gt;
| 8&lt;br /&gt;
| Filesystem image size in blocks&lt;br /&gt;
|-&lt;br /&gt;
| 0x18&lt;br /&gt;
| 4&lt;br /&gt;
| Filesystem Image block size&lt;br /&gt;
|-&lt;br /&gt;
| 0x1C&lt;br /&gt;
| 4&lt;br /&gt;
| Padding&lt;br /&gt;
|-&lt;br /&gt;
| 0x20 &lt;br /&gt;
| 0x118 in total&lt;br /&gt;
| Below is additional data for extdata. Not present in savegame or title database&lt;br /&gt;
|-&lt;br /&gt;
| 0x20&lt;br /&gt;
| 8&lt;br /&gt;
| Unknown&lt;br /&gt;
|-&lt;br /&gt;
| 0x28&lt;br /&gt;
| 4&lt;br /&gt;
| &#039;Action&#039; made on most recently mounted Extdata image&lt;br /&gt;
|-&lt;br /&gt;
| 0x2C&lt;br /&gt;
| 4&lt;br /&gt;
| Unknown&lt;br /&gt;
|-&lt;br /&gt;
| 0x30&lt;br /&gt;
| 4&lt;br /&gt;
| D of most recently mounted Extdata image&lt;br /&gt;
|-&lt;br /&gt;
| 0x34&lt;br /&gt;
| 4&lt;br /&gt;
| Unknown&lt;br /&gt;
|-&lt;br /&gt;
| 0x38&lt;br /&gt;
| 0x100&lt;br /&gt;
| Mount path, from most recently mounted Extdata image&lt;br /&gt;
|-&lt;br /&gt;
| Y &lt;br /&gt;
| 0x68 in total&lt;br /&gt;
| Below is Filesystem Information&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x00&lt;br /&gt;
| 4&lt;br /&gt;
| Unknown&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x04&lt;br /&gt;
| 4&lt;br /&gt;
| Data region block size&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x08&lt;br /&gt;
| 8&lt;br /&gt;
| Directory hash table offset&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x10&lt;br /&gt;
| 4&lt;br /&gt;
| Directory hash table bucket count (=1 for title database)&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x14&lt;br /&gt;
| 4&lt;br /&gt;
| Padding&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x18&lt;br /&gt;
| 8&lt;br /&gt;
| File hash table offset&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x20&lt;br /&gt;
| 4&lt;br /&gt;
| File hash table bucket count&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x24&lt;br /&gt;
| 4&lt;br /&gt;
| Padding&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x28&lt;br /&gt;
| 8&lt;br /&gt;
| File allocation table offset&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x30&lt;br /&gt;
| 4&lt;br /&gt;
| File allocation table entry count&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x34&lt;br /&gt;
| 4&lt;br /&gt;
| Padding&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x38&lt;br /&gt;
| 8&lt;br /&gt;
| Data region offset &lt;br /&gt;
(0 for savegame &amp;lt;code&amp;gt;duplicate data = false&amp;lt;/code&amp;gt; layout, as the data region is in partition B for that layout)&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x40&lt;br /&gt;
| 4&lt;br /&gt;
| Data region block count &lt;br /&gt;
(= number of file allocation table entries excluding the leading 0th entry. See below)&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x44&lt;br /&gt;
| 4&lt;br /&gt;
| Padding&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x48&lt;br /&gt;
| 8&lt;br /&gt;
| for savegame &amp;lt;code&amp;gt;duplicate data = false&amp;lt;/code&amp;gt; layout: directory entry table offset;&lt;br /&gt;
otherwise: u32 directory entry table starting block index + u32 directory entry table block count&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x50&lt;br /&gt;
| 4&lt;br /&gt;
| Maximum directory count, excluding the mandatory &amp;quot;root&amp;quot; directory &lt;br /&gt;
(=1 for title database, but that 1 free directory slot is never used)&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x54&lt;br /&gt;
| 4&lt;br /&gt;
| Padding&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x58&lt;br /&gt;
| 8&lt;br /&gt;
| for savegame &amp;lt;code&amp;gt;duplicate data = false&amp;lt;/code&amp;gt; layout: file entry table offset;&lt;br /&gt;
otherwise: u32 file entry table starting block index + u32 file entry table block count&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x60&lt;br /&gt;
| 4&lt;br /&gt;
| Maximum file count&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x64&lt;br /&gt;
| 4&lt;br /&gt;
| Padding&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Directory Entry Table ==&lt;br /&gt;
&lt;br /&gt;
The directory entry table is an array of the entry type shown below. It describes the directory hierarchy of the file system. There are two variants of the directory entry type.&lt;br /&gt;
&lt;br /&gt;
=== Savegame/Extdata Variant===&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! Offset&lt;br /&gt;
! Length&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x00&lt;br /&gt;
| 4&lt;br /&gt;
| Parent directory index. 0 for root&lt;br /&gt;
|-&lt;br /&gt;
| 0x04&lt;br /&gt;
| 16&lt;br /&gt;
| ASCII directory name in. All zero for root&lt;br /&gt;
|-&lt;br /&gt;
| 0x14&lt;br /&gt;
| 4&lt;br /&gt;
| Next sibling directory index. 0 if this is the last one&lt;br /&gt;
|-&lt;br /&gt;
| 0x18&lt;br /&gt;
| 4&lt;br /&gt;
| First subdirectory index. 0 if not exists&lt;br /&gt;
|-&lt;br /&gt;
| 0x1C&lt;br /&gt;
| 4&lt;br /&gt;
| First file index in file entry table. 0 for empty directory&lt;br /&gt;
|-&lt;br /&gt;
| 0x20&lt;br /&gt;
| 4&lt;br /&gt;
| Padding / zero?&lt;br /&gt;
|-&lt;br /&gt;
| 0x24&lt;br /&gt;
| 4&lt;br /&gt;
| Index of the next directory in the same hash table bucket. 0 if this is the last one&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Title Database Variant===&lt;br /&gt;
Because title database only has one directory for &amp;quot;root&amp;quot;, its directory entry table degenerates into many zeros whose structure is not recognizable. The size of one entry here is guessed.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! Offset&lt;br /&gt;
! Length&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x00&lt;br /&gt;
| 4&lt;br /&gt;
| Parent directory index = 0 for root&lt;br /&gt;
|-&lt;br /&gt;
| 0x04&lt;br /&gt;
| 4&lt;br /&gt;
| Next sibling directory index = 0 because this is the last one&lt;br /&gt;
|-&lt;br /&gt;
| 0x08&lt;br /&gt;
| 4&lt;br /&gt;
| First subdirectory index = 0 because there is no subdirectory&lt;br /&gt;
|-&lt;br /&gt;
| 0x0C&lt;br /&gt;
| 4&lt;br /&gt;
| First file index in file entry table. 0 for empty directory&lt;br /&gt;
|-&lt;br /&gt;
| 0x10&lt;br /&gt;
| 12&lt;br /&gt;
| Padding / zero?&lt;br /&gt;
|-&lt;br /&gt;
| 0x1C&lt;br /&gt;
| 4&lt;br /&gt;
| Index of the next directory in the same hash table bucket = 0 because there is no other directory&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Dummy Entry===&lt;br /&gt;
There are also some dummy entries in the array&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! Offset&lt;br /&gt;
! Length&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x00&lt;br /&gt;
| 4&lt;br /&gt;
| Current Total entry count&lt;br /&gt;
|-&lt;br /&gt;
| 0x04&lt;br /&gt;
| 4&lt;br /&gt;
| Maximum entry count = maximum directory count + 2&lt;br /&gt;
|-&lt;br /&gt;
| 0x08&lt;br /&gt;
| 28/20&lt;br /&gt;
| Padding / All zero&lt;br /&gt;
|-&lt;br /&gt;
| 0x24/0x1C&lt;br /&gt;
| 4&lt;br /&gt;
| Index of the next dummy entry. 0 if this is the last one&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The 0-th entry of the array is always a dummy entry, which functions as the head of the dummy entry linked list. The 1-st entry of the array is always the root. Therefore maximum entry count is two more than maximum directory count. Dummy entries are left there when deleting directories, and reserved for future use.&lt;br /&gt;
&lt;br /&gt;
== File Allocation Table ==&lt;br /&gt;
&lt;br /&gt;
The file allocation table is an array of a 8-byte entry shown below. The array size is actually &#039;&#039;one larger than&#039;&#039; the size recorded in the filesystem header. Each entry corresponds to a block in the data region (the block size is defined in filesystem header). However, the 0th entry corresponds to nothing, so the corresponding block index is off by one. e.g. entry 31 in this table corresponds to block 30 in the data region.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! Offset&lt;br /&gt;
! Length&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x00&lt;br /&gt;
| 4&lt;br /&gt;
| bit[0:30]: Index U; bit[31]: Flag U&lt;br /&gt;
|-&lt;br /&gt;
| 0x04&lt;br /&gt;
| 4&lt;br /&gt;
| bit[0:30]: Index V; bit[31]: Flag V&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Entries in this table forms several chains, representing how blocks in the data region should be linked together. However, unlike normal FAT systems, which uses chains of entries, 3DS savegames use chain of &#039;&#039;nodes&#039;&#039;. Each node spans one or multiple entries.&lt;br /&gt;
&lt;br /&gt;
One node spanning &amp;lt;code&amp;gt;n&amp;lt;/code&amp;gt; entries starting from &amp;lt;code&amp;gt;FAT[k]&amp;lt;/code&amp;gt; is in the following format:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;FAT[k + 0]:&lt;br /&gt;
    Index_U = index of the first entry of the previous node. 0 if this is the first node.&lt;br /&gt;
    Index_V = index of the first entry of the next node. 0 if this is the last node.&lt;br /&gt;
    Flag_U set if this is the first node.&lt;br /&gt;
    Flag_V set if this node has multiple entries.&lt;br /&gt;
&lt;br /&gt;
FAT[k + 1]:&lt;br /&gt;
    Index_U = k (the first entry index of this node)&lt;br /&gt;
    Index_V = k + n - 1 (the last entry index of this node)&lt;br /&gt;
    Flag_U always set&lt;br /&gt;
    Flag_V always clear&lt;br /&gt;
&lt;br /&gt;
FAT[k + 2] ~ FAT[k + n - 2]:&lt;br /&gt;
    All these entries are uninitialized&lt;br /&gt;
&lt;br /&gt;
FAT[k + n - 1]:&lt;br /&gt;
    Index_U = k&lt;br /&gt;
    Index_V = k + n - 1&lt;br /&gt;
    Flag_U always set&lt;br /&gt;
    Flag_V always clear&lt;br /&gt;
    (Same values as FAT[k + 1])&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* Note: all indices above are entry indices (block index + 1)&lt;br /&gt;
&lt;br /&gt;
All free blocks that are not allocated to any files also form a node chain in the allocation table. The head index of this &amp;amp;quot;free chain&amp;amp;quot; is recorded in &amp;lt;code&amp;gt;FAT[0].Index_V&amp;lt;/code&amp;gt;. Other fields of &amp;lt;code&amp;gt;FAT[0]&amp;lt;/code&amp;gt; are all zero&lt;br /&gt;
&lt;br /&gt;
Here is an example: [https://raw.githubusercontent.com/wwylele/3ds-save-tool/master/disa-fat.png]&lt;br /&gt;
&lt;br /&gt;
For extdata, because only two &amp;quot;files&amp;quot; (directory and file entry tables) are allocated in the data region, and their size never changes once the extdata is created, they are guaranteed continuous in the data region, and the FAT degenerates to two big nodes. Therefore, instead of going through FAT, the offset and size of directory / file entry table can be found directly by offset = entry_table_starting block * data_region_block_size + data_region_offset and size = entry_table_block_count * data_region_block_size.&lt;/div&gt;</summary>
		<author><name>Wwylele</name></author>
	</entry>
	<entry>
		<id>https://www.3dbrew.org/w/index.php?title=Inner_FAT&amp;diff=20940</id>
		<title>Inner FAT</title>
		<link rel="alternate" type="text/html" href="https://www.3dbrew.org/w/index.php?title=Inner_FAT&amp;diff=20940"/>
		<updated>2019-05-03T18:58:32Z</updated>

		<summary type="html">&lt;p&gt;Wwylele: Merge header info for savegame/extdata/database here&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This page describes a common FAT-like file system used in [[Savegames]], [[Extdata]] and [[Title Database]]. This file system format has several variants depending on which kind of data it stores. All the three kinds of data that use this file system structure also happen to use the [[DISA and DIFF]] container as well, but there is no direct relationship between the file system and the DISA/DIFF container. All data formats described here is in the inner data of the DISA/DIFF container (i.e. IVFC level 4). Please refer to the DISA/DIFF page for how to unwrap it first before trying to extract the file system.&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
&lt;br /&gt;
The file system consists of the following components:&lt;br /&gt;
* header&lt;br /&gt;
* directory hash table&lt;br /&gt;
* file hash table&lt;br /&gt;
* file allocation table&lt;br /&gt;
* directory entry table&lt;br /&gt;
* file entry table&lt;br /&gt;
* data region&lt;br /&gt;
&lt;br /&gt;
The file allocation table (FAT) forms several linked lists inside, each of which represents a &amp;quot;file&amp;quot; allocated in the data region. Please refer to the File Allocation Table section below for more detail. In some variants, the directory entry table and the file entry table are also allocated as two special &amp;quot;files&amp;quot; in the data region, managed by the FAT, while in others they are stand-alone tables located outside the data region.&lt;br /&gt;
&lt;br /&gt;
== Layout Variants ==&lt;br /&gt;
Four variants of the file system layout has been identified. A summary diagram can be found here: [https://github.com/wwylele/3ds-save-tool/raw/master/inner-fat.png]&lt;br /&gt;
&lt;br /&gt;
=== Savegame, &amp;lt;code&amp;gt;duplicate data = true&amp;lt;/code&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
Such savegame is a single DISA container that only has one partition which is always configured as external IVFC level 4 disabled (see [[DISA and DIFF|DISA]] format for details). All components are stored in this partition as&lt;br /&gt;
&lt;br /&gt;
* filesystem header at the beginning&lt;br /&gt;
* directory hash table&lt;br /&gt;
* file hash table&lt;br /&gt;
* file allocation table&lt;br /&gt;
* data region&lt;br /&gt;
** directory entry table is allocated inside data region&lt;br /&gt;
** file entry table as well&lt;br /&gt;
** all file data is also allocated here&lt;br /&gt;
&lt;br /&gt;
In this layout, all data is duplicated by DISA&#039;s DPFS tree, which is what the parameter &amp;lt;code&amp;gt;duplicate data&amp;lt;/code&amp;gt; implies.&lt;br /&gt;
&lt;br /&gt;
=== Savegame, &amp;lt;code&amp;gt;duplicate data = false&amp;lt;/code&amp;gt; === &lt;br /&gt;
Such savegame is a single DISA container that has two partitions. Partition A is always configured as external IVFC level 4 disabled, and partition B is configured as it enabled. Components are stored among the two partitions as&lt;br /&gt;
&lt;br /&gt;
* Partition A&lt;br /&gt;
** filesystem header at the beginning.&lt;br /&gt;
** directory hash table&lt;br /&gt;
** file hash table&lt;br /&gt;
** (stand-alone) file allocation table&lt;br /&gt;
** (stand-alone) directory entry table&lt;br /&gt;
** file entry table&lt;br /&gt;
* Partition B&lt;br /&gt;
** used as data region entirely, and only has file data allocated.&lt;br /&gt;
&lt;br /&gt;
In this layout, all file system metadata is duplicated by partition A DPFS tree, but file data is not as partition B has external IVFC level 4.&lt;br /&gt;
&lt;br /&gt;
=== Extdata ===&lt;br /&gt;
An extdata consists of several DIFF containers (device files), among which the special device file &amp;lt;code&amp;gt;00000000/00000001&amp;lt;/code&amp;gt; contains the inner FAT system, while other devices contains normal subfiles of the extdata. Please refer to [[Extdata]] for detail. The special file &amp;lt;code&amp;gt;00000000/00000001&amp;lt;/code&amp;gt; contists of the following components&lt;br /&gt;
&lt;br /&gt;
* filesystem header at the beginning&lt;br /&gt;
* directory hash table&lt;br /&gt;
* file hash table&lt;br /&gt;
* file allocation table (degenerate, because the data region only has two &amp;quot;files&amp;quot;: the directory entry table and the file entry table)&lt;br /&gt;
* data region&lt;br /&gt;
** directory entry table allocated inside data region&lt;br /&gt;
** file entry table as well&lt;br /&gt;
** normal subfiles are NOT in the data region. They are in their DIFF containers instead.&lt;br /&gt;
&lt;br /&gt;
=== Title database ===&lt;br /&gt;
All [[Title Database]] files are DIFF containers. Except for &amp;lt;code&amp;gt;certs.db&amp;lt;/code&amp;gt;, all of them uses this filesystem in the DIFF inner data, which consists of&lt;br /&gt;
&lt;br /&gt;
* database-specific pre-header at the beginning (See [[Title Database]])&lt;br /&gt;
* filesystem header&lt;br /&gt;
* directory Hash Table (degenerate and always has only one bucket, as there is only one directory for &amp;quot;root&amp;quot;)&lt;br /&gt;
* file Hash Table&lt;br /&gt;
* file allocation table&lt;br /&gt;
* data region&lt;br /&gt;
** directory entry table allocated inside data region (degenerate, as there is only one directory for &amp;quot;root&amp;quot;)&lt;br /&gt;
** file entry table as well&lt;br /&gt;
** title entries (title info or ticket) are allocated as normal files in the data region as well.&lt;br /&gt;
&lt;br /&gt;
== Filesystem Header ==&lt;br /&gt;
Offsets listed in the table below are all related to the beginning of the header. This is especially important for title database, as the offsets doesn&#039;t count the pre header there.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! Offset&lt;br /&gt;
! Length&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x00&lt;br /&gt;
| 4&lt;br /&gt;
| Magic (&amp;quot;SAVE&amp;quot; for savegame; &amp;quot;BDRI&amp;quot; for title database; &amp;quot;VSXE&amp;quot; for extdata)&lt;br /&gt;
|-&lt;br /&gt;
| 0x04&lt;br /&gt;
| 4&lt;br /&gt;
| Version (0x40000 for savegame; 0x30000 for title database and extdata)&lt;br /&gt;
|-&lt;br /&gt;
| 0x08&lt;br /&gt;
| 8&lt;br /&gt;
| Filesystem Information offset (Y, =0x20 for savegame and title database, =0x138 for extdata)&lt;br /&gt;
|-&lt;br /&gt;
| 0x10&lt;br /&gt;
| 8&lt;br /&gt;
| Filesystem image size in blocks&lt;br /&gt;
|-&lt;br /&gt;
| 0x18&lt;br /&gt;
| 4&lt;br /&gt;
| Filesystem Image block size&lt;br /&gt;
|-&lt;br /&gt;
| 0x1C&lt;br /&gt;
| 4&lt;br /&gt;
| Padding&lt;br /&gt;
|-&lt;br /&gt;
| 0x20 &lt;br /&gt;
| 0x118 in total&lt;br /&gt;
| Below is additional data for extdata. Not present in savegame or title database&lt;br /&gt;
|-&lt;br /&gt;
| 0x20&lt;br /&gt;
| 8&lt;br /&gt;
| Unknown&lt;br /&gt;
|-&lt;br /&gt;
| 0x28&lt;br /&gt;
| 4&lt;br /&gt;
| &#039;Action&#039; made on most recently mounted Extdata image&lt;br /&gt;
|-&lt;br /&gt;
| 0x2C&lt;br /&gt;
| 4&lt;br /&gt;
| Unknown&lt;br /&gt;
|-&lt;br /&gt;
| 0x30&lt;br /&gt;
| 4&lt;br /&gt;
| D of most recently mounted Extdata image&lt;br /&gt;
|-&lt;br /&gt;
| 0x34&lt;br /&gt;
| 4&lt;br /&gt;
| Unknown&lt;br /&gt;
|-&lt;br /&gt;
| 0x38&lt;br /&gt;
| 0x100&lt;br /&gt;
| Mount path, from most recently mounted Extdata image&lt;br /&gt;
|-&lt;br /&gt;
| Y &lt;br /&gt;
| 0x68 in total&lt;br /&gt;
| Below is Filesystem Information&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x00&lt;br /&gt;
| 4&lt;br /&gt;
| Unknown&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x04&lt;br /&gt;
| 4&lt;br /&gt;
| Data region block size&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x08&lt;br /&gt;
| 8&lt;br /&gt;
| Directory hash table offset&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x10&lt;br /&gt;
| 4&lt;br /&gt;
| Directory hash table bucket count (=1 for title database)&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x14&lt;br /&gt;
| 4&lt;br /&gt;
| Padding&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x18&lt;br /&gt;
| 8&lt;br /&gt;
| File hash table offset&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x20&lt;br /&gt;
| 4&lt;br /&gt;
| File hash table bucket count&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x24&lt;br /&gt;
| 4&lt;br /&gt;
| Padding&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x28&lt;br /&gt;
| 8&lt;br /&gt;
| File allocation table offset&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x30&lt;br /&gt;
| 4&lt;br /&gt;
| File allocation table entry count&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x34&lt;br /&gt;
| 4&lt;br /&gt;
| Padding&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x38&lt;br /&gt;
| 8&lt;br /&gt;
| Data region offset &lt;br /&gt;
(0 for savegame &amp;lt;code&amp;gt;duplicate data = false&amp;lt;/code&amp;gt; layout, as the data region is in partition B for that layout)&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x40&lt;br /&gt;
| 4&lt;br /&gt;
| Data region block count &lt;br /&gt;
(= number of file allocation table entries excluding the leading 0th entry. See below)&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x44&lt;br /&gt;
| 4&lt;br /&gt;
| Padding&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x48&lt;br /&gt;
| 8&lt;br /&gt;
| for savegame &amp;lt;code&amp;gt;duplicate data = false&amp;lt;/code&amp;gt; layout: directory entry table offset;&lt;br /&gt;
otherwise: u32 directory entry table starting block index + u32 directory entry table block count&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x50&lt;br /&gt;
| 4&lt;br /&gt;
| Maximum directory count, excluding the mandatory &amp;quot;root&amp;quot; directory &lt;br /&gt;
(=1 for title database, but that 1 free directory slot is never used)&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x54&lt;br /&gt;
| 4&lt;br /&gt;
| Padding&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x58&lt;br /&gt;
| 8&lt;br /&gt;
| for savegame &amp;lt;code&amp;gt;duplicate data = false&amp;lt;/code&amp;gt; layout: file entry table offset;&lt;br /&gt;
otherwise: u32 file entry table starting block index + u32 file entry table block count&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x60&lt;br /&gt;
| 4&lt;br /&gt;
| Maximum file count&lt;br /&gt;
|-&lt;br /&gt;
| Y + 0x64&lt;br /&gt;
| 4&lt;br /&gt;
| Padding&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== File Allocation Table ==&lt;br /&gt;
&lt;br /&gt;
The file allocation table is an array of a 8-byte entry shown below. The array size is actually &#039;&#039;one larger than&#039;&#039; the size recorded in the filesystem header. Each entry corresponds to a block in the data region (the block size is defined in filesystem header). However, the 0th entry corresponds to nothing, so the corresponding block index is off by one. e.g. entry 31 in this table corresponds to block 30 in the data region.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! Offset&lt;br /&gt;
! Length&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x00&lt;br /&gt;
| 4&lt;br /&gt;
| bit[0:30]: Index U; bit[31]: Flag U&lt;br /&gt;
|-&lt;br /&gt;
| 0x04&lt;br /&gt;
| 4&lt;br /&gt;
| bit[0:30]: Index V; bit[31]: Flag V&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Entries in this table forms several chains, representing how blocks in the data region should be linked together. However, unlike normal FAT systems, which uses chains of entries, 3DS savegames use chain of &#039;&#039;nodes&#039;&#039;. Each node spans one or multiple entries.&lt;br /&gt;
&lt;br /&gt;
One node spanning &amp;lt;code&amp;gt;n&amp;lt;/code&amp;gt; entries starting from &amp;lt;code&amp;gt;FAT[k]&amp;lt;/code&amp;gt; is in the following format:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;FAT[k + 0]:&lt;br /&gt;
    Index_U = index of the first entry of the previous node. 0 if this is the first node.&lt;br /&gt;
    Index_V = index of the first entry of the next node. 0 if this is the last node.&lt;br /&gt;
    Flag_U set if this is the first node.&lt;br /&gt;
    Flag_V set if this node has multiple entries.&lt;br /&gt;
&lt;br /&gt;
FAT[k + 1]:&lt;br /&gt;
    Index_U = k (the first entry index of this node)&lt;br /&gt;
    Index_V = k + n - 1 (the last entry index of this node)&lt;br /&gt;
    Flag_U always set&lt;br /&gt;
    Flag_V always clear&lt;br /&gt;
&lt;br /&gt;
FAT[k + 2] ~ FAT[k + n - 2]:&lt;br /&gt;
    All these entries are uninitialized&lt;br /&gt;
&lt;br /&gt;
FAT[k + n - 1]:&lt;br /&gt;
    Index_U = k&lt;br /&gt;
    Index_V = k + n - 1&lt;br /&gt;
    Flag_U always set&lt;br /&gt;
    Flag_V always clear&lt;br /&gt;
    (Same values as FAT[k + 1])&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* Note: all indices above are entry indices (block index + 1)&lt;br /&gt;
&lt;br /&gt;
All free blocks that are not allocated to any files also form a node chain in the allocation table. The head index of this &amp;amp;quot;free chain&amp;amp;quot; is recorded in &amp;lt;code&amp;gt;FAT[0].Index_V&amp;lt;/code&amp;gt;. Other fields of &amp;lt;code&amp;gt;FAT[0]&amp;lt;/code&amp;gt; are all zero&lt;br /&gt;
&lt;br /&gt;
Here is an example: [https://raw.githubusercontent.com/wwylele/3ds-save-tool/master/disa-fat.png]&lt;br /&gt;
&lt;br /&gt;
For extdata, because only two &amp;quot;files&amp;quot; (directory and file entry tables) are allocated in the data region, and their size never changes once the extdata is created, they are guaranteed continuous in the data region, and the FAT degenerates to two big nodes. Therefore, instead of going through FAT, the offset and size of directory / file entry table can be found directly by offset = entry_table_starting block * data_region_block_size + data_region_offset and size = entry_table_block_count * data_region_block_size.&lt;/div&gt;</summary>
		<author><name>Wwylele</name></author>
	</entry>
	<entry>
		<id>https://www.3dbrew.org/w/index.php?title=Inner_FAT&amp;diff=20939</id>
		<title>Inner FAT</title>
		<link rel="alternate" type="text/html" href="https://www.3dbrew.org/w/index.php?title=Inner_FAT&amp;diff=20939"/>
		<updated>2019-05-03T18:30:30Z</updated>

		<summary type="html">&lt;p&gt;Wwylele: Copy FAT info from savegame&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This page describes a common FAT-like file system used in [[Savegames]], [[Extdata]] and [[Title Database]]. This file system format has several variants depending on which kind of data it stores. All the three kinds of data that use this file system structure also happen to use the [[DISA and DIFF]] container as well, but there is no direct relationship between the file system and the DISA/DIFF container. All data formats described here is in the inner data of the DISA/DIFF container (i.e. IVFC level 4). Please refer to the DISA/DIFF page for how to unwrap it first before trying to extract the file system.&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
&lt;br /&gt;
The file system consists of the following components:&lt;br /&gt;
* header&lt;br /&gt;
* directory hash table&lt;br /&gt;
* file hash table&lt;br /&gt;
* file allocation table&lt;br /&gt;
* directory entry table&lt;br /&gt;
* file entry table&lt;br /&gt;
* data region&lt;br /&gt;
&lt;br /&gt;
The file allocation table (FAT) forms several linked lists inside, each of which represents a &amp;quot;file&amp;quot; allocated in the data region. Please refer to the File Allocation Table section below for more detail. In some variants, the directory entry table and the file entry table are also allocated as two special &amp;quot;files&amp;quot; in the data region, managed by the FAT, while in others they are stand-alone tables located outside the data region.&lt;br /&gt;
&lt;br /&gt;
== Layout Variants ==&lt;br /&gt;
Four variants of the file system layout has been identified. A summary diagram can be found here: [https://github.com/wwylele/3ds-save-tool/raw/master/inner-fat.png]&lt;br /&gt;
&lt;br /&gt;
=== Savegame, &amp;lt;code&amp;gt;duplicate data = true&amp;lt;/code&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
Such savegame is a single DISA container that only has one partition which is always configured as external IVFC level 4 disabled (see [[DISA and DIFF|DISA]] format for details). All components are stored in this partition as&lt;br /&gt;
&lt;br /&gt;
* filesystem header at the beginning&lt;br /&gt;
* directory hash table&lt;br /&gt;
* file hash table&lt;br /&gt;
* file allocation table&lt;br /&gt;
* data region&lt;br /&gt;
** directory entry table is allocated inside data region&lt;br /&gt;
** file entry table as well&lt;br /&gt;
** all file data is also allocated here&lt;br /&gt;
&lt;br /&gt;
In this layout, all data is duplicated by DISA&#039;s DPFS tree, which is what the parameter &amp;lt;code&amp;gt;duplicate data&amp;lt;/code&amp;gt; implies.&lt;br /&gt;
&lt;br /&gt;
=== Savegame, &amp;lt;code&amp;gt;duplicate data = false&amp;lt;/code&amp;gt; === &lt;br /&gt;
Such savegame is a single DISA container that has two partitions. Partition A is always configured as external IVFC level 4 disabled, and partition B is configured as it enabled. Components are stored among the two partitions as&lt;br /&gt;
&lt;br /&gt;
* Partition A&lt;br /&gt;
** filesystem header at the beginning.&lt;br /&gt;
** directory hash table&lt;br /&gt;
** file hash table&lt;br /&gt;
** (stand-alone) file allocation table&lt;br /&gt;
** (stand-alone) directory entry table&lt;br /&gt;
** file entry table&lt;br /&gt;
* Partition B&lt;br /&gt;
** used as data region entirely, and only has file data allocated.&lt;br /&gt;
&lt;br /&gt;
In this layout, all file system metadata is duplicated by partition A DPFS tree, but file data is not as partition B has external IVFC level 4.&lt;br /&gt;
&lt;br /&gt;
=== Extdata ===&lt;br /&gt;
An extdata consists of several DIFF containers (device files), among which the special device file &amp;lt;code&amp;gt;00000000/00000001&amp;lt;/code&amp;gt; contains the inner FAT system, while other devices contains normal subfiles of the extdata. Please refer to [[Extdata]] for detail. The special file &amp;lt;code&amp;gt;00000000/00000001&amp;lt;/code&amp;gt; contists of the following components&lt;br /&gt;
&lt;br /&gt;
* filesystem header at the beginning&lt;br /&gt;
* directory hash table&lt;br /&gt;
* file hash table&lt;br /&gt;
* file allocation table (degenerate, because the data region only has two &amp;quot;files&amp;quot;: the directory entry table and the file entry table)&lt;br /&gt;
* data region&lt;br /&gt;
** directory entry table allocated inside data region&lt;br /&gt;
** file entry table as well&lt;br /&gt;
** normal subfiles are NOT in the data region. They are in their DIFF containers instead.&lt;br /&gt;
&lt;br /&gt;
=== Title database ===&lt;br /&gt;
All [[Title Database]] files are DIFF containers. Except for &amp;lt;code&amp;gt;certs.db&amp;lt;/code&amp;gt;, all of them uses this filesystem in the DIFF inner data, which consists of&lt;br /&gt;
&lt;br /&gt;
* database-specific pre-header at the beginning (See [[Title Database]])&lt;br /&gt;
* filesystem header&lt;br /&gt;
* directory Hash Table (degenerate and always has only one bucket, as there is only one directory for &amp;quot;root&amp;quot;)&lt;br /&gt;
* file Hash Table&lt;br /&gt;
* file allocation table&lt;br /&gt;
* data region&lt;br /&gt;
** directory entry table allocated inside data region (degenerate, as there is only one directory for &amp;quot;root&amp;quot;)&lt;br /&gt;
** file entry table as well&lt;br /&gt;
** title entries (title info or ticket) are allocated as normal files in the data region as well.&lt;br /&gt;
&lt;br /&gt;
== File Allocation Table ==&lt;br /&gt;
&lt;br /&gt;
The file allocation table is an array of a 8-byte entry shown below. The array size is actually &#039;&#039;one larger than&#039;&#039; the size recorded in the filesystem header. Each entry corresponds to a block in the data region (the block size is defined in filesystem header). However, the 0th entry corresponds to nothing, so the corresponding block index is off by one. e.g. entry 31 in this table corresponds to block 30 in the data region.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! Offset&lt;br /&gt;
! Length&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x00&lt;br /&gt;
| 4&lt;br /&gt;
| bit[0:30]: Index U; bit[31]: Flag U&lt;br /&gt;
|-&lt;br /&gt;
| 0x04&lt;br /&gt;
| 4&lt;br /&gt;
| bit[0:30]: Index V; bit[31]: Flag V&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Entries in this table forms several chains, representing how blocks in the data region should be linked together. However, unlike normal FAT systems, which uses chains of entries, 3DS savegames use chain of &#039;&#039;nodes&#039;&#039;. Each node spans one or multiple entries.&lt;br /&gt;
&lt;br /&gt;
One node spanning &amp;lt;code&amp;gt;n&amp;lt;/code&amp;gt; entries starting from &amp;lt;code&amp;gt;FAT[k]&amp;lt;/code&amp;gt; is in the following format:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;FAT[k + 0]:&lt;br /&gt;
    Index_U = index of the first entry of the previous node. 0 if this is the first node.&lt;br /&gt;
    Index_V = index of the first entry of the next node. 0 if this is the last node.&lt;br /&gt;
    Flag_U set if this is the first node.&lt;br /&gt;
    Flag_V set if this node has multiple entries.&lt;br /&gt;
&lt;br /&gt;
FAT[k + 1]:&lt;br /&gt;
    Index_U = k (the first entry index of this node)&lt;br /&gt;
    Index_V = k + n - 1 (the last entry index of this node)&lt;br /&gt;
    Flag_U always set&lt;br /&gt;
    Flag_V always clear&lt;br /&gt;
&lt;br /&gt;
FAT[k + 2] ~ FAT[k + n - 2]:&lt;br /&gt;
    All these entries are uninitialized&lt;br /&gt;
&lt;br /&gt;
FAT[k + n - 1]:&lt;br /&gt;
    Index_U = k&lt;br /&gt;
    Index_V = k + n - 1&lt;br /&gt;
    Flag_U always set&lt;br /&gt;
    Flag_V always clear&lt;br /&gt;
    (Same values as FAT[k + 1])&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* Note: all indices above are entry indices (block index + 1)&lt;br /&gt;
&lt;br /&gt;
All free blocks that are not allocated to any files also form a node chain in the allocation table. The head index of this &amp;amp;quot;free chain&amp;amp;quot; is recorded in &amp;lt;code&amp;gt;FAT[0].Index_V&amp;lt;/code&amp;gt;. Other fields of &amp;lt;code&amp;gt;FAT[0]&amp;lt;/code&amp;gt; are all zero&lt;br /&gt;
&lt;br /&gt;
Here is an example: [https://raw.githubusercontent.com/wwylele/3ds-save-tool/master/disa-fat.png]&lt;br /&gt;
&lt;br /&gt;
For extdata, because only two &amp;quot;files&amp;quot; (directory and file entry tables) are allocated in the data region, and their size never changes once the extdata is created, they are guaranteed continuous in the data region, and the FAT degenerates to two big nodes. Therefore, instead of going through FAT, the offset and size of directory / file entry table can be found directly by offset = entry_table_starting block * data_region_block_size + data_region_offset and size = entry_table_block_count * data_region_block_size.&lt;/div&gt;</summary>
		<author><name>Wwylele</name></author>
	</entry>
	<entry>
		<id>https://www.3dbrew.org/w/index.php?title=Inner_FAT&amp;diff=20938</id>
		<title>Inner FAT</title>
		<link rel="alternate" type="text/html" href="https://www.3dbrew.org/w/index.php?title=Inner_FAT&amp;diff=20938"/>
		<updated>2019-05-03T18:24:04Z</updated>

		<summary type="html">&lt;p&gt;Wwylele: Layout Variants&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This page describes a common FAT-like file system used in [[Savegames]], [[Extdata]] and [[Title Database]]. This file system format has several variants depending on which kind of data it stores. All the three kinds of data that use this file system structure also happen to use the [[DISA and DIFF]] container as well, but there is no direct relationship between the file system and the DISA/DIFF container. All data formats described here is in the inner data of the DISA/DIFF container (i.e. IVFC level 4). Please refer to the DISA/DIFF page for how to unwrap it first before trying to extract the file system.&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
&lt;br /&gt;
The file system consists of the following components:&lt;br /&gt;
* header&lt;br /&gt;
* directory hash table&lt;br /&gt;
* file hash table&lt;br /&gt;
* file allocation table&lt;br /&gt;
* directory entry table&lt;br /&gt;
* file entry table&lt;br /&gt;
* data region&lt;br /&gt;
&lt;br /&gt;
The file allocation table (FAT) forms several linked lists inside, each of which represents a &amp;quot;file&amp;quot; allocated in the data region. Please refer to the File Allocation Table section below for more detail. In some variants, the directory entry table and the file entry table are also allocated as two special &amp;quot;files&amp;quot; in the data region, managed by the FAT, while in others they are stand-alone tables located outside the data region.&lt;br /&gt;
&lt;br /&gt;
== Layout Variants ==&lt;br /&gt;
Four variants of the file system layout has been identified. A summary diagram can be found here: [https://github.com/wwylele/3ds-save-tool/raw/master/inner-fat.png]&lt;br /&gt;
&lt;br /&gt;
=== Savegame, &amp;lt;code&amp;gt;duplicate data = true&amp;lt;/code&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
Such savegame is a single DISA container that only has one partition which is always configured as external IVFC level 4 disabled (see [[DISA and DIFF|DISA]] format for details). All components are stored in this partition as&lt;br /&gt;
&lt;br /&gt;
* filesystem header at the beginning&lt;br /&gt;
* directory hash table&lt;br /&gt;
* file hash table&lt;br /&gt;
* file allocation table&lt;br /&gt;
* data region&lt;br /&gt;
** directory entry table is allocated inside data region&lt;br /&gt;
** file entry table as well&lt;br /&gt;
** all file data is also allocated here&lt;br /&gt;
&lt;br /&gt;
In this layout, all data is duplicated by DISA&#039;s DPFS tree, which is what the parameter &amp;lt;code&amp;gt;duplicate data&amp;lt;/code&amp;gt; implies.&lt;br /&gt;
&lt;br /&gt;
=== Savegame, &amp;lt;code&amp;gt;duplicate data = false&amp;lt;/code&amp;gt; === &lt;br /&gt;
Such savegame is a single DISA container that has two partitions. Partition A is always configured as external IVFC level 4 disabled, and partition B is configured as it enabled. Components are stored among the two partitions as&lt;br /&gt;
&lt;br /&gt;
* Partition A&lt;br /&gt;
** filesystem header at the beginning.&lt;br /&gt;
** directory hash table&lt;br /&gt;
** file hash table&lt;br /&gt;
** (stand-alone) file allocation table&lt;br /&gt;
** (stand-alone) directory entry table&lt;br /&gt;
** file entry table&lt;br /&gt;
* Partition B&lt;br /&gt;
** used as data region entirely, and only has file data allocated.&lt;br /&gt;
&lt;br /&gt;
In this layout, all file system metadata is duplicated by partition A DPFS tree, but file data is not as partition B has external IVFC level 4.&lt;br /&gt;
&lt;br /&gt;
=== Extdata ===&lt;br /&gt;
An extdata consists of several DIFF containers (device files), among which the special device file &amp;lt;code&amp;gt;00000000/00000001&amp;lt;/code&amp;gt; contains the inner FAT system, while other devices contains normal subfiles of the extdata. Please refer to [[Extdata]] for detail. The special file &amp;lt;code&amp;gt;00000000/00000001&amp;lt;/code&amp;gt; contists of the following components&lt;br /&gt;
&lt;br /&gt;
* filesystem header at the beginning&lt;br /&gt;
* directory hash table&lt;br /&gt;
* file hash table&lt;br /&gt;
* file allocation table (degenerate, because the data region only has two &amp;quot;files&amp;quot;: the directory entry table and the file entry table)&lt;br /&gt;
* data region&lt;br /&gt;
** directory entry table allocated inside data region&lt;br /&gt;
** file entry table as well&lt;br /&gt;
** normal subfiles are NOT in the data region. They are in their DIFF containers instead.&lt;br /&gt;
&lt;br /&gt;
=== Title database ===&lt;br /&gt;
All [[Title Database]] files are DIFF containers. Except for &amp;lt;code&amp;gt;certs.db&amp;lt;/code&amp;gt;, all of them uses this filesystem in the DIFF inner data, which consists of&lt;br /&gt;
&lt;br /&gt;
* database-specific pre-header at the beginning (See [[Title Database]])&lt;br /&gt;
* filesystem header&lt;br /&gt;
* directory Hash Table (degenerate and always has only one bucket, as there is only one directory for &amp;quot;root&amp;quot;)&lt;br /&gt;
* file Hash Table&lt;br /&gt;
* file allocation table&lt;br /&gt;
* data region&lt;br /&gt;
** directory entry table allocated inside data region (degenerate, as there is only one directory for &amp;quot;root&amp;quot;)&lt;br /&gt;
** file entry table as well&lt;br /&gt;
** title entries (title info or ticket) are allocated as normal files in the data region as well.&lt;/div&gt;</summary>
		<author><name>Wwylele</name></author>
	</entry>
	<entry>
		<id>https://www.3dbrew.org/w/index.php?title=Inner_FAT&amp;diff=20937</id>
		<title>Inner FAT</title>
		<link rel="alternate" type="text/html" href="https://www.3dbrew.org/w/index.php?title=Inner_FAT&amp;diff=20937"/>
		<updated>2019-05-03T18:00:59Z</updated>

		<summary type="html">&lt;p&gt;Wwylele: Start a new page to unify the filesystem doc of save/extdata/database&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This page describes a common FAT-like file system used in [[Savegames]], [[Extdata]] and [[Title Database]]. This file system format has several variants depending on which kind of data it stores. All the three kinds of data that use this file system structure also happen to use the [[DISA and DIFF]] container as well, but there is no direct relationship between the file system and the DISA/DIFF container. All data formats described here is in the inner data of the DISA/DIFF container (i.e. IVFC level 4). Please refer to the DISA/DIFF page for how to unwrap it first before trying to extract the file system.&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
&lt;br /&gt;
The file system consists of the following components:&lt;br /&gt;
* header&lt;br /&gt;
* directory hash table&lt;br /&gt;
* file hash table&lt;br /&gt;
* file allocation table&lt;br /&gt;
* directory entry table&lt;br /&gt;
* file entry table&lt;br /&gt;
* data region&lt;br /&gt;
&lt;br /&gt;
The file allocation table (FAT) forms several linked lists inside, each of which represents a &amp;quot;file&amp;quot; allocated in the data region. Please refer to the File Allocation Table section below for more detail. In some variants, the directory entry table and the file entry table are also allocated as two special &amp;quot;files&amp;quot; in the data region, managed by the FAT, while in others they are stand-alone tables located outside the data region.&lt;/div&gt;</summary>
		<author><name>Wwylele</name></author>
	</entry>
	<entry>
		<id>https://www.3dbrew.org/w/index.php?title=NCCH&amp;diff=20935</id>
		<title>NCCH</title>
		<link rel="alternate" type="text/html" href="https://www.3dbrew.org/w/index.php?title=NCCH&amp;diff=20935"/>
		<updated>2019-05-01T16:01:07Z</updated>

		<summary type="html">&lt;p&gt;Wwylele: /* Encryption */ Just document the encryption stuff here instead of external link&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:File formats]]&lt;br /&gt;
The following text tries to document the structure of the NCCH (Nintendo Content Container Header) container format. This format is used to store the content of any installed [[Titles|title]].&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
There are two known NCCH container specializations used on the 3DS, &amp;quot;executable&amp;quot; and &amp;quot;non-executable&amp;quot;, officially known as CXI and CFA, respectively.&lt;br /&gt;
&lt;br /&gt;
=== CXI ===&lt;br /&gt;
&lt;br /&gt;
The CXI (CTR Executable Image) specialization of the NCCH container contains executable code, which runs on a single ARM11 core.&lt;br /&gt;
&lt;br /&gt;
The CXI format is structured in the following order:&lt;br /&gt;
* first a NCCH header,&lt;br /&gt;
* followed by an [[NCCH/Extended Header|extended header]],&lt;br /&gt;
* followed by an access descriptor,&lt;br /&gt;
* followed by an &#039;&#039;&#039;optional&#039;&#039;&#039; plain binary region,&lt;br /&gt;
* followed by an &#039;&#039;&#039;optional&#039;&#039;&#039; executable filesystem ([[ExeFS]]) - (contains ARM11 code, Home menu [[SMDH|icn]]/bnr and [[Logo|logo]]),&lt;br /&gt;
* and finally followed by an &#039;&#039;&#039;optional&#039;&#039;&#039; read-only filesystem ([[RomFS]]) - (Used for external file storage).&lt;br /&gt;
&lt;br /&gt;
The extended header contains additional information regarding access control. &lt;br /&gt;
The plain binary region is an area specifically stored in plaintext, mostly containing SDK library strings for identification.&lt;br /&gt;
&lt;br /&gt;
=== CFA ===&lt;br /&gt;
&lt;br /&gt;
The CFA (CTR File Archive) specialization of the NCCH container is not executable, but is used in conjunction with CXI files, e.g. the DLP Child Container and the Electronic Manual. (There is a system update NCCH which follows this format, but is used by the 3DS rather than the Application NCCH, and only works when embedded in the [[CCI]] format because the nVer is kept in the header of retail [[CCI]] files instead of the application NCCH). There are CFA files which exist alone in a title, but these are just [[Title list|System Data Archive]] titles and are found only in the [[Flash Filesystem#CTR partition|NAND]].&lt;br /&gt;
&lt;br /&gt;
CFA files are structured in the following order:&lt;br /&gt;
* first a NCCH header,&lt;br /&gt;
* followed by an &#039;&#039;&#039;optional&#039;&#039;&#039; executable filesystem ([[ExeFS]]) (same as in CXI, except no ARM11 code)&lt;br /&gt;
* followed by an &#039;&#039;&#039;optional&#039;&#039;&#039; read-only filesystem ([[RomFS]])&lt;br /&gt;
&lt;br /&gt;
== Container File Format ==&lt;br /&gt;
&lt;br /&gt;
=== Encryption ===&lt;br /&gt;
The [[NCCH/Extended Header|extended header]], the [[ExeFS]], and the [[RomFS]] are encrypted using [https://github.com/3dshax/ctr/blob/master/ctrtool/ncch.c 128-bit AES CTR] unless the NoCrypto flag is set in ncchflag[7]. There are different sets of encryption parameters in use, as over the time new system updates introduced more sophisticated means of encryption. &lt;br /&gt;
&lt;br /&gt;
All encrypted regions are grouped into two categories, each of which uses one kind of encryption scheme:&lt;br /&gt;
&lt;br /&gt;
* The &amp;quot;menu info&amp;quot; group, including the [[NCCH/Extended Header|extended header]], the [[ExeFS]] header, and the files &amp;quot;icon&amp;quot; and &amp;quot;banner&amp;quot; in [[ExeFS]], which are needed to display the game on the menu regardless whether system version supports the game, or whether the pre-downloaded eshop game is officially released.&lt;br /&gt;
&lt;br /&gt;
* The &amp;quot;content&amp;quot; group, including the rest files (&amp;quot;.code&amp;quot; and &amp;quot;.firm&amp;quot;) in [[ExeFS]], and the entire [[RomFS]], which is needed for actually running the game, and which can be only decrypted on the supported system (and when the seed is officially released for eshop games).&lt;br /&gt;
&lt;br /&gt;
The decryption key is generated using the [[AES|AES Engine]]. The keyX and keyY for each group are set as follows:&lt;br /&gt;
 &lt;br /&gt;
* The &amp;quot;menu info&amp;quot; group uses the primary key, always generated by keyX in the slot 0x2C (set by bootrom) and keyY from the first 0x10 bytes of the NCCH signature.&lt;br /&gt;
&lt;br /&gt;
* The &amp;quot;content&amp;quot; group uses the secondary key. The slot selection for keyX depends on ncchflag[3], as listed in the table below. &lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
!  ncchflag[3]&lt;br /&gt;
!  FW Introduced&lt;br /&gt;
!  Old3DS&lt;br /&gt;
!  [[AES#Keyslot|AES Keyslots]]&lt;br /&gt;
!  Notes&lt;br /&gt;
|-&lt;br /&gt;
|  0x00&lt;br /&gt;
|  The initial version&lt;br /&gt;
|  style=&amp;quot;background: #ccffbb&amp;quot; | Yes&lt;br /&gt;
|  0x2C&lt;br /&gt;
|  This keyslot is initialized by bootrom. This is the same key as the primary key.&lt;br /&gt;
|-&lt;br /&gt;
|  0x01&lt;br /&gt;
|  [[7.0.0-13|7.0.0-X]]&lt;br /&gt;
|  style=&amp;quot;background: #ccffbb&amp;quot; | Yes&lt;br /&gt;
|  0x25&lt;br /&gt;
|  This keyslot is [[Savegames|initialized]] by the 6.0 gamecard savegame keyY init function during boot, using a different portion of the [[Savegames|final]] hash (this keyslot is separate from the one used for the 6.0 save crypto).&lt;br /&gt;
|-&lt;br /&gt;
|  0x0A&lt;br /&gt;
|  [[9.3.0-21|9.3.0-X]]&lt;br /&gt;
|  style=&amp;quot;background: #ffccbb&amp;quot; | No&lt;br /&gt;
|  0x18&lt;br /&gt;
|  This keyslot is initialized by [[FIRM#New_3DS_FIRM|arm9loader]] on New3DS starting with [[8.1.0-0_New3DS]], but only [[9.3.0-21|9.3.0-X]] and later know how to use it with ncchflag[3].&lt;br /&gt;
|-&lt;br /&gt;
|  0x0B&lt;br /&gt;
|  [[9.6.0-24|9.6.0-X]]&lt;br /&gt;
|  style=&amp;quot;background: #ffccbb&amp;quot; | No&lt;br /&gt;
|  0x1B&lt;br /&gt;
|  [[9.6.0-24|9.6.0-X]]&#039;s [[FIRM#New_3DS_FIRM|arm9loader]] changed the contents of keyslots 0x19-0x1F; 9.6.0-X was the first time they were officially used, so this is not a breaking change (there is no content that would use the old versions of those keys).&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Besides all rules above, if ncchflag[7] bitmask 0x1 is set, and a fixed AES key instead is used for both groups. There are two fixed keys, one for titles which have the system category bit set (SystemFixedKey), and one for the rest (&amp;quot;zeros&amp;quot; key). These are debug keys, as they aren&#039;t nomally supported on retail systems.&lt;br /&gt;
&lt;br /&gt;
The initial CTR for decryption each region is generated from the partition ID, as described below:&lt;br /&gt;
&lt;br /&gt;
* if the version field (NCCH header + 0x112) is 0 or 2, the 16-byte CTR is [partition_id[7], partition_id[6], ..., partition_id[0], M, 0, ..., 0], where&lt;br /&gt;
** The 8-byte partition ID starts from the beginning in the reverse order. If the partition ID is viewed as a little-endian u64, and the CTR is viewed as big-endian u128, then this is to put the partition ID to the most significant bits of the CTR&lt;br /&gt;
** CTR[8] is set to a magic number M. For [[NCCH/Extended Header|extended header]], M = 1. For [[ExeFS]], M = 2. For [[RomFS]], M = 3.&lt;br /&gt;
** The rest 7 bytes (the least significant bits of big-endian CTR) are set to zero&lt;br /&gt;
&lt;br /&gt;
* if the version field is 1, the 16-byte CTR is [partition_id[0], partition_id[1], ...,partition_id[7], 0, 0, 0, 0, T[0], T[1], T[2], T[3]], where&lt;br /&gt;
** The 8-byte partition ID starts from the beginning in the same order. &lt;br /&gt;
** Then four zeros follow.&lt;br /&gt;
** Then a number T in big-endian follows. This number is the offset of each encrypted region to the NCCH beginning. So for [[NCCH/Extended Header|extended header]], T = 0x200. For [[ExeFS]]/[[RomFS]]. T = 0x200 * ExeFS/RomFS offset in media units&lt;br /&gt;
&lt;br /&gt;
Note that due to the key generation schemes described above, ExeFS can contain regions using different keys. Regardless of this, both regions shared the same initial CTR at the beginning of ExeFS. If one region doesn&#039;t start at the beginning of ExeFS, its actual CTR at its own beginning = ExeFS CTR + (region offset / AESBlockSize=16)&lt;br /&gt;
&lt;br /&gt;
=== Format ===&lt;br /&gt;
&lt;br /&gt;
Currently, only [[ExeFS]]:/.code can be compressed (with a LZ77 variant). A flag in the [[NCCH/Extended Header#System Info|exheader]] determines if this is the case.&lt;br /&gt;
&lt;br /&gt;
On retail for SD applications, exheader_systeminfoflags.flag bit1 must be set.&lt;br /&gt;
&lt;br /&gt;
Retail CFAs use the default NCCH product code &amp;quot;CTR-P-CTAP&amp;quot;, while retail title/gamecard CXIs use NCCH product code &amp;quot;CTR-X-XXXX&amp;quot;. This product code is the NCCH [[Serials|serial code]]. The region-locking info checked by home menu is stored in the [[SMDH#BNR Region|icon]].&lt;br /&gt;
&lt;br /&gt;
All of the hashes stored in this NCCH header are over the cleartext data. The ExeFS/RomFS superblock starts at offset 0x0 in the ExeFS/RomFS, and the size is specified by the hash region fields. Nintendo&#039;s NCCH validation code seems to have the size of this region fixed to 0x200 bytes (for ExeFS at least). &lt;br /&gt;
&lt;br /&gt;
As of [[5.0.0-11]] the application [[ExeFS]]:/logo can be loaded from the plaintext region between the access descriptor and the plain region, all applications built since [[5.0.0-11]] store the logo here. The size of this logo is always 0x2000-bytes.&lt;br /&gt;
&lt;br /&gt;
The plain region mainly contains tags for each SDK library used when building the CXI. The version used for the &amp;quot;FIRMWARE&amp;quot; tag is the kernel/FIRM [[Configuration_Memory|version]], this version can also be stored in the exheader &amp;quot;kernel release version&amp;quot; ARM11 kernel descriptor field. As of [[2.2.0-X]] the NATIVE_FIRM kernels check the CXI exheader &amp;quot;kernel release version&amp;quot; field, if it is stored in the CXI exheader. If the kernel/FIRM version specified by this field is higher than the version of the running NATIVE_FIRM, the kernel will return error-code 0xD9001413.&lt;br /&gt;
&lt;br /&gt;
=== NCCH 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 signature of the NCCH header, using SHA-256.&lt;br /&gt;
|-&lt;br /&gt;
|  0x100&lt;br /&gt;
|  4&lt;br /&gt;
|  Magic ID, always &#039;NCCH&#039;&lt;br /&gt;
|-&lt;br /&gt;
|  0x104&lt;br /&gt;
|  4&lt;br /&gt;
|  Content size, in media units (1 media unit = 0x200 bytes)&lt;br /&gt;
|-&lt;br /&gt;
|  0x108&lt;br /&gt;
|  8&lt;br /&gt;
|  Partition ID&lt;br /&gt;
|-&lt;br /&gt;
|  0x110&lt;br /&gt;
|  2&lt;br /&gt;
|  Maker code&lt;br /&gt;
|-&lt;br /&gt;
|  0x112&lt;br /&gt;
|  2&lt;br /&gt;
|  Version&lt;br /&gt;
|-&lt;br /&gt;
|  0x114&lt;br /&gt;
|  4&lt;br /&gt;
|  When ncchflag[7] = 0x20 starting with FIRM [[9.6.0-24|9.6.0-X]], this is compared with the first output u32 from a SHA256 hash. The data used for that hash is 0x18-bytes: &amp;lt;0x10-long title-unique content lock seed&amp;gt; &amp;lt;programID from NCCH+0x118&amp;gt;. This hash is only used for verification of the content lock seed, and is not the actual keyY.&lt;br /&gt;
|-&lt;br /&gt;
|  0x118&lt;br /&gt;
|  8&lt;br /&gt;
|  Program ID&lt;br /&gt;
|-&lt;br /&gt;
|  0x120&lt;br /&gt;
|  0x10&lt;br /&gt;
|  Reserved&lt;br /&gt;
|-&lt;br /&gt;
|  0x130&lt;br /&gt;
|  0x20&lt;br /&gt;
|  Logo Region SHA-256 hash. (For applications built with SDK 5+) (Supported from firmware: [[5.0.0-11]])&lt;br /&gt;
|-&lt;br /&gt;
|  0x150&lt;br /&gt;
|  0x10&lt;br /&gt;
|  Product code&lt;br /&gt;
|-&lt;br /&gt;
|  0x160&lt;br /&gt;
|  0x20&lt;br /&gt;
|  Extended header SHA-256 hash (SHA256 of 2x Alignment Size, beginning at 0x0 of ExHeader)&lt;br /&gt;
|-&lt;br /&gt;
|  0x180&lt;br /&gt;
|  4&lt;br /&gt;
|  Extended header size, in bytes&lt;br /&gt;
|-&lt;br /&gt;
|  0x184&lt;br /&gt;
|  4&lt;br /&gt;
|  Reserved&lt;br /&gt;
|-&lt;br /&gt;
|  0x188&lt;br /&gt;
|  8&lt;br /&gt;
|  Flags (See Below)&lt;br /&gt;
|-&lt;br /&gt;
|  0x190&lt;br /&gt;
|  4&lt;br /&gt;
|  Plain region offset, in media units&lt;br /&gt;
|-&lt;br /&gt;
|  0x194&lt;br /&gt;
|  4&lt;br /&gt;
|  Plain region size, in media units&lt;br /&gt;
|-&lt;br /&gt;
|  0x198&lt;br /&gt;
|  4&lt;br /&gt;
|  Logo Region offset, in media units (For applications built with SDK 5+) (Supported from firmware: [[5.0.0-11]])&lt;br /&gt;
|-&lt;br /&gt;
|  0x19c&lt;br /&gt;
|  4&lt;br /&gt;
|  Logo Region size, in media units (For applications built with SDK 5+) (Supported from firmware: [[5.0.0-11]])&lt;br /&gt;
|-&lt;br /&gt;
|  0x1A0&lt;br /&gt;
|  4&lt;br /&gt;
|  ExeFS offset, in media units&lt;br /&gt;
|-&lt;br /&gt;
|  0x1A4&lt;br /&gt;
|  4&lt;br /&gt;
|  ExeFS size, in media units&lt;br /&gt;
|-&lt;br /&gt;
|  0x1A8&lt;br /&gt;
|  4&lt;br /&gt;
|  ExeFS hash region size, in media units&lt;br /&gt;
|-&lt;br /&gt;
|  0x1AC&lt;br /&gt;
|  4&lt;br /&gt;
|  Reserved&lt;br /&gt;
|-&lt;br /&gt;
|  0x1B0&lt;br /&gt;
|  4&lt;br /&gt;
|  RomFS offset, in media units&lt;br /&gt;
|-&lt;br /&gt;
|  0x1B4&lt;br /&gt;
|  4&lt;br /&gt;
|  RomFS size, in media units&lt;br /&gt;
|-&lt;br /&gt;
|  0x1B8&lt;br /&gt;
|  4&lt;br /&gt;
|  RomFS hash region size, in media units&lt;br /&gt;
|-&lt;br /&gt;
|  0x1BC&lt;br /&gt;
|  4&lt;br /&gt;
|  Reserved&lt;br /&gt;
|-&lt;br /&gt;
|  0x1C0&lt;br /&gt;
|  0x20&lt;br /&gt;
|  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)&lt;br /&gt;
|-&lt;br /&gt;
|  0x1E0&lt;br /&gt;
|  0x20&lt;br /&gt;
|  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)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Given offsets are based on the start of the file.&lt;br /&gt;
&lt;br /&gt;
=== NCCH Flags ===&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
!  INDEX&lt;br /&gt;
!  DESCRIPTION&lt;br /&gt;
|-&lt;br /&gt;
|  3&lt;br /&gt;
|  Crypto Method: When this is non-zero, a NCCH crypto method using two keyslots is used(see above).&lt;br /&gt;
|-&lt;br /&gt;
|  4&lt;br /&gt;
|  Content Platform: 1 = CTR, 2 = snake (New 3DS).&lt;br /&gt;
|-&lt;br /&gt;
|  5&lt;br /&gt;
|  Content Type Bit-masks: Data = 0x1, Executable = 0x2, SystemUpdate = 0x4, Manual = 0x8, Child = (0x4&amp;lt;nowiki&amp;gt;|&amp;lt;/nowiki&amp;gt;0x8), Trial = 0x10. When &#039;Data&#039; is set, but not &#039;Executable&#039;, NCCH is a CFA. Otherwise when &#039;Executable&#039; is set, NCCH is a CXI.&lt;br /&gt;
|-&lt;br /&gt;
|  6&lt;br /&gt;
|  Content Unit Size i.e. u32 ContentUnitSize = 0x200*2^flags[6]; &lt;br /&gt;
|-&lt;br /&gt;
|  7&lt;br /&gt;
|  Bit-masks: FixedCryptoKey = 0x1, NoMountRomFs = 0x2, NoCrypto = 0x4, using a new keyY generator = 0x20(starting with FIRM [[9.6.0-24|9.6.0-X]]).&lt;br /&gt;
|}&lt;br /&gt;
CXIs NCCH header signature is verified using the RSA public key stored in the accessdesc,(which follows the exheader) while CFAs NCCH header is verified with a fixed RSA public key.&lt;br /&gt;
&lt;br /&gt;
==== NCCH header example for Lego Starwars III ====&lt;br /&gt;
 Signature:              720FF8F83F2A1E998322A026D1434165&lt;br /&gt;
                         ED19642ABC1CB2722135AA202BEAD60A&lt;br /&gt;
                         80BCD21C768C597B8268FEF2C64EA710&lt;br /&gt;
                         4C9BA5E12CFFBD1D0C619F4EF7B42CA7&lt;br /&gt;
                         DD8482CB4EB26720AD66CDA57ABCBCFB&lt;br /&gt;
                         D63268A6E2896A59B3B744E39E45B88A&lt;br /&gt;
                         ABB4C0980ACC6210818DCE6DAC838A10&lt;br /&gt;
                         95D0F66B352474D4B3DA4B333F49912D&lt;br /&gt;
                         29AF7EA58BC8C890B18C70B7D540A9FB&lt;br /&gt;
                         EBE24A5312055617D3353B28C3EB1D17&lt;br /&gt;
                         61021BEFF6AD22C384835B40BD44DFAD&lt;br /&gt;
                         981F6350F9458B17BCB5F768C92ABC93&lt;br /&gt;
                         2BCE9888855A8998F4CDE40C9543514A&lt;br /&gt;
                         C57B84EB75A680E7C742632614620D1D&lt;br /&gt;
                         A253284DF3DC01091EB3800C36FD62EE&lt;br /&gt;
                         BA15340F1FD498FAB67C0302E9CDA397&lt;br /&gt;
 Magic:                  NCCH&lt;br /&gt;
 Content size:           0x1cfef400&lt;br /&gt;
 Partition id:           0004000000038c00&lt;br /&gt;
 Maker code:             3436 (&amp;quot;46&amp;quot;)&lt;br /&gt;
 Version:                0002&lt;br /&gt;
 Program id:             0004000000038c00&lt;br /&gt;
 Temp flag:              00&lt;br /&gt;
 Product code:           CTR-P-ALGP&lt;br /&gt;
 Extended header hash:   0C27E3C1DE7B2AE2D3114F32A4EEBF46&lt;br /&gt;
                         9AFD0CF352C11D4984C2A9F1D2144C63&lt;br /&gt;
 Extended header size:   00000400&lt;br /&gt;
 Flags:                  0000030100000000&lt;br /&gt;
 Plain region offset:    0x00004a00&lt;br /&gt;
 Plain region size:      0x00000200&lt;br /&gt;
 ExeFS offset:           0x00004c00&lt;br /&gt;
 ExeFS size:             0x00143800&lt;br /&gt;
 ExeFS hash region size: 0x00000200&lt;br /&gt;
 RomFS offset:           0x00148400&lt;br /&gt;
 RomFS size:             0x1ceab000&lt;br /&gt;
 RomFS hash region size: 0x00000200&lt;br /&gt;
 ExeFS Superblock Hash:  130C042615F647C4C63225EA9E67F8A2&lt;br /&gt;
                         7B15246B88FBC7A927257B84977B787B&lt;br /&gt;
 RomFS Superblock Hash:  A65BEE1060BB6A6821BBCEC600035B7E&lt;br /&gt;
                         64FB6EACA7F0960CFB1F5A37087728F7&lt;br /&gt;
 Note: Offsets and sizes in media units have been converted to byte sizes.&lt;br /&gt;
&lt;br /&gt;
==== Plain region example for Lego Starwars III ====&lt;br /&gt;
 0004a00: 5b 53 44 4b 2b 4e 49 4e 54 45 4e 44 4f 3a 43 54  [SDK+NINTENDO:CT    [SDK+NINTENDO:CTR_SDK-0_14_23_200_none]&lt;br /&gt;
 0004a10: 52 5f 53 44 4b 2d 30 5f 31 34 5f 32 33 5f 32 30  R_SDK-0_14_23_20&lt;br /&gt;
 0004a20: 30 5f 6e 6f 6e 65 5d 00 5b 53 44 4b 2b 4e 49 4e  0_none].[SDK+NIN    [SDK+NINTENDO:Firmware-02_27]&lt;br /&gt;
 0004a30: 54 45 4e 44 4f 3a 46 69 72 6d 77 61 72 65 2d 30  TENDO:Firmware-0&lt;br /&gt;
 0004a40: 32 5f 32 37 5d 00 5b 53 44 4b 2b 4d 6f 62 69 63  2_27].[SDK+Mobic    [SDK+Mobiclip:Deblocker_1_0_2]&lt;br /&gt;
 0004a50: 6c 69 70 3a 44 65 62 6c 6f 63 6b 65 72 5f 31 5f  lip:Deblocker_1_&lt;br /&gt;
 0004a60: 30 5f 32 5d 00 5b 53 44 4b 2b 4d 6f 62 69 63 6c  0_2].[SDK+Mobicl    [SDK+Mobiclip:ImaAdpcmDec_1_0_0]&lt;br /&gt;
 0004a70: 69 70 3a 49 6d 61 41 64 70 63 6d 44 65 63 5f 31  ip:ImaAdpcmDec_1&lt;br /&gt;
 0004a80: 5f 30 5f 30 5d 00 5b 53 44 4b 2b 4d 6f 62 69 63  _0_0].[SDK+Mobic    [SDK+Mobiclip:MobiclipDec_1_0_1]&lt;br /&gt;
 0004a90: 6c 69 70 3a 4d 6f 62 69 63 6c 69 70 44 65 63 5f  lip:MobiclipDec_&lt;br /&gt;
 0004aa0: 31 5f 30 5f 31 5d 00 5b 53 44 4b 2b 4d 6f 62 69  1_0_1].[SDK+Mobi    [SDK+Mobiclip:MoflexDemuxer_1_0_2]&lt;br /&gt;
 0004ab0: 63 6c 69 70 3a 4d 6f 66 6c 65 78 44 65 6d 75 78  clip:MoflexDemux&lt;br /&gt;
 0004ac0: 65 72 5f 31 5f 30 5f 32 5d 00 00 00 00 00 00 00  er_1_0_2].......&lt;br /&gt;
 0004ad0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................&lt;br /&gt;
 0004ae0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................&lt;br /&gt;
&lt;br /&gt;
==== Example dependency list from the extended header ====&lt;br /&gt;
 00850 41 50 54 3A 55 00 00 00 24 68 69 6F 46 49 4F 00 APT:U...$hioFIO.&lt;br /&gt;
 00860 24 68 6F 73 74 69 6F 30 24 68 6F 73 74 69 6F 31 $hostio0$hostio1&lt;br /&gt;
 00870 61 63 3A 75 00 00 00 00 62 6F 73 73 3A 55 00 00 ac:u....boss:U..&lt;br /&gt;
 00880 63 61 6D 3A 75 00 00 00 63 65 63 64 3A 75 00 00 cam:u...cecd:u..&lt;br /&gt;
 00890 63 66 67 3A 75 00 00 00 64 6C 70 3A 46 4B 43 4C cfg:u...dlp:FKCL&lt;br /&gt;
 008A0 64 6C 70 3A 53 52 56 52 64 73 70 3A 3A 44 53 50 dlp:SRVRdsp::DSP&lt;br /&gt;
 008B0 66 72 64 3A 75 00 00 00 66 73 3A 55 53 45 52 00 frd:u...fs:USER.&lt;br /&gt;
 008C0 67 73 70 3A 3A 47 70 75 68 69 64 3A 55 53 45 52 gsp::Gpuhid:USER&lt;br /&gt;
 008D0 68 74 74 70 3A 43 00 00 6D 69 63 3A 75 00 00 00 http:C..mic:u...&lt;br /&gt;
 008E0 6E 64 6D 3A 75 00 00 00 6E 65 77 73 3A 75 00 00 ndm:u...&amp;lt;nowiki&amp;gt;news:u..&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
 008F0 6E 77 6D 3A 3A 55 44 53 70 74 6D 3A 75 00 00 00 nwm::UDSptm:u...&lt;br /&gt;
 00900 70 78 69 3A 64 65 76 00 73 6F 63 3A 55 00 00 00 pxi:dev.soc:U...&lt;br /&gt;
 00910 73 73 6C 3A 43 00 00 00 79 32 72 3A 75 00 00 00 ssl:C...y2r:u...&lt;br /&gt;
 00920 69 72 3A 55 53 45 52 00 6C 64 72 3A 72 6F 00 00 ir:USER.ldr:ro..&lt;br /&gt;
 00930 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................&lt;br /&gt;
 00940 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................&lt;br /&gt;
 00950 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................&lt;br /&gt;
 00960 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................&lt;br /&gt;
 ... ...&lt;br /&gt;
 009D0 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF                 &lt;br /&gt;
 009E0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................&lt;br /&gt;
 009F0 00 03 00 00 00 00 00 00 00 00 00 00 00 00 00 02 . .............&lt;br /&gt;
&lt;br /&gt;
== Tools ==&lt;br /&gt;
&lt;br /&gt;
[https://github.com/profi200/Project_CTR/tree/master/ctrtool ctrtool] - (CMD)(Windows/Linux) Parsing and decrypting (debug only) NCCH files&lt;/div&gt;</summary>
		<author><name>Wwylele</name></author>
	</entry>
	<entry>
		<id>https://www.3dbrew.org/w/index.php?title=ARM11_Interrupts&amp;diff=20934</id>
		<title>ARM11 Interrupts</title>
		<link rel="alternate" type="text/html" href="https://www.3dbrew.org/w/index.php?title=ARM11_Interrupts&amp;diff=20934"/>
		<updated>2019-04-29T00:13:57Z</updated>

		<summary type="html">&lt;p&gt;Wwylele: /* Hardware Interrupts */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Interrupts ==&lt;br /&gt;
&lt;br /&gt;
Interrupt priority is 0-0xF. A priority of 0xF means that the interrupt is disabled.&lt;br /&gt;
&lt;br /&gt;
= Private Interrupts =&lt;br /&gt;
&lt;br /&gt;
Each CPU core has 32 software interrupts that are private and belong to that core.  These interrupts are numbers 0-0x1F for each core.  The hardware interrupts are not core-specific and start at interrupt ID 0x20.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
!  IRQ&lt;br /&gt;
!  Listener&lt;br /&gt;
!  Description&lt;br /&gt;
|-&lt;br /&gt;
| 0&lt;br /&gt;
| &lt;br /&gt;
| MPCore software-interrupt. Not configured.&lt;br /&gt;
|-&lt;br /&gt;
| 0x1&lt;br /&gt;
| &lt;br /&gt;
| MPCore software-interrupt. Used by BOOT11 to kickstart Core1.&lt;br /&gt;
|-&lt;br /&gt;
| 0x2-0x3&lt;br /&gt;
| &lt;br /&gt;
| MPCore software-interrupt. Seem to be unused.&lt;br /&gt;
|-&lt;br /&gt;
| 0x4&lt;br /&gt;
| Kernel&lt;br /&gt;
| MPCore software-interrupt. Used to manage the performance counter.&lt;br /&gt;
|-&lt;br /&gt;
| 0x5&lt;br /&gt;
| Kernel&lt;br /&gt;
| MPCore software-interrupt. Does apparently nothing.&lt;br /&gt;
|-&lt;br /&gt;
| 0x6&lt;br /&gt;
| Kernel&lt;br /&gt;
| MPCore software-interrupt. Extensively used by [[SVC|KernelSetState]] (and contains most of the actual code of the latter).&lt;br /&gt;
|-&lt;br /&gt;
| 0x7&lt;br /&gt;
| Kernel&lt;br /&gt;
| MPCore software-interrupt. See [[KCacheMaintenanceInterruptEvent]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x8&lt;br /&gt;
| Kernel&lt;br /&gt;
| MPCore software-interrupt. Used for scheduling.&lt;br /&gt;
|-&lt;br /&gt;
| 0x9&lt;br /&gt;
| Kernel&lt;br /&gt;
| MPCore software-interrupt. Used when handling exceptions that require termination of a thread or a process, and in some cases by svcSetDebugThreadContext, to store VFP registers in the thread&#039;s register storage.&lt;br /&gt;
|-&lt;br /&gt;
| 0xA&lt;br /&gt;
| Kernel&lt;br /&gt;
| TLB operations interrupt, see [[KTLBOperationsInterruptEvent]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xB-0xE&lt;br /&gt;
|&lt;br /&gt;
| MPCore software-interrupt. Not configured.&lt;br /&gt;
|-&lt;br /&gt;
| 0xF&lt;br /&gt;
| dmnt/debugger&lt;br /&gt;
| MPCore software-interrupt. Used to abstract FIQ (debug). This interrupt is never sent to core2 nor core3 on N3DS.&lt;br /&gt;
|-&lt;br /&gt;
| 0x1D&lt;br /&gt;
| Kernel&lt;br /&gt;
| MPCore timer.&lt;br /&gt;
|-&lt;br /&gt;
| 0x1E&lt;br /&gt;
| Kernel&lt;br /&gt;
| MPCore watchdog - set when the watchdog counter reaches 0 in timer mode, causes interrupt 30 to set as pending.  Only set on core 1 as core 1&#039;s timer is used for everything.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= Hardware Interrupts =&lt;br /&gt;
&lt;br /&gt;
There are 0x60 hardware interrupts starting at 0x20 and continuing up to 0x7F.  These are not private and are accessible from any core.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
!  IRQ&lt;br /&gt;
!  Listener&lt;br /&gt;
!  Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x28&lt;br /&gt;
| gsp, TwlBg&lt;br /&gt;
| PSC0&lt;br /&gt;
|-&lt;br /&gt;
| 0x29&lt;br /&gt;
| gsp, TwlBg&lt;br /&gt;
| PSC1&lt;br /&gt;
|-&lt;br /&gt;
| 0x2A&lt;br /&gt;
| gsp, TwlBg&lt;br /&gt;
| PDC0 (VBlank0)&lt;br /&gt;
|-&lt;br /&gt;
| 0x2B&lt;br /&gt;
| gsp, TwlBg&lt;br /&gt;
| PDC1 (VBlank1)&lt;br /&gt;
|-&lt;br /&gt;
| 0x2C&lt;br /&gt;
| gsp, TwlBg&lt;br /&gt;
| PPF&lt;br /&gt;
|-&lt;br /&gt;
| 0x2D&lt;br /&gt;
| gsp, TwlBg&lt;br /&gt;
| P3D&lt;br /&gt;
|-&lt;br /&gt;
| 0x30&lt;br /&gt;
| Kernel&lt;br /&gt;
| ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x39&lt;br /&gt;
| Kernel&lt;br /&gt;
| DMA&lt;br /&gt;
|-&lt;br /&gt;
| 0x3A&lt;br /&gt;
| Kernel&lt;br /&gt;
| DMA&lt;br /&gt;
|-&lt;br /&gt;
| 0x3B&lt;br /&gt;
| Kernel&lt;br /&gt;
| DMA&lt;br /&gt;
|-&lt;br /&gt;
| 0x40&lt;br /&gt;
| nwm&lt;br /&gt;
| WIFI SDIO Controller @ 0x10122000&lt;br /&gt;
|-&lt;br /&gt;
| 0x41&lt;br /&gt;
| nwm&lt;br /&gt;
| ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x42&lt;br /&gt;
| nwm_dev?&lt;br /&gt;
| WIFI SDIO Controller @ 0x10100000&lt;br /&gt;
|-&lt;br /&gt;
| 0x45&lt;br /&gt;
| mvd (New3DS)&lt;br /&gt;
| ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x46&lt;br /&gt;
| mvd (New3DS)&lt;br /&gt;
| ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x48&lt;br /&gt;
| camera&lt;br /&gt;
| ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x49&lt;br /&gt;
| camera&lt;br /&gt;
| ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x4A&lt;br /&gt;
| dsp&lt;br /&gt;
| General interrupt from DSP, including semaphore and command/reply registers status change&lt;br /&gt;
|-&lt;br /&gt;
| 0x4B&lt;br /&gt;
| camera&lt;br /&gt;
| Y2R Conversion Finished&lt;br /&gt;
|-&lt;br /&gt;
| 0x4C&lt;br /&gt;
| TwlBg&lt;br /&gt;
| ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x4D&lt;br /&gt;
| TwlBg&lt;br /&gt;
| ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x4E&lt;br /&gt;
| mvd (New3DS)&lt;br /&gt;
| Y2R2 End Event&lt;br /&gt;
|-&lt;br /&gt;
| 0x4F&lt;br /&gt;
| mvd (New3DS)&lt;br /&gt;
| Related to mvd services&lt;br /&gt;
|-&lt;br /&gt;
| 0x50&lt;br /&gt;
| pxi, TwlBg&lt;br /&gt;
| Sync&lt;br /&gt;
|-&lt;br /&gt;
| 0x51&lt;br /&gt;
| pxi, TwlBg&lt;br /&gt;
| ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x52&lt;br /&gt;
| pxi, TwlBg&lt;br /&gt;
| Send Fifo Empty&lt;br /&gt;
|-&lt;br /&gt;
| 0x53&lt;br /&gt;
| pxi, TwlBg&lt;br /&gt;
| Receive Fifo Not Empty&lt;br /&gt;
|-&lt;br /&gt;
| 0x54&lt;br /&gt;
| i2c, TwlBg&lt;br /&gt;
| I2C Bus0 work done&lt;br /&gt;
|-&lt;br /&gt;
| 0x55&lt;br /&gt;
| i2c, TwlBg&lt;br /&gt;
| I2C Bus1 work done&lt;br /&gt;
|-&lt;br /&gt;
| 0x56&lt;br /&gt;
| spi, TwlBg&lt;br /&gt;
| ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x57&lt;br /&gt;
| spi, TwlBg&lt;br /&gt;
| SPI bus 0 transfer finished?&lt;br /&gt;
|-&lt;br /&gt;
| 0x58&lt;br /&gt;
| Kernel&lt;br /&gt;
| PDN&lt;br /&gt;
|-&lt;br /&gt;
| 0x59&lt;br /&gt;
| TwlBg&lt;br /&gt;
| ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x5A&lt;br /&gt;
| mic&lt;br /&gt;
| ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x5C&lt;br /&gt;
| i2c, TwlBg&lt;br /&gt;
| I2C Bus2 work done&lt;br /&gt;
|-&lt;br /&gt;
| 0x60&lt;br /&gt;
| gpio, TwlBg&lt;br /&gt;
| Shell opened&lt;br /&gt;
|-&lt;br /&gt;
| 0x62&lt;br /&gt;
| gpio, TwlBg&lt;br /&gt;
| Shell closed&lt;br /&gt;
|-&lt;br /&gt;
| 0x63&lt;br /&gt;
| gpio, TwlBg&lt;br /&gt;
| Touchscreen&lt;br /&gt;
|-&lt;br /&gt;
| 0x64&lt;br /&gt;
| gpio, TwlBg&lt;br /&gt;
| Headphone jack plugged in/out&lt;br /&gt;
|-&lt;br /&gt;
| 0x66&lt;br /&gt;
| gpio, TwlBg&lt;br /&gt;
| ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x68&lt;br /&gt;
| gpio, TwlBg&lt;br /&gt;
| IR&lt;br /&gt;
|-&lt;br /&gt;
| 0x69&lt;br /&gt;
| gpio, TwlBg&lt;br /&gt;
| ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x6A&lt;br /&gt;
| gpio, TwlBg&lt;br /&gt;
| ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x6B&lt;br /&gt;
| gpio, TwlBg&lt;br /&gt;
| ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x6C&lt;br /&gt;
| gpio, TwlBg&lt;br /&gt;
| ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x6D&lt;br /&gt;
| gpio, TwlBg&lt;br /&gt;
| ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x6E&lt;br /&gt;
| gpio, TwlBg&lt;br /&gt;
| ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x6F&lt;br /&gt;
| gpio, TwlBg&lt;br /&gt;
| ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x70&lt;br /&gt;
| gpio, TwlBg&lt;br /&gt;
| ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x71&lt;br /&gt;
| gpio, TwlBg&lt;br /&gt;
| MCU (HOME/POWER pressed/released or WiFi switch pressed)&lt;br /&gt;
|-&lt;br /&gt;
| 0x72&lt;br /&gt;
| gpio, TwlBg&lt;br /&gt;
| ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x73&lt;br /&gt;
| TwlBg&lt;br /&gt;
| ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x74&lt;br /&gt;
| ?&lt;br /&gt;
| Gamecard related&lt;br /&gt;
|-&lt;br /&gt;
| 0x75&lt;br /&gt;
| ?&lt;br /&gt;
| Gamecard inserted&lt;br /&gt;
|-&lt;br /&gt;
| 0x78 to 0x7B&lt;br /&gt;
| Kernel&lt;br /&gt;
| Core 0-3 Performance monitor counter (any) overflow&lt;br /&gt;
|-&lt;br /&gt;
| 0x7A to 0x82 (PDN_MPCORE_CFG bit2 set) or&lt;br /&gt;
0x7C to 0x84 (bit2 clear)&lt;br /&gt;
| Kernel&lt;br /&gt;
| ?&lt;br /&gt;
|}&lt;br /&gt;
(interrupts from 0x80 and up can&#039;t be mapped in available builds of the kernel)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
There are 2 tables in the ARM11 kernel: the first has 32 * 2(or 32 * 4) 8-byte entries.  This table is for the private interrupts that belong to each core.  The data for each interrupt can be found by doing table_base + (core_num * 0x100) + (intr_num * 8).  The second table is for public hardware interrupts and the data for each interrupt can be retrieved by doing table_base + (intr_num * 8).&lt;br /&gt;
&lt;br /&gt;
= InterruptData =&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;
!  Type&lt;br /&gt;
!  Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0&lt;br /&gt;
| [[KBaseInterruptEvent]] *&lt;br /&gt;
| Pointer to the KBaseInterruptEvent object for this interrupt &lt;br /&gt;
|-&lt;br /&gt;
| 0x4&lt;br /&gt;
| u8&lt;br /&gt;
| Interrupt will be disabled by the IRQ handler as soon as it is acknowledged.&lt;br /&gt;
Ignored for FIQ: the FIQ handler always sets bit2 of [[PDN_Registers#PDN_FIQ_CNT|PDN_FIQ_CNT]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x5&lt;br /&gt;
| u8&lt;br /&gt;
| Interrupt is disabled&lt;br /&gt;
|-&lt;br /&gt;
| 0x6&lt;br /&gt;
| u8&lt;br /&gt;
| Interrupt priority&lt;br /&gt;
|-&lt;br /&gt;
| 0x7&lt;br /&gt;
| u8&lt;br /&gt;
| Unused, alignment&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= Interrupt Table (New3DS) =&lt;br /&gt;
(0xFFF318F4 in 10.3)&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
!  Offset&lt;br /&gt;
!  Type&lt;br /&gt;
!  Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0&lt;br /&gt;
| InterruptData[224]&lt;br /&gt;
| Data for all hardware and software interrupts&lt;br /&gt;
|-&lt;br /&gt;
| 0x700&lt;br /&gt;
| [[KObjectMutex]]&lt;br /&gt;
| Mutex&lt;br /&gt;
|}&lt;/div&gt;</summary>
		<author><name>Wwylele</name></author>
	</entry>
	<entry>
		<id>https://www.3dbrew.org/w/index.php?title=CSND_Registers&amp;diff=20932</id>
		<title>CSND Registers</title>
		<link rel="alternate" type="text/html" href="https://www.3dbrew.org/w/index.php?title=CSND_Registers&amp;diff=20932"/>
		<updated>2019-04-20T23:32:58Z</updated>

		<summary type="html">&lt;p&gt;Wwylele: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=0x1EC03000=&lt;br /&gt;
?&lt;br /&gt;
&lt;br /&gt;
=0x1EC03400=&lt;br /&gt;
The channel registers are based at 0x1EC03400(process virtual address). There&#039;s 0x20-bytes total for each channel slot, thus the base-address for a channel&#039;s slot is determined with: 0x1EC03400 + (channel_index*0x20). The below offsets are relative to these channel register slots.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
!  Relative offset&lt;br /&gt;
!  Size&lt;br /&gt;
!  Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0&lt;br /&gt;
| 2&lt;br /&gt;
| REG_CSNDCHANX_CNT. For Type0 [[CSND_Shared_Memory|Cmd]] 0xE, CSND module basically writes this value here: u16 (cmdword[2] &amp;amp; 0xFFFF).&lt;br /&gt;
|-&lt;br /&gt;
| 0x2&lt;br /&gt;
| 2&lt;br /&gt;
| For Type0 [[CSND_Shared_Memory|Cmd]] 0xE, CSND module writes this value here: 0 - (cmdword[2]&amp;gt;&amp;gt;16).&lt;br /&gt;
|-&lt;br /&gt;
| 0x4&lt;br /&gt;
| 2&lt;br /&gt;
| For Type0 [[CSND_Shared_Memory|Cmd]] 0xE, CSND module writes value 0 here.&lt;br /&gt;
|-&lt;br /&gt;
| 0x6&lt;br /&gt;
| 2&lt;br /&gt;
| For Type0 [[CSND_Shared_Memory|Cmd]] 0xE, CSND module writes value 0 here.&lt;br /&gt;
|-&lt;br /&gt;
| 0x8&lt;br /&gt;
| 2&lt;br /&gt;
| For Type0 [[CSND_Shared_Memory|Cmd]] 0xE, CSND module writes this value here: (u16)cmdword[4].&lt;br /&gt;
|-&lt;br /&gt;
| 0xA&lt;br /&gt;
| 2&lt;br /&gt;
| For Type0 [[CSND_Shared_Memory|Cmd]] 0xE, CSND module writes this value here: cmdword[4]&amp;gt;&amp;gt;16.&lt;br /&gt;
|-&lt;br /&gt;
| 0xC&lt;br /&gt;
| 4&lt;br /&gt;
| This is the audio data physical address, for the main channel.&lt;br /&gt;
|-&lt;br /&gt;
| 0x10&lt;br /&gt;
| 4&lt;br /&gt;
| This is the audio data total byte-size. The CSND module masks the size loaded from the Type0 command-data with value 0x7FFFFFF, which is then used when writing these registers.&lt;br /&gt;
|-&lt;br /&gt;
| 0x14&lt;br /&gt;
| 4&lt;br /&gt;
| This is the audio data physical address, for the second channel. When this is not 0x0 stereo audio is used, otherwise mono audio is used.&lt;br /&gt;
|-&lt;br /&gt;
| 0x18&lt;br /&gt;
| 4&lt;br /&gt;
| When CSND module handles type0 Cmd 0xE with encoding!=IMA-ADPCM, CSND module sets this to zero. This register can be initialized via CSND module type0 Cmd 0xB.&lt;br /&gt;
|-&lt;br /&gt;
| 0x1C&lt;br /&gt;
| 4&lt;br /&gt;
| CSND module writes value zero here immediately after it writes to chanslotreg+0x18.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=0x1EC03800=&lt;br /&gt;
&lt;br /&gt;
There are two capture unit slot located at 0x1EC03800. Each slot has 0x10 bytes.&lt;/div&gt;</summary>
		<author><name>Wwylele</name></author>
	</entry>
	<entry>
		<id>https://www.3dbrew.org/w/index.php?title=IO_Registers&amp;diff=20927</id>
		<title>IO Registers</title>
		<link rel="alternate" type="text/html" href="https://www.3dbrew.org/w/index.php?title=IO_Registers&amp;diff=20927"/>
		<updated>2019-04-20T02:26:18Z</updated>

		<summary type="html">&lt;p&gt;Wwylele: /* Overview */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Overview =&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! Old3DS&lt;br /&gt;
! A9/A11&lt;br /&gt;
! Category&lt;br /&gt;
! Physaddr&lt;br /&gt;
! Used by&lt;br /&gt;
! Comments&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background: green&amp;quot; | Yes&lt;br /&gt;
| A9&lt;br /&gt;
| [[CONFIG9 Registers]]&lt;br /&gt;
| 0x10000000&lt;br /&gt;
| Boot9, Process9&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background: green&amp;quot; | Yes&lt;br /&gt;
| A9&lt;br /&gt;
| [[IRQ Registers]]&lt;br /&gt;
| 0x10001000&lt;br /&gt;
| Boot9, Process9, Kernel9&lt;br /&gt;
| ARM9 Interrupt Masking&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background: green&amp;quot; | Yes&lt;br /&gt;
| A9&lt;br /&gt;
| [[NDMA Registers]]&lt;br /&gt;
| 0x10002000&lt;br /&gt;
| Boot9, Process9&lt;br /&gt;
| DMA Engine&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background: green&amp;quot; | Yes&lt;br /&gt;
| A9&lt;br /&gt;
| [[TIMER Registers]]&lt;br /&gt;
| 0x10003000&lt;br /&gt;
| Boot9, Process9&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background: green&amp;quot; | Yes&lt;br /&gt;
| A9&lt;br /&gt;
| [[CTRCARD Registers]]&lt;br /&gt;
| 0x10004000 / 0x10005000&lt;br /&gt;
| Process9&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background: green&amp;quot; | Yes&lt;br /&gt;
| A9&lt;br /&gt;
| [[EMMC Registers]]&lt;br /&gt;
| 0x10006000 / 0x10007000&lt;br /&gt;
| Boot9, Process9, NewKernel9Loader&lt;br /&gt;
| 0x10007000 is normally not enabled on retail, all-zeros when read.&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background: green&amp;quot; | Yes&lt;br /&gt;
| A9&lt;br /&gt;
| [[PXI Registers]]&lt;br /&gt;
| 0x10008000&lt;br /&gt;
| Boot9, Process9&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background: green&amp;quot; | Yes&lt;br /&gt;
| A9&lt;br /&gt;
| [[AES Registers]]&lt;br /&gt;
| 0x10009000&lt;br /&gt;
| Boot9, Process9, NewKernel9Loader&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background: green&amp;quot; | Yes&lt;br /&gt;
| A9&lt;br /&gt;
| [[SHA Registers]]&lt;br /&gt;
| 0x1000A000&lt;br /&gt;
| Boot9, Process9, NewKernel9Loader&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background: green&amp;quot; | Yes&lt;br /&gt;
| A9&lt;br /&gt;
| [[RSA Registers]]&lt;br /&gt;
| 0x1000B000&lt;br /&gt;
| Boot9, Process9&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background: green&amp;quot; | Yes&lt;br /&gt;
| A9&lt;br /&gt;
| [[Corelink DMA Engines|XDMA Registers]]&lt;br /&gt;
| 0x1000C000&lt;br /&gt;
| Boot9, Kernel9&lt;br /&gt;
| [http://infocenter.arm.com/help/topic/com.arm.doc.subset.primecell.system/index.html CoreLink™ DMA-330 r0p0] (two channels).&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background: green&amp;quot; | Yes&lt;br /&gt;
| A9&lt;br /&gt;
| [[SPICARD Registers]]&lt;br /&gt;
| 0x1000D800&lt;br /&gt;
| Process9&lt;br /&gt;
|&lt;br /&gt;
|-style=&amp;quot;border-top: double&amp;quot;&lt;br /&gt;
| style=&amp;quot;background: green&amp;quot; | Yes&lt;br /&gt;
| A9&lt;br /&gt;
| [[CONFIG Registers]]&lt;br /&gt;
| 0x10010000&lt;br /&gt;
| Process9&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background: green&amp;quot; | Yes&lt;br /&gt;
| A9&lt;br /&gt;
| PRNG Registers&lt;br /&gt;
| 0x10011000&lt;br /&gt;
| Boot9, Process9&lt;br /&gt;
| Used as entropy-source for seeding random number generators.&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background: green&amp;quot; | Yes&lt;br /&gt;
| A9&lt;br /&gt;
| [[OTP Registers]]&lt;br /&gt;
| 0x10012000&lt;br /&gt;
| Boot9, Kernel9, NewKernel9Loader&lt;br /&gt;
| Top secret.&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background: green&amp;quot; | Yes&lt;br /&gt;
| A9&lt;br /&gt;
| [[ARM7|ARM7 Registers]]&lt;br /&gt;
| 0x10018000&lt;br /&gt;
| TwlProcess9&lt;br /&gt;
| Used to setup the ARM7 core for AGB/TWL&lt;br /&gt;
|-style=&amp;quot;border-top: double&amp;quot;&lt;br /&gt;
| style=&amp;quot;background: green&amp;quot; | Yes&lt;br /&gt;
| A11/A9&lt;br /&gt;
| Debug WIFI SDIO Registers?&lt;br /&gt;
| 0x10100000&lt;br /&gt;
| &lt;br /&gt;
| An SDIO controller is mapped here, NWM references this controller but doesn&#039;t have access to it.&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background: green&amp;quot; | Yes&lt;br /&gt;
| A11/A9&lt;br /&gt;
| [[HASH Registers]]&lt;br /&gt;
| 0x10101000&lt;br /&gt;
| [[Filesystem services]]&lt;br /&gt;
| These registers function the same as the [[SHA Registers]], with the exception of the FIFO being located at 0x10301000.&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background: green&amp;quot; | Yes&lt;br /&gt;
| A11/A9&lt;br /&gt;
| [[Y2R Registers]]&lt;br /&gt;
| 0x10102000&lt;br /&gt;
| [[Camera Services]]&lt;br /&gt;
| y2r&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background: green&amp;quot; | Yes&lt;br /&gt;
| A11/A9&lt;br /&gt;
| [[CSND Registers]]&lt;br /&gt;
| 0x10103000&lt;br /&gt;
| TwlBg, [[Codec Services]], [[CSND Services]], [[DSP Services]]&lt;br /&gt;
| Sound hardware.&lt;br /&gt;
|-style=&amp;quot;border-top: double&amp;quot;&lt;br /&gt;
| style=&amp;quot;background: green&amp;quot; | Yes&lt;br /&gt;
| A11/A9&lt;br /&gt;
| LGYFB0&lt;br /&gt;
| 0x10110000&lt;br /&gt;
| TwlBg&lt;br /&gt;
| IO registers used to access legacy output framebuffer, as well as configure the upscaling filter.&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background: green&amp;quot; | Yes&lt;br /&gt;
| A11/A9&lt;br /&gt;
| LGYFB1&lt;br /&gt;
| 0x10111000&lt;br /&gt;
| TwlBg&lt;br /&gt;
| IO registers used to access legacy output framebuffer, as well as configure the upscaling filter.&lt;br /&gt;
|-style=&amp;quot;border-top: double&amp;quot;&lt;br /&gt;
| style=&amp;quot;background: green&amp;quot; | Yes&lt;br /&gt;
| A11/A9&lt;br /&gt;
| [[Camera Registers]] &lt;br /&gt;
| 0x10120000&lt;br /&gt;
| [[Camera Services]]&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background: green&amp;quot; | Yes&lt;br /&gt;
| A11/A9&lt;br /&gt;
| [[Camera Registers]]&lt;br /&gt;
| 0x10121000&lt;br /&gt;
| [[Camera Services]]&lt;br /&gt;
| Mirror of 0x10120000?&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background: green&amp;quot; | Yes&lt;br /&gt;
| A11/A9&lt;br /&gt;
| [[WIFI Registers]]&lt;br /&gt;
| 0x10122000&lt;br /&gt;
| [[NWM Services]]&lt;br /&gt;
| WIFI SDIO bus registers&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background: green&amp;quot; | Yes&lt;br /&gt;
| A11/A9&lt;br /&gt;
| ?&lt;br /&gt;
| 0x10123000&lt;br /&gt;
| [[NWM Services]]&lt;br /&gt;
| WIFI?&lt;br /&gt;
|-style=&amp;quot;border-top: double&amp;quot;&lt;br /&gt;
| style=&amp;quot;background: red&amp;quot; | No&lt;br /&gt;
| A11/A9&lt;br /&gt;
| [[MVD Registers]]&lt;br /&gt;
| 0x10130000&lt;br /&gt;
| [[MVD Services]]&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background: red&amp;quot; | No&lt;br /&gt;
| A11/A9&lt;br /&gt;
| [[MVD Registers]]&lt;br /&gt;
| 0x10131000&lt;br /&gt;
| [[MVD Services]]&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background: red&amp;quot; | No&lt;br /&gt;
| A11/A9&lt;br /&gt;
| [[MVD Registers]]&lt;br /&gt;
| 0x10132000&lt;br /&gt;
| [[MVD Services]]&lt;br /&gt;
| &lt;br /&gt;
|-style=&amp;quot;border-top: double&amp;quot;&lt;br /&gt;
| style=&amp;quot;background: green&amp;quot; | Yes&lt;br /&gt;
| A11/A9&lt;br /&gt;
| [[CONFIG11 Registers]]&lt;br /&gt;
| 0x10140000&lt;br /&gt;
| Process9, Boot11, Kernel11, TwlBg, [[DSP Services]], [[NWM Services]], [[SPI Services]]&lt;br /&gt;
| Power management. &lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background: green&amp;quot; | Yes&lt;br /&gt;
| A11/A9&lt;br /&gt;
| [[CONFIG11 Registers]]&lt;br /&gt;
| 0x10141000&lt;br /&gt;
| Process9, Boot11, Kernel11, TwlBg, [[Codec Services]], [[NWM Services]], [[SPI Services]], [[PDN Services]]&lt;br /&gt;
| Power management&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background: green&amp;quot; | Yes&lt;br /&gt;
| A11/A9&lt;br /&gt;
| [[SPI Registers]]&lt;br /&gt;
| 0x10142000&lt;br /&gt;
| TwlBg, [[SPI Services]]&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background: green&amp;quot; | Yes&lt;br /&gt;
| A11/A9&lt;br /&gt;
| [[SPI Registers]]&lt;br /&gt;
| 0x10143000&lt;br /&gt;
| TwlBg, dmnt Module&lt;br /&gt;
| Debugger related?&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background: green&amp;quot; | Yes&lt;br /&gt;
| A11/A9&lt;br /&gt;
| [[I2C Registers]]&lt;br /&gt;
| 0x10144000&lt;br /&gt;
| Boot11, Kernel11, TwlBg, [[I2C Services]]&lt;br /&gt;
| 3DS I2C interface (MCU + Cameras + LCD)&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background: green&amp;quot; | Yes&lt;br /&gt;
| A11/A9&lt;br /&gt;
| [[CODEC Registers]]&lt;br /&gt;
| 0x10145000&lt;br /&gt;
| TwlBg, [[Codec Services]]&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background: green&amp;quot; | Yes&lt;br /&gt;
| A11/A9&lt;br /&gt;
| [[HID Registers]]&lt;br /&gt;
| 0x10146000&lt;br /&gt;
| Boot9, Boot11, Kernel11, TwlBg, [[HID Services]], dlp Services&lt;br /&gt;
| See [[PAD]].&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background: green&amp;quot; | Yes&lt;br /&gt;
| A11/A9&lt;br /&gt;
| [[GPIO Registers]]&lt;br /&gt;
| 0x10147000&lt;br /&gt;
| Boot11, TwlBg, [[GPIO Services]], [[DSP Services]](v0)&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| style=&amp;quot;background: green&amp;quot; | Yes&lt;br /&gt;
| A11/A9&lt;br /&gt;
| [[I2C Registers]]&lt;br /&gt;
| 0x10148000&lt;br /&gt;
| TwlBg, [[I2C Services]]&lt;br /&gt;
| 3DS I2C interface (Gyro + IR)&lt;br /&gt;
|-style=&amp;quot;border-top: double&amp;quot;&lt;br /&gt;
| style=&amp;quot;background: green&amp;quot; | Yes&lt;br /&gt;
| A11/A9&lt;br /&gt;
| [[SPI Registers]]&lt;br /&gt;
| 0x10160000&lt;br /&gt;
| Boot9, TwlBg, [[SPI Services]]&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background: green&amp;quot; | Yes&lt;br /&gt;
| A11/A9&lt;br /&gt;
| [[I2C Registers]]&lt;br /&gt;
| 0x10161000&lt;br /&gt;
| Boot11, TwlBg, [[I2C Services]]&lt;br /&gt;
| TWL I2C interface (MCU + Cameras)&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background: green&amp;quot; | Yes&lt;br /&gt;
| A11/A9&lt;br /&gt;
| [[MIC Registers]]&lt;br /&gt;
| 0x10162000&lt;br /&gt;
| [[MIC Services]]&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background: green&amp;quot; | Yes&lt;br /&gt;
| A11/A9&lt;br /&gt;
| [[PXI Registers]]&lt;br /&gt;
| 0x10163000&lt;br /&gt;
| Boot11, Kernel11, TwlBg, [[PXI Services]]&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background: green&amp;quot; | Yes&lt;br /&gt;
| A11/A9&lt;br /&gt;
| [[NTRCARD Registers]]&lt;br /&gt;
| 0x10164000&lt;br /&gt;
| Boot9, Process9&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background: green&amp;quot; | Yes&lt;br /&gt;
| A11/A9&lt;br /&gt;
| [[MP Registers]]&lt;br /&gt;
| 0x10165000&lt;br /&gt;
| [[MP Services]]&lt;br /&gt;
|&lt;br /&gt;
|-style=&amp;quot;border-top: double&amp;quot;&lt;br /&gt;
| style=&amp;quot;background: green&amp;quot; | Yes&lt;br /&gt;
| A11/A9&lt;br /&gt;
|  [[MP Registers]]&lt;br /&gt;
| 0x10170000&lt;br /&gt;
| [[MP Services]]&lt;br /&gt;
| NTR WIFI Registers, see [http://problemkaputt.de/gbatek.htm#dswirelesscommunications GBATek].&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background: green&amp;quot; | Yes&lt;br /&gt;
| A11/A9&lt;br /&gt;
|  [[MP Registers]]&lt;br /&gt;
| 0x10171000&lt;br /&gt;
| [[MP Services]]&lt;br /&gt;
| NTR WIFI Registers (mirror)&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background: green&amp;quot; | Yes&lt;br /&gt;
| A11/A9&lt;br /&gt;
|?&lt;br /&gt;
| 0x10172000&lt;br /&gt;
|?&lt;br /&gt;
| NTR WIFI Unused?&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background: green&amp;quot; | Yes&lt;br /&gt;
| A11/A9&lt;br /&gt;
|?&lt;br /&gt;
| 0x10173000&lt;br /&gt;
|?&lt;br /&gt;
| NTR WIFI Unused?&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background: green&amp;quot; | Yes&lt;br /&gt;
| A11/A9&lt;br /&gt;
| [[MP Registers]]&lt;br /&gt;
| 0x10174000&lt;br /&gt;
| [[MP Services]]&lt;br /&gt;
| NTR WIFI RAM&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background: green&amp;quot; | Yes&lt;br /&gt;
| A11/A9&lt;br /&gt;
| [[MP Registers]]&lt;br /&gt;
| 0x10175000&lt;br /&gt;
|?&lt;br /&gt;
| NTR WIFI RAM&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background: green&amp;quot; | Yes&lt;br /&gt;
| A11/A9&lt;br /&gt;
|  [[MP Registers]]&lt;br /&gt;
| 0x10176000&lt;br /&gt;
|?&lt;br /&gt;
| NTR WIFI Registers (mirror)&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background: green&amp;quot; | Yes&lt;br /&gt;
| A11/A9&lt;br /&gt;
|  [[MP Registers]]&lt;br /&gt;
| 0x10177000&lt;br /&gt;
|?&lt;br /&gt;
| NTR WIFI Registers (mirror)&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background: green&amp;quot; | Yes&lt;br /&gt;
| A11/A9&lt;br /&gt;
| [[MP Registers]]&lt;br /&gt;
| 0x10178000 - 0x10180000&lt;br /&gt;
| [[MP Services]]&lt;br /&gt;
| NTR WIFI WS1 Region&lt;br /&gt;
|-style=&amp;quot;border-top: double&amp;quot;&lt;br /&gt;
| style=&amp;quot;background: green&amp;quot; | Yes&lt;br /&gt;
| A11&lt;br /&gt;
| [[Corelink DMA Engines|CDMA]]&lt;br /&gt;
| 0x10200000&lt;br /&gt;
| Boot11, Kernel11&lt;br /&gt;
| [http://infocenter.arm.com/help/topic/com.arm.doc.subset.primecell.system/index.html CoreLink™ DMA-330 r0p0] (eight channels). Only used by bootrom on New3DS.&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background: green&amp;quot; | Yes&lt;br /&gt;
| A11&lt;br /&gt;
| ?&lt;br /&gt;
| 0x10201000&lt;br /&gt;
| TwlBg&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background: green&amp;quot; | Yes&lt;br /&gt;
| A11&lt;br /&gt;
| [[LCD Registers]]&lt;br /&gt;
| 0x10202000&lt;br /&gt;
| TwlBg, Kernel11, [[GSP Services]]&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background: green&amp;quot; | Yes&lt;br /&gt;
| A11&lt;br /&gt;
| [[DSP Registers]]&lt;br /&gt;
| 0x10203000&lt;br /&gt;
| [[DSP Services]]&lt;br /&gt;
| see the &amp;quot;DSi XpertTeak&amp;quot; section in [http://problemkaputt.de/gba.htm no$gba] help.&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background: green&amp;quot; | Yes&lt;br /&gt;
| A11&lt;br /&gt;
| &lt;br /&gt;
| 0x10204000&lt;br /&gt;
| &lt;br /&gt;
|&lt;br /&gt;
|-style=&amp;quot;border-top: double&amp;quot;&lt;br /&gt;
|  style=&amp;quot;background: red&amp;quot; | No&lt;br /&gt;
| A11&lt;br /&gt;
| [[Corelink DMA Engines|CDMA]]&lt;br /&gt;
| 0x10206000&lt;br /&gt;
| NewKernel11&lt;br /&gt;
| [http://infocenter.arm.com/help/topic/com.arm.doc.ddi0424d/index.html CoreLink™ DMA-330 r1p2] (eight channels). This is the DMA engine actually being used by the New3DS ARM11 kernel.&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background: red&amp;quot; | No&lt;br /&gt;
| A11&lt;br /&gt;
| [[MVD Registers]]&lt;br /&gt;
| 0x10207000&lt;br /&gt;
| [[MVD Services]]&lt;br /&gt;
| New 3DS only?&lt;br /&gt;
|-style=&amp;quot;border-top: double&amp;quot;&lt;br /&gt;
| style=&amp;quot;background: green&amp;quot; | Yes&lt;br /&gt;
| A11&lt;br /&gt;
| AXI&lt;br /&gt;
| 0x1020F000&lt;br /&gt;
| TwlBg, [[GSP Services]]&lt;br /&gt;
| [http://infocenter.arm.com/help/topic/com.arm.doc.ddi0422a/CHDGHIID.html CoreLink™ NIC-301 r1p0].&lt;br /&gt;
|-style=&amp;quot;border-top: double&amp;quot;&lt;br /&gt;
| style=&amp;quot;background: green&amp;quot; | Yes&lt;br /&gt;
| A11&lt;br /&gt;
| DMA region&lt;br /&gt;
| 0x10300000-0x10400000&lt;br /&gt;
|&lt;br /&gt;
| CDMA wants these addresses. Most pages in this region correspond to the same respective pages in the 0x10100000-0x10200000 region. The HASH FIFO register is located at 0x10301000 only.&lt;br /&gt;
|-style=&amp;quot;border-top: double&amp;quot;&lt;br /&gt;
| style=&amp;quot;background: green&amp;quot; | Yes&lt;br /&gt;
| A11&lt;br /&gt;
| [[GPU/External_Registers|GPU Registers]]&lt;br /&gt;
| 0x10400000&lt;br /&gt;
| Boot11, Kernel11, [[GSP Services]]&lt;br /&gt;
||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
IO registers starting at physical address 0x10200000 are not accessible from the ARM9 (which includes all LCD/GPU registers). It seems IO registers below physical address 0x10100000 are not accessible from the ARM11 bus.&lt;br /&gt;
&lt;br /&gt;
ARM11 kernel virtual address mappings for these registers varies for different builds. For ARM11 user mode applications you have:&lt;br /&gt;
 physaddr = virtaddr - 0x1EC00000 + 0x10100000&lt;/div&gt;</summary>
		<author><name>Wwylele</name></author>
	</entry>
	<entry>
		<id>https://www.3dbrew.org/w/index.php?title=CSND_Registers&amp;diff=20926</id>
		<title>CSND Registers</title>
		<link rel="alternate" type="text/html" href="https://www.3dbrew.org/w/index.php?title=CSND_Registers&amp;diff=20926"/>
		<updated>2019-04-20T02:24:38Z</updated>

		<summary type="html">&lt;p&gt;Wwylele: /* 0x1EC03000 */ No, these are not DSP registers, which are located at 1ED03000 (100000 bytes off). RE of CSND command 0x200 also shows that this region has different layout than DSP registers. DSP reigsters are all 2-bytes, while command 0x200 writes 1/4&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=0x1EC03000=&lt;br /&gt;
?&lt;br /&gt;
&lt;br /&gt;
=0x1EC03400=&lt;br /&gt;
The channel registers are based at 0x1EC03400(process virtual address). There&#039;s 0x20-bytes total for each channel slot, thus the base-address for a channel&#039;s slot is determined with: 0x1EC03400 + (channel_index*0x20). The below offsets are relative to these channel register slots.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
!  Relative offset&lt;br /&gt;
!  Size&lt;br /&gt;
!  Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x0&lt;br /&gt;
| 2&lt;br /&gt;
| REG_CSNDCHANX_CNT. For Type0 [[CSND_Shared_Memory|Cmd]] 0xE, CSND module basically writes this value here: u16 (cmdword[2] &amp;amp; 0xFFFF).&lt;br /&gt;
|-&lt;br /&gt;
| 0x2&lt;br /&gt;
| 2&lt;br /&gt;
| For Type0 [[CSND_Shared_Memory|Cmd]] 0xE, CSND module writes this value here: 0 - (cmdword[2]&amp;gt;&amp;gt;16).&lt;br /&gt;
|-&lt;br /&gt;
| 0x4&lt;br /&gt;
| 2&lt;br /&gt;
| For Type0 [[CSND_Shared_Memory|Cmd]] 0xE, CSND module writes value 0 here.&lt;br /&gt;
|-&lt;br /&gt;
| 0x6&lt;br /&gt;
| 2&lt;br /&gt;
| For Type0 [[CSND_Shared_Memory|Cmd]] 0xE, CSND module writes value 0 here.&lt;br /&gt;
|-&lt;br /&gt;
| 0x8&lt;br /&gt;
| 2&lt;br /&gt;
| For Type0 [[CSND_Shared_Memory|Cmd]] 0xE, CSND module writes this value here: (u16)cmdword[4].&lt;br /&gt;
|-&lt;br /&gt;
| 0xA&lt;br /&gt;
| 2&lt;br /&gt;
| For Type0 [[CSND_Shared_Memory|Cmd]] 0xE, CSND module writes this value here: cmdword[4]&amp;gt;&amp;gt;16.&lt;br /&gt;
|-&lt;br /&gt;
| 0xC&lt;br /&gt;
| 4&lt;br /&gt;
| This is the audio data physical address, for the main channel.&lt;br /&gt;
|-&lt;br /&gt;
| 0x10&lt;br /&gt;
| 4&lt;br /&gt;
| This is the audio data total byte-size. The CSND module masks the size loaded from the Type0 command-data with value 0x7FFFFFF, which is then used when writing these registers.&lt;br /&gt;
|-&lt;br /&gt;
| 0x14&lt;br /&gt;
| 4&lt;br /&gt;
| This is the audio data physical address, for the second channel. When this is not 0x0 stereo audio is used, otherwise mono audio is used.&lt;br /&gt;
|-&lt;br /&gt;
| 0x18&lt;br /&gt;
| 4&lt;br /&gt;
| When CSND module handles type0 Cmd 0xE with encoding!=IMA-ADPCM, CSND module sets this to zero. This register can be initialized via CSND module type0 Cmd 0xB.&lt;br /&gt;
|-&lt;br /&gt;
| 0x1C&lt;br /&gt;
| 4&lt;br /&gt;
| CSND module writes value zero here immediately after it writes to chanslotreg+0x18.&lt;br /&gt;
|}&lt;/div&gt;</summary>
		<author><name>Wwylele</name></author>
	</entry>
	<entry>
		<id>https://www.3dbrew.org/w/index.php?title=Extdata&amp;diff=20911</id>
		<title>Extdata</title>
		<link rel="alternate" type="text/html" href="https://www.3dbrew.org/w/index.php?title=Extdata&amp;diff=20911"/>
		<updated>2019-04-03T19:14:25Z</updated>

		<summary type="html">&lt;p&gt;Wwylele: /* VSXE Header */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This page describes the format and encryption of extdata, &amp;amp;quot;extra data&amp;amp;quot; stored on SD card and NAND, at:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;nand/data/&amp;amp;lt;ID&amp;amp;gt;/extdata/&amp;amp;lt;ExtdataID-High&amp;amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;sdmc/Nintendo 3DS/&amp;amp;lt;ID0&amp;amp;gt;/&amp;amp;lt;ID1&amp;amp;gt;/extdata/&amp;amp;lt;ExtdataID-High&amp;amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
ExtdataID-High is always 00000000 for SD, and always 00048000 for NAND. Regular apps can only mount SD extdata using the same extdataID which is stored in the CXI exheader. Therefore, regular apps which have the exheader extdataID set to zero can&#039;t use extdata. This restriction doesn&#039;t apply for shared extdata with extdataID high bitmask 0x48000 stored on NAND. System apps with a certain access right can mount arbitrary extdata. All NAND extdata is shared extdata, while all SD extdata is normal extdata.&lt;br /&gt;
&lt;br /&gt;
All data in this page is little-endian. All &amp;amp;quot;unused / padding&amp;amp;quot; fields can contain uninitialized data unless otherwise specified.&lt;br /&gt;
&lt;br /&gt;
= Format =&lt;br /&gt;
&lt;br /&gt;
To avoid confusion, the terms &#039;&#039;&#039;device directory / file&#039;&#039;&#039; and &#039;&#039;&#039;virtual directory / file&#039;&#039;&#039; are used with the following meanings:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Device directory / file&#039;&#039;&#039; are the real directory / file stored on SD / NAND that can be seen under path &amp;lt;code&amp;gt;nand/data/&amp;amp;lt;ID&amp;amp;gt;/extdata/&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;sdmc/Nintendo 3DS/&amp;amp;lt;ID0&amp;amp;gt;/&amp;amp;lt;ID1&amp;amp;gt;/extdata/&amp;lt;/code&amp;gt;.&lt;br /&gt;
* &#039;&#039;&#039;Virtual directory / file&#039;&#039;&#039; are directory / file stored inside extdata virtual file system, which can be seen by applications in the mounted extdata archives.&lt;br /&gt;
&lt;br /&gt;
An extdata consists of several device directories and files, which forms a file system consisting of multiple virtual directories and files.&lt;br /&gt;
&lt;br /&gt;
An extdata with ID &amp;lt;code&amp;gt;ExtdataId&amp;lt;/code&amp;gt; has the following device files:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;.../extdata/&amp;amp;lt;ExtdataID-High&amp;amp;gt;/&amp;amp;lt;ExtdataId-Low&amp;amp;gt;/Quota.dat&amp;lt;/code&amp;gt; (optional)&lt;br /&gt;
* &amp;lt;code&amp;gt;.../extdata/&amp;amp;lt;ExtdataID-High&amp;amp;gt;/&amp;amp;lt;ExtdataId-Low&amp;amp;gt;/&amp;amp;lt;SubDirID&amp;amp;gt;/&amp;amp;lt;SubFileID&amp;amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note:&lt;br /&gt;
&lt;br /&gt;
* All device files are [[DISA and DIFF|DIFF containers]]. &#039;&#039;&#039;All format description below is about the inner content of the containers&#039;&#039;&#039;. Please unwrap these files first according to the DIFF format description before reading them using the extdata format description below.&lt;br /&gt;
* &amp;lt;code&amp;gt;Quota.dat&amp;lt;/code&amp;gt; is only observed existing for NAND shared extdata.&lt;br /&gt;
* &amp;lt;code&amp;gt;&amp;amp;lt;SubDirID&amp;amp;gt;&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;&amp;amp;lt;SubFileID&amp;amp;gt;&amp;lt;/code&amp;gt; are 8-digit hex strings.&lt;br /&gt;
* Device file with &amp;lt;code&amp;gt;SubDirID = SubFileID = 00000000&amp;lt;/code&amp;gt; doesn&#039;t exist. Other ID combinations can exists.&lt;br /&gt;
* Device file with &amp;lt;code&amp;gt;SubDirID = 00000000&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;SubFileID = 00000001&amp;lt;/code&amp;gt; is the VSXE metadata file and must exist.&lt;br /&gt;
* Other files, besides &amp;lt;code&amp;gt;Quota.dat&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;00000000/00000001&amp;lt;/code&amp;gt;, are normal sub files, are these device files one-to-one correspond to virtual files. They contain raw virtual file data in the DIFF inner content.&lt;br /&gt;
* &amp;lt;code&amp;gt;SubDirID = 00000000&amp;lt;/code&amp;gt; is usually the only one device directory that can be seen. See [[#Device Directory Capacity]] for more information.&lt;br /&gt;
&lt;br /&gt;
== Quota File ==&lt;br /&gt;
&lt;br /&gt;
The inner data of &amp;lt;code&amp;gt;Quota.dat&amp;lt;/code&amp;gt; is 0x48 bytes with the following format. The exact function of this file is unclear.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! Offset&lt;br /&gt;
! Length&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x00&lt;br /&gt;
| 4&lt;br /&gt;
| Magic &amp;amp;quot;QUOT&amp;amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| 0x04&lt;br /&gt;
| 4&lt;br /&gt;
| Magic 0x30000&lt;br /&gt;
|-&lt;br /&gt;
| 0x08&lt;br /&gt;
| 4&lt;br /&gt;
| 0x1000, block size?&lt;br /&gt;
|-&lt;br /&gt;
| 0x0C&lt;br /&gt;
| 4&lt;br /&gt;
| Always 126. Probably device directory capacity. See the [[#Device Directory Capacity]] more information.&lt;br /&gt;
|-&lt;br /&gt;
| ...&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
| The meaning of other fields is unknown&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Device Directory Capacity ==&lt;br /&gt;
&lt;br /&gt;
A device directory in an extdata (a &amp;lt;code&amp;gt;&amp;amp;lt;SubDirID&amp;amp;gt;&amp;lt;/code&amp;gt; directory) seems to have a maximum number of device files it can contain. For SD extdata, this maximum number seems to be hard-coded as 126. For NAND extdata, the number is probably indicated by a field in Quota.dat, which is, again, always 126 as observed. 3DS FS tries to put all device files in the device directory &amp;lt;code&amp;gt;00000000&amp;lt;/code&amp;gt; if possible, and only when more than 126 files needed to add, a second device directory &amp;lt;code&amp;gt;00000001&amp;lt;/code&amp;gt; and so on are created. However, few extdata have such amount of files to store, so the behavior lacks of use cases to confirm.&lt;br /&gt;
&lt;br /&gt;
The number 126 is probably from some kind of other capacity of 128 with &amp;lt;code&amp;gt;&amp;amp;quot;.&amp;amp;quot;&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;&amp;amp;quot;..&amp;amp;quot;&amp;lt;/code&amp;gt; entries reserved. It is theorized that this is to keep a FAT directory table, with 0x20 bytes for each entry, in one 0x1000 cluster. The motivation is unclear.&lt;br /&gt;
&lt;br /&gt;
== VSXE File System Metadata ==&lt;br /&gt;
&lt;br /&gt;
The inner data of &amp;lt;code&amp;gt;00000000/00000001&amp;lt;/code&amp;gt; consists of the following components&lt;br /&gt;
&lt;br /&gt;
* VSXE header&lt;br /&gt;
* Directory Hash Table&lt;br /&gt;
* File Hash Table&lt;br /&gt;
* File Allocation Table&lt;br /&gt;
* Data region&lt;br /&gt;
** Directory Entry Table&lt;br /&gt;
** File Entry Table&lt;br /&gt;
&lt;br /&gt;
=== VSXE Header ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! Offset&lt;br /&gt;
! Length&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x00&lt;br /&gt;
| 4&lt;br /&gt;
| Magic &amp;amp;quot;VSXE&amp;amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| 0x04&lt;br /&gt;
| 4&lt;br /&gt;
| Magic 0x30000&lt;br /&gt;
|-&lt;br /&gt;
| 0x08&lt;br /&gt;
| 8&lt;br /&gt;
| File system Information offset (0x138)&lt;br /&gt;
|-&lt;br /&gt;
| 0x10&lt;br /&gt;
| 8&lt;br /&gt;
| Image size in blocks&lt;br /&gt;
|-&lt;br /&gt;
| 0x18&lt;br /&gt;
| 4&lt;br /&gt;
| Image block size&lt;br /&gt;
|-&lt;br /&gt;
| 0x1C&lt;br /&gt;
| 4&lt;br /&gt;
| Padding&lt;br /&gt;
|-&lt;br /&gt;
| 0x20&lt;br /&gt;
| 8&lt;br /&gt;
| Unknown&lt;br /&gt;
|-&lt;br /&gt;
| 0x28&lt;br /&gt;
| 4&lt;br /&gt;
| &#039;Action&#039; made on most recently mounted Extdata image&lt;br /&gt;
|-&lt;br /&gt;
| 0x2C&lt;br /&gt;
| 4&lt;br /&gt;
| Unknown&lt;br /&gt;
|-&lt;br /&gt;
| 0x30&lt;br /&gt;
| 4&lt;br /&gt;
| D of most recently mounted Extdata image&lt;br /&gt;
|-&lt;br /&gt;
| 0x34&lt;br /&gt;
| 4&lt;br /&gt;
| Unknown&lt;br /&gt;
|-&lt;br /&gt;
| 0x38&lt;br /&gt;
| 0x100&lt;br /&gt;
| Mount path, from most recently mounted Extdata image&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
| Below is File system Information, which is assumed following the same layout as [[Savegames#SAVE_Header]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x138&lt;br /&gt;
| 4&lt;br /&gt;
| Unknown&lt;br /&gt;
|-&lt;br /&gt;
| 0x13C&lt;br /&gt;
| 4&lt;br /&gt;
| Data region block size&lt;br /&gt;
|-&lt;br /&gt;
| 0x140&lt;br /&gt;
| 8&lt;br /&gt;
| Directory hash table offset&lt;br /&gt;
|-&lt;br /&gt;
| 0x148&lt;br /&gt;
| 4&lt;br /&gt;
| Directory hash table bucket count&lt;br /&gt;
|-&lt;br /&gt;
| 0x14C&lt;br /&gt;
| 4&lt;br /&gt;
| Padding&lt;br /&gt;
|-&lt;br /&gt;
| 0x150&lt;br /&gt;
| 8&lt;br /&gt;
| File hash table offset&lt;br /&gt;
|-&lt;br /&gt;
| 0x158&lt;br /&gt;
| 4&lt;br /&gt;
| File hash table bucket count&lt;br /&gt;
|-&lt;br /&gt;
| 0x15C&lt;br /&gt;
| 4&lt;br /&gt;
| Padding&lt;br /&gt;
|-&lt;br /&gt;
| 0x160&lt;br /&gt;
| 8&lt;br /&gt;
| File allocation table offset&lt;br /&gt;
|-&lt;br /&gt;
| 0x168&lt;br /&gt;
| 4&lt;br /&gt;
| File allocation table entry count&lt;br /&gt;
|-&lt;br /&gt;
| 0x16C&lt;br /&gt;
| 4&lt;br /&gt;
| Padding&lt;br /&gt;
|-&lt;br /&gt;
| 0x170&lt;br /&gt;
| 8&lt;br /&gt;
| Data region offset&lt;br /&gt;
|-&lt;br /&gt;
| 0x178&lt;br /&gt;
| 4&lt;br /&gt;
| Data region block count (= File allocation table entry count)&lt;br /&gt;
|-&lt;br /&gt;
| 0x17C&lt;br /&gt;
| 4&lt;br /&gt;
| Padding&lt;br /&gt;
|-&lt;br /&gt;
| 0x180&lt;br /&gt;
| 4&lt;br /&gt;
| Directory entry table starting block&lt;br /&gt;
|-&lt;br /&gt;
| 0x184&lt;br /&gt;
| 4&lt;br /&gt;
| Directory entry table block count&lt;br /&gt;
|-&lt;br /&gt;
| 0x188&lt;br /&gt;
| 4&lt;br /&gt;
| Maximum directory count&lt;br /&gt;
|-&lt;br /&gt;
| 0x18C&lt;br /&gt;
| 4&lt;br /&gt;
| Padding&lt;br /&gt;
|-&lt;br /&gt;
| 0x190&lt;br /&gt;
| 4&lt;br /&gt;
| File entry table starting block&lt;br /&gt;
|-&lt;br /&gt;
| 0x194&lt;br /&gt;
| 4&lt;br /&gt;
| File entry table block count&lt;br /&gt;
|-&lt;br /&gt;
| 0x198&lt;br /&gt;
| 4&lt;br /&gt;
| Maximum file count&lt;br /&gt;
|-&lt;br /&gt;
| 0x19C&lt;br /&gt;
| 4&lt;br /&gt;
| Padding&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
* All &amp;amp;quot;offsets&amp;amp;quot; are relative to the beginning of VSXE image. All &amp;amp;quot;starting block index&amp;amp;quot; are relative to the beginning of data region.&lt;br /&gt;
&lt;br /&gt;
=== File Allocation Table &amp;amp;amp; Data Region ===&lt;br /&gt;
&lt;br /&gt;
These function in the same way as [[Savegames#File Allocation Table|the file allocation in savegames]]. However, the only two &amp;amp;quot;files&amp;amp;quot; allocated in the data region are the directory entry table and file entry table, so the data region is usually pretty small, and the file allocation table is unchanged once created and has no free blocks. Thus, the offset and size of directory / file entry table can be found directly by &amp;lt;code&amp;gt;offset = entry_table_starting block * data_region_block_size + data_region_offset&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;size = entry_table_block_count * data_region_block_size&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Directory Hash Table &amp;amp;amp; File Hash Table ===&lt;br /&gt;
&lt;br /&gt;
These function in the same way as [[Savegames#Directory Hash Table &amp;amp;amp; File Hash Table|those in savegames]]&lt;br /&gt;
&lt;br /&gt;
=== Directory Entry Table ===&lt;br /&gt;
&lt;br /&gt;
This functions in the same way as [[Savegames#Directory Entry Table|the one in savegames]]. It lists all virtual directories in this extdata.&lt;br /&gt;
&lt;br /&gt;
=== File Entry Table ===&lt;br /&gt;
&lt;br /&gt;
This functions in a similar way as [[Savegames#File Entry Table|the one in savegames]]. It lists all virtual files in this extdata. However, the format of a (non-dummy) file entry is a little bit modified:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! Offset&lt;br /&gt;
! Length&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x00&lt;br /&gt;
| 4&lt;br /&gt;
| Parent directory index in directory entry table&lt;br /&gt;
|-&lt;br /&gt;
| 0x04&lt;br /&gt;
| 16&lt;br /&gt;
| ASCII file name&lt;br /&gt;
|-&lt;br /&gt;
| 0x14&lt;br /&gt;
| 4&lt;br /&gt;
| Next sibling file index. 0 if this is the last one&lt;br /&gt;
|-&lt;br /&gt;
| 0x18&lt;br /&gt;
| 4&lt;br /&gt;
| Padding&lt;br /&gt;
|-&lt;br /&gt;
| 0x1C&lt;br /&gt;
| 4&lt;br /&gt;
| &amp;lt;s&amp;gt;First block index in data region&amp;lt;/s&amp;gt; &#039;&#039;&#039;Always 0x80000000 because unused&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| 0x20&lt;br /&gt;
| 8&lt;br /&gt;
| &amp;lt;s&amp;gt;File size&amp;lt;/s&amp;gt; &#039;&#039;&#039;Unique identifier&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| 0x28&lt;br /&gt;
| 4&lt;br /&gt;
| Padding?&lt;br /&gt;
|-&lt;br /&gt;
| 0x2C&lt;br /&gt;
| 4&lt;br /&gt;
| Index of the next file in the same hash table bucket. 0 if this is the last one&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Each non-dummy file entry corresponds to a device file. The path to the device file is generated by the following computation:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;// See previous section about this capacity&lt;br /&gt;
const uint32_t device_dir_capacity = 126;&lt;br /&gt;
&lt;br /&gt;
// entry index is the index in the file entry table, with the first dummy entry as&lt;br /&gt;
// index = 0, which is never used for a real file.&lt;br /&gt;
// file_index = 1 is reserved for the VSXE Filesystem Metadata itself, so real files&lt;br /&gt;
// started from file_index = 2.&lt;br /&gt;
uint32_t file_index = entry_index + 1;&lt;br /&gt;
&lt;br /&gt;
uint32_t SubDirID = file_index / device_dir_capacity;&lt;br /&gt;
uint32_t SubFileID = file_index % pdevice_dir_capacity;&lt;br /&gt;
&lt;br /&gt;
char extdata_path[...]; // &amp;amp;quot;.../extdata/&amp;amp;lt;ExtdataID-High&amp;amp;gt;/&amp;amp;lt;ExtdataId-Low&amp;amp;gt;&amp;amp;quot;&lt;br /&gt;
char device_path[...]; // output path&lt;br /&gt;
sprintf(device_path, &amp;amp;quot;%s/%08x/%08x&amp;amp;quot;, extdata_path, SubDirID, SubFileID);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
When mounting extdata, the unique identifier is used to match the ID stored in subfile&#039;s [[DISA and DIFF#DIFF header|DIFF header]]. If the ID doesn&#039;t match, mounting will fail.&lt;br /&gt;
&lt;br /&gt;
== Virtual File System Structure ==&lt;br /&gt;
&lt;br /&gt;
When extdata is created, these are &#039;&#039;always&#039;&#039; created regardless of whether the title actually uses them.&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;/icon&amp;lt;/code&amp;gt; This virtual file contains the extdata icon displayed in data management. This icon can only be written to by titles when creating extdata, titles would have to recreate extdata to change the icon. This file can&#039;t be read directly, instead it is read via FS:ReadExtSaveDataIcon.&lt;br /&gt;
* &amp;lt;code&amp;gt;/user/&amp;lt;/code&amp;gt; This virtual directory contains the title&#039;s actual extdata files.&lt;br /&gt;
* &amp;lt;code&amp;gt;/boss/&amp;lt;/code&amp;gt; This virtual directory can contain SpotPass content. SpotPass content can only be downloaded to this &amp;lt;code&amp;gt;/boss&amp;lt;/code&amp;gt; virtual directory.&lt;br /&gt;
&lt;br /&gt;
User extdata and SpotPass extdata use separate mount points at &amp;lt;code&amp;gt;/user&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;/boss&amp;lt;/code&amp;gt;. Therefore one mount can&#039;t access the other virtual directory, and also can&#039;t access &amp;lt;code&amp;gt;/icon&amp;lt;/code&amp;gt;.(The title&#039;s SpotPass extdata can be mounted by the title itself, if it uses SpotPass)&lt;br /&gt;
&lt;br /&gt;
Other optional but notable directories include:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;/user/ExBanner&amp;lt;/code&amp;gt; This virtual directory can optionally store extended banners. When this is available, this banner is displayed instead of the CXI ExeFS banner. &amp;lt;code&amp;gt;COMMON.bin&amp;lt;/code&amp;gt; stores the common exbanner, while &amp;lt;code&amp;gt;&amp;amp;lt;regionlang_code&amp;amp;gt;.bin&amp;lt;/code&amp;gt; stores an optional separate region/language specific banner.(regionlang_code can be &amp;amp;quot;JPN_JP&amp;amp;quot;, &amp;amp;quot;USA_EN&amp;amp;quot;, etc)&lt;br /&gt;
&lt;br /&gt;
== SD Extdata ==&lt;br /&gt;
Usually the ExtdataID low is in the format &#039;00&amp;lt;Unique ID&amp;gt;&#039;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! JPN ExtdataID&lt;br /&gt;
! USA ExtdataID&lt;br /&gt;
! EUR ExtdataID&lt;br /&gt;
! Description&lt;br /&gt;
! Extdata images&lt;br /&gt;
|-&lt;br /&gt;
| 00000082&lt;br /&gt;
| 0000008f&lt;br /&gt;
| 00000098&lt;br /&gt;
| [[Home Menu]] extdata, this contains home-menu savedata and cached icons for applications.&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| 00000200&lt;br /&gt;
| 00000210&lt;br /&gt;
| 00000220&lt;br /&gt;
| [[System_Settings|System Settings]] extdata added with [[2.0.0-2]].&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| 00000207&lt;br /&gt;
| 00000217&lt;br /&gt;
| 00000227&lt;br /&gt;
| [[Mii Maker]], contains an ExBanner&lt;br /&gt;
| [https://dl.dropbox.com/u/20520664/extdata00000217.zip cleartext]&lt;br /&gt;
|-&lt;br /&gt;
| 00000208&lt;br /&gt;
| 00000218&lt;br /&gt;
| 00000228&lt;br /&gt;
| Streetpass Mii Plaza&lt;br /&gt;
| 11 mb big!&lt;br /&gt;
|-&lt;br /&gt;
| 00000209&lt;br /&gt;
| 00000219&lt;br /&gt;
| 00000229&lt;br /&gt;
| [[eShop]], contains store music in AAC format.&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| 0000020b&lt;br /&gt;
| 0000021b&lt;br /&gt;
| 0000022b&lt;br /&gt;
| Nintendo Zone&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| 0000020d&lt;br /&gt;
| 0000021d&lt;br /&gt;
| 0000022d&lt;br /&gt;
| Face Raiders, likely contains an ExBanner&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| 000002cc&lt;br /&gt;
| 000002cd&lt;br /&gt;
| 000002ce&lt;br /&gt;
| [[Home Menu]] theme&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| ?&lt;br /&gt;
| 000004aa&lt;br /&gt;
| 000004ab&lt;br /&gt;
| Nintendo Video Extra Data&lt;br /&gt;
This is where the video files are stored, and [[Nintendo_Video|includes]] the thumbnail, the description, and possibly some checksum info in each video file stored in the extdata images. There are always 9 files within the subdirectory &amp;quot;00000000&amp;quot; of this folder, even without any videos downloaded. The files are &amp;quot;00000001&amp;quot; - &amp;quot;00000009&amp;quot;, and &amp;quot;00000003&amp;quot; - &amp;quot;00000008&amp;quot; have the same filesize of 50.7 MB. It is possible to restore the older videos by overwriting all the files within this directory. Provided of course you have made a backup of the files before hand, by copying all the files within this directory to your computer. As far I&#039;m aware its not possible to mix and match the files in order to get certain videos in one grouping, ie. having all 3 Zelda orchestral recordings in one group of 4 Nintendo videos.&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
|00000306&lt;br /&gt;
|00000308&lt;br /&gt;
|00000307&lt;br /&gt;
|Mario Kart 7&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
| 0000030b&lt;br /&gt;
| 0000030d&lt;br /&gt;
| 0000030c&lt;br /&gt;
| Nintendogs + Cats&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| 00000326&lt;br /&gt;
| 00000326&lt;br /&gt;
| 00000326&lt;br /&gt;
| Pokédex 3D&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| 00000305&lt;br /&gt;
| 0000032d&lt;br /&gt;
| 0000033c&lt;br /&gt;
| Super Street Fighter IV 3D&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| 00000328&lt;br /&gt;
| 00000358&lt;br /&gt;
| 0000033b&lt;br /&gt;
| Ridge Racer 3D&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| ?&lt;br /&gt;
| 0000034d&lt;br /&gt;
| 00000402&lt;br /&gt;
| Samurai Warriors Chronicles&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| ?&lt;br /&gt;
| 0000034f&lt;br /&gt;
| 0000038a&lt;br /&gt;
| Dead or Alive Dimensions&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| 00000481&lt;br /&gt;
| N/A&lt;br /&gt;
| N/A&lt;br /&gt;
| Monster Hunter Tri G (Download-Quests)&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| ?&lt;br /&gt;
| 00000517&lt;br /&gt;
| 00000518&lt;br /&gt;
| Swapnote&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| 0000055d&lt;br /&gt;
| 0000055d&lt;br /&gt;
| 0000055d&lt;br /&gt;
| Pokémon X&amp;lt;br&amp;gt;Pokémon Y&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| ?&lt;br /&gt;
| 00000725&lt;br /&gt;
| 00000724&lt;br /&gt;
| Ambassador Certificate&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| ?&lt;br /&gt;
| ?&lt;br /&gt;
| 000007af&lt;br /&gt;
| New Super Mario Bros. 2&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| ?&lt;br /&gt;
| 00000863&lt;br /&gt;
| 00000864&lt;br /&gt;
| Animal Crossing: New Leaf&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| ?&lt;br /&gt;
| 00000a85&lt;br /&gt;
| 00000a86&lt;br /&gt;
| Professor Layton and the Miracle Mask&amp;lt;br&amp;gt;Professor Layton and the Azran Legacy&lt;br /&gt;
German Version ExtdataID is 00000a87&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| ?&lt;br /&gt;
| ?&lt;br /&gt;
| 00000b4f&lt;br /&gt;
| Fullblox / Crashmo&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| ?&lt;br /&gt;
| ?&lt;br /&gt;
| 00000ba9&lt;br /&gt;
| Pokémon Mystery Dungeon: Gates to Infinity&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| ?&lt;br /&gt;
| ?&lt;br /&gt;
| 00000c24&lt;br /&gt;
| Denpa men&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| 00000c73&lt;br /&gt;
| 00000c73&lt;br /&gt;
| 00000c73&lt;br /&gt;
| Save Data Transfer Tool&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| ?&lt;br /&gt;
| ?&lt;br /&gt;
| 00000d9a&lt;br /&gt;
| Donkey Kong Country™&amp;lt;br&amp;gt;Returns 3D: Trailer&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| ?&lt;br /&gt;
| ?&lt;br /&gt;
| 00000ea6&lt;br /&gt;
| Etrian Odyssey IV&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| ?&lt;br /&gt;
| 00000edf&lt;br /&gt;
| 00000ee0&lt;br /&gt;
| Super Smash Bros. for Nintendo 3DS&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| ?&lt;br /&gt;
| 00000f14&lt;br /&gt;
| 00000f1e&lt;br /&gt;
| Phoenix Wright: Ace Attorney - Dual Destinies&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| ?&lt;br /&gt;
| 00001007&lt;br /&gt;
| 00001005&lt;br /&gt;
| Professor Layton vs Phoenix Wright: Ace Attorney&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| ?&lt;br /&gt;
| ?&lt;br /&gt;
| 00001062&lt;br /&gt;
| Nintendo Pocket Football Club&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| ?&lt;br /&gt;
| ?&lt;br /&gt;
| 0000111c&lt;br /&gt;
| Yoshi&#039;s New Island&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| ?&lt;br /&gt;
| ?&lt;br /&gt;
| 00001131&lt;br /&gt;
| Fantasy Life&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| 000011c5&lt;br /&gt;
| 000011c5&lt;br /&gt;
| 000011c5&lt;br /&gt;
| Pokémon Omega Ruby&amp;lt;br&amp;gt;Pokémon Alpha Sapphire&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| ?&lt;br /&gt;
| ?&lt;br /&gt;
| 000012ca&lt;br /&gt;
| Mario vs. Donkey Kong: Tipping Stars&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| ?&lt;br /&gt;
| ?&lt;br /&gt;
| 00001499&lt;br /&gt;
| Korg DSN-12&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| ?&lt;br /&gt;
| ?&lt;br /&gt;
| 000014f2&lt;br /&gt;
| Animal Crossing: Happy Home Designer&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| 000014d1&lt;br /&gt;
| 000014d1&lt;br /&gt;
| 000014d1&lt;br /&gt;
| [[Home Menu]] badge&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| ?&lt;br /&gt;
| ?&lt;br /&gt;
| 00001632&lt;br /&gt;
| Fullblox / Stretchmo&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| ?&lt;br /&gt;
| ?&lt;br /&gt;
| 00001646&lt;br /&gt;
| Pokémon Rumble World&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| 00001648&lt;br /&gt;
| 00001648&lt;br /&gt;
| 00001648&lt;br /&gt;
| Pokémon Sun&amp;lt;br&amp;gt;Pokémon Moon&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| 0000165c&lt;br /&gt;
| 0000165c&lt;br /&gt;
| 0000165c&lt;br /&gt;
| [[Home Menu]] saved theme layouts&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| ?&lt;br /&gt;
| ?&lt;br /&gt;
| 00001678&lt;br /&gt;
| Yo-kai Watch&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| ?&lt;br /&gt;
| ?&lt;br /&gt;
| 000018fa&lt;br /&gt;
| Phoenix Wright: Ace Attorney - Spirit of Justice&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| ?&lt;br /&gt;
| ?&lt;br /&gt;
| 0000198f&lt;br /&gt;
| Animal Crossing: New Leaf - Welcome amiibo&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
| ?&lt;br /&gt;
| ?&lt;br /&gt;
| 00001a05&lt;br /&gt;
| Super Mario Maker&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| ?&lt;br /&gt;
| ?&lt;br /&gt;
| 00001a2e&lt;br /&gt;
| Swapdoodle&lt;br /&gt;
| &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== NAND Shared Extdata ==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
!  ExtdataID&lt;br /&gt;
!  Description&lt;br /&gt;
|-&lt;br /&gt;
| 0xe0000000&lt;br /&gt;
| Home Menu attempts to open this archive during boot, if [[FS:OpenArchive]] doesn&#039;t return an error Home Menu seems to then launch the [[System Transfer]] application. Home Menu doesn&#039;t actually use this archive at all except for checking whether it exists.&lt;br /&gt;
|-&lt;br /&gt;
|  0xf0000001&lt;br /&gt;
|  NAND JPEG/MPO files and phtcache.bin from the camera application are stored here. This also contains UploadData.dat.&lt;br /&gt;
|-&lt;br /&gt;
|  0xf0000002&lt;br /&gt;
|  NAND M4A files from the sound application are stored here&lt;br /&gt;
|-&lt;br /&gt;
|  0xf0000009&lt;br /&gt;
|  Used for [[BOSS_Services|SpotPass]] content storage for [[News_Services|notifications]].&lt;br /&gt;
|-&lt;br /&gt;
|  0xf000000b&lt;br /&gt;
|  Contains idb.dat, idbt.dat, gamecoin.dat, ubll.lst, CFL_DB.dat, and CFL_OldDB.dat. These files contain cleartext [[Mii_Maker|Miis]] and some data relating (including cached ICN data) to Play/Usage Records.&lt;br /&gt;
|-&lt;br /&gt;
|  0xf000000c&lt;br /&gt;
|  Contains bashotorya.dat and bashotorya2.dat.&lt;br /&gt;
|-&lt;br /&gt;
|  0xf000000d&lt;br /&gt;
|  Home Menu SpotPass content data [[BOSS_Services|storage]].&lt;br /&gt;
|-&lt;br /&gt;
|  0xf000000e&lt;br /&gt;
|  Contains [[VersionList|versionlist.dat]], used by Home Menu for the software update notification added with [[7.0.0-13]].&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Shared Extdata 0xf000000b gamecoin.dat ====&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;
| 0x4&lt;br /&gt;
| Magic number: 0x4F00&lt;br /&gt;
|-&lt;br /&gt;
| 0x4&lt;br /&gt;
| 0x2&lt;br /&gt;
| Total Play Coins&lt;br /&gt;
|-&lt;br /&gt;
| 0x6&lt;br /&gt;
| 0x2&lt;br /&gt;
| Total Play Coins obtained on the date stored below. When the below date does not match the current date, this field is reset to zero, then the date(and other fields) are updated. Once this value is &amp;gt;=10, no more Play Coins can be obtained until the current date changes.&lt;br /&gt;
|-&lt;br /&gt;
| 0x8&lt;br /&gt;
| 0x4&lt;br /&gt;
| Total step [[PTM:GetTotalStepCount|count]] at the time a new Play Coin was obtained.&lt;br /&gt;
|-&lt;br /&gt;
| 0xC&lt;br /&gt;
| 0x4&lt;br /&gt;
| Step count for the day the last Play Coin was obtained, for that day&#039;s step count(same as the step count displayed by home-menu when this file was updated).&lt;br /&gt;
|-&lt;br /&gt;
| 0x10&lt;br /&gt;
| 0x2&lt;br /&gt;
| Year&lt;br /&gt;
|-&lt;br /&gt;
| 0x12&lt;br /&gt;
| 0x1&lt;br /&gt;
| Month&lt;br /&gt;
|-&lt;br /&gt;
| 0x13&lt;br /&gt;
| 0x1&lt;br /&gt;
| Day&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The above date stores the last time new Play Coin(s) were obtained. The contents of this file is updated by home-menu. [[PTM:GetTotalStepCount]] is not checked constantly, after home-menu boot this is only checked when waking from sleep-mode. Each time home-menu updates the contents of this file, home-menu will set the Play Coin total to 300 if it&#039;s higher than the 300 Play Coin limit.&lt;br /&gt;
&lt;br /&gt;
[[Home Menu]] loads this file / opens this archive during [[Home Menu|startup]]. When accessing this file fails, like when the file/archive is corrupted(or at least on older system-versions), the result is a brick due to Home Menu using [[SVC|svcBreak]]. [[User:Yellows8|Yellows8]] bricked a 3DS this way due to corruption via invalid [[FSFile:Write]] flush flags. When opening this extdata archive(0xf000000b) fails, Home Menu executes svcBreak.&lt;br /&gt;
&lt;br /&gt;
==== Shared Extdata 0xf000000b ubll.lst ====&lt;br /&gt;
List of blocked users.&lt;br /&gt;
&lt;br /&gt;
Empty space is filled with 0xC-long sequences of 00 00 ... 07&lt;br /&gt;
&lt;br /&gt;
=== Tools ===&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/wwylele/3ds-save-tool 3ds-save-tool] - Extract/verifies extdata&lt;/div&gt;</summary>
		<author><name>Wwylele</name></author>
	</entry>
	<entry>
		<id>https://www.3dbrew.org/w/index.php?title=NWM_Services&amp;diff=20906</id>
		<title>NWM Services</title>
		<link rel="alternate" type="text/html" href="https://www.3dbrew.org/w/index.php?title=NWM_Services&amp;diff=20906"/>
		<updated>2019-03-13T00:20:54Z</updated>

		<summary type="html">&lt;p&gt;Wwylele: /* NWM local-WLAN service &amp;quot;nwm::UDS&amp;quot; */ Correct command ID. Verified against UDS disassembly&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Services]]&lt;br /&gt;
&lt;br /&gt;
These NWM services are used for local-WLAN communications, NWM module handles regular wifi APs as well. These services are used for creating/connecting to networks, and for sending/receiving data over the network etc. NWM module uses the wifi SDIO hardware via the IO registers for this.&lt;br /&gt;
&lt;br /&gt;
=NWM local-WLAN service &amp;quot;nwm::UDS&amp;quot;=&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
!  Command Header&lt;br /&gt;
!  Available since system version&lt;br /&gt;
!  Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x000102C2&lt;br /&gt;
| &lt;br /&gt;
| Initialize Deprecated. Appears to be handled about the same way as [[NWMUDS:InitializeWithVersion]], except this uses version=0x100 internally instead of loading it from the command request.&lt;br /&gt;
|-&lt;br /&gt;
| 0x00020000&lt;br /&gt;
| &lt;br /&gt;
| Scrap Not used by sub-wars. This sets a state value to 0x2 then signals an event. This is probably some sort of shutdown command since this state write will result in all UDS commands returning an error if used afterwards.&lt;br /&gt;
|-&lt;br /&gt;
| 0x00030000&lt;br /&gt;
| &lt;br /&gt;
| [[NWMUDS:Shutdown|Shutdown]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x00040402&lt;br /&gt;
| &lt;br /&gt;
| CreateNetwork Deprecated. Only used by very old titles.&lt;br /&gt;
|-&lt;br /&gt;
| 0x00050040&lt;br /&gt;
|&lt;br /&gt;
| [[NWMUDS:EjectClient|EjectClient]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x00060000&lt;br /&gt;
| &lt;br /&gt;
| [[NWMUDS:EjectSpectator|EjectSpectator]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x00070080&lt;br /&gt;
| &lt;br /&gt;
| [[NWMUDS:UpdateNetworkAttribute|UpdateNetworkAttribute]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x00080000&lt;br /&gt;
| &lt;br /&gt;
| [[NWMUDS:DestroyNetwork|DestroyNetwork]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x00090442&lt;br /&gt;
| &lt;br /&gt;
| ConnectNetwork Deprecated. Only used by very old titles.&lt;br /&gt;
|-&lt;br /&gt;
| 0x000A0000&lt;br /&gt;
| &lt;br /&gt;
| [[NWMUDS:DisconnectNetwork|DisconnectNetwork]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x000B0000&lt;br /&gt;
| &lt;br /&gt;
| [[NWMUDS:GetConnectionStatus|GetConnectionStatus]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x000C0000&lt;br /&gt;
| &lt;br /&gt;
| This writes two output u8 values to cmdreply[2] +0/+1. Not used by sub-wars.&lt;br /&gt;
|-&lt;br /&gt;
| 0x000D0040&lt;br /&gt;
| &lt;br /&gt;
| [[NWMUDS:GetNodeInformation|GetNodeInformation]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x000E0006&lt;br /&gt;
| &lt;br /&gt;
| &#039;&#039;Identical&#039;&#039; to [[NWMUDS:DecryptBeaconData|DecryptBeaconData]]. Deprecated, only used by old titles.&lt;br /&gt;
|-&lt;br /&gt;
| 0x000F0404&lt;br /&gt;
| &lt;br /&gt;
| [[NWMUDS:RecvBeaconBroadcastData|RecvBeaconBroadcastData]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x00100042&lt;br /&gt;
| &lt;br /&gt;
| [[NWMUDS:SetApplicationData|SetApplicationData]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x00110040&lt;br /&gt;
| &lt;br /&gt;
| [[NWMUDS:GetApplicationData|GetApplicationData]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x00120100&lt;br /&gt;
| &lt;br /&gt;
| [[NWMUDS:Bind|Bind]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x00130040&lt;br /&gt;
| &lt;br /&gt;
| [[NWMUDS:Unbind|Unbind]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x001400C0&lt;br /&gt;
| &lt;br /&gt;
| [[NWMUDS:PullPacket|PullPacket]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x00150080&lt;br /&gt;
| &lt;br /&gt;
| SetMaxSendDelay(u64 unk) Not used by sub-wars.&lt;br /&gt;
|-&lt;br /&gt;
| 0x00160040&lt;br /&gt;
| &lt;br /&gt;
| (u8 inputval) Unknown. Not used by sub-wars.&lt;br /&gt;
|-&lt;br /&gt;
| 0x00170182&lt;br /&gt;
| &lt;br /&gt;
| [[NWMUDS:SendTo|SendTo]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x00180040&lt;br /&gt;
| &lt;br /&gt;
| (u16 inputval) Unknown. Not used by sub-wars.&lt;br /&gt;
|-&lt;br /&gt;
| 0x00190040&lt;br /&gt;
| &lt;br /&gt;
| (u32 inputval) Unknown. Not used by sub-wars.&lt;br /&gt;
|-&lt;br /&gt;
| 0x001A0000&lt;br /&gt;
| &lt;br /&gt;
| [[NWMUDS:GetChannel|GetChannel]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x001B0302&lt;br /&gt;
| &lt;br /&gt;
| [[NWMUDS:InitializeWithVersion|InitializeWithVersion]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x001C0040&lt;br /&gt;
| &lt;br /&gt;
| (u8 inputval) Unknown. Not used by sub-wars.&lt;br /&gt;
|-&lt;br /&gt;
| 0x001D0044&lt;br /&gt;
| Unknown, &amp;gt;[[2.0.0-2]]&lt;br /&gt;
| [[NWMUDS:BeginHostingNetwork|BeginHostingNetwork]] This is a replacement for the original network-creation command.&lt;br /&gt;
|-&lt;br /&gt;
| 0x001E0084&lt;br /&gt;
| Unknown, &amp;gt;[[2.0.0-2]]&lt;br /&gt;
| [[NWMUDS:ConnectToNetwork|ConnectToNetwork]] This is a replacement for the original network-connection command.&lt;br /&gt;
|-&lt;br /&gt;
| 0x001F0006&lt;br /&gt;
| Unknown, &amp;gt;[[2.0.0-2]]&lt;br /&gt;
| [[NWMUDS:DecryptBeaconData|DecryptBeaconData]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x00200040&lt;br /&gt;
| Unknown, &amp;gt;[[2.0.0-2]]&lt;br /&gt;
| Flush (u8 data_frame_index) Unknown. Not used by sub-wars.&lt;br /&gt;
|-&lt;br /&gt;
| 0x00210080&lt;br /&gt;
| Unknown, &amp;gt;[[2.0.0-2]]&lt;br /&gt;
| [[NWMUDS:SetProbeResponseParam|SetProbeResponseParam]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x00220402&lt;br /&gt;
| Unknown, &amp;gt;[[2.0.0-2]]&lt;br /&gt;
| [[NWMUDS:ScanOnConnection|ScanOnConnection]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x00230000&lt;br /&gt;
| Unknown, &amp;gt;[[2.0.0-2]]&lt;br /&gt;
| This writes an output u16 value to cmdreply[2]. Unknown. Not used by sub-wars.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
PullPacket is used for receiving data over the network and SendTo is for sending data over the network.&lt;br /&gt;
&lt;br /&gt;
=NWM infrastructure service &amp;quot;nwm::INF&amp;quot;=&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
!  Command Header&lt;br /&gt;
!  Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x00010000&lt;br /&gt;
| ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x00020000&lt;br /&gt;
| ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x00030000&lt;br /&gt;
| ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x00040000&lt;br /&gt;
| ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x00050000&lt;br /&gt;
| ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x000603C4&lt;br /&gt;
| [[NWMINF:RecvBeaconBroadcastData|RecvBeaconBroadcastData]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x00070742&lt;br /&gt;
| [[NWMINF:ConnectToEncryptedAP|ConnectToEncryptedAP]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x00080302&lt;br /&gt;
| [[NWMINF:ConnectToAP|ConnectToAP]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x00090000&lt;br /&gt;
| ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x000A0000&lt;br /&gt;
| ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x000B0000&lt;br /&gt;
| ?, return event handle in cmdbuf[3]&lt;br /&gt;
|-&lt;br /&gt;
| 0x000C0040&lt;br /&gt;
| ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x000D0000&lt;br /&gt;
| ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x000E0002&lt;br /&gt;
| ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x000F0082&lt;br /&gt;
| ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x00100040&lt;br /&gt;
| ?&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=NWM socket service &amp;quot;nwm::SOC&amp;quot;=&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
!  Command Header&lt;br /&gt;
!  Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x00010042&lt;br /&gt;
| (u32 size, &amp;lt;static_buffer translate-hdr with static_buf_id=0&amp;gt;, addr) ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x00020080&lt;br /&gt;
| (u32 unk, u32 size) Unknown. Uses size=0x5F8 internally unless the input is &amp;lt;=0x5F8. Uses an ipc static_buffer(static_buf_id=0) for output with the specified size(also used when writing the translate-hdr). Writes an output u32 to cmdreply[2].&lt;br /&gt;
|-&lt;br /&gt;
| 0x00030042&lt;br /&gt;
| (u32 unk, u32 size, &amp;lt;static_buffer translate-hdr with static_buf_id=0&amp;gt;, addr) ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x00040042&lt;br /&gt;
| (u32 size, u32 unk, &amp;lt;static_buffer translate-hdr with static_buf_id=1&amp;gt;, addr) ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x00050040&lt;br /&gt;
| (u32 unk) ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x00060080&lt;br /&gt;
| (u32 unk0, u16 unk1) ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x00070040&lt;br /&gt;
| (u16 unk) This writes an output u32 to cmdreply[2].&lt;br /&gt;
|-&lt;br /&gt;
| 0x00080040&lt;br /&gt;
| [[NWMSOC:GetMACAddress|GetMACAddress]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x00090000&lt;br /&gt;
| This just copies data from state to the cmdreply, this always returns 0. u32 cmdreply[2] = sharedmem_size, cmdreply[4] = [[NWM_Shared_Memory|sharedmem_handle]], cmdreply[5] = eventhandle.&lt;br /&gt;
|-&lt;br /&gt;
| 0x000A0040&lt;br /&gt;
| (u32 unk) ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x000B0040&lt;br /&gt;
| (u32 unk) This writes an output u32 to cmdreply[2].&lt;br /&gt;
|-&lt;br /&gt;
| 0x000C0040&lt;br /&gt;
| (u32 unk) ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x000D0002&lt;br /&gt;
| ([[IPC|kernel_processid_translatehdr]], u32 processid) ?&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The only sysmodule which uses this is [[Socket_Services|socket]]-sysmodule. The first command used by socket-module is cmd9.&lt;br /&gt;
&lt;br /&gt;
=NWM service &amp;quot;nwm::SAP&amp;quot;=&lt;br /&gt;
&lt;br /&gt;
=NWM local-WLAN [[StreetPass]] service &amp;quot;nwm::CEC&amp;quot;=&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
!  Command Header&lt;br /&gt;
!  Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x00060002&lt;br /&gt;
| Unknown, called by CECD module, cmdbuf[2] takes an event handle.&lt;br /&gt;
|-&lt;br /&gt;
| 0x000D0082&lt;br /&gt;
| [[NWMCEC:SendProbeRequest|SendProbeRequest]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=NWM service &amp;quot;nwm::EXT&amp;quot;=&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
!  Command Header&lt;br /&gt;
!  Available since system version&lt;br /&gt;
!  Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x00010000&lt;br /&gt;
| &amp;lt;=[[2.0.0-2]]&lt;br /&gt;
| ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x00020000&lt;br /&gt;
| &amp;lt;=[[2.0.0-2]]&lt;br /&gt;
| ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x00030000&lt;br /&gt;
| &amp;lt;=[[2.0.0-2]]&lt;br /&gt;
| ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x00040040&lt;br /&gt;
| &amp;lt;=[[2.0.0-2]]&lt;br /&gt;
| ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x00050002&lt;br /&gt;
| &amp;lt;=[[2.0.0-2]]&lt;br /&gt;
| ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x00060000&lt;br /&gt;
| &amp;lt;=[[2.0.0-2]]&lt;br /&gt;
| ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x00070000&lt;br /&gt;
| &amp;lt;=[[2.0.0-2]]&lt;br /&gt;
| This copies 0x1C-bytes from NWM-module state to the data starting at cmdreply[2].&lt;br /&gt;
|-&lt;br /&gt;
| 0x00080040&lt;br /&gt;
| &amp;lt;=[[2.0.0-2]]&lt;br /&gt;
| [[NWMEXT:ControlWirelessEnabled|ControlWirelessEnabled]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x00090000&lt;br /&gt;
| &amp;lt;=[[2.0.0-2]]&lt;br /&gt;
| ?&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=NWM service &amp;quot;nwm::TST&amp;quot;=&lt;br /&gt;
&lt;br /&gt;
=BeaconDataReply Structure=&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;
| 0x4&lt;br /&gt;
| Max output size, from the command request.&lt;br /&gt;
|-&lt;br /&gt;
| 0x4&lt;br /&gt;
| 0x4&lt;br /&gt;
| Total amount of output data written relative to struct+0. 0xC when there&#039;s no entries.&lt;br /&gt;
|-&lt;br /&gt;
| 0x8&lt;br /&gt;
| 0x4&lt;br /&gt;
| Total entries, 0 for none.&lt;br /&gt;
|-&lt;br /&gt;
| 0xC&lt;br /&gt;
| &amp;lt;Rest of the structure&amp;gt;&lt;br /&gt;
| Beacon entries.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Beacon entry:&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;
| 0x4&lt;br /&gt;
| Size of this entire entry. The next entry starts at curentry_startoffset+curentry_size.&lt;br /&gt;
|-&lt;br /&gt;
| 0x4&lt;br /&gt;
| 0x1&lt;br /&gt;
| ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x5&lt;br /&gt;
| 0x1&lt;br /&gt;
| AP wifi channel.&lt;br /&gt;
|-&lt;br /&gt;
| 0x6&lt;br /&gt;
| 0x1&lt;br /&gt;
| ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x7&lt;br /&gt;
| 0x1&lt;br /&gt;
| ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x8&lt;br /&gt;
| 0x6&lt;br /&gt;
| AP MAC address.&lt;br /&gt;
|-&lt;br /&gt;
| 0xE&lt;br /&gt;
| 0x6&lt;br /&gt;
| ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x14&lt;br /&gt;
| 0x4&lt;br /&gt;
| Size of this entire entry, games use this value to traverse the beacons list.&lt;br /&gt;
|-&lt;br /&gt;
| 0x18&lt;br /&gt;
| 0x4&lt;br /&gt;
| Value 0x1C(size of this header and/or offset to the actual beacon data).&lt;br /&gt;
|-&lt;br /&gt;
| 0x1C&lt;br /&gt;
| Entry_size - 0x1C&lt;br /&gt;
| The actual beacon data is located here, starting at the 802.11 management frame header.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
This section describes the structure returned by [[NWMINF:RecvBeaconBroadcastData]] and [[NWMUDS:RecvBeaconBroadcastData]].&lt;br /&gt;
&lt;br /&gt;
=ScanInputStruct=&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
!  Index Word&lt;br /&gt;
!  Description&lt;br /&gt;
|-&lt;br /&gt;
| 0&lt;br /&gt;
| Two unknown u16s.&lt;br /&gt;
|-&lt;br /&gt;
| 1&lt;br /&gt;
| Two unknown u16s.&lt;br /&gt;
|-&lt;br /&gt;
| 2-3&lt;br /&gt;
| Host MAC address. The 6-bytes located here are normally all 0xFF, for all hosts. Otherwise when not set to broadcast-MAC, the command will only return info for the specified host MAC address.&lt;br /&gt;
|-&lt;br /&gt;
| 4-12&lt;br /&gt;
| Uninitialized for UDS.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
This section describes the 0x34-byte input structure used by [[NWMINF:RecvBeaconBroadcastData]] and [[NWMUDS:RecvBeaconBroadcastData]].&lt;br /&gt;
&lt;br /&gt;
=Local-WLAN=&lt;br /&gt;
UDS is used for 3DS&amp;lt;&amp;gt;3DS local-WLAN communications, and for 3DS&amp;lt;&amp;gt;Wii U communications. The latter is mainly only used for multi-player in games.&lt;br /&gt;
&lt;br /&gt;
All UDS local-WLAN communications have the CCMP key for data encryption generated via NWM module. The CCMP key passed to nwm::CEC commands(stored in a 0x44-byte input structure) for [[StreetPass]] is generated by the CECD module. The input data used with [[Process_Services|EncryptDecryptAes]] with [[PSPXI:EncryptDecryptAes|keytype1]] is a MD5 hash over the input passphrase. This input passphrase is fixed for [[Download Play]], it&#039;s unique per local-WLAN application. The CTR is a MD5 hash over the below 0x10-byte structure. The output from encrypting that data with AES-CTR is the final CCMP key. This passphrase is a raw input buffer: while the passphrase specified by user-processes is normally a string with the NUL-terminator included, it can be anything(like the [[DLP_Services|WirelessRebootPassphrase]] for example).&lt;br /&gt;
&lt;br /&gt;
The maximum number of nodes(including the host) which can be on an UDS network is 16.&lt;br /&gt;
&lt;br /&gt;
==NodeID==&lt;br /&gt;
There are two types of client connections: regular Client, and Spectator. The latter &#039;&#039;never&#039;&#039; sends &#039;&#039;any&#039;&#039; 802.11 frame at all to the host, hence &#039;&#039;nothing&#039;&#039; actually connected to the network(including the host) can know about any spectators. Once a spectator is &amp;quot;connected&amp;quot; to a network, it can only receive broadcasted data, no sending.&lt;br /&gt;
&lt;br /&gt;
DLP-client connects to the network as a spectator during DLP scanning to get various [[Download_Play|metadata]] including icon data.&lt;br /&gt;
&lt;br /&gt;
===NetworkNodeID===&lt;br /&gt;
This is the network u16 ID for each device on the UDS network. NodeID 0xFFFF is a broadcast alias. 0x1 is for the host, the 0x2 for the first client, 0x3 for the second client, and so on.&lt;br /&gt;
&lt;br /&gt;
The spectator doesn&#039;t have a NetworkNodeID, since it can&#039;t [[NWMUDS:SendTo|send]] any data.&lt;br /&gt;
&lt;br /&gt;
NetworkNodeIDs for clients do not change when any clients disconnect, likewise for the encrypted node-listing stored in the wifi beacons. When a client disconnects, the corresponding NetworkNodeID bit in the [[NWMUDS:GetConnectionStatus|node_bitmask]] is cleared. When a client is connecting, the client is assigned the NetworkNodeID with the lowest corresponding clear-bit in the [[NWMUDS:GetConnectionStatus|node_bitmask]], then that bit is set.&lt;br /&gt;
&lt;br /&gt;
===BindNodeID===&lt;br /&gt;
This u32 is an ID only used on the local device. How many devices are on the network or which device this system is does not affect this ID.&lt;br /&gt;
&lt;br /&gt;
The spectator uses BindNodeID 0x1. DLP uses BindNodeID 0x3 when connecting as an actual client. Hence, it seems BindNodeID bit0 is spectator-related. All normal nodes(host/client) start with BindNodeID 0x2. When connecting to a network again(and probably with network creation) without reinitializing NWMUDS, official user processes increase the used BindNodeID by 0x2.&lt;br /&gt;
&lt;br /&gt;
BindNodeID value 0x0 is invalid. The maximum number of BindNodeIDs which can be open at the same time is 16.&lt;br /&gt;
&lt;br /&gt;
==Application data transfer==&lt;br /&gt;
The protocol used for sending/receiving data over the network with UDS by official applications is [[PRUDP]](in some cases at least). Mario Kart 7 uses PRUDP here. Triforce Heroes uses plaintext for whatever protocol it uses for UDS.&lt;br /&gt;
&lt;br /&gt;
The UDS version of [[PRUDP]] is different from the normal UDP version it appears(no afa1/a1af data for example).&lt;br /&gt;
&lt;br /&gt;
==Communication protocol==&lt;br /&gt;
The process of connecting to a host and exchanging data follows the sequence:&lt;br /&gt;
&lt;br /&gt;
Client-&amp;gt;Server: Authentication frame SEQ1&lt;br /&gt;
&lt;br /&gt;
Server-&amp;gt;Client: Authentication frame SEQ2&lt;br /&gt;
&lt;br /&gt;
[There does not appear to be an association request frame sent by the client to the server, it is however possible that it was sent and just not captured by the test equipment]&lt;br /&gt;
&lt;br /&gt;
Server-&amp;gt;Client: Association Response frame with association id&lt;br /&gt;
&lt;br /&gt;
[From here on, the client is connected to the server]&lt;br /&gt;
&lt;br /&gt;
Client-&amp;gt;Server: Encrypted data packet containing an 8-byte 802.2 LLC header with ethertype = EAPoL (0x888E) and an u16 header of 0x201 ([[NWM_Services#EAPoL-Start frame|EAPoL-Start]])&lt;br /&gt;
&lt;br /&gt;
Server-&amp;gt;Broadcast: Encrypted data packet containing the updated node information after the client connected (Using ethertype = SecureData).&lt;br /&gt;
&lt;br /&gt;
Server-&amp;gt;Client: Encrypted data packet containing an 8-byte 802.2 LLC header with ethertype = EAPoL (0x888E) and an u16 header of 0x0202([[NWM_Services#EAPoL-Logoff frame|EAPoL-Logoff]])&lt;br /&gt;
&lt;br /&gt;
[From here on, data packets sent using SendTo are encapsulated with an LLC header with ethertype = 0x876D ([[NWM_Services#SecureData NWM header|SecureData]])]&lt;br /&gt;
&lt;br /&gt;
[The client also sends periodic SecureData data frames on its own, these are probably ping frames]&lt;br /&gt;
&lt;br /&gt;
==Data frames==&lt;br /&gt;
Data is transferred over the network using [[NWMUDS:PullPacket]]/[[NWMUDS:SendTo]]. That data is transferred using 802.11 data frames using CCMP encryption. The encrypted data contained in the frame starts with the 0x8-byte [https://en.wikipedia.org/wiki/Subnetwork_Access_Protocol#Use LLC header], then the 0xE-byte NWM header, followed by the actual application data from the previously mentioned commands. When [[NWMUDS:SendTo]] was used with dst_NodeID = broadcast, the data frame is sent to the 802.11 broadcast MAC address. Otherwise with a specific NodeID, the data frame is sent to the actual MAC address for that device.&lt;br /&gt;
&lt;br /&gt;
Official application data is normally stored here as big-endian.&lt;br /&gt;
&lt;br /&gt;
Application data packets are sent to the host using 802.11 unicast, which then acts as a router and forwards the packet to the right destination node id based on the SecureData header using either broadcast or unicast, it is not yet known how it chooses which to use.&lt;br /&gt;
&lt;br /&gt;
==Special data channels==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
!  Channel&lt;br /&gt;
!  Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x101&lt;br /&gt;
| Used when broadcasting the updated node information after a new client connects.&lt;br /&gt;
|-&lt;br /&gt;
| 0x103&lt;br /&gt;
| Used when sending what appears to be &amp;quot;ping&amp;quot; or &amp;quot;null&amp;quot; frames.&lt;br /&gt;
|-&lt;br /&gt;
| 0x104&lt;br /&gt;
| Used to signal the ejection of all spectators in the network.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==SecureData NWM 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;
| 0x0&lt;br /&gt;
| 0x2&lt;br /&gt;
| Size of the entire frame minus the 8 bytes from the LLC header.&lt;br /&gt;
|-&lt;br /&gt;
| 0x2&lt;br /&gt;
| 0x2&lt;br /&gt;
| unknown&lt;br /&gt;
|-&lt;br /&gt;
| 0x4&lt;br /&gt;
| 0x2&lt;br /&gt;
| Size of the entire frame minus 12 bytes.&lt;br /&gt;
|-&lt;br /&gt;
| 0x6&lt;br /&gt;
| 0x2&lt;br /&gt;
| Data channel. Applications can only use the low 8 bits, channels greater than 255 are reserved for management functions.&lt;br /&gt;
|-&lt;br /&gt;
| 0x8&lt;br /&gt;
| 0x2&lt;br /&gt;
| Sequence number, incremented after each sent packet.&lt;br /&gt;
|-&lt;br /&gt;
| 0xA&lt;br /&gt;
| 0x2&lt;br /&gt;
| Destination network node id&lt;br /&gt;
|-&lt;br /&gt;
| 0xC&lt;br /&gt;
| 0x2&lt;br /&gt;
| Source network node id&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
This data is stored as big-endian.&lt;br /&gt;
&lt;br /&gt;
==EAPoL-Start frame==&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;
| 0x2&lt;br /&gt;
| Always 0x201 in big-endian.&lt;br /&gt;
|-&lt;br /&gt;
| 0x2&lt;br /&gt;
| 0x2&lt;br /&gt;
| Association id of the sending client in big-endian.&lt;br /&gt;
|-&lt;br /&gt;
| 0x4&lt;br /&gt;
| 0x2&lt;br /&gt;
| Unknown. Always 0x1 in big-endian. The parser for this packet errors out if this is &amp;gt; 3.&lt;br /&gt;
|-&lt;br /&gt;
| 0x6&lt;br /&gt;
| 0x2&lt;br /&gt;
| Unknown&lt;br /&gt;
|-&lt;br /&gt;
| 0x8&lt;br /&gt;
| 0x28&lt;br /&gt;
| NodeInfo structure with all fields in big-endian&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
This data is stored as big-endian.&lt;br /&gt;
&lt;br /&gt;
==EAPoL-Logoff frame==&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;
| 0x2&lt;br /&gt;
| Always 0x202 in big-endian.&lt;br /&gt;
|-&lt;br /&gt;
| 0x2&lt;br /&gt;
| 0x2&lt;br /&gt;
| Unknown. Always 0?&lt;br /&gt;
|-&lt;br /&gt;
| 0x4&lt;br /&gt;
| 0x2&lt;br /&gt;
| Assigned network node id.&lt;br /&gt;
|-&lt;br /&gt;
| 0x6&lt;br /&gt;
| 0x6&lt;br /&gt;
| Mac address of the newly connected client.&lt;br /&gt;
|-&lt;br /&gt;
| 0xC&lt;br /&gt;
| 0x4&lt;br /&gt;
| Unknown&lt;br /&gt;
|-&lt;br /&gt;
| 0x10&lt;br /&gt;
| 0x2&lt;br /&gt;
| Unknown. Always 0.&lt;br /&gt;
|-&lt;br /&gt;
| 0x12&lt;br /&gt;
| 0x1&lt;br /&gt;
| Number of connected nodes, including the new client.&lt;br /&gt;
|-&lt;br /&gt;
| 0x13&lt;br /&gt;
| 0x1&lt;br /&gt;
| Max number of nodes.&lt;br /&gt;
|-&lt;br /&gt;
| 0x14&lt;br /&gt;
| 0x2&lt;br /&gt;
| Always 0.&lt;br /&gt;
|-&lt;br /&gt;
| 0x16&lt;br /&gt;
| 0x2&lt;br /&gt;
| Unknown.&lt;br /&gt;
|-&lt;br /&gt;
| 0x18&lt;br /&gt;
| 0x280&lt;br /&gt;
| List of 16 NodeInfo structures with all fields in big-endian&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
This data is stored as big-endian.&lt;br /&gt;
&lt;br /&gt;
==Structure used for generating the CTR for CCMP key generation==&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;
| 0x4&lt;br /&gt;
| wlancommID&lt;br /&gt;
|-&lt;br /&gt;
| 0x4&lt;br /&gt;
| 0x4&lt;br /&gt;
| networkID&lt;br /&gt;
|-&lt;br /&gt;
| 0x8&lt;br /&gt;
| 0x6&lt;br /&gt;
| Host MAC address.&lt;br /&gt;
|-&lt;br /&gt;
| 0xE&lt;br /&gt;
| 0x2&lt;br /&gt;
| id8&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
This data is stored as little-endian.&lt;br /&gt;
&lt;br /&gt;
==CTR used for beacon tags crypto==&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;
| 0x6&lt;br /&gt;
| Host MAC address&lt;br /&gt;
|-&lt;br /&gt;
| 0x6&lt;br /&gt;
| 0x4&lt;br /&gt;
| wlancommID&lt;br /&gt;
|-&lt;br /&gt;
| 0xA&lt;br /&gt;
| 0x1&lt;br /&gt;
| id8&lt;br /&gt;
|-&lt;br /&gt;
| 0xB&lt;br /&gt;
| 0x1&lt;br /&gt;
| Padding, value zero.&lt;br /&gt;
|-&lt;br /&gt;
| 0xC&lt;br /&gt;
| 0x4&lt;br /&gt;
| networkID&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
This data is stored as little-endian. All data here is all-zero except for the MAC address, when the u8 at offset 0x8 in the network-struct is 0.&lt;br /&gt;
&lt;br /&gt;
==Network structure==&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;
| 0x6&lt;br /&gt;
| This is the MAC address of the host. This is used for when [[NWMUDS:ConnectToNetwork|connecting]] to the network.&lt;br /&gt;
|-&lt;br /&gt;
| 0x6&lt;br /&gt;
| 0x1&lt;br /&gt;
| This is actually written as an u16 without byte-swapping. This is the network wifi channel. When connecting this is normally non-zero. When hosting, this can be 0 to automatically select a channel, otherwise the specified channel is used. When non-zero official user-processes require this value to be one of the following when hosting: 1, 6, or 11.&lt;br /&gt;
|-&lt;br /&gt;
| 0x7&lt;br /&gt;
| 0x1&lt;br /&gt;
| Padding&lt;br /&gt;
|-&lt;br /&gt;
| 0x8&lt;br /&gt;
| 0x1&lt;br /&gt;
| Initialized flag. Must be non-zero otherwise NWM-module will use value 0x0 for most/all(?) fields in this structure when reading these fields.&lt;br /&gt;
|-&lt;br /&gt;
| 0xC&lt;br /&gt;
| 0x3&lt;br /&gt;
| This is the OUI value for use with the beacon tags. Normally this is 001F32.&lt;br /&gt;
|-&lt;br /&gt;
| 0xF&lt;br /&gt;
| 0x1&lt;br /&gt;
| OUI type (21/0x15)&lt;br /&gt;
|-&lt;br /&gt;
| 0x10&lt;br /&gt;
| 0x4&lt;br /&gt;
| wlancommID. Local-WLAN communication ID, normally this is: (user_process [[Title_list|uniqueID]] &amp;lt;&amp;lt; 8) | val. Where val is 0x10 on retail([[Configuration_Memory#ENVINFO|ENVINFO]] bit0 set), 0x90 for devunit. Official software includes an input bool flag parameter for setting bit0 in this wlancommID, normally that flag isn&#039;t set. For [[Download Play]], this is always 0x2810 on retail(0x2890 on devunit).&lt;br /&gt;
&lt;br /&gt;
This wlancommID can have the side affect of region-locking when the title uses the uniqueID for the current title(hard-coded in .text normally), instead of using a fixed input uniqueID for each region of the title.&lt;br /&gt;
|-&lt;br /&gt;
| 0x14&lt;br /&gt;
| 0x1&lt;br /&gt;
| id8. ID, for [[Download Play]] this is 0x55. 0x55/&#039;U&#039; seems to be used for networks where Wii U can host it(Download Play, Smash Bros, ...) - this value isn&#039;t known to be actually checked anywhere however.&lt;br /&gt;
|-&lt;br /&gt;
| 0x15&lt;br /&gt;
| 0x1&lt;br /&gt;
| Number of times the network structure hash was updated.&lt;br /&gt;
|-&lt;br /&gt;
| 0x16&lt;br /&gt;
| 0x2&lt;br /&gt;
| This network attributes u16 bitmask can be written via [[NWMUDS:UpdateNetworkAttribute]].&lt;br /&gt;
Bitmasks:&lt;br /&gt;
* 0x1: When set, spectators are not allowed to connect(see [[NWMUDS:EjectSpectator|here]]). Checked by official user-processes before using [[NWMUDS:ConnectToNetwork]], when connecting as a Spectator. Must be clear otherwise that code returns error 0xE10113EA. If the initialized_flag at offset 0x8 is zero, this code handles it the same way as if this bit was set. The latest NWM-module handles checking this bit itself however.&lt;br /&gt;
* 0x2: When set, new regular-clients are not allowed to connect.&lt;br /&gt;
* 0x4: Unknown, has no affect on new clients/spectators connecting. Official software has an option for setting this bit via an input flag from the same code using bitmask 0x2. Official software always clears bitmask 0x6 when unblocking new connections.&lt;br /&gt;
|-&lt;br /&gt;
| 0x18&lt;br /&gt;
| 0x4&lt;br /&gt;
| u32 networkID, randomly-generated when creating the network. The network SSID used when a client connects to the network is sprintf(out, &amp;quot;%08X&amp;quot;, networkID).&lt;br /&gt;
|-&lt;br /&gt;
| 0x1C&lt;br /&gt;
| 0x1&lt;br /&gt;
| Total number of currently connected nodes, including the host.&lt;br /&gt;
|-&lt;br /&gt;
| 0x1D&lt;br /&gt;
| 0x1&lt;br /&gt;
| Maximum number of nodes, including the host. This also is the total number of entries stored under the array in the encrypted beacon data.&lt;br /&gt;
|-&lt;br /&gt;
| 0x1E&lt;br /&gt;
| 0xD&lt;br /&gt;
| ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x2B&lt;br /&gt;
| 0x14&lt;br /&gt;
| SHA1 hash of the network structure, starting at the OUI field (offset 0xC) and spanning SizeOfAppData + 0x34. The unused space of the app data buffer is not hashed.&lt;br /&gt;
|-&lt;br /&gt;
| 0x3F&lt;br /&gt;
| 0x1&lt;br /&gt;
| Size of appdata.&lt;br /&gt;
|-&lt;br /&gt;
| 0x40&lt;br /&gt;
| 0xC8&lt;br /&gt;
| Appdata(Application data), if any. Size of the appdata is specified via the u8 at offset 0x3F. This data is not used when the size-field is zero.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
This 0x108-byte structure is used for [[NWMUDS:BeginHostingNetwork]], [[NWMUDS:ConnectToNetwork]], etc. This data is stored as big-endian.&lt;br /&gt;
&lt;br /&gt;
==NodeInfo structure==&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;
| u64 ID, this is the UDS version of the FriendCodeSeed. This is loaded from BlkID 0x00090000 in the [[Config_Savegame|system-config]] via [[CfgS:GetConfigInfoBlk2]].&lt;br /&gt;
|-&lt;br /&gt;
| 0x8&lt;br /&gt;
| 0x14&lt;br /&gt;
| The first 0x18-bytes from BlkID 0x000A0000 in the [[Config_Savegame|system-config]] loaded via [[CfgS:GetConfigInfoBlk2]] is written here by user-processes. However, the data at +0x14(absolute offset 0x1C) is written by NWM-module later.&lt;br /&gt;
|-&lt;br /&gt;
| 0x1C&lt;br /&gt;
| 0x2&lt;br /&gt;
| u16, unknown. Set to 0x0 with the output from [[NWMUDS:DecryptBeaconData]].&lt;br /&gt;
|-&lt;br /&gt;
| 0x1E&lt;br /&gt;
| 0x1&lt;br /&gt;
| u8 flag, unknown. Originates from the u16 bitmask in the beacon node-list header. This flag is normally 0 since that bitmask is normally 0?&lt;br /&gt;
|-&lt;br /&gt;
| 0x1F&lt;br /&gt;
| 0x1&lt;br /&gt;
| Padding?&lt;br /&gt;
|-&lt;br /&gt;
| 0x20&lt;br /&gt;
| 0x2&lt;br /&gt;
| u16 NetworkNodeID&lt;br /&gt;
|-&lt;br /&gt;
| 0x22&lt;br /&gt;
| 0x6&lt;br /&gt;
| Normally zero?&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The first 0x20-bytes are written by the user-process before using this structure with [[NWMUDS:InitializeWithVersion]]. The data starting at offset 0x8 is only initialized by NWM-module.&lt;br /&gt;
&lt;br /&gt;
== UDS Beacons ==&lt;br /&gt;
The UDS host broadcasts a beacon containing at least two Nintendo-vendor tags(tag number 0xDD, see above for the OUI), normally the data stored in these tags are static. The second tag contains the big-endian u32 networkID, used by the clients when connecting to the host and for the above CCMP key generation. The Nintendo-vendor tag(s) following the first two are unique to the process using UDS, these tags are used for broadcasting metadata regarding the host.&lt;br /&gt;
&lt;br /&gt;
A tool for these beacons is available here: [https://github.com/yellows8/ctr-wlanbeacontool]&lt;br /&gt;
&lt;br /&gt;
=== UDS Beacon Tags ===&lt;br /&gt;
The following is the structure of each tag, starting at the OUI. The order of the tags is the same as listed below. All data stored under these tags are stored as big-endian.&lt;br /&gt;
&lt;br /&gt;
==== OUI Type 20 ====&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;
| 0x3&lt;br /&gt;
| OUI, see above.&lt;br /&gt;
|-&lt;br /&gt;
| 0x3&lt;br /&gt;
| 0x1&lt;br /&gt;
| OUI type (20/0x14)&lt;br /&gt;
|-&lt;br /&gt;
| 0x4&lt;br /&gt;
| 0x3&lt;br /&gt;
| Sample data: 0a 00 00&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Normally the size of this tag(from the tag size field) is 0x07.&lt;br /&gt;
&lt;br /&gt;
==== OUI Type 21 ====&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;
| 0x1F&lt;br /&gt;
| This is the network structure starting at offset 0xC, with the first 0x1F-bytes from there.&lt;br /&gt;
|-&lt;br /&gt;
| 0x1F&lt;br /&gt;
| 0x14&lt;br /&gt;
| SHA1 hash. When doing the hashing, this hash is cleared to zero. The hash data starts at offset 0x0(OUI), and the size is 0x34 + &amp;lt;value of the u8 at offset 0x33&amp;gt;.&lt;br /&gt;
|-&lt;br /&gt;
| 0x33&lt;br /&gt;
| 0x1&lt;br /&gt;
| Size of appdata. Normally zero. When non-zero this appdata is located at offset 0x34.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Normally the size of this tag(from the tag size field) is 0x34, not including appdata.&lt;br /&gt;
&lt;br /&gt;
==== OUI Type 24 ====&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;
| 0x3&lt;br /&gt;
| OUI, see above.&lt;br /&gt;
|-&lt;br /&gt;
| 0x3&lt;br /&gt;
| 0x1&lt;br /&gt;
| OUI type (24/0x18)&lt;br /&gt;
|-&lt;br /&gt;
| 0x4&lt;br /&gt;
| See below&lt;br /&gt;
| Encrypted data&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
This is the tag0 used with [[NWMUDS:DecryptBeaconData]]. The size of data stored under this tag has a maximum size of 0xFA-bytes, however normally the size is smaller than that. Additional encrypted data, if any, is stored under the below tag1.&lt;br /&gt;
&lt;br /&gt;
==== OUI Type 25 ====&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;
| 0x3&lt;br /&gt;
| OUI, see above.&lt;br /&gt;
|-&lt;br /&gt;
| 0x3&lt;br /&gt;
| 0x1&lt;br /&gt;
| OUI type (25/0x19)&lt;br /&gt;
|-&lt;br /&gt;
| 0x4&lt;br /&gt;
| See above&lt;br /&gt;
| Encrypted data&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
When this exists in the beacon, this is the tag1 used with [[NWMUDS:DecryptBeaconData]]. The data stored here is the 0xFA-bytes following the previous encrypted data in tag0, for more space for storing the encrypted data.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Encrypted beacon data ====&lt;br /&gt;
The following structure is for the plaintext version of the encrypted data, stored as big-endian.&lt;br /&gt;
&lt;br /&gt;
This data is encrypted with AES-CTR, by NWM module in software. The AES key is stored in NWM module itself. See above for the CTR. The size of this encrypted data is 0x12 + (0x1E*val), where val is the u8 from networkstruct offset 0x1D.&lt;br /&gt;
&lt;br /&gt;
===== Structure =====&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;
| 0x10&lt;br /&gt;
| MD5 over the rest of the data following this(plaintext).&lt;br /&gt;
|-&lt;br /&gt;
| 0x10&lt;br /&gt;
| 0x2&lt;br /&gt;
| u16 bitmask. Unknown, normally 0? Bit0 is for entry0, bit1 for entry1, and so on.&lt;br /&gt;
|-&lt;br /&gt;
| 0x12&lt;br /&gt;
| 0x1E * &amp;lt;total array entries&amp;gt;&lt;br /&gt;
| This is an array of entries for each of the devices on this network, the first entry is for the host and the rest is for the client(s).&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===== Array entry =====&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;
| 0x1C&lt;br /&gt;
| This is the first 0x1C-bytes of the NodeInfo structure, stored as big-endian.&lt;br /&gt;
|-&lt;br /&gt;
| 0x1C&lt;br /&gt;
| 0x2&lt;br /&gt;
| u16 NetworkNodeID, stored as big-endian.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Each entry is for a node.&lt;br /&gt;
&lt;br /&gt;
= Mapped IO =&lt;br /&gt;
&#039;&#039;All&#039;&#039; of the [[IO_Registers|IO]] mapped under the NWM-module process is listed below:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
!  Userland address&lt;br /&gt;
!  Physical address&lt;br /&gt;
!  Size&lt;br /&gt;
!  Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x1EC22000&lt;br /&gt;
| 0x10122000&lt;br /&gt;
| 0x1000&lt;br /&gt;
| [[WIFI_Registers]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x1EC40000&lt;br /&gt;
| 0x10140000&lt;br /&gt;
| 0x1000&lt;br /&gt;
| [[PDN_Registers]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x1EE22000&lt;br /&gt;
| 0x10322000&lt;br /&gt;
| 0x1000&lt;br /&gt;
| &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=Errors=&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
!  Error code&lt;br /&gt;
!  Description&lt;br /&gt;
|-&lt;br /&gt;
| 0xC8A06C0D&lt;br /&gt;
| The operation being performed is already done (e.g., if you run NWMEXT_ControlWirelessEnabled to turn wifi on when it&#039;s on already, you can&#039;t turn it on again).&lt;br /&gt;
|-&lt;br /&gt;
| 0xC8A113EA&lt;br /&gt;
| Returned when the command isn&#039;t allowed to be used on this device.&lt;br /&gt;
|-&lt;br /&gt;
| 0xC90113FA&lt;br /&gt;
| Node doesn&#039;t exist / invalid NetworkNodeID?&lt;br /&gt;
|-&lt;br /&gt;
| 0xC92113FB&lt;br /&gt;
| Returned when trying to connect to a host when the host has the specified connection-type blocked via the network attributes. There might be other causes too.&lt;br /&gt;
|-&lt;br /&gt;
| 0xE10113E9&lt;br /&gt;
| Returned when the input size is invalid. Returned by [[NWMUDS:PullPacket]] when the input size is smaller than the frame_size.&lt;br /&gt;
|-&lt;br /&gt;
| 0xE10113EA&lt;br /&gt;
| Invalid bind / data_channel is invalid(0x0).&lt;br /&gt;
|}&lt;/div&gt;</summary>
		<author><name>Wwylele</name></author>
	</entry>
	<entry>
		<id>https://www.3dbrew.org/w/index.php?title=Mii&amp;diff=20905</id>
		<title>Mii</title>
		<link rel="alternate" type="text/html" href="https://www.3dbrew.org/w/index.php?title=Mii&amp;diff=20905"/>
		<updated>2019-03-05T22:46:22Z</updated>

		<summary type="html">&lt;p&gt;Wwylele: /* Mii Database */ Record it in little-endian&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Originally [http://wiibrew.org/wiki/Mii_Data created for the Nintendo Wii] (and backported to a selection of DS/i games), the &#039;&#039;&#039;Mii&#039;&#039;&#039; format was expanded with a larger selection of facial features and a new &amp;quot;copying&amp;quot; permission for the 3DS family, and later implemented as-is on Wii U.&lt;br /&gt;
&lt;br /&gt;
See [[Mii Maker]] for the application chiefly designed to create, edit, delete, and trade Miis or convert them from and to a QR code.&lt;br /&gt;
&lt;br /&gt;
The default endianness in this page is little-endian, unless explicitly specified.&lt;br /&gt;
&lt;br /&gt;
==Mii Database==&lt;br /&gt;
Format of the Mii main database &#039;&#039;&#039;CFL_DB.dat&#039;&#039;&#039;, found in [[Extdata#NAND_Shared_Extdata|shared extdata]] archive f0000000b.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset&lt;br /&gt;
! Length&lt;br /&gt;
! &lt;br /&gt;
|-&lt;br /&gt;
| 0x0&lt;br /&gt;
| 0x4&lt;br /&gt;
| Header &amp;quot;CFOG&amp;quot; (Mii Maker section)&lt;br /&gt;
|-&lt;br /&gt;
| 0x4&lt;br /&gt;
| 0x4&lt;br /&gt;
| Header 0x00000100&lt;br /&gt;
|-&lt;br /&gt;
| 0x8&lt;br /&gt;
| 0x23F0 (100 * 0x5C)&lt;br /&gt;
| Array of owned (saved in Mii Maker) Miis. Order in file is unrelated to canonical order in-app.&lt;br /&gt;
|-&lt;br /&gt;
| 0x23F8&lt;br /&gt;
| 0x4&lt;br /&gt;
| Header &amp;quot;CFHE&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| 0x23FC&lt;br /&gt;
| 0x2&lt;br /&gt;
| Linked list tail index. 0xFFFF if the list is empty&lt;br /&gt;
|-&lt;br /&gt;
| 0x23FE&lt;br /&gt;
| 0x2&lt;br /&gt;
| Linked list head index. 0xFFFF if the list is empty&lt;br /&gt;
|-&lt;br /&gt;
| 0x2400&lt;br /&gt;
| 0xA410 (3000 * 0xE)&lt;br /&gt;
| Linked list of objects? See chapter&lt;br /&gt;
|-&lt;br /&gt;
| 0xC810&lt;br /&gt;
| 0xE&lt;br /&gt;
| Padding?&lt;br /&gt;
|-&lt;br /&gt;
| 0xC81E&lt;br /&gt;
| 0x2&lt;br /&gt;
| Checksum of all of the above (the first 0xC81E byte). See section [[#Checksum|below]].&lt;br /&gt;
|-&lt;br /&gt;
| 0xC820&lt;br /&gt;
| 0x4&lt;br /&gt;
| Header &amp;quot;CFRA&amp;quot; (Invitations section)&lt;br /&gt;
|-&lt;br /&gt;
| 0xC824&lt;br /&gt;
| 0x4&lt;br /&gt;
| Mii count in this section. Maximum 100&lt;br /&gt;
|-&lt;br /&gt;
| 0xC828&lt;br /&gt;
| 0x64 (100 * 0x1)&lt;br /&gt;
| Order index of Mii in this section?&lt;br /&gt;
|-&lt;br /&gt;
| 0xC88C&lt;br /&gt;
| 0x1C20 (100 * 0x48)&lt;br /&gt;
| Array of Miis contributed from games, used for Mii Plaza &amp;quot;invitations&amp;quot; feature.&amp;lt;br/&amp;gt;The format isn&#039;t that of a full Mii. The &amp;quot;author&amp;quot; field is missing&lt;br /&gt;
|-&lt;br /&gt;
| 0xE4AC&lt;br /&gt;
| 0x12&lt;br /&gt;
| 01 00 [..] 00&lt;br /&gt;
|-&lt;br /&gt;
| 0xE4BE&lt;br /&gt;
| 0x2&lt;br /&gt;
| Checksum over the data above starting from 0xC820&lt;br /&gt;
|-&lt;br /&gt;
| 0xE4C0&lt;br /&gt;
| 0x3D860 (3000 * 0x54)&lt;br /&gt;
| Another array of Miis. Seems related to the CFHE section. &amp;lt;br/&amp;gt;The Mii format in this section is modified. The &amp;quot;author&amp;quot; field is missing, A 4-byte timestamp (seconds since 2000) together with 8-byte zeros(?) is appended at the end.&lt;br /&gt;
|}&lt;br /&gt;
When encrypted in QR codes, 4 additional bytes are added. Two null bytes and a CRC-16. It&#039;s the exact same CRC-16 as for the Wii blocks on the 0x5e first bytes. It seems that the CRC is ignored, the Mii Maker expecting the result of APT:Unwrap to detect integrity loss.&lt;br /&gt;
&lt;br /&gt;
==CFHE object==&lt;br /&gt;
&lt;br /&gt;
A 0xE-byte long linked list node. The format is 4-byte Mii ID (See Mii format) + 6-byte MAC + 2-byte previous node index (prev) + 2-byte next node index (next).&lt;br /&gt;
&lt;br /&gt;
An invalid node has value: ID = 0, MAC = 0, prev = 0x7FFF, next = 0x7FFF.&lt;br /&gt;
&lt;br /&gt;
The highest bit of these fields has some special meaning and isn&#039;t part of the index value.&lt;br /&gt;
&lt;br /&gt;
==Checksum==&lt;br /&gt;
&lt;br /&gt;
The algorithm used to verify the integrity of the database is based on [http://srecord.sourceforge.net/crc16-ccitt.html CRC16-CCITT], though it&#039;s an incorrect implementation. It is the same algorithm used to verify [http://wiibrew.org/wiki/Mii_Data#Block_format Mii Data on the Wii].&lt;br /&gt;
&lt;br /&gt;
To obtain the correct value for the checksum, apply the algorithm to the first 0xC81E bytes of the database. This can be done using [https://gbatemp.net/threads/tutorial-give-your-mii-gold-pants-and-use-it-for-streetpass.379146/page-24#post-6569186 FixCRC]; alternativly a pseudocode implementation of the checksum algorithm is given below:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
def crc16_CCITTWii(u8[]: data) -&amp;gt; u16:&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Calculate a checksum of data using the CRC16-CCITT implementation of the Wii&lt;br /&gt;
&lt;br /&gt;
    This implementation uses 0x0000 as the starting value, which is different&lt;br /&gt;
    from what CRC16-CCITT specifies.&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    # note: a correct implementation of CRC16-CCITT&lt;br /&gt;
    #       would initialize this to 0xffff&lt;br /&gt;
    u32 crc := 0x0&lt;br /&gt;
&lt;br /&gt;
    for byte in data:&lt;br /&gt;
        # Iterate over every of the 8 bits in byte.&lt;br /&gt;
        # Begin with the most significant bit. (7, 6, ... , 1, 0)&lt;br /&gt;
        for bit in 7..0:&lt;br /&gt;
            # &amp;amp; - binary `and&#039;; &amp;lt;&amp;lt;/&amp;gt;&amp;gt; - bitshift left/right; ^ - binary `xor&#039;&lt;br /&gt;
            crc := (&lt;br /&gt;
                     (crc &amp;lt;&amp;lt; 1) | ((byte &amp;gt;&amp;gt; bit) &amp;amp; 0x1)&lt;br /&gt;
                     ^ (0x1021 if crc &amp;amp; 0x8000 else 0)&lt;br /&gt;
                   )&lt;br /&gt;
&lt;br /&gt;
    for _ in 0..15:&lt;br /&gt;
        crc := (crc &amp;lt;&amp;lt; 1) ^ (0x1021 if crc &amp;amp; 0x8000 else 0)&lt;br /&gt;
&lt;br /&gt;
    # only return the lowest 16 bit of crc&lt;br /&gt;
    return (u16) (crc &amp;amp; 0xffff)&lt;br /&gt;
&lt;br /&gt;
checksum := crc16_CCITTWii(miidb[0:0xc81e]) # checksum over the first 0xc81e bytes&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Mii format==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset&lt;br /&gt;
! Length&lt;br /&gt;
! &lt;br /&gt;
|-&lt;br /&gt;
| 0x0&lt;br /&gt;
| 0x1&lt;br /&gt;
| Always 3?&lt;br /&gt;
|-&lt;br /&gt;
| 0x1&lt;br /&gt;
| 0x1&lt;br /&gt;
| bit 0: allow copying&amp;lt;br/&amp;gt;bit 1: private name?&amp;lt;br/&amp;gt;bit 2-3: region lock (0=no lock, 1=JPN, 2=USA, 3=EUR)&amp;lt;br/&amp;gt;bit4-5:character set(0=JPN+USA+EUR, 1=CHN, 2=KOR, 3=TWN)&lt;br /&gt;
|-&lt;br /&gt;
| 0x2&lt;br /&gt;
| 0x1&lt;br /&gt;
| Mii position shown on the selection screen&amp;lt;br/&amp;gt;bit 0-3: page index &amp;lt;br/&amp;gt;bit 4-7: slot index&lt;br /&gt;
|-&lt;br /&gt;
| 0x3&lt;br /&gt;
| 0x1&lt;br /&gt;
| bit 0-3: ?&amp;lt;br/&amp;gt;bit 4-6: version? (1=Wii, 2=DSi, 3=3DS)&lt;br /&gt;
|-&lt;br /&gt;
| 0x4&lt;br /&gt;
| 0x8&lt;br /&gt;
| System ID (identifies owner, for purpose of enforcing editing restrictions and blue pants).&amp;lt;br/&amp;gt;Is not tied to the MAC address anymore.&lt;br /&gt;
|-&lt;br /&gt;
| 0xC&lt;br /&gt;
| 0x4&lt;br /&gt;
| Mii ID (big-endian 32bit unsigned integer):&amp;lt;br/&amp;gt;Bit 0..27: (bit[0..27] * 2) = date of creation (seconds since 01/01/2010 00:00:00)&amp;lt;br/&amp;gt;Bit 28: Always set?&amp;lt;br/&amp;gt;Bit 29: set for temporary Mii&amp;lt;br/&amp;gt;Bit 30: Set for DSi mii?&amp;lt;br/&amp;gt;Bit 31: not set iff Mii is special&lt;br /&gt;
|-&lt;br /&gt;
| 0x10&lt;br /&gt;
| 0x6&lt;br /&gt;
| Creator&#039;s full MAC&lt;br /&gt;
|-&lt;br /&gt;
| 0x16&lt;br /&gt;
| 0x2&lt;br /&gt;
| Padding (0000)&lt;br /&gt;
|-&lt;br /&gt;
| 0x18&lt;br /&gt;
| 0x2&lt;br /&gt;
| Bit-mapped: Birthday (4bit-day,5bit-month), Sex, Shirt color, Favorite (0x40 bit at 0x19)&lt;br /&gt;
|-&lt;br /&gt;
| 0x1A&lt;br /&gt;
| 0x14&lt;br /&gt;
| UTF-16 Mii Name (10 chars max, 0000 terminated)&lt;br /&gt;
|-&lt;br /&gt;
| 0x2E&lt;br /&gt;
| 0x2&lt;br /&gt;
| width &amp;amp; height&lt;br /&gt;
|-&lt;br /&gt;
| 0x30&lt;br /&gt;
| 0x1&lt;br /&gt;
| bit 0: disable sharing&amp;lt;br/&amp;gt;bit 1-4: face shape&amp;lt;br/&amp;gt;bit 5-7: skin color&lt;br /&gt;
|-&lt;br /&gt;
| 0x31&lt;br /&gt;
| 0x1&lt;br /&gt;
| bit 0-3: wrinkles&amp;lt;br/&amp;gt;bit 4-7: makeup&lt;br /&gt;
|-&lt;br /&gt;
| 0x32&lt;br /&gt;
| 0x1&lt;br /&gt;
| hair style&lt;br /&gt;
|-&lt;br /&gt;
| 0x33&lt;br /&gt;
| 0x1&lt;br /&gt;
| bit 0-2: hair color&amp;lt;br/&amp;gt;bit 3: flip hair&lt;br /&gt;
|-&lt;br /&gt;
| 0x34&lt;br /&gt;
| 0x4&lt;br /&gt;
| bit 0-5: eye style&amp;lt;br/&amp;gt;bit 6-8: eye color &amp;lt;br/&amp;gt;bit 9-12: eye scale &amp;lt;br/&amp;gt;bit 13-15: eye yscale&amp;lt;br/&amp;gt;bit 16-20: eye rotation&amp;lt;br/&amp;gt;bit 21-24: eye x spacing&amp;lt;br/&amp;gt;bit 25-29: eye y position&lt;br /&gt;
|-&lt;br /&gt;
| 0x38&lt;br /&gt;
| 0x4&lt;br /&gt;
| bit 0-4: eyebrow style&amp;lt;br/&amp;gt;bit 5-7: eyebrow color &amp;lt;br/&amp;gt;bit 8-11: eyebrow scale&amp;lt;br/&amp;gt;bit 12-14: eyebrow yscale &amp;lt;br/&amp;gt;bit 16-19: eyebrow rotation&amp;lt;br/&amp;gt;bit 21-24: eyebrow x spacing&amp;lt;br/&amp;gt;bit 25-29: eyebrow y position&lt;br /&gt;
|-&lt;br /&gt;
| 0x3C&lt;br /&gt;
| 0x2&lt;br /&gt;
| bit 0-4: nose style&amp;lt;br/&amp;gt;bit 5-8: nose scale&amp;lt;br/&amp;gt;bit 9-13: nose y position&lt;br /&gt;
|-&lt;br /&gt;
| 0x3E&lt;br /&gt;
| 0x2&lt;br /&gt;
| bit 0-5: mouse style&amp;lt;br/&amp;gt;biy 6-8: mouse color&amp;lt;br/&amp;gt;bit 9-12: mouse scale&amp;lt;br/&amp;gt;bit 13-15: mouse yscale&lt;br /&gt;
|-&lt;br /&gt;
| 0x40&lt;br /&gt;
| 0x2&lt;br /&gt;
| bit 0-4: mouse y position&amp;lt;br/&amp;gt;bit 5-7: mustach style&lt;br /&gt;
|-&lt;br /&gt;
| 0x42&lt;br /&gt;
| 0x2&lt;br /&gt;
| bit 0-2: beard style&amp;lt;br/&amp;gt;bit 3-5: beard color&amp;lt;br/&amp;gt;bit 6-9: mustache scale&amp;lt;br/&amp;gt;bit 10-14:mustache y position&lt;br /&gt;
|-&lt;br /&gt;
| 0x44&lt;br /&gt;
| 0x2&lt;br /&gt;
| bit 0-3: glasses style&amp;lt;br/&amp;gt;bit 4-6: glasses color&amp;lt;br/&amp;gt;bit 7-10: glasses scale&amp;lt;br/&amp;gt;bit 11-15: glasses y position&lt;br /&gt;
|-&lt;br /&gt;
| 0x46&lt;br /&gt;
| 0x2&lt;br /&gt;
| bit 0: enable mole&amp;lt;br/&amp;gt;bit 1-4: mole scale&amp;lt;br/&amp;gt;bit 5-9: mole x position&amp;lt;br/&amp;gt;bit 10-14: mole y position&lt;br /&gt;
|-&lt;br /&gt;
| 0x48&lt;br /&gt;
| 0x14&lt;br /&gt;
| UTF-16 Author Name (10 chars max, 0000 terminated)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Mii categories (pants colors)==&lt;br /&gt;
&lt;br /&gt;
====Special (gold) Miis====&lt;br /&gt;
Specialness will override any other color and make the Mii non-editable.&lt;br /&gt;
&lt;br /&gt;
Copying is rumored to have to be disabled.&lt;br /&gt;
&lt;br /&gt;
Zeroed system-id and timestamp?&lt;br /&gt;
&lt;br /&gt;
====Imported (blue) Miis====&lt;br /&gt;
Any (non-gold) Mii with a different System ID will appear as a foreign one.&lt;br /&gt;
&lt;br /&gt;
There is also a range of Mii IDs that are always foreign and uneditable, regardless of the System ID:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====Regular (black/red) Miis====&lt;br /&gt;
Always editable, since they can only appear as such on the console that created them.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====Personal (red) Mii====&lt;br /&gt;
A red Mii that happens to be the first in the file!&lt;br /&gt;
&lt;br /&gt;
==Mii values==&lt;br /&gt;
Each of the following values were found with NTR Debugger:&lt;br /&gt;
If you want to access the value, grab the given &amp;quot;NTR address&amp;quot; and add 0x08815000.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Data&lt;br /&gt;
! NTR address&lt;br /&gt;
! Variation (hex)&lt;br /&gt;
! Notes&lt;br /&gt;
|-&lt;br /&gt;
| Face style&lt;br /&gt;
| 0x894&lt;br /&gt;
| 00-0B&lt;br /&gt;
| Not ordered as in editor, read below&lt;br /&gt;
|-&lt;br /&gt;
| Face color&lt;br /&gt;
| 0x898&lt;br /&gt;
| 00-05&lt;br /&gt;
| From top to bottom&lt;br /&gt;
|-&lt;br /&gt;
| Wrinkles&lt;br /&gt;
| 0x89C&lt;br /&gt;
| 00-0B&lt;br /&gt;
| Same order as displayed in editor&lt;br /&gt;
|-&lt;br /&gt;
| Makeup&lt;br /&gt;
| 0x8A0&lt;br /&gt;
| 00-0B&lt;br /&gt;
| Same order as displayed in editor&lt;br /&gt;
|-&lt;br /&gt;
| Hair style&lt;br /&gt;
| 0x8A4&lt;br /&gt;
| 00-84&lt;br /&gt;
| Not ordered as in editor, read below&lt;br /&gt;
|-&lt;br /&gt;
| Hair color&lt;br /&gt;
| 0x8A8&lt;br /&gt;
| 00-07&lt;br /&gt;
| From top to bottom&lt;br /&gt;
|-&lt;br /&gt;
| Hair flipped&lt;br /&gt;
| 0x8AC&lt;br /&gt;
| 1 if true&lt;br /&gt;
| From top to bottom&lt;br /&gt;
|-&lt;br /&gt;
| Eye style&lt;br /&gt;
| 0x8B0&lt;br /&gt;
| 00-3C&lt;br /&gt;
| Not ordered as in editor, read below&lt;br /&gt;
|-&lt;br /&gt;
| Eyes color&lt;br /&gt;
| 0x8B4&lt;br /&gt;
| 00-05&lt;br /&gt;
| From top to bottom&lt;br /&gt;
|-&lt;br /&gt;
| Eyes size&lt;br /&gt;
| 0x8B8&lt;br /&gt;
| 07-00&lt;br /&gt;
| Left button increases value.&lt;br /&gt;
|-&lt;br /&gt;
| Eyes thickness&lt;br /&gt;
| 0x8BC&lt;br /&gt;
| 06-00&lt;br /&gt;
| Left button increases value.&lt;br /&gt;
|-&lt;br /&gt;
| Eyes rotation&lt;br /&gt;
| 0x8C0&lt;br /&gt;
| 00-07&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| Eyes spacing&lt;br /&gt;
| 0x8C4&lt;br /&gt;
| 00-0C&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| Eyes height&lt;br /&gt;
| 0x8C8&lt;br /&gt;
| 00-12&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| Eyebrows style&lt;br /&gt;
| 0x8CC&lt;br /&gt;
| 00-18&lt;br /&gt;
| Not ordered as in editor, read below&lt;br /&gt;
|-&lt;br /&gt;
| Eyebrows color&lt;br /&gt;
| 0x8D0&lt;br /&gt;
| 00-07&lt;br /&gt;
| From top to bottom&lt;br /&gt;
|-&lt;br /&gt;
| Eyebrows size&lt;br /&gt;
| 0x8D4&lt;br /&gt;
| 08-00&lt;br /&gt;
| Left button increases value.&lt;br /&gt;
|-&lt;br /&gt;
| Eyebrows thickness&lt;br /&gt;
| 0x8D8&lt;br /&gt;
| 06-00&lt;br /&gt;
| Left button increases value.&lt;br /&gt;
|-&lt;br /&gt;
| Eyebrows rotation&lt;br /&gt;
| 0x8DC&lt;br /&gt;
| 00-0B&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| Eyebrows spacing&lt;br /&gt;
| 0x8E0&lt;br /&gt;
| 00-0C&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| Eyebrows height&lt;br /&gt;
| 0x8E4&lt;br /&gt;
| 03-12&lt;br /&gt;
| Yup, minimum is 0x03&lt;br /&gt;
|-&lt;br /&gt;
| Nose style&lt;br /&gt;
| 0x8E8&lt;br /&gt;
| 00-11&lt;br /&gt;
| Not ordered as in editor, read below&lt;br /&gt;
|-&lt;br /&gt;
| Nose size&lt;br /&gt;
| 0x8EC&lt;br /&gt;
| 08-00&lt;br /&gt;
| Left button increases value.&lt;br /&gt;
|-&lt;br /&gt;
| Nose height&lt;br /&gt;
| 0x8F0&lt;br /&gt;
| 00-12&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| Mouth style&lt;br /&gt;
| 0x8F4&lt;br /&gt;
| 00-23&lt;br /&gt;
| Not ordered as in editor, read below&lt;br /&gt;
|-&lt;br /&gt;
| Mouth color&lt;br /&gt;
| 0x8F8&lt;br /&gt;
| 00-04&lt;br /&gt;
| From top to bottom.&lt;br /&gt;
|-&lt;br /&gt;
| Mouth size&lt;br /&gt;
| 0x8FC&lt;br /&gt;
| 08-00&lt;br /&gt;
| Left button increases value.&lt;br /&gt;
|-&lt;br /&gt;
| Mouth thickness&lt;br /&gt;
| 0x900&lt;br /&gt;
| 06-00&lt;br /&gt;
| Left button increases value.&lt;br /&gt;
|-&lt;br /&gt;
| Mouth height&lt;br /&gt;
| 0x904&lt;br /&gt;
| 00-12&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| Mustache style&lt;br /&gt;
| 0x908&lt;br /&gt;
| 00-05&lt;br /&gt;
| Order like in editor.&lt;br /&gt;
|-&lt;br /&gt;
| Beard style&lt;br /&gt;
| 0x90C&lt;br /&gt;
| 00-05&lt;br /&gt;
| Order like in editor.&lt;br /&gt;
|-&lt;br /&gt;
| Mustache/Beard color&lt;br /&gt;
| 0x910&lt;br /&gt;
| 00-07&lt;br /&gt;
| From top to button.&lt;br /&gt;
|-&lt;br /&gt;
| Mustache size&lt;br /&gt;
| 0x914&lt;br /&gt;
| 08-00&lt;br /&gt;
| Left button increases value.&lt;br /&gt;
|-&lt;br /&gt;
| Mustache height&lt;br /&gt;
| 0x918&lt;br /&gt;
| 00-10&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| Glasses style&lt;br /&gt;
| 0x91C&lt;br /&gt;
| 00-08&lt;br /&gt;
| Order like in editor.&lt;br /&gt;
|-&lt;br /&gt;
| Glasses color&lt;br /&gt;
| 0x920&lt;br /&gt;
| 00-05&lt;br /&gt;
| From top to bottom&lt;br /&gt;
|-&lt;br /&gt;
| Glasses size&lt;br /&gt;
| 0x924&lt;br /&gt;
| 07-00&lt;br /&gt;
| Left button increases value.&lt;br /&gt;
|-&lt;br /&gt;
| Glasses height&lt;br /&gt;
| 0x928&lt;br /&gt;
| 00-14&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| Mole enable&lt;br /&gt;
| 0x92C&lt;br /&gt;
| 1 if enabled, 0 else.&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| Mole size&lt;br /&gt;
| 0x930&lt;br /&gt;
| 08-00&lt;br /&gt;
| Left button increases value.&lt;br /&gt;
|-&lt;br /&gt;
| Mole horiz pos&lt;br /&gt;
| 0x934&lt;br /&gt;
| 00-10&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| Mole vert pos&lt;br /&gt;
| 0x938&lt;br /&gt;
| 00-1E&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| Mii height&lt;br /&gt;
| 0x93C&lt;br /&gt;
| 00-7F&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| Mii weight&lt;br /&gt;
| 0x940&lt;br /&gt;
| 00-7F&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| Mii name&lt;br /&gt;
| 0x944-0x959&lt;br /&gt;
| UTF-16&lt;br /&gt;
| Terminated with 0x0000. Not updated immediatly?&lt;br /&gt;
|-&lt;br /&gt;
| Creator&#039;s name&lt;br /&gt;
| 0x95A-96F&lt;br /&gt;
| UTF-16&lt;br /&gt;
| Terminated with 0x0000. Not updated immediatly?&lt;br /&gt;
|-&lt;br /&gt;
| Mii gender&lt;br /&gt;
| 0x970&lt;br /&gt;
| 0: Male, 1: Female&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| Birthdate month&lt;br /&gt;
| 0x974&lt;br /&gt;
| 01-0C&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| Birthdate day&lt;br /&gt;
| 0x978&lt;br /&gt;
| 01-1F&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| Mii shirt color&lt;br /&gt;
| 0x97C&lt;br /&gt;
| 00-0B&lt;br /&gt;
| Ordered like in editor.&lt;br /&gt;
|-&lt;br /&gt;
| Favorite&lt;br /&gt;
| 0x980&lt;br /&gt;
| 0: false, 1: true&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| Allow copy&lt;br /&gt;
| 0x981&lt;br /&gt;
| 0: false, 1: true&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| Unused byte?&lt;br /&gt;
| 0x982&lt;br /&gt;
| &lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| Allow sharing&lt;br /&gt;
| 0x983&lt;br /&gt;
| 0: true, 1: false&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
| ???&lt;br /&gt;
| 0x984-0x98F&lt;br /&gt;
| All zero?&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
| ???&lt;br /&gt;
| 0x990-0x997&lt;br /&gt;
| 4?&lt;br /&gt;
|&lt;br /&gt;
|}&lt;br /&gt;
0x08815998: Same 4 bytes as encrypted Mii: first 4 bits for Mii type, 4 next for number of seconds since 01/01/2010 00:00:00 UTC+3 (should be verified by other country and region 3DS) divided by 2.&lt;br /&gt;
0x0881599C: 6 bytes of MAC address of the 3DS that created the Mii.&lt;br /&gt;
0x088159A2: 6 unknow uses bytes&lt;br /&gt;
0x088159A8: Same 8 bytes as decrypted Mii at 0x04 through 0x0B. Seems NAND specific, kept the same on Miis created on same NAND but different 3DS via System Transfer. Might be a coincidence but the two first bytes are in ID0 folder name in the Nintendo 3DS folder.&lt;br /&gt;
&lt;br /&gt;
===Mapped Editor &amp;lt;-&amp;gt; Hex values===&lt;br /&gt;
&lt;br /&gt;
Most of the values are ordered (left button decreases, right increases, color choices are top to bottom...) but for most &amp;quot;main&amp;quot; part of the UI, where you choose the style of the part being edited, hex values has no correlation with displayed order.&lt;br /&gt;
Here is a JSON that can go from a Part, a Page and Position to the right hex value. This is 0 indexed (eg: datas[&amp;quot;face&amp;quot;][0][11]).&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;{&lt;br /&gt;
face: [&lt;br /&gt;
    0x00,0x01,0x08,&lt;br /&gt;
    0x02,0x03,0x09,&lt;br /&gt;
    0x04,0x05,0x0a,&lt;br /&gt;
    0x06,0x07,0x0b&lt;br /&gt;
],&lt;br /&gt;
hairs: [&lt;br /&gt;
    [0x21,0x2f,0x28,&lt;br /&gt;
    0x25,0x20,0x6b,&lt;br /&gt;
    0x30,0x33,0x37,&lt;br /&gt;
    0x46,0x2c,0x42],&lt;br /&gt;
    [0x34,0x32,0x26,&lt;br /&gt;
    0x31,0x2b,0x1f,&lt;br /&gt;
    0x38,0x44,0x3e,&lt;br /&gt;
    0x73,0x4c,0x77],&lt;br /&gt;
    [0x40,0x51,0x74,&lt;br /&gt;
    0x79,0x16,0x3a,&lt;br /&gt;
    0x3c,0x57,0x7d,&lt;br /&gt;
    0x75,0x49,0x4b],&lt;br /&gt;
    [0x2a,0x59,0x39,&lt;br /&gt;
    0x36,0x50,0x22,&lt;br /&gt;
    0x17,0x56,0x58,&lt;br /&gt;
    0x76,0x27,0x24],&lt;br /&gt;
    [0x2d,0x43,0x3b,&lt;br /&gt;
    0x41,0x29,0x1e,&lt;br /&gt;
    0x0c,0x10,0x0a,&lt;br /&gt;
    0x52,0x80,0x81],&lt;br /&gt;
    [0x0e,0x5f,0x69,&lt;br /&gt;
    0x64,0x06,0x14,&lt;br /&gt;
    0x5d,0x66,0x1b,&lt;br /&gt;
    0x04,0x11,0x6e]&lt;br /&gt;
    [0x7b,0x08,0x6a,&lt;br /&gt;
    0x48,0x03,0x15,&lt;br /&gt;
    0x00,0x62,0x3f,&lt;br /&gt;
    0x5a,0x0b,0x78],&lt;br /&gt;
    [0x05,0x4a,0x6c,&lt;br /&gt;
    0x5e,0x7c,0x19,&lt;br /&gt;
    0x63,0x45,0x23,&lt;br /&gt;
    0x0d,0x7a,0x71],&lt;br /&gt;
    [0x35,0x18,0x55,&lt;br /&gt;
    0x53,0x47,0x83,&lt;br /&gt;
    0x60,0x65,0x1d,&lt;br /&gt;
    0x07,0x0f,0x70],&lt;br /&gt;
    [0x4f,0x01,0x6d,&lt;br /&gt;
    0x7f,0x5b,0x1a,&lt;br /&gt;
    0x3d,0x67,0x02,&lt;br /&gt;
    0x4d,0x12,0x5c],&lt;br /&gt;
    [0x54,0x09,0x13,&lt;br /&gt;
    0x82,0x61,0x68,&lt;br /&gt;
    0x2e,0x4e,0x1c,&lt;br /&gt;
    0x72,0x7e,0x6f]&lt;br /&gt;
],&lt;br /&gt;
eyebrows: [&lt;br /&gt;
    [0x06,0x00,0x0c,&lt;br /&gt;
    0x01,0x09,0x13,&lt;br /&gt;
    0x07,0x15,0x08,&lt;br /&gt;
    0x11,0x05,0x04],&lt;br /&gt;
    [0x0b,0x0a,0x02,&lt;br /&gt;
    0x03,0x0e,0x14,&lt;br /&gt;
    0x0f,0x0d,0x16,&lt;br /&gt;
    0x12,0x10,0x17]&lt;br /&gt;
],&lt;br /&gt;
nose: [&lt;br /&gt;
    [0x01,0x0a,0x02,&lt;br /&gt;
    0x03,0x06,0x00,&lt;br /&gt;
    0x05,0x04,0x08,&lt;br /&gt;
    0x09,0x07,0x0B],&lt;br /&gt;
    [0x0d,0x0e,0x0c,&lt;br /&gt;
    0x11,0x10,0x0f]&lt;br /&gt;
],&lt;br /&gt;
mouth: [&lt;br /&gt;
    [0x17,0x01,0x13,&lt;br /&gt;
    0x15,0x16,0x05,&lt;br /&gt;
    0x00,0x08,0x0a,&lt;br /&gt;
    0x10,0x06,0x0d],&lt;br /&gt;
    [0x07,0x09,0x02,&lt;br /&gt;
    0x11,0x03,0x04,&lt;br /&gt;
    0x0f,0x0b,0x14,&lt;br /&gt;
    0x12,0x0e,0x0c],&lt;br /&gt;
    [0x1b,0x1e,0x18,&lt;br /&gt;
    0x19,0x1d,0x1c,&lt;br /&gt;
    0x1a,0x23,0x1f,&lt;br /&gt;
    0x22,0x21,0x20]&lt;br /&gt;
]&lt;br /&gt;
}&amp;lt;/nowiki&amp;gt;&lt;/div&gt;</summary>
		<author><name>Wwylele</name></author>
	</entry>
	<entry>
		<id>https://www.3dbrew.org/w/index.php?title=Mii&amp;diff=20904</id>
		<title>Mii</title>
		<link rel="alternate" type="text/html" href="https://www.3dbrew.org/w/index.php?title=Mii&amp;diff=20904"/>
		<updated>2019-03-05T16:08:09Z</updated>

		<summary type="html">&lt;p&gt;Wwylele: /* Mii Header */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Originally [http://wiibrew.org/wiki/Mii_Data created for the Nintendo Wii] (and backported to a selection of DS/i games), the &#039;&#039;&#039;Mii&#039;&#039;&#039; format was expanded with a larger selection of facial features and a new &amp;quot;copying&amp;quot; permission for the 3DS family, and later implemented as-is on Wii U.&lt;br /&gt;
&lt;br /&gt;
See [[Mii Maker]] for the application chiefly designed to create, edit, delete, and trade Miis or convert them from and to a QR code.&lt;br /&gt;
&lt;br /&gt;
The default endianness in this page is little-endian, unless explicitly specified.&lt;br /&gt;
&lt;br /&gt;
==Mii Database==&lt;br /&gt;
Format of the Mii main database &#039;&#039;&#039;CFL_DB.dat&#039;&#039;&#039;, found in [[Extdata#NAND_Shared_Extdata|shared extdata]] archive f0000000b.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset&lt;br /&gt;
! Length&lt;br /&gt;
! &lt;br /&gt;
|-&lt;br /&gt;
| 0x0&lt;br /&gt;
| 0x4&lt;br /&gt;
| Header &amp;quot;CFOG&amp;quot; (Mii Maker section)&lt;br /&gt;
|-&lt;br /&gt;
| 0x4&lt;br /&gt;
| 0x4&lt;br /&gt;
| Header 0x00010000&lt;br /&gt;
|-&lt;br /&gt;
| 0x8&lt;br /&gt;
| 0x23F0 (100 * 0x5C)&lt;br /&gt;
| Array of owned (saved in Mii Maker) Miis. Order in file is unrelated to canonical order in-app.&lt;br /&gt;
|-&lt;br /&gt;
| 0x23F8&lt;br /&gt;
| 0x4&lt;br /&gt;
| Header &amp;quot;CFHE&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| 0x23FC&lt;br /&gt;
| 0x2&lt;br /&gt;
| Linked list tail index. 0xFFFF if the list is empty&lt;br /&gt;
|-&lt;br /&gt;
| 0x23FE&lt;br /&gt;
| 0x2&lt;br /&gt;
| Linked list head index. 0xFFFF if the list is empty&lt;br /&gt;
|-&lt;br /&gt;
| 0x2400&lt;br /&gt;
| 0xA410 (3000 * 0xE)&lt;br /&gt;
| Linked list of objects? See chapter&lt;br /&gt;
|-&lt;br /&gt;
| 0xC810&lt;br /&gt;
| 0xE&lt;br /&gt;
| Padding?&lt;br /&gt;
|-&lt;br /&gt;
| 0xC81E&lt;br /&gt;
| 0x2&lt;br /&gt;
| Checksum of all of the above (the first 0xC81E byte). See section [[#Checksum|below]].&lt;br /&gt;
|-&lt;br /&gt;
| 0xC820&lt;br /&gt;
| 0x4&lt;br /&gt;
| Header &amp;quot;CFRA&amp;quot; (Invitations section)&lt;br /&gt;
|-&lt;br /&gt;
| 0xC824&lt;br /&gt;
| 0x4&lt;br /&gt;
| Mii count in this section. Maximum 100&lt;br /&gt;
|-&lt;br /&gt;
| 0xC828&lt;br /&gt;
| 0x64 (100 * 0x1)&lt;br /&gt;
| Order index of Mii in this section?&lt;br /&gt;
|-&lt;br /&gt;
| 0xC88C&lt;br /&gt;
| 0x1C20 (100 * 0x48)&lt;br /&gt;
| Array of Miis contributed from games, used for Mii Plaza &amp;quot;invitations&amp;quot; feature.&amp;lt;br/&amp;gt;The format isn&#039;t that of a full Mii. The &amp;quot;author&amp;quot; field is missing&lt;br /&gt;
|-&lt;br /&gt;
| 0xE4AC&lt;br /&gt;
| 0x12&lt;br /&gt;
| 01 00 [..] 00&lt;br /&gt;
|-&lt;br /&gt;
| 0xE4BE&lt;br /&gt;
| 0x2&lt;br /&gt;
| Checksum over the data above starting from 0xC820&lt;br /&gt;
|-&lt;br /&gt;
| 0xE4C0&lt;br /&gt;
| 0x3D860 (3000 * 0x54)&lt;br /&gt;
| Another array of Miis. Seems related to the CFHE section. &amp;lt;br/&amp;gt;The Mii format in this section is modified. The &amp;quot;author&amp;quot; field is missing, A 4-byte timestamp (seconds since 2000) together with 8-byte zeros(?) is appended at the end.&lt;br /&gt;
|}&lt;br /&gt;
When encrypted in QR codes, 4 additional bytes are added. Two null bytes and a CRC-16. It&#039;s the exact same CRC-16 as for the Wii blocks on the 0x5e first bytes. It seems that the CRC is ignored, the Mii Maker expecting the result of APT:Unwrap to detect integrity loss.&lt;br /&gt;
&lt;br /&gt;
==CFHE object==&lt;br /&gt;
&lt;br /&gt;
A 0xE-byte long linked list node. The format is 4-byte Mii ID (See Mii format) + 6-byte MAC + 2-byte previous node index (prev) + 2-byte next node index (next).&lt;br /&gt;
&lt;br /&gt;
An invalid node has value: ID = 0, MAC = 0, prev = 0x7FFF, next = 0x7FFF.&lt;br /&gt;
&lt;br /&gt;
The highest bit of these fields has some special meaning and isn&#039;t part of the index value.&lt;br /&gt;
&lt;br /&gt;
==Checksum==&lt;br /&gt;
&lt;br /&gt;
The algorithm used to verify the integrity of the database is based on [http://srecord.sourceforge.net/crc16-ccitt.html CRC16-CCITT], though it&#039;s an incorrect implementation. It is the same algorithm used to verify [http://wiibrew.org/wiki/Mii_Data#Block_format Mii Data on the Wii].&lt;br /&gt;
&lt;br /&gt;
To obtain the correct value for the checksum, apply the algorithm to the first 0xC81E bytes of the database. This can be done using [https://gbatemp.net/threads/tutorial-give-your-mii-gold-pants-and-use-it-for-streetpass.379146/page-24#post-6569186 FixCRC]; alternativly a pseudocode implementation of the checksum algorithm is given below:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
def crc16_CCITTWii(u8[]: data) -&amp;gt; u16:&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Calculate a checksum of data using the CRC16-CCITT implementation of the Wii&lt;br /&gt;
&lt;br /&gt;
    This implementation uses 0x0000 as the starting value, which is different&lt;br /&gt;
    from what CRC16-CCITT specifies.&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    # note: a correct implementation of CRC16-CCITT&lt;br /&gt;
    #       would initialize this to 0xffff&lt;br /&gt;
    u32 crc := 0x0&lt;br /&gt;
&lt;br /&gt;
    for byte in data:&lt;br /&gt;
        # Iterate over every of the 8 bits in byte.&lt;br /&gt;
        # Begin with the most significant bit. (7, 6, ... , 1, 0)&lt;br /&gt;
        for bit in 7..0:&lt;br /&gt;
            # &amp;amp; - binary `and&#039;; &amp;lt;&amp;lt;/&amp;gt;&amp;gt; - bitshift left/right; ^ - binary `xor&#039;&lt;br /&gt;
            crc := (&lt;br /&gt;
                     (crc &amp;lt;&amp;lt; 1) | ((byte &amp;gt;&amp;gt; bit) &amp;amp; 0x1)&lt;br /&gt;
                     ^ (0x1021 if crc &amp;amp; 0x8000 else 0)&lt;br /&gt;
                   )&lt;br /&gt;
&lt;br /&gt;
    for _ in 0..15:&lt;br /&gt;
        crc := (crc &amp;lt;&amp;lt; 1) ^ (0x1021 if crc &amp;amp; 0x8000 else 0)&lt;br /&gt;
&lt;br /&gt;
    # only return the lowest 16 bit of crc&lt;br /&gt;
    return (u16) (crc &amp;amp; 0xffff)&lt;br /&gt;
&lt;br /&gt;
checksum := crc16_CCITTWii(miidb[0:0xc81e]) # checksum over the first 0xc81e bytes&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Mii format==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset&lt;br /&gt;
! Length&lt;br /&gt;
! &lt;br /&gt;
|-&lt;br /&gt;
| 0x0&lt;br /&gt;
| 0x1&lt;br /&gt;
| Always 3?&lt;br /&gt;
|-&lt;br /&gt;
| 0x1&lt;br /&gt;
| 0x1&lt;br /&gt;
| bit 0: allow copying&amp;lt;br/&amp;gt;bit 1: private name?&amp;lt;br/&amp;gt;bit 2-3: region lock (0=no lock, 1=JPN, 2=USA, 3=EUR)&amp;lt;br/&amp;gt;bit4-5:character set(0=JPN+USA+EUR, 1=CHN, 2=KOR, 3=TWN)&lt;br /&gt;
|-&lt;br /&gt;
| 0x2&lt;br /&gt;
| 0x1&lt;br /&gt;
| Mii position shown on the selection screen&amp;lt;br/&amp;gt;bit 0-3: page index &amp;lt;br/&amp;gt;bit 4-7: slot index&lt;br /&gt;
|-&lt;br /&gt;
| 0x3&lt;br /&gt;
| 0x1&lt;br /&gt;
| bit 0-3: ?&amp;lt;br/&amp;gt;bit 4-6: version? (1=Wii, 2=DSi, 3=3DS)&lt;br /&gt;
|-&lt;br /&gt;
| 0x4&lt;br /&gt;
| 0x8&lt;br /&gt;
| System ID (identifies owner, for purpose of enforcing editing restrictions and blue pants).&amp;lt;br/&amp;gt;Is not tied to the MAC address anymore.&lt;br /&gt;
|-&lt;br /&gt;
| 0xC&lt;br /&gt;
| 0x4&lt;br /&gt;
| Mii ID (big-endian 32bit unsigned integer):&amp;lt;br/&amp;gt;Bit 0..27: (bit[0..27] * 2) = date of creation (seconds since 01/01/2010 00:00:00)&amp;lt;br/&amp;gt;Bit 28: Always set?&amp;lt;br/&amp;gt;Bit 29: set for temporary Mii&amp;lt;br/&amp;gt;Bit 30: Set for DSi mii?&amp;lt;br/&amp;gt;Bit 31: not set iff Mii is special&lt;br /&gt;
|-&lt;br /&gt;
| 0x10&lt;br /&gt;
| 0x6&lt;br /&gt;
| Creator&#039;s full MAC&lt;br /&gt;
|-&lt;br /&gt;
| 0x16&lt;br /&gt;
| 0x2&lt;br /&gt;
| Padding (0000)&lt;br /&gt;
|-&lt;br /&gt;
| 0x18&lt;br /&gt;
| 0x2&lt;br /&gt;
| Bit-mapped: Birthday (4bit-day,5bit-month), Sex, Shirt color, Favorite (0x40 bit at 0x19)&lt;br /&gt;
|-&lt;br /&gt;
| 0x1A&lt;br /&gt;
| 0x14&lt;br /&gt;
| UTF-16 Mii Name (10 chars max, 0000 terminated)&lt;br /&gt;
|-&lt;br /&gt;
| 0x2E&lt;br /&gt;
| 0x2&lt;br /&gt;
| width &amp;amp; height&lt;br /&gt;
|-&lt;br /&gt;
| 0x30&lt;br /&gt;
| 0x1&lt;br /&gt;
| bit 0: disable sharing&amp;lt;br/&amp;gt;bit 1-4: face shape&amp;lt;br/&amp;gt;bit 5-7: skin color&lt;br /&gt;
|-&lt;br /&gt;
| 0x31&lt;br /&gt;
| 0x1&lt;br /&gt;
| bit 0-3: wrinkles&amp;lt;br/&amp;gt;bit 4-7: makeup&lt;br /&gt;
|-&lt;br /&gt;
| 0x32&lt;br /&gt;
| 0x1&lt;br /&gt;
| hair style&lt;br /&gt;
|-&lt;br /&gt;
| 0x33&lt;br /&gt;
| 0x1&lt;br /&gt;
| bit 0-2: hair color&amp;lt;br/&amp;gt;bit 3: flip hair&lt;br /&gt;
|-&lt;br /&gt;
| 0x34&lt;br /&gt;
| 0x4&lt;br /&gt;
| bit 0-5: eye style&amp;lt;br/&amp;gt;bit 6-8: eye color &amp;lt;br/&amp;gt;bit 9-12: eye scale &amp;lt;br/&amp;gt;bit 13-15: eye yscale&amp;lt;br/&amp;gt;bit 16-20: eye rotation&amp;lt;br/&amp;gt;bit 21-24: eye x spacing&amp;lt;br/&amp;gt;bit 25-29: eye y position&lt;br /&gt;
|-&lt;br /&gt;
| 0x38&lt;br /&gt;
| 0x4&lt;br /&gt;
| bit 0-4: eyebrow style&amp;lt;br/&amp;gt;bit 5-7: eyebrow color &amp;lt;br/&amp;gt;bit 8-11: eyebrow scale&amp;lt;br/&amp;gt;bit 12-14: eyebrow yscale &amp;lt;br/&amp;gt;bit 16-19: eyebrow rotation&amp;lt;br/&amp;gt;bit 21-24: eyebrow x spacing&amp;lt;br/&amp;gt;bit 25-29: eyebrow y position&lt;br /&gt;
|-&lt;br /&gt;
| 0x3C&lt;br /&gt;
| 0x2&lt;br /&gt;
| bit 0-4: nose style&amp;lt;br/&amp;gt;bit 5-8: nose scale&amp;lt;br/&amp;gt;bit 9-13: nose y position&lt;br /&gt;
|-&lt;br /&gt;
| 0x3E&lt;br /&gt;
| 0x2&lt;br /&gt;
| bit 0-5: mouse style&amp;lt;br/&amp;gt;biy 6-8: mouse color&amp;lt;br/&amp;gt;bit 9-12: mouse scale&amp;lt;br/&amp;gt;bit 13-15: mouse yscale&lt;br /&gt;
|-&lt;br /&gt;
| 0x40&lt;br /&gt;
| 0x2&lt;br /&gt;
| bit 0-4: mouse y position&amp;lt;br/&amp;gt;bit 5-7: mustach style&lt;br /&gt;
|-&lt;br /&gt;
| 0x42&lt;br /&gt;
| 0x2&lt;br /&gt;
| bit 0-2: beard style&amp;lt;br/&amp;gt;bit 3-5: beard color&amp;lt;br/&amp;gt;bit 6-9: mustache scale&amp;lt;br/&amp;gt;bit 10-14:mustache y position&lt;br /&gt;
|-&lt;br /&gt;
| 0x44&lt;br /&gt;
| 0x2&lt;br /&gt;
| bit 0-3: glasses style&amp;lt;br/&amp;gt;bit 4-6: glasses color&amp;lt;br/&amp;gt;bit 7-10: glasses scale&amp;lt;br/&amp;gt;bit 11-15: glasses y position&lt;br /&gt;
|-&lt;br /&gt;
| 0x46&lt;br /&gt;
| 0x2&lt;br /&gt;
| bit 0: enable mole&amp;lt;br/&amp;gt;bit 1-4: mole scale&amp;lt;br/&amp;gt;bit 5-9: mole x position&amp;lt;br/&amp;gt;bit 10-14: mole y position&lt;br /&gt;
|-&lt;br /&gt;
| 0x48&lt;br /&gt;
| 0x14&lt;br /&gt;
| UTF-16 Author Name (10 chars max, 0000 terminated)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Mii categories (pants colors)==&lt;br /&gt;
&lt;br /&gt;
====Special (gold) Miis====&lt;br /&gt;
Specialness will override any other color and make the Mii non-editable.&lt;br /&gt;
&lt;br /&gt;
Copying is rumored to have to be disabled.&lt;br /&gt;
&lt;br /&gt;
Zeroed system-id and timestamp?&lt;br /&gt;
&lt;br /&gt;
====Imported (blue) Miis====&lt;br /&gt;
Any (non-gold) Mii with a different System ID will appear as a foreign one.&lt;br /&gt;
&lt;br /&gt;
There is also a range of Mii IDs that are always foreign and uneditable, regardless of the System ID:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====Regular (black/red) Miis====&lt;br /&gt;
Always editable, since they can only appear as such on the console that created them.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====Personal (red) Mii====&lt;br /&gt;
A red Mii that happens to be the first in the file!&lt;br /&gt;
&lt;br /&gt;
==Mii values==&lt;br /&gt;
Each of the following values were found with NTR Debugger:&lt;br /&gt;
If you want to access the value, grab the given &amp;quot;NTR address&amp;quot; and add 0x08815000.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Data&lt;br /&gt;
! NTR address&lt;br /&gt;
! Variation (hex)&lt;br /&gt;
! Notes&lt;br /&gt;
|-&lt;br /&gt;
| Face style&lt;br /&gt;
| 0x894&lt;br /&gt;
| 00-0B&lt;br /&gt;
| Not ordered as in editor, read below&lt;br /&gt;
|-&lt;br /&gt;
| Face color&lt;br /&gt;
| 0x898&lt;br /&gt;
| 00-05&lt;br /&gt;
| From top to bottom&lt;br /&gt;
|-&lt;br /&gt;
| Wrinkles&lt;br /&gt;
| 0x89C&lt;br /&gt;
| 00-0B&lt;br /&gt;
| Same order as displayed in editor&lt;br /&gt;
|-&lt;br /&gt;
| Makeup&lt;br /&gt;
| 0x8A0&lt;br /&gt;
| 00-0B&lt;br /&gt;
| Same order as displayed in editor&lt;br /&gt;
|-&lt;br /&gt;
| Hair style&lt;br /&gt;
| 0x8A4&lt;br /&gt;
| 00-84&lt;br /&gt;
| Not ordered as in editor, read below&lt;br /&gt;
|-&lt;br /&gt;
| Hair color&lt;br /&gt;
| 0x8A8&lt;br /&gt;
| 00-07&lt;br /&gt;
| From top to bottom&lt;br /&gt;
|-&lt;br /&gt;
| Hair flipped&lt;br /&gt;
| 0x8AC&lt;br /&gt;
| 1 if true&lt;br /&gt;
| From top to bottom&lt;br /&gt;
|-&lt;br /&gt;
| Eye style&lt;br /&gt;
| 0x8B0&lt;br /&gt;
| 00-3C&lt;br /&gt;
| Not ordered as in editor, read below&lt;br /&gt;
|-&lt;br /&gt;
| Eyes color&lt;br /&gt;
| 0x8B4&lt;br /&gt;
| 00-05&lt;br /&gt;
| From top to bottom&lt;br /&gt;
|-&lt;br /&gt;
| Eyes size&lt;br /&gt;
| 0x8B8&lt;br /&gt;
| 07-00&lt;br /&gt;
| Left button increases value.&lt;br /&gt;
|-&lt;br /&gt;
| Eyes thickness&lt;br /&gt;
| 0x8BC&lt;br /&gt;
| 06-00&lt;br /&gt;
| Left button increases value.&lt;br /&gt;
|-&lt;br /&gt;
| Eyes rotation&lt;br /&gt;
| 0x8C0&lt;br /&gt;
| 00-07&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| Eyes spacing&lt;br /&gt;
| 0x8C4&lt;br /&gt;
| 00-0C&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| Eyes height&lt;br /&gt;
| 0x8C8&lt;br /&gt;
| 00-12&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| Eyebrows style&lt;br /&gt;
| 0x8CC&lt;br /&gt;
| 00-18&lt;br /&gt;
| Not ordered as in editor, read below&lt;br /&gt;
|-&lt;br /&gt;
| Eyebrows color&lt;br /&gt;
| 0x8D0&lt;br /&gt;
| 00-07&lt;br /&gt;
| From top to bottom&lt;br /&gt;
|-&lt;br /&gt;
| Eyebrows size&lt;br /&gt;
| 0x8D4&lt;br /&gt;
| 08-00&lt;br /&gt;
| Left button increases value.&lt;br /&gt;
|-&lt;br /&gt;
| Eyebrows thickness&lt;br /&gt;
| 0x8D8&lt;br /&gt;
| 06-00&lt;br /&gt;
| Left button increases value.&lt;br /&gt;
|-&lt;br /&gt;
| Eyebrows rotation&lt;br /&gt;
| 0x8DC&lt;br /&gt;
| 00-0B&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| Eyebrows spacing&lt;br /&gt;
| 0x8E0&lt;br /&gt;
| 00-0C&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| Eyebrows height&lt;br /&gt;
| 0x8E4&lt;br /&gt;
| 03-12&lt;br /&gt;
| Yup, minimum is 0x03&lt;br /&gt;
|-&lt;br /&gt;
| Nose style&lt;br /&gt;
| 0x8E8&lt;br /&gt;
| 00-11&lt;br /&gt;
| Not ordered as in editor, read below&lt;br /&gt;
|-&lt;br /&gt;
| Nose size&lt;br /&gt;
| 0x8EC&lt;br /&gt;
| 08-00&lt;br /&gt;
| Left button increases value.&lt;br /&gt;
|-&lt;br /&gt;
| Nose height&lt;br /&gt;
| 0x8F0&lt;br /&gt;
| 00-12&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| Mouth style&lt;br /&gt;
| 0x8F4&lt;br /&gt;
| 00-23&lt;br /&gt;
| Not ordered as in editor, read below&lt;br /&gt;
|-&lt;br /&gt;
| Mouth color&lt;br /&gt;
| 0x8F8&lt;br /&gt;
| 00-04&lt;br /&gt;
| From top to bottom.&lt;br /&gt;
|-&lt;br /&gt;
| Mouth size&lt;br /&gt;
| 0x8FC&lt;br /&gt;
| 08-00&lt;br /&gt;
| Left button increases value.&lt;br /&gt;
|-&lt;br /&gt;
| Mouth thickness&lt;br /&gt;
| 0x900&lt;br /&gt;
| 06-00&lt;br /&gt;
| Left button increases value.&lt;br /&gt;
|-&lt;br /&gt;
| Mouth height&lt;br /&gt;
| 0x904&lt;br /&gt;
| 00-12&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| Mustache style&lt;br /&gt;
| 0x908&lt;br /&gt;
| 00-05&lt;br /&gt;
| Order like in editor.&lt;br /&gt;
|-&lt;br /&gt;
| Beard style&lt;br /&gt;
| 0x90C&lt;br /&gt;
| 00-05&lt;br /&gt;
| Order like in editor.&lt;br /&gt;
|-&lt;br /&gt;
| Mustache/Beard color&lt;br /&gt;
| 0x910&lt;br /&gt;
| 00-07&lt;br /&gt;
| From top to button.&lt;br /&gt;
|-&lt;br /&gt;
| Mustache size&lt;br /&gt;
| 0x914&lt;br /&gt;
| 08-00&lt;br /&gt;
| Left button increases value.&lt;br /&gt;
|-&lt;br /&gt;
| Mustache height&lt;br /&gt;
| 0x918&lt;br /&gt;
| 00-10&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| Glasses style&lt;br /&gt;
| 0x91C&lt;br /&gt;
| 00-08&lt;br /&gt;
| Order like in editor.&lt;br /&gt;
|-&lt;br /&gt;
| Glasses color&lt;br /&gt;
| 0x920&lt;br /&gt;
| 00-05&lt;br /&gt;
| From top to bottom&lt;br /&gt;
|-&lt;br /&gt;
| Glasses size&lt;br /&gt;
| 0x924&lt;br /&gt;
| 07-00&lt;br /&gt;
| Left button increases value.&lt;br /&gt;
|-&lt;br /&gt;
| Glasses height&lt;br /&gt;
| 0x928&lt;br /&gt;
| 00-14&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| Mole enable&lt;br /&gt;
| 0x92C&lt;br /&gt;
| 1 if enabled, 0 else.&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| Mole size&lt;br /&gt;
| 0x930&lt;br /&gt;
| 08-00&lt;br /&gt;
| Left button increases value.&lt;br /&gt;
|-&lt;br /&gt;
| Mole horiz pos&lt;br /&gt;
| 0x934&lt;br /&gt;
| 00-10&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| Mole vert pos&lt;br /&gt;
| 0x938&lt;br /&gt;
| 00-1E&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| Mii height&lt;br /&gt;
| 0x93C&lt;br /&gt;
| 00-7F&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| Mii weight&lt;br /&gt;
| 0x940&lt;br /&gt;
| 00-7F&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| Mii name&lt;br /&gt;
| 0x944-0x959&lt;br /&gt;
| UTF-16&lt;br /&gt;
| Terminated with 0x0000. Not updated immediatly?&lt;br /&gt;
|-&lt;br /&gt;
| Creator&#039;s name&lt;br /&gt;
| 0x95A-96F&lt;br /&gt;
| UTF-16&lt;br /&gt;
| Terminated with 0x0000. Not updated immediatly?&lt;br /&gt;
|-&lt;br /&gt;
| Mii gender&lt;br /&gt;
| 0x970&lt;br /&gt;
| 0: Male, 1: Female&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| Birthdate month&lt;br /&gt;
| 0x974&lt;br /&gt;
| 01-0C&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| Birthdate day&lt;br /&gt;
| 0x978&lt;br /&gt;
| 01-1F&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| Mii shirt color&lt;br /&gt;
| 0x97C&lt;br /&gt;
| 00-0B&lt;br /&gt;
| Ordered like in editor.&lt;br /&gt;
|-&lt;br /&gt;
| Favorite&lt;br /&gt;
| 0x980&lt;br /&gt;
| 0: false, 1: true&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| Allow copy&lt;br /&gt;
| 0x981&lt;br /&gt;
| 0: false, 1: true&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| Unused byte?&lt;br /&gt;
| 0x982&lt;br /&gt;
| &lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| Allow sharing&lt;br /&gt;
| 0x983&lt;br /&gt;
| 0: true, 1: false&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
| ???&lt;br /&gt;
| 0x984-0x98F&lt;br /&gt;
| All zero?&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
| ???&lt;br /&gt;
| 0x990-0x997&lt;br /&gt;
| 4?&lt;br /&gt;
|&lt;br /&gt;
|}&lt;br /&gt;
0x08815998: Same 4 bytes as encrypted Mii: first 4 bits for Mii type, 4 next for number of seconds since 01/01/2010 00:00:00 UTC+3 (should be verified by other country and region 3DS) divided by 2.&lt;br /&gt;
0x0881599C: 6 bytes of MAC address of the 3DS that created the Mii.&lt;br /&gt;
0x088159A2: 6 unknow uses bytes&lt;br /&gt;
0x088159A8: Same 8 bytes as decrypted Mii at 0x04 through 0x0B. Seems NAND specific, kept the same on Miis created on same NAND but different 3DS via System Transfer. Might be a coincidence but the two first bytes are in ID0 folder name in the Nintendo 3DS folder.&lt;br /&gt;
&lt;br /&gt;
===Mapped Editor &amp;lt;-&amp;gt; Hex values===&lt;br /&gt;
&lt;br /&gt;
Most of the values are ordered (left button decreases, right increases, color choices are top to bottom...) but for most &amp;quot;main&amp;quot; part of the UI, where you choose the style of the part being edited, hex values has no correlation with displayed order.&lt;br /&gt;
Here is a JSON that can go from a Part, a Page and Position to the right hex value. This is 0 indexed (eg: datas[&amp;quot;face&amp;quot;][0][11]).&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;{&lt;br /&gt;
face: [&lt;br /&gt;
    0x00,0x01,0x08,&lt;br /&gt;
    0x02,0x03,0x09,&lt;br /&gt;
    0x04,0x05,0x0a,&lt;br /&gt;
    0x06,0x07,0x0b&lt;br /&gt;
],&lt;br /&gt;
hairs: [&lt;br /&gt;
    [0x21,0x2f,0x28,&lt;br /&gt;
    0x25,0x20,0x6b,&lt;br /&gt;
    0x30,0x33,0x37,&lt;br /&gt;
    0x46,0x2c,0x42],&lt;br /&gt;
    [0x34,0x32,0x26,&lt;br /&gt;
    0x31,0x2b,0x1f,&lt;br /&gt;
    0x38,0x44,0x3e,&lt;br /&gt;
    0x73,0x4c,0x77],&lt;br /&gt;
    [0x40,0x51,0x74,&lt;br /&gt;
    0x79,0x16,0x3a,&lt;br /&gt;
    0x3c,0x57,0x7d,&lt;br /&gt;
    0x75,0x49,0x4b],&lt;br /&gt;
    [0x2a,0x59,0x39,&lt;br /&gt;
    0x36,0x50,0x22,&lt;br /&gt;
    0x17,0x56,0x58,&lt;br /&gt;
    0x76,0x27,0x24],&lt;br /&gt;
    [0x2d,0x43,0x3b,&lt;br /&gt;
    0x41,0x29,0x1e,&lt;br /&gt;
    0x0c,0x10,0x0a,&lt;br /&gt;
    0x52,0x80,0x81],&lt;br /&gt;
    [0x0e,0x5f,0x69,&lt;br /&gt;
    0x64,0x06,0x14,&lt;br /&gt;
    0x5d,0x66,0x1b,&lt;br /&gt;
    0x04,0x11,0x6e]&lt;br /&gt;
    [0x7b,0x08,0x6a,&lt;br /&gt;
    0x48,0x03,0x15,&lt;br /&gt;
    0x00,0x62,0x3f,&lt;br /&gt;
    0x5a,0x0b,0x78],&lt;br /&gt;
    [0x05,0x4a,0x6c,&lt;br /&gt;
    0x5e,0x7c,0x19,&lt;br /&gt;
    0x63,0x45,0x23,&lt;br /&gt;
    0x0d,0x7a,0x71],&lt;br /&gt;
    [0x35,0x18,0x55,&lt;br /&gt;
    0x53,0x47,0x83,&lt;br /&gt;
    0x60,0x65,0x1d,&lt;br /&gt;
    0x07,0x0f,0x70],&lt;br /&gt;
    [0x4f,0x01,0x6d,&lt;br /&gt;
    0x7f,0x5b,0x1a,&lt;br /&gt;
    0x3d,0x67,0x02,&lt;br /&gt;
    0x4d,0x12,0x5c],&lt;br /&gt;
    [0x54,0x09,0x13,&lt;br /&gt;
    0x82,0x61,0x68,&lt;br /&gt;
    0x2e,0x4e,0x1c,&lt;br /&gt;
    0x72,0x7e,0x6f]&lt;br /&gt;
],&lt;br /&gt;
eyebrows: [&lt;br /&gt;
    [0x06,0x00,0x0c,&lt;br /&gt;
    0x01,0x09,0x13,&lt;br /&gt;
    0x07,0x15,0x08,&lt;br /&gt;
    0x11,0x05,0x04],&lt;br /&gt;
    [0x0b,0x0a,0x02,&lt;br /&gt;
    0x03,0x0e,0x14,&lt;br /&gt;
    0x0f,0x0d,0x16,&lt;br /&gt;
    0x12,0x10,0x17]&lt;br /&gt;
],&lt;br /&gt;
nose: [&lt;br /&gt;
    [0x01,0x0a,0x02,&lt;br /&gt;
    0x03,0x06,0x00,&lt;br /&gt;
    0x05,0x04,0x08,&lt;br /&gt;
    0x09,0x07,0x0B],&lt;br /&gt;
    [0x0d,0x0e,0x0c,&lt;br /&gt;
    0x11,0x10,0x0f]&lt;br /&gt;
],&lt;br /&gt;
mouth: [&lt;br /&gt;
    [0x17,0x01,0x13,&lt;br /&gt;
    0x15,0x16,0x05,&lt;br /&gt;
    0x00,0x08,0x0a,&lt;br /&gt;
    0x10,0x06,0x0d],&lt;br /&gt;
    [0x07,0x09,0x02,&lt;br /&gt;
    0x11,0x03,0x04,&lt;br /&gt;
    0x0f,0x0b,0x14,&lt;br /&gt;
    0x12,0x0e,0x0c],&lt;br /&gt;
    [0x1b,0x1e,0x18,&lt;br /&gt;
    0x19,0x1d,0x1c,&lt;br /&gt;
    0x1a,0x23,0x1f,&lt;br /&gt;
    0x22,0x21,0x20]&lt;br /&gt;
]&lt;br /&gt;
}&amp;lt;/nowiki&amp;gt;&lt;/div&gt;</summary>
		<author><name>Wwylele</name></author>
	</entry>
	<entry>
		<id>https://www.3dbrew.org/w/index.php?title=Mii&amp;diff=20903</id>
		<title>Mii</title>
		<link rel="alternate" type="text/html" href="https://www.3dbrew.org/w/index.php?title=Mii&amp;diff=20903"/>
		<updated>2019-03-05T16:07:04Z</updated>

		<summary type="html">&lt;p&gt;Wwylele: /* Mii format */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Originally [http://wiibrew.org/wiki/Mii_Data created for the Nintendo Wii] (and backported to a selection of DS/i games), the &#039;&#039;&#039;Mii&#039;&#039;&#039; format was expanded with a larger selection of facial features and a new &amp;quot;copying&amp;quot; permission for the 3DS family, and later implemented as-is on Wii U.&lt;br /&gt;
&lt;br /&gt;
See [[Mii Maker]] for the application chiefly designed to create, edit, delete, and trade Miis or convert them from and to a QR code.&lt;br /&gt;
&lt;br /&gt;
The default endianness in this page is little-endian, unless explicitly specified.&lt;br /&gt;
&lt;br /&gt;
==Mii Database==&lt;br /&gt;
Format of the Mii main database &#039;&#039;&#039;CFL_DB.dat&#039;&#039;&#039;, found in [[Extdata#NAND_Shared_Extdata|shared extdata]] archive f0000000b.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset&lt;br /&gt;
! Length&lt;br /&gt;
! &lt;br /&gt;
|-&lt;br /&gt;
| 0x0&lt;br /&gt;
| 0x4&lt;br /&gt;
| Header &amp;quot;CFOG&amp;quot; (Mii Maker section)&lt;br /&gt;
|-&lt;br /&gt;
| 0x4&lt;br /&gt;
| 0x4&lt;br /&gt;
| Header 0x00010000&lt;br /&gt;
|-&lt;br /&gt;
| 0x8&lt;br /&gt;
| 0x23F0 (100 * 0x5C)&lt;br /&gt;
| Array of owned (saved in Mii Maker) Miis. Order in file is unrelated to canonical order in-app.&lt;br /&gt;
|-&lt;br /&gt;
| 0x23F8&lt;br /&gt;
| 0x4&lt;br /&gt;
| Header &amp;quot;CFHE&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| 0x23FC&lt;br /&gt;
| 0x2&lt;br /&gt;
| Linked list tail index. 0xFFFF if the list is empty&lt;br /&gt;
|-&lt;br /&gt;
| 0x23FE&lt;br /&gt;
| 0x2&lt;br /&gt;
| Linked list head index. 0xFFFF if the list is empty&lt;br /&gt;
|-&lt;br /&gt;
| 0x2400&lt;br /&gt;
| 0xA410 (3000 * 0xE)&lt;br /&gt;
| Linked list of objects? See chapter&lt;br /&gt;
|-&lt;br /&gt;
| 0xC810&lt;br /&gt;
| 0xE&lt;br /&gt;
| Padding?&lt;br /&gt;
|-&lt;br /&gt;
| 0xC81E&lt;br /&gt;
| 0x2&lt;br /&gt;
| Checksum of all of the above (the first 0xC81E byte). See section [[#Checksum|below]].&lt;br /&gt;
|-&lt;br /&gt;
| 0xC820&lt;br /&gt;
| 0x4&lt;br /&gt;
| Header &amp;quot;CFRA&amp;quot; (Invitations section)&lt;br /&gt;
|-&lt;br /&gt;
| 0xC824&lt;br /&gt;
| 0x4&lt;br /&gt;
| Mii count in this section. Maximum 100&lt;br /&gt;
|-&lt;br /&gt;
| 0xC828&lt;br /&gt;
| 0x64 (100 * 0x1)&lt;br /&gt;
| Order index of Mii in this section?&lt;br /&gt;
|-&lt;br /&gt;
| 0xC88C&lt;br /&gt;
| 0x1C20 (100 * 0x48)&lt;br /&gt;
| Array of Miis contributed from games, used for Mii Plaza &amp;quot;invitations&amp;quot; feature.&amp;lt;br/&amp;gt;The format isn&#039;t that of a full Mii. The &amp;quot;author&amp;quot; field is missing&lt;br /&gt;
|-&lt;br /&gt;
| 0xE4AC&lt;br /&gt;
| 0x12&lt;br /&gt;
| 01 00 [..] 00&lt;br /&gt;
|-&lt;br /&gt;
| 0xE4BE&lt;br /&gt;
| 0x2&lt;br /&gt;
| Checksum over the data above starting from 0xC820&lt;br /&gt;
|-&lt;br /&gt;
| 0xE4C0&lt;br /&gt;
| 0x3D860 (3000 * 0x54)&lt;br /&gt;
| Another array of Miis. Seems related to the CFHE section. &amp;lt;br/&amp;gt;The Mii format in this section is modified. The &amp;quot;author&amp;quot; field is missing, A 4-byte timestamp (seconds since 2000) together with 8-byte zeros(?) is appended at the end.&lt;br /&gt;
|}&lt;br /&gt;
When encrypted in QR codes, 4 additional bytes are added. Two null bytes and a CRC-16. It&#039;s the exact same CRC-16 as for the Wii blocks on the 0x5e first bytes. It seems that the CRC is ignored, the Mii Maker expecting the result of APT:Unwrap to detect integrity loss.&lt;br /&gt;
&lt;br /&gt;
==CFHE object==&lt;br /&gt;
&lt;br /&gt;
A 0xE-byte long linked list node. The format is 4-byte Mii ID (See Mii format) + 6-byte MAC + 2-byte previous node index (prev) + 2-byte next node index (next).&lt;br /&gt;
&lt;br /&gt;
An invalid node has value: ID = 0, MAC = 0, prev = 0x7FFF, next = 0x7FFF.&lt;br /&gt;
&lt;br /&gt;
The highest bit of these fields has some special meaning and isn&#039;t part of the index value.&lt;br /&gt;
&lt;br /&gt;
==Checksum==&lt;br /&gt;
&lt;br /&gt;
The algorithm used to verify the integrity of the database is based on [http://srecord.sourceforge.net/crc16-ccitt.html CRC16-CCITT], though it&#039;s an incorrect implementation. It is the same algorithm used to verify [http://wiibrew.org/wiki/Mii_Data#Block_format Mii Data on the Wii].&lt;br /&gt;
&lt;br /&gt;
To obtain the correct value for the checksum, apply the algorithm to the first 0xC81E bytes of the database. This can be done using [https://gbatemp.net/threads/tutorial-give-your-mii-gold-pants-and-use-it-for-streetpass.379146/page-24#post-6569186 FixCRC]; alternativly a pseudocode implementation of the checksum algorithm is given below:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
def crc16_CCITTWii(u8[]: data) -&amp;gt; u16:&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Calculate a checksum of data using the CRC16-CCITT implementation of the Wii&lt;br /&gt;
&lt;br /&gt;
    This implementation uses 0x0000 as the starting value, which is different&lt;br /&gt;
    from what CRC16-CCITT specifies.&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    # note: a correct implementation of CRC16-CCITT&lt;br /&gt;
    #       would initialize this to 0xffff&lt;br /&gt;
    u32 crc := 0x0&lt;br /&gt;
&lt;br /&gt;
    for byte in data:&lt;br /&gt;
        # Iterate over every of the 8 bits in byte.&lt;br /&gt;
        # Begin with the most significant bit. (7, 6, ... , 1, 0)&lt;br /&gt;
        for bit in 7..0:&lt;br /&gt;
            # &amp;amp; - binary `and&#039;; &amp;lt;&amp;lt;/&amp;gt;&amp;gt; - bitshift left/right; ^ - binary `xor&#039;&lt;br /&gt;
            crc := (&lt;br /&gt;
                     (crc &amp;lt;&amp;lt; 1) | ((byte &amp;gt;&amp;gt; bit) &amp;amp; 0x1)&lt;br /&gt;
                     ^ (0x1021 if crc &amp;amp; 0x8000 else 0)&lt;br /&gt;
                   )&lt;br /&gt;
&lt;br /&gt;
    for _ in 0..15:&lt;br /&gt;
        crc := (crc &amp;lt;&amp;lt; 1) ^ (0x1021 if crc &amp;amp; 0x8000 else 0)&lt;br /&gt;
&lt;br /&gt;
    # only return the lowest 16 bit of crc&lt;br /&gt;
    return (u16) (crc &amp;amp; 0xffff)&lt;br /&gt;
&lt;br /&gt;
checksum := crc16_CCITTWii(miidb[0:0xc81e]) # checksum over the first 0xc81e bytes&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Mii format==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset&lt;br /&gt;
! Length&lt;br /&gt;
! &lt;br /&gt;
|-&lt;br /&gt;
| 0x0&lt;br /&gt;
| 0x1&lt;br /&gt;
| Always 3?&lt;br /&gt;
|-&lt;br /&gt;
| 0x1&lt;br /&gt;
| 0x1&lt;br /&gt;
| bit 0: allow copying&amp;lt;br/&amp;gt;bit 1: private name?&amp;lt;br/&amp;gt;bit 2-3: region lock (0=no lock, 1=JPN, 2=USA, 3=EUR)&amp;lt;br/&amp;gt;bit4-5:character set(0=JPN+USA+EUR, 1=CHN, 2=KOR, 3=TWN)&lt;br /&gt;
|-&lt;br /&gt;
| 0x2&lt;br /&gt;
| 0x1&lt;br /&gt;
| Mii position shown on the selection screen&amp;lt;br/&amp;gt;bit 0-3: page index &amp;lt;br/&amp;gt;bit 4-7: slot index&lt;br /&gt;
|-&lt;br /&gt;
| 0x3&lt;br /&gt;
| 0x1&lt;br /&gt;
| bit 0-3: ?&amp;lt;br/&amp;gt;bit 4-6: version? (1=Wii, 2=DSi, 3=3DS)&lt;br /&gt;
|-&lt;br /&gt;
| 0x4&lt;br /&gt;
| 0x8&lt;br /&gt;
| System ID (identifies owner, for purpose of enforcing editing restrictions and blue pants).&amp;lt;br/&amp;gt;Is not tied to the MAC address anymore.&lt;br /&gt;
|-&lt;br /&gt;
| 0xC&lt;br /&gt;
| 0x4&lt;br /&gt;
| Mii ID (big-endian 32bit unsigned integer):&amp;lt;br/&amp;gt;Bit 0..27: (bit[0..27] * 2) = date of creation (seconds since 01/01/2010 00:00:00)&amp;lt;br/&amp;gt;Bit 28: Always set?&amp;lt;br/&amp;gt;Bit 29: set for temporary Mii&amp;lt;br/&amp;gt;Bit 30: Set for DSi mii?&amp;lt;br/&amp;gt;Bit 31: not set iff Mii is special&lt;br /&gt;
|-&lt;br /&gt;
| 0x10&lt;br /&gt;
| 0x6&lt;br /&gt;
| Creator&#039;s full MAC&lt;br /&gt;
|-&lt;br /&gt;
| 0x16&lt;br /&gt;
| 0x2&lt;br /&gt;
| Padding (0000)&lt;br /&gt;
|-&lt;br /&gt;
| 0x18&lt;br /&gt;
| 0x2&lt;br /&gt;
| Bit-mapped: Birthday (4bit-day,5bit-month), Sex, Shirt color, Favorite (0x40 bit at 0x19)&lt;br /&gt;
|-&lt;br /&gt;
| 0x1A&lt;br /&gt;
| 0x14&lt;br /&gt;
| UTF-16 Mii Name (10 chars max, 0000 terminated)&lt;br /&gt;
|-&lt;br /&gt;
| 0x2E&lt;br /&gt;
| 0x2&lt;br /&gt;
| width &amp;amp; height&lt;br /&gt;
|-&lt;br /&gt;
| 0x30&lt;br /&gt;
| 0x1&lt;br /&gt;
| bit 0: disable sharing&amp;lt;br/&amp;gt;bit 1-4: face shape&amp;lt;br/&amp;gt;bit 5-7: skin color&lt;br /&gt;
|-&lt;br /&gt;
| 0x31&lt;br /&gt;
| 0x1&lt;br /&gt;
| bit 0-3: wrinkles&amp;lt;br/&amp;gt;bit 4-7: makeup&lt;br /&gt;
|-&lt;br /&gt;
| 0x32&lt;br /&gt;
| 0x1&lt;br /&gt;
| hair style&lt;br /&gt;
|-&lt;br /&gt;
| 0x33&lt;br /&gt;
| 0x1&lt;br /&gt;
| bit 0-2: hair color&amp;lt;br/&amp;gt;bit 3: flip hair&lt;br /&gt;
|-&lt;br /&gt;
| 0x34&lt;br /&gt;
| 0x4&lt;br /&gt;
| bit 0-5: eye style&amp;lt;br/&amp;gt;bit 6-8: eye color &amp;lt;br/&amp;gt;bit 9-12: eye scale &amp;lt;br/&amp;gt;bit 13-15: eye yscale&amp;lt;br/&amp;gt;bit 16-20: eye rotation&amp;lt;br/&amp;gt;bit 21-24: eye x spacing&amp;lt;br/&amp;gt;bit 25-29: eye y position&lt;br /&gt;
|-&lt;br /&gt;
| 0x38&lt;br /&gt;
| 0x4&lt;br /&gt;
| bit 0-4: eyebrow style&amp;lt;br/&amp;gt;bit 5-7: eyebrow color &amp;lt;br/&amp;gt;bit 8-11: eyebrow scale&amp;lt;br/&amp;gt;bit 12-14: eyebrow yscale &amp;lt;br/&amp;gt;bit 16-19: eyebrow rotation&amp;lt;br/&amp;gt;bit 21-24: eyebrow x spacing&amp;lt;br/&amp;gt;bit 25-29: eyebrow y position&lt;br /&gt;
|-&lt;br /&gt;
| 0x3C&lt;br /&gt;
| 0x2&lt;br /&gt;
| bit 0-4: nose style&amp;lt;br/&amp;gt;bit 5-8: nose scale&amp;lt;br/&amp;gt;bit 9-13: nose y position&lt;br /&gt;
|-&lt;br /&gt;
| 0x3E&lt;br /&gt;
| 0x2&lt;br /&gt;
| bit 0-5: mouse style&amp;lt;br/&amp;gt;biy 6-8: mouse color&amp;lt;br/&amp;gt;bit 9-12: mouse scale&amp;lt;br/&amp;gt;bit 13-15: mouse yscale&lt;br /&gt;
|-&lt;br /&gt;
| 0x40&lt;br /&gt;
| 0x2&lt;br /&gt;
| bit 0-4: mouse y position&amp;lt;br/&amp;gt;bit 5-7: mustach style&lt;br /&gt;
|-&lt;br /&gt;
| 0x42&lt;br /&gt;
| 0x2&lt;br /&gt;
| bit 0-2: beard style&amp;lt;br/&amp;gt;bit 3-5: beard color&amp;lt;br/&amp;gt;bit 6-9: mustache scale&amp;lt;br/&amp;gt;bit 10-14:mustache y position&lt;br /&gt;
|-&lt;br /&gt;
| 0x44&lt;br /&gt;
| 0x2&lt;br /&gt;
| bit 0-3: glasses style&amp;lt;br/&amp;gt;bit 4-6: glasses color&amp;lt;br/&amp;gt;bit 7-10: glasses scale&amp;lt;br/&amp;gt;bit 11-15: glasses y position&lt;br /&gt;
|-&lt;br /&gt;
| 0x46&lt;br /&gt;
| 0x2&lt;br /&gt;
| bit 0: enable mole&amp;lt;br/&amp;gt;bit 1-4: mole scale&amp;lt;br/&amp;gt;bit 5-9: mole x position&amp;lt;br/&amp;gt;bit 10-14: mole y position&lt;br /&gt;
|-&lt;br /&gt;
| 0x48&lt;br /&gt;
| 0x14&lt;br /&gt;
| UTF-16 Author Name (10 chars max, 0000 terminated)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Mii Header==&lt;br /&gt;
* Byte 0: generally equals 3 (category?)&lt;br /&gt;
* Byte 1: 0/1 = copying off/on&lt;br /&gt;
* Byte 2, most significant hex digit: position on page (0-9)&lt;br /&gt;
* Byte 2, least significant hex digit: page (0-9)&lt;br /&gt;
* Byte 3: generally 0x30 (always for user-created ones?)&lt;br /&gt;
&lt;br /&gt;
===Mii categories (pants colors)===&lt;br /&gt;
&lt;br /&gt;
====Special (gold) Miis====&lt;br /&gt;
Specialness will override any other color and make the Mii non-editable.&lt;br /&gt;
&lt;br /&gt;
Copying is rumored to have to be disabled.&lt;br /&gt;
&lt;br /&gt;
Zeroed system-id and timestamp?&lt;br /&gt;
&lt;br /&gt;
====Imported (blue) Miis====&lt;br /&gt;
Any (non-gold) Mii with a different System ID will appear as a foreign one.&lt;br /&gt;
&lt;br /&gt;
There is also a range of Mii IDs that are always foreign and uneditable, regardless of the System ID:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====Regular (black/red) Miis====&lt;br /&gt;
Always editable, since they can only appear as such on the console that created them.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====Personal (red) Mii====&lt;br /&gt;
A red Mii that happens to be the first in the file!&lt;br /&gt;
&lt;br /&gt;
==Mii values==&lt;br /&gt;
Each of the following values were found with NTR Debugger:&lt;br /&gt;
If you want to access the value, grab the given &amp;quot;NTR address&amp;quot; and add 0x08815000.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Data&lt;br /&gt;
! NTR address&lt;br /&gt;
! Variation (hex)&lt;br /&gt;
! Notes&lt;br /&gt;
|-&lt;br /&gt;
| Face style&lt;br /&gt;
| 0x894&lt;br /&gt;
| 00-0B&lt;br /&gt;
| Not ordered as in editor, read below&lt;br /&gt;
|-&lt;br /&gt;
| Face color&lt;br /&gt;
| 0x898&lt;br /&gt;
| 00-05&lt;br /&gt;
| From top to bottom&lt;br /&gt;
|-&lt;br /&gt;
| Wrinkles&lt;br /&gt;
| 0x89C&lt;br /&gt;
| 00-0B&lt;br /&gt;
| Same order as displayed in editor&lt;br /&gt;
|-&lt;br /&gt;
| Makeup&lt;br /&gt;
| 0x8A0&lt;br /&gt;
| 00-0B&lt;br /&gt;
| Same order as displayed in editor&lt;br /&gt;
|-&lt;br /&gt;
| Hair style&lt;br /&gt;
| 0x8A4&lt;br /&gt;
| 00-84&lt;br /&gt;
| Not ordered as in editor, read below&lt;br /&gt;
|-&lt;br /&gt;
| Hair color&lt;br /&gt;
| 0x8A8&lt;br /&gt;
| 00-07&lt;br /&gt;
| From top to bottom&lt;br /&gt;
|-&lt;br /&gt;
| Hair flipped&lt;br /&gt;
| 0x8AC&lt;br /&gt;
| 1 if true&lt;br /&gt;
| From top to bottom&lt;br /&gt;
|-&lt;br /&gt;
| Eye style&lt;br /&gt;
| 0x8B0&lt;br /&gt;
| 00-3C&lt;br /&gt;
| Not ordered as in editor, read below&lt;br /&gt;
|-&lt;br /&gt;
| Eyes color&lt;br /&gt;
| 0x8B4&lt;br /&gt;
| 00-05&lt;br /&gt;
| From top to bottom&lt;br /&gt;
|-&lt;br /&gt;
| Eyes size&lt;br /&gt;
| 0x8B8&lt;br /&gt;
| 07-00&lt;br /&gt;
| Left button increases value.&lt;br /&gt;
|-&lt;br /&gt;
| Eyes thickness&lt;br /&gt;
| 0x8BC&lt;br /&gt;
| 06-00&lt;br /&gt;
| Left button increases value.&lt;br /&gt;
|-&lt;br /&gt;
| Eyes rotation&lt;br /&gt;
| 0x8C0&lt;br /&gt;
| 00-07&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| Eyes spacing&lt;br /&gt;
| 0x8C4&lt;br /&gt;
| 00-0C&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| Eyes height&lt;br /&gt;
| 0x8C8&lt;br /&gt;
| 00-12&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| Eyebrows style&lt;br /&gt;
| 0x8CC&lt;br /&gt;
| 00-18&lt;br /&gt;
| Not ordered as in editor, read below&lt;br /&gt;
|-&lt;br /&gt;
| Eyebrows color&lt;br /&gt;
| 0x8D0&lt;br /&gt;
| 00-07&lt;br /&gt;
| From top to bottom&lt;br /&gt;
|-&lt;br /&gt;
| Eyebrows size&lt;br /&gt;
| 0x8D4&lt;br /&gt;
| 08-00&lt;br /&gt;
| Left button increases value.&lt;br /&gt;
|-&lt;br /&gt;
| Eyebrows thickness&lt;br /&gt;
| 0x8D8&lt;br /&gt;
| 06-00&lt;br /&gt;
| Left button increases value.&lt;br /&gt;
|-&lt;br /&gt;
| Eyebrows rotation&lt;br /&gt;
| 0x8DC&lt;br /&gt;
| 00-0B&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| Eyebrows spacing&lt;br /&gt;
| 0x8E0&lt;br /&gt;
| 00-0C&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| Eyebrows height&lt;br /&gt;
| 0x8E4&lt;br /&gt;
| 03-12&lt;br /&gt;
| Yup, minimum is 0x03&lt;br /&gt;
|-&lt;br /&gt;
| Nose style&lt;br /&gt;
| 0x8E8&lt;br /&gt;
| 00-11&lt;br /&gt;
| Not ordered as in editor, read below&lt;br /&gt;
|-&lt;br /&gt;
| Nose size&lt;br /&gt;
| 0x8EC&lt;br /&gt;
| 08-00&lt;br /&gt;
| Left button increases value.&lt;br /&gt;
|-&lt;br /&gt;
| Nose height&lt;br /&gt;
| 0x8F0&lt;br /&gt;
| 00-12&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| Mouth style&lt;br /&gt;
| 0x8F4&lt;br /&gt;
| 00-23&lt;br /&gt;
| Not ordered as in editor, read below&lt;br /&gt;
|-&lt;br /&gt;
| Mouth color&lt;br /&gt;
| 0x8F8&lt;br /&gt;
| 00-04&lt;br /&gt;
| From top to bottom.&lt;br /&gt;
|-&lt;br /&gt;
| Mouth size&lt;br /&gt;
| 0x8FC&lt;br /&gt;
| 08-00&lt;br /&gt;
| Left button increases value.&lt;br /&gt;
|-&lt;br /&gt;
| Mouth thickness&lt;br /&gt;
| 0x900&lt;br /&gt;
| 06-00&lt;br /&gt;
| Left button increases value.&lt;br /&gt;
|-&lt;br /&gt;
| Mouth height&lt;br /&gt;
| 0x904&lt;br /&gt;
| 00-12&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| Mustache style&lt;br /&gt;
| 0x908&lt;br /&gt;
| 00-05&lt;br /&gt;
| Order like in editor.&lt;br /&gt;
|-&lt;br /&gt;
| Beard style&lt;br /&gt;
| 0x90C&lt;br /&gt;
| 00-05&lt;br /&gt;
| Order like in editor.&lt;br /&gt;
|-&lt;br /&gt;
| Mustache/Beard color&lt;br /&gt;
| 0x910&lt;br /&gt;
| 00-07&lt;br /&gt;
| From top to button.&lt;br /&gt;
|-&lt;br /&gt;
| Mustache size&lt;br /&gt;
| 0x914&lt;br /&gt;
| 08-00&lt;br /&gt;
| Left button increases value.&lt;br /&gt;
|-&lt;br /&gt;
| Mustache height&lt;br /&gt;
| 0x918&lt;br /&gt;
| 00-10&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| Glasses style&lt;br /&gt;
| 0x91C&lt;br /&gt;
| 00-08&lt;br /&gt;
| Order like in editor.&lt;br /&gt;
|-&lt;br /&gt;
| Glasses color&lt;br /&gt;
| 0x920&lt;br /&gt;
| 00-05&lt;br /&gt;
| From top to bottom&lt;br /&gt;
|-&lt;br /&gt;
| Glasses size&lt;br /&gt;
| 0x924&lt;br /&gt;
| 07-00&lt;br /&gt;
| Left button increases value.&lt;br /&gt;
|-&lt;br /&gt;
| Glasses height&lt;br /&gt;
| 0x928&lt;br /&gt;
| 00-14&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| Mole enable&lt;br /&gt;
| 0x92C&lt;br /&gt;
| 1 if enabled, 0 else.&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| Mole size&lt;br /&gt;
| 0x930&lt;br /&gt;
| 08-00&lt;br /&gt;
| Left button increases value.&lt;br /&gt;
|-&lt;br /&gt;
| Mole horiz pos&lt;br /&gt;
| 0x934&lt;br /&gt;
| 00-10&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| Mole vert pos&lt;br /&gt;
| 0x938&lt;br /&gt;
| 00-1E&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| Mii height&lt;br /&gt;
| 0x93C&lt;br /&gt;
| 00-7F&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| Mii weight&lt;br /&gt;
| 0x940&lt;br /&gt;
| 00-7F&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| Mii name&lt;br /&gt;
| 0x944-0x959&lt;br /&gt;
| UTF-16&lt;br /&gt;
| Terminated with 0x0000. Not updated immediatly?&lt;br /&gt;
|-&lt;br /&gt;
| Creator&#039;s name&lt;br /&gt;
| 0x95A-96F&lt;br /&gt;
| UTF-16&lt;br /&gt;
| Terminated with 0x0000. Not updated immediatly?&lt;br /&gt;
|-&lt;br /&gt;
| Mii gender&lt;br /&gt;
| 0x970&lt;br /&gt;
| 0: Male, 1: Female&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| Birthdate month&lt;br /&gt;
| 0x974&lt;br /&gt;
| 01-0C&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| Birthdate day&lt;br /&gt;
| 0x978&lt;br /&gt;
| 01-1F&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| Mii shirt color&lt;br /&gt;
| 0x97C&lt;br /&gt;
| 00-0B&lt;br /&gt;
| Ordered like in editor.&lt;br /&gt;
|-&lt;br /&gt;
| Favorite&lt;br /&gt;
| 0x980&lt;br /&gt;
| 0: false, 1: true&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| Allow copy&lt;br /&gt;
| 0x981&lt;br /&gt;
| 0: false, 1: true&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| Unused byte?&lt;br /&gt;
| 0x982&lt;br /&gt;
| &lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| Allow sharing&lt;br /&gt;
| 0x983&lt;br /&gt;
| 0: true, 1: false&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
| ???&lt;br /&gt;
| 0x984-0x98F&lt;br /&gt;
| All zero?&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
| ???&lt;br /&gt;
| 0x990-0x997&lt;br /&gt;
| 4?&lt;br /&gt;
|&lt;br /&gt;
|}&lt;br /&gt;
0x08815998: Same 4 bytes as encrypted Mii: first 4 bits for Mii type, 4 next for number of seconds since 01/01/2010 00:00:00 UTC+3 (should be verified by other country and region 3DS) divided by 2.&lt;br /&gt;
0x0881599C: 6 bytes of MAC address of the 3DS that created the Mii.&lt;br /&gt;
0x088159A2: 6 unknow uses bytes&lt;br /&gt;
0x088159A8: Same 8 bytes as decrypted Mii at 0x04 through 0x0B. Seems NAND specific, kept the same on Miis created on same NAND but different 3DS via System Transfer. Might be a coincidence but the two first bytes are in ID0 folder name in the Nintendo 3DS folder.&lt;br /&gt;
&lt;br /&gt;
===Mapped Editor &amp;lt;-&amp;gt; Hex values===&lt;br /&gt;
&lt;br /&gt;
Most of the values are ordered (left button decreases, right increases, color choices are top to bottom...) but for most &amp;quot;main&amp;quot; part of the UI, where you choose the style of the part being edited, hex values has no correlation with displayed order.&lt;br /&gt;
Here is a JSON that can go from a Part, a Page and Position to the right hex value. This is 0 indexed (eg: datas[&amp;quot;face&amp;quot;][0][11]).&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;{&lt;br /&gt;
face: [&lt;br /&gt;
    0x00,0x01,0x08,&lt;br /&gt;
    0x02,0x03,0x09,&lt;br /&gt;
    0x04,0x05,0x0a,&lt;br /&gt;
    0x06,0x07,0x0b&lt;br /&gt;
],&lt;br /&gt;
hairs: [&lt;br /&gt;
    [0x21,0x2f,0x28,&lt;br /&gt;
    0x25,0x20,0x6b,&lt;br /&gt;
    0x30,0x33,0x37,&lt;br /&gt;
    0x46,0x2c,0x42],&lt;br /&gt;
    [0x34,0x32,0x26,&lt;br /&gt;
    0x31,0x2b,0x1f,&lt;br /&gt;
    0x38,0x44,0x3e,&lt;br /&gt;
    0x73,0x4c,0x77],&lt;br /&gt;
    [0x40,0x51,0x74,&lt;br /&gt;
    0x79,0x16,0x3a,&lt;br /&gt;
    0x3c,0x57,0x7d,&lt;br /&gt;
    0x75,0x49,0x4b],&lt;br /&gt;
    [0x2a,0x59,0x39,&lt;br /&gt;
    0x36,0x50,0x22,&lt;br /&gt;
    0x17,0x56,0x58,&lt;br /&gt;
    0x76,0x27,0x24],&lt;br /&gt;
    [0x2d,0x43,0x3b,&lt;br /&gt;
    0x41,0x29,0x1e,&lt;br /&gt;
    0x0c,0x10,0x0a,&lt;br /&gt;
    0x52,0x80,0x81],&lt;br /&gt;
    [0x0e,0x5f,0x69,&lt;br /&gt;
    0x64,0x06,0x14,&lt;br /&gt;
    0x5d,0x66,0x1b,&lt;br /&gt;
    0x04,0x11,0x6e]&lt;br /&gt;
    [0x7b,0x08,0x6a,&lt;br /&gt;
    0x48,0x03,0x15,&lt;br /&gt;
    0x00,0x62,0x3f,&lt;br /&gt;
    0x5a,0x0b,0x78],&lt;br /&gt;
    [0x05,0x4a,0x6c,&lt;br /&gt;
    0x5e,0x7c,0x19,&lt;br /&gt;
    0x63,0x45,0x23,&lt;br /&gt;
    0x0d,0x7a,0x71],&lt;br /&gt;
    [0x35,0x18,0x55,&lt;br /&gt;
    0x53,0x47,0x83,&lt;br /&gt;
    0x60,0x65,0x1d,&lt;br /&gt;
    0x07,0x0f,0x70],&lt;br /&gt;
    [0x4f,0x01,0x6d,&lt;br /&gt;
    0x7f,0x5b,0x1a,&lt;br /&gt;
    0x3d,0x67,0x02,&lt;br /&gt;
    0x4d,0x12,0x5c],&lt;br /&gt;
    [0x54,0x09,0x13,&lt;br /&gt;
    0x82,0x61,0x68,&lt;br /&gt;
    0x2e,0x4e,0x1c,&lt;br /&gt;
    0x72,0x7e,0x6f]&lt;br /&gt;
],&lt;br /&gt;
eyebrows: [&lt;br /&gt;
    [0x06,0x00,0x0c,&lt;br /&gt;
    0x01,0x09,0x13,&lt;br /&gt;
    0x07,0x15,0x08,&lt;br /&gt;
    0x11,0x05,0x04],&lt;br /&gt;
    [0x0b,0x0a,0x02,&lt;br /&gt;
    0x03,0x0e,0x14,&lt;br /&gt;
    0x0f,0x0d,0x16,&lt;br /&gt;
    0x12,0x10,0x17]&lt;br /&gt;
],&lt;br /&gt;
nose: [&lt;br /&gt;
    [0x01,0x0a,0x02,&lt;br /&gt;
    0x03,0x06,0x00,&lt;br /&gt;
    0x05,0x04,0x08,&lt;br /&gt;
    0x09,0x07,0x0B],&lt;br /&gt;
    [0x0d,0x0e,0x0c,&lt;br /&gt;
    0x11,0x10,0x0f]&lt;br /&gt;
],&lt;br /&gt;
mouth: [&lt;br /&gt;
    [0x17,0x01,0x13,&lt;br /&gt;
    0x15,0x16,0x05,&lt;br /&gt;
    0x00,0x08,0x0a,&lt;br /&gt;
    0x10,0x06,0x0d],&lt;br /&gt;
    [0x07,0x09,0x02,&lt;br /&gt;
    0x11,0x03,0x04,&lt;br /&gt;
    0x0f,0x0b,0x14,&lt;br /&gt;
    0x12,0x0e,0x0c],&lt;br /&gt;
    [0x1b,0x1e,0x18,&lt;br /&gt;
    0x19,0x1d,0x1c,&lt;br /&gt;
    0x1a,0x23,0x1f,&lt;br /&gt;
    0x22,0x21,0x20]&lt;br /&gt;
]&lt;br /&gt;
}&amp;lt;/nowiki&amp;gt;&lt;/div&gt;</summary>
		<author><name>Wwylele</name></author>
	</entry>
	<entry>
		<id>https://www.3dbrew.org/w/index.php?title=Mii&amp;diff=20902</id>
		<title>Mii</title>
		<link rel="alternate" type="text/html" href="https://www.3dbrew.org/w/index.php?title=Mii&amp;diff=20902"/>
		<updated>2019-03-05T16:06:46Z</updated>

		<summary type="html">&lt;p&gt;Wwylele: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Originally [http://wiibrew.org/wiki/Mii_Data created for the Nintendo Wii] (and backported to a selection of DS/i games), the &#039;&#039;&#039;Mii&#039;&#039;&#039; format was expanded with a larger selection of facial features and a new &amp;quot;copying&amp;quot; permission for the 3DS family, and later implemented as-is on Wii U.&lt;br /&gt;
&lt;br /&gt;
See [[Mii Maker]] for the application chiefly designed to create, edit, delete, and trade Miis or convert them from and to a QR code.&lt;br /&gt;
&lt;br /&gt;
The default endianness in this page is little-endian, unless explicitly specified.&lt;br /&gt;
&lt;br /&gt;
==Mii Database==&lt;br /&gt;
Format of the Mii main database &#039;&#039;&#039;CFL_DB.dat&#039;&#039;&#039;, found in [[Extdata#NAND_Shared_Extdata|shared extdata]] archive f0000000b.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset&lt;br /&gt;
! Length&lt;br /&gt;
! &lt;br /&gt;
|-&lt;br /&gt;
| 0x0&lt;br /&gt;
| 0x4&lt;br /&gt;
| Header &amp;quot;CFOG&amp;quot; (Mii Maker section)&lt;br /&gt;
|-&lt;br /&gt;
| 0x4&lt;br /&gt;
| 0x4&lt;br /&gt;
| Header 0x00010000&lt;br /&gt;
|-&lt;br /&gt;
| 0x8&lt;br /&gt;
| 0x23F0 (100 * 0x5C)&lt;br /&gt;
| Array of owned (saved in Mii Maker) Miis. Order in file is unrelated to canonical order in-app.&lt;br /&gt;
|-&lt;br /&gt;
| 0x23F8&lt;br /&gt;
| 0x4&lt;br /&gt;
| Header &amp;quot;CFHE&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| 0x23FC&lt;br /&gt;
| 0x2&lt;br /&gt;
| Linked list tail index. 0xFFFF if the list is empty&lt;br /&gt;
|-&lt;br /&gt;
| 0x23FE&lt;br /&gt;
| 0x2&lt;br /&gt;
| Linked list head index. 0xFFFF if the list is empty&lt;br /&gt;
|-&lt;br /&gt;
| 0x2400&lt;br /&gt;
| 0xA410 (3000 * 0xE)&lt;br /&gt;
| Linked list of objects? See chapter&lt;br /&gt;
|-&lt;br /&gt;
| 0xC810&lt;br /&gt;
| 0xE&lt;br /&gt;
| Padding?&lt;br /&gt;
|-&lt;br /&gt;
| 0xC81E&lt;br /&gt;
| 0x2&lt;br /&gt;
| Checksum of all of the above (the first 0xC81E byte). See section [[#Checksum|below]].&lt;br /&gt;
|-&lt;br /&gt;
| 0xC820&lt;br /&gt;
| 0x4&lt;br /&gt;
| Header &amp;quot;CFRA&amp;quot; (Invitations section)&lt;br /&gt;
|-&lt;br /&gt;
| 0xC824&lt;br /&gt;
| 0x4&lt;br /&gt;
| Mii count in this section. Maximum 100&lt;br /&gt;
|-&lt;br /&gt;
| 0xC828&lt;br /&gt;
| 0x64 (100 * 0x1)&lt;br /&gt;
| Order index of Mii in this section?&lt;br /&gt;
|-&lt;br /&gt;
| 0xC88C&lt;br /&gt;
| 0x1C20 (100 * 0x48)&lt;br /&gt;
| Array of Miis contributed from games, used for Mii Plaza &amp;quot;invitations&amp;quot; feature.&amp;lt;br/&amp;gt;The format isn&#039;t that of a full Mii. The &amp;quot;author&amp;quot; field is missing&lt;br /&gt;
|-&lt;br /&gt;
| 0xE4AC&lt;br /&gt;
| 0x12&lt;br /&gt;
| 01 00 [..] 00&lt;br /&gt;
|-&lt;br /&gt;
| 0xE4BE&lt;br /&gt;
| 0x2&lt;br /&gt;
| Checksum over the data above starting from 0xC820&lt;br /&gt;
|-&lt;br /&gt;
| 0xE4C0&lt;br /&gt;
| 0x3D860 (3000 * 0x54)&lt;br /&gt;
| Another array of Miis. Seems related to the CFHE section. &amp;lt;br/&amp;gt;The Mii format in this section is modified. The &amp;quot;author&amp;quot; field is missing, A 4-byte timestamp (seconds since 2000) together with 8-byte zeros(?) is appended at the end.&lt;br /&gt;
|}&lt;br /&gt;
When encrypted in QR codes, 4 additional bytes are added. Two null bytes and a CRC-16. It&#039;s the exact same CRC-16 as for the Wii blocks on the 0x5e first bytes. It seems that the CRC is ignored, the Mii Maker expecting the result of APT:Unwrap to detect integrity loss.&lt;br /&gt;
&lt;br /&gt;
==CFHE object==&lt;br /&gt;
&lt;br /&gt;
A 0xE-byte long linked list node. The format is 4-byte Mii ID (See Mii format) + 6-byte MAC + 2-byte previous node index (prev) + 2-byte next node index (next).&lt;br /&gt;
&lt;br /&gt;
An invalid node has value: ID = 0, MAC = 0, prev = 0x7FFF, next = 0x7FFF.&lt;br /&gt;
&lt;br /&gt;
The highest bit of these fields has some special meaning and isn&#039;t part of the index value.&lt;br /&gt;
&lt;br /&gt;
==Checksum==&lt;br /&gt;
&lt;br /&gt;
The algorithm used to verify the integrity of the database is based on [http://srecord.sourceforge.net/crc16-ccitt.html CRC16-CCITT], though it&#039;s an incorrect implementation. It is the same algorithm used to verify [http://wiibrew.org/wiki/Mii_Data#Block_format Mii Data on the Wii].&lt;br /&gt;
&lt;br /&gt;
To obtain the correct value for the checksum, apply the algorithm to the first 0xC81E bytes of the database. This can be done using [https://gbatemp.net/threads/tutorial-give-your-mii-gold-pants-and-use-it-for-streetpass.379146/page-24#post-6569186 FixCRC]; alternativly a pseudocode implementation of the checksum algorithm is given below:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
def crc16_CCITTWii(u8[]: data) -&amp;gt; u16:&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Calculate a checksum of data using the CRC16-CCITT implementation of the Wii&lt;br /&gt;
&lt;br /&gt;
    This implementation uses 0x0000 as the starting value, which is different&lt;br /&gt;
    from what CRC16-CCITT specifies.&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    # note: a correct implementation of CRC16-CCITT&lt;br /&gt;
    #       would initialize this to 0xffff&lt;br /&gt;
    u32 crc := 0x0&lt;br /&gt;
&lt;br /&gt;
    for byte in data:&lt;br /&gt;
        # Iterate over every of the 8 bits in byte.&lt;br /&gt;
        # Begin with the most significant bit. (7, 6, ... , 1, 0)&lt;br /&gt;
        for bit in 7..0:&lt;br /&gt;
            # &amp;amp; - binary `and&#039;; &amp;lt;&amp;lt;/&amp;gt;&amp;gt; - bitshift left/right; ^ - binary `xor&#039;&lt;br /&gt;
            crc := (&lt;br /&gt;
                     (crc &amp;lt;&amp;lt; 1) | ((byte &amp;gt;&amp;gt; bit) &amp;amp; 0x1)&lt;br /&gt;
                     ^ (0x1021 if crc &amp;amp; 0x8000 else 0)&lt;br /&gt;
                   )&lt;br /&gt;
&lt;br /&gt;
    for _ in 0..15:&lt;br /&gt;
        crc := (crc &amp;lt;&amp;lt; 1) ^ (0x1021 if crc &amp;amp; 0x8000 else 0)&lt;br /&gt;
&lt;br /&gt;
    # only return the lowest 16 bit of crc&lt;br /&gt;
    return (u16) (crc &amp;amp; 0xffff)&lt;br /&gt;
&lt;br /&gt;
checksum := crc16_CCITTWii(miidb[0:0xc81e]) # checksum over the first 0xc81e bytes&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Mii format==&lt;br /&gt;
&lt;br /&gt;
Note: 0x18-3B have been copied as-is from [[Mii_Maker#Mii_QR_Code_format|the QR code specification]], so they&#039;re unverified.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset&lt;br /&gt;
! Length&lt;br /&gt;
! &lt;br /&gt;
|-&lt;br /&gt;
| 0x0&lt;br /&gt;
| 0x1&lt;br /&gt;
| Always 3?&lt;br /&gt;
|-&lt;br /&gt;
| 0x1&lt;br /&gt;
| 0x1&lt;br /&gt;
| bit 0: allow copying&amp;lt;br/&amp;gt;bit 1: private name?&amp;lt;br/&amp;gt;bit 2-3: region lock (0=no lock, 1=JPN, 2=USA, 3=EUR)&amp;lt;br/&amp;gt;bit4-5:character set(0=JPN+USA+EUR, 1=CHN, 2=KOR, 3=TWN)&lt;br /&gt;
|-&lt;br /&gt;
| 0x2&lt;br /&gt;
| 0x1&lt;br /&gt;
| Mii position shown on the selection screen&amp;lt;br/&amp;gt;bit 0-3: page index &amp;lt;br/&amp;gt;bit 4-7: slot index&lt;br /&gt;
|-&lt;br /&gt;
| 0x3&lt;br /&gt;
| 0x1&lt;br /&gt;
| bit 0-3: ?&amp;lt;br/&amp;gt;bit 4-6: version? (1=Wii, 2=DSi, 3=3DS)&lt;br /&gt;
|-&lt;br /&gt;
| 0x4&lt;br /&gt;
| 0x8&lt;br /&gt;
| System ID (identifies owner, for purpose of enforcing editing restrictions and blue pants).&amp;lt;br/&amp;gt;Is not tied to the MAC address anymore.&lt;br /&gt;
|-&lt;br /&gt;
| 0xC&lt;br /&gt;
| 0x4&lt;br /&gt;
| Mii ID (big-endian 32bit unsigned integer):&amp;lt;br/&amp;gt;Bit 0..27: (bit[0..27] * 2) = date of creation (seconds since 01/01/2010 00:00:00)&amp;lt;br/&amp;gt;Bit 28: Always set?&amp;lt;br/&amp;gt;Bit 29: set for temporary Mii&amp;lt;br/&amp;gt;Bit 30: Set for DSi mii?&amp;lt;br/&amp;gt;Bit 31: not set iff Mii is special&lt;br /&gt;
|-&lt;br /&gt;
| 0x10&lt;br /&gt;
| 0x6&lt;br /&gt;
| Creator&#039;s full MAC&lt;br /&gt;
|-&lt;br /&gt;
| 0x16&lt;br /&gt;
| 0x2&lt;br /&gt;
| Padding (0000)&lt;br /&gt;
|-&lt;br /&gt;
| 0x18&lt;br /&gt;
| 0x2&lt;br /&gt;
| Bit-mapped: Birthday (4bit-day,5bit-month), Sex, Shirt color, Favorite (0x40 bit at 0x19)&lt;br /&gt;
|-&lt;br /&gt;
| 0x1A&lt;br /&gt;
| 0x14&lt;br /&gt;
| UTF-16 Mii Name (10 chars max, 0000 terminated)&lt;br /&gt;
|-&lt;br /&gt;
| 0x2E&lt;br /&gt;
| 0x2&lt;br /&gt;
| width &amp;amp; height&lt;br /&gt;
|-&lt;br /&gt;
| 0x30&lt;br /&gt;
| 0x1&lt;br /&gt;
| bit 0: disable sharing&amp;lt;br/&amp;gt;bit 1-4: face shape&amp;lt;br/&amp;gt;bit 5-7: skin color&lt;br /&gt;
|-&lt;br /&gt;
| 0x31&lt;br /&gt;
| 0x1&lt;br /&gt;
| bit 0-3: wrinkles&amp;lt;br/&amp;gt;bit 4-7: makeup&lt;br /&gt;
|-&lt;br /&gt;
| 0x32&lt;br /&gt;
| 0x1&lt;br /&gt;
| hair style&lt;br /&gt;
|-&lt;br /&gt;
| 0x33&lt;br /&gt;
| 0x1&lt;br /&gt;
| bit 0-2: hair color&amp;lt;br/&amp;gt;bit 3: flip hair&lt;br /&gt;
|-&lt;br /&gt;
| 0x34&lt;br /&gt;
| 0x4&lt;br /&gt;
| bit 0-5: eye style&amp;lt;br/&amp;gt;bit 6-8: eye color &amp;lt;br/&amp;gt;bit 9-12: eye scale &amp;lt;br/&amp;gt;bit 13-15: eye yscale&amp;lt;br/&amp;gt;bit 16-20: eye rotation&amp;lt;br/&amp;gt;bit 21-24: eye x spacing&amp;lt;br/&amp;gt;bit 25-29: eye y position&lt;br /&gt;
|-&lt;br /&gt;
| 0x38&lt;br /&gt;
| 0x4&lt;br /&gt;
| bit 0-4: eyebrow style&amp;lt;br/&amp;gt;bit 5-7: eyebrow color &amp;lt;br/&amp;gt;bit 8-11: eyebrow scale&amp;lt;br/&amp;gt;bit 12-14: eyebrow yscale &amp;lt;br/&amp;gt;bit 16-19: eyebrow rotation&amp;lt;br/&amp;gt;bit 21-24: eyebrow x spacing&amp;lt;br/&amp;gt;bit 25-29: eyebrow y position&lt;br /&gt;
|-&lt;br /&gt;
| 0x3C&lt;br /&gt;
| 0x2&lt;br /&gt;
| bit 0-4: nose style&amp;lt;br/&amp;gt;bit 5-8: nose scale&amp;lt;br/&amp;gt;bit 9-13: nose y position&lt;br /&gt;
|-&lt;br /&gt;
| 0x3E&lt;br /&gt;
| 0x2&lt;br /&gt;
| bit 0-5: mouse style&amp;lt;br/&amp;gt;biy 6-8: mouse color&amp;lt;br/&amp;gt;bit 9-12: mouse scale&amp;lt;br/&amp;gt;bit 13-15: mouse yscale&lt;br /&gt;
|-&lt;br /&gt;
| 0x40&lt;br /&gt;
| 0x2&lt;br /&gt;
| bit 0-4: mouse y position&amp;lt;br/&amp;gt;bit 5-7: mustach style&lt;br /&gt;
|-&lt;br /&gt;
| 0x42&lt;br /&gt;
| 0x2&lt;br /&gt;
| bit 0-2: beard style&amp;lt;br/&amp;gt;bit 3-5: beard color&amp;lt;br/&amp;gt;bit 6-9: mustache scale&amp;lt;br/&amp;gt;bit 10-14:mustache y position&lt;br /&gt;
|-&lt;br /&gt;
| 0x44&lt;br /&gt;
| 0x2&lt;br /&gt;
| bit 0-3: glasses style&amp;lt;br/&amp;gt;bit 4-6: glasses color&amp;lt;br/&amp;gt;bit 7-10: glasses scale&amp;lt;br/&amp;gt;bit 11-15: glasses y position&lt;br /&gt;
|-&lt;br /&gt;
| 0x46&lt;br /&gt;
| 0x2&lt;br /&gt;
| bit 0: enable mole&amp;lt;br/&amp;gt;bit 1-4: mole scale&amp;lt;br/&amp;gt;bit 5-9: mole x position&amp;lt;br/&amp;gt;bit 10-14: mole y position&lt;br /&gt;
|-&lt;br /&gt;
| 0x48&lt;br /&gt;
| 0x14&lt;br /&gt;
| UTF-16 Author Name (10 chars max, 0000 terminated)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Mii Header==&lt;br /&gt;
* Byte 0: generally equals 3 (category?)&lt;br /&gt;
* Byte 1: 0/1 = copying off/on&lt;br /&gt;
* Byte 2, most significant hex digit: position on page (0-9)&lt;br /&gt;
* Byte 2, least significant hex digit: page (0-9)&lt;br /&gt;
* Byte 3: generally 0x30 (always for user-created ones?)&lt;br /&gt;
&lt;br /&gt;
===Mii categories (pants colors)===&lt;br /&gt;
&lt;br /&gt;
====Special (gold) Miis====&lt;br /&gt;
Specialness will override any other color and make the Mii non-editable.&lt;br /&gt;
&lt;br /&gt;
Copying is rumored to have to be disabled.&lt;br /&gt;
&lt;br /&gt;
Zeroed system-id and timestamp?&lt;br /&gt;
&lt;br /&gt;
====Imported (blue) Miis====&lt;br /&gt;
Any (non-gold) Mii with a different System ID will appear as a foreign one.&lt;br /&gt;
&lt;br /&gt;
There is also a range of Mii IDs that are always foreign and uneditable, regardless of the System ID:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====Regular (black/red) Miis====&lt;br /&gt;
Always editable, since they can only appear as such on the console that created them.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====Personal (red) Mii====&lt;br /&gt;
A red Mii that happens to be the first in the file!&lt;br /&gt;
&lt;br /&gt;
==Mii values==&lt;br /&gt;
Each of the following values were found with NTR Debugger:&lt;br /&gt;
If you want to access the value, grab the given &amp;quot;NTR address&amp;quot; and add 0x08815000.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Data&lt;br /&gt;
! NTR address&lt;br /&gt;
! Variation (hex)&lt;br /&gt;
! Notes&lt;br /&gt;
|-&lt;br /&gt;
| Face style&lt;br /&gt;
| 0x894&lt;br /&gt;
| 00-0B&lt;br /&gt;
| Not ordered as in editor, read below&lt;br /&gt;
|-&lt;br /&gt;
| Face color&lt;br /&gt;
| 0x898&lt;br /&gt;
| 00-05&lt;br /&gt;
| From top to bottom&lt;br /&gt;
|-&lt;br /&gt;
| Wrinkles&lt;br /&gt;
| 0x89C&lt;br /&gt;
| 00-0B&lt;br /&gt;
| Same order as displayed in editor&lt;br /&gt;
|-&lt;br /&gt;
| Makeup&lt;br /&gt;
| 0x8A0&lt;br /&gt;
| 00-0B&lt;br /&gt;
| Same order as displayed in editor&lt;br /&gt;
|-&lt;br /&gt;
| Hair style&lt;br /&gt;
| 0x8A4&lt;br /&gt;
| 00-84&lt;br /&gt;
| Not ordered as in editor, read below&lt;br /&gt;
|-&lt;br /&gt;
| Hair color&lt;br /&gt;
| 0x8A8&lt;br /&gt;
| 00-07&lt;br /&gt;
| From top to bottom&lt;br /&gt;
|-&lt;br /&gt;
| Hair flipped&lt;br /&gt;
| 0x8AC&lt;br /&gt;
| 1 if true&lt;br /&gt;
| From top to bottom&lt;br /&gt;
|-&lt;br /&gt;
| Eye style&lt;br /&gt;
| 0x8B0&lt;br /&gt;
| 00-3C&lt;br /&gt;
| Not ordered as in editor, read below&lt;br /&gt;
|-&lt;br /&gt;
| Eyes color&lt;br /&gt;
| 0x8B4&lt;br /&gt;
| 00-05&lt;br /&gt;
| From top to bottom&lt;br /&gt;
|-&lt;br /&gt;
| Eyes size&lt;br /&gt;
| 0x8B8&lt;br /&gt;
| 07-00&lt;br /&gt;
| Left button increases value.&lt;br /&gt;
|-&lt;br /&gt;
| Eyes thickness&lt;br /&gt;
| 0x8BC&lt;br /&gt;
| 06-00&lt;br /&gt;
| Left button increases value.&lt;br /&gt;
|-&lt;br /&gt;
| Eyes rotation&lt;br /&gt;
| 0x8C0&lt;br /&gt;
| 00-07&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| Eyes spacing&lt;br /&gt;
| 0x8C4&lt;br /&gt;
| 00-0C&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| Eyes height&lt;br /&gt;
| 0x8C8&lt;br /&gt;
| 00-12&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| Eyebrows style&lt;br /&gt;
| 0x8CC&lt;br /&gt;
| 00-18&lt;br /&gt;
| Not ordered as in editor, read below&lt;br /&gt;
|-&lt;br /&gt;
| Eyebrows color&lt;br /&gt;
| 0x8D0&lt;br /&gt;
| 00-07&lt;br /&gt;
| From top to bottom&lt;br /&gt;
|-&lt;br /&gt;
| Eyebrows size&lt;br /&gt;
| 0x8D4&lt;br /&gt;
| 08-00&lt;br /&gt;
| Left button increases value.&lt;br /&gt;
|-&lt;br /&gt;
| Eyebrows thickness&lt;br /&gt;
| 0x8D8&lt;br /&gt;
| 06-00&lt;br /&gt;
| Left button increases value.&lt;br /&gt;
|-&lt;br /&gt;
| Eyebrows rotation&lt;br /&gt;
| 0x8DC&lt;br /&gt;
| 00-0B&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| Eyebrows spacing&lt;br /&gt;
| 0x8E0&lt;br /&gt;
| 00-0C&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| Eyebrows height&lt;br /&gt;
| 0x8E4&lt;br /&gt;
| 03-12&lt;br /&gt;
| Yup, minimum is 0x03&lt;br /&gt;
|-&lt;br /&gt;
| Nose style&lt;br /&gt;
| 0x8E8&lt;br /&gt;
| 00-11&lt;br /&gt;
| Not ordered as in editor, read below&lt;br /&gt;
|-&lt;br /&gt;
| Nose size&lt;br /&gt;
| 0x8EC&lt;br /&gt;
| 08-00&lt;br /&gt;
| Left button increases value.&lt;br /&gt;
|-&lt;br /&gt;
| Nose height&lt;br /&gt;
| 0x8F0&lt;br /&gt;
| 00-12&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| Mouth style&lt;br /&gt;
| 0x8F4&lt;br /&gt;
| 00-23&lt;br /&gt;
| Not ordered as in editor, read below&lt;br /&gt;
|-&lt;br /&gt;
| Mouth color&lt;br /&gt;
| 0x8F8&lt;br /&gt;
| 00-04&lt;br /&gt;
| From top to bottom.&lt;br /&gt;
|-&lt;br /&gt;
| Mouth size&lt;br /&gt;
| 0x8FC&lt;br /&gt;
| 08-00&lt;br /&gt;
| Left button increases value.&lt;br /&gt;
|-&lt;br /&gt;
| Mouth thickness&lt;br /&gt;
| 0x900&lt;br /&gt;
| 06-00&lt;br /&gt;
| Left button increases value.&lt;br /&gt;
|-&lt;br /&gt;
| Mouth height&lt;br /&gt;
| 0x904&lt;br /&gt;
| 00-12&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| Mustache style&lt;br /&gt;
| 0x908&lt;br /&gt;
| 00-05&lt;br /&gt;
| Order like in editor.&lt;br /&gt;
|-&lt;br /&gt;
| Beard style&lt;br /&gt;
| 0x90C&lt;br /&gt;
| 00-05&lt;br /&gt;
| Order like in editor.&lt;br /&gt;
|-&lt;br /&gt;
| Mustache/Beard color&lt;br /&gt;
| 0x910&lt;br /&gt;
| 00-07&lt;br /&gt;
| From top to button.&lt;br /&gt;
|-&lt;br /&gt;
| Mustache size&lt;br /&gt;
| 0x914&lt;br /&gt;
| 08-00&lt;br /&gt;
| Left button increases value.&lt;br /&gt;
|-&lt;br /&gt;
| Mustache height&lt;br /&gt;
| 0x918&lt;br /&gt;
| 00-10&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| Glasses style&lt;br /&gt;
| 0x91C&lt;br /&gt;
| 00-08&lt;br /&gt;
| Order like in editor.&lt;br /&gt;
|-&lt;br /&gt;
| Glasses color&lt;br /&gt;
| 0x920&lt;br /&gt;
| 00-05&lt;br /&gt;
| From top to bottom&lt;br /&gt;
|-&lt;br /&gt;
| Glasses size&lt;br /&gt;
| 0x924&lt;br /&gt;
| 07-00&lt;br /&gt;
| Left button increases value.&lt;br /&gt;
|-&lt;br /&gt;
| Glasses height&lt;br /&gt;
| 0x928&lt;br /&gt;
| 00-14&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| Mole enable&lt;br /&gt;
| 0x92C&lt;br /&gt;
| 1 if enabled, 0 else.&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| Mole size&lt;br /&gt;
| 0x930&lt;br /&gt;
| 08-00&lt;br /&gt;
| Left button increases value.&lt;br /&gt;
|-&lt;br /&gt;
| Mole horiz pos&lt;br /&gt;
| 0x934&lt;br /&gt;
| 00-10&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| Mole vert pos&lt;br /&gt;
| 0x938&lt;br /&gt;
| 00-1E&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| Mii height&lt;br /&gt;
| 0x93C&lt;br /&gt;
| 00-7F&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| Mii weight&lt;br /&gt;
| 0x940&lt;br /&gt;
| 00-7F&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| Mii name&lt;br /&gt;
| 0x944-0x959&lt;br /&gt;
| UTF-16&lt;br /&gt;
| Terminated with 0x0000. Not updated immediatly?&lt;br /&gt;
|-&lt;br /&gt;
| Creator&#039;s name&lt;br /&gt;
| 0x95A-96F&lt;br /&gt;
| UTF-16&lt;br /&gt;
| Terminated with 0x0000. Not updated immediatly?&lt;br /&gt;
|-&lt;br /&gt;
| Mii gender&lt;br /&gt;
| 0x970&lt;br /&gt;
| 0: Male, 1: Female&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| Birthdate month&lt;br /&gt;
| 0x974&lt;br /&gt;
| 01-0C&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| Birthdate day&lt;br /&gt;
| 0x978&lt;br /&gt;
| 01-1F&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| Mii shirt color&lt;br /&gt;
| 0x97C&lt;br /&gt;
| 00-0B&lt;br /&gt;
| Ordered like in editor.&lt;br /&gt;
|-&lt;br /&gt;
| Favorite&lt;br /&gt;
| 0x980&lt;br /&gt;
| 0: false, 1: true&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| Allow copy&lt;br /&gt;
| 0x981&lt;br /&gt;
| 0: false, 1: true&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| Unused byte?&lt;br /&gt;
| 0x982&lt;br /&gt;
| &lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| Allow sharing&lt;br /&gt;
| 0x983&lt;br /&gt;
| 0: true, 1: false&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
| ???&lt;br /&gt;
| 0x984-0x98F&lt;br /&gt;
| All zero?&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
| ???&lt;br /&gt;
| 0x990-0x997&lt;br /&gt;
| 4?&lt;br /&gt;
|&lt;br /&gt;
|}&lt;br /&gt;
0x08815998: Same 4 bytes as encrypted Mii: first 4 bits for Mii type, 4 next for number of seconds since 01/01/2010 00:00:00 UTC+3 (should be verified by other country and region 3DS) divided by 2.&lt;br /&gt;
0x0881599C: 6 bytes of MAC address of the 3DS that created the Mii.&lt;br /&gt;
0x088159A2: 6 unknow uses bytes&lt;br /&gt;
0x088159A8: Same 8 bytes as decrypted Mii at 0x04 through 0x0B. Seems NAND specific, kept the same on Miis created on same NAND but different 3DS via System Transfer. Might be a coincidence but the two first bytes are in ID0 folder name in the Nintendo 3DS folder.&lt;br /&gt;
&lt;br /&gt;
===Mapped Editor &amp;lt;-&amp;gt; Hex values===&lt;br /&gt;
&lt;br /&gt;
Most of the values are ordered (left button decreases, right increases, color choices are top to bottom...) but for most &amp;quot;main&amp;quot; part of the UI, where you choose the style of the part being edited, hex values has no correlation with displayed order.&lt;br /&gt;
Here is a JSON that can go from a Part, a Page and Position to the right hex value. This is 0 indexed (eg: datas[&amp;quot;face&amp;quot;][0][11]).&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;{&lt;br /&gt;
face: [&lt;br /&gt;
    0x00,0x01,0x08,&lt;br /&gt;
    0x02,0x03,0x09,&lt;br /&gt;
    0x04,0x05,0x0a,&lt;br /&gt;
    0x06,0x07,0x0b&lt;br /&gt;
],&lt;br /&gt;
hairs: [&lt;br /&gt;
    [0x21,0x2f,0x28,&lt;br /&gt;
    0x25,0x20,0x6b,&lt;br /&gt;
    0x30,0x33,0x37,&lt;br /&gt;
    0x46,0x2c,0x42],&lt;br /&gt;
    [0x34,0x32,0x26,&lt;br /&gt;
    0x31,0x2b,0x1f,&lt;br /&gt;
    0x38,0x44,0x3e,&lt;br /&gt;
    0x73,0x4c,0x77],&lt;br /&gt;
    [0x40,0x51,0x74,&lt;br /&gt;
    0x79,0x16,0x3a,&lt;br /&gt;
    0x3c,0x57,0x7d,&lt;br /&gt;
    0x75,0x49,0x4b],&lt;br /&gt;
    [0x2a,0x59,0x39,&lt;br /&gt;
    0x36,0x50,0x22,&lt;br /&gt;
    0x17,0x56,0x58,&lt;br /&gt;
    0x76,0x27,0x24],&lt;br /&gt;
    [0x2d,0x43,0x3b,&lt;br /&gt;
    0x41,0x29,0x1e,&lt;br /&gt;
    0x0c,0x10,0x0a,&lt;br /&gt;
    0x52,0x80,0x81],&lt;br /&gt;
    [0x0e,0x5f,0x69,&lt;br /&gt;
    0x64,0x06,0x14,&lt;br /&gt;
    0x5d,0x66,0x1b,&lt;br /&gt;
    0x04,0x11,0x6e]&lt;br /&gt;
    [0x7b,0x08,0x6a,&lt;br /&gt;
    0x48,0x03,0x15,&lt;br /&gt;
    0x00,0x62,0x3f,&lt;br /&gt;
    0x5a,0x0b,0x78],&lt;br /&gt;
    [0x05,0x4a,0x6c,&lt;br /&gt;
    0x5e,0x7c,0x19,&lt;br /&gt;
    0x63,0x45,0x23,&lt;br /&gt;
    0x0d,0x7a,0x71],&lt;br /&gt;
    [0x35,0x18,0x55,&lt;br /&gt;
    0x53,0x47,0x83,&lt;br /&gt;
    0x60,0x65,0x1d,&lt;br /&gt;
    0x07,0x0f,0x70],&lt;br /&gt;
    [0x4f,0x01,0x6d,&lt;br /&gt;
    0x7f,0x5b,0x1a,&lt;br /&gt;
    0x3d,0x67,0x02,&lt;br /&gt;
    0x4d,0x12,0x5c],&lt;br /&gt;
    [0x54,0x09,0x13,&lt;br /&gt;
    0x82,0x61,0x68,&lt;br /&gt;
    0x2e,0x4e,0x1c,&lt;br /&gt;
    0x72,0x7e,0x6f]&lt;br /&gt;
],&lt;br /&gt;
eyebrows: [&lt;br /&gt;
    [0x06,0x00,0x0c,&lt;br /&gt;
    0x01,0x09,0x13,&lt;br /&gt;
    0x07,0x15,0x08,&lt;br /&gt;
    0x11,0x05,0x04],&lt;br /&gt;
    [0x0b,0x0a,0x02,&lt;br /&gt;
    0x03,0x0e,0x14,&lt;br /&gt;
    0x0f,0x0d,0x16,&lt;br /&gt;
    0x12,0x10,0x17]&lt;br /&gt;
],&lt;br /&gt;
nose: [&lt;br /&gt;
    [0x01,0x0a,0x02,&lt;br /&gt;
    0x03,0x06,0x00,&lt;br /&gt;
    0x05,0x04,0x08,&lt;br /&gt;
    0x09,0x07,0x0B],&lt;br /&gt;
    [0x0d,0x0e,0x0c,&lt;br /&gt;
    0x11,0x10,0x0f]&lt;br /&gt;
],&lt;br /&gt;
mouth: [&lt;br /&gt;
    [0x17,0x01,0x13,&lt;br /&gt;
    0x15,0x16,0x05,&lt;br /&gt;
    0x00,0x08,0x0a,&lt;br /&gt;
    0x10,0x06,0x0d],&lt;br /&gt;
    [0x07,0x09,0x02,&lt;br /&gt;
    0x11,0x03,0x04,&lt;br /&gt;
    0x0f,0x0b,0x14,&lt;br /&gt;
    0x12,0x0e,0x0c],&lt;br /&gt;
    [0x1b,0x1e,0x18,&lt;br /&gt;
    0x19,0x1d,0x1c,&lt;br /&gt;
    0x1a,0x23,0x1f,&lt;br /&gt;
    0x22,0x21,0x20]&lt;br /&gt;
]&lt;br /&gt;
}&amp;lt;/nowiki&amp;gt;&lt;/div&gt;</summary>
		<author><name>Wwylele</name></author>
	</entry>
	<entry>
		<id>https://www.3dbrew.org/w/index.php?title=Mii&amp;diff=20901</id>
		<title>Mii</title>
		<link rel="alternate" type="text/html" href="https://www.3dbrew.org/w/index.php?title=Mii&amp;diff=20901"/>
		<updated>2019-03-05T15:49:29Z</updated>

		<summary type="html">&lt;p&gt;Wwylele: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Originally [http://wiibrew.org/wiki/Mii_Data created for the Nintendo Wii] (and backported to a selection of DS/i games), the &#039;&#039;&#039;Mii&#039;&#039;&#039; format was expanded with a larger selection of facial features and a new &amp;quot;copying&amp;quot; permission for the 3DS family, and later implemented as-is on Wii U.&lt;br /&gt;
&lt;br /&gt;
See [[Mii Maker]] for the application chiefly designed to create, edit, delete, and trade Miis or convert them from and to a QR code.&lt;br /&gt;
&lt;br /&gt;
The default endianness in this page is little-endian, unless explicitly specified.&lt;br /&gt;
&lt;br /&gt;
==Mii Database==&lt;br /&gt;
Format of the Mii main database &#039;&#039;&#039;CFL_DB.dat&#039;&#039;&#039;, found in [[Extdata#NAND_Shared_Extdata|shared extdata]] archive f0000000b.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset&lt;br /&gt;
! Length&lt;br /&gt;
! &lt;br /&gt;
|-&lt;br /&gt;
| 0x0&lt;br /&gt;
| 0x4&lt;br /&gt;
| Header &amp;quot;CFOG&amp;quot; (Mii Maker section)&lt;br /&gt;
|-&lt;br /&gt;
| 0x4&lt;br /&gt;
| 0x4&lt;br /&gt;
| Header 0x00010000&lt;br /&gt;
|-&lt;br /&gt;
| 0x8&lt;br /&gt;
| 0x23F0 (100 * 0x5C)&lt;br /&gt;
| Array of owned (saved in Mii Maker) Miis. Order in file is unrelated to canonical order in-app.&lt;br /&gt;
|-&lt;br /&gt;
| 0x23F8&lt;br /&gt;
| 0x4&lt;br /&gt;
| Header &amp;quot;CFHE&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| 0x23FC&lt;br /&gt;
| 0x2&lt;br /&gt;
| Linked list tail index. 0xFFFF if the list is empty&lt;br /&gt;
|-&lt;br /&gt;
| 0x23FE&lt;br /&gt;
| 0x2&lt;br /&gt;
| Linked list head index. 0xFFFF if the list is empty&lt;br /&gt;
|-&lt;br /&gt;
| 0x2400&lt;br /&gt;
| 0xA410 (3000 * 0xE)&lt;br /&gt;
| Linked list of objects? See chapter&lt;br /&gt;
|-&lt;br /&gt;
| 0xC810&lt;br /&gt;
| 0xE&lt;br /&gt;
| Padding?&lt;br /&gt;
|-&lt;br /&gt;
| 0xC81E&lt;br /&gt;
| 0x2&lt;br /&gt;
| Checksum of all of the above (the first 0xC81E byte). See section [[#Checksum|below]].&lt;br /&gt;
|-&lt;br /&gt;
| 0xC820&lt;br /&gt;
| 0x4&lt;br /&gt;
| Header &amp;quot;CFRA&amp;quot; (Invitations section)&lt;br /&gt;
|-&lt;br /&gt;
| 0xC824&lt;br /&gt;
| 0x4&lt;br /&gt;
| Mii count in this section. Maximum 100&lt;br /&gt;
|-&lt;br /&gt;
| 0xC828&lt;br /&gt;
| 0x64 (100 * 0x1)&lt;br /&gt;
| Order index of Mii in this section?&lt;br /&gt;
|-&lt;br /&gt;
| 0xC88C&lt;br /&gt;
| 0x1C20 (100 * 0x48)&lt;br /&gt;
| Array of Miis contributed from games, used for Mii Plaza &amp;quot;invitations&amp;quot; feature.&amp;lt;br/&amp;gt;The format isn&#039;t that of a full Mii. The &amp;quot;author&amp;quot; field is missing&lt;br /&gt;
|-&lt;br /&gt;
| 0xE4AC&lt;br /&gt;
| 0x12&lt;br /&gt;
| 01 00 [..] 00&lt;br /&gt;
|-&lt;br /&gt;
| 0xE4BE&lt;br /&gt;
| 0x2&lt;br /&gt;
| Checksum over the data above starting from 0xC820&lt;br /&gt;
|-&lt;br /&gt;
| 0xE4C0&lt;br /&gt;
| 0x3D860 (3000 * 0x54)&lt;br /&gt;
| Another array of Miis. Seems related to the CFHE section. &amp;lt;br/&amp;gt;The Mii format in this section is modified. The &amp;quot;author&amp;quot; field is missing, A 4-byte timestamp (seconds since 2000) together with 8-byte zeros(?) is appended at the end.&lt;br /&gt;
|}&lt;br /&gt;
When encrypted in QR codes, 4 additional bytes are added. Two null bytes and a CRC-16. It&#039;s the exact same CRC-16 as for the Wii blocks on the 0x5e first bytes. It seems that the CRC is ignored, the Mii Maker expecting the result of APT:Unwrap to detect integrity loss.&lt;br /&gt;
&lt;br /&gt;
==CFHE object==&lt;br /&gt;
&lt;br /&gt;
A 0xE-byte long linked list node. The format is 4-byte Mii ID (See Mii format) + 6-byte MAC + 2-byte previous node index (prev) + 2-byte next node index (next).&lt;br /&gt;
&lt;br /&gt;
An invalid node has value: ID = 0, MAC = 0, prev = 0x7FFF, next = 0x7FFF.&lt;br /&gt;
&lt;br /&gt;
The highest bit of these fields has some special meaning and isn&#039;t part of the index value.&lt;br /&gt;
&lt;br /&gt;
==Checksum==&lt;br /&gt;
&lt;br /&gt;
The algorithm used to verify the integrity of the database is based on [http://srecord.sourceforge.net/crc16-ccitt.html CRC16-CCITT], though it&#039;s an incorrect implementation. It is the same algorithm used to verify [http://wiibrew.org/wiki/Mii_Data#Block_format Mii Data on the Wii].&lt;br /&gt;
&lt;br /&gt;
To obtain the correct value for the checksum, apply the algorithm to the first 0xC81E bytes of the database. This can be done using [https://gbatemp.net/threads/tutorial-give-your-mii-gold-pants-and-use-it-for-streetpass.379146/page-24#post-6569186 FixCRC]; alternativly a pseudocode implementation of the checksum algorithm is given below:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
def crc16_CCITTWii(u8[]: data) -&amp;gt; u16:&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Calculate a checksum of data using the CRC16-CCITT implementation of the Wii&lt;br /&gt;
&lt;br /&gt;
    This implementation uses 0x0000 as the starting value, which is different&lt;br /&gt;
    from what CRC16-CCITT specifies.&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    # note: a correct implementation of CRC16-CCITT&lt;br /&gt;
    #       would initialize this to 0xffff&lt;br /&gt;
    u32 crc := 0x0&lt;br /&gt;
&lt;br /&gt;
    for byte in data:&lt;br /&gt;
        # Iterate over every of the 8 bits in byte.&lt;br /&gt;
        # Begin with the most significant bit. (7, 6, ... , 1, 0)&lt;br /&gt;
        for bit in 7..0:&lt;br /&gt;
            # &amp;amp; - binary `and&#039;; &amp;lt;&amp;lt;/&amp;gt;&amp;gt; - bitshift left/right; ^ - binary `xor&#039;&lt;br /&gt;
            crc := (&lt;br /&gt;
                     (crc &amp;lt;&amp;lt; 1) | ((byte &amp;gt;&amp;gt; bit) &amp;amp; 0x1)&lt;br /&gt;
                     ^ (0x1021 if crc &amp;amp; 0x8000 else 0)&lt;br /&gt;
                   )&lt;br /&gt;
&lt;br /&gt;
    for _ in 0..15:&lt;br /&gt;
        crc := (crc &amp;lt;&amp;lt; 1) ^ (0x1021 if crc &amp;amp; 0x8000 else 0)&lt;br /&gt;
&lt;br /&gt;
    # only return the lowest 16 bit of crc&lt;br /&gt;
    return (u16) (crc &amp;amp; 0xffff)&lt;br /&gt;
&lt;br /&gt;
checksum := crc16_CCITTWii(miidb[0:0xc81e]) # checksum over the first 0xc81e bytes&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Mii format==&lt;br /&gt;
&lt;br /&gt;
Note: 0x18-3B have been copied as-is from [[Mii_Maker#Mii_QR_Code_format|the QR code specification]], so they&#039;re unverified.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset&lt;br /&gt;
! Length&lt;br /&gt;
! &lt;br /&gt;
|-&lt;br /&gt;
| 0x0&lt;br /&gt;
| 0x4&lt;br /&gt;
| Mii Header (see chapter)&lt;br /&gt;
|-&lt;br /&gt;
| 0x4&lt;br /&gt;
| 0x8&lt;br /&gt;
| System ID (identifies owner, for purpose of enforcing editing restrictions and blue pants).&amp;lt;br/&amp;gt;Is not tied to the MAC address anymore.&lt;br /&gt;
|-&lt;br /&gt;
| 0xC&lt;br /&gt;
| 0x4&lt;br /&gt;
| Mii ID (big-endian 32bit unsigned integer):&amp;lt;br/&amp;gt;Bit 0..27: (bit[0..27] * 2) = date of creation (seconds since 01/01/2010 00:00:00)&amp;lt;br/&amp;gt;Bit 31: not set iff Mii is special&lt;br /&gt;
|-&lt;br /&gt;
| 0x10&lt;br /&gt;
| 0x6&lt;br /&gt;
| Creator&#039;s full MAC&lt;br /&gt;
|-&lt;br /&gt;
| 0x16&lt;br /&gt;
| 0x2&lt;br /&gt;
| Padding (0000)&lt;br /&gt;
|-&lt;br /&gt;
| 0x18&lt;br /&gt;
| 0x2&lt;br /&gt;
| Bit-mapped: Birthday (4bit-day,5bit-month), Sex, Shirt color, Favorite (0x40 bit at 0x19)&lt;br /&gt;
|-&lt;br /&gt;
| 0x1A&lt;br /&gt;
| 0x14&lt;br /&gt;
| UTF-16 Mii Name (10 chars max, 0000 terminated)&lt;br /&gt;
|-&lt;br /&gt;
| 0x2E&lt;br /&gt;
| 0x2&lt;br /&gt;
| width &amp;amp; height&lt;br /&gt;
|-&lt;br /&gt;
| 0x30&lt;br /&gt;
| 0x1&lt;br /&gt;
| bit 0: disable sharing&amp;lt;br/&amp;gt;bit 1-4: face shape&amp;lt;br/&amp;gt;bit 5-7: skin color&lt;br /&gt;
|-&lt;br /&gt;
| 0x31&lt;br /&gt;
| 0x1&lt;br /&gt;
| bit 0-3: wrinkles&amp;lt;br/&amp;gt;bit 4-7: makeup&lt;br /&gt;
|-&lt;br /&gt;
| 0x32&lt;br /&gt;
| 0x1&lt;br /&gt;
| hair style&lt;br /&gt;
|-&lt;br /&gt;
| 0x33&lt;br /&gt;
| 0x1&lt;br /&gt;
| bit 0-2: hair color&amp;lt;br/&amp;gt;bit 3: flip hair&lt;br /&gt;
|-&lt;br /&gt;
| 0x34&lt;br /&gt;
| 0x4&lt;br /&gt;
| unknown&lt;br /&gt;
|-&lt;br /&gt;
| 0x38&lt;br /&gt;
| 0x1&lt;br /&gt;
| bit 0-4: eyebrow style&amp;lt;br/&amp;gt;bit 5-7: eyebrow color&lt;br /&gt;
|-&lt;br /&gt;
| 0x39&lt;br /&gt;
| 0x1&lt;br /&gt;
| bit 0-3: eyebrow scale&amp;lt;br/&amp;gt;bit 4-6: eyebrow yscale&lt;br /&gt;
|-&lt;br /&gt;
| 0x3A&lt;br /&gt;
| 0x2&lt;br /&gt;
| note that the bytes are swapped over (little-endian layout)&amp;lt;br/&amp;gt;bit 0-3: eyebrow rotation&amp;lt;br/&amp;gt;bit 5-8: eyebrow x spacing&amp;lt;br/&amp;gt;bit 9-13: eyebrow y position&lt;br /&gt;
|-&lt;br /&gt;
| 0x3C&lt;br /&gt;
| 0x4&lt;br /&gt;
| unknown&lt;br /&gt;
|-&lt;br /&gt;
| 0x40&lt;br /&gt;
| 0x1&lt;br /&gt;
| Allow Copying (?) (0D on 0E off 8D on)&lt;br /&gt;
|-&lt;br /&gt;
| 0x41&lt;br /&gt;
| 0x7&lt;br /&gt;
| unknown&lt;br /&gt;
|-&lt;br /&gt;
| 0x48&lt;br /&gt;
| 0x14&lt;br /&gt;
| UTF-16 Author Name (10 chars max, 0000 terminated)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Mii Header==&lt;br /&gt;
* Byte 0: generally equals 3 (category?)&lt;br /&gt;
* Byte 1: 0/1 = copying off/on&lt;br /&gt;
* Byte 2, most significant hex digit: position on page (0-9)&lt;br /&gt;
* Byte 2, least significant hex digit: page (0-9)&lt;br /&gt;
* Byte 3: generally 0x30 (always for user-created ones?)&lt;br /&gt;
&lt;br /&gt;
===Mii categories (pants colors)===&lt;br /&gt;
&lt;br /&gt;
====Special (gold) Miis====&lt;br /&gt;
Specialness will override any other color and make the Mii non-editable.&lt;br /&gt;
&lt;br /&gt;
Copying is rumored to have to be disabled.&lt;br /&gt;
&lt;br /&gt;
Zeroed system-id and timestamp?&lt;br /&gt;
&lt;br /&gt;
====Imported (blue) Miis====&lt;br /&gt;
Any (non-gold) Mii with a different System ID will appear as a foreign one.&lt;br /&gt;
&lt;br /&gt;
There is also a range of Mii IDs that are always foreign and uneditable, regardless of the System ID:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====Regular (black/red) Miis====&lt;br /&gt;
Always editable, since they can only appear as such on the console that created them.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====Personal (red) Mii====&lt;br /&gt;
A red Mii that happens to be the first in the file!&lt;br /&gt;
&lt;br /&gt;
==Mii values==&lt;br /&gt;
Each of the following values were found with NTR Debugger:&lt;br /&gt;
If you want to access the value, grab the given &amp;quot;NTR address&amp;quot; and add 0x08815000.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Data&lt;br /&gt;
! NTR address&lt;br /&gt;
! Variation (hex)&lt;br /&gt;
! Notes&lt;br /&gt;
|-&lt;br /&gt;
| Face style&lt;br /&gt;
| 0x894&lt;br /&gt;
| 00-0B&lt;br /&gt;
| Not ordered as in editor, read below&lt;br /&gt;
|-&lt;br /&gt;
| Face color&lt;br /&gt;
| 0x898&lt;br /&gt;
| 00-05&lt;br /&gt;
| From top to bottom&lt;br /&gt;
|-&lt;br /&gt;
| Wrinkles&lt;br /&gt;
| 0x89C&lt;br /&gt;
| 00-0B&lt;br /&gt;
| Same order as displayed in editor&lt;br /&gt;
|-&lt;br /&gt;
| Makeup&lt;br /&gt;
| 0x8A0&lt;br /&gt;
| 00-0B&lt;br /&gt;
| Same order as displayed in editor&lt;br /&gt;
|-&lt;br /&gt;
| Hair style&lt;br /&gt;
| 0x8A4&lt;br /&gt;
| 00-84&lt;br /&gt;
| Not ordered as in editor, read below&lt;br /&gt;
|-&lt;br /&gt;
| Hair color&lt;br /&gt;
| 0x8A8&lt;br /&gt;
| 00-07&lt;br /&gt;
| From top to bottom&lt;br /&gt;
|-&lt;br /&gt;
| Hair flipped&lt;br /&gt;
| 0x8AC&lt;br /&gt;
| 1 if true&lt;br /&gt;
| From top to bottom&lt;br /&gt;
|-&lt;br /&gt;
| Eye style&lt;br /&gt;
| 0x8B0&lt;br /&gt;
| 00-3C&lt;br /&gt;
| Not ordered as in editor, read below&lt;br /&gt;
|-&lt;br /&gt;
| Eyes color&lt;br /&gt;
| 0x8B4&lt;br /&gt;
| 00-05&lt;br /&gt;
| From top to bottom&lt;br /&gt;
|-&lt;br /&gt;
| Eyes size&lt;br /&gt;
| 0x8B8&lt;br /&gt;
| 07-00&lt;br /&gt;
| Left button increases value.&lt;br /&gt;
|-&lt;br /&gt;
| Eyes thickness&lt;br /&gt;
| 0x8BC&lt;br /&gt;
| 06-00&lt;br /&gt;
| Left button increases value.&lt;br /&gt;
|-&lt;br /&gt;
| Eyes rotation&lt;br /&gt;
| 0x8C0&lt;br /&gt;
| 00-07&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| Eyes spacing&lt;br /&gt;
| 0x8C4&lt;br /&gt;
| 00-0C&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| Eyes height&lt;br /&gt;
| 0x8C8&lt;br /&gt;
| 00-12&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| Eyebrows style&lt;br /&gt;
| 0x8CC&lt;br /&gt;
| 00-18&lt;br /&gt;
| Not ordered as in editor, read below&lt;br /&gt;
|-&lt;br /&gt;
| Eyebrows color&lt;br /&gt;
| 0x8D0&lt;br /&gt;
| 00-07&lt;br /&gt;
| From top to bottom&lt;br /&gt;
|-&lt;br /&gt;
| Eyebrows size&lt;br /&gt;
| 0x8D4&lt;br /&gt;
| 08-00&lt;br /&gt;
| Left button increases value.&lt;br /&gt;
|-&lt;br /&gt;
| Eyebrows thickness&lt;br /&gt;
| 0x8D8&lt;br /&gt;
| 06-00&lt;br /&gt;
| Left button increases value.&lt;br /&gt;
|-&lt;br /&gt;
| Eyebrows rotation&lt;br /&gt;
| 0x8DC&lt;br /&gt;
| 00-0B&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| Eyebrows spacing&lt;br /&gt;
| 0x8E0&lt;br /&gt;
| 00-0C&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| Eyebrows height&lt;br /&gt;
| 0x8E4&lt;br /&gt;
| 03-12&lt;br /&gt;
| Yup, minimum is 0x03&lt;br /&gt;
|-&lt;br /&gt;
| Nose style&lt;br /&gt;
| 0x8E8&lt;br /&gt;
| 00-11&lt;br /&gt;
| Not ordered as in editor, read below&lt;br /&gt;
|-&lt;br /&gt;
| Nose size&lt;br /&gt;
| 0x8EC&lt;br /&gt;
| 08-00&lt;br /&gt;
| Left button increases value.&lt;br /&gt;
|-&lt;br /&gt;
| Nose height&lt;br /&gt;
| 0x8F0&lt;br /&gt;
| 00-12&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| Mouth style&lt;br /&gt;
| 0x8F4&lt;br /&gt;
| 00-23&lt;br /&gt;
| Not ordered as in editor, read below&lt;br /&gt;
|-&lt;br /&gt;
| Mouth color&lt;br /&gt;
| 0x8F8&lt;br /&gt;
| 00-04&lt;br /&gt;
| From top to bottom.&lt;br /&gt;
|-&lt;br /&gt;
| Mouth size&lt;br /&gt;
| 0x8FC&lt;br /&gt;
| 08-00&lt;br /&gt;
| Left button increases value.&lt;br /&gt;
|-&lt;br /&gt;
| Mouth thickness&lt;br /&gt;
| 0x900&lt;br /&gt;
| 06-00&lt;br /&gt;
| Left button increases value.&lt;br /&gt;
|-&lt;br /&gt;
| Mouth height&lt;br /&gt;
| 0x904&lt;br /&gt;
| 00-12&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| Mustache style&lt;br /&gt;
| 0x908&lt;br /&gt;
| 00-05&lt;br /&gt;
| Order like in editor.&lt;br /&gt;
|-&lt;br /&gt;
| Beard style&lt;br /&gt;
| 0x90C&lt;br /&gt;
| 00-05&lt;br /&gt;
| Order like in editor.&lt;br /&gt;
|-&lt;br /&gt;
| Mustache/Beard color&lt;br /&gt;
| 0x910&lt;br /&gt;
| 00-07&lt;br /&gt;
| From top to button.&lt;br /&gt;
|-&lt;br /&gt;
| Mustache size&lt;br /&gt;
| 0x914&lt;br /&gt;
| 08-00&lt;br /&gt;
| Left button increases value.&lt;br /&gt;
|-&lt;br /&gt;
| Mustache height&lt;br /&gt;
| 0x918&lt;br /&gt;
| 00-10&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| Glasses style&lt;br /&gt;
| 0x91C&lt;br /&gt;
| 00-08&lt;br /&gt;
| Order like in editor.&lt;br /&gt;
|-&lt;br /&gt;
| Glasses color&lt;br /&gt;
| 0x920&lt;br /&gt;
| 00-05&lt;br /&gt;
| From top to bottom&lt;br /&gt;
|-&lt;br /&gt;
| Glasses size&lt;br /&gt;
| 0x924&lt;br /&gt;
| 07-00&lt;br /&gt;
| Left button increases value.&lt;br /&gt;
|-&lt;br /&gt;
| Glasses height&lt;br /&gt;
| 0x928&lt;br /&gt;
| 00-14&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| Mole enable&lt;br /&gt;
| 0x92C&lt;br /&gt;
| 1 if enabled, 0 else.&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| Mole size&lt;br /&gt;
| 0x930&lt;br /&gt;
| 08-00&lt;br /&gt;
| Left button increases value.&lt;br /&gt;
|-&lt;br /&gt;
| Mole horiz pos&lt;br /&gt;
| 0x934&lt;br /&gt;
| 00-10&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| Mole vert pos&lt;br /&gt;
| 0x938&lt;br /&gt;
| 00-1E&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| Mii height&lt;br /&gt;
| 0x93C&lt;br /&gt;
| 00-7F&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| Mii weight&lt;br /&gt;
| 0x940&lt;br /&gt;
| 00-7F&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| Mii name&lt;br /&gt;
| 0x944-0x959&lt;br /&gt;
| UTF-16&lt;br /&gt;
| Terminated with 0x0000. Not updated immediatly?&lt;br /&gt;
|-&lt;br /&gt;
| Creator&#039;s name&lt;br /&gt;
| 0x95A-96F&lt;br /&gt;
| UTF-16&lt;br /&gt;
| Terminated with 0x0000. Not updated immediatly?&lt;br /&gt;
|-&lt;br /&gt;
| Mii gender&lt;br /&gt;
| 0x970&lt;br /&gt;
| 0: Male, 1: Female&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| Birthdate month&lt;br /&gt;
| 0x974&lt;br /&gt;
| 01-0C&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| Birthdate day&lt;br /&gt;
| 0x978&lt;br /&gt;
| 01-1F&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| Mii shirt color&lt;br /&gt;
| 0x97C&lt;br /&gt;
| 00-0B&lt;br /&gt;
| Ordered like in editor.&lt;br /&gt;
|-&lt;br /&gt;
| Favorite&lt;br /&gt;
| 0x980&lt;br /&gt;
| 0: false, 1: true&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| Allow copy&lt;br /&gt;
| 0x981&lt;br /&gt;
| 0: false, 1: true&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| Unused byte?&lt;br /&gt;
| 0x982&lt;br /&gt;
| &lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| Allow sharing&lt;br /&gt;
| 0x983&lt;br /&gt;
| 0: true, 1: false&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
| ???&lt;br /&gt;
| 0x984-0x98F&lt;br /&gt;
| All zero?&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
| ???&lt;br /&gt;
| 0x990-0x997&lt;br /&gt;
| 4?&lt;br /&gt;
|&lt;br /&gt;
|}&lt;br /&gt;
0x08815998: Same 4 bytes as encrypted Mii: first 4 bits for Mii type, 4 next for number of seconds since 01/01/2010 00:00:00 UTC+3 (should be verified by other country and region 3DS) divided by 2.&lt;br /&gt;
0x0881599C: 6 bytes of MAC address of the 3DS that created the Mii.&lt;br /&gt;
0x088159A2: 6 unknow uses bytes&lt;br /&gt;
0x088159A8: Same 8 bytes as decrypted Mii at 0x04 through 0x0B. Seems NAND specific, kept the same on Miis created on same NAND but different 3DS via System Transfer. Might be a coincidence but the two first bytes are in ID0 folder name in the Nintendo 3DS folder.&lt;br /&gt;
&lt;br /&gt;
===Mapped Editor &amp;lt;-&amp;gt; Hex values===&lt;br /&gt;
&lt;br /&gt;
Most of the values are ordered (left button decreases, right increases, color choices are top to bottom...) but for most &amp;quot;main&amp;quot; part of the UI, where you choose the style of the part being edited, hex values has no correlation with displayed order.&lt;br /&gt;
Here is a JSON that can go from a Part, a Page and Position to the right hex value. This is 0 indexed (eg: datas[&amp;quot;face&amp;quot;][0][11]).&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;{&lt;br /&gt;
face: [&lt;br /&gt;
    0x00,0x01,0x08,&lt;br /&gt;
    0x02,0x03,0x09,&lt;br /&gt;
    0x04,0x05,0x0a,&lt;br /&gt;
    0x06,0x07,0x0b&lt;br /&gt;
],&lt;br /&gt;
hairs: [&lt;br /&gt;
    [0x21,0x2f,0x28,&lt;br /&gt;
    0x25,0x20,0x6b,&lt;br /&gt;
    0x30,0x33,0x37,&lt;br /&gt;
    0x46,0x2c,0x42],&lt;br /&gt;
    [0x34,0x32,0x26,&lt;br /&gt;
    0x31,0x2b,0x1f,&lt;br /&gt;
    0x38,0x44,0x3e,&lt;br /&gt;
    0x73,0x4c,0x77],&lt;br /&gt;
    [0x40,0x51,0x74,&lt;br /&gt;
    0x79,0x16,0x3a,&lt;br /&gt;
    0x3c,0x57,0x7d,&lt;br /&gt;
    0x75,0x49,0x4b],&lt;br /&gt;
    [0x2a,0x59,0x39,&lt;br /&gt;
    0x36,0x50,0x22,&lt;br /&gt;
    0x17,0x56,0x58,&lt;br /&gt;
    0x76,0x27,0x24],&lt;br /&gt;
    [0x2d,0x43,0x3b,&lt;br /&gt;
    0x41,0x29,0x1e,&lt;br /&gt;
    0x0c,0x10,0x0a,&lt;br /&gt;
    0x52,0x80,0x81],&lt;br /&gt;
    [0x0e,0x5f,0x69,&lt;br /&gt;
    0x64,0x06,0x14,&lt;br /&gt;
    0x5d,0x66,0x1b,&lt;br /&gt;
    0x04,0x11,0x6e]&lt;br /&gt;
    [0x7b,0x08,0x6a,&lt;br /&gt;
    0x48,0x03,0x15,&lt;br /&gt;
    0x00,0x62,0x3f,&lt;br /&gt;
    0x5a,0x0b,0x78],&lt;br /&gt;
    [0x05,0x4a,0x6c,&lt;br /&gt;
    0x5e,0x7c,0x19,&lt;br /&gt;
    0x63,0x45,0x23,&lt;br /&gt;
    0x0d,0x7a,0x71],&lt;br /&gt;
    [0x35,0x18,0x55,&lt;br /&gt;
    0x53,0x47,0x83,&lt;br /&gt;
    0x60,0x65,0x1d,&lt;br /&gt;
    0x07,0x0f,0x70],&lt;br /&gt;
    [0x4f,0x01,0x6d,&lt;br /&gt;
    0x7f,0x5b,0x1a,&lt;br /&gt;
    0x3d,0x67,0x02,&lt;br /&gt;
    0x4d,0x12,0x5c],&lt;br /&gt;
    [0x54,0x09,0x13,&lt;br /&gt;
    0x82,0x61,0x68,&lt;br /&gt;
    0x2e,0x4e,0x1c,&lt;br /&gt;
    0x72,0x7e,0x6f]&lt;br /&gt;
],&lt;br /&gt;
eyebrows: [&lt;br /&gt;
    [0x06,0x00,0x0c,&lt;br /&gt;
    0x01,0x09,0x13,&lt;br /&gt;
    0x07,0x15,0x08,&lt;br /&gt;
    0x11,0x05,0x04],&lt;br /&gt;
    [0x0b,0x0a,0x02,&lt;br /&gt;
    0x03,0x0e,0x14,&lt;br /&gt;
    0x0f,0x0d,0x16,&lt;br /&gt;
    0x12,0x10,0x17]&lt;br /&gt;
],&lt;br /&gt;
nose: [&lt;br /&gt;
    [0x01,0x0a,0x02,&lt;br /&gt;
    0x03,0x06,0x00,&lt;br /&gt;
    0x05,0x04,0x08,&lt;br /&gt;
    0x09,0x07,0x0B],&lt;br /&gt;
    [0x0d,0x0e,0x0c,&lt;br /&gt;
    0x11,0x10,0x0f]&lt;br /&gt;
],&lt;br /&gt;
mouth: [&lt;br /&gt;
    [0x17,0x01,0x13,&lt;br /&gt;
    0x15,0x16,0x05,&lt;br /&gt;
    0x00,0x08,0x0a,&lt;br /&gt;
    0x10,0x06,0x0d],&lt;br /&gt;
    [0x07,0x09,0x02,&lt;br /&gt;
    0x11,0x03,0x04,&lt;br /&gt;
    0x0f,0x0b,0x14,&lt;br /&gt;
    0x12,0x0e,0x0c],&lt;br /&gt;
    [0x1b,0x1e,0x18,&lt;br /&gt;
    0x19,0x1d,0x1c,&lt;br /&gt;
    0x1a,0x23,0x1f,&lt;br /&gt;
    0x22,0x21,0x20]&lt;br /&gt;
]&lt;br /&gt;
}&amp;lt;/nowiki&amp;gt;&lt;/div&gt;</summary>
		<author><name>Wwylele</name></author>
	</entry>
	<entry>
		<id>https://www.3dbrew.org/w/index.php?title=Mii&amp;diff=20891</id>
		<title>Mii</title>
		<link rel="alternate" type="text/html" href="https://www.3dbrew.org/w/index.php?title=Mii&amp;diff=20891"/>
		<updated>2019-02-19T15:48:52Z</updated>

		<summary type="html">&lt;p&gt;Wwylele: /* Mii Database */ Confirmed another checksum according to MarioCart DLP child code&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Originally [http://wiibrew.org/wiki/Mii_Data created for the Nintendo Wii] (and backported to a selection of DS/i games), the &#039;&#039;&#039;Mii&#039;&#039;&#039; format was expanded with a larger selection of facial features and a new &amp;quot;copying&amp;quot; permission for the 3DS family, and later implemented as-is on Wii U.&lt;br /&gt;
&lt;br /&gt;
See [[Mii Maker]] for the application chiefly designed to create, edit, delete, and trade Miis or convert them from and to a QR code.&lt;br /&gt;
&lt;br /&gt;
==Mii Database==&lt;br /&gt;
Format of the Mii main database &#039;&#039;&#039;CFL_DB.dat&#039;&#039;&#039;, found in [[Extdata#NAND_Shared_Extdata|shared extdata]] archive f0000000b.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset&lt;br /&gt;
! Length&lt;br /&gt;
! &lt;br /&gt;
|-&lt;br /&gt;
| 0x0&lt;br /&gt;
| 0x4&lt;br /&gt;
| Header &amp;quot;CFOG&amp;quot; (Mii Maker section)&lt;br /&gt;
|-&lt;br /&gt;
| 0x4&lt;br /&gt;
| 0x4&lt;br /&gt;
| Header 0x00010000&lt;br /&gt;
|-&lt;br /&gt;
| 0x8&lt;br /&gt;
| 0x23F0 (100 * 0x5C)&lt;br /&gt;
| Array of owned (saved in Mii Maker) Miis. Order in file is unrelated to canonical order in-app.&lt;br /&gt;
|-&lt;br /&gt;
| 0x23F8&lt;br /&gt;
| 0x4&lt;br /&gt;
| Header &amp;quot;CFHE&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| 0x23FC&lt;br /&gt;
| 0x4&lt;br /&gt;
| Header 0xFFFFFFFF&lt;br /&gt;
|-&lt;br /&gt;
| 0x2400&lt;br /&gt;
| 0xA41E&lt;br /&gt;
| Array of objects? See chapter&lt;br /&gt;
|-&lt;br /&gt;
| 0xC81E&lt;br /&gt;
| 0x2&lt;br /&gt;
| Checksum of all of the above (the first 0xC81E byte). See section [[#Checksum|below]].&lt;br /&gt;
|-&lt;br /&gt;
| 0xC820&lt;br /&gt;
| 0x4&lt;br /&gt;
| Header &amp;quot;CFRA&amp;quot; (Invitations section)&lt;br /&gt;
|-&lt;br /&gt;
| 0xC824&lt;br /&gt;
| 0x4&lt;br /&gt;
| Header? 0x39000000&lt;br /&gt;
|-&lt;br /&gt;
| 0xC861&lt;br /&gt;
| 0x2B&lt;br /&gt;
| Weird padding? 0x00&lt;br /&gt;
|-&lt;br /&gt;
| 0xC88C&lt;br /&gt;
| 0x1C20 (?)&lt;br /&gt;
| Array of Miis contributed from games, used for Mii Plaza &amp;quot;invitations&amp;quot; feature.&amp;lt;br/&amp;gt;The format isn&#039;t that of a full Mii.&lt;br /&gt;
|-&lt;br /&gt;
| 0xE4AC&lt;br /&gt;
| 0x12&lt;br /&gt;
| 01 00 [..] 00&lt;br /&gt;
|-&lt;br /&gt;
| 0xE4BE&lt;br /&gt;
| 0x2&lt;br /&gt;
| Checksum over the data above starting from 0xC820&lt;br /&gt;
|-&lt;br /&gt;
| 0xE4C0&lt;br /&gt;
| 0x3D860&lt;br /&gt;
| Empty (00)&lt;br /&gt;
|}&lt;br /&gt;
When encrypted in QR codes, 4 additional bytes are added. Two null bytes and a CRC-16. It&#039;s the exact same CRC-16 as for the Wii blocks on the 0x5e first bytes. It seems that the CRC is ignored, the Mii Maker expecting the result of APT:Unwrap to detect integrity loss.&lt;br /&gt;
&lt;br /&gt;
==CFHE object==&lt;br /&gt;
&lt;br /&gt;
A 0xE-byte long item.&lt;br /&gt;
&lt;br /&gt;
On my database, they&#039;re all 0000 0000 0000 0000 0000 FF7F FF7F.&lt;br /&gt;
&lt;br /&gt;
Wild speculation: blacklist of already scanned celebrity (gold) Mii QRs?&lt;br /&gt;
&lt;br /&gt;
Alternative interpretation: FFFF FFFF 0000 0000 0000 0000 0000 is the 1st item;  FF7F FF7F 0000 [...] the 2nd, etc;&lt;br /&gt;
&lt;br /&gt;
==Checksum==&lt;br /&gt;
&lt;br /&gt;
The algorithm used to verify the integrity of the database is based on [http://srecord.sourceforge.net/crc16-ccitt.html CRC16-CCITT], though it&#039;s an incorrect implementation. It is the same algorithm used to verify [http://wiibrew.org/wiki/Mii_Data#Block_format Mii Data on the Wii].&lt;br /&gt;
&lt;br /&gt;
To obtain the correct value for the checksum, apply the algorithm to the first 0xC81E bytes of the database. This can be done using [https://gbatemp.net/threads/tutorial-give-your-mii-gold-pants-and-use-it-for-streetpass.379146/page-24#post-6569186 FixCRC]; alternativly a pseudocode implementation of the checksum algorithm is given below:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
def crc16_CCITTWii(u8[]: data) -&amp;gt; u16:&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Calculate a checksum of data using the CRC16-CCITT implementation of the Wii&lt;br /&gt;
&lt;br /&gt;
    This implementation uses 0x0000 as the starting value, which is different&lt;br /&gt;
    from what CRC16-CCITT specifies.&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    # note: a correct implementation of CRC16-CCITT&lt;br /&gt;
    #       would initialize this to 0xffff&lt;br /&gt;
    u32 crc := 0x0&lt;br /&gt;
&lt;br /&gt;
    for byte in data:&lt;br /&gt;
        # Iterate over every of the 8 bits in byte.&lt;br /&gt;
        # Begin with the most significant bit. (7, 6, ... , 1, 0)&lt;br /&gt;
        for bit in 7..0:&lt;br /&gt;
            # &amp;amp; - binary `and&#039;; &amp;lt;&amp;lt;/&amp;gt;&amp;gt; - bitshift left/right; ^ - binary `xor&#039;&lt;br /&gt;
            crc := (&lt;br /&gt;
                     (crc &amp;lt;&amp;lt; 1) | ((byte &amp;gt;&amp;gt; bit) &amp;amp; 0x1)&lt;br /&gt;
                     ^ (0x1021 if crc &amp;amp; 0x8000 else 0)&lt;br /&gt;
                   )&lt;br /&gt;
&lt;br /&gt;
    for _ in 0..15:&lt;br /&gt;
        crc := (crc &amp;lt;&amp;lt; 1) ^ (0x1021 if crc &amp;amp; 0x8000 else 0)&lt;br /&gt;
&lt;br /&gt;
    # only return the lowest 16 bit of crc&lt;br /&gt;
    return (u16) (crc &amp;amp; 0xffff)&lt;br /&gt;
&lt;br /&gt;
checksum := crc16_CCITTWii(miidb[0:0xc81e]) # checksum over the first 0xc81e bytes&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Mii format==&lt;br /&gt;
&lt;br /&gt;
Note: 0x18-3B have been copied as-is from [[Mii_Maker#Mii_QR_Code_format|the QR code specification]], so they&#039;re unverified.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset&lt;br /&gt;
! Length&lt;br /&gt;
! &lt;br /&gt;
|-&lt;br /&gt;
| 0x0&lt;br /&gt;
| 0x4&lt;br /&gt;
| Mii ID (see chapter)&lt;br /&gt;
|-&lt;br /&gt;
| 0x4&lt;br /&gt;
| 0x8&lt;br /&gt;
| System ID (identifies owner, for purpose of enforcing editing restrictions and blue pants).&amp;lt;br/&amp;gt;Is not tied to the MAC address anymore.&lt;br /&gt;
|-&lt;br /&gt;
| 0xC&lt;br /&gt;
| 0x4&lt;br /&gt;
| Specialness and date of creation (big-endian 32bit unsigned integer):&amp;lt;br/&amp;gt;Bit 0..27: (bit[0..27] * 2) = date of creation (seconds since 01/01/2010 00:00:00)&amp;lt;br/&amp;gt;Bit 31: not set iff Mii is special&lt;br /&gt;
|-&lt;br /&gt;
| 0x10&lt;br /&gt;
| 0x6&lt;br /&gt;
| Creator&#039;s full MAC&lt;br /&gt;
|-&lt;br /&gt;
| 0x16&lt;br /&gt;
| 0x2&lt;br /&gt;
| Padding (0000)&lt;br /&gt;
|-&lt;br /&gt;
| 0x18&lt;br /&gt;
| 0x2&lt;br /&gt;
| Bit-mapped: Birthday (4bit-day,5bit-month), Sex, Shirt color, Favorite (0x40 bit at 0x19)&lt;br /&gt;
|-&lt;br /&gt;
| 0x1A&lt;br /&gt;
| 0x14&lt;br /&gt;
| UTF-16 Mii Name (10 chars max, 0000 terminated)&lt;br /&gt;
|-&lt;br /&gt;
| 0x2E&lt;br /&gt;
| 0x2&lt;br /&gt;
| width &amp;amp; height&lt;br /&gt;
|-&lt;br /&gt;
| 0x30&lt;br /&gt;
| 0x1&lt;br /&gt;
| bit 0: disable sharing&amp;lt;br/&amp;gt;bit 1-4: face shape&amp;lt;br/&amp;gt;bit 5-7: skin color&lt;br /&gt;
|-&lt;br /&gt;
| 0x31&lt;br /&gt;
| 0x1&lt;br /&gt;
| bit 0-3: wrinkles&amp;lt;br/&amp;gt;bit 4-7: makeup&lt;br /&gt;
|-&lt;br /&gt;
| 0x32&lt;br /&gt;
| 0x1&lt;br /&gt;
| hair style&lt;br /&gt;
|-&lt;br /&gt;
| 0x33&lt;br /&gt;
| 0x1&lt;br /&gt;
| bit 0-2: hair color&amp;lt;br/&amp;gt;bit 3: flip hair&lt;br /&gt;
|-&lt;br /&gt;
| 0x34&lt;br /&gt;
| 0x4&lt;br /&gt;
| unknown&lt;br /&gt;
|-&lt;br /&gt;
| 0x38&lt;br /&gt;
| 0x1&lt;br /&gt;
| bit 0-4: eyebrow style&amp;lt;br/&amp;gt;bit 5-7: eyebrow color&lt;br /&gt;
|-&lt;br /&gt;
| 0x39&lt;br /&gt;
| 0x1&lt;br /&gt;
| bit 0-3: eyebrow scale&amp;lt;br/&amp;gt;bit 4-6: eyebrow yscale&lt;br /&gt;
|-&lt;br /&gt;
| 0x3A&lt;br /&gt;
| 0x2&lt;br /&gt;
| note that the bytes are swapped over (little-endian layout)&amp;lt;br/&amp;gt;bit 0-3: eyebrow rotation&amp;lt;br/&amp;gt;bit 5-8: eyebrow x spacing&amp;lt;br/&amp;gt;bit 9-13: eyebrow y position&lt;br /&gt;
|-&lt;br /&gt;
| 0x3C&lt;br /&gt;
| 0x4&lt;br /&gt;
| unknown&lt;br /&gt;
|-&lt;br /&gt;
| 0x40&lt;br /&gt;
| 0x1&lt;br /&gt;
| Allow Copying (?) (0D on 0E off 8D on)&lt;br /&gt;
|-&lt;br /&gt;
| 0x41&lt;br /&gt;
| 0x7&lt;br /&gt;
| unknown&lt;br /&gt;
|-&lt;br /&gt;
| 0x48&lt;br /&gt;
| 0x14&lt;br /&gt;
| UTF-16 Author Name (10 chars max, 0000 terminated)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Mii ID==&lt;br /&gt;
* Byte 0: generally equals 3 (category?)&lt;br /&gt;
* Byte 1: 0/1 = copying off/on&lt;br /&gt;
* Byte 2, most significant hex digit: position on page (0-9)&lt;br /&gt;
* Byte 2, least significant hex digit: page (0-9)&lt;br /&gt;
* Byte 3: generally 0x30 (always for user-created ones?)&lt;br /&gt;
&lt;br /&gt;
===Mii categories (pants colors)===&lt;br /&gt;
&lt;br /&gt;
====Special (gold) Miis====&lt;br /&gt;
Specialness will override any other color and make the Mii non-editable.&lt;br /&gt;
&lt;br /&gt;
Copying is rumored to have to be disabled.&lt;br /&gt;
&lt;br /&gt;
Zeroed system-id and timestamp?&lt;br /&gt;
&lt;br /&gt;
====Imported (blue) Miis====&lt;br /&gt;
Any (non-gold) Mii with a different System ID will appear as a foreign one.&lt;br /&gt;
&lt;br /&gt;
There is also a range of Mii IDs that are always foreign and uneditable, regardless of the System ID:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====Regular (black/red) Miis====&lt;br /&gt;
Always editable, since they can only appear as such on the console that created them.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====Personal (red) Mii====&lt;br /&gt;
A red Mii that happens to be the first in the file!&lt;br /&gt;
&lt;br /&gt;
==Mii values==&lt;br /&gt;
Each of the following values were found with NTR Debugger:&lt;br /&gt;
If you want to access the value, grab the given &amp;quot;NTR address&amp;quot; and add 0x08815000.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Data&lt;br /&gt;
! NTR address&lt;br /&gt;
! Variation (hex)&lt;br /&gt;
! Notes&lt;br /&gt;
|-&lt;br /&gt;
| Face style&lt;br /&gt;
| 0x894&lt;br /&gt;
| 00-0B&lt;br /&gt;
| Not ordered as in editor, read below&lt;br /&gt;
|-&lt;br /&gt;
| Face color&lt;br /&gt;
| 0x898&lt;br /&gt;
| 00-05&lt;br /&gt;
| From top to bottom&lt;br /&gt;
|-&lt;br /&gt;
| Wrinkles&lt;br /&gt;
| 0x89C&lt;br /&gt;
| 00-0B&lt;br /&gt;
| Same order as displayed in editor&lt;br /&gt;
|-&lt;br /&gt;
| Makeup&lt;br /&gt;
| 0x8A0&lt;br /&gt;
| 00-0B&lt;br /&gt;
| Same order as displayed in editor&lt;br /&gt;
|-&lt;br /&gt;
| Hair style&lt;br /&gt;
| 0x8A4&lt;br /&gt;
| 00-84&lt;br /&gt;
| Not ordered as in editor, read below&lt;br /&gt;
|-&lt;br /&gt;
| Hair color&lt;br /&gt;
| 0x8A8&lt;br /&gt;
| 00-07&lt;br /&gt;
| From top to bottom&lt;br /&gt;
|-&lt;br /&gt;
| Hair flipped&lt;br /&gt;
| 0x8AC&lt;br /&gt;
| 1 if true&lt;br /&gt;
| From top to bottom&lt;br /&gt;
|-&lt;br /&gt;
| Eye style&lt;br /&gt;
| 0x8B0&lt;br /&gt;
| 00-3C&lt;br /&gt;
| Not ordered as in editor, read below&lt;br /&gt;
|-&lt;br /&gt;
| Eyes color&lt;br /&gt;
| 0x8B4&lt;br /&gt;
| 00-05&lt;br /&gt;
| From top to bottom&lt;br /&gt;
|-&lt;br /&gt;
| Eyes size&lt;br /&gt;
| 0x8B8&lt;br /&gt;
| 07-00&lt;br /&gt;
| Left button increases value.&lt;br /&gt;
|-&lt;br /&gt;
| Eyes thickness&lt;br /&gt;
| 0x8BC&lt;br /&gt;
| 06-00&lt;br /&gt;
| Left button increases value.&lt;br /&gt;
|-&lt;br /&gt;
| Eyes rotation&lt;br /&gt;
| 0x8C0&lt;br /&gt;
| 00-07&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| Eyes spacing&lt;br /&gt;
| 0x8C4&lt;br /&gt;
| 00-0C&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| Eyes height&lt;br /&gt;
| 0x8C8&lt;br /&gt;
| 00-12&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| Eyebrows style&lt;br /&gt;
| 0x8CC&lt;br /&gt;
| 00-18&lt;br /&gt;
| Not ordered as in editor, read below&lt;br /&gt;
|-&lt;br /&gt;
| Eyebrows color&lt;br /&gt;
| 0x8D0&lt;br /&gt;
| 00-07&lt;br /&gt;
| From top to bottom&lt;br /&gt;
|-&lt;br /&gt;
| Eyebrows size&lt;br /&gt;
| 0x8D4&lt;br /&gt;
| 08-00&lt;br /&gt;
| Left button increases value.&lt;br /&gt;
|-&lt;br /&gt;
| Eyebrows thickness&lt;br /&gt;
| 0x8D8&lt;br /&gt;
| 06-00&lt;br /&gt;
| Left button increases value.&lt;br /&gt;
|-&lt;br /&gt;
| Eyebrows rotation&lt;br /&gt;
| 0x8DC&lt;br /&gt;
| 00-0B&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| Eyebrows spacing&lt;br /&gt;
| 0x8E0&lt;br /&gt;
| 00-0C&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| Eyebrows height&lt;br /&gt;
| 0x8E4&lt;br /&gt;
| 03-12&lt;br /&gt;
| Yup, minimum is 0x03&lt;br /&gt;
|-&lt;br /&gt;
| Nose style&lt;br /&gt;
| 0x8E8&lt;br /&gt;
| 00-11&lt;br /&gt;
| Not ordered as in editor, read below&lt;br /&gt;
|-&lt;br /&gt;
| Nose size&lt;br /&gt;
| 0x8EC&lt;br /&gt;
| 08-00&lt;br /&gt;
| Left button increases value.&lt;br /&gt;
|-&lt;br /&gt;
| Nose height&lt;br /&gt;
| 0x8F0&lt;br /&gt;
| 00-12&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| Mouth style&lt;br /&gt;
| 0x8F4&lt;br /&gt;
| 00-23&lt;br /&gt;
| Not ordered as in editor, read below&lt;br /&gt;
|-&lt;br /&gt;
| Mouth color&lt;br /&gt;
| 0x8F8&lt;br /&gt;
| 00-04&lt;br /&gt;
| From top to bottom.&lt;br /&gt;
|-&lt;br /&gt;
| Mouth size&lt;br /&gt;
| 0x8FC&lt;br /&gt;
| 08-00&lt;br /&gt;
| Left button increases value.&lt;br /&gt;
|-&lt;br /&gt;
| Mouth thickness&lt;br /&gt;
| 0x900&lt;br /&gt;
| 06-00&lt;br /&gt;
| Left button increases value.&lt;br /&gt;
|-&lt;br /&gt;
| Mouth height&lt;br /&gt;
| 0x904&lt;br /&gt;
| 00-12&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| Mustache style&lt;br /&gt;
| 0x908&lt;br /&gt;
| 00-05&lt;br /&gt;
| Order like in editor.&lt;br /&gt;
|-&lt;br /&gt;
| Beard style&lt;br /&gt;
| 0x90C&lt;br /&gt;
| 00-05&lt;br /&gt;
| Order like in editor.&lt;br /&gt;
|-&lt;br /&gt;
| Mustache/Beard color&lt;br /&gt;
| 0x910&lt;br /&gt;
| 00-07&lt;br /&gt;
| From top to button.&lt;br /&gt;
|-&lt;br /&gt;
| Mustache size&lt;br /&gt;
| 0x914&lt;br /&gt;
| 08-00&lt;br /&gt;
| Left button increases value.&lt;br /&gt;
|-&lt;br /&gt;
| Mustache height&lt;br /&gt;
| 0x918&lt;br /&gt;
| 00-10&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| Glasses style&lt;br /&gt;
| 0x91C&lt;br /&gt;
| 00-08&lt;br /&gt;
| Order like in editor.&lt;br /&gt;
|-&lt;br /&gt;
| Glasses color&lt;br /&gt;
| 0x920&lt;br /&gt;
| 00-05&lt;br /&gt;
| From top to bottom&lt;br /&gt;
|-&lt;br /&gt;
| Glasses size&lt;br /&gt;
| 0x924&lt;br /&gt;
| 07-00&lt;br /&gt;
| Left button increases value.&lt;br /&gt;
|-&lt;br /&gt;
| Glasses height&lt;br /&gt;
| 0x928&lt;br /&gt;
| 00-14&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| Mole enable&lt;br /&gt;
| 0x92C&lt;br /&gt;
| 1 if enabled, 0 else.&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| Mole size&lt;br /&gt;
| 0x930&lt;br /&gt;
| 08-00&lt;br /&gt;
| Left button increases value.&lt;br /&gt;
|-&lt;br /&gt;
| Mole horiz pos&lt;br /&gt;
| 0x934&lt;br /&gt;
| 00-10&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| Mole vert pos&lt;br /&gt;
| 0x938&lt;br /&gt;
| 00-1E&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| Mii height&lt;br /&gt;
| 0x93C&lt;br /&gt;
| 00-7F&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| Mii weight&lt;br /&gt;
| 0x940&lt;br /&gt;
| 00-7F&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| Mii name&lt;br /&gt;
| 0x944-0x959&lt;br /&gt;
| UTF-16&lt;br /&gt;
| Terminated with 0x0000. Not updated immediatly?&lt;br /&gt;
|-&lt;br /&gt;
| Creator&#039;s name&lt;br /&gt;
| 0x95A-96F&lt;br /&gt;
| UTF-16&lt;br /&gt;
| Terminated with 0x0000. Not updated immediatly?&lt;br /&gt;
|-&lt;br /&gt;
| Mii gender&lt;br /&gt;
| 0x970&lt;br /&gt;
| 0: Male, 1: Female&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| Birthdate month&lt;br /&gt;
| 0x974&lt;br /&gt;
| 01-0C&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| Birthdate day&lt;br /&gt;
| 0x978&lt;br /&gt;
| 01-1F&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| Mii shirt color&lt;br /&gt;
| 0x97C&lt;br /&gt;
| 00-0B&lt;br /&gt;
| Ordered like in editor.&lt;br /&gt;
|-&lt;br /&gt;
| Favorite&lt;br /&gt;
| 0x980&lt;br /&gt;
| 0: false, 1: true&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| Allow copy&lt;br /&gt;
| 0x981&lt;br /&gt;
| 0: false, 1: true&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| Unused byte?&lt;br /&gt;
| 0x982&lt;br /&gt;
| &lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| Allow sharing&lt;br /&gt;
| 0x983&lt;br /&gt;
| 0: true, 1: false&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
| ???&lt;br /&gt;
| 0x984-0x98F&lt;br /&gt;
| All zero?&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
| ???&lt;br /&gt;
| 0x990-0x997&lt;br /&gt;
| 4?&lt;br /&gt;
|&lt;br /&gt;
|}&lt;br /&gt;
0x08815998: Same 4 bytes as encrypted Mii: first 4 bits for Mii type, 4 next for number of seconds since 01/01/2010 00:00:00 UTC+3 (should be verified by other country and region 3DS) divided by 2.&lt;br /&gt;
0x0881599C: 6 bytes of MAC address of the 3DS that created the Mii.&lt;br /&gt;
0x088159A2: 6 unknow uses bytes&lt;br /&gt;
0x088159A8: Same 8 bytes as decrypted Mii at 0x04 through 0x0B. Seems NAND specific, kept the same on Miis created on same NAND but different 3DS via System Transfer. Might be a coincidence but the two first bytes are in ID0 folder name in the Nintendo 3DS folder.&lt;br /&gt;
&lt;br /&gt;
===Mapped Editor &amp;lt;-&amp;gt; Hex values===&lt;br /&gt;
&lt;br /&gt;
Most of the values are ordered (left button decreases, right increases, color choices are top to bottom...) but for most &amp;quot;main&amp;quot; part of the UI, where you choose the style of the part being edited, hex values has no correlation with displayed order.&lt;br /&gt;
Here is a JSON that can go from a Part, a Page and Position to the right hex value. This is 0 indexed (eg: datas[&amp;quot;face&amp;quot;][0][11]).&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;{&lt;br /&gt;
face: [&lt;br /&gt;
    0x00,0x01,0x08,&lt;br /&gt;
    0x02,0x03,0x09,&lt;br /&gt;
    0x04,0x05,0x0a,&lt;br /&gt;
    0x06,0x07,0x0b&lt;br /&gt;
],&lt;br /&gt;
hairs: [&lt;br /&gt;
    [0x21,0x2f,0x28,&lt;br /&gt;
    0x25,0x20,0x6b,&lt;br /&gt;
    0x30,0x33,0x37,&lt;br /&gt;
    0x46,0x2c,0x42],&lt;br /&gt;
    [0x34,0x32,0x26,&lt;br /&gt;
    0x31,0x2b,0x1f,&lt;br /&gt;
    0x38,0x44,0x3e,&lt;br /&gt;
    0x73,0x4c,0x77],&lt;br /&gt;
    [0x40,0x51,0x74,&lt;br /&gt;
    0x79,0x16,0x3a,&lt;br /&gt;
    0x3c,0x57,0x7d,&lt;br /&gt;
    0x75,0x49,0x4b],&lt;br /&gt;
    [0x2a,0x59,0x39,&lt;br /&gt;
    0x36,0x50,0x22,&lt;br /&gt;
    0x17,0x56,0x58,&lt;br /&gt;
    0x76,0x27,0x24],&lt;br /&gt;
    [0x2d,0x43,0x3b,&lt;br /&gt;
    0x41,0x29,0x1e,&lt;br /&gt;
    0x0c,0x10,0x0a,&lt;br /&gt;
    0x52,0x80,0x81],&lt;br /&gt;
    [0x0e,0x5f,0x69,&lt;br /&gt;
    0x64,0x06,0x14,&lt;br /&gt;
    0x5d,0x66,0x1b,&lt;br /&gt;
    0x04,0x11,0x6e]&lt;br /&gt;
    [0x7b,0x08,0x6a,&lt;br /&gt;
    0x48,0x03,0x15,&lt;br /&gt;
    0x00,0x62,0x3f,&lt;br /&gt;
    0x5a,0x0b,0x78],&lt;br /&gt;
    [0x05,0x4a,0x6c,&lt;br /&gt;
    0x5e,0x7c,0x19,&lt;br /&gt;
    0x63,0x45,0x23,&lt;br /&gt;
    0x0d,0x7a,0x71],&lt;br /&gt;
    [0x35,0x18,0x55,&lt;br /&gt;
    0x53,0x47,0x83,&lt;br /&gt;
    0x60,0x65,0x1d,&lt;br /&gt;
    0x07,0x0f,0x70],&lt;br /&gt;
    [0x4f,0x01,0x6d,&lt;br /&gt;
    0x7f,0x5b,0x1a,&lt;br /&gt;
    0x3d,0x67,0x02,&lt;br /&gt;
    0x4d,0x12,0x5c],&lt;br /&gt;
    [0x54,0x09,0x13,&lt;br /&gt;
    0x82,0x61,0x68,&lt;br /&gt;
    0x2e,0x4e,0x1c,&lt;br /&gt;
    0x72,0x7e,0x6f]&lt;br /&gt;
],&lt;br /&gt;
eyebrows: [&lt;br /&gt;
    [0x06,0x00,0x0c,&lt;br /&gt;
    0x01,0x09,0x13,&lt;br /&gt;
    0x07,0x15,0x08,&lt;br /&gt;
    0x11,0x05,0x04],&lt;br /&gt;
    [0x0b,0x0a,0x02,&lt;br /&gt;
    0x03,0x0e,0x14,&lt;br /&gt;
    0x0f,0x0d,0x16,&lt;br /&gt;
    0x12,0x10,0x17]&lt;br /&gt;
],&lt;br /&gt;
nose: [&lt;br /&gt;
    [0x01,0x0a,0x02,&lt;br /&gt;
    0x03,0x06,0x00,&lt;br /&gt;
    0x05,0x04,0x08,&lt;br /&gt;
    0x09,0x07,0x0B],&lt;br /&gt;
    [0x0d,0x0e,0x0c,&lt;br /&gt;
    0x11,0x10,0x0f]&lt;br /&gt;
],&lt;br /&gt;
mouth: [&lt;br /&gt;
    [0x17,0x01,0x13,&lt;br /&gt;
    0x15,0x16,0x05,&lt;br /&gt;
    0x00,0x08,0x0a,&lt;br /&gt;
    0x10,0x06,0x0d],&lt;br /&gt;
    [0x07,0x09,0x02,&lt;br /&gt;
    0x11,0x03,0x04,&lt;br /&gt;
    0x0f,0x0b,0x14,&lt;br /&gt;
    0x12,0x0e,0x0c],&lt;br /&gt;
    [0x1b,0x1e,0x18,&lt;br /&gt;
    0x19,0x1d,0x1c,&lt;br /&gt;
    0x1a,0x23,0x1f,&lt;br /&gt;
    0x22,0x21,0x20]&lt;br /&gt;
]&lt;br /&gt;
}&amp;lt;/nowiki&amp;gt;&lt;/div&gt;</summary>
		<author><name>Wwylele</name></author>
	</entry>
	<entry>
		<id>https://www.3dbrew.org/w/index.php?title=Mii&amp;diff=20890</id>
		<title>Mii</title>
		<link rel="alternate" type="text/html" href="https://www.3dbrew.org/w/index.php?title=Mii&amp;diff=20890"/>
		<updated>2019-02-19T15:40:10Z</updated>

		<summary type="html">&lt;p&gt;Wwylele: /* Mii Database */ Fix obvious offset/size typo&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Originally [http://wiibrew.org/wiki/Mii_Data created for the Nintendo Wii] (and backported to a selection of DS/i games), the &#039;&#039;&#039;Mii&#039;&#039;&#039; format was expanded with a larger selection of facial features and a new &amp;quot;copying&amp;quot; permission for the 3DS family, and later implemented as-is on Wii U.&lt;br /&gt;
&lt;br /&gt;
See [[Mii Maker]] for the application chiefly designed to create, edit, delete, and trade Miis or convert them from and to a QR code.&lt;br /&gt;
&lt;br /&gt;
==Mii Database==&lt;br /&gt;
Format of the Mii main database &#039;&#039;&#039;CFL_DB.dat&#039;&#039;&#039;, found in [[Extdata#NAND_Shared_Extdata|shared extdata]] archive f0000000b.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset&lt;br /&gt;
! Length&lt;br /&gt;
! &lt;br /&gt;
|-&lt;br /&gt;
| 0x0&lt;br /&gt;
| 0x4&lt;br /&gt;
| Header &amp;quot;CFOG&amp;quot; (Mii Maker section)&lt;br /&gt;
|-&lt;br /&gt;
| 0x4&lt;br /&gt;
| 0x4&lt;br /&gt;
| Header 0x00010000&lt;br /&gt;
|-&lt;br /&gt;
| 0x8&lt;br /&gt;
| 0x23F0 (100 * 0x5C)&lt;br /&gt;
| Array of owned (saved in Mii Maker) Miis. Order in file is unrelated to canonical order in-app.&lt;br /&gt;
|-&lt;br /&gt;
| 0x23F8&lt;br /&gt;
| 0x4&lt;br /&gt;
| Header &amp;quot;CFHE&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| 0x23FC&lt;br /&gt;
| 0x4&lt;br /&gt;
| Header 0xFFFFFFFF&lt;br /&gt;
|-&lt;br /&gt;
| 0x2400&lt;br /&gt;
| 0xA41E&lt;br /&gt;
| Array of objects? See chapter&lt;br /&gt;
|-&lt;br /&gt;
| 0xC81E&lt;br /&gt;
| 0x2&lt;br /&gt;
| Checksum of all of the above (the first 0xC81E byte). See section [[#Checksum|below]].&lt;br /&gt;
|-&lt;br /&gt;
| 0xC820&lt;br /&gt;
| 0x4&lt;br /&gt;
| Header &amp;quot;CFRA&amp;quot; (Invitations section)&lt;br /&gt;
|-&lt;br /&gt;
| 0xC824&lt;br /&gt;
| 0x4&lt;br /&gt;
| Header? 0x39000000&lt;br /&gt;
|-&lt;br /&gt;
| 0xC861&lt;br /&gt;
| 0x2B&lt;br /&gt;
| Weird padding? 0x00&lt;br /&gt;
|-&lt;br /&gt;
| 0xC88C&lt;br /&gt;
| 0x1C20 (?)&lt;br /&gt;
| Array of Miis contributed from games, used for Mii Plaza &amp;quot;invitations&amp;quot; feature.&amp;lt;br/&amp;gt;The format isn&#039;t that of a full Mii.&lt;br /&gt;
|-&lt;br /&gt;
| 0xE4AC&lt;br /&gt;
| 0x14&lt;br /&gt;
| 01 00 [..] 00 D2 74&lt;br /&gt;
|-&lt;br /&gt;
| 0xE4C0&lt;br /&gt;
| 0x3D860&lt;br /&gt;
| Empty (00)&lt;br /&gt;
|}&lt;br /&gt;
When encrypted in QR codes, 4 additional bytes are added. Two null bytes and a CRC-16. It&#039;s the exact same CRC-16 as for the Wii blocks on the 0x5e first bytes. It seems that the CRC is ignored, the Mii Maker expecting the result of APT:Unwrap to detect integrity loss.&lt;br /&gt;
&lt;br /&gt;
==CFHE object==&lt;br /&gt;
&lt;br /&gt;
A 0xE-byte long item.&lt;br /&gt;
&lt;br /&gt;
On my database, they&#039;re all 0000 0000 0000 0000 0000 FF7F FF7F.&lt;br /&gt;
&lt;br /&gt;
Wild speculation: blacklist of already scanned celebrity (gold) Mii QRs?&lt;br /&gt;
&lt;br /&gt;
Alternative interpretation: FFFF FFFF 0000 0000 0000 0000 0000 is the 1st item;  FF7F FF7F 0000 [...] the 2nd, etc;&lt;br /&gt;
&lt;br /&gt;
==Checksum==&lt;br /&gt;
&lt;br /&gt;
The algorithm used to verify the integrity of the database is based on [http://srecord.sourceforge.net/crc16-ccitt.html CRC16-CCITT], though it&#039;s an incorrect implementation. It is the same algorithm used to verify [http://wiibrew.org/wiki/Mii_Data#Block_format Mii Data on the Wii].&lt;br /&gt;
&lt;br /&gt;
To obtain the correct value for the checksum, apply the algorithm to the first 0xC81E bytes of the database. This can be done using [https://gbatemp.net/threads/tutorial-give-your-mii-gold-pants-and-use-it-for-streetpass.379146/page-24#post-6569186 FixCRC]; alternativly a pseudocode implementation of the checksum algorithm is given below:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
def crc16_CCITTWii(u8[]: data) -&amp;gt; u16:&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Calculate a checksum of data using the CRC16-CCITT implementation of the Wii&lt;br /&gt;
&lt;br /&gt;
    This implementation uses 0x0000 as the starting value, which is different&lt;br /&gt;
    from what CRC16-CCITT specifies.&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    # note: a correct implementation of CRC16-CCITT&lt;br /&gt;
    #       would initialize this to 0xffff&lt;br /&gt;
    u32 crc := 0x0&lt;br /&gt;
&lt;br /&gt;
    for byte in data:&lt;br /&gt;
        # Iterate over every of the 8 bits in byte.&lt;br /&gt;
        # Begin with the most significant bit. (7, 6, ... , 1, 0)&lt;br /&gt;
        for bit in 7..0:&lt;br /&gt;
            # &amp;amp; - binary `and&#039;; &amp;lt;&amp;lt;/&amp;gt;&amp;gt; - bitshift left/right; ^ - binary `xor&#039;&lt;br /&gt;
            crc := (&lt;br /&gt;
                     (crc &amp;lt;&amp;lt; 1) | ((byte &amp;gt;&amp;gt; bit) &amp;amp; 0x1)&lt;br /&gt;
                     ^ (0x1021 if crc &amp;amp; 0x8000 else 0)&lt;br /&gt;
                   )&lt;br /&gt;
&lt;br /&gt;
    for _ in 0..15:&lt;br /&gt;
        crc := (crc &amp;lt;&amp;lt; 1) ^ (0x1021 if crc &amp;amp; 0x8000 else 0)&lt;br /&gt;
&lt;br /&gt;
    # only return the lowest 16 bit of crc&lt;br /&gt;
    return (u16) (crc &amp;amp; 0xffff)&lt;br /&gt;
&lt;br /&gt;
checksum := crc16_CCITTWii(miidb[0:0xc81e]) # checksum over the first 0xc81e bytes&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Mii format==&lt;br /&gt;
&lt;br /&gt;
Note: 0x18-3B have been copied as-is from [[Mii_Maker#Mii_QR_Code_format|the QR code specification]], so they&#039;re unverified.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Offset&lt;br /&gt;
! Length&lt;br /&gt;
! &lt;br /&gt;
|-&lt;br /&gt;
| 0x0&lt;br /&gt;
| 0x4&lt;br /&gt;
| Mii ID (see chapter)&lt;br /&gt;
|-&lt;br /&gt;
| 0x4&lt;br /&gt;
| 0x8&lt;br /&gt;
| System ID (identifies owner, for purpose of enforcing editing restrictions and blue pants).&amp;lt;br/&amp;gt;Is not tied to the MAC address anymore.&lt;br /&gt;
|-&lt;br /&gt;
| 0xC&lt;br /&gt;
| 0x4&lt;br /&gt;
| Specialness and date of creation (big-endian 32bit unsigned integer):&amp;lt;br/&amp;gt;Bit 0..27: (bit[0..27] * 2) = date of creation (seconds since 01/01/2010 00:00:00)&amp;lt;br/&amp;gt;Bit 31: not set iff Mii is special&lt;br /&gt;
|-&lt;br /&gt;
| 0x10&lt;br /&gt;
| 0x6&lt;br /&gt;
| Creator&#039;s full MAC&lt;br /&gt;
|-&lt;br /&gt;
| 0x16&lt;br /&gt;
| 0x2&lt;br /&gt;
| Padding (0000)&lt;br /&gt;
|-&lt;br /&gt;
| 0x18&lt;br /&gt;
| 0x2&lt;br /&gt;
| Bit-mapped: Birthday (4bit-day,5bit-month), Sex, Shirt color, Favorite (0x40 bit at 0x19)&lt;br /&gt;
|-&lt;br /&gt;
| 0x1A&lt;br /&gt;
| 0x14&lt;br /&gt;
| UTF-16 Mii Name (10 chars max, 0000 terminated)&lt;br /&gt;
|-&lt;br /&gt;
| 0x2E&lt;br /&gt;
| 0x2&lt;br /&gt;
| width &amp;amp; height&lt;br /&gt;
|-&lt;br /&gt;
| 0x30&lt;br /&gt;
| 0x1&lt;br /&gt;
| bit 0: disable sharing&amp;lt;br/&amp;gt;bit 1-4: face shape&amp;lt;br/&amp;gt;bit 5-7: skin color&lt;br /&gt;
|-&lt;br /&gt;
| 0x31&lt;br /&gt;
| 0x1&lt;br /&gt;
| bit 0-3: wrinkles&amp;lt;br/&amp;gt;bit 4-7: makeup&lt;br /&gt;
|-&lt;br /&gt;
| 0x32&lt;br /&gt;
| 0x1&lt;br /&gt;
| hair style&lt;br /&gt;
|-&lt;br /&gt;
| 0x33&lt;br /&gt;
| 0x1&lt;br /&gt;
| bit 0-2: hair color&amp;lt;br/&amp;gt;bit 3: flip hair&lt;br /&gt;
|-&lt;br /&gt;
| 0x34&lt;br /&gt;
| 0x4&lt;br /&gt;
| unknown&lt;br /&gt;
|-&lt;br /&gt;
| 0x38&lt;br /&gt;
| 0x1&lt;br /&gt;
| bit 0-4: eyebrow style&amp;lt;br/&amp;gt;bit 5-7: eyebrow color&lt;br /&gt;
|-&lt;br /&gt;
| 0x39&lt;br /&gt;
| 0x1&lt;br /&gt;
| bit 0-3: eyebrow scale&amp;lt;br/&amp;gt;bit 4-6: eyebrow yscale&lt;br /&gt;
|-&lt;br /&gt;
| 0x3A&lt;br /&gt;
| 0x2&lt;br /&gt;
| note that the bytes are swapped over (little-endian layout)&amp;lt;br/&amp;gt;bit 0-3: eyebrow rotation&amp;lt;br/&amp;gt;bit 5-8: eyebrow x spacing&amp;lt;br/&amp;gt;bit 9-13: eyebrow y position&lt;br /&gt;
|-&lt;br /&gt;
| 0x3C&lt;br /&gt;
| 0x4&lt;br /&gt;
| unknown&lt;br /&gt;
|-&lt;br /&gt;
| 0x40&lt;br /&gt;
| 0x1&lt;br /&gt;
| Allow Copying (?) (0D on 0E off 8D on)&lt;br /&gt;
|-&lt;br /&gt;
| 0x41&lt;br /&gt;
| 0x7&lt;br /&gt;
| unknown&lt;br /&gt;
|-&lt;br /&gt;
| 0x48&lt;br /&gt;
| 0x14&lt;br /&gt;
| UTF-16 Author Name (10 chars max, 0000 terminated)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Mii ID==&lt;br /&gt;
* Byte 0: generally equals 3 (category?)&lt;br /&gt;
* Byte 1: 0/1 = copying off/on&lt;br /&gt;
* Byte 2, most significant hex digit: position on page (0-9)&lt;br /&gt;
* Byte 2, least significant hex digit: page (0-9)&lt;br /&gt;
* Byte 3: generally 0x30 (always for user-created ones?)&lt;br /&gt;
&lt;br /&gt;
===Mii categories (pants colors)===&lt;br /&gt;
&lt;br /&gt;
====Special (gold) Miis====&lt;br /&gt;
Specialness will override any other color and make the Mii non-editable.&lt;br /&gt;
&lt;br /&gt;
Copying is rumored to have to be disabled.&lt;br /&gt;
&lt;br /&gt;
Zeroed system-id and timestamp?&lt;br /&gt;
&lt;br /&gt;
====Imported (blue) Miis====&lt;br /&gt;
Any (non-gold) Mii with a different System ID will appear as a foreign one.&lt;br /&gt;
&lt;br /&gt;
There is also a range of Mii IDs that are always foreign and uneditable, regardless of the System ID:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====Regular (black/red) Miis====&lt;br /&gt;
Always editable, since they can only appear as such on the console that created them.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====Personal (red) Mii====&lt;br /&gt;
A red Mii that happens to be the first in the file!&lt;br /&gt;
&lt;br /&gt;
==Mii values==&lt;br /&gt;
Each of the following values were found with NTR Debugger:&lt;br /&gt;
If you want to access the value, grab the given &amp;quot;NTR address&amp;quot; and add 0x08815000.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Data&lt;br /&gt;
! NTR address&lt;br /&gt;
! Variation (hex)&lt;br /&gt;
! Notes&lt;br /&gt;
|-&lt;br /&gt;
| Face style&lt;br /&gt;
| 0x894&lt;br /&gt;
| 00-0B&lt;br /&gt;
| Not ordered as in editor, read below&lt;br /&gt;
|-&lt;br /&gt;
| Face color&lt;br /&gt;
| 0x898&lt;br /&gt;
| 00-05&lt;br /&gt;
| From top to bottom&lt;br /&gt;
|-&lt;br /&gt;
| Wrinkles&lt;br /&gt;
| 0x89C&lt;br /&gt;
| 00-0B&lt;br /&gt;
| Same order as displayed in editor&lt;br /&gt;
|-&lt;br /&gt;
| Makeup&lt;br /&gt;
| 0x8A0&lt;br /&gt;
| 00-0B&lt;br /&gt;
| Same order as displayed in editor&lt;br /&gt;
|-&lt;br /&gt;
| Hair style&lt;br /&gt;
| 0x8A4&lt;br /&gt;
| 00-84&lt;br /&gt;
| Not ordered as in editor, read below&lt;br /&gt;
|-&lt;br /&gt;
| Hair color&lt;br /&gt;
| 0x8A8&lt;br /&gt;
| 00-07&lt;br /&gt;
| From top to bottom&lt;br /&gt;
|-&lt;br /&gt;
| Hair flipped&lt;br /&gt;
| 0x8AC&lt;br /&gt;
| 1 if true&lt;br /&gt;
| From top to bottom&lt;br /&gt;
|-&lt;br /&gt;
| Eye style&lt;br /&gt;
| 0x8B0&lt;br /&gt;
| 00-3C&lt;br /&gt;
| Not ordered as in editor, read below&lt;br /&gt;
|-&lt;br /&gt;
| Eyes color&lt;br /&gt;
| 0x8B4&lt;br /&gt;
| 00-05&lt;br /&gt;
| From top to bottom&lt;br /&gt;
|-&lt;br /&gt;
| Eyes size&lt;br /&gt;
| 0x8B8&lt;br /&gt;
| 07-00&lt;br /&gt;
| Left button increases value.&lt;br /&gt;
|-&lt;br /&gt;
| Eyes thickness&lt;br /&gt;
| 0x8BC&lt;br /&gt;
| 06-00&lt;br /&gt;
| Left button increases value.&lt;br /&gt;
|-&lt;br /&gt;
| Eyes rotation&lt;br /&gt;
| 0x8C0&lt;br /&gt;
| 00-07&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| Eyes spacing&lt;br /&gt;
| 0x8C4&lt;br /&gt;
| 00-0C&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| Eyes height&lt;br /&gt;
| 0x8C8&lt;br /&gt;
| 00-12&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| Eyebrows style&lt;br /&gt;
| 0x8CC&lt;br /&gt;
| 00-18&lt;br /&gt;
| Not ordered as in editor, read below&lt;br /&gt;
|-&lt;br /&gt;
| Eyebrows color&lt;br /&gt;
| 0x8D0&lt;br /&gt;
| 00-07&lt;br /&gt;
| From top to bottom&lt;br /&gt;
|-&lt;br /&gt;
| Eyebrows size&lt;br /&gt;
| 0x8D4&lt;br /&gt;
| 08-00&lt;br /&gt;
| Left button increases value.&lt;br /&gt;
|-&lt;br /&gt;
| Eyebrows thickness&lt;br /&gt;
| 0x8D8&lt;br /&gt;
| 06-00&lt;br /&gt;
| Left button increases value.&lt;br /&gt;
|-&lt;br /&gt;
| Eyebrows rotation&lt;br /&gt;
| 0x8DC&lt;br /&gt;
| 00-0B&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| Eyebrows spacing&lt;br /&gt;
| 0x8E0&lt;br /&gt;
| 00-0C&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| Eyebrows height&lt;br /&gt;
| 0x8E4&lt;br /&gt;
| 03-12&lt;br /&gt;
| Yup, minimum is 0x03&lt;br /&gt;
|-&lt;br /&gt;
| Nose style&lt;br /&gt;
| 0x8E8&lt;br /&gt;
| 00-11&lt;br /&gt;
| Not ordered as in editor, read below&lt;br /&gt;
|-&lt;br /&gt;
| Nose size&lt;br /&gt;
| 0x8EC&lt;br /&gt;
| 08-00&lt;br /&gt;
| Left button increases value.&lt;br /&gt;
|-&lt;br /&gt;
| Nose height&lt;br /&gt;
| 0x8F0&lt;br /&gt;
| 00-12&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| Mouth style&lt;br /&gt;
| 0x8F4&lt;br /&gt;
| 00-23&lt;br /&gt;
| Not ordered as in editor, read below&lt;br /&gt;
|-&lt;br /&gt;
| Mouth color&lt;br /&gt;
| 0x8F8&lt;br /&gt;
| 00-04&lt;br /&gt;
| From top to bottom.&lt;br /&gt;
|-&lt;br /&gt;
| Mouth size&lt;br /&gt;
| 0x8FC&lt;br /&gt;
| 08-00&lt;br /&gt;
| Left button increases value.&lt;br /&gt;
|-&lt;br /&gt;
| Mouth thickness&lt;br /&gt;
| 0x900&lt;br /&gt;
| 06-00&lt;br /&gt;
| Left button increases value.&lt;br /&gt;
|-&lt;br /&gt;
| Mouth height&lt;br /&gt;
| 0x904&lt;br /&gt;
| 00-12&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| Mustache style&lt;br /&gt;
| 0x908&lt;br /&gt;
| 00-05&lt;br /&gt;
| Order like in editor.&lt;br /&gt;
|-&lt;br /&gt;
| Beard style&lt;br /&gt;
| 0x90C&lt;br /&gt;
| 00-05&lt;br /&gt;
| Order like in editor.&lt;br /&gt;
|-&lt;br /&gt;
| Mustache/Beard color&lt;br /&gt;
| 0x910&lt;br /&gt;
| 00-07&lt;br /&gt;
| From top to button.&lt;br /&gt;
|-&lt;br /&gt;
| Mustache size&lt;br /&gt;
| 0x914&lt;br /&gt;
| 08-00&lt;br /&gt;
| Left button increases value.&lt;br /&gt;
|-&lt;br /&gt;
| Mustache height&lt;br /&gt;
| 0x918&lt;br /&gt;
| 00-10&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| Glasses style&lt;br /&gt;
| 0x91C&lt;br /&gt;
| 00-08&lt;br /&gt;
| Order like in editor.&lt;br /&gt;
|-&lt;br /&gt;
| Glasses color&lt;br /&gt;
| 0x920&lt;br /&gt;
| 00-05&lt;br /&gt;
| From top to bottom&lt;br /&gt;
|-&lt;br /&gt;
| Glasses size&lt;br /&gt;
| 0x924&lt;br /&gt;
| 07-00&lt;br /&gt;
| Left button increases value.&lt;br /&gt;
|-&lt;br /&gt;
| Glasses height&lt;br /&gt;
| 0x928&lt;br /&gt;
| 00-14&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| Mole enable&lt;br /&gt;
| 0x92C&lt;br /&gt;
| 1 if enabled, 0 else.&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| Mole size&lt;br /&gt;
| 0x930&lt;br /&gt;
| 08-00&lt;br /&gt;
| Left button increases value.&lt;br /&gt;
|-&lt;br /&gt;
| Mole horiz pos&lt;br /&gt;
| 0x934&lt;br /&gt;
| 00-10&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| Mole vert pos&lt;br /&gt;
| 0x938&lt;br /&gt;
| 00-1E&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| Mii height&lt;br /&gt;
| 0x93C&lt;br /&gt;
| 00-7F&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| Mii weight&lt;br /&gt;
| 0x940&lt;br /&gt;
| 00-7F&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| Mii name&lt;br /&gt;
| 0x944-0x959&lt;br /&gt;
| UTF-16&lt;br /&gt;
| Terminated with 0x0000. Not updated immediatly?&lt;br /&gt;
|-&lt;br /&gt;
| Creator&#039;s name&lt;br /&gt;
| 0x95A-96F&lt;br /&gt;
| UTF-16&lt;br /&gt;
| Terminated with 0x0000. Not updated immediatly?&lt;br /&gt;
|-&lt;br /&gt;
| Mii gender&lt;br /&gt;
| 0x970&lt;br /&gt;
| 0: Male, 1: Female&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| Birthdate month&lt;br /&gt;
| 0x974&lt;br /&gt;
| 01-0C&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| Birthdate day&lt;br /&gt;
| 0x978&lt;br /&gt;
| 01-1F&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| Mii shirt color&lt;br /&gt;
| 0x97C&lt;br /&gt;
| 00-0B&lt;br /&gt;
| Ordered like in editor.&lt;br /&gt;
|-&lt;br /&gt;
| Favorite&lt;br /&gt;
| 0x980&lt;br /&gt;
| 0: false, 1: true&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| Allow copy&lt;br /&gt;
| 0x981&lt;br /&gt;
| 0: false, 1: true&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| Unused byte?&lt;br /&gt;
| 0x982&lt;br /&gt;
| &lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| Allow sharing&lt;br /&gt;
| 0x983&lt;br /&gt;
| 0: true, 1: false&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
| ???&lt;br /&gt;
| 0x984-0x98F&lt;br /&gt;
| All zero?&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
| ???&lt;br /&gt;
| 0x990-0x997&lt;br /&gt;
| 4?&lt;br /&gt;
|&lt;br /&gt;
|}&lt;br /&gt;
0x08815998: Same 4 bytes as encrypted Mii: first 4 bits for Mii type, 4 next for number of seconds since 01/01/2010 00:00:00 UTC+3 (should be verified by other country and region 3DS) divided by 2.&lt;br /&gt;
0x0881599C: 6 bytes of MAC address of the 3DS that created the Mii.&lt;br /&gt;
0x088159A2: 6 unknow uses bytes&lt;br /&gt;
0x088159A8: Same 8 bytes as decrypted Mii at 0x04 through 0x0B. Seems NAND specific, kept the same on Miis created on same NAND but different 3DS via System Transfer. Might be a coincidence but the two first bytes are in ID0 folder name in the Nintendo 3DS folder.&lt;br /&gt;
&lt;br /&gt;
===Mapped Editor &amp;lt;-&amp;gt; Hex values===&lt;br /&gt;
&lt;br /&gt;
Most of the values are ordered (left button decreases, right increases, color choices are top to bottom...) but for most &amp;quot;main&amp;quot; part of the UI, where you choose the style of the part being edited, hex values has no correlation with displayed order.&lt;br /&gt;
Here is a JSON that can go from a Part, a Page and Position to the right hex value. This is 0 indexed (eg: datas[&amp;quot;face&amp;quot;][0][11]).&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;{&lt;br /&gt;
face: [&lt;br /&gt;
    0x00,0x01,0x08,&lt;br /&gt;
    0x02,0x03,0x09,&lt;br /&gt;
    0x04,0x05,0x0a,&lt;br /&gt;
    0x06,0x07,0x0b&lt;br /&gt;
],&lt;br /&gt;
hairs: [&lt;br /&gt;
    [0x21,0x2f,0x28,&lt;br /&gt;
    0x25,0x20,0x6b,&lt;br /&gt;
    0x30,0x33,0x37,&lt;br /&gt;
    0x46,0x2c,0x42],&lt;br /&gt;
    [0x34,0x32,0x26,&lt;br /&gt;
    0x31,0x2b,0x1f,&lt;br /&gt;
    0x38,0x44,0x3e,&lt;br /&gt;
    0x73,0x4c,0x77],&lt;br /&gt;
    [0x40,0x51,0x74,&lt;br /&gt;
    0x79,0x16,0x3a,&lt;br /&gt;
    0x3c,0x57,0x7d,&lt;br /&gt;
    0x75,0x49,0x4b],&lt;br /&gt;
    [0x2a,0x59,0x39,&lt;br /&gt;
    0x36,0x50,0x22,&lt;br /&gt;
    0x17,0x56,0x58,&lt;br /&gt;
    0x76,0x27,0x24],&lt;br /&gt;
    [0x2d,0x43,0x3b,&lt;br /&gt;
    0x41,0x29,0x1e,&lt;br /&gt;
    0x0c,0x10,0x0a,&lt;br /&gt;
    0x52,0x80,0x81],&lt;br /&gt;
    [0x0e,0x5f,0x69,&lt;br /&gt;
    0x64,0x06,0x14,&lt;br /&gt;
    0x5d,0x66,0x1b,&lt;br /&gt;
    0x04,0x11,0x6e]&lt;br /&gt;
    [0x7b,0x08,0x6a,&lt;br /&gt;
    0x48,0x03,0x15,&lt;br /&gt;
    0x00,0x62,0x3f,&lt;br /&gt;
    0x5a,0x0b,0x78],&lt;br /&gt;
    [0x05,0x4a,0x6c,&lt;br /&gt;
    0x5e,0x7c,0x19,&lt;br /&gt;
    0x63,0x45,0x23,&lt;br /&gt;
    0x0d,0x7a,0x71],&lt;br /&gt;
    [0x35,0x18,0x55,&lt;br /&gt;
    0x53,0x47,0x83,&lt;br /&gt;
    0x60,0x65,0x1d,&lt;br /&gt;
    0x07,0x0f,0x70],&lt;br /&gt;
    [0x4f,0x01,0x6d,&lt;br /&gt;
    0x7f,0x5b,0x1a,&lt;br /&gt;
    0x3d,0x67,0x02,&lt;br /&gt;
    0x4d,0x12,0x5c],&lt;br /&gt;
    [0x54,0x09,0x13,&lt;br /&gt;
    0x82,0x61,0x68,&lt;br /&gt;
    0x2e,0x4e,0x1c,&lt;br /&gt;
    0x72,0x7e,0x6f]&lt;br /&gt;
],&lt;br /&gt;
eyebrows: [&lt;br /&gt;
    [0x06,0x00,0x0c,&lt;br /&gt;
    0x01,0x09,0x13,&lt;br /&gt;
    0x07,0x15,0x08,&lt;br /&gt;
    0x11,0x05,0x04],&lt;br /&gt;
    [0x0b,0x0a,0x02,&lt;br /&gt;
    0x03,0x0e,0x14,&lt;br /&gt;
    0x0f,0x0d,0x16,&lt;br /&gt;
    0x12,0x10,0x17]&lt;br /&gt;
],&lt;br /&gt;
nose: [&lt;br /&gt;
    [0x01,0x0a,0x02,&lt;br /&gt;
    0x03,0x06,0x00,&lt;br /&gt;
    0x05,0x04,0x08,&lt;br /&gt;
    0x09,0x07,0x0B],&lt;br /&gt;
    [0x0d,0x0e,0x0c,&lt;br /&gt;
    0x11,0x10,0x0f]&lt;br /&gt;
],&lt;br /&gt;
mouth: [&lt;br /&gt;
    [0x17,0x01,0x13,&lt;br /&gt;
    0x15,0x16,0x05,&lt;br /&gt;
    0x00,0x08,0x0a,&lt;br /&gt;
    0x10,0x06,0x0d],&lt;br /&gt;
    [0x07,0x09,0x02,&lt;br /&gt;
    0x11,0x03,0x04,&lt;br /&gt;
    0x0f,0x0b,0x14,&lt;br /&gt;
    0x12,0x0e,0x0c],&lt;br /&gt;
    [0x1b,0x1e,0x18,&lt;br /&gt;
    0x19,0x1d,0x1c,&lt;br /&gt;
    0x1a,0x23,0x1f,&lt;br /&gt;
    0x22,0x21,0x20]&lt;br /&gt;
]&lt;br /&gt;
}&amp;lt;/nowiki&amp;gt;&lt;/div&gt;</summary>
		<author><name>Wwylele</name></author>
	</entry>
	<entry>
		<id>https://www.3dbrew.org/w/index.php?title=Savegames&amp;diff=20843</id>
		<title>Savegames</title>
		<link rel="alternate" type="text/html" href="https://www.3dbrew.org/w/index.php?title=Savegames&amp;diff=20843"/>
		<updated>2018-10-29T20:05:51Z</updated>

		<summary type="html">&lt;p&gt;Wwylele: /* File Allocation Table */ add example&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This page describes the format and encryption of savegames contained in gamecards, SD and NAND. You can find savegames from various 3DS games on the [[Games]] page.&lt;br /&gt;
&lt;br /&gt;
This page does not describe [[DISA and DIFF|DISA container format]], which all savegames use as wrappers.&lt;br /&gt;
&lt;br /&gt;
All data in this page is little-endian unless otherwise specified. All &amp;quot;unused / padding&amp;quot; fields can contain uninitialized data unless otherwise specified.&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
Savegames are stored in [[DISA and DIFF|DISA container format]] (follow this link for the container format description). It forms a file system inside the inner content of the container. In this page only the inner file system format of the content is described.&lt;br /&gt;
&lt;br /&gt;
Unlike SD and NAND savegames, gamecard savegames has additional encryption + wear leveling layer. They are described in the following sections.&lt;br /&gt;
&lt;br /&gt;
== Gamecard savegame Encryption ==&lt;br /&gt;
&lt;br /&gt;
=== Repeating CTR Fail ===&lt;br /&gt;
On the 3DS savegames are stored much like on the DS, that is on a FLASH chip in the gamecart. On the DS these savegames were stored in plain-text but on the 3DS a layer of encryption was added. This is AES-CTR, as the contents of several savegames exhibit the odd behavior that xor-ing certain parts of the savegame together will result in the plain-text appearing.&lt;br /&gt;
&lt;br /&gt;
The reason this works is because the stream cipher used has a period of 512 bytes. That is to say, it will repeat the same keystream after 512 bytes. The way you encrypt with a stream cipher is you XOR your data with the keystream as it is produced. Unfortunately, if your streamcipher repeats and you are encrypting a known plain-text (in our case, zeros) you are basically giving away your valuable keystream.&lt;br /&gt;
&lt;br /&gt;
So how do you use this to decrypt a savegame on a 3DS? First off, you chunk up the savegame into 512 byte chunks. Then, you bin these chunks by their contents, discarding any that contain only FF. Now look for the most common chunk. This is your keystream. Now XOR the keystream with your original savegame and you should have a fully decrypted savegame. XOR with the keystream again to produce an encrypted savegame.&lt;br /&gt;
&lt;br /&gt;
=== Savegame keyY ===&lt;br /&gt;
&lt;br /&gt;
All gamecard and SD savegames are encrypted with AES-CTR. The base CTR for gamecard savegames is all-zero. The gamecard savegame [[AES|keyslots]]&#039; keyY(these savegame keyslots use the hardware key-generator) is unique for each region and for each game. The [[NCSD]] partition flags determine the method used to generate this keyY. When the save [[NCSD]] flags checked by the running NATIVE_FIRM are all-zero, the system will use the repeating CTR, otherwise a proper CTR which never repeats within the image is used.&lt;br /&gt;
&lt;br /&gt;
The [[AES]]-CMAC (which uses a hardware key-generator keyslot, as mentioned above) at the the beginning of the savegame must match the calculated CMAC using the DISA/DIFF data, otherwise the savegame is considered corrupted(see below).&lt;br /&gt;
&lt;br /&gt;
When all of the flags checked by the running NATIVE_FIRM are clear, the keyY(original keyY method used with saves where the CTR repeats within the image) is the following:&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;
| First 8-bytes from the plaintext [[NCCH#CXI|CXI]] accessdesc signature.&lt;br /&gt;
|-&lt;br /&gt;
| 0x8&lt;br /&gt;
| 0x4&lt;br /&gt;
| u32 CardID0 from [[Gamecards|gamecard]] plaintext-mode command 0x90, Process9 reads this with the [[NTRCARD]] hw. The actual cmdID used by Process9 is different since Process9 reads it with the gamecard in encrypted-mode.&lt;br /&gt;
|-&lt;br /&gt;
| 0xC&lt;br /&gt;
| 0x4&lt;br /&gt;
| u32 CardID1 from [[Gamecards|gamecard]] plaintext-mode command 0xA0, Process9 reads this with the [[NTRCARD]] hw. The actual cmdID used by Process9 is different since Process9 reads it with the gamecard in encrypted-mode.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== [[2.0.0-2]] Hashed keyY and [[2.2.0-4]] Savegame Encryption ====&lt;br /&gt;
&lt;br /&gt;
When certain [[NCSD]] partition flags are set, a SHA-256 hash is calculated over the data from the CXI(same data used with the original plain keyY), and the 0x40-bytes read from a gamecard command(this 0x40-byte data is also read by [[Process_Services_PXI|GetRomId]], which is the gamecard-uniqueID). The first 0x10-bytes from this hash is used for the keyY. When flag[7] is set, the CTR will never repeat within the save image, unlike the original CTR-method. All games which had the retail NCSD image finalized after the [[2.2.0-4]] update(and contain [[2.2.0-4]]+ in the [[System Update CFA|System update partition]]), use this encryption method.&lt;br /&gt;
&lt;br /&gt;
This keyY generation method was implemented with [[2.0.0-2]] via NCSD partition flag[3], however the proper CTR wasn&#039;t implemented for flag[7] until [[2.2.0-4]]. The hashed keyY flag[3] implemented with [[2.0.0-2]] was likely never used with retail gamecards.&lt;br /&gt;
&lt;br /&gt;
==== [[6.0.0-11]] Savegame keyY ====&lt;br /&gt;
&lt;br /&gt;
[[6.0.0-11]] implemented support for generating the savegame keyY with a new method, this method is much more complex than previous keyY methods. This is enabled via new [[NCSD]] partition flags, all retail games which have the NCSD image finalized after the [[6.0.0-11]] release(and [[6.0.0-11]]+ in the system update partition) will have these flags set for using this new method.&lt;br /&gt;
&lt;br /&gt;
A SHA-256 hash is calculated over the same data used with the above hashed keyY method, after hashing the above data the following data is hashed: the CXI programID, and the ExeFS:/.code hash from the decrypted [[ExeFS]] header. An [[AES]]-CMAC (the keyslot used for this uses the hardware key-scrambler) is then calculated over this hash, the output CMAC is used for the savegame keyY.&lt;br /&gt;
&lt;br /&gt;
The keyY used for calculating this AES-CMAC is initialized while NATIVE_FIRM is loading, this keyY is generated via the [[RSA]] engine. The RSA slot used here is slot0(key-data for slot0 is initialized by bootrom), this RSA slot0 key-data is overwritten during system boot. This RSA slot0 key-data gets overwritten with the RSA key-data used for verifying RSA signatures, every time Process9 verifies any RSA signatures except for [[NCCH|NCCH]] accessdesc signatures. Starting with [[7.0.0-13]] this key-init function used at boot is also used to initialize a separate keyslot used for the new [[NCCH]] encryption method.&lt;br /&gt;
&lt;br /&gt;
This [[FIRM|Process9]] key-init function first checks if a certain 0x10-byte block in the 0x01FF8000 region is all-zero. When all-zero it immediately returns, otherwise it clears that block then continues to do the key generation. This is likely for supporting launching a v6.0+ NATIVE_FIRM under this FIRM.&lt;br /&gt;
&lt;br /&gt;
== Gamecard wear leveling ==&lt;br /&gt;
&lt;br /&gt;
The 3DS employs a wear leveling scheme on the savegame FLASH chips(only used for CARD1 gamecards). This is done through the usage of blockmaps and a journal. The blockmap is located at offset 0 of the flash chip, and is immediately followed by the journal. The initial state is dictated by the blockmap, and the journal is then applied to that.&lt;br /&gt;
&lt;br /&gt;
First, there are 8 bytes whose purposes are currently unknown. Then comes the actual blockmap.&lt;br /&gt;
The blockmap structure is simple:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
struct header_entry {&lt;br /&gt;
        uint8_t phys_sec; // when bit7 is set, block has checksums, otherwise checksums are all zero&lt;br /&gt;
        uint8_t alloc_cnt;&lt;br /&gt;
        uint8_t chksums[8];&lt;br /&gt;
} __attribute__((__packed__));&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There&#039;s one entry per sector, counting from physical sector 1 (sector 0 contains the blockmap/journal).&lt;br /&gt;
&lt;br /&gt;
The 2 bytes that follow the blockmap are the CRC16 (with starting value 0xFFFF (like modbus)) of the first 8 bytes and the blockmap.&lt;br /&gt;
&lt;br /&gt;
Then comes the journal.&lt;br /&gt;
The journal structure is as follows:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
struct sector_entry {&lt;br /&gt;
        uint8_t virt_sec;       // Mapped to sector&lt;br /&gt;
        uint8_t prev_virt_sec;  // Physical sector previously mapped to&lt;br /&gt;
        uint8_t phys_sec;       // Mapped from sector&lt;br /&gt;
        uint8_t prev_phys_sec;  // Virtual sector previously mapped to&lt;br /&gt;
        uint8_t phys_realloc_cnt;       // Amount of times physical sector has been remapped&lt;br /&gt;
        uint8_t virt_realloc_cnt;       // Amount of times virtual sector has been remapped&lt;br /&gt;
        uint8_t chksums[8];&lt;br /&gt;
} __attribute__((__packed__));&lt;br /&gt;
&lt;br /&gt;
struct long_sector_entry{&lt;br /&gt;
        struct sector_entry sector;&lt;br /&gt;
        struct sector_entry dupe;&lt;br /&gt;
        uint32_t magic;&lt;br /&gt;
}__attribute__((__packed__));&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
With magic being a constant 0x080d6ce0.&lt;br /&gt;
&lt;br /&gt;
The checksums in the blockmap/journal entries work as follows:&lt;br /&gt;
* each byte is the checksum of an encrypted 0x200 bytes large block&lt;br /&gt;
* to calculate the checksum, a CRC16 of the block (with starting value 0xFFFF) is calculated, and the two bytes of the CRC16 are XORed together to produce the 8bit checksum&lt;br /&gt;
&lt;br /&gt;
== Components and partitions ==&lt;br /&gt;
&lt;br /&gt;
A savegame, after unwrapping the DISA container, consists of the following components:&lt;br /&gt;
&lt;br /&gt;
* SAVE header&lt;br /&gt;
* directory hash table&lt;br /&gt;
* file hash table&lt;br /&gt;
* file allocation table&lt;br /&gt;
* directory entry table&lt;br /&gt;
* file entry table&lt;br /&gt;
* data region&lt;br /&gt;
&lt;br /&gt;
A DISA container can have one or two partitions, and correspondingly a savegame has two possible layouts. The layout is determined by the parameter &amp;lt;code&amp;gt;duplicate data&amp;lt;/code&amp;gt; passed in [[FS:FormatSaveData]] or [[FS:CreateSystemSaveData]].&lt;br /&gt;
&lt;br /&gt;
=== Layout for &amp;lt;code&amp;gt;duplicate data = true&amp;lt;/code&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
The DISA container only has one partition which is always configured as external IVFC level 4 disabled (see [[DISA and DIFF|DISA format for details]]). All components are stored in this partition as&lt;br /&gt;
&lt;br /&gt;
* SAVE header at the beginning&lt;br /&gt;
* directory hash table&lt;br /&gt;
* file hash table&lt;br /&gt;
* file allocation table&lt;br /&gt;
* data region&lt;br /&gt;
** directory entry table is allocated inside data region&lt;br /&gt;
** file entry table as well&lt;br /&gt;
** all file data is also allocated here&lt;br /&gt;
&lt;br /&gt;
In this layout, all data is duplicated by DISA&#039;s DPFS tree, which is what the parameter &amp;lt;code&amp;gt;duplicate data&amp;lt;/code&amp;gt; implies.&lt;br /&gt;
&lt;br /&gt;
=== Layout for &amp;lt;code&amp;gt;duplicate data = false&amp;lt;/code&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
The DISA container has two partitions. Partition A is always configured as external IVFC level 4 disabled, and partition B is configured as it enabled. Components are stored among the two partitions as&lt;br /&gt;
&lt;br /&gt;
* Partition A&lt;br /&gt;
** SAVE header at the beginning.&lt;br /&gt;
** directory hash table&lt;br /&gt;
** file hash table&lt;br /&gt;
** file allocation table&lt;br /&gt;
** directory entry table&lt;br /&gt;
** file entry table&lt;br /&gt;
* Partition B&lt;br /&gt;
** used as data region entirely, and only has file data allocated.&lt;br /&gt;
&lt;br /&gt;
In this layout, all file system metadata is duplicated by partition A DPFS tree, but file data is not as partition B has external IVFC level 4.&lt;br /&gt;
&lt;br /&gt;
=== SAVE Header ===&lt;br /&gt;
&lt;br /&gt;
The SAVE header defines the rest components of the savegame. All &amp;amp;quot;offsets&amp;amp;quot; in the table below are relative to the beginning of partition A (inner content), while all &amp;amp;quot;starting block index&amp;amp;quot; are relative to the beginning of data region.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! Offset&lt;br /&gt;
! Length&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x00&lt;br /&gt;
| 4&lt;br /&gt;
| Magic &amp;amp;quot;SAVE&amp;amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| 0x04&lt;br /&gt;
| 4&lt;br /&gt;
| Magic 0x40000&lt;br /&gt;
|-&lt;br /&gt;
| 0x08&lt;br /&gt;
| 8&lt;br /&gt;
| File system Information offset (0x20)&lt;br /&gt;
|-&lt;br /&gt;
| 0x10&lt;br /&gt;
| 8&lt;br /&gt;
| Image size in blocks&lt;br /&gt;
|-&lt;br /&gt;
| 0x18&lt;br /&gt;
| 4&lt;br /&gt;
| Image block size&lt;br /&gt;
|-&lt;br /&gt;
| 0x1C&lt;br /&gt;
| 4&lt;br /&gt;
| Padding&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
| Below is File system Information&lt;br /&gt;
|-&lt;br /&gt;
| 0x20&lt;br /&gt;
| 4&lt;br /&gt;
| Unknown&lt;br /&gt;
|-&lt;br /&gt;
| 0x24&lt;br /&gt;
| 4&lt;br /&gt;
| Data region block size&lt;br /&gt;
|-&lt;br /&gt;
| 0x28&lt;br /&gt;
| 8&lt;br /&gt;
| Directory hash table offset&lt;br /&gt;
|-&lt;br /&gt;
| 0x30&lt;br /&gt;
| 4&lt;br /&gt;
| Directory hash table bucket count&lt;br /&gt;
|-&lt;br /&gt;
| 0x34&lt;br /&gt;
| 4&lt;br /&gt;
| Padding&lt;br /&gt;
|-&lt;br /&gt;
| 0x38&lt;br /&gt;
| 8&lt;br /&gt;
| File hash table offset&lt;br /&gt;
|-&lt;br /&gt;
| 0x40&lt;br /&gt;
| 4&lt;br /&gt;
| File hash table bucket count&lt;br /&gt;
|-&lt;br /&gt;
| 0x44&lt;br /&gt;
| 4&lt;br /&gt;
| Padding&lt;br /&gt;
|-&lt;br /&gt;
| 0x48&lt;br /&gt;
| 8&lt;br /&gt;
| File allocation table offset&lt;br /&gt;
|-&lt;br /&gt;
| 0x50&lt;br /&gt;
| 4&lt;br /&gt;
| File allocation table entry count&lt;br /&gt;
|-&lt;br /&gt;
| 0x54&lt;br /&gt;
| 4&lt;br /&gt;
| Padding&lt;br /&gt;
|-&lt;br /&gt;
| 0x58&lt;br /&gt;
| 8&lt;br /&gt;
| Data region offset (if no partition B)&lt;br /&gt;
|-&lt;br /&gt;
| 0x60&lt;br /&gt;
| 4&lt;br /&gt;
| Data region block count (= File allocation table entry count)&lt;br /&gt;
|-&lt;br /&gt;
| 0x64&lt;br /&gt;
| 4&lt;br /&gt;
| Padding&lt;br /&gt;
|-&lt;br /&gt;
| 0x68&lt;br /&gt;
| 8&lt;br /&gt;
| If partition B exists: directory entry table offset;&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
| otherwise: u32 directory entry table starting block index + u32 directory entry table block count&lt;br /&gt;
|-&lt;br /&gt;
| 0x70&lt;br /&gt;
| 4&lt;br /&gt;
| Maximum directory count&lt;br /&gt;
|-&lt;br /&gt;
| 0x74&lt;br /&gt;
| 4&lt;br /&gt;
| Padding&lt;br /&gt;
|-&lt;br /&gt;
| 0x78&lt;br /&gt;
| 8&lt;br /&gt;
| If partition B exists: file entry table offset;&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
| otherwise: u32 file entry table starting block index + u32 file entry table block count&lt;br /&gt;
|-&lt;br /&gt;
| 0x80&lt;br /&gt;
| 4&lt;br /&gt;
| Maximum file count&lt;br /&gt;
|-&lt;br /&gt;
| 0x84&lt;br /&gt;
| 4&lt;br /&gt;
| Padding&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
* The file/directory bucket count &amp;amp;amp; maximum count are specified by the parameters of [[FS:FormatSaveData]] or [[FS:CreateSystemSaveData]].&lt;br /&gt;
* When partition B doesn&#039;t exist, directory &amp;amp;amp; file entry tables are allocated in the data region, and while be marked allocated in file allocation table as if they are two normal files. However, only continuous allocation has been observed, so directly reading &amp;lt;code&amp;gt;block_count * block_size&amp;lt;/code&amp;gt; bytes from &amp;lt;code&amp;gt;data_region + starting_block_index * block_size&amp;lt;/code&amp;gt; should be safe. See the section [[#File Allocation Table]] below for more information.&lt;br /&gt;
&lt;br /&gt;
=== Directory Entry Table ===&lt;br /&gt;
&lt;br /&gt;
The directory entry table is an array of the entry type shown below. It describes the directory hierarchy of the file system.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! Offset&lt;br /&gt;
! Length&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x00&lt;br /&gt;
| 4&lt;br /&gt;
| Parent directory index. 0 for root&lt;br /&gt;
|-&lt;br /&gt;
| 0x04&lt;br /&gt;
| 16&lt;br /&gt;
| ASCII directory name in. All zero for root&lt;br /&gt;
|-&lt;br /&gt;
| 0x14&lt;br /&gt;
| 4&lt;br /&gt;
| Next sibling directory index. 0 if this is the last one&lt;br /&gt;
|-&lt;br /&gt;
| 0x18&lt;br /&gt;
| 4&lt;br /&gt;
| First subdirectory index. 0 if not exists&lt;br /&gt;
|-&lt;br /&gt;
| 0x1C&lt;br /&gt;
| 4&lt;br /&gt;
| First file index in file entry table. 0 for empty directory&lt;br /&gt;
|-&lt;br /&gt;
| 0x20&lt;br /&gt;
| 4&lt;br /&gt;
| Padding / zero?&lt;br /&gt;
|-&lt;br /&gt;
| 0x24&lt;br /&gt;
| 4&lt;br /&gt;
| Index of the next directory in the same hash table bucket. 0 if this is the last one&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
There are also some dummy entries in the array:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! Offset&lt;br /&gt;
! Length&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x00&lt;br /&gt;
| 4&lt;br /&gt;
| Current Total entry count&lt;br /&gt;
|-&lt;br /&gt;
| 0x04&lt;br /&gt;
| 4&lt;br /&gt;
| Maximum entry count = maximum directory count + 2&lt;br /&gt;
|-&lt;br /&gt;
| 0x08&lt;br /&gt;
| 28&lt;br /&gt;
| Padding / All zero&lt;br /&gt;
|-&lt;br /&gt;
| 0x24&lt;br /&gt;
| 4&lt;br /&gt;
| Index of the next dummy entry. 0 if this is the last one&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The 0-th entry of the array is always a dummy entry, which functions as the head of the dummy entry linked list. The 1-st entry of the array is always the root. Therefore maximum entry count is two more than maximum directory count. Dummy entries are left there when deleting directories, and reserved for future use.&lt;br /&gt;
&lt;br /&gt;
=== File Entry Table ===&lt;br /&gt;
&lt;br /&gt;
The file entry table is an array of the entry type shown below. It contains information for each file.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! Offset&lt;br /&gt;
! Length&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x00&lt;br /&gt;
| 4&lt;br /&gt;
| Parent directory index in directory entry table&lt;br /&gt;
|-&lt;br /&gt;
| 0x04&lt;br /&gt;
| 16&lt;br /&gt;
| ASCII file name&lt;br /&gt;
|-&lt;br /&gt;
| 0x14&lt;br /&gt;
| 4&lt;br /&gt;
| Next sibling file index. 0 if this is the last one&lt;br /&gt;
|-&lt;br /&gt;
| 0x18&lt;br /&gt;
| 4&lt;br /&gt;
| Padding&lt;br /&gt;
|-&lt;br /&gt;
| 0x1C&lt;br /&gt;
| 4&lt;br /&gt;
| First block index in data region. 0x80000000 if the file is just created and has no data.&lt;br /&gt;
|-&lt;br /&gt;
| 0x20&lt;br /&gt;
| 8&lt;br /&gt;
| File Size&lt;br /&gt;
|-&lt;br /&gt;
| 0x28&lt;br /&gt;
| 4&lt;br /&gt;
| Padding?&lt;br /&gt;
|-&lt;br /&gt;
| 0x2C&lt;br /&gt;
| 4&lt;br /&gt;
| Index of the next file in the same hash table bucket. 0 if this is the last one&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Like directory entry table, file entry table also has some dummy entries:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! Offset&lt;br /&gt;
! Length&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x00&lt;br /&gt;
| 4&lt;br /&gt;
| Current total entry count&lt;br /&gt;
|-&lt;br /&gt;
| 0x04&lt;br /&gt;
| 4&lt;br /&gt;
| Maximum entry count = maximum file count + 1&lt;br /&gt;
|-&lt;br /&gt;
| 0x08&lt;br /&gt;
| 36&lt;br /&gt;
| Padding / All zero&lt;br /&gt;
|-&lt;br /&gt;
| 0x2C&lt;br /&gt;
| 4&lt;br /&gt;
| Index of the next dummy entry. 0 if this is the last one&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The 0-th entry of the array is always a dummy entry, which functions as the head of the dummy entry linked list. Therefore maximum entry count is one more than maximum file count. Dummy entries are left there when deleting files, and reserved for future use.&lt;br /&gt;
&lt;br /&gt;
=== Directory Hash Table &amp;amp;amp; File Hash Table ===&lt;br /&gt;
&lt;br /&gt;
This is a u32 array of size = bucket count, each of which is an index to the directory / file entry table. The directory / file name is hashed and its entry index is put to the corresponding bucket. If there is already a directory/file entry in the bucket, then it appends to the linked list formed by &amp;lt;code&amp;gt;Index of the next directory/file in the same hash table bucket&amp;lt;/code&amp;gt; field in the directory/file entry table. i.e. this is a hash table using separate chaining with linked lists&lt;br /&gt;
&lt;br /&gt;
The hash function takes the parent index and the name as key. The function is equivalent to&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;uint32_t GetBucket(&lt;br /&gt;
    char name[16], // takes all 16 bytes including trailing zeros&lt;br /&gt;
    uint32_t parent_dir_index,&lt;br /&gt;
    uint32_t bucket_count&lt;br /&gt;
) {&lt;br /&gt;
    uint32_t hash = parent_dir_index ^ 0x091A2B3C;&lt;br /&gt;
    for (int i = 0; i &amp;amp;lt; 4; ++i) {&lt;br /&gt;
        hash = (hash &amp;amp;gt;&amp;amp;gt; 1) | (hash &amp;amp;lt;&amp;amp;lt; 31);&lt;br /&gt;
        hash ^= (uint32_t)name[i * 4]&lt;br /&gt;
        hash ^= (uint32_t)name[i * 4 + 1] &amp;amp;lt;&amp;amp;lt; 8&lt;br /&gt;
        hash ^= (uint32_t)name[i * 4 + 2] &amp;amp;lt;&amp;amp;lt; 16&lt;br /&gt;
        hash ^= (uint32_t)name[i * 4 + 3] &amp;amp;lt;&amp;amp;lt; 24&lt;br /&gt;
    }&lt;br /&gt;
    return hash % bucket_count;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
=== File Allocation Table ===&lt;br /&gt;
&lt;br /&gt;
The file allocation table is an array of a 8-byte entry shown below. The array size is actually &#039;&#039;one larger than&#039;&#039; the size recorded in the SAVE header. Each entry corresponds to a block in the data region (the block size is defined in SAVE header). However, the 0th entry corresponds to nothing, so the corresponding block index is off by one. e.g. entry 31 in this table corresponds to block 30 in the data region.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! Offset&lt;br /&gt;
! Length&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x00&lt;br /&gt;
| 4&lt;br /&gt;
| bit[0:30]: Index U; bit[31]: Flag U&lt;br /&gt;
|-&lt;br /&gt;
| 0x04&lt;br /&gt;
| 4&lt;br /&gt;
| bit[0:30]: Index V; bit[31]: Flag V&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Entries in this table forms several chains, representing how blocks in the data region should be linked together. However, unlike normal FAT systems, which uses chains of entries, 3DS savegames use chain of &#039;&#039;nodes&#039;&#039;. Each node spans one or multiple entries.&lt;br /&gt;
&lt;br /&gt;
One node spanning &amp;lt;code&amp;gt;n&amp;lt;/code&amp;gt; entries starting from &amp;lt;code&amp;gt;FAT[k]&amp;lt;/code&amp;gt; is in the following format:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;FAT[k + 0]:&lt;br /&gt;
    Index_U = index of the first entry of the previous node. 0 if this is the first node.&lt;br /&gt;
    Index_V = index of the first entry of the next node. 0 if this is the last node.&lt;br /&gt;
    Flag_U set if this is the first node.&lt;br /&gt;
    Flag_V set if this node has multiple entries.&lt;br /&gt;
&lt;br /&gt;
FAT[k + 1]:&lt;br /&gt;
    Index_U = k (the first entry index of this node)&lt;br /&gt;
    Index_V = k + n - 1 (the last entry index of this node)&lt;br /&gt;
    Flag_U always set&lt;br /&gt;
    Flag_V always clear&lt;br /&gt;
&lt;br /&gt;
FAT[k + 2] ~ FAT[k + n - 2]:&lt;br /&gt;
    All these entries are uninitialized&lt;br /&gt;
&lt;br /&gt;
FAT[k + n - 1]:&lt;br /&gt;
    Index_U = k&lt;br /&gt;
    Index_V = k + n - 1&lt;br /&gt;
    Flag_U always set&lt;br /&gt;
    Flag_V always clear&lt;br /&gt;
    (Same values as FAT[k + 1])&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* Note: all indices above are entry indices (block index + 1)&lt;br /&gt;
&lt;br /&gt;
All free blocks that are not allocated to any files also form a node chain in the allocation table. The head index of this &amp;amp;quot;free chain&amp;amp;quot; is recorded in &amp;lt;code&amp;gt;FAT[0].Index_V&amp;lt;/code&amp;gt;. Other fields of &amp;lt;code&amp;gt;FAT[0]&amp;lt;/code&amp;gt; are all zero&lt;br /&gt;
&lt;br /&gt;
Here is an example: [https://raw.githubusercontent.com/wwylele/3ds-save-tool/master/disa-fat.png]&lt;br /&gt;
&lt;br /&gt;
== Initialization ==&lt;br /&gt;
&lt;br /&gt;
When a save FLASH contains all xFFFF blocks it&#039;s assumed uninitialized by the game cartridges and it initializes default data in place, without prompting the user. The 0xFFFFFFFF blocks are uninitialized data. When creating a non-gamecard savegame and other images/files, it&#039;s initially all 0xFFFFFFFF until it&#039;s formatted where some of the blocks are overwritten with encrypted data.&lt;br /&gt;
&lt;br /&gt;
I got a new game SplinterCell3D-Pal and I downloaded the save and it was 128KB of 0xFF, except the first 0x10 bytes which were the letter &#039;Z&#039; (uppercase) --[[User:Elisherer|Elisherer]] 22:41, 15 October 2011 (CEST)&lt;br /&gt;
&lt;br /&gt;
== Fun Facts ==&lt;br /&gt;
&lt;br /&gt;
If you have facts that you found out by looking at the binary files please share them here:&lt;br /&gt;
&lt;br /&gt;
* From one save to another the game backups the last files that were in the partition and the entire image header in &amp;quot;random&amp;quot; locations.. --[[User:Elisherer|Elisherer]] 22:41, 15 October 2011 (CEST)&lt;br /&gt;
&lt;br /&gt;
== Tools ==&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/3dshax/3ds/tree/master/3dsfuse 3dsfuse] supports reading and modifying savegames. In the mounted FUSE filesystem, the /output.sav is the raw FLASH save-image. When the save was modified, a separate tool to update the CMAC must be used with /clean.sav, prior to writing output.sav to a gamecard.&lt;br /&gt;
* [[3DSExplorer]] supports reading of savegames, it doesn&#039;t support reading the new encrypted savegames and maybe in the future it will support modifying (some of the modyfing code is already implemented).&lt;br /&gt;
* [https://github.com/wwylele/3ds-save-tool wwylele&#039;s 3ds-save-tool] supports extracting files from savegames and extdata. It properly reconstructs data from the DPFS tree and extracts files in directories hierarchy.&lt;br /&gt;
* [https://github.com/wwylele/3dsfuse-ex 3dsfuse-ex] similar to 3dsfuse, but supports savegame inner FS, proper DPFS handling, and automatic CMAC update. Still WIP.&lt;br /&gt;
&lt;br /&gt;
[[セーブデータ|Japanese]]&lt;/div&gt;</summary>
		<author><name>Wwylele</name></author>
	</entry>
</feed>