BMG files (Binary Message) are the JSystem file format for storing message data. The format is the same as it appears in GameCube and Wii games using the JSystem library, but with little endian fields. The file header is as follows:
| Offset | Type | Meaning |
|---|---|---|
| 0x00 | u32 | File signature. "MESG" for BMG files. |
| 0x04 | u32 | File type. "bmg1" for BMG files. |
| 0x08 | u32 | File size |
| 0x0C | u32 | Number of data blocks. |
| 0x10 | u8 | Character set. Can be narrow character (1), wide character (2), Shift-JIS (3), or UTF-8 (4). |
| 0x11 | u8[0xF] | Unused. |
The BMG file is composed of multiple data blocks. These are INF1, MID1, DAT1, STR1, FLW1, and FLI1. The data blocks have a common header structure:
| Offset | Type | Meaning |
|---|---|---|
| 0x00 | u32 | Block type |
| 0x04 | u32 | Block size, including this header. |
Each block's size is rounded up to a multiple of 32 bytes, and the size reported in the block header reflects this.
INF1 Block#
The INF1 (info) block stores the BMG message table. Each message is represented in the table with a JMSMesgEntry structure, whose structure may vary depending on the file. In general, the first 4 bytes of the structure are an offset into the DAT1 block. The other data fields are game-dependent (Mario Kart does not use any extra data).
| Offset | Type | Meaning |
|---|---|---|
| 0x00 | u16 | Number of entries |
| 0x02 | u16 | Size of the JMSMesgEntry struct |
| 0x04 | u16 | Group ID |
| 0x06 | u8 | Color ID |
| 0x07 | u8 | |
| 0x08 | JMSMesgEntry[...] | Offsets to strings. This is a list of offsets into the DAT1 block. |
DAT1 Block#
The DAT1 block stores message data. This block's data takes the form of a string pool, with data referenced by the INF1 block. In files produced by the Message Editor, the block begins with an empty string, with each successive string in the file concatenated (with null terminators).
Strings may contain tags to be processed by the library. Tags are started with a character code 1A (ASCII substitution character) in hex. This is followed by the following structure:
| Offset | Type | Meaning |
|---|---|---|
| 0x00 | u8 | Tag length (including the substitution character) |
| 0x01 | u8 | Tag group |
| 0x02 | u16 | Tag ID |
| 0x04 | u8[...] | Tag data |
When UTF-16 character encoding is used, the total length of the tag is padded to a multiple of 2, and the tag length byte reflects this.
The format defines a system tag group with ID FF in hex. In this system tag group, the following tags are defined:
| Tag ID | Meaning | Format |
|---|---|---|
| 0 | Color | u8 color; |
| 1 | Size | u16 size; |
| 2 | Ruby Text | u8 baseLength; u8 rubyText[0]; |
| 3 | Font | u8 font; |
| 4 | Word | |
| 5 | Message | |
| 6 | Jump | |
| 7 | Ruby Text Extended | u8 info; u8 baseLength; u8 rubyText[0]; |
The game is free to use other tag groups for their own purposes. Mario Kart DS defines some.
MID1 Block#
This block is optional, and maps each message index to an ID. Message IDs need not be in order or consecutive. The block format is as follows:
| Offset | Type | Meaning |
|---|---|---|
| 0x00 | u16 | Number of entries. |
| 0x02 | u8 | Info. This is 0x00 if the message IDs are out of order, or 0x10 if they are in order. |
| 0x03 | u8 | Format. |
| 0x04 | u8 | Reserved. |
The format identifies the breakdown of bits per entry. These are broken down as:
| Format | Bits |
|---|---|
| 0 | 32 low bits, 0 high bits |
| 1 | 24 low bits, 8 high bits |
| 2 | 16 low bits, 16 high bits |
| 3 | 8 low bits, 24 high bits |
| 4 | 0 low bits, 32 high bits |
The high ID bits become the low bits in the MID1 block. The message editor chooses the format with the smallest required number of bits for the high ID.
Following the header is an array of ID entries. The entry at index i defines the ID of entry i in the INF1 block. Each entry is 32 bits wide.