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