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 - Modes HAM et double champ de jeu (dual playfield)
(Article écrit par Philippe Rivaillon et extrait d'Amiga News Tech - juin 1992)
|
|
Grâce au mode HAM (Hold And Modify), on peut utiliser simultanément les 4096 couleurs de la palette. Mais cela
ne va hélas pas sans quelques contraintes...
Tout d'abord, ce mode ne peut être utilisé qu'en basse résolution (Lowres), entrelacée ou non (et pas en Hires
comme je l'ai lu dans un certain bouquin français dont je tairai le nom). Ensuite, l'Amiga ne pouvant utiliser
que six plans de bits, il en manque six autres pour pouvoir afficher normalement 4096 couleurs (puisque 4096=21^6).
Le subterfuge est en fait très simple et se résume dans le nom de ce mode graphique : Hold And Modify,
conserver et modifier. En gros, la couleur d'un point sera déduite de celle du point précédent en conservant
la valeur de deux de ses composantes RVB et en modifiant la troisième.
Pour déclencher le mode HAM, il suffit de fixer le nombre de plans de bits à 6 et de mettre le bit 11 de
BPLCON0 à 1. Les six plans de bits seront alors "découpés" en deux groupes, le premier regroupant
les plans de bits 1 à 4 (inclus) et le second regroupant les plans de bits 5 et 6. Suivant la valeur trouvée
dans les deux derniers plans de bits, les quatre premiers seront interprétés différemment.
B6 |
B5 |
Interprétation |
0 |
0 |
Tout se passe comme en mode normal 16 couleurs : les quatre premiers plans de bits désignent le numéro
du registre de couleur à utiliser pour le point à afficher |
0 |
1 |
La couleur du point est déduite de celle du point précédent : le rouge et le vert restent
les mêmes et les quatre premiers plans de bits indiquent la valeur du bleu (il n'est plus question de registre ici) |
1 |
0 |
Même chose que précédemment sauf qu'ici c'est le rouge qui est modifié |
1 |
1 |
Idem avec le vert |
Comme on le voit, le système est assez simple. On dispose de 16 couleurs que l'on peut qualifier de
"principales" et qui servent de point de départ pour les modifications. Notons qu'au début de chaque
ligne (et quel que soit le contenu des précédentes), la couleur 0 est prise comme base : il n'y a pas
la moindre continuité de couleur entre les lignes. Le principal défaut de ce système est qu'il ne
permet pas à deux couleurs n'ayant qu'une (ou même aucune) composante en commun de se succéder, à
moins que la deuxième ne soit une couleur principale... Mais on consomme vite ces 16 couleurs principales,
si bien que le problème se pose toujours dans les images aux couleurs contrastées et variées.
Malgré ce défaut important, le mode HAM est tout de même un compromis intéressant qui permet de
réaliser quelques effets sympathiques : il suffit de regarder quelques numérisations
et images de synthèse pour s'en convaincre. Par contre, il est évident que ce mode graphique n'est pas
fait pour l'animation en temps réel, bien que l'on voit ce genre "d'exploit" dans certaines démos.
Le HAM en action
L'exemple que je vous propose est très simple : nous allons faire des rasters verticaux grâce au HAM.
Pour afficher toujours la même ligne, on utilise des modulos négatifs. La couleur 0 est utilisée comme
base (pas d'action particulière puisque cela se fait automatiquement au début de chaque ligne, comme
décrit plus haut). On effectue ensuite diverses modulations : rouleaux bleu, vert, rouge, violet, bleu
clair, jaune, puis un pseudo arc-en-ciel. Mais laissons parler le code...
*************************************
* Programme de démonstration de HAM *
* par Rivaillon Philippe *
* *
* Réalisé sur MASTERSEKA V1.80 *
*************************************
START:
; On sauve quelques trucs...
bsr SAVE_ALL
move.w #%1000011111000000,$DFF096 ; canaux DMA
; Initialise les pointeurs d'écran dans la copperlist
move.l #DATA_P1,D1
move.w D1,PLAN1+6
swap D1
move.w D1,PLAN1+2
swap D1
add.l #40,D1 ; DATA_P2
move.w D1,PLAN2+6
swap D1
move.w D1,PLAN2+2
swap D1
add.l #40,D1 ; DATA_P3
move.w D1,PLAN3+6
swap D1
move.w D1,PLAN3+2
swap D1
add.l #40,D1 ; DATA_P4
move.w D1,PLAN4+6
swap D1
move.w D1,PLAN4+2
swap D1
add.l #40,D1 ; DATA_P5
move.w D1,PLAN5+6
swap D1
move.w D1,PLAN5+2
swap D1
add.l #40,D1 ; DATA_P6
move.w D1,PLAN6+6
swap D1
move.w D1,PLAN6+2
; On lance la copperlist
move.l #COPPERLIST,$DFF080
move.w #$0,$DFF088
WAIT_MOUSE:
btst #6,$BFE001 ; Hit the rat !
bne.s WAIT_MOUSE
; On remet en place quelques trucs
bsr RESTORE_ALL
rts
SAVE_ALL:
move.b #%10000111,$BFD100
move.l 4,A6
jsr -132(A6)
move.l $6C,SAVE_VECTEUR_IRQ
move.w $dff01C,SAVE_INTENA
or.w #$C000,SAVE_INTENA
move.w $DFF002,SAVE_DMACON
or.w #$8100,SAVE_DMACON
move.w #$7FFF,$DFF09A
move.w #$7FFF,$DFF096
rts
RESTORE_ALL:
move.l SAVE_VECTEUR_IRQ,$6C
move.w #$7FFF,$DFF09A
move.w SAVE_INTENA,$DFF09A
move.w #$7FFF,$DFF096
move.w SAVE_DMACON,$DFF096
move.l 4,A6
lea NAME_GLIB,A1
moveq #0,D0
jsr -552(A6)
move.l D0,A0
move.l 38(A0),$DFF080
clr.w $DFF088
move.l D0,A1
jsr -414(A6)
jsr -138(A6)
rts
SAVE_INTENA: dc.w 0
SAVE_DMACON: dc.w 0
SAVE_VECTEUR_IRQ: dc.l 0
NAME_GLIB: dc.b 'graphics.library',0
even
; DATA EN CHIP
; Tout se passe la dedans
COPPERLIST:
dc.w $0100,$6A00 ; BPLCON0: 6 plans de bits
; + HAM + Couleur
dc.w $0102,$0000 ; BPLCON1
dc.w $0180,$0000 ; Couleur 0: les autres ne sont
; pas utilisées
dc.w $008E,$2C81 ; Ecran de 320/200
dc.w $0090,$f4C1
dc.w $0092,$0038
dc.w $0094,$00D0
dc.w $0108,-0040 ; Modulo négatifs pour toujours
dc.w $010A,-0040 ; pointer sur la même ligne.
PLAN1: ; Les plans de bits
dc.w $00E0,$0000
dc.w $00E2,$0000
PLAN2:
dc.w $00E4,$0000
dc.w $00E6,$0000
PLAN3:
dc.w $00E8,$0000
dc.w $00EA,$0000
PLAN4:
dc.w $00EC,$0000
dc.w $00EE,$0000
PLAN5:
dc.w $00F0,$0000
dc.w $00F2,$0000
PLAN6:
dc.w $00F4,$0000
dc.w $00F6,$0000
dc.w $FFFF,$FFFE
; Contenu des 6 plans de bits (1 seule ligne pour chacun)
; défini une croissance puis décroissance d'intensité
DATA_P1:
blk.l 10,$5555AAAA
DATA_P2:
blk.l 10,$3333CCCC
DATA_P3:
blk.l 10,$0F0FF0F0
DATA_P4:
blk.l 10,$00FFFF00
; défini les composantes à modifier
; Couleur 0 = base au début de chaque ligne.
DATA_P5:
dc.l $FFFFFFFF,$FFFFFFFF,$00000000
dc.l $55555555,$FFFFFFFF,$AAAAAAAA
dc.l $0000FFFF,$FFFF0000,$FFFFFFFF
dc.l $0000FFFF
DATA_P6:
dc.l $00000000,$FFFFFFFF,$FFFFFFFF
dc.l $AAAAAAAA,$55555555,$FFFFFFFF
dc.l $FFFFFFFF,$0000FFFF,$FFFF0000
dc.l $FFFFFFFF
|
Deux écrans en un
Comme l'annonce son nom, le mode double champ de jeu ("dual playfield") permet d'utiliser simultanément deux
champs de jeu (ou "structures écran") indépendants l'un de l'autre. Ils seront placés l'un sur l'autre, les points
du champ de jeu inférieur n'étant visibles que là où il n'y a aucun point dans le champ de jeu supérieur. Cela
permet de réaliser des effets du style simulateur (cabine de pilotage au premier plan et 3D au second),
ou des défilements différentiels (le paysage en arrière-plan défilant indépendamment du premier plan).
C'est dans l'indépendance des deux champs de jeu que réside l'intérêt de ce mode : dans le cas du simulateur,
il n'y a pas besoin de réafficher sans cesse la cabine de pilotage, ce qui apporte un gain de temps
intéressant. Même remarque pour les défilements différentiels : le second plan pourra être déplacé à
l'aide des pointeurs plans de bits. Bref, ce mode graphique est souvent utilisé dans les jeux.
Le mode Dual peut être déclenché en n'importe quelle résolution (Lowres et Hires, entrelacé ou non) ; il
sufit de mettre le bit 10 de BPLCON0 à 1. On a alors à notre disposition deux champs de jeu se découpant
de la manière suivante :
- Champ de jeu 1 (initialement au premier plan) : plans de bits impairs (1, 3 et 5). Trois plans de bits maximum
en Lowres et deux en Hires. Il utilise les couleurs 0 à 7 suivant le nombre de plans de bits utilisés.
- Champ de jeu 2 (initialement au second plan) : plans de bits pairs (2, 4 et 6). Trois plans de bits maximum en
Lowres et deux en Hires. Il utilise les couleurs 8 à 15 suivant le nombre de plans de bits utilisés.
La couleur 8 sert ici de couleur de fond (couleur transparente).
Notes : Encore une fois, il est possible d'utiliser jusqu'à six
plans de bits (en Lowres). La répartition des plans de bits à tel ou tel champ de jeu se fait automatiquement quand
on fixe le nombre total de plans de bits. De ce fait, certaines combinaisons sont impossibles,
par exemple trois plans pour la premier champ de jeu et un seul pour la seconde.
On le voit, les deux champs de jeu sont réellement indépendantes l'une de l'autre, puisque la première utilise
les plans impairs et la seconde les plans pairs. Chacun aura donc son propre registre de modulo
(BPLIMOD et BPL2MOD), ses propres bits de décalage dans BPLCON1 et ses propres registres de couleurs.
Par contre, elles auront forcément la même résolution graphique. Il ne faut pas trop en demander tout de même...
Comme je le disais plus haut, certaines combinaisons d'allocation de plans de bits à tel où tel champ de jeu
sont impossibles. Ce problème est en partie réglé grâce au registre suivant :
BPLCON2 $DFF104 Troisième registre de contrôles des plans de bits.
Bit |
Nom |
Fonction |
15-7 |
- |
Inutilisés |
6 |
PF2PRI |
Si ce bit est mis, le champ de jeu 2 a priorité sur le champ de jeu 1 (il sera "sur" le champ de jeu 2) |
5-3 |
PFS2P2-0 |
Code de priorité du champ de jeu 2 sur les sprites. Voir ci-dessous |
2-0 |
PFS2P2-0 |
Idem pour le champ de jeu 1 |
Le code de priorité d'un champ de jeu (PF) sur les sprites (SP) se détermine de la façon suivante :
- 000 -> PF > SP(0/1) > SP(2/3) > SP(4/5) > SP(6/7).
- 001 -> SP(0/1) > PF > SP(2/3) > SP(4/5) > SP(6/7).
- 010 -> SP(0/1) > SP(2/3) > PF > SP(4/5) > SP(6/7).
- 011 -> SP(0/1) > SP(2/3) > SP(4/5) > PF > SP(6/7).
- 100 -> SP(0/1) > SP(2/3) > SP(4/5) > SP(6/7) > PF.
(le signe ">" signifie "a priorité sur")
Normalement, vous ne devriez pas avoir le moindre problème pour mettre ce mode en oeuvre, c'est
pourquoi je ne développerai pas ici d'exemple d'application.
BPLCON0 à la loupe
Nous en avons maintenant fini avec les modes graphiques. Mais avant de clore ce chapitre,
il peut être utile de nous livrer à une petite récapitulation concernant BPLCON0, ce qui me
permettra également de parler des autres mystérieux bits qui le composent.
BPLCON0 $DFF100 Premier registre de contrôle des plans de bits.
Bit |
Nom |
Fonction |
15 |
HIRES |
Commute l'affichage en haute résolution (640 colonnes) |
14-12 |
BPU2-0 |
Ces trois bits permettent de fixer le nombre de plans de bits que l'on désire utiliser : cinq maximum
en Lowres et quatre maximum en Hires. On peut utiliser jusqu'à six plans de bits en HAM, double champ de jeu et Half-Bright |
11 |
HOMOD |
Active le mode Hold And Modify : six plans de bits, 320x200 ou 320x400 |
10 |
DBLPF |
Active le mode double champ de jeu : six plans de bits en Lowres et quatre en Hires.
L'entrelacé est accepté |
9 |
COLOR |
Active le codage du signal vidéo en RVB (il doit toujours être à 1 pour l'utilisation d'un
moniteur conventionnel) |
8 |
GAUD |
Remplace la couleur 0 (couleur de fond) par une source vidéo externe. Nécessite une interface genlock |
7 |
EHB |
Active le mode Half-Bright : six plans de bits, 320x200 et 320x400 |
6-4 |
- |
Inutilisés |
3 |
LPEN |
Permet l'utilisation d'un crayon optique (port de contrôle 1 uniquement). Grâce à ce bit,
l'Amiga saura qu'il doit effectuer une action spéciale dès qu'il recevra une impulsion venant du port de
contrôle (vérifier instantanément la position du spot à l'écran) |
2 |
LACE |
Active le mode entrelacé (double le nombre de lignes visibles). C'est le seul mode pouvant
être utilisé avec n'importe quel autre mode graphique ou n'importe quel nombre de plans de bits |
1 |
ERSY |
Active la synchronisation externe du port du moniteur |
0 |
- |
Inutilisé |
Rappel important : On ne peut agir sur un seul bit de ce registre à la fois.
Pour modifier un bit particulier, il faut obligatoirement agir sur le mot entier avec l'instruction "move".
Optimisation graphique
Je vous sens trépigner d'impatience... Ne vous emballez pas trop vite, car je vais me contenter de
vous donner ici des conseils assez généraux et d'évoquer des tactiques assez élémentaires.
J'espère tout de même que vous trouverez ici une où deux idées intéressantes.
1. La première chose à faire pour accélérer un programme est de couper le multitâche et les interruptions
(NDLR : on parle bien sûr des démos et des jeux !). Il ne faut pas utiliser les modes graphiques à
tort et à travers : inutile de déclencher le double champ de jeu, HAM ou Half-Bright si vous pouvez vous
en passer. En effet, sachez que ces modes graphiques ne sont pas gratuits en cycles. Même remarque
pour le mode de résolution Hires, qui est très gourmand en cycles machine. De plus, plus la résolution
est forte, plus la taille de l'écran à exploiter est grande : la taille des objets à transférer et
des effacements à effectuer augmentent d'autant, ainsi que la perte de temps (je ne parle même pas
du Hires entrelacé...).
2. C'est un peu la même chose avec la taille du (ou des) champ(s) de jeu : plus l'écran sera grand, plus
l'ordinateur mettra de temps à l'afficher (et ne croyez pas que c'est un détail négligeable). De
plus, si l'écran est petit, la surface à effacer sera moindre.
3. Faîtes un effaçage intelligent : effacez le moins possible (uniquement la zone où il y a animation)
ou même pas du tout (si ce que vous réaffichez efface ce qu'il y avait avant : zoom, déplacement
d'objets ne se chevauchant pas, etc.). De plus, même si cela déplaît à certains, effacez à la fois
au Blitter et au 68000 (avec movem, c'est plus rapide) si vous en avez la possibilité. N'oubliez jamais
que pendant que le Blitter travaille, le 68000 est libre de faire autre chose. Essayez donc de structurer
votre programme en conséquence (les attentes doivent être les plus courtes possible). En utilisant
une structure IFF pour les plans de bits, vous pourrez augmenter les gains de temps de ce côté.
4. Évitez l'utilisation du Blitter quand c'est possible : on peut parfois arriver au même résultat en
tripatouillant certains registres comme les pointeurs plans de bits ou autres.
5. Pour faire du 25 (ou moins) images par seconde, il faut utiliser le double tampon mémoire
afin que le résultat soit propre. Le système est très simple : on utilise un écran visible et un de
travail que l'on inverse à la fréquence voulue en modifiant les pointeurs écrans (le tout est bien
entendu synchronisé). Personnellement, je fais même parfois du triple tampon mémoire :
un écran visible, un que j'efface au Blitter et un que je "remplis" au 68000. Quand vient le moment
de faire l'inversion, l'ex-écran visible devient l'écran à effacer, l'écran effacé devient l'écran
de travail, etc. Cela est seulement valable pour les animations de courbes en 3D, feux d'artifice
ou autres merveilles ne requérant que le 68000 pour l'affichage.
6. Je vous ai donné ici quelques conseils généraux qu'il n'est pas toujours bon de prendre au pied
de la lettre : du monochrome sur un timbre-poste est ridicule. A chaque problème convient une solution, à
vous de trouver la bonne (c'est parfois la plus tordue). De plus, ce type d'optimisation n'est
qu'un complément de l'optimisation de l'algorithme utilisé et du code lui-même. Pour être rapide, tout est important.
|