391
edits
m (Raphi moved page Animation file to Actor sprites file without leaving a redirect) |
(Rename animation file -> actor sprites file) |
||
Line 1: | Line 1: | ||
Actor sprite files are similar to [[Sprite set file|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 = | = Differences compared to sprite sets = | ||
* Each object in a sprite set sprite can have a different palette, whereas | * 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 | * 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 [https://problemkaputt.de/gbatek-lcd-obj-vram-character-tile-mapping.htm 2D character mapping], | * Sprites use [https://problemkaputt.de/gbatek-lcd-obj-vram-character-tile-mapping.htm 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 = | = File format = | ||
The | The actor sprite file stores multiple actors, and each actors can have multiple sprites. Each sprite can be made up of multiple GBA objects. | ||
<syntaxhighlight lang="c"> | <syntaxhighlight lang="c"> | ||
struct | struct ActorSpritesFile { | ||
/* offset 0x00 */ u32 unknown_0x00; | /* offset 0x00 */ u32 unknown_0x00; | ||
/* offset 0x04 */ u32 | /* offset 0x04 */ u32 actorCount; // Number of elements in the actors[] array | ||
/* offset 0x08 */ u32 unknown_0x08; | /* offset 0x08 */ u32 unknown_0x08; | ||
Line 18: | Line 18: | ||
/* offset 0x0c */ u32 offsetToTiles; | /* offset 0x0c */ u32 offsetToTiles; | ||
// Byte offset from start of the file to the | // Byte offset from start of the file to the sprites[] array | ||
/* offset 0x10 */ u32 | /* offset 0x10 */ u32 offsetToSprites; | ||
// Byte offset from start of the file to the objects[] array | // Byte offset from start of the file to the objects[] array | ||
/* offset 0x14 */ u32 offsetToObjects; | /* offset 0x14 */ u32 offsetToObjects; | ||
ActorSpritesActor actors[actorCount]; | |||
GBA_Tile tiles[]; | GBA_Tile tiles[]; | ||
ActorSprite sprites[]; | |||
ActorObject objects[]; | |||
}; | }; | ||
struct | struct ActorSpritesActor { | ||
/* offset 0x00 */ u16 id; // ID of this | /* offset 0x00 */ u16 id; // ID of this actor, used for loading it | ||
/* offset 0x02 */ u16 unknown_0x02; | /* offset 0x02 */ u16 unknown_0x02; | ||
/* offset 0x04 */ u8 widthPx; // Width of every | /* offset 0x04 */ u8 widthPx; // Width of every sprite in pixels | ||
/* offset 0x05 */ u8 heightPx; // Height of every | /* offset 0x05 */ u8 heightPx; // Height of every sprite in pixels | ||
/* offset 0x06 */ i8 offsetX; // X pixel offset of the | /* 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 | /* offset 0x07 */ i8 offsetY; // Y pixel offset of the actor, relative to the position provided by the game | ||
// Byte offset from start of the | // Byte offset from start of the sprites[] array to the first sprites of the actor | ||
/* offset 0x08 */ u32 | /* offset 0x08 */ u32 spritesOffset; | ||
}; | }; | ||
struct | struct ActorSprite { | ||
/* offset 0x00 */ u8 objectCount; // Number of objects in this | /* offset 0x00 */ u8 objectCount; // Number of objects in this sprite | ||
/* offset 0x01 */ u8 unknown_0x01; | /* offset 0x01 */ u8 unknown_0x01; | ||
Line 49: | Line 49: | ||
/* offset 0x02 */ u16 palette; | /* offset 0x02 */ u16 palette; | ||
// Byte offset from start of the tiles[] array to the first tile of this | // Byte offset from start of the tiles[] array to the first tile of this sprite | ||
/* offset 0x04 */ u16 tileOffset; | /* offset 0x04 */ u16 tileOffset; | ||
// Byte offset from start of the objects[] array to the first object of this | // 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 | // The objectCount field determines how many objects should be drawn | ||
/* offset 0x06 */ u16 objectOffset; | /* offset 0x06 */ u16 objectOffset; | ||
}; | }; | ||
struct | struct ActorObject { | ||
// Same as the shape field in https://boktaihacking.net/wiki/Sprite_set_file | // Same as the shape field in https://boktaihacking.net/wiki/Sprite_set_file | ||
/* offset 0x00 */ u8 shape; | /* offset 0x00 */ u8 shape; | ||
Line 67: | Line 67: | ||
= Tiles = | = Tiles = | ||
Each | 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 [https://problemkaputt.de/gbatek-lcd-obj-vram-character-tile-mapping.htm 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 0: Top-left tile of first object | ||
* Tile 1: Top-right tile of first object | * Tile 1: Top-right tile of first object |