//Fichier de référence pour le matériel de la GBA. Complète matériel.h.

#ifndef GBA_H
#define GBA_H

//Interruptions
#define INT_VBLANK 0x0001
#define INT_HBLANK 0x0002
#define INT_VCOUNT 0x0004
#define INT_TIMER0 0x0008
#define INT_TIMER1 0x0010
#define INT_TIMER2 0x0020
#define INT_TIMER3 0x0040
#define INT_COMMUNICATION 0x0080 //serial communication interupt
#define INT_DMA0 0x0100
#define INT_DMA1 0x0200
#define INT_DMA2 0x0400
#define INT_DMA3 0x0800
#define INT_JOY 0x1000
#define INT_CART 0x2000 //the cart can actually generate an interupt
#define INT_ALL 0x4000 //this is just a flag we can set to allow the my function to enable or disable all interrupts. Doesn't actually correspond to a bit in REG_IE


//Pour régler REG_DISPCNT
#define MODE_0 0x0
#define MODE_1 0x1
#define MODE_2 0x2
#define MODE_3 0x3
#define MODE_4 0x4
#define MODE_5 0x5

#define BACKBUFFER 0x10
#define H_BLANK_OAM 0x20

#define OBJ_MAP_2D 0x0
#define OBJ_MAP_1D 0x40

#define FORCE_BLANK 0x80

#define BG0_ENABLE 0x100
#define BG1_ENABLE 0x200
#define BG2_ENABLE 0x400
#define BG3_ENABLE 0x800
#define OBJ_ENABLE 0x1000

#define WIN1_ENABLE 0x2000
#define WIN2_ENABLE 0x4000
#define WINOBJ_ENABLE 0x8000


//Macro pour changer le mode graphique
#define SetMode(mode) REG_DISPCNT = (mode)

//Définitions pour le DMA
#define DMA ((volatile struct DMACHN *)0x040000b0)
#define DMA_DSTINC      0x0000
#define DMA_DSTDEC      0x0020
#define DMA_DSTUNCH     0x0040
#define DMA_DSTINCRESET 0x0060
#define DMA_SRCINC      0x0000
#define DMA_SRCDEC      0x0080
#define DMA_SRCUNCH     0x0100
#define DMA_REPEAT      0x0200
#define DMA_U16         0x0000
#define DMA_U32         0x0400
#define DMA_COPYNOW     0x8000
#define DMA_VBLANK      0x9000
#define DMA_HBLANK      0xA000
#define DMA_SPECIAL     0xB000
#define DMA_IRQ         0x4000
#define DMA_ENABLE      0x8000  /* deprecated */
#define REG_INTERRUPT   *(u32*)0x3007FFC		//Interrupt Register

//Pour un contrôleur DMA
struct DMACHN
{
  const void *src;
  void *dst;
  u16 count;
  u16 control;
};

//Adresse de base des DMA (il y en a 4)
#define DMA ((volatile struct DMACHN *)0x040000b0)

//Pour les timers
typedef struct TIMER_REC
{
  unsigned short count;
  unsigned short control;
} TIMER_REC;

//Idem que pour les DMA
#define TIMER ((volatile TIMER_REC *)0x04000100)
//Fréquences possibles pour les timers
#define TIMER_16MHZ      0x0000
#define TIMER_262KHZ     0x0001
#define TIMER_65KHZ      0x0002
#define TIMER_16KHZ      0x0003
#define TIMER_CASCADE    0x0004
#define TIMER_IRQ        0x0040
#define TIMER_ENABLE     0x0080

//Pour le son
#define SNDSTAT        (*(volatile u16*)0x04000084)
#define SNDSTAT_SQR1   0x0001
#define SNDSTAT_SQR2   0x0002
#define SNDSTAT_TRI    0x0004
#define SNDSTAT_NOISE  0x0008
#define SNDSTAT_ENABLE 0x0080

//Notez que bien que la Game Boy Advance inclue le matériel complet de la Game Boy Color, il n'est pas
//possible de l'utiliser en mode "Advance", car il utilise une autre tension. Seuls les canaux son sont
//utilisables dans les deux modes.
#define DMGSNDCTRL         (*(volatile u16 *)0x04000080)
#define DMGSNDCTRL_LVOL(x) (x)
#define DMGSNDCTRL_RVOL(x) ((x) << 4)
#define DMGSNDCTRL_LSQR1   0x0100
#define DMGSNDCTRL_LSQR2   0x0200
#define DMGSNDCTRL_LTRI    0x0400
#define DMGSNDCTRL_LNOISE  0x0800
#define DMGSNDCTRL_RSQR1   0x1000
#define DMGSNDCTRL_RSQR2   0x2000
#define DMGSNDCTRL_RTRI    0x4000
#define DMGSNDCTRL_RNOISE  0x8000

//Direct sound (son numérique haute qualité, ça c'est nouveau)
#define DSOUNDCTRL         (*(volatile u16 *)0x04000082)
#define DSOUNDCTRL_DMG25     0x0000
#define DSOUNDCTRL_DMG50     0x0001
#define DSOUNDCTRL_DMG100    0x0002
#define DSOUNDCTRL_A50       0x0000
#define DSOUNDCTRL_A100      0x0004
#define DSOUNDCTRL_B50       0x0000
#define DSOUNDCTRL_B100      0x0008
#define DSOUNDCTRL_AR        0x0100
#define DSOUNDCTRL_AL        0x0200
#define DSOUNDCTRL_ATIMER(x) ((x) << 10)
#define DSOUNDCTRL_ARESET    0x0400
#define DSOUNDCTRL_BR        0x1000
#define DSOUNDCTRL_BL        0x2000
#define DSOUNDCTRL_BTIMER(x) ((x) << 14)
#define DSOUNDCTRL_BRESET    0x8000

//Triangle
#define TRICTRL         (*(volatile u16 *)0x04000070)
#define TRICTRL_2X32    0x0000
#define TRICTRL_1X64    0x0020
#define TRICTRL_BANK(x) ((x) << 6)
#define TRICTRL_ENABLE  0x0080

//Carré
#define SQR1FREQ      (*(volatile u16 *)0x04000064)
#define SQR2FREQ      (*(volatile u16 *)0x0400006c)
#define TRIFREQ       (*(volatile u16 *)0x04000074)
#define FREQ_HOLD  0x0000
#define FREQ_TIMED 0x4000
#define FREQ_RESET 0x8000

//Fréquence de l'échantilloneur interne
#define SNDBIAS      (*(volatile u16 *)0x04000088)
#define SETSNDRES(x) SNDBIAS = (SNDBIAS & 0x3fff) | (x << 14)

//Fifo des canaux Direct Sound
#define DSOUND_FIFOA (*(volatile u32 *)0x040000a0)
#define DSOUND_FIFOB (*(volatile u32 *)0x040000a4)

#define TRILENVOL        (*(volatile u16 *)0x04000072)
#define TRILENVOL_LEN(x) (256 - (x))
#define TRILENVOL_MUTE   0x0000
#define TRILENVOL_25     0x6000
#define TRILENVOL_50     0x4000
#define TRILENVOL_75     0x8000
#define TRILENVOL_100    0x2000

#define SQR1SWEEP   (*(volatile u16 *)0x04000060)
#define SQR1SWEEP_OFF 0x0008

#define REG_SOUNDCNT_X *(vu16*)0x4000084

//Definitions supplémentaires
#define REG_TM0CNT_H    *(vu16*)0x4000102
#define REG_TM1CNT_H   *(vu16*)0x4000106
#define REG_DMA1CNT_H   *(u16*)0x40000C6

#endif

