Sprite set file

From Boktai Hacking Wiki
Revision as of 16:08, 16 September 2024 by Raphi (talk | contribs)

Sprite sets are stored in directory id_low = 0x5f29, id_high = 0xc8e5 in the master file table. Each sprite set contains multiple distinct sprites, and each sprite may be made of multiple GBA OBJs.

File format

TODO: very incomplete

struct spriteset_header {
  u16 unknown_0x00;
  u16 spriteCount; // number of sprites in this sprite set
  u16 unknown_0x04;
  u16 unknown_0x06;
  u16 unknown_0x08;
  u16 unknown_0x0a;

  u32 offsetToSprites; // byte offset from start of this struct to the spriteset_sprite[spriteCount] array
  u32 offsetToUnknown_0x10;
  u32 offsetToOBJs;    // byte offset from start of this struct to the spriteset_obj[] array
  u32 offsetToUnknown_0x18;
  u32 offsetToTiles;   // byte offset from start of this struct to the spriteset_tile[] array
};

struct spriteset_sprite {
  u16 unknown_0x00;
  u16 objCount; // Sprite is made up of this many OBJs
  u16 unknown_0x04;
  u16 unknown_0x06;
  u16 unknown_0x08;
  u16 unknown_0x0a;
  u16 unknown_0x0c;
  u16 unknown_0x0e;
  u32 objStart; // Start index for this sprite in the spriteset_obj[] array
};

struct spriteset_obj {
  u8 flip; // bitmask; 4 = horizontal, 8 = vertical

  // 00=8x8,   01=16x8,  02=8x16
  // 04=16x16, 05=32x8,  06=8x32
  // 08=32x32, 09=32x16, 10=16x32
  // 12=64x64, 13=64x32, 14=32x64
  u8 shape;

  i16 xOffset;
  i16 yOffset;

  // Bottom 12 bits: Start index for this OBJ in the raw tile data array
  // Top 4 bits: Palette index
  u16 tileAndPalette;
};

struct spriteset_tile {
  u8[32] data; // Raw GBA tile data
}

The OBJ palette must be loaded manually first. There is no link between a sprite set file and its matching palette file.

Usage example

void load_sprite(spriteset_header* spriteset, int spriteId)
{
  spriteset_sprite* sprites = (u8*)spriteset + spriteset->offsetToSprites;
  spriteset_obj* objs = (u8*)spriteset + spriteset->offsetToOBJs;
  spriteset_tile* tiles = (u8*)spriteset + spriteset->offsetToTiles;

  spriteset_sprite* sprite = &sprites[spriteId];
  // do something with sprite

  for (int objIndex=0; objIndex < sprite->objCount; objIndex++) {
    spriteset_obj* obj = &objs[sprite->objStart + objIndex];
    // do something with obj

    int tileIndex = obj->tileAndPalette & 0xfff;
    spriteset_tile* firstTile = &tiles[tileIndex];
    // number of tiles is implied by sprite->shape
    // do something with the tiles
  }
}