CODINGAMSLIVE ★ AMSLIVE N°08 - 3D - BRESEN MAD|2/2) ★

AMSLIVE n°08 - 3D - BRESEN MAD (2/2)Coding Amslive
Une routine assembleur, ô joie, est fournie avec cet article. Mais pour obtenir une telle routine, il faut d'abord triturer un peu l'algorithme concrétisé par le petit programme BASIC.
Je devine ce que vous vous dites : "on n'en a rien à faire des coefficients directeurs, des arrondis... On veut simplement tracer un segment". Soit, on va tracer un segment simplement.

JOINDRE LES DEUX BOUTS

Mettons qu'on veuille relier les pixels (0 ; 0) et (11 ; 2). Regardez le programme : la boucle T détermine la largeur en X, puisqu'à chaque pas de la boucle, X est incrémente. Si on appelle DX et DY les coordonnées du point destination, le coef. dir. égale DY/DX (parce que les coordonnées d'origine sont nulles). Lancez le programme avec les paramètres DX = 11 :DY = 2:M = DY/DX [...] FOR T=0 TO DX|...]:

Au fait, pour mieux vous rendre compte de ce qu'il se passe, c'est pas interdit de remplacer PLOT par LOCATE/PRINT (en arrangeant un peu X et Y) ou d'afficher l'état des variables dans la boucle.

DANS LES GRANDES LARGEURS

Le trait fait 12 pixels de large et 3 de haut. Pourtant, le segment fait à la base 11 sur 2 pixels (puisque les dimensions d'un pixel vallent celles d'une case). D'ailleurs le co, di. est 2/11 et non pas 1/4(3/12). Tout ceci parce que le segment commence et finit sur des milieux de pixels. La largeur de 11 unités est répartie sur 10 cases et 2 moitié, ce qui donne 1 2 pixels.

Si on prend le problème à l'envers, on peut dire que les pixels aux extrémités ne sont pas entièrement "traversés" par le segment. Pour que chaque pixel soit logé à la même enseigne, on fait partir le segment en bas à gauche pour le faire arriver en haut à droite :

Pour adapter le programme à cette nouvelle façon de voir, il faut calculer la largeur et la hauteur comme DX-OX+1 et DY-OY + 1 respectivement, avec (OX ; OY) coordonnées du point d'origine (ici nulles). D'où l'expression M = (DY+1)/(DX+1 ). De plus, la valeur de départ de YR n'est plus 0.5 mais 0.

La découpe est plus régulière dans la plupart des cas, mais attention, pour obtenir un segment n fois plus long suivant la même orientation, il ne faut pas multiplier DX et DY par n comme on le ferait avec l'ancienne version ou un DRAW du BASIC, mais opérer comme suit : DX=(DX+1 )*n-1 DY=(DY+1)*n-1.

Un petit blond à lunettes (tiens, qu'est-ce qu'il vient faire ici ?) remarque : "le Madram, il ferait mieux de plus dormir pendant les meetings. Parce que là, si on veut tracer une ligne horizontale, M ne va pas être égal à 0, et Y incrémentera à un moment ou un autre". Réponse : Y iVincrémentera pas tant que X ne dépassera pas DX, et c'est ce que l'on veut. En plus, cette incrémentation nous servira tout à l'heure.

ULTIMES TRANSFORMATIONS

Notre programme n'utilise plus que des opérations simples (additions, soustractions,
comparaisons). Cependant, YR n'est pas entier. Isolons son traitement :

M change rien)
YR <-0
Répète jusqu'à plus soif
YR Tant que YR > 1 fait YR<-YR-1
Fin répète

Vous conviendrez que comparer YR et 1 revient à comparer 12*YR et 12 (quand je vous disais que c'était du niveau collège). Pour que les valeurs successivement prises par YR soient multipliées par 12, on multiplie son état initial et les nombres qu'on lui ajoute par 12.

YR<-0
Répète jusqu'à ce que mort s'ensuive
YRTant que YR > 12 fait YR Fin répète

Fantastique ! En fixant la valeur initiale de

YR à -1 2 et en comparant avec 0, on obtient
un autre algo équivalent.
YR Répète ça si tu l'oses
YR Tant que YR > 0 fait YR Fin répète

Or, en assembleur, la comparaison avec 0 sera faite automatiquement car après une opération, les flags sont mis à jour. Si on atteint ou dépasse 0, Carry sera mis.

ALGO GENERAL

Autre astuce ! Pour détecter la fin du segment, il faut normalement se fier à la plus grande dimension : par exemple pour une ligne horizontale on ne va pas mesurer la hauteur ! Mais rappelez-vous qu'avec la nouvelle méthode le co. di. est choisi de façon à ce que le segment arrive en haut à droite du dernier pixel. Autrement dit, à partir de ce pixel, si on incrémente x, y va incrémenter, et vicc-versa.

On peut donc se servir de n'importe laquelle des coordonnées comme test de fin. D'ailleurs, vous pouvez tracer un segment vertical avec la dernière version du programme. Voilà l'algo, voili Olga. Entrées :

OX, OY, DX, DY (DX > OX et DY >OY)
Lar<-DX-OX+1
Hau A X <-OX
Y <-OY
BoucleX
affiche (X/Y)
A <-A+Hau
Si A < 0
alors goto MemeY
sinon A inc Y
si Y > DY alors fin
BoucleY
Si A > 0
alors affiche (X,Y)
A inc Y
si Y > DY alors fin
goto Boucle Y
MemcY
inc X
si X > DX alors fin
goto boucleX

Je vous ai placé les 2 tests de fin, mais il faut choisir l'un OU l'autre. Cet algo permet d'afficher des lignes dans le premier quartant, c'est à dire de midi à 3 heures.
Pour les autres quartants, remplacer inc X par dec X et/ou inc Y par dec Y.

L'ALGO OPTIMISE

Un être humain normal va vous conseiller de prendre un co. di. plus petit que 1 (autrement dit, Lar>Hau). On peut alors faire sauter tout BoucleY, car A ne dépassera jamais Lar, donc A-Lar est toujours plus petit que 0, pas la peine de le rctester. Pour les autres orientations (Hau>Lar), il faut inverser les rôles de x et y.

Pour ma part, je vous propose de choisir un co. di. plus grand que 1. Cette fois, on sait que A n'est jamais inférieur à -Lar. En lui ajoutant Hau qui est plus grand que Lar, il sera forcément positif. On peut lui ajouter directement Hau-Lar. La nouvelle boucle est :

BoucleX
affiche (X,Y)
A <-A+Hau-Lar
inc Y
BoucleY
Si A>0 alors affiche (X,Y)
A inc Y
goto Boucle Y
Même Y
inc X
si X > DX alors fin
goto boucleX

LE PROGRAMME ASSEMBLEUR

Il n'y a pas d'étiquettes pour que les paramètres soit facilement changes. J'ai utilisé des sous-programmes pour que la routine soit plus lisible et ne prenne pas 4 pages. De plus, ce n'est pas le plus dur à optimiser ! Il manque le calcul de l'adresse de départ. Pfff, on verra ça une prochaine fois. D'ici là, amusez-vous bien à afficher des étoiles.

DI ;On va se servir de A'
EX AF,AF'
PUSH AF
SCR_ADR LD HL,#C000 ;Adresse de départ
LD E, #88 ;Masque pixel. Pour mode 2 et 0 : #80 et #AA
DESTX LD C,110 ; Attention ! DESTX + 1
DESTY LD A, 130 ; Attention ! DESTY + 1
LD D,A ;Utilisé si DEST X plus grand
SUB C
JR C,XPLUSGR ; DESTX > DESTY
LD B,A
LD A,C ;Variable principale
NEG
LD D,C ;Pour test de fin de segment
BOUCLEX EX AF,AF' ;Les routines détruisent A
CALL AFFICHE
CALL INCY ;Y est incrémenté de toutes façons
EX AF,AF'
ADD A,B
JR NC,MEMEY
BOUCLEY EX AF,AF' ; Tiens, çq me rappelle
CALL AFFICHE ;quelque chose
CALL INCY
EX AF,AF'
SUB C
JR NQBOUCLEY
MEMEY CALL INCX
DEC D ;On a atteint DESTX + 1 ?
JR NC,BOUCLEX
JR FIN
XPLUSGR NEG ;Ce sous programme est
LD B,A ;le même que l'autre,
LD C,D ;mais le rôle des
LD A,D ;paramètres est inversé.
NEG
BOUCLEY EX AF,AF'
CALL AFFICHE
EX AF,AF'
CALL INCX ;X est incrémenté de toutes façons
ADD A,B
JR NC,MEMEX_
BOUCLEX EX AF,AF'
CALL AFFICHE
EX AF,AF'
CALL INCX
SUB C
JR NC,BOUCLEX_
MEMEX_ EX AF,AF'
CALL INCY
EX AF AF'
DEC D ;On a atteint DESTY + 1 ?
JR NC,BOUCLEY_
FIN POP AF
EX AF,AF'
EI
RET
AFFICHE LD A,(HL)
OR E ;Pour ne pas effacer le fond.
LD (HL),A
RET
INCX RRC E ;RRC permet à la fois de
RET NC ;décaler le masque correspondant
INC HL ;au pixel et de tester si on
RET ;doit passer à l'octet suivant.
INCY LD A,8
ADD A,H
JR NC,INCY_OK
LD A, #50
ADD A,L
LD L,A
LD A,#C8
ADC A,H
INCY_OK LD H,A
RET

AMSLIVE n°8

» La 1ere partie : AMSLIVE n°07 - BRESEN MAD (1/2)

★ ANNÉE: ???
★ AUTEUR: MADRAM

Page précédente : AMSLIVE n°07 - SINUS SITE , LA SUITE

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