RKG (File Format)

From Custom Mario Kart
Jump to navigation Jump to search

RKG is the format of Time Trial ghost data. This format is common between ghosts saved in the saved file, staff ghosts and ghosts stored on Time Trial servers. In a savefile all ghosts are saved in the rksys file.

The file consists of a header describing the settings of the ghost such as vehicle and character, as well as the driver information such as the Mii, controller type and drift type. The header also contains metadata such as finishing time of the ghost. The main contents of the file is then the sequence of controller inputs made by the player, which can be used to replay the ghost. This may be compressed or raw. Following the ghost input data is a CRC-32 which the game uses to verify the file has not corrupted.

If the game is perfectly deterministic, the same controller inputs should always yield the same finishing time. In practice however, Mario Kart Wii is not quite able to recreate the circumstances in which the ghost was recorded leading to the rare Wiggler Glitch. This causes the ghost to descynchronise from the original Time Trial, often failing to finish.

File Header

An RKG file begins with the 0x88 byte header.

Header of RKG file
Offset Size Description
0x00 4 "RKGD" in ASCII; Revolution Kart Ghost Data file identifier.
0x04 7 bits Minutes field of finishing time.
0x04.7 7 bits Seconds field of finishing time.
0x05.6 10 bits Milliseconds field of finishing time.
0x07 6 bits Track ID.
0x07.6 2 bits Unknown. Probably padding.
0x08 6 bits Vehicle ID used by the ghost.
0x08.6 6 bits Character ID used by the ghost.
0x09.4 7 bits Year that the ghost was set, stored relative to the year 2000.
0x0A.3 4 bits Month that the ghost was set.
0x0A.7 5 bits Day that the ghost was set.
0x0B.4 4 bits Controller ID; 0 for Wii Wheel, 1 for Wii Remote + Nunchuck, 2 for Classic Controller, 3 for GameCube Controller.
0x0C 4 bits Unknown. Always 0?
0x0C.4 1 bit Compressed flag; 1 for compressed, 0 for raw.
0x0C.5 2 bits Unknown. Always 0?
0x0C.7 7 bits Ghost type; 0x01 player's best time, 0x02 world record ghost, 0x03 continental record ghost, 0x04 rival ghost, 0x05 special ghost, 0x06 ghost race, 0x07-0x24 for all 30 friend ghosts, 0x25 normal staff ghost, 0x26 expert staff ghost.
0x0D.6 1 bit Drift type; 1 for automatic, 0 for manual.
0x0D.7 1 bit Unknown. Probably padding.
0x0E 2 Input data length, measured when decompressed and without padding.
0x10 1 Lap count; total laps driven by ghost.
0x11 3 × 5 Lap split times. Stored in the same 7 bit, 7 bit, 10 bit format as the finish time at offset 0x4. Unused split times are set to 0.
0x20 0x14 Unknown. Probably unused. The game attempts to store lap splits beyond the 5th here, but the internal data structures do not store that many splits, so RAM trash is stored instead when the lap count is greater than 5 (notably the finish time in the 6th split).
0x34 1 Country code or 0xFF if sharing location disabled.
0x35 1 State code or 0xFF if sharing location disabled.
0x36 2 Location code. 0x0000 typically, 0xFFFF if sharing location disabled.
0x38 4 Unknown. 0x00000000 typically.
0x3C 0x4A Driver's Mii Data.
0x86 2 CRC16-CCITT-XModem of Mii.
0x88 End of this header; start of data

Controller Input Data

The header is then followed by the input data. For compressed input data, the first 4 bytes are the length of the compressed data, followed by YAZ1 compressed data (including the YAZ1 header). The compressed data is always padded with zeros to a multiple of 4 bytes in length. Compressed data is used in the online rankings and in staff ghosts, uncompressed data is used in the save file. In a compressed ghost the compressed data (including YAZ1 header) must be less than or equal to 0x2774 bytes in length. For both compressed and uncompressed ghosts, the uncompressed input data must also be less than 0x2774 in length. In uncompressed files the input data is padded to exactly 0x2774 bytes in length. The length of the input data in the header always refers to the input data without padding.

The input data begins with the following 8 byte header.

Header of RKG input data section
Offset Size Description
0x00 2 Count of face button inputs.
0x02 2 Count of direction inputs.
0x04 2 Count of trick inputs.
0x06 2 Unknown. Probably padding.
0x08 End of this header; start of face button input data.

The actual input data then follows in complete sections in the order of face button inputs, direction inputs then trick inputs. Each uses a 2 byte format, 1 byte representing the state of the specified input then the next representing the duration for which that input was held in frames. The sections follow on sequentially from each other and are always 2 × count bytes in length. If an input state is held for more than 255 frames, it is continued as the next input. The meaning of the state bytes differs per section as follows.

Face button input byte
Bit mask Description
0x01 Accelerator button is pressed.
0x02 Brakes/drift button is pressed.
0x04 Fire item button is pressed.
0x08 Also set if brakes/drift button is pressed after having pressed the accelerator button and keep holding it.
0xF0 Unknown.
Direction input byte
Bit mask Description
0x0F Forward/backward input (a range; 0xE is forward, 0x0 is backward, 0x7 is neutral).
0xF0 Left/right input (0xE0 is right, 0x00 is left, 0x70 is neutral).
Trick input byte
Bit mask Description
0x0F Used if input state is held longer than 255 frames. Adds up with the input state duration byte for a total of 12 bits of size for input duration.
0x70 Trick input direction (0x00 no trick, 0x10 is up/wheelie, 0x20 is down, 0x30 is left, 0x40 is right).
0x80 Unknown. Probably unused.


Following the data is a CRC-32 of the file up to that point. For compressed files, this is a CRC of the compressed data not the decompressed data.


The following tools can handle RKG files:

A kaitai format description file can be found on this GitHub repository.