#include "commun.h"

//Variables diverses pour le texte
const u32 *fonte, *masque;
const char *tailles;
u32 hauteur_texte, largeur_texte;
u32 *adresse, largeur, hauteur;
u32 y_ww;
char *ligne2;
ZONE_TEXTE *zone_texte_courante;

//Certaines des fonctions qui se trouvent ci-dessous ne servent à rien dans le programme mais il pourrait
//être utile de vouloir les utiliser. Si une fonction est marquée comme inutiliséee, ce n'est pas qu'elle ne
//sert à rien, mais qu'elle n'est pas utilisée dans ce projet.

/*
    Fonctions de dessin.
    
    Le principe des fonctions à accès aux pixels a toujours été un peu du bidouillage. Et bien sûr, la GBA
    ne fait pas exception à la règle, car dessiner les pixels un à un serait impensable avec un processeur
    à 16 MHz. On va donc se débrouiller pour écrire plusieurs pixels à la fois. Voici la méthode que j'ai
    utilisé:
    
    Après avoir trouvé l'adresse du motif à modifier...
    Au départ, il faut passer un masque (AND). Les valeurs à zéro effaceront les pixels qui devront être
    modifiés. Ensuite on pourra écrire la nouvelle valeur souhaitée à l'aide d'un OR sans modifier les
    pixels qui ne font pas partie du motif. C'est commun comme méthode et cela permet de modifier plusieurs
    pixels en un accès.

    Prenons le cas où l'on veut dessiner un motif de 8 pixels (4 bits chacun) à la position x de 1. L'offset
    en y ne change absolument rien.
    D'abord: l'application du masque. Les valeur à 0xf représentent là où on écrira un pixel. Ce sera
    inversé par la suite, comme on le verra. On le fait d'abord décaler de 1 (x%8). Il faut savoir que par
    rapport à notre représentation d'un nombre hexa 0x12345678 par exemple, les pixels affichés à l'écran
    seront en fait 87654321. Donc pour faire décaler à droite, on fera en fait décaler le nombre vers la
    gauche.
    Masque: 0xffffffff, avec décalage (4 bits car 1 pixel d'offset): 0xfffffff0.
    Après inversion, on obtient 0x0000000f. Seul les 4 premiers bits ne seront pas modifiés, soit le
    premier pixel, comme voulu (car on dessine à la position 1, donc pas de modification du pixel 0!).
    Le faire avec un masque standard n'eût pas été possible. Car si on se retrouve avec 0x00000000
    (=effacer tous les pixels), un décalage dans quelle direction que ce soit ne donnera pas 0x0000000f
    car les bits décalés sont remplis avec des zéros.
    Maintenant l'écriture se fait de la même manière avec un OR. Un motif de 0x12345678 sera, après
    décalage, écrit 0x23456780, (les bits à l'extrémité ne seront pas écrits. Le pixel 1 n'est
    définitivement pas modifié (ouf!).
    Ensuite, il faut écrire la fin du motif (le pixel restant). Pour cela, on fait la même chose mais
    avec le comble du décalage (8-décalage courant), donc un décalage de 7 dans ce cas-là. Je vous laisse
    refaire le raisonnement avec cette valeur, on obtient bien ce qu'il faut...
*/

//Efface un pixel (Inutilisée)
void IN_IWRAM ClrPix(u32 x, u32 y)       {
    u32 *adr;
    
    //Calcule l'adresse pour se trouver dans la bonne mosaïque.
    adr=(adresse+(x&~7)+((y&~7)*largeur));
    //Y ajoute la ligne (modulo 8). Chaque ligne de 8 pixels fait 32 bits (4 bits par pixel).
    adr+=(y&7);
    //Stoque le pixel (prend un pixel de valeur 0xf et le fait décaler de 4 bits pour x modulo 8).
    *adr&=~(0xf<<((x&7)<<2));
}

//Met un pixel à la valeur 0xf (couleur 15 de la palette). Inutilisée.
void IN_IWRAM SetPix(u32 x, u32 y)       {
    u32 *adr;
    adr=(adresse+(x&~7)+((y&~7)*largeur));
    adr+=(y&7);

    *adr|=0xf<<((x&7)<<2);
}

//Ecrit un pixel d'une certaine couleur.
void IN_IWRAM EcritPixel(u32 x, u32 y, u32 couleur)       {
    u32 *adr;
    adr=(adresse+(x&~7)+((y&~7)*largeur));
    adr+=(y&7);

    //D'abord effacer le contenu (masque, ClrPix)
    *adr&=~(0xf<<((x&7)<<2));
    //Ensuite stoquer, non pas 0xf comme dans SetPix mais simplement la couleur désirée.
    *adr|=couleur<<((x&7)<<2);
}

/*
                                            PrepareMap
    Prépare un morceau de map pour qu'on puisse y écrire du texte. Dans la zone en question, chaque mosaïque
    aura une autre valeur, de sorte que chacune soit unique.

Paramètres:
    adresse: Pointeur sur la map à modifier. Cela peut être un ScreenBaseBlock ou une map en cache.
    x et y: Positions de départ (à la mosaïque près) où la modification va opérer.
    largeur et hauteur: Taille du rectangle modifié (à la mosaïque près).
*/
//L'offset est le numéro de la première mosaïque (en haut à gauche).
void IN_IWRAM PrepareMap(u16 *adresse, u32 x, u32 y, u32 offset, u32 largeur, u32 hauteur)       {
    int i,j;
    //La mosaïque zéro n'est pas utilisée et est considérée comme vide!
    offset++;
    for (j=0;j<hauteur;j++)
        for (i=0;i<largeur;i++)
            *(adresse+(j+y)*32+i+x)=offset+largeur*j+i;
}


//Ecrit un motif avec un masque
void IN_IWRAM EcritMotifMasque(u32 x, u32 y, u32 motif, u32 masque)        {
    u32 *adr;
    u32 i;
    adr=(adresse+(x&~7)+((y&~7)*largeur));
    adr+=(y&7);

    //Calcul du décalage à faire (x modulo largeur mosaïque) * 4 bits
    i=(x&7)<<2;
    //Masque (cf plus haut)
    *adr&=~(masque<<i);
    //Stoquage avec un OR par-dessus.
    *adr|=motif<<i;
    
    //Entre deux mosaïques? (Il n'y a qu'à la position 0 que le motif est parfaitement aligné).
    if (x&7)        {
        //Il faut reporter la partie manquante du motif sur la mosaïque à sa droite
        adr+=8;
        //Si on a par exemple décalé de 2 avant, ici on décalera de 6.
        i=32-i;
        *adr&=~(masque>>i);
        *adr|=motif>>i;
    }
}

//Ecrit plusieurs motifs et plusieurs masques
void IN_IWRAM EcritMotifsMasque(u32 x, u32 y, u32 nombre, const u32 *motifs, const u32 *masques)        {
    u32 *adr;
    u32 i,j;
//    adr=((u32*)CharBaseBlock(2)+((x>>3)<<3)+((y>>3)<<8));
    adr=(adresse+(x&~7)+((y&~7)*largeur));
    adr+=(y&7);

    //Préparation
    i=(x&7)<<2;
    if (x&7)        {
        j=32-i;
        while(nombre--)       {
            *adr&=~(*masques<<i);
            *adr|=*motifs<<i;
            *(adr+8)&=~(*masques>>j);
            *(adr+8)|=*motifs>>j;
            if ((y&7)==7)
                adr+=(largeur<<3)-7;
            else
                adr++;
            masques++, motifs++;
            y++;
        }
    }
    else    {
        while(nombre--)       {
            *adr&=~(*masques<<i);
            *adr|=*motifs<<i;
            if ((y&7)==7)
                adr+=(largeur<<3)-7;
            else
                adr++;
            masques++, motifs++;
            y++;
        }
    }
}

//Ecrit plusieurs motifs, plusieurs masques et effectue une multiplication.
void IN_IWRAM EcritMotifsMasqueCouleur(u32 x, u32 y, u32 nombre, const u32 *motifs, const u32 *masques, u32 couleur)        {
    u32 *adr;
    u32 i,j;
//    adr=((u32*)CharBaseBlock(2)+((x>>3)<<3)+((y>>3)<<8));
    adr=(adresse+(x&~7)+((y&~7)*largeur));
    adr+=(y&7);

    //Préparation
    i=(x&7)<<2;
    if (x&7)        {
        j=32-i;
        while(nombre--)       {
            *adr&=~(*masques<<i);
            *adr|=(*motifs*couleur)<<i;
            *(adr+8)&=~(*masques>>j);
            *(adr+8)|=(*motifs*couleur)>>j;
            if ((y&7)==7)
                adr+=(largeur<<3)-7;
            else
                adr++;
            masques++, motifs++;
            y++;
        }
    }
    else    {
        while(nombre--)       {
            *adr&=~(*masques<<i);
            *adr|=(*motifs*couleur)<<i;
            if ((y&7)==7)
                adr+=(largeur<<3)-7;
            else
                adr++;
            masques++, motifs++;
            y++;
        }
    }
}

//Dessine une chaîne de caractères aux positions demandées (Mode 0)
void IN_IWRAM DessTexte(u32 x, u32 y, char *chaine, u32 couleur)     {
    while(*chaine)      {
        if (x+tailles[*chaine-32]>largeur<<3)
            break;
        EcritMotifsMasqueCouleur(x,y,hauteur_texte,fonte+hauteur_texte*(*chaine-32),masque+hauteur_texte*(*chaine-32),couleur);
        x+=tailles[*chaine-32];
        chaine++;
    }
}

//Dessine un caractère (Mode 0)
void DessCar(u32 x, u32 y, u8 car, u32 couleur)     {
    Exec(EcritMotifsMasqueCouleur,x,y,hauteur_texte,fonte+hauteur_texte*(car-32),masque+hauteur_texte*(car-32),couleur);
}

//Idem, en italique.
void DessCarItalique(u32 x, u32 y, u8 car, u32 couleur)     {
    u32 i;
    for (i=0;i<hauteur_texte/3;i++)
        Exec(EcritMotifMasque,x+2,y+i,fonte[hauteur_texte*(car-32)+i]*couleur,masque[hauteur_texte*(car-32)+i]);
    for (;i<2*hauteur_texte/3;i++)
        Exec(EcritMotifMasque,x+1,y+i,fonte[hauteur_texte*(car-32)+i]*couleur,masque[hauteur_texte*(car-32)+i]);
    for (;i<hauteur_texte;i++)
        Exec(EcritMotifMasque,x+0,y+i,fonte[hauteur_texte*(car-32)+i]*couleur,masque[hauteur_texte*(car-32)+i]);
}

//Dessine du texte avec un support formatage basique et avec des retours à la ligne automatiques.
void IN_IWRAM DessTexteWW(u32 x, u32 y, char *chaine, u32 couleur)     {
    u32 xx, xbase=x, ybase=y, gras=0;
    char *temp;

    while(*chaine)      {
        if (*chaine==32)     {
            temp=chaine+1;
            xx=x+tailles[0];
            while (*temp!=32 && *temp!='\n' && *temp)      {
                xx+=tailles[*temp-32];
                temp++;
            }
            if (xx>=largeur<<3)     {
haut:
                if (y==ybase)
                    ligne2=chaine+1;
                y+=hauteur_texte, x=xbase;
                if (y+hauteur_texte>hauteur<<3)
                    break;
                chaine++;
                continue;
            }
        }
        if (*chaine=='§')         {
            chaine++;
            if (*chaine=='*')
                gras=!gras;
            else
                couleur=(*chaine)-'0';
        }
        else    {
            if (*chaine=='\n')
                goto haut;
            if (x+tailles[*chaine-32]>largeur<<3)
                goto haut;
            EcritMotifsMasqueCouleur(x,y,hauteur_texte,fonte+hauteur_texte*(*chaine-32),masque+hauteur_texte*(*chaine-32),couleur);
            if (gras)
                EcritMotifsMasqueCouleur(x+1,y,hauteur_texte,fonte+hauteur_texte*(*chaine-32),masque+hauteur_texte*(*chaine-32),couleur);
            x+=tailles[*chaine-32];
        }
        chaine++;
    }
    y_ww=y;
}

//Inutilisée. Peut être utile de l'avoir.
/*void DessTexteWWAvecScrolling(u32 x, u32 y, u32 scroll_y, char *chaine, u32 couleur)     {
    u32 xx, xbase=x, ybase=y;
    char *temp;

    while(*chaine)      {
//        EcritMotifsMasque(x,y,12,Verdana_fonte+12*(*chaine-32),Verdana_masque+12*(*chaine-32));
        if (*chaine==32)     {
            temp=chaine+1;
            xx=x+tailles[0];
            while (*temp!=32 && *temp!='\n' && *temp)      {
                xx+=tailles[*temp-32];
                temp++;
            }
            if (xx>=largeur<<3)     {
haut:
                y+=hauteur_texte, x=xbase;
                if (y+hauteur_texte+ybase>(hauteur<<3)+scroll_y)
                    break;
                chaine++;
                continue;
            }
        }
        if (*chaine=='\n')
            goto haut;
        if (x+tailles[*chaine-32]>largeur<<3)
            goto haut;
        if (y-ybase>=scroll_y)
            Exec(EcritMotifsMasqueCouleur,x,y-scroll_y+ybase,hauteur_texte,fonte+hauteur_texte*(*chaine-32),masque+hauteur_texte*(*chaine-32),couleur);
        x+=tailles[*chaine-32];
        chaine++;
    }
    y_ww=y;
}*/

//Change la palette (sur seize) utiliseé dans une certaine zone d'une map.
void ChangePaletteMap(u16 *adresse, u32 x, u32 y, u32 largeur, u32 hauteur, u32 nvPalette)       {
    int i,j;
    //La palette est définie dans les 4 derniers bits d'une mosaïque. On décale donc le numéro de palette par douze.
    for (j=0;j<hauteur;j++)
        for (i=0;i<largeur;i++)
            *(adresse+(j+y)*32+i+x)|=nvPalette<<12;
}

//Sélectionne un zone de texte.
void SelectZoneTexte(ZONE_TEXTE *z)      {
    adresse=(u32*)z->adresse;
    largeur=z->largeur, hauteur=z->hauteur;
    zone_texte_courante=z;
}

//Efface une zone de texte
void EffaceZone(ZONE_TEXTE *z)      {
    u32 zero=0;
    MemSet((void*)&zero,(void*)z->adresse,z->largeur*z->hauteur*8,DMA_32im);
}

/*
    Support du mode 0 en 256 couleurs. Pas utilisé, mais pourrait être utile...
*/
u32 *adresse256;
u32 largeur256, hauteur256;

//La meilleure pour le moment
void IN_IWRAM EcritPixel256(u32 x, u32 y, u32 couleur)       {
    u32 *adr;
    adr=adresse256+(((x&~7)+((y&~7)*largeur))<<1);
    adr+=(y&7)<<1;
    adr+=(x&7)>>2;

    *adr&=~(0xff<<((x&3)<<3));
    *adr|=couleur<<((x&3)<<3);
}

//Ecrit un motif avec un masque
void IN_IWRAM EcritPlusDe4Pixels256(u32 x, u32 y, u32 nbre, u32 *motif)        {
    u32 *adr;
    u32 i;
    const int masque=0xffffffff;

    adr=adresse256+(((x&~7)+((y&~7)*largeur))<<1);
    adr+=(y&7)<<1;
    adr+=(x&7)>>2;

    while(nbre--)     {
        i=(x&3)<<3;

        *adr&=~(masque<<i);
        *adr|=(*motif)<<i;

        if ((x&7)>=4)
            adr+=15;
        else
            adr++;

        i=(4-(x&3))<<3;
        *adr&=~(masque>>i);
        *adr|=(*motif)>>i;

        motif++;
        x+=4;
    }
}

/*
    Mode 4: Pour le lecteur de textes.
    Comme la fonction de ces fonctions est identique à celles pour le mode 0, je me passerai de commentaires.
*/
void IN_IWRAM Mode4_EcritPlusDe4Pixels(u32 x, u32 y, u32 nbre, u32 *motif)        {
    u32 *adr;
    u32 i,j;
    const int masque=0xffffffff;

    adr=(u32*)MemVideo+60*y+(x>>2);

    j=(x&3)<<3;

    while(nbre--)     {
        i=j;

        *adr&=~(masque<<i);
        *adr|=(*motif)<<i;

        adr++;

        i=32-j;
        //Ce n'est pas une erreur (<<)
        *adr&=~(masque<<i);
        *adr|=(*motif)>>i;

        motif++;
    }
}

void IN_IWRAM Mode4_EcritPlusDe4PixelsMasque(u32 x, u32 y, u32 nbre, u32 *motif, u32 *masque)        {
    u32 *adr;
    u32 i,j;

    adr=(u32*)MemVideo+60*y+(x>>2);

    j=(x&3)<<3;

    while(nbre--)     {
        i=j;

        *adr&=~((*masque)<<i);
        *adr|=(*motif)<<i;

        adr++;

        i=32-j;
        *adr&=~((*masque)>>i);
        *adr|=(*motif)>>i;

        motif++, masque++;
    }
}

void IN_IWRAM Mode4_EcritPlusDe4PixelsMasqueCouleur(u32 x, u32 y, u32 nbre, u32 *motif, u32 *masque, u32 couleur)        {
    u32 *adr;
    u32 i,j,val;

    adr=(u32*)MemVideo+60*y+(x>>2);

    j=(x&3)<<3;

    while(nbre--)     {
        val=(*motif)*couleur;

        i=j;
        *adr&=~((*masque)<<i);
        *adr|=val<<i;

        adr++;

        i=32-j;
        *adr&=~((*masque)>>i);
        *adr|=val>>i;

        masque++, motif++;
    }
}

void IN_IWRAM Mode4_EcritPixel(u32 x, u32 y, u32 couleur)       {
    u32 *adr;
    adr=(u32*)MemVideo+60*y+(x>>2);

    *adr&=~(0xff<<((x&3)<<3));
    *adr|=couleur<<((x&3)<<3);
}


//Pour le mode 4. Supporte le clipping (pas de dépassement en haut ou en bas de l'écran, mais attention: pas horizontalement).
void IN_IWRAM DessCar256(u32 x, s32 y, u8 car, u32 couleur)     {
    int i=0,h=hauteur_texte;
    u32 o;

    //Clipping (en y)
    if (y<0)        {
        if (y+h<0)
            return;
        i+=-y;
    }
    if (y+h>=160)       {
        if (y>=160)
            return;
        h-=(y+h)-160;
    }

    o=(hauteur_texte*largeur_texte)*(car-32)+i*largeur_texte;
    for (;i<h;i++)      {
        Mode4_EcritPlusDe4PixelsMasqueCouleur(x,y+i,largeur_texte,(u32*)(fonte+o),(u32*)(masque+o),couleur);
        o+=largeur_texte;
    }
}

//Idem.
void IN_IWRAM DessCarItalique256(u32 x, s32 y, u8 car, u32 couleur)     {
    int i=0,h=hauteur_texte;
    u32 o;

    //Clipping (en y)
    if (y<0)        {
        if (y+h<0)      {
            return;
        }
        i+=-y;
    }
    if (y+h>=160)       {
        if (y>=160)
            return;
        h-=(y+h)-160;
    }

    o=(hauteur_texte*largeur_texte)*(car-32)+i*largeur_texte;
    for (;i<h;i++)          {
        Mode4_EcritPlusDe4PixelsMasqueCouleur(x+(2-i/3),y+i,largeur_texte,(u32*)(fonte+o),(u32*)(masque+o),couleur);
        o+=largeur_texte;
    }
}


//Fonction de débogage. A décommenter si vous voulez l'utiliser en mode 0 (pendant la map).
/*void Debug(const char *format, ...)	{
    int j;
	char      str[100];
	va_list   arg_ptr;
	ZONE_TEXTE *z=zone_texte_courante;

    ChangeFonte(Verdana);
    SelectZoneTexte(&zt_debug);
    EffaceZone(&zt_debug);

	va_start(arg_ptr, format);
	j=vsprintf(str, format, arg_ptr);

    Exec(DessTexte,0,0,str,1);
    CopieDMA((void*)buffer_debug,(void*)CharBaseBlock(3)+32,sizeof(buffer_debug)>>1,DMA_16im);

	while(!(REG_TOUCHES&TOUCHE_SELECT));
	while((REG_TOUCHES&TOUCHE_SELECT));
	
	SelectZoneTexte(z);
}*/

//Fonction de débogage. A décommenter si vous voulez l'utiliser en mode 4 (pendant le lecteur de textes).
void Debug(const char *format, ...)	{
    int j=0,x=0;
	char      str[100], *ptr=str;
	va_list   arg_ptr;

    ChangeFonte256(Verdana);
    MemSet(&j,MemVideo,120*12,DMA_16im);

	va_start(arg_ptr, format);
	j=vsprintf(str, format, arg_ptr);

    while(*ptr)     {
        Exec(DessCar256,x,0,*ptr,0xfe);
        x+=tailles[*ptr-32];
        ptr++;
    }

	while(!(REG_TOUCHES&TOUCHE_SELECT));
	while((REG_TOUCHES&TOUCHE_SELECT));
}

//Variables globales pour récupérer le travail de DessTexteSpecial
LIEN IN_EWRAM liens[30];
u32 nEvenement;
char IN_EWRAM message_fond[100];

//Utilisée pour dessiner un menu. Support un offset vertical (scrolling en y), un handler auquel il demande
//les informations nécessaires, et met en couleur différente la sélection active.
//Remplit les liens trouvées dans les balises et le message associé à la sélection courante.
void IN_IWRAM DessTexteSpecial(u32 x, u32 y, char *chaine, u32 couleur, u32 selection, u32 offset, unsigned char *(*handler)(), u8 bAffiche)     {
    u32 xx, xbase=x, coul=couleur, interieur=0;
    char *temp, *chnesauve=NULL;
    u32 i, j;

    //A chaque mouvement, le menu est entièrement réanalysé et réaffiché. Tous les événements précédemment
    //trouvés sont vidés puis recréés. Même le texte qui n'est pas visible dans le menu est analysé pour
    //en connaître la largeur. Il ne sera seulement pas affiché dans ce cas-là.
    nEvenement=0;                               //Au départ, il n'y a aucun événement

redo:
    //Tant qu'on ne rencontre pas de caractère nul (fin de chaîne)
    while(*chaine)      {
        //C'est un espace
        if (*chaine==32)     {
            //On saute l'espace courant. Ce pointeur sera utilisé pour trouver le prochain espace.
            temp=chaine+1;
            //On va tester la taille de texte qu'il y a jusqu'au prochain espace pour savoir si cela ferait déborder la ligne.
            xx=x+tailles[0];
            //Tant que ce n'est pas un espace ou un saut de ligne et que la chaîne n'est pas terminée...
            while (*temp!=32 && *temp!='\n' && *temp!='#' && *temp)      {
                //On ajoute la taille
                xx+=tailles[*temp-32];
                //On incrémente le pointeur
                temp++;
            }
            //A-t-on dépassé la largeur maximale? (la largeur est définie en nombre de tiles, il faut donc la
            //multiplier par huit puisqu'on travaille en pixels, ce qui représente un décalage de 3 vers la gauche).
            if (xx>=largeur<<3)     {
haut:                                           //Label appeler pour passer à la prochaine ligne
                //Prochaine ligne
                y+=hauteur_texte;
                //A l'intérieur d'une option de menu?
                if (interieur)
                    x=xbase+9;                      //Oui -> indentation (9 pixels)
                else
                    x=xbase;                        //Non -> Reprise à gauche
                //Prochain caractère.
                chaine++;
                //Reprise au début de la boucle (le caractère n'est plus valide à présent).
                continue;
            }
        }

        //Caractère dièse: Insère un événement si le tableau n'est pas déjà rempli
        if (*chaine=='#' && nEvenement<sizeof(liens)/sizeof(liens[0])-1)           {
            //Prochain caractère
            chaine++;
            //L'événement en question est sélectionné -> couleur+1
            if (selection==nEvenement)
                coul++;
            //On va stocker le texte du lien dans le champ 'symbole' du lien
            i=0;
            //Tant que le champ n'est pas rempli, que ce n'est pas la fin du lien, de la chaîne ou enfin le début du message
            while(*chaine!='#' && *chaine!='|' && *chaine && i<sizeof(liens[nEvenement].symbole)-1)
                liens[nEvenement].symbole[i++]=*chaine++;
            //Toujours terminer la chaîne ;-)
            liens[nEvenement].symbole[i]=0;
            //Stocke la longueur dans j
            j=i;
            //On recommence
            i=0;
            //Dans le cas où l'option n'est pas sélectionné, le texte du message ne nous importe pas.
            if (selection==nEvenement)          {
                //Un message est défini
                if (*chaine=='|')
                    chaine++;
                //Jusqu'à la fermeture de la balise du lien
                while(*chaine!='#' && *chaine && i<sizeof(message_fond)-1)
                    message_fond[i++]=*chaine++;
                message_fond[i]=0;
            }
            else    {
                //Jusqu'à la fermeture du lien
                while(*chaine!='#' && *chaine)
                    chaine++;
            }
            //Position verticale
            liens[nEvenement].y=y;
            //Prochain caractère (passe le dièse)
            chaine++;
            //Texte du lien nul -> on questionne le handler
            if ((*chaine==0 || *chaine=='\n') && handler)          {
                liens[nEvenement].demande=nEvenement;
                chnesauve=chaine;
                chaine=handler(DEM_OPTION,nEvenement,0);
                if (chaine==NULL)
                    chaine=chnesauve, chnesauve=NULL;
            }
            else
                liens[nEvenement].demande=-1;
            nEvenement++;
            if (x==xbase)
                x+=9;
            interieur=1;
            continue;
        }
        else if (*chaine=='\n')      {
            if (interieur)      {
                liens[nEvenement-1].yfin=y+hauteur_texte;
                coul=couleur;
            }
            interieur=0;
            goto haut;
        }
        if (x+tailles[*chaine-32]>largeur<<3)
            goto haut;
        if (bAffiche && (signed)y-(signed)offset>=12 && (signed)y-(signed)offset+hauteur_texte<64)
            EcritMotifsMasqueCouleur(x,y-offset,hauteur_texte,fonte+hauteur_texte*(*chaine-32),masque+hauteur_texte*(*chaine-32),coul);
        x+=tailles[*chaine-32];
        chaine++;
    }
    
    if (chnesauve)      {
        chaine=chnesauve;
        chnesauve=NULL;
        goto redo;
    }

/*    if (x==xbase)
        y-=hauteur_texte;*/

    if (interieur)
        liens[nEvenement-1].yfin=y+hauteur_texte;
    y_ww=y;
}

void IN_IWRAM DessTexte256(u32 x, u32 y, char *chaine, u32 couleur)     {
    while(*chaine)      {
        if (x+tailles[*chaine-32]>240)
            break;
        DessCar256(x,y,*chaine,couleur);
        x+=tailles[*chaine-32];
        chaine++;
    }
}


