Actor sprites file

From Boktai Hacking Wiki
Revision as of 20:52, 22 October 2024 by Raphi (talk | contribs) (Rename animation file -> actor sprites file)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)

Actor sprite files are similar to sprite sets, but they are (slightly) simpler in structure. Actor sprites are used for "small" enemies (like boks or mummies) and most map objects (e.g. levers, candles, etc.), while sprite sets are used for "large" enemies (bosses and minibosses) and UI elements. Both actor sprites and sprite sets can store static and animated sprites as well.

Differences compared to sprite sets

  • Each object in a sprite set sprite can have a different palette, whereas every actor sprite must use the same palette for each object.
  • Each game has multiple sprite set files, but only one actor sprites file. However, the actor sprites file has an internal structure instead that allows one to reference specific actors in the file.
  • Sprites use 2D character mapping, actor sprites use 1D character mapping (for sprite set objects, consecutive rows of tiles are always stored 16 tiles apart, whereas for actor sprites consecutive rows follow immediately after the preceding row).

File format

The actor sprite file stores multiple actors, and each actors can have multiple sprites. Each sprite can be made up of multiple GBA objects.

struct ActorSpritesFile {
  /* offset 0x00 */ u32 unknown_0x00;
  /* offset 0x04 */ u32 actorCount;  // Number of elements in the actors[] array
  /* offset 0x08 */ u32 unknown_0x08;

  // Byte offset from start of the file to the tiles[] array
  /* offset 0x0c */ u32 offsetToTiles;

  // Byte offset from start of the file to the sprites[] array
  /* offset 0x10 */ u32 offsetToSprites;

  // Byte offset from start of the file to the objects[] array
  /* offset 0x14 */ u32 offsetToObjects;

  ActorSpritesActor actors[actorCount];
  GBA_Tile tiles[];
  ActorSprite sprites[];
  ActorObject objects[];
};

struct ActorSpritesActor {
  /* offset 0x00 */ u16 id;       // ID of this actor, used for loading it
  /* offset 0x02 */ u16 unknown_0x02;
  /* offset 0x04 */ u8 widthPx;   // Width of every sprite in pixels
  /* offset 0x05 */ u8 heightPx;  // Height of every sprite in pixels
  /* offset 0x06 */ i8 offsetX;   // X pixel offset of the actor, relative to the position provided by the game
  /* offset 0x07 */ i8 offsetY;   // Y pixel offset of the actor, relative to the position provided by the game

  // Byte offset from start of the sprites[] array to the first sprites of the actor
  /* offset 0x08 */ u32 spritesOffset;
};

struct ActorSprite {
  /* offset 0x00 */ u8 objectCount;   // Number of objects in this sprite
  /* offset 0x01 */ u8 unknown_0x01;

  // Palette index, same as https://boktaihacking.net/wiki/Sprite_set_file#Palettes
  /* offset 0x02 */ u16 palette;

  // Byte offset from start of the tiles[] array to the first tile of this sprite
  /* offset 0x04 */ u16 tileOffset;

  // Byte offset from start of the objects[] array to the first object of this sprite
  // The objectCount field determines how many objects should be drawn
  /* offset 0x06 */ u16 objectOffset;
};

struct ActorObject {
  // Same as the shape field in https://boktaihacking.net/wiki/Sprite_set_file
  /* offset 0x00 */ u8 shape;
  /* offset 0x01 */ u8 unknown_0x01;
  /* offset 0x02 */ i8 x; // X offset of this object in pixels
  /* offset 0x03 */ i8 y; // Y offset of this object in pixels
};

Tiles

Each sprite only stores the first tile that should be drawn for this sprite. The remaining tiles follow the first tile, in order, and using 1D character mapping. Example: Assume that we have an ActorSprite with two objects, one 16x16 px object, followed by one 8x16 px object:

  • Tile 0: Top-left tile of first object
  • Tile 1: Top-right tile of first object
  • Tile 2: Bottom-left tile of first object
  • Tile 3: Bottom-right tile of first object
  • Tile 4: Top tile of second object
  • Tile 5: Bottom tile of second object