cscg22-gearboy

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

sms.h (24571B)


      1/** @file sms/sms.h
      2    SMS/GG specific functions.
      3*/
      4#ifndef _SMS_H
      5#define _SMS_H
      6
      7#include <types.h>
      8#include <stdint.h>
      9#include <gbdk/version.h>
     10#include <sms/hardware.h>
     11
     12#define SEGA
     13#ifdef NINTENDO
     14#undef NINTENDO
     15#endif
     16#if defined(__TARGET_sms)
     17#define MASTERSYSTEM
     18#elif defined(__TARGET_gg)
     19#define GAMEGEAR
     20#endif
     21
     22
     23#define VBK_REG VDP_ATTR_SHIFT
     24
     25/** Joypad bits.
     26    A logical OR of these is used in the wait_pad and joypad
     27    functions.  For example, to see if the B button is pressed
     28    try
     29
     30    uint8_t keys;
     31    keys = joypad();
     32    if (keys & J_B) {
     33    	...
     34    }
     35
     36    @see joypad
     37 */
     38#define	J_UP         0b00000001
     39#define	J_DOWN       0b00000010
     40#define	J_LEFT       0b00000100
     41#define	J_RIGHT      0b00001000
     42#define	J_A          0b00010000
     43#define	J_B          0b00100000
     44#if defined(__TARGET_sms)
     45#define	J_SELECT     0b00100000
     46#define	J_START      0b00010000
     47#elif defined(__TARGET_gg)
     48#define	J_SELECT     0b00100000
     49#define	J_START      0b10000000
     50#endif
     51
     52/** Screen modes.
     53    Normally used by internal functions only.
     54    @see mode()
     55 */
     56#define	M_TEXT_OUT   0x02U
     57#define	M_TEXT_INOUT 0x03U
     58/** Set this in addition to the others to disable scrolling
     59
     60    If scrolling is disabled, the cursor returns to (0,0)
     61    @see mode()
     62*/
     63#define M_NO_SCROLL  0x04U
     64/** Set this to disable interpretation
     65    @see mode()
     66*/
     67#define M_NO_INTERP  0x08U
     68
     69/** If set the background tile will be flipped horizontally.
     70 */
     71#define S_FLIPX      0x02U
     72/** If set the background tile will be flipped vertically.
     73 */
     74#define S_FLIPY      0x04U
     75/** If set the background tile palette.
     76 */
     77#define S_PALETTE    0x08U
     78/** If set the background tile priority.
     79 */
     80#define S_PRIORITY   0x10U
     81
     82// VDP helper macros
     83#define __WRITE_VDP_REG(REG, v) shadow_##REG=(v);__critical{VDP_CMD=(shadow_##REG),VDP_CMD=REG;}
     84#define __READ_VDP_REG(REG) shadow_##REG
     85
     86void WRITE_VDP_CMD(uint16_t cmd) Z88DK_FASTCALL PRESERVES_REGS(b, c, d, e, iyh, iyl);
     87void WRITE_VDP_DATA(uint16_t data) Z88DK_FASTCALL PRESERVES_REGS(b, c, d, e, iyh, iyl);
     88
     89/** Set the current screen mode - one of M_* modes
     90
     91    Normally used by internal functions only.
     92
     93    @see M_TEXT_OUT, M_TEXT_INOUT, M_NO_SCROLL, M_NO_INTERP
     94*/
     95void mode(uint8_t m) OLDCALL;
     96
     97/** Returns the current mode
     98
     99    @see M_TEXT_OUT, M_TEXT_INOUT, M_NO_SCROLL, M_NO_INTERP
    100*/
    101uint8_t get_mode() OLDCALL;
    102
    103/* Interrupt flags */
    104/** Disable calling of interrupt service routines
    105 */
    106#define EMPTY_IFLAG  0x00U
    107/** VBlank Interrupt occurs at the start of the vertical blank.
    108
    109    During this period the video ram may be freely accessed.
    110    @see set_interrupts(), @see add_VBL
    111 */
    112#define VBL_IFLAG    0x01U
    113/** LCD Interrupt when triggered by the STAT register.
    114    @see set_interrupts(), @see add_LCD
    115*/
    116#define LCD_IFLAG    0x02U
    117/** Does nothing on SMS/GG
    118 */
    119#define TIM_IFLAG    0x04U
    120/** Does nothing on SMS/GG
    121 */
    122#define SIO_IFLAG    0x08U
    123/** Does nothing on SMS/GG
    124 */
    125#define JOY_IFLAG    0x10U
    126
    127void set_interrupts(uint8_t flags) Z88DK_FASTCALL;
    128
    129/* Limits */
    130/** Width of the visible screen in pixels.
    131 */
    132#define SCREENWIDTH  DEVICE_SCREEN_PX_WIDTH
    133/** Height of the visible screen in pixels.
    134 */
    135#define SCREENHEIGHT DEVICE_SCREEN_PX_HEIGHT
    136/** The Minimum X position of the Window Layer (Left edge of screen) @see move_win()
    137 */
    138#define MINWNDPOSX   0x00U
    139/** The Minimum Y position of the Window Layer (Top edge of screen) @see move_win()
    140 */
    141#define MINWNDPOSY   0x00U
    142/** The Maximum X position of the Window Layer (Right edge of screen) @see move_win()
    143 */
    144#define MAXWNDPOSX   0x00U
    145/** The Maximum Y position of the Window Layer (Bottom edge of screen) @see move_win()
    146 */
    147#define MAXWNDPOSY   0x00U
    148
    149
    150/** Interrupt handlers
    151 */
    152typedef void (*int_handler)(void) NONBANKED;
    153
    154/** Removes the VBL interrupt handler.
    155    @see add_VBL()
    156*/
    157void remove_VBL(int_handler h) Z88DK_FASTCALL PRESERVES_REGS(iyh, iyl);
    158
    159/** Removes the LCD interrupt handler.
    160    @see add_LCD(), remove_VBL()
    161*/
    162void remove_LCD(int_handler h) Z88DK_FASTCALL PRESERVES_REGS(b, c, iyh, iyl);
    163
    164void remove_TIM(int_handler h) Z88DK_FASTCALL;
    165void remove_SIO(int_handler h) Z88DK_FASTCALL;
    166void remove_JOY(int_handler h) Z88DK_FASTCALL;
    167
    168/** Adds a V-blank interrupt handler.
    169*/
    170void add_VBL(int_handler h) Z88DK_FASTCALL PRESERVES_REGS(d, e, iyh, iyl);
    171
    172/** Adds a LCD interrupt handler.
    173*/
    174void add_LCD(int_handler h) Z88DK_FASTCALL PRESERVES_REGS(b, c, iyh, iyl);
    175
    176/** Does nothing on SMS/GG
    177 */
    178void add_TIM(int_handler h) Z88DK_FASTCALL;
    179
    180/** Does nothing on SMS/GG
    181 */
    182void add_SIO(int_handler h) Z88DK_FASTCALL;
    183
    184/** Does nothing on SMS/GG
    185 */
    186void add_JOY(int_handler h) Z88DK_FASTCALL;
    187
    188/** Cancel pending interrupts
    189 */
    190inline uint8_t cancel_pending_interrupts() {
    191    return VDP_STATUS;
    192}
    193
    194inline void move_bkg(uint8_t x, uint8_t y) {
    195	__WRITE_VDP_REG(VDP_RSCX, -x);
    196	__WRITE_VDP_REG(VDP_RSCY, y);
    197}
    198
    199inline void scroll_bkg(int8_t x, int8_t y) {
    200	__WRITE_VDP_REG(VDP_RSCX, __READ_VDP_REG(VDP_RSCX) - x);
    201    int16_t tmp = __READ_VDP_REG(VDP_RSCY) + y;
    202	__WRITE_VDP_REG(VDP_RSCY, (tmp < 0) ? 224 + tmp : tmp % 224u);
    203}
    204
    205/** HALTs the CPU and waits for the vertical blank interrupt (VBL) to finish.
    206
    207    This is often used in main loops to idle the CPU at low power
    208    until it's time to start the next frame. It's also useful for
    209    syncing animation with the screen re-draw.
    210
    211    Warning: If the VBL interrupt is disabled, this function will
    212    never return. If the screen is off this function returns
    213    immediately.
    214*/
    215void wait_vbl_done() PRESERVES_REGS(b, c, d, e, h, l, iyh, iyl);
    216
    217/** Turns the display off.
    218
    219    @see DISPLAY_ON
    220*/
    221inline void display_off() {
    222	__WRITE_VDP_REG(VDP_R1, __READ_VDP_REG(VDP_R1) &= (~R1_DISP_ON));
    223}
    224
    225/** Turns the display back on.
    226    @see display_off, DISPLAY_OFF
    227*/
    228#define DISPLAY_ON \
    229	__WRITE_VDP_REG(VDP_R1, __READ_VDP_REG(VDP_R1) |= R1_DISP_ON)
    230
    231/** Turns the display off immediately.
    232    @see display_off, DISPLAY_ON
    233*/
    234#define DISPLAY_OFF \
    235	display_off();
    236
    237/** Copies data from shadow OAM to OAM
    238 */
    239void refresh_OAM();
    240
    241/** Blanks leftmost column, so it is not garbaged when you use horizontal scroll
    242    @see SHOW_LEFT_COLUMN
    243*/
    244#define HIDE_LEFT_COLUMN \
    245	__WRITE_VDP_REG(VDP_R0, __READ_VDP_REG(VDP_R0) |= R0_LCB)
    246
    247/** Shows leftmost column
    248    @see HIDE_LEFT_COLUMN
    249*/
    250#define SHOW_LEFT_COLUMN \
    251	__WRITE_VDP_REG(VDP_R0, __READ_VDP_REG(VDP_R0) &= (~R0_LCB))
    252
    253/** Turns on the background layer.
    254    Not yet implemented
    255*/
    256#define SHOW_BKG
    257
    258/** Turns off the background layer.
    259    Not yet implemented
    260*/
    261#define HIDE_BKG
    262
    263/** Turns on the window layer
    264    Not yet implemented
    265*/
    266#define SHOW_WIN
    267
    268/** Turns off the window layer.
    269    Not yet implemented
    270*/
    271#define HIDE_WIN
    272
    273/** Turns on the sprites layer.
    274    Not yet implemented
    275*/
    276#define SHOW_SPRITES
    277
    278/** Turns off the sprites layer.
    279    Not yet implemented
    280*/
    281#define HIDE_SPRITES
    282
    283/** Sets sprite size to 8x16 pixels, two tiles one above the other.
    284*/
    285#define SPRITES_8x16 \
    286	__WRITE_VDP_REG(VDP_R1, __READ_VDP_REG(VDP_R1) |= R1_SPR_8X16)
    287
    288/** Sets sprite size to 8x8 pixels, one tile.
    289*/
    290#define SPRITES_8x8 \
    291	__WRITE_VDP_REG(VDP_R1, __READ_VDP_REG(VDP_R1) &= (~R1_SPR_8X16))
    292
    293/** Macro returns TRUE if device supports color
    294 *  (it always does on SMS/GG)
    295 */
    296#define DEVICE_SUPPORTS_COLOR (TRUE)
    297
    298/** Global Time Counter in VBL periods (60Hz)
    299
    300    Increments once per Frame
    301
    302    Will wrap around every ~18 minutes (unsigned 16 bits = 65535 / 60 / 60 = 18.2)
    303*/
    304extern volatile uint16_t sys_time;
    305
    306/** Tracks current active ROM bank in frame 1
    307*/
    308#define _current_bank MAP_FRAME1
    309#define CURRENT_BANK MAP_FRAME1
    310
    311/** Obtains the __bank number__ of VARNAME
    312
    313    @param VARNAME Name of the variable which has a __bank_VARNAME companion symbol which is adjusted by bankpack
    314
    315    Use this to obtain the bank number from a bank reference
    316    created with @ref BANKREF().
    317
    318    @see BANKREF_EXTERN(), BANKREF()
    319*/
    320#ifndef BANK
    321#define BANK(VARNAME) ( (uint8_t) & __bank_ ## VARNAME )
    322#endif
    323
    324/** Creates a reference for retrieving the bank number of a variable or function
    325
    326    @param VARNAME Variable name to use, which may be an existing identifier
    327
    328    @see BANK() for obtaining the bank number of the included data.
    329
    330    More than one `BANKREF()` may be created per file, but each call should
    331    always use a unique VARNAME.
    332
    333    Use @ref BANKREF_EXTERN() within another source file
    334    to make the variable and it's data accesible there.
    335*/
    336#define BANKREF(VARNAME) void __func_ ## VARNAME() __banked __naked { \
    337__asm \
    338    .local b___func_ ## VARNAME \
    339    ___bank_ ## VARNAME = b___func_ ## VARNAME \
    340    .globl ___bank_ ## VARNAME \
    341__endasm; \
    342}
    343
    344/** Creates extern references for accessing a BANKREF() generated variable.
    345
    346    @param VARNAME Name of the variable used with @ref BANKREF()
    347
    348    This makes a @ref BANKREF() reference in another source
    349    file accessible in the current file for use with @ref BANK().
    350
    351    @see BANKREF(), BANK()
    352*/
    353#define BANKREF_EXTERN(VARNAME) extern const void __bank_ ## VARNAME;
    354
    355
    356/** Makes switch the active ROM bank in frame 1
    357    @param b   ROM bank to switch to
    358*/
    359
    360#define SWITCH_ROM(b) MAP_FRAME1=(b)
    361#define SWITCH_ROM1 SWITCH_ROM
    362
    363/** Makes switch the active ROM bank in frame 2
    364    @param b   ROM bank to switch to
    365*/
    366
    367#define SWITCH_ROM2(b) MAP_FRAME2=(b)
    368
    369/** Switches RAM bank
    370    @param b   SRAM bank to switch to
    371*/
    372
    373#define SWITCH_RAM(b) RAM_CONTROL=((b)&1)?RAM_CONTROL|RAMCTL_BANK:RAM_CONTROL&(~RAMCTL_BANK)
    374
    375/** Enables RAM
    376*/
    377
    378#define ENABLE_RAM RAM_CONTROL|=RAMCTL_RAM
    379
    380/** Disables RAM
    381*/
    382
    383#define DISABLE_RAM RAM_CONTROL&=(~RAMCTL_RAM)
    384
    385
    386/** Delays the given number of milliseconds.
    387    Uses no timers or interrupts, and can be called with
    388    interrupts disabled
    389 */
    390void delay(uint16_t d) Z88DK_FASTCALL;
    391
    392
    393/** Reads and returns the current state of the joypad.
    394*/
    395uint8_t joypad() OLDCALL PRESERVES_REGS(b, c, d, e, h, iyh, iyl);
    396
    397/** Waits until at least one of the buttons given in mask are pressed.
    398*/
    399uint8_t waitpad(uint8_t mask) Z88DK_FASTCALL PRESERVES_REGS(b, c, d, e, iyh, iyl);
    400
    401/** Waits for the directional pad and all buttons to be released.
    402
    403    Note: Checks in a loop that doesn't HALT at all, so the CPU
    404    will be maxed out until this call returns.
    405*/
    406void waitpadup() PRESERVES_REGS(b, c, d, e, iyh, iyl);
    407
    408/** Multiplayer joypad structure.
    409
    410    Must be initialized with @ref joypad_init() first then it
    411    may be used to poll all avaliable joypads with @ref joypad_ex()
    412*/
    413typedef struct {
    414    uint8_t npads;
    415    union {
    416        struct {
    417            uint8_t joy0, joy1, joy2, joy3;
    418        };
    419        uint8_t joypads[4];
    420    };
    421} joypads_t;
    422
    423/** Initializes joypads_t structure for polling multiple joypads
    424    @param npads	number of joypads requested (1, 2 or 4)
    425    @param joypads	pointer to joypads_t structure to be initialized
    426
    427    Only required for @ref joypad_ex, not required for calls to regular @ref joypad()
    428    @returns number of joypads avaliable
    429    @see joypad_ex(), joypads_t
    430*/
    431uint8_t joypad_init(uint8_t npads, joypads_t * joypads) Z88DK_CALLEE;
    432
    433/** Polls all avaliable joypads
    434    @param joypads	pointer to joypads_t structure to be filled with joypad statuses,
    435    	   must be previously initialized with joypad_init()
    436
    437    @see joypad_init(), joypads_t
    438*/
    439void joypad_ex(joypads_t * joypads) Z88DK_FASTCALL PRESERVES_REGS(iyh, iyl);
    440
    441
    442#if defined(__TARGET_sms)
    443
    444#define RGB(r,g,b)        ((r) | ((g) << 2) | ((b) << 4))
    445#define RGB8(r,g,b)       (((r) >> 6) | (((g) >> 6) << 2) | (((b) >> 6) << 4))
    446#define RGBHTML(RGB24bit) (((RGB24bit) >> 22) | ((((RGB24bit) & 0xFFFF) >> 14) << 2) | ((((RGB24bit) & 0xFF) >> 6) << 4))
    447
    448/** Common colors based on the EGA default palette.
    449 */
    450#define RGB_RED        RGB( 3,  0,  0)
    451#define RGB_DARKRED    RGB( 2,  0,  0)
    452#define RGB_GREEN      RGB( 0,  3,  0)
    453#define RGB_DARKGREEN  RGB( 0,  2,  0)
    454#define RGB_BLUE       RGB( 0,  0,  3)
    455#define RGB_DARKBLUE   RGB( 0,  0,  2)
    456#define RGB_YELLOW     RGB( 3,  3,  0)
    457#define RGB_DARKYELLOW RGB( 2,  2,  0)
    458#define RGB_CYAN       RGB( 0,  3,  3)
    459#define RGB_AQUA       RGB( 3,  1,  2)
    460#define RGB_PINK       RGB( 3,  0,  3)
    461#define RGB_PURPLE     RGB( 2,  0,  2)
    462#define RGB_BLACK      RGB( 0,  0,  0)
    463#define RGB_DARKGRAY   RGB( 1,  1,  1)
    464#define RGB_LIGHTGRAY  RGB( 2,  2,  2)
    465#define RGB_WHITE      RGB( 3,  3,  3)
    466
    467typedef uint8_t palette_color_t;
    468
    469#elif defined(__TARGET_gg)
    470
    471#define RGB(r,g,b)        ((uint16_t)(r) | (uint16_t)((g) << 4) | (uint16_t)((b) << 8))
    472#define RGB8(r,g,b)       ((uint16_t)((r) >> 4) | ((uint16_t)((g) >> 4) << 4) | ((uint16_t)((b) >> 4) << 8))
    473#define RGBHTML(RGB24bit) (((RGB24bit) >> 20) | ((((RGB24bit) & 0xFFFF) >> 12) << 4)|((((RGB24bit) & 0xFF) >> 4) << 8))
    474
    475/** Common colors based on the EGA default palette.
    476 */
    477#define RGB_RED        RGB(15,  0,  0)
    478#define RGB_DARKRED    RGB( 7,  0,  0)
    479#define RGB_GREEN      RGB( 0, 15,  0)
    480#define RGB_DARKGREEN  RGB( 0,  7,  0)
    481#define RGB_BLUE       RGB( 0,  0, 15)
    482#define RGB_DARKBLUE   RGB( 0,  0,  7)
    483#define RGB_YELLOW     RGB(15, 15,  0)
    484#define RGB_DARKYELLOW RGB( 7,  7,  0)
    485#define RGB_CYAN       RGB( 0, 15, 15)
    486#define RGB_AQUA       RGB(14,  2, 11)
    487#define RGB_PINK       RGB(15,  0, 15)
    488#define RGB_PURPLE     RGB(10,  0, 10)
    489#define RGB_BLACK      RGB( 0,  0,  0)
    490#define RGB_DARKGRAY   RGB( 5,  5,  5)
    491#define RGB_LIGHTGRAY  RGB(10, 10, 10)
    492#define RGB_WHITE      RGB(15, 15, 15)
    493
    494#define RGB_LIGHTFLESH RGB(15, 10,  7)
    495#define RGB_BROWN      RGB( 5,  5,  0)
    496#define RGB_ORANGE     RGB(15, 10,  0)
    497#define RGB_TEAL       RGB( 7,  7,  0)
    498
    499typedef uint16_t palette_color_t;
    500
    501#else
    502#error Unrecognized port
    503#endif
    504
    505void set_default_palette();
    506inline void cpu_fast() {}
    507
    508void set_palette_entry(uint8_t palette, uint8_t entry, uint16_t rgb_data) Z88DK_CALLEE PRESERVES_REGS(iyh, iyl);
    509#define set_bkg_palette_entry set_palette_entry
    510#define set_sprite_palette_entry(palette,entry,rgb_data) set_palette_entry(1,entry,rgb_data)
    511void set_palette(uint8_t first_palette, uint8_t nb_palettes, palette_color_t *rgb_data) Z88DK_CALLEE;
    512#define set_bkg_palette set_palette
    513#define set_sprite_palette(first_palette,nb_palettes,rgb_data) set_palette(1,1,rgb_data)
    514
    515void set_native_tile_data(uint16_t start, uint16_t ntiles, const void *src) Z88DK_CALLEE PRESERVES_REGS(iyh, iyl);
    516inline void set_bkg_4bpp_data(uint16_t start, uint16_t ntiles, const void *src) {
    517    set_native_tile_data(start, ntiles, src);
    518}
    519inline void set_sprite_4bpp_data(uint16_t start, uint16_t ntiles, const void *src) {
    520    set_native_tile_data((uint8_t)(start) + 0x100u, ntiles, src);
    521}
    522
    523#define COMPAT_PALETTE(C0,C1,C2,C3) (((uint16_t)(C3) << 12) | ((uint16_t)(C2) << 8) | ((uint16_t)(C1) << 4) | (uint16_t)(C0))
    524extern uint16_t _current_2bpp_palette;
    525inline void set_2bpp_palette(uint16_t palette) {
    526    _current_2bpp_palette = palette;
    527}
    528void set_tile_2bpp_data(uint16_t start, uint16_t ntiles, const void *src, uint16_t palette) Z88DK_CALLEE PRESERVES_REGS(iyh, iyl);
    529inline void set_bkg_data(uint16_t start, uint16_t ntiles, const void *src) {
    530    set_tile_2bpp_data(start, ntiles, src, _current_2bpp_palette);
    531}
    532inline void set_sprite_data(uint16_t start, uint16_t ntiles, const void *src) {
    533    set_tile_2bpp_data((uint8_t)(start) + 0x100u, ntiles, src, _current_2bpp_palette);
    534}
    535inline void set_bkg_2bpp_data(uint16_t start, uint16_t ntiles, const void *src) {
    536    set_tile_2bpp_data(start, ntiles, src, _current_2bpp_palette);
    537}
    538inline void set_sprite_2bpp_data(uint16_t start, uint16_t ntiles, const void *src) {
    539    set_tile_2bpp_data((uint8_t)(start) + 0x100u, ntiles, src, _current_2bpp_palette);
    540}
    541
    542extern uint16_t _current_1bpp_colors;
    543inline void set_1bpp_colors(uint8_t fgcolor, uint8_t bgcolor) {
    544    _current_1bpp_colors = ((uint16_t)bgcolor << 8) | fgcolor;
    545}
    546void set_tile_1bpp_data(uint16_t start, uint16_t ntiles, const void *src, uint16_t colors) Z88DK_CALLEE PRESERVES_REGS(iyh, iyl);
    547inline void set_bkg_1bpp_data(uint16_t start, uint16_t ntiles, const void *src) {
    548    set_tile_1bpp_data(start, ntiles, src, _current_1bpp_colors);
    549}
    550inline void set_sprite_1bpp_data(uint16_t start, uint16_t ntiles, const void *src) {
    551    set_tile_1bpp_data((uint8_t)(start) + 0x100u, ntiles, src, _current_1bpp_colors);
    552}
    553
    554
    555/** Copies arbitrary data to an address in VRAM
    556
    557    @param dst       destination VRAM Address
    558    @param src       Pointer to source buffer
    559    @param size      Number of bytes to copy
    560
    561    Copies __size__ bytes from a buffer at _src__ to VRAM starting at __dst__.
    562*/
    563void set_data(uint16_t dst, const void *src, uint16_t size) Z88DK_CALLEE PRESERVES_REGS(iyh, iyl);
    564void vmemcpy(uint16_t dst, const void *src, uint16_t size) Z88DK_CALLEE PRESERVES_REGS(iyh, iyl);
    565
    566void set_tile_map(uint8_t x, uint8_t y, uint8_t w, uint8_t h, const uint8_t *tiles) Z88DK_CALLEE PRESERVES_REGS(iyh, iyl);
    567void set_tile_map_compat(uint8_t x, uint8_t y, uint8_t w, uint8_t h, const uint8_t *tiles) Z88DK_CALLEE PRESERVES_REGS(iyh, iyl);
    568#define set_bkg_tiles set_tile_map_compat
    569#define set_win_tiles set_tile_map_compat
    570
    571extern uint8_t _map_tile_offset;
    572inline void set_bkg_based_tiles(uint8_t x, uint8_t y, uint8_t w, uint8_t h, const uint8_t *tiles, uint8_t base_tile) {
    573    _map_tile_offset = base_tile;
    574    set_tile_map_compat(x, y, w, h, tiles);
    575    _map_tile_offset = 0;
    576}
    577inline void set_win_based_tiles(uint8_t x, uint8_t y, uint8_t w, uint8_t h, const uint8_t *tiles, uint8_t base_tile) {
    578    _map_tile_offset = base_tile;
    579    set_tile_map_compat(x, y, w, h, tiles);
    580    _map_tile_offset = 0;
    581}
    582
    583void set_tile_submap(uint8_t x, uint8_t y, uint8_t w, uint8_t h, uint8_t map_w, const uint8_t *map) Z88DK_CALLEE PRESERVES_REGS(iyh, iyl);
    584void set_tile_submap_compat(uint8_t x, uint8_t y, uint8_t w, uint8_t h, uint8_t map_w, const uint8_t *map) Z88DK_CALLEE PRESERVES_REGS(iyh, iyl);
    585inline void set_bkg_submap(uint8_t x, uint8_t y, uint8_t w, uint8_t h, const uint8_t *map, uint8_t map_w) {
    586    set_tile_submap_compat(x, y, w, h, map_w, map);
    587}
    588inline void set_win_submap(uint8_t x, uint8_t y, uint8_t w, uint8_t h, const uint8_t *map, uint8_t map_w) {
    589    set_tile_submap_compat(x, y, w, h, map_w, map);
    590}
    591
    592extern uint8_t _submap_tile_offset;
    593inline void set_bkg_based_submap(uint8_t x, uint8_t y, uint8_t w, uint8_t h, const uint8_t *map, uint8_t map_w, uint8_t base_tile) {
    594    _submap_tile_offset = base_tile;
    595    set_tile_submap_compat(x, y, w, h, map_w, map);
    596    _submap_tile_offset = 0;
    597}
    598inline void set_win_based_submap(uint8_t x, uint8_t y, uint8_t w, uint8_t h, const uint8_t *map, uint8_t map_w, uint8_t base_tile) {
    599    _submap_tile_offset = base_tile;
    600    set_tile_submap_compat(x, y, w, h, map_w, map);
    601    _submap_tile_offset = 0;
    602}
    603
    604void fill_rect(uint8_t x, uint8_t y, uint8_t w, uint8_t h, const uint16_t tile) Z88DK_CALLEE PRESERVES_REGS(iyh, iyl);
    605void fill_rect_compat(uint8_t x, uint8_t y, uint8_t w, uint8_t h, const uint16_t tile) Z88DK_CALLEE PRESERVES_REGS(iyh, iyl);
    606#define fill_bkg_rect fill_rect_compat
    607#define fill_win_rect fill_rect_compat
    608
    609/** Shadow OAM array in WRAM, that is transferred into the real OAM each VBlank
    610*/
    611extern volatile uint8_t shadow_OAM[];
    612
    613/** MSB of shadow_OAM address is used by OAM copying routine
    614*/
    615extern volatile uint8_t _shadow_OAM_base;
    616
    617/** Flag for disabling of OAM copying routine
    618
    619    Values:
    620    \li 1: OAM copy routine is disabled (non-isr VDP operation may be in progress)
    621    \li 0: OAM copy routine is enabled
    622
    623    This flag is modified by all sms/gg GBDK API calls that write to the VDP.
    624    It is set to DISABLED when they start and ENABLED when they complete.
    625
    626    @note It is recommended to avoid writing to the Video Display Processor
    627    (VDP) during an interrupt service routine (ISR) since it can corrupt
    628    the VDP pointer of an VDP operation already in progress.
    629
    630    If it is necessary, this flag can be used during an ISR to determine
    631    whether a VDP operation is already in progress. If the value is `1`
    632    then avoid writing to the VDP (tiles, map, scrolling, colors, etc).
    633
    634    \code{.c}
    635    // at the beginning of and ISR that would write to the VDP
    636    if (_shadow_OAM_OFF) return;
    637    \endcode
    638
    639    @see @ref docs_consoles_safe_display_controller_access
    640*/
    641extern volatile uint8_t _shadow_OAM_OFF;
    642
    643/** Disable shadow OAM to VRAM copy on each VBlank
    644*/
    645#define DISABLE_VBL_TRANSFER \
    646    _shadow_OAM_base = 0
    647
    648/** Enable shadow OAM to VRAM copy on each VBlank
    649*/
    650#define ENABLE_VBL_TRANSFER \
    651    _shadow_OAM_base = (uint8_t)((uint16_t)&shadow_OAM >> 8)
    652
    653/** Amount of hardware sprites in OAM
    654*/
    655#define MAX_HARDWARE_SPRITES 64
    656
    657/** Sets address of 256-byte aligned array of shadow OAM to be transferred on each VBlank
    658*/
    659inline void SET_SHADOW_OAM_ADDRESS(void * address) {
    660    _shadow_OAM_base = (uint8_t)((uint16_t)address >> 8);
    661}
    662
    663/** Sets sprite number __nb__in the OAM to display tile number __tile__.
    664
    665    @param nb    Sprite number, range 0 - 39
    666    @param tile  Selects a tile (0 - 255) from memory at 8000h - 8FFFh
    667                 \n In CGB Mode this could be either in VRAM Bank
    668                 \n 0 or 1, depending on Bit 3 of the OAM Attribute Flag
    669                 \n (see @ref set_sprite_prop)
    670
    671    In 8x16 mode:
    672    \li The sprite will also display the next tile (__tile__ + 1)
    673        directly below (y + 8) the first tile.
    674    \li The lower bit of the tile number is ignored:
    675        the upper 8x8 tile is (__tile__ & 0xFE), and
    676        the lower 8x8 tile is (__tile__ | 0x01).
    677    \li See: @ref SPRITES_8x16
    678*/
    679inline void set_sprite_tile(uint8_t nb, uint8_t tile) {
    680    shadow_OAM[0x41+(nb << 1)] = tile;
    681}
    682
    683
    684/** Returns the tile number of sprite number __nb__ in the OAM.
    685
    686@param nb    Sprite number, range 0 - 39
    687
    688@see set_sprite_tile for more details
    689*/
    690inline uint8_t get_sprite_tile(uint8_t nb) {
    691    return shadow_OAM[0x41+(nb << 1)];
    692}
    693
    694inline void set_sprite_prop(uint8_t nb, uint8_t prop) {
    695    nb; prop;
    696}
    697
    698inline uint8_t get_sprite_prop(uint8_t nb) {
    699    nb;
    700    return 0;
    701}
    702
    703/** Moves sprite number __nb__ to the __x__, __y__ position on the screen.
    704
    705    @param nb  Sprite number, range 0 - 39
    706    @param x   X Position. Specifies the sprites horizontal position on the screen (minus 8).
    707               \n An offscreen value (X=0 or X>=168) hides the sprite, but the sprite
    708               still affects the priority ordering - a better way to hide a sprite is to set
    709               its Y-coordinate offscreen.
    710    @param y   Y Position. Specifies the sprites vertical position on the screen (minus 16).
    711               \n An offscreen value (for example, Y=0 or Y>=160) hides the sprite.
    712
    713    Moving the sprite to 0,0 (or similar off-screen location) will hide it.
    714*/
    715inline void move_sprite(uint8_t nb, uint8_t x, uint8_t y) {
    716    shadow_OAM[nb] = (y < VDP_SAT_TERM) ? y : 0xC0;
    717    shadow_OAM[0x40+(nb << 1)] = x;
    718}
    719
    720
    721/** Moves sprite number __nb__ relative to its current position.
    722
    723    @param nb  Sprite number, range 0 - 39
    724    @param x   Number of pixels to move the sprite on the __X axis__
    725               \n Range: -128 - 127
    726    @param y   Number of pixels to move the sprite on the __Y axis__
    727               \n Range: -128 - 127
    728
    729    @see move_sprite for more details about the X and Y position
    730 */
    731inline void scroll_sprite(uint8_t nb, int8_t x, int8_t y) {
    732    uint8_t new_y = shadow_OAM[nb] + y;
    733    shadow_OAM[nb] = (new_y < VDP_SAT_TERM) ? new_y : 0xC0;
    734    shadow_OAM[0x40+(nb << 1)] = x;
    735}
    736
    737
    738/** Hides sprite number __nb__ by moving it to zero position by Y.
    739
    740    @param nb  Sprite number, range 0 - 39
    741 */
    742inline void hide_sprite(uint8_t nb) {
    743    shadow_OAM[nb] = 0xC0;
    744}
    745
    746/**
    747 * Set byte in vram at given memory location
    748 *
    749 * @param addr address to write to
    750 * @param v value
    751 */
    752void set_vram_byte(uint8_t * addr, uint8_t v) Z88DK_CALLEE PRESERVES_REGS(iyh, iyl);
    753
    754/**
    755 * Set single tile t with attributes on background layer at x,y
    756 * @param x X-coordinate
    757 * @param y Y-coordinate
    758 * @param t tile index
    759 * @return returns the address of tile, so you may use faster set_vram_byte() later
    760 */
    761uint8_t * set_attributed_tile_xy(uint8_t x, uint8_t y, uint16_t t) Z88DK_CALLEE PRESERVES_REGS(iyh, iyl);
    762
    763/**
    764 * Set single tile t on background layer at x,y
    765 * @param x X-coordinate
    766 * @param y Y-coordinate
    767 * @param t tile index
    768 * @return returns the address of tile, so you may use faster set_vram_byte() later
    769 */
    770uint8_t * set_tile_xy(uint8_t x, uint8_t y, uint8_t t) Z88DK_CALLEE PRESERVES_REGS(iyh, iyl);
    771#define set_bkg_tile_xy set_tile_xy
    772#define set_win_tile_xy set_tile_xy
    773
    774/**
    775 * Get address of X,Y tile of background map
    776 */
    777uint8_t * get_bkg_xy_addr(uint8_t x, uint8_t y) Z88DK_CALLEE PRESERVES_REGS(iyh, iyl);
    778#define get_win_xy_addr get_bkg_xy_addr
    779
    780#endif /* _SMS_H */