Tutorial
Updated
Build DSi NAND from scratch
How do you build a NAND?
Before we start building NAND, let's look at the basic structure to help you to identify each section used, the placement, and purpose.
NAND Layout
Creating TWL_MAIN partition
Let's start with building the partitions in NAND. First, you must download the TWL_MAIN VBR with the extra bytes. Then insert both the VBR and extra bytes into a zerofilled file that is the full size of the partition (
Installing system titles
There are a few essential system titles* needed for the NAND to boot. These are the System Settings (
*I suggest starting with factory firmware, as this has fewer requirements to work. HWInfo (discussed later) is not needed, and configs can be somewhat ignored.
You can find lists of all titles, their versions, and downloads here. These downloads will need a TAD unpacker (perl | python).
DSiWare title data is split into two locations. One for the ticket, and one for the app + metadata (TMD):
To install, take the ticket file and save it to the ticket folder as
The name of the app is based on the app version. So, version
Each title installed MUST go into the paths listed above, otherwise it will be deleted by the Launcher, or cause the system to fail to boot. Below are preset title paths for the latest firmwares of each region. I suggest using the lists as a reference.
Copying System Data
I've listed all the paths below, with links to download the files. There isn't much more to this stage of the NAND setup than copying and pasting.
Unlaunch
Instead of the typical unlaunch install (unlaunch gets appended to the region specific Launcher), we're going to install it to the prototype Launcher directory. If the main Launcher ever fails (gets corrupted, is deleted), then stage2 will look for a prototype Launcher to boot. This fallback will cause the "backup unlaunch" to be loaded, giving us an extra layer of protection.
Install the unlaunch TMD to
By default, unlaunch will be disabled due to the region specific Launcher being valid. We can safely break the Launcher to enable unlaunch by changing the TMD from "HNAx" to "GNAx". Use specifically "GNAx", as this is used by custom installers. Now, write protect this TMD as well.
Unless you are using factory firmware, or you have a valid
Photo partition
Making TWL_PHOTO is pretty easy. Just like with TWL_MAIN, we'll insert the TWL_PHOTO VBR with extra bytes into a zerofilled file matching the partition's full size. The only difference is that this partition is
Rather than a bunch of files, we just need to create a single folder. Make
Creating full nand.bin
Now that we've prepared both partitions, it's time to put them into a larger nand.bin. First, make a zerofilled file with a size of
Download any stage2 that supports unlaunch, and matches your current console (retail on retail, dev on dev). Each stage2 (
Copying MBR
There are two possible MBRs depending on your NAND manufacturer, assuming you're using an official NAND chip. If you are using a custom chip (ie. SD card as NAND), you will need to set up the MBR manually to match the DSi's layout. I won't go into that here, but the Wikipedia article on MBR has very detailed information to get you started.
To add the MBR, overwrite the first 0x200 of NAND with the
Encrypting
Encrypting is pretty easy. Simply download twltool, then run the command below.
twltool nandcrypt --cid [cid] --consoleid [consoleID] --in [nand.bin] --out [nand.enc.bin]
no$gba footer
We're finally down to the last step. The footer is necessary to restoring the NAND dump, and testing in emulators. The structure is as follows:
Weirdly, the ConsoleID is in reverse endian compared to what most tools use, so swap the ID before you write it. Once you've created the no$gba footer, insert it into the NAND at
Thanks @k66 for testing this.
Before we start building NAND, let's look at the basic structure to help you to identify each section used, the placement, and purpose.
NAND Layout
| Address | Item | Notes |
|---|---|---|
| 0x00000000-0x00000200 | MBR (Samsung, ST) | This tells stage1 (BIOS) how NAND is laid out. |
| 0x00000200-0x0004E800 | stage2 | This is the bootloader, needed to run the console. There are two main options for stage2: v2665-9336, and v2435-8325. Both are explained later in the guide. This region does not get encrypted when the rest of NAND does. |
| 0x0010EE00-0x0010F000 | TWL_MAIN VBR | TWL_MAIN is a FAT16 partition used to store the firmware, system data, and games. The VBR is the start of the partition. |
| 0x0010F000-0x0010F018 | TWL_MAIN extra bytes | Not really sure what these are, but they're needed to make a valid partition. I included them in the VBR download. |
| 0x0CF09A00-0x0CF09C00 | TWL_PHOTO VBR | TWL_PHOTO is a FAT12 partition used to store photo data. Different bytes, but same purpose as TWL_MAIN vbr. |
| 0x0CF09C00-0x0CF09C04 | TWL_PHOTO extra bytes | Different bytes, but same purpose as TWL_MAIN extra bytes. |
| 0x0F000000-0x0F000040 | no$gba footer | A footer where the CID and ConsoleID are stored. This is used by emulators, NAND mounting tools, and NAND restore tools. |
Creating TWL_MAIN partition
Let's start with building the partitions in NAND. First, you must download the TWL_MAIN VBR with the extra bytes. Then insert both the VBR and extra bytes into a zerofilled file that is the full size of the partition (
0xCDF1200). Inserting the VBR makes the file a valid partition, so you can now mount the partition with the tool of your choice. Installing system titles
There are a few essential system titles* needed for the NAND to boot. These are the System Settings (
HNBx), Launcher (HNAx), wlanfirm (HNCA), and sysmenuVersion (HNLx).*I suggest starting with factory firmware, as this has fewer requirements to work. HWInfo (discussed later) is not needed, and configs can be somewhat ignored.
If you have WiFi module versions DWM-W024 or J27H020, you will need wlanfirm v512 or higher. Otherwise you will experience a brick. If you have DWM-W015, you can run any wlanfirm.
DSiWare title data is split into two locations. One for the ticket, and one for the app + metadata (TMD):
- Ticket folder :
nand:/ticket/[TID_CATEGORY]/
- App+TMD folder :
nand:/title/[TID_CATEGORY]/[TID_UNIQUE]/content/
The
The
TID_CATEGORY is the application type (Launcher, system, user, data), obtained from 0x234-237 in the app (may be .nds). The bytes are in reverse order, so you'll need to flip them around (eg. 0f 00 03 00 --] 00 03 00 0f).The
TID_UNIQUE, found from 0x230-233 in the app, is a unique 4 byte ASCII identifier. This ID is also in reverse order.[TID_UNIQUE].tik. Now take the TMD and copy it to the title folder as title.tmd. The naming of the app is a bit more complicated.The name of the app is based on the app version. So, version
1 of the app would mean the app gets saved to the title folder as 00000001.app. The version of the app can be found at 0x1E4-1E7 in the TMD. Dev apps will be a bit different, having hex strings in place of versions, like 0f960d6a.Each title installed MUST go into the paths listed above, otherwise it will be deleted by the Launcher, or cause the system to fail to boot. Below are preset title paths for the latest firmwares of each region. I suggest using the lists as a reference.
Copying System Data
I've listed all the paths below, with links to download the files. There isn't much more to this stage of the NAND setup than copying and pasting.
nand:/sys/cert.sys(prod | dev)
nand:/sys/TWLFontTable.dat(Worldwide | China | Korea)
nand:/shared1/TWLCFG1.dat(all)
nand:/shared1/TWLCFG0.dat(all)
nand:/shared2/launcher/wrap.bin(all)
nand:/shared2/0000(all)
nand:/sys/HWINFO_N.dat(all)
HWINFO_S.dat, you can place it in nand:/sys/. This file is tied to the CPU, and is signed, so your HWInfo MUST match the console you install it to. You can verify that the HWInfo matches the target console with this script. If you have a development unit, it is also possible to resign HWInfo.
Code:
[b]Verify HWINFO_S using retail key:[/b]
python3 hwinfo.py --consoleid [consoleid] --hwinfo HWINFO_S_prod.dat verify
[b]Verify HWINFO_S using dev key:[/b]
python3 hwinfo.py --consoleid [consoleid] --hwinfo HWINFO_S_dev.dat verify --dev
[b]Resign HWINFO_S using dev key:[/b]
python3 hwinfo.py --consoleid [consoleid] --hwinfo HWINFO_S.dat resign --dev
The existing file must have data from 0x0-0x80 in it. So, if you're making HWINFO_S from scratch, put 0x80 of zeroes infront of the actual data, then run the resign command.
This will create a new file HWINFO_S_resigned.dat with the signature changed (0x0-0x80).
Unlaunch
Instead of the typical unlaunch install (unlaunch gets appended to the region specific Launcher), we're going to install it to the prototype Launcher directory. If the main Launcher ever fails (gets corrupted, is deleted), then stage2 will look for a prototype Launcher to boot. This fallback will cause the "backup unlaunch" to be loaded, giving us an extra layer of protection.
Install the unlaunch TMD to
nand:/title/00030017/484e4141/content/title.tmd. Be mindful of if there is an existing TMD in that location. If there is, overwrite the start of the unlaunch TMD with the pre-existing TMD. With the TMD as it is now, the Launcher will try to delete it. Write protect the unlaunch TMD to prevent this.By default, unlaunch will be disabled due to the region specific Launcher being valid. We can safely break the Launcher to enable unlaunch by changing the TMD from "HNAx" to "GNAx". Use specifically "GNAx", as this is used by custom installers. Now, write protect this TMD as well.
Unless you are using factory firmware, or you have a valid
HWINFO_S.dat, unlaunch MUST be enabled.Photo partition
Making TWL_PHOTO is pretty easy. Just like with TWL_MAIN, we'll insert the TWL_PHOTO VBR with extra bytes into a zerofilled file matching the partition's full size. The only difference is that this partition is
0x20B6600 long.Rather than a bunch of files, we just need to create a single folder. Make
photo:/photo/. The photo folder is seen as the "root" of the partition, so, without it, the management file cannot be created, and the camera app will fail.Creating full nand.bin
Now that we've prepared both partitions, it's time to put them into a larger nand.bin. First, make a zerofilled file with a size of
0x0F000000. Now, insert both TWL_MAIN and TWL_PHOTO.- TWL_MAIN gets copied at NAND offset
0x0010EE00, until the entire file is written
- TWL_PHOTO get copied at NAND offset
0x0CF09A00, until the entire file is written
Download any stage2 that supports unlaunch, and matches your current console (retail on retail, dev on dev). Each stage2 (
.nand extension) will be one to one with how it appears in NAND, with the exception of MBR being zerofilled. As such, we can copy 0x00 onwards of the stage2 into 0x00 onwards of the NAND, until the entire file has been written.There are a few different stage2s available. The standard one shipped on all DSis (
v2435-8325) works fine, but we use a slightly updated version (v2665-9336) for the NAND builder. The later revision stage2 is functionally the same, but it blocks the dangerous standard unlaunch installer, pushing people into using a safer alternative. Though if you've followed my guide this far, you probably don't care about safety (:Copying MBR
There are two possible MBRs depending on your NAND manufacturer, assuming you're using an official NAND chip. If you are using a custom chip (ie. SD card as NAND), you will need to set up the MBR manually to match the DSi's layout. I won't go into that here, but the Wikipedia article on MBR has very detailed information to get you started.
To add the MBR, overwrite the first 0x200 of NAND with the
.bin.Encrypting
Encrypting is pretty easy. Simply download twltool, then run the command below.
twltool nandcrypt --cid [cid] --consoleid [consoleID] --in [nand.bin] --out [nand.enc.bin]
If you try to compress your newly built NANDs, you will notice that the size stays the same. Why? Negative encryption.
When you initially work on the NAND, it is decrypted, and filled with zerobytes. This compresses well. However, when we encrypt the NAND in order to flash it back, all those zerobytes will turn into encrypted data. When this happens, the entire NAND becomes high entropy data, none of which compresses well. There is a solution to this though.
Encrypt the data region of TWL_MAIN (make sure to avoid the file tables), then mount and write to the partition. Afterwards, the final encryption with twltool will turn unused encrypted data back into zeroes.
When you initially work on the NAND, it is decrypted, and filled with zerobytes. This compresses well. However, when we encrypt the NAND in order to flash it back, all those zerobytes will turn into encrypted data. When this happens, the entire NAND becomes high entropy data, none of which compresses well. There is a solution to this though.
Encrypt the data region of TWL_MAIN (make sure to avoid the file tables), then mount and write to the partition. Afterwards, the final encryption with twltool will turn unused encrypted data back into zeroes.
no$gba footer
We're finally down to the last step. The footer is necessary to restoring the NAND dump, and testing in emulators. The structure is as follows:
- 16 bytes of ASCII:
DSi eMMC CID/CPU
- 16 bytes:
[cid]
- 32 bytes:
[consoleid]
- 24 bytes:
0x00repeating
0x40, and should be appended to the end of the NAND. Not overwritten.Weirdly, the ConsoleID is in reverse endian compared to what most tools use, so swap the ID before you write it. Once you've created the no$gba footer, insert it into the NAND at
0x0F000000. Now that you've written the footer, your NAND is finished, and should be ready to flash to the console!Thanks @k66 for testing this.
Last edited by rvtr,











