Obligement - L'Amiga au maximum

Dimanche 27 juillet 2025 - 20:22  

Translate

En De Nl Nl
Es Pt It Nl


Rubriques

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

Articles in English


Réseaux sociaux

Suivez-nous sur X




Liste des 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,
ALL


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


Galeries

Menu des galeries

BD d'Amiga Spécial
Caricatures Dudai
Caricatures Jet d'ail
Diagrammes de Jay Miner
Images insolites
Fin de jeux (de A à E)
Fin de Jeux (de F à O)
Fin de jeux (de P à Z)
Galerie de Mike Dafunk
Logos d'Obligement
Pubs pour matériels
Systèmes d'exploitation
Trombinoscope Alchimie 7
Vidéos


Téléchargement

Documents
Jeux
Logiciels
Magazines
Divers


Liens

Associations
Jeux
Logiciels
Matériel
Magazines et médias
Pages personnelles
Réparateurs
Revendeurs
Scène démo
Sites de téléchargement
Divers


Partenaires

Annuaire Amiga

Amedia Computer

Relec


A Propos

A propos d'Obligement

A Propos


Contact

David Brunet

Courriel

 


Programmation : asl.library et GFA Basic
(Article écrit par Guillaume Guittenit et extrait de lesdocs.fr/amiga - juin 2025, mis à jour en juillet 2025)


Sous AmigaOS, la bibliothèque ASL (Application Support Library) affiche une boite de dialogue pour choisir des fichiers, des modes d'écran et des typographies. Cette bibliothèque fut judicieusement implémentée dans le Kickstart 2.0 en 1990, puis mise à jour à chaque évolution du Workbench, jusqu'au dernier Kickstart 3.2.3 sorti en 2025.

asl.library et GFA Basic
La traditionnelle requête ASL dans OctaMED SoundStudio

Le Blitz Basic, le HiSoft BASIC, AQB et le PureBasic fournissent dans leurs exemples d'installation, des codes de requêtes ASL prêts à l'emploi.

asl.library et GFA Basic
Exemple de requête ASL simple avec le HiSoft BASIC

Hélas, le GFA Basic ne reconnaît pas l'asl.library. Pour sélectionner des fichiers, il existe la commande FILESELECT mais elle est peu ergonomique et a un style ancien.

asl.library et GFA Basic
La boite de dialogue du GFA (FILESELECT) est un poil austère...

Mon amour pour ce langage obsolète étant ignoré par la raison, je décide de créer un code 100% GFA pour lancer des requêtes ASL. Je m'appuie sur sa syntaxe "moderne" qui intègre beaucoup de routines du système et permet de gérer les pointeurs.

1. Création de la procédure

Je commence par créer une procédure aslreq() avec quelques paramètres afin que ce code puisse être réutilisable dans n'importe quel autre programme GFA Basic.

@aslreq("Choisis ton fichier","OK","Cancel","","RAM:")
PROCEDURE aslreq(titre$,oktexte$,canceltexte$,fichierdep$,dossierdep$)
   ...
RETURN

2. Ouverture de l'asl.library

J'ouvre l'asl.library avec la fonction système OpenLibrary() gérée nativement par le GFA, puis je récupère en retour l'adresse de base ASL dans la variable "aslbase%" :

aslname$="asl.library"+CHR$(0)
aslbase%=OpenLibrary(V:aslname$,0)

Le nom de la bibliothèque doit se terminer par un caractère nul qui correspond au code ASCII numéro 0 indiquant la fin d'une chaîne de caractères. Il faut donc concaténer un CHR$(0) à la chaîne "asl.library".

Si l'ajout du CHR$(0) vous semble un odieux bricolage, le GFA Basic propose l'instruction CHAR{} permettant de lire ou écrire un texte au format C en ponctuant les textes d'un octet nul :

aslname$="asl.library"
CHAR{aslname$}=aslname$
aslbase%=OpenLibrary(V:aslname$,0)

Dans le premier paramètre d'OpenLibrary(), "V:" désigne le pointeur de la variable "aslname$".

3. Structure FileRequester

Vient ensuite l'allocation d'une structure FileRequester dans laquelle sont indiqués les "tags", à savoir le titre de la fenêtre de la requête, le texte du bouton "OK", le texte du bouton "Cancel", le fichier et le dossier initiaux. Ces indications sont transmises via les paramètres de ma fonction GFA aslreq().

Le GFA Basic ne gérant pas les structures, elle est reconstituée dans la mémoire en se documentant sur le fichier libraries/asl.h des Includes et Autodocs. En voici un extrait permettant de définir les tags utilisés dans le code GFA :

/************************************************************************/
/* Tags for AllocAslRequest() and AslRequest()				*/
/************************************************************************/

#define ASL_Dummy (TAG_USER + 0x80000)

#define ASL_Hail	ASL_Dummy+1	/* Hailing text follows		     */
#define ASL_Window	ASL_Dummy+2	/* Parent window for IDCMP & screen  */
#define	ASL_LeftEdge	ASL_Dummy+3	/* Initialize LeftEdge		     */
#define	ASL_TopEdge	ASL_Dummy+4	/* Initialize TopEdge		     */
#define	ASL_Width	ASL_Dummy+5
#define	ASL_Height	ASL_Dummy+6
#define	ASL_HookFunc	ASL_Dummy+7	/* Hook function pointer	     */

/* Tags specific to file request					     */
#define	ASL_File	ASL_Dummy+8	/* Initial name of file follows	     */
#define	ASL_Dir		ASL_Dummy+9	/* Initial string of filerequest dir */

/* Tags specific to font request					     */
#define	ASL_FontName	ASL_Dummy+10	/* Initial font name		     */
#define	ASL_FontHeight	ASL_Dummy+11	/* Initial font height		     */
#define	ASL_FontStyles	ASL_Dummy+12	/* Initial font styles		     */
#define	ASL_FontFlags	ASL_Dummy+13	/* Initial font flags for textattr   */
#define	ASL_FrontPen	ASL_Dummy+14	/* Initial frontpen color	     */
#define	ASL_BackPen	ASL_Dummy+15	/* Initial backpen color	     */
#define	ASL_MinHeight	ASL_Dummy+16	/* Minimum font height to display    */
#define	ASL_MaxHeight	ASL_Dummy+17	/* Max font height to display	     */

#define	ASL_OKText	ASL_Dummy+18	/* Text displayed in OK gadget	     */
#define	ASL_CancelText	ASL_Dummy+19	/* Text displayed in CANCEL gadget   */

Une Taglist est un tableau de paires : tag-valeur. Le tag est un entier de 32 bits. La valeur a également une taille de 32 bits. Il peut s'agir d'un entier ou d'un pointeur. La Taglist doit se terminer par le tag 0 (Fin de liste). Voici la Taglist que je vais créer :

Tag (4 octets) Valeur (4 octets)
Adresse ASL_Hail Pointeur vers "Choisis ton fichier"
Adresse ASL_OKText Pointeur vers "OK"
Adresse ASL_CancelText Pointeur vers "Cancel"
Adresse ASL_File Pointeur vers ""
Adresse ASL_Dir Pointeur vers "RAM:"
Adresse TAG_END 0

Pour commencer, je réserve une zone de mémoire de 88 octets remplis de zéros (paramètre 65536). La variable "tags%" reçoit l'adresse de départ de la zone réservée :

tags%=MALLOC(88,65536)

Pour déterminer l'adresse de base des tags de la requête ASL, j'additionne le TAG_USER qui vaut &H80000000 et le décalage ("offset") des tags de la requête ASL qui vaut &H80000. La somme des deux donne &H80080000. Le TAG_USER est défini dans utility/tagitem.h et vaut ((ULONG)(1UL<<31)), ce qui fait &H80000000 en hexadécimal (1 décalé de 31 bits vers la gauche). J'écris donc en GFA :

tagasl%=&H80080000

En référence à l'inclusion asl.h, j'écris chaque tag-valeur pour personnaliser la boite de dialogue ASL :

LONG{tags%}=tagasl%+1      ! Titre du requester (ASL_Hail)
titre$=titre$+CHR$(0)
LONG{tags%+4}=V:titre$
LONG{tags%+8}=tagasl%+18   ! Texte OK (ASL_OKText)
oktexte$=oktexte$+CHR$(0)
LONG{tags%+12}=V:oktexte$
LONG{tags%+16}=tagasl%+19  ! Texte Cancel (ASL_CancelText)
canceltexte$=canceltexte$+CHR$(0)
LONG{tags%+20}=V:canceltexte$
LONG{tags%+24}=tagasl%+8   ! Fichier de départ (ASL_File)
fichierdep$=fichierdep$+CHR$(0)
LONG{tags%+28}=V:fichierdep$
LONG{tags%+32}=tagasl%+9   ! Dossier de départ (ASL_Dir)
dossierdep$=dossierdep$+CHR$(0)
LONG{tags%+36}=V:dossierdep$
LONG{tags%+40}=0           ! Fin de liste

En GFA Basic, "LONG{adr%}=x%" écrit la valeur de la variable "x%" sur quatre octets à l'adresse "adr%".

Après avoir renseigné les tags, j'écris un pointeur vers l'endroit où la liste des tags est stockée dans registre "a0" qui correspond à "regs%(8)" :

regs%(8)=tags%

4. Appel des fonctions AllocAslRequest() et AslRequest()

La fonction système AllocAslRequest() n'est pas gérée nativement par le GFA. Je vais donc l'appeler à l'aide de l'instruction GFA Basic "RCALL" dont la syntaxe est :

RCALL adresse, reg%()

L'instruction "RCALL" stocke certaines valeurs dans les registres du processeur avant de lancer une routine assembleur, puis de tester le contenu des registres après exécution de la routine. J'utilise un tableau de seize entiers de quatre octets : reg%(). Avant le lancement de la routine, les entrées du tableau sont copiées dans les registres, et après exécution de la routine, le contenu des registres est écrit dans les éléments correspondants du tableau :

Registres de données d0 à d7 dans reg%(0) à reg%(7)
Registres d'adresse a0 à a6 dans reg%(8) à reg%(14)
User Stack Pointer a7 dans reg%(15) (retour seulement)

Pour appeler une fonction d'une bibliothèque système, je dois placer l'adresse de base de la bibliothèque dans le registre "a6" qui correspond à "regs%(14)" :

regs%(14)=aslbase%

Sous AmigaOS, l'espace d'adressage d'une bibliothèque peut se faire dans les deux sens, ce qui permet l'usage d'un seul pointeur (Library Base). L'adressage avec un décalage négatif permet d'appeler les fonctions de la bibliothèque.

asl.library et GFA Basic
Structure de la bibliothèque de l'Amiga et table de saut

Une fois qu'une application a ouvert une bibliothèque, elle peut commencer à utiliser ses fonctions. Pour accéder à une fonction, une application a besoin de l'adresse de base de la bibliothèque renvoyée par OpenLibrary() et du décalage du vecteur de bibliothèque (Library Vector Offset) de la fonction. Le LVO d'une fonction est le décalage entre l'adresse de base de la bibliothèque et le vecteur de la fonction. Un LVO est un nombre négatif car les vecteurs précèdent la base de la bibliothèque en mémoire.

Voici les décalages indiqués dans le ROM Kernel Manual Includes And Autodocs :

***************** asl
* "asl.library"
##base _AslBase
##bias 30
##public
*--- functions in V36 or higher (distributed as Release 2.0) ---
*
 30 $ffe2 -$001e AllocFileRequest()()
 36 $ffdc -$0024 FreeFileRequest(fileReq)(a0)
 42 $ffd6 -$002a RequestFile(fileReq)(a0)
 48 $ffd0 -$0030 AllocAslRequest(type,tagList)(d0/a0)
 54 $ffca -$0036 FreeAslRequest(request)(a0)
 60 $ffc4 -$003c AslRequest(request,tagList)(a0/a1)
##end

D'après les indications du RKM ci-dessus, la fonction AllocAslRequest() est accessible au décalage -48 en décimal, c'est-à-dire -&H30 en hexadécimal. J'écris donc en GFA Basic :

RCALL aslbase%-&H30,regs%()

Je lance AllocASLRequest() pour réserver une zone mémoire qui servira à inscrire la sélection de l'utilisateur.

La boite de dialogue ASL va finalement apparaître grâce à la fonction AslRequest() qui est appelée avec l'instruction "RCALL" car cette fonction n'est pas gérée nativement par le GFA.

RCALL aslbase%-&H3C,regs%()

asl.library et GFA Basic
Whaouuuuu ! C'est de toute beauté !

Quand l'utilisateur valide sa sélection, le nom du fichier et du dossier sont écrits dans la mémoire. Au décalage 4, j'ai un pointeur vers le nom du fichier, et au décalage 8, un pointeur vers le chemin. Le résultat de la requête est mis dans le registre "d0" correspondant à "regs%(0)". C'est ce que je teste pour savoir si l'utilisateur a cliqué sur "Cancel".

IF regs%(0)
  ' L'utilisateur a choisi un fichier
  fichier$=CHAR{LONG{monfilereq%+4}}
  chemin$=CHAR{LONG{monfilereq%+8}}
  PRINT "Fichier sélectionné : ";fichier$
  PRINT "Chemin : ";chemin$
  PAUSE 100
ENDIF

Le fichier et le dossier sélectionnés seront ensuite lus avec l'instruction "LONG" puis publiés dans une fenêtre avec l'incontournable "PRINT". C'est du BASIC, n'oublions pas !

asl.library et GFA Basic

5. Le code final

Le code complet fonctionne aussi bien en mode interprété que compilé. J'ai tenté de l'écrire de la façon la plus concise possible afin de ne pas trop rougir de la comparaison avec les autres langages.

' ASL Requester en GFA Basic par Guillaume Guittenit
' Ouverture d'une fenêtre
OPENW #5
@aslreq("Choisis ton fichier","OK","Cancel","","RAM:")
PROCEDURE aslreq(titre$,oktexte$,canceltexte$,fichierdep$,dossierdep$)
  ' Ouverture de la asl.library
  aslname$="asl.library"+CHR$(0)
  aslbase%=OpenLibrary(V:aslname$,0)
  IF aslbase%=0
    PRINT "Impossible d'ouvrir la asl.library"
    END
  ENDIF
  ' Allocation d'une structure FileRequester
  tags%=MALLOC(88,65536)     ! Réserve 88 octets remplis de zéros
  tagasl%=&H80080000
  LONG{tags%}=tagasl%+1      ! Titre du requester ASL
  titre$=titre$+CHR$(0)
  LONG{tags%+4}=V:titre$
  LONG{tags%+8}=tagasl%+18   ! Texte OK
  oktexte$=oktexte$+CHR$(0)
  LONG{tags%+12}=V:oktexte$
  LONG{tags%+16}=tagasl%+19  ! Texte Cancel
  canceltexte$=canceltexte$+CHR$(0)
  LONG{tags%+20}=V:canceltexte$
  LONG{tags%+24}=tagasl%+8   ! Fichier de départ
  fichierdep$=fichierdep$+CHR$(0)
  LONG{tags%+28}=V:fichierdep$
  LONG{tags%+32}=tagasl%+9   ! Dossier de départ
  dossierdep$=dossierdep$+CHR$(0)
  LONG{tags%+36}=V:dossierdep$
  LONG{tags%+40}=0           ! Fin de liste
  ' Dimensionnement du tableau de registres pour l'instruction RCALL
  DIM regs%(15)
  regs%(8)=tags%             ! Registre A0
  regs%(14)=aslbase%         ! Base dans le registre A6
  RCALL aslbase%-&H30,regs%()
  monfilereq%=regs%(0)
  ' Appel du sélecteur de fichiers
  regs%(8)=regs%(0)
  RCALL aslbase%-&H3C,regs%()
  ' Le résultat est lu. Si on a zéro, l'utilisateur a sélectionné Cancel
  IF regs%(0)
    ' L'utilisateur a choisi un fichier
    fichier$=CHAR{LONG{monfilereq%+4}}
    chemin$=CHAR{LONG{monfilereq%+8}}
    PRINT "Fichier sélectionné : ";fichier$
    PRINT "Chemin : ";chemin$
    PAUSE 100
  ENDIF
RETURN
' Fermeture de la asl.library et libération de la mémoire
~CloseLibrary(aslbase%)
~MFREE(tags%,88)
CLOSEW #5

Les fichiers sont disponibles ici :
6. Résultat

Le code interprété ou compilé fonctionne nickel sur mon Amiga 1200 avec AmigaOS 3.2.3 :

asl.library et GFA Basic

Le code 68k compilé fonctionne également sous MorphOS. Merci à son compilateur Trance Just In Time :

asl.library et GFA Basic
Étonnant, non ?


[Retour en haut] / [Retour aux articles]


Soutenez le travail de l'auteur