pokeemerald/gflib/sprite.h
2022-06-03 15:38:03 -04:00

327 lines
9.3 KiB
C

#ifndef GUARD_SPRITE_H
#define GUARD_SPRITE_H
#define MAX_SPRITES 64
#define SPRITE_NONE 0xFF
#define TAG_NONE 0xFFFF
// Given to SetSpriteMatrixAnchor to skip anchoring one of the coords.
#define NO_ANCHOR 0x800
struct SpriteSheet
{
const void *data; // Raw uncompressed pixel data
u16 size;
u16 tag;
};
struct CompressedSpriteSheet
{
const u32 *data; // LZ77 compressed pixel data
u16 size; // Uncompressed size of pixel data
u16 tag;
};
struct SpriteFrameImage
{
const void *data;
u16 size;
};
#define obj_frame_tiles(ptr) {.data = (u8 *)ptr, .size = sizeof ptr}
#define overworld_frame(ptr, width, height, frame) {.data = (u8 *)ptr + (width * height * frame * 64)/2, .size = (width * height * 64)/2}
struct SpritePalette
{
const u16 *data; // Raw uncompressed palette data
u16 tag;
};
struct CompressedSpritePalette
{
const u32 *data; // LZ77 compressed palette data
u16 tag;
};
struct AnimFrameCmd
{
// If the sprite has an array of images, this is the array index.
// If the sprite has a sheet, this is the tile offset.
u32 imageValue:16;
u32 duration:6;
u32 hFlip:1;
u32 vFlip:1;
};
struct AnimLoopCmd
{
u32 type:16;
u32 count:6;
};
struct AnimJumpCmd
{
u32 type:16;
u32 target:6;
};
// The first halfword of this union specifies the type of command.
// If it -2, then it is a jump command. If it is -1, then it is the end of the script.
// Otherwise, it is the imageValue for a frame command.
union AnimCmd
{
s16 type;
struct AnimFrameCmd frame;
struct AnimLoopCmd loop;
struct AnimJumpCmd jump;
};
#define ANIMCMD_FRAME(...) \
{.frame = {__VA_ARGS__}}
#define ANIMCMD_LOOP(_count) \
{.loop = {.type = -3, .count = _count}}
#define ANIMCMD_JUMP(_target) \
{.jump = {.type = -2, .target = _target}}
#define ANIMCMD_END \
{.type = -1}
struct AffineAnimFrameCmd
{
s16 xScale;
s16 yScale;
u8 rotation;
u8 duration;
};
struct AffineAnimLoopCmd
{
s16 type;
s16 count;
};
struct AffineAnimJumpCmd
{
s16 type;
u16 target;
};
struct AffineAnimEndCmdAlt
{
s16 type;
u16 val;
};
union AffineAnimCmd
{
s16 type;
struct AffineAnimFrameCmd frame;
struct AffineAnimLoopCmd loop;
struct AffineAnimJumpCmd jump;
struct AffineAnimEndCmdAlt end; // unused in code
};
#define AFFINEANIMCMDTYPE_LOOP 0x7FFD
#define AFFINEANIMCMDTYPE_JUMP 0x7FFE
#define AFFINEANIMCMDTYPE_END 0x7FFF
#define AFFINEANIMCMD_FRAME(_xScale, _yScale, _rotation, _duration) \
{.frame = {.xScale = _xScale, .yScale = _yScale, .rotation = _rotation, .duration = _duration}}
#define AFFINEANIMCMD_LOOP(_count) \
{.loop = {.type = AFFINEANIMCMDTYPE_LOOP, .count = _count}}
#define AFFINEANIMCMD_JUMP(_target) \
{.jump = {.type = AFFINEANIMCMDTYPE_JUMP, .target = _target}}
#define AFFINEANIMCMD_END \
{.type = AFFINEANIMCMDTYPE_END}
#define AFFINEANIMCMD_END_ALT(_val) \
{.end = {.type = AFFINEANIMCMDTYPE_END, .val = _val}}
struct AffineAnimState
{
u8 animNum;
u8 animCmdIndex;
u8 delayCounter;
u8 loopCounter;
s16 xScale;
s16 yScale;
u16 rotation;
};
enum
{
SUBSPRITES_OFF,
SUBSPRITES_ON,
SUBSPRITES_IGNORE_PRIORITY, // on but priority is ignored
};
struct Subsprite
{
s8 x; // was u16 in R/S
s8 y; // was u16 in R/S
u16 shape:2;
u16 size:2;
u16 tileOffset:10;
u16 priority:2;
};
struct SubspriteTable
{
u8 subspriteCount;
const struct Subsprite *subsprites;
};
struct Sprite;
typedef void (*SpriteCallback)(struct Sprite *);
struct SpriteTemplate
{
u16 tileTag;
u16 paletteTag;
const struct OamData *oam;
const union AnimCmd *const *anims;
const struct SpriteFrameImage *images;
const union AffineAnimCmd *const *affineAnims;
SpriteCallback callback;
};
// UB: template pointer is often used to point to temporary storage,
// then later dereferenced after being freed. Usually this won't
// be visible in-game, but this is (part of) what causes the item
// icon palette to flicker when changing items in the bag.
struct Sprite
{
/*0x00*/ struct OamData oam;
/*0x08*/ const union AnimCmd *const *anims;
/*0x0C*/ const struct SpriteFrameImage *images;
/*0x10*/ const union AffineAnimCmd *const *affineAnims;
/*0x14*/ const struct SpriteTemplate *template;
/*0x18*/ const struct SubspriteTable *subspriteTables;
/*0x1C*/ SpriteCallback callback;
/*0x20*/ s16 x, y;
/*0x24*/ s16 x2, y2;
/*0x28*/ s8 centerToCornerVecX;
/*0x29*/ s8 centerToCornerVecY;
/*0x2A*/ u8 animNum;
/*0x2B*/ u8 animCmdIndex;
/*0x2C*/ u8 animDelayCounter:6;
bool8 animPaused:1;
bool8 affineAnimPaused:1;
/*0x2D*/ u8 animLoopCounter;
// general purpose data fields
/*0x2E*/ s16 data[8];
/*0x3E*/ bool16 inUse:1; //1
bool16 coordOffsetEnabled:1; //2
bool16 invisible:1; //4
bool16 flags_3:1; //8
bool16 flags_4:1; //0x10
bool16 flags_5:1; //0x20
bool16 flags_6:1; //0x40
bool16 flags_7:1; //0x80
/*0x3F*/ bool16 hFlip:1; //1
bool16 vFlip:1; //2
bool16 animBeginning:1; //4
bool16 affineAnimBeginning:1; //8
bool16 animEnded:1; //0x10
bool16 affineAnimEnded:1; //0x20
bool16 usingSheet:1; //0x40
bool16 anchored:1; //0x80
/*0x40*/ u16 sheetTileStart;
/*0x42*/ u8 subspriteTableNum:6;
u8 subspriteMode:2;
/*0x43*/ u8 subpriority;
};
struct OamMatrix
{
s16 a;
s16 b;
s16 c;
s16 d;
};
extern const struct OamData gDummyOamData;
extern const union AnimCmd *const gDummySpriteAnimTable[];
extern const union AffineAnimCmd *const gDummySpriteAffineAnimTable[];
extern const struct SpriteTemplate gDummySpriteTemplate;
extern u8 gReservedSpritePaletteCount;
extern struct Sprite gSprites[];
extern u8 gOamLimit;
extern u16 gReservedSpriteTileCount;
extern s16 gSpriteCoordOffsetX;
extern s16 gSpriteCoordOffsetY;
extern struct OamMatrix gOamMatrices[];
extern bool8 gAffineAnimsDisabled;
void ResetSpriteData(void);
void AnimateSprites(void);
void BuildOamBuffer(void);
u8 CreateSprite(const struct SpriteTemplate *template, s16 x, s16 y, u8 subpriority);
u8 CreateSpriteAtEnd(const struct SpriteTemplate *template, s16 x, s16 y, u8 subpriority);
u8 CreateInvisibleSprite(void (*callback)(struct Sprite *));
u8 CreateSpriteAndAnimate(const struct SpriteTemplate *template, s16 x, s16 y, u8 subpriority);
void DestroySprite(struct Sprite *sprite);
void ResetOamRange(u8 start, u8 end);
void LoadOam(void);
void SetOamMatrix(u8 matrixNum, u16 a, u16 b, u16 c, u16 d);
void CalcCenterToCornerVec(struct Sprite *sprite, u8 shape, u8 size, u8 affineMode);
void SpriteCallbackDummy(struct Sprite *sprite);
void ProcessSpriteCopyRequests(void);
void RequestSpriteCopy(const u8 *src, u8 *dest, u16 size);
void FreeSpriteTiles(struct Sprite *sprite);
void FreeSpritePalette(struct Sprite *sprite);
void FreeSpriteOamMatrix(struct Sprite *sprite);
void DestroySpriteAndFreeResources(struct Sprite *sprite);
void AnimateSprite(struct Sprite *sprite);
void SetSpriteMatrixAnchor(struct Sprite* sprite, s16 x, s16 y);
void StartSpriteAnim(struct Sprite *sprite, u8 animNum);
void StartSpriteAnimIfDifferent(struct Sprite *sprite, u8 animNum);
void SeekSpriteAnim(struct Sprite *sprite, u8 animCmdIndex);
void StartSpriteAffineAnim(struct Sprite *sprite, u8 animNum);
void StartSpriteAffineAnimIfDifferent(struct Sprite *sprite, u8 animNum);
void ChangeSpriteAffineAnim(struct Sprite *sprite, u8 animNum);
void ChangeSpriteAffineAnimIfDifferent(struct Sprite *sprite, u8 animNum);
void SetSpriteSheetFrameTileNum(struct Sprite *sprite);
u8 AllocOamMatrix(void);
void FreeOamMatrix(u8 matrixNum);
void InitSpriteAffineAnim(struct Sprite *sprite);
void SetOamMatrixRotationScaling(u8 matrixNum, s16 xScale, s16 yScale, u16 rotation);
u16 LoadSpriteSheet(const struct SpriteSheet *sheet);
void LoadSpriteSheets(const struct SpriteSheet *sheets);
u16 AllocTilesForSpriteSheet(struct SpriteSheet *sheet);
void AllocTilesForSpriteSheets(struct SpriteSheet *sheets);
void LoadTilesForSpriteSheet(const struct SpriteSheet *sheet);
void LoadTilesForSpriteSheets(struct SpriteSheet *sheets);
void FreeSpriteTilesByTag(u16 tag);
void FreeSpriteTileRanges(void);
u16 GetSpriteTileStartByTag(u16 tag);
u16 GetSpriteTileTagByTileStart(u16 start);
void RequestSpriteSheetCopy(const struct SpriteSheet *sheet);
u16 LoadSpriteSheetDeferred(const struct SpriteSheet *sheet);
void FreeAllSpritePalettes(void);
u8 LoadSpritePalette(const struct SpritePalette *palette);
void LoadSpritePalettes(const struct SpritePalette *palettes);
u8 AllocSpritePalette(u16 tag);
u8 IndexOfSpritePaletteTag(u16 tag);
u16 GetSpritePaletteTagByPaletteNum(u8 paletteNum);
void FreeSpritePaletteByTag(u16 tag);
void SetSubspriteTables(struct Sprite *sprite, const struct SubspriteTable *subspriteTables);
bool8 AddSpriteToOamBuffer(struct Sprite *object, u8 *oamIndex);
bool8 AddSubspritesToOamBuffer(struct Sprite *sprite, struct OamData *destOam, u8 *oamIndex);
void CopyToSprites(u8 *src);
void CopyFromSprites(u8 *dest);
u8 SpriteTileAllocBitmapOp(u16 bit, u8 op);
void ClearSpriteCopyRequests(void);
void ResetAffineAnimData(void);
#endif //GUARD_SPRITE_H