Obligement - L'Amiga au maximum

Mercredi 26 septembre 2018 - 06:23  

Translate

En De Nl Nl
Es Pt It Nl


Rubriques

 · Accueil
 · A Propos
 · Articles
 · Galeries
 · Glossaire
 · Liens
 · Liste jeux Amiga
 · Quizz
 · Téléchargements
 · Trucs et astuces


Articles

 · Actualité (récente)
 · Actualité (archive)
 · Comparatifs
 · Dossiers
 · Entrevues
 · Matériel (tests)
 · Matériel (bidouilles)
 · Points de vue
 · En pratique
 · Programmation
 · Reportages
 · Tests de jeux
 · Tests de logiciels
 · Tests de compilations
 · Articles divers

 · Articles in english
 · Articles en d'autres langues


Twitter

Suivez-nous sur Twitter




Liens

 · Sites de téléchargements
 · Associations
 · Pages Personnelles
 · Matériel
 · Réparateurs
 · Revendeurs
 · Presse et médias
 · Programmation
 · Logiciels
 · Jeux
 · Scène démo
 · Divers


Jeux Amiga

0, A, B, C, D, E, F,
G, H, I, J, K, L, M,
N, O, P, Q, R, S, T,
U, V, W, X, Y, Z


Trucs et astuces

0, A, B, C, D, E, F,
G, H, I, J, K, L, M,
N, O, P, Q, R, S, T,
U, V, W, X, Y, Z


Glossaire

0, A, B, C, D, E, F,
G, H, I, J, K, L, M,
N, O, P, Q, R, S, T,
U, V, W, X, Y, Z


Partenaires

Annuaire Amiga

Amedia Computer

Relec

Hit Parade


Contact

David Brunet

Courriel

 


Programmation : C - Un silencieux pour lecteur de disquette
(Article écrit par Frédéric Mazué et extrait d'Amiga News Tech - octobre 1990)


Heureux de vous retrouver, je vous propose aujourd'hui de mettre un silencieux dans vos lecteurs de disquette. Ce n'est pas plus bête que de vouloir mettre un tigre dans son moteur, c'est moins dangereux et c'est 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 lecteurs, 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 mémoire, puis toutes les adresses de saut sont modifiées afin d'obtenir à nouveau un programme susceptible de fonctionner, puis ledit nouveau trackdisk est modifié afin que les lecteurs ne cliquettent plus. Il suffit en fait de changer un seul octet 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 mémoire.
  • Je n'aime pas ce genre de programmes qui utilisent directement des bouts de ROM sans passer par les bibliothèques 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 bogue. 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 bogues devant l'éternel. En effet, sur un Amiga 500, en amorçant sur disque dur A590, avec une disquette quelconque en DF1: et aucune disquette en DF0: 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 DF0:, 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 qu'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 DF0:. Lorsque le processus DF0: a reçu ce message, il s'occupe tout seul (vive les ordinateurs multitâches !) 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 drapeau 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 drapeau 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 drapeau 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 d'attente (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 d'attente ne ralentit que peu l'ordinateur. Des esprits chagrins m'objecteront également que NoClick n'empêche pas l'accès aux lecteurs contrairement à mon programme. A ceux-là je réponds que si l'on met une disquette dans le lecteur :
  • Le lecteur 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 n'en a pas besoin et dans ce cas l'utilisation de l'attente (alias "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 bogue.
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 périphérique logique est, pour ce qui est des offsets négatifs, structuré comme une bibliothèque. Pour les offsets positifs du trackdisk.device, on trouve d'abord un mot nul afin de pointer sur une adresse multiple de 4, puis quatre longs mots. Ces quatre longs mots sont des pointeurs sur les ports des lecteurs de disquette. 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 :

c

Ainsi est défini un tableau de pointeur sur les ports 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 :

c

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 périphérique logique (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 lecteurs 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.

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 trépelu (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 ! 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 disquette 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 Kernel Manual "Includes And Autodocs", on trouve les structures suivantes :

c

Je ne saurais encore dire à quoi servent les "dp_Arg2" jusqu'à "dp_Arg7", mais par contre "dp_Arg1" est un drapeau qui a l'effet suivant :
  • dp_Arg 1 = -1, le DosPacket est pris en compte par le processus.
  • dp_arg 1 = 0, l'effet du DosPacket est annulé.
On trouve ensuite dans les fichiers includes une autre structure :

c

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 PutMsg() 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.

Disk_Busy

Nous allons maintenant expliquer en détail la fonction Disk_Busy du programme. C'est elle qui permet d'inhiber un processus.

c

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 :

c

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 !). 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 In_Name on a un pointeur sur une chaîne de caractères :

c

Ainsi, dp_Link qui doit être un pointeur sur une structure message est initialisé sur l'adresse de la structure Message du StandardPacket. Les deux structures DosPacket et Standard Packet sont maintenant intimement liées (comme l'indique le nom dp_Link) :

c

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 permets 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 deux lignes suivantes qui parlent d'elles-mêmes. Ensuite nous avons :

c

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 "libraries/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 outils (à 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".

c
c
c
c


[Retour en haut] / [Retour aux articles]