mirror of
https://github.com/SAT-R/sa2.git
synced 2026-10-28 09:43:38 +00:00
202 lines
10 KiB
C
202 lines
10 KiB
C
#ifndef GUARD_SPRITE_H
|
|
#define GUARD_SPRITE_H
|
|
|
|
#include "core.h"
|
|
#include "rect.h"
|
|
#include "malloc_vram.h"
|
|
|
|
// TODO: Verify "(in)active" name
|
|
#define HITBOX_STATE_INACTIVE -1
|
|
#define HITBOX_IS_ACTIVE(hb) ((hb).index != HITBOX_STATE_INACTIVE)
|
|
|
|
#define SPRITE_ANIM_SPEED(speed) ((int)((float)(speed)*0x10))
|
|
#define SPRITE_OAM_ORDER(index) ((index) << 6)
|
|
#define GET_SPRITE_OAM_ORDER(s) ((((s)->oamFlags) & 0x7C0) >> 6)
|
|
|
|
typedef struct {
|
|
/* 0x00 */ s16 unk0[4];
|
|
/* 0x08 */ s16 qDirX;
|
|
/* 0x0A */ s16 qDirY;
|
|
|
|
/* 0x0C */ s16 unkC[2];
|
|
|
|
/* 0x10 */ s32 posX;
|
|
/* 0x14 */ s32 posY;
|
|
|
|
/* 0x18 */ s16 unk18[2][2];
|
|
/* 0x20 */ u16 affineIndex;
|
|
} UnkSpriteStruct;
|
|
|
|
typedef struct {
|
|
/* 0x00 */ u32 numTiles;
|
|
/* 0x04 */ AnimId anim;
|
|
/* 0x06 */ u8 variant;
|
|
} TileInfo;
|
|
|
|
// NOTE: (Only?) used by by src/game/sa2/stage/bosses/final_intro.c
|
|
typedef struct {
|
|
/* 0x00 */ void *tiles;
|
|
/* 0x04 */ AnimId anim;
|
|
/* 0x06 */ u8 variant;
|
|
} TileInfoPtr;
|
|
|
|
PACKED(TileInfo16, {
|
|
/* 0x00 */ u16 numTiles;
|
|
/* 0x02 */ AnimId anim;
|
|
/* 0x04 */ u16 variant;
|
|
});
|
|
|
|
#if (ENGINE == ENGINE_1)
|
|
typedef struct {
|
|
u32 anim : 16;
|
|
u32 variant : 8;
|
|
u32 size : 8;
|
|
} TileInfoBitfield;
|
|
|
|
// Used in the background code of Casino Paradise
|
|
// TODO: Rename TileInfoFirework!
|
|
typedef struct {
|
|
/* 0x00 */ AnimId anim;
|
|
/* 0x04 */ u8 variant;
|
|
/* 0x06 */ u8 numTiles;
|
|
} TileInfoFirework;
|
|
|
|
typedef struct {
|
|
AnimId anim;
|
|
u16 variant;
|
|
} TileInfoBarrel;
|
|
#endif
|
|
|
|
extern const u8 gOamShapesSizes[12][2];
|
|
|
|
AnimCmdResult UpdateSpriteAnimation(Sprite *);
|
|
|
|
void DisplaySprite(Sprite *);
|
|
void ProcessOamBuffers(void);
|
|
OamData *OamMalloc(u8 order);
|
|
|
|
void TransformSprite(Sprite *, SpriteTransform *);
|
|
// NOTE: Not actually unused in SA1. TODO: Align name with SA2!
|
|
void UnusedTransform(Sprite *, SpriteTransform *);
|
|
void SA2_LABEL(sub_8004E14)(Sprite *, SpriteTransform *);
|
|
void SA2_LABEL(sub_80047A0)(u16 angle, s16 p1, s16 p2, u16 affineIndex);
|
|
|
|
s16 SA2_LABEL(sub_8004418)(s16 x, s16 y);
|
|
void numToASCII(u8 digits[5], u16 number);
|
|
u32 Base10DigitsToHexNibbles(u16 num);
|
|
|
|
#if ((GAME == GAME_SA1) || (GAME == GAME_SA2))
|
|
#define GET_SPRITE_ANIM(s) ((s)->graphics.anim)
|
|
#else
|
|
#define GET_SPRITE_ANIM(s) ((s)->anim)
|
|
#endif
|
|
|
|
#define SpriteShouldUpdate(sprite) (((sprite)->prevVariant != (sprite)->variant) || ((sprite)->prevAnim != (sprite)->graphics.anim))
|
|
|
|
#define SPRITE_INIT_ANIM_IF_CHANGED(_sprite) \
|
|
if (SpriteShouldUpdate(_sprite)) { \
|
|
(_sprite)->graphics.size = 0; \
|
|
(_sprite)->prevVariant = (_sprite)->variant; \
|
|
(_sprite)->prevAnim = (_sprite)->graphics.anim; \
|
|
(_sprite)->animCursor = 0; \
|
|
(_sprite)->qAnimDelay = 0; \
|
|
SPRITE_FLAG_CLEAR(_sprite, ANIM_OVER); \
|
|
}
|
|
|
|
#define SPRITE_INIT_ANIM(_sprite, _anim, _variant, _order) \
|
|
_sprite->graphics.anim = _anim; \
|
|
_sprite->variant = _variant; \
|
|
_sprite->oamFlags = SPRITE_OAM_ORDER(_order); \
|
|
_sprite->graphics.size = 0;
|
|
|
|
#define SPRITE_INIT_SCRIPT(_sprite, _speed) \
|
|
_sprite->animCursor = 0; \
|
|
_sprite->qAnimDelay = Q(0); \
|
|
_sprite->prevVariant = -1; \
|
|
_sprite->animSpeed = SPRITE_ANIM_SPEED(_speed); \
|
|
_sprite->palId = 0; \
|
|
_sprite->hitboxes[0].index = HITBOX_STATE_INACTIVE;
|
|
|
|
#define SPRITE_INIT_ANIM_AND_SCRIPT(_sprite, _anim, _variant, _order) \
|
|
SPRITE_INIT_ANIM(_sprite, _anim, _variant, _order); \
|
|
SPRITE_INIT_SCRIPT(_sprite, 1.0);
|
|
|
|
#define SPRITE_INIT_WITH_POS(_sprite, _numTiles, _anim, _variant, _order, _priority) \
|
|
_sprite->graphics.dest = VramMalloc(_numTiles); \
|
|
SPRITE_INIT_ANIM(_sprite, _anim, _variant, _order); \
|
|
_sprite->x = 0; \
|
|
_sprite->y = 0; \
|
|
SPRITE_INIT_SCRIPT(_sprite, 1.0) \
|
|
_sprite->frameFlags = SPRITE_FLAG(PRIORITY, _priority);
|
|
|
|
#define SPRITE_INIT_WITHOUT_VRAM(_sprite, _anim, _variant, _order, _priority, _flags) \
|
|
SPRITE_INIT_ANIM_AND_SCRIPT(_sprite, _anim, _variant, _order); \
|
|
_sprite->frameFlags = (SPRITE_FLAG(PRIORITY, _priority) | (_flags));
|
|
|
|
#define SPRITE_INIT_WITHOUT_ANIM_OR_VRAM(_sprite, _order, _priority, _flags) \
|
|
_sprite->oamFlags = SPRITE_OAM_ORDER(_order); \
|
|
_sprite->graphics.size = 0; \
|
|
SPRITE_INIT_SCRIPT(_sprite, 1.0); \
|
|
_sprite->frameFlags = (SPRITE_FLAG(PRIORITY, _priority) | (_flags));
|
|
|
|
#define SPRITE_INIT_FLAGS(_sprite, _numTiles, _anim, _variant, _order, _priority, _flags) \
|
|
_sprite->graphics.dest = VramMalloc(_numTiles); \
|
|
SPRITE_INIT_WITHOUT_VRAM(_sprite, _anim, _variant, _order, _priority, _flags);
|
|
|
|
#define SPRITE_INIT(_sprite, _numTiles, _anim, _variant, _order, _priority) \
|
|
SPRITE_INIT_FLAGS(_sprite, _numTiles, _anim, _variant, _order, _priority, 0)
|
|
|
|
#define SF_SHIFT(name) (SPRITE_FLAG_SHIFT_##name)
|
|
|
|
#define SPRITE_FLAG(flagName, value) ((value) << SF_SHIFT(flagName))
|
|
|
|
#define SPRITE_FLAG_GET(sprite, flagName) (((sprite)->frameFlags & (SPRITE_FLAG_MASK_##flagName)) >> (SF_SHIFT(flagName)))
|
|
|
|
#define SPRITE_FLAG_CLEAR(sprite, flagName) (sprite)->frameFlags &= ~(SPRITE_FLAG_MASK_##flagName)
|
|
|
|
#define SPRITE_FLAG_SET(sprite, flagName) (sprite)->frameFlags |= (SPRITE_FLAG_MASK_##flagName)
|
|
|
|
#define SPRITE_FLAG_FLIP(sprite, flagName) (sprite)->frameFlags ^= (SPRITE_FLAG_MASK_##flagName)
|
|
|
|
#define SPRITE_FLAG_SET_VALUE(sprite, flagName, value) (sprite)->frameFlags |= SPRITE_FLAG(flagName, value)
|
|
|
|
#define SPRITE_FLAG_ENABLE_ROTATION(value) \
|
|
(SPRITE_FLAG(ROT_SCALE, value) | SPRITE_FLAG_MASK_ROT_SCALE_ENABLE | SPRITE_FLAG_MASK_ROT_SCALE_DOUBLE_SIZE)
|
|
|
|
#define SPRITE_FLAG_SHIFT_ROT_SCALE 0
|
|
#define SPRITE_FLAG_SHIFT_ROT_SCALE_ENABLE 5
|
|
#define SPRITE_FLAG_SHIFT_ROT_SCALE_DOUBLE_SIZE 6
|
|
#define SPRITE_FLAG_SHIFT_OBJ_MODE 7
|
|
#define SPRITE_FLAG_SHIFT_MOSAIC 9
|
|
#define SPRITE_FLAG_SHIFT_X_FLIP 10
|
|
#define SPRITE_FLAG_SHIFT_Y_FLIP 11
|
|
#define SPRITE_FLAG_SHIFT_PRIORITY 12
|
|
#define SPRITE_FLAG_SHIFT_ANIM_OVER 14
|
|
#define SPRITE_FLAG_SHIFT_BG_ID 15
|
|
#define SPRITE_FLAG_SHIFT_17 17
|
|
#define SPRITE_FLAG_SHIFT_18 18
|
|
#define SPRITE_FLAG_SHIFT_19 19
|
|
#define SPRITE_FLAG_SHIFT_26 26
|
|
#define SPRITE_FLAG_SHIFT_30 30
|
|
#define SPRITE_FLAG_SHIFT_31 31
|
|
|
|
#define SPRITE_FLAG_MASK_ROT_SCALE SPRITE_FLAG(ROT_SCALE, 0x1F) // 0x1F
|
|
#define SPRITE_FLAG_MASK_ROT_SCALE_ENABLE SPRITE_FLAG(ROT_SCALE_ENABLE, 1) // 0x20
|
|
#define SPRITE_FLAG_MASK_ROT_SCALE_DOUBLE_SIZE SPRITE_FLAG(ROT_SCALE_DOUBLE_SIZE, 1) // 0x40
|
|
|
|
#define SPRITE_FLAG_MASK_OBJ_MODE SPRITE_FLAG(OBJ_MODE, 3) // 0x180
|
|
#define SPRITE_FLAG_MASK_MOSAIC SPRITE_FLAG(MOSAIC, 1) // 0x200
|
|
#define SPRITE_FLAG_MASK_X_FLIP SPRITE_FLAG(X_FLIP, 1) // 0x400
|
|
#define SPRITE_FLAG_MASK_Y_FLIP SPRITE_FLAG(Y_FLIP, 1) // 0x800
|
|
#define SPRITE_FLAG_MASK_PRIORITY SPRITE_FLAG(PRIORITY, 3) // 0x3000
|
|
#define SPRITE_FLAG_MASK_ANIM_OVER SPRITE_FLAG(ANIM_OVER, 1)
|
|
#define SPRITE_FLAG_MASK_BG_ID SPRITE_FLAG(BG_ID, 3)
|
|
#define SPRITE_FLAG_GLOBAL_OFFSET SPRITE_FLAG(17, 1)
|
|
#define SPRITE_FLAG_MASK_18 SPRITE_FLAG(18, 1) // 0x40000
|
|
#define SPRITE_FLAG_MASK_19 SPRITE_FLAG(19, 1)
|
|
#define SPRITE_FLAG_MASK_26 SPRITE_FLAG(26, 1)
|
|
#define SPRITE_FLAG_MASK_30 SPRITE_FLAG(30, 1)
|
|
#define SPRITE_FLAG_MASK_31 SPRITE_FLAG(31, 1)
|
|
|
|
#endif
|