Obligement - L'Amiga au maximum

Samedi 15 août 2026 - 23:48  

Translate

En De Nl Nl
Es Pt It Nl


Rubriques

Actualité (récente)
Actualité (archive)
Comparatifs
Dossiers
Entrevues
Matériel (tests)
Matériel (bidouilles)
Points de vue
En pratique
Programmation
Reportages
Quizz
Tests de jeux
Tests de logiciels
Tests de compilations
Trucs et astuces
Articles divers

Articles in English


Réseaux sociaux

Suivez-nous sur Mastodon




Liste des jeux Amiga

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


Trucs et astuces

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


Glossaire

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


Galeries

Menu des galeries

BD d'Amiga Spécial
Caricatures Dudai
Caricatures Jet d'ail
Diagrammes de Jay Miner
Images insolites
Fin de jeux (de A à E)
Fin de Jeux (de F à O)
Fin de jeux (de P à Z)
Galerie de Mike Dafunk
Logos d'Obligement
Pubs pour matériels
Systèmes d'exploitation
Trombinoscope Alchimie 7
Vidéos


Téléchargement

Documents
Jeux
Logiciels
Magazines
Divers


Liens

Associations
Jeux
Logiciels
Matériel
Magazines et médias
Pages personnelles
Réparateurs
Revendeurs
Scène démo
Sites de téléchargement
Divers


Partenaires

Annuaire Amiga

Amedia Computer

Relec


A Propos

A propos d'Obligement

A Propos


Contact

David Brunet

Courriel

 


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 :
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).

Blitter
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 :

Blitter

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".

Blitter
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.

Blitter
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 :
  1. Création de masques.
  2. Détermination des minterms.
  3. Les modulos.
  4. Intégration du mode entrelacé.
  5. Les masques en mode entrelacé.
  6. 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).

Blitter
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é.

Blitter
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.

Blitter
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.

Blitter
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 :
  1. Synchronisation verticale avec le balayage du moniteur.
  2. Gestion du double tampon vidéo.
  3. Rétablissement du décor sous les BOB.
  4. Calcul des nouvelles coordonnées des BOB.
  5. Affichage des BOB.
  6. 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 :

(ABSCISSE BOB)*4

...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.

Blitter

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


[Retour en haut] / [Retour aux articles] [Article précédent]