BYML
BYML is a simplified, binary form of YAML.
Only the version 2+ format is documented in this article.
Structure
The file is broken up into a node structure, with possible interlinking between the nodes. Each node has a one byte format identifier. The File begins with a header which points to three special nodes; the hash key table; the string table node and the root node.
Header
Offset | Size | Description |
---|---|---|
0x00 | 2 | “BY” (big endian) or “YB” (little endian). |
0x02 | 2 | Version 2 in Breath of the Wild, Versions 4 to 7 in Tears of the Kingdom. 1 and 3 are also valid version numbers. |
0x04 | 4 | Offset to the hash key table, relative to start (usually 0x010). May be 0 if no hash nodes are used. Must be a string value node (0xc2). |
0x08 | 4 | Offset to the string table, relative to start. May be 0 if no strings are used. Must be a string value node (0xc2). |
0x0c | 4 | Offset to the root node, relative to start. May be 0 if the document is totally empty. Must be either an array node (0xc0) or one of the hash nodes (0x20, 0x21 or 0xc1). |
Nodes
Every node format has a unique one byte identifier as follows. Some nodes are considered value nodes as indicated below. The container nodes have a longer encoding in the file, which must be four byte aligned. The order of encoding full nodes within the file does not seem to matter.
Identifier | Type | Description | Version |
---|---|---|---|
0x20 | Container | Plain hash. Node is a mapping from 32-bit hashes to other nodes. | 7+ |
0x21 | Container | Value hash. Node is a mapping from 32-bit hashes to other nodes and a second 4 byte value. | 7+ |
0xA0 | Value (Index) | String. Value is an index into the string table. | 2+ |
0xA1 | Value (Special) | Binary data. | 4+ |
0xA2 | Value (Special) | File data. Node contains the binary data of another file. | 5+ |
0xC0 | Container | Array. Node is an array of nodes, typically, though not necessarily, all of the same format. | 2+ |
0xC1 | Container | String hash. Node is a mapping from strings in the hash key table to other nodes. | 2+ |
0xC2 | Container (Special) | String table. Special purpose node type only seen in the hash key table and the string table. | 2+ |
0xD0 | Value | Bool. Node is 1 or 0 representing true or false respectively. | 2+ |
0xD1 | Value | Int. Node is a signed 32 bit integer value. | 2+ |
0xD2 | Value | Float. Node is a binary32 floating-point number. | 2+ |
0xD3 | Value | UInt. Node is an unsigned 32 bit integer value. The game uses this for some CRC32 hashes and for masks. | 2+ |
0xD4 | Value (Special) | Int64. Node is a 64 bit integer value. | 3+ |
0xD5 | Value (Special) | UInt64. Node is an unsigned 64 bit integer value. | 3+ |
0xD6 | Value (Special) | Double. Node is a binary64 floating-point number. | 3+ |
0xFF | Value | Null. Value is always 0. | 3+ |
Value Nodes
Value nodes can only be encoded as children of container nodes. Each value node has a direct four byte encoding.
For string nodes, this encoding is simply a four byte index into the string table respectively.
For special value nodes, the value is an offset relative to the start of the file.
0x20 - Hash Node
Hash / dictionary nodes are used to encode name value collections. Entries must sorted by their hash value.
Offset | Size | Description |
---|---|---|
0x00 | 1 | 0x20 node type. |
0x01 | 3 | Number of entries in dictionary. |
0x04 | 8*N | Dictionary entries. |
0x04+8*N | 1*N | Array of N types, on for each entry in the dictionary. This is padded to 4 bytes. |
Each entry in the dictionary has the following structure.
Offset | Size | Description |
---|---|---|
0x00 | 4 | Hash. A 32-bit hash of the key. |
0x04 | 4 | Value. For regular value nodes, this is the 4 byte node value. For other nodes, this is a 4 byte offset to the node relative to the start of the file. |
0x21 - Value Hash Node
This type is the similar to the hash node with the addition of a 4-byte value in each dictionary entry.
Offset | Size | Description |
---|---|---|
0x00 | 4 | Value. For regular value nodes, this is the 4 byte node value. For other nodes, this is a 4 byte offset to the node relative to the start of the file. |
0x04 | 4 | Hash. A 32-bit hash of the key. |
0x08 | 4 | Unknown. Always 0 in Tears of the Kingdom. |
0xA1 - Binary Data Node
Offset | Size | Description |
---|---|---|
0x00 | 4 | Data length |
0x04 | variable | Data |
0xA2 - File Node
Offset | Size | Description |
---|---|---|
0x00 | 4 | File length |
0x04 | 4 | Unknown. Always 0x1000. |
0x08 | variable | File data |
0xC0 - Array Node
Offset | Size | Description |
---|---|---|
0x00 | 1 | 0xC0 node type. |
0x01 | 3 | Number of entries in array. |
0x04 | N | Array of N node types; the type of each element in the array. |
0x04 + N’ | 4*N | Array of N node values. For regular value nodes, this is a 4 byte node value. For other nodes, this is a 4 byte offset to the node relative to the start of the file. |
N’ is N rounded up to the nearest multiple of 4.
0xC1 - String Hash Node
Hash / dictionary nodes are used to encode name value collections. Entries must be lexicographically sorted[1].
Offset | Size | Description |
---|---|---|
0x00 | 1 | 0xC1 node type. |
0x01 | 3 | Number of entries in dictionary. |
What then follows is a variable length array of dictionary entries. Each entry has the following structure.
Offset | Size | Description |
---|---|---|
0x00 | 3 | Name. Value is an index in the hash key table. |
0x03 | 1 | The node type. |
0x04 | 4 | Value. For regular value nodes, this is the 4 byte node value. For other nodes, this is a 4 byte offset to the node relative to the start of the file. |
0xC2 - String Table Node
Offset | Size | Description |
---|---|---|
0x00 | 1 | 0xC2 node type. |
0x01 | 3 | Number of entries in the string table. |
0x04 | Y=4*(N+1) | Array of N+1 offsets to each string relative to the start of the node. The last entry is an offset to the end of the last string. |
0x04+Y’ | variable | Array of N null-terminated strings stored in alphabetical order. |
Y’ is Y rounded up to the nearest multiple of 4.
Usage in Nintendo games
Game | Endianness | Version | Notes |
---|---|---|---|
Breath of the Wild (Wii U) | Big endian | 2 | Uses SMO's library (in al::) |
Breath of the Wild (Switch) | Little endian | 2 | Uses SMO's library (in al::), but with unused code and support for big endian eliminated |
Super Mario Odyssey (Switch) | Little endian (supports big endian as well) | 3 | |
Splatoon 2 (Switch) | Little endian (supports big endian as well) | 3? | Uses SMO's library, but in the Lp::Utl:: namespace |
Animal Crossing: New Horizons (Switch) | Little endian (supports big endian as well) | 4 |
The v3 format seems to be identical to v2 but with the 64-bit node types added.
Extensions
Nintendo uses several file extensions for BYML files in BotW. The basic format is the same even though each kind has a different purpose and contains different parameters. Known extensions:
TotK has added the following extensions:
- .bgyml
Tools
Tool | Cross-platform | Setup | Known issues |
---|---|---|---|
byml-v2 | Yes |
Install the |
None |
ninten-file-tool | Yes |
|
|
Byaml Editor | Yes | ||
Wild Bits | Yes |
|
On some system configurations, launching with |
Switch Toolbox | No |
|
This article was adapted from documentation in the handsomematt/botw-modding repo.
- ↑ Nintendo's BYML library performs a binary search when looking up items by key in a hash node.