CODINGSDCC TUT'S PAR STEPHBB75 ★ Put pixel très rapide ★

Sdcc - 12 - Put Pixel Tres RapideCoding Sdcc Tut's Par Stephbb75
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 deépart de l écran \ 2
     ; REMARQUE
     ; si vous voulez dessiner dans un autre écran 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 deépart
 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 déplacement
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 deépart de l écran \ 2
     ; REMARQUE
     ; si vous voulez dessiner dans un autre écran 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 deépart
 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 déplacement
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 deépart de l écran \ 2
     ; REMARQUE
     ; si vous voulez dessiner dans un autre écran 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 deépart
 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 déplacement
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

stephbb75

ANNÉE: 2013
★ AUTEUR: Stephbb75


Page précédente : Sdcc - 11 - Attaquer le Crtc

★ AMSTRAD CPC ★ A voir aussi sur CPCrulez , les sujets suivants pourront vous intéresser...

Lien(s):
» Coding » Sdcc - 22 - Afficher uneImage
» Coding » Sdcc - 17 - 3D - Trace Points
» Coding » Sdcc - 06 - Lire un Fichier
» Coding » Sdcc - 08 - Swap d'Ecran
» Coding » Sdcc - 24bis - Bezier
» Coding » Sdcc - 21 - 3D - Face Plaine 2
Je participe au site:

» Vous avez remarqué une erreur dans ce texte ?
» Aidez-nous à améliorer cette page : en nous contactant via le forum ou par email.

CPCrulez[Content Management System] v8.732-desktop/c
Page créée en 493 millisecondes et consultée 2680 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.