Suivez-nous sur Mastodon

|
|
|
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 : Création d'une démo - chapitre 4, partie 2, le Blitter
(Article écrit par Nori - mai 2026)
|
|
Imaginez-le, philosophe auto-proclamé, écumant les plateaux télé, se comparant presque systématiquement
à Bourdieu ou Camus (la modestie, une seconde nature chez lui). J'avais l'idée de débuter mon billet
par une diatribe contre ce triste sire mais je me suis dit que cela allait plomber l'ambiance. Alors,
j'ai changé d'avis.
J'ai le souvenir précis d'un garçon précis. Un souvenir lycéen. Dans ma classe. Ses cheveux longs, roux,
sa petite taille, ses tee-shirts noirs en lettres rouge sang, écris : Slayer. Il nous devançait dans
toutes les matières, sauf une. Étrangement, il semblait détaché de cette excellence. C'est ce jour où
nous déposions nos dossiers post bac, lui, le seul, n'avait à l'esprit qu'une chose : être accepté aux
Arts Déco de Strasbourg. Je me souviens de ce sentiment, teinté d'incompréhension et d'une idée floue :
celle que ce que je vivais était important. Mais impossible de comprendre le pourquoi, le comment. Comment
pouvait-il ainsi atterrir chez les artistes ? Comment se défaire de l'idée que j'ai raté quelque chose.
Cette incapacité à rêver. Je ne suis même pas certain que, depuis, mon esprit étriqué en ait tiré le moindre
enseignement. Dommage pour moi.
Et à part ça ? C'est plutôt bon de vous retrouver.
Au fait, le cuistre en question : Raphael Enthoven.
Plan des articles
Voici les articles déjà parus de notre série sur la création d'une démo Amiga :
- Chapitre 1, partie 1, affichage de rasters à l'aide du Copper.
- Chapitre 1, partie 2, affichage de rasters à l'aide du Copper.
- Chapitre 2, partie 1, les plans de bits.
- Chapitre 2, partie 2, les plans de bits.
- Chapitre 3, partie 1, les lutins.
- Chapitre 3, partie 2, les lutins,
- Chapitre 4, partie 1, le Blitter.
De quoi parlons-nous ?
A présent, l'unique problème dont nous avons à nous inquiéter est l'affichage de BOB. Ici même, nous allons
prendre la suite de notre article sur
le Blitter. Apprendre à incruster et bouger des données graphiques dans les plans de bits. Pour ce
faire, nous devrons passer par plusieurs étapes avant d'arriver au résultat final. Il faudra décrire pêle-mêle,
la manière dont nous allons organiser les données graphiques, aborder la notion de masque, établir la
logique booléenne de la copie, effacer les BOB et enfin lancer l'opération de copie du BOB vers les plans de bits.
A la périphérie de tout ça, nous allons voir comment effectuer des calculs en virgule fixe. Un prérequis
nécessaire si vous êtes débutant (après tout, cet article vous est dédié) est de lire la partie numéro un
de cet article, comme de bien entendu.
Organisation des données
Nous avons eu l'occasion dans certains billets précédents d'utiliser le petit logiciel bien pratique,
IffMaster. Il permet de convertir un fichier graphique IFF-LBM en format brut (entre autres). Le
premier est dissocié de la machine, le second est lui directement compréhensible par les circuits de
l'Amiga, donc affichable sans conversion. Parmi ces formats de conversion, il y en a deux qui nous
intéressent : le format brut et le format brut entrelacé.
Ces deux-là ne contiennent que les données graphiques (pas d'entête, ni de segments ou palettes, rien,
nada, walou). Seule l'organisation des données les différencie. Le premier suit une organisation séquentielle :
les plans entiers se suivent. Le deuxième, a les plans entrelacés.
Les deux peuvent être utilisés. Ils ont chacun leurs avantages et leurs inconvénients. En ce qui nous concerne,
nous choisirons pour notre démo, une organisation de plans entrelacés. J'aborderai plus tard les raisons de
ce choix.
Le but est de copier des données graphiques brutes de la Source (le BOB) vers la Destination (les plans de bits).
Là où nous voyons des données graphiques affichées en deux dimensions, l'Amiga lui, lorsqu'il manipule des
BOB ou les plans de bits, n'y voit que des mots séquentiellement rangés sur une seule dimension (un tableau
ou espace à une dimension). L'animation ci-dessous nous montre une version simplifiée et imagée de ce que serait
une copie d'un BOB en quatre couleurs vers un écran lui aussi en quatre couleurs (deux plans de bits). J'ai
séparé l'animation en deux lignes. La première (1D) montre le schéma d'une copie simplifiée telle que le voit
l'Amiga et plus bas le même processus (2D) tel que le programmeur se l'imagine. Dans la ligne (1D), chaque
point vert ou rouge correspond à un mot et idem pour les segments dans la ligne (2D).
Figure 1 - copie d'un BOB vers des plans de bits rangés en format brut simple
Comme déjà dit, les segments rouges et verts correspondent aux mots du BOB copiés vers les PdB (plans de bits) lorsque
l'organisation des données graphiques est simplement séquentielle. Les plans se suivent sans se croiser.
Remarque : la représentation de la case "1D/DESTINATION" n'est pas tout à fait juste. Il manque
les sauts de ligne dans les plans de bits après chaque copie d'une ligne d'un plan du BOB. Cela est dû au manque
de place latérale dans cette case. En réalité, voilà ce à quoi cela devrait ressembler :
Passons à présent à l'organisation entrelacée ("interleaved" en anglais). Les lignes de chaque plan se
suivent donnant cette impression qu'ils sont entremêlés. Concrètement, en mémoire, nous avons à la suite,
la première ligne du premier plan, puis la première ligne du second plan, ainsi va pour tous les plans
(dans le cas de notre démo : deux plans). Vient ensuite la deuxième ligne du premier plan, puis la deuxième
ligne du deuxième plan, puis la deuxième ligne du troisième plan, etc.
Cette organisation que je viens de décrire vaut autant pour la destination (plans de bits) que pour la source (BOB).
Bien, voici ci-dessous, le même type de schéma pour une description d'un transfert Blitter en format entrelacé.
La représentation n'est pas à l'échelle et ne montre pas la copie complète du BOB vers l'écran mais elle a
l'avantage de dresser une description visuelle de la manière dont se déroule cette copie. Comme je le disais
plus haut, le principe d'entrelacement des lignes est le même qu'il vienne du BOB ou des plans de bits.
La seule différence est que l'écran est plus large que le BOB, il y a donc des espaces entre les mots copiés
(ce que montre la case "(1D)/DESTINATION".
Figure 2 - copie en format entrelacé
Conversion des données graphiques
Concrètement, passons à l'étape suivante qui convertit notre BOB (dessiné sous Deluxe Paint ou tout autre
logiciel de dessin de votre choix) en IFF-ILBM vers un format brut. La figure 3 nous montre la page options
d'IffMaster. Nous nous intéresserons plus particulièrement à la ligne "B". C'est celle qui définit le format de
sortie du fichier image (notre BOB). La ligne "Raster save" (modulo/sequence save) indique qu'il sauvegardera
les plans du BOB en format entrelacé.
J'ai chargé l'image du BOB, puis j'ai sélectionné la zone de celui-ci. La taille de la sélection est de
48x49 pixels. Un BOB en quatre couleurs dont le fichier sera de 3 mots x 49 lignes x 2 plans. Il
y aura donc pour chaque BOB 294 mots à copier par le Blitter. Si tout se passe bien, vous devriez avoir un
fichier qui fait 588 octets. Dans notre cas précis, nous n'avons pas besoin de fichier externe au source
principal, j’ai donc converti le fichier binaire en un fichier texte inclus dans le programme. Pour des
raisons que je vous ai expliquées à maintes reprises, toutes les données doivent se retrouver dans un seul
fichier texte, en l'occurrence, le source.
Figure 3 - options du logiciel IffMaster
J'oubliais, ce petit logiciel nous permet aussi de sauver la palette en format texte.
Ce que nous devrons comprendre :
- Création de masques.
- Détermination des minterms.
- Les modulos.
- Intégration du mode entrelacé.
- Les masques en mode entrelacé.
- Conversion coordonnées cartésiennes en adresses et décalage.
1. Pourquoi les masques ?
Le masque est l'ombre du BOB. Une ombre utile, invisible, indispensable. Elle fait partie intégrante du processus
de copie d'un BOB à l'écran. Le masquage consiste à utiliser un masque binaire pour effacer dans le
fond les pixels aux positions où le BOB n'est pas transparent. L'opération se fait en deux phases combinées,
simultanées (la magie du Blitter) : "ET" du fond avec le "NON" masque (masque inversé) pour "nettoyer la zone",
OU du BOB avec le décor pour le fusionner. Cette technique permet d'obtenir une transparence basique,
pourtant amplement suffisante.
Pour créer le masque du BOB de notre démo, nous aurions pu utiliser IffMaster pour les générer et les
intégrer directement dans notre source. Mais, nous allons le faire nous-mêmes. Il suffit d'écrire un petit
sous-programme et l'insérer parmi les routines d'initialisations de notre démo. Le masque sera généré à
partir du BOB lui-même par des opérations Blitter successives.
2. Détermination des minterms
Le Blitter copie des rectangles (du moins à l'écran cela se matérialise tel quel).
Si on faisait une simple copie directe du BOB à l'écran (valeur $x9F0 dans BLTCON0), nous nous retrouverions
avec une zone noire autour du BOB, effaçant ainsi une partie du décor sous la partie transparente du BOB.
Pour pallier ce problème, on pourrait effectuer une copie en appliquant entre le BOB et les plans de bits
une opération OU logique, le décor autour du BOB serait préservé (du moins à l'endroit où les pixels du
BOB sont éteints) mais partout ailleurs les couleurs du BOB seraient altérées. Il faut donc procéder différemment.
La logique de l'opération est plutôt simple en fait, il faut laisser passer les pixels du BOB non nuls et
les incruster dans le décor sans l'endommager ou l'écraser. Pour ce faire, on sélectionne les pixels non
nuls du BOB (grâce au masque) et en même temps, "on fait un trou" dans le décor grâce au masque inversé.
C'est ce que traduit cette équation : D = AB+aC.
Avec :
- a = NON masque (masque inversé)
- A = masque
- B = BOB.
- C = plans de bits
- D = plans de bits
Si vous avez parcouru le précédent article sur le Blitter, cela ne devrait pas poser de problème pour
développer l'équation. Une fois développée, vous aurez à la liste complète des minterms. Il suffira
d'additionner leurs valeurs, ce qui nous donnera la valeur à injecter dans le registre BLTCON0.
Vous devriez obtenir : $CA. C'est une valeur connue des programmeurs Amiga. Pour information, il est
possible de procéder différemment, par exemple, en utilisant un masque inversé.
En termes simples, AB ne laisse passer que les bits activés dans le masque et le BOB. aC,
quant à lui, "fait un trou" dans le plan de bits. D'ailleurs, les Rosbifs ont un joli terme imagé pour
ça : "cookie cut" (les trous dans la pâte à petits gâteaux de Noël une fois que l'on a enlevé l'emporte-pièce).
Figure 4 - copie d'un BOB sans altération du décor
3. Une histoire de modulo
Nous avons déjà abordé la notion de modulo. Pour la destination, c'est une notion simple. A chaque fois que le Blitter
aura fini d'afficher une ligne d'un plan BOB, avant de passer à la suivante, il appliquera un modulo à la destination.
Plus simplement, il additionnera la valeur modulo, à l'adresse de destination à chaque ligne affichée (Cf. figure 5). Rien de bien compliqué
et qui plus est, identique à la manière dont on utiliserait les modulos en mode non entrelacé.
Occupons-nous plutôt des modulos pour la source, à savoir le BOB. Le principe est rigoureusement identique,
auquel il faudra rajouter une subtilité mineure. Ce n'est pas en soi indispensable à connaître ou à
appliquer, cela relève plus de l'astuce, d'une volonté d'économiser de la mémoire.
Si l'on veut afficher notre BOB au pixel près horizontalement, il faudra utiliser le décalage (bits ASH0-ASH3
et BSH0-BASH3 de BLTCON 0 et 1). A cause de cela, tous les bits décalés et qui sortent du dernier mot de
chaque ligne du BOB reviennent dans le premier mot de la ligne suivante. Il faut donc que notre BOB
soit plus large d'un mot à droite. Mais ça, vous le savez déjà. Pourtant, nous n'élargirons pas le BOB (au
sens rajouter une colonne vide d'un mot à droite dans la banque graphique), par contre, nous allons tout
de même incrémenter le BLTSIZE d'une unité tout en gardant la même taille de BOB en mémoire. Logiquement,
en faisant cela, on affiche une colonne supplémentaire qui est erronée car largeur réelle et largeur du
BLTSIZE ne sont pas identiques. Un problème qui n'en devient plus un si l'on efface le masque du registre
BLTALWM. En faisant cela, la dernière colonne s'efface. Lors des décalages en barillet, les bits qui
rentrent par la gauche sont donc nuls.
Mais aussi, en faisant cela, on introduit un autre problème, comme il n'y a plus de concordance entre
la taille horizontale du BOB renseignée dans BLTSIZE et la vraie largeur du BOB, les modulos, eux aussi,
ne s'y retrouvent plus et sont décalés à chaque affichage d'une ligne d'un plan. Ce problème peut être
corrigé en adaptant les modulos du BOB. Il suffit simplement de décrémenter de 2 ce modulo. Et comme les
plans du BOB se suivent sans espace entre (=0), le modulo prendra donc la valeur 0 - 2 = -2.
L'intégrité du BOB affiché est préservée. Pour parler d'une manière imagée : le Blitter affiche une
ligne plus large d'un mot et au moment d'appliquer le modulo, il revient en arrière de deux octets = un
mot, pour se repositionner correctement pour la copie du prochain plan.
4. Intégrer le mode entrelacé
A la lumière de ce que nous venons de voir, nous sommes en mesure de déterminer la manière dont sont
calculés les modulos en mode entrelacé.
Figure 5 - modulos destination en mode entrelacé
Que nous dit la figure 5 ? On voit l'organisation entrelacée des plans de bits (les quatre rectangles bleus
qui se suivent horizontalement). Et dans chaque plan de bits, un plan du BOB (disque).
Modulo destination = (largeur plan de bits) - (largeur BOB)
|
Ceci permet au Blitter d'afficher les plans du BOB à la même position horizontale dans chaque plan de bits.
Ici, dans la figure 5, le modulo est représenté par la distance des deux lignes vertes. A part l'organisation
entrelacée des plans de bits, le reste n'est que du déjà-vu.
Bien, passons à une représentation graphique de ce concept des modulos source. Comme déjà expliqué
un peu plus haut, c'est un peu plus délicat, mais pas compliqué pour autant.
Figure 6 - modulo de la source (BOB) en mode entrelacé
Comme je le disais, le principe d'application des modulos est exactement le même que celui des plans de bits.
Si l'on observe la figure 6, les deux lignes représentent l'organisation des plans de deux BOB
identiques en apparence. Le premier (la première ligne) est un BOB de taille 48x49 (taille en pixels et
lignes), tandis que le deuxième, sur la deuxième ligne, représente un BOB de 64x49. Il y a donc un mot
de plus en largeur. Ce mot, si l'on veut afficher un BOB en abscisse au pixel près est nécessaire pour
le décalage en barillet. Mais ça, vous l'avez intégré.
Si l'on suit cette nécessité, il faudrait, lors de la conversion de IFF-ILBM vers le format brut entrelacé
sauver en plus cette colonne vide d'un mot supplémentaire à droite. Pourtant, nous ne le ferons pas, pour
une raison d'économie de mémoire. Nous utiliserons l'organisation du BOB de la première ligne. Stocké
en mémoire, nous aurons donc un BOB de trois mots (48 pixels) de large, par contre, à l’affichage, nous
aurons bel et bien un BOB de quatre mots. En faisant cela, on devrait avoir un BOB affiché avec la colonne
du plan suivant affichée. Non. Pourquoi ? À cause, ou plutôt grâce au registre masque BLTALWM ($DFF046).
Si on efface ce registre, tous les derniers mots d'une ligne d'un BOB seront effacés. Et en ce qui concerne
le modulo source = -2, nous pouvons dire qu'heureusement, les concepteurs du Blitter ont permis
les opérations signées pour les registres modulos.
Affaire réglée, comme le montre l'animation ci-dessous.
Figure 7 - description de l'effet de modulo SOURCE = -2
Le Blitter effectue bel et bien une copie de quatre mots par ligne et plan du BOB. Grâce au modulo négatif,
il se repositionne automatiquement sur le premier mot du second plan pour le début de la copie de la
ligne du deuxième plan. Et c'est ainsi de suite, jusqu'à copier tous les mots du BOB.
6. Conversion coordonnées cartésiennes en adresses et décalage
Convertir des coordonnées d'un plan cartésien vers des adresses (et décalages) d'un plan de bits nécessite
un peu de calcul. Calculs simples et qui ne sont pas sans rappeler ceux qu’on utilisait pour calculer
la position au pixel près du logo oscillant.
L'ordonnée : sachant la largeur en octets d'un plan de bits, il suffit de multiplier l'ordonnée par
ce nombre pour obtenir l'adresse relative verticale.
L'abscisse : diviser l'abscisse par 16 puis multiplier par 2 (car le Blitter ne copie que des mots,
donc à des adresses paires). Ensuite, il faut déterminer le décalage du BOB durant la copie (un décalage
compris entre 0 et 15) par soustraction de l'abscisse réelle et de la même abscisse arrondie à un
multiple de 16 inférieure.
Je ne vous ai décrit que très succinctement cette conversion pour la raison que nous n'allons pas utiliser
cette méthode. Dans le programme de la démo, pour déterminer l'adresse et le décalage du BOB,
nous utiliserons des tables précalculées. C'est plus rapide (du moins sur un Amiga 500 de base).
L'esprit d'une démo, sans battre de record, est de pondre des routines assez rapides tout de même.
Le programme
Que fait notre programme de BOB ? Il bouge plusieurs BOB identiques dans des mouvements sinusoïdaux (courbes
de Lissajous). Un effet démo de la vieille école ultra vu et revu. Facile, et donc idéal pour débuter.
Voici la structure succincte du traitement des BOB dans la boucle principale du programme :
- Synchronisation verticale avec le balayage du moniteur.
- Gestion du double tampon vidéo.
- Rétablissement du décor sous les BOB.
- Calcul des nouvelles coordonnées des BOB.
- Affichage des BOB.
- Retour étape 1.
Remarque : dans notre démo, la phase 3 est un cas particulier, elle ne rétablit pas au sens
général du terme, mais se contente d'effacer les BOB à la position précédente. Ce qui est en termes
d'exécution, plus rapide que de rétablir un décor. J'ai envie de dire, tant mieux.
Avant de nous attaquer à la boucle principale, le coeur de l'effet, commençons comme à notre habitude
par décortiquer les routines d'initialisation. Discrètes mais indispensables routines d'initialisations.
Pour que nos BOB soient visibles, il faut activer les plans de bits au début de l'écran principal.
Tout ceci dans la liste Copper, bien sûr. Construisons notre liste.
A la lisière inférieure de la fenêtre écran du logo et de l'écran principal, juste en dessous, nous
commençons par désactiver les DMA plans de bits. Cela nous permettra de laisser un peu de temps (juste
une ligne) au Copper pour préparer les données de l'écran des BOB.
; ecran principal = degrade + barres couleurs + BOB
move.l #(($2b+HL)<<24)+($df<<16)+$fffe,(a0)+ ; wait fin logo et debut rasters, Bobs = $6bdffffe
move.l #$01000200,(a0)+ ; desactive tous les plan de bits
|
Les palettes du logo et des BOB sont différentes, il nous faut donc charger de nouvelles couleurs, celles
de l'écran des BOB, dans les registres appropriés.
lea palep(pc),a1 ; table contenant les valeurs RVB de la palette
move.w #$0180,d0 ; 1er registre couleur
move.w #(1<<NBP)-1,d7 ; nb de couleurs
.1: ;
move.w d0,(a0)+ ; registre couleur
move.w (a1)+,(a0)+ ; couleur RVB
addq.w #2,d0 ; incremente registre couleur
dbf d7,.1 ; prochaine couleur
|
Il est temps de charger les pointeurs des plans de bits de l'écran des BOB dans les registres BPLxPTH BPLxPTL.
Si le logo avait le même nombre de plans de bits que la partie BOB, nous pourrions éventuellement laisser
courir les DMA plans de bits sans rien y toucher, mais ici, ce n'est pas le cas. Les adresses des plans de bits
de l'écran BOB se trouvent aux blocs mémoires "planbob0" et "planbob1".
move.l a0,scpdbbob ; sauve position des pts copper des adresses pdb de l'ecran BOB
move.l #planbob0,d0 ; adr par defaut en initialisation
move.l #WS/8,d1 ; plans de bits entrelaces
move.w #NBP-1,d7 ; nb de pdb
bsr setpdb ; injecte init pdb ds liste copper
|
Pour information, on aurait pu (dû) utiliser AllocMem() pour réserver la mémoire des plans de l'écran Bob0 mais
nous les avons définis par des blocs (méthode programmeur démo de la très vieille école) :
planbob0: blk.w (WS/16)*HS*NBP,$0000 ; reservation memoire plans de bits ecran des BOB : trame paire
planbob1: blk.w (WS/16)*HS*NBP,$0000 ; reservation memoire plans de bits ecran des BOB : trame impaire
|
Voilà, c'est presque tout, il ne reste plus qu'à figer le retard de DMA des plans de bits. Pourquoi le
faire ? Parce que le logo qui oscille latéralement plus haut modifie ce registre de retard. Si on ne
le faisait pas, l'écran des BOB plus bas tremblerait horizontalement en fonction de l'oscillation du logo au-dessus.
move.l #$01020000,(a0)+ ; RAZ retard de DMA plans de bits
|
Après le WAIT, nous nous retrouvons à la fin verticale de l'écran des BOB, nous coupons donc les DMA plans de bits
pour ne pas avoir de données parasites qui s'afficheraient sous cet écran. Ce que fait l'instruction :
move.l #$01000000,(a0)+ ; coupe DMA plans de bits
|
Nous en avons fini avec les initialisations dans la liste Copper. Passons à celles qui concernent l'effet en lui-même.
Tout d'abord, nous initialisons le compteur de BOB à effacer. Lorsque l'on lance la démo, à la toute première
exécution de la routine d'effacement des BOB, il n'y a aucun BOB à effacer et pour cause, nous ne les avons
pas encore affichés. Une valeur = -1 veut dire que le compteur de BOB est nul (le compteur est
décrémenté par une instruction DBF).
moveq #-1,d0 ; init valeurs nbr de BOB a effacer
lea nbbob0(pc),a0 ;
move.w d0,(a0) ; trame paire
move.w d0,nbbob1-nbbob0(a0) ; trame impaire
|
Vient une partie intéressante et très facile. Nous en avons longuement parlé plus haut : la création
des masques du BOB en utilisant le Blitter. C'est ce que fait cette routine :
; creation masque BOB
move.l #boulem,d1 ; adr masque BOB
move.l d1,d2 ;
lea $dff000,a6 ;
move.w #NBP-1,d7 ; nb de plans masque
.5:
move.l #boule,d0 ; adr BOB
move.l d2,d1 ;
move.w #NBP-1,d6 ; nb de plans bob
.4: ;
waitblt ;
move.l #$0dfc0000,$40(a6) ; d = 2 sources + 1 destination. fc = minterns 'ou logique'
move.l #$ffffffff,$44(a6) ; masques g/d
move.w #(LBOULE*NBP-LBOULE)/8,$62(a6) ; modulo B = masque BOB
move.l #((LBOULE*NBP-LBOULE)/8)<<16+((LBOULE*NBP-LBOULE)/8),$64(a6) ; modulos A = BOB D = masque BOB
move.l d1,$4c(a6) ; B = masque bob
move.l d0,$50(a6) ; A = bob
move.l d1,$54(a6) ; D = masque bob
move.w #(LBOULE/16)+64*HBOULE,$58(a6) ; bltsize
addq.l #LBOULE/8,d0 ; decale source d'une largeur de BOB
dbf d6,.4 ; prochain plan BOB
addq.l #LBOULE/8,d2 ; decale destination d'une largeur de BOB
dbf d7,.5 ; tt prochain plan du masque
|
Elle ne traite qu'un seul BOB mais elle est très facilement adaptable pour en traiter plusieurs.
Le compteur de plans du BOB = 2. Notre modèle de BOB est donc en quatre couleurs.
Concernant l'opération Blitter, nous utilisons deux sources et bien sûr une destination.
- A = BOB
- B = masque BOB
- D = masque BOB
Nous effectuons un OU logique entre le BOB et le masque (la zone masque est vide au départ). Nous traitons
autant de OU qu'il y a de plans, en l'occurrence deux fois. Mais nous effectuons ces opérations autant
de fois qu'il y a de plans du masque. La raison est que l'organisation des données graphiques est entrelacée.
En format brut non entrelacé, le masque n'a qu'un seul plan.
Dans le billet précédent, je vous ai déjà montré en détail comment calculer les minterms pour effectuer un
OU logique. Nous avions obtenu une valeur $FC. Valeur que l'on retrouve injectée dans BLTCON0 :
move.l #$0dfc0000,$40(a6) ; d = 2 sources + 1 destination. fc = minterns 'ou logique'
|
Remarque : le "d" dans BLTCON0 correspond au nombre de sources et destination.
Rien de bien compliqué comme vous le constatez.
Et enfin, pour conclure la partie initialisation, nous allons générer une table de sinus (indispensable pour
les mouvements en Lissajous des BOB). Cette routine n'est pas la mienne, je l'ai reçue d'un ami qui n'est
lui-même pas l'auteur. Jusqu'ici, j'avais ma propre routine qui utilisait les développements limités pour
générer la fonction sinus. Celle que je vous propose ici est plus rapide, plus précise (de l'ordre de 4 à 5%).
Le pied. En plus, c'est du code compact. Merci et bravo à cet illustre inconnu qui nous a pondu ce chef d'oeuvre.
gentrigo:
lea tbsin(pc),a0
moveq #0,d0
move.w #511+2,a1
.l:
subq.l #2,a1
move.l d0,d1
move.w d1,d2
not.w d2
mulu.w d1,d2
divu.w #75781/2,d2
lsr.w #3,d2
sub.w d2,d1
asr.l #2,d1
move.w d1,(a0)+
neg.w d1
move.w d1,(1024-2,a0)
add.l a1,d0
bne.b .l
|
Les valeurs générées sont en format 2,14. Ce qui nous fait deux bits pour la partie entière et quatorze
pour la partie décimale. Signées, bien sûr. La table contient 1024 éléments. Et la plage des valeurs est
[-16384,16384]. Pour les mouvements horizontaux, nous avons besoin d'une table de cosinus. Inutile de la
générer de A à Z. Cos() est simplement un sinus déphasé, et on peut donc le reconstruire directement à
partir de la table sinus. Ce que fait cette partie :
lea tbsin(pc),a0 ;
lea tbsin+1024*2(pc),a1 ;
move.w #1024/4-1,d7 ; pi/2 nb d'elements a copier
.0: ;
move.w (a0)+,(a1)+ ;
dbf d7,.0 ;
|
J'ai conscience que les maths, c'est chiant, vraiment chiant. Mais je vais encore vous bassiner avec une
notion importante pour notre démo : la normalisation (dans notre cas précis, ce serait plutôt une pseudo
normalisation).
Vous vous demandez peut-être pourquoi nous avons choisi ce format 2,14 plutôt qu'un 9,7 ou un 4,12 ou même
un 8,8 ? La réponse tient en un mot : la plage.
Un format en virgule fixe se note toujours sous la forme nombre de bits pour la partie entière, nombre de
bits pour la partie décimale. Plus on donne de bits à la partie entière, plus on peut représenter de
grands nombres sans conversion. Mais plus on en donne à la partie décimale, plus la précision est fine
pour les calculs en amont. Et ça, c'est le plus important.
Pour une table trigonométrique, nous savons que les valeurs de sinus et cosinus sont toujours comprises
entre -1 et +1. Avec un format 2,14, la partie entière occupe deux bits (bits 15 et 14) : cela permet
de représenter des nombres de -2 à +1,999... Ce qui couvre largement l'intervalle [-1, +1] dont
nous avons besoin. Et surtout, cela nous laisse 14 bits pour la partie décimale, donc une précision de 1/16384.
Pourquoi ne pas prendre un format 1,15, alors
? Parce que cela complexifierait certaines multiplications (à
cause du bit de signe). Le format 2,14 offre une meilleure compatibilité avec d'autres formats utilisés
dans nos calculs (comme le 14,2), nous n'aurions pas à arrondir par excès à chaque opération.
A l'inverse, un format comme 9,7 aurait gaspillé 7 bits (9-2) pour une partie entière dont nous n'avons pas
entièrement besoin, et n'aurait offert que 7 bits de précision décimale (1/128). Dans nos calculs de mouvements
où la fluidité est primordiale (moins qu’en 3D mais tout de même), chaque bit de précision compte. Donc,
pour toutes ces raisons, on préfère donner le maximum de bits à la partie décimale, et seulement le strict
nécessaire à la partie entière.
C'est pour cela que le 2,14 est le format idéal pour une table trigonométrique : il couvre juste la bonne
plage de valeurs avec la meilleure précision possible sur 16 bits.
En choisissant cela, lorsque nous multiplierons ces deux formats, il suffira d'une simple instruction
SWAP pour retomber sur la partie entière du résultat.
Une fois tous les calculs effectués, juste avant le rendu, il nous suffira de procéder à un changement
d'échelle (ici un simple ASR #4 après le SWAP) pour pouvoir afficher dans notre écran les BOB.
Idéal pour notre rendu sur écran.
Remarque : parfois, lorsque la précision n'est pas primordiale, utiliser le format 8,8 peut être
intéressant, notamment des calculs qui nécessitent beaucoup d'interpolations (linéaires ou non).
La boucle principale
Nous voilà au coeur de l'action. La boucle principale. Avant toute chose, nous allons gérer le double tampon :
eor.b #$ff,flgdf ; permute drapeau double tampon
beq.b .page2 ;
; tt page n
move.l scpdbbob(pc),a0 ; recupere position liste Copper pr pts plans de bits
move.l #planbob0,d0 ; permute page ecran BOB
move.l #WS/8,d1 ;
move.w #NBP-1,d7 ;
bsr setpdb ; change pointeurs PdB dans liste Copper
lea adrpdb(pc),a0 ;
move.l #planbob1,adrpdb ; plan de bits de travail
move.l #lseffbob0,ptlst-adrpdb(a0) ; pointe vers vars de travail pour trame n (eff+affichage)
bra.b .s ;
.page2:
; tt page n+1
move.l scpdbbob(pc),a0 ; recupere position liste Copper pr pts plans de bits
move.l #planbob1,d0 ; permutte page ecran BOB
move.l #WS/8,d1 ;
move.w #NBP-1,d7 ;
bsr setpdb ; change pointeurs PdB dans liste Copper
lea adrpdb(pc),a0 ;
move.l #planbob0,(a0) ; plan de bits de travail
move.l #lseffbob1,ptlst-adrpdb(a0) ; pointe vers vars de travail pour trame n (eff+affichage)
bra.b .s
nop ;
.s:
rts
|
L'Amiga n'est pas assez rapide (d'ailleurs aucun modèle d'Amiga ne le serait) pour afficher autant de
BOB dans un écran en cours d'affichage (Cf.
affichage_moniteur_images_amiga_pal.php).
Pour pallier ce problème, nous allons utiliser deux écrans. L'un en cours d'affichage. Celui-là, nous n'y
touchons pas. L'autre écran est caché (ou pas en cours d'affichage si vous préférez). C'est celui-ci que
nous utiliserons pour effacer et afficher les BOB à la nouvelle position. Une fois effectué tout le travail,
nous attendons la synchronisation verticale. Puis nous échangeons les deux écrans (tampons : planbob0 et planbob1),
pour travailler sur l'écran qui fut affiché à la trame précédente, tandis que le tampon sur lequel nous avions
travaillé est à présent affiché. Ainsi de suite.
Comment permuter les tampons ? Simple, il suffit de modifier les pointeurs des plans de bits dans la
liste Copper. Une fois fait, notre écran tampon sera affiché au début de la prochaine trame (tout ça sans
grand effort ni longue copie). Ce que fait précisément :
; tt page n
move.l scpdbbob(pc),a0 ; recupere position liste Copper pr pts plans de bits
move.l #planbob0,d0 ; permute page ecran BOB
move.l #WS/8,d1 ;
move.w #NBP-1,d7 ;
bsr setpdb ; change pointeurs PdB dans liste Copper
|
Ensuite, nous indiquons à notre programme quelle est l'adresse du plan sur lequel nous allons travailler :
lea adrpdb(pc),a0 ;
move.l #planbob1,adrpdb ; plan de bits de travail
|
Nous indiquons aussi quelles sont les tables de travail (coordonnées BOB, positions effacement BOB) :
move.l #lseffbob0,ptlst-adrpdb(a0) ; pointe vers vars de travail pour trame n (eff+affichage)
|
Pourquoi ? Il faut doubler les variables et tables (une pour chaque tampon). Car elles sont spécifiques à
chaque tampon (car à chaque trame, les BOB bougent et écraseraient les anciennes valeurs encore indispensables).
Ensuite, il est temps d’effacer les BOB :
; tt effacement BOBs
effbob:
lea $dff000,a6 ; base adresse registres specialises
move.l ptlst(pc),a0 ; recupere adr liste effacement des BOB du tampon memoire video cache
move.w nbbob0-lseffbob0(a0),d7 ; y'a-t-il des BOB a effacer ?
bmi.b .1 ; non -> sortie tt effacement
move.w #$8400,$96(a6) ; oui -> active priorite blitter sur 68000 durant phase d'effacement
waitblt ; renseigne registres Blitter invariables
move.l #$01000000,$40(a6) ; tous les DMA blitter coupes excepte D
move.w #(WS-(LBOULE+16))/8,$66(a6) ; modulo D
.0: ;
waitblt ; attente blitter libre
move.l (a0)+,$54(a6) ; D = plan de bits
move.w #(LBOULE+16)/16+64*(HBOULE)*NBP,$58(a6) ; bltsize
dbf d7,.0 ; prochain BOB a effacer
.1:
|
Nous utilisons le Blitter (le plus rapide pour ce genre de travail). Ici, nous n'aurons besoin que de la
destination D et rien d'autre. Gros gain en termes de DMA Blitter. D'ailleurs, on peut sortir cette
instruction de la boucle d'effacement car son contenu ne change jamais (idem pour le modulo de D) :
move.l #$01000000,$40(a6) ; tous les DMA blitter coupes sauf D
move.w #(WS-(LBOULE+16))/8,$66(a6) ; modulo D
|
Comme il n'y a qu'un canal DMA (D) activé, on peut donc activer la priorité du Blitter sur le processeur
sans craindre de trop pénaliser le 68000 :
move.w #$8400,$96(a6) ; oui -> active priorite blitter sur 68000 durant phase d'effacement
|
Ne reste que ces instructions, le coeur de l'effacement, le coeur de la boucle, limitées à leurs strict minimum :
.0: ;
waitblt ; attente blitter libre
move.l (a0)+,$54(a6) ; D = plan de bits
move.w #(LBOULE+16)/16+64*(HBOULE)*NBP,$58(a6) ; bltsize
dbf d7,.0 ; prochain BOB a effacer
|
Si vous deviez avoir des BOB de différentes tailles affichés à l'écran, il faudrait rajouter le modulo
dans cette boucle.
A présent, nous calculons les nouvelles coordonnées des BOB. Ici, rien de bien compliqué. Vous êtes
totalement libres de modifier cette section et de traiter les mouvements que vous désirez. Les index
des tables trigo sont en fait des angles.
; tt mouvement des bobs
lea tbcos(pc),a0 ; tables trigo [-16384,16384]
lea tbsin(pc),a1 ; 2,14
lea itbcos(pc),a2 ; base table index
lea tbxybob(pc),a3 ; table coordonnees bob
move.w #NBBOB-1,d7 ; nbre de bobs
.0: ;
move.w (a2),d0 ; index cos()
move.w itbsin-itbcos(a2),d1 ; index sin()
move.w (a0,d0.w),d2 ; cos()
move.w (a1,d1.w),d3 ; sin()
muls #128*($4000>>8),d2 ; Rx*cos()
muls #32*($4000>>8),d3 ; Ry*sin()
swap d2 ;
swap d3 ;
asr.w #4,d2 ;
asr.w #4,d3 ;
add.w #(WS-32)/2,d2 ; recentrage abscisse
add.w #(HS-106)/2,d3 ; recentrage ordonnee
move.w d2,(a3)+ ; stocke abscisse bob
move.w d3,(a3)+ ; stocke ordonnee bob
add.w #12,d0 ; incremente index cos()
add.w #6,d1 ; incremente index sin()
and.w #$07ff,d0 ; evite debordement index
and.w #$07ff,d1 ; idem
move.w d0,(a2) ; injecte nouvelle valeur index de cos()
move.w d1,itbsin-itbcos(a2) ; idem index de sin()
addq.w #2,a2 ; prochain index
dbf d7,.0 ; prochain bob
|
Et enfin, l'affichage des BOB. C'est là qu'il faudrait apporter un soin particulier à une programmation
optimisée. Le moindre gain, ne serait-ce de deux cycles, est important.
; tt affichage bobs
lea tbxybob(pc),a0 ; table coordonnees bob
lea tbbltcon(pc),a1 ; table des $xFCAx000
lea tbxadr(pc),a2 ; table des adresses relatives horizontales
lea tbyadr(pc),a3 ; table des adresses verticales relatives
move.l ptlst(pc),a4 ; liste effacement BOB
move.w #NBBOB,nbbob0-lseffbob0(a4) ; nb de bobs pour effacement
; tt premier element de la liste (1er BOB)
waitblt ; renseigne registres Blitter invariables
move.l #$ffff0000,$44(a6) ; masques gauche/droite
move.l #((WS-(LBOULE+16))/8)<<16+$fffe,$60(a6) ; modulos C B
move.l #$fffe<<16+((WS-(LBOULE+16))/8),$64(a6) ; modulos A D
move.w #$0400,$96(a6) ; desactive priorite blitter sur 68000 durant phase d'affichage
move.w #NBBOB-1,d7 ; nb de BOB a afficher
.1: ;
movem.w (a0)+,d0/d1 ; coordonnees bobs
add.w d1,d1 ; (x,y) bob = d0,d1
add.w d1,d1 ;
add.w d0,d0 ;
moveq #0,d4 ;
move.w (a2,d0.w),d4 ; adr. destination en X
add.w d0,d0 ;
move.l (a1,d0.w),d2 ; $xFCAx000
add.l (a3,d1.w),d4 ; adr. finale destination bob
add.l adrpdb(pc),d4 ; adr. finale bob : dest
waitblt ; attente blitter se libere
move.l d2,$40(a6) ; $xFCAx000 : x = decalage mot
move.l d4,$48(a6) ; C = pdb
move.l #boule,$4c(a6) ; B = bob
move.l #boulem,$50(a6) ; A = masque bob
move.l d4,$54(a6) ; D = pdb
move.w #((LBOULE+16)/16)+64*HBOULE*NBP,$58(a6) ; bltsize
move.l d4,(a4)+ ; sauve D pour effacement
dbf d7,.1 ;
|
Le registre A4 pointe vers la table d'effacement. Effacement qui se fera deux trames plus tard.
Nous avons plus haut, parlé de cette fameuse colonne d'un mot supplémentaire permettant d'afficher le BOB
au pixel près horizontalement. Nous ajoutons donc +1 (ici +16 pixels) au mot du BLTSIZE.
Vous aurez remarqué que l'on multiplie la valeur hauteur du BLTSIZE par NBP (nombre de plans).
Cela est dû à l'organisation spéciale du mode entrelacé (autant de plans par ligne pour sauter à la
prochaine ligne du BOB). C'est une chose qu'il est inutile de faire en mode non entrelacé.
move.w #((LBOULE+16)/16)+64*HBOULE*NBP,$58(a6) ; bltsize
|
Et nous masquons la colonne de droite avec cette instruction (0000). Quant au $ffff, il correspond à
la colonne de gauche, colonne que nous affichons.
move.l #$ffff0000,$44(a6) ; masques gauche/droite
|
Nous avions parlé aussi des problèmes de modulos de la source (problème de concordance entre le BLTSIZE
et le modulo des sources), nous avions montré qu’il faut mettre une valeur = -2 dans leurs modulos.
C'est ce que nous faisons ici pour A et B (-2 = $fffe) :
move.l #((WS-(LBOULE+16))/8)<<16+$fffe,$60(a6) ; modulos C B
move.l #$fffe<<16+((WS-(LBOULE+16))/8),$64(a6) ; modulos A D
|
Nous désactivons la priorité avant la boucle d'affichage pour ne pas pénaliser le 68000 (les quatre
canaux DMA du Blitter sont utilisés) :
move.w #$0400,$96(a6) ; desactive priorite blitter sur 68000 durant phase d'affichage
|
Nous n'avons pas besoin de calculer les valeurs de BLTCON 0 & 1 et les adresses de D (registre D4)
grâce à l'utilisation de tables préremplies :
movem.w (a0)+,d0/d1 ; coordonnees bob
add.w d1,d1 ; (x,y) bob = d0,d1
add.w d1,d1 ;
add.w d0,d0 ;
moveq #0,d4 ;
move.w (a2,d0.w),d4 ; adr. destination en X
add.w d0,d0 ;
move.l (a1,d0.w),d2 ; $xFCAx000 = BLTCON 0 et 1
add.l (a3,d1.w),d4 ; adr. finale destination bob
add.l adrpdb(pc),d4 ; adr. finale bob : dest
|
Pour ce faire, nous avons créés des tables contenant à l'avance, toutes les valeurs de BLTCON0 & 1,
indexées sur l'abscisse du BOB (registre A1). Il suffit d'utiliser un index de la sorte :
...et nous retrouvons la bonne valeur de BLTCON0 et 1. Presque aucun calcul. Cool.
Remarque : l'utilisation de tables sur des Amiga plus rapides n'est pas forcément une bonne idée
(selon le contexte).
; table des decalages Blitter (BLTCON0 & 1)
tbbltcon:
REPT WS/16
dc.l $0fca0000,$1fca1000,$2fca2000,$3fca3000
dc.l $4fca4000,$5fca5000,$6fca6000,$7fca7000
dc.l $8fca8000,$9fca9000,$afcaa000,$bfcab000
dc.l $cfcac000,$dfcad000,$efcae000,$ffcaf000
ENDR
|
Même principe pour les adresses horizontales et verticales de D (pointe sur l'écran). Pour trouver l'adresse
écran où afficher le BOB aux coordonnées (x,y), on utilise les tables suivantes :
; table adresses relatives horizontales des BOB
tbxadr:
uu SET 0
REPT WS/16
blk.w 16,uu
uu SET uu+2
ENDR
tbyadr: ; table adresses relatives verticales des BOB
vv SET 0
REPT HS
dc.l vv
vv SET vv+WS/8*NBP
ENDR
|
(ABSCISSE*2) sera l'index de la table "tbxadr". Et (ORDONNEE)*4 sera l'index de la table "tbyadr".
Ce sont toutes les deux des tables d'adresses relatives, qu'il faudra additionner pour trouver l'adresse
de l'écran finale (registre D4).
Sans oublier de sauver cette adresse D dans une liste pour pouvoir procéder à l'effacement au moment venu :
move.l d4,(a4)+ ; sauve D pour effacement
|
Mais pourquoi ?
Oui, pourquoi avoir utilisé le mode brut entrelacé ? La réponse est qu'il permet de ne faire qu’une
seule opération de copie pour un BOB, là où en mode brut, il faut deux opérations (autant d'opérations de
copies que de plans). Le fait de recharger les registres Blitter en chaque copie à une incidence sur
la vitesse de copie d'un BOB.
Voilà, nous avons fait le tour ou presque. Le reste du programme n'est pas compliqué à comprendre.
Dans notre démo, les BOB sont en quatre couleurs et relativement gros en taille (64x49 en taille Blitter).
On pourrait en mettre plus, mais il reste encore d'autres parties à ajouter, mieux vaut donc être prudent
et garder d'éventuels ajouts pour la fin. A bien y réfléchir, on aurait pu concevoir le BOB (la sphère)
en huit couleurs avec un nombre à peu près équivalent affichable. Tant pis.
A ce stade, il reste à peu près encore 30% de temps machine pour d'autres effets et ainsi rester à une
fréquence de 50 Hz. Les options pour optimiser sont légion, mais nous ne les aborderons pas. Le but
est de rester le plus simple possible sans tronquer les performances.
Lorsque j'ai tapé la première version de ce programme, j'ai utilisé une tout autre méthode. Il s'agissait
d'utiliser les interruptions du Blitter (IRQ Blitter). Dans ce cas précis (et j'insiste sur la notion de
prendre en compte la spécificité de chaque démo pour l'utilisation d'une méthode de copie ou une autre),
cette manière de faire permet d'afficher plus de BOB mais j'ai abandonné et réécrit pour une version
plus traditionnelle, plus simple, plus adaptée à la cible des lecteurs. Il faut savoir que la méthode
de l'interruption Blitter permet de simuler une file d'attente de tâches (Job queue), ce qui permet de
s'octroyer pas mal de temps machine pour le 68000 (le 68000 ne perd pas de temps à attendre que le Blitter
soit libéré pour continuer son traitement). Ainsi, le gestionnaire d'interruption devenu autonome gère
les opérations Blitter, tandis que le 68000 continue son travail de son côté, sans contrainte d'attente
(ou si peu). Par contre, c'est une méthode à double tranchant, si dans certains cas, elle fait gagner
pas mal de temps machine, dans la majorité des cas elle en fait perdre, et pas qu'un peu (à cause de la
préparation et le retour d'une interruption).
Sachez que la méthode la plus rapide pour afficher des BOB est d'utiliser le Copper (le jeu Mega Typhoon,
par exemple, utilise cette technique). Il permet d'éliminer le temps d’attente de chargement des registres
Blitter au maximum, rendant le démarrage du Blitter pour l'opération suivante beaucoup plus rapide. Par
contre, cette méthode à un désavantage, et de taille. Mélanger des instructions Copper/Blitter et des dégradés
(ou autre) peut être problématique.
Dans notre démo, l'utilisation du Blitter pour l'affichage de BOB est la plus simple.
Dans un jeu, par exemple, si les objets affichés à l'écran sont de différents tailles, couleurs,
mouvements, etc, il faudrait alors utiliser des listes de structures descriptives de ces différents
objets affichés à l'écran. Dans notre démo, la taille, le BOB, le manque d'animation, font que les
opérations sont les plus simples que l'on puisse trouver pour gérer la liste des objets.
A suivre
La prochaine fois, qu'allons-nous ajouter à notre démo ? Un défilement horizontal de texte tout en bas de
l'écran. Un indispensable dans les démos de la vieille école. L'apprentissage sera plus rapide car
toutes les notions pour programmer cet effet, vous les possédez déjà. Cool.
A bientôt, et portez-vous bien.
Le programme dans sa globalité
; **************************************************
; * *
; * DEMO OBLIGEMENT *
; * *
; **************************************************
; date: aout 2023
; auteur: NoRi
; plateforme: Amiga OCS (512Ko minimum)
; compileur/linkeur: ASm-One ou VASM + VLINK
; publication: Amiga Obligement
INCDIR "" ; recherche fichiers et donnees dans le repertoire
section programme,code_p ; hunk pour DOS, alloue memoire pour code
DEBUG = 0 ; drapeau activation des parties code pour debogage
; constantes ecran
LECRAN = 320 ; largeur ecran video affichage
HECRAN = 256 ; hauteur ecran video affichage
; donnees affichage ecran (centrage affichage)
XSTRT = 129 ; position de depart
XSTOP = XSTRT+LECRAN ; 129+320
YSTRT = $2c ;
YSTOP = YSTRT+HECRAN ;
HSTRT = XSTRT-16 ; 129-16
RES = 8 ; 8=basse resolution (4=haute resolution)
; **************************************************
; * CONSTANTES ECRAN PRINCIPAL *
; **************************************************
NBP = 2 ; nb de plan de bits partie ecran BOB
WS = LECRAN ; largeur ecran de travail = 320
HS = 208 ; hauteur ecran de travail
NBBOB = 16 ; nb de BOB maximum a traiter et afficher
LBOULE = 48 ; largeur en pixels BOB (multiple de mots)
HBOULE = 49 ; hauteur en nbre de lignes BOB
; **************************************************
; * CONSTANTES RASTERS *
; **************************************************
COLB = $0000 ; couleur bordure
NBB = 16 ; nb de barres rasters
HBR = 16 ; hauteur en pixel d'une barre
; **************************************************
; * CONSTANTES LOGO *
; **************************************************
HL = 64 ; hauteur en pixels logo
LL = 640 ; largeur en pixels logo
NBPDBL = 1 ; nb de plans de bits partie logo
WL = WS ; largeur ecran logo, DMA*16
; **************************************************
; * CONSTANTES LUTINS *
; **************************************************
NBLG = 4 ; nb de grands lutins champ etoile
NBLM = 7 ; nb de moyens lutins champ etoile
NBLP = 11 ; nb de petits lutins champ etoile
TGL = 8 ; hauteur lutins -grands
TML = 6 ; hauteur lutins -moyens
TPL = 4 ; hauteur lutins -petits
VGL = 5 ; vitesse champs de lutins -grands
VML = 2 ; vitesse champs de lutins -moyens
VPL = 1 ; vitesse champs de lutins -petits
; ***************************************************
; * MACRO DEFINITION *
; ***************************************************
; macro d'attente de la liberation du blitter
waitblt MACRO
tst.b $02(a6) ; evite bug A4000
.\@ btst #6,$02(a6) ;
bne.b .\@ ;
ENDM
debut:
; **************************************************
; * INIT GENERALES *
; **************************************************
bsr sauvesys ; pas terrible a remplacer par qqch de plus solide
lea $dff000,a6 ; adresse de base registres specialises de l'amiga
waitblt ; on s'assure que le blitter ait fini
bsr initcopvide ; genere la liste copper vide
move.w #$7fff,$96(a6) ; desactive tous les DMA
lea $dff000,a6 ; attend d'être dans la zone non affichable
move.l #300<<8,d1 ; avant de continuer
bsr vbl ;
move.w #$83e0,$96(a6) ; active DMA pdb,copper,blitter
move.w #$7fff,$9a(a6) ; coupe interruptions
bsr init ; inits generales
; **************************************************
; * *
; * BOUCLE PRINCIPALE *
; * *
; **************************************************
bouclep:
lea $dff000,a6 ; synchro verticale
move.l #280<<8,d1 ;
bsr vbl ;
move.l principal,a0 ; recupere pointeur vers routine principale en cours
jsr (a0) ; tt principal
btst.b #6,$bfe001 ; test bouton gauche souris appuye ?
bne.b bouclep ; non alors continue la boucle
exit: ; oui
bsr restauresys ; pas terrible a remplacer par qqch de plus solide
clr.l d0 ; code retour Amiga DOS
rts ; sortie vers DOS
; **************************************************
; * *
; * SOUS-ROUTINES GENERALES *
; * *
; **************************************************
; synchro verticale
; entree: d1 = position verticale raster * 256
; a6 = $dff000
; sortie:
; regs : d0/d1/d2
vbl:
move.l #$1ff00,d2 ; masque
.1: ;
move.l $04(a6),d0 ; position faisceau a electron en cours
and.l d2,d0 ;
cmp.l d1,d0 ; position atteinte ?
bne.b .1 ; non alors on continue a attendre
rts ; oui commence tt trame
sauvesys:
move.b #%10000111,$bfd100 ;
move.w $dff01c,sintena ;
or.w #$c000,sintena ;
move.w $dff002,sdmacon ;
or.w #$8100,sdmacon ;
rts ;
restauresys:
move.w #$7fff,$dff09a ;
move.w sintena,$dff09a ;
move.w #$7fff,$dff096 ;
move.w sdmacon,$dff096 ;
move.l 4,a6 ;
lea nom_glib,a1 ;
moveq #0,d0 ;
jsr -552(a6) ;
move.l d0,a0 ;
move.l 38(a0),$dff080 ;
clr.w $dff088 ;
move.l 4,a6 ;
jsr -138(a6) ;
rts
; *************************************************
; * *
; * INITIALISATIONS *
; * *
; *************************************************
init:
move.l #initpart6,principal ; init pt routine principale
; desactive eventuels lutins parasites
; lea $dff000,a6 ; on veut etre surs d'etre dans la zone
; move.l #300<<8,d1 ; du temps mort vertical avant de
; bsr vbl ; traiter la desactivation des lutins
; duplique lutins dans liste
lea ptlut(pc),a0 ; liste des lutins de reference pour copie
lea nlutc(pc),a1 ; nb de copie par lutin
lea tlut(pc),a2 ; table taille lutin
move.w #8-1,d7 ; 8 listes lutins
.c0: ;
move.l (a0)+,a3 ; pt vers lutin
move.l a3,a5 ;
move.l (a2)+,d6 ; taille d'un lutin
lea (a3,d6.w),a4 ; adr depart copie
subq.w #1,d6 ; compteur pr copie
move.w d6,d4 ;
moveq #0,d5 ;
move.b (a1)+,d5 ;
subq.w #2,d5 ; compteur pr copie
.c1: ;
move.l a5,a3 ; adr source corrigee
move.w d4,d6 ; compteur copie
.c2: ;
move.b (a3)+,(a4)+ ; duplique lutin
dbf d6,.c2 ; copie d'un lutin
dbf d5,.c1 ; copie prochaine lutin de la liste
dbf d7,.c0 ; tt prochaine liste lutins
; init ordonnees lutins champs etoiles -grandes-
lea coorlut0(pc),a0 ; ordonnees
lea lut0,a1 ; liste lutins pairs -grande taille
lea lut1,a2 ; liste lutins impairs -grande taille
lea lut2,a3 ; 2eme partie lutin
lea lut3,a4 ; 2eme partie lutin
moveq #NBLG-1,d7 ; nb-1 lutins
.0: ;
move.b (a0)+,d0 ; y
move.b d0,(a1) ;
move.b d0,(a2) ;
move.b d0,(a3) ;
move.b d0,(a4) ;
addq.b #TGL,d0 ;
move.b d0,2(a1) ; y+hauteur+1
move.b d0,2(a2) ; idem pour lutin impair
move.b d0,2(a3) ; idem 2eme partie lutin
move.b d0,2(a4) ; idem 2eme partie lutin
lea flut0-lut0(a1),a1 ; passe au prochain lutin de la liste
lea flut0-lut0(a2),a2 ; idem pour lutin impair
lea flut0-lut0(a3),a3 ; idem 2eme partie lutin
lea flut0-lut0(a4),a4 ; idem 2eme partie lutin
dbf d7,.0 ; tt prochain lutin
; init ordonnees lutins champs etoiles -moyennes-
lea coorlut1(pc),a0 ; ordonnees
lea lut4,a1 ; liste lutins
lea lut5,a2 ; 2eme partie lutin
moveq #NBLM-1,d7 ; nb-1 lutins
.1: ;
move.b (a0)+,d0 ; y
move.b d0,(a1) ;
move.b d0,(a2) ;
addq.b #TML,d0 ;
move.b d0,2(a1) ; y+hauteur+1
move.b d0,2(a2) ; idem pour lutin impair
lea flut4-lut4(a1),a1 ; passe au prochain lutin de la liste
lea flut5-lut5(a2),a2 ; idem pour lutin impair
dbf d7,.1 ; tt prochain lutin
; init ordonnees lutins champs etoiles -petites-
lea coorlut2(pc),a0 ; ordonnees
lea lut6,a1 ; liste lutins
lea lut7,a2 ; 2eme partie lutin
moveq #NBLP-1,d7 ; nb-1 lutins
.2: ;
move.b (a0)+,d0 ; y
move.b d0,(a1) ;
move.b d0,(a2) ;
addq.b #TPL,d0 ;
move.b d0,2(a1) ; y+hauteur+1
move.b d0,2(a2) ; idem pour lutin impair
lea flut6-lut6(a1),a1 ; passe au prochain lutin de la liste
lea flut7-lut7(a2),a2 ; idem pour lutin impair
dbf d7,.2 ; tt prochain lutin
; genere des abscisses pseudo aleatoires lutins
moveq #0,d0 ; genere une racine base de
lea $dff000,a6 ; la generation nbre aleatoire
move.w 6(a6),d0 ;
lsl.w #8,d0 ;
nop ;
move.b 7(a6),d0 ; racine
lea ptlut(pc),a0 ; liste des lutins
lea nlut(pc),a1 ; liste nb de nbre aleatoire a generer par lutin
lea lluti(pc),a2 ; liste taille lutins (en octets)
lea llut(pc),a3 ; liste taille entre deux lutins (en octets)
moveq #4-1,d7 ; nb-1 de paires de lutins a traiter
.3: ;
move.w d0,d1 ; copie racine
move.l (a0),a4 ; pointeur vers mot controle lutin
move.l (a2)+,d3 ; distance entre lutin pair/impair
move.l (a3)+,d2 ; taille d'un lutin
moveq #0,d6 ;
move.b (a1)+,d6 ;
subq.w #1,d6 ; nb-1 lutins de la liste
.4: ;
lsl.w #5,d1 ;
add.w d0,d1 ;
addq.w #1,d1 ; nb aleatoire
move.w d1,d0 ; nouvelle racine
move.b d1,1(a4) ; abscisse lutin
move.b d1,1(a4,d3.w) ; meme abscisse lutin impair
add.w d2,a4 ; prochain lutin liste
dbf d6,.4 ;
addq.w #8,a0 ; prochain lutin pair
dbf d7,.3 ; prochain nbre
; table trigo
bsr gentrigo ; genere table trigo
rts
nlut: dc.b NBLG,NBLG,NBLM,NBLP ; nb de nbr aleatoires a generer par liste
nlutc: dc.b NBLG,NBLG,NBLG,NBLG,NBLM,NBLM,NBLP,NBLP ; nb de nbr aleatoires a generer par liste developpee
even
lluti: dc.l lut1-lut0,lut3-lut2,lut5-lut4,lut7-lut6 ; taille lutins
llut: dc.l flut0-lut0,flut2-lut2,flut4-lut4,flut6-lut6 ; taille lutins
tlut: dc.l flut0-lut0,flut1-lut1,flut2-lut2,flut3-lut3 ; taille lutins pour duplication en init
dc.l flut4-lut4,flut5-lut5,flut6-lut6,flut7-lut7 ;
; construction liste copper
; entree:
; sortie:
; regs : d0/d1/d7/a0/a1
initcop:
lea copper0,a0 ;
move.l #$01060000,(a0)+ ; bplcon3 minimal
move.l #$01fc0000,(a0)+ ; mode 16 bits lutins/plan de bits
move.l #$00968020,(a0)+ ; active DMA lutins
; partie superieure = logo
lea pallogo(pc),a1 ; table contenant les valeurs RVB de la palette
move.w #$0180,d0 ; 1er registre couleur
move.w #(1<<NBPDBL)-1,d7 ; nb-1 couleurs / tt 2 couleurs
.c: ;
move.w d0,(a0)+ ; registre couleur
move.w (a1)+,(a0)+ ; couleur RVB
addq.w #2,d0 ; incremente registre couleur
dbf d7,.c ; tt prochaine couleur
move.l #$008e2c91,(a0)+ ; DIWSTRT / cache le 1er mot de DMA a chqe ligne
move.l #$00902cc1,(a0)+ ; DIWSTOP
move.l #$00920038,(a0)+ ; DDFSTR
move.l #$009400d0,(a0)+ ; DDTSTOP / 20 mots de DMA charges a chqe ligne
move.l a0,sptlogo ; sauve pos registre pdb ds liste copper
move.l #logo,d0 ; adr 1er pdb
move.l #(LL/8)*(HL),d1 ; taille en octets d'1 pdb => 80*64 = 5120 octets
move.w #NBPDBL-1,d7 ; nb-1 de pdb
bsr setpdb ; injecte init pdb ds liste copper
move.l a0,sretardlogo ; sauve pos dans liste copper du registre retard
addq.l #2,sretardlogo ; on se cale directement sur la valeur du registre
move.l #$01020000,(a0)+ ; delai DMA plan de bits
move.l #$01040000,(a0)+ ; priorite pdb/lutins
move.w #$0108,(a0)+ ;
move.w #(LL/8)-(WL/8),(a0)+ ; modulo plans impairs = 40
move.w #$010a,(a0)+ ;
move.w #(LL/8)-(WL/8),(a0)+ ; modulo plans pairs = 40
move.w #$0100,(a0)+ ; registre contrôle pdb
move.w #(NBPDBL*$1000)+$0200,(a0)+ ; ecran 1 plan de bits
; palette lutins
lea pall(pc),a1 ; liste palette source
move.w #$01a0,d0 ; 1er registre couleur
move.w #16-1,d7 ; nb de couleurs
.lc: ;
move.w d0,(a0)+ ; registre couleur
move.w (a1)+,(a0)+ ; couleur
addq.w #2,d0 ; incremente registre couleur
dbf d7,.lc ;
; pointeurs lutins
lea ptlut(pc),a1 ; liste des pointeurs donnees lutins
move.w #$0120,d0 ; registre pointeur
moveq #16-1,d7 ;
.lp: ;
move.l (a1)+,d1 ; pt lutin
beq.b .e ; sortie boucle si fin de liste
move.w d0,(a0)+ ; registre pointeur partie haute
swap d1 ; partie haute adresse lutin
move.w d1,(a0)+ ; partie haute adresse lutin
addq.w #2,d0 ;
move.w d0,(a0)+ ; registre pointeur partie basse
addq.w #2,d0 ;
swap d1 ; partie basse adresse lutin
move.w d1,(a0)+ ; partie basse adresse lutin
bra.b .lp ; tt prochain lutin
.e:
; degrade couleurs ds logo
move.l a0,sdeglogocop ; sauve pos. ds liste copper des couleurs du degrade logo
addq.l #6,sdeglogocop ; on se positionne directement sur la 1ere couleur
lea deglogo(pc),a1 ; table de couleurs du degrade
move.l #$2bdffffe,d0 ; 1er WAIT
move.w #HL-1,d7 ; nb-1 de lignes a traiter -> couleurs sur toute la hauteur du logo
.l1: ;
move.l d0,(a0)+ ; WAIT copper
move.w #$0182,(a0)+ ; registre couleur du logo a degrader
move.w (a1)+,(a0)+ ; couleur de la ligne
add.l #$01000000,d0 ; incremente ordonnee du WAIT
dbf d7,.l1 ; tt prochaine ligne
; ecran principal = degrade + barres couleurs + BOB
move.l #(($2b+HL)<<24)+($df<<16)+$fffe,(a0)+ ; wait fin logo et debut rasters, Bobs = $6bdffffe
move.l #$01000200,(a0)+ ; desactive tous les plans de bits
; ecran BOB
lea palep(pc),a1 ; table contenant les valeurs RVB de la palette
move.w #$0180,d0 ; 1er registre couleur
move.w #(1<<NBP)-1,d7 ; nb de couleurs
.1: ;
move.w d0,(a0)+ ; registre couleur
move.w (a1)+,(a0)+ ; couleur RVB
addq.w #2,d0 ; incremente registre couleur
dbf d7,.1 ; prochaine couleur
move.l a0,scpdbbob ; sauve position des pts copper des adresses pdb de l'ecran BOB
move.l #planbob0,d0 ; adr par defaut en initialisation
move.l #WS/8,d1 ; plans de bits entrelaces
move.w #NBP-1,d7 ; nb de pdb
bsr setpdb ; injecte init pdb ds liste copper
move.l #(($2b+HL+1)<<24)+($df<<16)+$fffe,(a0)+ ; wait fin logo et debut rasters
move.l #($0100<<16)+(NBP<<12)+($0200),(a0)+ ; active les plans de bits
move.l #$01020000,(a0)+ ; RAZ retard de DMA plans de bits
;NBP = 2 ; nb de plan de bits partie ecran BOB
;WS = LECRAN ; largeur ecran de travail = 320
;HS = 208 ; hauteur ecran de travail
; barres horizontales couleurs
move.l a0,sdegcop ; sauve pos. ds liste copper du degrade de couleurs
lea degrade(pc),a1 ;
move.l #$6ce3fffe,d0 ; partie droite ligne
move.l #$6c07fffe,d1 ; partie gauche ligne
move.w #HS-HL-1,d7 ; nb-1 de lignes a traiter
.l2: ;
move.l d1,(a0)+ ; wait pour bordure gauche
move.w #$0180,(a0)+ ; couleur de fond degradee
move.w (a1)+,(a0)+ ; couleur de la ligne
move.l d0,(a0)+ ; wait pour bordure droite
move.w #$0180,(a0)+ ;
move.w #COLB,(a0)+ ; couleur bordure (noire)
add.l #$01000000,d0 ;
add.l #$01000000,d1 ;
dbf d7,.l2 ; prochaine ligne
move.l d1,(a0)+ ; dernier WAIT du degrade
move.l #$01000000,(a0)+ ; coupe DMA plans de bits
move.l #$01800000,(a0)+ ; fin de degrade en noir
; partie ecran texte defilant
move.l #$fffffffe,(a0)+ ; fin liste copper
rts
; active un ecran noir
initcopvide:
lea copperv,a0 ; liste copper minimaliste
move.l #$01000200,(a0)+ ; aucun plans de bits
move.l #$01800000,(a0)+ ; fond noir
move.l #$fffffffe,(a0)+ ; fin liste copper
move.l #copperv,$dff080 ;
clr.w $dff088 ; active liste copper noire
rts
; injecte pts pdbs dans liste copper
; entree: d0= adr 1er pdb
; d1= taille en octets d'1 pdb
; a0= pos liste copper
; d7= nb-1 de pdb
; sortie:
; Regs : d0/d1/d2/d7/a0
setpdb:
move.w #$00e0,d2 ; premier registre pt pdb
.l: ;
move.w d2,(a0) ; registre pt pdb poids fort
move.w d0,6(a0) ; adresse pdb poids faible
swap d0 ;
addq.w #2,d2 ;
move.w d2,4(a0) ; registre pt pdb poids faible
move.w d0,2(a0) ; adresse pdb poids fort
swap d0 ;
add.l d1,d0 ;
addq.w #2,d2 ; prochain registre pt pdb
addq.l #8,a0 ; prochaine position dans liste copper
dbf d7,.l ; tt prochain plan
rts
; **************************************************
; * *
; * VARS/TABLES *
; * *
; **************************************************
principal: dc.l 0 ; pt vers sous routine principale
sdegcop: dc.l 0 ; pt vers degrade couleurs ds liste copper
degrade:
dc.w $000,$000,$000,$000,$000,$000,$001,$000 ; couleurs du degrade
dc.w $001,$001,$101,$001,$101,$101,$111,$101
dc.w $111,$111,$111,$111,$112,$111,$112,$112
dc.w $112,$112,$112,$112,$112,$112,$112,$112
dc.w $112,$112,$112,$112,$112,$112,$213,$212
dc.w $213,$213,$213,$213,$213,$213,$213,$213
dc.w $213,$213,$213,$213,$213,$213,$213,$213
dc.w $213,$213,$213,$213,$213,$213,$213,$213
dc.w $213,$213,$223,$213,$223,$223,$223,$223
dc.w $223,$223,$223,$223,$223,$223,$223,$223
dc.w $223,$223,$223,$223,$223,$223,$223,$223
dc.w $223,$223,$223,$223,$223,$223,$223,$223
dc.w $223,$223,$223,$223,$223,$223,$223,$223
dc.w $223,$223,$223,$223,$223,$223,$223,$223
dc.w $223,$223,$223,$223,$223,$223,$223,$223
dc.w $223,$223,$223,$223,$223,$223,$223,$223
dc.w $223,$223,$223,$223,$233,$233,$233,$233
dc.w $233,$233,$233,$233,$233,$233,$233,$233
dc.w $233,$233,$233,$233,$233,$233,$243,$233
dc.w $243,$243,$243,$243,$243,$243,$243,$243
dc.w $244,$244,$244,$244,$244,$244,$244,$244
dc.w $244,$244,$244,$244,$244,$244,$244,$244
dc.w $244,$244,$244,$244,$244,$244,$254,$244
dc.w $254,$254,$254,$254,$254,$254,$254,$254
dc.w $254,$254,$253,$254,$253,$253,$253,$253
dc.w $353,$353,$353,$353,$353,$353,$353,$353
dc.w $353,$353,$452,$353,$452,$452,$452,$452
dc.w $452,$452,$452,$452,$452,$452,$452,$452
dc.w $552,$552,$552,$552,$552,$552,$551,$552
dc.w $561,$561,$561,$561,$561,$561,$561,$561
dc.w $561,$561,$561,$561,$661,$561,$661,$661
dc.w $661,$661,$661,$661,$661,$661,$661,$661
itbsinr: blk.w NBB,0 ; indexes table mvt barres rasters
tbsinr: dc.b 128,126,124,123,121,120,118,117,115,113,112 ; table des ordonnees barres rasters
dc.b 110,109,107,106,104,103,101,100,99,97,96,94
dc.b 93,92,91,89,88,87,86,84,83,82,81,80,79,78
dc.b 77,76,75,74,73,72,72,71,70,70,69,68,68,67
dc.b 67,66,66,65,65,65,64,64,64,64,64,64,64,64
dc.b 64,64,64,64,64,64,65,65,65,66,66,66,67,67
dc.b 68,69,69,70,71,71,72,73,74,75,75,76,77,78
dc.b 79,80,82,83,84,85,86,87,89,90,91,92,94,95
dc.b 97,98,99,101,102,104,105,107,108,110,111
dc.b 113,114,116,117,119,120,122,124,125,127
dc.b 128,130,131,133,135,136,138,139,141,142
dc.b 144,145,147,148,150,151,153,154,156,157
dc.b 158,160,161,163,164,165,166,168,169,170
dc.b 171,172,173,175,176,177,178,179,180,180
dc.b 181,182,183,184,184,185,186,186,187,188
dc.b 188,189,189,189,190,190,190,191,191,191
dc.b 191,191,191,191,191,191,191,191,191,191
dc.b 191,190,190,190,189,189,188,188,187,187
dc.b 186,185,185,184,183,183,182,181,180,179
dc.b 178,177,176,175,174,173,172,171,169,168
dc.b 167,166,164,163,162,161,159,158,156,155
dc.b 154,152,151,149,148,146,145,143,142,140
dc.b 138,137,135,134,132,131,129,128
barre: dc.w $0518,$0627,$0746,$0865 ; couleurs barre raster de 16 lignes de haut
dc.w $0A84,$0B93,$0CB2,$0DD1
dc.w $0DD1,$0CB2,$0B93,$0A84
dc.w $0865,$0746,$0627,$0518
itbmvtlogo: dc.w 0 ; index table mvt logo
tbmvtlogo:
dc.w 0,-3,-7,-11,-15,-19,-23,-27,-31,-35,-39,-42,-46 ; table des abscisses du mvt logo
dc.w -50,-54,-57,-61,-65,-68,-72,-75,-79,-82,-85,-89
dc.w -92,-95,-98,-101,-104,-107,-110,-113,-116,-118
dc.w -121,-124,-126,-128,-131,-133,-135,-137,-139
dc.w -141,-143,-144,-146,-148,-149,-150,-152,-153
dc.w -154,-155,-156,-157,-157,-158,-158,-159,-159
dc.w -159,-159,-159,-159,-159,-159,-159,-158,-158
dc.w -157,-156,-155,-154,-153,-152,-151,-150,-148
dc.w -147,-145,-144,-142,-140,-138,-136,-134,-132
dc.w -130,-127,-125,-122,-120,-117,-114,-112,-109
dc.w -106,-103,-100,-97,-94,-90,-87,-84,-80,-77,-73
dc.w -70,-66,-63,-59,-55,-52,-48,-44,-40,-37,-33
dc.w -29,-25,-21,-17,-13,-9,-5,-1,1,5,9,13,17,21
dc.w 25,29,33,37,40,44,48,52,55,59,63,66,70,73,77
dc.w 80,84,87,90,94,97,100,103,106,109,112,114,117
dc.w 120,122,125,127,130,132,134,136,138,140,142,144
dc.w 145,147,148,150,151,152,153,154,155,156,157
dc.w 158,158,159,159,159,159,159,159,159,159,159
dc.w 159,158,158,157,157,156,155,154,153,152,150
dc.w 149,148,146,144,143,141,139,137,135,133,131
dc.w 128,126,124,121,118,116,113,110,107,104,101
dc.w 98,95,92,89,85,82,79,75,72,68,65,61,57,54,50
dc.w 46,42,39,35,31,27,23,19,15,11,7,3
sretardlogo: dc.l 0 ; pt vers registre retard logo ds liste copper
sptlogo: dc.l 0 ; pt vers registres pt pdb logo ds liste copper
pallogo: dc.w $0000,$0ffe ; palette logo
sdeglogocop: dc.l 0 ; sauve pt vers degrade couleurs logo ds liste copper
deglogo:
dc.w $FFF,$FFF,$FFF,$EFF,$EFF,$EFF,$EFF,$DFF ; liste couleurs du degrade de couleurs logo
dc.w $DFF,$DEF,$CEF,$CEF,$CEF,$CEF,$BEF,$BEF
dc.w $BEF,$AEF,$AEF,$ADF,$ADF,$9DF,$9DF,$9DF
dc.w $8DF,$8DF,$8DF,$8DF,$7CF,$7CF,$7CF,$6CF
dc.w $6CF,$6CF,$6CF,$5CF,$5CF,$5CF,$5CF,$5CE
dc.w $5CE,$5CD,$6CD,$6CD,$6CC,$6CC,$6CB,$7CB
dc.w $7CA,$7BA,$7BA,$7B9,$8B9,$8B8,$8B8,$8B7
dc.w $8B7,$9B7,$9B6,$9B6,$9B5,$9A5,$AA4,$AA4
dc.w $AA4,$AA3,$BA3,$BA2,$BA2,$BA1,$CA1,$CA1
dc.w $CA0,$CA0,$CA0,$CA0,$CA1,$CA1,$CA1,$CA2
dc.w $DA2,$DA2,$DA3,$DA3,$DA3,$DA4,$DA4,$E94
dc.w $E95,$E95,$E95,$E96,$E96,$E97,$F97,$F98
dc.w $F98,$F99,$F99,$F9A,$F9A,$F9A,$F9A,$F9A
dc.w $F9A,$FAB,$FAB,$FAB,$FAB,$FBB,$FBC,$FBC
dc.w $FBC,$FCC,$FCD,$FCD,$FCD,$FDD,$FDD,$FDE
dc.w $FDE,$FEE,$FEE,$FEF,$FEF,$FFF,$FFF,$FFF
fdeglogo:
ideglogo: dc.w 0 ; index table degrade couleurs logo
sintena: dc.w 0 ; sauve intena
sdmacon: dc.w 0 ; sauve dmacon
nom_glib: dc.b"graphics.library",0 ; nom de la librairie
even
; donnees lutins
pall: dc.w $0000,$0115,$0225,$0236,$0246,$0256,$0167
dc.w $0177,$0198, $01A8,$00B8,$00C9,$00D9,$00EA
dc.w $00FA,$0000
; liste pointeurs vers lutins
ptlut: dc.l lut0,lut1,lut2,lut3,lut4,lut5,lut6,lut7 ;
dc.l 0 ; marqueur fin de liste
; ordonnees des 3 listes de lutins
coorlut0: dc.b $2c+04,$2c+16,$2c+32,$2c+48 ; 4x ordonnees lutins taille 32x8
dc.b 0 ; marqueur de fin de liste
coorlut1: dc.b $2c+00,$2c+08,$2c+16,$2c+24,$2c+38,$2c+48,$2c+58 ; 7x ordonnees lutins taille 16x6
dc.b 0 ; marqueur de fin de liste
coorlut2: dc.b $2c+02,$2c+07,$2c+12,$2c+18,$2c+24,$2c+30,$2c+36 ; 11x ordonnees lutins taille 16x4
dc.b $2c+42,$2c+48,$2c+54,$2c+60 ;
dc.b 0 ; marqueur de fin de liste
even
; **************************************************
; * *
; * SOUS-ROUTINES BOUCLE PRINCIPALE *
; * *
; **************************************************
; tt double tampon
; entree:
; sortie:
; regs : d0/d1/d7/a0
dtampon:
eor.b #$ff,flgdf ; permute drapeau double tampon
beq.b .page2 ;
; tt page n
move.l scpdbbob(pc),a0 ; recupere position liste Copper pr pts plans de bits
move.l #planbob0,d0 ; permute page ecran BOB
move.l #WS/8,d1 ;
move.w #NBP-1,d7 ;
bsr setpdb ; change pointeurs PdB dans liste Copper
lea adrpdb(pc),a0 ;
move.l #planbob1,adrpdb ; plan de bits de travail
move.l #lseffbob0,ptlst-adrpdb(a0) ; pointe vers vars de travail pour trame n (eff+affichage)
bra.b .s ;
.page2:
; tt page n+1
move.l scpdbbob(pc),a0 ; recupere position liste Copper pr pts plans de bits
move.l #planbob1,d0 ; permutte page ecran BOB
move.l #WS/8,d1 ;
move.w #NBP-1,d7 ;
bsr setpdb ; change pointeurs PdB dans liste Copper
lea adrpdb(pc),a0 ;
move.l #planbob0,(a0) ; plan de bits de travail
move.l #lseffbob1,ptlst-adrpdb(a0) ; pointe vers vars de travail pour trame n (eff+affichage)
bra.b .s
nop ;
.s:
rts
; initialisations propres aux effets de la demo
; entree:
; sortie:
; regs : d0/d7/a0
initpart6:
bsr initcopvide ; ecran noir et vide durant la phase d'init
; init les index des barres rasters
lea itbsinr(pc),a0 ;
moveq #0,d0 ;
move.w #NBB-1,d7 ;
.ib: ;
and.w #$00ff,d0 ; empêche debordement index
move.w d0,(a0)+ ;
add.w #6,d0 ; dephase le prochain index de 6
dbf d7,.ib ; tt prochain index
bsr initcop ; construction nouvelle liste copper
clr.w itbsinr ; raz index table sinus
addq.l #6,sdegcop ; pointe directement sur couleur ds liste degrade copper
moveq #-1,d0 ; init valeurs nbr de BOB a effacer
lea nbbob0(pc),a0 ;
move.w d0,(a0) ; trame paire
move.w d0,nbbob1-nbbob0(a0) ; trame impaire
; creation masque BOB
move.l #boulem,d1 ; adr masque BOB
move.l d1,d2 ;
lea $dff000,a6 ;
move.w #NBP-1,d7 ; nb de plans masque
.5:
move.l #boule,d0 ; adr BOB
move.l d2,d1 ;
move.w #NBP-1,d6 ; nb de plans bob
.4: ;
waitblt ;
move.l #$0dfc0000,$40(a6) ; d = 2 sources + 1 destination. fc = minterns 'ou logique'
move.l #$ffffffff,$44(a6) ; masques g/d
move.w #(LBOULE*NBP-LBOULE)/8,$62(a6) ; modulo B = masque BOB
move.l #((LBOULE*NBP-LBOULE)/8)<<16+((LBOULE*NBP-LBOULE)/8),$64(a6) ; modulos A = BOB D = masque BOB
move.l d1,$4c(a6) ; B = masque bob
move.l d0,$50(a6) ; A = bob
move.l d1,$54(a6) ; D = masque bob
move.w #(LBOULE/16)+64*HBOULE,$58(a6) ; bltsize
addq.l #LBOULE/8,d0 ; decale source d'une largeur de BOB
dbf d6,.4 ; prochain plan BOB
addq.l #LBOULE/8,d2 ; decale destination d'une largeur de BOB
dbf d7,.5 ; tt prochain plan du masque
lea itbcos(pc),a0 ; base table index
clr.w d0 ; init index cos()
clr.w d1 ; init index sin()
clr.w d2 ; increment index cos()
clr.w d3 ; increment index sin()
move.w #NBBOB-1,d7 ; nbre de bobs
.6: ;
add.w d2,d0 ; dephase prochain index cos()
add.w d3,d1 ; idem index sin()
move.w d0,(a0) ; index cos()
move.w d1,itbsin-itbcos(a0) ; index sin()
add.w #8,d2 ; incremente dephasage cos()
add.W #8,d3 ; idem dephasage sin()
and.w #$07ff,d2 ; evite debordement de l'index
and.w #$07ff,d3 ; evite debordement de l'index
addq.w #2,a0 ; prochains index
dbf d7,.6 ; prochains index
move.l #copper0,$dff080 ; liste copper de notre demo activee (a la prochaine trame)
move.l #part6,principal ; a la prochaine trame, le tt se fera dans l'effet demo en-soi
rts
; genere une table sinus() en 2,14
; a0 = table 2048 octets
; nb elements = 1024
; taille element = W
; plage : [-16384,16384]
gentrigo:
lea tbsin(pc),a0
moveq #0,d0
move.w #511+2,a1
.l:
subq.l #2,a1
move.l d0,d1
move.w d1,d2
not.w d2
mulu.w d1,d2
divu.w #75781/2,d2
lsr.w #3,d2
sub.w d2,d1
asr.l #2,d1
move.w d1,(a0)+
neg.w d1
move.w d1,(1024-2,a0)
add.l a1,d0
bne.b .l
; genere relicat table cos() en fonction de sin()
lea tbsin(pc),a0 ;
lea tbsin+1024*2(pc),a1 ;
move.w #1024/4-1,d7 ; pi/2 nb d'elements a copier
.0: ;
move.w (a0)+,(a1)+ ;
dbf d7,.0 ;
rts
part6:
bsr dtampon ; tt double tampon
bsr mvtetoiles ; deplace lutins du champ etoiles
bsr rasters ; effet de couleurs barres et fond colore
bsr cologo ; effet couleurs dans logo
bsr mvtlogo ; oscillation horizontale logo
bsr bobs ; traitement BOB
rts
; couleurs mouvantes dans logo
; entree:
; sortie:
; regs : d0/d1/d7/a0/a1
cologo:
lea deglogo(pc),a0 ; table des couleurs
move.w ideglogo(pc),d0 ; index
addq.w #2,d0 ; deplace couleurs
and.w #$00ff,d0 ; empêche debordement index
move.w d0,ideglogo-deglogo(a0) ; sauve nouvel index
move.l sdeglogocop(pc),a1 ; 1ere couleur du degrade ds liste copper
move.w #HL-1,d7 ; nb-1 de couleurs a traiter
.l: ;
and.w #$00ff,d0 ; empêche debordement index
move.w (a0,d0.w),(a1) ; injecte nouvelle couleur ds liste copper
addq.w #8,a1 ; on se positionne sur prochaine ligne copper
addq.w #2,d0 ; deplace pos. 1ere couleur
and.w #$00ff,d0 ; empêche debordement index
dbf d7,.l ; tt prochaine ligne
rts
; mvt oscillatoire logo
; entree:
; sortie:
; regs : d0/d1/d2/d7/a0
mvtlogo:
lea tbmvtlogo(pc),a0 ; table mvt logo
moveq #0,d0 ;
move.w itbmvtlogo(pc),d0 ; index table
move.w d0,d1 ;
addq #2,d1 ; mouvement grace a incrementation index
and.w #$00ff,d1 ; empêche debordement index
move.w d1,itbmvtlogo-tbmvtlogo(a0) ; reinjecte nouvel index
add.w d0,d0 ; table en .W
move.w (a0,d0.w),d0 ; abscisse
add.w #WL/2,d0 ; recentrage abscisse logo
move.w d0,d1 ;
lsr.w #4,d0 ; nbre de mots
add.w d0,d0 ; adresse partielle paire, en octets
add.l #logo,d0 ; adresse finale plan du logo
and.w #$000f,d1 ; uniquement 4 bits poids faible abscisse logo
move.w #15,d2 ;
sub.w d1,d2 ;
move.w d2,d1 ; retard plans pairs
lsl.w #4,d2 ; calcul retard plans impairs
or.w d2,d1 ; retard plans pairs et impairs
move.l sretardlogo(pc),a0 ; pos. du registre retard ds liste copper
move.w d1,(a0) ; injecte nouvelle valeur retard ds liste copper
move.l sptlogo(pc),a0 ; pos. ds liste copper
move.l #LL/8*HL,d1 ; taille en octets d'1 pdb
move.w #NBPDBL-1,d7 ; nb-1 de pdb a traiter
bsr setpdb ; injecte pt pdb ds liste copper
rts
; tt effets de couleurs au copper
; entree:
; sortie:
; regs : d0/d6/d7/a0/a1/a2/a3/a4
rasters:
; tt effacement barres rasters
lea degrade(pc),a0 ; couleurs du degrade de fond
move.l sdegcop(pc),a2 ; pt vers liste copper
move.w #HS-HL-1,d7 ; 256 lignes a traiter
.clr: ;
move.w (a0)+,(a2) ; injecte couleur ds liste copper
lea 16(a2),a2 ; prochaine ligne copper
dbf d7,.clr ; tt prochaine ligne
; tt affichage barres rasters
lea itbsinr(pc),a0 ; liste d'index des 16 barres rasters
lea tbsinr(pc),a1 ;
move.l sdegcop(pc),a2 ; pointe vers liste copper
move.w #NBB-1,d7 ; nb-1 barres rasters
.2:
move.w (a0),d0 ; index table sinus
addq.w #1,(a0)+ ; incremente index
and.w #$00ff,d0 ; evite debordement
move.b (a1,d0.w),d0 ; ordonnee ecran de la barre raster
sub.w #HL-1,d0 ; recentrage
lsl.w #4,d0 ; adresse offset ds liste copper
move.l a2,a3 ; base adr. debut degrade dans liste copper
add.w d0,a3 ; a3 = adr. cible ds liste copper où y dessiner barre
lea barre(pc),a4 ; pointe sur couleurs de la barre raster
move.w #HBR-1,d6 ; hauteur-1 d'une barre raster
.1: ;
move.w (a4)+,(a3) ; injecte couleur ligne barre raster ds liste copper
lea 16(a3),a3 ;
dbf d6,.1 ; tt prochaine ligne de la barre
dbf d7,.2 ; tt prochaine barre
rts ;
; deplace lutins en parallax
; entree:
; sortie:
; regs : d0/d7/a1/a2/a3/a4
mvtetoiles:
; deplacement etoiles -grandes-
lea lut0+1,a1 ; liste lutins pairs -grande taille
lea lut1+1,a2 ; liste lutins impairs -grande taille
lea lut2+1,a3 ; liste 2eme partie lutins pairs -grande taille
lea lut3+1,a4 ; liste 2eme partie lutins impairs -grande taille
moveq #4-1,d7 ; nb-1 lutins
.0: ;
move.b (a1),d0 ;
addq.b #VGL,d0 ; deplacement de 6 pixels a droite
move.b d0,(a1) ; injecte nouvelle abscisse
move.b d0,(a2) ; idem pour lutin impair
addq.b #8,d0 ; abscisse 2eme partie lutins
move.b d0,(a3) ; injecte nouvelle abscisse
move.b d0,(a4) ; idem pour lutin impair
lea flut0-lut0(a1),a1 ; passe au prochain lutin de la liste
lea flut0-lut0(a2),a2 ; idem pour lutin impair
lea flut0-lut0(a3),a3 ; passe au prochain lutin de la liste
lea flut0-lut0(a4),a4 ; idem pour 2eme partie lutins
dbf d7,.0 ;
; deplacement etoiles -moyennes-
lea lut4+1,a1 ; liste lutins pairs -grande taille
lea lut5+1,a2 ; liste lutins impairs -grande taille
moveq #7-1,d7 ; nb-1 lutins
.1: ;
move.b (a1),d0 ;
addq.b #VML,d0 ; deplacement de 4 pixels a droite
move.b d0,(a1) ; injecte nouvelle abscisse
move.b d0,(a2) ; idem pour lutin impair
lea flut4-lut4(a1),a1 ; passe au prochain lutin de la liste
lea flut5-lut5(a2),a2 ; idem pour lutin impair
dbf d7,.1 ;
; deplacement etoiles -petites-
lea lut6+1,a1 ; liste lutins pairs -grande taille
lea lut7+1,a2 ; liste lutins impairs -grande taille
moveq #11-1,d7 ; nb-1 lutins
.2: ;
move.b (a1),d0 ;
addq.b #VPL,d0 ; deplacement de 2 pixels a droite
move.b d0,(a1) ; injecte nouvelle abscisse
move.b d0,(a2) ; idem pour lutin impair
lea flut6-lut6(a1),a1 ; passe au prochain lutin de la liste
lea flut7-lut7(a2),a2 ; idem pour lutin impair
dbf d7,.2 ;
rts
; ***********************************************
; * TRAITEMENT BOBs *
; ***********************************************
bobs:
bsr effbob ; efface bobs trame precedente
; tt mouvement des bobs
lea tbcos(pc),a0 ; tables trigo [-16384,16384]
lea tbsin(pc),a1 ; 2,14
lea itbcos(pc),a2 ; base table index
lea tbxybob(pc),a3 ; table coordonnees bob
move.w #NBBOB-1,d7 ; nbre de bobs
.0: ;
move.w (a2),d0 ; index cos()
move.w itbsin-itbcos(a2),d1 ; index sin()
move.w (a0,d0.w),d2 ; cos()
move.w (a1,d1.w),d3 ; sin()
muls #128*($4000>>8),d2 ; Rx*cos()
muls #32*($4000>>8),d3 ; Ry*sin()
swap d2 ;
swap d3 ;
asr.w #4,d2 ;
asr.w #4,d3 ;
add.w #(WS-32)/2,d2 ; recentrage abscisse
add.w #(HS-106)/2,d3 ; recentrage ordonnee
move.w d2,(a3)+ ; stocke abscisse bob
move.w d3,(a3)+ ; stocke ordonnee bob
add.w #12,d0 ; incremente index cos()
add.w #6,d1 ; incremente index sin()
and.w #$07ff,d0 ; evite debordement index
and.w #$07ff,d1 ; idem
move.w d0,(a2) ; injecte nouvelle valeur index de cos()
move.w d1,itbsin-itbcos(a2) ; idem index de sin()
addq.w #2,a2 ; prochain index
dbf d7,.0 ; prochain bob
; tt affichage bobs
lea tbxybob(pc),a0 ; table coordonnees bob
lea tbbltcon(pc),a1 ; table des $xFCAx000
lea tbxadr(pc),a2 ; table des adresses relatives horizontales
lea tbyadr(pc),a3 ; table des adresses verticales relatives
move.l ptlst(pc),a4 ; liste effacement BOB
move.w #NBBOB,nbbob0-lseffbob0(a4) ; nb de bobs pour effacement
; tt premier element de la liste (1er BOB)
waitblt ; renseigne registres Blitter invariables
move.l #$ffff0000,$44(a6) ; masques gauche/droite
move.l #((WS-(LBOULE+16))/8)<<16+$fffe,$60(a6) ; modulos C B
move.l #$fffe<<16+((WS-(LBOULE+16))/8),$64(a6) ; modulos A D
move.w #$0400,$96(a6) ; desactive priorite blitter sur 68000 durant phase d'affichage
move.w #NBBOB-1,d7 ; nb de BOB a afficher
.1: ;
movem.w (a0)+,d0/d1 ; coordonnees bobs
add.w d1,d1 ; (x,y) bob = d0,d1
add.w d1,d1 ;
add.w d0,d0 ;
moveq #0,d4 ;
move.w (a2,d0.w),d4 ; adr. destination en X
add.w d0,d0 ;
move.l (a1,d0.w),d2 ; $xFCAx000 = BLTCON0 et 1
add.l (a3,d1.w),d4 ; adr. finale destination bob
add.l adrpdb(pc),d4 ; adr. finale bob : dest
waitblt ; attente blitter se libere
move.l d2,$40(a6) ; $xFCAx000 : x = decalage mot
move.l d4,$48(a6) ; C = pdb
move.l #boule,$4c(a6) ; B = bob
move.l #boulem,$50(a6) ; A = masque bob
move.l d4,$54(a6) ; D = pdb
move.w #((LBOULE+16)/16)+64*HBOULE*NBP,$58(a6) ; bltsize
move.l d4,(a4)+ ; sauve D pour effacement
dbf d7,.1 ;
rts
; tt effacement BOBs
effbob:
lea $dff000,a6 ; base adresse registres specialises
move.l ptlst(pc),a0 ; recupere adr liste effacement des BOB du tampon memoire video cache
move.w nbbob0-lseffbob0(a0),d7 ; y'a-t-il des BOB a effacer ?
bmi.b .1 ; non -> sortie tt effacement
move.w #$8400,$96(a6) ; oui -> active priorite blitter sur 68000 durant phase d'effacement
waitblt ; renseigne registres Blitter invariables
move.l #$01000000,$40(a6) ; tous les DMA blitter coupes exceptes D
move.w #(WS-(LBOULE+16))/8,$66(a6) ; modulo D
.0: ;
waitblt ; attente blitter libre
move.l (a0)+,$54(a6) ; D = plan de bits
move.w #(LBOULE+16)/16+64*(HBOULE)*NBP,$58(a6) ; bltsize
dbf d7,.0 ; prochain BOB a effacer
.1:
rts
scpdbbob: dc.l 0 ; pts dans liste copper des adresses pdb de l'ecran BOB
adrpdb: dc.l 0 ; adresse plan cache
ptlst: dc.l 0 ; pt vers liste de travail trame n
nbbob: dc.w 0 ; compteur BOB irq
; ne pas changer l'ordre des declarations ci-dessous !
nbbob0: dc.w 0 ; nb de BOB a effacer trammer paire
; listes operations blitter trame paire (effacement)
lseffbob0:
e1: dc.l 0 ; adresse D
e9:
REPT NBBOB-1 ; liste effacement BOB
dc.w 0 ; modulo D
dc.l 0 ; adresse D
dc.w 0 ; bltsize
ENDR
nbbob1: dc.w 0 ; nb de BOB a effacer trammer impaire
; listes operations blitter trame impaire (effacement)
lseffbob1: REPT NBBOB ; liste effacements BOB
dc.l 0 ; adresse D
ENDR
flgdf: dc.b 0 ; drapeau bascule page ecran BOB
even
palep: dc.w $000,$8df,$64e,$328 ; palette ecran des BOB
; table adresses relatives horizontales des BOB
tbxadr:
uu SET 0
REPT WS/16
blk.w 16,uu
uu SET uu+2
ENDR
tbyadr: ; table adresse relatives verticales des BOB
vv SET 0
REPT HS
dc.l vv
vv SET vv+WS/8*NBP
ENDR
; table des decalages Blitter (BLTCON0 & 1)
tbbltcon:
REPT WS/16
dc.l $0fca0000,$1fca1000,$2fca2000,$3fca3000
dc.l $4fca4000,$5fca5000,$6fca6000,$7fca7000
dc.l $8fca8000,$9fca9000,$afcaa000,$bfcab000
dc.l $cfcac000,$dfcad000,$efcae000,$ffcaf000
ENDR
itbcos: blk.w NBBOB*2,0 ; index tables cos()
itbsin: blk.w NBBOB*2,0 ; index tables sin()
tbxybob: blk.w NBBOB*2,0 ; table de stockage des coordonnees bob
; ***********************************************
; * tables trigo *
; ***********************************************
even
tbsin: blk.w 1024,0 ; table sinus 2:14 [16384,-16384]
ftbsin:
blk.w 1024/4,0 ; partie cos
tbcos = tbsin+2048/4
; ***********************************************
; * *
; * CHIP RAM *
; * *
; ***********************************************
section donneesgraph,data_c
; donnees graphique du BOB
; taille : 32x32 pixels
; nombre de plans : 2 (4 couleurs)
boule:
DC.B $00, $00, $1f, $f0, $00, $00, $00, $00
DC.B $1f, $f0, $00, $00, $00, $00, $ff, $fe
DC.B $00, $00, $00, $00, $ff, $fe, $00, $00
DC.B $00, $07, $ff, $ff, $c0, $00, $00, $07
DC.B $ff, $ff, $c0, $00, $00, $0f, $ff, $ff
DC.B $e0, $00, $00, $0f, $ff, $ff, $e0, $00
DC.B $00, $3f, $ff, $ff, $f8, $00, $00, $3f
DC.B $ff, $ff, $f8, $00, $00, $7f, $ff, $ff
DC.B $fc, $00, $00, $7f, $ff, $ff, $fc, $00
DC.B $00, $ff, $ff, $ff, $fe, $00, $00, $ff
DC.B $ff, $ff, $fe, $00, $01, $ff, $ff, $ff
DC.B $ff, $00, $01, $ff, $ff, $ff, $ff, $00
DC.B $03, $f8, $3f, $ff, $ff, $80, $03, $ff
DC.B $ff, $ff, $ff, $80, $07, $f0, $1f, $ff
DC.B $ff, $c0, $07, $ff, $ff, $ff, $ff, $c0
DC.B $0f, $e7, $0f, $ff, $ff, $e0, $0f, $f8
DC.B $ff, $ff, $ff, $e0, $0f, $cf, $87, $ff
DC.B $ff, $e0, $0f, $f0, $7f, $ff, $ff, $e0
DC.B $1f, $df, $c7, $ff, $ff, $f0, $1f, $e0
DC.B $3f, $ff, $ff, $f0, $1f, $9f, $c3, $ff
DC.B $ff, $f0, $1f, $e0, $3f, $ff, $ff, $f0
DC.B $3f, $9f, $c3, $ff, $ff, $f8, $3f, $e0
DC.B $3f, $ff, $ff, $f8, $3f, $8f, $83, $ff
DC.B $ff, $f8, $3f, $f0, $7f, $ff, $ff, $f8
DC.B $7f, $87, $03, $ff, $ff, $fc, $7f, $f8
DC.B $ff, $ff, $ff, $fc, $7f, $80, $03, $ff
DC.B $ff, $fc, $7f, $ff, $ff, $ff, $ff, $fc
DC.B $7f, $c0, $07, $ff, $ff, $fc, $7f, $ff
DC.B $ff, $ff, $ff, $fc, $7f, $c0, $07, $ff
DC.B $ff, $fc, $7f, $ff, $ff, $ff, $ff, $fc
DC.B $ff, $e0, $0f, $ff, $ff, $fe, $ff, $ff
DC.B $ff, $ff, $ff, $fe, $ff, $f0, $1f, $ff
DC.B $ff, $fe, $ff, $ff, $ff, $ff, $ff, $fe
DC.B $ff, $f8, $3f, $ff, $ff, $fe, $ff, $ff
DC.B $ff, $ff, $ff, $fe, $ff, $ff, $ff, $ff
DC.B $ff, $fe, $ff, $ff, $ff, $ff, $ff, $fe
DC.B $ff, $ff, $ff, $ff, $ff, $fe, $ff, $ff
DC.B $ff, $ff, $ff, $fe, $ff, $ff, $ff, $ff
DC.B $ff, $fe, $ff, $ff, $ff, $ff, $ff, $fe
DC.B $ff, $ff, $ff, $ff, $ff, $fe, $ff, $ff
DC.B $ff, $ff, $ff, $fe, $ff, $ff, $ff, $ff
DC.B $ff, $fe, $ff, $ff, $ff, $ff, $ff, $fe
DC.B $ff, $ff, $ff, $ff, $ff, $fe, $ff, $ff
DC.B $ff, $ff, $ff, $fe, $7f, $ff, $ff, $ff
DC.B $ff, $fc, $7f, $ff, $ff, $ff, $ff, $fc
DC.B $7f, $ff, $ff, $ff, $ff, $fc, $7f, $ff
DC.B $ff, $ff, $ff, $fc, $7f, $ff, $ff, $ff
DC.B $ff, $fc, $7f, $ff, $ff, $ff, $ff, $fc
DC.B $7f, $ff, $ff, $ff, $ff, $fc, $7f, $ff
DC.B $ff, $ff, $ff, $fc, $3f, $ff, $ff, $ff
DC.B $ff, $f8, $3f, $ff, $ff, $ff, $ff, $f8
DC.B $3f, $ff, $ff, $ff, $ff, $f8, $3f, $ff
DC.B $ff, $ff, $ff, $f8, $1f, $ff, $ff, $ff
DC.B $ff, $f0, $1f, $ff, $ff, $ff, $ff, $f0
DC.B $1f, $ff, $ff, $ff, $ff, $f0, $1f, $ff
DC.B $ff, $ff, $ff, $f0, $0f, $ff, $ff, $ff
DC.B $ff, $e0, $0f, $ff, $ff, $ff, $ff, $e0
DC.B $0f, $ff, $ff, $ff, $ff, $e0, $0f, $ff
DC.B $ff, $ff, $ff, $e0, $07, $ff, $ff, $ff
DC.B $ff, $c0, $07, $ff, $ff, $ff, $ff, $c0
DC.B $03, $ff, $ff, $ff, $ff, $80, $03, $ff
DC.B $ff, $ff, $ff, $80, $01, $ff, $ff, $ff
DC.B $ff, $00, $01, $ff, $ff, $ff, $ff, $00
DC.B $00, $ff, $ff, $ff, $fe, $00, $00, $ff
DC.B $ff, $ff, $fe, $00, $00, $7f, $ff, $ff
DC.B $fc, $00, $00, $7f, $ff, $ff, $fc, $00
DC.B $00, $3f, $ff, $ff, $f8, $00, $00, $3f
DC.B $ff, $ff, $f8, $00, $00, $0f, $ff, $ff
DC.B $e0, $00, $00, $0f, $ff, $ff, $e0, $00
DC.B $00, $07, $ff, $ff, $c0, $00, $00, $07
DC.B $ff, $ff, $c0, $00, $00, $00, $ff, $fe
DC.B $00, $00, $00, $00, $ff, $fe, $00, $00
DC.B $00, $00, $1f, $f0, $00, $00, $00, $00
DC.B $1f, $f0, $00, $00
boulem:
blk.b boulem-boule,0 ; masque BOB
;logo: blk.b 80*64,0
; premier plan du logo qui est deja precharge par le graphisme du logo
logo:
dc.l $00000000,$00000000,$0007FE00,$00000000,$00000000,$00000000,$00000000,$00000000
dc.l $00000000,$00000000,$00000000,$00000000,$00000000,$00000000,$00000000,$00000000
dc.l $00000000,$00000000,$00000000,$00000000,$00000000,$00000000,$001FFF80,$00000000
dc.l $00000000,$00000000,$00000000,$00000000,$00000000,$00000000,$00000000,$00000000
dc.l $00000000,$00000000,$00000000,$00000000,$00000000,$00000000,$00000000,$00000000
dc.l $00000000,$00000000,$003FFFE0,$00001FF8,$00000000,$00000000,$00000000,$00000000
dc.l $00000000,$003F8000,$00000000,$00000000,$00000000,$00000000,$00000000,$00000000
dc.l $00000000,$00000000,$00000000,$00000000,$00000000,$00000000,$007FFFF8,$0000FFF0
dc.l $00000000,$00000000,$00000000,$00000000,$00000000,$03FFF800,$00000000,$00000000
dc.l $00000000,$00000000,$00000000,$00000000,$00000000,$00000000,$00000000,$00000000
dc.l $00000000,$00000000,$00FFFFFC,$0003FFF0,$00000000,$00000000,$00000000,$00000000
dc.l $00000000,$0FFFFE00,$00000000,$00000000,$00000000,$00000000,$00000000,$00000000
dc.l $00000000,$00000000,$00000000,$00000000,$00000000,$00000000,$00FFFFFE,$000FFFF0
dc.l $00000000,$00007F00,$00000000,$00000000,$00000000,$3FFFFF80,$007F8000,$0000FE00
dc.l $0FE00000,$00000000,$00000000,$00000000,$00000000,$00000000,$000FF000,$00000000
dc.l $00000000,$00000000,$01FFFFFF,$001FFFE0,$00000000,$0000FFC0,$00000000,$00000000
dc.l $00000000,$FFFFFFC0,$007FC000,$0000FF80,$1FF00000,$00000000,$00000000,$00000000
dc.l $00000000,$00000000,$000FFC00,$00000000,$00000000,$00000000,$01FFFFFF,$807FFFE0
dc.l $00000000,$0001FFE0,$00000000,$00000000,$00000001,$FFFFFFE0,$007FF000,$0000FFC0
dc.l $3FF80000,$00000000,$00000000,$00000000,$00000000,$00000000,$0007FE00,$00000000
dc.l $00000000,$00000000,$03FFFFFF,$C0FFFFC0,$00000000,$0001FFE0,$00000000,$00000000
dc.l $00000003,$FFFFFFF0,$003FF000,$0000FFE0,$7FFC0000,$00000000,$00000000,$00000000
dc.l $00000000,$00000000,$0007FE00,$00000000,$00000000,$00000000,$03FFFFFF,$E3FFFFC0
dc.l $00000000,$0003FFE0,$00000000,$00000000,$00000007,$FF80FFF8,$003FF800,$0000FFF0
dc.l $7FFC0000,$00000000,$00000000,$00000000,$00000000,$00000000,$0007FF00,$00000000
dc.l $00000000,$00000000,$03FFFFFF,$F7FFFFC0,$00000000,$0003FFE0,$00000000,$00000000
dc.l $0000000F,$FE003FFC,$007FF800,$0000FFF0,$7FFC0000,$00000000,$00000000,$00000000
dc.l $00000000,$00000000,$0007FF00,$00000000,$00000000,$00000000,$01FFFF0F,$FFFF7F80
dc.l $00000000,$0001FFE0,$00000000,$00000000,$0000001F,$F8001FFC,$007FF800,$0000FFF0
dc.l $7FFC0000,$00000000,$00000000,$00000000,$00000000,$00000000,$000FFF00,$00000000
dc.l $00000000,$00000000,$01FFFF07,$FFFE7F80,$00000000,$0000FFC0,$00000000,$00000000
dc.l $0000003F,$F0000FFE,$00FFF800,$0001FFF0,$3FF80000,$00000000,$00000000,$00000000
dc.l $00000000,$00000000,$000FFF00,$00000000,$00000000,$00000000,$00FFFF03,$FFF8FF80
dc.l $00000000,$00007F80,$00000000,$00000000,$0000007F,$E00007FE,$00FFF000,$0001FFE0
dc.l $1FF00000,$00000000,$00000000,$00000000,$00000000,$00000000,$001FFE00,$00000000
dc.l $00000000,$00000000,$00FFFF00,$FFF0FF00,$00000000,$00001E00,$00000000,$00000000
dc.l $000000FF,$C00003FF,$00FFF000,$0003FFE0,$07C00000,$00000000,$00000000,$00000000
dc.l $00000000,$00000000,$001FFE00,$00000000,$00000000,$00000000,$007FFF81,$FFE1FF00
dc.l $00000000,$00000000,$00000000,$00000000,$000000FF,$800003FF,$01FFF000,$0003FFC0
dc.l $00000000,$00000000,$00000000,$00000000,$00000000,$00000000,$003FFE00,$00000000
dc.l $00000000,$00000000,$003FFFC3,$FFE1FF00,$00000000,$00000000,$00000000,$00000000
dc.l $000001FF,$000003FF,$01FFE000,$0003FFC0,$00000000,$00000000,$00000000,$00000000
dc.l $00000000,$00000000,$003FFC00,$00000000,$00000000,$00000000,$000FFFE7,$FFC3FE3F
dc.l $C0000000,$0001FE00,$00000000,$00000000,$000001FF,$03FF81FF,$83FFE3FE,$0007FFC0
dc.l $7F800000,$00000000,$FF007F80,$00000000,$0000FF00,$3F000000,$003FFC00,$00000000
dc.l $00000000,$00000000,$0003FF8F,$FFC3FE3F,$F01FF00F,$F007FF00,$00007F00,$000007F0
dc.l $000003FE,$0FFFE1FF,$83FFEFFF,$8007FF80,$FFC00000,$1FE0000F,$FFE03FE0,$1FF00FE0
dc.l $000FFFE0,$7FE007FC,$007FFC00,$00000000,$00000000,$00000000,$00007E1F,$FFC7FE1F
dc.l $F87FF87F,$FC07FF00,$01FFFFC0,$007FC7F8,$000003FE,$3FFFF1FF,$87FFFFFF,$E00FFF80
dc.l $FFE0007F,$FFF8003F,$FFF03FF0,$7FF87FFC,$003FFFF0,$3FF03FFF,$07FFFF80,$00000000
dc.l $00000000,$00000000,$0000003F,$FFE7FE1F,$F8FFFCFF,$FE07FF00,$07FFFFE0,$01FFE7FC
dc.l $000003FC,$7FFFF9FF,$87FFFFFF,$F00FFF00,$FFE001FF,$FFFC00FF,$FFF83FF9,$FFF9FFFE
dc.l $00FFFFF8,$3FF8FFFF,$9FFFFFC0,$00000000,$00000000,$00000000,$3800007F,$FFFFFC1F
dc.l $FDFFFFFF,$FF07FF00,$1FFFFFF0,$07FFFFFE,$000007FC,$FFFFF9FF,$8FFFFFFF,$F01FFF00
dc.l $FFE007FF,$FFFC01FF,$F3F83FFF,$FFFFFFFE,$01FFF3F8,$3FF9FFFF,$DFFFFFC0,$00000000
dc.l $00000000,$00000000,$F80000FF,$FFFFFC1F,$FFFFFFFF,$FF07FF00,$7FFFFFF0,$0FFFFFFE
dc.l $000007FD,$FFFFF9FF,$8FFFF03F,$F81FFF01,$FFE00FFF,$FFFE03FF,$E1FC3FFF,$FFFFFFFF
dc.l $03FFE1FC,$3FFFFFFF,$FFFFFFC0,$00000000,$00000000,$00000003,$F80001FF,$FFFFF83F
dc.l $FFCFFFFF,$FF07FF00,$FFFFFFF0,$1FFFFFFE,$000007FF,$FFFFF9FF,$9FFFC03F,$F81FFE01
dc.l $FFE01FFF,$FFFE07FF,$C1FC3FFF,$8FFFFFFF,$07FFC1FC,$3FFFFFFF,$FBFFE780,$00000000
dc.l $00000000,$00000007,$F80003FF,$FCFFF83F,$FF07FF8F,$FF0FFF01,$FFF3FFF0,$3FFE7FFE
dc.l $000007FF,$FFFFF9FF,$9FFF801F,$F83FFE01,$FFC03FFC,$FFFE0FFF,$C1FC3FFF,$07FF8FFF
dc.l $0FFFC1FC,$3FFFC3FF,$C1FFE000,$00000000,$00000000,$0000000F,$F80007FF,$F87FF83F
dc.l $FE07FF07,$FF0FFE03,$FFC1FFF0,$7FF83FFE,$000003FF,$FFFFFBFF,$9FFF003F,$FC3FFE03
dc.l $FFC07FF8,$3FFE1FFF,$81FC7FFE,$07FE0FFF,$1FFF81FC,$3FFF81FF,$C3FFE000,$00000000
dc.l $00000000,$0000001F,$F8000FFF,$F87FF87F,$FE07FE0F,$FF1FFE03,$FFC0FFF0,$FFF01FFE
dc.l $000003FF,$F0FFF3FF,$BFFE003F,$FC7FFC03,$FFC0FFF0,$1FFE1FFF,$83FC7FFC,$07FE0FFE
dc.l $1FFF83FC,$7FFF03FF,$C3FFC000,$00000000,$00000000,$0000003F,$F8003FFF,$F03FF87F
dc.l $FC07FE0F,$FF1FFE07,$FF80FFF0,$FFF03FFC,$000001FF,$E0FFF3FF,$BFFE003F,$FC7FFC07
dc.l $FF81FFF0,$1FFE3FFF,$87FC7FFC,$0FFC1FFE,$3FFF87FC,$7FFE07FF,$C7FFC000,$00000000
dc.l $00000000,$0000003F,$FC007FFF,$F07FF07F,$FC0FFC1F,$FE1FFC0F,$FF80FFF1,$FFF03FFC
dc.l $0000007F,$C0FFE7FF,$3FFE007F,$FC7FFC07,$FF81FFE0,$1FFE3FFF,$8FF8FFF8,$1FFC1FFE
dc.l $3FFF8FF8,$FFFC07FF,$87FFC000,$00000000,$00000000,$0000007F,$FE01FFFF,$E07FF07F
dc.l $F81FFC1F,$FE3FFC0F,$FF00FFF1,$FFF07FF8,$0000001F,$C3FFC7FF,$3FFE00FF,$F8FFFC07
dc.l $FF03FFE0,$3FFC7FFF,$FFF8FFF8,$1FF83FFC,$7FFFFFF8,$FFFC0FFF,$87FFC000,$00000000
dc.l $00000000,$0000007F,$FF8FFFFF,$E0FFF0FF,$F83FF83F,$FE3FF81F,$FF01FFF3,$FFF07FF8
dc.l $1C00001F,$E3FF0FFF,$3FFE00FF,$F8FFF80F,$FF03FFE0,$3FFC7FFF,$FFF0FFF8,$3FF87FFC
dc.l $7FFFFFF0,$FFF81FFF,$8FFFC03C,$00000000,$00000000,$0000007F,$FFFFFFFF,$C0FFF0FF
dc.l $F83FF87F,$FC7FF81F,$FF83FFF3,$FFF07FF0,$3E00001F,$E1FC1FFF,$3FFE03FF,$F8FFF80F
dc.l $FF07FFE0,$7FFCFFFF,$FFF1FFF0,$7FF07FFC,$FFFFFFF1,$FFF01FFF,$0FFFC07C,$00000000
dc.l $00000000,$0000007F,$FFFFFFFF,$C0FFF1FF,$F07FF07F,$FC7FF81F,$FFC7FFE3,$FFF8FFF0
dc.l $3E00003F,$F0003FFE,$3FFF07FF,$F8FFF81F,$FE07FFF1,$FFFCFFFF,$FFE1FFF0,$7FF0FFF8
dc.l $FFFFFFE1,$FFF03FFF,$0FFFC0FC,$00000000,$00000000,$0000007F,$FFFFFFFF,$80FFF1FF
dc.l $F07FF0FF,$F87FF83F,$FFFFFFE3,$FFFFFFF0,$7C00003F,$F000FFFE,$3FFFFFFF,$F1FFFC1F
dc.l $FE07FFFF,$FFFCFFFF,$FFC3FFF0,$FFF0FFF8,$FFFFFFC3,$FFF03FFE,$0FFFC0FC,$00000000
dc.l $00000000,$0000007F,$FFFFFFFF,$01FFE3FF,$F0FFF0FF,$F8FFF87F,$FFFFFFE3,$FFFFFFF0
dc.l $7C00003F,$FC03FFFC,$3FFFFFFF,$F1FFFC1F,$FE0FFFFF,$FFF8FFFF,$FF87FFE0,$FFE1FFF8
dc.l $FFFFFF87,$FFE03FFE,$0FFFC1F8,$00000000,$00000000,$0000007F,$FFFFFFFE,$01FFE3FF
dc.l $F0FFE1FF,$F8FFF87F,$FFFFFFE3,$FFFFFFF0,$F800003F,$FFFFFFFC,$1FFFFFFF,$F1FFFF7F
dc.l $FE1FFFFF,$FFF8FFFE,$7F07FFE1,$FFE1FFF0,$FFFE7F07,$FFE07FFE,$0FFFE7F0,$00000000
dc.l $00000000,$0000007F,$FFFFFFFE,$01FFE3FF,$E1FFE1FF,$F8FFFDFF,$FFFFFFC3,$FFFFFFFD
dc.l $F000003F,$FFFFFFF8,$1FFFFFFF,$E1FFFFFF,$FFBFFFFF,$FFF87FFE,$001FFFE1,$FFE1FFF0
dc.l $7FFE001F,$FFE07FFE,$1FFFFFF0,$00000000,$00000000,$0000003F,$FFFFFFFC,$01FFF7FF
dc.l $E1FFE1FF,$F8FFFFFF,$FFFFFFC3,$FFFFFFFF,$F000003F,$FFFFFFF8,$1FFFFFFF,$C1FFFFFF
dc.l $FFFFFFFF,$FFF87FFF,$003FFFE3,$FFC1FFF0,$7FFF003F,$FFC07FFE,$0FFFFFE0,$00000000
dc.l $00000000,$0000003F,$FFFFFFF8,$03FFF7FF,$E3FFE1FF,$F8FFFFFF,$FFFFFFC1,$FFFFFFFF
dc.l $E000001F,$FFFFFFF0,$0FFFFFFF,$C1FFFFFF,$FFFFFFFF,$FFF03FFF,$81FFFFC3,$FFC1FFF0
dc.l $3FFF81FF,$FFC07FFE,$0FFFFFC0,$00000000,$00000000,$0000001F,$FFFFFFF8,$03FFFFFF
dc.l $E3FFC1FF,$FCFFFFEF,$FFFFFFC1,$FFFFFFFF,$C000001F,$FFFFFFE0,$07FFFFFF,$80FFFFFF
dc.l $FFFFFFFF,$FFF03FFF,$FFFFFFC3,$FFC1FFF8,$3FFFFFFF,$FFC07FFF,$0FFFFF80,$00000000
dc.l $00000000,$0000000F,$FFFFFFF0,$03FFFFFF,$E3FFC0FF,$FFFFFFC7,$FFFFFF80,$FFFFFFFF
dc.l $8000001F,$FFFFFFC0,$03FFFFFF,$00FFFFFF,$FFF9FFFF,$FFF01FFF,$FFFFFFC7,$FFC1FFFF
dc.l $1FFFFFFF,$FFC03FFF,$EFFFFF00,$00000000,$00000000,$0000000F,$FFFFFFE0,$03FFFFFF
dc.l $C3FFC0FF,$FFFFFF83,$FFFFFF80,$7FFE7FFF,$0000000F,$FFFFFF80,$01FFFFFC,$00FFFFEF
dc.l $FFF0FFFF,$FFF00FFF,$FFFFFFC7,$FFC0FFFF,$0FFFFFFF,$FFC03FFF,$E7FFFE00,$00000000
dc.l $00000000,$00000007,$FFFFFFC0,$01FFFFFF,$C3FFC07F,$FF3FFF01,$FFEFFF80,$3FFC3FFE
dc.l $00000007,$FFFFFF00,$007FFFF8,$007FFF87,$FFC03FFB,$FFE007FF,$FFE7FFC7,$FFC0FFFF
dc.l $07FFFFE7,$FFC01FFF,$C7FFFC00,$00000000,$00000000,$00000003,$FFFFFF00,$01FFFFFF
dc.l $C3FFC03F,$FE0FFC00,$3F0FFF00,$1FF01FF8,$00000007,$FFFFFC00,$001FFFC0,$001FFE03
dc.l $FF800FE3,$FFE001FF,$FF01FFC3,$FFC03FFE,$01FFFF01,$FFC00FFF,$81FFF000,$00000000
dc.l $00000000,$00000000,$FFFFFE00,$01FFFF3F,$C1FFC00F,$F803E000,$001FFF00,$07C007E0
dc.l $00000003,$FFFFF800,$0001FE00,$0007F000,$FC000003,$FFC0001F,$F0007FC3,$FF800FF8
dc.l $001FF000,$7FC003FE,$007F8000,$00000000,$00000000,$00000000,$3FFFF800,$00FFFE00
dc.l $00FF0000,$00000000,$001FFF00,$00000000,$00000000,$FFFFC000,$00000000,$00000000
dc.l $00000007,$FFC00000,$00000000,$FE000000,$00000000,$00000000,$00000000,$00000000
dc.l $00000000,$00000000,$0FFFC000,$007FF800,$00000000,$00000000,$003FFE00,$00000000
dc.l $00000000,$3FFE0000,$00000000,$00000000,$00000007,$FFC00000,$00000000,$00000000
dc.l $00000000,$00000000,$00000000,$00000000,$00000000,$00000000,$00000000,$000F8000
dc.l $00000000,$00000003,$007FFE00,$00000000,$00000000,$00000000,$00000000,$00000000
dc.l $0000E00F,$FF800000,$00000000,$00000000,$00000000,$00000000,$00000000,$00000000
dc.l $00000000,$00000000,$00000000,$00000000,$00000000,$00000007,$C0FFFC00,$00000000
dc.l $00000000,$00000000,$00000000,$00000000,$0000F81F,$FF800000,$00000000,$00000000
dc.l $00000000,$00000000,$00000000,$00000000,$00000000,$00000000,$00000000,$00000000
dc.l $00000000,$00000007,$FFFFFC00,$00000000,$00000000,$00000000,$00000000,$00000000
dc.l $0001FFFF,$FF000000,$00000000,$00000000,$00000000,$00000000,$00000000,$00000000
dc.l $00000000,$00000000,$00000000,$00000000,$00000000,$00000007,$FFFFF800,$00000000
dc.l $00000000,$00000000,$00000000,$00000000,$0001FFFF,$FF000000,$00000000,$00000000
dc.l $00000000,$00000000,$00000000,$00000000,$00000000,$00000000,$00000000,$00000000
dc.l $00000000,$0000000F,$FFFFF800,$00000000,$00000000,$00000000,$00000000,$00000000
dc.l $0001FFFF,$FE000000,$00000000,$00000000,$00000000,$00000000,$00000000,$00000000
dc.l $00000000,$00000000,$00000000,$00000000,$00000000,$0000000F,$FFFFF000,$00000000
dc.l $00000000,$00000000,$00000000,$00000000,$0001FFFF,$FE000000,$00000000,$00000000
dc.l $00000000,$00000000,$00000000,$00000000,$00000000,$00000000,$00000000,$00000000
dc.l $00000000,$00000007,$FFFFE000,$00000000,$00000000,$00000000,$00000000,$00000000
dc.l $0001FFFF,$FC000000,$00000000,$00000000,$00000000,$00000000,$00000000,$00000000
dc.l $00000000,$00000000,$00000000,$00000000,$00000000,$00000007,$FFFFE000,$00000000
dc.l $00000000,$00000000,$00000000,$00000000,$0001FFFF,$F8000000,$00000000,$00000000
dc.l $00000000,$00000000,$00000000,$00000000,$00000000,$00000000,$00000000,$00000000
dc.l $00000000,$00000007,$FFFFC000,$00000000,$00000000,$00000000,$00000000,$00000000
dc.l $0000FFFF,$F0000000,$00000000,$00000000,$00000000,$00000000,$00000000,$00000000
dc.l $00000000,$00000000,$00000000,$00000000,$00000000,$00000003,$FFFF8000,$00000000
dc.l $00000000,$00000000,$00000000,$00000000,$0000FFFF,$F0000000,$00000000,$00000000
dc.l $00000000,$00000000,$00000000,$00000000,$00000000,$00000000,$00000000,$00000000
dc.l $00000000,$00000001,$FFFF0000,$00000000,$00000000,$00000000,$00000000,$00000000
dc.l $00007FFF,$C0000000,$00000000,$00000000,$00000000,$00000000,$00000000,$00000000
dc.l $00000000,$00000000,$00000000,$00000000,$00000000,$00000000,$FFFE0000,$00000000
dc.l $00000000,$00000000,$00000000,$00000000,$00003FFF,$80000000,$00000000,$00000000
dc.l $00000000,$00000000,$00000000,$00000000,$00000000,$00000000,$00000000,$00000000
dc.l $00000000,$00000000,$7FF80000,$00000000,$00000000,$00000000,$00000000,$00000000
dc.l $00000FFF,$00000000,$00000000,$00000000,$00000000,$00000000,$00000000,$00000000
dc.l $00000000,$00000000,$00000000,$00000000,$00000000,$00000000,$0FE00000,$00000000
dc.l $00000000,$00000000,$00000000,$00000000,$000003FC,$00000000,$00000000,$00000000
dc.l $00000000,$00000000,$00000000,$00000000,$00000000,$00000000,$00000000,$00000000
dc.l $00000000,$00000000,$00000000,$00000000,$00000000,$00000000,$00000000,$00000000
dc.l $00000000,$00000000,$00000000,$00000000,$00000000,$00000000,$00000000,$00000000
dc.l $00000000,$00000000,$00000000,$00000000,$00000000,$00000000,$00000000,$00000000
dc.l $00000000,$00000000,$00000000,$00000000,$00000000,$00000000,$00000000,$00000000
dc.l $00000000,$00000000,$00000000,$00000000,$00000000,$00000000,$00000000,$00000000
dc.l $00000000,$00000000,$00000000,$00000000,$00000000,$00000000,$00000000,$00000000
dc.l $00000000,$00000000,$00000000,$00000000,$00000000,$00000000,$00000000,$00000000
; liste lutins 32x8 pairs
lut0: dc.w $0000,$0000
dc.w $2666,$1E1E,$6666,$1E1E,$E666,$1E1E,$E666,$1E1E
dc.w $E666,$1E1E,$E666,$1E1E,$6666,$1E1E,$2666,$1E1E
flut0:
blk.b NBLG*(flut0-lut0),0
dc.w $0000,$0000 ; fin de liste
; liste lutins 32x8 impairs x4
lut1: dc.w $0000,$0080
dc.w $01FE,$0001,$01FE,$0001,$01FE,$0001,$01FE,$0001
dc.w $01FE,$0001,$01FE,$0001,$01FE,$0001,$01FE,$0001
flut1:
blk.b NBLG*(flut1-lut1),0
dc.w $0000,$0000 ; fin de liste
; liste lutins 32x8 pairs
lut2: dc.w $0000,$0000
dc.w $1998,$0784,$1998,$0786,$1998,$0787,$1998,$0787
dc.w $1998,$0787,$1998,$0787,$1998,$0786,$1998,$0784
flut2:
blk.b NBLG*(flut2-lut2),0 ; 3 autres lutins
dc.w $0000,$0000 ; fin de liste
; liste lutins 32x8 impairs x4
lut3: dc.w $0000,$0080
dc.w $007C,$FFFC,$007E,$FFFE,$007F,$FFFF,$007F,$FFFF
dc.w $007F,$FFFF,$007F,$FFFF,$007E,$FFFE,$007C,$FFFC
flut3:
blk.b NBLG*(flut3-lut3),0 ; 3 autres lutins
dc.w $0000,$0000 ; fin de liste
; liste lutins 16x6 pairs x7
lut4: dc.w $0000,$0000
dc.w $2670,$1E0C,$E673,$1E0F,$E673,$1E0F,$E673,$1E0F
dc.w $E673,$1E0F,$2670,$1E0C
flut4:
blk.b NBLM*(flut4-lut4),0 ; 6 autres lutins
dc.w $0000,$0000 ; fin de liste
; liste lutins 16x6 impairs x7
lut5: dc.w $0000,$0080
dc.w $01FC,$0000,$01FF,$0000,$01FF,$0000,$01FF,$0000
dc.w $01FF,$0000,$01FC,$0000
flut5:
blk.b NBLM*(flut5-lut5),0 ; 6 autres lutins
dc.w $0000,$0000 ; fin de liste
; liste lutins 16x4 pairs x11
lut6: dc.w $0000,$0000
dc.w $6300,$1F00,$E300,$1F00,$E300,$1F00,$6300,$1F00
flut6:
blk.b NBLP*(flut6-lut6),0 ; 11 autres lutins
dc.w $0000,$0000 ; fin de liste
; liste lutins 16x4 impairs x11
lut7: dc.w $0000,$0080
dc.w $0080,$0000,$00C0,$0000,$00C0,$0000,$0080,$0000
flut7:
blk.b NBLP*(flut7-lut7),0 ; 11 autres lutins
dc.w $0000,$0000 ; fin de liste
; liste copper principale
even
copper0: blk.b 8192,0 ; a modifier par un allocmem()
fcopper0:
even
nulblt: dc.w 0 ; sert pour une operation Blitter de lancement IRQ
even
copperv: blk.b 24,0 ; liste copper vide (ecran noir)
planbob0: blk.w (WS/16)*HS*NBP,$0000 ; reservation memoire plans de bits ecran des BOB : trame paire
planbob1: blk.w (WS/16)*HS*NBP,$0000 ; reservation memoire plans de bits ecran des BOB : trame impaire
end
|
|