summaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
Diffstat (limited to 'include')
-rw-r--r--include/gba/defines.h61
-rw-r--r--include/gba/flash_internal.h76
-rw-r--r--include/gba/gba.h10
-rw-r--r--include/gba/io_reg.h401
-rw-r--r--include/gba/m4a_internal.h462
-rw-r--r--include/gba/macro.h80
-rw-r--r--include/gba/syscall.h24
-rw-r--r--include/gba/types.h108
-rw-r--r--include/global.h30
-rw-r--r--include/task.h29
10 files changed, 1192 insertions, 89 deletions
diff --git a/include/gba/defines.h b/include/gba/defines.h
new file mode 100644
index 000000000..0f7f06755
--- /dev/null
+++ b/include/gba/defines.h
@@ -0,0 +1,61 @@
+#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) (BG_VRAM + (0x4000 * (n)))
+#define BG_SCREEN_ADDR(n) (BG_VRAM + (0x800 * (n)))
+
+// text-mode BG
+#define OBJ_VRAM0 (VRAM + 0x10000)
+#define OBJ_VRAM0_SIZE 0x8000
+
+// bitmap-mode BG
+#define OBJ_VRAM1 (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 000000000..6156b6c14
--- /dev/null
+++ b/include/gba/flash_internal.h
@@ -0,0 +1,76 @@
+#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 (*programFlashByte)(u16, u32, u8);
+ 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 (*ProgramFlashByte)(u16, u32, u8);
+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 ProgramFlashByte_MX(u16 sectorNum, u32 offset, u8 data);
+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 000000000..26342cf88
--- /dev/null
+++ b/include/gba/gba.h
@@ -0,0 +1,10 @@
+#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/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
index 1ef639793..0be92fa60 100644
--- a/include/gba/io_reg.h
+++ b/include/gba/io_reg.h
@@ -24,16 +24,20 @@
#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
@@ -47,45 +51,49 @@
#define REG_OFFSET_BLDALPHA 0x52
#define REG_OFFSET_BLDY 0x54
-#define REG_OFFSET_SOUND1CNT 0x60
#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_SOUND2CNT 0x68
+#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_SOUND3CNT 0x70
+#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_SOUND4CNT 0x78
+#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_SOUNDCNT 0x80
+#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_WAVE_RAM 0x90
+#define REG_OFFSET_SOUNDBIAS_L 0x88
+#define REG_OFFSET_SOUNDBIAS_H 0x89
#define REG_OFFSET_WAVE_RAM0 0x90
-#define REG_OFFSET_WAVE_RAM0_L 0x90
-#define REG_OFFSET_WAVE_RAM0_H 0x92
#define REG_OFFSET_WAVE_RAM1 0x94
-#define REG_OFFSET_WAVE_RAM1_L 0x94
-#define REG_OFFSET_WAVE_RAM1_H 0x96
#define REG_OFFSET_WAVE_RAM2 0x98
-#define REG_OFFSET_WAVE_RAM2_L 0x98
-#define REG_OFFSET_WAVE_RAM2_H 0x9a
#define REG_OFFSET_WAVE_RAM3 0x9c
-#define REG_OFFSET_WAVE_RAM3_L 0x9c
-#define REG_OFFSET_WAVE_RAM3_H 0x9e
-#define REG_OFFSET_FIFO 0xa0
#define REG_OFFSET_FIFO_A 0xa0
-#define REG_OFFSET_FIFO_A_L 0xa0
-#define REG_OFFSET_FIFO_A_H 0xa2
#define REG_OFFSET_FIFO_B 0xa4
-#define REG_OFFSET_FIFO_B_L 0xa4
-#define REG_OFFSET_FIFO_B_H 0xa6
#define REG_OFFSET_DMA0 0xb0
#define REG_OFFSET_DMA0SAD 0xb0
@@ -128,6 +136,7 @@
#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
@@ -192,16 +201,20 @@
#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)
@@ -215,87 +228,76 @@
#define REG_ADDR_BLDALPHA (REG_BASE + REG_OFFSET_BLDALPHA)
#define REG_ADDR_BLDY (REG_BASE + REG_OFFSET_BLDY)
-#define REG_ADDR_SOUND1CNT (REG_BASE + REG_OFFSET_SOUND1CNT)
#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_SOUND2CNT (REG_BASE + REG_OFFSET_SOUND2CNT)
+#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_SOUND3CNT (REG_BASE + REG_OFFSET_SOUND3CNT)
+#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_SOUND4CNT (REG_BASE + REG_OFFSET_SOUND4CNT)
+#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_SOUNDCNT (REG_BASE + REG_OFFSET_SOUNDCNT)
+#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_WAVE_RAM (REG_BASE + REG_OFFSET_WAVE_RAM)
+#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_RAM0_L (REG_BASE + REG_OFFSET_WAVE_RAM0_L)
-#define REG_ADDR_WAVE_RAM0_H (REG_BASE + REG_OFFSET_WAVE_RAM0_H)
#define REG_ADDR_WAVE_RAM1 (REG_BASE + REG_OFFSET_WAVE_RAM1)
-#define REG_ADDR_WAVE_RAM1_L (REG_BASE + REG_OFFSET_WAVE_RAM1_L)
-#define REG_ADDR_WAVE_RAM1_H (REG_BASE + REG_OFFSET_WAVE_RAM1_H)
#define REG_ADDR_WAVE_RAM2 (REG_BASE + REG_OFFSET_WAVE_RAM2)
-#define REG_ADDR_WAVE_RAM2_L (REG_BASE + REG_OFFSET_WAVE_RAM2_L)
-#define REG_ADDR_WAVE_RAM2_H (REG_BASE + REG_OFFSET_WAVE_RAM2_H)
#define REG_ADDR_WAVE_RAM3 (REG_BASE + REG_OFFSET_WAVE_RAM3)
-#define REG_ADDR_WAVE_RAM3_L (REG_BASE + REG_OFFSET_WAVE_RAM3_L)
-#define REG_ADDR_WAVE_RAM3_H (REG_BASE + REG_OFFSET_WAVE_RAM3_H)
-#define REG_ADDR_FIFO (REG_BASE + REG_OFFSET_FIFO)
#define REG_ADDR_FIFO_A (REG_BASE + REG_OFFSET_FIFO_A)
-#define REG_ADDR_FIFO_A_L (REG_BASE + REG_OFFSET_FIFO_A_L)
-#define REG_ADDR_FIFO_A_H (REG_BASE + REG_OFFSET_FIFO_A_H)
#define REG_ADDR_FIFO_B (REG_BASE + REG_OFFSET_FIFO_B)
-#define REG_ADDR_FIFO_B_L (REG_BASE + REG_OFFSET_FIFO_B_L)
-#define REG_ADDR_FIFO_B_H (REG_BASE + REG_OFFSET_FIFO_B_H)
#define REG_ADDR_DMA0 (REG_BASE + REG_OFFSET_DMA0)
#define REG_ADDR_DMA0SAD (REG_BASE + REG_OFFSET_DMA0SAD)
-#define REG_ADDR_DMA0SAD_L (REG_BASE + REG_OFFSET_DMA0SAD_L)
-#define REG_ADDR_DMA0SAD_H (REG_BASE + REG_OFFSET_DMA0SAD_H)
#define REG_ADDR_DMA0DAD (REG_BASE + REG_OFFSET_DMA0DAD)
-#define REG_ADDR_DMA0DAD_L (REG_BASE + REG_OFFSET_DMA0DAD_L)
-#define REG_ADDR_DMA0DAD_H (REG_BASE + REG_OFFSET_DMA0DAD_H)
#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_DMA1SAD_L (REG_BASE + REG_OFFSET_DMA1SAD_L)
-#define REG_ADDR_DMA1SAD_H (REG_BASE + REG_OFFSET_DMA1SAD_H)
#define REG_ADDR_DMA1DAD (REG_BASE + REG_OFFSET_DMA1DAD)
-#define REG_ADDR_DMA1DAD_L (REG_BASE + REG_OFFSET_DMA1DAD_L)
-#define REG_ADDR_DMA1DAD_H (REG_BASE + REG_OFFSET_DMA1DAD_H)
#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_DMA2SAD_L (REG_BASE + REG_OFFSET_DMA2SAD_L)
-#define REG_ADDR_DMA2SAD_H (REG_BASE + REG_OFFSET_DMA2SAD_H)
#define REG_ADDR_DMA2DAD (REG_BASE + REG_OFFSET_DMA2DAD)
-#define REG_ADDR_DMA2DAD_L (REG_BASE + REG_OFFSET_DMA2DAD_L)
-#define REG_ADDR_DMA2DAD_H (REG_BASE + REG_OFFSET_DMA2DAD_H)
#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_DMA3SAD_L (REG_BASE + REG_OFFSET_DMA3SAD_L)
-#define REG_ADDR_DMA3SAD_H (REG_BASE + REG_OFFSET_DMA3SAD_H)
#define REG_ADDR_DMA3DAD (REG_BASE + REG_OFFSET_DMA3DAD)
-#define REG_ADDR_DMA3DAD_L (REG_BASE + REG_OFFSET_DMA3DAD_L)
-#define REG_ADDR_DMA3DAD_H (REG_BASE + REG_OFFSET_DMA3DAD_H)
#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)
@@ -344,11 +346,152 @@
#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
@@ -360,6 +503,15 @@
#define DISPCNT_MODE_5 0x0005
#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
@@ -369,6 +521,102 @@
#define DISPSTAT_HBLANK_INTR 0x0010 // H-Blank interrupt enabled
#define DISPSTAT_VCOUNT_INTR 0x0020 // V-Count interrupt enabled
+// 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_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_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
+
// interrupt flags
#define INTR_FLAG_VBLANK (1 << 0)
#define INTR_FLAG_HBLANK (1 << 1)
@@ -385,4 +633,49 @@
#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 000000000..84b448243
--- /dev/null
+++ b/include/gba/m4a_internal.h
@@ -0,0 +1,462 @@
+#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_842FC88;
+
+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 m4aMPlayTempoControl(struct MusicPlayerInfo *mplayInfo, u16 tempo);
+void m4aMPlayVolumeControl(struct MusicPlayerInfo *mplayInfo, u16 trackBits, u16 volume);
+void m4aMPlayPitchControl(struct MusicPlayerInfo *mplayInfo, u16 trackBits, u16 pitch);
+void m4aMPlayPanpotControl(struct MusicPlayerInfo *mplayInfo, u16 trackBits, s8 pan);
+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 *);
diff --git a/include/gba/macro.h b/include/gba/macro.h
index 5578f90ba..62d3e73fa 100644
--- a/include/gba/macro.h
+++ b/include/gba/macro.h
@@ -1,15 +1,85 @@
#ifndef GUARD_GBA_MACRO_H
#define GUARD_GBA_MACRO_H
-#define CPU_FILL(dest, value, size, bit) \
-do { \
+#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)); \
-} while (0)
+}
-#define CpuFill16(dest, value, size) CPU_FILL(dest, value, size, 16)
-#define CpuFill32(dest, value, size) CPU_FILL(dest, value, size, 32)
+#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 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]; \
+}
#endif // GUARD_GBA_MACRO_H
diff --git a/include/gba/syscall.h b/include/gba/syscall.h
index 0f4198b44..3f41abba1 100644
--- a/include/gba/syscall.h
+++ b/include/gba/syscall.h
@@ -1,10 +1,32 @@
#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);
+
#define CPU_SET_SRC_FIXED 0x01000000
#define CPU_SET_16BIT 0x00000000
#define CPU_SET_32BIT 0x04000000
-extern void CpuSet(void *src, void *dest, u32 controlData);
+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 ObjAffineSet(struct ObjAffineSrcData *src, void *dest, s32 count, s32 offset);
#endif // GUARD_GBA_SYSCALL_H
diff --git a/include/gba/types.h b/include/gba/types.h
new file mode 100644
index 000000000..be7390d5a
--- /dev/null
+++ b/include/gba/types.h
@@ -0,0 +1,108 @@
+#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;
+};
+
+struct OamData
+{
+ /*0x00*/ u32 y:8;
+ /*0x01*/ u32 affineMode:2;
+ u32 objMode:2;
+ u32 mosaic:1;
+ u32 bpp:1;
+ u32 shape:2;
+
+ /*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 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
diff --git a/include/global.h b/include/global.h
index 37473afc8..0047fcbdb 100644
--- a/include/global.h
+++ b/include/global.h
@@ -1,34 +1,6 @@
#ifndef GUARD_GLOBAL_H
#define GUARD_GLOBAL_H
-typedef unsigned char u8;
-typedef unsigned short u16;
-typedef unsigned int u32;
-typedef signed char s8;
-typedef signed short s16;
-typedef signed int s32;
-
-typedef volatile u8 vu8;
-typedef volatile u16 vu16;
-typedef volatile u32 vu32;
-typedef volatile s8 vs8;
-typedef volatile s16 vs16;
-typedef volatile s32 vs32;
-
-typedef float f32;
-typedef double f64;
-
-typedef u8 bool8;
-typedef u16 bool16;
-typedef u32 bool32;
-
-#define NULL (void *)0
-
-#define TRUE 1
-#define FALSE 0
-
-#include "gba/io_reg.h"
-#include "gba/syscall.h"
-#include "gba/macro.h"
+#include "gba/gba.h"
#endif // GUARD_GLOBAL_H
diff --git a/include/task.h b/include/task.h
new file mode 100644
index 000000000..a536bcab5
--- /dev/null
+++ b/include/task.h
@@ -0,0 +1,29 @@
+#ifndef GUARD_TASK_H
+#define GUARD_TASK_H
+
+typedef void (*TaskFunc)(u8 taskId);
+
+struct Task
+{
+ TaskFunc func;
+ bool8 isActive;
+ u8 prev;
+ u8 next;
+ u8 priority;
+ s16 data[16];
+};
+
+extern struct Task gTasks[];
+
+void ResetTasks();
+u8 CreateTask(TaskFunc func, u8 priority);
+void DestroyTask(u8 taskId);
+void RunTasks();
+void TaskDummy(u8 taskId);
+void SetTaskFuncWithFollowupFunc(u8 taskId, TaskFunc func, TaskFunc followupFunc);
+void SwitchTaskToFollowupFunc(u8 taskId);
+bool8 FuncIsActiveTask(TaskFunc func);
+u8 FindTaskIdByFunc(TaskFunc func);
+u8 GetTaskCount();
+
+#endif // GUARD_TASK_H