Nitro Files
Contents
Nitro Studio Files Specification
Current status
This specification is far from complete, and it may contain errors, since it is the result of reverse-engineering.
- 11 August 2007 - First published by [email protected]
- 16 April 2019 - Published on the apicula github wiki
- 19 April 2019 - Added information from LowLines' ConsoleTool doc
0. Introduction |
Most 3D models found in Nintendo DS games use the following set of Nitro files:
- `NSBMD` (Nitro Model), which stores polygon models.
- `NSBTX` (Nitro Texture), which stores texture image and palette data.
- `NSBCA` (Nitro Character Animation), which stores skeletal animation data.
- `NSBTP` (Nitro Texture Pattern anim), which stores texture-swap animations.
- `NSBTA` (Nitro Texture Animation), which stores UV-change animations.
- `NSBMA` (Nitro Material Animation), which stores material-swap animations.
- `NSBVA` (Unknown)
0.1 Terminology
File format is explained in C-style struct declaration. The following types of variables are used:
s8 1 byte // signed char
s16 2 bytes // signed short
s32 4 bytes // signed long
u8 1 byte // unsigned char
u16 2 bytes // unsigned short
u32 4 bytes // unsigned long
text n bytes // ASCII char string
;// The general format for every data field outlined here is:
-------- ----- ----- ;// ----------------------------------
Offset Size Type ;// Description
-------- ----- ----- ;// ----------------------------------
0x00 4 u32 ;// Example
0.2 Nitro Standard File Header
Many files (besides sound-related) found in DS ROMs share this header structure:
/*
** This is the standard DS Nitro header format: any nitro file starts with this.
*/
typedef struct Nitro_Header
{
0x00 4 text;// File identifier: can be 'SDAT', 'BMD0', 'BTX0', 'BCA0', etc...
0x04 4 u32 ;// Magic stamp: is either 0x0001FEFF or 0x0002FEFF
0x08 4 u32 ;// Size of this file (including this struct)
0x0C 2 u16 ;// Size of this structure (always 16)
0x0E 2 u16 ;// Amount of Blocks
---- Offsets (repeats * Amount of Blocks)
0x00 4 u32 ;// Block offset #1
0x04 4 u32 ;// Block offset #2
etc
};
0.3 General Data Sub-header
In addition to the Standard File Header, the following format of "sub-header" is encountered often in NSB__ files:
/*
** This is the format of the general-purpose headers that are used in many places within nitro files.
*/
typedef struct Header
{
0x00 1 u8 ;// dummy 0
0x01 1 u8 ;// Amount of objects
0x02 2 u16 ;// Size of this Header
---- Unknown Section
---- Sub-Header
0x00 2 u16 ;// Size of this Sub-Header, always = 8
0x02 2 u16 ;// Size of this Unknown Section
0x04 4 u32 ;// Constant = 0x0000017f
---- Unknown Data (repeats * Amount of objects)
0x08 4 u32 ;// Unknown
0x0C 4 u32 ;// ...
etc
---- Data Info Section
---- Sub-Header
0x00 2 u16 ;// Size of each Data entry, usually = 4
0x02 2 u16 ;// Size of this Data Info Section
---- Data (repeats * Amount of objects)
0x04 n ??? ;// The Data stored here is used for several different things, explained when used.
0x04+n n ??? ;// ...
etc
---- Name Section (repeats * Amount of objects)
0x00 16 text;// Name of Model
0x10 16 text;// ...
etc
};
1. NSBMD Format |
It has one or two blocks - 'MDL0' and 'TEX0'.
'MDL0' block is usually found at offset 0x14 (depending on how many block_offsets there are before it)
The 'MDL0' block can potentially be followed by a 'TEX0' block, or otherwise the 'TEX0' block is defined in an external NSBTX file.
1.1 'MDL0' Block
NSBMD
------
struct Nitro_Header;// File identifier is 'BMD0' (Basic Model Data)
typedef struct Block_MDL0
{
0x00 4 u32 ;// Block identifier: 'MDL0' (Model Block)
0x04 4 u32 ;// Block size
struct Header;// Model Header: one Header object for each model
{// The 'Data' for this Header is like so:
0x00 4 u32 ;// The offset of Model_1, relative to the start of Block_MDL0
}
---- Model_1 (All offsets are relative to this Model_1 section)
0x00 4 u32 ;// Size of Model_1 (including these 4 bytes)
0x04 4 u32 ;// Offset of Additional Model Data
0x08 4 u32 ;// Offset of Texture & Palette Offset
0x0C 4 u32 ;// Offset of Display List Start
0x10 4 u32 ;// Offset of Display List End
0x14 1 u8 ;// Unknown
0x15 1 u8 ;// Unknown
0x16 1 u8 ;// Unknown
0x17 1 u8 ;// Amount of Objects
0x18 1 u8 ;// Amount of Materials
0x19 1 u8 ;// Amount of Polygons
0x1A 2 u16 ;// Unknown
0x1C 4 u32 ;// Model scale?
0x20 4 u32 ;// Bound scale?
0x24 2 u8 ;// Amount of Vertices
0x26 2 u8 ;// Amount of Surfaces
0x28 2 u8 ;// Amount of Triangles
0x2A 2 u8 ;// Amount of Quads
0x2C 2 s16 ;// Bounding box X (signed fixed point 1.3.12)
0x2E 2 s16 ;// Bounding box Y (signed fixed point 1.3.12)
0x30 2 s16 ;// Bounding box Z (signed fixed point 1.3.12)
0x32 2 s16 ;// Bounding box Width (signed fixed point 1.3.12)
0x34 2 s16 ;// Bounding box Height (signed fixed point 1.3.12)
0x36 2 s16 ;// Bounding box Depth (signed fixed point 1.3.12)
0x38 4 u32 ;// Runtime use data
0x3C 4 u32 ;// Runtime use data
struct Header;// Object Header: one Header object for each Polygonal Object
{// The 'Data' for this Header is like so:
0x00 4 u32 ;// The offset of Object Definition, relative to the start of this Object Header
}
---- Object Definition (repeats * Amount of objects)
In each definition:
0x00 1 u8 ;// Transform Flag byte
0x01 1 u8 ;// Unknown
0x02 1 u8 ;// Unknown
0x03 1 u8 ;// Unknown
// The Transform Flag byte is set up like so:
// bits: 7.......0
// 0b NNNN PSRT
//
// T: if set, Translation = Identity (No Translation)
// if = 0, then 12 bytes follow:
// 0x04 4 s32 ;// Translation X (signed fixed point 1.3.12)
// 0x08 4 s32 ;// Translation Y (signed fixed point 1.3.12)
// 0x0C 4 s32 ;// Translation Z (signed fixed point 1.3.12)
// R: if set, Rotation = Zero (No Rotation)
// if = 0, then depends on the 'P' bit.
// S: if set, Scale = Identity (No Scale)
// if = 0, then 12 bytes follow:
// 0x04 4 s32 ;// Scale X (signed fixed point 1.3.12)
// 0x08 4 s32 ;// Scale Y (signed fixed point 1.3.12)
// 0x0C 4 s32 ;// Scale Z (signed fixed point 1.3.12)
// P: if = 0 and R = 0, then 16 bytes follow:
// 0x00 4 s32 ;// Rotation A
// 0x04 4 s32 ;// Rotation B
// 0x08 4 s32 ;// Rotation C
// 0x0C 4 s32 ;// Rotation D
// if set, Pivot exists- so 4 bytes follow:
// 0x04 2 s16 ;// value A (signed fixed point 1.3.12)
// 0x06 2 s16 ;// value B (signed fixed point 1.3.12)
// NNNN = Pivot matrix type (0..8)
// 0: | 1 0 0| 1: | 0 1 0| 2: | 0 0 1|
// | 0 A B| | A 0 B| | A B 0|
// | 0 B -A| | B 0 -A| | B -A 0|
//
// 3: | 0 A B| 4: | A 0 B| 5: | A B 0|
// | 1 0 0| | 0 1 0| | 0 0 1|
// | 0 B -A| | B 0 -A| | B -A 0|
//
// 6: | 0 A B| 7: | A 0 B| 8: | A B 0|
// | 0 B -A| | B 0 -A| | B -A 0|
// | 1 0 0| | 0 1 0| | 0 0 1|
---- Bone/Skeleton Section
0x00 ? definitions;
// Each definition consists of 1 Command Byte + Parameters. Each Parameter is 1 byte.
//
// Command Params Description
// 0x06 3 params: Object ID, Parent ID, dummy 0
// 0x26 4 params: Object ID, Parent ID, dummy 0, Stack ID
// 0x46 4 params: Object ID, Parent ID, dummy 0, Stack ID
// 0x66 5 params: Object ID, Parent ID, dummy 0, Stack ID, Restore ID
//
// 0x00 0 NOP (empty command)
// 0x01 0 End of Bone/Skeleton Section
// 0x02 2 params: Node ID, Visibility
// 0x03 1 Set Polygon Stack ID?
// 0x04 3 params: Material ID, 0x5, Polygon ID
// 0x05 1 ??
// 0x06 3 params: Object ID, Parent ID, Dummy 0
// 0x07 1 ??
// 0x08 1 ??
// 0x09 8 ??
//
// 0x0B 0 BEGIN (indicate begin of Polygon/Material pairing)
// 0x2B 0 END (indicate end of Polygon/Material pairing)
//
// These are Material/Polygon pairing commands, 4 bytes.
// The lower nibble of 2nd Paramter must be 5.
// 0x04 3 Material ID, 05, Polygon ID
// 0x24 3 ...
// 0x44 3 ...
---- Texture & Palette Offset
0x00 2 u16 ;// Offset of Texture Section (relative to Texture & Palette Offset)
0x02 2 u16 ;// Offset of Palette Section (relative to Texture & Palette Offset)
---- Material Section
struct Header;// Material Header: one Header object for each material
{// The 'Data' for this Header is like so:
0x00 4 u32 ;// The offset of Material Definition, relative to the start of this Material Section
}
---- Texture Section
struct Header;// Texture Header: one Header object for each texture
{// The u32 'Data' for this Header is like so:
0x00 2 u16 ;// Offset of Matching Data (relative to Texture & Palette Offset)
0x02 2 u16 ;// Amount of associated Materials (a texture can be in more than one material)
}
---- Palette Section
struct Header;// Palette Header: one Header object for each palette
{// The u32 'Data' for this Header is like so:
0x00 2 u16 ;// Offset of Matching Data (relative to Texture & Palette Offset)
0x02 2 u16 ;// Amount of associated Materials (a palette can be in more than one material)
}
---- Material Definition (repeats * Amount of Materials)
;// Usually 44 (or 48?) bytes for each material
0x00 2 u16 ;// Zero
0x02 2 u16 ;// Size of this material
0x04 28 ;// Unknown
0x20 2 u16 ;// Width
0x22 2 u16 ;// Height
0x24 8 ;// Unknown
---- Polygon Section
struct Header;// Polygon Header: one Header object for each material
{// The 'Data' for this Header is like so:
0x00 4 u32 ;// The offset of Polygon Definition, relative to the start of this Polygon Section
}
---- Polygon Definition (repeats * Amount of Polygons)
0x00 4 u32 ;//
0x04 4 u32 ;//
0x08 4 u32 ;// Offset of Display List, relative to Polygon Definition, see below
0x0c 4 u32 ;// Size of Display List
0x10 4 u32 ;//
0x14 4 u32 ;//
0x18 4 u32 ;// Offset of Display List, relative to Polygon Definition, see below
0x1c 4 u32 ;// Size of Display List
...
---- Display List
// The Display List is actually packed geometry command.
// See the DStek specification for more information:
// http://www.akkit.org/info/gbatek.htm#ds3dvideo
---- Model_2
...
};
2. NSBTX Format |
The NSBTX file format stores texture image and palette information.
2.1 'TEX0' Block
The 'TEX0' Block can be found in certain NSBMD files, not just in NSBTX files.
NSBTX
------
struct Nitro_Header;// File identifier is 'BTX0' (Basic Texture)
typedef struct Block_TEX0
{
0x00 4 u32 ;// Block identifier: 'TEX0' (Texture Block)
0x04 4 u32 ;// Block size
---- Texture Header
0x08 4 u32 ;// Padding (= 0)
0x0C 2 u16 ;// Texture Data Size (bitshift << 3)
0x0E 2 u16 ;// Texture Info Offset (0x3C)
0x10 4 u32 ;// Padding (= 0)
0x14 4 u32 ;// Texture Data Offset
0x18 4 u32 ;// Padding (= 0)
0x1C 2 u16 ;// Compressed Texture Data Size (bitshift << 3)
0x1E 2 u16 ;// Compressed Texture Info Offset (0x3C)
0x20 4 u32 ;// Padding (= 0)
0x24 4 u32 ;// Compressed Texture Data Offset
0x28 4 u32 ;// Compressed Texture Info Data Offset
0x2C 4 u32 ;// Padding (= 0)
0x30 4 u32 ;// Palette Data Size (bitshift << 3)
0x34 4 u32 ;// Palette Info Offset
0x38 4 u32 ;// Palette Data Offset
---- Texture Info Section
struct Header;// Texture Header: one Header object for each texture
{// The u32 'Data' for this Header is like so:
0x00 2 u16 ;// (bitshift << 3) Texture Offset, relative to the start of Texture Data
0x02 2 u16 ;// Parameters
// The format is:
// bit: 15..............0
// 0 b --CFFFHHHWWW----
// where:
// C = Palette ID
// F = Format (0-7)
// H = Height (8 << Height)
// W = Width (8 << Width)
//
// To Calculate the Data Size of a Texture:
// Bit Depth = Format:<0, 8, 2, 4, 8, 2, 8, 16>
// Width * Height * BitDepth / 8
0x04 1 u8 ;// Width (should match W << 3)
0x05 1 u8 ;// Unknown (is 0x00 or 0x80)
0x06 1 u8 ;// Height? (can be 0, 1, 2, 4, 8)
0x07 1 u8 ;// Unknown (is 0x80)
}
---- Palette Info Section
struct Header;// Palette Header: one Header object for each palette
{// The u32 'Data' for this Header is like so:
0x00 2 u16 ;// (bitshift << 3) Palette Offset, relative to the start of Palette Data
0x00 2 u16 ;// Unknown (is 0 or 1)
}
---- Texture Data Section
---- Compressed Texture Data Section
---- Compressed Texture Info Data Section
---- Palette Data Section
};
3. NSBCA Format |
The NSBCA file format stores character skeletal animation data.
3.1 'JNT0' Block
The 'JNT0' Block can be found in NSBCA files, it stores bone/joint animation data.
NSBCA
------
struct Nitro_Header;// File identifier is 'BCA0' (Basic Character Animation)
typedef struct Block_JNT0
{
0x00 4 u32 ;// Block identifier: 'JNT0' (Joint Block)
0x04 4 u32 ;// Block size
struct Header;// Joint Header: one Header object for each joint
{// The 'Data' for this Header is like so:
0x00 4 u32 ;// The offset of Joint_1, relative to the start of Block_JNT0
}
---- Joint Section (repeats * Amount of Objects)
0x00 4 u32 ;// Magic Stamp 'J.AC' (Joint Animation Content ?)
0x04 2 u16 ;// Amount of Frames
0x06 2 u16 ;// Amount of Objects being animated. Should equal to the number of Objects in a model.
0x08 4 u32 ;// Unknown
0x0C 4 u32 ;// Offset to Offset1 chunk. Relative to start of this block.
0x10 4 u32 ;// Offset to Offset2 chunk. Relative to start of this block.
0x14 4 u32 ;// Object Info Offset (repeats * Amount of Objects), relative to start of this Joint Section.
---- Object Info - Repeats * Number of Objects
0x00 2 u16 ;// Flag - Indicates what sort of Transformations are applied.
// The format is:
// bit: 15..............0
// 0 b --zyx-Sr-RZYX-T-
// T is Translation
// R is Rotation
// S is Scale
// If these bits are cleared, transformation data follows.
// X, Y, Z, r, x, y, z are flags that identify how the data is stored.
0x02 1 u32 ;// Unknown
0x03 1 u32 ;// ID Number
---- Transformation Info (Translation XYZ, Rotation, Scale XYZ) when set
0x00 4 u32 ;// Actual value.
---- Transformation Info (Translation XYZ, Rotation, Scale XYZ) when cleared
0x00 2 u16 ;// Unknown - typically 0.
0x02 2 u16 ;// Unknown
0x04 4 u32 ;// Offset to data. Relative to end Object Info Header (Object Info Offset + 4).
---- Offset1 Chunk - Repeats until Offset2
0x00 2 u16 ;// I've seen 36, 32 & 0.
0x02 2 s16 ;// Unknown
0x04 2 s16 ;// Unknown
---- Offset2 Chunk - Repeats until end of file
// All transformation offsets point somewhere in this section.
// It's clearly broken up into parts (Translation, Rotation & Scale) however I'm not totally sure how data is store in here yet.
};
4. NSBTP Format |
The NSBTP file format stores texture pattern animation data.
4.1 'PAT0' Block
The 'PAT0' Block can be found in NSBTP files, it stores pattern animation data.
NSBTP
------
struct Nitro_Header;// File identifier is 'BTP0' (Basic Texture Pattern animation)
typedef struct Block_PAT0
{
0x00 4 u32 ;// Block identifier: 'PAT0' (Pattern Block)
0x04 4 u32 ;// Block size
// Unknown beyond this point
};
5. NSBTA Format |
The NSBTA file format stores texture animation data.
5.1 'SRT0' Block
The 'SRT0' Block can be found in NSBTA files, texture animation data.
NSBTA
------
struct Nitro_Header;// File identifier is 'BTA0' (Basic Texture Animation)
typedef struct Block_SRT0
{
0x00 4 u32 ;// Block identifier: 'SRT0' (??? Block)
0x04 4 u32 ;// Block size
// Unknown beyond this point
};
6. NSBMA Format |
The NSBMA file format stores material animation data.
6.1 'MAT0' Block
The 'MAT0' Block can be found in NSBMA files, it stores material animation data.
NSBMA
------
struct Nitro_Header;// File identifier is 'BMA0' (Basic Material Animation)
typedef struct Block_MAT0
{
0x00 4 u32 ;// Block identifier: 'MAT0' (Material Block)
0x04 4 u32 ;// Block size
// Unknown beyond this point
};
7. NSBVA Format |
The NSBVA file format stores general-purpose value animation data perhaps ..?
7.1 'VIS0' Block
The 'VIS0' Block can be found in NSBVA files, it stores value animation data perhaps ..?
NSBVA
------
struct Nitro_Header;// File identifier is 'BVA0' (Basic ??? Animation)
typedef struct Block_VIS0
{
0x00 4 u32 ;// Block identifier: 'VIS0' (??? Block)
0x04 4 u32 ;// Block size
// Unknown beyond this point
};