User Tools

Site Tools


banjo_kazooie:sprites

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Next revision
Previous revision
banjo_kazooie:sprites [2025/04/12 12:10]
snowboundmage2 created
banjo_kazooie:sprites [2025/04/12 13:01] (current)
snowboundmage2 [Sprite Asset]
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 romAll 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 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 ​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              | 
 +| 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!''​
  
banjo_kazooie/sprites.1744459850.txt.gz · Last modified: 2025/04/12 12:10 by snowboundmage2