git.y1.nz

gbdk-2020

GameBoy Development Kit
download: https://git.y1.nz/archives/gbdk.tar.gz
README | Files | Log | Refs | LICENSE

gbdk-lib/include/gb/metasprites.h

      1 /** @file gb/metasprites.h
      2 
      3     @anchor metasprite_main_docs
      4     # Metasprite support
      5 
      6     A metasprite is a larger sprite made up from a
      7     collection of smaller individual hardware sprites.
      8     Different frames of the same metasprites can share
      9     tile data.
     10 
     11     The api supports metasprites in both
     12     @ref SPRITES_8x8 and @ref SPRITES_8x16 mode. If
     13     8x16 mode is used then the height of the metasprite
     14     must be a multiple of 16.
     15 
     16     The origin (pivot) for the metasprite is not required
     17     to be in the upper left-hand corner as with regular
     18     hardware sprites.
     19 
     20     Use the @ref utility_png2asset tool to convert single
     21     or multiple frames of graphics into metasprite
     22     structured data for use with the ...metasprite...()
     23     functions.
     24 
     25     # Metasprites composed of variable numbers of sprites
     26 
     27     When using png2asset, it's common for the output of
     28     different frames to be composed of different numbers
     29     of hardware sprites (since it's trying to create each
     30     frame as efficiently as possible). Due to that, it's
     31     good practice to clear out (hide) unused sprites in the
     32     shadow_OAM that have been set by previous frames.
     33 
     34     \code
     35     // Example:
     36     // Hide rest of the hardware sprites, because amount
     37     // of sprites differ between animation frames.
     38     // (where hiwater == last hardware sprite used + 1)
     39     hide_sprites_range(hiwater, MAX_HARDWARE_SPRITES);
     40     \endcode
     41 
     42     @anchor metasprite_and_sprite_properties
     43     # Metasprites and sprite properties (including cgb palette)
     44 
     45     When the move_metasprite_*() functions are called they
     46     update all properties for the affected sprites in the
     47     Shadow OAM. This means any existing property flags set
     48     for a sprite (CGB palette, BG/WIN priority, Tile VRAM Bank)
     49     will get overwritten.
     50 
     51     How to use sprite property flags with metasprites:
     52     - Primary method: Use the `base_prop` parameter for the
     53       move_metasprite_*() functions.
     54       - For more details about the properties on the Game Boy see: https://gbdev.io/pandocs/OAM.html#byte-3--attributesflags
     55       - This can be left at zero for defaults
     56       - Various `OAMF_*` flags can be used depending on the platform:
     57         - @ref OAMF_BANK0, @ref OAMF_BANK1
     58         - @ref OAMF_CGB_PAL0, @ref OAMF_CGB_PAL1, @ref OAMF_CGB_PAL2, @ref OAMF_CGB_PAL3,
     59           @ref OAMF_CGB_PAL4, @ref OAMF_CGB_PAL5, @ref OAMF_CGB_PAL6, @ref OAMF_CGB_PAL7,
     60         - @ref OAMF_PAL0, @ref OAMF_PAL1,
     61         - @ref OAMF_PALMASK, @ref OAMF_PRI, @ref OAMF_XFLIP, @ref OAMF_YFLIP
     62 
     63     - Alternate method: The metasprite structures can have the
     64       property flags modified before compilation (such as with
     65       `-sp <props>` in the @ref utility_png2asset "png2asset" tool).
     66 
     67     The following functions only support hardware sprite flipping
     68     on the Game Boy / Mega Duck and NES. For other consoles which
     69     do not have hardware sprite flipping see the cross-platform
     70     metasprite example for a workaround (with some performance penalty).
     71 
     72     - @ref move_metasprite_flipx()
     73     - @ref move_metasprite_flipy()
     74     - @ref move_metasprite_flipxy()
     75 
     76     To test for hardware support see
     77     @ref HARDWARE_SPRITE_CAN_FLIP_X and @ref HARDWARE_SPRITE_CAN_FLIP_Y.
     78     Also see @ref docs_consoles_supported_list for a brief summary of
     79     console capabilities.
     80 */
     81 
     82 #ifndef _METASPRITES_H_INCLUDE
     83 #define _METASPRITES_H_INCLUDE
     84 
     85 #include <gb/hardware.h>
     86 #include <types.h>
     87 #include <stdint.h>
     88 
     89 /** Metasprite sub-item structure
     90     @param dy        (int8_t)  Y coordinate of the sprite relative to the metasprite origin (pivot)
     91     @param dx        (int8_t)  X coordinate of the sprite relative to the metasprite origin (pivot)
     92     @param dtile     (uint8_t) Start tile relative to the metasprites own set of tiles
     93     @param props     (uint8_t) Property Flags
     94 
     95     Metasprites are built from multiple metasprite_t items (one for each sub-sprite)
     96     and a pool of tiles they reference. If a metasprite has multiple frames then each
     97     frame will be built from some number of metasprite_t items (which may vary based
     98     on how many sprites are required for that particular frame).
     99 
    100     A metasprite frame is terminated with a {metasprite_end} entry.
    101 */
    102 typedef struct metasprite_t {
    103     int8_t  dy, dx;
    104     uint8_t dtile;
    105     uint8_t props;
    106 } metasprite_t;
    107 
    108 #define metasprite_end -128
    109 #define METASPR_ITEM(dy,dx,dt,a) {(dy),(dx),(dt),(a)}
    110 #define METASPR_TERM {metasprite_end}
    111 
    112 extern const void * __current_metasprite;
    113 extern uint8_t __current_base_tile;
    114 extern uint8_t __current_base_prop;
    115 extern uint8_t __render_shadow_OAM;
    116 
    117 
    118 static uint8_t __move_metasprite(uint8_t id, uint16_t yx);
    119 static uint8_t __move_metasprite_flipx(uint8_t id, uint16_t yx);
    120 static uint8_t __move_metasprite_flipy(uint8_t id, uint16_t yx);
    121 static uint8_t __move_metasprite_flipxy(uint8_t id, uint16_t yx);
    122 static uint8_t __move_metasprite_vflip(uint8_t id, uint16_t yx);
    123 static uint8_t __move_metasprite_hflip(uint8_t id, uint16_t yx);
    124 static uint8_t __move_metasprite_hvflip(uint8_t id, uint16_t yx);
    125 static void __hide_metasprite(uint8_t id);
    126 
    127 /**
    128     Hides all hardware sprites in range from <= X < to
    129     @param from start OAM index
    130     @param to finish OAM index (must be <= MAX_HARDWARE_SPRITES)
    131 
    132     @see hide_sprite, MAX_HARDWARE_SPRITES
    133  */
    134 void hide_sprites_range(uint8_t from, uint8_t to);
    135 
    136 /** Moves metasprite to the absolute position x and y
    137 
    138     @param metasprite   Pointer to the first struct of the metasprite (for the desired frame)
    139     @param base_tile    Number of the first tile where the metasprite's tiles start
    140     @param base_prop    Base sprite property flags (can be used to set palette, etc)
    141     @param base_sprite  Number of the first hardware sprite to be used by the metasprite
    142     @param x            Absolute x coordinate of the sprite
    143     @param y            Absolute y coordinate of the sprite
    144 
    145     Moves __metasprite__ to the absolute position __x__ and __y__
    146     (with __no flip__ on the X or Y axis). Hardware sprites are
    147     allocated starting from __base_sprite__, using tiles
    148     starting from __base_tile__.
    149 
    150     Sets:
    151     \li __current_metasprite = metasprite;
    152     \li __current_base_tile = base_tile;
    153 
    154     Note: Overwrites OAM sprite properties (such as CGB Palette), see
    155           @ref metasprite_and_sprite_properties "Metasprites and sprite properties".
    156 
    157     @return Number of hardware sprites used to draw this metasprite
    158  */
    159 inline uint8_t move_metasprite_ex(const metasprite_t * metasprite, uint8_t base_tile, uint8_t base_prop, uint8_t base_sprite, uint8_t x, uint8_t y) {
    160     __current_metasprite = metasprite;
    161     __current_base_tile = base_tile;
    162     __current_base_prop = base_prop;
    163     return __move_metasprite(base_sprite, (y << 8) | (uint8_t)x);
    164 }
    165 
    166 /** Obsolete. This function has been replaced by move_metasprite_ex()
    167 */
    168 inline uint8_t move_metasprite(const metasprite_t * metasprite, uint8_t base_tile, uint8_t base_sprite, uint8_t x, uint8_t y) {
    169     __current_metasprite = metasprite;
    170     __current_base_tile = base_tile;
    171     __current_base_prop = 0;
    172     return __move_metasprite(base_sprite, (y << 8) | (uint8_t)x);
    173 }
    174 
    175 /** Moves metasprite to the absolute position x and y, __flipped by X (horizontally)__
    176 
    177     @param metasprite   Pointer to the first struct of the metasprite (for the desired frame)
    178     @param base_tile    Number of the first tile where the metasprite's tiles start
    179     @param base_prop    Base sprite property flags (can be used to set palette, etc)
    180     @param base_sprite  Number of the first hardware sprite to be used by the metasprite
    181     @param x            Absolute x coordinate of the sprite
    182     @param y            Absolute y coordinate of the sprite
    183 
    184     Same as @ref move_metasprite(), but with the metasprite flipped by X (horizontally).
    185 
    186     Sets:
    187     \li __current_metasprite = metasprite;
    188     \li __current_base_tile = base_tile;
    189 
    190     Note: Overwrites OAM sprite properties (such as CGB palette), see
    191           @ref metasprite_and_sprite_properties "Metasprites and sprite properties".
    192 
    193     This function is only available on Game Boy and related clone consoles.
    194 
    195     @return Number of hardware sprites used to draw this metasprite
    196 
    197     @see move_metasprite()
    198 */
    199 inline uint8_t move_metasprite_flipx(const metasprite_t * metasprite, uint8_t base_tile, uint8_t base_prop, uint8_t base_sprite, uint8_t x, uint8_t y) {
    200     __current_metasprite = metasprite;
    201     __current_base_tile = base_tile;
    202     __current_base_prop = base_prop;
    203     return __move_metasprite_flipx(base_sprite, (y << 8) | (uint8_t)(x - 8u));
    204 }
    205 
    206 /** Obsolete. This function has been replaced by move_metasprite_flipx()
    207 */
    208 inline uint8_t move_metasprite_vflip(const metasprite_t * metasprite, uint8_t base_tile, uint8_t base_sprite, uint8_t x, uint8_t y) {
    209     __current_metasprite = metasprite;
    210     __current_base_tile = base_tile;
    211     __current_base_prop = 0;
    212     return __move_metasprite_vflip(base_sprite, (y << 8) | (uint8_t)(x - 8u));
    213 }
    214 
    215 
    216 /** Moves metasprite to the absolute position x and y, __flipped by Y (vertically)__
    217 
    218     @param metasprite   Pointer to the first struct of the metasprite (for the desired frame)
    219     @param base_tile    Number of the first tile where the metasprite's tiles start
    220     @param base_prop    Base sprite property flags (can be used to set palette, etc)
    221     @param base_sprite  Number of the first hardware sprite to be used by the metasprite
    222     @param x            Absolute x coordinate of the sprite
    223     @param y            Absolute y coordinate of the sprite
    224 
    225     Same as @ref move_metasprite(), but with the metasprite flipped by Y (vertically).
    226 
    227     Sets:
    228     \li __current_metasprite = metasprite;
    229     \li __current_base_tile = base_tile;
    230 
    231     Note: Overwrites OAM sprite properties (such as CGB palette), see
    232           @ref metasprite_and_sprite_properties "Metasprites and sprite properties".
    233 
    234     This function is only available on Game Boy and related clone consoles.
    235 
    236     @return Number of hardware sprites used to draw this metasprite
    237 
    238     @see move_metasprite()
    239 */
    240 inline uint8_t move_metasprite_flipy(const metasprite_t * metasprite, uint8_t base_tile, uint8_t base_prop, uint8_t base_sprite, uint8_t x, uint8_t y) {
    241     __current_metasprite = metasprite;
    242     __current_base_tile = base_tile;
    243     __current_base_prop = base_prop;
    244     return __move_metasprite_flipy(base_sprite, ((y - ((LCDC_REG & LCDCF_OBJ16) ? 16u : 8u)) << 8) | x);
    245 }
    246 
    247 /** Obsolete. This function has been replaced by move_metasprite_flipy()
    248 */
    249 inline uint8_t move_metasprite_hflip(const metasprite_t * metasprite, uint8_t base_tile, uint8_t base_sprite, uint8_t x, uint8_t y) {
    250     __current_metasprite = metasprite;
    251     __current_base_tile = base_tile;
    252     __current_base_prop = 0;
    253     return __move_metasprite_hflip(base_sprite, ((y - ((LCDC_REG & LCDCF_OBJ16) ? 16u : 8u)) << 8) | x);
    254 }
    255 
    256 /** Moves metasprite to the absolute position x and y, __flipped by X and Y (horizontally and vertically)__
    257 
    258     @param metasprite   Pointer to the first struct of the metasprite (for the desired frame)
    259     @param base_tile    Number of the first tile where the metasprite's tiles start
    260     @param base_prop    Base sprite property flags (can be used to set palette, etc)
    261     @param base_sprite  Number of the first hardware sprite to be used by the metasprite
    262     @param x            Absolute x coordinate of the sprite
    263     @param y            Absolute y coordinate of the sprite
    264 
    265     Same as @ref move_metasprite(), but with the metasprite flipped by X and Y (horizontally and vertically).
    266 
    267     Sets:
    268     \li __current_metasprite = metasprite;
    269     \li __current_base_tile = base_tile;
    270 
    271     Note: Overwrites OAM sprite properties (such as CGB palette), see
    272           @ref metasprite_and_sprite_properties "Metasprites and sprite properties".
    273 
    274     This function is only available on Game Boy and related clone consoles.
    275 
    276     @return Number of hardware sprites used to draw this metasprite
    277 
    278     @see move_metasprite()
    279 */
    280 inline uint8_t move_metasprite_flipxy(const metasprite_t * metasprite, uint8_t base_tile, uint8_t base_prop, uint8_t base_sprite, uint8_t x, uint8_t y) {
    281     __current_metasprite = metasprite;
    282     __current_base_tile = base_tile;
    283     __current_base_prop = base_prop;
    284     return __move_metasprite_flipxy(base_sprite, ((y - ((LCDC_REG & LCDCF_OBJ16) ? 16u : 8u)) << 8) | (uint8_t)(x - 8));
    285 }
    286 
    287 /** Obsolete. This function has been replaced by move_metasprite_flipxy()
    288 */
    289 inline uint8_t move_metasprite_hvflip(const metasprite_t * metasprite, uint8_t base_tile, uint8_t base_sprite, uint8_t x, uint8_t y) {
    290     __current_metasprite = metasprite;
    291     __current_base_tile = base_tile;
    292     __current_base_prop = 0;
    293     return __move_metasprite_hvflip(base_sprite, ((y - ((LCDC_REG & LCDCF_OBJ16) ? 16u : 8u)) << 8) | (uint8_t)(x - 8));
    294 }
    295 
    296 /** Hides a metasprite from the screen
    297 
    298     @param metasprite    Pointer to first struct of the desired metasprite frame
    299     @param base_sprite   Number of hardware sprite to start with
    300 
    301     Sets:
    302     \li __current_metasprite = metasprite;
    303 
    304  **/
    305 inline void hide_metasprite(const metasprite_t * metasprite, uint8_t base_sprite) {
    306     __current_metasprite = metasprite;
    307     __hide_metasprite(base_sprite);
    308 }
    309 
    310 #endif

This webpage is intended to be an accessible preview of this repository. To get a fuller picture, clone it and use the git CLI.