-
Notifications
You must be signed in to change notification settings - Fork 1
NDS Format
This is a currently in-progress understanding of how NDS files are formatted to help guide me along the process of making this program functional. A lot of information regarding the header and the basics of the NitroROM File System where thanks to this guide.
This is an overview of how the NDS format looks on a very basic level. Values that are stored in the header will be noted as Header (offset)
. They are 4 byte little endian integers unless otherwise noted.
Name | Purpose | Start | Size |
---|---|---|---|
Header | Stores information about the file | 0h | 200h |
Padding | Zero padding until 4000h | 200h | 3E00h |
ARM9 ROM | ARM9 boot code (?) | Header 20h | Header 2Ch |
ARM9 Overlay | ARM9 overlay table | Header 50h | Header 54h |
Overlay Files (?) | Overlay entries placed here (?) | ? | ? |
ARM7 ROM | ARM7 boot code (?) | Header 30h | Header 3Ch |
ARM7 Overlay | ARM7 overlay table | Header 58h | Header 5Ch |
File Name Table | Directory and file name information | Header 40h | Header 44h |
File Allocation Table | File offset information | Header 48h | Header 4Ch |
After the header is zero padding up to the 4000h
byte mark. This is because ARM9 code must start at at least 4000h
into the file and must be on a 1000h
byte mark. ARM7 code should be at least at 8000h
and also be on a 1000h
byte mark, although there are working examples where it is on a 100h
byte mark instead.
Padding after the header is usually filled with zeroes, but in many other places in the file FFh
is used for padding instead. For example, when padding the file to the nearest power of two size FFh
is used instead of 00h
.
Overlay files can be found in a ROM by finding the starting file id in the root node of the FNT. Any entry in the FAT that falls under the starting file id is an overlay file. These files vary in size and as of now their purpose is unknown. From my testing it seems it is best to put the overlay files exactly where they used to be in the file by reading the old FAT.
Here is a pseudo code example:
int start_file_id = FNT.root().file_id();
for (int i = 0; i < start_file_id; i++)
{
// Get FAT entry at index i and use it to read the overlay from the ROM
}
Address | Bytes | Explanation |
---|---|---|
000h | 12h | Game Title |
00Ch | 4h | Gamecode |
010h | 2h | Makercode |
012h | 1h | Unitcode |
013h | 1h | Encryption Seed Select |
014h | 1h | Devicecapacity |
015h | 9h | Reserved |
01Eh | 1h | ROM Version |
01Fh | 1h | Autostart |
020h | 4h | ARM9 rom_offset |
024h | 4h | ARM9 entry_address |
028h | 4h | ARM9 ram_address |
02Ch | 4h | ARM9 size |
030h | 4h | ARM7 rom_offset |
034h | 4h | ARM7 entry_address |
038h | 4h | ARM7 ram_address |
03Ch | 4h | ARM7 size |
040h | 4h | File Name Table |
044h | 4h | File Name Table |
048h | 4h | File Allocation Table |
04Ch | 4h | File Allocation Table |
050h | 4h | File ARM9 overlay_offset |
054h | 4h | File ARM9 overlay_size |
058h | 4h | File ARM7 overlay_offset |
05Ch | 4h | File ARM7 overlay_size |
060h | 4h | Port 40001A4h setting for normal commands |
064h | 4h | Port 40001A4h setting for KEY1 commands |
068h | 4h | Icon_title_offset |
06Ch | 2h | Secure Area Checksum, CRC-16 of [ [20h]..7FFFh] |
06Eh | 2h | Secure Area Loading Timeout |
070h | 4h | ARM9 Auto Load List RAM Address |
074h | 4h | ARM7 Auto Load List RAM Address |
078h | 8h | Secure Area Disable |
080h | 4h | Total Used ROM size |
084h | 4h | ROM Header Size |
088h | 38h | Reserved |
0C0h | 9Ch | Nintendo Logo |
15Ch | 2h | Nintendo Logo Checksum (CF56h) |
15Eh | 2h | Header Checksum, CRC-16 of [000h-15Dh] |
160h | 4h | Debug rom_offset |
164h | 4h | Debug size |
168h | 4h | Debug ram_address |
16Ch | 4h | Reserved |
170h | 90h | Reserved |