metasprites.h (9847B)
1/** @file gb/metasprites.h 2 3 # Metasprite support 4 5 A metasprite is a larger sprite made up from a 6 collection of smaller individual hardware sprites. 7 Different frames of the same metasprites can share 8 tile data. 9 10 The api supports metasprites in both 11 @ref SPRITES_8x8 and @ref SPRITES_8x16 mode. If 12 8x16 mode is used then the height of the metasprite 13 must be a multiple of 16. 14 15 The origin (pivot) for the metasprite is not required 16 to be in the upper left-hand corner as with regular 17 hardware sprites. 18 19 Use the @ref utility_png2asset tool to convert single 20 or multiple frames of graphics into metasprite 21 structured data for use with the ...metasprite...() 22 functions. 23 24 # Metasprites composed of variable numbers of sprites 25 26 When using png2asset, it's common for the output of 27 different frames to be composed of different numbers 28 of hardware sprites (since it's trying to create each 29 frame as efficiently as possible). Due to that, it's 30 good practice to clear out (hide) unused sprites in the 31 shadow_OAM that have been set by previous frames. 32 33 \code 34 // Example: 35 // Hide rest of the hardware sprites, because amount 36 // of sprites differ between animation frames. 37 // (where hiwater == last hardware sprite used + 1) 38 for (uint8_t i = hiwater; i < 40; i++) shadow_OAM[i].y = 0; 39 \endcode 40 41 @anchor metasprite_and_sprite_properties 42 # Metasprites and sprite properties (including cgb palette) 43 44 When the move_metasprite_*() functions are called they 45 update all properties for the affected sprites in the 46 Shadow OAM. This means any existing property flags set 47 for a sprite (CGB palette, BG/WIN priority, Tile VRAM Bank) 48 will get overwritten. 49 50 How to use sprite property flags with metasprites: 51 - Metsaprite structures can be copied into RAM so their 52 property flags can be modified at runtime. 53 - The metasprite structures can have the property flags 54 modified before compilation (such as with `-sp <props>` 55 in the @ref utility_png2asset "png2asset" tool). 56 - Update properties for the affected sprites after calling 57 a move_metasprite_*() function. 58 59 The following functions are only available for Game Boy and 60 related clone consoles due to lack of hardware support for 61 sprite flipping in other consoles. See @ref docs_consoles_supported_list 62 - @ref move_metasprite_vflip() 63 - @ref move_metasprite_hflip() 64 - @ref move_metasprite_hvflip() 65*/ 66 67#ifndef _METASPRITES_H_INCLUDE 68#define _METASPRITES_H_INCLUDE 69 70#include <gb/hardware.h> 71#include <types.h> 72#include <stdint.h> 73 74/** Metasprite sub-item structure 75 @param dy (int8_t) Y coordinate of the sprite relative to the metasprite origin (pivot) 76 @param dx (int8_t) X coordinate of the sprite relative to the metasprite origin (pivot) 77 @param dtile (uint8_t) Start tile relative to the metasprites own set of tiles 78 @param props (uint8_t) Property Flags 79 80 Metasprites are built from multiple metasprite_t items (one for each sub-sprite) 81 and a pool of tiles they reference. If a metasprite has multiple frames then each 82 frame will be built from some number of metasprite_t items (which may vary based 83 on how many sprites are required for that particular frame). 84 85 A metasprite frame is terminated with a {metasprite_end} entry. 86*/ 87typedef struct metasprite_t { 88 int8_t dy, dx; 89 uint8_t dtile; 90 uint8_t props; 91} metasprite_t; 92 93#define metasprite_end -128 94#define METASPR_ITEM(dy,dx,dt,a) {(dy),(dx),(dt),(a)} 95#define METASPR_TERM {metasprite_end} 96 97extern const void * __current_metasprite; 98extern uint8_t __current_base_tile; 99extern uint8_t __render_shadow_OAM; 100 101 102static uint8_t __move_metasprite(uint8_t id, uint8_t x, uint8_t y) OLDCALL; 103static uint8_t __move_metasprite_vflip(uint8_t id, uint8_t x, uint8_t y) OLDCALL; 104static uint8_t __move_metasprite_hflip(uint8_t id, uint8_t x, uint8_t y) OLDCALL; 105static uint8_t __move_metasprite_hvflip(uint8_t id, uint8_t x, uint8_t y) OLDCALL; 106static void __hide_metasprite(uint8_t id) OLDCALL; 107 108/** 109 * Hides all hardware sprites in range from <= X < to 110 * @param from start OAM index 111 * @param to finish OAM index 112 */ 113void hide_sprites_range(UINT8 from, UINT8 to) OLDCALL PRESERVES_REGS(b, c); 114 115/** Moves metasprite to the absolute position x and y 116 117 @param metasprite Pointer to the first struct of the metasprite (for the desired frame) 118 @param base_tile Number of the first tile where the metasprite's tiles start 119 @param base_sprite Number of the first hardware sprite to be used by the metasprite 120 @param x Absolute x coordinate of the sprite 121 @param y Absolute y coordinate of the sprite 122 123 Moves __metasprite__ to the absolute position __x__ and __y__ 124 (with __no flip__ on the X or Y axis). Hardware sprites are 125 allocated starting from __base_sprite__, using tiles 126 starting from __base_tile__. 127 128 Sets: 129 \li __current_metasprite = metasprite; 130 \li __current_base_tile = base_tile; 131 132 Note: Overwrites OAM sprite properties (such as CGB Palette), see 133 @ref metasprite_and_sprite_properties "Metasprites and sprite properties". 134 135 @return Number of hardware sprites used to draw this metasprite 136 */ 137inline uint8_t move_metasprite(const metasprite_t * metasprite, uint8_t base_tile, uint8_t base_sprite, uint8_t x, uint8_t y) { 138 __current_metasprite = metasprite; 139 __current_base_tile = base_tile; 140 return __move_metasprite(base_sprite, x, y); 141} 142 143/** Moves metasprite to the absolute position x and y, __flipped on the Y axis__ 144 145 @param metasprite Pointer to the first struct of the metasprite (for the desired frame) 146 @param base_tile Number of the first tile where the metasprite's tiles start 147 @param base_sprite Number of the first hardware sprite to be used by the metasprite 148 @param x Absolute x coordinate of the sprite 149 @param y Absolute y coordinate of the sprite 150 151 Same as @ref move_metasprite(), but with the metasprite flipped on the Y axis only. 152 153 Sets: 154 \li __current_metasprite = metasprite; 155 \li __current_base_tile = base_tile; 156 157 Note: Overwrites OAM sprite properties (such as CGB palette), see 158 @ref metasprite_and_sprite_properties "Metasprites and sprite properties". 159 160 This function is only available on Game Boy and related clone consoles. 161 162 @return Number of hardware sprites used to draw this metasprite 163 164 @see move_metasprite() 165*/ 166inline uint8_t move_metasprite_vflip(const metasprite_t * metasprite, uint8_t base_tile, uint8_t base_sprite, uint8_t x, uint8_t y) { 167 __current_metasprite = metasprite; 168 __current_base_tile = base_tile; 169 return __move_metasprite_vflip(base_sprite, x - 8, y); 170} 171 172 173/** Moves metasprite to the absolute position x and y, __flipped on the X axis__ 174 175 @param metasprite Pointer to the first struct of the metasprite (for the desired frame) 176 @param base_tile Number of the first tile where the metasprite's tiles start 177 @param base_sprite Number of the first hardware sprite to be used by the metasprite 178 @param x Absolute x coordinate of the sprite 179 @param y Absolute y coordinate of the sprite 180 181 Same as @ref move_metasprite(), but with the metasprite flipped on the X axis only. 182 183 Sets: 184 \li __current_metasprite = metasprite; 185 \li __current_base_tile = base_tile; 186 187 Note: Overwrites OAM sprite properties (such as CGB palette), see 188 @ref metasprite_and_sprite_properties "Metasprites and sprite properties". 189 190 This function is only available on Game Boy and related clone consoles. 191 192 @return Number of hardware sprites used to draw this metasprite 193 194 @see move_metasprite() 195*/ 196inline uint8_t move_metasprite_hflip(const metasprite_t * metasprite, uint8_t base_tile, uint8_t base_sprite, uint8_t x, uint8_t y) { 197 __current_metasprite = metasprite; 198 __current_base_tile = base_tile; 199 return __move_metasprite_hflip(base_sprite, x, y - ((LCDC_REG & 0x04U) ? 16 : 8) ); 200} 201 202/** Moves metasprite to the absolute position x and y, __flipped on the X and Y axis__ 203 204 @param metasprite Pointer to the first struct of the metasprite (for the desired frame) 205 @param base_tile Number of the first tile where the metasprite's tiles start 206 @param base_sprite Number of the first hardware sprite to be used by the metasprite 207 @param x Absolute x coordinate of the sprite 208 @param y Absolute y coordinate of the sprite 209 210 Same as @ref move_metasprite(), but with the metasprite flipped on both the X and Y axis. 211 212 Sets: 213 \li __current_metasprite = metasprite; 214 \li __current_base_tile = base_tile; 215 216 Note: Overwrites OAM sprite properties (such as CGB palette), see 217 @ref metasprite_and_sprite_properties "Metasprites and sprite properties". 218 219 This function is only available on Game Boy and related clone consoles. 220 221 @return Number of hardware sprites used to draw this metasprite 222 223 @see move_metasprite() 224*/ 225inline uint8_t move_metasprite_hvflip(const metasprite_t * metasprite, uint8_t base_tile, uint8_t base_sprite, uint8_t x, uint8_t y) { 226 __current_metasprite = metasprite; 227 __current_base_tile = base_tile; 228 return __move_metasprite_hvflip(base_sprite, x - 8, y - ((LCDC_REG & 0x04U) ? 16 : 8)); 229} 230 231/** Hides a metasprite from the screen 232 233 @param metasprite Pointer to first struct of the desired metasprite frame 234 @param base_sprite Number of hardware sprite to start with 235 236 Sets: 237 \li __current_metasprite = metasprite; 238 239 **/ 240inline void hide_metasprite(const metasprite_t * metasprite, uint8_t base_sprite) { 241 __current_metasprite = metasprite; 242 __hide_metasprite(base_sprite); 243} 244 245#endif