MSBT (File Format)
MSBT (MessageStudio Binary Text) is a text file format used in many Nintendo games such as Super Mario Galaxy 2, Mario Kart 8 and Super Mario Odyssey, as well as in some mobile games. Though it has been around for many years, the content has changed and new sections have replace older ones.
File Format
Header
The file starts with the following header:
Offset | Type | Description |
---|---|---|
0x00 | Char[8] | File magic. Always MsgStdBn in ASCII. |
0x08 | UInt16 | Byte-order-mark. FE FF for big endian, FF FE for little endian. |
0x0A | UInt16 | Unknown. |
0x0C | Byte | String encoding. UTF8 = 0, UTF16 = 1. |
0x0D | Byte | Possibly a version number. Games on Wii, Nintendo 3DS and Wii U as well as Mario Kart Tour use 3, games on Nintendo Switch and Super Mario Run use 4. |
0x0E | UInt16 | Number of sections. |
0x10 | UInt16 | Unknown. |
0x12 | UInt32 | File size in bytes. |
0x16 | Byte[10] | Unknown. Always 0. |
LBL1
The LBL1 section stores messages using key strings (labels). Each message has a unique key name which is used to access an message. The section has the following layout:
Offset | Type | Description |
---|---|---|
0x00 | Char[4] | Section magic. Always LBL1 in ASCII. |
0x04 | UInt32 | Section size (starting from 0x10). |
0x08 | Byte[8] | Unknown. Always 0. |
0x10 | Int32 | Number of entries. |
Label Entry
After the header comes the entries. Each entry has the following structure:
Offset | Type | Description |
---|---|---|
0x00 | Int32 | Number of labels. |
0x04 | UInt32 | Offset to an array of labels, relative to 0x10 in the LBL1 header. |
Label
Each label has the following structure:
Offset | Type | Description |
---|---|---|
0x00 | Byte | Key string size (K). |
0x01 | String | Key string used to access this message. The string has the length K and is not null-terminated. The string is always stored in ASCII. |
0x01 + K | Int32 | Message string, represented as an index into the TXT2 strings. |
NLI1
The NLI1 section stores messages using node IDs. Each message has a unique ID which is used by the game to get a specific message. The section has the following layout:
Offset | Type | Description |
---|---|---|
0x00 | Char[4] | Section magic. Always NLI1 in ASCII. |
0x04 | UInt32 | Section size (starting from 0x10). |
0x08 | Byte[8] | Unknown. Always 0. |
0x10 | Int32 | Number of entries. |
Node
After the header comes the nodes. Each entry has the following structure:
Offset | Type | Description |
---|---|---|
0x00 | UInt32 | Node ID. |
0x04 | Int32 | Node string, represented as an index into the TXT2 strings. |
ATR1
The ATR1 section stores attribute data. It has the following structure:
Offset | Type | Description |
---|---|---|
0x00 | Char[4] | Section magic. Always ATR1 in ASCII. |
0x04 | UInt32 | Section size (starting from 0x10). |
0x08 | Byte[8] | Unknown. Always 0. |
0x10 | Int32 | Number of entries. |
0x14 | UInt32 | Entry size in bytes. The entry structure depends on the game. |
ATR1 ARMS Entry
In ARMS each entry has the following structure:
Offset | Type | Description |
---|---|---|
0x00 | Byte | Unknown |
ATR1 SMT Entry
In Super Mario Tour each entry has the following structure:
Offset | Type | Description |
---|---|---|
0x00 | Byte | Unknown |
ATR1 SMG2 Entry
In Super Mario Galaxy 2 each entry has the following structure:
Offset | Type | Description |
---|---|---|
0x00 | Byte | Unknown. |
0x01 | Byte | Unknown. |
0x02 | Byte | Dialog type. 0 = Normal, 1 = Shout, 2 = Start when close, 3 = Start when anywhere |
0x03 | Byte | Unknown. |
0x04 | UInt16 | Unknown. |
0x06 | UInt16 | Unknown. Usually 0xFFFF |
0x08 | UInt32 | String offset, relative to the 0x10 in the ATR1 header. Points to a null-terminated string. |
ATR1 TLOZLA Entry
In The Legend of Zelda: Link's Awakening each entry has the following structure:
Offset | Type | Description |
---|---|---|
0x00 | UInt16 | Unknown |
TXT2
The TXT2 section contains text strings. It starts with the following structure:
Offset | Type | Description |
---|---|---|
0x00 | Char[4] | Section magic. Always TXT2 in ASCII. |
0x04 | UInt32 | Section size (starting from 0x10). |
0x08 | Byte[8] | Unknown. Always 0. |
0x10 | Int32 | Number of entries. |
After the TXT2 header, there are 32-bit unsigned offsets, containing the offsets to the strings.
Control Tag
The strings can also contain tags to modify text and/or rendering consisting of this structure:
Offset | Type | Description |
---|---|---|
0x00 | UInt16 | Tag Group magic (0x0E00), 0x0F00 for ending the effects of a previous tag (in newer software). |
0x02 | UInt16 | Tag Type index (0 is System while others are application-specific. If the game use an MSBP file, it's probably possible to find their custom tag structures). |
0x04 | UInt16 | Tag Group index. |
0x06 | UInt16 | Tag Parameters size. |
If the size of the tag's parameters is greater than 0, parameters are defined for the given tag type and tag group.
System Tag
The System tag may be modified in games but usually follows this structure:
Tag Type | Parameters | Description |
---|---|---|
0x00 | UInt16 + String | Applies Ruby syntaxing to text. |
0x01 | UInt16 | Changes the face of font. |
0x02 | UInt16 | Changes the size of text. The value can either be usually the text size or size index (Small, Medium, Large). |
0x03 | UByte[4] / UInt16 | Applies color to text. The value can either be 4 unsigned bytes for RGBA channels or usually the color index depending on the application. |
0x04 | None | Breaks the current text into another page, and usually halts text rendering, requiring user input to advance or terminate the text. |
ATO1
The ATO1 section stores attribute offsets.
Offset | Type | Description |
---|---|---|
0x00 | Char[5] | Section magic. Always ATO1 in ASCII. |
0x04 | UInt32 | Section size (starting from 0x10). |
0x08 | Byte[8] | Unknown. Always 0. |
TSY1
The TSY1 section stores text style information.
Offset | Type | Description |
---|---|---|
0x00 | Char[5] | Section magic. Always TSY1 in ASCII. |
0x04 | UInt32 | Section size (starting from 0x10). |
0x08 | Byte[8] | Unknown. Always 0. |
Tools
The following tools can handle MSBT files:
- MSBT Editor Reloaded, by IcySon55