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