; 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