Hack64 Wiki
Other Titles
Hack64 Wiki
Other Titles
This is an old revision of the document!
This page documents the binary layout of sprite files found in the Banjo-Kazooie ROM (Nintendo 64). These files contain image data composed of one or more frames, each composed of a series of image chunks.
All multi-byte values are stored in big endian. Unless otherwise stated, all examples use sprite ID `06EB`.
A sprite file is divided into the following sections:
The header occupies the first 0x10 bytes of the file and contains basic metadata about the sprite.
Offset | Size | Description |
---|---|---|
0x00 | 2 bytes | Frame count (`frameCnt`) |
0x02 | 2 bytes | Format ID / type (`type`) — usually `0x0100` |
0x04 | 2 bytes | Unknown (`unk4`) |
0x06 | 2 bytes | Unknown (`unk6`) |
0x08 | 2 bytes | Possibly default width (`unk8`) |
0x0A | 2 bytes | Possibly default height (`unkA`) |
0x0C | 4 bytes | Bitfield flags (`unkC`) — see below |
0x10 | … | Frame offset table (`offsets[]`) |
The bitfield at `0x0C` may contain rendering options or format hints.
The 32-bit word at offset `0x0C` includes the following layout:
Bits | Field | Description |
---|---|---|
31–28 | `bit31` | Possibly render mode |
27–25 | `bit27` | Possibly format ID |
24–23 | `bit24` | Possibly compression |
22–21 | `bit22` | Possibly blending or layer mode |
20–0 | `pad` | Unused or reserved |
Immediately following the header is the frame offset table. This table contains 32-bit pointers to each frame's data section, relative to the start of the offset table.
Offset | Size | Description |
---|---|---|
0x10 | 4 bytes | Frame 0 offset: `0x00000004` (points to 0x18 from file start) |
Total size of this section = `4 × frameCnt`
Each frame starts with a 20-byte structure:
Offset | Size | Field | Description |
---|---|---|---|
+0x00 | 2 bytes | `unk0` | Possibly X offset |
+0x02 | 2 bytes | `unk2` | Possibly Y offset |
+0x04 | 2 bytes | `w` | Width in pixels |
+0x06 | 2 bytes | `h` | Height in pixels |
+0x08 | 2 bytes | `chunkCnt` | Number of image chunks |
+0x0A | 2 bytes | `unkA` | Unknown |
+0x0C | 2 bytes | `unkC` | Unknown |
+0x0E | 2 bytes | `unkE` | Unknown |
+0x10 | 2 bytes | `unk10` | Unknown |
+0x12 | 2 bytes | `unk12` | Unknown |
After the frame header, a sequence of chunk definitions begins.
Each chunk describes a rectangular image section used to draw part of the frame.
Offset | Size | Field | Description |
---|---|---|---|
+0x00 | 2 bytes | `x` | X position |
+0x02 | 2 bytes | `y` | Y position |
+0x04 | 2 bytes | `w` | Width |
+0x06 | 2 bytes | `h` | Height |
There are `chunkCnt` chunk structures per frame, immediately following the frame header.
The sprite rendering system likely interprets pixel data using the following enum:
Value | Name | Description |
---|---|---|
0 | `CI4` | Color Indexed 4-bit |
1 | `CI8` | Color Indexed 8-bit |
2 | `I4` | Intensity 4-bit |
3 | `I8` | Intensity 8-bit |
4 | `RGBA16` | 16-bit RGBA |
5 | `RGBA32` | 32-bit RGBA |
6 | `IA4` | Intensity + Alpha 4-bit |
7 | `IA8` | Intensity + Alpha 8-bit |
8 | `UNKNOWN` | Fallback / unknown |
Format may be deduced from the header `type` field or the bitfield at `0x0C`.
The following C-like structures represent the sprite format as reverse-engineered:
typedef struct { u16 frameCnt; u16 type; u16 unk4; u16 unk6; u16 unk8; u16 unkA; struct { u32 bit31 : 4; u32 bit27 : 3; u32 bit24 : 2; u32 bit22 : 2; u32 pad_bit20 : 21; } unkC; u32 offsets[]; } BKSprite; typedef struct { s16 unk0; s16 unk2; s16 w; s16 h; s16 chunkCnt; s16 unkA; s16 unkC; s16 unkE; s16 unk10; s16 unk12; } BKSpriteFrame; typedef struct { s16 x; s16 y; s16 w; s16 h; } BKSpriteTextureBlock;
This format is still under investigation. Contributions and corrections welcome.