Obligement - L'Amiga au maximum

Samedi 21 octobre 2017 - 23:28  

Translate

En De Nl Nl
Es Pt It Nl


Rubriques

 · Accueil
 · A Propos
 · Articles
 · Galeries
 · Glossaire
 · Hit Parade
 · 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 in other languages


Twitter

Suivez-nous sur Twitter




Liens

 · Sites de téléchargements
 · Associations
 · Pages Personnelles
 · Moteurs de recherche
 · Pages de liens
 · Constructeurs matériels
 · Matériel
 · Autres sites de matériel
 · Réparateurs
 · Revendeurs
 · Presse et médias
 · Programmation
 · Développeurs logiciels
 · Logiciels
 · Développeurs de jeux
 · Jeux
 · Autres sites de jeux
 · Scène démo
 · Divers
 · Informatique générale


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 : Assembleur - une seconde commande Ask
(Article écrit par Frédéric Delacroix et extrait d'Amiga News - juillet/août 1996)


Les rares d'entre vous qui utilisent l'AmigaDOS pour l'écriture de fichiers "batch" trouvent peut-être la commande Ask un peu pauvre avec son mode Y/N. Il y a bien sûr la fonction RequestChoice du Kickstart 3.0 pour des choix un peu plus élaborés, mais elle casse "l'ambiance" du Shell. Voici une troisième solution.

Je dois tout d'abord vous avouer que ceci me sert principalement à vous présenter une possibilité assez méconnue de la dos.library, mais certains trouveront peut-être une réelle utilité à ce programme dans la vie de tous les jours.

Cahier des charges

De quoi avons-nous besoin ? Les principaux défauts de Ask sont le fait qu'elle n'accepte que "Y" et "N" comme réponse et qu'il faille valider la réponse en appuyant sur la touche retour-chariot. Ce serait bien qu'un programme prenne en compte la réponse dès l'appui sur la touche. On voudrait également permettre de multiples réponses (la condition précédente les limitant à une seule touche) autres que Y/N.

Tant qu'à faire, prévoyons un mode multicommandes où on pourrait recevoir plusieurs réponses comme "A", "B", "C" ou "1", "2", "?", et un mode (baptisé "ASK") se comportant comme une commande Ask dont on pourrait changer les réponses attendues et renvoyant les mêmes codes de retour, rendant facile un test par IF WARN et consorts.

La solution

Le principal problème est la première condition, tout le reste n'étant qu'artifices de programmation auxquels vous êtes habitués. En effet, la fenêtre du Shell que vous utilisez est une fenêtre CON:, c'est-à-dire une console en mode "cuisiné" (par opposition à "cru"), où toute ligne est éditable et n'est envoyée au programme qu'après la touche retour-chariot pressée. Tant que vous éditez la ligne, le programme en lecture de la console attend et n'a aucune connaissance de ce que vous faites. Il y a cependant un autre type de fenêtre : les fenêtres RAW:, correspondant au mode "cru" (traduction de RAW) du gestionnaire de console de l'AmigaDOS.

Dans ce mode RAW, tout événement satisfait immédiatement la demande de lecture qui est retournée au programme après conversion ANSI (c'est-à-dire en caractère ASCII ou chaîne ANSI pour les touches de fonction). Il n'y a également pas d'écho automatique des caractères à l'écran. La solution consiste donc à faire passer la fenêtre de console du Shell du mode CON au mode RAW. Ceci se fait par le type de paquet ACTION_SCREEN_MODE ou, à partir du Kickstart 2.0, par la fonction SetMode() de la dos.library (ce qui est beaucoup plus facile). Cependant, un tel passage peut échouer, par exemple à cause de l'utilisation simultanée de la console par plusieurs tâches (lancées par Run).

Il suffit donc de passer en paramètres à cette fonction le canal d'entrée (obtenu par Input()) et le mode voulu (1 pour RAW, 0 pour CON) et le tour est joué. C'est le stratagème utilisé par l'assembleur lorsqu'il a fini l'assemblage et vous demande d'appuyer sur une touche.

Le programme

Baptisé ReadKey, il respecte le cahier des charges décrit ci-dessus. Les arguments et les codes de retour sont détaillés dans le source du programme, je vous y renvoie pour l'usage. La présence (ou non) du mot-clé COMMANDS détermine respectivement le mode multicommandes ou le mode Ask. On a également conservé la possibilité de quitter le programme en appuyant sur la touche "Esc" quel que soit le mode. J'ai de plus ajouté un temps limite grâce à la fonction WaitForChar() de la dos.library. Ce temps est à exprimer en microsecondes (je n'avais pas envie d'allonger le programme avec une routine de multiplication par 1000000).

Remarquons qu'il n'est pas possible, même en mode multicommandes, d'utiliser les apostrophes inverses pour récupérer la lettre produite, étant donné que lorsque le programme est appelé entre de telles apostrophes, le canal retourné par Input() n'est plus valide. Ceci est une restriction de l'AmigaShell. On peut toutefois ruser en détournant la sortie en ENV:Variable puis en la récupérant par un GetEnv Variable.

Tel qu'il est écrit, ce programme ne sait traiter que les séquences d'un seul caractère. Il ne saura donc par exemple distinguer les séquences ANSI des touches de curseur par exemple. A vous d'écrire la version 2.0. :-)

Sur ce, je vous laisse avec le listage du programme et un petit script (pardon, scénario ;-)) AmigaDOS pour vous amuser pendant ces vacances que je vous souhaite excellentes.

Fichier FillData

.bra {
.ket }

; script de test pour ReadKey:
;  execute FillData 
;  créée un fichier base de données à partir des informations saisies au
;  clavier dans le Shell. Ah le bon temps des interfaces simples!

lab EncoreUn
echo "Nom   : " NOLINE
set >NIL: str ?
echo >>{DATABASE} "*N"
echo >>{DATABASE} $str

echo "Prénom: " NOLINE
set >NIL: str ?
echo >>{DATABASE} $str

echo "Sexe  : (H)omme"
echo "        (F)emme"
echo "        (S)ans"
ReadKey >>{DATABASE} COMMANDS="hfs"

echo "Utilisateur de (M)S-DOS ou (A)migaOS ?"
ReadKey YES=m NO=a
if warn
  echo >>{DATABASE} "Individu peu fréquentable."
else
  echo >>{DATABASE} "Personne respectable."
endif

echo "Encore un ?"
ReadKey YES=o NO=n
if warn
  skip EncoreUn BACK
endif

type {DATABASE}

Fichier ReadKey.s

; Programme: ReadKey, version 1.0
;
; arguments:
;   COMMANDS/K: si spécifié, demande le mode multicommandes,
;               seules les touches indiquées seront reconnues
;               (plus ESC). Le caractère correspondant est affiché
;               à l'écran; utilisation > possible, par ex:
;               ReadKey >ENV:Variable COMMANDS="ABC"
;               (on ne peut malheureusement pas utiliser les apostrophes
;               inverses avec l'AmigaShell d'origine, mais on peut ruser
;               de cette façon).
;   YES et NO:  Ne sont pris en compte que si COMMANDS n'est pas spécifié,
;               pour le mode "ASK": se comporte alors comme la commande
;               Ask, avec les touches indiquées pour Y et N (par défaut:
;               y et n). Attention à la casse.
;   TIMEOUT:    Temps limite au-delà duquel le programme se termine. Infini
;               si TIMEOUT est à 0. Exprimé en microsecondes (!).
;               Par défaut:0.
;
; codes de retour:
;   OK (0):     YES en mode ASK, touche reconnue (et affichée) en mode
;               multicommandes.
;   WARN (5):   NO en mode ASK.
;   ERROR (10): temps limite dépassé ou ESC rencontré.
;   FAIL (20):  erreur grave d'initialisation du programme.

            include exec/exec.i
            include exec/exec_lib.i
            include dos/dos.i
            include dos/dos_lib.i

Start       moveq   #20,d7  ; code de retour: erreur fatale
            move.l  4.w,a6
            move.l  a6,Exec.Base
            lea     DOS.Name(pc),a1 ; ouverture de la dos.library
            moveq   #37,d0
            jsr     _LVOOpenLibrary(a6)
            move.l  d0,DOS.Base
            beq     NoDOS
            move.l  #Args.Template,d1   ; lecture des arguments
            move.l  #Args.Array,d2
            moveq   #0,d3
            move.l  DOS.Base(pc),a6
            jsr     _LVOReadArgs(a6)
            move.l  d0,Args.RDArgs
            beq     CloseDOS

            jsr     _LVOInput(a6)       ; canal standard d'entrée
            move.l  d0,Input.Handle     ; (normalement la fenêtre du Shell)
            beq.s   FreeArgs
            move.l  d0,d1
            moveq   #1,d2   ; passe en mode RAW
            jsr     _LVOSetMode(a6)
            tst.w   d0  ; réussi ?
            beq.s   FreeArgs
            moveq   #10,d7              ; code de retour: temps limite dépassé
            move.l  Input.Handle(pc),d1
            jsr     _LVOFlush(a6)

GetLoop     move.l  Input.Handle(pc),d1
            move.l  TimeOut.Arg(pc),d2
            beq.s   .NoWaitForChar      ; pas de timeout: attendre par Read().
            jsr     _LVOWaitForChar(a6)
            tst.l   d0
            beq.s   ToCON   ; si timeout
.NoWaitForChar
            move.l  Input.Handle(pc),d1
            move.l  #Char.Buf,d2
            moveq   #1,d3
            jsr     _LVORead(a6)
            moveq   #20,d7              ; code de retour: erreur fatale
            cmp.l   d0,d3               ; 1 caractère lu?
            bne.s   ToCON               ; non: erreur fatale
            move.b  Char.Buf(pc),d6     ; l'octet lu
            tst.l   Commands.Arg        ; mode Ask ou mode multicommandes?
            bne.s   MultiCommands
            moveq   #5,d7               ; code de retour correspondant à YES
            move.l  Yes.Arg(pc),a0
            cmp.b   (a0),d6
            beq.s   ToCON               ; fini
            moveq   #0,d7               ; code de retour correspondant à NO
            move.l  No.Arg(pc),a0
            cmp.b   (a0),d6
            beq.s   ToCON
            moveq   #10,d7              ; code de retour pour l'échappement
            cmp.b   #27,Char.Buf        ; escape
            bne     GetLoop

ToCON       move.l  Input.Handle(pc),d1
            moveq   #0,d2               ; passe en mode CON
            jsr     _LVOSetMode(a6)     ; ne peut échouer
FreeArgs
            move.l  Args.RDArgs(pc),d1
            move.l  DOS.Base(pc),a6
            jsr     _LVOFreeArgs(a6)
CloseDOS
            move.l  DOS.Base(pc),a1
            move.l  Exec.Base(pc),a6
            jsr     _LVOCloseLibrary(a6)
NoDOS       move.l  d7,d0
            rts

MultiCommands
            move.l  Commands.Arg(pc),a0
.SearchCmd
            cmp.b   (a0)+,d6
            beq.s   .Found
            tst.b   -1(a0)
            bne.s   .SearchCmd
; caractère non trouvé
            moveq   #10,d7              ; code de retour pour l'échappement
            cmp.b   #27,Char.Buf        ; escape
            beq     ToCON
            bra     GetLoop             ; demande un autre caractère
.Found      move.l  #Char.Buf,d1
            moveq   #2,d2
            jsr     _LVOWriteChars(a6)  ; affiche le caractère à l'écran
            moveq   #0,d7               ; code de retour: OK
            bra     ToCON

Exec.Base       dc.l    0
DOS.Base        dc.l    0
Args.RDArgs     dc.l    0
Input.Handle    dc.l    0

Args.Array
Commands.Arg    dc.l    0
Yes.Arg dc.l    Y.String
No.Arg  dc.l    N.String
TimeOut.Arg     dc.l    0

DOS.Name        dc.b    "dos.library",0
Args.Template   dc.b    "COMMANDS/K,YES,NO,TIMEOUT/N",0
Y.String        dc.b    "y",0           ; minuscules/majuscules importantes!
N.String        dc.b    "n",0
Char.Buf        dc.b    0               ; le caractère lu
                dc.b    10              ; et le saut de ligne pour l'affichage.


[Retour en haut] / [Retour aux articles] [Article précédent] / [Article suivant]