BYAML (File Format)

From Wexos's Wiki
Revision as of 17:21, 1 May 2024 by Wexos (talk | contribs) (Imported from avsys wiki)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigationJump to search
For the Mario Kart 8 and Mario Kart 8 Deluxe-specific course BYAML, see course_muunt.byaml (File Format).

BYAML is a generic file format used on Wii U and the Nintendo Switch in games like Mario Kart 8 and Mario Kart 8 Deluxe. BYML is basically the same, and is used in games like Super Mario 3D World and Super Mario Odyssey.

File Format

Header

The file starts with a 0x10 or 0x14 bytes long header. An offset can be 0 meaning it points to nothing.

Offset Type Description
0x00 Char[2] File magic. BY for big endian files, and YB for little endian files.
0x02 UInt16 File format version.
0x04 UInt32 Node name string table node offset.
0x08 UInt32 String value string table node offset..
0x0C UInt32 Serialized data table node offset. Usually doesn't exist for BYML files.
0x10 UInt32 Root node. Must be an array node or dictionary node.

Nodes

The file consists of multiple nodes, stored in a hierarchy. There are two special-purpose nodes, string table node and serialized data table node, which can only be linked by the header and cannot be stored in the hierarchy of nodes. Only two nodes allow storing children, dictionary node and array node. Each child element consists of a 32-bit integer. If the child node is four bytes long, then the 32-bit integer represents the value of the child node. If the child node is larger than four bytes, then the 32-bit integer represents an absolute offset to the data of the node. For Int32 and Float, the data is stored directly since those are exactly four bytes long, but array node and Int64 are examples where an offset is stored.

The following table shows all available node types:

ID Name Available since version
0xA0 String reference 1
0xA1 Serialized data reference 1
0xC0 Array 1
0xC1 Dictionary 1
0xC2 String table 1
0xC3 Serialized data table 1
0xD0 Boolean 1
0xD1 Int32 1
0xD2 Float 1
0xD3 UInt32 2
0xD4 Int64 2 or 3
0xD5 UInt64 2 or 3
0xD6 Double 2
0xFF Null 2 or 3

Array Node

An array node consists a collection of child nodes, all of arbitrary types. An array node has the following structure:

Offset Type Description
0x00 Byte Node type. Must be 0xC0.
0x01 UInt24 Number of child elements.
0x04 Byte[N] Child node types. Each byte represents a node type.
Align by 4.

The child elements comes after the structure, altough at an offset aligned by four. If the size of the child node is four bytes, then the direct value is stored. Otherwise a 32-bit offset is stored, which points to the child data. See nodes.

Dictionary Node

A dictionary node consists of a named child nodes. Like an array node, it stores a collection of child nodes, although in a dictionary node all child nodes are named. A dictionary node has the following structure:

Offset Type Description
0x00 Byte Node type. Must be 0xC1.
0x01 UInt24 Number of child elements.

After that, each dictionary entry is stored, each of which describes a child node. It has the following structure:

Offset Type Description
0x00 UInt24 Name index. Index of string into the node name string table node linked in the header which represents the name of this node.
0x03 Byte Child node type. See nodes.
0x04 UInt32 Child element. If the size of the child node is four bytes, then the direct value is stored. Otherwise a 32-bit offset is stored, which points to the child data. See nodes.
Dictionary look-up

When looking up a string in a dictionary node, binary search is done twice. First, binary search is used to find the index of the name into the node name string table node. If the name doesn't exist, then there is no node in the dictionary with that name. However, if it does exist, binary search is used again to find if there is a node with a name index matching the index which was looked up earlier. In order for this to work, the dictionary entries must be sorted on name index.

String Table Node

A string table node stores strings and is accessed by an index in a dictionary node or string node. The node can only be linked in the header. All strings are null-terminated, and must be sorted on true UTF-8 order in order to allow binary search. The node starts with the following structure:

Offset Type Description
0x00 Byte Node type. Must be 0xC2.
0x01 UInt24 Number of strings.
0x04 UInt32[N + 1] String offsets. The last offset points to the end of the last string. The offsets are relative to the start of this node structure.

Serialized Data Table Node

The serialized data table node stores a collection of generic data. What the data contains is game-specific. Serialized data is accessed by a serialized data node. The node starts with the following structure:

Offset Type Description
0x00 Byte Node type. Must be 0xC3.
0x01 UInt24 Number of serialized data elements.
0x04 UInt32[N + 1] Serialized data offsets. The last offset points to the end of the last entry. The offsets are relative to the start of this node structure. The size of each entry is known by looking at the next data offset.

Value Nodes

The following table shows all nodes which cannot contain children and are not special-purpose.

ID Name Size Descrption
0xA0 String reference 4 32-bit integer which represents an index into the string value string table linked in the header.
0xA1 Serialized data reference 4 32-bit integer which represents an index into the serialized data table node linked in the header.
0xD0 Boolean 4 32-bit integer boolean, where 1 represents true and 0 represents false.
0xD1 Int32 4 32-bit signed integer.
0xD2 Float 4 32-bit floating-point.
0xD3 UInt32 4 32-bit unsigned integer.
0xD4 Int64 8 64-bit signed integer.
0xD5 UInt64 8 64-bit unsigned integer.
0xD6 Double 8 64-bit floating-point.
0xFF Null 4 Null. Generally this is used to specify a null value for a string. A 32-bit zero value is stored as a dummy value.

Tools

The following tools can handle BYAML/BYML files:

  • (none)