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