Tile map file
Tile maps store visual data for the GBA's background layers. Each tile map file contains:
- The tile set used by this tile map file, as an array of standard 8x8 px 4 bpp tiles. Optional, if the tile map file does not contain tile set data, then they must be loaded by an external mechanism (generally a script). Tile maps for menus are usually storing the tile sets themselves, while normal overworld/dungeon maps depend on a global tile set.
- An array of metatiles: Each metatile is 2x2 tiles in size. This serves as a compression mechanism.
- An array of layers: Each tile map file may one or multiple different "layers". tile map files only contain a single layer, but menus can have one layer per page in the menu for example. All layers in a tile map file share the same tile set and metatile set.
Compression
Most tile map files are stored LZ77 (swi 0x11
) compressed. When loading a tile map file, the game checks if the file starts with the ASCII characters "MP" (hex: 0x4d, 0x50
). If it does, then the file is not compressed, and used by the game as-is. If it does not start with these characters, the game will LZ77 decompress it to EWRAM. Note that the first 4 bytes after decompression must be discarded (they will contain the uncompressed length of the file).
File format
struct TilemapHeader {
/* offset 0x00 */ char magic[2]; // Always the two ASCII characters "MP"
/* offset 0x02 */ u16 unknown_0x02;
/* offset 0x04 */ u16 layerCount; // Number of layers in this file
/* offset 0x06 */ u16 tileCount; // Number of tiles in this file's tileset (if it exists)
/* offset 0x08 */ u32 unknown_0x08;
// Byte offset from start of this struct to the layerDefinitions[] array
/* offset 0x0c */ u32 offsetToLayerDefinitions;
// Byte offset from start of this struct to the tileset[] array
// If it's zero, then this file does not contain a tileset.
/* offset 0x10 */ u32 offsetToTileset;
// Byte offset from start of this struct to the metatiles[] array
/* offset 0x14 */ u32 offsetToMetatiles;
// TODO: how are these ordered?
TilemapLayer layerDefintions[layerCount];
// Each metatile contains four GBA BG screen entries:
// https://problemkaputt.de/gbatek-lcd-vram-bg-screen-data-format-bg-map.htm
// This includes the tile number and the palette bits (TODO: Does it include the flip bits?).
// For each metatile, element 0=top left, 1=top right, 2=bottom left, 3=bottom right.
u16 metatiles[][4];
// Only if offsetToTiles != 0. Array of 8x8 px 4 bpp GBA tiles to use.
u8 tileset[][32];
// Each layer is an array of TilemapLayer.width * TilemapLayer.height metatile numbers,
// in row-major order.
// Each individual u16 in this array references a metatile, which is 16x16 px in size.
u16 layerData[][];
};
struct TilemapLayer {
/* offset 0x00 */ u16 width; // Width of layer in metatiles
/* offset 0x02 */ u16 height; // Height of layer in metatiles
/* offset 0x04 */ u32 unknown_0x4;
// Byte offset from start of **the TilemapHeader struct** to the layer data
/* offset 0x08 */ u32 offsetToTilemap;
};