Site logo

Triceraprog
La programmation depuis le Crétacé

VG5000µ, SetPoint en BASIC, l'implémentation ()

Ça y est, après avoir vu la structure des caractères semi-graphiques, l'arrangement en mémoire des valeurs d'affichage et fait un essai de manipulation de ces valeurs, nous voici prêts pour écrire un morceau de programme qui peut prendre en entrée des coordonnées et allumer ou éteindre un point à l'écran.

Le BASIC est un langage, dans les versions de l'époque de cette machine, assez limité. Il n'y a entre autre pas de notion de portée lexicale des variables. La portée lexicale d'une variable, c'est l'ensemble des parties d'un code source depuis lesquelles une variable, ou plus généralement un symbole, est accessible. En BASIC sur VG5000µ, comme sur les BASIC d'autres machines de cette période, c'est simple, les variables simples sont accessibles de partout à partir du moment où elles ont été définies.

À cela s'ajoute le fait que seuls les deux premiers caractères d'une variable sont significatifs. ABC et ABD désignent les mêmes variables. Cela limite fortement la possibilité d'utiliser des noms de variables intéressants.

Deux caractères significatifs pour les variables

Cette aparté terminée, revenons à la définition du problème.

Modélisation du problème

En entrée, nous avons : des coordonnées X et Y, comprises entre 0 et 79 pour X et 0 et 74 pour Y.

En effet de bord, c'est-à-dire en modification de l'état de la machine, nous voulons : le point correspondant à l'écran qui prend la couleur d'encre définie.

Dans un premier temps, la procédure ne prendra pas d'information de couleur, je me contenterai d'utiliser la couleur d'encre 0 (noir) sur fond 6 (bleu), qui est la combinaison à l'initialisation de la machine.

Les étapes, d'après les articles précédents, sont donc :

  • À partir de X et Y, trouver les coordonnées du caractère à modifier à l'écran
  • À partir de X et Y, trouver les coordonnées à l’intérieur du caractère semi-graphique
  • À partir de coordonnées du caractère, calculer l'adresse mémoire écran correspondante
  • Récupérer les valeurs pour la paire d'adresse mémoire
  • Si le caractère présent n'était pas un caractère semi-graphique standard, considérer qu'il était complètement éteint (valeur 0 pour le caractère)
  • Modifier la valeur du caractère récupéré en fonction des coordonnées à l'intérieur du caractère semi-graphique
  • Modifier la mémoire écran avec les nouvelles valeurs

Prenons un exemple avec les coordonnées (2, 7) que j'avais déjà utilisées dans l'article sur les changements de repère. Les coordonnées du caractères sont (0, 2) et les coordonnées dans le caractères sont (0, 1).

À partir des coordonnées (0, 2), je trouve que l'adresse mémoire est &"4000"+160. Une paire de PEEK me donne les valeurs déjà présentes 128 et 230. Cela signifie qu'il y a un caractère graphique étendu à cet endroit. Je le considère donc comme un caractère éteint, de valeur 0.

À partir des coordonnées (0, 1), j'obtiens pour valeur de caractère 64+4 = 68, qui sera donc la première valeur.

La seconde valeur, en fonction des couleurs sera 224. Une paire de POKE avec ces valeurs allumera le bon point.

Des peeks

Maintenant, que se passe-t-il si un caractère graphique est déjà présent ? Pour vérifier cela, je vais allumer le point aux coordonnées (3, 7). Cela donne la paire de coordonnées (0, 2) et (1, 1). C'est-à-dire les mêmes emplacements mémoires mais avec un point différent dans le caractère semi-graphique.

Les valeurs récupérées sont donc 68 et 224, celles que je viens de calculer et mettre en mémoire avec POKE. 224 reste identique, puisque les couleurs sont fixes. Le numéro de caractère, lui, doit être changé. Le nouveau gros pixel à allumer est celui de valeur 8. Je peux donc ajouter 8 à 68 pour donner 76. Et cela marcherait.

Mais c'est faux dans le cas général.

L'addition ne fonctionne pas. Si j'allume deux fois le même gros pixel, il ne faut pas ajouter le numéro de ce pixel, puisqu'il est déjà pris en compte.

L'opération qu'il faut utiliser ici est une opération OU. Je ne m'étendrai pas dessus ici. Retenez juste que faire un OU entre le numéro du caractère actuel et le numéro associé au pixel revient à ajouter ce numéro associé uniquement s'il n'est déjà pas pris en compte par le caractère.

En BASIC, le OU est écrit OR. 68 OR 8 donne 76. Parfait.

Des pokes

Voici le programme en BASIC, commenté, qui reprend ces opérations.

100 REM AFFICHE UN POINT DANS L'ESPACE SEMI-GRAPHIQUE
110 REM X CONTIENT L'ABSCISSE ENTRE 0 et 79
120 REM Y CONTIENT L'ABSCISSE ENTRE 0 et 74
130 ZX=INT(X/2):ZY=INT(Y/3)         : REM Calcul des coordonnées écran (ZX, ZY)
140 RX=X-ZX*2:RY=Y-ZY*3             : REM Calcul des coordonnées dans le caractère (RX, RY)
150 CH=2^(RY*2+RX)                  : REM Calcul du numéro de pixel associé
160 DI=&"4000"+ZY*80+ZX*2           : REM Calcul de l'emplacement mémoire écran
170 AT=PEEK(DI+1)                   : REM Récupération de la valeur d'attribut
180 REM Si c'est un caractère graphique, la valeur du caractère est récupérée dans OL
190 REM Sinon, OL reste à 64
200 OL=64:IF (AT AND 128) = 128 THEN OL=PEEK(DI)
210 REM Si le caractère était étendu, OL est remis à 64
220 IF (OL AND 128) = 128 THEN OL=64
230 POKE DI,OL OR CH                : REM Le caractère est augmenté de la nouvelle valeur
240 POKE DI+1,224                   : REM Les couleurs sont fixes
250 RETURN                          : REM Fin de la routine, retour à l'appelant

Je ne m'étendrai pas non plus ici sur le AND en ligne 200. Retenez que cette opération vérifie si le bit de rang 7, qui décrit si le caractère est semi-graphique, est à 1. De même sur la ligne 200, où je vérifie si le bit de rang 7, qui décrit si le caractère est étendu, est à 1.

Et voici comment peut-être utilisé ce programme. X et Y sont initialisés avec les coordonnées, puis la routine en ligne 100 est appelée avec GOSUB.

10 INIT
20 X=20:Y=10:GOSUB 100
21 X=21:Y=10:GOSUB 100
22 X=19:Y=11:GOSUB 100
23 X=19:Y=12:GOSUB 100
24 X=22:Y=11:GOSUB 100
25 X=22:Y=12:GOSUB 100
26 X=20:Y=13:GOSUB 100
27 X=21:Y=13:GOSUB 100
30 END

Tracer des images, ou tout simplement des objets géométriques de cette façon serait très fastidieux. On pourra améliorer ça dans un futur article.

Le résultat

Le listing