Accueil

CPC


 Dev C sur CPC :

  • le C sur CPC
  • SDCC débuter
  • fichier BAT pour compiler
  • Dessiner Sur CPC
  • Optimiser le dessin
  • Ecrire du texte
  • Lire un fichier
  • Ecrire un fichier
  • Swap d'écran
  • CLS ultra rapide
  • H line
  • Attaquer le CRTC
  • Full Overscan
  • Put pixel très rapide
  • Afficher une image
  • Slide show 1
  • Bézier
  • faire un fichier pour Bézier

  • Quelque fonctions utile

  • Animation
  • 3D
  • Raster
  • Manche a balais

    Le plan du Site

  •  
      Ici les nouvelle du site  
     
    Recherche ?
    Saissisez un mot clé

     
      Quelques chiffres
    Visiteurs:11188
    Visiteurs aujourd'hui:16
     
     
    Me contacter
    Donnez votre avis
     
    Le site de Steph : Le CPC

    Slide Show


    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 ...