From: Francois Fleuret Date: Sat, 24 Aug 2013 15:26:18 +0000 (+0200) Subject: Initial commit X-Git-Url: https://fleuret.org/cgi-bin/gitweb/gitweb.cgi?a=commitdiff_plain;h=4398cc94248136e1023d3cd1ee15d1863383fc3f;p=turmites.git Initial commit --- 4398cc94248136e1023d3cd1ee15d1863383fc3f diff --git a/Turmites b/Turmites new file mode 100644 index 0000000..ba5de7a Binary files /dev/null and b/Turmites differ diff --git a/Turmites.TXT b/Turmites.TXT new file mode 100644 index 0000000..77e250b --- /dev/null +++ b/Turmites.TXT @@ -0,0 +1,23 @@ + + Les commandes au clavier sont : + + 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 le terrain en blocs + f5 Remplie le terrain + f6 Ramène l'image memorisée + + La nutrition automatique ramène automatiquement l'image sauvée + avec la commande "M" toutes les 15 secondes; cela permet de laisser + les turmites vivre sans avoir à les nourrir constamment. + + François Fleuret + Juillet 1990 diff --git a/Turmites.s b/Turmites.s new file mode 100644 index 0000000..6bf1e24 --- /dev/null +++ b/Turmites.s @@ -0,0 +1,1435 @@ + +; 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