diff options
Diffstat (limited to 'include/gba')
-rw-r--r-- | include/gba/defines.h | 62 | ||||
-rw-r--r-- | include/gba/flash_internal.h | 73 | ||||
-rw-r--r-- | include/gba/gba.h | 11 | ||||
-rw-r--r-- | include/gba/io_reg.h | 727 | ||||
-rw-r--r-- | include/gba/m4a_internal.h | 463 | ||||
-rw-r--r-- | include/gba/macro.h | 137 | ||||
-rw-r--r-- | include/gba/multiboot.h | 55 | ||||
-rw-r--r-- | include/gba/syscall.h | 48 | ||||
-rw-r--r-- | include/gba/types.h | 129 |
9 files changed, 1705 insertions, 0 deletions
diff --git a/include/gba/defines.h b/include/gba/defines.h new file mode 100644 index 0000000..7fd429d --- /dev/null +++ b/include/gba/defines.h @@ -0,0 +1,62 @@ +#ifndef GUARD_GBA_DEFINES +#define GUARD_GBA_DEFINES + +#include <stddef.h> + +#define TRUE 1 +#define FALSE 0 + +#define IWRAM_DATA __attribute__((section("iwram_data"))) +#define EWRAM_DATA __attribute__((section("ewram_data"))) + +#define ALIGNED(n) __attribute__((aligned(n))) + +#define SOUND_INFO_PTR (*(struct SoundInfo **)0x3007FF0) +#define INTR_CHECK (*(u16 *)0x3007FF8) +#define INTR_VECTOR (*(void **)0x3007FFC) + +#define PLTT 0x5000000 +#define PLTT_SIZE 0x400 + +#define BG_PLTT PLTT +#define BG_PLTT_SIZE 0x200 + +#define OBJ_PLTT (PLTT + 0x200) +#define OBJ_PLTT_SIZE 0x200 + +#define VRAM 0x6000000 +#define VRAM_SIZE 0x18000 + +#define BG_VRAM VRAM +#define BG_VRAM_SIZE 0x10000 +#define BG_CHAR_ADDR(n) (void *)(BG_VRAM + (0x4000 * (n))) +#define BG_SCREEN_ADDR(n) (void *)(BG_VRAM + (0x800 * (n))) +#define BG_TILE_ADDR(n) (void *)(BG_VRAM + (0x80 * (n))) + +// text-mode BG +#define OBJ_VRAM0 (void *)(VRAM + 0x10000) +#define OBJ_VRAM0_SIZE 0x8000 + +// bitmap-mode BG +#define OBJ_VRAM1 (void *)(VRAM + 0x14000) +#define OBJ_VRAM1_SIZE 0x4000 + +#define OAM 0x7000000 +#define OAM_SIZE 0x400 + +#define DISPLAY_WIDTH 240 +#define DISPLAY_HEIGHT 160 + +#define TILE_SIZE_4BPP 32 +#define TILE_SIZE_8BPP 64 + +#define TOTAL_OBJ_TILE_COUNT 1024 + +#define RGB(r, g, b) ((r) | ((g) << 5) | ((b) << 10)) + +#define RGB_BLACK RGB(0, 0, 0) +#define RGB_WHITE RGB(31, 31, 31) + +#define WIN_RANGE(a, b) (((a) << 8) | (b)) + +#endif // GUARD_GBA_DEFINES diff --git a/include/gba/flash_internal.h b/include/gba/flash_internal.h new file mode 100644 index 0000000..48d8843 --- /dev/null +++ b/include/gba/flash_internal.h @@ -0,0 +1,73 @@ +#ifndef GUARD_GBA_FLASH_INTERNAL_H +#define GUARD_GBA_FLASH_INTERNAL_H + +#define FLASH_BASE ((u8 *)0xE000000) + +#define FLASH_WRITE(addr, data) ((*(vu8 *)(FLASH_BASE + (addr))) = (data)) + +#define FLASH_ROM_SIZE_1M 131072 // 1 megabit ROM + +#define SECTORS_PER_BANK 16 + +struct FlashSector +{ + u32 size; + u8 shift; + u16 count; + u16 top; +}; + +struct FlashType { + u32 romSize; + struct FlashSector sector; + u16 wait[2]; // game pak bus read/write wait + + // TODO: add support for anonymous unions/structs if possible + union { + struct { + u8 makerId; + u8 deviceId; + } separate; + u16 joined; + } ids; +}; + +struct FlashSetupInfo +{ + u16 (*programFlashSector)(u16, u8 *); + u16 (*eraseFlashChip)(void); + u16 (*eraseFlashSector)(u16); + u16 (*waitForFlashWrite)(u8, u8 *, u8); + const u16 *maxTime; + struct FlashType type; +}; + +extern u16 gFlashNumRemainingBytes; + +extern u16 (*ProgramFlashSector)(u16, u8 *); +extern u16 (*EraseFlashChip)(void); +extern u16 (*EraseFlashSector)(u16); +extern u16 (*WaitForFlashWrite)(u8, u8 *, u8); +extern const u16 *gFlashMaxTime; +extern const struct FlashType *gFlash; + +extern u8 (*PollFlashStatus)(u8 *); +extern u8 gFlashTimeoutFlag; + +extern const struct FlashSetupInfo MX29L010; +extern const struct FlashSetupInfo LE26FV10N1TS; +extern const struct FlashSetupInfo DefaultFlash; + +void SwitchFlashBank(u8 bankNum); +u16 ReadFlashId(void); +void StartFlashTimer(u8 phase); +void SetReadFlash1(u16 *dest); +void StopFlashTimer(void); + +u16 WaitForFlashWrite_Common(u8 phase, u8 *addr, u8 lastData); + +u16 EraseFlashChip_MX(void); +u16 EraseFlashSector_MX(u16 sectorNum); +u16 ProgramFlashSector_MX(u16 sectorNum, u8 *src); + +#endif // GUARD_GBA_FLASH_INTERNAL_H diff --git a/include/gba/gba.h b/include/gba/gba.h new file mode 100644 index 0000000..42ae3cd --- /dev/null +++ b/include/gba/gba.h @@ -0,0 +1,11 @@ +#ifndef GUARD_GBA_GBA_H +#define GUARD_GBA_GBA_H + +#include "gba/defines.h" +#include "gba/io_reg.h" +#include "gba/types.h" +#include "gba/multiboot.h" +#include "gba/syscall.h" +#include "gba/macro.h" + +#endif // GUARD_GBA_GBA_H diff --git a/include/gba/io_reg.h b/include/gba/io_reg.h new file mode 100644 index 0000000..6dbe5e8 --- /dev/null +++ b/include/gba/io_reg.h @@ -0,0 +1,727 @@ +#ifndef GUARD_GBA_IO_REG_H +#define GUARD_GBA_IO_REG_H + +#define REG_BASE 0x4000000 // I/O register base address + +// I/O register offsets + +#define REG_OFFSET_DISPCNT 0x0 +#define REG_OFFSET_DISPSTAT 0x4 +#define REG_OFFSET_VCOUNT 0x6 +#define REG_OFFSET_BG0CNT 0x8 +#define REG_OFFSET_BG1CNT 0xa +#define REG_OFFSET_BG2CNT 0xc +#define REG_OFFSET_BG3CNT 0xe +#define REG_OFFSET_BG0HOFS 0x10 +#define REG_OFFSET_BG0VOFS 0x12 +#define REG_OFFSET_BG1HOFS 0x14 +#define REG_OFFSET_BG1VOFS 0x16 +#define REG_OFFSET_BG2HOFS 0x18 +#define REG_OFFSET_BG2VOFS 0x1a +#define REG_OFFSET_BG3HOFS 0x1c +#define REG_OFFSET_BG3VOFS 0x1e +#define REG_OFFSET_BG2PA 0x20 +#define REG_OFFSET_BG2PB 0x22 +#define REG_OFFSET_BG2PC 0x24 +#define REG_OFFSET_BG2PD 0x26 +#define REG_OFFSET_BG2X 0x28 +#define REG_OFFSET_BG2X_L 0x28 +#define REG_OFFSET_BG2X_H 0x2a +#define REG_OFFSET_BG2Y 0x2c +#define REG_OFFSET_BG2Y_L 0x2c +#define REG_OFFSET_BG2Y_H 0x2e +#define REG_OFFSET_BG3PA 0x30 +#define REG_OFFSET_BG3PB 0x32 +#define REG_OFFSET_BG3PC 0x34 +#define REG_OFFSET_BG3PD 0x36 +#define REG_OFFSET_BG3X 0x38 +#define REG_OFFSET_BG3X_L 0x38 +#define REG_OFFSET_BG3X_H 0x3a +#define REG_OFFSET_BG3Y 0x3c +#define REG_OFFSET_BG3Y_L 0x3c +#define REG_OFFSET_BG3Y_H 0x3e +#define REG_OFFSET_WIN0H 0x40 +#define REG_OFFSET_WIN1H 0x42 +#define REG_OFFSET_WIN0V 0x44 +#define REG_OFFSET_WIN1V 0x46 +#define REG_OFFSET_WININ 0x48 +#define REG_OFFSET_WINOUT 0x4a +#define REG_OFFSET_MOSAIC 0x4c +#define REG_OFFSET_BLDCNT 0x50 +#define REG_OFFSET_BLDALPHA 0x52 +#define REG_OFFSET_BLDY 0x54 + +#define REG_OFFSET_SOUND1CNT_L 0x60 +#define REG_OFFSET_NR10 0x60 +#define REG_OFFSET_SOUND1CNT_H 0x62 +#define REG_OFFSET_NR11 0x62 +#define REG_OFFSET_NR12 0x63 +#define REG_OFFSET_SOUND1CNT_X 0x64 +#define REG_OFFSET_NR13 0x64 +#define REG_OFFSET_NR14 0x65 +#define REG_OFFSET_SOUND2CNT_L 0x68 +#define REG_OFFSET_NR21 0x68 +#define REG_OFFSET_NR22 0x69 +#define REG_OFFSET_SOUND2CNT_H 0x6c +#define REG_OFFSET_NR23 0x6c +#define REG_OFFSET_NR24 0x6d +#define REG_OFFSET_SOUND3CNT_L 0x70 +#define REG_OFFSET_NR30 0x70 +#define REG_OFFSET_SOUND3CNT_H 0x72 +#define REG_OFFSET_NR31 0x72 +#define REG_OFFSET_NR32 0x73 +#define REG_OFFSET_SOUND3CNT_X 0x74 +#define REG_OFFSET_NR33 0x74 +#define REG_OFFSET_NR34 0x75 +#define REG_OFFSET_SOUND4CNT_L 0x78 +#define REG_OFFSET_NR41 0x78 +#define REG_OFFSET_NR42 0x79 +#define REG_OFFSET_SOUND4CNT_H 0x7c +#define REG_OFFSET_NR43 0x7c +#define REG_OFFSET_NR44 0x7d +#define REG_OFFSET_SOUNDCNT_L 0x80 +#define REG_OFFSET_NR50 0x80 +#define REG_OFFSET_NR51 0x81 +#define REG_OFFSET_SOUNDCNT_H 0x82 +#define REG_OFFSET_SOUNDCNT_X 0x84 +#define REG_OFFSET_NR52 0x84 +#define REG_OFFSET_SOUNDBIAS 0x88 +#define REG_OFFSET_SOUNDBIAS_L 0x88 +#define REG_OFFSET_SOUNDBIAS_H 0x89 +#define REG_OFFSET_WAVE_RAM0 0x90 +#define REG_OFFSET_WAVE_RAM1 0x94 +#define REG_OFFSET_WAVE_RAM2 0x98 +#define REG_OFFSET_WAVE_RAM3 0x9c +#define REG_OFFSET_FIFO_A 0xa0 +#define REG_OFFSET_FIFO_B 0xa4 + +#define REG_OFFSET_DMA0 0xb0 +#define REG_OFFSET_DMA0SAD 0xb0 +#define REG_OFFSET_DMA0SAD_L 0xb0 +#define REG_OFFSET_DMA0SAD_H 0xb2 +#define REG_OFFSET_DMA0DAD 0xb4 +#define REG_OFFSET_DMA0DAD_L 0xb4 +#define REG_OFFSET_DMA0DAD_H 0xb6 +#define REG_OFFSET_DMA0CNT 0xb8 +#define REG_OFFSET_DMA0CNT_L 0xb8 +#define REG_OFFSET_DMA0CNT_H 0xba +#define REG_OFFSET_DMA1 0xbc +#define REG_OFFSET_DMA1SAD 0xbc +#define REG_OFFSET_DMA1SAD_L 0xbc +#define REG_OFFSET_DMA1SAD_H 0xbe +#define REG_OFFSET_DMA1DAD 0xc0 +#define REG_OFFSET_DMA1DAD_L 0xc0 +#define REG_OFFSET_DMA1DAD_H 0xc2 +#define REG_OFFSET_DMA1CNT 0xc4 +#define REG_OFFSET_DMA1CNT_L 0xc4 +#define REG_OFFSET_DMA1CNT_H 0xc6 +#define REG_OFFSET_DMA2 0xc8 +#define REG_OFFSET_DMA2SAD 0xc8 +#define REG_OFFSET_DMA2SAD_L 0xc8 +#define REG_OFFSET_DMA2SAD_H 0xca +#define REG_OFFSET_DMA2DAD 0xcc +#define REG_OFFSET_DMA2DAD_L 0xcc +#define REG_OFFSET_DMA2DAD_H 0xce +#define REG_OFFSET_DMA2CNT 0xd0 +#define REG_OFFSET_DMA2CNT_L 0xd0 +#define REG_OFFSET_DMA2CNT_H 0xd2 +#define REG_OFFSET_DMA3 0xd4 +#define REG_OFFSET_DMA3SAD 0xd4 +#define REG_OFFSET_DMA3SAD_L 0xd4 +#define REG_OFFSET_DMA3SAD_H 0xd6 +#define REG_OFFSET_DMA3DAD 0xd8 +#define REG_OFFSET_DMA3DAD_L 0xd8 +#define REG_OFFSET_DMA3DAD_H 0xda +#define REG_OFFSET_DMA3CNT 0xdc +#define REG_OFFSET_DMA3CNT_L 0xdc +#define REG_OFFSET_DMA3CNT_H 0xde + +#define REG_OFFSET_TMCNT 0x100 +#define REG_OFFSET_TM0CNT 0x100 +#define REG_OFFSET_TM0CNT_L 0x100 +#define REG_OFFSET_TM0CNT_H 0x102 +#define REG_OFFSET_TM1CNT 0x104 +#define REG_OFFSET_TM1CNT_L 0x104 +#define REG_OFFSET_TM1CNT_H 0x106 +#define REG_OFFSET_TM2CNT 0x108 +#define REG_OFFSET_TM2CNT_L 0x108 +#define REG_OFFSET_TM2CNT_H 0x10a +#define REG_OFFSET_TM3CNT 0x10c +#define REG_OFFSET_TM3CNT_L 0x10c +#define REG_OFFSET_TM3CNT_H 0x10e + +#define REG_OFFSET_SIOCNT 0x128 +#define REG_OFFSET_SIODATA8 0x12a +#define REG_OFFSET_SIODATA32 0x120 +#define REG_OFFSET_SIOMLT_SEND 0x12a +#define REG_OFFSET_SIOMLT_RECV 0x120 +#define REG_OFFSET_SIOMULTI0 0x120 +#define REG_OFFSET_SIOMULTI1 0x122 +#define REG_OFFSET_SIOMULTI2 0x124 +#define REG_OFFSET_SIOMULTI3 0x126 + +#define REG_OFFSET_KEYINPUT 0x130 +#define REG_OFFSET_KEYCNT 0x132 + +#define REG_OFFSET_RCNT 0x134 + +#define REG_OFFSET_JOYCNT 0x140 +#define REG_OFFSET_JOYSTAT 0x158 +#define REG_OFFSET_JOY_RECV 0x150 +#define REG_OFFSET_JOY_RECV_L 0x150 +#define REG_OFFSET_JOY_RECV_H 0x152 +#define REG_OFFSET_JOY_TRANS 0x154 +#define REG_OFFSET_JOY_TRANS_L 0x154 +#define REG_OFFSET_JOY_TRANS_H 0x156 + +#define REG_OFFSET_IME 0x208 +#define REG_OFFSET_IE 0x200 +#define REG_OFFSET_IF 0x202 + +#define REG_OFFSET_WAITCNT 0x204 + +// I/O register addresses + +#define REG_ADDR_DISPCNT (REG_BASE + REG_OFFSET_DISPCNT) +#define REG_ADDR_DISPSTAT (REG_BASE + REG_OFFSET_DISPSTAT) +#define REG_ADDR_VCOUNT (REG_BASE + REG_OFFSET_VCOUNT) +#define REG_ADDR_BG0CNT (REG_BASE + REG_OFFSET_BG0CNT) +#define REG_ADDR_BG1CNT (REG_BASE + REG_OFFSET_BG1CNT) +#define REG_ADDR_BG2CNT (REG_BASE + REG_OFFSET_BG2CNT) +#define REG_ADDR_BG3CNT (REG_BASE + REG_OFFSET_BG3CNT) +#define REG_ADDR_BG0HOFS (REG_BASE + REG_OFFSET_BG0HOFS) +#define REG_ADDR_BG0VOFS (REG_BASE + REG_OFFSET_BG0VOFS) +#define REG_ADDR_BG1HOFS (REG_BASE + REG_OFFSET_BG1HOFS) +#define REG_ADDR_BG1VOFS (REG_BASE + REG_OFFSET_BG1VOFS) +#define REG_ADDR_BG2HOFS (REG_BASE + REG_OFFSET_BG2HOFS) +#define REG_ADDR_BG2VOFS (REG_BASE + REG_OFFSET_BG2VOFS) +#define REG_ADDR_BG3HOFS (REG_BASE + REG_OFFSET_BG3HOFS) +#define REG_ADDR_BG3VOFS (REG_BASE + REG_OFFSET_BG3VOFS) +#define REG_ADDR_BG2PA (REG_BASE + REG_OFFSET_BG2PA) +#define REG_ADDR_BG2PB (REG_BASE + REG_OFFSET_BG2PB) +#define REG_ADDR_BG2PC (REG_BASE + REG_OFFSET_BG2PC) +#define REG_ADDR_BG2PD (REG_BASE + REG_OFFSET_BG2PD) +#define REG_ADDR_BG2X (REG_BASE + REG_OFFSET_BG2X) +#define REG_ADDR_BG2X_L (REG_BASE + REG_OFFSET_BG2X_L) +#define REG_ADDR_BG2X_H (REG_BASE + REG_OFFSET_BG2X_H) +#define REG_ADDR_BG2Y (REG_BASE + REG_OFFSET_BG2Y) +#define REG_ADDR_BG2Y_L (REG_BASE + REG_OFFSET_BG2Y_L) +#define REG_ADDR_BG2Y_H (REG_BASE + REG_OFFSET_BG2Y_H) +#define REG_ADDR_BG3PA (REG_BASE + REG_OFFSET_BG3PA) +#define REG_ADDR_BG3PB (REG_BASE + REG_OFFSET_BG3PB) +#define REG_ADDR_BG3PC (REG_BASE + REG_OFFSET_BG3PC) +#define REG_ADDR_BG3PD (REG_BASE + REG_OFFSET_BG3PD) +#define REG_ADDR_BG3X (REG_BASE + REG_OFFSET_BG3X) +#define REG_ADDR_BG3X_L (REG_BASE + REG_OFFSET_BG3X_L) +#define REG_ADDR_BG3X_H (REG_BASE + REG_OFFSET_BG3X_H) +#define REG_ADDR_BG3Y (REG_BASE + REG_OFFSET_BG3Y) +#define REG_ADDR_BG3Y_L (REG_BASE + REG_OFFSET_BG3Y_L) +#define REG_ADDR_BG3Y_H (REG_BASE + REG_OFFSET_BG3Y_H) +#define REG_ADDR_WIN0H (REG_BASE + REG_OFFSET_WIN0H) +#define REG_ADDR_WIN1H (REG_BASE + REG_OFFSET_WIN1H) +#define REG_ADDR_WIN0V (REG_BASE + REG_OFFSET_WIN0V) +#define REG_ADDR_WIN1V (REG_BASE + REG_OFFSET_WIN1V) +#define REG_ADDR_WININ (REG_BASE + REG_OFFSET_WININ) +#define REG_ADDR_WINOUT (REG_BASE + REG_OFFSET_WINOUT) +#define REG_ADDR_MOSAIC (REG_BASE + REG_OFFSET_MOSAIC) +#define REG_ADDR_BLDCNT (REG_BASE + REG_OFFSET_BLDCNT) +#define REG_ADDR_BLDALPHA (REG_BASE + REG_OFFSET_BLDALPHA) +#define REG_ADDR_BLDY (REG_BASE + REG_OFFSET_BLDY) + +#define REG_ADDR_SOUND1CNT_L (REG_BASE + REG_OFFSET_SOUND1CNT_L) +#define REG_ADDR_NR10 (REG_BASE + REG_OFFSET_NR10) +#define REG_ADDR_SOUND1CNT_H (REG_BASE + REG_OFFSET_SOUND1CNT_H) +#define REG_ADDR_NR11 (REG_BASE + REG_OFFSET_NR11) +#define REG_ADDR_NR12 (REG_BASE + REG_OFFSET_NR12) +#define REG_ADDR_SOUND1CNT_X (REG_BASE + REG_OFFSET_SOUND1CNT_X) +#define REG_ADDR_NR13 (REG_BASE + REG_OFFSET_NR13) +#define REG_ADDR_NR14 (REG_BASE + REG_OFFSET_NR14) +#define REG_ADDR_SOUND2CNT_L (REG_BASE + REG_OFFSET_SOUND2CNT_L) +#define REG_ADDR_NR21 (REG_BASE + REG_OFFSET_NR21) +#define REG_ADDR_NR22 (REG_BASE + REG_OFFSET_NR22) +#define REG_ADDR_SOUND2CNT_H (REG_BASE + REG_OFFSET_SOUND2CNT_H) +#define REG_ADDR_NR23 (REG_BASE + REG_OFFSET_NR23) +#define REG_ADDR_NR24 (REG_BASE + REG_OFFSET_NR24) +#define REG_ADDR_SOUND3CNT_L (REG_BASE + REG_OFFSET_SOUND3CNT_L) +#define REG_ADDR_NR30 (REG_BASE + REG_OFFSET_NR30) +#define REG_ADDR_SOUND3CNT_H (REG_BASE + REG_OFFSET_SOUND3CNT_H) +#define REG_ADDR_NR31 (REG_BASE + REG_OFFSET_NR31) +#define REG_ADDR_NR32 (REG_BASE + REG_OFFSET_NR32) +#define REG_ADDR_SOUND3CNT_X (REG_BASE + REG_OFFSET_SOUND3CNT_X) +#define REG_ADDR_NR33 (REG_BASE + REG_OFFSET_NR33) +#define REG_ADDR_NR34 (REG_BASE + REG_OFFSET_NR34) +#define REG_ADDR_SOUND4CNT_L (REG_BASE + REG_OFFSET_SOUND4CNT_L) +#define REG_ADDR_NR41 (REG_BASE + REG_OFFSET_NR41) +#define REG_ADDR_NR42 (REG_BASE + REG_OFFSET_NR42) +#define REG_ADDR_SOUND4CNT_H (REG_BASE + REG_OFFSET_SOUND4CNT_H) +#define REG_ADDR_NR43 (REG_BASE + REG_OFFSET_NR43) +#define REG_ADDR_NR44 (REG_BASE + REG_OFFSET_NR44) +#define REG_ADDR_SOUNDCNT_L (REG_BASE + REG_OFFSET_SOUNDCNT_L) +#define REG_ADDR_NR50 (REG_BASE + REG_OFFSET_NR50) +#define REG_ADDR_NR51 (REG_BASE + REG_OFFSET_NR51) +#define REG_ADDR_SOUNDCNT_H (REG_BASE + REG_OFFSET_SOUNDCNT_H) +#define REG_ADDR_SOUNDCNT_X (REG_BASE + REG_OFFSET_SOUNDCNT_X) +#define REG_ADDR_NR52 (REG_BASE + REG_OFFSET_NR52) +#define REG_ADDR_SOUNDBIAS (REG_BASE + REG_OFFSET_SOUNDBIAS) +#define REG_ADDR_SOUNDBIAS_L (REG_BASE + REG_OFFSET_SOUNDBIAS_L) +#define REG_ADDR_SOUNDBIAS_H (REG_BASE + REG_OFFSET_SOUNDBIAS_H) +#define REG_ADDR_WAVE_RAM0 (REG_BASE + REG_OFFSET_WAVE_RAM0) +#define REG_ADDR_WAVE_RAM1 (REG_BASE + REG_OFFSET_WAVE_RAM1) +#define REG_ADDR_WAVE_RAM2 (REG_BASE + REG_OFFSET_WAVE_RAM2) +#define REG_ADDR_WAVE_RAM3 (REG_BASE + REG_OFFSET_WAVE_RAM3) +#define REG_ADDR_FIFO_A (REG_BASE + REG_OFFSET_FIFO_A) +#define REG_ADDR_FIFO_B (REG_BASE + REG_OFFSET_FIFO_B) + +#define REG_ADDR_DMA0 (REG_BASE + REG_OFFSET_DMA0) +#define REG_ADDR_DMA0SAD (REG_BASE + REG_OFFSET_DMA0SAD) +#define REG_ADDR_DMA0DAD (REG_BASE + REG_OFFSET_DMA0DAD) +#define REG_ADDR_DMA0CNT (REG_BASE + REG_OFFSET_DMA0CNT) +#define REG_ADDR_DMA0CNT_L (REG_BASE + REG_OFFSET_DMA0CNT_L) +#define REG_ADDR_DMA0CNT_H (REG_BASE + REG_OFFSET_DMA0CNT_H) +#define REG_ADDR_DMA1 (REG_BASE + REG_OFFSET_DMA1) +#define REG_ADDR_DMA1SAD (REG_BASE + REG_OFFSET_DMA1SAD) +#define REG_ADDR_DMA1DAD (REG_BASE + REG_OFFSET_DMA1DAD) +#define REG_ADDR_DMA1CNT (REG_BASE + REG_OFFSET_DMA1CNT) +#define REG_ADDR_DMA1CNT_L (REG_BASE + REG_OFFSET_DMA1CNT_L) +#define REG_ADDR_DMA1CNT_H (REG_BASE + REG_OFFSET_DMA1CNT_H) +#define REG_ADDR_DMA2 (REG_BASE + REG_OFFSET_DMA2) +#define REG_ADDR_DMA2SAD (REG_BASE + REG_OFFSET_DMA2SAD) +#define REG_ADDR_DMA2DAD (REG_BASE + REG_OFFSET_DMA2DAD) +#define REG_ADDR_DMA2CNT (REG_BASE + REG_OFFSET_DMA2CNT) +#define REG_ADDR_DMA2CNT_L (REG_BASE + REG_OFFSET_DMA2CNT_L) +#define REG_ADDR_DMA2CNT_H (REG_BASE + REG_OFFSET_DMA2CNT_H) +#define REG_ADDR_DMA3 (REG_BASE + REG_OFFSET_DMA3) +#define REG_ADDR_DMA3SAD (REG_BASE + REG_OFFSET_DMA3SAD) +#define REG_ADDR_DMA3DAD (REG_BASE + REG_OFFSET_DMA3DAD) +#define REG_ADDR_DMA3CNT (REG_BASE + REG_OFFSET_DMA3CNT) +#define REG_ADDR_DMA3CNT_L (REG_BASE + REG_OFFSET_DMA3CNT_L) +#define REG_ADDR_DMA3CNT_H (REG_BASE + REG_OFFSET_DMA3CNT_H) + +#define REG_ADDR_TMCNT (REG_BASE + REG_OFFSET_TMCNT) +#define REG_ADDR_TM0CNT (REG_BASE + REG_OFFSET_TM0CNT) +#define REG_ADDR_TM0CNT_L (REG_BASE + REG_OFFSET_TM0CNT_L) +#define REG_ADDR_TM0CNT_H (REG_BASE + REG_OFFSET_TM0CNT_H) +#define REG_ADDR_TM1CNT (REG_BASE + REG_OFFSET_TM1CNT) +#define REG_ADDR_TM1CNT_L (REG_BASE + REG_OFFSET_TM1CNT_L) +#define REG_ADDR_TM1CNT_H (REG_BASE + REG_OFFSET_TM1CNT_H) +#define REG_ADDR_TM2CNT (REG_BASE + REG_OFFSET_TM2CNT) +#define REG_ADDR_TM2CNT_L (REG_BASE + REG_OFFSET_TM2CNT_L) +#define REG_ADDR_TM2CNT_H (REG_BASE + REG_OFFSET_TM2CNT_H) +#define REG_ADDR_TM3CNT (REG_BASE + REG_OFFSET_TM3CNT) +#define REG_ADDR_TM3CNT_L (REG_BASE + REG_OFFSET_TM3CNT_L) +#define REG_ADDR_TM3CNT_H (REG_BASE + REG_OFFSET_TM3CNT_H) + +#define REG_ADDR_SIOCNT (REG_BASE + REG_OFFSET_SIOCNT) +#define REG_ADDR_SIODATA8 (REG_BASE + REG_OFFSET_SIODATA8) +#define REG_ADDR_SIODATA32 (REG_BASE + REG_OFFSET_SIODATA32) +#define REG_ADDR_SIOMLT_SEND (REG_BASE + REG_OFFSET_SIOMLT_SEND) +#define REG_ADDR_SIOMLT_RECV (REG_BASE + REG_OFFSET_SIOMLT_RECV) +#define REG_ADDR_SIOMULTI0 (REG_BASE + REG_OFFSET_SIOMULTI0) +#define REG_ADDR_SIOMULTI1 (REG_BASE + REG_OFFSET_SIOMULTI1) +#define REG_ADDR_SIOMULTI2 (REG_BASE + REG_OFFSET_SIOMULTI2) +#define REG_ADDR_SIOMULTI3 (REG_BASE + REG_OFFSET_SIOMULTI3) + +#define REG_ADDR_KEYINPUT (REG_BASE + REG_OFFSET_KEYINPUT) +#define REG_ADDR_KEYCNT (REG_BASE + REG_OFFSET_KEYCNT) + +#define REG_ADDR_RCNT (REG_BASE + REG_OFFSET_RCNT) + +#define REG_ADDR_JOYCNT (REG_BASE + REG_OFFSET_JOYCNT) +#define REG_ADDR_JOYSTAT (REG_BASE + REG_OFFSET_JOYSTAT) +#define REG_ADDR_JOY_RECV (REG_BASE + REG_OFFSET_JOY_RECV) +#define REG_ADDR_JOY_RECV_L (REG_BASE + REG_OFFSET_JOY_RECV_L) +#define REG_ADDR_JOY_RECV_H (REG_BASE + REG_OFFSET_JOY_RECV_H) +#define REG_ADDR_JOY_TRANS (REG_BASE + REG_OFFSET_JOY_TRANS) +#define REG_ADDR_JOY_TRANS_L (REG_BASE + REG_OFFSET_JOY_TRANS_L) +#define REG_ADDR_JOY_TRANS_H (REG_BASE + REG_OFFSET_JOY_TRANS_H) + +#define REG_ADDR_IME (REG_BASE + REG_OFFSET_IME) +#define REG_ADDR_IE (REG_BASE + REG_OFFSET_IE) +#define REG_ADDR_IF (REG_BASE + REG_OFFSET_IF) + +#define REG_ADDR_WAITCNT (REG_BASE + REG_OFFSET_WAITCNT) + +// I/O registers + +#define REG_DISPCNT (*(vu16 *)REG_ADDR_DISPCNT) +#define REG_DISPSTAT (*(vu16 *)REG_ADDR_DISPSTAT) +#define REG_VCOUNT (*(vu16 *)REG_ADDR_VCOUNT) +#define REG_BG0CNT (*(vu16 *)REG_ADDR_BG0CNT) +#define REG_BG1CNT (*(vu16 *)REG_ADDR_BG1CNT) +#define REG_BG2CNT (*(vu16 *)REG_ADDR_BG2CNT) +#define REG_BG3CNT (*(vu16 *)REG_ADDR_BG3CNT) +#define REG_BG0HOFS (*(vu16 *)REG_ADDR_BG0HOFS) +#define REG_BG0VOFS (*(vu16 *)REG_ADDR_BG0VOFS) +#define REG_BG1HOFS (*(vu16 *)REG_ADDR_BG1HOFS) +#define REG_BG1VOFS (*(vu16 *)REG_ADDR_BG1VOFS) +#define REG_BG2HOFS (*(vu16 *)REG_ADDR_BG2HOFS) +#define REG_BG2VOFS (*(vu16 *)REG_ADDR_BG2VOFS) +#define REG_BG3HOFS (*(vu16 *)REG_ADDR_BG3HOFS) +#define REG_BG3VOFS (*(vu16 *)REG_ADDR_BG3VOFS) +#define REG_BG2PA (*(vu16 *)REG_ADDR_BG2PA) +#define REG_BG2PB (*(vu16 *)REG_ADDR_BG2PB) +#define REG_BG2PC (*(vu16 *)REG_ADDR_BG2PC) +#define REG_BG2PD (*(vu16 *)REG_ADDR_BG2PD) +#define REG_BG2X (*(vu32 *)REG_ADDR_BG2X) +#define REG_BG2X_L (*(vu16 *)REG_ADDR_BG2X_L) +#define REG_BG2X_H (*(vu16 *)REG_ADDR_BG2X_H) +#define REG_BG2Y (*(vu32 *)REG_ADDR_BG2Y) +#define REG_BG2Y_L (*(vu16 *)REG_ADDR_BG2Y_L) +#define REG_BG2Y_H (*(vu16 *)REG_ADDR_BG2Y_H) +#define REG_BG3PA (*(vu16 *)REG_ADDR_BG3PA) +#define REG_BG3PB (*(vu16 *)REG_ADDR_BG3PB) +#define REG_BG3PC (*(vu16 *)REG_ADDR_BG3PC) +#define REG_BG3PD (*(vu16 *)REG_ADDR_BG3PD) +#define REG_BG3X (*(vu32 *)REG_ADDR_BG3X) +#define REG_BG3X_L (*(vu16 *)REG_ADDR_BG3X_L) +#define REG_BG3X_H (*(vu16 *)REG_ADDR_BG3X_H) +#define REG_BG3Y (*(vu32 *)REG_ADDR_BG3Y) +#define REG_BG3Y_L (*(vu16 *)REG_ADDR_BG3Y_L) +#define REG_BG3Y_H (*(vu16 *)REG_ADDR_BG3Y_H) +#define REG_WIN0H (*(vu16 *)REG_ADDR_WIN0H) +#define REG_WIN1H (*(vu16 *)REG_ADDR_WIN1H) +#define REG_WIN0V (*(vu16 *)REG_ADDR_WIN0V) +#define REG_WIN1V (*(vu16 *)REG_ADDR_WIN1V) +#define REG_WININ (*(vu16 *)REG_ADDR_WININ) +#define REG_WINOUT (*(vu16 *)REG_ADDR_WINOUT) +#define REG_MOSAIC (*(vu16 *)REG_ADDR_MOSAIC) +#define REG_BLDCNT (*(vu16 *)REG_ADDR_BLDCNT) +#define REG_BLDALPHA (*(vu16 *)REG_ADDR_BLDALPHA) +#define REG_BLDY (*(vu16 *)REG_ADDR_BLDY) + +#define REG_SOUND1CNT_L (*(vu16 *)REG_ADDR_SOUND1CNT_L) +#define REG_NR10 (*(vu8 *)REG_ADDR_NR10) +#define REG_SOUND1CNT_H (*(vu16 *)REG_ADDR_SOUND1CNT_H) +#define REG_NR11 (*(vu8 *)REG_ADDR_NR11) +#define REG_NR12 (*(vu8 *)REG_ADDR_NR12) +#define REG_SOUND1CNT_X (*(vu16 *)REG_ADDR_SOUND1CNT_X) +#define REG_NR13 (*(vu8 *)REG_ADDR_NR13) +#define REG_NR14 (*(vu8 *)REG_ADDR_NR14) +#define REG_SOUND2CNT_L (*(vu16 *)REG_ADDR_SOUND2CNT_L) +#define REG_NR21 (*(vu8 *)REG_ADDR_NR21) +#define REG_NR22 (*(vu8 *)REG_ADDR_NR22) +#define REG_SOUND2CNT_H (*(vu16 *)REG_ADDR_SOUND2CNT_H) +#define REG_NR23 (*(vu8 *)REG_ADDR_NR23) +#define REG_NR24 (*(vu8 *)REG_ADDR_NR24) +#define REG_SOUND3CNT_L (*(vu16 *)REG_ADDR_SOUND3CNT_L) +#define REG_NR30 (*(vu8 *)REG_ADDR_NR30) +#define REG_SOUND3CNT_H (*(vu16 *)REG_ADDR_SOUND3CNT_H) +#define REG_NR31 (*(vu8 *)REG_ADDR_NR31) +#define REG_NR32 (*(vu8 *)REG_ADDR_NR32) +#define REG_SOUND3CNT_X (*(vu16 *)REG_ADDR_SOUND3CNT_X) +#define REG_NR33 (*(vu8 *)REG_ADDR_NR33) +#define REG_NR34 (*(vu8 *)REG_ADDR_NR34) +#define REG_SOUND4CNT_L (*(vu16 *)REG_ADDR_SOUND4CNT_L) +#define REG_NR41 (*(vu8 *)REG_ADDR_NR41) +#define REG_NR42 (*(vu8 *)REG_ADDR_NR42) +#define REG_SOUND4CNT_H (*(vu16 *)REG_ADDR_SOUND4CNT_H) +#define REG_NR43 (*(vu8 *)REG_ADDR_NR43) +#define REG_NR44 (*(vu8 *)REG_ADDR_NR44) +#define REG_SOUNDCNT_L (*(vu16 *)REG_ADDR_SOUNDCNT_L) +#define REG_NR50 (*(vu8 *)REG_ADDR_NR50) +#define REG_NR51 (*(vu8 *)REG_ADDR_NR51) +#define REG_SOUNDCNT_H (*(vu16 *)REG_ADDR_SOUNDCNT_H) +#define REG_SOUNDCNT_X (*(vu16 *)REG_ADDR_SOUNDCNT_X) +#define REG_NR52 (*(vu8 *)REG_ADDR_NR52) +#define REG_SOUNDBIAS (*(vu16 *)REG_ADDR_SOUNDBIAS) +#define REG_SOUNDBIAS_L (*(vu8 *)REG_ADDR_SOUNDBIAS_L) +#define REG_SOUNDBIAS_H (*(vu8 *)REG_ADDR_SOUNDBIAS_H) +#define REG_WAVE_RAM0 (*(vu32 *)REG_ADDR_WAVE_RAM0) +#define REG_WAVE_RAM1 (*(vu32 *)REG_ADDR_WAVE_RAM1) +#define REG_WAVE_RAM2 (*(vu32 *)REG_ADDR_WAVE_RAM2) +#define REG_WAVE_RAM3 (*(vu32 *)REG_ADDR_WAVE_RAM3) +#define REG_FIFO_A (*(vu32 *)REG_ADDR_FIFO_A) +#define REG_FIFO_B (*(vu32 *)REG_ADDR_FIFO_B) + +#define REG_DMA0SAD (*(vu32 *)REG_ADDR_DMA0SAD) +#define REG_DMA0DAD (*(vu32 *)REG_ADDR_DMA0DAD) +#define REG_DMA0CNT (*(vu32 *)REG_ADDR_DMA0CNT) +#define REG_DMA0CNT_L (*(vu16 *)REG_ADDR_DMA0CNT_L) +#define REG_DMA0CNT_H (*(vu16 *)REG_ADDR_DMA0CNT_H) + +#define REG_DMA1SAD (*(vu32 *)REG_ADDR_DMA1SAD) +#define REG_DMA1DAD (*(vu32 *)REG_ADDR_DMA1DAD) +#define REG_DMA1CNT (*(vu32 *)REG_ADDR_DMA1CNT) +#define REG_DMA1CNT_L (*(vu16 *)REG_ADDR_DMA1CNT_L) +#define REG_DMA1CNT_H (*(vu16 *)REG_ADDR_DMA1CNT_H) + +#define REG_DMA2SAD (*(vu32 *)REG_ADDR_DMA2SAD) +#define REG_DMA2DAD (*(vu32 *)REG_ADDR_DMA2DAD) +#define REG_DMA2CNT (*(vu32 *)REG_ADDR_DMA2CNT) +#define REG_DMA2CNT_L (*(vu16 *)REG_ADDR_DMA2CNT_L) +#define REG_DMA2CNT_H (*(vu16 *)REG_ADDR_DMA2CNT_H) + +#define REG_DMA3SAD (*(vu32 *)REG_ADDR_DMA3SAD) +#define REG_DMA3DAD (*(vu32 *)REG_ADDR_DMA3DAD) +#define REG_DMA3CNT (*(vu32 *)REG_ADDR_DMA3CNT) +#define REG_DMA3CNT_L (*(vu16 *)REG_ADDR_DMA3CNT_L) +#define REG_DMA3CNT_H (*(vu16 *)REG_ADDR_DMA3CNT_H) + +#define REG_TMCNT(n) (*(vu16 *)(REG_ADDR_TMCNT + ((n) * 4))) +#define REG_TM0CNT (*(vu32 *)REG_ADDR_TM0CNT) +#define REG_TM0CNT_L (*(vu16 *)REG_ADDR_TM0CNT_L) +#define REG_TM0CNT_H (*(vu16 *)REG_ADDR_TM0CNT_H) +#define REG_TM1CNT (*(vu32 *)REG_ADDR_TM1CNT) +#define REG_TM1CNT_L (*(vu16 *)REG_ADDR_TM1CNT_L) +#define REG_TM1CNT_H (*(vu16 *)REG_ADDR_TM1CNT_H) +#define REG_TM2CNT (*(vu32 *)REG_ADDR_TM2CNT) +#define REG_TM2CNT_L (*(vu16 *)REG_ADDR_TM2CNT_L) +#define REG_TM2CNT_H (*(vu16 *)REG_ADDR_TM2CNT_H) +#define REG_TM3CNT (*(vu32 *)REG_ADDR_TM3CNT) +#define REG_TM3CNT_L (*(vu16 *)REG_ADDR_TM3CNT_L) +#define REG_TM3CNT_H (*(vu16 *)REG_ADDR_TM3CNT_H) + +#define REG_SIOCNT (*(vu16 *)REG_ADDR_SIOCNT) +#define REG_SIODATA8 (*(vu16 *)REG_ADDR_SIODATA8) +#define REG_SIODATA32 (*(vu32 *)REG_ADDR_SIODATA32) +#define REG_SIOMLT_SEND (*(vu16 *)REG_ADDR_SIOMLT_SEND) +#define REG_SIOMLT_RECV (*(vu64 *)REG_ADDR_SIOMLT_RECV) +#define REG_SIOMULTI0 (*(vu16 *)REG_ADDR_SIOMULTI0) +#define REG_SIOMULTI1 (*(vu16 *)REG_ADDR_SIOMULTI1) +#define REG_SIOMULTI2 (*(vu16 *)REG_ADDR_SIOMULTI2) +#define REG_SIOMULTI3 (*(vu16 *)REG_ADDR_SIOMULTI3) + +#define REG_KEYINPUT (*(vu16 *)REG_ADDR_KEYINPUT) +#define REG_KEYCNT (*(vu16 *)REG_ADDR_KEYCNT) + +#define REG_RCNT (*(vu16 *)REG_ADDR_RCNT) + +#define REG_IME (*(vu16 *)REG_ADDR_IME) +#define REG_IE (*(vu16 *)REG_ADDR_IE) +#define REG_IF (*(vu16 *)REG_ADDR_IF) + +#define REG_WAITCNT (*(vu16 *)REG_ADDR_WAITCNT) + +// I/O register fields + +// DISPCNT +#define DISPCNT_MODE_0 0x0000 // BG0: text, BG1: text, BG2: text, BG3: text +#define DISPCNT_MODE_1 0x0001 // BG0: text, BG1: text, BG2: affine, BG3: off +#define DISPCNT_MODE_2 0x0002 // BG0: off, BG1: off, BG2: affine, BG3: affine +#define DISPCNT_MODE_3 0x0003 // Bitmap mode, 240x160, BGR555 color +#define DISPCNT_MODE_4 0x0004 // Bitmap mode, 240x160, 256 color palette +#define DISPCNT_MODE_5 0x0005 // Bitmap mode, 160x128, BGR555 color +#define DISPCNT_OBJ_1D_MAP 0x0040 +#define DISPCNT_FORCED_BLANK 0x0080 +#define DISPCNT_BG0_ON 0x0100 +#define DISPCNT_BG1_ON 0x0200 +#define DISPCNT_BG2_ON 0x0400 +#define DISPCNT_BG3_ON 0x0800 +#define DISPCNT_BG_ALL_ON 0x0F00 +#define DISPCNT_OBJ_ON 0x1000 +#define DISPCNT_WIN0_ON 0x2000 +#define DISPCNT_WIN1_ON 0x4000 +#define DISPCNT_OBJWIN_ON 0x8000 + +// DISPSTAT +#define DISPSTAT_VBLANK 0x0001 // in V-Blank +#define DISPSTAT_HBLANK 0x0002 // in H-Blank +#define DISPSTAT_VCOUNT 0x0004 // V-Count match +#define DISPSTAT_VBLANK_INTR 0x0008 // V-Blank interrupt enabled +#define DISPSTAT_HBLANK_INTR 0x0010 // H-Blank interrupt enabled +#define DISPSTAT_VCOUNT_INTR 0x0020 // V-Count interrupt enabled + +// BGCNT +#define BGCNT_PRIORITY(n) (n) // Values 0 - 3. Lower priority BGs will be drawn on top of higher priority BGs. +#define BGCNT_CHARBASE(n) ((n) << 2) // Values 0 - 3. Base block for tile pixel data. +#define BGCNT_MOSAIC 0x0040 +#define BGCNT_16COLOR 0x0000 // 4 bits per pixel +#define BGCNT_256COLOR 0x0080 // 8 bits per pixel +#define BGCNT_SCREENBASE(n) ((n) << 8) // Values 0 - 31. Base block for tile map. +#define BGCNT_WRAP 0x2000 // Only affects affine BGs. Text BGs wrap by default. +#define BGCNT_TXT256x256 0x0000 // Internal screen size size of text mode BG in pixels. +#define BGCNT_TXT512x256 0x4000 +#define BGCNT_TXT256x512 0x8000 +#define BGCNT_TXT512x512 0xC000 +#define BGCNT_AFF128x128 0x0000 // Internal screen size size of affine mode BG in pixels. +#define BGCNT_AFF256x256 0x4000 +#define BGCNT_AFF512x512 0x8000 +#define BGCNT_AFF1024x1024 0xC000 + +// BLDCNT +// Bits 0-5 select layers for the 1st target +#define BLDCNT_TGT1_BG0 (1 << 0) +#define BLDCNT_TGT1_BG1 (1 << 1) +#define BLDCNT_TGT1_BG2 (1 << 2) +#define BLDCNT_TGT1_BG3 (1 << 3) +#define BLDCNT_TGT1_OBJ (1 << 4) +#define BLDCNT_TGT1_BD (1 << 5) +// Bits 6-7 select the special effect +#define BLDCNT_EFFECT_NONE (0 << 6) // no special effect +#define BLDCNT_EFFECT_BLEND (1 << 6) // 1st+2nd targets mixed (controlled by BLDALPHA) +#define BLDCNT_EFFECT_LIGHTEN (2 << 6) // 1st target becomes whiter (controlled by BLDY) +#define BLDCNT_EFFECT_DARKEN (3 << 6) // 1st target becomes blacker (controlled by BLDY) +// Bits 8-13 select layers for the 2nd target +#define BLDCNT_TGT2_BG0 (1 << 8) +#define BLDCNT_TGT2_BG1 (1 << 9) +#define BLDCNT_TGT2_BG2 (1 << 10) +#define BLDCNT_TGT2_BG3 (1 << 11) +#define BLDCNT_TGT2_OBJ (1 << 12) +#define BLDCNT_TGT2_BD (1 << 13) + +// BLDALPHA +#define BLDALPHA_BLEND(target1, target2) (((target2) << 8) | (target1)) + +// SOUNDCNT_H +#define SOUND_CGB_MIX_QUARTER 0x0000 +#define SOUND_CGB_MIX_HALF 0x0001 +#define SOUND_CGB_MIX_FULL 0x0002 +#define SOUND_A_MIX_HALF 0x0000 +#define SOUND_A_MIX_FULL 0x0004 +#define SOUND_B_MIX_HALF 0x0000 +#define SOUND_B_MIX_FULL 0x0008 +#define SOUND_ALL_MIX_FULL 0x000E +#define SOUND_A_RIGHT_OUTPUT 0x0100 +#define SOUND_A_LEFT_OUTPUT 0x0200 +#define SOUND_A_TIMER_0 0x0000 +#define SOUND_A_TIMER_1 0x0400 +#define SOUND_A_FIFO_RESET 0x0800 +#define SOUND_B_RIGHT_OUTPUT 0x1000 +#define SOUND_B_LEFT_OUTPUT 0x2000 +#define SOUND_B_TIMER_0 0x0000 +#define SOUND_B_TIMER_1 0x4000 +#define SOUND_B_FIFO_RESET 0x8000 + +// SOUNDCNT_X +#define SOUND_1_ON 0x0001 +#define SOUND_2_ON 0x0002 +#define SOUND_3_ON 0x0004 +#define SOUND_4_ON 0x0008 +#define SOUND_MASTER_ENABLE 0x0080 + +// DMA +#define DMA_DEST_INC 0x0000 +#define DMA_DEST_DEC 0x0020 +#define DMA_DEST_FIXED 0x0040 +#define DMA_DEST_RELOAD 0x0060 +#define DMA_SRC_INC 0x0000 +#define DMA_SRC_DEC 0x0080 +#define DMA_SRC_FIXED 0x0100 +#define DMA_REPEAT 0x0200 +#define DMA_16BIT 0x0000 +#define DMA_32BIT 0x0400 +#define DMA_DREQ_ON 0x0800 +#define DMA_START_NOW 0x0000 +#define DMA_START_VBLANK 0x1000 +#define DMA_START_HBLANK 0x2000 +#define DMA_START_SPECIAL 0x3000 +#define DMA_START_MASK 0x3000 +#define DMA_INTR_ENABLE 0x4000 +#define DMA_ENABLE 0x8000 + +// timer +#define TIMER_1CLK 0x00 +#define TIMER_64CLK 0x01 +#define TIMER_256CLK 0x02 +#define TIMER_1024CLK 0x03 +#define TIMER_INTR_ENABLE 0x40 +#define TIMER_ENABLE 0x80 + +// serial +#define SIO_ID 0x0030 // Communication ID + +#define SIO_8BIT_MODE 0x0000 // Normal 8-bit communication mode +#define SIO_32BIT_MODE 0x1000 // Normal 32-bit communication mode +#define SIO_MULTI_MODE 0x2000 // Multi-player communication mode +#define SIO_UART_MODE 0x3000 // UART communication mode + +#define SIO_9600_BPS 0x0000 // baud rate 9600 bps +#define SIO_38400_BPS 0x0001 // 38400 bps +#define SIO_57600_BPS 0x0002 // 57600 bps +#define SIO_115200_BPS 0x0003 // 115200 bps + +#define SIO_MULTI_SI 0x0004 // Multi-player communication SI terminal +#define SIO_MULTI_SD 0x0008 // SD terminal +#define SIO_MULTI_BUSY 0x0080 + +#define SIO_ERROR 0x0040 // Detect error +#define SIO_START 0x0080 // Start transfer +#define SIO_ENABLE 0x0080 // Enable SIO + +#define SIO_INTR_ENABLE 0x4000 + +#define SIO_MULTI_SI_SHIFT 2 +#define SIO_MULTI_SI_MASK 0x1 +#define SIO_MULTI_DI_SHIFT 3 +#define SIO_MULTI_DI_MASK 0x1 + +// keys +#define A_BUTTON 0x0001 +#define B_BUTTON 0x0002 +#define SELECT_BUTTON 0x0004 +#define START_BUTTON 0x0008 +#define DPAD_RIGHT 0x0010 +#define DPAD_LEFT 0x0020 +#define DPAD_UP 0x0040 +#define DPAD_DOWN 0x0080 +#define R_BUTTON 0x0100 +#define L_BUTTON 0x0200 +#define KEYS_MASK 0x03FF +#define KEY_INTR_ENABLE 0x0400 +#define KEY_OR_INTR 0x0000 +#define KEY_AND_INTR 0x8000 +#define DPAD_ANY 0x00F0 +#define JOY_EXCL_DPAD 0x030F + +// interrupt flags +#define INTR_FLAG_VBLANK (1 << 0) +#define INTR_FLAG_HBLANK (1 << 1) +#define INTR_FLAG_VCOUNT (1 << 2) +#define INTR_FLAG_TIMER0 (1 << 3) +#define INTR_FLAG_TIMER1 (1 << 4) +#define INTR_FLAG_TIMER2 (1 << 5) +#define INTR_FLAG_TIMER3 (1 << 6) +#define INTR_FLAG_SERIAL (1 << 7) +#define INTR_FLAG_DMA0 (1 << 8) +#define INTR_FLAG_DMA1 (1 << 9) +#define INTR_FLAG_DMA2 (1 << 10) +#define INTR_FLAG_DMA3 (1 << 11) +#define INTR_FLAG_KEYPAD (1 << 12) +#define INTR_FLAG_GAMEPAK (1 << 13) + +// WAITCNT +#define WAITCNT_SRAM_4 (0 << 0) +#define WAITCNT_SRAM_3 (1 << 0) +#define WAITCNT_SRAM_2 (2 << 0) +#define WAITCNT_SRAM_8 (3 << 0) +#define WAITCNT_SRAM_MASK (3 << 0) + +#define WAITCNT_WS0_N_4 (0 << 2) +#define WAITCNT_WS0_N_3 (1 << 2) +#define WAITCNT_WS0_N_2 (2 << 2) +#define WAITCNT_WS0_N_8 (3 << 2) +#define WAITCNT_WS0_N_MASK (3 << 2) + +#define WAITCNT_WS0_S_2 (0 << 4) +#define WAITCNT_WS0_S_1 (1 << 4) + +#define WAITCNT_WS1_N_4 (0 << 5) +#define WAITCNT_WS1_N_3 (1 << 5) +#define WAITCNT_WS1_N_2 (2 << 5) +#define WAITCNT_WS1_N_8 (3 << 5) +#define WAITCNT_WS1_N_MASK (3 << 5) + +#define WAITCNT_WS1_S_4 (0 << 7) +#define WAITCNT_WS1_S_1 (1 << 7) + +#define WAITCNT_WS2_N_4 (0 << 8) +#define WAITCNT_WS2_N_3 (1 << 8) +#define WAITCNT_WS2_N_2 (2 << 8) +#define WAITCNT_WS2_N_8 (3 << 8) +#define WAITCNT_WS2_N_MASK (3 << 8) + +#define WAITCNT_WS2_S_8 (0 << 10) +#define WAITCNT_WS2_S_1 (1 << 10) + +#define WAITCNT_PHI_OUT_NONE (0 << 11) +#define WAITCNT_PHI_OUT_4MHZ (1 << 11) +#define WAITCNT_PHI_OUT_8MHZ (2 << 11) +#define WAITCNT_PHI_OUT_16MHZ (3 << 11) +#define WAITCNT_PHI_OUT_MASK (3 << 11) + +#define WAITCNT_PREFETCH_ENABLE (1 << 14) + +#define WAITCNT_AGB (0 << 15) +#define WAITCNT_CGB (1 << 15) + +#endif // GUARD_GBA_IO_REG_H diff --git a/include/gba/m4a_internal.h b/include/gba/m4a_internal.h new file mode 100644 index 0000000..ff92fcc --- /dev/null +++ b/include/gba/m4a_internal.h @@ -0,0 +1,463 @@ +#ifndef GUARD_M4A_INTERNAL_H +#define GUARD_M4A_INTERNAL_H + +#include "gba/gba.h" + +// ASCII encoding of 'Smsh' in reverse +// This is presumably short for SMASH, the developer of MKS4AGB. +#define ID_NUMBER 0x68736D53 + +#define C_V 0x40 // center value for PAN, BEND, and TUNE + +#define SOUND_MODE_REVERB_VAL 0x0000007F +#define SOUND_MODE_REVERB_SET 0x00000080 +#define SOUND_MODE_MAXCHN 0x00000F00 +#define SOUND_MODE_MAXCHN_SHIFT 8 +#define SOUND_MODE_MASVOL 0x0000F000 +#define SOUND_MODE_MASVOL_SHIFT 12 +#define SOUND_MODE_FREQ_05734 0x00010000 +#define SOUND_MODE_FREQ_07884 0x00020000 +#define SOUND_MODE_FREQ_10512 0x00030000 +#define SOUND_MODE_FREQ_13379 0x00040000 +#define SOUND_MODE_FREQ_15768 0x00050000 +#define SOUND_MODE_FREQ_18157 0x00060000 +#define SOUND_MODE_FREQ_21024 0x00070000 +#define SOUND_MODE_FREQ_26758 0x00080000 +#define SOUND_MODE_FREQ_31536 0x00090000 +#define SOUND_MODE_FREQ_36314 0x000A0000 +#define SOUND_MODE_FREQ_40137 0x000B0000 +#define SOUND_MODE_FREQ_42048 0x000C0000 +#define SOUND_MODE_FREQ 0x000F0000 +#define SOUND_MODE_FREQ_SHIFT 16 +#define SOUND_MODE_DA_BIT_9 0x00800000 +#define SOUND_MODE_DA_BIT_8 0x00900000 +#define SOUND_MODE_DA_BIT_7 0x00A00000 +#define SOUND_MODE_DA_BIT_6 0x00B00000 +#define SOUND_MODE_DA_BIT 0x00B00000 +#define SOUND_MODE_DA_BIT_SHIFT 20 + +struct WaveData +{ + u16 type; + u16 status; + u32 freq; + u32 loopStart; + u32 size; // number of samples + s8 data[1]; // samples +}; + +#define TONEDATA_TYPE_CGB 0x07 +#define TONEDATA_TYPE_FIX 0x08 +#define TONEDATA_TYPE_SPL 0x40 // key split +#define TONEDATA_TYPE_RHY 0x80 // rhythm + +#define TONEDATA_P_S_PAN 0xc0 +#define TONEDATA_P_S_PAM TONEDATA_P_S_PAN + +struct ToneData +{ + u8 type; + u8 key; + u8 length; // sound length (compatible sound) + u8 pan_sweep; // pan or sweep (compatible sound ch. 1) + struct WaveData *wav; + u8 attack; + u8 decay; + u8 sustain; + u8 release; +}; + +struct CgbChannel +{ + u8 sf; + u8 ty; + u8 rightVolume; + u8 leftVolume; + u8 at; + u8 de; + u8 su; + u8 re; + u8 ky; + u8 ev; + u8 eg; + u8 ec; + u8 echoVolume; + u8 echoLength; + u8 d1; + u8 d2; + u8 gt; + u8 mk; + u8 ve; + u8 pr; + u8 rp; + u8 d3[3]; + u8 d5; + u8 sg; + u8 n4; + u8 pan; + u8 panMask; + u8 mo; + u8 le; + u8 sw; + u32 fr; + u32 wp; + u32 cp; + u32 tp; + u32 pp; + u32 np; + u8 d4[8]; +}; + +struct MusicPlayerTrack; + +struct SoundChannel +{ + u8 status; + u8 type; + u8 rightVolume; + u8 leftVolume; + u8 attack; + u8 decay; + u8 sustain; + u8 release; + u8 ky; + u8 ev; + u8 er; + u8 el; + u8 echoVolume; + u8 echoLength; + u8 d1; + u8 d2; + u8 gt; + u8 mk; + u8 ve; + u8 pr; + u8 rp; + u8 d3[3]; + u32 ct; + u32 fw; + u32 freq; + struct WaveData *wav; + u32 cp; + struct MusicPlayerTrack *track; + u32 pp; + u32 np; + u32 d4; + u16 xpi; + u16 xpc; +}; + +#define MAX_DIRECTSOUND_CHANNELS 12 + +#define PCM_DMA_BUF_SIZE 1584 // size of Direct Sound buffer + +struct SoundInfo +{ + // This field is normally equal to ID_NUMBER but it is set to other + // values during sensitive operations for locking purposes. + // This field should be volatile but isn't. This could potentially cause + // race conditions. + u32 ident; + + vu8 pcmDmaCounter; + + // Direct Sound + u8 reverb; + u8 maxChans; + u8 masterVolume; + u8 freq; + + u8 mode; + u8 c15; + u8 pcmDmaPeriod; // number of V-blanks per PCM DMA + u8 maxLines; + u8 gap[3]; + s32 pcmSamplesPerVBlank; + s32 pcmFreq; + s32 divFreq; + struct CgbChannel *cgbChans; + u32 func; + u32 intp; + void (*CgbSound)(void); + void (*CgbOscOff)(u8); + u32 (*MidiKeyToCgbFreq)(u8, u8, u8); + u32 MPlayJumpTable; + u32 plynote; + u32 ExtVolPit; + u8 gap2[16]; + struct SoundChannel chans[MAX_DIRECTSOUND_CHANNELS]; + s8 pcmBuffer[PCM_DMA_BUF_SIZE * 2]; +}; + +struct SongHeader +{ + u8 trackCount; + u8 blockCount; + u8 priority; + u8 reverb; + struct ToneData *tone; + u8 *part[1]; +}; + +struct PokemonCrySong +{ + u8 trackCount; + u8 blockCount; + u8 priority; + u8 reverb; + struct ToneData *tone; + u8 *part[2]; + u8 gap; + u8 part0; // 0x11 + u8 tuneValue; // 0x12 + u8 gotoCmd; // 0x13 + u32 gotoTarget; // 0x14 + u8 part1; // 0x18 + u8 tuneValue2; // 0x19 + u8 cont[2]; // 0x1A + u8 volCmd; // 0x1C + u8 volumeValue; // 0x1D + u8 unkCmd0D[2]; // 0x1E + u32 unkCmd0DParam; // 0x20 + u8 xreleCmd[2]; // 0x24 + u8 releaseValue; // 0x26 + u8 panCmd; + u8 panValue; // 0x28 + u8 tieCmd; // 0x29 + u8 tieKeyValue; // 0x2A + u8 tieVelocityValue; // 0x2B + u8 unkCmd0C[2]; // 0x2C + u16 unkCmd0CParam; // 0x2E + u8 end[2]; // 0x30 +}; + +#define MPT_FLG_VOLSET 0x01 +#define MPT_FLG_VOLCHG 0x03 +#define MPT_FLG_PITSET 0x04 +#define MPT_FLG_PITCHG 0x0C +#define MPT_FLG_START 0x40 +#define MPT_FLG_EXIST 0x80 + +struct MusicPlayerTrack +{ + u8 flags; + u8 wait; + u8 patternLevel; + u8 repN; + u8 gateTime; + u8 key; + u8 velocity; + u8 runningStatus; + u8 keyM; + u8 pitM; + s8 keyShift; + s8 keyShiftX; + s8 tune; + u8 pitX; + s8 bend; + u8 bendRange; + u8 volMR; + u8 volML; + u8 vol; + u8 volX; + s8 pan; + s8 panX; + s8 modM; + u8 mod; + u8 modT; + u8 lfoSpeed; + u8 lfoSpeedC; + u8 lfoDelay; + u8 lfoDelayC; + u8 priority; + u8 echoVolume; + u8 echoLength; + struct SoundChannel *chan; + struct ToneData tone; + u8 gap[10]; + u16 unk_3A; + u32 unk_3C; + u8 *cmdPtr; + u8 *patternStack[3]; +}; + +#define MUSICPLAYER_STATUS_TRACK 0x0000ffff +#define MUSICPLAYER_STATUS_PAUSE 0x80000000 + +#define MAX_MUSICPLAYER_TRACKS 16 + +#define TEMPORARY_FADE 0x0001 +#define FADE_IN 0x0002 +#define FADE_VOL_MAX 64 +#define FADE_VOL_SHIFT 2 + +struct MusicPlayerInfo +{ + struct SongHeader *songHeader; + u32 status; + u8 trackCount; + u8 priority; + u8 cmd; + u8 unk_B; + u32 clock; + u8 gap[8]; + u8 *memAccArea; + u16 tempoD; + u16 tempoU; + u16 tempoI; + u16 tempoC; + u16 fadeOI; + u16 fadeOC; + u16 fadeOV; + struct MusicPlayerTrack *tracks; + struct ToneData *tone; + u32 ident; + u32 func; + u32 intp; +}; + +struct MusicPlayer +{ + struct MusicPlayerInfo *info; + struct MusicPlayerTrack *track; + u8 unk_8; + u16 unk_A; +}; + +struct Song +{ + struct SongHeader *header; + u16 ms; + u16 me; +}; + +extern const struct MusicPlayer gMPlayTable[]; +extern const struct Song gSongTable[]; + + + +extern u8 gMPlayMemAccArea[]; + +//u8 gPokemonCrySong[52]; +//u8 gPokemonCrySongs[52 * MAX_POKEMON_CRIES]; + +#define MAX_POKEMON_CRIES 2 + +extern struct PokemonCrySong gPokemonCrySong; +extern struct PokemonCrySong gPokemonCrySongs[]; + +extern struct MusicPlayerInfo gPokemonCryMusicPlayers[]; +extern struct MusicPlayerTrack gPokemonCryTracks[]; + +extern char SoundMainRAM[]; + +extern void *gMPlayJumpTable[]; + +typedef void (*XcmdFunc)(struct MusicPlayerInfo *, struct MusicPlayerTrack *); +extern const XcmdFunc gXcmdTable[]; + +extern struct CgbChannel gCgbChans[]; + +extern const u8 gScaleTable[]; +extern const u32 gFreqTable[]; +extern const u16 gPcmSamplesPerVBlankTable[]; + +extern const u8 gCgbScaleTable[]; +extern const s16 gCgbFreqTable[]; +extern const u8 gNoiseTable[]; + +extern const struct PokemonCrySong gPokemonCrySongTemplate; + +extern const struct ToneData voicegroup_pokemon_cry; + +extern char gNumMusicPlayers[]; +extern char gMaxLines[]; + +#define NUM_MUSIC_PLAYERS ((u16)gNumMusicPlayers) +#define MAX_LINES ((u32)gMaxLines) + +u32 umul3232H32(u32 multiplier, u32 multiplicand); +void SoundMain(void); +void SoundMainBTM(void); +void TrackStop(struct MusicPlayerInfo *mplayInfo, struct MusicPlayerTrack *track); +void MPlayMain(void); +void RealClearChain(void *x); + +void MPlayContinue(struct MusicPlayerInfo *mplayInfo); +void MPlayStart(struct MusicPlayerInfo *mplayInfo, struct SongHeader *songHeader); +void m4aMPlayStop(struct MusicPlayerInfo *mplayInfo); +void FadeOutBody(struct MusicPlayerInfo *mplayInfo); +void TrkVolPitSet(struct MusicPlayerInfo *mplayInfo, struct MusicPlayerTrack *track); +void MPlayFadeOut(struct MusicPlayerInfo *mplayInfo, u16 speed); +void ClearChain(void *x); +void Clear64byte(void *addr); +void SoundInit(struct SoundInfo *soundInfo); +void MPlayExtender(struct CgbChannel *cgbChans); +void m4aSoundMode(u32 mode); +void MPlayOpen(struct MusicPlayerInfo *mplayInfo, struct MusicPlayerTrack *track, u8 a3); +void CgbSound(void); +void CgbOscOff(u8); +u32 MidiKeyToCgbFreq(u8, u8, u8); +void DummyFunc(void); +void MPlayJumpTableCopy(void **mplayJumpTable); +void SampleFreqSet(u32 freq); +void m4aSoundVSyncOn(void); +void m4aSoundVSyncOff(void); + +void ClearModM(struct MusicPlayerTrack *track); +void m4aMPlayModDepthSet(struct MusicPlayerInfo *mplayInfo, u16 trackBits, u8 modDepth); +void m4aMPlayLFOSpeedSet(struct MusicPlayerInfo *mplayInfo, u16 trackBits, u8 lfoSpeed); + +struct MusicPlayerInfo *SetPokemonCryTone(struct ToneData *tone); +void SetPokemonCryVolume(u8 val); +void SetPokemonCryPanpot(s8 val); +void SetPokemonCryPitch(s16 val); +void SetPokemonCryLength(u16 val); +void SetPokemonCryRelease(u8 val); +void SetPokemonCryProgress(u32 val); +int IsPokemonCryPlaying(struct MusicPlayerInfo *mplayInfo); +void SetPokemonCryChorus(s8 val); +void SetPokemonCryStereo(u32 val); +void SetPokemonCryPriority(u8 val); + +// sound command handler functions +void ply_fine(struct MusicPlayerInfo *, struct MusicPlayerTrack *); +void ply_goto(struct MusicPlayerInfo *, struct MusicPlayerTrack *); +void ply_patt(struct MusicPlayerInfo *, struct MusicPlayerTrack *); +void ply_pend(struct MusicPlayerInfo *, struct MusicPlayerTrack *); +void ply_rept(struct MusicPlayerInfo *, struct MusicPlayerTrack *); +void ply_memacc(struct MusicPlayerInfo *, struct MusicPlayerTrack *); +void ply_prio(struct MusicPlayerInfo *, struct MusicPlayerTrack *); +void ply_tempo(struct MusicPlayerInfo *, struct MusicPlayerTrack *); +void ply_keysh(struct MusicPlayerInfo *, struct MusicPlayerTrack *); +void ply_voice(struct MusicPlayerInfo *, struct MusicPlayerTrack *); +void ply_vol(struct MusicPlayerInfo *, struct MusicPlayerTrack *); +void ply_pan(struct MusicPlayerInfo *, struct MusicPlayerTrack *); +void ply_bend(struct MusicPlayerInfo *, struct MusicPlayerTrack *); +void ply_bendr(struct MusicPlayerInfo *, struct MusicPlayerTrack *); +void ply_lfos(struct MusicPlayerInfo *, struct MusicPlayerTrack *); +void ply_lfodl(struct MusicPlayerInfo *, struct MusicPlayerTrack *); +void ply_mod(struct MusicPlayerInfo *, struct MusicPlayerTrack *); +void ply_modt(struct MusicPlayerInfo *, struct MusicPlayerTrack *); +void ply_tune(struct MusicPlayerInfo *, struct MusicPlayerTrack *); +void ply_port(struct MusicPlayerInfo *, struct MusicPlayerTrack *); +void ply_xcmd(struct MusicPlayerInfo *, struct MusicPlayerTrack *); +void ply_endtie(struct MusicPlayerInfo *, struct MusicPlayerTrack *); +void ply_note(struct MusicPlayerInfo *, struct MusicPlayerTrack *); + +// extended sound command handler functions +void ply_xxx(struct MusicPlayerInfo *, struct MusicPlayerTrack *); +void ply_xwave(struct MusicPlayerInfo *, struct MusicPlayerTrack *); +void ply_xtype(struct MusicPlayerInfo *, struct MusicPlayerTrack *); +void ply_xatta(struct MusicPlayerInfo *, struct MusicPlayerTrack *); +void ply_xdeca(struct MusicPlayerInfo *, struct MusicPlayerTrack *); +void ply_xsust(struct MusicPlayerInfo *, struct MusicPlayerTrack *); +void ply_xrele(struct MusicPlayerInfo *, struct MusicPlayerTrack *); +void ply_xiecv(struct MusicPlayerInfo *, struct MusicPlayerTrack *); +void ply_xiecl(struct MusicPlayerInfo *, struct MusicPlayerTrack *); +void ply_xleng(struct MusicPlayerInfo *, struct MusicPlayerTrack *); +void ply_xswee(struct MusicPlayerInfo *, struct MusicPlayerTrack *); +void ply_xcmd_0C(struct MusicPlayerInfo *, struct MusicPlayerTrack *); +void ply_xcmd_0D(struct MusicPlayerInfo *, struct MusicPlayerTrack *); + +#endif // GUARD_M4A_INTERNAL_H diff --git a/include/gba/macro.h b/include/gba/macro.h new file mode 100644 index 0000000..a0edf2a --- /dev/null +++ b/include/gba/macro.h @@ -0,0 +1,137 @@ +#ifndef GUARD_GBA_MACRO_H +#define GUARD_GBA_MACRO_H + +#define CPU_FILL(value, dest, size, bit) \ +{ \ + vu##bit tmp = (vu##bit)(value); \ + CpuSet((void *)&tmp, \ + dest, \ + CPU_SET_##bit##BIT | CPU_SET_SRC_FIXED | ((size)/(bit/8) & 0x1FFFFF)); \ +} + +#define CpuFill16(value, dest, size) CPU_FILL(value, dest, size, 16) +#define CpuFill32(value, dest, size) CPU_FILL(value, dest, size, 32) + +#define CPU_COPY(src, dest, size, bit) CpuSet(src, dest, CPU_SET_##bit##BIT | ((size)/(bit/8) & 0x1FFFFF)) + +#define CpuCopy16(src, dest, size) CPU_COPY(src, dest, size, 16) +#define CpuCopy32(src, dest, size) CPU_COPY(src, dest, size, 32) + +#define CpuFastFill(value, dest, size) \ +{ \ + vu32 tmp = (vu32)(value); \ + CpuFastSet((void *)&tmp, \ + dest, \ + CPU_FAST_SET_SRC_FIXED | ((size)/(32/8) & 0x1FFFFF)); \ +} + +#define CpuFastFill16(value, dest, size) CpuFastFill(((value) << 16) | (value), (dest), (size)) + +#define CpuFastCopy(src, dest, size) CpuFastSet(src, dest, ((size)/(32/8) & 0x1FFFFF)) + +#define DmaSet(dmaNum, src, dest, control) \ +{ \ + vu32 *dmaRegs = (vu32 *)REG_ADDR_DMA##dmaNum; \ + dmaRegs[0] = (vu32)(src); \ + dmaRegs[1] = (vu32)(dest); \ + dmaRegs[2] = (vu32)(control); \ + dmaRegs[2]; \ +} + +#define DMA_FILL(dmaNum, value, dest, size, bit) \ +{ \ + vu##bit tmp = (vu##bit)(value); \ + DmaSet(dmaNum, \ + &tmp, \ + dest, \ + (DMA_ENABLE | DMA_START_NOW | DMA_##bit##BIT | DMA_SRC_FIXED | DMA_DEST_INC) << 16 \ + | ((size)/(bit/8))); \ +} + +#define DmaFill16(dmaNum, value, dest, size) DMA_FILL(dmaNum, value, dest, size, 16) +#define DmaFill32(dmaNum, value, dest, size) DMA_FILL(dmaNum, value, dest, size, 32) + +// Note that the DMA clear macros cause the DMA control value to be calculated +// at runtime rather than compile time. The size is divided by the DMA transfer +// unit size (2 or 4 bytes) and then combined with the DMA control flags using a +// bitwise OR operation. + +#define DMA_CLEAR(dmaNum, dest, size, bit) \ +{ \ + vu##bit *_dest = (vu##bit *)(dest); \ + u32 _size = size; \ + DmaFill##bit(dmaNum, 0, _dest, _size); \ +} + +#define DmaClear16(dmaNum, dest, size) DMA_CLEAR(dmaNum, dest, size, 16) +#define DmaClear32(dmaNum, dest, size) DMA_CLEAR(dmaNum, dest, size, 32) + +#define DMA_COPY(dmaNum, src, dest, size, bit) \ + DmaSet(dmaNum, \ + src, \ + dest, \ + (DMA_ENABLE | DMA_START_NOW | DMA_##bit##BIT | DMA_SRC_INC | DMA_DEST_INC) << 16 \ + | ((size)/(bit/8))) + +#define DmaCopy16(dmaNum, src, dest, size) DMA_COPY(dmaNum, src, dest, size, 16) +#define DmaCopy32(dmaNum, src, dest, size) DMA_COPY(dmaNum, src, dest, size, 32) + +#define DmaStop(dmaNum) \ +{ \ + vu16 *dmaRegs = (vu16 *)REG_ADDR_DMA##dmaNum; \ + dmaRegs[5] &= ~(DMA_START_MASK | DMA_DREQ_ON | DMA_REPEAT); \ + dmaRegs[5] &= ~DMA_ENABLE; \ + dmaRegs[5]; \ +} + +#define DmaCopyLarge(dmaNum, src, dest, size, block, bit) \ +{ \ + const void *_src = src; \ + void *_dest = dest; \ + u32 _size = size; \ + while (1) \ + { \ + DmaCopy##bit(dmaNum, _src, _dest, (block)); \ + _src += (block); \ + _dest += (block); \ + _size -= (block); \ + if (_size <= (block)) \ + { \ + DmaCopy##bit(dmaNum, _src, _dest, _size); \ + break; \ + } \ + } \ +} + +#define DmaClearLarge(dmaNum, dest, size, block, bit) \ +{ \ + u32 _size = size; \ + while (1) \ + { \ + DmaFill##bit(dmaNum, 0, dest, (block)); \ + dest += (block); \ + _size -= (block); \ + if (_size <= (block)) \ + { \ + DmaFill##bit(dmaNum, 0, dest, _size); \ + break; \ + } \ + } \ +} + +#define DmaCopyLarge16(dmaNum, src, dest, size, block) DmaCopyLarge(dmaNum, src, dest, size, block, 16) + +#define DmaCopyLarge32(dmaNum, src, dest, size, block) DmaCopyLarge(dmaNum, src, dest, size, block, 32) + +#define DmaCopyDefvars(dmaNum, src, dest, size, bit) \ +{ \ + const void *_src = src; \ + void *_dest = dest; \ + u32 _size = size; \ + DmaCopy##bit(dmaNum, _src, _dest, _size); \ +} + +#define DmaCopy16Defvars(dmaNum, src, dest, size) DmaCopyDefvars(dmaNum, src, dest, size, 16) +#define DmaCopy32Defvars(dmaNum, src, dest, size) DmaCopyDefvars(dmaNum, src, dest, size, 32) + +#endif // GUARD_GBA_MACRO_H diff --git a/include/gba/multiboot.h b/include/gba/multiboot.h new file mode 100644 index 0000000..e88b43a --- /dev/null +++ b/include/gba/multiboot.h @@ -0,0 +1,55 @@ +#ifndef GUARD_GBA_MULTIBOOT_H +#define GUARD_GBA_MULTIBOOT_H + +#define MULTIBOOT_NCHILD 3 // Maximum number of slaves +#define MULTIBOOT_HEADER_SIZE 0xc0 // Header size +#define MULTIBOOT_SEND_SIZE_MIN 0x100 // Minimum transmission size +#define MULTIBOOT_SEND_SIZE_MAX 0x40000 // Maximum transmission size + +struct MultiBootParam +{ + u32 system_work[5]; + u8 handshake_data; + u8 padding; + u16 handshake_timeout; + u8 probe_count; + u8 client_data[MULTIBOOT_NCHILD]; + u8 palette_data; + u8 response_bit; + u8 client_bit; + u8 reserved1; + u8 *boot_srcp; + u8 *boot_endp; + u8 *masterp; + u8 *reserved2[MULTIBOOT_NCHILD]; + u32 system_work2[4]; + u8 sendflag; + u8 probe_target_bit; + u8 check_wait; + u8 server_type; +}; + +#define MULTIBOOT_ERROR_04 0x04 +#define MULTIBOOT_ERROR_08 0x08 +#define MULTIBOOT_ERROR_0c 0x0c +#define MULTIBOOT_ERROR_40 0x40 +#define MULTIBOOT_ERROR_44 0x44 +#define MULTIBOOT_ERROR_48 0x48 +#define MULTIBOOT_ERROR_4c 0x4c +#define MULTIBOOT_ERROR_80 0x80 +#define MULTIBOOT_ERROR_84 0x84 +#define MULTIBOOT_ERROR_88 0x88 +#define MULTIBOOT_ERROR_8c 0x8c +#define MULTIBOOT_ERROR_NO_PROBE_TARGET 0x50 +#define MULTIBOOT_ERROR_NO_DLREADY 0x60 +#define MULTIBOOT_ERROR_BOOT_FAILURE 0x70 +#define MULTIBOOT_ERROR_HANDSHAKE_FAILURE 0x71 + +#define MULTIBOOT_CONNECTION_CHECK_WAIT 15 + +#define MULTIBOOT_SERVER_TYPE_NORMAL 0 +#define MULTIBOOT_SERVER_TYPE_QUICK 1 + +#define MULTIBOOT_HANDSHAKE_TIMEOUT 400 + +#endif // GUARD_GBA_MULTIBOOT_H diff --git a/include/gba/syscall.h b/include/gba/syscall.h new file mode 100644 index 0000000..deddec5 --- /dev/null +++ b/include/gba/syscall.h @@ -0,0 +1,48 @@ +#ifndef GUARD_GBA_SYSCALL_H +#define GUARD_GBA_SYSCALL_H + +#define RESET_EWRAM 0x01 +#define RESET_IWRAM 0x02 +#define RESET_PALETTE 0x04 +#define RESET_VRAM 0x08 +#define RESET_OAM 0x10 +#define RESET_SIO_REGS 0x20 +#define RESET_SOUND_REGS 0x40 +#define RESET_REGS 0x80 +#define RESET_ALL 0xFF + +void SoftReset(u32 resetFlags); + +void RegisterRamReset(u32 resetFlags); + +void VBlankIntrWait(void); + +u16 Sqrt(u32 num); + +u16 ArcTan2(s16 x, s16 y); + +#define CPU_SET_SRC_FIXED 0x01000000 +#define CPU_SET_16BIT 0x00000000 +#define CPU_SET_32BIT 0x04000000 + +void CpuSet(const void *src, void *dest, u32 control); + +#define CPU_FAST_SET_SRC_FIXED 0x01000000 + +void CpuFastSet(const void *src, void *dest, u32 control); + +void BgAffineSet(struct BgAffineSrcData *src, struct BgAffineDstData *dest, s32 count); + +void ObjAffineSet(struct ObjAffineSrcData *src, void *dest, s32 count, s32 offset); + +void LZ77UnCompWram(const void *src, void *dest); + +void LZ77UnCompVram(const void *src, void *dest); + +void RLUnCompWram(const void *src, void *dest); + +void RLUnCompVram(const void *src, void *dest); + +int MultiBoot(struct MultiBootParam *mp); + +#endif // GUARD_GBA_SYSCALL_H diff --git a/include/gba/types.h b/include/gba/types.h new file mode 100644 index 0000000..480619d --- /dev/null +++ b/include/gba/types.h @@ -0,0 +1,129 @@ +#ifndef GUARD_GBA_TYPES_H +#define GUARD_GBA_TYPES_H + +#include <stdint.h> + +typedef uint8_t u8; +typedef uint16_t u16; +typedef uint32_t u32; +typedef uint64_t u64; +typedef int8_t s8; +typedef int16_t s16; +typedef int32_t s32; +typedef int64_t s64; + +typedef volatile u8 vu8; +typedef volatile u16 vu16; +typedef volatile u32 vu32; +typedef volatile u64 vu64; +typedef volatile s8 vs8; +typedef volatile s16 vs16; +typedef volatile s32 vs32; +typedef volatile s64 vs64; + +typedef float f32; +typedef double f64; + +typedef u8 bool8; +typedef u16 bool16; +typedef u32 bool32; + +struct PlttData +{ + u16 r:5; // red + u16 g:5; // green + u16 b:5; // blue + u16 unused_15:1; +} /*__attribute__((packed))*/; + +struct OamData +{ + /*0x00*/ u32 y:8; + /*0x01*/ u32 affineMode:2; // 0x1, 0x2 = 0x3 + u32 objMode:2; // 0x4, 0x8 = 0xC + u32 mosaic:1; // 0x10 + u32 bpp:1; // 0x20 + u32 shape:2; // 0x40, 0x80 + + /*0x02*/ u32 x:9; + u32 matrixNum:5; // bits 3/4 are h-flip/v-flip if not in affine mode + u32 size:2; + + /*0x04*/ u16 tileNum:10; + u16 priority:2; + u16 paletteNum:4; + /*0x06*/ u16 affineParam; +}; + +#define ST_OAM_OBJ_NORMAL 0 +#define ST_OAM_OBJ_BLEND 1 +#define ST_OAM_OBJ_WINDOW 2 + +#define ST_OAM_AFFINE_OFF 0 +#define ST_OAM_AFFINE_NORMAL 1 +#define ST_OAM_AFFINE_ERASE 2 +#define ST_OAM_AFFINE_DOUBLE 3 + +#define ST_OAM_AFFINE_ON_MASK 1 +#define ST_OAM_AFFINE_DOUBLE_MASK 2 + +#define ST_OAM_4BPP 0 +#define ST_OAM_8BPP 1 + +#define ST_OAM_SQUARE 0 +#define ST_OAM_H_RECTANGLE 1 +#define ST_OAM_V_RECTANGLE 2 + +struct BgAffineSrcData +{ + s32 texX; + s32 texY; + s16 scrX; + s16 scrY; + s16 sx; + s16 sy; + u16 alpha; +}; + +struct BgAffineDstData +{ + s16 pa; + s16 pb; + s16 pc; + s16 pd; + s32 dx; + s32 dy; +}; + +struct ObjAffineSrcData +{ + s16 xScale; + s16 yScale; + u16 rotation; +}; + +// Multi-player SIO Control Structure +struct SioMultiCnt +{ + u16 baudRate:2; // baud rate + u16 si:1; // SI terminal + u16 sd:1; // SD terminal + u16 id:2; // ID + u16 error:1; // error flag + u16 enable:1; // SIO enable + u16 unused_11_8:4; + u16 mode:2; // communication mode (should equal 2) + u16 intrEnable:1; // IRQ enable + u16 unused_15:1; + u16 data; // data +}; + +#define ST_SIO_MULTI_MODE 2 // Multi-player communication mode + +// baud rate +#define ST_SIO_9600_BPS 0 // 9600 bps +#define ST_SIO_38400_BPS 1 // 38400 bps +#define ST_SIO_57600_BPS 2 // 57600 bps +#define ST_SIO_115200_BPS 3 // 115200 bps + +#endif // GUARD_GBA_TYPES_H |