Triceraprog
La programmation depuis le Crétacé

VG5000µ, deux routines (quasi) identiques ()

Hier, en continuant le commentaire systématique de la ROM du VG5000µ, j'ai eu une impression de déjà-vu. Il me semblait bien avoir déjà commenté la partie « redéfinir un caractère étendu » (commandes SETE et SETG en BASIC).

L'impression persiste, voire s’accroît, au fur et à mesure et je me décide à aller voir dans ce que j'ai déjà commenté. J'ai commencé, lentement, ce commentaire en août 2017, avec moult pauses, mais aussi du « butinage ». Il y a donc des parties que je ne me rappelle plus avoir déjà traitées.

Et effectivement, un peu plus loin, je vois des commentaires similaires à ceux que je suis en train d'écrire. Les termes sont un peu différents, car au fil des commentaires, j'ai fait évoluer certains termes ou la manière de commenter, mais en regardant de plus près, oui, c'est évident, il y a deux fois la même routine dans la ROM.

Je ne sais pas si c'est quelque chose de connu, alors voici mes commentaires.

Le VDP

Le Video Display Processor du VG5000µ, un EF9345, est utilisé par le BASIC de manière généralement indirecte. Les commandes comme les changement de couleur, de type de caractères ou encore de position du curseur, modifient des registres internes en RAM. Ces registres sont juste des emplacements réservés dans la RAM principale, celle accessible au Z80, ils n'ont rien de spécial.

Ces registres se trouvent à partir de $47fa et pointés en tout temps par le registre IX.

Le BASIC maintient aussi une représentation de l'écran, en $4000, et afficher quelque chose en BASIC revient à modifier cette représentation d'écran, en se basant sur les registres BASIC.

À chaque rafraîchissement demandé par le VDP, via l'IRQ du Z80 et si le BASIC considère qu'il est temps de mettre à jour l'affichage, un transfert des données est fait vers le VDP.

C'est le fonctionnement de base.

Cependant, la ROM contient aussi des routines qui s'adressent directement au VDP. On peut envoyer un caractère dans la mémoire écran du VDP sans passer par la représentation maintenue par le BASIC. Bien évidemment, si on laisse faire le rafraîchissement du BASIC, cette donnée sera écrasée rapidement. On peut aussi lire un caractère depuis la mémoire écran du VDP.

Ces quatre routines, putahl, putici, getahl et getici ne sont jamais utilisées par la ROM. Ce sont des routines mises à disposition pour l'utilisateur à une adresse fixe, dont le seul code est un branchement à l'implémentation.

Une autre routine mise à disposition est setext, qui s'occupe de la redéfinition d'un caractère texte ou graphique dans le VDP. Le VDP est en effet configuré par défaut pour offrir 4 « polices de caractères », dont 2 en ROM, et 2 en RAM (celle accessible directement par le VDP). Les deux en RAM peuvent être modifiées via cette routine setext en fournissant le numéro du caractère à changer et 10 octets qui représentent les 10 lignes d'affichage du caractère.

setext se trouve en $001b et branche immédiatement sur son implémentation en $0d85.

setext vs. SETE(T/G)

Le BASIC offre deux commandes pour redéfinir les caractères : SETET, pour redéfinir un caractère texte, et SETEG, pour redéfinir un caractère graphique. La différence entre caractère texte et graphique sort du périmètre de cet article.

Du point de vue de l'interpréteur BASIC, il n'y a qu'une seule commande SETE, qui vérifie si le caractère suivant est T ou G. On pourrait dire que la dernière lettre de la commande est vue par l'interpréteur comme son premier paramètre.

L'exécution de SETE se trouve en $0ced dans la ROM BASIC.

On pourrait s'attendre à ce que SETE utilise la routine setext. Ou bien que les deux routines aient une partie commune. Ce n'est pas le cas.

Des 141 octets de l'implémentation de setext, environ 100 (à la louche) sont strictement identiques dans SETE, routine qui elle pèse 160 octets (en incluant sa routine annexe, qu'elle est la seule à appeler).

Différences

Les deux routines font la même chose, dans le même ordre :

  • Couper le rafraîchissement de l'écran depuis sa représentation RAM,
  • Déterminer si on veut un caractère graphique ou texte,
  • Récupérer le numéro du caractère,
  • Envoyer les commandes au VDP pour préparer la définition,
  • Envoyer les 10 lignes au VDP,
  • Rétablir le rafraîchissement de l'écran.

Pour setext, c'est très simple, les informations sont dans le registre A pour le caractère et son type, et HL pointe vers les données.

Pour SETE, c'est un peu plus complexe. Le type de caractère est déterminé par la présence de T ou G, il y a une vérification de la validité du premier paramètre de la commande (numéro de caractère), puis la chaîne de caractères de description, suite de nombres hexadécimaux en ASCII, doit être décodée. C'est la raison pour laquelle la routine est plus longue.

Cependant, le corps de la routine qui envoie toutes les commandes est identique, à la récupération de la donnée prêt. Et bien que les deux routines utilisent bien les mêmes appels pour envoyer une commande au VDP ou attendre que celui-ci soit prêt à recevoir une commande, il doit bien y avoir une centaine d'octets pouvant être mis en commun.

Pourquoi ?

Je n'ai pas d'explication à la duplication de cette routine. Il reste un peu de place inutilisé dans la ROM, et peut être qu'il n'était plus nécessaire d'optimiser la place prise et que c'est juste resté « comme ça ».

Ce n'est pas, à mon avis, une question de performances avec setext qui serait plus rapide. Elle l'est, en effet, mais pourrait l'être encore plus. En effet, setext garde de SETE le fait de « retourner » chaque octet des descriptions de ligne pour les passer d'une visualisation humaine au format demandé par le VDP. La suite de commandes à envoyer pourraient aussi être rendue plus rapide à l'aide d'un buffer de commandes et l'utilisation de la routine regst.

Amélioration ?

Une amélioration possible de la ROM serait de réécrire ces deux routines. Il y aurait peut-être même moyen de profiter de la place gagnée pour caser deux commandes PSET et PRESET, qui font cruellement défaut sur le VG5000µ.