/** * \file sprite_eng.h * \brief Sprite engine * \author Stephane Dallongeville * \date 10/2013 * * Sprite engine providing advanced sprites manipulation and operations.
* This unit use both the vram memory manager (see vram.h file for more info)
* and the Sega Genesis VDP sprite capabilities (see vdp_spr.h file for more info). */ #if !LEGACY_SPRITE_ENGINE #ifndef _SPRITE_ENG_H_ #define _SPRITE_ENG_H_ #include "vdp_tile.h" #include "vdp_spr.h" #include "pal.h" #include "pool.h" /** * \brief * No collision type */ #define COLLISION_TYPE_NONE 0 /** * \brief * Bouding box collision type (Box structure) */ #define COLLISION_TYPE_BOX 1 /** * \brief * Round circle collision type (Circle structure) */ #define COLLISION_TYPE_CIRCLE 2 /** * \brief * Special flag to indicate that we want to add the sprite at position 0 (head / top) in the list
* instead of adding it in last / bottom position (default) */ #define SPR_FLAG_INSERT_HEAD 0x4000 /** * \brief * Disable animation auto loop.
* By default animation always restart after the last frame has been played. * This flag prevent the animation to restart and so the animation end on the last frame forever (see #SPR_getAnimationDone(..)) */ #define SPR_FLAG_DISABLE_ANIMATION_LOOP 0x2000 /** * \brief * Disable delaying of frame update when we are running out of DMA capacity.
* By default we delay the frame update when DMA is already full so the frame update happen as soon we have enough DMA capacity to do it. * This flag forces frame update to always happen immediately but that may cause graphical glitches. */ #define SPR_FLAG_DISABLE_DELAYED_FRAME_UPDATE 0x1000 /** * \brief * Enable automatic VRAM allocation */ #define SPR_FLAG_AUTO_VRAM_ALLOC 0x0800 /** * \brief * Enable automatic upload of sprite tiles data into VRAM */ #define SPR_FLAG_AUTO_TILE_UPLOAD 0x0400 /** * \brief * Enable automatic visibility calculation */ #define SPR_FLAG_AUTO_VISIBILITY 0x0200 /** * \brief * Enable fast visibility calculation (only meaningful if SPR_FLAG_AUTO_VISIBILITY is used).
* If you set this flag the automatic visibility calculation will be done globally for the (meta) sprite and not per internal * hardware sprite. This result in faster visibility computation at the expense of using extra (wasting) hardware sprites. */ #define SPR_FLAG_FAST_AUTO_VISIBILITY 0x0100 /** * \brief * Mask for sprite flag */ #define SPR_FLAG_MASK (SPR_FLAG_INSERT_HEAD | SPR_FLAG_DISABLE_DELAYED_FRAME_UPDATE | SPR_FLAG_AUTO_VRAM_ALLOC | SPR_FLAG_AUTO_TILE_UPLOAD | SPR_FLAG_AUTO_VISIBILITY | SPR_FLAG_FAST_AUTO_VISIBILITY) /** * \brief * Minimum depth for a sprite (always above others sprites) */ #define SPR_MIN_DEPTH (-0x8000) /** * \brief * Maximum depth for a sprite (always below others sprites) */ #define SPR_MAX_DEPTH 0x7FFF /** * \brief * Sprite visibility enumeration */ typedef enum { VISIBLE, /**< Sprite is visible (no computation needed) */ HIDDEN, /**< Sprite is hidden (no computation needed) */ AUTO_FAST, /**< Automatic visibility calculation - FAST (computation made on global meta sprite) */ AUTO_SLOW, /**< Automatic visibility calculation - SLOW (computation made per hardware sprite) */ } SpriteVisibility; /** * \brief * Simple Box structure for collision * * \param x * X position (left) * \param y * Y position (top) * \param w * width * \param h * heigth */ typedef struct { s8 x; s8 y; u8 w; u8 h; } BoxCollision; /** * \brief * Simple Circle structure (can be used for collision detection) * * \param x * X center position * \param y * Y center position * \param ray * circle ray */ typedef struct { s8 x; s8 y; u16 ray; } CircleCollision; /** * \struct Collision * \brief * Collision definition union. * * \param typeHit * Collision type for hit collision:
* Allowed values are #COLLISION_TYPE_BOX or #COLLISION_TYPE_CIRCLE. * \param typeAttack * Collision type for attack collision (can be used as alternative hit collision):
* Allowed values are #COLLISION_TYPE_BOX or #COLLISION_TYPE_CIRCLE. * \param box * BoxCollision definition if type = #COLLISION_TYPE_BOX * \param circle * CircleCollision definition if type = #COLLISION_TYPE_CIRCLE * \param inner * if current collision is verified then we test inner for more precise collision if needed * \param next * if current collision is not verified then we test next for next collision if needed */ typedef struct _collision { u8 typeHit; u8 typeAttack; union { BoxCollision box; CircleCollision circle; } hit; union { BoxCollision box; CircleCollision circle; } attack; } Collision; /** * \brief * Single VDP sprite info structure for sprite animation frame. * * \param offsetY * Y offset for this VDP sprite relative to global Sprite position * \param offsetYFlip * Y offset (flip version) for this VDP sprite relative to global Sprite position * \param size * sprite size (see SPRITE_SIZE macro) * \param offsetX * X offset for this VDP sprite relative to global Sprite position * \param offsetXFlip * X offset (flip version) for this VDP sprite relative to global Sprite position * \param numTile * number of tile for this VDP sprite (should be coherent with the given size field) */ typedef struct { u8 offsetY; // respect VDP sprite field order, may help u8 offsetYFlip; u8 size; u8 offsetX; u8 offsetXFlip; u8 numTile; } FrameVDPSprite; /** * \brief * Sprite animation frame structure. * * \param numSprite * number of VDP sprite which compose this frame. * bit 7 is used as a special flag for the sprite engine so always use 'numSprite & 0x7F' to just retrieve the number of sprite * \param timer * active time for this frame (in 1/60 of second) * \param tileset * tileset containing tiles for this animation frame (ordered for sprite) * \param collision * collision structure (not used currently) * \param frameSprites * array of VDP sprites info composing the frame */ typedef struct { s8 numSprite; u8 timer; TileSet* tileset; // TODO: have a tileset per VDP sprite --> probably not a good idea performance wise Collision* collision; // Require many DMA queue operations and fast DMA flush as well, also bring extra computing in calculating delayed update FrameVDPSprite frameVDPSprites[]; } AnimationFrame; /** * \brief * Sprite animation structure. * * \param numFrame * number of different frame for this animation (max = 255) * \param loop * frame index for loop (last index if no loop) * \param frames * frames composing the animation */ typedef struct { u8 numFrame; u8 loop; AnimationFrame** frames; } Animation; /** * \brief * Sprite definition structure. * * \param w * frame cell width in pixel * \param h * frame cell height in pixel * \param palette * default palette data * \param numAnimation * number of animation for this sprite * \param animations * animation definitions * \param maxNumTile * maximum number of tile used by a single animation frame (used for VRAM tile space allocation) * \param maxNumSprite * maximum number of VDP sprite used by a single animation frame (used for VDP sprite allocation) * * Contains all animations for a Sprite and internal informations. */ typedef struct { u16 w; u16 h; Palette* palette; u16 numAnimation; Animation** animations; u16 maxNumTile; u16 maxNumSprite; } SpriteDefinition; /** * \brief * Sprite structure used by the Sprite Engine to store state for a sprite.
* WARNING: always use the #SPR_addSprite(..) method to allocate Sprite object.
* * \param status * Internal state and automatic allocation information (internal) * \param visibility * visibility information of current frame for each VDP sprite (max = 16) * \param spriteDef * Sprite definition pointer * \param onFrameChange * Custom callback on frame change event (see #SPR_setFrameChangeCallback(..) method) * \param animation * Animation pointer cache (internal) * \param frame * AnimationFrame pointer cache (internal) * \param animInd * current animation index (internal) * \param frameInd * current frame animation index (internal) * \param timer * timer for current frame (internal) * \param x * current sprite X position on screen offseted by 0x80 (internal VDP position) * \param y * current sprite Y position on screen offseted by 0x80 (internal VDP position) * \param depth * current sprite depth (Z) position used for Z sorting * \param attribut * sprite specific attribut and allocated VRAM tile index (see TILE_ATTR_FULL() macro) * \param data * this is a free field for user data, use it for whatever you want (flags, pointer...) * \param prev * pointer on previous Sprite in list * \param next * pointer on next Sprite in list * * Used to manage an active sprite in game condition. */ typedef struct Sprite { u16 status; u16 visibility; const SpriteDefinition* definition; void (*onFrameChange)(struct Sprite* sprite); Animation* animation; AnimationFrame* frame; s16 animInd; s16 frameInd; s16 timer; s16 x; s16 y; s16 depth; u16 attribut; u32 data; struct Sprite* prev; struct Sprite* next; } Sprite; /** * \brief * Sprite frame change event callback.
* * \param sprite * The sprite for which frame just changed. * * This event occurs onframe change process during #SPR_update() call (CAUTION: sprite->status field is not up to date at this point).
* It let opportunity to the developer to apply special behavior or process when sprite frame just changed:
* for instance we can disable animation looping by setting sprite->timer to 0 when we meet the last animation frame. */ typedef void FrameChangeCallback(Sprite* sprite); /** * Sprites object pool for the sprite engine */ extern Pool* spritesPool; /** * First allocated sprite (NULL if no sprite allocated) */ extern Sprite* firstSprite; /** * Last allocated sprite (NULL if no sprite allocated) */ extern Sprite* lastSprite; /** * Allocated VRAM (in tile) for Sprite Engine */ extern u16 spriteVramSize; /** * \brief * Initialize the Sprite engine with default parameters. * * Initialize the sprite engine using default parameters (420 reserved tiles in VRAM).
* This also initialize the hardware sprite allocation system. * * \see SPR_initEx(void) * \see SPR_end(void) */ void SPR_init(void); /** * \brief * Init the Sprite engine with specified advanced parameters (VRAM allocation size and decompression buffer size). * * \param vramSize * size (in tile) of the VRAM region for the automatic VRAM tile allocation.
* If set to 0 the default size is used (420 tiles) * * Initialize the sprite engine.
* This allocates a VRAM region for sprite tiles and initialize hardware sprite allocation system. * * \see SPR_init(void) * \see SPR_end(void) */ void SPR_initEx(u16 vramSize); /** * \brief * End the Sprite engine. * * End the sprite engine and release attached resources.
* This releases the allocated VRAM region and hardware sprites. */ void SPR_end(void); /** * \brief * FALSE if sprite cache engine is not initialized, TRUE otherwise. */ bool SPR_isInitialized(void); /** * \brief * Reset the Sprite engine.
* * This method releases all allocated sprites and their resources. */ void SPR_reset(void); /** * \brief * Adds a new sprite with specified parameters and returns it. * * \param spriteDef * the SpriteDefinition data to assign to this sprite. * \param x * default X position. * \param y * default Y position. * \param attribut * sprite attribut (see TILE_ATTR() macro). * \param flag * specific settings for this sprite:
* #SPR_FLAG_DISABLE_DELAYED_FRAME_UPDATE = Disable delaying of frame update when we are running out of DMA capacity.
* If you set this flag then sprite frame update always happen immediately but may lead to some graphical glitches (tiles data and sprite table data not synchronized). * You can use SPR_setDelayedFrameUpdate(..) method to change this setting.
* #SPR_FLAG_AUTO_VISIBILITY = Enable automatic sprite visibility calculation (you can also use SPR_setVisibility(..) method).
* #SPR_FLAG_FAST_AUTO_VISIBILITY = Enable fast computation for the automatic visibility calculation (disabled by default)
* If you set this flag the automatic visibility calculation will be done globally for the (meta) sprite and not per internal * hardware sprite. This result in faster visibility computation at the expense of some waste of hardware sprite. * You can set the automatic visibility computation by using SPR_setVisibility(..) method.
* #SPR_FLAG_AUTO_VRAM_ALLOC = Enable automatic VRAM allocation (enabled by default)
* If you don't set this flag you will have to manually define VRAM tile index position for this sprite with the attribut parameter or by using the #SPR_setVRAMTileIndex(..) method
* #SPR_FLAG_AUTO_TILE_UPLOAD = Enable automatic upload of sprite tiles data into VRAM (enabled by default)
* If you don't set this flag you will have to manually upload tiles data of sprite into the VRAM (you can change this setting using #SPR_setAutoTileUpload(..) method).
* #SPR_FLAG_INSERT_HEAD = Allow to insert the sprite at the start/head of the list.
* When you use this flag the sprite will be inserted at the head of the list making it top most (equivalent to #SPR_setDepth(#SPR_MIN_DEPTH))
* while default insertion position is at the end of the list (equivalent to #SPR_setDepth(#SPR_MAX_DEPTH))
*
* It's recommended to use the following default settings:
* SPR_FLAG_AUTO_VISIBILITY | SPR_FLAG_AUTO_VRAM_ALLOC | SPR_FLAG_AUTO_TILE_UPLOAD
* \return the new sprite or NULL if the operation failed (some logs can be generated in the KMod console in this case) * * By default the sprite uses the provided flag setting for automatic resources allocation and sprite visibility computation.
* If auto visibility is not enabled then sprite is considered as not visible by default (see SPR_setVisibility(..) method).
* You can release all sprite resources by using SPR_releaseSprite(..) or SPR_reset(..).
* IMPORTANT NOTE: sprite allocation can fail (return NULL) when you are using auto VRAM allocation (SPR_FLAG_AUTO_VRAM_ALLOC) even if there is enough VRAM available,
* this can happen because of the VRAM fragmentation. You can use #SPR_addSpriteExSafe(..) method instead so it take care about VRAM fragmentation. * * \see SPR_addSprite(..) * \see SPR_addSpriteExSafe(..) * \see SPR_releaseSprite(..) */ Sprite* SPR_addSpriteEx(const SpriteDefinition* spriteDef, s16 x, s16 y, u16 attribut, u16 flag); /** * \brief * Adds a new sprite with auto resource allocation enabled and returns it. * * \param spriteDef * the SpriteDefinition data to assign to this sprite. * \param x * default X position. * \param y * default Y position. * \param attribut * sprite attribut (see TILE_ATTR() macro). * \return the new sprite or NULL if the operation failed (some logs can be generated in the KMod console in this case) * * By default the sprite uses automatic resources allocation (VRAM and hardware sprite) and visibility is set to ON.
* You can change these defaults settings later by calling SPR_setVRAMTileIndex(..), SPR_setAutoTileUpload(..) and SPR_setVisibility(..) methods.
* You can release all sprite resources by using SPR_releaseSprite(..) or SPR_reset(..).
* IMPORTANT NOTE: sprite allocation can fail (return NULL) because of automatic VRAM allocation even if there is enough VRAM available, * this can happen because of the VRAM fragmentation.
You can use #SPR_addSpriteSafe(..) method instead so it take care about VRAM fragmentation. * * \see SPR_addSpriteEx(..) * \see SPR_addSpriteSafe(..) * \see SPR_releaseSprite(..) */ Sprite* SPR_addSprite(const SpriteDefinition* spriteDef, s16 x, s16 y, u16 attribut); /** * \brief * Adds a new sprite with specified parameters and returns it. * * \param spriteDef * the SpriteDefinition data to assign to this sprite. * \param x * default X position. * \param y * default Y position. * \param attribut * sprite attribut (see TILE_ATTR() macro). * \param flag * specific settings for this sprite:
* #SPR_FLAG_DISABLE_DELAYED_FRAME_UPDATE = Disable delaying of frame update when we are running out of DMA capacity.
* If you set this flag then sprite frame update always happen immediately but may lead to some graphical glitches (tiles data and sprite table data not synchronized). * You can use SPR_setDelayedFrameUpdate(..) method to change this setting.
* #SPR_FLAG_AUTO_VISIBILITY = Enable automatic sprite visibility calculation (you can also use SPR_setVisibility(..) method).
* #SPR_FLAG_FAST_AUTO_VISIBILITY = Enable fast computation for the automatic visibility calculation (disabled by default)
* If you set this flag the automatic visibility calculation will be done globally for the (meta) sprite and not per internal * hardware sprite. This result in faster visibility computation at the expense of some waste of hardware sprite (scanline limit). * You can set the automatic visibility computation by using SPR_setVisibility(..) method.
* #SPR_FLAG_AUTO_VRAM_ALLOC = Enable automatic VRAM allocation (enabled by default)
* If you don't set this flag you will have to manually define VRAM tile index position for this sprite with the attribut parameter or by using the #SPR_setVRAMTileIndex(..) method
* #SPR_FLAG_AUTO_TILE_UPLOAD = Enable automatic upload of sprite tiles data into VRAM (enabled by default)
* If you don't set this flag you will have to manually upload tiles data of sprite into the VRAM (you can change this setting using #SPR_setAutoTileUpload(..) method).
* #SPR_FLAG_INSERT_HEAD = Allow to insert the sprite at the start/head of the list.
* When you use this flag the sprite will be inserted at the head of the list making it top most (equivalent to #SPR_setDepth(#SPR_MIN_DEPTH))
* while default insertion position is at the end of the list (equivalent to #SPR_setDepth(#SPR_MAX_DEPTH))
*
* It's recommended to use the following default settings:
* SPR_FLAG_AUTO_VISIBILITY | SPR_FLAG_AUTO_VRAM_ALLOC | SPR_FLAG_AUTO_TILE_UPLOAD
* \return the new sprite or NULL if the operation failed (some logs can be generated in the KMod console in this case) * * By default the sprite uses the provided flag setting for automatic resources allocation and sprite visibility computation.
* If auto visibility is not enabled then sprite is considered as not visible by default (see SPR_setVisibility(..) method).
* You can release all sprite resources by using SPR_releaseSprite(..) or SPR_reset(..). * * \see SPR_addSpriteSafe(..) * \see SPR_addSpriteEx(..) * \see SPR_releaseSprite(..) */ Sprite* SPR_addSpriteExSafe(const SpriteDefinition* spriteDef, s16 x, s16 y, u16 attribut, u16 flag); /** * \brief * Adds a new sprite with auto resource allocation enabled and returns it. * * \param spriteDef * the SpriteDefinition data to assign to this sprite. * \param x * default X position. * \param y * default Y position. * \param attribut * sprite attribut (see TILE_ATTR() macro). * \return the new sprite or NULL if the operation failed (some logs can be generated in the KMod console in this case) * * By default the sprite uses automatic resources allocation (VRAM and hardware sprite) and visibility is set to ON.
* You can change these defaults settings later by calling SPR_setVRAMTileIndex(..), SPR_setAutoTileUpload(..) and SPR_setVisibility(..) methods.
* You can release all sprite resources by using SPR_releaseSprite(..) or SPR_reset(..).< * * \see SPR_addSpriteSafeEx(..) * \see SPR_addSprite(..) * \see SPR_releaseSprite(..) */ Sprite* SPR_addSpriteSafe(const SpriteDefinition* spriteDef, s16 x, s16 y, u16 attribut); /** * \brief * Release the specified sprite (no more visible and release its resources). * * \param sprite * Sprite to release * * This method release resources for the specified Sprite object and remove it from the screen at next SPR_update() call. * * \see SPR_releasesSprite(..) */ void SPR_releaseSprite(Sprite* sprite); /** * \brief * Returns the number of active sprite (number of sprite added with SPR_addSprite(..) or SPR_addSpriteEx(..) methods). */ u16 SPR_getNumActiveSprite(void); /** * \brief * Returns the (maximum) number of used VDP sprite from current active sprites (sum of maximum hardware sprite usage from all active sprites). */ u16 SPR_getUsedVDPSprite(void); /** * \brief * Returns the current remaining free VRAM (in tile) for the sprite engine. */ u16 SPR_getFreeVRAM(void); /** * \brief * Return the current largest free VRAM block size (in tile) for the sprite engine. */ u16 SPR_getLargestFreeVRAMBlock(void); /** * \brief * Indicate that we want to prevent adding a new sprite if there is possibly not enough hardware sprite to display it * (counting the maximum hardware sprite usage from all active sprites) and so this ensures to always display all of them.
* By default the sprite engine allow to add a new sprite even if we may run out of hardware sprite to display all of them, * that can lead to some sprite disappearence in some situations but ultimately it allows to handle more active sprites at once. * * \see SPR_disableVDPSpriteChecking(..) * \see SPR_getNumVDPSprite(..) */ void SPR_enableVDPSpriteChecking(); /** * \brief * Indicate that we allow the sprite engine to add a new sprite even if we may run out of hardware sprite to display all of them, * that can lead to some sprite disappearence in some situation but ultimately it allows to handle more active sprites at once (default behavior). * * \see SPR_enableVDPSpriteChecking(..) * \see SPR_getNumVDPSprite(..) */ void SPR_disableVDPSpriteChecking(); /** * \brief * Defragment allocated VRAM for sprites, that can help when sprite allocation fail (SPR_addSprite(..) or SPR_addSpriteEx(..) return NULL). */ void SPR_defragVRAM(void); /** * \brief * Load all frames of SpriteDefinition using DMA at specified VRAM tile index and return the indexes table.
* WARNING: This function should be call at init/loading time as it can be quite long (several frames) * * \param sprDef * the SpriteDefinition we want to load frame data in VRAM. * \param index * the tile position in VRAM where we will upload all sprite frame tiles data. * \param totalNumTile * if not NULL then the function will store here the total number of tile used to load all animation frames. * \param tm * Transfer method to upload sprite frame data.
* Accepted values are:
* - CPU
* - DMA
* - DMA_QUEUE
* - DMA_QUEUE_COPY
* * Load all frames of spriteDef at specified VRAM tile index and return the indexes table.
* The returned index table is a dynamically allocated 2D table[anim][frame] so you need to release it using #MEM_free(..) * when you don't need the table anymore.
* You can use the frame change callback (see #SPR_setFrameChangeCallback(..)) to automatically update the VRAM index using the indexes table:
* frameIndexes = SPR_loadAllFrames(sprite->definition, ind);
* SPR_setFrameChangeCallback(sprite, &frameChanged);
* ....
* void frameChanged(Sprite* sprite)
* {
* u16 tileIndex = frameIndexes[sprite->animInd][sprite->frameInd];
* SPR_setVRAMTileIndex(sprite, tileIndex);
* }
* * \return the 2D indexes table or NULL if there is not enough memory to allocate the table. * \see SPR_setFrameChangeCallback(...); */ u16** SPR_loadAllFramesEx(const SpriteDefinition* sprDef, u16 index, u16* totalNumTile, TransferMethod tm); /** * \brief * Same as all frames of SpriteDefinition at specified VRAM tile index and return the indexes table.
* WARNING: This function should be call at init/loading time as it can be quite long (several frames) * * \param sprDef * the SpriteDefinition we want to load frame data in VRAM. * \param index * the tile position in VRAM where we will upload all sprite frame tiles data. * \param totalNumTile * if not NULL then the function will store here the total number of tile used to load all animation frames. * * Load all frames of spriteDef (using DMA) at specified VRAM tile index and return the indexes table.
* The returned index table is a dynamically allocated 2D table[anim][frame] so you need to release it using #MEM_free(..) * when you don't need the table anymore.
* You can use the frame change callback (see #SPR_setFrameChangeCallback(..)) to automatically update the VRAM index using the indexes table:
* frameIndexes = SPR_loadAllFrames(sprite->definition, ind);
* SPR_setFrameChangeCallback(sprite, &frameChanged);
* ....
* void frameChanged(Sprite* sprite)
* {
* u16 tileIndex = frameIndexes[sprite->animInd][sprite->frameInd];
* SPR_setVRAMTileIndex(sprite, tileIndex);
* }
* * \return the 2D indexes table or NULL if there is not enough memory to allocate the table. * \see SPR_setFrameChangeCallback(...); */ u16** SPR_loadAllFrames(const SpriteDefinition* sprDef, u16 index, u16* totalNumTile); /** * \brief * Same as #SPR_loadAllFrames(..) but only computes the indexes table without actually loading the Sprite frame data to VRAM (see #SPR_loadAllTiles(..) for that). * * \param sprDef * the SpriteDefinition we want to compute the indexes table. * \param index * the tile position in VRAM where we want to upload all sprite frame data (note that VRAM data upload won't be done here). * \param totalNumTile * if not NULL then the function will store here the total number of tile used to load all animation frames. * * \return the 2D indexes table or NULL if there is not enough memory to allocate the table. * \see SPR_loadAllFrames(...) * \see SPR_loadAllTiles(...) */ u16** SPR_loadAllIndexes(const SpriteDefinition* sprDef, u16 index, u16* totalNumTile); /** * \brief * Same as #SPR_loadAllFrames(..) but only perform the Sprite tile data upload process, SPR_loadAllIndexes(..) should be called first to compute the indexes table. * * \param sprDef * the SpriteDefinition we want to load frame data in VRAM. * \param index * the tile position in VRAM where we will upload all sprite frame tiles data. * \param index * the 2D indexes table providing the tile index position in VRAM for each sprite frame (previously build using #SPR_loadAllIndexes(..) method). * \param tm * Transfer method to upload sprite frame data.
* Accepted values are:
* - CPU
* - DMA
* - DMA_QUEUE
* - DMA_QUEUE_COPY
* * \return the number of tile uploaded to VRAM. * \see SPR_loadAllFrames(...) * \see SPR_loadAllIndexes(...) */ u16 SPR_loadAllTiles(const SpriteDefinition* sprDef, u16 index, u16** indexes, const TransferMethod tm); /** * \brief * Set the Sprite Definition. * * \param sprite * Sprite to set definition for. * \param spriteDef * the SpriteDefinition data to assign to this sprite. * * Set the Sprite Definition for this sprite.
* By default the first frame of the first animation from Sprite Definition is loaded. * * \return FALSE if auto resource allocation failed, TRUE otherwise. */ bool SPR_setDefinition(Sprite* sprite, const SpriteDefinition* spriteDef); /** * \brief * Get sprite position X. */ s16 SPR_getPositionX(Sprite* sprite); /** * \brief * Get sprite position Y. */ s16 SPR_getPositionY(Sprite* sprite); /** * \brief * Set sprite position. * * \param sprite * Sprite to set position for * \param x * X position * \param y * Y position */ void SPR_setPosition(Sprite* sprite, s16 x, s16 y); /** * \brief * Set sprite Horizontal Flip attribut. * * \param sprite * Sprite to set attribut for * \param value * The horizontal flip attribut value (TRUE or FALSE) */ void SPR_setHFlip(Sprite* sprite, bool value); /** * \brief * Set sprite Vertical Flip attribut. * * \param sprite * Sprite to set attribut for * \param value * The vertical flip attribut value (TRUE or FALSE) */ void SPR_setVFlip(Sprite* sprite, bool value); /** * \brief * Set sprite Palette index to use. * * \param sprite * Sprite to set attribut for * \param value * The palette index to use for this sprite (PAL0, PAL1, PAL2 or PAL3) */ void SPR_setPalette(Sprite* sprite, u16 value); /** * \brief * Set sprite Priority attribut. * * \param sprite * Sprite to set attribut for * \param value * The priority attribut value (TRUE or FALSE) */ void SPR_setPriority(Sprite* sprite, bool value); /** * \deprecated * Use #SPR_setPriority(..) instead */ #define SPR_setPriorityAttribut(sprite, value) _Pragma("GCC error \"This method is deprecated, use SPR_setPriority(..) instead.\"") /** * \brief * Set sprite depth (for sprite display ordering) * * \param sprite * Sprite to set depth for * \param value * The depth value (SPR_MIN_DEPTH to set always on top) * * Sprite having lower depth are display in front of sprite with higher depth.
* The sprite is *immediately* sorted when its depth value is changed. */ void SPR_setDepth(Sprite* sprite, s16 value); /** * \brief * Same as #SPR_setDepth(..) */ void SPR_setZ(Sprite* sprite, s16 value); /** * \brief * Set sprite depth so it remains above others sprite - same as SPR_setDepth(SPR_MIN_DEPTH) * * \param sprite * Sprite to change depth for * * \see SPR_setDepth(Sprite*) */ void SPR_setAlwaysOnTop(Sprite* sprite); /** * \brief * Set sprite depth so it remains behind others sprite - same as SPR_setDepth(SPR_MAX_DEPTH) * * \param sprite * Sprite to change depth for * * \see SPR_setDepth(Sprite*) */ void SPR_setAlwaysAtBottom(Sprite* sprite); /** * \brief * Set current sprite animation and frame. * * \param sprite * Sprite to set animation and frame for * \param anim * animation index to set * \param frame * frame index to set */ void SPR_setAnimAndFrame(Sprite* sprite, s16 anim, s16 frame); /** * \brief * Set current sprite animation. * * \param sprite * Sprite to set animation for * \param anim * animation index to set. */ void SPR_setAnim(Sprite* sprite, s16 anim); /** * \brief * Set current sprite frame. * * \param sprite * Sprite to set frame for * \param frame * frame index to set. */ void SPR_setFrame(Sprite* sprite, s16 frame); /** * \brief * Pass to the next sprite frame. * * \param sprite * Sprite to pass to next frame for */ void SPR_nextFrame(Sprite* sprite); /** * \brief * Enable/disable auto animation for the current animation (default is on).
* * \param sprite * Sprite we want to enable/disable auto animation. * \param value * TRUE to enable auto animation (default), FALSE otherwise * * \see #SPR_getAutoAnimation(Sprite*) */ void SPR_setAutoAnimation(Sprite* sprite, bool value); /** * \brief * Return TRUE if auto animation is enabled, FALSE otherwise. * * \see #SPR_setAnimationLoop(Sprite*, bool) */ bool SPR_getAutoAnimation(Sprite* sprite); /** * \brief * Enable/disable animation loop (default is on).
* When disable the sprite will stay on the last animation frame when animation ended instead of restarting it. * * \param sprite * Sprite we want to enable/disable animation loop for. * \param value * TRUE to enable animation loop (default), FALSE otherwise * * \see SPR_FLAG_DISABLE_ANIMATION_LOOP * \see #SPR_getAnimationDone(Sprite*) */ void SPR_setAnimationLoop(Sprite* sprite, bool value); /** * \brief * Returns TRUE if the sprite reached the end of the current animation.
* When auto animation is enabled (see SPR_setAutoAnimation(..)) the function returns TRUE only when we reached * the last *tick* of the last animation frame.
* When auto animation is disabled the function returns TRUE as soon we are on last animation frame. * * \see #SPR_setAutoAnimation(Sprite*, bool) */ bool SPR_isAnimationDone(Sprite* sprite); /** * \brief * Set the VRAM tile position reserved for this sprite. * * \param sprite * Sprite to set the VRAM tile position for * \param value * the tile position in VRAM where we will upload the sprite tiles data.
* Use -1 for auto allocation.
* \return FALSE if auto allocation failed (can happen only if sprite is currently active), TRUE otherwise * * By default the Sprite Engine auto allocate VRAM for sprites tiles but you can force * manual allocation and fix the sprite tiles position in VRAM with this method. */ bool SPR_setVRAMTileIndex(Sprite* sprite, s16 value); /** * \brief * Enable/disable the automatic upload of sprite tiles data into VRAM. * * \param sprite * Sprite we want to enable/disable auto tile upload for * \param value * TRUE to enable the automatic upload of sprite tiles data into VRAM.
* FALSE to disable it (mean you have to handle that on your own).
*/ void SPR_setAutoTileUpload(Sprite* sprite, bool value); /** * \brief * Enable/disable the delayed frame update. * * \param sprite * Sprite we want to enable/disable delayed frame update * \param value * TRUE to enable the delayed frame update when DMA is running out of transfert capacity (default).
* FALSE to disable it. In which case sprite frame is always updated immediately but that may cause graphical glitches (update during active display).
* * \see #SPR_FLAG_DISABLE_DELAYED_FRAME_UPDATE */ void SPR_setDelayedFrameUpdate(Sprite* sprite, bool value); /** * \brief * Set the frame change event callback for this sprite. * * \param sprite * Sprite we want to set the frame change callback * \param callback * the callback (function pointer) to call when we just changed the animation frame for this sprite. * * The callback (if not NULL) will be called on frame change process during #SPR_update() call (CAUTION: sprite->status field is not up to date at this point).
* It let opportunity to the developer to apply special behavior or process when sprite frame just changed:
* for instance we can disable animation looping by setting sprite->timer to 0 when we meet the last animation frame. * * \see #FrameChangeCallback */ void SPR_setFrameChangeCallback(Sprite* sprite, FrameChangeCallback* callback); /** * \brief * Return the visibility state for this sprite.
* WARNING: this is different from SPR_isVisible(..) method, possible value are:
* SpriteVisibility.VISIBLE = sprite is visible
* SpriteVisibility.HIDDEN = sprite is not visible
* SpriteVisibility.AUTO_FAST = visibility is automatically computed - global visibility (only using sprite X position)
* SpriteVisibility.AUTO_SLOW = visibility is automatically computed - per hardware sprite visibility (only using sprite X position)
* * \param sprite * Sprite to return visibility state * * \return * the visibility state for this sprite. * * \see SPR_isVisible(...) * \see SPR_setVisibility(...) */ SpriteVisibility SPR_getVisibility(Sprite* sprite); /** * \brief * Return the visible state for this sprite (meaningful only if AUTO visibility is enabled, see #SPR_setVisibility(..) method).
* * \param sprite * Sprite to return visible state * \param recompute * Force visibility computation.
* Only required if SPR_update() wasn't called since last sprite position change (note that can force the frame update processing). * * Note that only the sprite X position is used to determine if it's visible (see #SPR_setVisibility(..) method for more information) * \return * the visible state for this sprite. * * \see SPR_setVisibility(...) */ bool SPR_isVisible(Sprite* sprite, bool recompute); /** * \brief * Set the visibility state for this sprite. * * \param sprite * Sprite to set the visibility information * \param value * Visibility value to set.
* SpriteVisibility.VISIBLE = sprite is visible
* SpriteVisibility.HIDDEN = sprite is not visible
* SpriteVisibility.AUTO_FAST = visibility is automatically computed - global visibility (only using sprite X position)
* SpriteVisibility.AUTO_SLOW = visibility is automatically computed - per hardware sprite visibility (only using sprite X position)
* * The only interest in having a sprite hidden / not visible is to avoid having it consuming scanline sprite budget:
* The VDP is limited to a maximum of 20 sprites or 320 pixels of sprite per scanline (16 sprites/256 px in H32 mode).
* If we reach this limit, following sprites won't be renderer so it's important to try to optimize the number of sprites on a single scanline.
* When a sprite is set to not visible (automatically or manually), its position is set offscreen *vertically* so it won't eat * anymore the scanline sprite rendering budget, only X position test is required for that so a sprite is determined not visible only using its X coordinate. * * \see SPR_computeVisibility(...) * \see SPR_getVisibility(...) * \see SPR_isVisible(...) */ void SPR_setVisibility(Sprite* sprite, SpriteVisibility value); /** * \deprecated Use #SPR_setVisibility(..) method instead. */ #define SPR_setAlwaysVisible(sprite, value) _Pragma("GCC error \"This method is deprecated, use SPR_setVisibility(..) instead.\"") /** * \deprecated Use #SPR_setVisibility(..) method instead. */ #define SPR_setNeverVisible(sprite, value) _Pragma("GCC error \"This method is deprecated, use SPR_setVisibility(..) instead.\"") /** * \deprecated Use SPR_isVisible(..) instead. */ #define SPR_computeVisibility(sprite) _Pragma("GCC error \"This method is deprecated, use SPR_isVisible(sprite, TRUE) instead.\"") /** * \brief * Clear all displayed sprites. * * This method allow to quickly hide all sprites (without releasing their resources).
* Sprites can be displayed again just by calling SPR_update(). */ void SPR_clear(void); /** * \brief * Update and display the active list of sprite. * * This actually updates all internal active sprites states and prepare the sprite list * cache to send it to the hardware (VDP) at Vint. * * \see #SPR_addSprite(..) */ void SPR_update(void); /** * \brief * Log the profil informations (when enabled) in the KMod message window. */ void SPR_logProfil(void); /** * \brief * Log the sprites informations (when enabled) in the KMod message window. */ void SPR_logSprites(void); #endif // _SPRITE_ENG_H_ #endif