summaryrefslogtreecommitdiffstats
path: root/src/common.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/common.h')
-rw-r--r--src/common.h189
1 files changed, 153 insertions, 36 deletions
diff --git a/src/common.h b/src/common.h
index ff5ea12..7a0c50c 100644
--- a/src/common.h
+++ b/src/common.h
@@ -83,29 +83,45 @@
83#define SCREEN_WIDTH 240 83#define SCREEN_WIDTH 240
84#define SCREEN_HEIGHT 160 84#define SCREEN_HEIGHT 160
85 85
86//
87// Colors.
88//
89
86// The GBA in mode 3 expects rbg15 colors in the VRAM, where each component 90// The GBA in mode 3 expects rbg15 colors in the VRAM, where each component
87// (RGB) have a 0--31 range. For example, pure red would be rgb15(31, 0, 0). 91// (RGB) have a 0--31 range. For example, pure red would be rgb15(31, 0, 0).
88typedef u16 Color; 92typedef u16 Color;
89 93
90// A palette is composed of 16 colors, with color at index 0 being transparent. 94// A palette is composed of 16 colors, with color at index 0 being transparent
95// for sprites.
91typedef Color Palette[16]; 96typedef Color Palette[16];
92 97
98// Inline function to calculate the 15 bit color value.
99static inline Color
100rgb15(u32 red, u32 green, u32 blue ) {
101 return (blue << 10) | (green << 5) | red;
102}
103
104// Some nice default colors.
105#define COLOR_RED rgb15(31, 0, 12)
106#define COLOR_BLUE rgb15(2, 15, 30)
107#define COLOR_CYAN rgb15(0, 30, 30)
108#define COLOR_GREY rgb15(4, 4, 4)
109#define COLOR_BLACK rgb15(0, 0, 0)
110#define COLOR_WHITE rgb15(28, 28, 28)
111
93// 112//
94// Tile memory access. 113// Tile memory access.
95// 114//
96 115
97// NOTE: Only defining 4bpp tiles for now. 116// NOTE: Only defining 4bpp tiles for now.
98typedef struct Tile { 117typedef struct Tile {
99 u32 data[8]; 118 u32 row[8];
100} Tile; 119} Tile;
101 120
121// Screenblocks and charblocks (tile blocks).
102typedef Tile TileBlock[512]; 122typedef Tile TileBlock[512];
103#define TILE_MEM ((TileBlock*) MEM_VRAM) 123#define TILE_MEM ((TileBlock*) MEM_VRAM)
104
105// Screenblocks and charblocks for backgrounds.
106typedef u16 ScreenBlock[1024]; 124typedef u16 ScreenBlock[1024];
107typedef Tile CharBlock[512];
108#define CHARBLOCK_MEM ((CharBlock*)MEM_VRAM)
109#define SCREENBLOCK_MEM ((ScreenBlock*)MEM_VRAM) 125#define SCREENBLOCK_MEM ((ScreenBlock*)MEM_VRAM)
110 126
111// Screenblock entry bits. 127// Screenblock entry bits.
@@ -113,40 +129,24 @@ typedef Tile CharBlock[512];
113#define SCREENBLOCK_ENTRY_V_FLIP (1 << 0xB) 129#define SCREENBLOCK_ENTRY_V_FLIP (1 << 0xB)
114#define SCREENBLOCK_ENTRY_PAL(N) ((N) << 0xC) 130#define SCREENBLOCK_ENTRY_PAL(N) ((N) << 0xC)
115 131
116size_t se_index(size_t tile_x, size_t tile_y, size_t map_width) { 132size_t
133se_index(size_t tile_x, size_t tile_y, size_t map_width) {
117 size_t sbb = ((tile_x >> 5) + (tile_y >> 5) * (map_width >> 5)); 134 size_t sbb = ((tile_x >> 5) + (tile_y >> 5) * (map_width >> 5));
118 return sbb * 1024 + ((tile_x & 31) + (tile_y & 31) * 32); 135 return sbb * 1024 + ((tile_x & 31) + (tile_y & 31) * 32);
119} 136}
120 137
121
122// We can treat the screen as a HxW matrix. With the following macro we can 138// We can treat the screen as a HxW matrix. With the following macro we can
123// write a pixel to the screen at the (x, y) position using: 139// write a pixel to the screen at the (x, y) position using:
124// 140//
125// FRAMEBUFFER[y][x] = color; 141// FRAMEBUFFER[y][x] = color;
126// 142//
127typedef Color Scanline[SCREEN_WIDTH]; 143typedef Color Scanline[SCREEN_WIDTH];
128#define FRAMEBUFFER ((Scanline*)MEM_VRAM) 144#define FRAMEBUFFER ((Scanline*) MEM_VRAM)
129#define SCREEN_BUFFER ((u16*) MEM_VRAM) 145#define SCREEN_BUFFER ((u16*) MEM_VRAM)
130#define PAL_BUFFER_BG ((u16*) MEM_PAL) 146#define PAL_BUFFER_BG ((u16*) MEM_PAL)
131#define PAL_BUFFER_SPRITES ((u16*) 0x05000200) 147#define PAL_BUFFER_SPRITES ((u16*)(MEM_PAL + 0x200))
132#define PAL_BANK_BG ((Palette*) MEM_PAL) 148#define PAL_BANK_BG ((Palette*) MEM_PAL)
133#define PAL_BANK_SPRITES ((Palette*) 0x05000200) 149#define PAL_BANK_SPRITES ((Palette*)(MEM_PAL + 0x200))
134
135//
136// Colors.
137//
138
139static inline Color
140rgb15(u32 red, u32 green, u32 blue ) {
141 return (blue << 10) | (green << 5) | red;
142}
143
144#define COLOR_RED rgb15(31, 0, 12)
145#define COLOR_BLUE rgb15(2, 15, 30)
146#define COLOR_CYAN rgb15(0, 30, 30)
147#define COLOR_GREY rgb15(4, 4, 4)
148#define COLOR_BLACK rgb15(0, 0, 0)
149#define COLOR_WHITE rgb15(28, 28, 28)
150 150
151// 151//
152// Sprites. 152// Sprites.
@@ -191,12 +191,6 @@ rgb15(u32 red, u32 green, u32 blue ) {
191#define OBJ_PRIORITY(N) ((N) << 0xA) 191#define OBJ_PRIORITY(N) ((N) << 0xA)
192#define OBJ_PAL_BANK(N) ((N) << 0xC) 192#define OBJ_PAL_BANK(N) ((N) << 0xC)
193 193
194static inline void
195wait_vsync(void) {
196 while(DISP_VCOUNT >= 160);
197 while(DISP_VCOUNT < 160);
198}
199
200// 194//
201// Mode 4 page flipping 195// Mode 4 page flipping
202// 196//
@@ -505,11 +499,12 @@ irs_set(IrqIndex idx, IrsFunc func) {
505 IRQ_CTRL = irq_ctrl; 499 IRQ_CTRL = irq_ctrl;
506} 500}
507 501
508#define IRS_MAIN *(IrsFunc*)(0x03007FFC)
509
510// External irs_main function, has to be written in ARM assembly. 502// External irs_main function, has to be written in ARM assembly.
511void irs_main(void); 503void irs_main(void);
512 504
505// Initialize the function pointer for the main IRS routine written in ARM
506// assembly and enable interrupts.
507#define IRS_MAIN *(IrsFunc*)(0x03007FFC)
513void 508void
514irq_init() { 509irq_init() {
515 IRS_MAIN = irs_main; 510 IRS_MAIN = irs_main;
@@ -519,6 +514,128 @@ irq_init() {
519// Stub function pointer needed for when we want to enable interrupts that don't 514// Stub function pointer needed for when we want to enable interrupts that don't
520// require a custom function, such as for the BIOS VSync. 515// require a custom function, such as for the BIOS VSync.
521void 516void
522irq_stub() {} 517irs_stub() {}
518
519//
520// BIOS function declarations.
521//
522
523// These functions declarations can be used to call the BIOS functions from the
524// asm code.
525int bios_vblank_wait();
526int bios_div(int num, int denom);
527
528//
529// Sound.
530//
531
532// Sound registers.
533#define SOUND_SQUARE1_SWEEP *((vu16*)(MEM_IO + 0x60))
534#define SOUND_SQUARE1_CTRL *((vu16*)(MEM_IO + 0x62))
535#define SOUND_SQUARE1_FREQ *((vu16*)(MEM_IO + 0x64))
536#define SOUND_SQUARE2_CTRL *((vu16*)(MEM_IO + 0x68))
537#define SOUND_SQUARE2_FREQ *((vu16*)(MEM_IO + 0x6C))
538#define SOUND_WAVE_MODE *((vu16*)(MEM_IO + 0x70))
539#define SOUND_WAVE_CTRL *((vu16*)(MEM_IO + 0x72))
540#define SOUND_WAVE_FREQ *((vu16*)(MEM_IO + 0x74))
541#define SOUND_NOISE_CTRL *((vu16*)(MEM_IO + 0x78))
542#define SOUND_NOISE_FREQ *((vu16*)(MEM_IO + 0x7C))
543#define SOUND_DMG_MASTER *((vu16*)(MEM_IO + 0x80))
544#define SOUND_DSOUND_MASTER *((vu16*)(MEM_IO + 0x82))
545#define SOUND_STATUS *((vu16*)(MEM_IO + 0x84))
546#define SOUND_BIAS *((vu16*)(MEM_IO + 0x88))
547
548// Sound DMG master bits.
549#define SOUND_VOLUME_LEFT(N) (N)
550#define SOUND_VOLUME_RIGHT(N) ((N) << 4)
551#define SOUND_ENABLE_SQUARE1_LEFT (1 << 0x8)
552#define SOUND_ENABLE_SQUARE2_LEFT (1 << 0x9)
553#define SOUND_ENABLE_WAVE_LEFT (1 << 0xA)
554#define SOUND_ENABLE_NOISE_LEFT (1 << 0xB)
555#define SOUND_ENABLE_SQUARE1_RIGHT (1 << 0xC)
556#define SOUND_ENABLE_SQUARE2_RIGHT (1 << 0xD)
557#define SOUND_ENABLE_WAVE_RIGHT (1 << 0xE)
558#define SOUND_ENABLE_NOISE_RIGHT (1 << 0xF)
559
560typedef enum {
561 SOUND_SQUARE1 = (0x1 << 0),
562 SOUND_SQUARE2 = (0x1 << 1),
563 SOUND_WAVE = (0x4 << 2),
564 SOUND_NOISE = (0x8 << 3),
565} SoundChannel;
566
567u16
568sound_volume(SoundChannel channels, u8 volume) {
569 volume = volume & 0x7;
570 channels = channels & 0xF;
571 return volume | (volume << 0x4) | (channels << 0x8) | (channels << 0xC);
572}
573
574// Sound Direct Sound master bits.
575#define SOUND_DMG25 0x0
576#define SOUND_DMG50 0x1
577#define SOUND_DMG100 0x2
578#define SOUND_DSOUND_RATIO_A (1 << 0x2)
579#define SOUND_DSOUND_RATIO_B (1 << 0x3)
580#define SOUND_DSOUND_LEFT_A (1 << 0x8)
581#define SOUND_DSOUND_RIGHT_A (1 << 0x9)
582#define SOUND_DSOUND_TIMER_A (1 << 0xA)
583#define SOUND_DSOUND_RESET_A (1 << 0xB)
584#define SOUND_DSOUND_LEFT_B (1 << 0xC)
585#define SOUND_DSOUND_RIGHT_B (1 << 0xD)
586#define SOUND_DSOUND_TIMER_B (1 << 0xE)
587#define SOUND_DSOUND_RESET_B (1 << 0xF)
588
589// Sound status bits.
590#define SOUND_ENABLE (1 << 0x7)
591
592// DMG square control bits.
593#define SOUND_SQUARE_LEN(N) (N)
594#define SOUND_SQUARE_DUTY(N) ((N) << 0x6)
595#define SOUND_SQUARE_ENV_TIME(N) ((N) << 0x8)
596#define SOUND_SQUARE_ENV_INC (1 << 0xB)
597#define SOUND_SQUARE_ENV_VOL(N) ((N) << 0xC)
598
599// DMG square frequency bits.
600#define SOUND_SQUARE_TIMED (1 << 0xE)
601#define SOUND_SQUARE_RESET (1 << 0xF)
602
603typedef enum {
604 NOTE_C,
605 NOTE_C_SHARP,
606 NOTE_D,
607 NOTE_D_SHARP,
608 NOTE_E,
609 NOTE_F,
610 NOTE_F_SHARP,
611 NOTE_G,
612 NOTE_G_SHARP,
613 NOTE_A,
614 NOTE_A_SHARP,
615 NOTE_B,
616} Note;
617
618u32
619sound_rate(Note note, u32 octave) {
620 const u32 base_rate[12] = {
621 8013, 7566, 7144, 6742, // C , C#, D , D#
622 6362, 6005, 5666, 5346, // E , F , F#, G
623 5048, 4766, 4499, 4246 // G#, A , A#, B
624 };
625 return 2048 - (base_rate[note] >> (4 + octave));
626}
627
628//
629// Misc.
630//
631
632// Custom VSync option. This will waste a lot of battery power, since the
633// machine is not clocked down. Prefer using `bios_vblank_wait()` if interrupts
634// are enabled.
635static inline void
636wait_vsync(void) {
637 while(DISP_VCOUNT >= 160);
638 while(DISP_VCOUNT < 160);
639}
523 640
524#endif // GBAEXP_COMMON_H 641#endif // GBAEXP_COMMON_H