--- /dev/null
+
+; TURMITES (c) F.Fleuret 28/11/89
+; version assembleur AMIGA
+
+; opt d+ ; option d'assemblage (sauve les labels)
+
+ExecBase=4
+
+OldOpenLibrary=-408
+CloseLibrary=-414
+Forbid=-132
+AllocMem=-198
+FreeMem=-210
+FindTask=-294
+WaitPort=-384
+GetMsg=-372
+ReplyMsg=-378
+
+DisplayAlert equ -90
+
+pr_CLI=$AC
+pr_MsgPort=$5C
+
+Frequence = 500
+
+ntur equ 1024 ; nombre maximum de turmites
+
+X equ 0 ; abscisse
+Y equ 2 ; ordonnée
+E equ 4 ; état
+O equ 6 ; orientation
+V equ 8 ; niveau d'énergie
+Table equ 10 ; table de comportement
+
+ndatas equ 58
+
+Startup:
+ sub.l a1,a1
+ move.l ExecBase,a6
+ jsr FindTask(a6)
+ move.l d0,a2
+ tst.l pr_CLI(a2)
+ bne.s FromCLI
+
+ lea pr_MsgPort(a2),a0
+ jsr WaitPort(a6)
+ lea pr_MsgPort(a2),a0
+ jsr GetMsg(a6)
+ move.l d0,WBMsg
+
+FromCLI:
+
+; On réserve de la mémoire en CHIP-RAM pour les bitplanes,
+; les sprites et la copper-list. (l'ami Thomas va etre heureux !)
+
+ move.l ExecBase,a6
+ move.l #$8000*4+256*8+32*2,d0
+ move.l #$10002,d1 ; CHIP et CLEAR
+ jsr AllocMem(a6)
+
+ move.l d0,plan1 ; premier bitplan
+ beq alerte ; si pas de chip reservée !
+ add.l #$8000,d0
+ move.l d0,plan2 ; second bitplan
+ add.l #$8000,d0
+ move.l d0,SaveImage ; zone de sauvegarde
+ add.l #$10000,d0
+ move.l d0,copper_list ; copper-list
+ add.l #256,d0
+ move.l d0,SpriteCursor ; et les sprites
+ add.l #256,d0
+ move.l d0,SpriteVide
+ add.l #256,d0
+ move.l d0,SpriteSelect
+ add.l #256,d0
+ move.l d0,SpriteTableau
+ add.l #1024,d0
+ move.l d0,SpriteNombre
+
+ bsr main ; LA routine
+
+; On rend la mémoire
+
+ move.l ExecBase,a6
+ move.l plan1,a1
+ move.l #$8000*4+256*8+32*2,d0
+ jsr FreeMem(a6)
+
+EmergencyReturn:
+ move.l WBMsg(pc),d0
+ beq.s More
+ move.l d0,a1
+ jsr Forbid(a6)
+ jsr ReplyMsg(a6)
+More:
+ moveq #0,d0
+ rts
+
+WBMsg: dc.l 0
+
+
+alerte:
+ lea IntuitionName(pc),a1
+ move.l (ExecBase).w,a6
+ jsr OldOpenLibrary(a6)
+ move.l d0,a6
+
+ lea TexteAlerte(pc),a0
+ moveq #0,d0
+ move.l #32,d1
+ jsr DisplayAlert(a6)
+
+ move.l a6,a1
+ move.l (ExecBase).w,a6
+ jsr CloseLibrary(a6)
+ bra EmergencyReturn
+
+TexteAlerte:
+ dc.b 0,32,18," Turmites meditation: pas assez de CHIP ! ",0,0
+ even
+
+
+; ************************************************************
+; ************************************************************
+; ************* Voila le coeur du programme !!! *************
+; ************************************************************
+; ************************************************************
+
+main:
+
+ bsr save_all ; sauve tout pour pouvoir revenir
+ bsr Inits ; initialise les registres hard
+
+ lea TableAdan,a1 ; copie le tableau de la première turmite
+ bsr BigStart
+ clr.w FlagQuit
+
+MainBoucle:
+
+ clr.w VblFlag
+ bsr turmites
+synchro:
+ tst.w VblFlag
+ beq synchro
+
+ bsr AfficheNombre ; routine pour afficher le nombre de turmites
+ bsr GetKey ; routine de lecture clavier
+ tst.w d0
+ bmi pasdetouche
+ tst.b d0 ; si appuie et pas relache, on ne fait rien
+ bmi pasdetouche
+ and.w #$7f,d0
+
+; A Nutrition automatique
+; P Pause
+; I Informations
+; 1-2-3-4 Changement de couleur de nourriture
+; Q Quitter
+; R Reset (repart avec turmite actuelle)
+; F Suivre la turmite sélectionnée
+; T Mode tuer
+; S Mode sélection
+; M Mémorise l'image actuelle
+; f1-f2-f3-f4 Reconstruit terrain en blocs
+; f5 Remplie le terrain
+; f6 Ramène l'image sauvée
+
+ cmp.w #$10,d0 ; "A"
+ bne PasAuto
+ not.w FlagAuto
+ eor.b #2,$bfe001
+PasAuto:
+
+ cmp.w #$21,d0 ; "S"
+ bne PasModeSelection
+ move.w #-1,ModeDroite
+ move.l SpriteCursor,a0
+ lea ImageCursor,a1
+ bsr InitSprites ; copie les données bitmap du sprite 'selection'
+PasModeSelection:
+
+ cmp.w #$14,d0 ; "T"
+ bne PasModeTuer
+ clr.w ModeDroite
+ move.l SpriteCursor,a0
+ lea ImageTuer,a1
+ bsr InitSprites ; copie les données bitmap du sprite 'tuer'
+PasModeTuer:
+
+ cmp.w #$23,d0 ; "F"
+ bne PasSuivre
+ not.w FlagSuivre ; commute le flag
+ bra ApresKeys
+PasSuivre:
+
+ cmp.w #$55,d0 ; "f6"
+ bne Pasf6
+ bsr AfficheImage
+ bra ApresKeys
+Pasf6:
+
+ cmp.w #$29,d0 ; "M"
+ bne PasRameneImage
+ move.l plan1,a0
+ move.l SaveImage,a1
+ move.w #16383,d0
+RameneImage:
+ move.l (a0)+,(a1)+
+ dbf d0,RameneImage
+ bra ApresKeys
+PasRameneImage:
+
+ cmp.w #$50,d0 ; "f1" à "f4"
+ bmi Pasfx
+ cmp.w #$54,d0
+ bpl Pasfx
+ sub.w #$50-5,d0
+ move.w #1,d1
+ lsl.w d0,d1
+ move.w d1,d0
+ bsr DrawWorld ; redessine le terrain
+ bra ApresKeys
+Pasfx:
+
+ cmp.w #$54,d0 ; "f5"
+ bne Pasf5
+ bsr ClearWorld ; vide avec la couleur en cours
+ bra ApresKeys
+Pasf5:
+
+ cmp.b #$19,d0 ; "P"
+ bne PasPause
+ not.w FlagPause ; commute le flag
+ bra ApresKeys
+PasPause:
+
+ cmp.b #$20,d0 ;"Q"
+ bne PasQuit
+ move.w #-1,FlagQuit ; personnellement, je suis contre, mais
+ bra ApresKeys ; les meilleurs choses ont une fin...
+PasQuit:
+
+ move.w d0,d1 ; "1" à "4"
+ sub.w #1,d1
+ bmi PasColors
+ cmp.w #4,d1
+ bpl PasColors
+ move.w d1,Color ; change la couleur en cours
+ add.w d1,d1
+ move.w CouleursSouris(pc,d1.w),$dff180+18*2
+ bra ApresKeys
+CouleursSouris:
+ dc.w $000,$f00,$00f,$ec0 ; noir, rouge, bleu, jaune.
+PasColors:
+
+ cmp.w #$17,d0 ; "I"
+ bne PasAffiche
+ bsr ClearTableau
+ not.w FlagAffiche ; commute le flag de l'affichage
+ tst.w FlagAffiche
+ beq ApresKeys
+ bsr AfficheCerveau ; si mode affiche
+ bra ApresKeys
+PasAffiche:
+
+ cmp.w #$13,d0 ; "R"
+ bne PasReset
+ tst.w nombre
+ beq ResetComplet ; si toutes mortes, on repart du début
+ tst.l AdrSelect
+ beq PasReset
+ move.l AdrSelect,a1
+ lea Table(a1),a1
+ bsr BigStart ; reprend au début
+ bra ApresKeys
+ResetComplet:
+ lea TableAdan,a1 ; copie le tableau de la première turmite
+ bsr BigStart
+ bra ApresKeys
+PasReset:
+
+ApresKeys:
+pasdetouche:
+
+ tst.w FlagAuto
+ beq PasDejeuner
+ add.w #1,CompteurFreq
+ cmp.w #Frequence,CompteurFreq
+ bne PasDejeuner
+ bsr AfficheImage
+ clr.w CompteurFreq
+PasDejeuner:
+
+
+ btst #6,$bfe001 ; test de la touche gauche de la souris
+ bne PasMouseKey
+ bsr Paves ; routine qui affiche la nourriture
+PasMouseKey:
+
+ tst.w FlagAffiche ; le mode affichage y-est-il ?
+ beq PasNouveau
+ move.l AdrSelect,d0
+ cmp.l PAdrSelect,d0 ; la turmite a-t-elle changé ?
+ beq PasNouveau
+ move.l AdrSelect,PAdrSelect ; mémorise la nouvelle turmite
+ bsr AfficheCerveau
+PasNouveau:
+
+ tst.w FlagQuit ; veut-on quitter ?
+ beq MainBoucle
+
+ and.b #253,$bfe001
+ bsr restore_all ; remet tout en place
+ moveq #0,d0 ; et revient
+ rts
+
+VblFlag: dc.w 0 ; flag de synchronisation VBL
+ModeDroite: dc.w -1 ; role du bouton droit souris (select/tuer)
+FlagAuto: dc.w 0 ; flag pour la nutrition auto.
+CompteurFreq: dc.w 0 ; Compteur pour la nutrition
+FlagPause: dc.w 0 ; flag pour le mode pause
+FlagSuivre: dc.w 0 ; flag pour 'follow'
+FlagQuit: dc.w 0 ; flag pour quitter
+FlagAffiche: dc.w 0 ; flag pour l'affichage du tableau
+PAdrSelect: dc.l 0 ; turmite actuellement affichée
+Color: dc.w 2 ; couleur de la nourriture actuelle
+
+
+; **********************************************************
+; ********* Affichage du nombre de turmites à l'écran ******
+; **********************************************************
+
+AfficheNombre:
+ move.w nombre,d0
+ lea TableCarChiffres,a4 ; table des caractères numériques
+ divu #10,d0 ; utilise le reste d'une division par 10
+ swap d0
+ lsl.w #4,d0
+ lea (a4,d0.w),a1
+ clr.w d0
+ swap d0
+ divu #10,d0
+ swap d0
+ lsl.w #4,d0
+ lea (a4,d0.w),a2
+ clr.w d0
+ swap d0
+ divu #10,d0
+ swap d0
+ lsl.w #4,d0
+ lea (a4,d0.w),a3
+ clr.w d0
+ swap d0
+ divu #10,d0
+ swap d0
+ lsl.w #4,d0
+ lea (a4,d0.w),a4
+
+ move.l SpriteNombre,a0 ; adresse des datas de ce sprite
+ lea 4(a0),a0 ; datas bitmap
+ move.w #5,d0 ; caractères de 6 lignes
+BoucleAfficheNombre: ; recopie les caractères de la table
+ move.w (a4)+,d1 ; dans le sprite.
+ lsl.w #5,d1
+ or.w (a3)+,d1
+ move.w d1,(a0)
+ clr.w 2(a0)
+ move.w (a2)+,d1
+ lsl.w #5,d1
+ or.w (a1)+,d1
+ lsl.w #6,d1
+ move.w d1,32(a0)
+ clr.w 34(a0)
+ add.l #4,a0
+ dbf d0,BoucleAfficheNombre
+ rts
+
+
+; **********************************************************
+; *** Routine d'initialisation de la table des turmites ****
+; **********************************************************
+
+BigStart:
+ lea DataTurmites,a0
+ lea AdressesLibres,a5 ; constitue la table des adresses libres
+ move.w #ntur-1,d0
+RempliePile:
+ clr.w V(a0)
+ move.l a0,-(a5)
+ add.l #ndatas,a0
+ dbf d0,RempliePile
+
+ move.l (a5)+,a0 ; initialise la première turmite
+ move.l a5,SPtur
+ move.w #255,X(a0)
+ move.w #255,Y(a0)
+ move.w #0,E(a0)
+ move.w #0,O(a0)
+ move.w #1,V(a0)
+ lea Table(a0),a0
+ move.w #(ndatas-Table)/2-1,d0
+BoucleBigStart:
+ move.w (a1)+,(a0)+
+ dbf d0,BoucleBigStart
+
+ move.w #256,d0
+ bsr DrawWorld ; affiche le décors avec un bloc central de 256
+
+ clr.l AdrSelect ; on vire la sélection et l'affichage
+ clr.w FlagAffiche
+ bsr ClearTableau
+
+ rts
+
+; **********************************************************
+; ******* Routine d'affichage des paves de nourriture ******
+; **********************************************************
+
+Paves:
+ move.w Xmousew,d0 ; si on dépasse à droite alors on corrige
+ cmp.w #498,d0
+ bmi PasPavesDroite
+ move.w #497,d0
+PasPavesDroite:
+ move.w d0,d4
+ and.w #$0f,d4 ; masque pour le décalage
+ move.w Ymousew,d1
+ cmp.w #497,d1 ; test le dépassement en bas
+ bmi PasPavesBas
+ move.w #496,d1
+PasPavesBas:
+ ; calcul de l'adresse en mémoire vidéo
+ lsl.w #6,d1 ; 64 octets par ligne (512 points)
+ lsr.w #3,d0 ; on divise X par 8
+ and.w #$fffe,d0 ; force une adresse paire
+ add.w d1,d0 ; X+Y
+ move.l plan1,a0 ; + base de la mémoire
+ lea (a0,d0),a0
+ move.l plan2,a1 ; idem plan 2
+ lea (a1,d0),a1
+
+ move.l #$ffff0000,d0 ; dessin du bloc
+ lsr.l d4,d0 ; avec décalage
+ not.l d0 ; et masque
+
+ move.w Color,d1
+ clr.l d2 ; dessin pour le plan 1
+ clr.l d3 ; dessin pour le plan 2
+
+ ; on modifie d2 et d3 en fonction des bits de la couleur
+ btst #0,d1
+ beq PasPlan0
+ move.l d0,d2
+ not.l d2
+PasPlan0:
+ btst #1,d1
+ beq PasPlan1
+ move.l d0,d3
+ not.l d3
+PasPlan1:
+
+ move.w #15,d4 ; blocs de 16 lignes de haut
+BouclePaves:
+ and.l d0,(a0)
+ or.l d2,(a0)
+ add.l #64,a0
+ and.l d0,(a1)
+ or.l d3,(a1)
+ add.l #64,a1
+ dbf d4,BouclePaves
+FinPaves:
+ rts
+
+; **********************************************************
+; *********** Routine d'affichage d'un 'Cerveau' ***********
+; **********************************************************
+
+AfficheCerveau:
+ movem.l d0-a6,-(sp)
+ tst.l AdrSelect ; y a-t-il une turmite sélectionnée ?
+ beq PasCerveau ; si non, alors ne rien faire
+
+ move.l SpriteTableau,a0 ; sprite pour afficher le tableau
+ lea 4(a0),a0 ; adresse des données bitmap du sprite
+ move.l AdrSelect,a1 ; adresse de la turmite sélectionnée
+ lea Table(a1),a1 ; adresse de son tableau de comportement
+ move.w #3,d0 ; 4 états
+BoucleEtat:
+ move.w #3,d1 ; et 4 couleurs par état
+BoucleCouleur:
+ move.b (a1)+,d3
+ add.b #1,d3
+ ext.w d3
+ lsl.w #4,d3
+ lea TableCarDirections,a2 ; table des caractères (g/a/d)
+ lea (a2,d3.w),a2
+ move.b (a1)+,d3
+ ext.w d3
+ lsl.w #4,d3
+ lea TableCarEtats,a3 ; table des caractères états (A/B/C/D)
+ lea (a3,d3.w),a3
+ move.b (a1)+,d3
+ ext.w d3
+ lsl.w #4,d3
+ lea TableCarChiffres,a4 ; chiffres (0/1/2/3...)
+ lea (a4,d3.w),a4
+
+ move.w #5,d2
+BoucleCar:
+ moveq #0,d3
+ or.w (a2)+,d3
+ or.w (a3)+,d3
+ or.w (a4)+,d3
+ move.w d3,(a0)+
+ clr.w (a0)+
+ dbf d2,BoucleCar
+ add.w #256-24,a0
+ dbf d1,BoucleCouleur
+ add.w #28-256*4,a0
+ dbf d0,BoucleEtat
+
+PasCerveau:
+ movem.l (sp)+,d0-a6
+ rts
+
+ClearTableau: ; vide la bitmap du sprite tableau
+ movem.l d0/a0,-(sp)
+ move.l SpriteTableau,a0
+ lea 4(a0),a0
+ move.w #55,d0
+BoucleClearTableau:
+ clr.w 256(a0)
+ clr.w 512(a0)
+ clr.w 768(a0)
+ clr.w (a0)+
+ dbf d0,BoucleClearTableau
+ movem.l (sp)+,d0/a0
+ rts
+
+; **********************************************************
+; **** Routine de gestion des déplacements des turmites ****
+; **********************************************************
+
+nombre: dc.w 0
+
+turmites:
+ clr.w nombre ; vide le nombre
+ lea DataTurmites,a0 ; tableau des turmites
+ move.l SPtur,a5 ; pile des adresses libres
+ move.l plan1,a4 ; base mémoire vidéo plan 1
+ move.l plan2,a3 ; base mémoire vidéo plan 2
+ move.l #ntur-1,d0 ; nombre de turmites
+boucle:
+
+ tst.w V(a0) ; est-elle en vie ?
+ beq finboucle ; si non, sniff...
+
+ add.w #1,nombre ; une de plus en vie !
+
+ move.w X(a0),d1
+ move.w Y(a0),d2
+
+ move.w Xmousew,d3 ; est-elle sous la souris ?
+ sub.w d1,d3
+ bpl PasAbs1
+ neg.w d3
+PasAbs1:
+ cmp.w #8,d3
+ bpl PasSousMouse
+
+ move.w Ymousew,d3
+ sub.w d2,d3
+ bpl PasAbs2
+ neg.w d3
+PasAbs2:
+ cmp.w #8,d3
+ bpl PasSousMouse
+ btst #10,$dff016 ; POTGOR
+ bne PasSousMouse
+
+; elle est sous la souris
+
+ tst.w ModeDroite
+ beq ModeTuer
+ModeSelection: ; si mode sélection, mémorise son adresse
+ move.l a0,AdrSelect
+ bra PasSousMouse
+ModeTuer:
+ clr.w V(a0) ; si mode tuer, on la desintègre
+ move.l a0,-(a5) ; nouvelle adresse libre dans la pile
+ cmp.l AdrSelect,a0 ; si c'était elle qui était sélectionnée
+ bne finboucle
+ clr.l AdrSelect ; elle ne l'est plus
+ clr.w FlagSuivre ; le mode follow dégage
+ clr.w FlagAffiche ; le tableau disparait
+ bsr ClearTableau ; il faut l'effacer
+ bra finboucle
+PasSousMouse:
+
+ tst.w FlagPause ; est-on en mode pause
+ bne finboucle ; si oui, on ne fait pas les mouvements
+
+ move.w d1,d3 ; si non
+ lsl.w #6,d2
+ lsr.w #3,d3
+ add.w d3,d2 ; d2 adr dans le bitplan
+ not.w d1
+ and.w #7,d1
+
+ moveq #0,d3 ; d3 couleur de la case sous la turmite
+ btst d1,(a4,d2.w) ; on test les bits en mémoire vidéo
+ beq bit0nul
+ or.w #1,d3
+bit0nul:
+ btst d1,(a3,d2.w)
+ beq bit1nul
+ or.w #2,d3
+bit1nul:
+ add.w d3,V(a0)
+
+; calcul de l'adresse de la case dans le tableau de comportement
+
+ move.w d3,d4 ; d3=d3*3 (pour la colonne, 3 octets par case)
+ add.w d3,d3
+ add.w d4,d3
+
+ move.w E(a0),d4 ; d4=état*12 (pour la ligne, 12 octets par ligne)
+ add.w d4,d4
+ add.w d4,d4
+ add.w d4,d3
+ add.w d4,d4
+ add.w d4,d3
+ move.w d3,d4
+
+ lea Table(a0,d4),a1
+ move.b 1(a1),E+1(a0) ; nouvel état
+ move.b 0(a1),d3
+ add.b d3,O+1(a0)
+ and.b #3,O+1(a0) ; nouvelle direction
+ moveq #0,d3
+ move.b 2(a1),d3 ; couleur à mettre sous la turmite avant de partir
+
+bit0d: ; le plot pour afficher la turmite
+ btst #0,d3 ; surement optimisable...
+ beq bit0dnul
+bit0dnnul:
+ bset d1,(a4,d2.w)
+ bra bit1d
+bit0dnul:
+ bclr d1,(a4,d2.w)
+bit1d:
+ btst #1,d3
+ beq bit1dnul
+bit1dnnul:
+ bset d1,(a3,d2.w)
+ bra finbitd
+bit1dnul:
+ bclr d1,(a3,d2.w)
+finbitd:
+
+PasPlot:
+ sub.w #1,V(a0) ; elle se fatigue
+ sub.w d3,V(a0) ; et perd la valeur de ce qu'elle met sur la case
+ bgt PasMorte ; est-elle morte de fatigue ?
+Morte:
+ clr.w V(a0) ; la vie est dure au pays des turmites
+ move.l a0,-(a5) ; nouvelle adresse libre dans la pile
+ cmp.l AdrSelect,a0 ; si c'était elle qui était sélectionnée
+ bne finboucle
+ clr.l AdrSelect ; elle ne l'est plus
+ clr.w FlagSuivre ; le mode follow dégage
+ clr.w FlagAffiche ; le tableau disparait
+ bsr ClearTableau ; il faut l'effacer
+ bra finboucle
+PasMorte:
+ move.w O(a0),d1 ; sinon, mouvement
+ btst #0,d1
+ bne DeplaceHoriz
+
+DeplaceVert:
+ btst #1,d1
+ bne Monte
+ add.w #1,Y(a0)
+ and.w #511,Y(a0) ; limite à 512 points en hauteur
+ bra FinDeplace
+Monte:
+ sub.w #1,Y(a0)
+ and.w #511,Y(a0)
+ bra FinDeplace
+
+DeplaceHoriz:
+ btst #1,d1
+ bne Gauche
+ add.w #1,X(a0)
+ and.w #511,X(a0) ; limite à 512 points en largeur
+ bra FinDeplace
+Gauche:
+ sub.w #1,X(a0)
+ and.w #511,X(a0)
+
+FinDeplace:
+ cmp.w #128,V(a0) ; a-t-elle suffisament d'énergie pour se reproduire ?
+ bmi finboucle ; non
+Duplique:
+ lsr.w V(a0) ; elle perd de l'énergie
+ cmp.l #AdressesLibres,a5 ; y-a-t-il de la place ?
+ beq finboucle ; non...
+
+ move.l (a5),a1
+
+ move.l a0,a2
+ rept ndatas/2 ; recopie son tableau dans son descendant
+ move.w (a2)+,(a1)+
+ endr
+
+ move.l (a5)+,a2
+
+; **** Mutations ****
+
+ move.w #3,d6
+aleatoire:
+ ; d3 et d4 = random(256)
+
+ move.w CompteurRnd,d4
+ add.l #$87654321,d4
+ move.l d4,d5
+ add.l d5,d5
+ add.l d5,d4
+ move.l d4,CompteurRnd
+
+ move.w CompteurRnd,d3
+ add.l #$87654321,d3
+ move.l d3,d5
+ add.l d5,d5
+ add.l d5,d3
+ move.l d3,CompteurRnd
+
+ move.w d4,d5
+ lsr.w #2,d5
+ and.w #15,d5 ; 16 cases possibles dans le tableau
+ move.w d5,d1 ; *3 car 3 octets par case
+ add.w d5,d5
+ add.w d1,d5
+ lea Table(a2,d5.w),a1
+
+ and.w #3,d4
+ cmp.w #1,d4 ; modifie-t-on la direction ?
+ bne PasDir ; si non...
+ChercheRnd3:
+ move.w CompteurRnd,d3
+ add.l #$87654321,d3
+ move.l d3,d5
+ add.l d5,d5
+ add.l d5,d3
+ move.l d3,CompteurRnd
+ and.w #3,d3
+ cmp.w #3,d3
+ beq ChercheRnd3
+ move.b rnd3(pc,d3),0(a1)
+ bra finaleatoire
+rnd3: dc.b -1,0,1,0
+PasDir:
+ and.w #3,d3 ; modifie-t-on l'état ?
+ cmp.w #2,d4 ; si non...
+ bne PasEta
+ move.b d3,1(a1)
+ bra finaleatoire
+PasEta:
+ cmp.w #3,d4 ; modifie-t-on la couleur ?
+ bne aleatoire ; si non, on revient au début
+ move.b d3,2(a1)
+finaleatoire:
+ dbf d6,aleatoire ; et on fait ça 4 fois
+
+finboucle:
+
+ add.l #ndatas,a0 ; turmite suivante
+ dbf d0,boucle
+ move.l a5,SPtur ; sauve le nouveau pointeur
+ rts
+
+CompteurRnd: dc.l 0
+AdrSelect: dc.l 0
+
+; ******************************************************
+; *********** Routine de traçage du terrain ************
+; ******************************************************
+
+; D0=Largeur du coté (32/64/128/256)
+
+DrawWorld:
+ movem.l d0-a6,-(sp)
+
+ move.l plan1,a0 ; bases des bitplanes
+ move.l plan2,a1
+ moveq #0,d1
+ moveq #0,d2
+ move.w #$1fff,d3 ; tout d'abord, on efface
+ClearScreen:
+ move.l d1,(a0)+
+ move.l d2,(a1)+
+ dbf d3,ClearScreen
+
+ move.w d0,d1 ; calcul de l'adresse de début, on passe
+ move.w d0,d2 ; des octets pour la marge de gauche.
+ lsl.w #5,d1
+ lsr.w #4,d2
+ add.w d2,d1
+ move.l plan1,a0
+ move.l plan2,a1
+ add.w d1,a0
+ add.w d1,a1
+
+ bsr ChoixBits ; voire ci-dessous
+
+ move.l #512,d3 ; combien de carrés ?
+ divu d0,d3 ; un DIVU ne peut pas faire de mal
+ lsr.w #1,d3 ; (enfin, pas trop de mal...)
+ sub.w #1,d3
+ move.w d3,a2
+
+ move.w d0,d3
+ sub.w #1,d3
+ move.w d3,a3
+
+ move.w d0,d6
+ lsr.w #4,d6
+ sub.w #1,d6
+ lsl.w #6,d0
+
+ move.w a2,d4 ; boucle verticale des carrés
+DWboucleV:
+ move.w a2,d5 ; idem horizontale
+DWboucleH:
+
+ move.w a3,d3 ; les boucles pour UN carré
+DWpetiteboucleV:
+ move.w d6,d7
+DWpetiteboucleHfill:
+ move.w d1,(a0)+
+ move.w d2,(a1)+
+ dbf d7,DWpetiteboucleHfill
+ move.w d6,d7
+DWpetiteboucleHclear:
+ clr.w (a0)+
+ clr.w (a1)+
+ dbf d7,DWpetiteboucleHclear
+ dbf d3,DWpetiteboucleV
+
+ dbf d5,DWboucleH
+ add.w d0,a0
+ add.w d0,a1
+ dbf d4,DWboucleV
+ movem.l (sp)+,d0-a6
+ rts
+
+
+ClearWorld: ; remplie l'écran avec la couleur en cours
+ movem.l d0-a6,-(sp)
+ move.l plan1,a0
+ move.l plan2,a1
+ bsr ChoixBits
+ move.w #$3fff,d3
+ClearScreen2:
+ move.w d1,(a0)+
+ move.w d2,(a1)+
+ dbf d3,ClearScreen2
+ movem.l (sp)+,d0-a6
+ rts
+
+
+
+AfficheImage:
+ move.l SaveImage,a0
+ move.l plan1,a1
+ move.w #16383,d0
+SauveImage:
+ move.l (a0)+,(a1)+
+ dbf d0,SauveImage
+ rts
+
+
+ChoixBits: ; la routine qui détermine les mots en
+ moveq #0,d1 ; fonction des bits de la couleur
+ moveq #0,d2
+ move.w Color,d3
+ btst #0,d3
+ beq PasCls0
+ move.w #-1,d1
+PasCls0:
+ btst #1,d3
+ beq PasCls1
+ move.w #-1,d2
+PasCls1:
+ rts
+
+
+; ******************************************************
+; ******************* Initialisations ******************
+; ******************************************************
+
+Inits:
+ lea $dff000,a6
+
+ move.w #$7fff,$9a(a6) ; INTENA
+ move.w #$7fff,$96(a6) ; DMACON
+ move.w #$c020,$9a(a6) ; IT vbl uniquement
+ move.w #$83a0,$96(a6) ; copper et bitplan
+
+ move.l SpriteVide,a0
+ clr.l (a0)+
+ clr.l (a0)+
+
+ move.l SpriteTableau,a0 ; positionne les sprites
+ move.w #$2e50,(a0)
+ move.w #$4a00,2(a0)
+ move.w #$2e58,256(a0)
+ move.w #$4a00,256+2(a0)
+ move.w #$2e60,512(a0)
+ move.w #$4a00,512+2(a0)
+ move.w #$2e68,768(a0)
+ move.w #$4a00,768+2(a0)
+
+ move.l SpriteNombre,a0
+ move.w #$2ec2,(a0)
+ move.w #$3400,2(a0)
+ move.w #$2eca,32(a0)
+ move.w #$3400,34(a0)
+
+ move.l SpriteCursor,a0
+ lea ImageCursor,a1
+ bsr InitSprites
+ move.l SpriteSelect,a0
+ lea ImageSelect,a1
+ bsr InitSprites
+
+ move.l copper_list,a0
+
+ move.l #$00e00000,(a0)+ ; la copper-list met les pointeurs
+ move.l #$00e20000,(a0)+ ; bitplanes
+ move.l #$00e40000,(a0)+
+ move.l #$00e60000,(a0)+
+ move.l #$01020000,(a0)+
+ move.l #$fffffffe,(a0)+
+
+; On se met en 256*256 2 bitplanes (4 couleurs) avec 16 points cachés
+; sur la gauche pour pouvoir faire un scrolling avec le delay.
+
+ move.l copper_list,$80(a6) ; COP1LC
+ clr.w $88(a6) ; COPJMP1
+ move.l #$2ca12ca1,$8e(a6) ; DIWSTRT et DIWSTOP
+ move.w #$2200,$100(a6) ; BPLCON0
+ clr.l $102(a6) ; BPLCON1 et BPLCON2
+ move.w #30,$108(a6) ; BPLMOD1
+ move.w #30,$10a(a6) ; BPLMOD2
+ move.l #$004000c0,$92(a6) ; DDFSTRT et DDFSTOP
+
+ move.l #irq,$6c ; vecteur irq
+
+ move.w #$0024,$dff104 ; priorité des sprites
+ move.w #$555,$dff180+17*2 ; couleurs de ces meme sprites
+ move.w #$00f,$dff180+18*2
+ move.w #$fff,$dff180+19*2
+ move.w #$fff,$dff180+21*2
+ move.w #$fff,$dff180+25*2
+ move.w #$fff,$dff180+29*2
+
+ clr.w $dff180 ; couleur playfield
+ move.w #$f00,$dff182 ; noir, rouge, bleu, jaune
+ move.w #$00f,$dff184
+ move.w #$ec0,$dff186
+ bsr InitClavier ; initialise le clavier
+
+ rts
+
+InitSprites
+ move.w #15,d0
+ clr.l (a0)+
+RecopieSprites:
+ move.l (a1)+,(a0)+
+ dbf d0,RecopieSprites
+ clr.l (a0)+
+ rts
+
+; ********************************************************
+; ******************* Gestion de la souris ***************
+; ********************************************************
+
+Souris:
+ move.b $dff00a,d1 ; abscisse souris (absolue) JOY0DAT
+ move.b d1,d3
+ move.b $dff00b,d0 ; ordonnée souris (absolue) JOY0DAT
+ move.b d0,d2
+
+ sub.b PrecXmouse,d0 ; - précédente abscisse= déplacement relatif
+ cmp.b #127,d0 ; > 127, c'est que l'on a fait un tour complet
+ bmi OkXmouse
+ add.b #255,d0 ; on corrige
+OkXmouse:
+
+ sub.b PrecYmouse,d1 ; idem pour l'ordonnée
+ cmp.b #127,d1
+ bmi OkYmouse
+ add.b #255,d1
+OkYmouse:
+
+ ext.w d0 ; passage en .W (relatif, peut etre négatif)
+ ext.w d1
+ move.b d3,PrecYmouse ; nouvelle coordonnées absolues du système
+ move.b d2,PrecXmouse
+ add.w d0,Xmouse ; ajoute le mouvement relatif aux coordonnées du
+ add.w d1,Ymouse ; programme (qui sont absolues)
+
+ cmp.w #255,Xmouse ; dépasse-t-on à droite ?
+ bmi PasMouseDroite
+ move.w Xmouse,d0 ; si oui, on déplace la fenetre
+ move.w #255,Xmouse ; et on remet la valeur maximum
+ sub.w #255,d0
+ add.w d0,Xwindow
+ bra PasMouseGauche
+PasMouseDroite:
+ tst.w Xmouse ; dépasse-t-on à gauche ?
+ bpl PasMouseGauche
+ move.w Xmouse,d0 ; si oui, on déplace aussi la fenetre
+ clr.w Xmouse ; et on met la valeur minimum
+ add.w d0,Xwindow
+PasMouseGauche:
+ cmp.w #255,Ymouse ; idem pour Y
+ bmi PasMouseBas
+ move.w Ymouse,d0
+ move.w #255,Ymouse
+ sub.w #255,d0
+ add.w d0,Ywindow
+ bra PasMouseHaut
+PasMouseBas:
+ tst.w Ymouse
+ bpl PasMouseHaut
+ move.w Ymouse,d0
+ clr.w Ymouse
+ add.w d0,Ywindow
+PasMouseHaut:
+
+ move.w Xmouse,d0
+ move.w Ymouse,d1
+ add.w #$a0,d0 ; coordonnées translatées dans le cadre écran
+ add.w #$2c,d1
+
+ move.w d1,d2
+ add.w #8,d2 ; Y du bas du sprite
+
+ move.w d0,d3 ; calcul des deux mots de controle en fonction
+ lsr.w #1,d3 ; de HSTART, VSTART et VSTOP
+ move.w d1,d4
+ lsl.w #8,d4
+ move.b d3,d4
+
+ move.b d2,d5
+ lsl.w #8,d5
+ roxl.w #8,d1
+ roxl.b #1,d5
+ roxl.w #8,d2
+ roxl.b #1,d5
+ roxr.b #1,d0
+ roxl.b #1,d5
+
+ move.l SpriteCursor,a0 ; met en place les deux mots de controle
+ move.w d4,(a0)+
+ move.w d5,(a0)
+
+ rts
+
+ImageCursor:
+ dc.w $ff00,$fe00 ; une petit flèche 8*8
+ dc.w $8200,$fc00
+ dc.w $8400,$f800
+ dc.w $8800,$f000
+ dc.w $9000,$e000
+ dc.w $a000,$c000
+ dc.w $c000,$8000
+ dc.w $8000,$0000
+ImageTuer:
+ dc.w $ff00,$ff00 ; un petit carré 8*8
+ dc.w $8100,$fe00
+ dc.w $bd00,$c200
+ dc.w $a500,$c600
+ dc.w $a500,$c600
+ dc.w $bd00,$de00
+ dc.w $8100,$fe00
+ dc.w $ff00,$8000
+ImageSelect:
+ dc.w $d800,$d800 ; une petite mire 8*8
+ dc.w $8800,$8800
+ dc.w $0000,$0000
+ dc.w $8800,$8800
+ dc.w $d800,$d800
+ dc.w $0000,$0000
+ dc.w $0000,$0000
+ dc.w $0000,$0000
+
+Xmouse: dc.w 256
+Ymouse: dc.w 256
+PrecXmouse: dc.w 0
+PrecYmouse: dc.w 0
+Xwindow: dc.w 128
+Ywindow: dc.w 128
+Xmousew: dc.w 384
+Ymousew: dc.w 384
+
+; ******************************************************
+; *************** Routine du 'scrolling' **************
+; ******************************************************
+
+Screen:
+ tst.w FlagSuivre ; est-on-en mode suivie automatique ?
+ beq PasSuivie ; non
+ tst.l AdrSelect ; une turmite est-elle sélectionnée ?
+ beq PasSuivie ; non
+ move.l AdrSelect,a0 ; si oui
+ tst.w V(a0) ; est-elle vivante ?
+ beq PasSuivie ; non
+PasFinSuivre:
+ move.w X(a0),d0 ; prend ses coordonnées
+ sub.w #128,d0 ; centre
+ move.w d0,Xwindow ; et les met dans celles de la fenetre
+ move.w Y(a0),d0
+ sub.w #128,d0
+ move.w d0,Ywindow
+PasSuivie:
+
+ move.w Xwindow,d0 ; on corrige éventuellement les
+ bpl PasWindowGauche ; coordonnées de la fenetre
+ moveq #0,d0
+ move.w d0,Xwindow
+ bra PasWindowDroite
+PasWindowGauche:
+ cmp.w #256,d0
+ bmi PasWindowDroite
+ move.w #256,d0
+ move.w d0,Xwindow
+PasWindowDroite:
+ move.w Ywindow,d1
+ bpl PasWindowHaut
+ moveq #0,d1
+ move.w d1,Ywindow
+ bra PasWindowBas
+PasWindowHaut:
+ cmp.w #256,d1
+ bmi PasWindowBas
+ move.w #256,d1
+ move.w d1,Ywindow
+PasWindowBas:
+
+ move.w Xmouse,Xmousew ; coordonnées absolues de la souris dans
+ add.w d0,Xmousew ; le terrain
+ move.w Ymouse,Ymousew
+ add.w d1,Ymousew
+
+ lsl.w #6,d1 ; calcule de l'adresse de départ des bitplanes
+ move.w d0,d2
+ lsr.w #3,d2
+ and.w #$fffe,d2
+ add.w d2,d1
+ not.w d0
+ and.w #15,d0
+ moveq #0,d2
+ move.w d0,d2
+ lsl.w #4,d0
+ or.w d0,d2
+
+ move.l copper_list,a1 ; met le delay dans la copper-list
+ move.w d2,2+16(a1)
+
+ move.l plan1,a0
+ add.w d1,a0
+ move.l a0,d0
+
+ move.w d0,6(a1) ; met l'adresse dans la copper-list
+ swap d0
+ move.w d0,2(a1)
+ swap d0
+
+ add.l #$8000,d0 ; deuxième bitplan
+ move.w d0,6+8(a1)
+ swap d0
+ move.w d0,2+8(a1)
+
+ moveq #0,d4 ; gestion du sprite curseur de sélection
+ moveq #0,d5
+ move.l AdrSelect,d0
+ beq PasSpriteSelection
+ move.l d0,a0
+ tst.w V(a0)
+ beq PasSpriteSelection
+ move.w X(a0),d0
+ sub.w Xwindow,d0
+ bmi PasSpriteSelection
+ cmp.w #255,d0
+ bpl PasSpriteSelection
+ move.w Y(a0),d1
+ sub.w Ywindow,d1
+ bmi PasSpriteSelection
+ cmp.w #255,d1
+ bpl PasSpriteSelection
+
+ add.w #$9d,d0 ; pareil que pour celui de la souris
+ add.w #$2a,d1
+
+ move.w d1,d2
+ add.w #8,d2
+
+ move.w d0,d3
+ lsr.w #1,d3
+ move.w d1,d4
+ lsl.w #8,d4
+ move.b d3,d4
+
+ move.b d2,d5
+ lsl.w #8,d5
+ roxl.w #8,d1
+ roxl.b #1,d5
+ roxl.w #8,d2
+ roxl.b #1,d5
+ roxr.b #1,d0
+ roxl.b #1,d5
+
+PasSpriteSelection:
+ move.l SpriteSelect,a0
+ move.w d4,(a0)+
+ move.w d5,(a0)
+
+ rts
+
+
+; ******************************************************
+; ****************** Routines de l'IRQ *****************
+; ******************************************************
+
+irq:
+ movem.l d0-a6,-(sp)
+ bsr GereSprites
+ bsr Souris
+ bsr Screen
+ move.w #-1,VblFlag
+ movem.l (sp)+,d0-a6
+ move.w #$20,$dff09c ; it vbl traitée INTREQ
+ rte
+
+; ******************************************************
+; ***** Routine de gestion des sprites (début VBL) *****
+; ******************************************************
+
+GereSprites:
+ move.l SpriteCursor,$dff120 ; SPR0PT
+ move.l SpriteSelect,$dff124 ; SPR1PT
+ move.l SpriteNombre,d0
+ move.l d0,$dff128 ; SPR2PT
+ add.l #32,d0
+ move.l d0,$dff12c ; SPR3PT
+ move.l SpriteTableau,d0 ; 4 sprites pour le tableau
+ move.l d0,$dff130 ; SPR4PT
+ add.l #256,d0
+ move.l d0,$dff134 ; SPR5PT
+ add.l #256,d0
+ move.l d0,$dff138 ; SPR6PT
+ add.l #256,d0
+ move.l d0,$dff13c ; SPR7PT
+ rts
+
+; ******************************************************
+; **************** Routines du clavier *****************
+; ******************************************************
+
+InitClavier:
+ clr.w PointeurClavierRead ; vide les pointeurs du tampon
+ move.w #1,PointeurClavierWrite
+ lea ItClavier(pc),a0 ; en PC-relatif !
+ move.l a0,$68 ; vecteur niveau 2 (clavier)
+ move.b #%10001000,$bfed01 ; ICR, bit SP (fin de transfert série)
+ move.w #$8008,$dff09a ; INTENA (IT CIA-A)
+ rts
+
+ItClavier:
+ movem.l a0/d0/d1,-(sp)
+ move.w $dff01e,d0 ; INTREQ (read: IT CIA-A ?)
+ btst #3,d0
+ beq FinItClavier
+
+ move.b $bfed01,d0
+ btst #3,d0 ; pas clavier
+ beq PasClavier
+ move.w PointeurClavierWrite,d1
+ moveq #0,d0
+ move.b $bfec01,d0
+ or.b #$40,$bfee01
+ not.b d0
+ ror.b #1,d0
+ add.b #1,d1
+ cmp.w PointeurClavierRead,d1
+ beq TamponClavierSature
+ lea TamponClavier(pc),a0
+ move.b d0,(a0,d1.w)
+ move.w d1,PointeurClavierWrite
+TamponClavierSature:
+ and.b #$bf,$bfee01
+PasClavier:
+ move.w #$0008,$dff09c ; INTREQ (IT traitée)
+FinItClavier:
+ movem.l (sp)+,a0/d0/d1
+ rte
+
+GetKey:
+ moveq #0,d0
+ move.l d1,-(sp)
+ move.w PointeurClavierRead,d1 ; pointeur relatif sur le tampon
+ add.b #1,d1 ; touche suivante
+ cmp.w PointeurClavierWrite,d1 ; a-t-on vidé le tampon ?
+ beq NoKey
+ move.b TamponClavier(pc,d1.w),d0 ; si non, on remet le code
+ move.w d1,PointeurClavierRead ; sauve le pointeur
+ move.l (sp)+,d1 ; et on revient
+ rts
+NoKey:
+ not.w d0 ; code d'erreur -1
+ move.l (sp)+,d1
+ rts
+
+PointeurClavierRead: dc.w 0
+PointeurClavierWrite: dc.w 0
+TamponClavier: ds.b 256
+
+
+save_all:
+ move.b #%10000111,$bfd100
+ move.l 4,a6
+ jsr -132(a6)
+ move.l $68,save_vecteur_kbd
+ move.l $6c,save_vecteur_irq
+ move.w $dff01c,save_intena ; INTENA (read)
+ or.w #$c000,save_intena
+ move.w $dff002,save_dmacon ; DMACON (read)
+ or.w #$8100,save_dmacon
+ rts
+
+restore_all:
+ move.w #$7fff,$dff09a ; INTENA (write: clear all)
+ move.w #$7fff,$dff096 ; DMACON (write: clear all)
+ move.l save_vecteur_kbd,$68 ; vecteur IT clavier
+ move.l save_vecteur_irq,$6c ; vecteur IT vbl
+ move.w save_intena,$dff09a ; INTENA (write: remet les bits)
+ move.w save_dmacon,$dff096 ; DMACON (write: remet les bits)
+ move.l 4,a6
+ lea GraphicName,a1
+ jsr OldOpenLibrary(a6)
+ move.l d0,a0
+ move.l 38(a0),$dff080 ; COP1LC
+ clr.w $dff088 ; COPJMP1
+ move.l d0,a1
+ jsr CloseLibrary(a6)
+ rts
+
+save_intena: dc.w 0
+save_dmacon: dc.w 0
+save_vecteur_irq: dc.l 0
+save_vecteur_kbd: dc.l 0
+
+GraphicName: dc.b "graphics.library",0
+DosName: dc.b "dos.library",0
+IntuitionName: dc.b "intuition.library",0
+
+ even
+
+; Table des caractères
+
+TableCarDirections:
+ dc.w $0000,$0400,$0C00,$1C00,$0C00,$0400,0,0
+ dc.w $0000,$1800,$1800,$1800,$1800,$1800,0,0
+ dc.w $0000,$2000,$3000,$3800,$3000,$2000,0,0
+TableCarEtats:
+ dc.w $00C0,$0120,$0120,$01E0,$0120,$0120,0,0
+ dc.w $01C0,$0120,$01C0,$0120,$0120,$01C0,0,0
+ dc.w $00E0,$0100,$0100,$0100,$0100,$00E0,0,0
+ dc.w $01C0,$0120,$0120,$0120,$0120,$01C0,0,0
+TableCarChiffres:
+ dc.w $0006,$0009,$0009,$0009,$0009,$0006,0,0
+ dc.w $0002,$0006,$000A,$0002,$0002,$0002,0,0
+ dc.w $0006,$0009,$0001,$0002,$0004,$000F,0,0
+ dc.w $0006,$0009,$0002,$0001,$0009,$0006,0,0
+ dc.w $0008,$0008,$000A,$000F,$0002,$0002,0,0
+ dc.w $000F,$0008,$000E,$0001,$0001,$000E,0,0
+ dc.w $0007,$0008,$000E,$0009,$0009,$0006,0,0
+ dc.w $000F,$0001,$0001,$0002,$0002,$0002,0,0
+ dc.w $0006,$0009,$0006,$0009,$0009,$0006,0,0
+ dc.w $0006,$0009,$0009,$0007,$0001,$000E,0,0
+
+A equ 0
+B equ 1
+C equ 2
+D equ 3
+
+g equ -1
+a equ 0
+d equ 1
+
+; turmite de départ
+
+TableAdan:
+ dc.b d,B,1,a,A,0,a,B,0,a,B,0
+ dc.b a,B,0,a,A,0,d,C,0,a,A,0
+ dc.b a,B,0,a,A,0,a,D,0,a,A,0
+ dc.b a,B,0,a,A,0,g,A,0,a,A,0
+
+Copyrights:
+ dc.b " Ecrit par F.Fleuret, Novembre 1989 " ; je suis toujours possessif
+
+ section data1,bss
+startbss:
+ ds.l ntur ; Pile des adresses libres
+AdressesLibres:
+SPtur: ds.l 1
+plan1: ds.l 1 ; pointeurs pour la CHIP-RAM réservée
+plan2: ds.l 1 ; Le Devpac se plante (et si !) si il
+SaveImage: ds.l 1 ; y a des DC.x dans le segment BSS
+copper_list: ds.l 1
+SpriteCursor: ds.l 1
+SpriteSelect: ds.l 1
+SpriteTableau: ds.l 1
+SpriteVide: ds.l 1
+SpriteNombre: ds.l 1
+
+ section data2,bss
+
+DataTurmites:
+ ds.w ndatas/2*ntur
+
+ end