#ifndef GUARD_SPRITE_H #define GUARD_SPRITE_H #define MAX_SPRITES 64 struct SpriteSheet { const u8 *data; // Raw uncompressed pixel data u16 size; u16 tag; }; struct CompressedSpriteSheet { const u8 *data; // LZ77 compressed pixel data u16 size; // Uncompressed size of pixel data u16 tag; }; struct SpriteFrameImage { const u8 *data; u16 size; }; #define obj_frame_tiles(ptr) {.data = (u8 *)ptr, .size = sizeof ptr} struct SpritePalette { const u16 *data; // Raw uncompressed palette data u16 tag; }; struct CompressedSpritePalette { const u8 *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; }; union AffineAnimCmd { s16 type; struct AffineAnimFrameCmd frame; struct AffineAnimLoopCmd loop; struct AffineAnimJumpCmd jump; }; #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_LOOP(_count) \ {.loop = {.type = AFFINEANIMCMDTYPE_LOOP, .count = _count}} #define AFFINEANIMCMD_JUMP(_target) \ {.jump = {.type = AFFINEANIMCMDTYPE_JUMP, .target = _target}} 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; struct SpriteTemplate { u16 tileTag; u16 paletteTag; const struct OamData *oam; const union AnimCmd *const *anims; const struct SpriteFrameImage *images; const union AffineAnimCmd *const *affineAnims; void (*callback)(struct Sprite *); }; 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*/ void (*callback)(struct Sprite *); /*0x20*/ struct Coords16 pos1; /*0x24*/ struct Coords16 pos2; /*0x28*/ s8 centerToCornerVecX; /*0x29*/ s8 centerToCornerVecY; /*0x2A*/ u8 animNum; /*0x2B*/ u8 animCmdIndex; /*0x2C*/ u8 animDelayCounter:6; u8 animPaused:1; u8 affineAnimPaused:1; /*0x2D*/ u8 animLoopCounter; // general purpose data fields /*0x2E*/ s16 data[8]; /*0x3E*/ u16 inUse:1; //1 u16 coordOffsetEnabled:1; //2 u16 invisible:1; //4 u16 flags_3:1; //8 u16 flags_4:1; //0x10 u16 flags_5:1; //0x20 u16 flags_6:1; //0x40 u16 flags_7:1; //0x80 /*0x3F*/ u16 hFlip:1; //1 u16 vFlip:1; //2 u16 animBeginning:1; //4 u16 affineAnimBeginning:1; //8 u16 animEnded:1; //0x10 u16 affineAnimEnded:1; //0x20 u16 usingSheet:1; //0x40 u16 flags_f: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 s16 gSpriteCoordOffsetX; extern s16 gSpriteCoordOffsetY; extern struct Sprite gSprites[]; 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 a, u8 b); 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 sub_800142C(u32 a1, u32 a2, u16 *a3, u16 a4, u32 a5); void AnimateSprite(struct Sprite *sprite); 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