//Définit les priorités des arrière-plans
#define BG_PRIORITE_0 0x0000
#define BG_PRIORITE_1 0x0001
#define BG_PRIORITE_2 0x0002
#define BG_PRIORITE_3 0x0003
//Le CharBlock (adresse de base des mosaïques) qu'ils utilisent. Il y a 4 charblocks de 16 ko.
#define BG_CHARBLOCK_0 0x0000
#define BG_CHARBLOCK_1 0x0004
#define BG_CHARBLOCK_2 0x0008
#define BG_CHARBLOCK_3 0x000C
//Effet mosaïque, que je n'utilise pas ici.
#define BG_EFFET_MOSAIQUE 0x0040
//Si on utilise une palette de 256 couleurs, chaque pixel sera codé sur 8 bits.
#define BG_1_PALETTE 0x0080
//Ici, on a 16x16 couleurs, et chaque pixel est codé sur 4 bits, et il faudra choisir le numéro de palette (sur les 16) à utiliser.
#define BG_16_PALETTES 0x0000
//Définit si l'arrière-plan "tourne en rond" (i.e. ce qui est tout à droite revient à gauche).
#define BG_WRAP 0x2000

//En mode texte, les mosaïques sont codées sur 16 bits (2 octets)
//Mode normale 256x256 (32x32 mosaïques)
#define BG_TEXTE_256x256 0x0000
//Mode large 512x256 (64x32 mosaïques)
#define BG_TEXTE_512x256 0x4000
//Mode haute 256x512 (32x64 mosaïques)
#define BG_TEXTE_256x512 0x8000
//Mode immense 512x512 (64x64 mosaïques)
#define BG_TEXTE_512x512 0xC000

//En mode rotation, les mosaïques sont codées sur 16 bits (2 octets)
//Petite map rotation 128x128
#define BG_ROTATION_128x128 0x0000
//Moyenne map rotation 256x256
#define BG_ROTATION_256x256 0x4000
//Grande map rotation 512x512
#define BG_ROTATION_512x512 0x8000
//Très grande map rotation, utile pour les jeux de course par exemple.
#define BG_ROTATION_1024x1024 0xC000

//Début de la RAM (256 ko externes, lents)
#define EWRAM  ((volatile u8 *)0x02000000)

//Chaque charblock fait 16 ko (il contient 512 mosaïques 4 bits par exemple)
#define CharBaseBlock(n) ((void*)(((n)*0x4000)+0x6000000))
//Chaque screenblock fait 2 ko (il contient une map texte de 256x256 par exemple)
#define ScreenBaseBlock(n) ((void*)(((n)*0x0800)+0x6000000))

//Activation des divers arrière-plans. Il y en a quatre.
#define VIDEO_BG0_ENABLED 0x100
#define VIDEO_BG1_ENABLED 0x200
#define VIDEO_BG2_ENABLED 0x400
#define VIDEO_BG3_ENABLED 0x800

//Activer les objets
#define OBJ_ENABLED 0x1000


//Six modes graphiques... Les modes 0 à 2 sont des modes de mosaïques, ils ont 64 ko pour les mosaïques,
//et 32 ko pour les sprites. 128 sprites sont affichables en même-temps. Chaque BG peut utiliser la
//transparence, et la rotation uniquement si c'est proposé par le mode (modes 1/2). Malheureusement, le
//coefficient de transparence est le même pour tout...

//Mode 0: 4 arrière-plans conventionnels
#define VIDEO_MODE0 0x0
//Mode 1: 2 arrière-plans conventionnels, 1 arrière-plan rotation
#define VIDEO_MODE1 0x1
//Mode 2: 2 arrière-plans rotation
#define VIDEO_MODE2 0x2

//Les modes 3 à 5 sont des modes bitmap, en ce sens que les pixels sont directement stockés dans un
//tableau. L'utilisation de ces modes n'est pas avantageuse puisque outre le support de 16 ko pour 128
//sprites et la rotation de l'écran entier (excluant les sprites qui peuvent l'être individuellement)
//la console n'offre aucun support graphique dans ces modes. Ils sont généralement utilisés pour les
//images fixes ou des applications spéciales comme les moteurs 3D.

//Mode 3: 16 bits par pixel, 1 buffer, 240x160 pixels (écran entier)
#define VIDEO_MODE3 0x3
//Mode 4: 8 bits par pixel, double-buffering, 240x160 pixels (écran entier)
#define VIDEO_MODE4 0x4
//Mode 5: 16 bits par pixel, double-buffering, 160x128 pixels (il est possible de le redimensionner mais
//le nombre de pixels réels disponible de va pas augmenter).
#define VIDEO_MODE5 0x5


//Définitions des registres DMA (Direct Memory Access) qui permettent d'effectuer des copies très rapides
//dans la mémoire. Le DMA3 peut accéder à toute la mémoire, mais il est plus lent, tandis que le DMA0 ne
//peut acceder au GamePak (cartouche de jeu). Enfin, les DMA1 et DMA2 sont utilisés pour le son, et sont
//donc en général monopolisés.

//Adresse source
#define REG_DMA3SAD *(volatile unsigned int*)0x40000D4
//Adresse destination
#define REG_DMA3DAD *(volatile unsigned int*)0x40000D8
//Registre de contrôle
#define REG_DMA3CNT *(volatile unsigned int*)0x40000DC
//C'est la même chose pour tous.
#define REG_DMA2SAD *(volatile unsigned int*)0x40000C8
#define REG_DMA2DAD *(volatile unsigned int*)0x40000CC
#define REG_DMA2CNT *(volatile unsigned int*)0x40000D0
#define REG_DMA1SAD *(volatile unsigned int*)0x40000BC
#define REG_DMA1DAD *(volatile unsigned int*)0x40000C0
#define REG_DMA1CNT *(volatile unsigned int*)0x40000C4
#define REG_DMA0SAD *(volatile unsigned int*)0x40000B0
#define REG_DMA0DAD *(volatile unsigned int*)0x40000B4
#define REG_DMA0CNT *(volatile unsigned int*)0x40000B8

//A écrire dans le registre de contrôle pour:
//Démarrer le transfert
#define DMA_ENABLED 0x80000000
//Tout de suite, sont possibles aussi à la prochaine HBLANK, VBLANK ou FIFO (son).
#define DMA_TIMING_IMMEDIAT 0x00000000
//Transfert 16 bits.
#define DMA_16 0x00000000
//Transfert 32 bits.
#define DMA_32 0x04000000
//Décrémente le compteur de la destination
#define DMA_DSTDECREMENT (0x00200000)
//Décrémente le compteur de la source
#define DMA_SRCDECREMENT (0x00800000)
//Fixe le compteur de la source
#define DMA_SRCFIXE (0x01000000)


//Contient directement les options nécessaires pour commencer à copier 16 ou 32 bits.
#define DMA_16im (DMA_ENABLED | DMA_TIMING_IMMEDIAT | DMA_16)
#define DMA_32im (DMA_ENABLED | DMA_TIMING_IMMEDIAT | DMA_32)

//Le registre des touches
#define REG_KEYS *(volatile unsigned long*) 0x4000130
//Les mosaïques des objets
#define tilesObj (volatile unsigned short *) 0x06010000

//Pour les touches, il faut inverser (à la base, les bits sont à zéro quand le bouton est pressé).
#define REG_TOUCHES (~(REG_KEYS) & 0x3FF)
//Les diverses touches, masques à l'aide d'un AND logique
#define TOUCHE_A 0x0001
#define TOUCHE_B 0x0002
#define TOUCHE_SELECT 0x0004
#define TOUCHE_START 0x0008
#define TOUCHE_DROITE 0x0010
#define TOUCHE_GAUCHE 0x0020
#define TOUCHE_HAUT 0x0040
#define TOUCHE_BAS 0x0080
#define TOUCHE_R 0x0100
#define TOUCHE_L 0x0200

//Un objet (sprite) est constitué de 4 paramètres (attributs).
typedef struct
{
    unsigned short attribut0;
    unsigned short attribut1;
    unsigned short attribut2;
    unsigned short attribut3;
} TypeSprite;

//Pour activer la semi-transparence (alpha-blend) d'un sprite.
#define MODE_NORMAL 0x0
#define MODE_TRANSPARENT 0x400


//Spécification des sections pour placer le code et les données.
#define IN_IWRAM __attribute__ ((section (".iwram")))
#define IN_EWRAM __attribute__ ((section (".ewram")))

//Non-documenté, règle le timing d'accès à l'EWRAM.
#define REG_WSRAM *(volatile unsigned long*) 0x4000800

//Définition des rotsets
typedef struct tagRotData
{
    //En fait, seuls 3 des 4 attributs d'un sprite sont vraiment utilisé. En combinant
    //l'espace gagné sur 4 sprites, on peut créer un rotset, constitué de 4 paramètres.
    u16 filler1[3];
    u16 pa;
    u16 filler2[3];
    u16 pb;
    u16 filler3[3];
    u16 pc;
    u16 filler4[3];
    u16 pd;
}RotData,*pRotData;

/*
        Fonctions et routines lointaines...

        Pour exécuter les routines qui se trouvent en IWRAM sans utiliser __FarFunction
        et __FarProcedure (je les utilise trop intensément sans savoir comment elles
        fonctionnent ;)) qui rendent les prototypes des fonctions trop compliqués
        (u32 LaFonction(u32 *FuncAddr, ...)), j'ai écrit deux simples routines de bran-
        chement qui sont certainement plus rapides et qui n'imposent pas de complications
        inutiles (déjà que ça l'est bien assez :D).
        Note: Si l'optimiseur est amélioré, il faudra peut-être ajouter volatile aux poin-
        teurs sur les fonctions pour pouvoir le recompiler correctement...
*/

void (*pRoutineLointaine)();
#define Exec(a,b...) ({ pRoutineLointaine = (void*)(a); pRoutineLointaine(b); })

u32 (*pFctLointaine)();
#define ExecFct(a,b...) ({ pFctLointaine = (void*)(a); pFctLointaine(b); })

//Déjà (faussement) défini dans mygba.h
#undef RGB
#define RGB(r,g,b)          ((r)+((g)<<5)+((b)<<10))
//#define RVB(r,g,b)          (coeffs[r]+(coeffs[g]<<5)+(coeffs[b]<<10))

//Paramètres du mode "sleep" permettant d'attendre sur la prochaine interruption en basse
//consommation ou de mettre la GBA en veille.
#define REG_STOPCNT *(volatile unsigned char*) 0x4000301


