CODINGSDCC TUT'S PAR STEPHBB75 ★ Slide Show ★

Sdcc - 23 - Slide ShowCoding Sdcc Tut's Par Stephbb75

Si vous avez lu l'article "Afficher une image", on vas repartir de ce que l'on y a vue pour faire un Slide Show ( en bon français un Diaporama ... ca fait moins cool :-) )

Le plus compliqué là, c'est les images à afficher, j'ai choisi de belle mécanique...mais les goûts et les couleurs ...

Donc, j'ai repris chaque effets dans l'article précédent pour en faire une fonction pour chaque. Au passage j'ai fait quelques modifications / optimisation.
Premier changement, pour le calcule de l'adresse du Y à l'écran, j'ai fait une fonction, cela évite de dupliquer ce code dans toutes les fonctions (un petit gain de place), je ne l'est pas fait pour cette article, mais il faudrait l'écrire en ASM, cela serais bien plus rapide...
Pour les 4 effets d'affichage par le haut, bas, droite et gauche pas de changement :

//
// Fonctions pour les différents effets d'affichage d'une image
//
int CalYAdr( unsigned char y )
{
    return ( y >> 3 ) * 80 + ( y & 7 ) * 0x800;
}

void AffHautBas(char* BufScr, char* BufDep)
{
    unsigned char y;
    unsigned char x;  // attention, c'est pas les pixels mais les octets qui sont utilisé ici !!!
    int iAdr; // adresse de l'écran (relatif à BufScr)

    // Affichage de l'image en partant du haut de l'image vers le bas
    for (y = 0; y<200; y++)
    {
        // Calcule de l'adresse de debut de la ligne
        iAdr = CalYAdr( y );
        
        for (x = 0; x<80; x++)
        {
            BufScr[iAdr+x] = BufDep[iAdr+x];
        }
    }
}

void AffBasHaut(char* BufScr, char* BufDep)
{
    int y;
    unsigned char x;  // attention, c'est pas les pixels mais les octets qui sont utilisé ici !!!
    int iAdr; // adresse de l'écran (relatif à BufScr)

    // Affichage de l'image en partant du bas de l'image vers le haut
    for (y = 199; y>=0; y--)
    {
        // calcule de l'adresse de debut de la ligne
        iAdr = CalYAdr( y );
        
        for (x = 0; x<80; x++)
        {
            BufScr[iAdr+x] = BufDep[iAdr+x];
        }
    }
}

void AffDroiteGauche(char* BufScr, char* BufDep)
{
    unsigned char y;
    unsigned char x;  // attention, c'est pas les pixels mais les octets qui sont utilisé ici !!!
    int iAdr; // adresse de l'écran (relatif à BufScr)

    // Affichage de l'image en partant de la droite vers la gauche
    for (x = 0; x<80; x++)
    {
        for (y = 0; y<200; y++)
        {
            // Calcule de l'adresse de debut de la ligne
            iAdr = CalYAdr( y );
            BufScr[iAdr+x] = BufDep[iAdr+x];
        }
    }
}

void AffGaucheDroite(char* BufScr, char* BufDep)
{
    unsigned char y;
    char x;  // attention, c'est pas les pixels mais les octets qui sont utilisé ici !!!
    int iAdr; // adresse de l'écran (relatif à BufScr)

    // Affichage de l'image en partant de la gauche vers la droite
    for (x = 79; x>=0; x--)
    {
        for (y = 0; y<200; y++)
        {
            // Calcule de l'adresse de debut de la ligne
            iAdr = CalYAdr( y );
            BufScr[iAdr+x] = BufDep[iAdr+x];
        }
    }
}


Pour l'affichage par carré, j'ai un peut modifier la fonction qui retourne un nombre aléatoire, en plus de prendre les valeurs de poids faible du timer, j'utilise la valeur du registre R du Z80...

// gestion pour les nombres aléatoire
// En fait c'est pas vraiment des nombres aléatoire, c'est plus une suite ...
// c'est bien compliqué à expliquer ici....
// j'ai donc fait un truc simple pour le CPC
// je part du GetTime et utilise aussi la valeur du registre R du Z80....

unsigned char rStart;
// initalisation pour les nombre aléatoire
void m_randomize()
{
    // on appel la fonction GetTime_s mais on s'en fout de sont retour,
    // ce qui m'intéresse c'est la variable global char2 que cette fonction utilise...
    GetTime_s();
    
    rStart = char2;
}

char regR;
void getR()
{
__asm
    LD HL, #_regR
    LD A, R
    LD (HL), A
__endasm;    
}

// récupére un nombre "aléatoire" compris entre 0 et valmax
// il ne faut pas mettre 255 ou 0 pour valmax
unsigned char m_random(unsigned char valmax)
{
    unsigned char rRet = 255;
    
    while (rRet > valmax)
    {
        // on appel la fonction GetTime_s mais on s'en fout de sont retour,
        // ce qui m'intéresse c'est la variable global char2 que cette fonction utilise...
        getR();
        GetTime_s();
        
        rRet = (unsigned char)((int)((rStart * char2) / regR ) % valmax);
    }    
    
    return rRet;
}


Pour la partie d'affichage en carré, seul modif, on utilise une fonction memcpy optimisé pour le CPC (Z80 en fait), qui vas bien plus vite que si on utilisais le memcpy de la biblio standard du C proposé par SDCC.
La fonction memcpy optimisé :

// fonction de copie mémoire optimisé pour le CPC
// bien plus rapide que la fonction de la bibli stendard
void m_memcpy(void* dest, void* src, int lenght)
{
    __asm
    
        push     HL
        push     DE
        push     BC
        
        LD E, 4(IX)   ; (6) HL = adresse de départ
        LD D, 5(IX)   ; (6)
        
        LD L, 6(IX)   ; (6) DE = adresse de destination
        LD H, 7(IX)   ; (6)

        LD C, 8(IX)   ; (6) BC = nombre d'octets
        LD B, 9(IX)   ; (6)
        
        LDIR        ; (5) Recopie de bloc
        
        pop BC
        pop DE
        pop HL
        
    __endasm;
}


Voici donc la fonction pour l'affichage en caré :

void AffCare(char* BufScr, char* BufDep)
{
    unsigned char y;
    unsigned char x;  // attention, c'est pas les pixels mais les octets qui sont utilisé ici !!!
    int iAdr; // adresse de l'écran (relatif à BufScr)

    // pour effect carre
    unsigned char my;
    unsigned char mx;  // attention, c'est pas les pixels mais les octets qui sont utilisé ici !!!
    char ir,jr;
    
    // affichage de l'image par carré (aléatoire):
    // les blocs font 16*8, il y a donc 20 blocs (4 octets par bloc) en X et 25 bloc en Y
    // on vas faire une matrice de bloc en mémoire

    //Initialise la matrice
    for(my=0;my<25;my++)
    {
        for(mx=0;mx<20;mx++)
        {
            Bufmatrice[mx][my].x = mx<<4;
            Bufmatrice[mx][my].y = my<<3;
        }    
    }
    
    //Melange la matrice
    m_randomize();
    for(my=0;my<25;my++)
    {
        for(mx=0;mx<20;mx++)
        {
            ir=m_random(19);    //Bloc aleatoire
            jr=m_random(24);
            
            //Echange avec un autre bloc
            BufmatriceTMP.x = Bufmatrice[mx][my].x;
            Bufmatrice[mx][my].x = Bufmatrice[ir][jr].x;
            Bufmatrice[ir][jr].x = BufmatriceTMP.x;

            BufmatriceTMP.y = Bufmatrice[mx][my].y;
            Bufmatrice[mx][my].y = Bufmatrice[ir][jr].y;
            Bufmatrice[ir][jr].y = BufmatriceTMP.y;
        }    
    }

    //Affiche la matrice
    for(my=0;my<25;my++)
    {
        for(mx=0;mx<20;mx++)
        {
            for(y=0;y<8;y++)
            {
                // calcule de l'adresse de debut de la ligne
                iAdr = CalYAdr( (Bufmatrice[mx][my].y+y) );
                m_memcpy( BufScr+iAdr+(Bufmatrice[mx][my].x/4), BufDep+iAdr+(Bufmatrice[mx][my].x/4), 4 );
            }
        }
    }
}


La plus grosse modification c'est pour l'affichage avec l'effet roulo, la on utilise le m_memcpy ce qui fait gagner bien du temps, et le roulo est un peut plus haut, ce qui donne un effet un peut mieux.

void AffRoulo(char* BufScr, char* BufDep)
{
    unsigned char y;
    char x;  // attention, c'est pas les pixels mais les octets qui sont utilisé ici !!!
    unsigned int iAdr; // adresse de l'écran (relatif à BufScr)

    // pour l'effec roulo
    unsigned char yr,i;
    unsigned int iAdrd; // adresse destination
    unsigned char hroulo;  // hauteur du roulo
    
    unsigned char Roulo_t[23];

    // affichage en roulo
    hroulo = 23;
    for(i=0;i> 3 ) * 80 + ( yr & 7 ) * 0x800;
                iAdrd = ( y+i >> 3 ) * 80 + ( y+i & 7 ) * 0x800;
                
                // copie la ligne
                m_memcpy( BufScr+iAdrd, BufDep+iAdr, 80 );
            }
        }
        
        // calcule de l'adresse de debut de la ligne
        iAdr = CalYAdr( y );
        // copie la ligne
        m_memcpy( BufScr+iAdr, BufDep+iAdr, 80 );
    }
}


Voila pour les effets, ils sont pret...

On ne vas rien changer au chargement des palettes et des images, le code reste identique à celui de l'article précédent.
Par contre je vais implémenter le fait de mettre un effet aléatoirement à l'image que l'on vas afficher, cela permet de le changer à chaque fois, vous pouvez lancer le Slide Show, les images apparaitront jamais 2 fois de la même façon ! (vous pouvez quand même avoir 2 images de suite avec les même effet, mais si vous relancer le Slide, vous n'aurais pas les même effets ...)
Autre choses, pendant que l'on regarde une image, on charge la suivante, un petit gain de temps !
Sinon, juste comme cela, on appuie sur une touche pour passer à l'image suivante, mais la touche "ESC" permet de quitter directement le Slide Show.
Voici donc le main de notre programme :

void main()
{
    char* BufDep; // buffer de départ
    char* BufScr; // buffer de l'écran
    unsigned char curFile;
    unsigned char RendEffet;
    char pressChar;

    BufDep = (char*)((unsigned int)0x4000);
    BufScr = (char*)((unsigned int)0xC000);
    
    // initalisation pour les nombres aléatoite
    m_randomize();

    curFile = 0;
    
    // on charge les 1er fichiers images
    // chargement du fichier .pal
    ReadFileBin( (char*)FileP[curFile], 0x2000);
    // chargement de l'images non compresse. On la charge en 0x4000
    ReadFileBin( (char*)FileS[curFile], 0x4000);

    curFile++;
    
    while ( 1 )
    {
        // on applique la palette
        ApplyPal();

        // on fait l'effet d'afichage de façon aléatoire...
        RendEffet = m_random(7);
        
        switch( RendEffet )
        {
            case 0:
            case 1: AffHautBas(BufScr, BufDep);
                break;
            case 2: AffBasHaut(BufScr, BufDep);
                break;
            case 3: AffDroiteGauche(BufScr, BufDep);
                break;
            case 4: AffGaucheDroite(BufScr, BufDep);
                break;
            case 5: AffCare(BufScr, BufDep);
                break;
            case 6: AffRoulo(BufScr, BufDep);
                break;
        }

        // si le fichier à lire est vide, on quite la boucle...
        if ( FileP[curFile] == 0 )
        {
            // on attent quand même une touche...
            KM_WAIT_CHAR_s;
            break;
        }


        // on charge le fichier suivent ...
        // chargement du fichier .pal
        ReadFileBin( (char*)FileP[curFile], 0x2000);
        // chargement de l'images non compresse. On la charge en 0x4000
        ReadFileBin( (char*)FileS[curFile], 0x4000);
        
        curFile++;

        // une touche de pressé ....
        pressChar = GetChar();
        while ( pressChar == 0 )
            pressChar = GetChar();
        
        // esc, on quite
        if ( pressChar == -4 )
            break;
            
        pressChar = 255;    
    }

}


Et voila, on a fait notre premier Slide Show. Comme dit dans l'article précédent, les images ne sont pas compressé, donc on ne peut pas en mettre beaucoup sur une face de disquette, la on en a 9 (seulement ! ? )

Voila, comme d'hab, le tout se trouve dans se ZIP, bon SlideShow ... Diaporama ;-)

La suite ... utiliser des images compressées... mais c'est la suite ...

stephbb75

★ ANNÉE: 2013
★ AUTEUR: Stephbb75

Page précédente : Sdcc - 22 - Afficher uneImage

CPCrulez[Content Management System] v8.7-desktop/cache
Page créée en 076 millisecondes et consultée 883 fois

L'Amstrad CPC est une machine 8 bits à base d'un Z80 à 4MHz. Le premier de la gamme fut le CPC 464 en 1984, équipé d'un lecteur de cassettes intégré il se plaçait en concurrent  du Commodore C64 beaucoup plus compliqué à utiliser et plus cher. Ce fut un réel succès et sorti cette même années le CPC 664 équipé d'un lecteur de disquettes trois pouces intégré. Sa vie fut de courte durée puisqu'en 1985 il fut remplacé par le CPC 6128 qui était plus compact, plus soigné et surtout qui avait 128Ko de RAM au lieu de 64Ko.