Nintendo DS File Formats
Note: All the contents of this article are entirely copied from http://llref.emutalk.net/nds_formats.htm for archival purpose. *1
Sections
- Generic Header Format
- Graphic File Formats
- Archive File Formats
- Sound File Formats
- Custom File Formats
- Compression Formats
Generic Header Format
Offset | Length | Name | Description |
---|---|---|---|
0x0 | 0x4 | Magic ID | Identifies the file format. |
0x4 | 0x4 | Constant | Always (0xFFFE0001) |
0x8 | 0x4 | Section Size | Size of this section, including the header. |
0xC | 0x2 | Header Size | Size of this header. (Should always equal 0x10) |
0xE | 0x2 | Number of Sections | The number of sub-sections in this section. |
Graphic File Formats
Nintendo Tile Format Palette (NTFP)
Offset | Length | Name | Description |
---|---|---|---|
DATA | 0x2 | Palette Color | Format is BGR555 (XBBBBBGGGGGRRRRR). |
Nintendo Tile Format Tile (NTFT)
Offset | Length | Name | Description |
---|---|---|---|
DATA | 8Bits or 4Bits | Tile Data | Indexes to colors in a palette. |
Nintendo Tile Format Screen (NTFS)
Offset | Length | Name | Description |
---|---|---|---|
DATA | 0x2 | Screen Data | Indexes to a tile. Format is (YYYYXXNNNNNNNNNN) Y4 Palette Number X2 Transformation (YFlip/XFlip) N10 Tile Number |
Nintendo Color Resource (NCLR/RLCN)
- uses Generic Header
- magic ID is #RLCN (0x524C434E)
- contains 2 sub-sections
#1 Section - Palette Data (TTLP)
Offset | Length | Name | Description |
---|---|---|---|
0x0 | 0x4 | Magic ID | #TTLP (0x54544C50) |
0x4 | 0x4 | Section Size | Size of this section, including the header. |
0x8 | 0x4 | Palette Bit Depth | 3 = 4 Bits 4 = 8 Bits |
0xC | 0x4 | Padding? | Always ( 0x000000) |
0x10 | 0x4 | Palette Data Size | Size of Palette Data in bytes. if (0x200-size > 0) then size = 0x200-size also if the bit depth is 8 palette is 0x200 |
0x14 | 0x4 | Colors Per Palette | Probably always (16 colors). |
DATA | Palette Data stored as NTFP |
#2 Section - Palette Count Map? (PMCP)
Offset | Length | Name | Description |
---|---|---|---|
0x0 | 0x4 | Magic ID | #PMCP (0x504D4350) |
0x4 | 0x4 | Section Size | Should always be (0x12). |
0x8 | 0x2 | Palette Count | Number of palettes in file. |
0xA | 0x6 | Unknown | Always (0xEFBE080000) |
DATA | 0x2 | Palette ID | Simple ID number for each palette (starting from 0x0). |
Nintendo Character Graphic Resource (NCGR/RGCN)
- uses Generic Header
- magic ID is #RGCN (0x5247434E)
- contains 2 sub-sections
#1 Section - Character Data (RAHC)
Offset | Length | Name | Description |
---|---|---|---|
0x0 | 0x4 | Magic ID | #RAHC (0x52414843) |
0x4 | 0x1 | Header Size | Should always be (0x20) |
0x4 | 0x4 | Section Size | Size of this section, including the header. |
0x8 | 0x2 | Tile Count | Multiplied by 1024 gets the total number of pixels in the file. |
0xA | 0x2 | Tile Size | Always (0x20) |
0xC | 0x4 | Tile Bit Depth | 3 = 4 Bits 4 = 8 Bits |
0x10 | 0x8 | Padding? | Always (0x0) |
0x18 | 0x4 | Tile Data Size | Divided by 1024 should equal Tile Count. |
0x1C | 0x4 | Unknown | Always (0x24) |
DATA | Tile Data stored as NTFT |
#2 Section - (SOPC)
Offset | Length | Name | Description |
---|---|---|---|
0x0 | 0x4 | Magic ID | #SOPC (0x534F5043) |
0x4 | 0x4 | Section Size | Should always be (0x10) |
0x8 | 0x4 | Padding | Always (0x0) |
0xC | 0x2 | Tile Size? | Always (0x20) |
0xE | 0x2 | Tile Count | Is always identical to Tile Count in #1 Section. |
Nintendo Screen Resource (NSCR/RCSN)
- uses Generic Header
- magic ID is #RCSN (0x5243534E)
- contains only 1 sub-section
#1 Section - Screen Data (NRCS)
Offset | Length | Name | Description |
---|---|---|---|
0x0 | 0x4 | Magic ID | #NRCS (0x4E524353) |
0x4 | 0x1 | Header Size | Should always be (0x14) |
0x4 | 0x4 | Section Size | Size of this section, including the header. |
0x8 | 0x2 | Screen Width | Value is in pixels. |
0xA | 0x2 | Screen Height | Value is in pixels. |
0xC | 0x4 | Padding | Always (0x0) |
0x10 | 0x4 | Screen Data Size | |
DATA | Screen Data stored as NTFS |
Nintendo Animation Resource (NANR/RNAN)
- uses Generic Header
- magic ID is #RNAN (0x?)
- contains 3 sub-sections
#1 Section - Animation Bank (KNBA)
Offset | Length | Name | Description |
---|---|---|---|
0x0 | 0x4 | Magic ID | #KNBA (0x?) |
0x4 | 0x4 | Section Size | Size of this section, including the header. |
0x8 | 0x2 | Number of Animations | Each animation is 16 bytes. |
0xA | 0x2 | Frame Count | Each frame is 8 bytes. |
0xC | 0x4 | Unknown Constant | |
0x10 | 0x4 | Unknown | |
0x14 | 0x4 | Unknown Size | |
0x18 | 0x8 | Padding | (Always 0x0) |
DATA | Animation Blocks | ||
0x0 | 0x4 | Number of Frames | |
0x4 | 0x2 | Unknown | |
0x6 | 0x2 | Unknown | Always (0x1) |
0x8 | 0x4 | Unknown | |
0xC | 0x4 | First Frame Offset | RELATIVE to the end of this section. |
DATA | Frame Blocks | ||
0x4 | Unknown Offset | ||
0x2 | Frame Width | ||
0x2 | Unknown | Always (0xBEEF) | |
DATA | Frame Data |
Nintendo CEII Resource (NCER/RECN)
- uses Generic Header
- magic ID is #RECN (0x5245434E)
- contains 3 sub-sections
#1 Section - CEII Bank (KBEC)
Offset | Length | Name | Description |
---|---|---|---|
0x0 | 0x4 | Magic ID | #KBEC (0x4B424543) |
0x4 | 0x4 | Section Size | Size of this section, including the header. |
0x8 | 0x4 | Number of Images | |
0xC | 0x4 | Unknown | Always (0x12) |
0x10 | 0x4 | Boundary Size | Specifies the the area in which the image can be drawn multiplied by 64. ie a boundary size of 2 means that the area is 128x128 pixels. |
0x14 | 0x12 | Padding | Always (0x0) |
DATA | Cell Table (8 bytes each) | ||
0x0 | 0x2 | Number of Cells | The number of cells that make up an image. |
0x2 | 0x2 | Unknown | |
0x4 | 0x4 | Cell Data Offset | This offset is RELATIVE to the end of the Cell Table. |
DATA | Cell Data (Starts at Number of Cells * 8 | each cell is made up of 6 bytes) | ||
0x0 | 0x1 | Row Data | Format is (RRY1Y2??) RR = Row (Note that the row order is 2, 3, 0, 1) Y1 = Y Offset from the top of the row. (Multiplied by 16) Y2 = Y Offset from the top of the row. (Multiplied by 4) |
0x1 | 0x1 | Cell Width | Format is (WW????FF) WW = Width of the cell. FF = Vertical Flag (Not sure if this is used or not). |
0x2 | 0x1 | Column Data | Format is (CCX1X2??) CC = Column (Note that the column order is 2, 3, 0, 1) X1 = X Offset from the top of the row. (Multiplied by 16) X2 = X Offset from the top of the row. (Multiplied by 4) |
0x3 | 0x1 | Cell Height | Format is (HH????FF) HH = Height of the cell. FF = Horizontal flag. |
Rows/Columns:
Row/Column are numbered like that because for regular images, they shouldn't exceed the size of 0 & 1 (128x128 pixels), the frist two rows/columns are meant for larger images up to 256x256 pixels).
The height and width of the cell is determined by referencing to 2D array. I am yet to find any cells that use nodes with ??.
Height | |||||
---|---|---|---|---|---|
Width | 00 | 01 | 10 | 11 | |
00 | 8x8 | 16x16 | 32x32 | 64x64 | |
01 | 16x8 | 32x8 | 32x16 | 64x32 | |
10 | 8x16 | 8x32 | 16x32 | 32x64 | |
11 | ?? | ?? | ?? | ?? |
So if a cell has a WW of 0 and a HH of 3 it's size is 64x64.
X & Y Offsets:
I am not sure if the Y Offset is affected in the same way, but if the position of a cell is within the far right column and the FF (Flag) value is equal to 1. The offset is subtracted by 256.
0x4 | 0x2 | Tile Offset | The offset into the tile data where this cell starts. |
The last two sections of both files use the same format.
#2 Section - Animation Label (LABL)
Offset | Length | Name | Description |
---|---|---|---|
0x0 | 0x4 | Magic ID | #LBAL (0x4C42414C) |
0x4 | 0x4 | Section Size | Size of this section, including the header. |
DATA | |||
0x8 | 0x4 | Label Offset | |
DATA | |||
Label Name | Terminated by (0x0) |
#3 Section - (TXEU)
Offset | Length | Name | Description |
---|---|---|---|
0x0 | 0x4 | Magic ID | #TXEU (0x54584555) |
0x4 | 0x4 | Section Size | Size of this section, including the header. |
0x8 | 0x4 | Unknown | 0 or 1 |
Archive File Formats
Nintendo Archive (ARC/NARC)
- uses Generic Header
- magic ID is #NARC (0x4E415243)
- contains 3 sub-sections
#1 Section - File Allocation Table (BTAF)
Offset | Length | Name | Description |
---|---|---|---|
0x0 | 0x4 | Magic ID | #BTAF (0x42544146) |
0x4 | 0x1 | Header Size | |
0x4 | 0x4 | Section Size | Size of this section, including the header. |
0x8 | 0x4 | Number of Files | The number of files in the archive. |
DATA | See below. | ||
0xC | 0x4 | Start Offset | Is RELATIVE to the GMIF section start offset. |
0x10 | 0x4 | End Offset | Is RELATIVE to the GMIF section start offset. |
#2 Section - File Name Table (BTNF)
Offset | Length | Name | Description |
---|---|---|---|
0x0 | 0x4 | Magic ID | #BTNF (0x42544E46) |
0x4 | 0x4 | Section Size | Size of this section, including the header. |
DATA | Directory Table | ||
0x4 | Directory Start Offset | All other offsets are RELATIVE to the first directory start offset which is the root folder. | |
0x2 | First File Position | ||
0x2 | Directory Count / Parent Directory | For the root folder it has the total number of directories in the archive, and the latter for everything else. | |
DATA | Name Table | ||
0x1 | Size of Name | The first bit specifies whether it is a file or a folder. | |
0xLENGTH | Name String | ||
EXTRA | 0x2 | Directory ID | The number reference of that directory. |
#3 Section - File Image (GMIF)
Offset | Length | Name | Description |
---|---|---|---|
0x0 | 0x4 | Magic ID | #GMIF (0x474D4946) |
0x4 | 0x4 | Section Size | Size of this section, including the header. |
0x8 | 0x4 | Compression ID | #LZ77 (0x4C5A3737) Indicates that the file data is compressed. |
Sound File Formats
Sound Data File (SDAT)
- uses Generic Header
- magic ID is #SDAT (0x53444154)
- contains 4 sub-sections
Section Offsets
Offset | Length | Name | Description |
---|---|---|---|
0x0 | 0x4 | SYMB Offset | Offset to SYMB Section |
0x4 | 0x4 | SYMB Size | Size of SYMB Section |
0x8 | 0x4 | INFO Offset | Offset to INFO Section |
0xC | 0x4 | INFO Size | Size of INFO Section |
0x10 | 0x4 | FAT Offset | Offset to FAT Section |
0x14 | 0x4 | FAT Size | Size of FAT Section |
0x18 | 0x4 | FILE Offset | Offset to FILE Section |
0x1C | 0x4 | FILE Size | Size of FILE Section |
0x20 | 0x16 | Padding |
#1 Section - (SYMB)
Offset | Length | Name | Description |
---|---|---|---|
0x0 | 0x4 | Magic ID | #SYMB (0x53594D42) |
0x4 | 0x4 | Section Size | Size of this section, including the header. |
0x8 | 0x4 | Sequences Offset | |
0xC | 0x4 | Sound Effects Offset | |
0x10 | 0x4 | Banks Offset | |
0x14 | 0x4 | Waves Offset | |
0x18 | 0x4 | Players Offset | |
0x1C | 0x4 | Groups Offset | |
0x20 | 0x4 | Streams Offset | |
0x24 | 0x4 | Unknown Offset | |
0x28 | 0x24 | Padding | |
DATA | |||
0x40 | 0x4 | Number of Files | The number of files in this section |
0x44 | 0x4 | Filename Offset | Offset is RELATIVE to each section offset |
#2 Section - Information (INFO)
Offset | Length | Name | Description |
---|---|---|---|
0x0 | 0x4 | Magic ID | #INFO (0x?) |
0x4 | 0x4 | Section Size | Size of this section, including the header. |
0x8 | 0x4 | Sequences Offset | |
0xC | 0x4 | Sound Effects Offset | |
0x10 | 0x4 | Banks Offset | |
0x14 | 0x4 | Waves Offset | |
0x18 | 0x4 | Players Offset | |
0x1C | 0x4 | Groups Offset | |
0x20 | 0x4 | Streams Offset | |
0x24 | 0x4 | Unknown Offset | |
0x28 | 0x24 | Padding | |
DATA | |||
0x4 | Number of Elements | ||
0x4 | Offset to First Element | ||
0x4 | ID of Current Element | ||
0x8 | Sequences Variables | ||
0x8 | Banks Variables | ||
0x8 | Players Variables | ||
0x8 | Groups Variables |
#3 Section - FIle Allocation Table (FAT)
Offset | Length | Name | Description |
---|---|---|---|
0x0 | 0x4 | Magic ID | #FAT (0x?) |
0x4 | 0x4 | Section Size | Size of this section, including the header. |
0x8 | 0x4 | Number of Files | |
DATA | FAT Table (Repeats) | ||
0x4 | File Offset | ||
0x4 | File Size | ||
0x8 | Unknown |
#4 Section - File Data (FILE)
Offset | Length | Name | Description |
---|---|---|---|
0x0 | 0x4 | Magic ID | #FILE (0x?) |
0x4 | 0x4 | Section Size | Size of this section, including the header. |
0x8 | 0x4 | Number of Files | |
0xC | 0x4 | Unknown |
Sound Sequence (SSEQ)
- uses Generic Header
- magic ID is #SSEQ (0x?)
- contains only one section?
#1 Section - Sequence Data (DATA)
Offset | Length | Name | Description |
---|---|---|---|
0x0 | 0x4 | Magic ID | #DATA (0x?) |
0x4 | 0x4 | Section Size | Size of this section, including the header. |
0x8 | 0x4 | Start Offset | The offset to where the notation data begins. |
0xC | 0x3 | Track Description (Command) | |
DATA | (Track Reference which repeats for the number of tracks) | ||
0x4 | Open Track (Command) | Fist bytes is the command code, second byte is the track number, and the last 2 bytes are the track offet. | |
DATA | |||
0x3 | Set Mono/Poly (Command) | ||
0x3 | Set Tempo (Command) |
Sequence Commands
Code | Value Length | Name | Description |
---|---|---|---|
0x00 - 0x7F | 0x2 | Music Note | Format is (0xVVDD) V2 = Velocity D2 = Duration |
0x80 | 0x1 | Rest Note | Duration of rest note. |
0x81 | 0x1 | Change Instrument | Instrument number to change to. |
0x93 | 0x4 | Open Track | Format is (0xAABBBBBB) A2 = Track number B6 = Track offset (RELATIVE to the start offset) |
0x94 | 0x3 | Jump | Move to postion in the track and loop. |
0x95 | 0x3 | Call | Move to the start of another track. |
0xC0 | 0x1 | Channel Panning | Set panning value (-128 to 127) |
0xC1 | 0x1 | Channel Volume | Set volume |
0xC2 | 0x1 | Global Volume | Set the sequence volume |
0xC3 | 0x1 | Transpose | |
0xC4 | 0x1 | Portamento | |
0xC5 | 0x1 | Portamento Range | |
0xC6 | 0x1 | Priority | Set the priority of the track. |
0xC7 | 0x1 | Mono / Poly | Set the phonie 0 = Polyphonie 1 = Monophonie |
0xCA | 0x1 | Vibrato Depth | |
0xCB | 0x1 | Vibrato Speed | |
0xE1 | 0x1 | Tempo | Set the tempo. |
0xFD | 0x0 | Return | Return from the previous "Call" command. |
0xFE | 0x2 | Track Description | Number of tracks and their position. |
0xFF | 0x0 | End | End of the track. |
Sound Sequence Archive (SSAR)
- uses Generic Header
- magic ID is #SSAR (0x?)
- contains only 1 section
#1 Section - Data (DATA)
Offset | Length | Name | Description |
---|---|---|---|
0x0 | 0x4 | Magic ID | #DATA (0x?) |
0x4 | 0x4 | Section Size | Size of this section, including the header. |
0x8 | 0x4 | Unknown Offset | |
0xC | 0x4 | Number of elements | |
0x10 | 0x4 | Padding | Always (0x0) |
DATA | |||
0x8 | Unknown | ||
0x4 | Data Offset | RELATIVE to Unknown Offset | |
DATA | Actual Data |
Sound Wave Archive (SWAR)
- uses Generic Header
- magic ID is #SWAR (0x?)
- contains only 1 section
#1 Section - Data (DATA)
Offset | Length | Name | Description |
---|---|---|---|
0x0 | 0x4 | Magic ID | #DATA (0x?) |
0x4 | 0x4 | Section Size | Size of this section, including the header. |
0x8 | 0x32 | Unknown | |
0x28 | 0x4 | Number of Files | |
DATA | Repeats by Number of Files. | ||
0x2C | 0x4 | Wave Offset | RELATIVE to the start of the file. |
DATA | Data at Wave Offset. | ||
0x0 | 0x1 | Wave Type | 0 = PCM 8Bit 1 = PCM 16Bit 2 = ADPCM |
0x1 | 0x1 | Loop Support | 0 = False 1 = True |
0x2 | 0x2 | Sample Rate | |
0x4 | 0x2 | Duration | |
0x6 | 0x2 | Loop Start | Multiply by 4. |
0x8 | 0x4 | Loop Length | Multiply by 4. |
DATA | Wave Data |
Sound Bank (SBNK)
- uses Generic Header
- magic ID is #SBNK (0x?)
- contains only 1 section
#1 Section - Data (DATA)
Offset | Length | Name | Description |
---|---|---|---|
0x0 | 0x4 | Magic ID | #DATA (0x?) |
0x4 | 0x4 | Section Size | Size of this section, including the header. |
0x8 | 0x32 | Unknown | |
0x28 | 0x4 | Number of Samples | |
0x2C | 0x1 | Unknown Type | |
DATA | |||
0x2D | 0x3 | Data Offset | RELATIVE to the start of the file. |
DATA | Sample Data | ||
0x0 | 0x2 | Sample Number | |
0x2 | 0x? | Unknown Flag |
Custom File Formats
Package File (PAK)
- found in Digimon Games
- groups files (ie Palette/Graphic/Animation) either in separate PAK files for each type, or in a single file with each file in an ordered manner
- no filenames so referencing should be done by the index in the offset table (see below)
- each file is compressed
Section Offsets
Offset | Length | Name | Description |
---|---|---|---|
0x0 | 0x4 | Number of Files | |
DATA | |||
0x4 | File Start Offset | ||
0x4 | File Size |
PAK5 Files
- known file formats with a custom 5 byte header added before the start of the normal file format
- found in PAK files and files in the normal file system of Digimon Games (named using a combination of a hex number and letter representing what format the file contains)
Compression Formats
Files may be stored using a variety of different compression formats including LZ77, Huffman and RLUncomp. Because there's a real lack of good easy to understand documentation on it (and trust me I know in order to be able to write this), I'm going to write my interpretations here.
Generally the filenames of files will indicate whether or not they are compressed, but otherwise you have to guess it on your own. For starters if while looking at a file in a Hex Editor, the first 5 Bytes are then followed by a Magic ID, then it is almost guaranteed to be a compressed known file format, and this is where documentation helps!
So first off we have a look at the first 4 Bytes or rather first 32 Bits, keeping in mind that the Nintendo DS works from right to left (Least Significant to Most Significant), which is Little Endian if you aren't very familiar with stuff like that.
Compression Header (Same for all types)
Offset (Bits) | Length (Bits) | Name | Description |
---|---|---|---|
0x0 | 0x4 | Reserved / Compression Size | Should always be (0x0) unless Compression Type is Huffman, in which case this specifies the Compression Size. |
0x4 | 0x4 | Compression Type | Specifies what type of compression is used. 1 = LZ77 2 = Huffman 3 = RLUncomp |
0x8 | 0x24 | Decompressed File Size | The size the file will be after being decompressed. |
After the header comes the compressed data, and depending on what Compression Type it is will affect how it is stored.
#1 Type - LZ77 Compression
Offset (Bits) | Length (Bits) | Name | Description |
---|---|---|---|
0x0 | 0x8 | Flag | Each Bit tells if the corresponding Block of Data is compressed or uncompressed. 0 = Uncompressed 1 = Compressed |
0x8 | Uncompressed Data | No decompression needed, single byte can be copied to the end of the place where the decompressed file is being stored. | |
0x16 | Compressed Reference | Format is (MMMMNNNNLLLLLLLL) M4 = Most significant Bits N4 = Number of Bytes to be copied L8 = Least significant Bits Copy Offset = (L8 | M4 << 8) +1 |
So when the decompressor finds a compressed block, it copies N+3 Bytes from the current position in the decompressed file minus the Copy Offset.
example:
data = getBytes ( Data:decompressedData , Offset:currentOffset-copyOffset , Length:copyCount );
An important thing to note is that if the Copy Count greater than the distance between the Copy Offset and the Current Offset in the decompressed file, the data is repeatedly copied until it matches the Copy Count. This will often occur when the compressed data has the same value.
#2 Type - Huffman Compression
(No notes were written)
#3 Type - RL Compression
Offset (Bits) | Length (Bits) | Name | Description |
---|---|---|---|
0x0 | 0x7 | Expanded Length / Copy Count | If the Flag is 0 this specifies how many bytes after the flag are copied to where the decompressed file is being stored. Otherwise it specifies how many times the next byte is copied to where the decompressed file is being stored. |
0x7 | 0x1 | Flag | 0 = Uncompressed (Add 1 to the Copy Count) 1 = Compressed (Add 3 to the Expanded Length) |
This is much simpler than the other two formats as you are only copying bytes from the source file to the decompressed file.
*1:The server was dead when I found the site... oh well