Nitro Files

From The VG Resource Wiki
Jump to: navigation, search

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
};