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 */