Le VG 5000 pour les programmeurs Basic

Révision du 03/08/2022



Ce petit document contient un certain nombre d'informations utiles ou pas à tout programmeur Basic. Les curieux pourront consulter les deux documents technique Philips décrivant les bugs et évolutions du Basic (disponibles sur le site de Carl, http://vg5000.free.fr ). Ils complètent les informations de l'article.


Les bugs spécifiques au Basic 1.0

Le Basic 1.0, made in Microsoft, contient malheureusement quelques jolies pétouilles. Ces erreurs sont corrigées par la version 1.1. Celles listées ci-dessous sont celles que j'ai rencontrées en réalisant des programmes. Il en existe d'autres moins flagrantes. Si vous voulez que vos programmes soient compatibles avec tous les VG 5000, il faut tenir compte de ces erreurs :

Bug utilisation notation hexadécimale :
Certaines commandes ne fonctionnent pas correctement si on utilise des valeurs numériques en hexadécimal. Le bug se produit lorsque la valeur est suivi d'un espace.

Ex :

IF PEEK(&"7FFF")=&"F3" THEN GOTO 100 : incorrect !
IF PEEK(&"7FFF")=&"F3"THEN GOTO 100 : correct

Sur une boucle FOR .. NEXT, c'est la même chose.

FOR I=&"7F00" TO &"7F01":PRINT:NEXTI : incorrect !
FOR I=&"7F00"TO &"7F01" :PRINT:NEXTI : incorrect !
FOR I=&"7F00"TO &"7F01":PRINT:NEXTI : correct !

Bug CALL dans un IF :
On ne peut pas utiliser la commande CALL après l'instruction IF. Cette erreur a été détectée en programmant le jeu Strip 21.

10 C=1:IF C=1 THEN CALL &"5880":GOTO 20 ' plante !

10 C=1:CALL &"5880":IF C=1 THEN GOTO 20 ' ok


Les bugs et bizarreries du Basic (toutes versions)

Bug commandes STICKX(), STICKY() et ACTION() :
Si une interface VG 5200 ou VU 0001 n'est pas connectée sur l'ordinateur, interroger ces trois commandes avec les valeurs 0 (manette 1) ou 1 (manette 2) ne retourne pas 0 au repos. Exemple :

10 k=STICKX(0):PRINT k:GOTO 10

En fonction des machines, les comportements divergent. Soit on obtient une valeur systématiquement à 1 ou 255, soit on a une majorité de 0 avec quelques 1. La commande ACTION elle retourne un 3. C'est l'erreur la plus grave car elle n'est pas contournable et le bug le plus connu du VG 5000. Le "bulletin technique du Basic 1.1" semble ne pas considérer ce comportement comme une anomalie. Admettons...

Bug commande après un CLOAD :
On ne peut pas faire suivre l'instruction CLOAD" par une autre commande si on charge un fichier binaire. On se retrouve alors avec une erreur fantaisiste "Erreur en ligne xx". Ce bug est documenté dans la version 1.1 du "Technical Bulletin Basic Manual".

10 CLEAR 50,&"5FFF":CLOAD"TEST",&"6000":PRINT ' plante
10 CLEAR 50,&"5FFF":CLOAD"TEST",&"6000" ' ok

Bug scrolling :
L'affichage d'un caractère en position X=39 et Y=24 se traduit inmanquablement par un scrolling, même si vous mettez un ";" à la fin de la commande PRINT. Exemple :

10 CURSORY 39:CURSORY 24:PRINT "A";:CURSORY 1

Ce bug a été détecté dans le programme "Exocet" publié dans le livre "VG 5000 Jeux d'action" chez Sybex. Coup de chance, il existe une commande Basic qui permet de figer le scrolling, PAGE. Enfin une occasion de l'utiliser !

Bug commande ON xx GOTO :
Si la commande ON xx GOTO contient une liste d'au moins 8 lignes dont les numéro sons inférieurs à 100, on obtient une erreur "Opérande Manquante". La ligne n'est pas enregistrée par l'interpréteur Basic.
La commande ON xx GOSUB n'est pas affectée par ce mal mystérieux...

exemple :

10 A=1
20 ON a GOTO 30,31,32,33,34,35,36,37
20 ON a GOSUB 90,91,92,93,94,95,96,97
20 ON a GOTO 10,20,30,40,50,60,70,80

Avec des lignes commençant à 100, plus de problème !

10 A=1
20 ON a GOTO 100,101,102,103,104,105,106,107,108,109,110,111,112

Si on ne met dans la commande que 7 lignes inférieure à 100, cela fonctionne aussi.

Ce bug étrange a été détecté en 2022 lors de la mise au point du programme "Mabool" de Baptiste Bideaux.

La commande RND n'est pas vraiment aléatoire :
Ce qui suit n'est pas un bug, mais mérite d'être signalé.
La commande RND(1) n'est pas aléatoire et tire toujours la même suite de valeurs entre 0 et 1. Tapez et exécuter le programme suivant après avoir fait un reset de la machine :

10 A=RND(1)
20 PRINT A

Je peux déjà vous donner le résultat : .245121 !

Ce comportement peut s'avérer gênant dans des jeux de hasard, car l'utilisateur aura alors l'impression de toujours refaire la même partie. On peut contourner ce désagrément avec une boucle qui demande au joueur de taper sur une touche tout en tirant des numéros.

La commande INPUT n'efface pas le contenu de la variable en paramètre :
Autre particularité du VG 5000, cette fois-ci sur une commande pourtant classique, INPUT. Si lors de la saisie l'utilisateur valide directement, l'ancienne valeur de la variable utilisée est conservée ! Ceci est valable autant pour les variables numériques que pour les chaînes.

10 A$="COUCOU"
20 INPUT A$
30 PRINT A$

Si vous tapez sur la touche "ENTREE" quand l'ordinateur vous demande de saisir une donnée, le message "COUCOU" s'affichera.

La numérotation des lignes Basic ne peut dépasser 65529 :
C'est Mokona qui nous livre l'explication de cette caractéristique sur le forum system-cfg en juillet 2019 :

"Cela fait partie du BASIC Microsoft. Dans le décodage du numéro de ligne, qui commence en $257c sur VG 5000µ et dont le label est "ATOH" dans une version annotée du BASIC Microsoft, la limite est explicite. La comparaison sur VG 5000µ est en $2580/$2583. La valeur comparée est $1998 (6552). A chaque accumulation du décodage, il y a vérification de non dépassement de cette valeur puis une multiplication par 10, ce qui nous donne 65520. 65520+10 = 65530 dont la limite est 65530-1 soit 65529. Vu que ce morceau de code se retrouve sur différents BASIC Microsoft, je leur attribue cette particularité, et non aux implémentations spécifiques."


Les commandes manquantes du Basic VG 5000

Si vous avez l'habitude de travailler avec d'autres langages Basic, vous serez surpris de l'absence de certaines commandes usuelles ou astuces pourtant bien utiles. Autant en prendre son parti.

- Pas de commande de suppression d'un ensemble de lignes dans un programme (typiquement, la commande DELETE dans d'autres Basic). Pour supprimer plusieurs lignes, il faut taper leurs numéros et valider.

- Impossibilité de sortir d'une boucle FOR I=... NEXT I avec un GOTO. On peut toujours accélérer la sortie d'une boucle en mettant la variable compteur à son maximum :

10 FOR I=1 TO 10
20 IF I=5 THEN I=10:GOTO 40
30 PRINT I
40 NEXT I

Une simple sortie de la boucle FOR n'est pas possible, car le Basic considère alors que la boucle n'est pas terminée. A la prochaine boucle FOR...NEXT avec la même variable compteur, la boucle ne commencera pas à la valeur que vous avez indiquée, mais à celle de la précédente boucle FOR...NEXT. Ca n'est pas clair ? Vous trouverez plus d'explications dans le document "VG5000_Technical bulletin_Basic 1.1.pdf" disponible sur le site http://vg5000.free.fr .

- La commande NEXT doit toujours être suivie d'une variable. Dommage pour l'optimisation mémoire...

- Pas de ELSE à la suite d'un IF ... THEN ... C'est clairement la plus grosse lacune du Basic.

- Pas de commande de gestion des erreurs ni de variable remontant la dernière erreur rencontrée dans un programme.

- Pas de commande permettant de sauvegarder un tableau de chaînes.

- Pas de commande pour convertir une chaîne de caractères en majuscules/minuscules.


Les commandes non documentées dans le manuel du Basic VG 5000

Elles ne sont pas nombreuses, mais sont utiles.

Commandes STICKX(), STICKY() et ACTION() :
Elles peuvent utiliser une variable en paramètre (valeur 0, 1 ou 2). C'est pratique quand vous voulez que votre programme fonctionne avec les touches fléchées ou une manette en fonction du choix de l'utilisateur.

Exemple :

10 a=0:b=STICKX(a)

Commande PRINT FRE(" ") :
Permet d'avoir le nombre d'octets disponible dans l'espace mémoire réservé aux chaînes de caractères. La taille de cette zone correspond au premier paramètre de la commande CLEAR. La valeur par défaut de cette zone est de 50 et doit souvent être augmentée dès que votre programme manipule des chaînes de caractères.


Mon programme plante mais le message d'erreur ne s'affiche pas !

En fonction de l'endroit où votre programme se bloque, les paramètres d'affichage (texte ou graphique et couleurs) ne permettent pas de voir le message d'erreur retourné par le Basic. Là, on peut vraiment parler de gros défaut !

Il faut ruser et taper directement sous la ligne où devrait se trouver le message d'erreur.

FOR I=16385 TO 18385 STEP 80:POKE I,230:NEXTI

Pour la mise au point d'un programme, vous pouvez créer une ligne à la fin de votre listing et l'appeler en mode direct quand votre programme est planté.

Exemple : on rajoute une ligne.

5000 FOR I=16385 TO 18385 STEP 80:POKE I,230:NEXTI

GOTO 5000


Optimiser l'espace mémoire d'un programme

Le Basic du VG 5000 a été conçu pour une machine ayant peu de mémoire vive. De fait, préserver cette précieuse ressource peut devenir un enjeu à partir du moment où votre programme devient conséquent. Cette optimisation présente un autre avantage, elle permet d'améliorer un petit peu la vitesse de votre programme. Tout ce que l'interpréteur BASIC n'aura pas à analyser, c'est du temps gagné !

Une majorité des astuces présentées peuvent être utilisées avec d'autres Basic.



Il est possible de se passer d'espace entre les instructions. Cette source de gain est habituellement la plus intéressante dans un listing. Sur un très gros programme, on peut ainsi récupérer plusieurs centaines d'octets.

Exemple :

10 FOR I=1 TO 100:PRINT "COUCOU":NEXT I ' standard

10 FORI=1TO100:PRINT"COUCOU":NEXTI ' sans les espaces !

Si la lisibilité devient hasardeuse, le gain en octets n'est pas à négliger lorsque votre programme est au point et rentre au chausse-pied dans la mémoire de la machine.

Certaines commandes ne peuvent se passer d'espaces. Vous pouvez les entrer sans, mais le VG5000 rajoutera automatiquement des blancs lorsque vous listerez la ligne concernée. Il s'agit des commandes prenant comme paramètre une adresse de ligne : GOTO, GOSUB, RESTORE.
En fait, l'espace n'est pas stocké en mémoire, il est simplement rajouté par la machine lorsqu'elle affiche la ligne Basic.


Vous pouvez limiter le nom des variables au maximum à deux caractères. Au dessus, c'est de l'espace gaspillé car le VG5000 n'en tient pas compte. Pire, il va confondre les variables.

coucou est équivalent à co


Si la dernière commande d'une ligne est un PRINT"texte" ou l'assignation d'une chaîne de caractères dans une variable (A$="COUCOU"), vous pouvez supprimer le dernier guillemet : un octet de gagné !

L'astuce est également valable pour les commandes de redéfinition de caractères SETET et SETEG.

Vous pouvez vous passer du ";" quand vous affichez des variables à la suite d'une commande PRINT"texte". En lieu et place de PRINT"texte";A$ , vous pouvez taper PRINT"texte"A$ .

Mieux, vous pouvez mettre plusieurs variables à la suite les unes des autres.

Exemple : PRINT"texte"A$B$C$

Cela fonctionne aussi avec tous les types de variables, avec une limitation pour les entiers : on ne peut mettre qu'une seule variable à la suite du PRINT"texte".

Exemple : PRINT"texte"a

Si vous voulez afficher plusieurs fois de suite la valeur de a, il faudra vous résoudre à séparer les variables par des points virgule.

PRINT"texte"a;a;a

Si vous n'en mettez pas, l'interpréteur Basic affichera non pas trois fois la variable a, mais une fois la variable aaa (en fait aa à cause de la limitation du nom des variables à deux caractères significatifs).

Pour les variables dans des tableaux ou des chaînes, pas de problème !

Exemple : PRINT"texte"a(1)a(2)

Exemple : PRINT"texte"a$(1)a$(1)

A chaque point virgule supprimé, un octet de gagné !

Si vous définissez une valeur numérique réelle comprise entre 0 et 1, vous pouvez vous passer du 0 avant le point. Ca sera un octet de gagné.

Exemple : 10 A=0.1

est identique à : 10 A=.1

Trivial mais efficace : si vous redéfinissez des caractères avec les commandes SETEG ou SETET, faites-le dans un loader avant le chargement du programme principal. Les rédéfinitions sont conservées dans la mémoire de la puce vidéo !


Les paramètres de choix des couleurs dans les modes texte ou graphique admettent trois paramètres. Ces derniers ne sont pas obligatoires. Si les valeurs ne changent pas entre deux commandes, on peut réduire la commande à un seul paramètre voire aucun si vous affichez des caractères texte en blanc (TX, ET) ou des caractères graphiques blancs sur fond noir (GR,EG).

Exemple :

10 TX 3,0,0:PRINT "COUCOU"
20 TX 2:PRINT "COUCOU"
30 TX:PRINT "COUCOU"

La première ligne affiche le texte en rouge, la deuxième en vert, et la troisième en blanc.

N'hésitez pas à remplacer une instruction CHR$(x) dont la valeur est fixe par le caractère correspondant. Ce sont deux octets de gagné et l'affichage est probablement plus rapide !

Exemple :

10 PRINT CHR$(65)CHR$(66)

peut avantageusement être remplacé par :
10 PRINT "AB"


N'utilisez pas les comparateurs <= ou >=, modifiez la valeur à tester en conséquence pour n'utiliser que < ou >. Ca fera un octet de gagné !

Exemple :

10 IF K>=1 THEN PRINT "COUCOU" est identique à :

10 IF K>0 THEN PRINT "COUCOU"


Si une variable numérique dans la commande IF doit être différente de zéro, un simple IF sans comparateur suffit.

Exemple :

10 IF K<>0 THEN PRINT "COUCOU" est identique à :

10 IF K THEN PRINT "COUCOU"


Remplacer la commande IF ... THEN GOTO par IF ... GOTO ou IF ... THEN, vous gagnerez deux octets !

Exemple : IF I=1 THEN GOTO 100 est identique à :

IF I=1 THEN 100 ou IF I=1 GOTO 100


Limitez autant que possible l'usage de la notation hexadécimale. C'est parfois moins lisible, mais une valeur en hexadécimal occupe en mémoire deux octets de plus que son équivalent décimal. Accessoirement, cela vous évitera d'avoir à traquer des bugs sur la version 1.0 du Basic.