Suivez-nous sur X

|
|
|
0,
A,
B,
C,
D,
E,
F,
G,
H,
I,
J,
K,
L,
M,
N,
O,
P,
Q,
R,
S,
T,
U,
V,
W,
X,
Y,
Z,
ALL
|
|
0,
A,
B,
C,
D,
E,
F,
G,
H,
I,
J,
K,
L,
M,
N,
O,
P,
Q,
R,
S,
T,
U,
V,
W,
X,
Y,
Z
|
|
0,
A,
B,
C,
D,
E,
F,
G,
H,
I,
J,
K,
L,
M,
N,
O,
P,
Q,
R,
S,
T,
U,
V,
W,
X,
Y,
Z
|
|
A propos d'Obligement
|
|
David Brunet
|
|
|
|
Programmation : Assembleur 68k - affichage de BOB avec le Blitter
(Article écrit par François Fleuret et extrait de Génération 4 - juin 1989)
|
|
Toujours dans le cadre de la programmation de démos, après le fameux article
sur les sprites nous allons voir comment afficher à l'écran des BOB
comme ceux de la démo de D.O.C ou bien de la XXX International Demo (qui ne sont pas des sprites matériels,
contrairement à ce que suggèrent les auteurs dans leur texte défilant).
Eh, BOB !
Avant tout, il faut bien comprendre ce qu'est un BOB. Comme son nom l'indique (BOB = Blitter OBject), le
BOB est un petit motif affiché grâce au Blitter dans la mémoire vidéo de l'Amiga. Comme les sprites,
les BOB permettent d'afficher de petits objets mobiles (tels que les démons dans la démo de D.O.C)
d'une manière assez rapide pour pouvoir en afficher un nombre conséquent. Il faut tout de même bien
différencier les sprites des BOB car ils sont fondamentalement différents d'un point de vue technique :
si les BOB sont affichés à l'écran par l'intermédiaire de la mémoire vidéo, les sprites, eux, sont
rajoutés par-dessus le plan par le processeur vidéo et sont donc totalement indépendants. Cela implique
deux choses pour les BOB :
- D'énormes contraintes, car si un BOB doit se déplacer, il faudra effacer sa précédente
position (ce qui devient réellement compliqué lorsque le BOB est sur un décor et encore plus
si plusieurs BOB se superposent).
- Une plus grande souplesse d'utilisation aussi bien au niveau de la taille que du nombre de
couleurs disponibles.
Donc, en réalité, l'affichage d'un BOB est une copie de données par le Blitter dans la mémoire vidéo
(plan de bits). La conception d'une routine de BOB revient donc à déterminer tous les paramètres de
la copie à envoyer au Blitter pour afficher le BOB que l'on veut, où l'on veut, à l'écran. Les paramètres
qui doivent être fournis sont nombreux :
- Adresses des sources A, B et C de la copie.
- Adresse de la destination D de la copie.
- Modulos (sources et destination).
- Opération logique.
- Masques des bouts sur la source A.
- Décalage de A et/ou B.
- Taille du transfert.
Le Blitter permet de transférer des données d'une adresse à une autre adresse, en faisant même, si on le
lui demande, une opération logique entre ses trois sources. Mais on en arrive vite à se demander comment
on peut afficher un BOB à l'abscisse que l'on veut étant donné que les adresses doivent être paires et
que donc le transfert se fera avec une précision horizontale de 16 points...
Pour remédier à ce problème,
les géniaux concepteurs du Blitter ont intégré un système de "barillet" qui permet de faire subir à la
source une rotation pour avoir une précision d'un pixel lors de l'affichage. Ce décalage se fait comme
dans un barillet, ce qui signifie que ce qui sort sur la droite du bloc de données revient sur
la gauche. Le problème avec ce barillet est qu'il faut avoir la place pour faire le décalage, cela oblige
donc le programmeur à prendre une image qui fait 16 points de plus horizontalement, les 16 points de droite
ne contenant pas de donnée serviront à recevoir la partie décalée qui sort à droite.
Notre routine
La routine que nous allons faire se limite à afficher des BOB 32x32 en 8 couleurs dans une image de
n'importe quelle largeur. On connaît au départ X, Y (coordonnées du BOB à afficher), l'adresse de l'image
32x32 du BOB (prise dans une grande image) et la largeur des images (plans de bits et grande image où
l'on prend l'image du BOB). Ici, l'écran est en 320x256 en 8 couleurs et l'image où se trouve le BOB
est elle aussi en 320x256 en 8 couleurs mais elle n'est pas au format IFF, il faut donc la convertir avec
le petit programme en BASIC fourni plus bas.
Notre routine va traiter séparément les trois plans de l'image (bien que cette méthode ne soit pas la meilleure
pour ce qui est de la vitesse, comme vous pourrez le lire plus bas). On va donc faire au début les initialisations
qui ne dépendent pas des adresses de départ et d'arrivée du transfert puis, pour chacun des trois transferts,
on calculera les adresses.
On cherche donc au départ les paramètres qui sont toujours les mêmes. Il s'agit de l'opération logique, des
masques de A, des modulos et du décalage. L'opération logique est un calcul booléen opéré par le Blitter
entre ses trois sources afin d'obtenir la destination. L'utilité de ce système est grande : imaginons que
l'on veuille recopier un BOB qui représente une balle sur un fond qui contient un décor. Comme l'image du BOB
n'est pas carrée, il y aura autour de lui une zone noire copiée en même temps que l'image de la balle (car
le Blitter ne fait que des transferts carrés) ce qui est relativement laid, il faut le dire. Pour éviter
cela, la fonction logique permet de tenir compte du fond. Par exemple, si la source A pointe sur l'image et la
B sur le fond, on pourra mettre D=A or B et dans ce cas le Blitter viendra rajouter, avec un OU logique, A
sur le décor. Dans notre cas, il y a trois plans de bits à traiter, il faut donc que pour chaque point du BOB,
si sa couleur est différente de 0, on la recopie dans les plans de bits. On va donc constituer ce que l'on
appelle un masque. Chaque bit de ce masque représente un point. Si ce bit est à 0, cela signifie que le BOB
est transparent à cet endroit-là (couleur 0), s'il est à 1, cela signifie que le BOB possède une couleur
différente de 0 à ce point-là.
Pour l'affichage, on utilisera les trois sources A, B, et C en faisant pointer B
sur l'image, A sur le masque et C sur le décor. On utilise A comme masque car cette source possède elle-même
des masques qui permettent de supprimer les 16 points les plus à droite du BOB afin de vider la zone où
va se faire le décalage. On fera alors :
D=(B and A) or (C and not A)
|
Le "and not" permet d'effacer le décor là où il y a un point du BOB. Le "or" copie le BOB dans le plan de bits,
et enfin le premier "and" permet de ne pas afficher les données parasites qui se trouvent transférées avec le
BOB.
Mais le Blitter ne peut utiliser l'opération sous cette forme. Il faut l'arranger avant de la programmer (pour
plus de précisions, voir le Hardware Manual page 171 ou La Bible De L'Amiga page 195) en utilisant l'algèbre
booléenne (on notera l'opération "not" en écrivant les lettres en minuscules, l'opération "and" étant représentée
comme une multiplication et le "or" comme une addition) :
D=(B*A)-F(C*a)
D=BA+Ca
D=BA(C+c)+Ca(B+b)
D=BAC+BAc+CaB+Cab
D=ABC+ABc+aBC+abC
|
Cette opération correspond à la valeur "$CA" pour les huit bits de poid faible de BLTCON0.
Comme vous pouvez vous en douter, l'image des masques s'obtient très facilement en faisant un "or"
logique entre les trois plans de l'image des BOB. Si un des bits est différent de 0 (et donc la couleur du
point correspondant différente de 0), alors le masque contiendra un 1.
Pour les modulos de la destination, il suffit de calculer la largeur en octets de l'image affichée moins
la largeur en octets de l'image transférée pour le BOB ; mais on a vu plus haut que l'on était obligé de prendre
une image plus large de 16 points afin d'avoir de la place pour faire le décalage. Comme notre BOB
a 32 points de large et que l'on transfère 16 points de plus, on transfèrera finalement 48 points soit six
octets de large. Le modulo de la destination est donc :
C'est exactement la même chose pour les sources.
Pour les masques des bouts des lignes sur A, on veut effacer les 16 points de droite (car ce sont des données
non initialisées que l'on prend pour pouvoir faire le décalage, sans savoir à quoi elles correspondent) et
garder les 16 points à gauche, donc le masque sera 0 pour la droite et $ffff pour la gauche.
Pour le décalage de B et de A (il faut aussi décaler le masque car les opérations logiques se font après le
barillet) il est toujours le même puisque l'abscisse reste identique pour les trois transferts. On obtient
assez rapidement ce décalage en faisant X and 15 (on prend les 15 bits de poids faible de X).
Enfin, pour la taille du transfert, c'est toujours 32 lignes de haut et 48 points (trois mots de large),
ce qui donne comme valeur 32x64+3 pour BLTSIZE.
Maintenant que l'on possède les paramètres constants pour les trois transferts, il reste à trouver ceux
qui sont particuliers à chacun d'entre eux : les adresses. Celles-ci s'obtiennent à partir de X, Y et l'adresse
de base des plans des bits et de l'image où se trouve l'image du BOB. Pour calculer l'adresse relative du
transfert dans les plans de bits, on fait simplement Y*40 (car on a 40 octets par ligne) + (X/8) and $fffe.
Le "X/8" fournit l'adresse dans la ligne et le "and $fffe" permet d'obtenir une adresse paire (car le Blitter
ne fait ses transferts qu'avec une précision d'un mot, pas d'un octet). Ensuite, pour chacun des trois transferts,
on ajoute aux adresses la taille d'un plan de bits (aussi bien pour la mémoire vidéo que pour l'image des BOB).
Pour faire fonctionner notre belle routine de BOB, nous allons mettre autour un petit programme qui permet
d'afficher un BOB en cliquant avec la souris, pour cela, on prend les coordonnées X et Y de la souris (voir
précédent numéro pour
des explications limpides et exhaustives) et on affiche un BOB à cet endroit-là si la touche droite est enfoncée.
Pour pouvoir utiliser cette fantastique routine dans vos propres programmes, il ne faut pas oublier de
placer également la routine PREPARE_MASQUES qui construit la table des masques des BOB. Il suffit, pour
la mettre en oeuvre, de placer les images des BOB au label BITMAP et d'appeler la routine au début du
programme. Pour la routine de BOB elle-même (DRAW_BOB), il faut lui passer plusieurs paramètres dans
les registres (voir les commentaires du listing).
Programme de conversion d'images IFF
Voici à présent le petit programme en BASIC pour préparer l'image IFF (320x256 en 8 couleurs non compactée)
qui contient le dessin du BOB (en haut à gauche 32x32). Ce programme a déjà été donné dans un précédent
numéro mais enfin bon, comme il est court et que vous n'avez peut-être pas le numéro en question, le
revoilà. Il prend une image 320x256 en 8 couleurs IFF non-compactée et la met en format plan de bits
plus simple à utiliser pour les programmeurs (les plans de bits se suivent et la palette est au format
de la palette d'Agnus).
Comme je le disais au début, pour faire un affichage de BOB parfait, il faut faire comme les programmeurs
de D.O.C, c'est-à-dire transférer tous les plans de bits en un seul transfert. C'est possible en prenant
un autre format de mémoire vidéo et pour les images des BOB et en répétant trois fois chaque masque. Le
format de la mémoire vidéo doit être le même que le format IFF : les lignes se succèdent (et non pas les
plans de bits), en faisant cela (il suffit de mettre un modulo de 80 octets pour le plan et de faire
commencer les pointeurs vidéo à des adresses décalées de 40 octets les unes par rapport aux autres) et en
faisant la même chose au moment du transfert Blitter avec les images des BOB et les masques (avec des
modulos de 0 octet pour la source et de 34 pour la destination) on peut copier les trois plans de bits
en un seul transfert. Mais il faut que les masques soit répétés trois fois puisque l'on ne peut pas
réutiliser le même masque pour les trois plans.
Ce n'est pas très clair mais je vous donnerai peut-être une routine utilisant ce système un de ces jours.
Vous pouvez maintenant rajouter des démons partout dans vos démos, bon travail.
|