Effet d'interférences
Un vieil effet bien connu des plateformes Commodore repose sur le mélange de deux motifs très proches qui tournent autour de leur zone de phase. Bon, en phase, c'est moche, par contre, dès lors qu'on s'éloigne légèrement,les motifs se mélangent et avec une opération logique type XOR ou OR, on peut obtenir des résultats intéressants. Si on part d'un motif de ce genre (au plus grand des hasards), contenant 8 couleurs. Et qu'on le mélange avec un deuxième motif plus simple, contenant l'encre 0 et 8.

Notre palette serait un dégradé allant des couleurs 0 à 7 et pour les couleurs 8 à 15, le même dégradé inversé. Vous pouvez récupérer les fichiers [oeil.bin] et [oeil2.bin] avant d'assembler ce code buildsna bankset 0 org #100 run #100ld bc,#7F80+%1100 : out (c),c ld hl,palette ld bc,#7F00 setPalette out (c),c : inc c : inc b : outi : ld a,(hl) : or a : jr nz,setPalette ld hl,#4000 ld de,#8000+10 ld bc,#C000 OuLogique ld a,(de) : or (hl) : ld (bc),a : inc c : inc de : inc l : jr nz,OuLogique : inc h : inc b : jr nz,OuLogique jr $ palette defb #54,#50,#55,#57,#5F,#53,#5B,#4B defb #4B,#5B,#53,#5F,#57,#55,#50,#54,0 org #4000 : incbin 'oeil.bin' org #8000 : incbin 'oeil2.bin' En décalant de 10 octets la deuxième image (et en se moquant clairement de mal mélanger les octets sur les bords), on obtient déjà une idée de l'effet et ça a l'air plutôt pas mal non? 
Bon, on va linéariser nos écrans pour en faire des sprites (plus d'entrelacement) et on va piocher dans les données en ne partant pas toujours du même endroit. On va aussilimiter la largeur affichée et la hauteur affichée. L'idée, c'est qu'à partir d'un gros sprite de la taille d'un écran (80 octets sur 200 lignes), on affiche un sprited'une taille de 40 octets sur 160 lignes. Ça nous laisse une amplitude énorme de 40 octets en X et 40 lignes en hauteur. Dans un premier temps, un des deux sprites sera fixe. Pour l'autre, on va suivre la trajectoire d'un cercle (cosinus/sinus). Vous pouvez récupérer les fichiers [oeilFlat.bin] et [oeil2Flat.bin] avant d'assembler ce code buildsna bankset 0 org #100 run #100ld bc,#7F80+%1100 : out (c),c ld hl,palette ld bc,#7F00 setPalette out (c),c : inc c : inc b : outi : ld a,(hl) : or a : jr nz,setPalette ld ix,monCercle AfficheInterference ld hl,#4000+20 ; on se centre un peu en X ld de,(ix+0) : inc xl : inc xl ; chope le cercle et incrémente ld bc,#C000 OuLogique ld yh,160 laHauteur ld yl,40 : push bc laLigne ld a,(de) : or (hl) : ld (bc),a : inc bc : inc de : inc hl : dec yl : jr nz,laLigne ld bc,40 : add hl,bc : ex hl,de : add hl,bc : ex hl,de ; nos sprites sont +larges que la zone affichée! pop bc : ld a,8 : add b : ld b,a : jr nc,.novf ld a,80 : add c : ld c,a : ld a,#C0 : adc b : ld b,a : .novf dec yh : jr nz,laHauteur jr AfficheInterference palette defb #54,#50,#55,#57,#5F,#53,#5B,#4B defb #4B,#5B,#53,#5F,#57,#55,#50,#54,0 align 256 monCercle ang=0 repeat 128 defw #8000+20+cos(ang)*13+20*80+int(sin(ang)*19)*80 ang+=720/128 rend org #4000 : incbin 'oeilFlat.bin' org #8000 : incbin 'oeil2Flat.bin' Alors c'est pas le plus rapide jamais réalisé, mais ce code laisse la place à des tas d'optimisations : - Dérouler le code!!! - Réduire la taille de l'écran physique à 64 octets pour faire des incréments 8 bits - Augmenter la largeur physique des lignes (avec du rien) pour les aligner sur 128 octets et profiter aussi d'incréments 8 bits - Faire du code généré, exploser la mémoire pour gagner encore en vitesse 
On se lâche? Le motif bi-couleur ne contient que les valeurs 0, 1, 2 ou 3 sur tout le fichier, extrait : ... 00002fc0 00 00 00 03 03 02 00 00 01 03 03 00 00 01 03 03 |................| 00002fd0 01 03 03 00 00 01 03 03 02 00 00 03 03 03 00 00 |................| 00002fe0 01 03 03 02 00 00 01 03 03 03 00 00 00 01 03 03 |................| 00002ff0 03 03 00 00 00 00 00 00 00 00 00 00 00 00 01 03 |................| 00003000 03 03 03 00 00 00 01 03 03 03 00 00 00 03 03 03 |................| 00003010 00 00 01 03 03 02 00 00 03 03 03 00 00 01 03 03 |................| ...Si on fixe ce motif sur le fond, ça voudrait dire qu'on pourrait générer des lignes de code beaucoup plus rapides qui ressembleraient à ça : ld a,(de) : ld (bc),a : inc e : inc c ; pas de OR car OR 0 ne fait... rien! ld a,(de) : or 1 : ld (bc),a : inc e : inc cNotre registre HL étant libre, on peut l'utiliser en préchargeant H et L avec 3 et 2. Quant au 1 il serait réalisé par un INC car les données de l'autre fichier n'en contienne jamais, ça reviendrait au même que le OR 1. Notre dessin étant symétrique, on ne génèrera que les 80 lignes du haut et on exécutera en ordre inverse pour faire les 80 lignes du bas. L'autre motif aussi est symétrique, on pourra le couper en deux si nous avons besoin de place à force de s'étaler en mémoire comme des gorets. Enfin, comme on le voit sur la capture plus haut, l'effet occupe moins de la moitié de l'écran, ce qui veut dire qu'on pourrait faire un double buffer dans la même bank en redimensionnant l'écrangrâce aux registres 1 et 6 (respectivement largeur/hauteur visible), ainsi que les registres 2 et 7 pour placer l'écran au centre du moniteur Les curieux pourront toujours me demander la moulinette qui a généré le code des lignes, ça fait 20 lignes de C à tout casser. On aurait pu le faire en Basic (et même en assembleur) mais une fois de plus,je voulais démontrer que l'important est la préparation des données, et le code généré fait partie des 'données' utiles à préparer. Concentrons-nous plutôt sur ce qui va changer dans notre programme général avec nos nouvelles données [oeilFlat128.bin] et [interferenceCodgen.asm] Notez que les routines de passage de ligne et de calcul de cercle ont été adaptées pour l'écran de 40 octets ainsi que les données alignées sur 128 octets buildsna bankset 0 org #100 run #100ld sp,#100 ld bc,#7F80+%1100 : out (c),c ld hl,palette ld bc,#7F00 setPalette out (c),c : inc c : inc b : outi : ld a,(hl) : or a : jr nz,setPalette ld bc,#BC00+1 : out (c),c : ld bc,#BD00+20 : out (c),c ; largeur écran réduite ld bc,#BC00+2 : out (c),c : ld bc,#BD00+36 : out (c),c ; positionner l'écran en X ld bc,#BC00+6 : out (c),c : ld bc,#BD00+20 : out (c),c ; 160 lignes = 20 lignes de blocs de 8 lignes ld bc,#BC00+7 : out (c),c : ld bc,#BD00+28 : out (c),c ; positionner l'écran en Y ld ix,monCercle Reboucle ld de,(ix+0) : inc xl : inc xl ; chope le cercle et incrémente ld bc,#C000+20*40 call AfficherInterferences call WaitVBL : ld bc,#BC00+12 : out (c),c : ld bc,#BD31 : out (c),c : ld bc,#BC00+13 : out (c),c : ld bc,#BD90 : out (c),c ld de,(ix+0) : inc xl : inc xl ; chope le cercle et incrémente ld bc,#C000 call AfficherInterferences call WaitVBL : ld bc,#BC00+12 : out (c),c : ld bc,#BD30 : out (c),c : ld bc,#BC00+13 : out (c),c : inc b : out (c),0 jp Reboucle WaitVBL ld b,#F5 .loop in a,(c) : rra : jr nc,.loop : ret AfficherInterferences ; BC=destination écran ld iy,interference_codlist ; notre liste de routines ld a,160 .afficherLignes exa ; compteur dans A' ld hl,(iy+0) : inc yl : inc iy : push bc : jp (hl) .retour ; nos routines générées reviennent toutes ici! ; notre sprite est toujours +large et en prime aligné sur 128 octets ld a,e : add 88 : ld e,a : ld a,d : adc 0 : ld d,a pop bc : ld a,8 : add b : ld b,a : jr nc,.novf ld a,40 : add c : ld c,a : ld a,#C0 : adc b : ld b,a : .novf exa : dec a : jr nz,.afficherLignes ret palette defb #54,#50,#55,#57,#5F,#53,#5B,#4B defb #4B,#5B,#53,#5F,#57,#55,#50,#54,0 align 256 monCercle ang=0 repeat 128 defw #1000+20+cos(ang)*13+20*128+int(sin(ang)*19)*128 ; ajusté pour des données alignées sur 128 ang+=720/128 rend org #1000 : incbin 'oeilFlat128.bin' ; données graphiques alignées gonflées à 25k! org #8000 : include 'interferenceCodgen.asm' ; moins de 16k! Nettement mieux en termes de fluidité non? ;) 
Et si vous aimez les interférences originales, vous pouvez jeter un oeil à [cette production]  Avant de charger la démo, faire
poke &0128,128 : run"arpoiluRoudoudou CPCrulez[Content Management System] v8.732-desktop Page créée en 539 millisecondes et consultée 16 foisL'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. |
|