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 ¼(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èteVous 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èteFantastique ! 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èteOr, 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 boucleXJe 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 boucleXLE PROGRAMME ASSEMBLEURIl 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 RETAMSLIVE n°8 » La 1ere partie : AMSLIVE n°07 - BRESEN MAD (1/2) ★ AMSTRAD CPC ★ A voir aussi sur CPCrulez , les sujets suivants pourront vous intéresser... |
CPCrulez[Content Management System] v8.7-desktop/c Page créée en 225 millisecondes et consultée 2879 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. |
|
|