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 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 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 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 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 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 stephbb75
★ AMSTRAD CPC ★ A voir aussi sur CPCrulez , les sujets suivants pourront vous intéresser... |
|
|