BIN (File Format)
BIN is a file format used in Mario Kart 8 to store binary lookup tables. They consist of several sections as defined in the file / main header, in which there are groups containing specific elements of data of a given type. They are found in the Filesystem/content/common/mush directory.
The format is similar to the one used in Mario Kart 7, though it strips a lot of textual data describing the entries of the groups, which makes giving meaning to the values of the elements harder, though many elements are simply evolved or even ported from Mario Kart 7.
They are used to lookup typical tabular data like the item probabilities at distances to the lead racer, the distances for this themselves, course information, audio information, controller mappings (possibly), kart body / tire / glider settings or engine statistics.
Mario Kart 8 (Wii U) stores the files in big endian, Mario Kart 8 Deluxe (Switch) in little endian.
The generic file format used in both games only differs in the section header, with Deluxe storing additional 4 bytes of unknown purpose. Of course, the element counts in specific sections also differ to store new / different driver and kart statistics, but this information is not known or required at the base format layer.
In the following, C# data types are used to describe the data.
Each BIN file starts with a main header which provides information about the available sections in the file.
|0x00||4||uint||File identifier. Takes the form of a 4 character long ASCII string acronym of the file's purpose.|
|0x04||4||int||File size in bytes. Sometimes slightly off from the real file size, unclear why this is the case.|
|0x08||2||short||Number of sections following the header.|
|0x0C||4||int||Version number. Always 1000.|
|0x10||4 * Number of sections||int[numberOfSections]|| Offsets to the sections, relative to the end of the header.
This means that the first offset is always 0, as the first section always starts directly after the header.
Each section header at the offsets given in the main header describes the number of groups of data in the section, the number of elements in each group, and the type of the elements.
|0x00||4||uint||Section identifier. Takes the form of a 4 character long ASCII string acronym of the section's purpose.|
|0x04||2||short||Element count. The number of elements in a group.|
|0x06||2||short||Group count. The number of groups in the section.|
|0x08||4||int||Type ID. Depending on this value, the format of the section data is different.|
|if Mario Kart 8 Deluxe|
|0x0C||4||int||Unknown value, might just be a longer type ID.|
Groups are simply arrays of the given number of elements. Depending on the type ID provided in the section header, the format (and thus size) of the elements differs. The type IDs seem to be the same as the ones used in Mario Kart 7.
The start and end of each section is aligned by 4 bytes, which is important for those sections containing strings.
Dword Array (Type 0)
The group elements are arrays with 4-byte numerical data types (either integer or floats, or both mixed) of a specific length. The game knows the data type of each element and array length by switching on the section identifier (it can be assumed it directly reads those into structures). Without this knowledge, the length of the element arrays can still be computed with the following formula:
elementLength = sectionSizeWithoutHeader / (groupCount * elementCount) / sizeof(int)
|0x00||4 * elementCount * elementLength|| int[elementCount][elementLength] or
|Integer or float arrays.|
String Array (Type 160)
The group elements are an array of offsets pointing to elements of the following array of 0-terminated strings.
|0x00||4 * elementCount||int[elementCount]||String offsets, relative to the end of the last offset. E.g., the first offset is always 0.|
|-||-||string[elementCount]||Strings, 0-terminated, pointed to by the preceeding offsets.|
There are several other types holding other values (most ending with a list of strings) which have not been covered here yet.
The following tools can operate on BIN files: