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:13797
    Visiteurs aujourd'hui:5
     
     
    Me contacter
    Donnez votre avis
     
    Le site de Steph : Le CPC

    Afficher un point très rapidement


    On a vue comment afficher un pixel à l'écran avec les fonctions PutPixelMode0, PutPixelMode1 et PutPixelMode2, elles sont déjà rapide, mais on peut encore faire beaucoup plus rapide...
    Mais pour cela vous vous en doutez bien, il vas falloir passer pas de l'assembleur.
    Je vous propose donc ici 3 fonctions (une pour chaque mode du CPC) pour afficher un pixel de façon ultrarapide, j'ai récupéré les code ASM sur le site The CPC Wiki dans la partie programmation ici

    Ce code (les 3 fonctions sont presque identique, juste un changement pour le mode) permet de calculer l'adresse du point et de modifier en mémoire la valeur voulue, elle fait donc la même choses que les fonctions PutPixelModeX, mais en bien plus vite du fait qu'elle ont été faite en ASM.
    Petite particularité pour la couleur, en fait le code d'origine utilise une valeur mémoire système qui mémoire la couleur (en fait le GRAPHICS PEN) utilisé, on peut passer par cela ou utiliser une variable globale pour cette couleur, ce que j'ai fait.
    Je vous fournie donc aussi la fonction pour initialiser la couleur (attention, elle permet de choisir le No de couleur utiliser, mais de définie pas la couleur)
    Aller place au code, j'ai juste francisé les commentaire du code.

    Pour le mode 1 :
    unsigned char glob_color = 0;
    
    void SetPenM1( unsigned char color )
    {
    	switch ( color % 4 )
    	{
    		case 0:
    			glob_color = 0;
    			break;
    		case 1:
    			glob_color = 240;  // 0xF0
    			break;
    		case 2:
    			glob_color = 15;  // 0x0F
    			break;
    		case 3:
    			glob_color = 255;  // 0xFF
    			break;
    	}
    }
    
    void PutPixelFastMode1(unsigned int nX, unsigned char nY)
    {
    // Input: DE = X (0..319), HL = Y (0..199) 
    
    __asm
    
    	; on récupère les paramètres
    	LD E, 4(IX)
    	LD D, 5(IX)
    
    	LD L, 6(IX)
    	LD H,0			; juste pour être sur.
    
    FPLOT:
    	LD A, L			;A = octet bas de Y
    	AND #0x7		;isole les Bit 0..2  (00000111)
    	LD H, A			;= y MOD 8 vers H
    	XOR L			;A = Bit 3..7 of Y
    	LD L, A			;= (Y\8)*8 vers L
    	LD C, A			;stock dans C
    	LD B, #0x60		;B = &C0\2 = octet haut adresse de depart de l ecran \ 2
    					; REMARQUE
    					; si vous voulez dessiner dans un autre ecran que celui d'origine en C000 (par exemple 4000)
    					; il faut changer cette valeur.
    		
    	ADD HL, HL		;HL * 2
    	ADD HL, HL		;HL * 4
    	ADD HL, BC		;+ BC = adresse de depart
    	ADD HL, HL		;de la ligne de pixels
    		
    	LD A, E			;octet bas de X dans A
    	SRL D			;calcule X\4, Car 
    	RR E			;4 pixels par bit
    	SRL E
    	ADD HL, DE		;+ HL = adresse du pixel à modifier
    		
    	LD C, #0x88		;masque de bits pour le mode 1 (10001000)
    	AND #3			;A = X MOD 4 (00000011)
    	JR Z, NSHIFT	;-> = 0, aucun deplacement
    SHIFT:
     	SRL C			;déplacer masque de pixel
    	DEC A			;compteur de boucle
    	JR NZ,SHIFT		;-position
    		
    NSHIFT:
    	LD A,(#_glob_color); recupere le masque de couleur
    					; REMARQUE
    					; La couleur peut etre recupere en memoire a l'adresse B6A3 pour les 664 et 6128 et B338 pour le 464
    					; moi j'ai préféré passer par un variable globale.
    	XOR (HL)		;XOR octet du pixel
    	AND C			;AND masque de pixel
    	XOR (HL)		;XOR octet du pixel
    	LD (HL), A		;nouveau octet du pixel
    	
    __endasm;
    }
    

    la même choses pour le mode 2 :
    unsigned char glob_color = 0;
    
    void SetPenM2( unsigned char color )
    {
    	switch ( color % 2 )
    	{
    		case 0:
    			glob_color = 0;
    			break;
    		case 1:
    			glob_color = 255;  // 0xF0
    			break;
    	}
    }
    
    void PutPixelFastMode2(unsigned int nX, unsigned char nY)
    {
    // Input: DE = X (0..319), HL = Y (0..199) 
    
    __asm
    
    	; on récupére les paramètres
    	LD E, 4(IX)
    	LD D, 5(IX)
    
    	LD L, 6(IX)
    	LD H,0			; juste pour être sur.
    
    FPLOT:
    	LD A, L			;A = octet bas de Y
    	AND #0x7		;isole les Bit 0..2  (00000111)
    	LD H, A			;= y MOD 8 vers H
    	XOR L			;A = Bit 3..7 of Y
    	LD L, A			;= (Y\8)*8 vers L
    	LD C, A			;stock dans C
    	LD B, #0x60		;B = &C0\2 = octet haut adresse de depart de l ecran \ 2
    					; REMARQUE
    					; si vous voulez dessiner dans un autre ecran que celui d'origine en C000 (par exemple 4000)
    					; il faut changer cette valeur.
    		
    	ADD HL, HL		;HL * 2
    	ADD HL, HL		;HL * 4
    	ADD HL, BC		;+ BC = adresse de depart
    	ADD HL, HL		;de la ligne de pixels
    		
    	SRL D			;calcule X\8, Car 
    	RR E			;8 pixels par bit
    	SRL D
    	RR E
    	SRL E
    	ADD HL, DE		;+ HL = adresse du pixel à modifier
    		
    	LD C, #0x80		;masque de bits pour le mode 2 (10000000)
    	AND #7			;A = X MOD 8 (00000111)
    	JR Z, NSHIFT	;-> = 0, aucun deplacement
    SHIFT:
     	SRL C			;déplacer masque de pixel
    	DEC A			;compteur de boucle
    	JR NZ,SHIFT		;-position
    		
    NSHIFT:
    	LD A,(#_glob_color); recupere le masque de couleur
    					; REMARQUE
    					; La couleur peut etre recupere en memoire a l'adresse B6A3 pour les 664 et 6128 et B338 pour le 464
    					; moi j'ai préféré passer par un variable globale.
    	XOR (HL)		;XOR octet du pixel
    	AND C			;AND masque de pixel
    	XOR (HL)		;XOR octet du pixel
    	LD (HL), A		;nouveau octet du pixel
    	
    __endasm;
    }
    

    Et pour finir, la même pour le mode 0
    unsigned char glob_color = 0;
    
    void SetPenM0( unsigned char color )
    {
    	switch ( color % 16 )
    	{
    		case 0:
    			glob_color = 0;
    			break;
    		case 1:
    			glob_color = 192;  // 0xC0
    			break;
    		case 2:
    			glob_color = 12;  // 0x0C
    			break;
    		case 3:
    			glob_color = 204;  // 0xCC
    			break;
    		case 4:
    			glob_color = 48;  // 0x30
    			break;
    		case 5:
    			glob_color = 240;  // 0xF0
    			break;
    		case 6:
    			glob_color = 60;  // 0x3C
    			break;
    		case 7:
    			glob_color = 252;  // 0xFC
    			break;
    		case 8:
    			glob_color = 3;  // 0x03
    			break;
    		case 9:
    			glob_color = 195;  // 0xc3
    			break;
    		case 10:
    			glob_color = 15;  // 0x0F
    			break;
    		case 11:
    			glob_color = 207;  // 0xCF
    			break;
    		case 12:
    			glob_color = 51;  // 0x33
    			break;
    		case 13:
    			glob_color = 243;  // 0xF3
    			break;
    		case 14:
    			glob_color = 63;  // 0x3F
    			break;
    		case 15:
    			glob_color = 255;  // 0xFF
    			break;
    	}	
    }
    
    void PutPixelFastMode0(unsigned int nX, unsigned char nY)
    {
    // DE = X (0..159), HL = Y (0..199) 
    
    __asm
    
    	; on récupére les paramètres
    	LD E, 4(IX)
    	LD D, 5(IX)
    
    	LD L, 6(IX)
    	LD H,0			; juste pour être sur.
    
    FPLOT:
    	LD A, L			;A = octet bas de Y
    	AND #0x7		;isole les Bit 0..2  (00000111)
    	LD H, A			;= y MOD 8 vers H
    	XOR L			;A = Bit 3..7 of Y
    	LD L, A			;= (Y\8)*8 vers L
    	LD C, A			;stock dans C
    	LD B, #0x60		;B = &C0\2 = octet haut adresse de depart de l ecran \ 2
    					; REMARQUE
    					; si vous voulez dessiner dans un autre ecran que celui d'origine en C000 (par exemple 4000)
    					; il faut changer cette valeur.
    		
    	ADD HL, HL		;HL * 2
    	ADD HL, HL		;HL * 4
    	ADD HL, BC		;+ BC = adresse de depart
    	ADD HL, HL		;de la ligne de pixels
    
    	
    	SRL E			;calcule X\2, Car 2 pixels par bit
    		
    	LD C, #0xAA		;masque de bits pour le mode 0 (10101010)
    	JR Z, NSHIFT	;-> = 0, aucun deplacement
    SHIFT:
    	LD C,#0x55		;masque pour les autres pixel de droite (01010101)
    	
     	SRL C			;déplacer masque de pixel
    	DEC A			;compteur de boucle
    	JR NZ,SHIFT		;-position
    		
    NSHIFT:
    	ADD HL, DE		;+ HL = adresse du pixel à modifier
    	LD A,(#_glob_color); recupere le masque de couleur
    					; REMARQUE
    					; La couleur peut etre recupere en memoire a l'adresse B6A3 pour les 664 et 6128 et B338 pour le 464
    					; moi j'ai préféré passer par un variable globale.
    	XOR (HL)		;XOR octet du pixel
    	AND C			;AND masque de pixel
    	XOR (HL)		;XOR octet du pixel
    	LD (HL), A		;nouveau octet du pixel
    	
    __endasm;
    }
    

    Pour faire une comparaison, j'ai repris le code fait pour la fonction PutPixelMode1, il suffit de mettre la nouvelle fonction. Tout est dans le ZIP, voici le résultat ....

    Les animations sont fidèles en temps vis à vis d'un CPC
    A Gauche avec la fonction PutPixelFastMode1 et à droite avec la fonction PutPixelMode1

      


    Y'a pas photo :-)