This shows you the differences between two versions of the page.
Next revision | Previous revision | ||
banjo_kazooie:sprites [2025/04/12 12:10] snowboundmage2 created |
banjo_kazooie:sprites [2025/05/01 12:05] (current) snowboundmage2 removed emojis for easier reading |
||
---|---|---|---|
Line 1: | Line 1: | ||
====== Sprite Data ====== | ====== Sprite Data ====== | ||
- | This page documents the binary layout of a sprite file used in the Banjo Kazooie game (based on the n64 rom) . All multi-byte values are stored in **big endian**. | + | This page documents the binary sprite format derived from Banjo-Kazooie’s N64 rom. It supports both single-chunk and multi-frame layouts, with support for various pixel formats and chunk-based rendering. |
- | ===== Sprite File Binary Layout ===== | + | All integers are **big-endian** unless stated otherwise. |
- | The sprite file begins with a 16-byte header, followed by a frame offset table, and then the actual frame data. | + | ---- |
- | ==== Header Section (First 0x10 bytes) ==== | + | ===== Overview ===== |
- | ^ Offset ^ Bytes ^ Big Endian Value ^ Description ^Â | + | This format is used for static or animated sprite graphics in the ROM. Depending on frame count, it can store a simple image or a complex animation. |
- | | 0x00 | 00 01 | 0x0001 | Frame count = 1 |Â | + | |
- | | 0x02 | 01 00 | 0x0100 | Format ID = 0x100 |Â | + | |
- | | 0x04 | FF FF FF FF | 0xFFFFFFFF | Likely unused or sentinel |Â | + | |
- | | 0x08 | 00 BE | 0x00BE = 190 | Possibly a default width? |Â | + | |
- | | 0x0A | 00 BE | 0x00BE = 190 | Possibly a default height? |Â | + | |
- | | 0x0C | 00 00 00 00 | 0x00000000 | Padding or flags | | + | |
- | At offset `0x10`, the **frame offset table** begins. | + | ---- |
- | ==== Frame Offset Table (0x10–0x14) ==== | + | ===== Reference Table ===== |
- | ^ Offset ^ Bytes ^ Big Endian Value ^ Description ^ | + | ==== File Header (offsets 0x00–0x03) ==== |
- | | 0x10 | 00 00 00 04 | 0x00000004 | Offset to Frame 0: `0x04 + 0x14 = 0x18` | | + | |
- | The frame offset table contains a single `uint32_t`, pointing to the first frame header. Since there's only one frame, the table is 4 bytes long. | + | ^ Field ^ Offset ^ Type ^ Description ^Â |
+ | | Frame Count | 0x00 | `uint16_t` | Number of frames |Â | ||
+ | | Format ID | 0x02 | `uint16_t` | Format identifier | | ||
- | ==== Frame 0 Header (starts at 0x18) ==== | + | ==== Format ID Mappings ====Â |
+ | Â | ||
+ | ^ Format ID ^ Enum ^ Description ^ Bits per Pixel ^Â | ||
+ | | 0x0001 | CI4 | 4-bit color indexed | 4 |Â | ||
+ | | 0x0004 | CI8 | 8-bit color indexed | 8 |Â | ||
+ | | 0x0020 | I4 | 4-bit intensity | 4 |Â | ||
+ | | 0x0040 | I8 | 8-bit intensity | 8 |Â | ||
+ | | 0x0100 | IA4 | 4-bit intensity(with alpha) | 4 |Â | ||
+ | | 0x0200 | IA8 | 8-bit intensity(with alpha) | 8 |Â | ||
+ | | 0x0400 | RGBA16 | 16-bit RGBA (5-5-5-1 format) | 16 |Â | ||
+ | | 0x0800 | RGBA32 | 32-bit RGBA | 32 |Â | ||
+ | Â | ||
+ | ----Â | ||
+ | Â | ||
+ | ===== Single Chunk Sprite Layout =====Â | ||
+ | Â | ||
+ | Used if `frameCount > 256` (`0x0100`). | ||
+ | Â | ||
+ | ==== Structure ====Â | ||
+ | Â | ||
+ | ^ Field ^ Offset ^ Type ^ Description ^Â | ||
+ | | X | 0x08 | `int16_t` | X position |Â | ||
+ | | Y | 0x0A | `int16_t` | Y position |Â | ||
+ | | Width | 0x0C | `uint16_t` | Width in pixels |Â | ||
+ | | Height | 0x0E | `uint16_t` | Height in pixels |Â | ||
+ | | Data Offset | ~0x10+ | — | 8-byte aligned after header | | ||
+ | | Data Size | — | computed | Width × Height × bpp ÷ 8 | | ||
+ | Â | ||
+ | ==== Notes ====Â | ||
+ | * No frame table or chunk headers are present. | ||
+ | * Pixel data begins after a 16-byte header, aligned to the next 8-byte boundary. | ||
+ | Â | ||
+ | ----Â | ||
+ | Â | ||
+ | ===== Multi-Frame Sprite Layout =====Â | ||
+ | Â | ||
+ | Used if `frameCount ≤ 256` (`0x0100`). | ||
+ | Â | ||
+ | ==== Frame Table ====Â | ||
+ | Â | ||
+ | * Offset: `0x10`Â | ||
+ | * Entry size: 4 bytes per frame | ||
+ | * Each entry contains a **relative** 32-bit offset from the start of the frame data block. | ||
+ | Â | ||
+ | ==== Frame Data Block ====Â | ||
+ | Â | ||
+ | Starts at: `0x10 + (frameCount × 4)` | ||
+ | Â | ||
+ | === Frame Header ===Â | ||
+ | Â | ||
+ | ^ Field ^ Offset ^ Type ^ Description ^Â | ||
+ | | X | 0x00 | `int16_t` | Frame X offset |Â | ||
+ | | Y | 0x02 | `int16_t` | Frame Y offset |Â | ||
+ | | Width | 0x04 | `uint16_t` | Frame width |Â | ||
+ | | Height | 0x06 | `uint16_t` | Frame height |Â | ||
+ | | Chunk Count | 0x08 | `uint16_t` | Number of chunks |Â | ||
+ | Â | ||
+ | === Palette Data (for CI4 / CI8 only) ===Â | ||
+ | Â | ||
+ | ^ Field ^ Offset ^ Size ^ Description ^Â | ||
+ | | Palette Data | aligned after 0x14 | 32 or 512B | 16×2 or 256×2 bytes, depending on format | | ||
+ | Â | ||
+ | === Chunk Table ===Â | ||
+ | Â | ||
+ | Each chunk entry is 8 bytes:Â | ||
+ | Â | ||
+ | ^ Field ^ Offset ^ Type ^ Description ^Â | ||
+ | | Chunk X | 0x00 | `int16_t` | Chunk X position |Â | ||
+ | | Chunk Y | 0x02 | `int16_t` | Chunk Y position |Â | ||
+ | | Chunk Width | 0x04 | `uint16_t` | Width of chunk |Â | ||
+ | | Chunk Height | 0x06 | `uint16_t` | Height of chunk |Â | ||
+ | Â | ||
+ | * Pixel data for each chunk follows the chunk table. | ||
+ | * All data is aligned to the next 8-byte boundary. | ||
+ | Â | ||
+ | ----Â | ||
+ | Â | ||
+ | ===== Design Rationale =====Â | ||
+ | Â | ||
+ | === Format ID and Versatility ===Â | ||
+ | * 16-bit format ID allows for clean extensibility. | ||
+ | * Decoding behavior is format-specific (e.g. CI formats require palettes). | ||
+ | Â | ||
+ | === Single vs Multi-frame Decision ===Â | ||
+ | * A `frameCount > 0x0100` indicates the file is a simple image without a frame table. | ||
+ | * Keeps parsing logic simpler for single-use graphics. | ||
+ | Â | ||
+ | === Frame Table Abstraction ===Â | ||
+ | * Offsets are relative to the frame data block, not absolute. | ||
+ | * Allows reorganization and stream-friendly parsing. | ||
+ | Â | ||
+ | === 8-byte Alignment ===Â | ||
+ | * Ensures data structures are aligned in memory. | ||
+ | * Improves DMA or cache line performance on N64. | ||
+ | Â | ||
+ | === Chunk-Based Rendering ===Â | ||
+ | * Chunks allow tile reuse or sub-rectangles. | ||
+ | * Efficient layout, supports tilemaps or partial redraws. | ||
+ | Â | ||
+ | === Optional Palette ===Â | ||
+ | * CI4 and CI8 include palettes automatically. | ||
+ | * Size and format are inferred based on format ID. | ||
+ | Â | ||
+ | ----Â | ||
+ | Â | ||
+ | ===== Validation Checklist =====Â | ||
+ | Â | ||
+ | Use the following to verify whether a file matches this format:Â | ||
+ | Â | ||
+ | - [ ] File size ≥ 4 bytes | ||
+ | - [ ] Read and parse frame count and format IDÂ | ||
+ | - [ ] If frameCount > 0x0100 → parse as single-chunk | ||
+ | - [ ] If ≤ 0x0100 → validate frame table offsets | ||
+ | - [ ] Parse each frame header and chunk table | ||
+ | - [ ] Validate alignment and total chunk data sizes | ||
+ | Â | ||
+ | ---- | ||
- | ^ Offset ^ Bytes ^ Big Endian Value ^ Description ^Â | + | ===== Notes ===== |
- | | 0x18 | 00 00 | 0 | X position |Â | + | |
- | | 0x1A | 00 00 | 0 | Y position |Â | + | |
- | | 0x1C | 03 91 | 0x0391 = 913 | Width in pixels |Â | + | |
- | | 0x1E | 00 13 | 0x0013 = 19 | Height in pixels |Â | + | |
- | | 0x20 | 00 3E | 0x003E = 62 | Chunk count |Â | + | |
- | | 0x22 | 00 00 | — | Unknown or padding | | + | |
- | More details on **chunk data** may follow after offset `0x24`. | + | * All integers are stored in **big-endian** format. |
+ | * Offsets in the frame table are **relative** to the frame data section. | ||
+ | * Data structures and pixel data must be aligned to 8-byte boundaries. | ||
+ | * CI4/CI8 formats require an internal palette directly after the frame header. | ||
---- | ---- | ||
+ | ''This documentation is a work in progress based on reverse engineering efforts. Contributions welcome!'' | ||