cscg22-gearboy

CSCG 2022 Challenge 'Gearboy'
git clone https://git.sinitax.com/sinitax/cscg22-gearboy
Log | Files | Refs | sfeed.txt

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