Mes astuces en GFA BASIC, sur ATARI ST

(GfA Basic v3.x) par Dadu, 31/07/1992

Voici des astuces qui ne sont pas marquées dans les bouquins. Pour plus d'informations, référez-vous à ces mêmes bouquins.

ADRESSES

Pour stocker un écran graphique ou le manipuler sur STF, il nécessaire que l'adresse de son buffer soit multiple de 256.
Voilà ce qu'il faut:
ecran_phys%=MALLOC(32000) AND &HFFF00
Sans cela, vous aurez droit à de superbes décalages et plantages.

CHARGEMENT DES DONNES

Avec INPUT #1,line$ par ex. L'énorme problème est que lorsque le GFA rencontre une virgule, il considère que la suite est une autre ligne. Le seul "remède" est de remplacer la virgule par un autre caractère peu utilisé (ex: @), et de le remplacer avec une virgule, après que la ligne ait étée chargée.

DATA

En bout de ligne, on a du mal à mettre un texte avec des espaces.
Ex:
DATA CELA EST UN EXEMPLE,CECI AUSSI !
cela donne:
DATA CELA EST UN EXEMPLE,CECIAUSSI!
Le remède:
DATA CELA EST UN EXEMPLE,"CECI AUSSI !"
Le mieux étant:
DATA "CELA EST UN EXEMPLE","CECI AUSSI !"

EDIT, END

Je préfère EDIT, car l'on retourne dessuite à l'éditeur.

a$=INKEY$
L'ennui avec cette instruction, c'est qu'elle ne renvoie pas les codes des touches de fonction, de HELP, de UNDO, ...
KEYTEST c'est du pipeau.
Le seul moyen, c'est d'aller voir directement dans le "hard":
t%=PEEK(&HFFFFC02)
On obtient le "scancode". Il ne correspond pas, bien sûr, au code ascii (ce serait trop simple !).

INLINE

Cette instruction est très utile. C'est un peu comme le INCBIN sous DevPac. A cette ligne, le .GFA contient une routine en assembleur.
La routine doit être totalement relogeable, ne pas utiliser de SECTION BSS (transférer cela dans la SECTION DATA), et se terminer par un RTS.
Pour éviter les problèmes après la compilation, mieux vaut mettre: $C+ au début du listing GFA.

MALLOC, MFREE

Ces instructions sont très utiles. Elles permettent de réserver de la mémoire système (donc pas celle du GFA). L'avantage par rapport à A$, c'est que MALLOC permet d'allouer des blocs mémoires de plus de 32 Ko.
MFREE permet de libérer la mémoire allouée (Memory ALLOCation) avec MALLOC. Il est indispensable avant que le PRG se soit terminé (EDIT ou END).

RCALL et CALL

Ces instructions permettent d'exécuter des routines assembleur qui sont en mémoire (INLINE, MALLOC, ...). La meilleure est RCALL car elle permet simplement de mettre des valeurs dans les registres (faire un DIM REG%(15)) qui pourront être pris en compte simplement par la routine asm.
CALL peut faire cela aussi, mais la routine devra récupérer les valeurs envoyées dans la pile (SP). Et c'est plus compliqué à faire.

Il vaut mieux ne pas stocker (après l'avoir chargé) une routine dans un A$ car le GFA peut déplacer la variable A$ en mémoire pour ses besoins. Alors la routine asm peut ensuite déconner.
J'ai même vu des fous (un listing de ST Replay 4), qui ont stocké une routine dans un DIM A%(10000) (10000 étant la taille de la routine). C'est vraiment le genre de truc à ne jamais faire.

RESERVE

Il faut savoir que d'origine, le GFA BASIC réserve toute la mémoire disponible pour son propre usage. Donc si vous souhaitez allouer de la mémoire avec MALLOC, ou utiliser un accessoire, ..., cela ne sera pas possible par "manque de mémoire".
Cette instruction sert à spécifier la quantité d'octets que le GFA BASIC réservera pour son propre usage (pour les DIM, et les variables (A$, C%,...)). Donc le GFA restitue la mémoire au système. En fait chaque programme en GFA devrait faire cela.
Lorsque le prg est terminé, avant de faire END ou EDIT, il faut mettre un RESERVE (tout court, sans rien après). Il va restituer au système la mémoire que le GFA s'était mis de côté. Généralement, avec RESERVE 70000 on s'en sort dans la pluspart des cas.
N'oubliez jamais qu'un SGET EXEMPLE$ prends 32000 octets dans la réserve du GFA. Donc lorsque vous n'avez plus besoin de l'écran EXEMPLE$, faites un EXEMPLE$=""

TEXTE (dépassement du)

Lorsqu'on fait un PRINT de plus de 80 caractères en moyenne résolution (ou 40 en basse) tout est normal, le texte continue sur la ligne suivante. Mais en compilé commencent les problèmes. Le texte s'arrête à la dernière colonne de la première ligne !. Il faut rajouter cette ligne (c'est un appel au VT 52):
PRINT CHR$(27);"v";
Elle autorise le dépassement le caractères. Il faut la remettre après chaque changement de résolution.

SPRITE

Pour afficher un sprite en GFA, c'est à dire un bloc graphique à travers lequel (couleur transparente: 0) on voit ce qu'il y avait derrière.
Il faut le dessin du sprite, et son masque (son ombre colorée en couleur 15). On prends ces dessin (par ex. dans une .PI1 que l'on a chargé) avec GET, puis:
VSYNC
PUT 32,60,logo_masque$,4
PUT 32,60,logo$,7

TIMER

Il faut le diviser par 200 pour obtenir le nombre de secondes.
old_time%=TIMER
...
time%=(TIMER-old_time%)/200

VARIABLES, MALLOCS, FRE()

Il arrive que le GFA s'emmêle les pédales dans la gestion des variables, et qu'il ne restitue pas la ram qui était occupée par des variables.
L'instruction PRINT FRE() indique la mémoire disponible dans la ram réservée au GFA. Si vous faites PRINT FRE(7) (on peut mettre n'importe quel chiffre à la place de 7), le GFA va effectuer un "Garbage Collection", c'est à dire qu'il va faire le ménage dans les variables (voir paragraphe précédent).

Pour réserver un peu de mémoire facilement avec une variable pour y stocker des données (c'est plus facile d'y traiter du texte), on peut faire:
a$=SPACE$(20000)
Mais le mieux est:
a$=STRING$(20000,0) (cela vous évitera des bugs)

VSYNC

Cet instruction permet d'éviter:
o le clignotement lors de l'affichage d'un sprite,
o le décalage d'écran lors d'un changement de résolution (cela ne marche pas à tout les coups. Turbo ST a tendance à augmenter le taux d'échec lors des changements de résolution).

POUR ATTENDRE UNE TOUCHE:

J'utilise la routine qui suit. Elle renvoie le code ascii de la touche dans t%, et le caractère majuscule dans t$. Comme cela l'utilisateur n'a pas le souci de savoir si le clavier est en majuscules ou en minuscules.
PROCEDURE t
t%=INP(2)
t$=UPPER$(CHR$(t%))
RETURN

c% c& c| c# TRUE FALSE

Une variable (ex: var) sans rien après son nom est considérée être: var&
Dans l'ordre des variables qui occupent le plus de place:
c# 8 octets, permet d'atteindre les nombres les plus grands.
c% 4 octets, ne permet d'utiliser que des nombres positifs ou 0.
c& 2 octets, de -65000 à +65000.
c| 1 octets, de 0 à 254.
Le mieux est de prendre l'habitude de toujours rajouter un % après la virgule. Le % est la taille minimale si l'on veut indiquer une adresse de la mémoire. Après on peut si l'on veut étudier la routine de plus près pour voir où l'on peut économiser de la mémoire.

En fait on n'économise de la mémoire qu'avec les DIM, sinon, le gain est négligeable. L'avantage c'est que le listing est plus clair.

TRUE et FALSE sont très clair à utiliser. Ex: gateau!=TRUE La variable ne peut avoir que 2 états: vrai ou faux. Lorsque le gâteau aura été mangé, il suffira de mettre gateau!=FALSE
Logiquement la variable gateau ne devrait occuper qu'un bit (1/8 ème d'octet). En fait elle utilise un octet, c'est plus rapide à gérer pour le GFA.