Sponsors

FacebookTwitterGoogle Bookmarks

HONNI SOIT QUI MAL Y PENSE ! Et le maulubec vous trousque ! Car il est intéressant de reconsidérer le problème et je m’en explique. Le programme “noclick” travaille de la manière suivante : il fait une recherche d’octets en ROM afin de localiser le trackdisk.device (pour que le programme puisse fonctionner selon les versions connues du kickstart). Ceci fait, le trackdisk.device en question est entièrement recopié en RAM, puis toutes les addresses de saut sont modifiées afin d’obtenir à nouveau un programme susceptible de fonctionner, puis ledit nouveau trackdisk est modifié afin que les drives ne cliquettent plus. Il suffit en fait de changer UN SEUL BIT pour obtenir ce résultat. Ils auraient quand même pu faire un effort chez Commodore !!! Enfin l’Amiga est astucieusement leurré afin que ce nouveau trackdisk.device soit utilisé. Bien. L’avantage de cette méthode est qu’aucune tâche n'est ajoutée donc l’Amiga n’est ralenti en rien. Par contre, il y a à mon avis quelques inconvénients : - Occupation d’une grande quantité de RAM. - Je n’aime pas ce genre de programmes qui utilisent directement des bouts de ROM sans passer par les librairies car il y a toujours le risque que Commodore modifie (et c’est son droit) légèrement l’organisation du kickstart sur une nouvelle série d’ordinateurs sans prévenir personne, et on se retrouve ainsi avec un programme qui ne marche plus ou pire : qui invoque le gourou au moment le plus inopportun. - Enfin “noclick” comporte un bug. Bon j’avoue tout de suite que je suis allé le chercher loin celui-là, mais c’est dans ma nature de grand pourfendeur de bugs devant l'éternel. En effet, sur un Amiga 500, en bootant sur disque dur A590, avec une disquette quelconque en DF1: et aucune disquette en DFO: et si “noclick” est placé en début du startup-sequence, il se passe la chose suivante : DF1: ne cliquettera effectivement plus si vous retirez la disquette mais DFO: lui, cliquettera Ad Vitam Eternam. UNE AUTRE SOLUTION Un lecteur de disquette ne cliquette que quand il est vide. Le cliquetis est généré par une routine d’interruption qui vérifie régulièrement si une disquette est insérée dans le lecteur, mais cette routine a le malheur de faire déplacer la tête du lecteur à chaque test, ce test s’effectuant à travers le trackdisk.device en ROM. Quand un lecteur contient une disquette il ne cliquette plus car la routine d’interruption considère à juste titre que le lecteur est occupé et ne fait plus son test (en fait je simplifie un peu). Ceci considéré, il faut savoir que AmigaDOS traite chaque lecteur de disquette en tant que processus à son plus haut niveau, sans se préoccuper le moins du monde de ce que fait le trackdisk.device. Pour être plus précis, ce qui se passe quand un accès disque est nécessaire est qu’AmigaDOS envoie un message particulier appelé DosPacket à un processus DOS, par exemple DFO:. Lorsque le processus DFO: a reçu ce message, il s’occupe tout seul (vive les ordinateurs multi-tâches I) de lancer le trackdisk.device et d’y écrire ou lire des données. Ce qui est intéressant c’est que ces fameux DosPacket permettent une quantité de commandes différentes dont une : ACTION_ INHIBIT qui lorsqu’elle est envoyée a pour effet “d’inhiber” le processus qui la reçoit. C’est-à-dire qu’il deviendra impossible d’accéder au processus par d’autres commandes DOS tant que dure cet état de fait.

Click image to download PDF

AMIGA NEWS TECH numero 16 (10-1990)

Document sans nom TRANSACTOR
Mettez un silencieux dans vos lecteurs de disquettes
par F. Mazué, P. 34
Utilisation de Config. Amos (suite)
par F. Lionet, P. 42
LANGAGE C
¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦
Le 3D se cache
par P. Amiable, p. 38 ASSEMBLEUR
Un animal doué de raison,
par Max, p. 51
Les Librairies Mathématiques
par D. Genot, P. 54 REQUESTER p. 58
EdîTo
Le courrier que nous recevons régulièrement nous indique que de plus en plus vous appréciez l'ANT. Voilà qui fait plaisir à toute l’équipe dont la devise est : “ne pas s’endormir sur ses lauriers et toujours s’efforcer d’améliorer le journal”.
Vous avez certainement remarqué que la rubrique Requester occupe désormais régulièrement 2 pages. Nous, nous avons remarqué que plus le Requester grandit et plus vous nous écrivez car vous êtes très avides de renseignements complémentaires. Comme il est impossible de répondre personnellement à tout le monde ni de passer toutes les questions dans la rubrique, nous choisissons celles qui se rapportent aux articles récemment parus et qui demandent des approfondissements. Mais soyez certains que nous lisons toutes vos lettres et que nous en tenons toujours compte.
A ce propos, nous introduisons petit à petit le langage C dans l’ANT. Nous aimerions savoir si vous appréciez ceci ou si vous avez des difficultés pour vous procurer et ou utiliser un compilateur, etc. De même nous aimerions savoir si par exemple vous souhaitez plus d’assembleur et moins de GFA ou l’inverse ou encore d’autres choses. Certes nous ne répondrons pas à ce type de lettres, mais nous en tiendrons compte car nous en avons besoin afin de construire l’ANT conformément à sa vocation : vous satisfaire.
Pour terminer, je voudrais tout particulièrement remercier les lecteurs qui nous envoient leurs programmes dans l’espoir de les voir publiés dans leur rubrique préférée. Certes, par manque de temps, nous n’en accusons pas toujours réception, et par manque de place nous en publions rarement. Mais rassurez-vous.Tout est soigneusement classé et nous sommes prêts à ressortir l’une de vos disquette à la première occasion. Alors encore une fois merci pour votre travail et votre confiance.
F. MAZUE
ERRATUM REQUESTER CR 26
Quelques coquilles se sont glissées dans le Requester de Commodore Revue n° 26, p. 56. En effet dans notre deuxième réponse il fallait lire :
« ... de copy c:AssignlCopylMakedirlEcho to RAM:C qui assure immanquablement la présence de Makedir dans RAM:C peut-être avez-vous tapé Copy C:Assign Copy Makedir Echo to RAM:C. »
APPLICATION C
Heureux de vous retrouver, je vous propose aujourd’hui de mettre un silencieux dans vos lecteurs de disquettes. Ce n’est pas plus bête que de vouloir mettre un tigre dans son moteur, c’est moins dangereux et c’esso si facile alors pourquoi à l’essence privée ?
MURMURES.....
Pourquoi aller s’en priver disais-je donc, or voilà que j’entends des murmures dans le fond de la classe ! Comment ? On veut nous donner un programme qui empêche de cliqueter les drives, alors qu’il existe un programme du domaine public nommé “noclick” qui remplit déjà cet office ! Seraient-ils à court d’idées chez Commodore Revue ?
HONNI SOIT QUI MAL Y PENSE !
Et le maulubec vous trousque ! Car il est intéressant de reconsidérer le problème et je m’en explique. Le programme “noclick” travaille de la manière suivante : il fait une recherche d’octets en ROM afin de localiser le trackdisk.device (pour que le programme puisse fonctionner selon les versions connues du kickstart). Ceci fait, le trackdisk.device en question est entièrement recopié en RAM, puis toutes les addresses de saut sont modifiées afin d’obtenir à nouveau un programme susceptible de fonctionner, puis ledit nouveau trackdisk est modifié afin que les drives ne cliquettent plus. Il suffit en fait de changer UN SEUL BIT pour obtenir ce résultat. Ils auraient quand même pu faire un effort chez Commodore !!! Enfin l’Amiga est astucieusement leurré afin que ce nouveau trackdisk.device soit utilisé. Bien. L’avantage de cette méthode est qu’aucune tâche n'est ajoutée donc l’Amiga n’est ralenti en rien. Par contre, il y a à mon avis quelques inconvénients :
- Occupation d’une grande quantité de RAM.
- Je n’aime pas ce genre de programmes qui utilisent directement des bouts de ROM sans passer par les librairies car il y a toujours le risque que Commodore modifie (et c’est son droit) légèrement l’organisation du kickstart sur une nouvelle série d’ordinateurs sans prévenir personne, et on se retrouve ainsi avec un programme qui ne marche plus ou pire : qui invoque le gourou au moment le plus inopportun.
- Enfin “noclick” comporte un bug. Bon j’avoue tout de suite que je suis allé le chercher loin celui-là, mais c’est dans ma nature de grand pourfendeur de bugs devant l'éternel.
En effet, sur un Amiga 500, en bootant sur disque dur A590, avec une disquette quelconque en DF1: et aucune disquette en DFO: et si “noclick” est placé en début du startup-sequence, il se passe la chose suivante : DF1: ne cliquettera effectivement plus si vous retirez la disquette mais DFO: lui, cliquettera Ad Vitam Eternam.
UNE AUTRE SOLUTION
Un lecteur de disquette ne cliquette que quand il est vide. Le cliquetis est généré par une routine d’interruption qui vérifie régulièrement si une disquette est insérée dans le lecteur, mais cette routine a le malheur de faire déplacer la tête du lecteur à chaque test, ce test s’effectuant à travers le trackdisk.device en ROM. Quand un lecteur contient une disquette il ne cliquette plus car la routine d’interruption considère à juste titre que le lecteur est occupé et ne fait plus son test (en fait je simplifie un peu). Ceci considéré, il faut savoir que AmigaDOS traite chaque lecteur de disquette en tant que processus à son plus haut niveau, sans se préoccuper le moins du monde de ce que fait le trackdisk.device. Pour
être plus précis, ce qui se passe quand un accès disque est nécessaire est qu’AmigaDOS envoie un message particulier appelé DosPacket à un processus DOS, par exemple DFO:. Lorsque le processus DFO: a reçu ce message, il s’occupe tout seul (vive les ordinateurs multi-tâches
I) de lancer le trackdisk.device et d’y écrire ou lire des données. Ce qui est intéressant c’est que ces fameux DosPacket permettent une quantité de commandes différentes dont une : ACTION_ INHIBIT qui lorsqu’elle est envoyée a pour effet “d’inhiber” le processus qui la reçoit. C’est-à-dire qu’il deviendra impossible d’accéder au processus par d’autres commandes DOS tant que dure cet état de fait.
Il faut maintenant s’intéresser au niveau le plus bas. La routine d’interruption dont nous avons parlé tout à l’heure accède au trackdisk, mais pas au lecteur de disquette directement. Ça c’est le trackdisk qui le fait en envoyant un message au port du lecteur de disquette et ceci uniquement si le flag de disponibilité du port-lecteur le permet. J’espère être suffisamment clair ! Maintenant que nous savons tout ça, voilà le plan suivi par le programme que je vous propose :
- On inhibe le processus correspondant.
- On force le flag de disponibilité et le lecteur ne cliquette plus.
Le programme ouvre ensuite une toute petite fenêtre dans un coin du workbench. Cliquer sur le gadget de fermeture de cette fenêtre provoquera l’effet inverse du précédent :
- On rétablit le flag de disponibilité.
- On “réveille” le processus précédemment inhibé et le lecteur revient à la vie. Cette solution comporte un léger inconvénient : ajouter des tâches à l’état waiting, ce qui ralentit légèrement l’Amiga. Je dis légèrement car il ne faut pas oublier que pour compenser, un processus est inhibé. De plus une tâche waiting ne ralentit que peu l'ordinateur. Des esprits chagrins m’objecteront également que “noclick” n’empêche pas l’accès aux drives contrairement à mon programme. A ceux-là je réponds que si l’on met une disquette dans le lecteur :
- Le drive ne cliquette pas.
- Que c’est pour travailler sur la disquette.
- L'utilisation de mon programme ou celle de “noclick” ne se justifie donc pas.
Par contre si le lecteur reste vide, c'est qu’on en a pas besoin et dans ce cas l’utilisation de busy (c’est comme ça que j’appelle mon programme) est justifiée. De plus si l’on change d’avis, il suffit d’insérer une disquette et de “réveiller” le processus. La disquette sera bien sûr reconnue comme il se doit.
Par contre il y a des avantages :
- Peu de mémoire occupée.
- Pas d’accès directs en ROM donc possibilité de fonctionnement avec tout kickstart passé, présent et à venir.
- Oserais-je le dire ? Pas de bug.
POURQUOI EN C ?
Le programme que je vous propose cette fois est écrit en C alors que je vous avais habitué jusqu’alors à des listings en assembleur. Ceci s’explique très simplement : je suis paresseux. En effet un tel programme est beaucoup plus facile (à mon avis en tout cas) à écrire en C plutôt qu’en assembleur.
Vous verrez par vous même très bientôt. Normalement un device est, pour ce qui est des offsets négatifs, structuré comme une librairie. Pour les offsets positifs du trackdisk.device, on trouve d’abord un mot nul afin de pointer sur une adresse multiple de 4, puis 4 longs mots. Ces 4 longs mots sont des pointeurs sur les ports des lecteurs de disquettes. Si un lecteur n’est pas connecté, le long mot correspondant est nul. Comme les autres aspects du trackdisk.device ne m'intéressent pas aujourd'hui, je me contente de construire une petite structure trackdisk à ma convenance comme ceci : struct trackdisk (
struct Library ddjibrary; USHORT trackdiskjxid; struct Unit *port [4];
Ainsi est défini un tableau de pointeur sur les port-lecteurs. Il suffira de tester si un élément du tableau est nul pour savoir que le lecteur correspondant n’est pas connecté. L’adresse de base du trackdisk.device est trouvée puis castée sur notre propre structure comme ceci :
if ((track=(struct trackdisk *)
FindName(&(SysBase->DeviceList),"trackdisk.device")) == NULL) CleanJMO; * si pas trouvé *
Je passe sur les parties du programme qui s’occupent des fenêtres ou des gadgets car ce n’est pas l’objet de cet article. Remarquez bien que le nom Unit choisi dans la structure n’est pas innocent. En effet, le terme générique de tout périphérique géré par un device est Unit. Cette structure est parfois étendue suivant le cas, mais pour ce que nous avons à faire, la structure minima Unit sera largement suffisante. Maintenant il s’agit de vérifier si le numéro du lecteur entré est correct, si le lecteur de ce numéro existe bien, si le processus correspondant n’a pas déjà été inhibé une fois. Il faut également prévoir que le programme peut être lancé avec tous les drives inhibés, auquel cas il faut pouvoir sortir. Ici ce sera par l’appui sur la touche X. Tout ceci est testé en une seule boucle do-while ! Que celui qui est capable d'écrire en assembleur une telle boucle de tests avec aussi peu de lignes se fasse connaître immédiatement au journal ! Ceci montre bien la puissance et l'efficacité du langage C. Et encore ! Il n’est pas impossible qu’un petit malin trouve le moyen de raccourcir encore le programme avec quelques astuces.
SOUFFLONS UN PEU...
Il faut absolument que je vous explique la situation. Vous, vous lirez probablement cet article début Octobre. Sachez que moi je l'écris début Août. Rappelez-vous, le mois de la canicule.
Alors voilà : il fait une chaleur épouvantable, l'alimentation de mon disque dur est chaude au point de pouvoir y faire cuire un œuf, je transpire à grosses gouttes et je meurs de soif. Je vais donc vous laisser un petit moment, juste le temps de laisser refroidir l’électronique, de prendre une douche froide et de boire un ENOOOORME verre de quelque chose de très frais. Pour vous faire patienter, voici une petite charade de mienne composition :
- Mon premier est un groupe de rock mondialement célèbre.
- Pour mon deuxième, Max a perdu sa souris (la souris de son Amiga bien sûr, qu’alliez-vous penser...).
- Mon tout est un proverbe connu.
LE GROS MORCEAU
Bien. Me voilà prêt pour attaquer la grosse difficulté de ce programme. Il s’agit de trouver le moyen d’envoyer un de ces fameux DosPacket à un processus.
Dans un petit livre trepelu (comme aurait dit mon bon maître Rabelais), la bible de l’amiga pour ne pas la nommer, il est fait mention de deux routines de la dos.library : GetPacket et QueuePacket qui permettraient de recevoir ou d’envoyer un DosPacket. Mais il y a de gros problèmes :
- La structure d'un DosPacket n’est pas donnée donc on ne sait pas ce qu’elle doit contenir II. C’est un tantinet gênant.
- GetPacket permettrait de recevoir un DosPacket. Moi je veux bien, mais comme dans notre cas le receveur du paquet est un processus AmigaDOS, je vois mal comment utiliser cette routine. En se déguisant en lecteur de disquettes peut-être.
- QueuePacket permettrait d’envoyer un DosPacket mais on ne sait pas à quel processus !
Dans le genre renseignements inutilisables, j’ai rarement vu mieux ! Si mon bon maître Rabelais avait vu ça, il aurait encore dit que : “cil qui oncques ne peult, rien entreprendre ne doibt. “Il faut donc se débrouiller autrement. En fouinant dans les fichiers include d’un compilateur C ou dans l’Amiga Rom KernelManual “includes et autodocs’’, on trouve les structures suivantes :
struct DosPacket I
struct Message *dp_Link; struct MsgPort *dp_Port;
LONGdp_Type;
LONGdp Resl;
LONGdp_Res2;
define dp_Action dp_Type define dp_Status dp_Resl define dp_Status2 dp_Argl LONGdp Argl;
LONGdp_Arg2;
LONGdp_Arg3;
LONGdp_Arg4;
LONGdp_Arg5;
LONGdp_Arg6;
LONGdp_Arg7;
Je ne saurais encore dire à quoi servent les dp_Arg2 jusqu’à dp_Arg7, mais par contre dp_Arg1 est un flag qui a l’effet suivant :
- dp_Argl = -1 le DosPacket est pris en compte par le processus
- dp_argl = 0 l’effet du DosPacket est annulé.
On trouve ensuite dans les fichiers includes une autre structure :
struct StandardPacket (
struct Message sp_Msg; struct DosPacket sp_Pkt;
1;
Voilà qui va nous permettre de réfléchir sainement : finalement nous voulons à partir de notre programme envoyer un DosPacket à un autre programme, mais nous ne savons pas comment faire. Par contre, ce que nous savons faire c’est envoyer un message à un autre programme grâce aux routines PutMsgO et consorts de exec.library. Ce n’est donc pas pour rien que les structures que nous venons de découvrir contiennent des structures Message, et c’est ce procédé qu’il va falloir utiliser. Je suis vraiment désolé, mais pour être en état de vous expliquer à peu près clairement la suite, il faut absolument que j’aille à nouveau prendre une douche froide et que je me serve un autre ENOOOORME quelque chose de très frais. Voici une autre petite charade de mienne composition pour vous faire patienter en attendant que je revienne :
- Mon premier n’aime pas l’ail.
- Mon deuxième est fonctionnaire des PTT.
- Mon troisième rit de très méchante humeur.
- Mon quatrième n’est pas une flèche.
- Mon tout est un célèbre poète et écrivain français.
DISKJ3USY
Nous allons maintenant expliquer en détail la fonction Disk_Busydu programme. C’est elle qui permet d’inhiber un processus.
Tsk=(struct Process *)FindTask(NULL);
Ceci permet à notre programme de trouver l’adresse de sa propre structure Task qui est immédiatement castée en structure Process. Nous avons le droit de faire ça. Il faut en effet savoir que tout programme lancé depuis le CLI ou le Workbench n’est pas une’Task”, mais un “Process”. Une Task est en fait très limitée, elle n’a pas le droit d'accéder à une fonction de la dos.library. Un Process n’est rien d’autre qu’une structure Task très étendue qui comporte (et ça c’est très important) d'office un port message. Pour plus de renseignements, vous pouvez consulter les fichiers include. Ensuite de la mémoire est réservée pour une structure StandardPacket, puis : pk->sp_Msg.mn_Node.ln_Name=(UBYTE *)&(pk->sp_Pkt);
Euh pas évidente cette ligne. Elle a pour fonction de placer l’adresse du DosPacket dans le nom du noeud du message du StandardPacket (NDLR : Oh que c’est lourd I). Ceci est nécessaire afin qu’exec.library puisse retrouver à quoi correspond le message qu’on va lui demander de transmettre. Le cast (UBYTE *) est indispensable car d’habitude en ln_Name on a un pointeur sur une chaîne de caractères : pk->sp_Pkt.dp_Link=&(pk->Msg);
Ainsi dp_Link qui doit être un pointeur sur une structure message est initialisé sur l’adresse de la structure Message du StandardPacket. Les 2 structures DosPacket et Standard Packet sont maintenant intimement liées (comme l'indique le nom dpJJnk) :
pk->sp_Pkt.dp_Port=&(tsk->pr_MsgPort);
Ainsi dp_Port qui doit être un pointeur sur la structure Port qui va envoyer le message est initialisé sur l’adresse du Port Message de notre programme. Je me permet de vous rappeler que ce Port existe et qu'il n’est pas besoin de le créer puisque notre programme dépend d’une structure Process. Je passe les 2 lignes suivantes qui parlent d’elles- mêmes. Ensuite nous avons :
* un caractère de plus pour le 0 final V
PutMsg(DeviceProc(unite),(struct Message *)pk);
Comment cela peut-il marcher ? Je pose cette question car d’après la bible de l’amiga la fonction DeviceProc renvoie le canal I O utilisé par le processus. Ceci m’a autrefois valu quelques gourous car bien entendu ce renseignement est encore faux !!! Si vous consultez le fichier include “libraires dosextens.h" vous verrez que DeviceProc renvoie en fait un pointeur sur le Port Message du processus recherché, ce qui change tout et qui explique que la ligne de programme envoie bien un message StandardPacket sur le Port Message du Processus correspondant au lecteur de disquette.
Le reste ne mérite pas de grosses explications : on attend le message de retour (WaitPort), puis on le retire (GetMsg), on libère ma mémoire et c’est tout. J’espère avoir été suffisamment clair sur une chose qui n’était pas vraiment évidente au premier abord. Il me reste à vous dire que le programme est conçu pour être lancé du workbench en cliquant sur une icône de type tools (à vous de vous fabriquer votre icône). Si vous tenez absolument à lancer ce programme sous CLI vous pouvez le faire, mais par l’intermédiaire de la commande run. Si vous avez eu le courage de me lire jusqu’ici, alors vous méritez bien une récompense. Voici donc la solution des charades.
- Pierre qui roule n’amasse pas mousse. (Rolling Stones, n’a Max pas mouse)
- Victor Hugo explication :
Mon premier est vie car vie tue ail.
Mon deuxième est tor car tor est facteur.
Mon troisième est u car u rit noir.
Mon quatrième est go car go est lent.
En attendant de se retrouver sous des cieux moins eschauffants, esca- lordants, estourbissants et assomants, gaudissez tant que plaira et beuvez frais si faire se peult.
F. MAZUE
aime pantagrueliser.
Définition du gadget
struct Gadget MyGadget =
NULL,
r pas d'autre gadget *
95,28,
* position dans la fenêtre 7
20,10,
' largeur et hauteur *
GADGHCOMP,
* flags *
* GADGCOMP donne un "curseur" *
RELVERIFY,
* activation *
STRGADGET,
* gadget type 7
NULL,
NULL,
NULL,
* pas de texte associé *
NULL,
(APTR)&MyStringInfo,
* pointeur sur stringinfo pour
stringgadget *
0,
* rien *
NULL
* pas de data personnel 7
Programme : Busy.c
Fonction : sélectionner un drive et l'empêcher de cliqueter à vide
Ce programme a été écrit sur Lattice C 5.04 (the best) Compiler et linker par : le -L busy
Définition de la fenêtre à ouvrir pour la demande de choix du drive
include exec types.h> ffinclude exec execbase.h> ffinclude exec memory.h> ffinclude exec devices.h> ffinclude libraries dosextens.h> ffinclude intuition intuition.h> ffinclude intuition screens.h> ffinclude string.h> ffifdef LATTICE ffinclude proto exec.h> ffinclude proto dos.h> ffinclude proto graphics.h> ffinclude proto intuition.h> ffendif
extern strud ExecBase ‘SysBase; struct IntuitionBase 'IntuiüonBase = NULL; struct GfxBase ‘GfxBase = NULL;
struct NewWindow Demande =
I
100,100,
200. 50,
1,3,
GADGETUP,
ACWATEIGIMMEZEROZERO,
&MyGadget,
NULL,
“BUSY 1.0 F MAZUE",
NULL,
NULL,
200. 50,
200. 50,
WBENCHSCREEN
r position *
* dimensions 7 * fond et crayon *
* flags evenement *
* flag *
* pointeur sur gadget 7 * pas d'image par défaut 7 A titre *
‘écran courant* r pas de bitmap particulière 7 r dimensions mini 7 * dimensions maxi *
* dans l’écran du workbench *
FI
mm
UMBOS®
jHHGüD HBBH
Définition de la fenêtre dont la fermeture permettra de remettre le drive dans son état initial
if (BufferfOl =='x I BufferfO] ==T) (
CloseWindow(MyWindow);
Clean_Exit();
str_num[l] = BufferfOl; numéro = atoi(str_num);
struct NewWindow Libéré =
1
560,0,
80,10,
0,1,
CLOSEWINDOWi
WINDOWCLOSEIWINDOWDRAG, NULL,
NULL,
NULL,
NULL,
NULL,
0,0,
80,10
WBENCHSCREEN
)while((BuffeifO] > '3') I (BufferfO] '01
I (!track->port[numerol)
I (track->port[numero]->unit_flags == UN1TF_ACTIVE)); CloseWindow(MyWindow);
¦
Maintenant que le drive est sélectionné, on lui coupe le sifflet ! Et toc !
Structure trackdisk.device "maison" avec un tableau de pointeurs sur les structures de port-lecteur
struct trackdisk
struct Library dd_library; USHORT trackdiskjxrd; struct Unit *port[4];
char *demande[] =
“numéro du drive",
"à anesthésier (0-3)",
1;
char lecteur[5] = "DFx:“;
VOID Clean_Exit(void);
VOID Disk_Busy(UBYTE 'unité, long flag);
VOD_main()
1
struct Window 'MyWindow; struct Window *Libere_Lecteur; struct trackdisk ‘track;
char str_num[2];
int numéro;
if (!(GfxBase=
(struct GfxBase *)OpenLibrary("graphics.library",0)))
Clean_Exit();
if (KlntuitionBase =
(struct IntuitionBase *)OpenLibrary("intuition.library”,0)))
Clean_Exit();
if ((track=
(struct trackdisk *)FindName(&(SysBase->DeviceList),"trackdisk.device")) ¦ NULL)
Clean_Exit();
if ((MyWindow = (struct Window *)OpenWindow(&Demande)) == NULL) Clean_Exit();
Move(MyWindow->RPort, 10,10); Text(MyWindow->RPort,demande[01,strlen(demande[0]));
Move(MyWindow->FÏPort, 10,20);
Text(MyWindow->FtPort,demande! 1 ],strlen(demandel 1 ]));
Voilà maintenant une boucle d'attente telle que le C permet aux paresseux (comme moi) d'en écrire
strcpy(str_num,"+4");
ActivateGadget(&MyGadget,MyWindow,0); Wait( IL « MyWindow->UserPort->mp_SigBit);
lecteur[2] = BufferfO]; * complète le nom du drive *
Libere.TopEdge = 150 + 15'numero;
Libere.Trtle , = lecteur;
Disk_Busy(lecteur,TRUE);
if ((Libere_Lecteur =(struct Window *)OpenWindow(&Libere» == NULL) Clean_Exit();
Disk_Busy(lecteur,TRUE);
Delcty(200);
track->port[numero]->urrit_flags = UNITF_ACTIVE;
WaitdL « Libere_Lecteur->UserPort->mp_SigBit); track->port[numero]->unit_flags = UN1TF_1NTASK;
Disk_Busy(lecteur,FALSE);
CloseWindow(Libere_Lecteur);
Clean_Exit();
Fonction pour rendre la main proprement
VOID Clean_Exit()
if (GfxBase) CloseLibrary(GfxBase);
if (IntuitionBase) CloseLibrary(IntuitionBase);
exit(0);
Fonction pour annihiler un processus DOS
VOID Disk_Busy(UBYTE 'unité,long flag)
1
struct StandardPacket 'pk;
struct Process 'tsk;
tsk = (struct Process ')FindTask(NULL); if (pk=(struct StandardPacket *)
AllocMem(sizeof(struct StandardPacket),MEMF_PUBLIC!MEMF_CLEAR)) I
pk->sp_Msg.mn_Node.ln_Name=(UBYTE')&(pk->sp_Pkt); pk->sp_Pkt.dp_Link =&(pk->sp_Msg); pk->sp_Pkt.dp_Port=&(tsk->pr_MsgPort); pk->sp_Pkt.dp_Type=ACnON_INHBlT; pk->sp_Pkt.dp_Argl=(flag ? -IL ; 0L);
PutMsg(DeviceProc(unite),(struct Message *)pk);
WaitPort (&(tsk->pr_MsgPort));
GetMsg (&(tsk->pr_MsgPort));
FreeMemtpk, (long)sizeof('pk));
FI
La plupart des applications en infographie nécessitent l’affichage d’objets tridimensionnels avec un degré de réalisme assez élevé. Jusqu'à maintenant nous avons réussi à afficher l’objet sous la forme d’un squelette filaire. Cette représentation, comme vous l’avez sans doute remarqué, devient vite ambiguë dès que l’objet est complexe et autorise le plus souvent, plusieurs interprétations possibles de la même entité (Fig. 1). Pour remédier à ce problème nous allons essayer de donner à ces objets filiformes une notion d'opacité des faces afin de les considérer comme des volumes à part entière. Pour ce faire on utilise la méthode d'élimination des parties cachées.
REPRESENTATION INTERNE D’UN VOLUME
6 nbr de face 0 2 1 -Face 1 0 3 2 -Face 2 0 4 2 -Face 3 0 1 4 -Face 4 4 3 2 -Face 5 4 2 1 -Face 6
QUE NOUS MANQUE-T-IL DESORMAIS ?
Les coefficients des plans associés aux faces bien sûr, et ils se calculent. Voici les formules :
a = YA'(ZB-ZC) - YB’(ZA-ZC) + YC*(ZA-ZB) b = -(XA*(ZB-ZC) - XB*(ZA-ZC) + XC*(ZA-ZB)) c = XA*(YB-YC) - XB*(YA-YC) + XC‘(YA-YB) h = XA*(YB*ZC-YC*ZB) - XB*(YA*ZC-YC*ZA) + XC*(YA’ZB-YB*ZA)
ELIMINATION DES CONTOURS CACHES
C’est là que les choses sérieuses commencent. Nous allons développer un algorithme qui ne trace que la partie visible d’un segment de droite dénommé PQ. Cet algorithme consiste à déterminer pour chaque facette triangulaire ABC si celle-ci cache entièrement PQ ou seulement une partie de ce segment. Nous connaissons les coordonnées des 5 sommets A,B,C,P,Q, les coefficients de l’équation du plan a,b,c,h et le point d’observation E. Considérons la pyramide infinie de sommet E et passant par les côtés AB, BC et CA (Fig.5). Tout point de PQ situé dans la pyramide et derrière ABC est caché les autres sont visibles. Dans la figure 5 PQ coupe la pyramide en I et J on voit bien que le tronçon IJ est invisible.
Pour représenter un volume composé de faces opaques, la modélisation à base de tableaux, de points et de lignes ne suffit plus, il faut également modéliser les faces. Une face d’un objet est une région plane et finie limitée par des segments de droite (ex : un polygone). Comme le but de cet article est de vous proposer un exemple simple de fonction d’élimination de parties cachées, nous allons apporter une contrainte supplémentaire à ces faces, elles seront triangulaires (Fig. 2). Cela signifie que tout objet devra être décomposé en facettes triangulaires. Une facette triangulaire sera définie dans un premier temps par la liste de ces sommets.
On part d’un sommet arbitraire et on passe au suivant dans le sens trigo- nométrique (anti-horaire) et ainsi de suite pour les trois sommets. Pour la pyramide de la figure 2 on obtient la liste des faces suivantes.
De plus, la connaissance du plan associé à chaque face est nécessaire pour l’élimination de parties cachées, il faudra stocker les coefficients du plan pour chaque face.
Un plan est défini par l’équation ax+by+cz = h.
Nous allons donc stocker en plus des numéros des sommets, A, B, C, les coefficients a, b, c,h du plan (Fig. 3).
Ce genre de tableau hétérogène -3 entiers (short) et 4 coefficients (float)- se représente très facilement en C à l’aide d’un tableau de structure.
Struct short A,B,C; float a,b,c,h;
jFace [100] *pour 100 faces*
Pour l’élimination des parties cachées nous avons besoin des coordonnées Xs, Ys, et Zs des différents sommets après changement de repère par rapport à un observateur E ou R représente la distance entre l’observateur et l’origine de la scène alpha et teta les angles suivant X et Y entre la direction de vision et l'axe Z du repère absolu (Fig.4).
Xs = -X*sin(alpha) + Y'cos(alpha)
Ys = X‘sin(teta)‘cos(alpha) + Y*sin(teta)*sin(alpha) +Z*cos(teta)
Zs = -X*cos(teta)*cos(alpha) - Y*cos(teta)*sin(alpha) +Z*sin(teta) +R
tapi® ©.
Pour tester cette invisibilité potentielle une série de tests est nécessaire. Test 1 :
Si les deux Points P et Q sont positionnés devant ou dans le plan ABC alors PQ est visible entièrement. Ceci n’a lieu que si :
lai IXPI lal IXQI
Ibl . IYPI = h Ibl . IYQI = h
Ici IZPI Ici IZQI
soit axp+byp+czp h et axq+byq+czq h
Test 2 :
Si la droite PQ se trouve à l’extérieur de la pyramide alors PQ est apparent. Comment faire ?
Soit le plan EPQ d’équation dx+ey+fz= g
d = YP.ZQ - YQ.ZP e = ZP.XQ-ZQ.XP f = XP.YQ - XQ.YP
on remplace (x,y,z) dans l’équation du plan par les coordonnées de A, B et C
ga = dxa+eya+fza, gb = dxb+eyb+fzb, gc = dxc+eyc+fzc
si ga, gb et gc sont de même signe PQ est à l’extérieur de la pyramide.
Note : il se peut que l'un des trois coefficients soit nul (PQ passant par
un des points A,B,C).
Pour résoudre ce cas particulier on modifie le test supplémentaire.
Pour chaque point A,B,C (
si g 0 alors somme = somme -1 si g>0 alors somme = somme + 1 )
si valeur absolue (somme) >2 PQ est extérieur.
Test 3 :
Dans le cas où PQ n’est pas extérieur à la pyramide, il faut déterminer s’il est entièrement contenu dans la pyramide ou non. Pour ce faire, il faut déterminer l’intersection (lorsqu’elle existe) de PQ avec les plans EAB, EBC et EAC. Prenons le cas EAB (c’est pareil pour les autres plans) : soit A1x+A2y+A3z = 0 l'équation ramenée à 0 du plan EAB
(A1*XP + A2‘XP A3*ZP)
lambda = -
A1 *(XQ-XP) + A2*(YQ-YP) + A3*(ZQ-ZP)
A1 = YA*ZB - YB*ZA A2 = XB*ZA - XA*ZB A3 = XA*YB - XB*YA
soit B1x+B2y+B3z = 0 l’équation ramenée à 0 du plan EPQ
B1 *XA+B2*YA+B3*ZA-
mu = - -
B1*(XB-XA) + B2*(YB-YA) + B3*(ZB-ZA)
B1 = YP'ZQ - YQ*ZP B2 = XQ'ZP - XP*ZQ B3 = XP*YQ - XQ’YP
PQ et EAB possède un point commun si 0 = lambda = 1 et 0 =mu = 1
On effectue le même test pour EBC et EAC on obtient donc 3 lambda et 3 mu on recherchera également les Lamdamin et Lambdamax (NDLR : qu'est-ce qu'il a Max ?) Qui satisfont au test ci-dessus.
Test 4 :
Si aucun des deux points P et Q n'est à l’extérieur de la pyramide (et que les trois premiers tests ont échoués) alors PQ est entièrement caché par la Face.
Test 5 :
Si un point 1 intersection de PQ avec la pyramide se trouve devant ABC alors PQ est apparent.
Soit les coefficients :
R1 = XQ -XP R2 = YQ -YP R3 = ZQ -ZP
Xmin = XP+Lambdamin*R1 Ymin = YP+Lambdamin*R2 Zmin = ZP + Lambdamin*R3
Si (a*Xmin+b*Ymin+c*Zmin h) alors PQ visible
Xmax = XP+Lambdamax*R1 Ymax = YP+Lambdamax*R2 Zmax = ZP + Lambdamax*R3
Si (a*Xmax+b*Yrtiax+c*Zmax h) alors PQ visible Test 6 :
à ne réaliser que si PQ coupe la pyramide derrière le triangle. C'est-à-dire
si le test 5 a échoué; cas où
l=J.
Si P est hors de la pyramide alors PI est apparent
Si Q est hors de la pyramide alors JQ est apparent
Une fois ces tests réalisés, on trace ou non PQ, PI, JQ et le tour est joué. On fait cela pour chaque segment et chaque face et l’élimination des parties cachées est réalisée.
Cet article représente donc une approche algorithmique permettant de résoudre le problème de l’élimination des parties cachées. Il existe bien d’autres méthodes pour éliminer les faces cachées (méthode du Z-buffer, algorithme de Warnock etc...) celle-ci ayant le mérite d’être assez simple à programmer. Je vous laisse donc un mois pour essayer d'écrire le programme correspondant à cet algorithme, je vous donnerai une solution possible le mois prochain. Egalement en novembre, un programme de génération automatique d’objets et un concours sur le thème “le 3D EN C”. Affûtez vos compilateurs et à bientôt.
Herr Doktor Von GlutenStimmelimDorf
se cache jusqu’au prochain article.
Nous avons commencé le mois dernier à mettre au point un mini-utilitaire de disquettes, permettant diverses opérations sur les fichiers et sur les secteurs du disk. Ce mois-ci, nous abordons les premières fonctions dédiées aux fichiers.
APPLICATION
GFA-Dmon, PART II
Avant toute chose, il semble important de rappeler que GFA-Dmon- puisque tel est son nom - n'a, et de loin, pas la prétention d’égaler un programme comme DiskMaster ou DiskCraft. Simplement, il sert d’exemple pour la programmation en GfA-Basic d’une part, et celle d’AmigaDOS depuis ce langage d’autre part. Un emploi modeste certes, mais utile tout de même.
Dans ce qui va suivre, nous allons développer trois procédures de type “primaire”, c’est-à-dire pas bien compliquées. Elles portent les doux noms de FileView, FileErase et FileRename. Vous noterez que bien que GfA-Basic dispose des instructions KILL et NAME AS, nous avons préféré, encore une fois pour des raisons d’illustration, appeler directement AmigaDOS via les fonctions DeleteFileO et RenameO de la dos.library. Cela complique un tout petit peu les choses, puisque les noms des fichiers sont passés sous forme de pointeurs plutôt que directement de chaînes de caractères, mais GfA-Basic met à notre disposition la fonction V: qui renvoie l’adresse d’une variable alphanumérique. Exactement ce qu’il nous faut.
FILEVIEW
Cette procédure affiche à l’écran le contenu d'un fichier, de préférence texte ascii, mais un fichier binaire peut également être visualisé de cette manière. Ici de même, nous avons préféré utiliser OpenO de la dos.library plutôt que OPEN du GfA (la nuance est subtile...) ainsi que Read() et CloseO en lieu et place de INPUT et CLOSE, respectivement. Les choses sont de fait légèrement plus compliquées, ReadO exigeant de savoir combien de caractères elle doit extraire du fichier. Pour nous simplifier toutefois un peu la vie, nous avons limité ce nombre à 1 et construisons une chaîne l$ qui sera affichée à l’écran dès que sa longueur aura atteint 80 caractères (largeur maximale de l’écran) OU que l’on aura lu un Line-Feed (ASCII10). On passe alors à la ligne suivante, et, toutes les 20 lignes affichées, on demande à l'utilisateur s’il désire poursuivre la visualisation ou bien s’il préfère arrêter là. Dans le second cas, la boucle WHILE... WEND se termine, sinon elle continue jusqu’à ce que ReadO ait renvoyé le code 0, signifiant que la fin du fichier a été atteinte.
PROCEDURE fileview LOCAL p&,f %, n %, l% ,f$ , buf$ , l$ , a$ selectfile(“Fichier à visionner ?”)
IF LEN(fichier$ ) f$ =fichier$ +CHR$ (0) f%=Open(V:f$ , 1005)
IF f%
buf$ =SPACE$ (4)
n%=-1
p&=1
WHILE a$ >CHR$ (27) AND n% >0
CLEARW 1
l%=1
PRINT AT(1,2);fichier$ +” -> page “;p&
PRINT
REPEAT
l$ =””
REPEAT
n%=Read(f%,V:buf$ , 1 ) l$ =l$ +LEFT$ (buf$ )
UNTIL n%=0 OR ASC(buf$ )=10 OR LEN(I$ )=80 PRINT l$ ;
INC l%
UNTIL n%=0 OR l%=20 PRINT
PRINT “*** Enter> : page suivante, ESC> arrête...” a$ =@getkey$
INC p&
WEND
~Close(f%)
ENDIF ENDIF CLEARW 1 RETURN
FILERENAME
Cette procédure sert à donner un nouveau nom à un fichier existant sur la disquette. L’instruction GfA FILESELECT est utilisée pour entrer à la fois l’ancien nom du fichier ET le nouveau, nous évitant ainsi l’écriture de routines de gestions des gadgets d’intuition, totalement hors de propos ici. Ensuite, et de même que dans la procédure précédente, on appelle la dos.library - fonction Rename() - avec comme paramètres les pointeurs sur les deux noms de fichiers, obtenus par la fonction V:. Si tout se passe bien, la variable status% contient la valeur -1, sinon elle contient un code d’erreur que nous affichons dans une ALERT, après avoir pris soin de ramener notre écran devant les autres grâce à la fonction de l’intuition.library ScreenToFrontO, ceci au cas où un Requester système serait apparu lors de l’exécution de Rename() (“Pleaseinsert volume XXXX in any drive”, etc.).
PROCEDURE filerename LOCAL r%,temp$ ,f1 $ ,f2$ ,status% selectfile(“Ancien nom ?”)
IF LEN(fichier$ ) temp$ =fichier$ selectfilef’Nouveau nom ?”)
IF LEN(fichierS)
ALERT 1 ,”Renommerl”+temp$ +”lenl”+fichier$ ,1 ,”OuilNon”,r%
IF r%=1
f1$ =temp$ +CHR$ (0) f2$ =fichier$ +CHR$ (0) status%=Rename(V:f1 $ ,V:f2$ )
IF status% >-1 ~ScreenToFront(SCREEN(1 ))
ALERT 1,"Erreur dans RENAME :I”+STR$ (status%), 1,"Oups”,r% ENDIF ENDIF ENDIF ENDIF RETURN
H
INFORMATIQUE
m
FILEERASE
La dernière procédure pour ce mois-ci propose d’effacer un fichier du disque, par le biais de la fonction DeleteFileO de la dos.library. Là encore, on aurait très bien pu utiliser l'instruction KILL du GfA-Basic, mais bon... Tout comme dans FILERENAME, la variable status% contient le résultat de l’opération : -1 si tout va bien, un code d’erreur dans le cas contraire, code d’erreur qui est affiché dans une ALERT.
PROCEDURE fileerase LOCAL r%,status%,f$ selectfileC’Fichier à supprimer ?")
DEMONSTRATION PERMANENTE ET SUR RENDEZ VOUS INSTALLATION RAPIDE FORMATION EFFICACE MAINTENANCE ASSUREE ASCII : 10 rue de Lépante. 06000 NICE
C 93.13.08.66. Fax 93.13 90.95 Serveur minitel direct 93.13.90.96
IF LEN(fichier$ )
ALERT 1, “Supprimerl "+fichier$ , 1, "OuilNon” ,r%
IF r%=l
I$ =lichier$ +CHR$ (0)
status%=DeleteFile(V:f$ )
IF status%o-l ~ScreenToFront(SCREEN( 1 ))
ALERT 1,“Erreur dans DELETE :l"+STR$ (status%),l,“Oups",r%
ENDIF
NOUVEAUTES
ENDIF
ENDIF
RETURN
Insérez donc ces trois petits listings dans le programme principal donné le mois dernier.
SEE YOU SOON
Voilà, on s’arrêtera là pour aujourd’hui. Ces trois procédures ne sont certes pas bien compliquées, mais j’espère qu’elles vous auront suffisamment mis l’eau à la bouche pour nous retrouver le mois prochain, où nous développerons l’édition hexadécimale ASCII d’un fichier et commencerons l’étude des fonctions de catalogue. D’ici là, bon courage...
Etienne Mouratila
LE MINI SERVEUR
Restez en contact avec votre micro ordinateur par le biais du minitel. Mono voie sur Amiga
1990F
PRIX :
Soft + cordon
LE PROTEGE CLAVIER
En plastique thermo formé souple il protégera votre clavier contre toute
agression extérieure (café, miettes de gateau, champagne, etc ...) et cela tout en autorisant la frappe. Disponible pour tout type de clavier
(Amiga, Atari, IBM, MAC)
LES 100 DISQUETTES VIERGES
499F
LE CACHE TRANSPARENT SURMOULE POUR A500
160F
LE LECTEUR EXTERNE 3 POUCES ET DEMI
850F
L’EXTENSION MEMOIRE 1 MEGA POUR A500
140F
PRIX
590F
Sont disponibles tous les produits CIS, BUS h ... ETC ...
PRIX
LE COMMANDEUR
Pour tous ceux qui rêvent de piloter leur cafetière, l'arrosage de leur jardin ou l'alarme de leur villa à partir de leur Amiga, PC ou Atari. Existe en version A(8 sorties) et B(4 entrées+ 4 sorties) : PRECISER A LA COMMANDE.
2490F
NOM : ...,w......7 ......Prénom : ...
Profession : ...Machine : .
Adresse : Tel : ....
COMMANDE :
Article
Quant
Prix unitaire
Total
Documentation
?
?
?
TOTAL
» 20F DE PARTICIPATION
Ci-joint mon règlement par : Qchèque Ocarte bleue. Signature N" carte bleue : ...
CONFIGURATION
UTILISATION DE CONFIG.AMOS, (suite)
Bienvenue dans la deuxième cession de la rubrique AMOS, et un grand merci : des milliers (millions ?) De lettres sont arrivées à la rédaction, réclamant plus de place pour nous. Résultat, un gain d'une page, 100 % de croissance mensuelle. Si je calcule bien, dans 6 mois nous en serons à 256 pages. Merci Commodore Revue !
Je n’avais pu finir de commenter les points principaux du programme de configuration dans l'article précédent.
- Menu “Set”, Option “Help accessory”
Cette option importante - et mal documentée - permet de changer le nom du programme appelé lors d’une pression sur la touche HELP.
Le premier nom est le nom du programme à charger de la disquette. Vous pouvez bien entendu spécifier un autre disque ou répertoire.
Le deuxième nom est le nom du programme APPELE dans la mémoire. En général, il est le même que précédemment (sans le cheminement dans les répertoires bien sûr).
Vous pouvez ainsi avoir un accès direct à un autre programme que HELPACC, par exemple Sprite_Editor.AMOS, ou une calculatrice...
Plus intéressant, vous pouvez ANNULER l'effet de la touche HELP en effaçant les deux noms. C’est une option bienvenue pour les maladroits comme moi !
- Menu “Set”, Option “Drives and Ports”
La liste affichée correspond aux lecteurs de disques qu'AMOS reconnaît lorsqu’ils sont branchés à la machine. Si vous possédez un lecteur exotique ne figurant pas dans cette liste, insérez-le et il sera affiché dans le sélecteur de fichier.
Le dernier nom de la liste correspond au port ouvert lors de l’utilisation de LPRINT. Le port parallèle direct (PAR:) est sélectionné par défaut, car il consomme beaucoup moins de mémoire (4 Ko) et suffit pour la majorité des imprimantes. En inscrivant PRT: à sa place, vous pourrez faire fonctionner une imprimante série (en prenant soin de changer les préférences sous WorkBench).
- Menu “Edit”
Tous les messages que proposent ce menu peuvent être effacés et remplacés par des chaînes vides, si vous êtes vraiment à cours de mémoire. N’oubliez pas de garder une copie de votre ancienne configuration !
LA VERSION 1.2
La version 1.2 est disponible au moment même où vous me lisez, sous la forme d’un programme domaine public qui modifie votre disquette AMOS. Outre la correction de certains bugs, cette version apporte de nouvelles instructions et améliorations :
- Un meilleur multi-tâches. La boucle de l’éditeur et du mode direct ont été améliorés pour permettre une meilleure utilisation multi-tâches AMOS ne prend plus tout le temps machine aux autres programmes.
En mode programme, vous devrez parsemer votre programme de l’instruction :
Multi Wait... qui rend la main aux autres programmes, pendant approximativement un balayage d'écran. Attention, cette instruction est d’autant plus imprécise que le nombre de tâches est élevé. Préférez Wait Vbl pour synchroniser votre programme.
Multi Wait est l’idéal pour attendre une option de menu, ou la pression d'une touche.
- Le retourneur de sprites
Il s’agit d’une des principales techniques pour réduire la place mémoire occupée par un programme.
Dans un jeu, les graphismes occupent la majeure partie de la mémoire (avec la musique). Plus un jeu est complexe, plus il faudra de sprites, et donc de mémoire. En général, le personnage principal peut se diriger dans toutes les directions : gauche-droite pour un jeu à scrolling latéral, haut-bas (en général) pour un shoot’em-up, et même dans tous les sens. Le personnage principal, est aussi le mieux animé.
Tout ceci fait que la banque de sprite d’un jeu est principalement constituée des phases d’animation du personnage principal dans une direction, puis dans une autre, par simple symétrie des sprites.
Les nouvelles instructions de l'AMOS, permettent une symétrie AUTOMATIQUE des sprites. Il suffit de ne conserver qu’une seule direction dans la banque çle sprites.
Le gros problème lors de la programmation de ces nouvelles fonctions, était de conserver la compatibilité avec la version 1.1. J’ai donc dû ruser : tout se fait par l’intermédiaire du numéro de l'image à afficher. Exemple : imaginons que l’image 1 dans la banque de sprites représente un vaisseau spatial dirigé vers le HAUT-DROITE.
BOB 1,160,100,1 affichera le vaisseau à droite
BOB 1,160,100,$ 8001 fera une symétrie passant par l’axe vertical. Le
vaisseau sera pointé en HAUT à GAUCHE
BOB 1,160,100,$ 4001 fera une symétrie par rapport à l’axe horizontal. Le vaisseau sera pointé en BAS à DROITE
BOB 1,160,100,$ C001 effectuera les deux symétries précédentes. Le vaisseau pointera en BAS à GAUCHE
Vous avez compris que pour indiquer au générateur de bobs le retournement d’une image, il faut se servir des bits 15 et 14 du numéro de l’image.
Bit 15 : symétrie verticale Bit 14 : symétrie horizontale Pour ceux que l’hexadécimal rebute, j’ai rajouté trois nouvelles instructions :
=HREV(image) : symétrie horizontale =VREV(image) : symétrie verticale =REV(image) : double symétrie
... ces fonctions effectuent une simple addition de respectivement $ 8000, $ 4000 et $ C000 au numéro de l’image.
- Fonctionnement du retourneur de sprites
Le programme travaille DIRECTEMENT dans la banque de sprites, au moment même de l’affichage.
La fonction SPRITE BASE (image) ramène une adresse pointant sur la définition d’une image dans la banque de sprites.
SPRITE BASE: +0 (Mot) (Taille image en X) 16
+2 (Mot) (Taille image en Y)
+4 (Mot) Nombre de plans mémoire
+6 (Mot) Position du point chaud en X
+8 (Mot) Position du point chaud en Y
+10 Premier plan image
+??? Deuxième plan image
+??? Dernier plan image
Vous pouvez ainsi connaître la taille d’une image avec deek :
A=Sprite Base(1)
Print “Taille en X:”;Deek(A)*16 Print “Taille en Y:”;Deek(A+2)
J’ai utilisé le sixième mot de cette définition pour stocker les drapeaux indiquant le retournement de l’image. Le BIT 15 de la position du point chaud en X indique que l'image est actuellement retournée en X dans la banque ; le BIT 14a la même fonction en Y.
Ml®!
Imaginons que vous utilisiez l’instruction :
BOB 1,100,100, HREV(5)
Au retour de balayage suivant, AMOS inspecte la liste des bobs à afficher. Il trouve l'image $ 8005. Il regarde le bit 15 de l’adresse 6 dans la définition de l’image. L’image est dans son état originel, le bit est à zéro. AMOS appelle donc la routine de retournement en X, et POSITIONNE LE BIT 15 à 1. Ceci fait, le bob inversé est affiché normalement à l’écran.
Imaginons maintenant que vous bougiez le bob, sans en changer la forme :
BOB 1,101,100,HREV(5)
Au prochain balayage, AMOS recommence les mêmes opérations. Il trouve encore l’image $ 8005 à afficher à une autre position. Il inspecte le BIT 15 de l’adresse 6 : celui-ci est à 1, signifiant que cette image est déjà dans le bon sens : AMOS n’a pas besoin de retourner l’image, d’où un énorme gain de temps !
Cet exemple nous a permis de comprendre le fonctionnement du système, et de voir les avantages de la méthode utilisée :
- Elle ne nécessite aucun espace mémoire supplémentaire
- Elle n’effectue les inversions qu’un nombre limité de fois.
Le dernier point n’est plus vérifié si l'on utilise plusieurs BOBs pour afficher la même image :
BOB 1,160,100,$ 4001 BOB 2,160,100,1
A chaque balayage, AMOS retournera une première fois l’image pour afficher le premier BOB, puis seconde pour afficher le deuxième ! Imaginez le désastre lorsque la taille des bobs est importante ou lorsque vous avez une dizaine de bobs en même temps.
Il faut donc éviter à tout prix d’utiliser plusieurs fois une image et sa symétrique en même temps sur l’écran.
- Paste Bob et Paste Icon
Le retourneur de bob est également implémenté pour ces instructions. Pour la deuxième, en l’occurrence, il s’agit d’un retourneur d’icônes.
- Inverser les sprites hardware
Les routines sont totalement automatiques pour les bobs. Pour ne pas trop en alourdir la gestion, je n'ai pas implémenté le système pour les sprites hardware. On peut cependant l’utiliser par un moyen détourné. Le retourneur travaille directement dans la banque. Lorsque vous affichez un sprite hardware par l’instruction SPRITE, AMOS explore la même banque. Si l’une des images est retournée à ce moment, elle sera affichée tel quel.
Pour résumer, voici comment afficher en SPRITE les quatre symétriques de l’image numéro 2 : (notez l’utilisation de Paste Bob en dehors de l'écran pour inverser l’image dans la banque...)
' Charge une banque de sprites
Load “AMOS_DATA:Sprites Amostéroids.Abk”
1 Libère tous les sprites hardware du système
Hide On
' Sens original
Paste Bob 500,500,2
Sprite 8,200,200,2
Wait Key
‘ Symétrique en X Paste Bob 500,500,VREV(2)
Sprite 8,200,200,2 Wait Key
‘ Symétrique en Y Paste Bob 500,500,HREV(2)
Sprite 8,200,200,2 Wait Key
' Symétrique en X et en Y Paste Bob 500,500,REV(2)
Sprite 8,200,200,2
ATTENTION ! Vous devez être sûr de la position de l'image dans la banque lorsque AMOS calcule les sprites, faute de quoi le sprite hardware sera affiché aléatoirement.
Le problème est exactement le même que pour les sprites hardware. Le programme de collision utilise la banque d'image dans l’état où elle se trouve au moment de l’instruction. Le programme suivant ne fonctionnera pas :
Do
Bob 1,160,100,1
Bob 2,X Screen(X Mouse),Y Screen(Y Mouse),REV(1)
Wait Vbl
Exit If Collide(1,2)
Loop
Voyons d’où vient l’erreur : au moment du balayage d’écran, AMOS commence par dessiner le Bob numéro 1. L’inverseur d’image remet donc l’image dans le sens originel. Puis AMOS appelle de nouveau l’inverseur pour dessiner le symétrique en X et en Y.
Vient l’instruction Collide. Elle ne fonctionnera pas correctement, car nous lui demandons de détecter une collision entre l’image 1 de la banque ET SON INVERSE. Or, à ce moment précis, SEUL l’inverse se trouve dans la banque ! Collide fera ce qu’elle pourra, et détectera les collisions entre les DEUX inverses. Le résultat de la détection de collision sera donc ERRONE !
Une conclusion s’impose : il ne faut JAMAIS essayer de détecter les collisions entre une image et son inverse. Ou mieux, la détection de collision entre images inversées n'est valable que si UN SEUL bob utilise l’image à ce moment.
- AMAL et l’inverseur de bobs
Afin d’autoriser l’utilisation du “retourneur”, j'ai implémenté l’hexadéci- mal en AMAL. Vous pouvez donc maintenant taper n’importe quel chiffre sous les deux formes.
Exemples d’adaptations : AMAL 1,"Anim 0,(1,2)(2,2)(3,2)(4,2)” devient : AMAL 1,’Anim 0,($ C001,2)($ C002,2)($ C003,2)($ C004,2)” pour une inversion en X et en Y.
N’essayez pas de modifier le compteur d'une boucle, faites plutôt le changement au moment de l'affectation de la valeur à l’image:
Exemple : AMAL 1,"For R0=1 To 10; Let A=R0; Next R0” devient : AMAL 1,"For R0=1 To 10; Let A=$ 4000+R0; Next R0”
- Inverser les blocs
Ayant fait les routines de symétrie de bobs, il m'était très facile de faire deux nouvelles instructions pour renverser les blocs :
HREV BLOCK numéro : fait une symétrie horizontale VREV BLOCK numéro : fait une symétrie verticale ou numéro désigne le bloc.
- BANK SWAP Bankl, Bank2
Cette nouvelle instruction échange deux banques mémoire entre elles. Vous pourrez ainsi avoir plus d’une banque d’images dans un programme ; échanger une banque de sprites et d’icônes ; avoir plusieurs musiques.
- =DEV FIRST$ (“filtre”)
- =DEV NEXT$
Ces deux instructions fonctionnent de la même manière que DIR FIRST$ (“") et DIR NEXT$ , mais elles retournent les noms des DEVICES (autrement dit des lecteurs de disquettes) branchés sur votre Amiga. Pour obtenir le nom réel, vous devez supprimer les espaces à l’aide de la soustraction de chaînes.
Exemple :
' Device directory D$ =Dev First$ (“*‘”)
While D$ >”"
Print D$ -” “
D$ =Dev Next$
Wend
La version 1.2 est en même temps un peu plus petite que la précédente : deux kilos de précieuse mémoire en plus, ça aide. On se retrouve le mois prochain pour de nouvelles aventures en AMOS ! D’ici là, n’oubliez pas que vous pouvez me retrouver sur le serveur 3615 ComRev pour toute question urgente.
François Lionet
Annoncée le mois dernier, en sus de l'initiation à Amos que tient dorénavant son auteur en personne, j'ai nommé François Lionet, voici une nouvelle rubrique dans Commodore Revue qui vous apprendra à créer vos propres jeux.
APPLICATION
FAITES VOS JEUX
L’Amos a été choisi pour illustrer ces articles grâce aux facilités qu’il offre pour la gestion des bobs, sprites, bruitages, musiques, etc. Cette rubrique restera toutefois assez généraliste, vous permettant ainsi d'adapter vos nouvelles connaissances à d’autres langages - Basic, C ou Assembleur.
PAC-REV ET COM-ROID SONT DANS UN BATEAU...
Le but de cette rubrique n'est pas de vous donner toutes les routines nécessaires à la création du jeu du siècle, mais plutôt tous les éléments essentiels à la réalisaton d’un jeu, quel qu’il soit. Car en effet, que vous programmiez un Lode Runner, un Battle Chess ou un Pendu, les bases restent les mêmes, seules changent les règles du jeu.
Ce premier article sera essentiellement théorique ; nous y aborderons des notions importantes (comme la synchronisation vidéo, le double- buffering, etc.) qui ne seront pas reprises par la suite. Nous vous engageons donc plus que vivement à le lire avec énormément d'attention. Nous nous lancerons ensuite lentement mais sûrement dans la réalisation d’un Pac-Man, Oh bien sûr, nous n’en développerons que le squelette, laissant à votre sagacité le soin de créer de nouveaux tableaux et de nouvelles difficultés. Il en ira de même pour le casse-briques du plus pur style Arkanoïd que nous construirons par la suite, ainsi que du “shoot’em up” inspiré de Xénon qui sera l'objet de notre quatrième rendez-vous.
SEQUENTIALITE ET MULTI-TACHES
L'Amiga est multi-tâches, je ne vous apprends rien. Cela signifie qu’il est capable d'exécuter plusieurs programmes en même temps, vous permettant par exemple d'écouter la cinquième de Beethoven tout en écrivant une lettre à votre grand-mère ou en dessinant la pin-up de vos rêves. C'est d’ailleurs peut-être ce qui a motivé votre achat (sans parler de ses qualités graphiques et sonores, cela va de soi).
Alors si j'arrive avec mes gros sabots et en vous apprenant sans prendre de précaution que vous vous êtes fait lamentablement berné, vous allez certainement m’en vouloir... Pourtant, le fait est là : votre Amiga n’est capable de n’exécuter QU’UN SEUL programme à la fois. Le multi-tâches version Amiga n’est que supercherie : on l’obtient grâce à certaines astuces de programmation, en exécutant chaque programme L’UN APRES L’AUTRE, suffisamment rapidement pour donner L’ILLUSION que tout fonctionne en même temps.
Quel rapport avec les jeux, vous demanderez-vous ? Simplement celui- ci : même dans les plus gros “hits” que vous puissiez posséder
- Shadow of the Beast, Battle Squadron et autres - chaque personnage, chaque vaisseau, chaque boulet de canon est déplacé séquentiellement, c’est-à-dire suivant un ordre bien précis et défini par le programmeur du jeu. Pour prendre un exemple plus concret : dans Shadow of the Beast, le décor ne défile pas PENDANT que le personnage court, mais AVANT. L’ordre des actions effectuées par l’ordinateur dans ce cas est : 1) faire défiler le décor ; 2) afficher le personnage. Encore une fois, si cela est fait suffisamment rapidement, l’illusion de simultanéité des deux événements est parfaite.
Ce sera notre première notion essentielle : la séquentialité. La seconde notion essentielle découle de ce qui vient d'être dit : la rapidité.
SYNCHRONISATION
Avez-vous déjà remarqué, lorsque vous déplacez une fenêtre dans l’écran du Workbench, que le cadre “fantôme” censé représenter son contour n'est pas toujours complètement affiché, suivant que le déplacement se situe dans la partie supérieure de l’écran ou dans sa partie inférieure ? Il en “manque” tantôt le haut, tantôt le milieu, tantôt le bas. Ce phénomène que les anglicistes nomment “flickering” est connu chez nous sous le nom de “scintillement”. Il est dû à un problème de synchronisation de l’affichage avec le balayage du rayon électronique qui produit l’image siir le moniteur. Pour simplifier le problème, disons que ce rayon est comme un pinceau qui peindrait l’image sur le moniteur d’après les données qu'il trouverait dans la mémoire de l'ordinateur. Son travail est répétitif et régulier : il commence par représenter la première ligne sur l’écran, puis la seconde, la troisième, et ainsi de suite jusqu’à la dernière, pour ensuite “remonter” vers le haut de l’écran et tout recommencer, le tout à une fréquence de 50 Hz,soit 50 Images par seconde.
Arrivé à ce stade, Il convient de bien différencier les termes "écran” et “moniteur”. Dans cette série d’articles, le mot écran représentera toujours l'image telle qu'elle est codée dans la mémoire de l’ordinateur, c’est-à-dire sous forme d'octets de 8 bits. Le mot “moniteur” désigne quant à lui l'appareil qui permet de visualiser cet écran, comme le 1084 S de Commodore ou, plus modestement, le poste de télévision. Imaginez maintenant que ce rayon électronique ait déjà représenté la moitié de l'image et que l’on décide d'afficher un objet quelconque dont la hauteur sera égale à celle de l’écran. Que va-t-il se passer ? Simple : l’Amiga va dessiner l'objet dans sa mémoire graphique, cette même mémoire que le rayon électronique balaye ; ce dernier continuant sont travail indépendamment de ce que peut bien faire l’ordinateur, il va soudainement trouver dans cette mémoire une moitié d'objet - celle appartenant à la moitié d’écran pas encore balayée - qu’il va tout simplement afficher avec le reste. SI l’on pouvait geler l’Image à ce moment-là, on ne verrait qu'une moitié de l’objet dans le bas de l'écran ; la moitié supérieure ne sera quant à elle représentée qu’au prochain passage du rayon dans le haut de l’écran. C’est ce qui provoque ce scintillement désagréable.
De cela on déduit que si l'on pouvait attendre que le rayon ait complètement balayé l’écran entier avant d’y dessiner quoi que ce soit, tout nouvel objet serait entièrement affiché en un seul passage du rayon. Cette attente est bien évidemment possible, et elle est notre troisième notion essentielle : la synchronisation.
DOUBLE BUFFERING
Vous en avez peut-être déjà entendu parler, de cette technique du double-buffering, mais les explications que vous avez pu lire à droite et à gauche ne sont sans doute pas très claires. Il est vrai que, comme l’a dit je ne sais plus quel grand homme, les choses les plus simples sont souvent les plus difficiles à expliquer.
Le double-buffering est une extension de la synchronisation. Son utilité tient du fait qu’il n’est pas toujours possible, notamment dans les jeux les plus complexes où beaucoup d’objets doivent être affichés, de modifier l'image entière en un seul passage du rayon électronique. On obtient alors de nouveau et pour les mêmes raisons le phénomène de scintillement.
Pour y remédier, on va devoir jongler avec un deuxième écran virtuel dans la mémoire de l’ordinateur. Evidemment, un seul de ces deux écrans sera visible sur le moniteur, ce qui permet de dessiner tous nos objets dans le second écran. Une fois celui-ci terminé, on attend la synchronisation et on demande à l'ordinateur de l'afficher sur le moniteur, pendant que l’on continue nos dessins dans le premier écran (devenu à ce moment là invisible) et ainsi de suite, De cette manière, aucun scintillement n’est plus possible.
50 IMAGES PAR SECONDE !
Rappelez-vous ce qui a été dit plus haut : le rayon électronique balaye l’écran 50 fois par seconde. En d’autres termes, il affiche 50 images par seconde. Or, lorsque que le programme est suffisamment bien fait, c'est-à-dire avant tout suffisamment rapide (tout dépend bien entendu de la complexité du jeu), la technique de synchronisation vidéo seule est suffisante pour produire une animation parfaite, elle aussi à cinquante images par seconde.
Dans ie cas du double-buffering, l’animation est ralentie de moitié, puisqu'un seul passage du rayon ne suffisant plus, il faut en attendre un second avant d’afficher l’image modifiée. Un rapide calcul mental indique donc que la fréquence d’animation tombe à 25 images par seconde. Cette fréquence est à comparer avec celle d’un film au cinéma : ce sont 24 images par seconde qui sont projetées et le mouvement est toujours très net.
Il est par contre totalement déconseillé d’attendre un troisième passage de rayon : la fréquence tomberait alors à 16 images par seconde... soit à peine plus que les 12 images par seconde des meilleurs dessins animés japonais, L’Amiga est tout de même capable de faire un peu mieux que ça, non ?
ET AMOS DANS TOUT CA ?
S’il est possible de réaliser (plus ou moins) facilement une animation au cinquantième en Assembleur ou en C, qui est un langage compilé, cela est beaucoup moins évident en Basic, qui reste un langage interprété et en tant que tel, est obligé de tester, pour chaque instruction, si les paramètres fournis sont valides, puis d'appeler la routine correspondant à cette instruction, ce qui consomme autant de temps. Ceci est évidemment (et malheureusement) valable pour Amos, pour lequel, à part dans quelques cas vraiment très simples, l’animation au cinquantième est à exclure.
C’est pourquoi il est préférable de s’habituer dès maintenant à la technique du double-buffering, qui produira toujours une animation fluide. Amos possède heureusement tout ce qu’il faut pour ça. Ces remarques risquent évidemment de devenir caduques dès lors que le compilateur Amos sera sorti, ce qui ne devrait plus tarder maintenant (note de l’Auteur : ben alors, François, qu’est-ce que tu fous ?). Mais pour l’instant, nous nous bornerons à utiliser l’interpréteur d’Amos, dans la version que vous possédez actuellement.
Vous trouverez en annexe un exemple de déplacement de 10 Bobs en double-buffering selon deux méthodes, l’une “automatique” (Amos se charge de tout), l'autre “manuelle” (on se tape tout le boulot nous- mêmes), histoire de vous permettre de vous familiariser avec cette technique et avec les instructions d’Amos propres à sa gestion. Par curiosité, retirez la commande “Double Buffer” du premier listing... Et n’hésitez surtout pas à le modifier selon votre bon plaisir, car n’oubliez pas le proverbe breton : “c’est en se mouchant que l’on devient moucheron".
Stéphane Schreiber
Rsm ******************************************* Rem * Exemple de double-buffering en AMOS... *
Rem * Ici, on laisse AMOS se charger de tout *
Rem * le processus de double-buffering *
Rsm ******************************************* Rem * Mettez donc un Rem devant l'instruction *
Rem * 'Double Buffer' pour constater la *
Rem * différence sans double-buffering ! *
Rem *******************************************
Rem * Chargement d'un Bob
Load "AMOS_DATA:Sprites Octopus.abk" : Make Mask
Get Sprite Palette
Curs Off : Flash Off : Cls 0
Double Buffer
t
Repeat Wait Vbl
Y=Y Screen(Y Mouse)
For 1=0 To 9 Bob 1,1*32,Y, 1 Next I
Rsm *****************************************
Rem * L'instruction suivante est une astuce *
Rem * souvent employée par les programmeurs *
Rem * de jeux : elle permet de savoir où se *
Rem * trouve le rayon électronique, et donc *
Rem * de savoir combien de temps on dispose *
Rem * avant la fin du balayage de l'écran. *
Rem * ' *
Rem * Plus la zone bleue est basse, moins *
Rem * il reste de temps ! *
Rsm *****************************************
Doke $ DFF180,$ F
X
Until Mouse Key
Default
Edit
Rsm *****************************************
Rem * Deuxième exemple de double-buffering *
Rem * en AMOS *
Rsm *****************************************
Rem * Cette fois, on se charge de tout *
Rem * nous-mêmes. Comparez (grâce à la zone *
Rem * bleue) le temps restant avant le *
Rem * retour du balayage... *
Rsm *****************************************

Rem * Chargement d'un Bob
Load "AMOS_DATA:Sprites Octopus.abk" : Make Mask
Get Sprite Palette
Flash Off : Curs Off : Cls 0
X
Double Buffer : Autoback 0 : Update Off Repeat
Screen Swap : Wait Vbl : Bob Clear Y=Y Screen(Y Mouse)
For 1=0 To 9 Bob I,1*32,Y,1 Next I Bob Draw
X
Doke $ DFF180,$ F
X
Until Mouse Key
Default
Edit
DIGITALISE!! 2 partie
CINCH DROITE U1
h II 1
2
7 II Cl
3 iv .
X=PIN 12 DU PORT
Y=PIN 13...... ......
2“Pin i 1,11 11 11 11,1 5V SUR PORT PIN:14 HASSE PIN:25
DIGITALISEUR STEREûl O.MlSCCR12
Effectivement, nous avons vu que nous utiliserons l’ADC809, mais hélas, après quelques relevés expérimentaux, FADC809, n’a pu convenir à cause de sa trop grande marge d’erreurs ainsi que sa vitesse inadéquate. Aussi, nous nous servirons donc de l’AD 7576 ou de son équivalent le MAX7576, plus rapides et mieux adaptés à l’Amiga.
Nous disposerons de nos huit entrées différentes le mois prochain grâce à un montage compatible avec la majorité des digitaliseurs de sons. Assez de bavardages, et intéressons-nous à la pra
Ça n’a pas été trop dur d’attendre tout ce temps pour voir enfin arriver la suite et fin du digitaliseur audio ?
Sans plus attendre, voici toutes les révélations...
Cl: 220NF 111:4066
C2:220NF U2:LH324
C3:lyF 16V tantale C4:l00pF RI : 33Kohns
R2:33KohhS R3:15Koh«s R4 :12K ohns R5:100KohMs Pl:l00Koh«s P2‘ 9ftVnhMC
tique, qui, c’est bien connu, est bien plus difficile que la théorie (tiens, ça me rappelle quelque chose...).
Donc, munissez-vous de la liste des composants et dans un premier temps faites votre cuivre (circuit imprimé). Commencez à souder et mettez les circuits intégrés sur support, cela vous permettra de réparer en cas de panne éventuelle.
Maintenant réglez VREF qui permettra de fixer le zéro de digitalisation, pour cela munissez-vous d’un voltmètre ou oscilloscope, puis réglez-le à la tension de 2,5 V, une fois le tout branché sur l’Amiga, lancez un soft de digitalisation, par exemple Perfect Sound disponible sur une des disquettes Comrev (en vente chez Commodore Revue).
Puis introduisez une source sonore (attention, placez le volume à zéro) puis augmentez le volume d’un cran. Digitalisez, répétez l’opération plusieurs fois jusqu’à l’obtention du niveau sonore le plus adéquat pour vous, si des signaux carrés apparaissent à l’écran cela signifie que vous saturez donc le niveau sonore est trop haut. Incontournable, me direz-vous !
Olivier Mangon dit le “bidouilleur fou”
LISTE DES COMPOSANTS :
BROCHAGE AD7576 :
1 : CS
CHIP SELECT
2 : RD
READY
3 : MODE
+5V
4 : BUSY
(NON CONNECTE)
5 : CLK
HORLOGE
6 : D7
BROCHE 9 du port parallèle
7 : D6
8
8 : D5
7
9 : :GND
MASSE
10 : D4
BROCHE 6
11 : D3
5
12 : D2
4
13 : D1
3
14: DO
2
15 :AGND
Relié à la Masse
16 : AIN
Ax entrée Analogique
17 : VREF
VREF
18 : VCC
+5V
14
D0
13
- D1
12
D2
11
D3
10
- D4
8
- D5
7
- D6
6
- D7
UN ANIMAL DOUE DE RAISON
Dans le but toujours poursuivi de mieux découvrir notre machine, nous allons aujourd’hui voir comment l’on gère depuis l’assembleur les déplacements de ce petit animal sympathique que l'on nomme “souris”.
Mais d’abord, un peu de théorie sur son fonctionnement. Lorsqu’on la déplace sur la table, la souris émet des impulsions électriques en direction de l'Amiga, par l’intermédiaire du câble les reliant l’une à l’autre. Sans entrer dans les détails des “quadrature puise” et autres gâteries typiquement Amiga, il faut savoir que la souris est incapable de signaler à l’ordinateur dans quelle direction précisément elle s’est déplacée, mais simplement si le mouvement fut horizontal ou vertical, ou bien les deux (diagonal, quoi). C’est au logiciel par la suite de déterminer la direction exacte en fonction de cette information, ainsi que la vitesse du déplacement.
On se sert pour cela du registre hardware JOYODAT pour le port 1, ou JOY1 DAT pour le port 2. Notez au passage que ces registres sont également ceux utilisés pour tester les joysticks, et qu’ils s'adaptent parfaitement à l’un ou l’autre de ces périphériques, sans aucun besoin de programmation particulière. Après lecture de JOYxDAT, on obtient un mot de 16 bits à décomposer comme suit :
Bit : 15 14 13 12 11 10 9 8 7 6 4 5 3 2 1 0
Sens : V7 V6 V5 V4 V3 V2 V1 VO H7 H6 H5 H4 H3 H2 H1 HO
En d’autres termes, les 8 bits supérieurs contiennent le nombre d’impulsions électriques “horizontales” et les 8 bits inférieurs, le nombre d'impulsions électriques “verticales”.
Reste maintenant à déterminer la direction du mouvement, c’est-à-dire vers la gauche ou vers la droite dans le cas de l’horizontal, et vers le “haut” ou vers le “bas” dans le cas du vertical (un mouvement diagonal étant obtenu, il ne paraît pas superflu de le rappeler, par un déplacement à la fois horizontal et vertical). Il n’existe qu’un seul moyen d’y parvenir, c’est de mémoriser l’ancienne valeur de JoxDAT et de lui soustraire la nouvelle. Si le résultat est positif, le déplacement était vers la droite (respectivement, le haut), sinon, il était vers la gauche (respectivement, le bas).
Un dernier piège est à éviter : les compteurs JoxDAT sont circulaires, c’est-à-dire qu’une fois arrivés à 255, ils bouclent sur 0. Pour éviter tout problème de lecture, il faut donc lire ces compteurs de manière régulière, et quoi de mieux pour ce faire que l’interruption VBL survenant tous les 1 50e de seconde, franchement, je vous le demande, quoi de mieux ? Hein ?
Je ne vous ferai pas l’affront de vous rappeler que le bouton gauche se teste par le 6e bit du port A du CIA A (adresse$ bfe001), ni que le droit se teste par l’intermédiaire du 10e bit du registre hardware POTGOR (adresse $ dff016). De même que je ne dirais pas que si l’un de ces deux bits est à 0, c'est que le bouton correspondant est appuyé : vous saviez déjà tout cela.
UN EXEMPLE, UN EXEMPLE !
Le petit programme d’exemple que voici met tout ceci en pratique. Il déplace le sprite hardware numéro 0 au gré des mouvements de la souris, sous l’interruption VBL. Pour le plaisir, il teste également le joystick, juste histoire que vous puissiez comparer le mode de gestion de ces deux périphériques. Et pour encore plus de plaisir, l’interruption générée “ - par le Copper est utilisée pour changer la couleur du fond suivant la position du sprite. Vous reconnaîtrez sûrement la routine de positionnement d’un sprite, elle est quasiment identique à celle donnée dans l’exceeeeelllllente série “Animation de sprites sous IRQ”.
Le programme a été écrit pour Devpac II de HiSoft, est-il besoin de ie préciser, et ne fonctionnera pas sous K-Seka. Et c'est pas la peine d’appeler pour demander les modifications à effectuer.
Voilà. On verra le mois prochain de quoi on parlera. D’ici là, j’attends votre courrier et demandes de routines à la rédaction, dont vous trouverez l’adresse quelque part dans ce canard. A plus.
Max
;MickeyMouse ; Par Max
; exec.library
ExecBase
EQU
4
CloseLibrary
EQU
- 414
OpenLibrary
EQU
- 552
; Custom chips
Custom
EQU
$ dff000
DMACONR
EQU
$ 002
IOY0DAT
EQU
$ 00a
JOY1DAT
EQU
$ 00c
POTGOR
EQU
$ 016
INTENAR
EQU
$ 01 c
INTREQR
EQU
$ 01 e
COP1LCH
EQU
$ 080
COPJMP1
EQU
$ 088
DIWSTRT
EQU
$ 08e
DIWSTOP
EQU
$ 090
DDFSTRT
EQU
$ 092
DDFSTOP
EQU
$ 094
DMACON
EQU
$ 096
MENA
EQU
$ 09a
INTREQ
EQU
$ 09c
BPL1PTH
EQU
$ 0e0
BPL1PTL
EQU
$ 0e2
BPLCON0
EQU
$ 100
BPLCON1
EQU
$ 102
BPLCON2
EQU
$ 104
BPL1MOD
EQU
$ 108
BPL2MOD
EQU
$ 10a
SPR0PTH
EQU
$ 120
; Couleur du fond COLOR00
EQU
$ 180
; Couleurs du sprite 0
COLOR17
EQU
$ 1a2
COLOR18
EQU
$ 1a4
COLOR19
EQU
$ 1 a6
;CiaA
CIAA_PRA
EQU
$ bfe001
; Interruption de niveau 3 (VBL, Copper et Blitter) IRQ_LEV3 EQU $ fc
section Un,CODE
; On commence par sauvegarder le contexte Start: move.l (ExecBase).w,a6
GfxName(pc),a1
lea
moveq
jsr
beq
move.l
move.l
jsr
0,d0
OpenLibrary(a6)
NoGfx
d0,a1
; CopperList système
38(a1 ),01dCopper CloseLibrary(a6)
lea Custom,a6
move.w DMAC0NR(a6),01dDMA ; DMACON
move.w INTENAR(a6),01dINT ; INTENA
move.l (IRO_LEV3).w,01dlRO ; Vecteur IRQ 3
; Maintenant, on s'installe
move.w $ 7fff,DMACON(a6) ;TousDMAsoff move.w $ 7fff,INTENA(a6) ; Toutes KO off
; Construit le bitplane-pointer 1 dans la CopperList lea CLPlanes,a0
move.l Plane,d0
move.w d0,6(a0)
swap d0
move.w d0,2(a0)
; Construit le sprite-pointer 0 dans la CopperList lea CLSprites,a0
move.l Sprite,d0
move.w d0,6(a0)
swap d0
move.w d0,2(a0)
; Construit les 7 autres sprite-pointeis move.l SPRNUL,d0
moveq 6,d1
MakeSprites:
addq.l 8,a0
move.w d0,6(a0)
swap d0
move.w d0,2(a0)
swap
dbra
d1, MakeSprites
move.1 NewCopper,COP1LCH(a6) move.w d0,COPJMP1(a6) move.l NewIRQ,(lRQ_LEV3).w
move.w JOY0DAT(a6),MCounter ;InitialiseMCounter
move.w $ 83a0,DMACON(a6)
;DMA:
;BPLEN!COPENISPREN ; IRQ: VERTBICOPER
move.w $ c030,INTENA(a6)
; Attend le bouton aauche de la souris
Wait: btst 6,CIAA_PRA
bne.s Wait
; On remet tout en état
move.w $ 7fff,DMACON(a6) move.w $ 7fff,INTENA(a6) move.l OldIRQ(pc),(IR0_LEV3).w move.l OldCopper(pc),COP1LCH(c[6) move.w d0,COPJMP1(a6) move.w OldDMA(pc),d0 ori.w 38000,d0
move.w d0,DMACON(a6) move.w OldINT(pc),d0
ori.w 3c000,d0
move.w d0,INTENA(a6) moveq 0,d0
NoGfx: rts
. ************************************
; Routine IRQ de niveau 3
NewIRQ: movem.l d0-d4 a0,-(sp) ; Sauve les registres utilisés
marna hbhb
ÿr ......
move.w INTREQR(a6),d0
; Détermine quelle IRQ est
andw INTENAR(a6),d0
; survenue
btst 5,d0
bne.s VBL
; VBL?
Btst 4,d0
bne.s COP
; ouCopper?
Bra.s IRQEnd
; Ca ne devrait pas arriver...
; Interruption Copper (juste pour rire)
COP: btst 10,POTGOR(a6)
; Bouton droit de la souris
beq.s COPEnd
; Appuyé -> ne rien faire
move.w MouseY(p Ad0
cmpi.w Sfe,d0
bcs.s .1
move.w $ fe,d0
.1 : move.b d0,CLWait
addq.b 1,d0
movei d0,CLWcrit+8
COPEnd: move.w $ 10,INTREQ(a6) ; IRQ Copper traitée
bras IRQEnd
; Interruption VBL
; Teste la souris et le joystick puis déplace le sprite
VBL: bsr.s TestMouse ; Teste la souris
bsr.s Testjoystick ; Teste aussi le joystick
bsr.s Clip
;Clipping du sprite
bsr MovSpr
; Déplace le sprite
move.w $ 20,INTREQ(a6)
; IRQ Vbl traitée
IRQEnd: movem.1 (sp)+,d0-d4 a0
rte
: Routine de gestion du déplacement de la
souris (port 0)
; Actualise les coordonnées (MouseX,MouseY)
TestMouse:
lea MouseX(pc),a0
move.w JOY0DAT(a6),d0
; lit le compteur
move.w 4(a0),d2
; récupère l'ancien
move.w d0,4(a0)
; et sauve le nouveau
TestMx: move.w d0,d3
; Teste le mouvement horizontal
andiw $ ff,d3
move.w d2,d1
; récupère l'ancien compteur
andi.w 3ff,d1
sub.b d1,d3 ’
; vitesse=ancien compteur-nouveau
extw d3
; extension pour addition 16 bits
add.w d3,(a0)
; MouseX=MouseX+Vitesse X
TestMy: move.w d0,d4
; Teste le mouvement vertical
Isr.w 8,d4
move.w d2,d1
: récupère l'ancien compteur
lsr.w 8,d1
subi d1 ,d4
; vitesse=ancien compteur-nouveau
extw d4
; extension pour addition 16 bits
add.w d4,2(a0)
; MouseY=MouseY+Vitesse Y
rts
; Et voilà : rapide et simple !
; Routine de gestion du Joystick (port 1 )
; Actualise les coordonnées (MouseX,MouseY)
Testjoystick:
lea MouseX(pc),a0
move.w JOY1DAT(a6),d0
move.w d0,d1
ror.w 1,d1
btst 1,d0
bne.s Joy1
subq.w 2,(a0)
; Gauche
Joy1: btst 9,d0
bne.s Joy2
addq.w 2,(a0)
; Droite
Joy2: eor.w d1,d0
btst 0,d0
bne.s Joy3
subq.w 2,2(a0)
;Haut
Joy3: btst 8,d0
bne.s Joy4
addq.w 2,2(a0)
;Bas
Joy4: rts
©IF
; Empêche le sprite de sortir de l'écran
Clip:
lea MouseX(pc),a0
movem.w (a0),d0-d1
; d0=MouseX, d1 =MouseY
cmpi.w
$ 80, d0
; clip gauche
bcc.s
Clipl
move.w
$ 80,d0
bra.s
Clip2
Clipl:
cmpi.w $ 1be,d0
; clip droit
bcs.s
Cüp2
move.w
$ 1be,d0
Clip2:
cmpi.w $ 29,d1
; clip haut
bcc.s
Clip3
move.w
$ 29,d1
bra.s
Clip4
Clip3:
cmpi.w $ !27,d1
; clip bas
bcs.s
Clip4
move.w
$ 127,d1
Clip4:
movem.w d0-d1 ,(a0)
rts
; Actualise les coordonnées du sprite
; Voir la série "Animation de sprites sous IRQ"
; pour en savoir plus.
MovSpr:
lea Sprite,a0
movem.w MouseX(pc),d0-d1
moveq
0,d2
move.l
d2,d3
move.b
2(a0),d2
sub.b
(a0),d2
; d2=VSTOP-VSTART=hauteur+1
move.b
d1,(a0)
; VSTART
btst
8,d1
beq.s
NoE8
ori.b
%10,d3
;E8
NoE8:
add.w d2,d1
move.b
d1,2(a0)
; VSTOP
btst
8,d1
beq.s
NoL8
ori.b
%1,d3
;L8
NoL8:
Isr-w* 1,d0
;x=H0
roxl.w
1 ,d3
move.b
d0,1(a0)
;HSTART
move.b
d3,3(a0)
rts
; C'est tout !
; Données pas nécessairement en Chip-Ram
OldCopper:
dc. l 0
OldDMA:
dc. w 0
OldINT:
dc. w 0
OldIRQ:
dc. l 0
GfxName:
dab "graphics.library",0,0
MouseX:
dc. w $ 80
MouseY:
dc. w $ 29
Mcounter:
dc. w 0
; Sauve IOY0DAT entre 2 lectures
dc. w
dc. w
dc. w
dc. w CLPlanes:
dc. w CLSprites:
CLVAR REPT
dc. w CLVAR ENDR ; Couleurs du sprite 0
; Données obligatoirement en Chip-Ram ; Rappel : la directive "section" permet de forcer ; l'assemblage d'une partie du programme en ; zone CODE, DATA ou BSS mais aussi en CHIP- ; RAM en précisant CODE_C, DATA_C ou BSS_C
section Deux,DÀïA_C
NewCopper:
; Définition de l'écran en 320x256,1 seul bitplane ; sprites prioritaires aux bitplanes (cf. BPLCON2)
dc. w DIWSTRT,$ 2981 ,DIWSTOP,$ 29c1
DDFSTRT,$ 0038,DDFSTOP,$ 00d0 BPLCON0,$ 1000 BPLCON1,$ 0000,BPLCON2,$ 0024 BPL1MOD,$ 0000,BPL2MOD,$ 0000
BPL1 PTH,$ 0000,BPL1 PTL,$ 0000
SET
SPR0PTH
CLVAR,$ 0000,CLVAR+2,$ 0000 SET CLVAR+4
dc. w COLOR17,$ 0888,COLOR18,$ 0444
dc. w COLOR19,$ 0FFF ; Couleur de l’écran
dc. w COLOR00,$ 0444 CLWait: dc.w $ 290f,$ fffe,COLOR00,$ 0007
dc. w $ 2a0f,$ fffe,COLOR00,$ 0000 ; Déclenche une IT Copper
dc. w INTREQ,$ 8010
$ 7e00
$ 4300
$ 4300
$ 34c0
CLEnd:
dc. l
-2
; Données du sprite
Sprite:
dc. l
$ 29403A00
dc. w
$ 0000
$ 0000,
dc. w
$ 3e00
$ 7f00 ,
dc. w
$ 3c00
$ 4600 ,
dc. w
$ 3700
$ 4980 ,
dc. w
$ 01C0
$ 0260 ,
dc. w
$ 0040
$ 00a0 ,
dc. w
$ 0000
$ 0000,
dc. w
$ 0000
$ 0000,
dc. w
$ 0000
$ 0000
, ************************************
Trois,BSS_C ds.l 2560
section
Plane:
SPRNUL:
; 1 bitplane 320x256
ds.l 2
[**********¦
END
AMIGA500
AMIGA5Œ)
+ souris
FROMO
+ peritel
INCROYABLE
AMIGA500
+peritel
AMIGA500
+extension 512K
+ écran 1084
+horloge
FROMO
3890
AMIGA500
LECTEUR3"1 2
avec compatibilité
PC
EXTERTE
nous consulter
790
A500+péritel+ext512K+horloge 3890
A500+péritel+lect ext 3” 1 2 .3890
A500+1084S+ext512K+horloge .5990
A500+1084S+ext512K+lect 3" 1 2 ..6590
AMIGA500
AMIGA2000
+écran 1084
+écran 1084
+Deluxe Paint III
+carteXT
+Star LC-10 Coukurs
+Star LC-10
8290
11990
EC10 ...1890
AMIGA2000
LclOcoul ....2490
+ecran 1084
1X24-10 .....2990
+carteXT
SWIFT24 ...3790
+disqueGVP46Mo
15990
AMIGA2000
Carie extension*
¦fécran 1084
2 Mo
- rcarteAT
+Star LC-10 couleur
extensible à 8
15990
2950
VENTE PAR CORRESPONDANCE - PRIX T.T.C.
. PHASE
GALERIE"LHSQL)ARE
93. AvenueduGl Leclerc 75014 PARIS
45 45 73 00
M" Alésia- lOhà 19h Lundi-Samedi
disquedur20MopourA500 ...
digitaliseurstéréoTrilogic ..
3990 510
Nordic Power ..
..850
REPRISE POSSIBLE DE VOTRE ANCIEN MICRO CREDIT-DÉTAXE
APPLICATION
LES LIBRAIRIES MATHEMATIQUES
Nous vous proposons aujourd’hui, un excellent article de complément sur les librairies mathématiques écrit par le non moins excellent D. GENOT. Pour des raisons de place, nous avons dû couper cet article en deux parties. Vous trouverez la deuxième partie dans l’ANT du mois prochain.
Cet article fait suite à celui de Commodore Revue de mai 1990 (N° 23) sur les librairies mathématiques. Dans le susdit article étaient abordées les librairies “mathffp” et “mathtrans”. Quelques précisions seront utiles pour les conversions envisagées aujourd’hui : il s’agit de transformer une chaîne alphanumérique en nombre et lycée de Versailles...
QUE VEUT DIRE FFP:
Ces deux librairies permettent de manipuler des nombres entiers ou décimaux qui sont pour cela stockés sous une forme particulière dite FFP: Fast Floating Point (ou encore flottant en simple précision). Cela signifie que le nombre n’est pas stocké sous une forme immédiatement compréhensible. Chaque nombre est codé avec un mot long (4 octets) dont les bits ont la signification suivante :
MMMMMMMM MMMMMMMM MMMMMMMM SEEEEEEE mot long = 4octets
31 23 15 7 - bits
M correspond à la mantisse, codée sur 24 bits.
S est le signe du nombre.
E est la puissance de 2 associée au nombre, codée sur 7 bits.
( Ce mot long est en général placé dans le registre DO )
J’en vois qui toussent... Prenons un exemple en base 10. Le nombre 41,25 peut aussi s'écrire 0,4125 x 10 exp 2. Dans cette dernière expression, 0,4125 sera appelée la mantisse du nombre et 10 exp 2 est la puissance de 10 associée. Cette écriture signifie que pour retrouver le nombre, il faut prendre la mantisse 0,4125 dans laquelle on décale la virgule 2 fois vers la droite.
Dans le cas général, la mantisse est un nombre compris entre 1 10 et 1, donc la mantisse est supérieure ou égale à 0,1 et inférieure à 1 et l’exposant indique le nombre de décalages que la virgule a subi EN BASE 10.
Or notre génial microprocesseur calcule en base 2, et il écrira donc les nombres sous la forme : mantisse x 2 exp n.
Dans ce cas, la mantisse est un nombre compris entre 1 2 et 1, donc un nombre supérieur ou égal à 0,5 et inférieur à 1 et l’exposant indiquera le nombre de décalages que la virgule a subi quand le nombre est écrit EN BASE 2. (Cette écriture est repérée en assembleur par le signe %).
Ex : le nombre 5 peut s’écrire % 101, on aura donc comme mantisse %0,101 dans les bits 8 à 31 (en complétant à droite avec des 0), le bit 7 sera mis à 0, et l’exposant +3 (décaler 3 fois la virgule à droite pour retrouver le nombre) est codé avec les bits 0 à 6.
Remarque : Dans tous les cas, il faut coder le signe de l’exposant, c’est-à-dire le sens de décalage de la virgule. En réalité, l’exposant est codé en notation “excess-64” : ce terme aussi barbare qu’intraduisible signifie que l'exposant peut varier de -64 (-$ 40) à +63 (+$ 3F) et il sera codé de 0 à 127($ 7F). (NDLR : l’exposant -$ 40 est codé par 0 et l’exposant +$ 3f est codé par 127).
Dans l'exemple du nombre 5, l’exposant 3 sera codé avec $ 43 (%100
0011)
donc : % (0,) 10100000 00000000 00000000 01000011 soit $ A0000043
C’est cette valeur que l’on obtient (dans D0) en appelant SPFIt avec 5 dans D0 en mode trace... (NDLR : Par mode trace, l’auteur entend le suivi pas à pas du programme avec un débogueur quelconque [Seka Devpac...], rien à voir avec le mode trace du 68000).
Cette connaissance est-elle vraiment nécessaire ? Elle ne l’est pas pour faire des calculs, car les librairies ont des routines qui convertissent automatiquement (voir N° 23 : les offsets SPFixet SPFIt). Ces détails sont pourtant utiles pour connaître la précision du calcul effectué. En effet, le plus grand nombre manipulable est calculé en fixant tous les bits à 1 (sauf les bits de signes), ce qui donne :
en base 2 11111111 11111111 11111111 00111111 soit le nombre
% 11111111 11111111 11111111 suivi de 39 zéros ! (63-24 zéros)
soit finalement: >
9,22337177 x 10 exp 18 ce qui nous laisse de beaux jours !
Cela prouve qu’il n’y a guère de limitation en taille, à moins de faire un calcul astronomique (comme le montant de ses impôts ?)
Ce qui limite davantage, c’est le codage de la mantisse car on ne lui accorde que 24 bits soit au maximum le nombre 0,16777215 soit 8 chiffres significatifs dans le meilleur des cas... Ceci explique certaines bizarreries où un calcul donne 12,239999.. au lieu de 12,24.
Comment remédier à cela ? En accordant davantage de bits à la mantisse, c’est le mode IEEE.
QUE VEUT DIRE IEEE ?
C’est l’autre façon de coder un nombre flottant et on l’appelle parfois “double précision” dans un souci de clarté bien compréhensible...
Le nombre est alors stocké sur 2 mots longs (8 octets) sous la forme suivante :
SEEEEEEE EEEEMMMM MMMMMMMM MMMMMMMM 1er mot dans D0
63 55 47 39 - bits
MMMMMMMM MMMMMMMM MMMMMMMM MMMMMMMM 2e mot dans D1
31 23 15 7 - bits
avec les mêmes conventions :
M désigne la mantisse codée sur 52 bits
S est le signe du nombre IEEE
E est la puissance de 2 correspondante, codée sur 11 bits
Cette notation autorise tous les nombres entre -1,8 x 10 exp 307 et 1,8 x 10 exp 307 et surtout elle est beaucoup plus précise car la mantisse peut aller jusqu’à $ F FFFF FFFF FFFF ! (ce qui autorise 16 chiffres significatifs).
ATTENTION : des erreurs d'approximation peuvent se produire si le nombre comporte plus de 16 chiffres...
Bien sûr, d’autres librairies sont à utiliser pour ce mode IEEE. Voici un tableau récapitulatif :
MODE FFP MODE IEEE
conversions,calculs “mathffp.library” “mathieeedoubbas
courants (+,-,x, ) .library"
calculs transcendants “mathtrans “mathieeedoubtrans
(cos.sin.log,...) .library” .library”
Sur ces 4 librairies, seule la “mathffp” est en ROM, et les 3 autres doivent donc figurer dans le tiroir LIBS: de votre disquette système.
Pour simplifier les choses :
©MF
pË]5I!DflüHHH5
- les offsets valables pour la librairie “mathffp" le sont aussi pour la librairie “mathieeedoubbas” et idem pour les deux autres. Ce qui est important, c'est de penser qu’en mode IEEE les nombres nécessitent 2 mots longs pour être manipulés et mis en mémoire (sinon bonjour le GURU I). Les nombres sont donc associés à des paires de registres : D0 D1 (opérations courantes) et D2 D3.
- Les conditions d’entrée et de sortie des routines sont les mêmes que pour les deux premières librairies à condition de raisonner sur des paires de registres en mode IEEE.
Exemple : pour additionner 15 et 23 en double précision (la librairie “mathieeedoubbas” est supposée ouverte) :
= SPFlt = SPAdd = SPFix
- 36
- 66
- 30
IEEEDPFlt
IEEEDPAdd
IEEEDPFix
move.l 15,DO jsr IEEEDPFlt(A6) movem.l DO 1, (A7) move.l 23,DO jsr IEEEDPFlt(A6) movem.l (A7)+,D2-3 jsr IEEEDPAdd(A6)
si A6 = adresse de base de "mathieeedoubbas" 15 en IEEE mis de côté
- > 23 en IEEE dans D0 D1
récupère 15 dans D2 D3
additionne D0 D1 et D2 D3
le résultat est dans D0 D1: c'est le cas de
toutes les opérations.
On peut ajouter jsr IEEEDPFix(A6) pour voir le résultat entier dans DO en mode trace soit 38 (ou $ 26).
Dans la pratique, il suffit de nommer les offsets le plus simplement possible, IEEEDPFlt -> Fit par exemple, et de régler A6 sur une librairie FFP ou IEEE suivant le type de calcul à effectuer (ou utiliser bien sûr des fichiers “include”).
IMPORTANT : Une remarque cependant sur les librairies IEEE: toute tâche qui les utilise doit les ouvrir elle-même (et non pas récupérer ailleurs un pointeur sur l’adresse de base) car ces librairies sont reliées à la structure de la tâche qui les a ouvertes.
CHANGEMENT DE MODE
On peut désirer convertir un nombre FFP en nombre IEEE ou l’inverse. D’après le ROM KERNAL MANUEL “Libraries and Devices", il semble qu’il existe un mode hybride appelé “ieee simple précision” codé sur un registre seulement... Il existe en tout cas 2 offsets de traduction dans les mathtrans...library :
* Dans la "mathtrans.library"
Tieee = -102 (-$ 66) entrée :D0 = nombre FFP
sortie :D0 = nombre ieee simple précision
Fieee = -108 ( $ 6C) entrée : DO = nombre ieee simple précision
sortie :D0 = nombre FFP
* Dans la "mathieeedoubtrans.library"
Tieee = -102 (-$ 66) entrée :D0 D1 = nombre IEEE
sortie :D0 = nombre ieee simple précision
Fieee = -108 (-$ 6C) entrée :D0 = nombre ieee simple précision sortie :D0 D1 = nombre IEEE
A titre indicatif, voici une routine qui permet de convertir un nombre IEEE en nombre FFP (les librairies sont supposées ouvertes) :
La conversion inverse 321 (FFP) donne 329 (IEEE) !! Ces routines seraient-elles beuuuguées ? (NDLR : Il semble effectivement que cela soit le cas pour Fieee de mathieeedoubtrans. Pour preuve, les développeurs du compilateur Lattice C ont réécrit ces routines.)
Une dernière chose avant de passer à la pratique : pour les programmeurs en C, le mode FFP correspond à la déclaration "float” et le mode IEEE correspond à la déclaration “double”. Le C possède bien les fonctions float=afp (chaîne) et fpa (float,chaine) mais ces fonctions travaillent en mode FFP et sont imprécises si le nombre comporte une dizaine de chiffres.
CONVERSION ASCII -> FLOTTANT
Dans ce qui suit, on suppose que le nombre à convertir est stocké sous forme ASCII dans une chaîne terminée par un octet 0 (voir l’étiquette “ascii” dans le source-exemple). La chaîne est considérée comme formée de 4 parties :
- le signe + ou - au début (pas de signe est interprété comme+).
- la partie entière.
- un séparateur qui peut être une virgule ou un point.
- la partie décimale.
Pour convertir la chaîne :
- la partie entière est convertie en flottant FFP ou IEEE.
- la partie décimale est convertie en flottant FFP ou IEEE.
- le nombre de chiffres après la virgule est calculé, appelons-le n.
- la partie décimale flottante est alors divisée par 10 exp n puis additionnée à la partie entière flottante.
- on tient enfin compte du signe si la chaîne commençait par -,
ex. : la chaîne “-123.45” donnerait
- 123 en flottant
- 45 en flottant et 2 chiffres après la virgule
- 45 10 exp 2 (soit 0,45) additionné à 123 en flottant, doncl 23,45.
- on prend l’opposé du résultat avec jsr Neg(a6), donc -123,45.
Pour convertir un entier ASCII en flottant :
- chaque chiffre est lu, on lui enlève $ 30 (valeur ASCII de 0) pour avoir sa valeur.
- on multiplie le total que l’on avait par 10 et on y ajoute ce dernier chiffre.
Ex. : Pour convertir “123" on aura successivement comme total :
0x10+1 (lu), puis 1x10+2(lu) soit 12, puis 12x10+3(lu) soit 123 c’est ce que fait la routine “atoi”
i conversion ASCII -> FFP I
I_I
Fix EQU -30
Fit EQU -36
Cnp EQU -42
Tst EQU -48
Abs EQU -54
Neg EQU -60
Add EQU -66
Sub EQU -72
Mul EQU -78
Div EQU -84
Floor EQU -90 ; calcule le plus grand entier inférieur ou égal à DO
Ceil EQU -96 ; calcule le plus petit entier supérieur ou égal à DO
"mathieeedoubbas"
move.l _doubbasbase,a6 move.l 321,dO jsr Flt(a6) move.l _dtbase,a6 jsr Tieee(a6) move.l _mtbase,a6 jsr Fieee(a6) move.l _ffpbase,a6 jsr Fix(a6)
321 pour essayer
traduit 321 en IEEE
"mathieeedoubtrans"
traduit 321 en ieee simple précision
"mathtrans"
traduit 321 en FFP
"mathffp"
donne D0 = 321 ($ 141) en mode trace
i-----------1
I MATH: routines TRANSCENDENTALES I
I____________I
Atan EQU -30
Sin EQU -36
Cos EQU -42
FI
Tan
EQU
- 48
Sincos
EQU
- 54
Sinh
EQU
- 60
Cosh
EQU
- 66
Tanh
EQU
- 72
Exp
EQU
- 78
Log
EQU
- 84
Pow
EQU
- 90
Sqrt
EQU
- 96
Tieee
EQU
- 102
Fieee
EQU
- 108
Asin
EQU
- 114
Acos
EQU
- 120
LoglO
EQU
- 126
I-
I routines EXEC:
I_
OldOpenLibrary =-408
CloseLibrary =-414
run:
move.l ffpname,al moveq 0, dO move.l 4,a6 jsr OldOpenLibrary(a6)
move.l dO,_ffpbase beq fin move.l d0,a6 lea ascii,aO move.b (a0),d0 clr.l signe cmp.b "-",d0 bne rl
; adresse tpn ascii ; 0 si positif
move.l fl,signe add.l l,a0 rl: bsr atoi move.l dO,pent clr.l pdec clr.l ndec clr.l dO tst.b (aO)+ beq r2 bsr atoi move.l dO,pdec move.l d3,ndec subq.l 41,d3 move.l 110,dO jsr fit(a6) move.l d0,d4 moveq.1 41,dû jsr flt(a6) bclel: move.l d4,dl jsr mul(a6) dbra d3,bclel move.l d0,dl move.l pdec,d0 jsr div(a6) r2:
1 si négatif avancer d'un caract.
- > D3 = nbre de chiffres
- > DO = val entière FLT, AO pointe sur dernier caract lu + 1 0 si partie déc. Absente 0 si pas de chiffre
; pas de partie déc.
; -> DO = part déc et D3 = nbre de ch.
; 10 en FLT
; calcule 10 exp ndec en FLT ; de côté
; divise pdec par 10 exp ndec
move.l d0,dl move.l pent.dC jsr add(a6) tst.l signe beq r3 jsr neg(a6) r3:
; partie ent. En FLT ; + partie déc. En FLT
; positif ; prend l'opposé
; si on veut stocker le résultat
move.l dO,resul
move.l _ffpbase,ai move.l 4,a6 jsr CloseLibrary(a6) fin: rts
atoi: ; CE: AO pointe sur 1er caract. D'un nbre entier en ASCII.
; CS: DO = val entiere FLT, D3 = nbre caract.
; AO = pointe sur dern val + 1.
Clr.l d2 move.b (a0),d2 sub.l 4$ 30,d2 move.l d2,d0 jsr fit (a6) move.l d0,d5 move.l 410,dO jsr fit(a6) move.l d0,d4 moveq.1 41,d3 addq.l 41, aO move.l d5,d0 al:
tst.b (aO) beq fatoi cmp.b a0) beq fatoi cmp.b (aO) beq fatoi move.b (a0),d2 sub.l $ 30,d2 move.l d4,dl jsr mul(a6) move.l d0,d5 move.l d2,d0 . Jsr fit(a6) move.l d5,dl jsr add(a6) addq.l l,d3 addq.l 41,aO bra al fatoi: rts
; 1er chiffre en FLT ; 10 en FLT
; fin de chaine ?
; séparateur ?
; séparateur ?
; nbre courant x 10 en FLT
; chiffre courant en FLT
; + nbre courant ; un chiffre de plus
even
ascii: dc.b ”-123,45'',0 ; pour les essais even
signe: dc.l 0 pent: dc.l 0 pdec: dc.l 0 ndec: dc.l 0 resul: dc.l 0
even
_ffpbase: dc.l 0
ffpname: dc.b "mathffp.library",0
Ce source fonctionne mais il n’est pas possible de vérifier à la fin le résultat à moins de le multiplier par 100, de prendre la valeur absolue avec jsr Neg(A6) et de le convertir en entier avec jsr Fix(A6). En mode trace, cela affichera DO = 12345 soit $ 3039.
Je vous laisse découvrir les limites de ce mode en essayant plusieurs chaînes ascii de la forme : “-4578,5”,”458.67849”, etc.
Pour la conversion en mode IEEE, les routines sont légèrement compliquées car il faut considérer des paires de registres, mais le principe est le même :
Ce programme transforme un nombre ASCII en DP I
(flottant, double précision)
MATH : routines de base
Fix
EQU
- 30
Fit
EQU
- 36
Cmp
EQU
- 42
Tst
EQU
- 48
Abs
EQU
- 54
Neg
EQU
- 60
Add
EQU
- 66
Sub
EQU
- 72
Mul
EQU
- 78
Div
EQU
- 84
Floor
EQU
- 90
Ceil
EQU
- 96
1 MATH: routines TRANSCENDENTALES
1
Atan
EQU
- 30
Sin
EQU
- 36
Cos
EQU
- 42
Tan
EQU
- 48
Sincos
EQU
- 54
Sinh
EQU
- 60
Cosh
EQU
- 66
Tanh
EQU
- 72
Exp
EQU
- 78
Log
EQU
- 84
Pow
EQU
- 90
Sqrt
EQU
- 96
Tieee
EQU
- 102
Fieee
EQU
- 108
Asin
EQU
- 114
Acos
EQU
- 120
LoglO
EQU
- 126
routines EXEC:
OldOpenLibrary = -408
CloseLibrary = -414
run:
move.l doubname,al moveq 0,d0 » move.l 4,a6 jsr OldOpenLibrary(a6) move.l d0,_doubbasbase beq fin
; ouvre mathieeedoubbas.library
adresse tpn ascii convertit
lea ascii,a0 jsr AtoDP
move.l _doubbasbase,al move.l 4,a6 jsr CloseLibrary(a6) fin: rts
; referme mathieeedoubbas.library
AtoDP: ; CE: A0 pointe sur le nombre ASCII terminé par un zéro CS: RESUL contient la valeur IEEE move.l _doubbasbase,a6 move.b (a0),d0 clr.l signe ;0 si positif cmp.b "-",d0 bne rl
move.l 1,signe add.l fl,a0 rl:
1 si négatif avancer d'un caract.
- > D7 = nbre de chiffres
- > D0 D1 = val entière FLT, AO pointe
dernier caract lu + 1 0 si absente 0 si pas de chiffre
bsr atoi sur
movem.l d0-l,pent clr.l pdec clr.l ndec clr.l dO clr.l dl tst.b (aO)+ beq r2 bsr atoi
pas de partie déc.
- > D0 D1 = part déc et D7 = nbre de ch.
Movem.l d0-l,pdec move.l d7,ndec subq.l l,d7
move.l d7,d4 ; compteur
move.l 10,dO
jsr fit(a6) ; 10 en FLT
movem.l dO-l,interm ; dans interm
moveq.l l,d0
js:: fit (a6)
bclel:
movem.l interm,d2-3
jsr mul(a6)
dbra d4,bclel
calcule 10 exp ndec en FLT
move.l d0,d2 ;
move.l dl,d3
movem.l pdec,d0-l
jsr div(a6)
divisé pdec par 10 exp ndec
r2:
move.l d0,d2
move.l dl,d3
movem.l pent,d0-l
jsr add(a6)
+ pdec en FLT
tst.l signe
beq r3
positif
jsr neg(a6)
prend l'opposé
r3:
movem.l d0-l,resul
rts
atoi: ;CE: A0 pointe sur 1er caract.
;CS: D0 D1 = val entière format IEEE.
; D7 = nbre caract.
; A0 - pointe sur dern val + 1.
Clr.l d2
move.b (a0)+,d2
move.l a0,-(a7)
sub.l 530,d2
move.l d2,d0
jsr flt(a6)
; 1er chiffre en DP
movem.l d0-l,interm
move.l 10,dO
jsr fit(a6)
; 10 en DP
movem.l d0-l,tpl0
moveq.l l,d7
movem.l interm,d0-l
atl:
move.l (a7)+,a0
tst.b (aO)
beq fatoi
cmp.b ".",(aO)
beq fatoi
cmp.b ",",(aO)
beq fatoi
move.b (a0)+,d6
move.l a0,-(a7)
sub.l $ 30,d6
movem.l tpl0,d2-3
jsr mul(a6)
; nbre courant x 10 en DP
movem.l d0-l,interm
move.l d6,d0
jsr fit(a6)
; chiffre courant en DP
movem.l interm,d2-3
jsr add(a6) '
; somme des deux
addq.l l,d7
bra atl
; chiffre suivant
fatoi:
rts
ascii: dc.b "321.1234567E
'',0
even
signe: dc.l 0
pent: dc.l 0,0
; 2 mots longs en double
pdec: dc.l 0,0
; précision ( IEEE )
ndec: dc.l 0,0
resul: dc.l 0,0
interm: dc.l 0,0
tplO: dc.l 0,0
even
doubbasbase: dc.l 0
doubname: dc.b "mathieeedoubbas.library",0
La suite de cet article sera publiée le mois prochain.
IBHCÜB BBHP
REQUESTER
Question : Fou de programmation en assembleur, j’ai beaucoup apprécié la série d’articles sur le blitter. J’aimerais cependant en savoir plus sur les points suivants :
- programmation du blitter dans une copper-list
- obtenir une animation de 50 images seconde
- animation de bobs, détection des collisions de bobs
- scrollings différentiels (!!)
Cela peut paraître beaucoup, mais j’espère que vous publierez des programmes d’applications sur le blitter. Je fais confiance à l’ANT pour m’éclairer car c’est le seul moyen que j’ai pour apprendre à programmer sérieusement, la “doc” française étant franchement mauvaise sur ce sujet. Encore bravo et félicitations à l’ANT. ,
Guilbert Cyrille
(qui a oublié de donner son adresse)
Réponse : Programmer le blitter dans une copper-list ? Mais rien de plus simple si vous êtes déjà capable d’établir une copper- list élémentaire du type de celle qui ferait un dégradé de la couleur de fond de l'écran (NDLR : de la grand-mère de mon mari de la sœur...). Si vous savez faire ça (si vous ne savez pas regardez donc mon petit programme du n° 21 “exemple de boot), vous savez que le copper peut écrire des valeurs dans les registres machine dont font partie les registres du blitter. Il n'y a donc qu’à initialiser les registres dudit blitter de cette manière au lieu de le faire par le microprocesseur. Il y a cependant une précaution à prendre : de même qu’il fallait s’assurer que le blitter ait fini de travailler avant d’y accéder par le 68000, de même, il faut que le copper s’assure que le blitter soit effectivement disponible. Pour cela, il suffit de mettre le bit RFD de l’instruction copper WA1T à zéro. Ainsi le copper ne touchera pas le blitter si celui-ci est occupé. Pour plus de renseignements vous pouvez consulter la bible de l’amiga ou l’Amiga Hardware Référence Manual page 31.
Une animation de 50 images par seconde ? Encore plus simple.
Il faut savoir que le faisceau d’électrons (“raster’j qui crée l’image sur le moniteur “revient” tout les 50e de seconde donc 50 fois par seconde. Chaque fois que le raster est en haut de l’écran le copper commence l’exécution de sa copper-list, on a donc déjà, comme Monsieur Jourdain qui faisait de la prose sans le savoir, une animation de 50 images par seconde !
Dans mon article “blitter-scrolling”, le programme lit dans un registre machine la position du raster et le scrolling en question est donc lui aussi une animation (certes modeste) de 50 images par seconde. Notez également que l’image qui scrolle n’est ni plus ni moins qu'un bob (rudimentaire car à un seul plan de bits) et que l’obstacle est un autre bob tout simplement immobile. Ce qui a été dit à propos du test de collision est évidemment valable si le deuxième bob eut été animé. Pour animer des bobs beaucoup plus colorés, il suffit de “scroller” chaque plan de bits avant le passage du raster. Pas de panique, même si le programme paraît très long, le blitter travaille tellement vite que tout va très bien. D’autres moyens d’animation? Reportez-vous à l’article du n° 25 “Animation de sprite sous IRQ” où la routine d’interruption IRQ3 est détournée. On peut encore installer un serveur d’interruption du niveau convenable avec exec.library ou faire une requête d’interruption dans le hardware comme expliqué page 61 de l’Amiga Hardware Référence Manual. En ce qui concerne les scrollings différentiels, j’ai donné dans mon article le moyen d’obtenir des vitesses de scrollings variables. Il n’y a plus qu’à programmer deux scrollings de vitesses différentes lors d’un même passage du raster (on a le temps, le blitter travaille vite ) pour obtenir l’effet recherché. A l’occasion je vous ferai un petit article d’explication sur les interruptions mais patience, il y a tant à dire sur l’Amiga...
0
Question : Cher Frédéric Mazué (NDLR : suspense insoutenable, est-ce une charmante admiratrice qui s’adresse à moi si agréablement ?) Tout d’abord, félicitations pour TANT, c’est la partie de Commodore Revue que je préfère. Voici la question que je me pose (ainsi que tous ceux qui veulent écrire leurs propres boot- blocks) : quel est l’étrange petit programme qui se trouve sur un boot-block “normal”. J’ai vu qu’il faisait un test, mais je ne sais pas lequel ! Pourquoi n’y a-t-il pas simplement un RTS (4E75) ?
Ewalenko Bernard (Ramatuelle) (NDLR : zut ! C’est raté pour l’admiratice une prochaine fois peut-être ...)
Réponse : L’étrange petit programme en question cherche l’adresse de base de la dos.library ce qui est une manière de vérifier que la structure résidante correspondante est bien installée. Si ce n'est pas le cas nous aurions une petite méditation du gourou de n° 30000001. Mais alors, me direz -vous, à quoi sert ceci, puisque la dos.library est en ROM et donc qu’elle a 100 % de chance d’être convenablement installée ? (Remarque ô combien pertinente, d’autant plus que finalement c’est moi qui l’ai faite ! ). Je pense que ceci est un reliquat de l’ancien temps des Amiga 1000 où le Kickstart était chargé à partir d’une disquette. Il fallait alors bien vérifier que tout était correct. De cela on peut déduire que le programme boot est un tantinet désuet, mais il ne faut cependant jamais l’omettre car chaque version du kickstart continue de l’exiger. Chez Commodore on aime bien tester plusieurs fois une même chose afin d’être bien sûr que tout va bien. Un peu comme ceux qui mettent une ceinture ET des bretelles à leur pantalon... Mais j’y pense, dans le CR n° 20, il y a un excellent article sur les boot-blocks et un non moins excellent installateur de boot-block écrit par un certain F.M . Courez l’acheter immédiatement ( le CR n° 20 bien sûr, pas le F.M).
0
Question : Frédéric Mazué (NDLR : est-ce l’admiratice tant attendue ?)
Bonjour, avant tout, mauvaise nouvelle. Bien que cette lettre te soit adressée personnellement, ce n’est pas pour te féliciter, ni pour te poser une question sur tes articles (désolé), mais pour discuter avec toi d’un article paru dans CR n° 23 p 72-75, dans lequel l’un de tes confrères dit que le mode “dynamic ham” consiste à changer 16 couleurs de la palette tous les 16 points. Ayant moi-même essayé d’en faire autant, j’en suis arrivé à changer seulement 1 couleur tous les 16 points (haute résolution, 2 bitplanes) Qu’en penses-tu ? Ne voulait-il pas plutôt dire 16 couleurs toutes les lignes ? Pourrais-tu envisager de disséquer un peu ce mode graphique, en particulier la structure de la copper- list associée ? Ce qui a motivé cette lettre, ce n’est pas le plaisir de mettre Commodore Revue en défaut, mais le désir d’acquérir des connaissances, que je compte mettre en application. [...] Tu te demandes peut-être pourquoi je t’ai envoyé cette lettre à toi personnellement ? Et bien pensant (à tort ?) Que Laurent Charbonnel était peut-être plus intéressé par l’utilisation des logiciels que par leur programmation, j’ai voulu m’adresser à quelqu’un qui serait sans doute intéressé lui aussi de connaître la réponse à ma question. Or vu les astuces parfois employées dans tes articles ... bref je t’ai choisi.
Baudrin Gérald (Marly)
(NDLR : flûte, c’est encore raté pour l’admiratrice).
Réponse : Fichtre ! Que d’honneur. J’espère que le grand patron lira tout ça, et qu’il se rappellera que m’octroyer une petite augmentation serait vraiment du meilleur aloi car j’en aurais bien besoin pour soigner mon SIDDA. (SIDDA = Salaire Inchangé Depuis Des Années). (Note du directeur “je signale à tous les pigistes que je ne suis pas un banquier, mais un homme libre"). Ainsi il s’agit de discuter, voilà qui convient à merveille à un bavard comme moi, d’autant plus que Commodore Revue n’est pas mis en défaut. Les 16 premiers registres couleurs sont bien
GROUPE ALLIANCE
VIDEO SHOP
260, rue de Charenton 75012 Paris Tél. : 43.43.00.64
251, bd Raspail, 75014 Paris-Tél. : 43.21.54.45
de]
oie
REMISE 10 % Adhérents Club
Egalement disponible chez :
VIDEO SHOP
50, rue de Richelieu 75001 Paris Tél. : 42.86.03.44
VIGILANTE 320
WORLD GAMES 290
WORLD SOCCER 285
WORLD GRAND PRIX 99 WONDERBOY. 285
WONDERBOY2 285
WONDERBOY 3 320
Y’S 395
ZILLION 2 285
ROCKY SLAP SHOT SCRAMBLE SPIRIT SHINOBI
SECRET COMMAND SUPER TENNIS TENNIS ACE THUNDERBLADE TEDDY BOY
290
320
290
320
99
99
320
290
320
99
320
320
395
320
290
290
325
99
GLOBAL DEFENSE 99 GOLDEN AXE 320 GOLVELIUS 320
GREAT GOLF 265 GREAT BASKETBALL 285 GREAT VOLLEY BALL 285 KUNGFUKID 265 LORD OFTHE SWORD320
NINJA
OPERATION WOLF PSYCHO FOX PHANTASY STAR RC GRAND PRIX RASTAN RAMPAGE RTYPE
RESCUEt MISSION
DEAD EAGLE 290
DOUBLE DRAGON 320
DYNAMITE DUX 320
ENDURO RAGER 99
FANTASY ZONE 99
FANTASY ZONE 2 290
FANTASY ZONE 3 265
GALAXY FORCE 320
GHOSTBUSTEtj 290 MIRACLE WARRIOR 395
ALTERED BEAST 290
BATTLE OUT RUN 320
BASKETBALL NIGHTMARE 290
BLACK BaT 285
CALIFORNIA GAMES 290
CHASE HQ 320
CHOPUFTER 285
CLOUO MASTER 290
Console 690 F Master System 990 F Super System 290 F
ACTION FIGHTER 99 AFTER BURNER 320 ALEX KIDD 265
ALEX KIDD 2 290
ALEX KIDD 3 285
SEGA
8
BITS
Garantie totale 2 ans
RUSH'N ATTACK
340
SIMONS OUEST
390
SOLOMON'S KEY
320
SECTION Z
340
SOCCER
290
SUPER MARIO 2
390
TRACK&FIELD2
390
TIGERHEU
320
WIZARTS & WARRIORS
340
690 F
GHOST'N GOBLINS GRADIUS IKARI WARRIOR CE HOCKEY UNK (ZELDA 2)
UFE FORCE LÊGEND OF ZELDA MAGAMAN RYGAR
ROBOT WARRIOR
320
320
340
290
390
340
390
340
340
340
Console
KLAX
299
N0 EXIT
299
TENNIS CUP
299
OPERATION THUNDER30LT
299
BATMAN
299
DOUBLE DRAGON
299
BARBARIAN 11
299
FIRE AND F0RGET II
299
ALPHA MISSION AIR WOLF COBRA TRIANGLE CASTLE VANIA DRAGON BALL DONKEY KONG CLASSIC 290 RIGHTING GOLF 390
GALAGA 320
NINTENDO
AMSTRAD GX 4000 990 F
345
SOKOBAN
345
345
SPACE HARRIER II
345
345
SUPER HANG ON MOTO
345
345
SUPER MASTER GOLF
345
345
SUPER MONACO GP
380
390
SUPER SHINOBI
345
350
TATSUJIN
345
345
THUNDERFORCE II
345
380
TURBO OUT RUN
380
345
WHIP RUSH
345
345
WORLD CUPSOCCER
345
345
ZOOM
345
FORGOTTEN WORLD GHOSTBUSTERS GHOULS AND GHOSTS GOLDEN AXE HERZOG2 HURRICANE1943 KEN LAST BATTLE LEYNOS MOONWALKER NEWZEALANDSTORY PHELIOS RAMBO III
MEGADRIVE
NEO-GEO SNK
CONSOLE
3490 F
GOLF
1990 -
MAHJONG
1990
BASEBALL
1990
MAGICIAN LORD
1990
NAM 1975
1990
345
380
345
345
345
345
345
345
BASKETBALL
3ATMAN
COLUMNS
CURSE
DARWIN 4081
DJBOY
ES-WAT
FINAL BLOWBOXING
Console + 2 jeux 1690 F Megadrive +
moniteur 2290 F
3615 VS
Toutes les nouveautés et astuces sur les consoles Tous les nouveaux
345
345
345
290
KFTER BURNER 2 AIR OIVER ALTERED BEAST ALEX KID
V
¦ ami mm
[ FORMATION FOOTBALL
329
LEGENDARY AXE
390
POWER DRIFT
390
SPLATTERHOUSE
390
pr: hNïi Nh
1 GALAGA 88
390
MRHEU
450
POWER LEAGUE BASEBALL
290
SUPERSTAR SOLDIER
329
¦ Ml
m vin v mi
M -“T. GONOLASPEED
329
NAXAT OPEN GOLF
390
RADIO LEPUS SPECIAL
329
SUPER VOLLEYBALL
329
GUNHED
390
NEWZEALANDSTORY
390
RASTAN SAGA 2
329
T1GER ROAD
390
Console 1290 F
DEVIL CRUSH
390 HEAVY UNIT
390
NINJA SPIRIT
329
ROAD RUNNER
290
VIGILANTE
390
Suoer GRAFX 2490 F
DIE HARO
329 HELL EXPLORER
329
NINJA WARRIOR
390
SHINOBI
390
WORLD BEACH VOLLEY
290
vUUvi unm a ev i
DOWNLOAD
390 HONEYIN THE SKY II
329
OPERATION WOLF
329
SHOW MOMOTARO
329
WORLD COURTTENNIS
340
BATMAN 329
DRAGON SPIRIT
390 IMAGE FIGHT
329
P47
390
SIDEARMS
390
W-RING
329
BLUE BLINK 340
F1 CIRCUS
329 KINGOFSWORDII
329
PC KID
390
SPACE HARRIER
290
XEVIOUS
290
CHASE HO 390
F1 TRIPLE BATTLE
390 KLAX
329
PUZNIC
390
SPACE INVADER
329
SOLAR STRIKER
160
SPACE INVADERS
220
SUPER MARIOLAND
160
TENNIS
220
TETRIS
160
VOLLEYBALL
220
WORLD BOWLING
220
- §K-
DISQUETTES 3" 1 2 DF DD
par 10 : 3,90 F l'unité par 100 : 3,50 l'unité
TITRES
Participation aux frais de port et d'emballage + 15 F
* TOTAL à payer :
Règlement : je joins ? Chèque bancaire ? CCP ? Mandat-lettre 0 CB ? Je préféré payer au facteur i réception (en ajoutant 30 F pour frais de rembt.)
J L
_L
Date d'expiration ....J.....
GAMEBOY
DOUBLE DRAGON HYPER LOAD RUNNER
220
220
CONSOLE
590 F
KEN
MICKEY MOUSE
220
220
ALLEYWAY
160
MOTOR CROSS NAVY BLUE
220
220
BATMAN
160
PINBALL
220
BOXING
220
POPEYE
220
CHESS
220
SOCCER BOY
220
CODE POSTAL ... VILLE
Tél ......
J_l I I I I L
NOM .
ADRESSE
J L
N° Carte Bleue Signature :
VENTE PAR CORRESPONDANCE à adresser uniqument à :
VIDEO SHOP VPC
BP 105 75749 PARIS CEDEX 15
CONSOLE
1390 F
GAUNTLET
290
CALIFORNIA GAMES
290
GATES OF ZEN DOCON
290
BLUE LIGHTING
290
ELECTRO COP
290
CHIPS CHALLENGE
290
REPRISE ANCIENNES CONSOLES ATARI, MATTEL, COLECO, VECTREX*
* Pour tout achat minimum de 2000 F
Livraison sous 24 h en Coliss[mo Express CONSOLE PRIX
C827
changés tous les 16 points dans ce mode “Dynamic Ham”. Comment est-ce possible ? Très simple. En mode haute résolution, l’instruction WAIT du copper peut être programmée tous les 8 points. New Tek a choisi une bonne solution : utiliser WAIT tous les 16 points. Voilà qui est rusé car l’écran ouvert par Digi View
4. 0 est à 4 plans de bits et peut donc théoriquement supporter 16 couleurs et ceci offre la possibilité suivante : le copper attend que le raster soit en bonne position et lorsque que c’est le cas il change (car ainsi le veut la copper-list) les 16 premières valeurs de couleurs dans les registres machine puis il a juste le temps de tester la nouvelle position du raster et ainsi de suite. Le moins que l’on puisse dire est que le copper et les canaux DMA sont accaparés par ce procédé et que la copper-list est vraiment très longue, ce qui justifie la remarque de Laurent Charbonnel : l’Amiga ne peut plus faire autre chose que de nous afficher une très belle image ! Mais pour ce qui est du nombre de couleurs différentes possibles, il est tellement élevé que je n’ai même pas le courage de faire le calcul. Votre routine ne marche pas ? Désolé mais c’est normal puisque vous utilisez seulement 2 bit- planes donc seuls les 4 premiers registres couleurs seront utilisés, et il n’est plus possible de changer les couleurs que 4 par 4. De plus si vous arrivez à ne changer qu’une couleur c’est probablement parce que vous allumez les points dans un seul des deux bitplanes ou bien que vous ne modifiez pas les quatre premiers registres couleur. Par exemple mettre une valeur dans le registre 31 est inutile car le nombre de bitplanes est insuffisant pour que ce registre ne soit jamais pointé. Voilà.
0
Question : Salut Maxou... (NDLR : décidément pour l’admiratrice, j’ai tout faux)
Mon pote et moi sommes deux fans de l’Amiga. Nous avons quelques questions à te poser.
- Toutes les 5 minutes environ, nos Amiga plantent : l’écran se vide en gardant la couleur du fond et il n’y a plus rien à faire. C’est comme lorsqu’on désactive les canaux DMA ; y aurait-il un problème de ce côté ?
- Si tu n’as pas de solutions, la meilleure chose à faire est de sauvegarder nos listings à des intervalles réguliers. Mais encore faut- il y penser. Pourrais-tu nous dégoter une routine qui se chargerait de le faire toutes les 2 mn par exemple ?
- D’autre part, nous recherchons une routine permettant de sélectionner des bandes fixes sur l’écran à la manière des menus déroulants sauf qu’ici les menus seront déroulés. (NDLR : ??!%&$ ??) (Marie, tout cela est très normal).
- N’as-tu jamais songé à l’indépendance de TANT ?
- Nous souhaiterions également de plus amples informations au sujet de A.M.O.S: peut-on créer aussi rapidement qu’il est dit des jeux el ou des démos ? Que penses-tu d’un article en détail sur ce langage ?
En espérant que tu répondras prochainement à notre lettre, nous
te laissons méditer tel un Gourou en Chaleur ..
Scrap & Lolo (Aix-les-bains) (NDLR : Cette fois c’est fini : pour l’admiratrice j’abandonne !)
Réponse : Je réponds à la place de Max qui, c’est bien connu, en fait toujours un minimum. Vos deux machines ont la même panne ??? A mon avis pas de doute, il s’agit du virus Byte Bandit ou d’un de ses clones. Il faut utiliser un chasseur de virus pour nettoyer tout ça. Moi j’aime bien VirusX 4.0 mais il en existe plein d'autres dans le domaine public. Si c’est le Byte Bandit en personne (qui effectivement coupe le DMA après 5 minutes environ), il existe un truc : appuyer sur les 5 touches Alt-Commodore- Espace-Amiga-Alt simultanément ramène l’ordinateur à la vie. Il n’est pas envisageable de faire la routine de sauvegarde demandée si l’éditeur employé ne possède pas un port Arexx ou n’utilise pas le clipboard.device. Effectivement il faudrait modifier le programme de l’éditeur lui-même et ce n’est pas très légal sans la permission de l’auteur. Pour la souris : soit Intuition est utilisée et les IntuiMessages fournissent les coordonnées de la souris si le flag REPORTMOUSE est activé soit il faut aller lire le contenu des registres JOYODAT ou JOY1DAT dans le hardware. L’ANT indépendante nous y pensons depuis longtemps mais ce n’est pas encore pour tout de suite, patience...
0
Question : Je vous remercie tout d’abord pour l’aide que vous m’avez apporté au sujet de mon problème avec le format IFF. Ainsi j’ai pu commencer à développer une routine d’affichage d’une image IFF en 320*200 et en huit couleurs, mais je souhaiterai que vous me disiez pourquoi elle ne marche pas. De plus je souhaiterais que vous me disiez comment est structurée la partie RODY du format IFE [...]
Dumonl Frédéric (Gorcy)
Réponse : Aaargh !! Ce sympathique lecteur m'envoie un listing de 4 pages ! Il fait beaucoup trop chaud pour que j’ai le courage de m’y plonger. Avis à la population : dans un cas comme ça, il faut envoyer un programme sur DISQUETTE. La partie BODY maintenant. Voyons : 8 couleurs impliquent 3 bitplanes. Un bit- plane a une taille de (320*200) 8 = 8.000 octets. Comme il y a trois bitplanes le BODY doit contenir 8000*3 = 24.000 octets. Maintenant il faut savoir que l’image est définie ligne par ligne. Ceci veut dire qu’il faut lire les 40 (pour une ligne) premiers octets et les placer dans le premier bitplane, puis lire les 40 autres et les placer dans le deuxième bitplane puis encore 40 octets dans le troisième bitplane et la PREMIERE ligne de l’image est ainsi reconstituée. Incrémenter les pointeurs et recommencer le processus pour chaque ligne. Pour le reste l’article de Max est très clair.
0
Question : Ronjour ! Je vous écris au sujet du programme “Sectorise” de TANT de CR n° 17 (ça fait un bail pas vrai ?). Ce programme est écrit sous Lattice C. Comme je fais toujours tout dans le mauvais sens (NDLR : honni soit qui mal y pense !), il se trouve que je possède l’Aztec C (v3.40 je crois). Donc, j’aurais aimé savoir si l’adaptation en Aztec nécessite des modifications et si oui lesquelles. Autre chose de plus technique à vous demander : je possède un Amiga 2000A et à chaque démarrage l’écran s’affiche d’abord vert, puis gris foncé. Alors d’après vous, est-ce que ce vert pourrait provenir d’une panne interne (je pense aux circuits genre Denise et ses copines, ou autres) ? Voilà, j'ai fini, j’arrête de vous embêter et je vous laisse travailler malgré la chaleur...
C. Mathieu (Aix-les-bains)
Réponse : Vous possédez un compilateur Aztec ? Que faire dans Inca comme celui-ci ? Facile : rien. Une source en C doit pouvoir être compilée par n’importe quel compilateur C, c’est un des nombreux avantage du C (pour ceux qui ont de petits moyens, il existe des compilateurs C dans le domaine public). Comme le précise l'auteur de l’article, les instructions : ttinclude “proto dos.h” et include”proto exec.h’’ sont spécifiques au Lattice et vous devez donc les supprimer et rien ne devrait pêcher, quoiqu’avec un aztec on ne sait jamais... (je ne le referais plus promis). De plus les fichiers script contenant les commandes de compilation n’iront qu’avec le Lattice. Consultez votre notice pour les commandes de compilation Aztec. Une couleur jaune, rouge ou ... verte est normalement le signe qu’un circuit spécialisé est en panne. Mais dans votre cas, puisque l’ordinateur accepte quand même de fonctionner, il n’y a rien de grave. Peut-être une poussière mal placée ou un circuit mal enfoncé dans son support (si si, ça c’est déjà vu).
Remède : ouvrir l’Amiga, le nettoyer avec un pinceau propre (pas de produits nettoyant suspects SVP), appuyer délicatement sur les gros composants noirs avec le doigt afin de les remettre en place et il n’y paraîtra plus. Envisager de donner un grand coup de poing sur l’ordinateur histoire de faire d’une pierre deux coups n’est pas une bonne idée ! (ça aussi c’est du déjà vu). C’est vrai qu’il fait chaud. Bonsoir.
Un bail pas vrai ?). Ce programme est écrit sous Lattice C. Comme je fais toujours tout dans le mauvais sens (NDLR : honni soit qui mal y pense !), il se trouve que je possède l’Aztec C (v3.40 je crois). Donc, j’aurais aimé savoir si l’adaptation en Aztec nécessite des modifications et si oui lesquelles. Autre chose de plus technique à vous demander : je possède un Amiga 2000A et à chaque démarrage l’écran s’affiche d’abord vert, puis gris foncé. Alors d’après vous, est-ce que ce vert pourrait provenir d’une panne interne (je pense aux circuits genre Denise et ses copines, ou autres) ? Voilà, j'ai fini, j’arrête de vous embêter et je vous laisse travailler malgré la chaleur...
C. Mathieu (Aix-les-bains)
Réponse : Vous possédez un compilateur Aztec ? Que faire dans Inca comme celui-ci ? Facile : rien. Une source en C doit pouvoir être compilée par n’importe quel compilateur C, c’est un des nombreux avantage du C (pour ceux qui ont de petits moyens, il existe des compilateurs C dans le domaine public). Comme le précise l'auteur de l’article, les instructions : ttinclude “proto dos.h” et include”proto exec.h’’ sont spécifiques au Lattice et vous devez donc les supprimer et rien ne devrait pêcher, quoiqu’avec un aztec on ne sait jamais... (je ne le referais plus promis). De plus les fichiers script contenant les commandes de compilation n’iront qu’avec le Lattice. Consultez votre notice pour les commandes de compilation Aztec. Une couleur jaune, rouge ou ... verte est normalement le signe qu’un circuit spécialisé est en panne. Mais dans votre cas, puisque l’ordinateur accepte quand même de fonctionner, il n’y a rien de grave. Peut-être une poussière mal placée ou un circuit mal enfoncé dans son support (si si, ça c’est déjà vu).
Remède : ouvrir l’Amiga, le nettoyer avec un pinceau propre (pas de produits nettoyant suspects SVP), appuyer délicatement sur les gros composants noirs avec le doigt afin de les remettre en place et il n’y paraîtra plus. Envisager de donner un grand coup de poing sur l’ordinateur histoire de faire d’une pierre deux coups n’est pas une bonne idée ! (ça aussi c’est du déjà vu). C’est vrai qu’il fait chaud. Bonsoir.

Click image to download PDF

AMIGA NEWS TECH numero 16 (10-1990)

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


Thanks for you help to extend Amigaland.com !
frdanlenfideelhuitjanoplptroruessvtr

Connexion

Pub+

32.1% 
18.5% 
5.6% 
5.3% 
4.9% 
4% 
2.8% 
2% 
1.8% 
1.2% 

Today: 19
Yesterday: 94
This Week: 642
Last Week: 669
This Month: 2436
Last Month: 2931
Total: 63504

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