aboutsummaryrefslogtreecommitdiffstats
path: root/src/gba/gba.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/gba/gba.h')
-rw-r--r--src/gba/gba.h667
1 files changed, 667 insertions, 0 deletions
diff --git a/src/gba/gba.h b/src/gba/gba.h
new file mode 100644
index 0000000..56c4876
--- /dev/null
+++ b/src/gba/gba.h
@@ -0,0 +1,667 @@
1#ifndef GBA_H
2#define GBA_H
3
4#include "shorthand.h"
5
6#define CPU_FREQUENCY (2 << 23)
7
8//
9// Memory sections.
10//
11
12// Defines for the different memory sections in the GBA.
13#define MEM_SROM 0x00000000
14#define MEM_EW 0x02000000
15#define MEM_IW 0x03000000
16#define MEM_IO 0x04000000
17#define MEM_PAL 0x05000000
18#define MEM_VRAM 0x06000000
19#define MEM_OAM 0x07000000
20#define MEM_PAK 0x08000000
21#define MEM_CART 0x0E000000
22
23//
24// Display modes.
25//
26
27// Display registers.
28#define DISP_CTRL *((vu32*)(MEM_IO + 0x0000))
29#define DISP_STATUS *((vu16*)(MEM_IO + 0x0004))
30#define DISP_VCOUNT *((vu16*)(MEM_IO + 0x0006))
31
32// The first three bits in the DISP_CTRL are used to control the video mode.
33#define DISP_MODE_0 0x0000
34#define DISP_MODE_1 0x0001
35#define DISP_MODE_2 0x0002
36#define DISP_MODE_3 0x0003
37#define DISP_MODE_4 0x0004
38#define DISP_MODE_5 0x0005
39#define DISP_GB (1 << 3)
40#define DISP_PAGE (1 << 4)
41#define DISP_OAM_HBLANK (1 << 5)
42#define DISP_OBJ_1D (1 << 6)
43#define DISP_BLANK (1 << 7)
44#define DISP_BG_0 (1 << 8)
45#define DISP_BG_1 (1 << 9)
46#define DISP_BG_2 (1 << 10)
47#define DISP_BG_3 (1 << 11)
48#define DISP_OBJ (1 << 12)
49#define DISP_ENABLE_SPRITES DISP_OBJ | DISP_OBJ_1D
50
51// These bits are used to control the DISP_STATUS register.
52#define DISP_VBLANK_STATUS (1 << 0x0)
53#define DISP_HBLANK_STATUS (1 << 0x1)
54#define DISP_VCOUNT_STATUS (1 << 0x2)
55#define DISP_VBLANK_IRQ (1 << 0x3)
56#define DISP_HBLANK_IRQ (1 << 0x4)
57#define DISP_VCOUNT_IRQ (1 << 0x5)
58#define DISP_VCOUNT_TRIGGER(N) ((N) << 0x8)
59
60// Registers to control of BG layers.
61#define BG_CTRL(N) *((vu16*)(0x04000008 + 0x0002 * (N)))
62
63// Bits to control the background.
64#define BG_PRIORITY(N) ((N) & 0x3)
65#define BG_CHARBLOCK(N) ((N) << 2)
66#define BG_MOSAIC (1 << 6)
67#define BG_HIGH_COLOR (1 << 7)
68#define BG_SCREENBLOCK(N) ((N) << 8)
69#define BG_AFFINE (1 << 0xD)
70#define BG_SIZE(N) ((N) << 0xE)
71
72// BG registers for horizontal displacement.
73#define BG_H_SCROLL_0 *((vu16*)(0x04000010 + 0x0004 * 0))
74#define BG_H_SCROLL_1 *((vu16*)(0x04000010 + 0x0004 * 1))
75#define BG_H_SCROLL_2 *((vu16*)(0x04000010 + 0x0004 * 2))
76#define BG_H_SCROLL_3 *((vu16*)(0x04000010 + 0x0004 * 3))
77
78// BG registers for vertical displacement.
79#define BG_V_SCROLL_0 *((vu16*)(0x04000012 + 0x0004 * 0))
80#define BG_V_SCROLL_1 *((vu16*)(0x04000012 + 0x0004 * 1))
81#define BG_V_SCROLL_2 *((vu16*)(0x04000012 + 0x0004 * 2))
82#define BG_V_SCROLL_3 *((vu16*)(0x04000012 + 0x0004 * 3))
83
84// Screen settings.
85#define SCREEN_WIDTH 240
86#define SCREEN_HEIGHT 160
87
88//
89// Colors.
90//
91
92// The GBA in mode 3 expects rbg15 colors in the VRAM, where each component
93// (RGB) have a 0--31 range. For example, pure red would be rgb15(31, 0, 0).
94typedef u16 Color;
95
96// A palette is composed of 16 colors, with color at index 0 being transparent
97// for sprites.
98typedef Color Palette[16];
99
100// Inline function to calculate the 15 bit color value.
101#define RGB15(R,G,B) (u16)(((B) << 10) | ((G) << 5) | (R));
102
103// Some nice default colors.
104#define COLOR_RED RGB15(31, 0,12)
105#define COLOR_BLUE RGB15(2, 15,30)
106#define COLOR_CYAN RGB15(0, 30,30)
107#define COLOR_GREY RGB15(12,12,12)
108#define COLOR_BLACK RGB15(0, 0, 0)
109#define COLOR_WHITE RGB15(28,28,28)
110
111//
112// Tile memory access.
113//
114
115// NOTE: Only defining 4bpp tiles for now.
116// TODO: typedef u32 Tile[8];
117typedef struct Tile {
118 u32 row[8];
119} Tile;
120
121// Screenblocks and charblocks (tile blocks).
122typedef Tile TileBlock[512];
123#define TILE_MEM ((TileBlock*) MEM_VRAM)
124typedef u16 ScreenBlock[1024];
125#define SCREENBLOCK_MEM ((ScreenBlock*)MEM_VRAM)
126
127// Screenblock entry bits.
128#define SCREENBLOCK_ENTRY_H_FLIP (1 << 0xA)
129#define SCREENBLOCK_ENTRY_V_FLIP (1 << 0xB)
130#define SCREENBLOCK_ENTRY_PAL(N) ((N) << 0xC)
131
132inline size_t
133se_index(size_t tile_x, size_t tile_y, size_t map_width) {
134 size_t sbb = ((tile_x >> 5) + (tile_y >> 5) * (map_width >> 5));
135 return sbb * 1024 + ((tile_x & 31) + (tile_y & 31) * 32);
136}
137
138// We can treat the screen as a HxW matrix. With the following macro we can
139// write a pixel to the screen at the (x, y) position using:
140//
141// FRAMEBUFFER[y][x] = color;
142//
143typedef Color Scanline[SCREEN_WIDTH];
144#define FRAMEBUFFER ((Scanline*) MEM_VRAM)
145#define SCREEN_BUFFER ((u16*) MEM_VRAM)
146#define PAL_BUFFER_BG ((u16*) MEM_PAL)
147#define PAL_BUFFER_SPRITES ((u16*)(MEM_PAL + 0x200))
148#define PAL_BANK_BG ((Palette*) MEM_PAL)
149#define PAL_BANK_SPRITES ((Palette*)(MEM_PAL + 0x200))
150
151//
152// Sprites.
153//
154
155// Using macros instead of aligned structs for setting up OBJ attributes and
156// affine parameters.
157// TODO: Benchmark if this would be slower or the same that TONC's
158// implementation.
159// TODO: Cleanup OBJ/OAM memory copying and access.
160#define OBJ_ATTR_0(N) *((vu16*)(MEM_OAM + 0 + 8 * (N)))
161#define OBJ_ATTR_1(N) *((vu16*)(MEM_OAM + 2 + 8 * (N)))
162#define OBJ_ATTR_2(N) *((vu16*)(MEM_OAM + 4 + 8 * (N)))
163#define OBJ_AFFINE_PA(N) *((vs16*)(MEM_OAM + 6 + 8 * 0 + 8 * 4 * (N)))
164#define OBJ_AFFINE_PB(N) *((vs16*)(MEM_OAM + 6 + 8 * 1 + 8 * 4 * (N)))
165#define OBJ_AFFINE_PC(N) *((vs16*)(MEM_OAM + 6 + 8 * 2 + 8 * 4 * (N)))
166#define OBJ_AFFINE_PD(N) *((vs16*)(MEM_OAM + 6 + 8 * 3 + 8 * 4 * (N)))
167
168// OBJ_ATTR_0 parameters
169#define OBJ_Y_COORD(N) ((N) & 0xFF)
170#define OBJ_NORMAL (0x00 << 0x8)
171#define OBJ_AFFINE (0x01 << 0x8)
172#define OBJ_HIDDEN (0x02 << 0x8)
173#define OBJ_AFFINE_2X (0x03 << 0x8)
174#define OBJ_ALPHA_BLEND (0x01 << 0xA)
175#define OBJ_WINDOW (0x02 << 0xA)
176#define OBJ_SHAPE_SQUARE (0x00 << 0xE)
177#define OBJ_SHAPE_WIDE (0x01 << 0xE)
178#define OBJ_SHAPE_TALL (0x02 << 0xE)
179
180// OBJ_ATTR_1 parameters
181#define OBJ_X_COORD(N) ((N) & 0x1FF)
182#define OBJ_AFFINE_IDX(N) ((N) << 0x9)
183#define OBJ_H_FLIP (0x01 << 0xC)
184#define OBJ_V_FLIP (0x01 << 0xD)
185#define OBJ_SIZE_SMALL (0x00 << 0xE)
186#define OBJ_SIZE_MID (0x01 << 0xE)
187#define OBJ_SIZE_BIG (0x02 << 0xE)
188#define OBJ_SIZE_HUGE (0x03 << 0xE)
189
190// OBJ_ATTR_2 parameters
191#define OBJ_TILE_INDEX(N) ((N) & 0x3FF)
192#define OBJ_PRIORITY(N) ((N) << 0xA)
193#define OBJ_PAL_BANK(N) ((N) << 0xC)
194
195//
196// Mode 4 page flipping
197//
198
199static inline
200void
201flip_page(vu16 *backbuffer) {
202 backbuffer = (u16*)((u32)backbuffer ^ 0x0A000);
203 DISP_CTRL ^= DISP_PAGE;
204}
205
206#define SCREEN_PAGE_1 ((vu16*) MEM_VRAM)
207#define SCREEN_PAGE_2 ((vu16*) (MEM_VRAM + 0xa000))
208
209//
210// Profiling.
211//
212
213#define TIMER_DATA_0 *((vu16*) (0x04000100 + 0x04 * 0))
214#define TIMER_DATA_1 *((vu16*) (0x04000100 + 0x04 * 1))
215#define TIMER_DATA_2 *((vu16*) (0x04000100 + 0x04 * 2))
216#define TIMER_DATA_3 *((vu16*) (0x04000100 + 0x04 * 3))
217#define TIMER_CTRL_0 *((vu16*) (0x04000102 + 0x04 * 0))
218#define TIMER_CTRL_1 *((vu16*) (0x04000102 + 0x04 * 1))
219#define TIMER_CTRL_2 *((vu16*) (0x04000102 + 0x04 * 2))
220#define TIMER_CTRL_3 *((vu16*) (0x04000102 + 0x04 * 3))
221
222// Timer control bits.
223#define TIMER_CTRL_FREQ_0 0
224#define TIMER_CTRL_FREQ_1 1
225#define TIMER_CTRL_FREQ_2 2
226#define TIMER_CTRL_FREQ_3 3
227#define TIMER_CTRL_CASCADE (1 << 2)
228#define TIMER_CTRL_IRQ (1 << 6)
229#define TIMER_CTRL_ENABLE (1 << 7)
230#define TIMER_CTRL_DISABLE (0 << 7)
231
232// We use timers 2 and 3 to count the number of cycles since the profile_start
233// functions is called. Don't use if the code we are trying to profile make use
234// of these timers.
235static inline
236void
237profile_start(void) {
238 TIMER_DATA_2 = 0;
239 TIMER_DATA_3 = 0;
240 TIMER_CTRL_2 = 0;
241 TIMER_CTRL_3 = 0;
242 TIMER_CTRL_3 = TIMER_CTRL_ENABLE | TIMER_CTRL_CASCADE;
243 TIMER_CTRL_2 = TIMER_CTRL_ENABLE;
244}
245
246static inline
247u32
248profile_stop(void) {
249 TIMER_CTRL_2 = 0;
250 return (TIMER_DATA_3 << 16) | TIMER_DATA_2;
251}
252
253static inline
254u32
255profile_measure(void) {
256 return (TIMER_DATA_3 << 16) | TIMER_DATA_2;
257}
258
259//
260// Input handling.
261//
262
263// Memory address for key input and control register
264#define KEY_INPUTS *((vu16*) 0x04000130)
265#define KEY_CTRL *((vu16*) 0x04000132)
266
267// Key control register bits.
268#define KEY_IRQ_KEY(N) (N)
269#define KEY_IRQ (1 << 0xE)
270#define KEY_IRQ_IF_SET (1 << 0xF)
271
272// Alias for key pressing bits.
273#define KEY_A (1 << 0)
274#define KEY_B (1 << 1)
275#define KEY_SELECT (1 << 2)
276#define KEY_START (1 << 3)
277#define KEY_RIGHT (1 << 4)
278#define KEY_LEFT (1 << 5)
279#define KEY_UP (1 << 6)
280#define KEY_DOWN (1 << 7)
281#define KEY_R (1 << 8)
282#define KEY_L (1 << 9)
283
284#define KEY_MASK 0x03FF
285
286// Saving the previous and current key states as globals for now.
287static u16 key_curr = 0;
288static u16 key_prev = 0;
289
290static inline
291void
292poll_keys(void) {
293 key_prev = key_curr;
294 key_curr = ~KEY_INPUTS & KEY_MASK;
295}
296
297// Returns true if the given key has been pressed at time of calling and was not
298// pressed since the previous call. For example, if a key is being held, this
299// function will return `true` only on the frame where the key initially
300// activated.
301static inline
302u32
303key_tap(u32 key) {
304 return (key_curr & key) & ~(key_prev & key);
305}
306
307// Check if a given key is currently pressed.
308static inline
309u32
310key_pressed(u32 key) {
311 return (key_curr & key);
312}
313
314// Check if a given key was just released.
315static inline
316u32
317key_released(u32 key) {
318 return ~(key_curr & key) & (key_prev & key);
319}
320
321// Check if the given key is pressed and has been since at least one frame.
322static inline
323u32
324key_hold(u32 key) {
325 return key_curr & key_prev & key;
326}
327
328// Check if the given key/button is currently pressed.
329#define KEY_PRESSED(key) (~(KEY_INPUTS) & key)
330
331// Back/unpack bits.
332static inline
333u32
334unpack_1bb(u8 hex) {
335 const u32 conversion_u32[16] = {
336 0x00000000, 0x00000001, 0x00000010, 0x00000011,
337 0x00000100, 0x00000101, 0x00000110, 0x00000111,
338 0x00001000, 0x00001001, 0x00001010, 0x00001011,
339 0x00001100, 0x00001101, 0x00001110, 0x00001111,
340 };
341 u8 low = hex & 0xF;
342 u8 high = (hex >> 4) & 0xF;
343 return (conversion_u32[high] << 16) | conversion_u32[low];
344}
345
346// Unpack N tiles packed at 1bpp.
347static inline
348void
349unpack_tiles(u32 *src, u32 *dst, size_t n_tiles) {
350 u32 *target_src = src + n_tiles * 2;
351 while (src != target_src) {
352 *dst++ = unpack_1bb((*src >> 24) & 0xFF);
353 *dst++ = unpack_1bb((*src >> 16) & 0xFF);
354 *dst++ = unpack_1bb((*src >> 8) & 0xFF);
355 *dst++ = unpack_1bb(*src & 0xFF);
356 src++;
357 }
358}
359
360//
361// Direct Memory Access (DMA)
362//
363
364
365// Source, destination, and control registers.
366#define DMA_SRC(N) *((vu32*) 0x040000B0 + (N) * 12)
367#define DMA_DST(N) *((vu32*) 0x040000B4 + (N) * 12)
368#define DMA_CTRL(N) *((vu32*) 0x040000B8 + (N) * 12)
369
370// DMA control bits.
371#define DMA_DST_INC (0 << 0x15)
372#define DMA_DST_DEC (1 << 0x15)
373#define DMA_DST_FIXED (2 << 0x15)
374#define DMA_DST_RELOAD (3 << 0x15)
375#define DMA_SRC_INC (0 << 0x17)
376#define DMA_SRC_DEC (1 << 0x17)
377#define DMA_SRC_FIXED (2 << 0x17)
378#define DMA_REPEAT (1 << 0x19)
379#define DMA_CHUNK_16 (0 << 0x1A)
380#define DMA_CHUNK_32 (1 << 0x1A)
381#define DMA_NOW (0 << 0x1C)
382#define DMA_VBLANK (1 << 0x1C)
383#define DMA_HBLANK (2 << 0x1C)
384#define DMA_REFRESH (3 << 0x1C)
385#define DMA_IRQ (1 << 0x1E)
386#define DMA_ENABLE (1 << 0x1F)
387
388// Custom struct for cleaner DMA transfer functions.
389typedef struct DmaStr {
390 const void *src;
391 void *dst;
392 u32 ctrl;
393} DmaStr;
394
395#define DMA_TRANSFER ((volatile DmaStr*) 0x040000B0)
396
397// Transfer `count` number of chunks from src to dst using a DMA channel. Note
398// that chunks are not bytes, but instead configured based on bits set by
399// DMA_CTRL.
400inline
401void
402dma_transfer_copy(void *dst, const void *src, u32 count, int channel, u32 options) {
403 DMA_TRANSFER[channel].ctrl = 0;
404 DMA_TRANSFER[channel].src = src;
405 DMA_TRANSFER[channel].dst = dst;
406 DMA_TRANSFER[channel].ctrl = count | options;
407}
408
409inline
410void
411dma_transfer_fill(void *dst, volatile u32 src, u32 count, int channel, u32 options) {
412 DMA_TRANSFER[channel].ctrl = 0;
413 DMA_TRANSFER[channel].src = (const void *)&src;
414 DMA_TRANSFER[channel].dst = dst;
415 DMA_TRANSFER[channel].ctrl = count | options | DMA_SRC_FIXED;
416}
417
418// Copy N number of bytes using a DMA channel.
419inline
420void
421dma_copy(void *dst, const void *src, u32 size, int channel) {
422 dma_transfer_copy(dst, src, size / 4, channel, DMA_CHUNK_32 | DMA_ENABLE);
423}
424
425// Fill the dst location with the word set at src.
426inline
427void
428dma_fill(void *dst, vu32 src, u32 size, int channel) {
429 dma_transfer_fill(dst, src, size / 4, channel, DMA_CHUNK_32 | DMA_ENABLE);
430}
431
432//
433// Interrupts.
434//
435
436#define IRQ_ENABLE *((vu16*) 0x04000200)
437#define IRQ_ACK *((vu16*) 0x04000202)
438#define IRQ_CTRL *((vu16*) 0x04000208)
439#define IRQ_ACK_BIOS *((vu16*) 0x03007FF8)
440
441typedef enum {
442 IRQ_VBLANK,
443 IRQ_HBLANK,
444 IRQ_VCOUNT,
445 IRQ_TIMER_0,
446 IRQ_TIMER_1,
447 IRQ_TIMER_2,
448 IRQ_TIMER_3,
449 IRQ_SERIAL,
450 IRQ_DMA_0,
451 IRQ_DMA_1,
452 IRQ_DMA_2,
453 IRQ_DMA_3,
454 IRQ_KEYPAD,
455 IRQ_GAMEPAK,
456} IrqIndex;
457
458typedef void (*IrsFunc)(void);
459
460// Stub function pointer needed for when we want to enable interrupts that don't
461// require a custom function, such as for the BIOS VSync.
462void irs_stub(void);
463
464// Set and enable a given function in the interrupt table. If func is NULL, the
465// interrupt will be disabled instead.
466void irs_set(IrqIndex idx, IrsFunc func);
467
468// Initialize the function pointer for the main IRS routine written in ARM
469// assembly and enable interrupts.
470void irq_init(void);
471
472//
473// BIOS function declarations.
474//
475
476// These functions declarations can be used to call the BIOS functions from the
477// asm code.
478int bios_vblank_wait();
479int bios_div(int num, int denom);
480
481//
482// Sound.
483//
484
485// Sound registers.
486#define SOUND_SQUARE1_SWEEP *((vu16*)(MEM_IO + 0x60))
487#define SOUND_SQUARE1_CTRL *((vu16*)(MEM_IO + 0x62))
488#define SOUND_SQUARE1_FREQ *((vu16*)(MEM_IO + 0x64))
489#define SOUND_SQUARE2_CTRL *((vu16*)(MEM_IO + 0x68))
490#define SOUND_SQUARE2_FREQ *((vu16*)(MEM_IO + 0x6C))
491#define SOUND_WAVE_MODE *((vu16*)(MEM_IO + 0x70))
492#define SOUND_WAVE_CTRL *((vu16*)(MEM_IO + 0x72))
493#define SOUND_WAVE_FREQ *((vu16*)(MEM_IO + 0x74))
494#define SOUND_NOISE_CTRL *((vu16*)(MEM_IO + 0x78))
495#define SOUND_NOISE_FREQ *((vu16*)(MEM_IO + 0x7C))
496#define SOUND_DMG_MASTER *((vu16*)(MEM_IO + 0x80))
497#define SOUND_DSOUND_MASTER *((vu16*)(MEM_IO + 0x82))
498#define SOUND_STATUS *((vu16*)(MEM_IO + 0x84))
499#define SOUND_BIAS *((vu16*)(MEM_IO + 0x88))
500
501// Sound DMG master bits.
502#define SOUND_VOLUME_LEFT(N) (N)
503#define SOUND_VOLUME_RIGHT(N) ((N) << 4)
504#define SOUND_ENABLE_SQUARE1_LEFT (1 << 0x8)
505#define SOUND_ENABLE_SQUARE2_LEFT (1 << 0x9)
506#define SOUND_ENABLE_WAVE_LEFT (1 << 0xA)
507#define SOUND_ENABLE_NOISE_LEFT (1 << 0xB)
508#define SOUND_ENABLE_SQUARE1_RIGHT (1 << 0xC)
509#define SOUND_ENABLE_SQUARE2_RIGHT (1 << 0xD)
510#define SOUND_ENABLE_WAVE_RIGHT (1 << 0xE)
511#define SOUND_ENABLE_NOISE_RIGHT (1 << 0xF)
512
513typedef enum {
514 SOUND_DSOUND = (0x0 << 0),
515 SOUND_SQUARE1 = (0x1 << 0),
516 SOUND_SQUARE2 = (0x1 << 1),
517 SOUND_WAVE = (0x1 << 2),
518 SOUND_NOISE = (0x1 << 3),
519} SoundChannel;
520
521inline u16
522sound_volume(SoundChannel channels, u8 volume) {
523 volume = volume & 0x7;
524 channels = channels & 0xF;
525 return volume | (volume << 0x4) | (channels << 0x8) | (channels << 0xC);
526}
527
528// Sound Direct Sound master bits.
529#define SOUND_DMG25 0x0
530#define SOUND_DMG50 0x1
531#define SOUND_DMG100 0x2
532#define SOUND_DSOUND_RATIO_A (1 << 0x2)
533#define SOUND_DSOUND_RATIO_B (1 << 0x3)
534#define SOUND_DSOUND_LEFT_A (1 << 0x8)
535#define SOUND_DSOUND_RIGHT_A (1 << 0x9)
536#define SOUND_DSOUND_TIMER_A (1 << 0xA)
537#define SOUND_DSOUND_RESET_A (1 << 0xB)
538#define SOUND_DSOUND_LEFT_B (1 << 0xC)
539#define SOUND_DSOUND_RIGHT_B (1 << 0xD)
540#define SOUND_DSOUND_TIMER_B (1 << 0xE)
541#define SOUND_DSOUND_RESET_B (1 << 0xF)
542
543// Direct sound FIFO queues.
544#define SOUND_FIFO_A ((u16*)(MEM_IO + 0xA0))
545#define SOUND_FIFO_B ((u16*)(MEM_IO + 0xA4))
546
547// Sound status bits.
548#define SOUND_ENABLE (1 << 0x7)
549
550// DMG square control bits.
551#define SOUND_SQUARE_LEN(N) (N)
552#define SOUND_SQUARE_DUTY(N) ((N) << 0x6)
553#define SOUND_SQUARE_ENV_TIME(N) ((N) << 0x8)
554#define SOUND_SQUARE_ENV_DIR(N) ((N) << 0xB)
555#define SOUND_SQUARE_ENV_VOL(N) ((N) << 0xC)
556
557// DMG square 1 sweep control bits.
558#define SOUND_SWEEP_NUMBER(N) (N)
559#define SOUND_SWEEP_DIR(N) ((N) << 0x3)
560#define SOUND_SWEEP_TIME(N) ((N) << 0x4)
561
562// DMG frequency bits (Square/Wave).
563#define SOUND_FREQ_TIMED (1 << 0xE)
564#define SOUND_FREQ_RESET (1 << 0xF)
565
566// DMG wave ram.
567#define SOUND_WAVE_RAM_0 *((vu32*)(MEM_IO + 0x90))
568#define SOUND_WAVE_RAM_1 *((vu32*)(MEM_IO + 0x94))
569#define SOUND_WAVE_RAM_2 *((vu32*)(MEM_IO + 0x98))
570#define SOUND_WAVE_RAM_3 *((vu32*)(MEM_IO + 0x9C))
571
572// DMG wave control bits.
573#define SOUND_WAVE_LENGTH(N) (N)
574#define SOUND_WAVE_MUTE 0x0
575#define SOUND_WAVE_VOL_100 (0x1 << 0xD)
576#define SOUND_WAVE_VOL_75 (0x4 << 0xD)
577#define SOUND_WAVE_VOL_50 (0x2 << 0xD)
578#define SOUND_WAVE_VOL_25 (0x3 << 0xD)
579
580// DMG wave mode bits.
581#define SOUND_WAVE_BANK_MODE(N) ((N) << 0x5)
582#define SOUND_WAVE_BANK_SELECT(N) ((N) << 0x6)
583#define SOUND_WAVE_ENABLE (1 << 0x7)
584
585typedef u8 WaveBank[32];
586
587#define SOUND_WAVE_RAM ((WaveBank*)(MEM_IO + 0x90))
588
589typedef enum {
590 NOTE_C_2 , NOTE_C_SHARP_2 , NOTE_D_2 , NOTE_D_SHARP_2 ,
591 NOTE_E_2 , NOTE_F_2 , NOTE_F_SHARP_2 , NOTE_G_2 ,
592 NOTE_G_SHARP_2 , NOTE_A_2 , NOTE_A_SHARP_2 , NOTE_B_2 ,
593 NOTE_C_3 , NOTE_C_SHARP_3 , NOTE_D_3 , NOTE_D_SHARP_3 ,
594 NOTE_E_3 , NOTE_F_3 , NOTE_F_SHARP_3 , NOTE_G_3 ,
595 NOTE_G_SHARP_3 , NOTE_A_3 , NOTE_A_SHARP_3 , NOTE_B_3 ,
596 NOTE_C_4 , NOTE_C_SHARP_4 , NOTE_D_4 , NOTE_D_SHARP_4 ,
597 NOTE_E_4 , NOTE_F_4 , NOTE_F_SHARP_4 , NOTE_G_4 ,
598 NOTE_G_SHARP_4 , NOTE_A_4 , NOTE_A_SHARP_4 , NOTE_B_4 ,
599 NOTE_C_5 , NOTE_C_SHARP_5 , NOTE_D_5 , NOTE_D_SHARP_5 ,
600 NOTE_E_5 , NOTE_F_5 , NOTE_F_SHARP_5 , NOTE_G_5 ,
601 NOTE_G_SHARP_5 , NOTE_A_5 , NOTE_A_SHARP_5 , NOTE_B_5 ,
602 NOTE_C_6 , NOTE_C_SHARP_6 , NOTE_D_6 , NOTE_D_SHARP_6 ,
603 NOTE_E_6 , NOTE_F_6 , NOTE_F_SHARP_6 , NOTE_G_6 ,
604 NOTE_G_SHARP_6 , NOTE_A_6 , NOTE_A_SHARP_6 , NOTE_B_6 ,
605 NOTE_C_7 , NOTE_C_SHARP_7 , NOTE_D_7 , NOTE_D_SHARP_7 ,
606 NOTE_E_7 , NOTE_F_7 , NOTE_F_SHARP_7 , NOTE_G_7 ,
607 NOTE_G_SHARP_7 , NOTE_A_7 , NOTE_A_SHARP_7 , NOTE_B_7 ,
608 NOTE_C_8
609} Note;
610
611static const u32 sound_rates[] = {
612 44 , 156 , 262 , 363 , 457 , 547 , 631 , 710 , 785 , 856 , 923 , 986 ,
613 1046, 1102, 1155, 1205, 1252, 1297, 1339, 1379, 1416, 1452, 1485, 1517,
614 1547, 1575, 1601, 1626, 1650, 1672, 1693, 1713, 1732, 1750, 1766, 1782,
615 1797, 1811, 1824, 1837, 1849, 1860, 1870, 1880, 1890, 1899, 1907, 1915,
616 1922, 1929, 1936, 1942, 1948, 1954, 1959, 1964, 1969, 1973, 1977, 1981,
617 1985, 1988, 1992, 1995, 1998, 2001, 2003, 2006, 2008, 2010, 2012, 2014,
618 2016,
619};
620
621//
622// System control.
623//
624
625// Used to configure gamepak access timings.
626#define SYSTEM_WAIT *((vu16*)(MEM_IO + 0x0204))
627
628// This register defaults to 0, but manufacture cartridges use the values
629// provided below.
630#define SYSTEM_WAIT_DEFAULT 0
631#define SYSTEM_WAIT_CARTRIDGE 0x4317
632
633//
634// Misc.
635//
636
637// Custom VSync option. This will waste a lot of battery power, since the
638// machine is not clocked down. Prefer using `bios_vblank_wait()` if interrupts
639// are enabled.
640static inline void
641wait_vsync(void) {
642 while(DISP_VCOUNT >= 160);
643 while(DISP_VCOUNT < 160);
644}
645
646// General utility macros.
647#define MIN(A, B) ((A) <= (B) ? (A) : (B))
648#define MAX(A, B) ((A) >= (B) ? (A) : (B))
649#define CLAMP(X, MIN, MAX) ((X) <= (MIN) ? (MIN) : (X) > (MAX) ? (MAX): (X))
650#define LEN(ARR) (sizeof(ARR) / sizeof((ARR)[0]))
651
652// Fixed-point arithmetic for (i.P) numbers.
653#define FP_MUL(A,B,P) (((A) * (B)) >> (P))
654#define FP_DIV(A,B,P) (((A) << (P)) / (B))
655#define FP_LERP(Y0,Y1,X,P) ((Y0) + FP_MUL((X), ((Y1) - (Y0)), P))
656
657//
658// Memory section macros for devkitARM.
659//
660
661#define IWRAM_DATA __attribute__((section(".iwram")))
662#define IWRAM_CODE __attribute__((section(".iwram"), long_call, target("arm")))
663#define EWRAM_DATA __attribute__((section(".ewram")))
664#define EWRAM_CODE __attribute__((section(".ewram"), long_call))
665#define EWRAM_BSS __attribute__((section(".sbss")))
666
667#endif // GBA_H