Sponsors

FacebookTwitterGoogle Bookmarks

ORGANISATION DE LA MEMOIRE Le MC68000 dispose d’un bus d'adresse de 24 bits. Les 8 bits de poids fort ne sont pas utilisés. Ce bus lui perrret d'adresser 16 méga-octets de mémoire en ligne. Une adresse d'exiet peut être indifféremment paire ou impaire, mais une adresse de mot ou de mot long doit oblgatoiremcnt être paire. Une instruction étant constitué de mots, elle aura nécessairement une adresse paire. Les registres de données Dn peuvent être lus ou écrits sur leur octet de poids faible, sur leur mot de poids faible ou sur leur mot long tout entier : les registres d'adresse An ne peuv ent être lu ou écrits que sur leur mot de poids faible ou sur leur mot long tout entier. LES EXCEPTIONS Le processeur travail dans deux modes : - lemodeutilisaieur: - le mode superviseur ; En mode superviseur, caractérisé par la mise à 1 du bit S de SR. Toutes les instructions peuvent être utilisées et le pointeur de pie est AT. également appelé SSP (Supervisa- Stack Pointer). En mode utilisateur, le jeu d'instructions est restreint et le pointeur de pile est Al. également appelé USP (User Stack Pointer). L'intérêt de l'existence de deux modes, est de permettre au système d'exploitation d'assurer la pérenité de son espace de données. Près avoir lu cet artide, vous saurez tout sur le MC68000 qui équipe votre amiga chéri, depuis les modes d’adressages jusqu’aux temps d'exécution en passant par une description détaillée de chaque instruction. Je vous l’ai dit : un véritable petit bijou.

Click image to download PDF

AMIGA NEWS TECH numero 21 (04-1991)

Document sans nom 2
Stéphane Schreiber
3
4
François Lionnet
6
Loïc Far
10
Frédéric Mazué
12
Jérôme Etienne
16
Lilian Margerie
18
Frédéric Mazué
22
HDR GlutenStim.
25
Max et Stéphane Schreibe
30
Frédéric Mazué
Edito
News
Langages : AMT deuxième ExecBase : le 68000 de A à Z ToolBox : compilateur C "DP" : DICE Démo : Bobs et lissajous Concours Listing :Un ciel étoilées améliorer votre ordinaire avec SuperShell SUB.way :un peu d’intuition que Diantre ! SUB.way II iconsole device suite et fin Requester : le cours rieur délecté
La voici, la voilà, la mascoootte de I'Ant. Elle se prénomme Denise. Nous attendons vos dessins, les meilleurs pouraient servir à l'occasion d'illustration de cette Une (la couverture)...
Ce numéro 21 de l’Amiga News-Tech a été tiré à 3000 exemplaires (2592 abonnés enregistrés le 11.03.91). Ce magazine est une publication Commodore Revue Sari. Télénhnnp dp la rédaction • m 4î> 4R0 ?qn
Edito
OURS
Amiga News-Tech est une revue totalement indépendante de Commodore France, éditée par Commodore Revue SARTL. Société Anonyme à Responsabilité Très Limitée sise au 5 bis. Rue de la Fidélité. 75010 Paris I.e numéro de téléphone de la rédaction n'a pas changé depuis le mois dernier : composez de vos petits doiats fébriles le (1) 42 469 290 ou le (1) 47 700 821 pour la porteuse (celle de la télécopie, pas celle de la Gare de l'Est).
La direction est toujours assurée par Jean-Yves Primas, qui possède sa propre ligne directe pour ne pas se mélanger aux journalistes. Composez-donc le
(1) 42 471 216 pour entendre sa douce voix.
La rédaction en chef a été confiée à Yves Huitric. Qui ferait mieux de s'occuper de son crapiion plutôt que de passer nuit blanche sur nuit blanche à jouer avec ProPage. Car c'est également lui qui fait toute la PAO du journal.
Quant au rédacteur en chef adjoint. Stéphane Schreiber. Il se tape tout le sale boulot mais il aime ça.
Plusieurs pigiste ont également collaboré à ce numéro : Pascal "CD Rom" Amiable. Jerôme TKC Etienne. Loïc "BZH" Far. François "AMOS" Lionel. Max. Frédéric "KCKCKK" Mazué et Stéphane "Omniprésent" Schreiber.
Au moindre problème d'abonnement ou plus simplement pour faire découvrir TANT autour de vous, téléphonez à Amiaa VPC. Au (1)43 789 210.
Le fiashage des films à partir de fichiers PostScript est expédié avec une increvable efficacité (XDLR : à l'étage du dessous) par ColorWay, 5. Rue de la Fidélité. 75010 Paris. Tel : (1) 47 708 787. Le journal est imprimé avec passion par N'.I.G Béthé- nv Reims. Tel : (16) 26 075 787.
L'ANT compte à ce jour 2592 abonnés (Tel : voir bolin). Voilà qui va faire plaisir à Denise. D est réalisé entièrement en PAO sur un Amiga 2000B (7 Mo de mémoire. 68030. FlickerRxer) avec ProPage 10 et DeluxePaint
III. Et sur un Amiga 3000-25 avec Excellence! 20.
Amiga et Commodore sont des marques déposées par leur propriétaire, à savoir Commodore Business Machines. ProPage est une manque déposée par Gold Disk. Inc.
DeluxePaint 111 est une marque déposée par Electronic Arts. Excellence! Est une marque déposée par Micro-Systcms Software. Inc.
.Axel Crapiion est une marque déposée par Y ves I luitric.
Dans ce numéro vingt-et-un de TANT, que d'aucuns considèrent en fait comme le numéro deux, plein de promesses ne sont pas tenues : où est donc passé Fred Fish ? Et l ’agenda de présence de nos collaborateurs sur le 3615 ANT ?
La réponse tient en deux mots : "nostia culpa".
A l’heure où j’écris ces lignes, V interview de Fred Fish n’est toujours pas terminée. Les notes de téléphone de l’ANT vont être salées ce mois-ci.
Le 3615 ANT ne démarrera pas en "solo” comme il était initialement prévu. Pour des raisons indépendantes de notre volonté, il sera dans un premier temps accessible par le 3615 COMREV. Nous serons présents le 16 mars à 20 h 00 sur le serveur.
Il était un peu soufflant, mais maintenant il va beaucoup mieux : Maître Jaunâtre procédera au tirage au sort du gagnant de la carte accélératrice (celle mise en jeu pour les abonnements souscris avant le premier janvier 1991) incessapeu sous ment. Celui-ci sera aveiti directement par counier personnel.
Un dernier mot concernant notre sondage du mois dernier : de nombreuses réponses nous arrivent, dont certaine sont, il faut bien l’avouer, assez suiprenantes. Le dépouillement et les noms des gagnants des heures de connexion en 3614 sur le serveur Minitel de l’ANT, seront rendus publics dans notre numéro 23 (juin 91 ).
Stéphane Schreiber
ERRATUM ANT EST.
Quelques coquilles se sont glissées dans notre dernier numéro, ainsi que sur sa disquette.
La plus grave fut de s’apercevoir mais un peu tard, que ProPage 2.0 "bouffait" cairément les anti-slcishes lors de l’importation de texte. Ce qui peut se révéler gênant, swtoiit dans un listing assembleur comme celui de Franck Charlet ("les rasters verticaux"), où ce caractère sert d’introduction aux paramètres des macros. Vous comprendrez aisément que Ton ne puisse par re-publier ce listing... Aussi n ’hésitez pas à téléphoner à la rédaction si vous n ’arrivez pas à vous en débrouiller.
Il semblerait que nombre d’entre vous aient reçu une disquette baptisée "copy of ANT20", au lieu de "ANT20" tout court. Ce qui n’est certes pas réelleinent ennuyeux, cette disquette-ci n’étant pas autoboot, mais peut se révéler fort désobligeant avec TANT21. Nous avons tiré les oreilles de notre dupliqueur pour que celà n’arrive plus, mais au cas où, sachez que la disquette accompagnant le journal s’appelle toujours ANTxx, où xx réprésente bien entendu le nutnéro en cours.
En parlant de disquette : beaucoup ont réclamé un boot particulier à TANT... Frédéric Mazué est en train de travailler dessus, pour vous offrir une petite intro, multi-tâche de surcroît. A venir j’espère pour TANT22.
Avez-vous remarqué ? Tous les programme écrits en Cque ce soit dans TANT ou ailleurs, sont linkés avec une obscure Amiga.lib, celle-là même qui fait défaut à DICE, le compilateur de Matt Dillon.
Mais qu'est-elle donc, cette Amiga.lib ? Que contient-elle de si important pour que chaque programme C, et beaucoup de programmes Assembleur , en aient à ce point besoin ? Hé bien pour simplifier, je dirai que c’est grâce à elle que le linker est capable de résoudre toutes les réferences externes impfidtes des programmes C (j’ai vraiment dit ’ 'simplifier' ' ?).
L’Amig&lib contient principalement :
- les "stubs" : soit en français, les moignoas. Ce sont des routines qui permettent d’appeler les fonctions des bibliothèques de l'Amiga. En récupérant les paramètres de la pile (le C passe tous les paramètres des fonctions par la pile) dans les registres adéquats. Ainsi, lorsque vous écrivez:
DisplayBeep(NULL);
le compilateur génère le code :
PEA $ 0.W
JSR DisplayBeep(PC) ADDQ.L 4,A7
et le linker ajoute la routine DisplayBeep suivante dans l'exécutable final :
DispJayBccp:
MOVEAJ. 4(A7>A0 :Rccupèrc le paramètre
(NUIJ.)
MOVEAJ, _IntuitionBase.V6 -.Intuitionltee dans 6 JMP I.VODispfayBeeptA6) cSautà _LYODispta>Beep
- les oflsets : autrement dit. Les valeurs des symboles _LVOxxx. Pour reprendre l’exemple ci-dessus, c’est l’Amigalib qui informe le linker que _LVODisplayBeep vaut -96.
- exec_support : des routines destinées à faciliter quelques procédures Exec. Comme la création d’un MessagePort (CreatePort). De tâches (CreateTask), etc.
- clib : une bibliothèque de fonction C spécialement écrites pour l’Amiga. C’est-à-dire exploitant scs spécificités (ce que ne fait bien entendu pas la bibliothèque C standard telle que l’ont défini Kemighan et Ritchie). On trouve ici les routines comme printfO. Etc.
- autres : une bibliothèques de fonctions diverses, appelables depuis n'importe quel langage (mais surtout le C ou l'assembleur).
LES FONCTIONS D’AMIGA.LIB
Elles sont au nombre de 12. Si l'on excepte bien sûr les fonctions de type stdio et math, propres au C. Dans le tableau qui suit on donne le prototype de la fonction, suivi d’une explication de son utilité et d'une description de ses paramètres.
Void AddTOF(struct Isrvstr *i, APTR p. APTR
a) ;
Cette fonction ajoute une tâche à la liste des serveurs d'interruption VBL.
I pointeur sur une structure Isrvstr correctement initiâlisée.
P pointeur sur le code C à appeler à chaque VBL. A pointeur sur un tableau de ULONGs servant de paramètres à la routine pointée par p.
void RemTOF(struct Isvrstr *i);
Enlève une tâche de la liste des serveurs d'interruption VBL.
I pointeur sur la structure Isvrstr de la tâche à éliminer de la liste.
Void BeginKX struct IORequest *io);
Envoie une requêtre d’entréc sortie asynchrone.
Iopointeur sur la structure IORequest associée au device concerné.
Struct IORequest *CreateExtIO(struct MsgPort
* mp. ULONG s);
Alloue de la mémoire pour et initialise une structure IORequest.
Mp pointeur sur le MessagePort à utiliser avec le ReplyPort de lTORcquest.
S taille de la structure à créeér (utile en cas de structure étendue, comme avec le trackdisk.device).
void DeleteExtIO(struct IORequest *io);
Libère la mémoire allouée par CreateExtlCK) pour la structure IORequest passée en paramètre, qui n'est évidemment plus utilisable ensuite.
Iopointeur sur une structure IORequest initiâlisée par CreateExtlCK).
Struct MsgPort *CreatePort(char :ïname. LONG pri):
Alloue de la mémoire pour et initialise une structure MsgPort. Name pointeur sur le nom du nouveau port s'il
doit être public. NULL sinon, pri priorité du nouveau port.
Void DeletePort(struct MsgPort *mp);
Libère la mémoire allouée par CreatePortO pour la structure MsgPort passée en paramètre, qui n'est évidemment plus utilisable ensuite.
Mp pointeur sur une structure MsgPort initiâlisée par CreatePortO.
Struct Task *CreateTask(char *name, LONG pri. FuncEntrv initPC, ULONG ssize);
Crée une nouvelle tâche avec le nom. La priorité et la pile donnés.
Name pointeur sur le nom de la nouvelle tâche, pri priorité de la tâche.
InitTCadresse de la première instruction exécutable, ssize taille de la pile pour cette tâche.
Void DeleteTask(struct Task *t);
Supprime la tâche pointée en paramètre de la liste des tâches actives
t pointeur sur la tâche créée par CreateTask( ) et à supprimer.
Void NewList(struct List *1):
Initialise une structure List, qui sera vide et prête à l’emploi.
1 pointeur sur une structure List à initialiser.
ULONG FastRand( ULONG seed);
Génère une nombre pseudo-aléatoire suivant la formule : retum( ( seed « 1 )A 0x1 D872B41 ):
seed un entier sur 32 bits, généralement le résultat d'un précédent appel à FastRandf ).
USHORT RangeRandfUSHORT v);
Renvoie un nombre pseudo-aléatoire compris entre 0 et v.
v valeur 16 bits définissant la limite supérieure du nombre aléatoire à générer.
Voilà pour les fonctions destinées à simplifier la vie des programmeurs sous Exec. Nous v errons le mois prochain les fonctions appartenant à la partie clib de l’Amigalib. Avec des exemples d'utilisation en assembleur (quel intérêt en C ?). Histoire cfe se faciliter les choses dans des cas bien précis (sortie ASCII de nombres en virgule flottante, etc.).
Denis JARRIL
Bienvenue dans la rubrique AMOS de l’ANT, AMOS Technique (AMT pour les intimes). Après avoir vu comment créer une extension à l’AMOS, nous allons brancher des routines sur les interruptions et améliorer le procéssus de rafraîchissement d'écran...
Et pour commencer, nous allons voir comment brancher une routine sur les interruptions VBL. AMOS utilise intensivement les interruptions de retour de balayage. Beaucoup de choses y sont effectuées :
- Changement de listes de sprites
- Gestion des écrans entrelacés (fait en interruption sous AMOS !)
- Modification des couleurs dans la liste copper (FLASH, SHIFl, FADE),
- Appel d’AMAL,
- Appel des routines musicales,
- Gestion de la souris.
Elles sont pour le moins chargées!
Une extension peut bien sur modifier le vecteur en S6C pour se brancher sur le serveur d'interruption. Je ne vous le conseille pas : certaines tâches effectuées par AMOS ont absolument besoin de se produire IMMEDIATEMENT après le signal de retour de balayage.-Ce sont toutes les opérations modifiant la liste copper (changement des couleurs, écran entrelacé, sprites). Le fait de retarder l'entrée de la routine VBL de F AMOS provoquerait un accès simultané du copper et du 68000 aux mêmes addresses. La réponse du DMA serait sans appel : plantage!
C'est pourquoi j’ai ménagé un moyen très simple pour programmer une interruption VBL.
Dans la zone de données (pointée par A5). Se trouve un petite liste de 8 addresses. Les routines pointées par ces addresses sont appelées par AMOS lors de l'interruption VBL.
Voici la partie de programme qui effectue l’appel :
lea
move.l
beq.s
move.l
jsr
move.l
bne.s
VblRout(a5),a4 (a4)+,d0 VblPaCa 30, aO (aO)
(a4)+,d0
VblCall
Le programme explore la liste et appelle toute adresse différente de zéro. La boucle d'exploration se termine à la première adresse nulle. Il ne faut pas modifier les registres A4, A5 et A6.
INSERER SA PROPRE ROUTINE
Il faut explorer la liste depuis le début, à la recherche de la première adresse nulle :
* Insère l'adresse AO dans la liste VBL PutVBL: lea VblRout(a5),al
Pvbl tst.l (al)+
bne.s Pvbl move.l a0,-4(al) rts
Av ex» tisse- ne- r» t
ATTENTION : vous ne devez pas poker une adresse à une position fixe dans la liste : votre extension peut-être chargée APRES une autre, qui utilisera la même position !
La liste peut contenir 7 adresses, et doit se terminer par un zéro. La première est en général utilisée par l'extension musicale.
AVOIR SA PROPRE ROUTINE UPDATE
Quelques explications : le principal avantage d'AMAL est l’animation automatique des bobs, sprites, écrans et autres rainbows : ils bougent en interruption pendant que le programme Basic continue à fonctionner...
Il n'était pas possible de programmer TOUT le système en interruption, pour une raison très simple : les interruptions VBL doivent absolument durer moins de l 50ième de seconde, sous peine de planter la machine.
Or. Afficher plusieurs bobs, recalculer la liste copper, dessiner un rainbow peut prendre largement plus de ce temps : il a fallu ruser!
AMAL fonctionne véritablement sous interruptions. Son rôle est de calculer et de modifier les coordonnées, et seulement les coordonnées de chacun des canaux animés. Chaque fois qu'AMAL change un canal, il positionne un flag du canal et un flag dans la zone de données de l'AMOS.
Pour éviter de planter le système, le nombre de canaux animés durant les interruptions est limité à 16 (SYNCHRO ON).
Avant chaque instruction de branchement, ou lors d'une boucle d'attente (par exemple WA1T), AMOS teste le flag général. Si ce flag est à 1. AMOS appelle la routine de dessin de bob. Sprite. écran, etc...
On peut ainsi garder l'avantage des interruptions (stabilité des déplacements, indépendance par rapport au Basic), tout en autorisant le déplacement de très gros objets...
AU FAIT, AU FAIT !
Quel rapport avec les extensions ? Il est possible de réaliser une extension se greffant automatiquement sur le processus d’update. Vous pouvez donc créer votre propre version d'AMAL en utilisant une routine VBL positionnant les flags UPDATES.
J'ai réalisé ceci en pensant à AMOS 3D (qui doit sortir très prochainement, sans blaque !). Les programmeurs de cette extension voulaient réaliser un pseudo AMAL traitant 3 coordonnées : X. Y et Z. pour gérer des objets en 3 dimensions.
COMMENT FAIRE
Le principe se rapproche de celui utilisé pour les interruptions : une liste de routines à appeler, plus des flags à positionner.
La liste des routines d'UPDATE se trouve à l’adresse ExtTests+4(a5), et peut contenir 7 addresses.
Quant aux flags. Les voilà :
- Actual+l(a5) : les bits 1 à 7 signalent un routine à appeler. Au bit 1 correspond l’adresse contenue en ExtTests+4(a5), au bit 2, l’adresse contenue dans ExtTests+8(a5), etc...
- ActuMask+l(a5) : il s'agit d'un masque appliqué au contenu de Actual. Pour inhiber certaines routines UPDATE.
Voici un extrait de la routine d’appel des extensions :
move.w
ActuMask(a5), d7
move.w
Actual(a5) ,d6
and.w
d7,d6
T8t3 lsr.
B l,d6
beq.s
Tst4
lea
ExtTests(a5),al
bra.s
Tst3b
Tst3a move.l (al),d0
beq.s
Tst3b
move.l
d0,a0
jsr
(aO)
Tst3b addq.l 4,al
lsr.b
l,d6
bcs. S
Tst3a
fcme.s
Tst3b
Tst4 ...
Vous pouvez voir en inspectant cette routine, que la première adresse de la ligne et le bit 0 du flag Actual ne sont pas accessibles. La routine doit en plus préserver les registres D6 D7, Al et A5.
UN EXEMPLE
Voici le listing d’une extension complètement... nulle. Elle propose une merveilleuse instruction, dont le seul objet est de poker dans la mémoire d’un écran tous les 1 50 de seconde, en interruption :
MOUVEMENT NUL adresse,taille
L’installation des routines est réalisée dans la partie initialisation de l’extension. Pour les deux routines, on recherche une place libre dans la liste, puis on LOKE l’adresse.
Pour la partie UPDATE, il faut en plus garder le numéro du bit à positionner pour l’appel...
Update_In:
Pas besoin de se soucier de l’effacement des routines : tout est effectué par AMOS.
Pour avoir une démonstration de l’instruction, passer en mode direct, effacez l’écran (CLS 0) puis tapez:
MOUVEMENT NUL Logbase(0),8000
Updl
Update_Out:
Un octet progresse sur l’écran. C’est idiot, mais c’est une bonne démonstration du processus :
- l’incrémentation de l’adresse de l’octet est réalisée pendant l'interruption VBL ;
- l'affichage dudit octet est réalisé lors de l’UPDATE. Si vous bougez l’écran de mode direct (avec les flèches haut et bas), certaines positions ne sont pas affichées, le calcul de la liste copper fait "sauter" un balayage écran...
Ciel, le compteur de mon traitement de texte indique déjà 9000 caractères, il se fait tard, je dois vous laisser ! Le mois prochain nous nous attaquerons à la structure des banques de mémoire: sprites, musique etc...
Mvnl
Tk:
üpd_Nul
Cpt_Nul
Adr_Nul
MaxNul
François LIONET communique :
PSI (salut à toute la rédaction) : La version française d'Amos 1.23 distribuée en France par Ubi Soft, sera disponible à la mi-mars, autant dire qu'elle devrait déjà l'être !
PS2 (bonjour IBM !) : le compilateur Amos sortira fin mars (NDLR : autant dire que c'est déjà demain !) D'abord en Angleterre, suivi nous l’espérons de près en France...
PS3 : Amos 3D quant à lui est prévu fin avril (NDLR : et il trouve encore le temps d'écrire des articles pour l’Ant et Amiga Revue ? Mais que oui, car celui-ci est développé par une équipe de programmeurs de Mandarin Software).
INCLUSION DES VARIABLES SYSTEME Include "Equ.s"
NUMERO DE L'EXTENSION DANS LA LISTE equ 10
ROUTINE APPELLEE LORS DU CHARGEMENT (COLD START) move.l a0,d0 lea Tk(pc),a0 move.l dO,Table-Tk(aO)
Insère la routine UPDATE dans la liste
moveq 0,d0
lea ExtTests+4(a5), al
addq.w l,d0
tst.l (al)+
bne.s Itest
lea Update_In(pc),a2
move.l a2,-4(al)
move.w dO,Upd_Nul-Tk(a 0)
Insère la routine d'interruption
lea VblRout(a5),al
tst.l (al) +
bne.s Ivbl
lea Vbl_In(pc), a2
move.l a2,-4(al)
Fin normale...
Welcome(pc),al Warm(pc), a2 End(pc), a3 0,d2
lea
lea
lea
moveq
moveq
moveq
rts
ExtNumb-l,dl
0,d0
SCREEN RESET (rien ici!) Rts
QUIT (idem) rts
ROUTINE D'INTERRUPTION
lea tst.l beq.s addq.1 move.w
Tk(pc),a0 Adr_Nul-Tk(aO) Vbl_Out
l,Cpt_Nul-Tk(a0) Upd_Nul-Tk(aO),dO
Marque 1'update!
Bset
dO,Actual+1(a5)
rts
ROUTINE UPDATE
Tk(pc), al Adr_Nul-Tk(al),dO Update_Out d0,a0
lea
move.l beq. S move.l move.l
rrmp. 1
bcs. S moveq move.l move.b
Cpt_Nul-Tk(al),d0 Max_Nul-Tk(al),dO Updl 0,d0
dO,CPt_Nul-Tk(al) -1,0(aO,dO.1)’
rts
INSTRUCTION "mouvement_nul lea Tk(pc),a0 clr.l Cpt_Nul-Tk(aO) bclr dO,ActuMask+1(a5) move.l (a3)+,Max_Nul-Tk(aO) move.l (a3)+,Adr_Nul-Tk(aO) beq.s Mvnl
Autorise l'appel de 1'update move.w Upd_Nul-Tk(a0),d0 bset dO,ActuMask+l(a5) rts
LISTE DBS INSTRUCTIONS ET FONCTIONS
dc. w 1,0 de .b $ 80,-1
dc. w Mvt_Nul-Tk,1
dc. b "mouvement nu","l"+$ 80,"10,0",-1 de .w 0
ZONE DE DONNEES DE L'EXTENSION
adresse,maximum
dc. w de. 1
dc. l de. 1
ADRESSE DE LA TABLE DU BASIC
dc. l 0
TITRE DE L'EXTENSION
dc. b 27,"Y",48+15,"Extension nulle",0
Attention, les rubriques ExecBase de ce mois-ci et du prochain valent de Vor ! Photocopiez-les, recopiez-les, décalquez-les, faites-en ce que vous voulez, mais gardez-en une copie à portée de main !
ORGANISATION DES REGISTRES
Le MC68000 dispose de 18 registres internes, à savoir :
- 8 registres de données 32 bits : DO. D1..... D7
- 8 registres d'adresses 32 bits : AO. A1..._ A7
- 1 compteur de programme 32 bits : PC
- 1 registre d'etar 16 bits : SR
Le registre d'état SR est en fait composé de deux sous-registres 8 bits. L'octet de poids tort est appelé "octet superviseur", l'octet de poids faible, "octet utilisateur" ou condition codes register" (CCR).
Description des bits de SR
Bit
Non
Signification
15
T
Trace
14
• -
non utilisé
13
S
morte Superviseur
12
-
non utilisé
11
-
non utilisé
10
12
9
II
masque d'Interruption
8
10

7
_
non utilisé
6
-
non utilisé
5
-
non utilisé
4
X
extend (bit d'extension)
3
N
Négative (bit de signe)
2
z
Zéro (bit de zéro)
1
V
oVerflow (bit de dépassement de capacité)
0
c
Carry (bit de retenue)
Note : en mode utilisateur, on ne peut écrire que dans l'octet utilisateur (CCR) : en mode superviseur, on peut écrire dans le mot entier.
Le registre A7 joue un rôle particulier : le 68000 l'utilise comme pointeur de pile system; pour la sauvegarde du PC lois des sauts aux sous-programmes. En mode superviseur. A7 devient A7 pointeur de pile superviseur.
ORGANISATION DE LA MEMOIRE
Le MC68000 dispose d’un bus d'adresse de 24 bits. Les 8 bits de poids fort ne sont pas utilisés. Ce bus lui perrret d'adresser 16 méga-octets de mémoire en ligne.
Une adresse d'exiet peut être indifféremment paire ou impaire, mais une adresse de mot ou de mot long doit oblgatoiremcnt être paire. Une instruction étant constitué de mots, elle aura nécessairement une adresse paire.
Les registres de données Dn peuvent être lus ou écrits sur leur octet de poids faible, sur leur mot de poids faible ou sur leur mot long tout entier : les registres d'adresse An ne peuv ent être lu ou écrits que sur leur mot de poids faible ou sur leur mot long tout entier.
LES EXCEPTIONS
Le processeur travail dans deux modes :
- lemodeutilisaieur:
- le mode superviseur ;
En mode superviseur, caractérisé par la mise à 1 du bit S de SR. Toutes les instructions peuvent être utilisées et le pointeur de pie est AT. également appelé SSP (Supervisa- Stack Pointer).
En mode utilisateur, le jeu d'instructions est restreint et le pointeur de pile est Al. également appelé USP (User Stack Pointer).
L'intérêt de l'existence de deux modes, est de permettre au système d'exploitation d'assurer la pérenité de son espace de données.
Près avoir lu cet artide, vous saurez tout sur le MC68000 qui équipe votre amiga chéri, depuis les modes d’adressages jusqu’aux temps d'exécution en passant par une description détaillée de chaque instruction. Je vous l’ai dit : un véritable petit bijou.
Le pissaoi* du mode superviseur au mode utilisateur peut se réaliser de deax manières :
- au retour d'une exception :
- en invalidant le bit S de SR au moyen d'iastiuctions spécialisés (MOVE to SR. ANDI toSRouEORltoSR):
Toutes les exceptions sait exécutées en mode superviseur.
Lorsque le processeur détecte une exception (interruption, erreur dans le programme, instruction TRAP....). il génère de manière interne un numéro d'exception qui. Une fois multiplié par 4. Donne l'adresse du vecteur d'exception. Le 68000 y trouve l’adresse de la routine à exécuter pour traiter l'exception. H existe 256 vecteurs d exceptions, qui occupent le premier kilo-octet de mémoire.
Vecteur Adresse Exception concernée
0
$ 0000
Reset : initialisation de SSP
$ 0004
Reset : initialisation de PC
*
2
$ 0008
Erreur Bus
3
$ 000C
Erreur d'adresse
4
$ 0010
Intruction illégale
5
$ 0014
Division par zéro
6
$ 0018
Instruction CHK
7
$ 001C
Instruction TRAFV
8
$ 0020
Violation de privilège
9
$ 0024
hfode Trace
10
$ 0028
r. inp a (instruction $ Axxx)
11
$ 002C
Line F (instruction $ Fxxx)
12-14
$ 0030-38
Réservés
15
$ 003C
Interruption non initialisés
16-23
$ 0040-50
Réservés
24
$ 0060
Interruption parasite
25
$ 0064
Interruption niveau 1
26
$ 0068
Interruption niveau 2
27
$ 0060
Interruption niveau 3
28
$ 0070
Interruption niveau 4
29
$ 0074
Interruption niveau 5
30
$ 0078
Interruption niveau 6
31
$ 0070
Interruption niveau 7
32-47
$ 0080-BC
Instructions TRAP
48-63
$ 00CO-FC
Réservés
64-255
$ 0100-3FC
Vecteurs d'interruptions utilisateur
TRAITEMENT D’UNE EXCEPTION
Losqu' il détecte une exception, le 68000 procède en quatre étapes :
- copie du registre d'état SR dans un registre interne, mise à 1 du bit S et mise à 0 du bit T (TRACE" étant elle-même une exception). Si l'exception est RESET ou une interruption, le masque d'interruption de SR (bits 12 à 10) est positionne en conséquence (niveau 7 pour RESET) :
- le numéro du vecteur d'exception est déterminé par la logique interne :
- le 68000 sauv egarde son contexte actuel (sauf dans le cas du RESET) : la valoir du PC et la copie interne de SR soit placés dans la pile superviseur. PC pointe généralement l'instruction suivant immédiatement celle ayant déclenché l'exception, niais dans le cas d'une erreur Bus ou d'une erreur d'adresse, la valeur de PC est imprevisible (à cause du phénomène d'anticipation). Dans ces deux cas-là. Des informations supplémentaires sont également empilées dans SSP : .....
- le PC est chargé avec le contenu du vecteur d'exception dont l'adresse a été déterminée
dans la phase 2 et le processeur reprend l'exécution des instructions ;
LES MODES D’ADRESSAGE
Le software du MC68000 distingue 14 modes d’adressages, regroupés sous six rubriques (chaque mode d'adressage est suivi d'un exemple de syntaxe et d une rapide description) :
* Adressage absolu
- adressage absolu court : TSTE S4.W
l'adresse sur 16 bits est étendue à 32 bits avant d'être
traitée comme opérande.
- adressage absolu long : TST.L S40000
l'adresse sur 32 bits est directement traitée comme opérande.
* Adressage direct de registres
- adressage direct de registres de données : TST DO le registre est l'un des 8 registre de données Dn
- adressage direct de registres d'adresses : TSTU AO le registre est l'un des 8 registres de données Aa
- adressage direct du registre d'état : ANDI S20.SR
le registre d'étal est directement traité comme opérande. Ces instructions sont privilégiées.
* Adresse immédiat
- adressage immédiai "simple" : MOVEW $ 1010£>4 l'opérande 16 ou 32 bits est contenu daas le mot suivant celui de l'instruction, ou dans le mot long suivant. Si un registre d'adresse est utilisé a si la taille est le mou l'opérande subit une extension de signe avant le transfert.
- adressage immédiai "rapide" : MOVEQ $ 1OXW l'opérande 8 bits est directement contenu dans le mot d'ins- struction. Seuls les registres et données Dn peuvent être utilisés.
Note : les données immédiates sou notées rSionnée.
* Adressage indirect de registres
- adressage indirect de registre "simple" : MOVEW (A I )D0 le registre d'adresse spécifié contient l'adresse de la donnée à transférer.
- adressage indirect postincrérrenié : MOVEW (Al H-DO le registre d'adresse spécifié contient l'adresse de la donnée à transférer. D est ENSUITE incrementé de :
- un si la taille est l'octet ;
- deux si la taile est le mot ;
- quatre si la taille est le mot long :
- adressage indirect predécremenlé : MOVEW -(Al)JX)
le registre d'adresse spécifié est D'ABORD décrémenté avant de contenir l'adresse de la donnée à transférer. La décrémentation est de :
- un si la taille est l'octet :
- deux si la taille est le mot :
- quatre si la taille est le mot long ;
- adressage indirect avec déplacement : MOVEW dcKA 1 )XX) l'adresse de l'opérande est calculée en additionnant le déplaçaient dd 16 bits au contenu du registre d'adresse.
- adressage indirect indexé avec déplacement : MOVE d( A1 .D 1 ).D0 l'adresse de l'opérande est calculée en additionnant le déplacement d 8 bits, le contenu du registre d'index et le contenu du registre d’adresse.
* Adressage relatif au PC
- adressage relatif au PC avec déplacement : MOVEW dd(PC).D0 l'adresse de l'opérande est calculée en additionnant le déplacement dd 16 bits au contenu du PC.
- adressage indexé relatif au PC : MOVEW d(PCD 1 U)D0 l’adresse de l'opérande est calculée en additionnant le déplacement d 8 bits, le contenu du reigstre d’index et le contenu du PC.
Note : dans tous les modes d'adressage indexés, le registre utilisé comme index peut être indifféremment un registre de données Dn ou un registre d'adresses An, et l'on peut spécifier la taille de l’index (mot ou mot long).
CODAGE DES INSTRUCTIONS
Les codes opératoires du MC68000 suivant presque tous le même schéma : un mot d'instruction pouvant être suivi d'un maximum de deux mois longs d'extension. La plus grande taille pour une instruction est donc de 10 octets.
Les 4 bits de poids fort (bits 15 à 12) du mot d'instruction spécifient le ripe de l'instruction:
0000
Manipulation de bits, M0VEP, iumédiat
0001
MOVE sur des octets
0010
MOVE sur des mots longs
0011
MOVE sur des mots
0100
Autres instructions
0101
ADDQ, SOBQ, Scc, Dbcc
0110
Bcc, BSR
OUI
M3VEQ
1C00
OR, DIV, S3CD
1001
SÜB, SUBX
icio
non utilisé (line A)
1011
CMP, ECR
1100
AND, MOL, ABCS), EXG
ATS), ADDX
1110
Décalages et rotations
1111
non utilisé (line F)
Les modes d'adressages sont codés sur 3 bits dans le mot d'instruction. Daas le tableau ci-dessous, la colonne REGISTRE contient sur 3 bits également soit le numéro du registre utilisé dans l'instruction (de 0 à 7). Soit un code distinctif du mode d'adressage. Quand un déplacement ou un registre d’index est utilisé, il est codé daas le mu d'extension de l'iastruction.
Mode_Code-Op_Registre
En
000
An
001
N" du registre
(An) +
- (An) dd(An) d(An,Ri)
011
N" du registre N‘ du registre N' du registre N‘ du registre
101
110
xx. w
xx. L dd(PC)
111
111
111
000
001
010
d(FC,Ri)
111
111
011
100
TEMPS D’EXECUTION DES INSTRUCTIONS
Conventions : dans les tableaux qui suivent la notation x(y z) représente la durée totale en cycles d'horloge de l'instruction, x. y et z sont définis comme suit :
- x = nombre total de cycles d'horloge :
- y=nombre de cycles de lecture :
- z = nombre de cy cles d’écriture :
Un cycle de lecture ou d'écriture prenant en général 4 cy cles d'horloge, y et z doivent chacun être multipliés par 4 puis additionnés pour donner x. Si une différence subsiste, elle indique le nombre de cycles d'horloges nécessaires au fonctionnement interne.
Les temps donnés dans ces tableaux sont calcules pour une horloge à 8 Mhz. Avec laquelle un cycle dure exactement 125 as.
Calcul des addresses effectives
Mode .B, .W .L
Dn 0(0 0) 0(0 0)
An 0(0 0) 0(0 0)
(An) 4(1 0) 8(2 0)
(An)+ 4(1 0) 8(2 0)
- (An) 6(1 0) 10(2 0)
d(An) 8(2 0) 12(3 0)
d(An,Ri) 10(2 0) 14(3 0)
xx. W 8(2 0) 12(3 0)
xx. L 12(3 0) 16(4 0)
d(PC) 10(2 0) 14(3 0)
xx 4(1 0) 8(2 0)
La taille du registre d'index n'influence pas le temps d'exécution.
Move (octet et mot)__
fvxiree Destinafion-
Dn An (An) (An)+ -(An) d(An) d(AnJtï)xx.W xxJ.
Dn 4(1X1) 4(1X1) 8(1 1) 8(1 1) 8(1 1) 12(2 1) 14(2 1) 12(2 1) 16(3 1)
An 4(1X1) 4 1AH 8(1 1) 8(1 1) 8(1 1) 12(2 1) 14(2 1) 12(2 1) 16(3(1)
(An) 8(2*)) 8(2 0) 12(2 1) 12(2 1) 12(2 1) 16(3(1) 18(31) 16(3(1) 20(41)
(An* 8(2 0) 8(2X1) 12(21) 12(21) 12(21) 16(31) 18(31) 16(31) 20(41)
- (An) 10(2*)) 10(2*)) 14(21) 14(21) 14(21) 18(31) 20(31) 18(31) 22(41)
d(An) 12(3*)) 12(3*)) I6(.V1) 16(31) 16(3 1) 20(41) 22(41) 20(31) 24(51)
dlAuRD 14(30) 14(30) 18(31) 18(3 1) 18(31) 22(41) 21(41) 22(41) 26(51)
xx. W 12(30) 12(30) 16(31) 16(31) 16(31) 20(41) 22(41) 20(41) 24(51)
.vcL 16(40) 16(40) 20(41) 20(41) 20(4 1) 24.51) 26(5 1) 24(51) 28(61)
d(PQ 12(30) 12(30) 16(31) 16(31) 16(31) 20(41) 22(41) 20(41) 24(51)
dtPQRD 14(30) 14(30) 18(2 1) 18(31) 18(31) 22(41) 24(41} 22(41) 26(51)
xx 8(2*)) 12(21) 12(21) 12(21) 12(21) 16(31) 18(31) 16(3 1) 20(41)
La taille du registre d’index de modifie pas le temps d'exécution
Instruction à 1 opérande
Instr. Taille Registre Mémoire
Mme (mol long)
Cm .B, .W 4(1 0) 8(1 1) +
.h 6(1 0) 12(1 2)+
NBCD .B 6(1 0) 8(1 1)+
NEG .B, .W 4(1 0) 8(1 1) +
.L 6(1 0) 12(1 2)+
NEGX .B, .W 4(1 0) 8(1 1) +
Source Destination
Dn An (An) (An H- -(An) cKAn) d(Anfb')xx. V xxJ.
Dn 410) -K1A») 1HV2) 12(1 2) 12(1 2) 16(2 2) 18(2 2) 16)2fl) 20(3 2)
An 410) -KM)) 12(1 2) 12(1 2) 12(1 2) 16(2 2) 18(2 2) 16(2H) 20(3 2)
(An) 1230) 12(3(1)) 20(.V2) 20(-Y2) 20321 24(4(2) 26(4(2) 24(4(2) 28(5(2)
(An>f 1230) 12(30) 20(3(2) 20(3 2) 20(3(21 24(4(2) 26(4(2) 24(4 2) 28(5(2)
- (An) 14(30) 14(30) 22 32) 22(32) 22(321 26(42) 28(42) 26 42) 30(52)
dlAnl 16(44)) 16(40) 24(42) 24(42) 21(42) 28(52) 30(52) 28(52) 32 62)
clAnJtii 18(40) 18(40) 26(42) 26(42) 26(42) 30(52) 32(52) 30(52) 31(62)
xx-W 16 40) 16(40) 2442) 2442) 2442) 28 52) 30)52) 28(52) 32)62)
xtL 20(50) 20(50) 28(52) 28(52) 28(52) 32(62) 34.62) 32(62) 36(7 2)
ckPCi 16(40) 16(40) 2442) 24(42) 24(42) 28(52) 30(52) 28(52) 32(52)
d PCRi) 18(40) 18(40) 26(42) 26(42) 26(421 30(52) 32(52) 30(52) 31(62)
xx 12(30) 12(30) 20(32) 20(32) 20(32) 2442) 26(42) 2442) 28(52)
¦ X» 6(1 0) 12(1 2) +
MOT .B, .W 4(1 0) 8(1 1) +
.L
6(1 0)
12(1 2)+
Soc
.B False
4(1 0)
8(1 1)+
.B True
6(1 0)
8(1 1)+
TAS
.B
4(1 0)
10(1 1)+
TST
.B, .W
4(1 0)
4(1 0)+
-L
4(1 0)
4(1 0)+
Notes :+ajouter le temps de calcul de l'adresse effective
La taille du registre d'index de nxxiifie pas le temps d’exécution
Décalage Rotations Taille
Instructions usuelles
Registre Mémoire
Instr.
Instr. Taille ea>An ea>JDn Dn, M>
ASL,ASR LSL,LSR ROL,ROR RQXL ROXR
6+2n(l 0)
8+2n(l 0)
6+2n(l 0)
8+2n(l 0)
6+2n(l 0)
8+2n(l 0)
6+2n(l 0)
82+n(l 0)
8(1 1)+
8(1 1)+
8(1 1)+
8(1 1)+
.B, .W .L
- B, .W .L
.B, .W .L
.B, .W ¦ L
MO .B, .W 8(1 0) 4(1 0) 8(1 1)
.I> 6(1 0)** 6(1 0)** 12(1 2)
AND .B, .W - 4(1 0) 8(1 1)
.L - 6(1 0)** 12(1 2)
CMP .B, .W 6(1 0) 4(1 0)
• L 6(1 0) 6(1 0)
DIVS - - 158(1 0)*
DIVÜ - - 140(1 0)*
EOR .B, .W - 4(1 0)*** 8(1 1)
.L - 8(1 0)*** 2(1 2)
MULS - - 70(1 0)*
MTOÜ - - 70(1 0)*
OR .B. .W - 4(1 0) 8(1 1)
.L - 6(1 0)** 12(1 2)
SUB .B, -W 8(1 0) 4(1 0) 8(1 1)
.L 6(1 0)** 6(1 0)** 12(1 2)
Notes : n représente le nombre de décalages rotations
+ajouter le temps de calcul de l'adresse effective
Manipulations de bits
Instr. Taille
Statique
Registre
12(2 0)*
14(2 0)*
12(2 0)*
10(2 0)
Dynamique
Registre Mémoire 8(1 1)+
8(1 1)+
8(1 1)+
4(1 0)+
Mémoire
12(2 1)+
12(2 1)+
12(2 1)+
8(2 0)+
BCHG
BCLR
BSET
BTST
.B .L
• B .L .B .L .B .L
8(1 0)*
10(1 0)*
8(1 0)*
6(1 0)
Notes : Additionner aux présents temps, les temps de calcul de l'adresse effective.
* indique le temps maximum. ** si le mode d'adressage est indirect de registre ou immédiat le temps de base est de 6 périodes. *** seulement si le mode d'adressage est direct de registre.
DIVS. DIVü : l'algorvthrre de division engendre une marge de 109c entre le meilleur «le pire cas.
MULS, MULU : l'algorythme de multiplication requiert 38+2n cycles, où n vaut :
- dans te cas (te MULU :1e nombre de bits à 1 dans ea>
- dans te cas de MULS : te nombre de combinaisons de bits à 10 et 01 dans la source.
Notes : * indique le temps maximum
+ ajouter le temps de calcul de l'adresse effective
Instructions de branchement
Instructions immédiates
Instr.
Taille
Saut
Pas saut
Instr. Taille xJDn ft'tAn xAl
Bcc
BRA
BSR
DBCC
.S
.L
.S
.L
.S
•L
cc True cc False
10(2 0)
10(2 0)
10(2 0)
10(2 0)
18(2 2)
18(2 2)
10(2 0)
8(1 0)
12(2 0)
AUDI .B, .W 8(2 0) - 12(2 1)+
.L 16(3 0) - 20(3 2)+
ADDQ .B, .W 4(1 0) 8(1 0)* 8(1 1)+
.L 8(1 0) 8(1 0)* 12(1 2)+
ANDI .B, .W 8(2 0) - 12(1 2) +
.L 16(3 0) - 20(3 1)+
CMPI .B, .W 8(2 0) - 8(2 0) +
.L 14(3 0) - 12(3 0)+
EORI .B, .W 8(2 0) - 12(2 1)+
.L 16(3 0) - 20(3 2)+
M3VBQ -L 4(1 0)
ORI .B, .W 8(2 0) - 12(2 1)+
.L 16(3 0) - 20(3 2)+
SUBI .B, .W 8(2 0) - 12(2 1) +
.b 16(3 0) - 20(3 2)+
SUBQ -B, .W 4(1 0) 8(1 0)* 8(1 1)+
.L 8(1 0) 8(1 0)* 12(1 2)+
12(2 0)
14(3 0)
JMP, JSR, LEA. PEA et MOVEM
Source Destination
_Tafllc (An) (AnH -(An) dlAn) dCAnRùxxAV xsl. D(PC> dlPCRi)
JMP - «301 - 10(30) 1430) 10(20) 12(30) 10(20) 1430)
JSR - 162 2) - - 18(2 2) 22(22) l«2 2) 20(32) 18(22) 2222)
LEA - 41 0) - - «20) 1220) «20) 12(30) 8(20) 12(20)
PEA - 121 2) - - 1«22) 20(22» 16(22) 20(3(2) 1622) 20(22)
MJVEMWord 12+4» 12+4» - 16+4» 18+4i 16+4» 20+4» 16+4» 18+4i
M->R (3h»0) (3+nO) (4+tvO) (4+nO) (4+nO) (5+nO) (4wO) (4+nO)
Ixmg !2+8n 12+8n - 16+8n 18+8n 16+8n 20+8n 16+8n 18+8n
5+2n0> (3+2n0i (4+2nOi (4+2nO t4+2n0i (5+2nQi «+2ntt O+2n0)
MM-MVVord 8+4i 8+to 12+4i 14+4i 12+4i 16+4»
R->M (2 n) (2h) (3n) (3 n) (3ta) (4b)
Long 8+8n - 8+«n 12+8n 14+8n 12+8n 18+8n
(22n) (22n) (32n) (32n) (32) (42n)
Notes : * mot seulement
+ajouter te temps de calcul de l'adresse effective
ARP, les disquettes d’Amiga Revue : bibliothèque de fichiers 3D (Sculpt, Turbo Silver), des musiques, les domaines publics dont on parle...
Notes : n représente te nombre de registres
La taille du registre d'index de modifie pas te temps d'exécution
Instructions en multiprécision
rid
“s
s
2
S
rS.
ZD
u-
Z
w
00
Z
rs
Z2
M,K
oc
A
8(1 1)
12(2 0)
12(2 0)
ANDI to CCR .B 20(3 0) ANDI to SR .W 20(3 0) CHK 10(1 0)+
EORI to CCR .B 20(3 0) EORI to SR .W 20(3 0) OKI to CCR .B 20(3 0) ORI to SR.W 20(3 0) MOVE fran SR 6(1 0) M3VE to CCR 12(2 0) MOVE to SR 12(2 0)
EXG 6(1 0) -
EXT .W 4(1 0)
.L 4(1 0) -
LINK 16(2 2)
MOVE fran US? 4(1 0)
MOVE to DSP 4(1 0) NOP 4(1 0)
RESET 132(1 0)
RTE 20(5 0)
RTS 16(4 0)
STOP 4(0 0)
SNA? 4(1 0) -
TRAPV 4(1 0)
OTLK 12(3 0)
ADDX .3, .W 4(1 0) 18(3 1)
.L 8(1 0) 30(5 2)
OÎPM .B, .W - 12(3 0)
.1 - 20(5 0)
SÜBX .B, .W 4(1 0) 18(3 1)
.L 8(1 0) 30(5 2)
ABCD .B 6(1 0)18(3 1)
SBCD.B 6(1 0)18(3 1)
par Loïc FAR
Instr. Taille Registre Mémoire
instructions diverses
Instr. Taille r», Dr.
Note : + ajouter le temps de calcul de l'adresse effective
MOVEP
Instr. Taille R->M M->R
M3VEP .W 16(2 2) 16(4 0)
.L 24(2 4) 24(6 0)
Procédures d'exceptions
ExceptionPériodes
Address Error 50(4 7)
Bus Error50(4 7)
CHK Instruction 44 (5 4) +
Divide by zéro 42(5 4)
Illégal instruction 34(4 3) Interrupt44(5 3)*
Privilège violation 34(4 3) RESET** 40(6 0)
Trace 34(4 3)
7RAP instruction 38(4 4)
TRAPV instruction 34(4 3)
Notes :+ajouter le temps de calcul de l'adresse effective
* le cycle de reconnaissance de l'interruption est considère prenant 4 périodes d’horloge
ir
* * indique le temps passé entre l'instant où RESET et HALT sont aflimiés. Et le début de l'instruction
Le mois prochain, ExecBase vous proposera une liste complète et détaillée de toutes les instructions du 68000 : syntaxe, mode(s) d'adressage, codage de l’instruction, flag(s) modifié(s)... Préparez la photocopieuse !
|0[ COMPILATEUR CT>P"
Ce compilateur est Voeuvre de Matt Dülon, programmeur altruiste s’il en est, et que tous ceux qui suivent un tant soit peu le domaine public connaissent bien. DICE est normalement distribué sur la disquette Fred FISH359, mais comme la bonté de l’équipe d’Amiga News Tech n ’a pas de limites, vous le trouverez dans le répertoire DICE de | notre disquette du mois.
En fait, ce programme n’est pas vraiment du domaine public, mais "shareware". Ceci veut dire que si vous êtes satisfait du programme et que vous l’utilisez souvent, il est de bon aloi d’envoyer une somme d’argent à son auteur. Ici, tout est affaire de conscience. Matt suggère la somme de 40 dollars (soit environ 200 F), ce qui est donné pour un compilateur C. L’adresse de Matt Dilon est dans la doc.
Le principe Shareware fonctionne très mal dans notre pays à la belle mentalité (français égale voleur ?). Il serait bon que cela change, car alors nombre de développeurs seraient incités à donner leurs produits, et les éditeurs distriburaient les logiciels avec un peu plus d’entrain qu'actuellement. Les coûts baisseraient et les produits seraient plus faciles à trouver, ce qui ne serait assurément pas un mal. Bref, le monde serait plus beau. On peut rêver.
RECUPERATION DES FICHIERS
Dans le répertoire DICE de nome disquette, vous verrez quelques fichiers texte destinés à vous fournir certaines informations utiles, ainsi qu’un gros fichier nommé DICE.lzh. Ce fichier est le compilateur compacté (comme sur la Fred FISH) car sinon, il occuperait à lui seul tout la disquette (plus de 680 Ko !).
11 faut donc d’abord décompacter tout ça en procédant comme suit depuis le Shell.
1) premier cas. Vous êtes l'heureux possesseur de deux lecteurs de disquettes:
- mettre en DF1: une disquette et la formater de cette manière avec la commande "format drive dfl: name DICE noicons" :
- faire ensuite "cd dfl:" :
- après l'avoir protégée en écriture, insérer la disquette du journal en dlü: et taper "ANT21:DICÈ LHArc -x -a -m x ANT21:DICE dice.Izh".
Ainsi tout se décompactera et le résultat sera sur votre disquette fraîchement formatée. Faites néanmoins bien attention à ne pas faire de fautes dans la ligne de commande de LHArc afin d’éviter des résultats inattendus ou catastrophiques. Il est indispensable de protéger la disquette de l’ANT en écriture, le programme de décompactage n’ayant normalement pas besoin d'y écrire quoi que ce soit.
2) deuxième cas. Vous ne disposez que d’un lecteur de disquettes :
- formater d'abord une disquette par avec "format drive dfO: name DICE noicons" ;
- faire ensuite, avec la disquette qui vient d’être formattée en dfO:. "cd dice:":
- après avoir protégée en écriture la disquette du journal, taper "ANT21:DICE LHArc -x -a -m x ANT21:DICE dice.Izh .
Et. ô miracle de la technologie moderne, le compilateur sera décompacté et prêt à être installé. Il est néanmoins conseillé d'ajouter dans la Startup-Sequence. La ligne "Assign DICE: DH0:DICE".
INSTALLATION DU COMPILATEUR
Lorsque les opérations précédentes seront terminées, vous trouverez sur votre disquette ou répertoire DICE :
- un répertoire nommé bin qui contient les éxécutables du compilateur :
- un répertoire nommé c qui contient quelques utilitaires, notamment l'assembleur du domaine public A68k et l'éditeur de Matt Dillon, DME :
- un répertoire nommé diib qui contient les librairies propres à ce compilateur ;
- un répertoire nommé doc qui contient les documentations (mais si) en anglais :
- un répertoire nommé dutil qui contient le source C de l'utilitaire libtos, dont nous reparlerons plus loin ;
- un répertoire nommé examples. Devinez ce qu'il contient :
- un répertoire nommé include qui contient... des fichiers include :
- enfin un répertoire nommé lib qui contient les sources de dlib.
Voilà. Pour pouvoir être utilisé, le compilateur a besoin de savoir comment accéder à certains des répertoires vus ci-dessus, c’est ce qui s’appelle l'installation. Il vous suffit d'écrire le fichier script suivant nommé par exemple et au hasard "dice" :
Assign DINCLUDE: dicerinclude Assign DLIB: dice:dlib Path dice:bin ADD
Pour installer le compilateur, il vous suffira de faire "execute dice" et ce sera prêt. Vous pouvez également, sur WorkBench 1.3, rendre ce fichier directement éxécutable par "protect dice +s". Il suffira alors d’appeler ce programme par son nom, sans utiliser la commande "execute". Mais le mieux est encore d’inclure ces lignes dans votre Startup-Sequence, si vous possédez un disque dur.
Voilà notre compilateur prêt à être utilisé. Il y a cependant une ombre au tableau : si vous examinez le contenu du répertoire include, vous verrez que celui-ci ne CONTIENT PAS les fichiers include Commodore, de même que le répertoire dlib ne contient pas la librairie Amiga.lib. Cette situation provient du fait que Commodore ne considère pas du tout ses fichiers include comme faisant partie du domaine public, ce qui nous interdit de les distribuer sur notre disquette.
Si vous avez déjà le compilateur Lattice ou Aztec. Alors vous possédez ces fichiers, sinon il faut vous les procurer auprès de Commodore (et non pas auprès de Commodore Revue, ni même de l'ANT. Ne confondons pas tout).
Et vous parviendrez au résultat escompté, dans la mesure ou vous aurez la
patience de faire tous les changements de disquette que le système vous COMMENÇONS demandera. Bon courage !
3) troisième cas, vous avez un disque dur (petit veinard) :
- créer au préalable un répertoire DICE sur votre disque dur, avec la commande "nid DH0:DICE" (ou FHO: ou JHO: ou je ne sais quoi) ;
- se positionner dans le répertoire nouvellement créé, avec "cd DH0:DICE":
- protéger ensuite la disquette du journal et l'introduire dans DFO: ;
- enfin, taper "ANT21:DICE LHArc -x -a -m x ANT21:DICE dice.lzh".
L'Amiga.lib n'est pas utilisable directement par DICE. Il faut user du programme libtos (l’éxécutable est dans le répertoire bin) afin de rendre Amiga.lib utilisable par DICE. Procédez comme suit:
- copy xxx amiga.lib to ram: (xxx est l'endroit ou vous avez rangé votre amiga.lib) :
- libtos ramramiga.Iib ramrtoto.lib
DICE
par Frédéric MAZUE P | n|
- delete ram:amiga.lib
- rename ram:toto.lib ram:amiga.Iib
- copy ramramiga.Iib DICErdlib
COMPILONS
cette fois tout est prêt et nous pouvons essayer avec le traditionnel "hello world” (coucou anglais).
Main()

printff'hello world"); retum(O);
}
Supposons que ce source nommé hello.c soit en ram:. La commande ' globale" de compilation est dcc. Il y a bien sûr plusieurs options mais commençons par le plus simple et le minimum.
Dcc ramrhello.c -o ramrhello
Explication : le premier paramètre à donner est le nom du source à compiler. Ensuite, le compilateur doit savoir où placer et comment nommer le résultat avec l’option -o (l’endroit effectif est ram:hello). Respectez bien l'espace derrière -o. Par cette commande le programme est d’un seul coup compilé, assemblé et linké. Hello est maintenant un programme exécutable.
Voyons quelques options intéressantes :
- l'option -c Oa commande de l’exemple devient: dcc -c ram:hello.c -o ramrhello) : cette option fait que le programme sera compilé et assemblé mais non linké. On obtient donc un fichier objet :
- l’option -a : interdit l’assemblage (et donc l’édition de liens). En fait, on obtient ainsi un source assembleur. Cette option est vraiment très intéressante, car ainsi vous avez la possibilité de modifier le source à votre guise, à des fins d’optimisation par exemple. Il faut quand même dire que le code initialement produit est très bon ;
- 1 option -s : ajoute les informations de débogage. Le débogueur n'existe pas encore, mais il est facile par exemple d’utiliser celui de Devpac 2.
Il existe bien sûr beaucoup d'autres options, mais il ne pas question de réécrire ici la doc, qui est d’ailleurs d'un anglais très accessible.
L’EDITEUR DE LIENS
Il s'appelle dlink. C’est un excellent programme très rapide. Il est toutefois à regretter qu’il ne puisse pas générer d'overlays. Ceci sera possible, aux dires de Matt Dillon. Dans une version ultérieure.
Bien sûr. Le premier exemple donné plus haut appelle directement dlink. Sans qu’il soit besoin de s’en soucier. Nez en moins, les programmeurs C aiment souvent avoir la main et linker eux-mêmes leurs programmes.
Dlink s’utilise comme suit :
- il faut d abord écrire un fichier ASCII qui contient le nom des codes objets à linker et le nom des librairies :
Exemple : fichier "fïles.lnk" alpha.o
beta.o
beta_asm.o
dlib:c.lib dlib:amiga.lib dlib:auto.lib
Notre fichier "fïles.lnk" contient le nom de trois codes objet. Les deux premiers sont issus de sources c, le troisième d’un source assembleur. Il contient enfin la liste des libraries avec lesquelles il faut linker. Dans notre exemple, il y a les librairies traditionelles. Mais rien ne vous empêche d ajouter vos libraries personnelles. La première librairie définie dans "file.lnk" est la première utilisée.
Pour linker. Il suffit maintenant de taper:
dlink dlib:c.o @files dlib:x.o -o rani:delta
Le programme à bien sûr besoin d'un startup. Ici "c.o" (ceux qui parmi vous se sentent I âme d un bidouilleur peuvent évidemment écrire un startup personnel). Ensuite, nous avons x.o. Une originalité, car c’est un code de sortie de programme. Même si ça semble bizarre au début, cela offre des possibilités qui pourront faire le bonheur des bidouilleurs. Enfin, comme dans DCC, la directive de sortie. Dans notre exemple, les programmes alpha.o. beta.o et beta_asm seraient linkés en un seul éxécutable appelé ram:delta.
ET PLEIN D’AUTRES CHOSES ENCORE
Tout ne peut être montré dans le cadre de cet article. Les programmes DCPP (le préprocesseur), DC1 (le compilateur proprement dit). DAS (l’assembleur) sont documentés sur la disquette.
CONCLUSION
DICE est un excellent compilateur C qui donnera satisfaction à tous ceux qui n ont pas les moyens d'acheter un Lattice ou un Aztec. Il faudra toutefois, je le rappelle, acheter les fichiers include auprès de Commodore France.
DICE compile vite et bien. Mes essais montrent qu’il compile plus vite que ' Aztec ou le Lattice. Le code produit est très optimisé. Mais il est à regretter qu il n y ait pas d option de vérification de dépassement de pile (c’est assez vite aimé en C sur de gros programmes), ni de possibilité de passer les paramètres directement par les registres (comme les protos du Lattice) au lieu de la pile.
J'ai essayé DICE sur nombre de programmes et tout c'est bien passé, sauf... avec 1 utilitaire SuperShell de ce mois où DICE plante sur la fonction AdjustMenu() (semble-t-il) et produit un gourou. Je n’ai pas eu le temps d approfondir la question, mais il est certainement possible d’écrire ce programme un peu différement afin que cela "passe” à la compilation. Malgré ce petit bug. DICE est un utilitaire remarquable, surtout si l’on songe qu’il est le résultat du travail d’une seule personne. De plus. Matt Dillon envisage d’améliorer sans cesse DICE afin qu'il puisse un jour procurer un environnement de développement comparable à celui des compilateurs "pro". Tout en restant toujours dans le domaine public. Pareille délicatesse mérite bien d'être récompensée par 40 dollars n’est-ce pas ?
Frédéric MAZUE TH
BOBS ET LISSAJOUS
Vous avez tous vu tôt ou tard une démo avec des Bobs tournant dans tous les sens, selon une courbe mathématique dont Vutilisateur peut modifier les paramètres. C’est exactement ce que je vous propose de réaliser aujourd’hui.
Pour cela, nous n'avons pas besoin de grand chose : une bonne table de sinus rangée quelque part en mémoire, l'image d'un Bob à afficher - plus il est petit, plus on peut en mettre : ici. On affiche 86 Bobs de 16x16 pixels en 8 couleurs contenu dans une matrice de 32x16 pixels - et une bonne courbe de base suffiront amplement. Par la suite, c'est à l'utilisateur de modifier certains paramètres, qui influeront sur la courbe. Pour commencer, une bonne Lissajou fera l'affaire : son équation est suffisamment simple pour être exécutée rapidement, tout en produisant un effet visuel satisfaisant.
Les valeurs courantes seront affichées à l'écran en utilisant un Sprite. Ce qui évite de gérer la sur-impression des caractères et des bobs. Le joystick branché dans le port 1 permet de modifier les paramètres de la courbe. Comme d'habituc. On utilise le bouton gauche de la souris pour terminer la démo. Le bouton droit sert à acier l'animation.
"include:" "hardware custcm.i" "exec exec lib.i"
inedir
include
include
section text,code
ciaapra = SbfeOOl startlist = 38 key = SbfecOl custcm = $ dff000 execbase = 4 chip = $ 2 clear = $ 10000
coplist_size = 4*4000*2
spr_x = 16 spr_y = 14 spr depth = 3 spr_width = spr_x 8 spr_modulo = 2
spr_blt = spr_y*spr_depth*64+(spr_width+2) 2
bpl_x = 320
bpl_y =256
nb_bpl = 3
bpl_width = bpl_x 8
medulo = bpl_width*(nb_bpl-l)
tpl_size = bpl_width*bpl _y *nb_bpl
nbspr =70
mem_need SET (fcpl_size*2) msm_need SET mem_need+ ( 12 *nb_spr ) msn_need SET mem_need+$ 800 mem_need SET mem_need+(4*tpl_y) mem need SET mem_need+coplist_size
add.w (al,d0.w),d2
spr_ang_ax:
ds.l
1
move.w spr_ang_c_3(pc),d0
spr_ang_ay:
ds.l
1
and.w d4,d0
spr_ang_bx:
ds.l
1
add.w d0,d0
spr_ang_by:
ds.l
1
add.w (a0,d0.w),dl
spr_ang_c_l:
ds.l
1
move.w spr_ang_c_4(pc),dO
spr_ang_c_2:
ds.l
1
and.w d4,d0
spr_ang_c_3:
ds.l
1
add.w d0,d0
spr_ang_c_4:
ds.l
1
add.w (al,d0.w),d2
spd_ang_ax:
dc. l
$ 50000
spd_ang_ay:
dc. l
$ 35000
convertit (X,Y) en adresse + shift
spd_ang_bx:
dc. l
$ 2a300
add.w d2,d2
spd_.ang_by:
dc. l
$ 13000
add.w d2,d2
gap_.ax :
dc. l
$ a0000
move.l (a3,d2.w), 32
gap_ay:
dc. l
$ c0000
add.l bpl_adr(pc),d2
gap_bx:
dc. l
$ b0000
move.w dl,d0
gap_by:
dc. l
$ 90000
and.w d5,d0
tab_shift_adr
ds.l
1
lsr.w 3,d0 add.w d0,d2
tab_shi ft_adr_
buffer:
ds.l
* main prg *
* ***********
bsr
raain_init
main_loop:
move.l and. 1 errp. 1 fcne.s
bsr
move.b
vposr(a5),d0 $ lff00,d0 $ 12a00,d0 main„loop
move_spr
key,d0
not dO ror.b l,d0 cmp.b $ 45,dO bec init_end btst 6, $ bfe001 bec init_end btst 10,$ dff016
?ne. S no_freeze freeze btst 10,$ dff016 beq.s freeze no_freeze: bra mainloop
* ANIM spr *
* ***********
dst_mod EQO bpl_width- ( spr_.width+2 )
moveq 0,d0 move.w 0,bltal*«n(a5) move.w -l,bltafvan(a5) move.w spr_modulo,bltamod(a5) move.w spr_modulo,bltbnod(a5) move.w dst_mod,bltcmod(a5) move.w dst_mod,bltdmod(a5)
; *** Efface tcus les Bobs movem. 1 spd _ang ax(pc), d0-d3 lea spr_ang_ax(pc),a4 add.l dO,(a4) + add.l dl,(a4)+ add.l d2, (a4) + add.l d3, (a4) +
movem. 1 spr_ang_ax (pc ), d0-d3 movem.l d0-d3,spr_ang_c_l move.1 mul_sin_tab(pc),al move.1 mul_cos_tab(pc),aO move.l tab_shift_adr(pc),a2 move.l line_adr(pc),a3 move.w $ lff,d4 move.w $ lf0,d5 move.w spr_blt, d6 moveq nb_spr-l,d7
coor_each_spr:
btst 14,dmaconr(a5) ine.s coor_each_spr move.w d5,bltcon0(a5) move.w 0,bltadat(a5) move.l (a2),bltdpt(a5) move.w d6,bltsize(a5)
,- *** Calcule leurs nouvelles coordonnées move.w (bpl_x-spr_x) 2,dl moveq (tpl_y-spr_y) 2,d2 move.w spr_ang_c_l (pc ), dO and.w d4,d0 add.w d0,d0 add.w (aO.dO.w),dl move.w spr_ang_c_2(pc),dO and.w d4,d0 add.w d0,d0
d2,(a2)+
irove.l
and.w
ror.w
move.w
movem.l
lea
add.l
add.l
add.l
add.l
dbf
$ f,dl 4,dl dl,(a2)+
gap_ax(pc),dO-d3 spr_ang_c__l (pc), a4 dO,(a4)+ dl,(a4)+ d2,(a4)+ d3,(a4)+
d7,coor_each_spr
Affiche à nouveau tous les Bobs move.l tab_shift__adr(pc) ,a0 move.w $ 0fca,dl move.1 pic adr,d2
move.l pic_mask,d3
move.w spr_blt,d4
nb_spr-l,d7
moveq
aff_each_spr: btst bne.s move.l move.l move.l move.l move.w move.w or.w move.w move.w dbf
14,dmaconr(a5)
af f_each_spr
d2,bltbpt(a5)
d3,bltapt(a5)
(aO),bltcpt(a5)
(a0)+,bltdpt(a5)
(a0)+,d0
dO,bltccnl(a5)
dl. dO
dO,bltconO(a5) d4,bltsize(éi5) d7,aff_each_spr
; *** Swappe les deux écrans
move.l ccplist_adr(pc),a0
moveq nb_bpl-l,d0
move.l bpladr(pc),dl
loop_init_bplpth_clistl: addq.l 2,a0
swap dl
move.w dl,(a0)+
swap dl
addq.l 2,a0
move.w dl,(a0)+
add.l bpl width,dl
dbf dO,loop_init_bplpth_clistl
move.1 bpl_adr(pc),dû
tpl_adr_buffer(pc),bpl_adr dO,bpl_adr_buffer tab_shift_adr(pc),dO
move.l move.l move.l move.l
tab_shift_adr_buffer(pc),dl
move.l dl, tai>_shi f t_adr
dO,tab_shift_adrbuffer changepara
move.l
bsr
rts
init_spr: lea pic_palette,aO moveq 7,d0 lea color(a5),al loop_init_cmap: move.w (a0)+,(al)+ dbf dO,loop_inic„cmap
lea pic_adr,aO lea 64(a0),al lea 64(al),a2 lea pic_mask,a3 move.w 16-1,dO loop_init_mask: move.l (aO)+,dl or.l (al)+,dl or.l (a2)+,dl move.l dl,(a3)+ dbra dO,loop_init_mask
clr.l spr_ang_ax clr.l spr_ang_ay clr.l spr ang bx clr.l spr_ang_by
move.l tab_shift_adr(pc),a0 move.l tab_shift_adr_buffer(pc),al moveq nb spr-l,dO init_tab_for_first_clr: move.l tpl_adr(pc),(a0)+ clr.w (a0) +
move.l fcpl_adr_tuffer(pc), (al) + clr.w (al)+
dbf dO.init tab_for_first_clr
lea spr2_adr,aO addq.l 4,a0 lea spd ang ax (pc ), a2 moveq 8-1,d7 init_spd_ang_ax_on_scr: move.l (a2)+,d5 lsr.l 8,d5 roi.w 4,d5 bar aff_number lea 4*6(a0),a0
dbf d7,init_spd_ang ax on_scr
move.w $ aaa,color+18*2(a5) move.w $ a0,color+22*2(a5)
moveq 0,dl lea sin_tab(pc),aO lea cos_tab(pc),al move.l nul_sin_tab(pc),a2 move.l nul_cos_tab(pc),a3 build_mul_sin_tab: move.w dl,dO add.w dO,dO move.w (a0,d0.w),d0 nuls (bpl_y-spr_y) 4,d0 add.l dO,dO swap dO
move.w dO, a2) +
move.w dl,dO
add.w dO,dO
move.w (al,d0.w),d0
muls (tpl_x-spr_x) 4,dO
add.l dO.dO
swap dO
move.w dO,(a3)+
addq.w l,dl
cmp.w $ 200,dl
tue.s build_nul_sin_tab
moveq 0,d0
move.l line_adr(pc),a0 build_line_adr: move.l d0,dl mulu bpl_width+modulo,dl move.l dl,(a0) + addq.w l,d0 cnp.w fcpl_y,d0 bue.s buildlineadr rts
tpl_adr: ds.l 1 tpl_adr_buf fer : ds.l 1 nul_sin_tab : ds. 11
mul_cos_tab:
ds.l 1
rept
3
1ine_adr: ds. 1
1
lsl.w
5,d0
lsl.w
5,dl
lsl.w
5,d2
end_spr rts
lsl.w
5,d3
lsl.w
5,d4
move.w
d5,d6
pos_arrcw: ds.l
1
and.w
$ f,d6
change_para:
add.w
d6,d6
* ** change_randcm_para
add.w
d6,d6
movem.l
move.l
tab adr_aff(pc,d
md_inc_spd_ang_ax(pc)
d0-d7
jsr
(al)
lea
rnd_spd_ang_ax(pc),aO
rol.w
4,d5
add.l
dO,(a0)+
endr
add.l
dl,(a0)+
movem. 1
d0-d4,(aO)
add.l
d2,(a0)+
rts
add.l
d3,(a0)+
add.l
d4,(a0)+
tab adr aff:
add.l
d5,(a0)+
dc. l
aff 0,aff l,aff_
add.l
d6,(a0)+
de. 1
aff_4,aff_5,aff_
add.l
d7,(a0)+
dc. l
aff 8,aff 9,aff
dc. l
aff c,aff_d,aff_
lea
rnd_spd_ang_ax(pc),aO
rept
4
choose.. randctrt_curve :
and.l
$ 7f000,(a0)+
btst
7,$ bfe001
endr
bne.s
no_ but ton
and.l
$ lff000,(a0) +
movan.l
md_spd_ang_ax (pc
and.l
$ lff000,(a0>+
movem.l
d0-d7,spd_ang_ax
and.l
$ ff000,(a0)+
no_button:
and.l
$ ff000,(a0)+
rts
* ** aff new para
md spd ang ax:
dc. l $ f2000
move.w
joyldat(a5),dO
md_spd_ ang_ay :
dc. l $ 52900
move.w
d0,dl
md_spd_ang_x :
dc. l $ 32000
move.w
d0,d2
md_spd_ang_by :
dc. l $ a0000
lsr.w
l,dl
md gap ang ax :
dc. l $ 7c000
eor.w
d0,dl
md oap ana av :
dc. l $ 81000
btst
0,dl
md_gap_ang_x :
dc. l $ 93000
beq.s
no_top
md_gap_angby :
dc. l $ a0000
add.l
$ 2000,pos arrcw
md_inc_spd_ang_ax
dc. l $ 2000
no_top: btst
8,dl
md_inc_spd_ang_ay
dc. l $ 9000
beq.s
no_bottcc
md_inc_ spd_ang_x :
dc. l $ 2000
sub.l
$ 2000,pos_arrow
md_inc_spd_ang_by
dc. l $ 6000
no_bottcm:
md inc_gap_ang_ax
dc. l $ c000
and.w
$ f, pos__arrow
md inc gap ang_ay
dc. l $ 1000
crrp.w
8,pos_arrow
md_ inc_gap_ang_x :
dc. l $ 3000
ble.s
no_chane_pos_arrcw
md_inc_gap_ang by
dc. l $ a000
clr.w
pos arrow
no_chane_pos_arrcw :
move.w
pos arrcw(pc),d0
aff 0: or.b
%0110,d0
add.w
d0,d0
or.b
mooi,di
move.w
d0,dl
or.b
mooi,d2
add.w
d0,d0
or.b
r-aooi,d3
add.w
dl. dO
or.b
%0110,d4
add.w
$ 29,dO
rts
lea
spr3_adr,a0
aff_l: or.b
%0010,d0
move.b
dO,(aO)
or.b
%0110,dl
addq.w
5,d0
or.b
%1010,d2
move.b
dO,2(aO)
or.b
%0010,d3
or.b
%0111,d4
cnp.w
8,pos_arrow
rts
beq
choose_randcoi_curve
aff_2: or.b
%0110,d0
or.b
%1001,dl
lea
spd_ ang_ax(pc), aO
or.b
%0010,d2
move.w
pos arrow(pc),d0
or.b
%0100,d3
add.w
d0,d0
or.b
mill,d4
add.w
d0,d0
rts
lea
(a0,d0.w),a0
aff 3: or.b
%1110,d0
or.b
%0001,dl
btst
l,d2
or.b
%0110,d2
beq.s
inc_value
or.b
%0001,d3
add.l
$ 1000,(aO)
or.b
%1110,d4
inc_value:
rts
btst
9,d2
aff_4: or.b
%1000,d0
beq.s
dec value
or.b
smooo.di
sub.l
$ 1000,(aO)
or.b
r-&1010,d2
dec_value:
or.b
%1110,d3
and.l
$ fff000,(aO)
or.b
%0010,d4
move.l
(a0),d5
rts
lsr.l
8,d5
aff_5: or.b
%llll,d0
roi .w
4,d5
or.b
°-aooo,di
lea
spr2_adr+4,a0
or.b
5ail0,d2
move.w
pos arrow (pc),d0
or.b
%0001,d3
nulu
6*4,dO
or.b
%1110,d4
lea
(a0,d0.w),a0
rts
aff_6: or.b
V)110,d0
aff_number:
or.b
%1000,dl
moveq
0,d0
or.b
r-&1110,d2
moveq
0,dl
or.b
%1001,d3
moveq
0,d2
or.b
%0110,d4
moveq
0,d3
rts
moveq
0,d4
aff 7: or.b
%llll,d0
AMIGA NHWS-TECH IF N 21 AVRIL I99I
13
or.b *0001.dl
move.w
$ 03e0,dmacoa(a5)
move.w Sfcpl2mod,(a0)+
or.b *0010.d2
move.w modulo, (a0) +
or.b *0100,cl3
bsr
init_spr
or.b *1000,d4
bsr
init__plane
move.
1 $ fffffffe,(a0)+
rts
bsr
init_coplist
rts
aff 8: or.b *0110,dO
or.b *1001,dl
move.l
coplist_adr,copllc(a5)
or.b *0110,d2
clr.w
copjnpl (a5)
sin_tab:
or.b *1001,d3
move.w
$ 87e0,dmacon(a5)
dc. w
$ 0000,$ 0192,$ 0324,$ 04B6
or.b *0110,d4
rts
dc. w
$ 0647,$ 07D9,$ 096A, $ 0AFB
rts
dc. w
S0C83,S0E13,$ 0FAB,$ 1139
aff_9: or.b *0110,dO
man_adr dc.l
0
dc. w
$ 12C8,$ 1455,$ 15B2,$ 176D
or.b *1001,dl
dc. w
$ 18F8,$ 1A82,$ 1003,$ 1093
or.b *0111,d2
* ********
dc. w
$ 1F19,$ 209F,$ 2223,$ 23A6
or.b *0001,d3
init_plane:
dc. w
$ 2528,$ 26A8,$ 2826,$ 29A3
or.b *1110,d4
move.l
$ 32000000,fcplcon0(a5)
dc. w
$ 231?,$ 2098,$ 2E11,$ 2F87
rts
move.w
$ 0024,bplcon2(a5)
dc. w
$ 30FB,$ 326E,$ 33DE,$ 354D
aff a: or.b *0110,dO
move.w
modulo, bpl Imod ( a5 )
dc. w
S363A,$ 3824,$ 3980,$ 3AF2
or.b *100l,dl
move.w
modulo,bpl2mod(a5)
dc. w
$ 3056,$ 3DB8,$ 3F17,$ 4073
or.b *1111,d2
move.l
$ 298129cl,diwstrt(a5)
dc. w
$ 41CE,$ 4325,$ 447A,$ 45CD
or.b *1001,d3
move.l
$ 003800d0,ddfstrt(a5)
dc. w
$ 4710,$ 4869,$ 49B4,$ 4AFB
or.b *100l,d4
rts
dc. w
$ 4C3F,$ 4D81,$ 4EBF,$ 4FFB
rts
dc. w
$ 5133,$ 5269,$ 539B,$ 54CA
aff_b: or.b *1110,dO
dc. w
$ 55F5,$ 5710,$ 5842,$ 5964
or.b *1001,dl
init_coplist:
dc. w
$ 5A82,$ 5B9D,$ 5CB4,$ 5DC7
or.b *1110, 32
move.l
coplist_adr(pc),a0
dc. w
$ 5ED7,$ 5FE3,$ 60EC,$ 61F1
or.b *1001,d3
dc. w
$ 62F2,$ 63EF,$ 6438,$ 6510
or.b *1110,d4
moveq
nb bpl-l,d0
dc. w
$ 66CF,$ 67BD,$ 68A6,$ 6980
rts
move.w
bplpt,dl
dc. w
$ 6A6D,$ 634A,$ 6024,$ 6CF9
aff c: or.b *0111,dO
move.l
bpl_adr(pc),d2
dc. w
$ 6DCA,$ 6396,$ 6F5F, $ 7023
or.b *1000,dl
loop_init_bplpth_clist :
dc. w
$ 7032,$ 7193,$ 7255,$ 7307
or.b *1000,d2
move.w
dl,(a0)+
dc. w
$ 73B5,$ 745F,$ 7504,$ 75A5
or.b *1000,d3
addq.w
2,dl
dc. w
$ 7641,$ 76D9,$ 7760,$ 77FA
or.b *0111,d4
swap
d2
dc. w
$ 7884,$ 7909,$ 798A,$ 7A05
rts
move.w
d2,(a0)+
dc. w
$ 7A7D,$ 7AEF,$ 7B5D,$ 7BC5
aff d: or.b *1110,dO
swap
d2
dc. w
$ 7029,$ 7089,$ 7CE3,$ 7D39
or.b *1001,dl
move.w
dl,(a0) +
dc. w
$ 7D8A, $ 7306, $ 7E1D, $ 735F
or.b *1001,d2
addq.w
2,dl
dc. w
$ 7E9D,$ 7ED5,$ 7F09,$ 7F38
or.b *1001,d3
move.w
d2,(a0)+
dc. w
$ 7F62,$ 7F87,$ 7FA7,$ 7FC2
or.b *1110,d4
add.l
tpl_width,d2
dc. w
$ 7FD8,$ 7FE9,$ 7FF6,$ 7FFD
rts
dbf
cos_tab:
aff_e: or.b *1111,dO
dO,loop_init_bplpth_clist
dc. w
$ 7fff,$ 7FFD,$ 7FF6,$ 7FE
or.b *1000,dl
9,$ 7FD8,$ 7FC2,$ 7FA7,$ 7F87
or.b *1110, 32
; init spr4pth to spr7pth
dc. w
$ 7F62,$ 7F38,$ 7F09,$ 7ED5
or.b *1000,d3
move.1
spr_null_adr,dO
dc. w
$ 7E9D, $ 7E5F, $ 7E1D, $ 7DD6
or.b *1111,d4
move.w
sprpt+4*4, dl
dc. w
$ 7D8A,$ 7D39,$ 7CE3,$ 7089
rts
moveq
4-1,d2
dc. w
$ 7029,$ 7BC5,$ 7B5D,$ 7AEF
aff_f : or.b *1111,dO
loop_init_clist_spr
dc. w
$ 7A7D,$ 7A05,$ 798A,$ 7909
or.b *1000,dl
move.w
dl,(a0)+
dc. w
$ 7884,$ 77FA,$ 7760,$ 76D9
or.b *1110,d2
addq.l
2,dl
dc. w
$ 7641,$ 75A5,$ 7504,$ 745F
or.b *1000,d3
swap
dO
dc. w
$ 73B5,$ 7307,$ 7255,$ 719E
or.b *1000,d4
move.w
dO, (a0) +
dc. w
$ 7032,$ 7023,$ 6F5F,$ 6396
rts
swap
dO
dc. w
$ 6DCA,$ 6CF9,$ 6024,$ 6B4A
move.w
dl,(a0)+
dc. w
$ 6A6D,$ 6980,$ 68A6,$ 67BD
addq. 1
2,dl
dc. w
S66CF,$ 65DD,$ 64E8,$ 63BF
* MAIN INIT *
move.w
dû, (a0) +
dc. w
$ 62F2,$ 61F1,$ 6030,$ 5FE3
• •••*•*•*•••••
dbf
d2,loop_init_clist_spr
dc. w
$ 5ED7,$ 5DC7,$ 5CB4,S5B9D
maininit:
; init sprOpt
dc. w
$ 5A82,$ 5964,$ 5842,$ 571D
move.1 $ 4.w, a6
move.l
spr0_adr,d0
dc. w
$ 55F5,$ 54CA,S539B,$ 5269
move.1 mem_need,dO
move.w
sprpt, (a0) +
dc. w
$ 5133,$ 4FFB,$ 4EBF,$ 4081
move.l $ 10002,dl
swap
dO
dc. w
$ 4C3F,$ 4AFB,$ 49B4,$ 4869
jsr _LVOAllocMem(a6)
move.w
dO,(aO)+
dc. w
$ 4710,$ 45CD,$ 447A,$ 4325
move.l d0,mem_adr
swap
dO
dc. w
$ 41CE,$ 4073,$ 3F17,$ 3DB8
fcoe.s ok_mem
move.w
sprpt+2,(a0)+
dc. w
$ 3056,$ 3AP2,$ 3980,$ 3824
move.w
dO,(aO)+
dc. w
$ 36BA,$ 354D,$ 33DE,$ 3263
addq.l 4,sp
; init sprlpt
dc. w
$ 30FB,$ 2F87,$ 2E11,$ 2098
moveq -l,d0
move.l
sprl_adr,d0
dc. w
$ 2B1F,$ 29A3,$ 2826, $ 26A8
rts
move.w
sprpt+l*4,(a0)+
dc. w
$ 2528,$ 23A6,$ 2223,$ 209F
swap
dO
dc. w
$ 1F19,$ 1D93,$ 1C0B,$ 1A82
ok_mem move.l dQ,bpl_adr
move.w
dO, (a0) +
dc. w
$ 18F8,$ 176D,$ 1532,$ 1455
add.l tpl_size,dO
swap
dO
dc. w
$ 1208,$ 1139,$ 0FAB,$ 0B1B
move.l dO,fcpl_adr_buffer
move.w
sprpt+l*4+2,(a0)+
dc. w
$ 0C8B,$ 0AFB,$ 096A,$ 07D9
add.l bpl_size,d0
move.w
dO,(a0) +
dc. w
$ 0647,$ 04B6,$ 0324,$ 0192
; init spr2pt
dc. w
$ 0000,$ FE6E,$ FCDC,$ FB4A
move.l d0,tab shift adr
move.l
spr2_adr,d0
dc. w
$ F9B9,$ F827,$ F696,SF505
add.l 6*nb_spr,d0
move.w
sprpt+2*4,(a0)+
dc. w
$ F375,$ F1E5,$ F055,$ EEC7
move.1 dO,tab_shift_adr_buffer
swap
dO
dc. w
$ ED38,$ EBAB,$ EA1E,$ E893
add.l 6*nb_spr,d0
move.w
dO,(a0)+
dc. w
$ 3708,$ 3573,$ E3F5,$ E26D
swap
dO
dc. w
$ E0E7,$ DF61,$ DDDD,$ DC5A
move.1 dO,mul_sin_tab
move.w
sprpt+2*4+2,(a0)+
dc. w
$ DAD8,$ 0958,$ D7DA,$ D65D
add.l 2*$ 200,d0
move.w
dO,(a0)+
dc. w
$ D4E1,$ D368,$ D1EF,$ D079
move.1 dO,mul_cos_tab
; init spr3pt
dc. w
$ CF05,$ CD92,$ CC22,$ CAB3
add.l 2*$ 200,d0
move.l
spr3_adr,d0
dc. w
$ 0946,$ C7DC,$ 0674,$ C50B
move.w
sprpt+3*4,(a0)+
dc. w
$ C3AA,$ C24 8,$ C0E9,$ BF8D
move.l dO,line adr
swap
dO
dc. w
$ BB32,$ BCDB,$ BB86,$ BA33
add.l 4*fcpl_y,d0
move.w
dO, (a0) +
dc. w
$ B8E4,$ B797,$ B64C,$ B505
swap
dO
dc. w
$ 3301,$ B27F,$ B141, $ 3005
move.l d0,coplist_adr
move.w
sprpt+3*4+2,(a0)+
dc. w
$ AECD,$ AD97,$ AC65,$ AB36
move.w
dO,(a0)+
dc. w
SAAOB,$ A8E3,$ A7BE,$ A69C
lea custcxn, a5
dc. w
$ A57E,SA463,$ A34C,$ A239
jsr _LVOForbid(a6)
move.w
Sbpllmod, (a0) +
dc. w
$ A129,SAOID,$ 9F14,$ 9E0F
j sr _LVODisable(a6)
move.w
modulo, (a0) +
dc. w
S9D0E,$ 9011,$ 9B18,S9A23
AMIGA NEWS-TECH
i 2 N- 21 AVRIL 1991
jsr
LVOPermit(a6)
dc. l
541110000100000000
dc. l
541001000100000000
move.l
mem_adr(pc),al
dc. l
541110000100000000
move.l
Sinen need.dO
jsr
LVOFreeMem ( a6 )
sprl_adr:
dc. w
$ 2948,$ 6c00
moveq
0,d0
dc. l
540001100010100000
rts
dc. l
54COIOOIOOIOIOOHO
dc. l
54OOIIIIOOOIOOOOOO
dc. l
540010010010100110
wait_blt:
dc. l
560010010010100000
btst
14,dmaconr(a5)
dc. l
0
bne.s
wait_blt
dc. l
560001100010100000
rts
dc. l
540010010010100110
dc. l
540011110001000000
dc. l
dc. l
540010010001000110
560010010001000000
; variables
coplist_adr:
ds.l 1
dc. l
0
dc. l
560011100010100000
* ****** data for txt
dc. l
540010010010100110
gfxbase de. 1
gfxname de .b
1
dc. l
550011110001000000
"graphies.library",0
dc. l
560010010010100110
even
dc. l
560011100010100000
dc. l
0
section
spr data,data_c
dc. l
560011100010100000
dc. l
560010010010100110
spr0_adr:
dc. l
560011110001000000
dc. w
$ 2940,$ 6c00
dc. l
560010010001000110
dc. l
%0111011100111000
dc. l
560011100001000000
dc. l
%1000010010100100
dc. l
0
dc. l
“-sOllOOlllOOlOOlOO
dc. l
560001100010100000
dc. l
560001010000100100
dc. l
560010010010100110
dc. l
561110010000111000
dc. l
560011110001000000
dc. l
0
dc. l
560010010010100110
dc. l
H0111011100111000
dc. l
560010010010100000
dc. l
%1000010010100100
dc. l
0
dc. l
SollOOlllOOlOOlOO
dc. l
560001100010100000
dc. l
560001010000100100
dc. l
560010010010100110
dc. l
561110010000111000
dc. l
560011110001000000
dc. l
0
dc. l
560010010001000110
dc. l
560111011100111000
dc. l
560010010001000000
dc. l
561000010010100100
dc. l
0
dc. l
%0110011100100100
dc. l
%0011100010100000
dc. l
%0001010000100100
dc. l
560010010010100110
dc. l
561110010000111000
dc. l
560011110001000000
dc. l
0
dc. l
560010010010100110
dc. l
560111011100111000
dc. l
560011100010100000
dc. l
%1000010010100100
dc. l
0
dc. l
%011001U00100100
dc. l
560011100010100000
dc. l
%0001010000100100
dc. l
560010010010100110
dc. l
%1110010000111000
dc. l
560011110001000000
dc. l
0
dc. l
560010010001000110
dc. l
560111100110011100
dc. l
560011100001000000
dc. l
5&1000001001010010
dc. l
0
dc. l
561001101001011100
dc. l
560111000110010001
dc. l
561000101111010000
dc. l
560100101001011011
dc. l
560111001001010000
dc. l
560100101001010101
dc. l
0
dc. l
560100101001010001
dc. l
560111100110011100
dc. l
560111000110010001
dc. l
561000001001010010
dc. l
0
dc. l
561001101001011100
dc. l
560011111001100101
dc. l
%1000101111010000
dc. l
560000100010010101
dc. l
%0111001001010000
dc. l
560000100010010010
dc. l
0
dc. l
560000100010010010
dc. l
560111100110011100
dc. l
561100000110001000
dc. l
561000001001010010
dc. l
0
dc. l
561001101001011100
dc. l
561111111111111111
dc. l
ÎSIOOOIOIIIIOIOOOO
dc. l
560000000000000000
dc. l
%0111001001010000
dc. l
540011101110011011
dc. l
0
dc. l
560100001001010101
dc. l
540111100110011100
dc. l
560010001001010001
dc. l
541000001001010010
dc. l
560001001001010001
dc. l
541001101001011100
dc. l
560110001110010001
dc. l
541000101111010000
dc. l
540111001001010000
spr2_adr:
dc. l
0
dc. w
$ 2950,$ 5800
dc. l
541110001100010001
ds.l
8*6
dc. l
541001010010011001
dc. l
541110010010010101
spr3_adr:
dc. l
541010011110010011
dc. w
$ 2958,$ 2e00
dc. l
541001010010010001
dc. l
560000001111111110
dc. l
0
dc. l
560000011111111100
dc. l
541001001110111100
dc. l
560000111111111000
dc. l
541001010000100000
dc. l
560000011111111100
dc. l
541001001100111000
dc. l
560000001111111110
dc. l
541001000010100000
dc. l
540110011100111100
spr null adr:
dc. l
0
dc. l
0
dc. l
$ ffff
dc. l
0
pic_palette
inebin "Balle.spr"
dc. l
541110010001000000
pic_adr
EQU pic_palette+16
dc. l
541001001010000000
pic_ma sk deb. B
64,0
Lilian Margerie de Rueil-Malmaison avait dans un fond de tiroir, une vielle intro réalisée quelques jours seulement après rachat de son Amiga. Et pourquoi ne pas en faire profiter les plus novices d’entre vous ?
Dc.w $ 9931,$ 9843,$ 975A,$ 9674
dc. w $ 9593,$ 94B6,$ 93DC,$ 9307
dc. w $ 9236,$ 916A,$ 90A1,$ 8FDD
dc. w $ 8F1E,$ 8E62,$ 8EAB,$ 8CF9
dc. w $ 8C4B,$ 8BA1,$ 8AFC,$ 8A53
dc. w $ 89B?,$ 8927,$ 8894,$ 8806
dc. w $ 877C,$ 86F7,$ 8676,$ 85F3
dc. w $ 8583,$ 8511,$ 84A3,$ 843B
dc. w $ 83D7,$ 8377,$ 831D,$ 82C7
dc. w $ 8276,$ 822A,S81E3, $ 81A1
dc. w $ 8163,$ 812B,$ 80F7,$ 80C8
dc. w $ 809E,$ 8079,$ 8059,$ 803E
dc. w $ 8028,$ 8017,$ 800A, $ 8003
dc. w $ 8000,$ 8003,$ 800A,$ 8017
dc. w $ 8028,$ 803E,$ 8059,$ 8079
dc. w $ 809E,$ 80C8,$ 80F7,$ 812B
dc. w $ 8163,$ 81A1,$ 81E3,$ 822A
dc. w $ 8276,$ 82C7,$ 831D,$ 8377
dc. w $ 83D7,$ 843B,$ 84A3,$ 8511
dc. w $ 8583,$ 85FB,$ 8676,$ 86F7
dc. w $ 877C,$ 8806,$ 8894,$ 8927
dc. w $ 89BF,$ 8A5B,$ 8AFC,$ 8BA1
dc. w $ 8C43,$ 8CF9,$ 8DA3,$ 8E62
dc. w $ 8F1E,$ 8FDD,$ 90A1,$ 916A
dc. w $ 9236,$ 9307,$ 93DC,$ 94B6
dc. w $ 9593,$ 9674,$ 975A,$ 9843
dc. w $ 9931,$ 9A23,$ 9318,$ 9C11
dc. w $ 9D0E,$ 9E0F,$ 9F14, $ A01D
dc. w $ A129,$ A239,$ A34C,$ A463
dc. w $ A57E,$ A69C,$ A7BE,$ A8E3
dc. w $ AA0B,$ AB36,$ AC65,$ AD97
dc. w $ AEO),$ B005,$ B141,$ B27F
dc. w $ B3C1.$ B505,$ B64C,$ B797
dc. w $ B8E4,$ BA33,$ 3B86,$ BCD3
dc. w $ BE32,$ BF8D,$ C0E9,$ C248
dc. w $ C3AA,$ C50B,$ C674,$ C7DC
dc. w $ C946,$ CAB3,$ CC22,$ CD92
dc. w $ CF05,$ D079,$ D1EF,$ D363
dc. w $ D4E1,$ D65D,$ D7DA,$ D953 de.w $ DAD8, $ DC5A, $ DDDD, $ DF61
dc. w $ E0E7,$ E26D,$ E3F5,$ E57E
dc. w $ E708,$ E893,$ EA1E,$ EBA3
dc. w $ ED38,$ EEC7,$ F055,$ F1E5
dc. w $ F375,$ F505,$ F696,$ F827
dc. w $ F9B9,$ FB4A,$ FCDC,$ FE6E
dc. w $ 0000,$ 0192,$ 0324,$ 04B6
dc. w $ 0647,$ 07D9,$ 096A,$ 0AFB
dc. w $ 0C8B,$ 0E1B,$ 0FAB,$ 1139
dc. w $ 12C8,$ 1455,$ 15E2,$ 176D
dc. w $ 18F8,$ 1A82,$ 1C0B,$ 1093
dc. w $ 1F19,$ 209F,$ 2223,$ 23A6
dc. w $ 2528,S26A8,$ 2826,$ 29A3
dc. w $ 2B1F,$ 2C98,$ 2E11,$ 2F87
dc. w $ 30FB,$ 326E,$ 33DE,$ 354D
dc. w $ 36BA,$ 3824,$ 398C,$ 3AF2
dc. w $ 3C56,$ 3DB8,$ 3F17,$ 4073
dc. w $ 41CE,$ 4325,$ 447A,$ 45CD
dc. w $ 471C,$ 4869,$ 49B4,$ 4AFB
dc. w $ 4C3F,$ 4D81,$ 4EBF,$ 4FFB
dc. w $ 5133,$ 5269,$ 539B,$ 54CA
dc. w $ 55F5,$ 571D,$ 5842,$ 5964
dc. w $ 5A82,$ 5B9D,$ 5CB4,$ 5DC7
dc. w $ 5ED7,$ 5FE3,$ 60EC,$ 61F1
dc. w $ 62F2,$ 63EF,$ 64E8,$ 65DD
dc. w $ 66CF,$ 67BD,$ 68A6,$ 698C
dc. w $ 6A6D,$ 6B4A,$ 6C24,$ 6CF9
dc. w $ 6DCA,$ 6E96,$ 6F5F,$ 7023
dc. w $ 70E2,$ 719E,$ 7255,$ 7307
dc. w $ 73B5,$ 745F,$ 7504,$ 75A5
dc. w $ 7641,$ 76D9,$ 776C,$ 77FA
dc. w $ 7884,$ 7909,$ 798A,$ 7A05 de.w $ 7A7D,$ 7AEF,$ 7B5D,$ 7BC5
dc. w $ 7C29,$ 7C89,$ 7CE3,$ 7D39
dc. w $ 7D8A,$ 7DD6,$ 7E1D,$ 7E5F
dc. w $ 7E9D,$ 7ED5,$ 7F09,$ 7F38
dc. w $ 7F62,$ 7F87,$ 7FA7,$ 7FC2
dc. w $ 7FD8,$ 7FE9,$ 7FF6,$ 7FFD
réactivation de l'old coplist restore nultitasking & dmacon init_end: bsr end_spr bsr wait_blt lea gfxnaine(pc) ,al meveq 0,d0
jsr _LV(X£>enLlbrary(a6) nove.l d0,a4
nove.l startlist(a4),ccpllc(a5) clr.w copjmpl(a5) nove.w $ 83e0,daacca(a5) jsr _LV0Enable(a6)
1 suffisait d'y penser... et de nous envoyer la disquette. L'intro propose un ciel étoilé en perspective, ainsi qu'un petit scrolling de texte. C'est trois fois rien, mais tout de même mignon à voir.
Deux sources sont inclus : le plus gros, en assembleur, est le programme principal. Le second, en GfA Basic, produit le fichier binaire des coordonnées des étoiles.
Note aux abonnés dans disquette : le programme INTRO.S inclut un fichier nommé HARDWARE.I. propre à Lilian. Que nous ne pouvons publier par manque de place. Il contient des EQL’ates pour les registres hardware de l'Amiga. Vous pouvez trouver leur valeur un peu partout, et notamment dans la Bible de f Amiga ou dans le fichier "include:hard vare custom.i" de Devpac 2 (dans ce dernier cas, réglez la différenciation minuscules majuscules sur OFF pour assembler correctement).
Crée les coordonnées X et Y des étoiles ainsi que leur vitesse V. On n'a pas besoin de Z vu qu'au déixit, toutes les étoiles ont la même profondeur
DIM x&(99),y&(99),v&(99)
FOR i&=0 TO 99
x&(i&)=RANDCM(-20)+RANDCM(20) y&(i&)=RANDCM(-30) v&(i&)=RANDCM(10)+5 NEXT i&
OPEN "o". lf"RAD:StarsXYZ.bin" BPUT l,VARPTR(x&(0)),200 BPOT l,VARPTR(y&(0)),200 BPOT l,VARPTR(v&(0)),200 CLOSE 1 EDIT
dc. b
dc. b
dc. b
dc. b
even
! Coordonnée X ! Coordonnée Y ! Vitesse de déplacement
include
"Hardware.I"
Swidth
EQU
40
Sheight
EQU
200
Sdepth
EQU
2 ; 4 couleurs
BPLSize
EQU
Swidth*SHeight
ScreenSize ECU
BPLSize'SDepth
ScrollW
ECU
42
ScrollH
EQU
56
ScrollD
EQU
3 ; 8 couleurs
ScrollBPL
EQU
ScrollW*ScrollH
ScrollSize EQU
ScrollBPL*ScrollD
MemSize
ECU
( ScreenSize*2 ) -t-ScrollSize
section
toto,code c
DemoStrt:
bra
Start
Screenl
dc. l
0
Screen2
dc. l
0
PlaneAdr
dc. l
0
ScrollAdr
dc. l
0
GfxBase
dc. l
0
CLAdr
dc. l
NewCopper
SpriteAdr dc.l
Sprite
Mess
dc. l
Message
Vitesse
dc. b
2
Shift
dc. b
$ 7
Passe
dc. b
0
Stop
dc. b
0
NewCopper:
dc. w
DIWSTRT,$ 2981,DIWSTOP,$ 29cl,
dc. w
BPL1MOD,$ 0000,BPL2MDD,$ 0000,
dc. w
BPLCON1,$ 0000,BPLCON2,$ 0000
CLPlanes:
dc. w
BPL1PTH,0,BPL1PTL,0,BPL2PTH,
dc. w COLOROO,$ 000,COIZJR01,$ 555,COLOR02,$ 777,COLOR03, $ CCC
dc. w $ 8d0f,$ fffe,COLOROO,$ 004,$ 8fOf,$ fffe,COLOROO,$ 005
dc. w $ 910f,$ fffe,COLOROO,$ 007,$ 950f,$ fffe,COLOR00,$ 009
dc. w $ 9d0f,$ fffe,COLOROO,$ 00B,$ ad0f,$ fffe,COLOROO,$ 00D
dc. w $ cd0f,$ fffe,COLOROO,$ 00P CLWait dc.b 241,$ 0f,$ ff,$ fe
dc. w BPLCON0,$ 3000,BPL1MDD,$ 0002,BPL2MDD,$ 0002 CLScroll dc.wBPLIPTC,0,BPL1PTL,0,3PL2PTH,0,BPL2PTL, 0
dc. w BPL3PTH,0,BPL3PTL,0 CLColors2 dc.w COLOROO,$ 000,COLOR01,$ bef,COLOR02,$ 9cf,COLOR03,$ 7ad
dc. w COLOR04,$ 58b,COLOR05,$ 369,COLOR06,$ 147,COLOR07,$ FOO CLWait2: dc.w$ ffdf,$ fffe de. W $ 060f,$ fffe,COLOROO,$ 202,$ 070f,$ fffe,COLOROO,$ 404
dc. w $ 080f,$ fffe,COLOROO,$ 606,$ 090f,$ fffe,COLOROO,$ 808 de .w $ 0a0f,$ fffe,COLOROO,$ A0A,$ 0b0f,$ fffe, COLOROO, $ C0C de .w $ 0c0f,$ fffe,COLOROO,$ F0F,$ 0d0f,$ fffe,COLOROO, $ A0A
dc. w $ 0e0f,$ fffe,COLOROO,$ 808,$ 0f0f,$ fffe,COLOROO, $ 606
dc. w $ 100f,$ fffe,COLOROO,$ 404,$ 110f,$ fffe,COLOROO,$ 202
dc. w $ 120f,$ fffe,COLOROO,$ 000 CLEnd: dc.l -2 CLSize EQU '-NewCopper
Chars: dc.b "A", 0,"B", 1, "C",2,"D",3,"E",4,"F",5,"G”,6
dc. b "H",7, "I", 8, "J”, 9, "K", 10, "L", 11, "M", 12
dc. b “N", 13, ”0",14, "P",15,"Q",16,”R",17,”S",18 de. B “T",19,"ü”,20,"V",21,"W”,22,"X",23,"Y",24
dc. b “Z",25,"!",26,"?",27,":",28,";",29,”0",30
dc. b "1",31,"2",32,"3",33,"4",34,"5",35,"6",36
dc. b "7“,37,"8",38,"9",39,'"',40,"(",41,")",42
dc. b ",",43,"-",44,".”,45,"'",46,"*",47," ",48
dc. b 255,255 even
NBStars EQU 100
StarsXYZ: inchin "StarsXYZ.bin" dcb.w NBStars, -1000
GfxName de. B "graphies. 1 ibrary”, 0 even
Start move.l (ExecBase) .w,a6 move.l MemSize,d0 move.l $ 10002,dl CALL AllocMem move.l dO.PlaneAdr beq NoMem move.l dû,Screenl lea CLPlanes(pc),a0 moveq SDepth-l,dl MakeCL raave.w d0,6(a0) swap dO
move.w d0,2(a0) swap dO
addi.l BPLSize,d0 addq.l 8,a0 dbra dl, MakeCL move.l dO,Screen2 addi.l ScreenSize,dO move.l dO,ScrollAdr lea ScrTab(pc),a0 move.w SHeight-l,d0 moveq 0,dl MakeTabmove.w dl, (aO) + addi. W swidth, dl dbra dO,MakeTab lea CLScroll (pc ) ,a0 move.l ScrollAdr(pc),d0 moveq 2,dl MakeCL2 move.w d0,6(a0) swap dO
Message dc.b 4," vive L'ANT ! ",0
dc. b "DANS QUELQUES SECONDES CETTE INTRO S'AOTO-DETRUIRA APRES TROIS ANS D'EXISTENCE ET.r.F VIEILLE - ", 1 "J'ADORE LES CIELS ETOILES, PAS VOUS ? "
", 4
255
AMIGA NEWS-TECH NUMERO 21 AVRIL 1991
1 6;
suite page 29
move.w d0,2(a0) swap dO
addi.l ScrollBPL,dO addq.l 8,a0 dbra dl,MakeCL2 lea GfxName(pc),al moveq 0,d0 CALL OpenLibrary move.l dO.GfxBase beq.s NoGfx CALL Disable bsr.s Main
move.l (ExecBase).w,a6 CALL Enable Out move.l GfxBase(pc),al CALL CloseLibrary NcGfx move.l PlaneAdr(pc),al move.l ( ScreenSize*2 ) +ScrollSize,dO CALL FreeMem tfcMem moveq 0,d0 rts
Main: move.l GfxBase(pc),a6 CALL OwnBlitter move.b %10000111,CIAB_PRB lea Custcm,a6
move.w $ 0020,EMACON(a6) ; Ciao les sprites ! Bsr.s Vsync
move.l CLAdr(pc),COP2LCH(a6) move.w dO,COPOMP2(a6)
WaitlMB btst 6,CIAA_PRA ; IMB ? Beq.s MainRet bsr.s Vsync bsr.s Switch bsr BltClear bsr Stars
btst 10,POTGOR(a6) ; RMB ? Beq.s WaitlMB bsr Scroll bra.s WaitlMB
MainRet move.w $ 8020,EMACON(a6) ; Hello les sprites ! Move.l GfxBase(pc),a6 CALL DisomBlitter rts
Vsvnc: cnp.b $ 29,VHPOSR(a6) tne.s Vsync rts
Switch: lea Screenl(pc),a0 move.l (aO),dO move.l 4(a0),dl exg dO,dl move.l dO,(aO) move.l dl,4(a0) move.l CLAdr(pc),a0 lea CLPlanes-NewCopper(aO) ,a0 moveq SDepth-l,dO SwitchLmove.w dl,6(a0) swap dl
move.w dl,2(aO) swap dl
addi.1 BPLSize,dl addq.l 8,a0 dbra dO, SwitchL rts
Stars: lea StarsXYZ(pc),aO lea 200(a0),al lea 200(al),a3 lea 200(a3),a2 moveq NBStars-l,d7 StarsLoop: move.w (a0)+,d0 ; d0=x move.w (al)+,dl ; dl=y move.w (a2),d2 ; d2=z lsl.w 4,d0 lsl.w 2,dl lsl.w l,d2 ; Calcule les coordonnées écran de l'étoile beq.s SetColor ; si d2=0 évite la division ext.l dO lsl.l 8,d0 divs d2, dO
add.w 160,dO ; xe=160+((x*256) z)
ext.l
dl
lsl.l
8,dl
divs
32,dl
neg.w
dl
add.w
100,dl ; ye=100+((y*256) z)
; Décide
de la couleur de l'étoile en fonction de sa "distance"
SetColor
move.w
(a2),d2
cmp.w
-300,d2 ; > -300 => blanche
bit. S
Colorl
moveq
3,d3
bra.s
Stars1
Colorl:
cinp .w
-600,d2 ; -600 => gris foncé
bgt.s
Color2
moveq
l,d3
bra.s
Stars1
Color2:
moveq
2,d3 ; sinon gris clair
; Dessine le point
(d0,dl) en couleur d3
Stars1:
tst.w
dO ; Test de clipping
fcmi.s
NoPlot ; Si l'étoile "sort" de
tst.w
dl ; de l'écran, on remet sa
bmi .s
NoPlot ; coordonnée Z à -1000
cmpi.w
319,dO
bgt.s
NoPlot
cnpi.w
199,dl
bgt.s
NoPlot
Plotlt:
move.1
Screenl(pc),a4
add.w
dl. dl
move.w
ScrTab ( pc, dl. W), dl
lea
(a4,dl.w),a4
move.w
d0,dl
lsr.w
3,dl ; int(x 8)
not.w
dO
and.w
%lll,d0
moveq
l,d4 ; 2 plans max
PlotLoop
asr.w
l,d3
bcc.s
PlotOff
; Allume
le pixel du plan concerné
PlotOn:
bset
dO, (a4,dl.w) ; 7- (X MDD 8)
bra.s
PlotNext
; Eteint
le pixel du plan concerné (sinon le point pourrait
; prendre
une autre
couleur que celle voulue)
PlotOff
bclr
dO, (a4,dl.w) ; 7-(X M3D 8)
PlotNext
lea
BPLSize(a4),a4
dbra
d4,PlotLoop; Plan suivant, please
bra.s
Stars2
NoPlOt:
move.w
-1000,d2 ; z=-1000
move.w
VHPOSR(a6),d4
add.b
d4,d2
Stars2:
add.w
(a3)+,d2 ; Change sa "distance"
move.w
d2,(a2)+
dbra
d7, StarsLoop
rts
ScrTab:
dcb.w
Sheight,0
; *******
* *********
* ******************
Scroll:
tst.b
Stop
beq.s
Scrolll
subq.b
1,Stop
rts
Scrolll
move.b
Shift(pc),d0
addq.b
1,Passe
and.b
dO,Passe
beq.s
NewChar
Scroll2
move.l
ScrollAdr(pc),aO
lea
42*40-2(a0),a0
moveq
2,d0 ; Compteur Bitplanes
moveq
0,dl ; Modulos A & B
moveq
-l,d2 ; BLTAFWM & BLTALWM
moveq
0,d3
move.b
Vitesse(pc),d3
ror.w
4,d3
ori .w
$ 09f0,d3 ; BLTCCN0
swap
d3
addq.w
%10,d3 ; BLTCON1
move.w
(25*64)+21,d4 ; BLTSIZE
ScrollL
bsr
WaitBlit
move.l
aO,BLTAPTH(a6)
move.l
aO,BLTDPTH(a6)
move.l
dl,BLTAM0D(a6)
move.l
d2,BLTAFWM(a6)
move.l
d3,BLTCONO(a6)
move.w
d4,BLTSIZE(a6)
lea
ScrollBPL(aO),aO
dbra
dO, Scrolll,
rts
NewChar
move.l
Mess(pc),a0
move.b
(a0)+,d0
bpl.s
NewChar1
ne fenêtre Shell n'est ni plus ni moins qu'une fenêtre Intuition. Notre programme, lancé depuis cette fenêtre, doit tout d'abord en rechercher le pointeur. C'est très simple : la structure Process de notre programme contient un pointeur sur la console_task associée (le Shell). Il nous suffit d'envoyer à cette console_task un DosPacket de type ACTION_DISK_INFO avec en argl. Un pointeur sur une structure InfoData. En retour, on recevra le pointeur de la fenêtre utilisée par la console (pour en savoir plus sur les DosPacket. Vous pouvez vous reporter à l'exceeelllent article "Mettez un silencieux dans vos lecteurs de disquettes" d'Amiga News-Tech n' 16).
Cette fenêtre, comme quelques essais permettent de s'en convaincre, n'utilise aucun flag LDCMP et ne comporte donc pas de port utilisateur. Il nous faudra donc d'abord créer un port, puis l'attacher à la fenêtre, modifier les flags IDCMP puis installer le menu. Tout ceci ne mérite pas grandes explications car ce n'est que l'utilisation de routines système bien connues. Voila, le menu est installé et nous pouvons déjà utiliser les raccourcis clavier ainsi définis, afin d'accéder ultra-rapidement à vos outils préférés (moi c'est Devpac2 [Genam2-Monam2]).
Je vous propose aujourd'hui d'allier la convivialité du WorkBench avec la rigueur du Shell. Comment Tout simplement en ajoutant un menu Intuition aux fenêtres Shell (ou CLI, cela s'entend). Ceci nous permettra d'utiliser depuis le Shell tous les raccourcis clavier que l'on voudra, avec en plus une option spécial fainéants : le seul fait d'insérer une disquette dans un lecteur quelconque en affichera le catalogue.
CATALOGUE AUTOMATIQUE
Cela est rendu possible par le fait qu'un message Intuition est généré lorsqu'on insère une disquette. D'abord, il faut savoir que ce message sera envoyé à la fenêtre que celle-ci soit active ou pas. Ce sera donc à notre programme d'effectuer ce test en examinant ActiveWindow d'IntuitionBase.
Les routines qui déterminent dans quel drive la disquette a été insérée sont directement inspirées de VirusX de Steve Tibctt. Afin d'éviter le sac de noeuds entre les sorties de plusieurs programmes, le catalogue est affiché dans une fenêtre Dos spécialement ouverte à cette effet. L'option catalogue automatique peut être désactivée par le menu.
RENDRE LA MAIN PROPREMENT
Ce programme, écrit avec le Lattice 5.10, DOIT être linké avec cback.o, de façon à tourner en tâche de fond. Nous avons donc la situation suivante : deux programmes distincts utilisent la même conso!e_task. C'est pour cela que vous ne pourrez pas ajouter une option "endeli" dans le menu.
L'option "quitter" stoppe le programme, mais laisse le Shell actif qui redevient un Shell classique. Si vous faites directement un "endeli" depuis le Shell, la fenêtre ne sera toutefois pas fermée pour la même raison. D vous suffira alors d’actionner Amiga-Q (il serait bien sûr possible d'améliorer ceci, mais cela ralongerait considérablement le listing, donc je préfère vous laisser exercer votre sagacité).
Remarquez toutefois qu’il est impératif de supprimer tous les messages "pendants" au port de la fenêtre (fonction SafelyIDCMP) et d’effacer soi-même le port, sinon c'est le gourou assuré.
UTILISATION DU PROGRAMME
Il y a deux manières de lier le SuperShell à un Shell standard :
- par simple appel depuis le Shell :
- mais vous pouvez aussi le placer au début du fichier Shell-Startup (ou Cli-Startup). Ainsi, tout Shell ouvert sera automatiquement un SuperShell.
J'ai été très bref dans les explications, car le programme est lui assez long et je ne dispose pas de l’ANT pour moi tout seul. Si vous avez absolument besoin d'explications complémentaires, écrivez-moi au journal.
Avec SuperShell. Frédéric MAZUE améliore votre environnement.
Programme : SuperShell.c
Fonction: Accroche un menu à une fenêtre Shell (ou CLI) Utilisation: - Appel depuis Shell
- Installation dans le Shell-Startup ou dans le Cli-Startup Ccnpilateur: Lattice C 5.10
* Ccnpilation: le -cist -v -y
* Linkage: FROî LIB:cback.o+"SuperShel1.o"
TO "SuperShell"
LIB LIB:lc.lib LIB:amiga.lib
NODEBUG
SMALLCODE
SMALLDATA
DEFINE main= tinymain
Auteur: F MAZUE pour ANT le 18 12 90
ttinclude exec types.h> ttinclude exec nodes.h>
include exec lists.h> ttinclude exec ports.h>
include exec memory.h>
include intuiticai intuition.h> ttinclude intuition intuitionbase. H> include libraries dos.h> ttinclude libraries dosextens.h> ttinclude devices trackdisk.h> ttinclude string.h>
ttinclude proto exec.h> ttinclude proto intuition.h> ttinclude proto graphics.h> ttinclude proto dos.h>
DECLARATION POUR CBACR
extern BPTR _Backstdcut; char *_procname = "SuperShell"; LONG _BackGroundIO = 1;
LONG _stack = 4000;
LONG _priority = 20;
*
définition du menu qui sera ajouté a la fenêtre cli
struct TextAttr TOPAZ80 =

(STRPTR)"tcpaz.font",
TOPAZ_EIGHTY,
0,
0
};
struct IntuiText AutoText[] =

2,1,JAM2,2,1,NULL," List ",NULL}
struct Menultesn Autoltem [ ] =

* List *

NULL,0 0,0,0,
rrEMTEXT| ITEMENABLEDIHIGHCCMPICHECKITIMENOTOGGLE|CHECKED, 0,
ORDINAIRE AVEC "Su
* ***********
* ************
* ******************
(AFTR)&AutoText[0],NULL,NULL,NULL,MENUNULL
}
;
struct IntuiText ToolText[]=

2,1, JAM2,2,1,NULL,"Genam2",NULL},
2,1, uAM2,2,1, NULL, "Monam2 n, NULL},
2,1, JAM2,2,1, NULL,"DPaint",NULL},
2,1,JAM2,2,1,NULL,"Quitter”,NULL}
};
struct MenuItem ToolItem[]=

* Genam2 »
&ToolItem[l], 0,0,0,0,
ITEHTEXT | CCMMSEQ | I1EMENABLEDIHK3KXMP, 0,
(APTR)S:ToolText [0], NULL, 'G',NULL,MENUNULL
},
* Monam2 *
&ToolItem[2],0,0,0,0,
ITEHTEXTICCMMSEQIITEMENABLEDIHIGHCCMP, 0,
(APTR)SToolText[1],NULL, 'M', NULL, MENUNULL
,
* Dpaint *
&ToolItem[3],0,10,0,0,
m-Mi'KXT ICCMMSEQ | ITEMENABLED | HK5ÎCQMP, 0 ,
(APTR)SrToolText [2],NULL, 'P',NULL,MENUNULL
},
* Quitter *
NULL, 0,10,0,0,
ITEKTEXTICCKMSEQ | ITEMENABLEDIHIGHCCMP, 0,
(APTR)ScTOOlText [3] ,NOLL, 'Q',NULL,MENUNULL
}
};
struct Menu Menus[]=

(&Menus[1],0,0,0,0,MENUENABLED,"Tools",&ToolIt€an[0] },
NULL,80,0,0,0,MENUENABLED,"AutO",&AutOltem[0]}
};
struct Menu *FirstMenu = Smenus[0];
struct IntuiText WinText[)=

3,0,JAM2,54,28,&TOPAZ80,"üow to do a Menu",NULL},
3,0,JAM2,70,38,&TOPAZ80,“(with Style)", &WinText[0]}
};
struct NevWindow NewWindow =

202,66,234,66,2,1,MENUPICKICLOSEWXNDOW,
WINDCWI»AG I WINDCWDEP'IH IWINDCW3LOSEI ACTIVAIS | NOCAREREFRESH,
NULL,NULL,"Menus”,NULL,NULL,0,0,-1,-l.WBENCHSCREEN };
* fonctions de gestion du menu *
BOOL AdjustMenus(struct Menu *,struct textAttr *);
VOID Adjustltems(struct RastPort *, struct Menultem *, struct TextAttr
* , OSHORT, OSHORT, USHORT, USHC«T);
VOID AdjustText(struct IntuiText *text, struct TextAttr *attr);
USHORT MaxLength(struct RastPort *, struct Menultem *, USHORT);
struct IntuiMessage "message;
* Pour ces deux fonctions, se reporter aux *
* rmk Libraries and Devices pages 171 *
VOID StripIntuiMessages ( struct MsgPort "np, struct Wiixiow *win) ;
VOID IDCMPSafely ( struct Windcw *win) ; int handl elDCMP ( struct Windcw *win);
* pour recherche du pointeur de fenêtre du cli courant *
VOID mainO
int signal; int signalmask; int OK=0;
if(!(IntuitionBase=(struct IntuitionBase *)
CpenLibrary("intuition.library",0L) ) ) CleanExitO;
if(!(GfxBase=(struct GfxBase *)
Cï»nLibrary("graphies.library",0L) ) ) CleanExitO;
CliWindow = (struct Window *)GetWindow(); if(!CliWindow) CleanRxit();
diskport = (struct MsgPort OcreatePort (NULL,NULL); if(Idiskport) CleanExitO;
diskreq = (struct IOExtTD *)
CreateExtIO((struct MsgPort *)diskport,sizeof(struct IOExtTD)); if(îdiskreq) CleanExitO;
WinPort = (struct MsgPort *)CreatePort(NULL,NULL);
AdjustMenus (FirstMenu, CliWindow->WScreen->Font) ; SetMenuStrip (CliWindow, FirstMenu) ;
signalmask = IL CliWindow->UserPort->np_SigBit;
do

signal = Wait(signalmask); if (signal & signalmask)
OK = handlelDCMP (CliWindow) ;
}while(!0K);
SetWindcwTitles(CliWindow, "AmigaShell", (char ")-l); Ref reshWindcwFrame (CliWindow) ;
IDCMPSaf ely (CliWindow) ,-
define BOTC(hptr) ( (lcaig) (pbtr)«2) * cœrversicm BCPL -> C * Sdefine CTOB(cptr) ( (lcog) (cptr)»2) * ccxrversion C -> BCPL *
struct Window *GetWindow(); struct Window "CliWindow; struct MsgPort "WinPort;
struct IntuitionBase *IntuitionBase= NULL; struct GfxBase "GfxBase = NULL;
CliWindcw- >UserPort = WinPort;
MbdifyIDCMP (CliWimisw, MENUPICK IDISKINSERTED) ;
SetWindcwTitles(CliWindow,"SuperShell par F Mazué",(char *)-l); RefreshWindcwFrame (CliWindow) ;
* On attache le port nouvellement créé à la fenêtre gt.t
* Puis on modifie les flags IDCMP de la fenêtre
* Maintenant, on initialise le menu et on l'attache à * la f entre ct.t
pour gestion des drives
PROGRAtME PRINCIPAL
* ****************
InitDrive();
LONG ChangeCount[4]; struct MsgPort "diskport; struct IOExtTD "diskreq;
VOID InitDrive (} ; int DriveNumO ;
VOID CleanExitO;
ClearMenuStrip(CliWindow) ;
CleanExit();
struct Window *GetWindcw()

struct Process *proc; struct StandardPacket *packet; struct infoData «infodata; long resuit; struct window «win;
proc=(struct Process »)FindTask(NOLL); if(!proc->pr_ConsoleTask) retum (NüLL) ;
packet = (struct StandardPacket *)
AllocMem( sizeof (struct StandardPacket) ,MEMF_CLEARIMEMF_POBLIC) ; infodata =(struct InfoData *)
AllocMemfsizeof(struct infoData),MEMF CLEARIMEMF_PUBLIC);
packet->sp_Msg.mn_Node.ln_Name=(char »)&(packet->sp_Pkt); packet->sp_Pkt.dp_Link=&packet->sp_Msg; packe t->sp_Pkt.dp_ Port =&proc->pr_MsgPort; packet->sp_Pkt.dp_Type=ACTION_DISK_INFO; packet->sp_Pkt.dp_Argl =CTOB(infodata);
PutMsg((struct MsgPort *)proc->prConsoleTask,(struct Message *)packet); WaitPort(&proc->pr_MsgPort);
GetMsg(Sproc->pr_MsgPort);
resuit = packet->sp_Pkt,dp_Resl;
win =(struct window *)infodata->id_VolumeNode;
FreeMem(packet, sizeof(struct StandardPacket));
FreeMem(infodata,sizeof(struct InfoData)); if ( ! Resuit ) retum (NÜLL) ; retum(win) ;
}
BOOL AdjustMenus(struct Menu *firstmenu, struct TextAttr *attr)

struct RastPort textrp = 0}; struct Menu «menu; struct TextFont «fcnt;
DSHORT start,width,height,space;
BOOL retval = FALSE;
if((font = (struct TextFont *)CpenFcnt(attr)))

SetFont(&textrp,font); width = font->tf_XSize;
height = (fcait->tf_YSize 8) ? 8 :font->tf_YSize; height+*;
start = 2;
menu = firstmenu; while(menu)

menu->LeftBdge = start; menu->Width = space =
TextLength ( stextrp, menu - >MenuName,
(LQH3)strlen(roenu->MenuNaine) ) + width;
AdjustItems(&textrp,inenu->FirstItem,attr,width,height, 0,0) ;
menu = menu->NextMenu;
start += (space +(width * 2));
)
CloseFont(font); retval = TRUE;
)
retum ( retval ) ;
)
VOID AdjustItems(struct RastPort *txtrp, struct Menultem *fi, struct TextAttr *atr, OSHORT wdth, DSHORT hght,
ÜSHORT lvl» ÜSHORT edge)

struct Menultem «item = fi; register ÜSHORT num;
DSHORT strip_width, subedge;
if (fi==NDLL) retum;
strip_width = MaxLength(txtrp, item, wdth) ;
num = 0;
v*ile(item)

item->TopEdge = (num * hght) - lvl; item->LeftEdge = edge; item->width = strip_width; item->Height = hght; sub_edge = strip_width - wdth;
AdjustText((struct IntuiText *)item->ItemFill,atr);
AdjustItems(txtrp,item->SubItem,atr,wdth,hght,l,suh_edge);
item = item->NextItem;
num++;
}
DSHORT MaxLength ( struct RastPort * txtrp, struct Menultem *fi, DSHCSW width)
DSHORT maxval = 0,textien; struct Menultem *item = fi; struct IntuiText *itext;
while(item)

if item->Flags & CXWMSEQ)

width += (width + CCMMWIDTK); break;
}
item = item- >NextItem;
item = fi; vdiile(item)

itext = (struct IntuiText *)item->ItemFill; textlen = itext->LeftEdge +
TextLength(txtrp,itext->IText,
(IXX*3)strlen(itext->IText) ) + width;
maxval = ( textlen maxval ) ?maxval : textlen; item = item->NextItem;
retum (maxval ) ;
VOID AdjustText(struct IntuiText *text, struct TextAttr *attr)

struct IntuiText *nt; nt = text; while(nt)

nt-> ItextFont=attr; nt = nt->NextText;
}
)
* Cette fonction initialise le tableau ChangeCount en: *
* - examinant si les drives sont connectés (non = -1) *
* - si cui, en examinant le status actuel pour remplir *
* le tableau en conséquence *
.....
VOID initDrive()

LONG x;
BYTE error = 0;
for (x = 0; x 4; x++) * go thru ail 4 possible drives *

error = QpenDevice("trackdisk.device", (LCaJG)x,
(struct IORequest *)diskreq,0L); if (error > 0)

ChangeCount[x] = -1;
)
else

diskreq->iotd_Req.io_Ccmnand = TDCHANGENUM;
DoI0((struct IORequest *)diskreq);
ChangeCount[x] = diskreq->iotd_Req.io_Actual;
CloseDevicef(struct IORequest *Idiskreq);
* Cette fonction renvoie dans un entier le numéro
* du drive dans lequel une disquette vient d'être insérée
int DriveNumO
int RetVal = -1;
LCKG x;
BYTE error = 0;
for (x = 0; x 4; x++)

if (ChangeCount[x] == -1) continue;
* pas de lecteur *
error = OpenDevice("trackdisk.device", (LONG)x, (struct IORequest *)diskreq,0L);
if (error > 0) continue;
* quelques chose a raté *
di skreq- > iotd_Req ¦ io_Cctnmand = TD_CHANGESTATE;
DoIO((struct IORequest *)diskreq); if (diskreq->iotd_Req.io_Actual != 0)

CloseDevice((struct IORequest *)diskreq); continue;
di skreq->iotd_Req.io_Ccnmand = TD_CHAN3ENÜM;
DoI0((struct IORequest *)diskreq); if (diskreq->iotd_Req.io_Actual != ChangeCount[x])

RetVal = (int)x;
ChangeCount[x] = diskreq-> iotd_Req.io_Actual;
CloseDevice((struct IORequest *)diskreq); break;
CloseDevice((struct IORequest *)diskreq);
}
retum (RetVal) ;
VOID IDCMPSafely( struct Window *win)

ForbidO;
StripIntuiMessages(win->OserPort, win ); win->OserPort = NULL;
ModifyIDCMP(win,NOLL);
PermitO;
VOID StripIntuiMessages (struct MsgPort *np, struct Window *win)

struct IntuiMessage *msg, *succ;
msg = (struct IntuiMessage *)np->mp_MsgList.lh_Head;
while(succ = (struct IntuiMessage *)msg->
ExecMessace. Mn_Node. Ln_Succ )

if(msg->IDCMPWindow == win)

Remove((struct Node *)msg);
ReplyMsg((struct Message *)msg);
}
msg = suce;
)
int handlelDCMP ( struct Window *win)

int drive; int done =0;
USHORT code,flag;
struct IntuiMessage *message = NOLL;
LONG class, itemNum, menuNum, file; char cmd[10]; char titre[22];
strcpy(cmd,"list dfx:");
strepy(titre,"CON:l ll 520 200 dfx:");
while(message = (struct IntuiMessage *)GetMsg(win->OserPort))

class = message->Class; code = me s sage->Code;
ReplyMsg((struct Message *)message);
switch(class)

case DISKINSERTED:
drive = DriveNum();
flag =( (struct Menultem *) ItemMdress
(FirstMenu, (SHlFlMBîrod) ISHIFTITEM(O))))->Flags;
if (CliWindow == Intui t ionBase - >Ac t i veWindow )

if(flag & CHECKED) * si auto cd sélectionné *

end[7] = (char) (drive+ 0X30); titre[19] = (char)(drive*0X30); file = Cpen(titre,MDDE_OLDFILE)
Exécuté(cmd,NULL,file);
Delay(150);
Close(file);
}
}
break;
case MENÜPICK:
itenWum = ITEMNUM(code); menuNum = MENONOM(code); switch(menuNum)

case 0:
switch(itemNum)

case 0:
Exécuté("genam2*,NOLL,_Backstdout); break;
case 1:
Exécuté ( "inonam2 -, NOLL, _Backstdout ) ; break;
case 2:
Exécuté(-DeluxePaintlII:DPaint",NOLL,_Backstdout); break;
case 3: done = 1; break;
default: break;
default: break;
}
default: break;
}
}
retum (done) ;
VOID CleanExit()

if (WinPort) DeletePortt(struct MsgPort *)WinPort); if(diskreq) DeleteBxtIO((struct IORequest *)diskreq); if(diskport) DeletePort((struct MsgPort *)diskport); if(GfxBase) CloseLibrary((struct Library *)GfxBase); if(IntuitionBase) CloseLibrary((struct Library *)IntuitionBase);
if (_Backstdout)

Close (_Backstdout); *
_Backstdout=0;
exit(0);
* itoa *
on libère le CLI *
UN PEU D’INTUITION
Le mois dernier¦ nous avons étudié comment ouvrir un écran à F aide de la bibliothèque graphies.library. Aujourd’hui, nous allons effectuer le même travail avec intuition.library.
Dans le même temps, nous aborderons la notion de fenêtre et (dans l'exemple) de requester. Avec en fin d'article un programme récapitulant tous les aspects théoriques de cette" étude. Commençons sans plus attendre par un tour d'horizon des fonctionnalités de la bibliothèque intuition.library.
s
struct TextAttr *Font;
UBYTE *DefaultTitle; struct Gadget *Gadgets; struct BitMap *CustomBitMap; ) ;
GENERALITES SUR INTUITION
Intuition est un environnement de programmation permettant de créer, de manière simple, des programmes possédant une interface conviviale à base de menus déroulants, multifenêtrage et autres gadgets. Elle permet également, à partir d'outils standards, de développer une application personnalisée, et ce avec un minimum de contraintes (ces contraintes étant nécessaires pour la cohérence de l'ensemble). L'avantage d'un tel environnement de programmation standardisé apparait nettement : outre un temps de développement réduit, l'utilisateur peut d'appréhender un nouveau produit avec une impression réconfortante de "déjà vu".
L'ensemble des objets et fonctionnalités d'intuition peut être défini comme suit :
- les écrans : ils servent de support aux fenêtres d’une application ;
- les fenêtres : elle permettent à l'application de communiquer avec l'utilisateur, aussi bien en entrée qu'en sortie d’informations :
- les menus, requesters et alertes : ce sont les différents mécanismes d'interaction entre l'utilisateur et l’application. Les menus gèrent l'envoi de commandes de la part de l’utilisateur, les requesters (requêtes), l’entrée d'informations et les alertes, les communications d’urgence (situations critiques).
Les méthodes utilisées pour la gestion des entrées sorties sont le port IDCMP de la fenêtre (Intuition Direct Communication Message Ports), le console.device ou les fonctions de la graphics.library (Text(). Animation, etc.).
Avant tout travail avec Intuition, il est nécessaire d’inclure les fichiers "include" se rapportant à Intuition, de déclarer un pointeur de type (struct IntuitionBase *) dénommé IntuitionBase et d'y stocker l’adresse de base de la bibliothèque Intuition renvoyée par la fonction OpenLibraryO (cf. Exemple).
Toute application repose sur un écran, que ce soit celui du Workbench ou celui que vous avez créé. Donc à tout seigneur tout honneur, nous allons commencer par voir de quelle manière ouvrir un écran.
OUVERTURE D’UN ECRAN
L'ouverture d'un écran sous Intuition est très simple, beaucoup plus simple qu’avec la graphics.library. En résumé, il suffit :
- de renseigner une structure NewScreen définissant l'écran à créer ;
- de faire un appel à OpenScreenO qui crée physiquement l’écran à partir de la structure NewScreen :
- de récupérer le pointeur sur la structure Screen renvoyé par OpenScreenO, qui permettra par la suite de manipuler l’écran (cette fonction retourne NULL si l’écran n’a pu être ouvert).
La structure NewScreen est définie en C dans intuition screens.h : struct NewScreen
SHORT LeftEdge, TopEdge, Width, Height, Depth;
UBYTE DetailPen, BlockPen;
USHORT ViewModes ;
USHORT Type;
LeftEdge : Indique la position initiale en X de l'écran. Il n’est pas utilisé actuellement en KickStart 1.2 1.3, mais doit être initialisé à 0 pour des questions de compatibilité ascendante. Le KickStart 2.0 de l'Amiga 3000, lui, l’utilise.
TopEdge : Indique la position initiale en Y.
Width : Largeur de l'écran, soit 320 pixels en basse résolution ou 640 en haute résolution.
Height : Hauteur de l'écran, soit 256 lignes en mode non entrelacé (200 en NTSC) ou 512 en mode entrelacé (400 en NTSC).
Depth : Nombre de bitplanes associés à l’écran (de 1 à 6). Ce qui influe directement sur le nombre de couleurs affichables N. tel que N = 2ADepth.
DetailPen : Numéro du registre de couleur utilisé pour le titre de l'écran.
BlockPen : Numéro du registre de couleur utilisé pour la barre de titre.
ViewModes : Mode de visualisation de l’écran, lié à la hauteur et à la profondeur. Si la largeur est de 640. On indiquera HIRES (la profondeur maxi de l’écran étant alors de 4). Si la hauteur est de 512. On devra choisir INTERLACE. Tout cela suppose bien sûr que l'on désire que l'écran entier soit visualisable sur le moniteur (pas de scrolling). Les modes SPRITES. DUALPF. EXTRA_HALFBRITE et HAM sont également utilisables.
Type : Indique... le type de l'écran. L’écran du WorkBench est de type WBENCHSCREEN, l'écran d'une application est de type CUSTOMSCREEN. On peut également indiquer SCREENQUIET, qui empêche le dessin des gadgets dans la barre de titre (même s'ils sont toujours actifs) et SCREENBEHIND. Qui ouvre l'écran derrière tous les autres (donc de manière invisible).
Font : Pointeur sur une structure TextAttr, qui définit la police de caractères utilisée par l’écran. Si ce pointeur est NULL, c’est la police TOPAZ 8 qui est choisie par défaut.
DefaultTitle : Titre de l'écran, représenté simplement par un pointeur sur une chaîne de caractères terminée par un caractère nul. On indique NULL si l’on ne veut pas de titre.
Gadget : Adresse du premier des gadgets liés à l’écran. Pour l’instant, il est impossible d’avoir des gadgets d’écran, il faut donc mettre ce pointeur à NULL pour garder une compatibilité ascendante.
CustomBitMap : Pointeur sur une structure BitMap initialisée par vos soins, par exemple pour créer une bitmap plus grande que l’écran et la faire scroller en tous sens. NULL sinon.
Voilà pour la structure NewScreen. Une fois cette structure correctement renseignée, il ne reste plus qu’à appeler OpenScreenO.
Struct Screen * écran;
écran = (struct Screen *)OpenScreen(&nouvecran);
OpenScreenO alloue et remplit la structure Screen et crée physiquement l'écran, mais qu'a-t-il bien pu mettre dans cette structure Screen....
La plupart des informations contenues dans la structure Screen servent selon l’application que vous développez. Dans ce premier article, nous allons nous contenter de les décrire, mais je vous rassure il nous serviront dans les prochains numéros.
QUE DIANTRE !
TopEdge : Position du haut de l'écran suivant Y. Cette valeur va par exemple augmenter si l'utilisateur descend l'écran à la souris.
MouseX. MouseY : Position du pointeur de souris en X et Y relativement au coin haut et gauche de l'écran.
ViewPort. Rastport. BitMap. Layerlnfo : Instances (et PAS des pointeurs sur) des structures du même nom, décrivant les caractéristiques de l'écran comme nous avons pu les étudier le mois dernier.
BarLaycr : Pointeur sur la structure layer liée à la barre de titre.
Le dernier point que nous allons voir ce mois-ci concernant les écrans, est la fonction qui nous permet de les refermer. 11 s'agit de CloseScreenO à laquelle on passe le pointeur sur la structure Screen.
CloseScreen(écran);
Cette fonction se charge de refermer l'écran et de libérer toutes les ressources qui lui sont associées.
OUVERTURE D’UNE FENETRE
Nous allons maintenant étudier comment ouvrir une fenêtre en C. Vous savez tous ce qu'est une fenêtre, je ne m'étendrai donc pas sur sa description mais simplement sur la manière de l'ouvrir. De la même façon qu'il faut renseigner une structure NewScreen pour ouvrir un écran, nous allons commencer par regarder la description de la structure NewWindow qui va servir à Intuition pour créer la fenêtre. Elle est définie dans intuition intuition.h :
struct NewWindow
SHORT Le f tEdge,TopEdge;
SHORT Width, Height;
UBYTE DetailPen, BlockPen;
USHORT IDCMPFlags;
ULONG Flags;
struct Gadget *FirstGadget; struct Image *CheckMark;
UBYTE *Title; struct Screen *Screen; struct BitMap *BitMap;
SHORT MinWidth,MinHeight;
SHORT MaxWidth, MaxHeight;
USHORT Type;
;
Le ft Edge. TopEdge. Width, Height
Ces quatre valeurs décrivent la position initiale de la fenêtre à l'écran (au moment de l'ouverture). LeftEdge et TopEdge indiquent la position du coin haut-gauche de la fenêtre par rapport au coin haut-gauche de l’écran qui la contient. Width et Height représentent sa largeur et sa hauteur.
DetailPen. BlockPen : DetailPen contient le numéro du registre de couleur servant au tracé des détails associés à la fenêtre (texte dans la barre de titre, gadgets...). Une valeur de -1 dans ce champs indique à Intuition de prendre le même registre que celui de l'écran.
BlockPen correspond quant à lui à la couleur utilisée pour le remplissage des blocs (barre de titre ou contour de la fenêtre). Une valeur de -1 correspond au même registre que pour l'écran.
Flags : Il est possible d'associer un certain nombre de valeurs à ce champ : WINDOWSIZING demande à Intuition de créer un gadget autorisant le dimensionnement de la fenêtre. En indiquant en plus SIZEBRIGHT, le gadget est placé dans la bordure droite (par défaut) alors qu'avec SIZEBBOTTOM. Il est placé dans la bordure du bas (on peut aussi mettre les deux). WTNDOWDEPTH indique à Intuition de créer un gadget permettant à l'utilisateur de faire passer la fenêtre devant ou derrière d'autres fenêtres existantes. WINDOWCLOSE crée le gadget de fermeture de fenêtre. WINDOWDRAG transforme la barre de titre en un gadget permettant le déplacement de la fenêtre sur l'écran. SMARTREFRESH indique à Intuition qu'il doit vous avertir lorsque l'utilisateur utilise le gadget de dimensionnement (et seulement en ce cas). Ceci vous permet de modifier votre affichage par exemple. Par contre, dans le cas de superposition de fenêtres ou de déplacement, c'est Intuition qui gère le rafraîchissement de la fenêtre.
IDCMPFlags : Si un seul de ces flags est positionné. Intuition préviendra l'application des interactions effectuées par l'utilisateur. Nous reviendrons plus en détails sur ce sujet dans un prochain article.
FirstGadget : Pointe sur le premier élément d'une liste de gadgets qui seront liés à la fenêtre (en dehors des gadgets système). NULL si aucun gagdget n'est à ajouter.
CheckMark : Pointe sur une Image qui remplacera le CheckMark par défaut des menus, par l'image de votre choix.
Tilde : Pointe sur une chaîne de caractères qui représente le titre de la fenêtre.
Type : Indique le type de l'écran qui contient la fenêtre, soit WBENCHSCREEN. Soit CUSTOMSCREEN.
Screen : Pointeur sur l’écran contenant la fenêtre, tel qu'il a été renvoyé par OpenScreenO. NULL si la fenêtre est sans l'écran du WorkBench.
BitMap : Pointeur sur une BitMap associée à la fenêtre. Dans le cas où ce champ est NULL, Intuition se charge automatiquement de l'allocation de la BitMap.
MinWidth. MinHeight, MaxWidth. MaxHeight : Ces quatre valeurs correspondent respectivement aux largeur et hauteur minimum et maximum autorisées lors du dimensionnement de la fenêtre.
Une fois cette structure renseignée, il suffit de déclarer un pointeur sur une structure Window (que nous ne détaillerons que dans un prochain article, faute de place) et de faire appel à OpenWindow() pour ouvrir la fenêtre.
Struct Window *fenetre:
fenetre = OpenWindow(&Nouvfenetre):
Pour refermer une fenêtre il suffit d'appeler la fonction CloseWindowO
CloseWindow(fenetre);
CONCLUSION
Je vous conseille maintenant d'étudier le petit programme d’exemple associé à cet article. Pour le requester et la gestion des messages port, ne paniquez pas. Il seront expliqués en détails dans un prochain numéro (remarquez, ça n’est pas très difficile et vous devriez comprendre sans problème). A bientôt donc et d'ici là... ayez de l’Intuition.
* : *
* Ouverture d'un écran,d'une fenêtre et d'un requester *
* Auteur Pascal AMIABLE (c) 1991 . *
. *
* *
* Quelques includes utiles ......*
* *
include stdio.h>
include intuition intuiticai.h>
include intuition intuitionbase.h>
include exec types.h> v
* Les defines maintenant *
*------ V
def me H7IUTTÏ0N_REV OL *Version de la bibliothèque (la dernière) *
'* --
* Définition des variables globales *
'* *
struct Screen *écran = NULL;
struct Screen *OpenScreen();
struct Window *OpenWindow();
struct Windcw 'fenetre = NULL;
struct IntuitionBase 'IntuitionBase = NULL;
. -
Programme principal, il gere les interactions utilisateur *
-
void main() t
struct IntuiMessage *message; lcng GetMsgO;
ULONG classemessage;
void init(),ouvrecran(),ouvrefenetre(),ouvrerequete(),referme();
init(); cuvrecranO; ouvrefenetre(); cuvrerequete();
while(l) * boucle infinie *
message = (struct IntuiMessage *)GetMsg(fenetre->UserPort); if (message) * y-a-t'il un message ? *
classemessage = message->Class; * en récupéré la classe * ReplyMsg(message); * libéré le message * if (classemessage == CLOSEWINDOW) * fermeture ? *
refermeO; * on ferme tout * exit(TRUE); * et on sort tranquillement *
)
}
}
On ouvre la bibliothèque "intuition.library"
void ouvrefenetre()

struct NevWindcw nouvfenetre;
nouvfenetre.LeftSdge =0; ncuvfenetre.TcpEdge =0; nouvfenetre.Width = 320; ncuvfenetre.Height = 150; ncuvfenetre.DetailPen =0; nouvfenetre.BlockPen = 1;
ncuvf enetre. Flags = WINDCVCLOSEISMARTREFRESHIWINDOWSIZINGI WINECWDBAGIWINDOWDEPTO; nouvfenetre. IXCMPFlags = CLOSEWINDOW; nouvfenetre.FirstGadget = NULL; nouvfenetre.CheckMark = NULL; nouvfenetre.Title = "fenetre et san requester"; ncuvfenetre.Screen = écran; ncuvf enetre. BitMap = NULL; ncuvf enetre. MinWidth = 50; ncuvfenetre.MinHeight =50; nouvfenetre.MaxWidth = 640; nouvfenetre.MaxHeight = 200; nouvfenetre.Type = CUSTCMSCREEN;
fenetre = CfcenWindow(&nouvfenetre); if (fenetre == NULL)
printf("la fenetre ne veut pas s'ouvrir"); if(écran) CloseScreen(écran);
if(IntuitionBase) CloseLibrary(IntuitionBase); exit(FALSE);
}
Cette fonction referme l'écran et la fenetre
void refermeO
if(fenetre) CloseWindow(fenetre);
if(écran) CloseScreen(écran);
if(IntuitionBase) CloseLibrary(IntuitionBase);
)
* ----------------------------------------------
f*
*
Cette fonction ouvre un Requester de type VRAI FAUX
void initQ
struct Library *OpenLibrary(),-
IntuiticnBase = (struct IntuitionBase*) CpenLibrary("intuition.library'MNroiTICN REV) ; if (!IntuitionBase)
printf("Mais où est donc passée intuition ?"); exit(FALSE);
}
)
Fonction pennttant l'ouverture d'un écran intuition
void ouvrecran()

struct NewScreen nouvecran;
ncuvecran.LeftEdge = 0; nouvecran.TopEdge = 0; nouvecran.Width = 640; ncuvecran.Height = 256; nouvecran.Depth = 3; nouvecran.DetailPen = 0; nouvecran.BlockPen = 1; nouvecran.ViewModes = HIRES; nouvecran.Type = CUSTCMSCREEN; nouvecran.Font = NULL; nouvecran.DefaultTitle = "Un écran"; nouvecran.Gadgets = NULL; ncuvecran.CustanBitMap = NULL;
écran = OpenScreen(&nouvecran); if (écran == NULL)
printf("l'écran ne veut pas apparaitre "); if(IntuitionBase) CloseLibrary(IntuitionBase); exit(FALSE);
void cuvrerequete()

int val;
struct IntuiText blabla, positiftexte, négatiftexte;
blabla.FrontPen =1;
blabla.BackPen =0;
blabla.DrawMode = 1;
blabla.LeftEdge = 25;
blabla.TopEdge =10;
blabla.ITextFont = NULL;
blabla.IText = "cannent ca va ?";
blabla.NextText = NULL;
positiftexte.FrontPen = 1; positiftexte.BackPen =0; positiftexte.DrawMode = 1; positiftexte.LeftEdge =5; positiftexte.TopEdge = 5; positiftexte.ITextFont = NULL; positiftexte.IText = "Bien"; positiftexte.NextText = NULL;
négatiftexte.FrontPen = 0; négatiftexte.BackPen =1; négatiftexte.DrawMode = 1; négatiftexte.LeftEdge = 5; négatiftexte. TopEdge = 5; négatiftexte.ITextFont = NULL; négatiftexte.IText = "Mal"; négatiftexte.NextText = NULL;
val = AutoRequest(fenetre, fcblabla, &positiftexte, Snegatiftexte, NULL, NULL, 200L, 60L);
if(val == TRUE) printf("tant mieux"); else
printf("tant pis ");
}
Ouverture d'un fenetre sous intuition
:•
Après avoir vu comment le console.device pouvait servir à Ventrée et à la sortie de caractères dans une fenêtre Intuition, il nous reste à voir comment il peut permettre, simplement et sans fatigue, de tout bonnement recevoir des caractères en entrée et les afficher à Vaide de la graphies, library.
TE ET FIN
n peut d’emblée se demander quel peut bien être l’avantage de sortir nous-même les caractères reçus, alors qu’une tâche bienveillante peut s’en occuper pour nous. D’autant plus que la gestion du curseur est automatique, de même que le clipping (ou devrais-je dire "wrapping" ?), le style et toutes ces sortes de choses.
Oui, mais... Avez-vous déjà essayé de positionner le curseur à une position déterminée dans la fenêtre ? 11 faut envoyer une suite de codes ANSI par l’intermédiaire de DolO(), ce qui utilise autant de mémoire. Idem pour passer en gras, italique ou souligné. Quant à changer de fonte ou simplement de taille des caractères, n’en parlons même pas. La méthode que nous allons voir maintenant est beaucoup plus simple à mettre en oeuvre, même si elle peut sembler plus longue. En tous cas, un de ses gros avantages est de permettre de se passer d’un MessagePort supplémentaire, toujours ennuyeux à gérer avec ses signaux particuliers. Mais lisez plutôt.
PETIT DETOUR PAR LA GRAPHICS.LIBRARY
Pour résumer la méthode, je dirais simplement qu’elle consiste à ouvrir une fenêtre Intuition de manière tout-à-fait normale, en spécifiant RAWKEY comme flag IDCMP. Il est évidemment possible d'en utiliser d’autres, comme MENUPICK ou INTUITICKS - voyez à ce sujet les RKM ou l’article de Herr Doktor Von GlutenStimmellmDorf dans ce même numéro pour la version française. Il faut simplement faire attention à bien utiliser le flag RAWKEY et non VANILLAKEY, qui, s’il traduit bien les codes clavier en caractères ASCII, occulte complètement au passage les touches spéciales (touches de fonction, curseur et help).
Par la suite, à chaque message de type RAWKEY reçu, on appelle la fonction RawKeyConvert() du console.device, qui se charge de la traduction désirée, en accord avec le KeyMap spécifié. Ce qui signifie que si vous désirez que votre programme parle le suédois, le javanais ou l'espéranto, rien n’est plus facile.
Tertio, les caractères sont affichés à l’aide de la graphics.library, via la fonction Text(). Dans le programme d'exemple qui illustre cet article, le curseur est dessiné par nos soins et par la fonction RectFill(). Cela suppose bien entendu que l’on gère soi-même sa position, mais c’est enfantin. De plus, cela permet à ceux qui aiment bien se faire remarquer, d’en modifier la taille ou carrément l’apparence. Ce n’est qu’une question d’imagination - et de goût.
RAWKEYCONVERT()
En citant tout-à-l'heure RawKeyConvertO, j’ai parlé de fonction, et non de commande. Qu’est-ce à dire ? Hé bien tout simplement qu'il s’agit d’une fonction et non d’une commande. Si. C'est là une particularité que le console.device partage avec le serial.device et le trackdisk.device : offrir des fonctions, tout comme une bibliothèque standard, en plus des commandes (CMD_WRITE et consoeurs). Il est d’ailleurs à regretter que cette fonction ne fasse pas partie de l’intuition.library’. qui d’ailleurs l’utilise à outrance, mais bon... Celà nous oblige tout de même à utiliser une structure IOStdReq, à ouvrir le device, à récupérer un pointeur sur son adresse de base (j’en profiter pour rappeler au passage qu’un device a la même structure de base qu’une bibliothèque "classique"). Enfin, celà ne prend que quelques lignes de code et peu de mémoire.
L’ouverture du device se fait maintenant de manière un peu différence à celle vue le mois dernier : en mettant le numéro d'unité à -1 lors de l’appel à OpenDeviceQ, on n'a pas besoin de se créer de MessagePort, et une seule structure IOStdReq suffit. Le pointeur sur l’adresse de base du device est ensuite récupérée dans cette structure, de la manière suivante :
struct IOStdReq ioreq;
if (!OpenDevice("console.device", -1, fcioreq, 0))
ConsoleDevice = (struct ConsoleDevice
* )ioreq.io_Device;
*
... suite du programe ...
*
CloseDevice(&ioreq) ;
}?
Ce qui donne en assembleur :
Ouvre_Console:
lea conname(pc),aO lea ioreq(pc),al moveq -l,d0 moveq 0,dl CALLEXEC OpenDevice tst.b dO
bne Erreur_Console movea.1 dû,aO move.1 IO_DEVICE(aO),_ ; *** Suite du programme
ConsoleDevice
lea ioreq(pc),al CALLEXEC CloseDevice Erreur_Console:
; *** Fin du programme
Comme vous le voyez, c’est loin d'être compliqué. Notez au passage que le nom de variable ConsoleDevice est obligatoire, du moins en C, pour que le linker y retrouve ses billes lors de l’édition de liens avec l'Amiga.lib. Elle doit être de type (struct ConsoleDevice *).
Bien. Voyons maintenant l’utilisation de RawKeyConvertO. Son synopsys est le suivant :
nombre = RawKeyConvert(event, buffer, buflen, keymap); dO aO al dl a2
avec :
event
buffer
buflen
keymap
nombre
pointeur sur une structure InputEvent ; pointeur sur le buffer recevant le(s) caractère(s) ; taille de ce buffer ;
pointeur sur un keymap particulier ou NULL ;
nombre de caractères "traduits" ou -1 si le buffer était trop petit.
On voit ici que event pointe sur une structure de type InputEvent, alors qu’intuition ne nous envoie que des IntuiMessages. Conclusion : il va falloir se fabriquer une structure InputEvent et la remplir nous-même, en recopiant tout simplement les champs de l’IntuiMessage. Cet extrait de la fonction doKeys du listing montre comme faire :
AMIGA NEWS-TECH NUMERO 21 AVRIL 1991
25
fonction C qui réalise ceci (en supposant que la diskfon correctement ouverte) :
void GetFontSizes(ta, fontw, fontH, fontB) struct TextAttr *ta; * fonte à inspecter * USHORT *fontW; * contiendra la lageur en p
UBYTE doKeys(void)

static struct InputEvent ievent =
NULL, IECLASS_RAWKEY, 0, 0, 0, NULL, NULL );
y*****************************************************
?Les variables globales sont initialisées comme suit:* ?msgCode = IntuiMessage->im_Code;
?msgQualifier = lntuiMessage->im_Qualifier; 1
?msgData = IntuiMessage->im_IAddress; *
* define BUFSIZE 4 *
?UBYTE *charBuf[BUFSIZE]; *
* ****************************************************
if (msgCode & IECODE_UP_PREFIX) return(FALSE); * ignore Key-Up *
ievent.ie_Code = msgCode;
ievent.ie_Qualifier = msgQualifier; ievent.ie_EventAddress = (APTR)*msgData;
?charBuf = '0';
if (RawKeyConvert(&ievent, charBuf, BUFSIZE, NULL) .' =
1)
return(doSpecialKeys()); * C'est une touche spéciale
*
*** etc, etc, etc. ***
USHORT *fontH; * contiendra la hauteur *
USHORT *fontB; * contiendra la Baseline *

struct TextFont *fnt; if (ta->ta_Flags & FPB_DlSKFONT) fnt = OpenDiskFont(ta->ta_Name); else
fnt = OpenFont(ta->ta_Name); if (fnt)
*fontW = fnt->tf_XSize;
?fontH = fnt->tf_YSize;
?fontB = fnt->tf_Baseline;
CioseFont(fnt);
y
else * fonte inconnue au bataillon *
?fontw = *fontH = *fontB - 0;
}
Avec ces trois variables. On positionne le curseur où l’on veut :
void Cursor(rp, cursx, cursy, cursw, cursh, curspen, curspap)
struct RastPort *rp; * RastPort où dessiner le
C'était pas bien difficile. Je laisse aux 68000eurs le soin de transcrire cette routine dans leur langage préféré.
Au retour de RawKeyConvertO, on obient le nombre de caractères "traduits" dans le buffer. Ou -I si celui-ci était trop petit. Normalement, ce nombre devrait être égal à un, du moins tant qu'à la touche concernée, correspond un code ASCII affichage. Dans le cas des touches "spéciales" (F 1.. F10, curseur. HELP), le buffer contient la transcription AN SI de ces touches, à savoir (tous les codes sont en hexadécimal) :
FI 0x9b, 0x30, 0x7e
F2 0x9b, 0x31, 0x7e
F10 0x9b, 0x39, 0x7e
HAUT 0x9b, 0x41 BAS 0x9b, 0x42 DROITE 0x9b, 0x43 GAUCHE 0x9b, 0x44 HELP 0x9b, 0x3f, 0x7e
Cela oblige à écrire une routine (plutôt complexe) qui interprète ces codes ANS1 afin de réagir convenablement suivant la touche enfoncée...
Il y a évidemment plus simple : oublier alors RawKeyConvertO et utiliser l'IntuiMessage. C'est exactement de cette façon qu'agit la fonction DoSpccialKeysQ dans le listing. A noter que les touches comme CTRL C ou CTRL Y sont "traduites" en leur vraie valeur ASCII (3. 25. Etc.).
PETITE DISGRESSION
Notre étude du console.device étant maintenant terminée, j'en profite qu'il me reste un peu de place pour parler de la gestion du curseur au travers de la graphies.library.
curseur *
USHORT cursx, cursy; * position du curseur en caractères *
USHORT cursw, cursh; * largeur et hauteur du curseur *
USHORT curspen, curspap; * couleurs du curseur *

USHORT xl, yl, x2, y2;
SetAPen(rp, curspen);
SetBPenfrp, curspap);
SetDrMd(rp, JAM2I COMPLEMENT);
xl = cursx * fontW; yl = cursy * fontH; x2 = xl + cursw; y2 = yl + cursh;
RectFill (rp, xl, yl, x2, y2) ; * dessine le curseur
*
)
En utilisant cette fonction, veillez à ce que le curseur soit d'au moins I pixels moins large et moins haut que la fonte en cours, sinon il "mordra " sur le caractère voisin.
Voilà qui vous donne tous les éléments pour créer un éditeur de texte ultra-rapide. C'est comme ça que fonctionne GcnAm2. L'éditeur du Dcvpac. Ou même Memacs, l'éditeur fourni sur la disquette Extras du WorkBcnch. Ed quant à lui. Utilise le console.devicc pour la sortie des caractères... voyez la différence. Vous trouverez de plus dans le listing les routines appropriées pour éditer une ligne (BackSpacc et Del sont gérées), à vous de l'adapter à plusieurs lignes, puis à un texte entier, cela est beaucoup moins difficile que ça n'en a l'air.
Notre SUB.Way du mois prochain nous conduira tout droit au beau pays des Resources, qui permettent d'accéder directement aux registres hardware, tout en restant parfaitement multi-lâche. Mais je n'en dis pas plus, car c'est déjà tout un programme...
Bien que le listing proposé dans cet article n'agisse pas de cette manière (•a honte soit sur moi et ma famille jusqu'à la cinquante deuxième génération), il est recommandé, pour le positionnement et la taille du curseur, de connaître les largeur, hauteur et ligne de base de la fonte cours. J'ai utilisé des definc pour la fonte topaz évidemment des moyens beaucoup plus officiels de procéder.
I---
taille 8. Mais il y a I 7
Voici une l______
AMIGA NEWS-TECH KM N" 21 AVRIL 1991
......
* Programme : Mi ni HP
* Fonctions : Aucune ( ! )
* Ce programme est une démonstration du console.device
* et de RawKeyConvert().
* Il ressemble à un éditeur de texte, mais ce n'en est
* pas un ! ! !
* Compilation :Lattice C 5.10
* LC -cist -v
* LinJcage : FRQM LIB:c.o+"7.o"
* to »7"
* LIB LlB-.lcs.lib LIB:am.iga.lib
* SMALLCODE
* SMALLDATA
* VERBOSB
* DEFINE __main= tinymain
* Auteur : Stéphane Schreiber pour Amiga News Tech
include exec types.h>
Kinclude intuition intuition.h>
include intuition screens.h>
include graphies text,h>
Kinclude exec memory.h>
Kinclude exec io.h>
Kinclude exec tasks.h>
Kinclude devices inputevent ¦ h>
include devices console.h>
Kinclude libraries dos.h>
Kinclude libraries dosextens.h>
*** Taille de la fonte Topaz 8 (voir article) *
Kdefine FontH 8 Kdefine Fontw 8 define FontB 6 define TtlBar 12
*** couleurs du texte *
Kdefine TEXTPEN 1 Kdefine TEXTPAP 0 Kdefine TEXTMOD JAM2
*** Couleurs du curseur *
Kdefine CURSPEN 1 Kdefine CORSPAP 0 define CURSMDD ( JAM2 I COMPLEMENT)
... couleurs de la ligne d'info *
define STATPEN 2 define STATPAP 3 Kdefine STA1MOD JAM2
*** Constantes diverses *
define BUFSIZE 4 * Taille du buffer peur RawKeyConvertO *
define MAXLEN 79 * Taille maximum de la ligne *
define MAXLINE 28 * Nombre maximi.im de lignes *
*.. Touches (codes ASCII) *
Kdefine BS 8 define TAB 9 Kde fine LF 10 Kde fine CR 13 Kdefine ESC 27 Kdefine DEL 127
*** Touches (codes clavier) *
Kdefine LEFT_KEY 0x4f Kdefine RI(3îr_KEY 0x4e Kdefine DP_KEY 0x4c Kdefine DCMN_KEY 0x4d Kdefine HELP_KEY 0x5f
*** Qualifiers utilisés *
* A noter un bug du Lattice : si on ne met pas de parenthèses dans les defines ci-dessous (seulement les composés), le code produit est carrément n'importe quoi ! Et la priorité des opérateurs, alors ? Non nais !
*
Kdefine IE_SHIFTED ( IEQOALIFIER_LSHIFT I IEQüALIFIER_RSHIFT) Kdefine IE_CTRLED ( IEQüALIFIER_COt7TROL )
Kdefine IE_ALTED ( IEQÜALIFIER_IALT I IEQQALIFIER_RALT)
Kdefine IE_NÜMPAD (IEQDALIFIER_NOMPAD) **. Variables globales *
struct IntuitionBase *IntuitionBase = NOLL;
struct GfxBase ‘GfxBase = NULL;
struct ConsoleDevice ‘ConsoleDevice = NOLL;
struct Screen *myScreen = NOLL;
struct RastPort ‘myRastPort = NULL;
struct Window *myWindcw = NULL;
struct MsgPort *myUserPort = NULL;
USHORT CursX, CursY, editLen;
USHORT msgCode, msgQualifier;
ULON3 FreeMemory, msgClass;
APTR msgData;
struct IOStdReq ioreq;
struct TextAttr ta =
"topaz.font", TOPAZ_EIGHTY, 0, 0 ;
struct NewScreen ns =
0, 0, 640, 256, 2,
0, 1,
HIRES, CUSTC84SCREEN,
&ta, "Démo console.device - ESC pour quitter", NULL, NULL };
struct NewWindcw nw =
0, 0, 640, 256,
- 1, -1,
RAWKEY, *** Ce flag suffit amplement ici*
NOCAREREFRESH|ACTIVATE|BACKDROP|BORDERLESS,
NULL, NULL, NULL, NULL, NULL,
0, 0, 0, 0, CUSTCMSCREEN };
UW3RD myPalette[] =
0x0666, OxOFFF, 0x0000, 0x068B ;
UBYTE charBuf [BUFSIZE], *** Buffer pour RawKeyConvertO*
editStr[256]; *** Chaîne pour l'édition*
**** Prototypes des fonctions *
Kinclude stdio.h>
Kinclude string.h>
Kinclude stdlib.h>
Kifdef LATTICE Kinclude proto exec.h>
Kinclude protO intuition.h>
Kinclude proto graphics.h>
Kinclude proto console.h>
Kendif
void main(void) ;
UBYTE doKeys(void);
UBYTE doSpecialKeys(void); void WriteStr (UBYTE *, ULCNG) ;
Public Assistance
On attend vos PA (petites annonces) Elles seront bien évidement gratuites et exel usi vements réservées aux aaantbonnés
void Cursor (void) ; void StatusLine (void) ; void cleanExit (BYTE *) ;
*** Attention, c'est parti ! *********«**************«**********
void main (void)

UBYTE Fini = FALSE;
struct IntuiMessage "message;
IntuitionBase = (struct IntuitionBase *)
OpenLibrary("intuition.library", 33L);
GfxBase = (struct GfxBase *)
OpenLibraryf"graphies.library", 33L);
if ( !IntuitionBase || !GfxBase ) cleanExit ( "CXi sont les libraries ?");
if ( (myScreen = OpenScreen(tos)) == NULL ) cleanExit("Pas d'écran !”);
nw.Screen = myScreen;
if ( (myWindow = OpenWinâow(inw) ) == NULL ) cleanExit("Et la fenêtre ?");
LoadRGB4(&(myScreen->ViewPort), myPalette, 4);
*********************************************************
* Récupère les pointeurs sur le messageport et sur le *
* rastport de la fenêtre *
* *******•******»**»********»*»*»*»****************»**•***
myUserPort = myWindow- >UserPort ; myRastPort = myWindow- >RPort ;
* Ouverture du console.device. Unit=-1, donc pas besoin *
* de MessagePort pour ccmnuniquer avec lui (puisque du *
* coup, il n'y a pas de ccnrounication possible !) *
* ******************************************************** f
if ( OpenDevice("console.device", -1, iioreq, 0) ) cleanExit("Ctaps ! Pas de console.device !");
* Récupère un pointeur sur le console.device, qui nous *
* permettra d'accéder à ses fonctions. En 1'occurence, *
* il s'agit de RawKeyConvert() *
* ************************************»**•»*•••*»»»•»•»••*
ConsoleDevice = (struct ConsoleDevice *)ioreq.io_Device;
* Initialise les variables importantes pour l'édition *
CursX = CursY = editLen = 0;
* Affiche le curseur en mode CCMPLEMENT *
Cursor();
* Boucle principale. Sortie par ESC * while ( ! Fi Tri )
StatusLineO; * Affiche la ligne de status *
WaitPort(myUserPort); * Attend un événement * while (message = (struct IntuiMessage *)
GetMsg(myUserPort))
msgClass = message->Class;
nsgCode = message->Code;
msgOialifier - message->Qualifier; msgData - message->IAddress;
ReplyMsg((struct Message *)message);
switch (msgClass )
case RAWKEY :
Fini = doKeys(); break;
* Il peurrait bien entendu y en avoir d'autres : *
* case MENUPICK : ... }; break; *
* case REQSET : ___>;. Break; »
default :
puts("Message inattendu."); break ,- ) * switch msgclass *
) * while getmsgO *
* while fini * cleanExit("Everything's ok”);
)
* Réaction aux touches du clavier *
UBYTE doKeys(void)

static struct InputEvent ievent =
NULL, IECLASS_RAWKEY, 0, 0, 0, NULL, NULL }; * Voir article *
define Key ÇcharBuf)
if (msgCode & IECODE_UP_PREFIX) * Ignore Key-Up *
return(FALSE);
Key = '0';
ievent.ie_Code = msgCode;
ievent.ie_Qualifier = msgQualifier;
ievent.ie_EventAddress = (APTO) *msgData;
if ( RawKeyCorrvert (Sievent, charBuf, BUFSIZE, NULL) != 1) re tum ( doSpec ia Ikeys ( ) ) ;
switch( Key )
case TAB : break; case ESC :
retum ( TRUE ) ; break; case LF : case CR :
if ( CursY MAXLINE )
CursorO;
++CursY;
CursX = editLen = 0;
break; case DEL :
if ( CursX editLen )
movmesn(&editStr [CursX+1],
SeditStr[CursX], editLen-CursX);
editLen;
break; case BS : if ( CursX )
CursX; movmemf&editstr [CursX+1],
SeditStr[CursX], editLen-CursX);
editLen;
}
break; default :
if ( Key > 31 )
( if ( editLen MAXLEN )
movmem (SeditStr [CursX],
&editStr[CursX+1], editLen-CursX); editStr[CursX++] = Key; editLen++;
}
break;
)
editStr[editLen] = '0';
WriteStr(editStr, editLen);
CursorO; retum ( FALSE ) ;
}
...
* Traitement des touches spéciales (flèches, HELP, etc.) *
.....t.*.,,...,,...,,.,.,,,,,,,,,,,,,,,.,,,,.,,,,,,,,,,,,,,,,,,,
UBYTE doSpecialKeys(void)

CursorO; switch (msgCode)
case LEFT_KEY :
if (rnsg ialifier & IE_SHIFTED)
CursX = 0; else if (CursX)
CursX; else
DisplayBeep(myScreen); break;
case RIGHT_KEY : if (msgQualifier & IE_SHIFTED)
CursX = editLen; else if (CursX editLen)
++CursX;
else
DisplayBeep(myScreen) ; break; case HELP_KEY : strcpy(editStr, "Help ! A l'aide !"); WriteStr(editStr, (editLen = CursX = 17));
}
CursorO ;
retum (FALSE) ;
* Ecrit une chaine de caractères à la position du curseur
* Utilise TextO de la graphies.library
void WriteStr(str, len)
UBYTE *Str;
UL0N3 len;
_
SetAPen(myRastPort, TEXTPEN);
SetBPen(myRastPort, TEXTPAP);
SetDrMd (myRastPort, TEXTMDD) ;
Move(myRastPort, 0, (CursY*FontH)+TtlBar+FontB); Text(myRastPort, str, len);
ClearEOL(myRastPort);
* Affiche le curseur à sa position courante
* Utilise RectFill() de la graphies.library
void Cursor(void)

ÜSHORT xl,yl,x2,y2;
xl = CursX*FontW; yl = (CursY*FontH)+TtlBar; x2 = xl+FontW-1; y2 = yl+FontH-1;
SetAPen(myRastPort, CURSPEN);
SetBPen(myRastPort, CURSPAP);
SetDrMd (myRastPort, CURSMDD) ;
RectFill(myRastPort, xl, yl, x2, y2);
* Affiche la ligne de status. Utilise aussi Text()
void StatusLine(void) t
static UBYTE infoBuf[100]; * Buffer volontairement trop grand * ULCNS 1;
l=sprintf(infoBuf, " Ligne: %4d Col: Long: %4d",
CursY+1, CursX+1, editLen+1);
SetAPen(myRastPort, STATPEN);
SetBPen(myRastPort, STATPAP);
SetDrMd (myRastPort, STATMOD);
Move(myRastPort, 0, 256-(FontH-FontB));
Text(myRastPort, infoBuf, 1);
ClearEOL(myRastPort);
î
Fin du progrance. Ferme tout bien ccmme il faut
void cleanExit(str)
BYTE *str;

if (CansoleDevice) CloseDevice(fcioreq);
if (myWindow) CloseWindcw(myWindow) ;
if (myScreen) CloseScreen(myScreen);
if (GfxBase) CloseLibrary(GfxBase);
if (IntuitionBase) CloseLibrary(IntuitionBase);
puts(str);
exit(RETORN_FAXL);
lea
Message(pc),aO
move.b
(a0)+,d0
NewOiarl move.l
aO,Mess
cmç.b
$ lf,d0
bgt.s
NewChar2
tst.b
dO
bne.s
NewCharl_l
move.b
100,Stcp
move.b
' ',d0
bra.s
NewCharl_l:
NewChar2
cnp.b
15,dO
bgt.s
NewChar2
move.b
dO,Vitesse
andi.w
$ f,d0
move.b
ShiftTab(pc,dQ.w),Shift
bra.s
NewChar
ShiftTab dc.b NewChar2:
0,15,7,0,3,0,0,0,1,0,0,0,0,0,0,1
bsr.s
FindChar
move.l
ScrollAdr(pc),al
lea
15*42+40(al),al
moveq
2,d0 ; Cctrpteur Bitplanes
moveq
38,dl ; BLTAMOD
swap
dl
move.w
40,dl ; BLTEMOD
moveq
-l,d2 ; BLTAFVM & BLTLWM
moveq
0,d3
move.w
$ 09f0,d3 ; BLTCONO
swap
d3 ; BLTCCm
move.w
(25*64)+l,d4 ; BLTSIZE
NewCharL bsr
WaitBlit
move.l
aO,BLTAPTH(a6)
move.l
al,BLTDPTO(a6)
move.l
dl,BLTAMDD(a6)
move.l
d2,BLTAFWM(a6)
move.l
d3,BLTCCN0(a6)
move.w
d4,BLTSIZE(a6)
lea
40*80(a0),a0
lea
ScrollBPL(al),al
dbra
dO,NewCharL
bra
Scroll2
FindChar moveq
0,dl
andi.w
$ ff,d0
lea
Chars(pc),a0
FindChL move.b
l(a0),dl
bmi.s
NotHere
cnp.b
(a0),d0
beq.s
FoundCh
addq.1
2,a0
bra.s
FindChL
NotHere moveq
0,d0
FoundCh add. W
dl. dl
move.w
ChOffset(pc,dl.w),d0
move.l
SpriteAdr(pc),aO
lea
rts
(a0,d0.w),a0
ChOffset de.w
0000,0002,0004,0006,0008,0010,0012,0014,
de .w
0020,0022,0024,0026,0028,0030,0032,0034,
de .w
1000,1002,1004,1006,1008,1010,1012,1014,
dc. w
1020,1022,1024,1026,1028,1030,1032,1034,
dc. w
2000,2002,2004,2006,2008,2010,2012,2014,
dc. w
2020,2022,2024,2026,2028,2030,2032,2034,
. **************4
r*********************
waitBlit btst WaitBlitter:
14,EKACCNR(a6)
btst
14,EMACONR(a6)
bne.s
rts
WaitBlitter
; Efface l'écran
au blitter
BltClear bsr.s
WaitBlit
move.l
Screenl(pc),BLTDPTH (a6)
move.w
0, BLTEMOD (a6)
move.w
0,BLTADAT(a6)
move.l
-l,BLTAFWM(a6)
move.l
$ 01f00000,BLTCCN0(a6)
move.w
rts
(400*64)+20,BLTSIZE(a6)
Sprite:
inebin "Fonte"
SpriteEnd:
cnop 0,4
SpriteSize
EQU *-Sprite
zj= = ; s WÊiïie&ËÀ
__
Please insert letter ANT
in any boite postale
‘ £ s g* si Requester
Cela fait plaisir : aux vues des premiers résultats du sondage de notre dernier numéro, le Requester est l’une des rubriques de l’ANT les plus appréciées. Remarquez, c’est normal : je me donne un mal fou pour répondre à vos questions, toutes plus pertinentes les unes que les autres. Mais continuez, j’aime ça.
J'ai deux questions (FM : pour le prix d'une !).
1) Je possède déjà les RKM (librairies & devices, includes & autodocs), les 2 Amiga Programmer's Handbook et le Programmer’s Guide to the Amiga. Y a t-il un ouvrage complet sur l'AmigaDOS ? Les RKM font parfois référence à un "AmigaDOS Manual". Où peut-on se le procurer ? Epargnez moi s’il vous plaît les références aux ouvrages français (FM : n 'ayez crainte)...
2) Je ne maîtrise pas du tout le langage Arexx et je trouve l’ARexx User's Reference Manual fort laconique et sibyllin. Pourtant, j'en ai un besoin impérieux : j'utilise CygnusEd Pro et j'assemble avec le Genlm2 du Devpac. Et je donnerais gros (FM : pus de problème, j'accepte les chèques) pour disposer de macro-commandes Arexx me permettant au moins d’assembler à partir de CED Pro, et éventuellement de tracker les erreurs, ou autres gadgets propres à me faciliter l'assemblage.
Où puis-je trouver cela ? Je lance un appel à quiconque disposerait de tels outils.
Pierre-Louis MANGEARD (Ile de la Réunion)
L’AmigaDOS Technical Reference Manual est un ouvrage quasi-introuvable en France. Pour se le procurer, il faut s’adresser directement à Commodore France qui de toute façon refusera si vous n'avez pas au moins le status développeur. C’est dire. Vous pouvez essayer de ruser : trouvez un développeur qui acceptera d’acheter le livre pour vous le revendre ensuite. Comme j’en vois venir, je précise d’emblée que ni TANT ni Amiga Revue n’ont le status développeur - on peut pas être à la fois journaliste et programmeur, paraît-il...
Il y a foison de commandes Arexx susceptibles de vous satisfaire dans le domaine public, notamment dans la collection Fred Fish. Il faut vous procurer le catalogue afin de localiser les disquettes pouvant vous intéresser.
Ce serait tout à fait dans l’esprit de TANT si un lecteur pouvait répondre à cet appel. Et également nous en faire part car cela peut toujours servir. De notre côté, nous cherchons quelqu'un connaissant suffisamment bien Arexx pour nous faire une rubrique dessus. Je crois qu’on a trouvé, un peu de patience...
Bonjour à toute l’équipe ! Je suis vraiment content que F ANT soit devenu indépendant. Nous avons enfin en France un vrai journal pour les programmeurs sur Amiga. Je ne veux pas dire que l’ANT d'avant, celui intégré à Commodore Revue, n’était pas bien, mais un vrai journal c’est tout de même mieux.
Voilà ce qui m'amène : jusqu’ici, je programmais uniquement en assembleur (à propos, vous avez raison : Devpac, c’est vraiment ce qu’il y a de mieux), mais je me rends compte qu’il est certainement plus avantageux de programmer en C pour de gros programmes. Aussi j’envisage d'acheter un compilateur, mais je n’arrive pas à me décider entre l'Aztec et le Lattice. C’est un gros investissement pour moi, alors mieux vaut ne pas risquer d'être déçu. Vous paraissez pour le Lattice, mais les gars d’A-News (que je lis aussi, j'espère que vous ne m'en voudrez pas trop) semblent plutôt préférer l’Aztec. Donc j’hésite. Comment faire un choix ? Est-il vrai que le Lattice comporte des bugs ?
Denis Bortolin (Melun)
Effectivement, je ne jure que par le Lattice et tous ici à l'ANT nous l'utilisons. En toute objectivité, il faut dire que les deux compilateurs sont excellents, chacun avec leurs avantages et leurs défauts. Par exemple, l’Aztec compile sensiblement plus vite, mais je trouve l'éditeur de liens peu pratique, et pour générer des overlays, c’est une vraie m.... (ou alors j'ai rien compris). Paralèllement. Le Lattice compile plus lentement, mais l’éditeur de liens est à mon avis très souple d’utilisation et également plus rapide (BLink version 5.10). On pourrait ainsi multiplier les exemples.
Pour faire un choix, il peut être judicieux d’examiner les options de compilation présentées par chacun, ainsi que leurs librairies. Toutefois on peut considérer que l'environnement de l'Aztec est un peu austère, et c'est là surtout que se fait la différence. Le Lattice permet de compiler et linker depuis l'éditeur, ce qui est loin d'être désagréable (SS : le Turbo C permet aussi de debugger depuis l'éditeur, et c'est encore plus pratique.
Pourquoi pas le Lattice ?). Réciproquement, si l’on compile depuis le
CLI. Une option provoque l'appel de l'éditeur si une erreur est rencontrée, ce qui permet des corrections très rapides. A propos d'éditeur, celui de l'Aztec est par trop épouvantable. Le Lattice propose également un startup catch, ainsi que certains utilitaires (tb, lprof. Lstat...) que l'on ne retrouve pas dans l'Aztec. Enfin les
"keywords" chip et asm. Entres autres, sont de véritables bijoux
spécifiques au Lattice.
On peut éventuellement résumer la situation ainsi : l'Aztec est un excellent compilateur, très rigoureux, très "C”, mais qui n’offre pas un confort en rapport avec les capacités de l'Amiga. Le Lattice est un excellent compilateur, un peu moins rigoureusement "C", mais beaucoup plus Amiga. C’est surtout sur l'environnement de développement que se fait, à mon avis, la supériorité du Lattice.
Le Lattice comporte effectivement quelques bugs, mais il y a toujours moyen de s’en sortir. N'allez pas croire ce que certains disent, le Lattice n'est pas buggué de partout. D'ailleurs, il ne faut pas se faire d'illusions. Je suis sûr que l'on peut également se heurter à des bugs dans l’Aztec lors d'une utilisation poussée. En lui "tirant les vers du nez" comme dirait Herr Doktor Von GlutenStimmellmDorf.
Je tiens vraiment à vous féliciter pour votre programme Sentinelle du mois de Décembre. En effet, j’ai pu grâce à lui trouver sur quel fichier s’était installé un virus-coquille qui voulait me faire de grosses misères. Mais, même si je vous félicite, je n 'ai pas toute confiance. Je suis devenu plutôt méfiant à cause de mes déboires avec les virus ces derniers temps. Aussi je voudrais avoir le moyen de m ’assurer à n 'importe quel moment si votre Sentinelle est toujours en train de surveiller l’ordinateur. Ce moyen est sûrement donné dans l’article, mais je suis vraiment débutant et je n ’ai pas tout compris. Autre chose. Un copain à moi a programmé un petit utilitaire destiné à vérifier le bit 31 des vecteurs de sauts d'exec.library, afin de voir par ce moyen s’il n’y aurait pas virus (c’est mon copain qui dit tout ça, hein, moi je ne comprends pas tout). On souhaiterait savoir si l’idée est bonne. De plus, nous avons remarqué que s’il l’on place son petit programme au début de la Startup-Sequence, tout va bien, mais si on le place à la fin, il indique la présence d'un virus. Mais cette fois, nous n’avons pas pu en localiser. Que se passe-t-il ?
Gilles Mingot (Strasbourg)
Pour vérifier que la Sentinelle est bien active, vous pouvez utiliser le programme suivant :
include 'exec execbase.i'
move .1 $ 4, aO
move. 1 dO, CoolCapture ( aO )
rts
Si vous appelez ce programme depuis le CLI et que l'alerte apparaît, c’est que tout va bien, la Sentinelle veille au grain. Il vous suffit alors de cliquer le bouton gauche.
Votre idée est très bonne. Rassurez-vous, vous n’avez pas de virus. C’est le programme SetPatch de la Startup-Sequence qui provoque cela, et c’est normal car ce programme détourne certains sauts (qui ne vont donc plus en ROM) afin de corriger quelques bugs des librairies de l’Amiga. Il vous faut donc d’abord savoir quelques sont les valeurs de saut normales APRES l’appel de SetPatch et programmer votre utilitaire en conséquence (SS : j’ai eu le même problème avec SetPach et la Sentinelle ; en fait, si SetPatch est utilisé sans l’option "r" (résident ?) Les messages disparaissent).
Je programme en assembleur et j'ai acheté Devpac puisque vous avez tellement insisté. J'en suis d’ailleurs extrêmement content. Le débuggeur est vraiment remarquable. C'est quand même autre chose que la petite fenêtre minable de Seka. Toutefois il m’arrive quelque chose de très bizarre. Un programme qui allait bien avec Seka ne fonctionne plus avec Devpac. Je veux dire que Devpac n’arrive pas à l'assembler. Il bloque à la ligne move.l S0a,6(a0)+. Pouvez vous m’expliquer ce qui se passe exactement et comment faire fonctionner mon programme ?
Philippe Boussugue (Brest)
Ooouuaaahhh- ! Une question sur Seka. Je vais pouvoir déverser tout mon fiel. Houba ! Surtout que dans ce cas, il y a vraiment de quoi rire... Voilà ce qu’il se passe : une instruction d’adressage avec distance et post-incrémentation N’EXISTE PAS en 68000. C’est donc on ne peut plus normal que ce brave Devpac refuse de l’assembler.
Partant de là, voyons un peu les élucubrations du Seka. Celui-ci assemble comme si de rien n'était l’instruction. Mais en fait, si l’on examine le code produit, on s’aperçoit que l’instruction a été remplacée par move.l S0a,6(a0,d0.w). Est la même chose ? Pas du tout ! La post-incrémentation a été remplacée par une distance relative au contenu de DO. Mais le contenu de DO N’A PAS été initialisé en conséquence. C’est donc déjà un véritable miracle que votre programme marche. De plus, ce mode d’adressage ne modifiera pas AO, donc en aucun cas il y aura post-incrémentation. C’est encore plus un miracle si votre programme marche ! Et enfin, si par malheur
DO contient une valeur impaire, c’est un gourou assuré. Vous êtes vraiment sûr que votre programme marche ?
Puisque j’y suis, en voilà (parmi tant d’autres) une bien bonne. Soit l’instruction movea.l S10000.a0. Voilà une instruction 68000 parfaitement correcte. Et bien cette fois. Seka refuse obstinément de l'assembler. Moralité, cet abruti de Seka assemble les instruction inexistantes, mais n’assemble pas celles qui existent. Je me marre !
Comment un programme peut-il se détacher du CLI ? Je parle des programmes comme VirusX, Cygnus Editor ou DiskMuster, qui "rendent la main" au CLI même si on ne les lance pas avec la commande RUN. Je possède la Bible, mais les routines concernant cette fonction sont en C, et je ne fais que de l'assembleur. Et je ne trouve une telle routine dans aucun ANT. Pourriez-vous en publier une ? S’il vous plaît, répondez-moi, car si vous, programmeurs de TANT, ne répondez pas à vos lecteurs avides de connaissances, qui le fera ?!?
Xavier Averbouch (Baillet)
Les programmes que vous citez ont un moyen fort simple de se détâcher du CLI : écrits sans aucun doute avec le Lattice C. ils sont élé linkés avec "cback.o", un startup spécifique au Lattice qui permet de genre de miracle.
Etes-vous sûr d'avoir bien lu TOUS les ANT ? Je me souviens avoir donné dans ces mêmes pages, une routine assembleur équivalente au "cback.o", nommée BackStart.i et destinée à être incluse en début de source, à la place du Startup.i standard (ou du EasyStart.i du Devpac). Mais si. Cherchez bien : c’était dans le numéro 19 de TANT (c’est pourtant pas si vieux). Allez, la bonté et la générosité de l'équipe de TANT n’ayant pas de limites (je crois avoir déjà dit ça quelque part ?), nous allons include BackStart.i sur la disquette de ce numéro, c'est-y-pas beau ?
Salut ! Juste une question simple, par curiosuté : j’ai vu récemment dans le source d'un copain, qu’il testait DEUX FOIS le bit 14 du registre DMACONR, avant de démarrer une opération avec le Blitter. Quand je lui en ai demandé la raison, il m'a rétorqué que c’était OBLIGATOIRE, sinon, ça pouvait faire foirer le Blitter. Etant donné que c’est la première fois que je vois ça, pourriez-vous m’en dire un peu plus ?
Alain Garnier (Roanne)
Votre copain a certainement lu - et il en a été bien avisé - les RKM ou quelque ouvrage en étant inspiré (je ne parle bien entendu pas de la Bible). Celà dit, il n’a que partiellement raison. Je m’explique.
Tout le monde sait que le Blitter travaille en parallèle avec le 68000. Ce dernier se chargeant de l'initialiser. Mais pour ce faire, il ne faut pas que Blitter soit déjà en train de travailler, sinon ça fait pas beau à l'écran. C’est le travail du bit 14 de DMACONR, appelé DMAF_BLTDONE. Qui renseigne le 68000 su une éventuelle activité du Blitter. Or, celui-ci ne positionne DMAF_BLTDONE que lorsqu’il a reçu son premier cycle DMA. Ce qui peut durer un certain temps si le DMA est surchargé de travail, ou si un 68030 travaille en FAST-RAM en mode cache... La solution pour être sûr que le Blitter fut effectivement disponible, était de tester deux fois DMAF_BLTDONE. Je dis "était", car depuis que Fat Agus a été créé, ce "bug" a été corrigé : le Blitter positionne dorénavant DMAF_BLTDONE dès l’écriture dans BLTSIZE. Rendant ce double test obsolète. Celà dit, si l’on veut être sûr que son programme tournera sans problème sur tous les modèles d’Amiga. Et particulièrement l’A1000, il est préférable de le laisser.
La première chose à faire lorsque l'on programme "système" est d'utiliser les includes officiels de Commodore-Amiga. Et non des includes personnels, pouvant être source d'erreur dans certains cas, mais qui surtout limitent la maintenance du logiciel en cas d'upgrade du système. Et ceci quelque soit le langage utilisé : C. assembleur, Pascal. Fortran... Certaines sociétés proposent leurs propres includes, souvent avec l'aval de Commodore-Amiga. Ceux-ci sont également sains à utiliser.
REGLES GENERALES DE DEVELOPPEMENT
Depuis le temps qu ’on vous le dit et le répète :
Vamiga nyestpas une machine comme les autres; ne faîtes pas ceci, ne faîtes pas celà, au contraire faîtes comme ça... Voici une bonne fois pour toutes les recommandations officielles des gens qui ont fait Vamiga.
L'environnement de l'Amiga est très différent de celui d’autres ordinateurs plus anciens. L'Amiga est multi-tâche, ce qui signifie que plusieurs programme doivent se partager la même machine sans interférer les uns avec les autres. Celà impose quelques règles à suivre.
1) Assurez-vous toujours de recevoir ce que vous demandez : allocations de mémoire, fenêtres, écrans, fichiers, bibliothèques, devices, ports, etc. Quand une fonction peut provoquer une erreur, prévoyez une porte de sortie : beaucoup de programmes mal écrits semblent fonctionner correctement, jusqu'à ce que des conditions inhabituelles surviennent (manque de mémoire, disque corrompu...), qui le font travailler avec des pointeurs invalides ou se brancher sur des routines non testées.
2) Faites le ménage derrière vous ! Celà s’applique aussi bien à une fin normale de programme qu’à une sortie prématurée, à cause d'erreurs inattendues. Tout ce qui a été ouvert doit être fermé, tout ce qui a été alloué doit être dé-alloué. Il est généralement conseillé de fermer en sens inverse des ouvertures. Vérifiez dans le manuel de votre système de développement que les routines startup ne libèrent pas certaines ressources pour vous en cas de terminaison anormale, pour ne pas les libérer deux fois. _ Si vous programmez en C, faites en sorte que l'appui sur CTRL-C provoque toujours une porte de sortie de votre programme.
3) Rappelez-vous que la taille mémoire, les périphériques et même les ROMs peuvent différer d'une machine à une autre. Ne supposez jamais comme valides certaines plages d'adresses ou certaines noms de volumes, spécialement de disques durs. Ne sautez jamais directement en ROM. Ne vous attendez pas à trouver certaines structures système à une adresse particulière. La seule adresse absolue dans le système est l'adresse 0x00000004, qui contient l’adresse de base d’exec.library.
4) Votre programme ne peut et ne doit jamais accéder au hardware directement. Le hardware est contrôlé par un système qui n’apprécie guère les ingérences. Partager du hardware entre plusieurs programmes requiert des protocoles stricts. Utiliser les interfaces définies pour vous assurera votre logiciel de tourner sur les prochaines version de l'Amiga.
5) N'accédez jamais à des structures publiques sans les avoir au préalable réservées ("lockées") : d'autres programmes que le votre peuvent vouloir y accéder en même temps.
VIVRE
6) Le système de gère pas la pile de ses tâches. Attention au débordement de pile. Des versions futures du système pourront réclamer plus d'espace libre sur la pile qu'actuellement. Prévoyez large.
7) Si votre programme doit attendre des événement extérieurs, comme la sélection d'un menu ou l'appui sur une touche, n'entrez pas dans une boucle répétitive, qui ralentirait considérablement le système. Laissez plutôt votre programme "en sommeil" avec Wait() jusqu’à ce que l'événement ait lieu. Assurez-vous de répondre avec ReplyMsgO à tous les messages que le système ou d'autres lâches peuvent vous envoyer.
8) Les tâches et les processus s’exécutent dans le mode utilisateur du 68000. Le mode Superviseur est réservé pour les interruptions, les traps. Et le partage du temps entre les tâches. Faites très attention si certaines de vos routine s’exécutent en mode superviseur : les exceptions en mode superviseur sont irréparables.
9) La plupart des fonctions du système requièrent certaines conditions particulières pour fonctionner. Toutes les fonctions du DOS et celles qui peuvent appeler le DOS indirectement (commerouverture d’un device, d'une bibliothèque...) ne peuvent le faire que depuis un processus. Une tâche n'est pas suffisante.
10) n'interdisez pas le multi-tâche - Forbid() - ou les interruptions - DisableO - pendant de trop longues périodes. Il faut également savoir que toutes les fonctions qui, à un moment ou à un autre, attendent - Wait() - brisent provisoirement l'interdiction du multi-tâche. Ceci inclut les fonctions DOS et les entrées sorties standard, comme par exemple printf().
11 ) toutes les données des custom chips doivent être logés en Chip Memory : bitplanes, samples. Buffers pour le trackdisk, images, sprites. Bobs... La fonction AllocMem() dispose d'un flag qui spécifie la Chip Memory.
12) N'utilisez pas de boucles de temporisation ! Dans une environnement multi-tâche. Une même boucle peut s'exécuter deux à dix fois plus vite, selon le nombre de tâches actives et le processeur utilisé. La fonction DelayO de l'AmigaDOS assure un moyen simple d'attendre quelques instants. Les deux 8520 disposent chacun de deux timers que les programmeurs qui oublient le système n’en on sans doute entendu parlé.
13) Obéissez aux conventions :
- toute adresse accédant à un mot ou à un mot long doit être paire :
- tous les pointeurs sont 32 bits (non 24). Les 8 bits supplémentaires ne doivent pas être utilisés pour stocker des données ;
- tout champ non défini ou réservé dans une structure doit être mis à NULL, pour compatibilité antérieure :
- l’allocation dynamique de structures assure qu'elles seront alignées sur des addresses paires.
NOTES AU PROGRAMMEURS EN ASSEMBLEUR
1) N'utilisez pas l’instruction "TAS", qui assume un cycle indivisible de lecture-modification-écriture. Le DMA système pourrait entrer en conflit avec ce cycle spécial.
2) Les fonctions du système sont appelées avec a6 pointant sur l’adresse de base de la bibliothèque ou du device concerné.
3) Sauf quand indiqué, les fonctions système peuvent utiliser les registres aO. Al, dO et dl. Les autres registres sont préservés.
4) Les fonctions qui retournent une valeur n'affectent pas obligatoirement les flags du processeur. C’est au programmeur de s’assurer de la validité du retour (soit avec TST. Soit avec MOVE).
5) Compatibilité 60000 68010 68020 68030 :
- n’utilisez pas l’instruction "MOVE SR,...", privilégiée sur certaines catégories de 680x0. Utilisez à la place GetCC() d'exec.library ;
- n'utilisez pas de code auto-modifiable.
Si vous suivez toutes ces recommandations, alors votre programme est assuré d'une longue vie sur l’Amiga. Le non-respect de l'une de ces règles peut empêcher votre application de fonctionner sur une machine particulière !
(c) CATS 1987-1991 (Commodore Amiga TechicaT Support)
ce, d'une bibliothèque...) ne peuvent le faire que depuis un processus. Une tâche n'est pas suffisante.
10) n'interdisez pas le multi-tâche - Forbid() - ou les interruptions - DisableO - pendant de trop longues périodes. Il faut également savoir que toutes les fonctions qui, à un moment ou à un autre, attendent - Wait() - brisent provisoirement l'interdiction du multi-tâche. Ceci inclut les fonctions DOS et les entrées sorties standard, comme par exemple printf().
11 ) toutes les données des custom chips doivent être logés en Chip Memory : bitplanes, samples. Buffers pour le trackdisk, images, sprites. Bobs... La fonction AllocMem() dispose d'un flag qui spécifie la Chip Memory.
12) N'utilisez pas de boucles de temporisation ! Dans une environnement multi-tâche. Une même boucle peut s'exécuter deux à dix fois plus vite, selon le nombre de tâches actives et le processeur utilisé. La fonction DelayO de l'AmigaDOS assure un moyen simple d'attendre quelques instants. Les deux 8520 disposent chacun de deux timers que les programmeurs qui oublient le système n’en on sans doute entendu parlé.
13) Obéissez aux conventions :
- toute adresse accédant à un mot ou à un mot long doit être paire :
- tous les pointeurs sont 32 bits (non 24). Les 8 bits supplémentaires ne doivent pas être utilisés pour stocker des données ;
- tout champ non défini ou réservé dans une structure doit être mis à NULL, pour compatibilité antérieure :
- l’allocation dynamique de structures assure qu'elles seront alignées sur des addresses paires.
NOTES AU PROGRAMMEURS EN ASSEMBLEUR
1) N'utilisez pas l’instruction "TAS", qui assume un cycle indivisible de lecture-modification-écriture. Le DMA système pourrait entrer en conflit avec ce cycle spécial.
2) Les fonctions du système sont appelées avec a6 pointant sur l’adresse de base de la bibliothèque ou du device concerné.
3) Sauf quand indiqué, les fonctions système peuvent utiliser les registres aO. Al, dO et dl. Les autres registres sont préservés.
4) Les fonctions qui retournent une valeur n'affectent pas obligatoirement les flags du processeur. C’est au programmeur de s’assurer de la validité du retour (soit avec TST. Soit avec MOVE).
5) Compatibilité 60000 68010 68020 68030 :
- n’utilisez pas l’instruction "MOVE SR,...", privilégiée sur certaines catégories de 680x0. Utilisez à la place GetCC() d'exec.library ;
- n'utilisez pas de code auto-modifiable.
Si vous suivez toutes ces recommandations, alors votre programme est assuré d'une longue vie sur l’Amiga. Le non-respect de l'une de ces règles peut empêcher votre application de fonctionner sur une machine particulière !
(c) CATS 1987-1991 (Commodore Amiga TechicaT Support)

Click image to download PDF

AMIGA NEWS TECH numero 21 (04-1991)

Merci pour votre aide à l'agrandissement d'Amigaland.com !


Thanks for you help to extend Amigaland.com !
frdanlenfideelhuitjanoplptroruessvtr

Connexion

Pub+

35% 
16.1% 
6.7% 
4.4% 
4.4% 
3.6% 
3.3% 
2.5% 
1.7% 
1.4% 

Today: 4
Yesterday: 57
This Week: 507
Last Week: 630
This Month: 2483
Last Month: 3072
Total: 66623

Information cookies

Cookies are short reports that are sent and stored on the hard drive of the user's computer through your browser when it connects to a web. Cookies can be used to collect and store user data while connected to provide you the requested services and sometimes tend not to keep. Cookies can be themselves or others.

There are several types of cookies:

  • Technical cookies that facilitate user navigation and use of the various options or services offered by the web as identify the session, allow access to certain areas, facilitate orders, purchases, filling out forms, registration, security, facilitating functionalities (videos, social networks, etc..).
  • Customization cookies that allow users to access services according to their preferences (language, browser, configuration, etc..).
  • Analytical cookies which allow anonymous analysis of the behavior of web users and allow to measure user activity and develop navigation profiles in order to improve the websites.

So when you access our website, in compliance with Article 22 of Law 34/2002 of the Information Society Services, in the analytical cookies treatment, we have requested your consent to their use. All of this is to improve our services. We use Google Analytics to collect anonymous statistical information such as the number of visitors to our site. Cookies added by Google Analytics are governed by the privacy policies of Google Analytics. If you want you can disable cookies from Google Analytics.

However, please note that you can enable or disable cookies by following the instructions of your browser.

Visitors

Visite depuis
03-10-2004
Visite depuis
23-02-2014