Site logo

Triceraprog
La programmation depuis le Crétacé

Sous le capot de l'Alice 32/90, un EF9345 ()

La machine de la nouvelle session du « Retro Programmers United for Obscure Systems » est connue. C'est le Matra Alice. Et plus exactement les version 32 et 90, afin de s'échapper de la trop grande proximité entre le Alice premier du nom et le Tandy MC-10 (une telle proximité que ce sont les mêmes machines).

Les versions 32 et 90 étant très similaires niveau hardware, je les nommerais conjointement Alice 32/90.

Pour cet article, ce qui va m'intéresser est que l'Alice 32/90 utilise un EF9345, comme le VG5000. Et l'EF9345 étant aussi utilisé dans le VG5000µ, c'est une puce que je connais bien. Cependant, l'Alice 32/90 l'utilise différemment. Je dirais même qu'il l'utilise mieux.

L'autre axe de cet article est que je veux utiliser l'EF9345 depuis le BASIC. La machine tournant avec un 6803, les I/O sont mappées en mémoire. Et il est donc possible d'accéder aux registres de l'EF9345 depuis le BASIC avec des PEEKs et POKEs. Pas besoin de passer par l'assembleur. Par contre, pas de mystère, c'est lent !

Le mode graphique en BASIC sur l'Alice

Première chose amusante, l'Alice 32/90 démarre dans un mode 32 colonnes qui n'existe pas pour l'EF9345. Je pense que ce mode par défaut, qui utilise en fait le mode 40 colonnes de l'EF9345, est là pour être compatible avec le Alice 4k au niveau BASIC. Pour assurer cette compatibilité, des caractères utilisateurs sont chargés dans la RAM vidéo au démarrage pour représenter les différentes combinaison d'un bloc de 2x2 « gros pixels » pour chaque caractère.

L'Alice 32/90 peut cependant utiliser l'EF9345 en vrai mode 40 colonnes, et même en mode 80 colonnes. Pour cela passer d'un mode à l'autre, il faut utiliser les commandes CLS32, CLS40 et CLS80. Je vais me concentrer sur le mode 40 colonnes.

Celui-ci est initialisé dans le mode « 40 CHAR LONG ». C'est un mode qui prend trois pages de 1Ko en mémoire vidéo. La première page contient les caractères, la deuxième les attributs et la troisième les couleurs. Ça fait beaucoup sur les 8ko de RAM vidéo de la machine, et le VG5000µ avait fait le choix d'utilise le mode « 40 CHAR SHORT » qui ne prend que 2ko. Cependant, on y gagner en simplicité et flexibilité au niveau des attributs.

Autre choix de l'Alice : le système ne conserve pas de miroir en RAM de l'affichage. Là encore, bon choix pour l'utilisation de la RAM principale. En contrepartie cela signifie que les opérations non prévues par le BASIC devront se faire en s'adressant directement à l'EF9345.

Plus techniquement, le mode est initialisé avec les registres suivants :

- TGS = 0x10 (binaire: 00010000) -> 312 lignes non entrelacées, synchro composite, pas de synchro entrante, service row = 0, 40 Char Long
- MAT = 0x28 (binaire: 00101000) -> couleur de marge noire, curseur complet clignotant, curseur désactivé (!), simple hauteur
- PAT = 0x67 (binaire: 01100111) -> service row visible, bulk haut et bas visible, conceal désactivé, flash activé
- DOR = 0x13 (binaire: 00010011) -> page G'0 située en Z = 3, page G'10 située en Z = 2, page Q située en Z = 0
- ROR = 0x08 (binaire: 00001000) -> première ligne bulk = 8, page d'origine Z = 0

Les registres de l'EF9345

Depuis le processeur, l'EF9345 est accessible via 8 registres. Ces registres sont accessibles en lecture et écriture, et sont tous des registres de 8 bits. Ils sont accessibles via les adresses suivantes :

- R0 = $BF20 ; 48928 (commande)
- R1 = $BF21 ; 48929 (paramètre principal)
- R2 = $BF22 ; 48930 (paramètre)
- R3 = $BF23 ; 48931 (paramètre)
- R4 = $BF24 ; 48932 (pointeur auxiliaire haut)
- R5 = $BF25 ; 48933 (pointeur auxiliaire bas)
- R6 = $BF26 ; 48934 (pointeur principal haut)
- R7 = $BF27 ; 48935 (pointeur principal bas)

Une adresse supplémentaire est située en $BF28 (48936). Il s'agit en fait de R0 mais avec le flag d'exécution (bit 7 du numéro de registre) mis à 1. Cela permet de demander à l'EF9345 d'exécuter la commande indiquée dans R0.

Techniquement, n'importe quel registre peut être utilisé pour exécuter une commande en mettant le bit 7 à 1. Cela permet d'ailleurs quelques optimisations. Je n'ai pas vérifié si les adresses au delà de $BF28 étaient mappées. Si ce n'est pas le cas, on n'utilisera pas, voire jamais, R0 directement en écriture directement, mais toujours via le « faux registre » R8.

Note additionnel : le livre "les astuces d'Alice 32 et 90" indique qu'il est en effet possible d'utiliser tous les registres en mode « exécution ».

Un premier affichage

Voici un programme qui place tous les registres directs correctement pour afficher un « A » à l'écran sur la ligne 0 (ligne de service), colonne 10. Notez que cela fonctionnera parfaitement en mode CLS32. Vous pouvez vous amuser à écrire où vous voulez dans l'espace de 40 colonnes par 25 lignes pour constater que le mode 32 colonnes est en fait le mode 40.

Attention, dans cette configuration de l'EF9345, la deuxième ligne affichée est la ligne... numéro 8.

100 REM AFFICHE UN CARACTERE
110 POKE 48928, 0   : REM R0 (COMMANDE) KRF / INUTILE
120 POKE 48929, 65  : REM R1 (C)
130 POKE 48930, 0   : REM R2 (B)
140 POKE 48931, 20  : REM R3 (A)
150 POKE 48932, 0   : REM R4 (NA pour KRF)
160 POKE 48933, 0   : REM R5 (NA pour KRF)
170 POKE 48934, 0   : REM R6 (MP / LIGNE)
180 POKE 48935, 10  : REM R7 (MP / COL)
190 POKE 48936, 1   : REM R0 + EXEC (KRF)

Une démonstration plus complète

Voici un programme de démonstration plus complet, mais pas entièrement, puisqu'il y a plein de choses à faire avec l'EF9345 qui ne sont pas démontrées ici.

Attention : je n'ai pas du tout testé sur vrai matériel. L'EF9345 étant sensible aux synchronisations (on ne peut pas lui parler n'importe quand), je ne sais pas à quel point le BASIC est capable de gérer cela. Il est possible que ce programme ne fonctionne pas bien sur vrai matériel. Je suis preneur de retours (et j'essaierai moi même un de ces jours).

Voici quelques commentaires :

  • En ligne 100, on initialise les registres nécessaires pour afficher une chaîne de caractère utilisant les mêmes attributs.
  • En ligne 200, on initialise les registres restants pour afficher un caractère et passer à la colonne suivante (attention, il n'y a pas de détection de fin de ligne).
  • En ligne 300, on initialise tous les registres pour afficher un caractère avec des attributs différents. Dans les commentaires KRF est le nom de la commande d'affichage d'un caractère en mode « 40 CHAR LONG ».
  • En ligne 400, une routine se charge de monter en mémoire vidéo les données pour un caractère utilisateur.
  • En ligne 10000, c'est le début du test et j'affichage "BONJOUR". C'est un PRINT en bien plus compliqué et bien plus lent...
  • En ligne 10100, j'affiche les 128 caractères alphanumériques en ROM de l'EF9345.
  • En ligne 10200, j'affiche une autre plage de 32 caractères, graphiques, en ROM de l'EF9345.
  • En ligne 10300, j'affiche les 128 caractères semi-graphiques en ROM de l'EF9345. Dans ces trois affichages, c'est la variable B qui indique le type de caractères à utiliser.
  • En ligne 10400, j'affiche un caractère graphique plein pour montrer les 16 teintes disponibles pour les caractères.
  • En ligne 11000, je tente de lire les registres indirects de l'EF9345. Cela ne fonctionne pas tout à fait bien. Possible que ce soit un problème de synchro (d'où la petite boucle, même si 1/ ce n'est pas comme cela qu'on synchronise l'EF9345 2/ la lenteur du BASIC me fait penser que quoique l'on fasse, il y a toujours un risque de tomber au mauvais moment).
  • En ligne 12300, je modifie le registre indirect ROR afin de faire un scrolling vertical. Comme la mémoire « sous » l'écran n'est pas préparée, cela affiche un peu n'importe quoi. C'est surtout une démonstration de l'utilisation de registre indirect en écriture.
  • En ligne 13000, je charge un caractère utilisateur (le bonhomme du manuel du VG5000µ) puis j'affichage un des « sets » de caractères redéfinis. Particularité : c'est un ensemble de 100 caractères allant de 0 à 3, puis de 32 à 127... L'adresse de destination A=192 est aussi assez compliquée à calculer (en tout cas, ça ne s'invente pas, et le datasheet demande une grande attention, je ferai peut-être un article séparé là-dessus). Dans les caractères affichés, vous verrez les blocs redéfinis pour la compatibilité avec l'Alice 4k.

Pour la manière dont fonctionne la mémoire de l'EF9345, en attendant un article, vous pouvez tentez de comprendre avec le code du fichier ef9345_memory.py dans mon dépôt GitHub dédié aux outils d'étude pour le VG5000µ.

10 CLS:GOTO 10000

100 REM PREPARATION AFFICHAGE CARACTERE
110 POKE 48930,B
120 POKE 48931,A
130 POKE 48934,Y
140 POKE 48935,X
150 RETURN

200 REM AFFICHE UN CARACTERE AVEC INCREMENTATION
210 POKE 48929,C
220 POKE 48936,1:REM KRF + INCR
230 RETURN

300 REM AFFICHE UN SEUL CARACTERE COMPLET
310 POKE 48929,C
320 POKE 48930,B
330 POKE 48931,A
340 POKE 48934,Y
350 POKE 48935,X
360 POKE 48936,0:REM KRF
370 RETURN

400 REM CHARGEMENT D'UN CARACTERE REDÉFINI
410 FOR I=1 TO 10
420 READ C
430 POKE 48932,INT(A/256)
440 POKE 48933,A AND 255
450 POKE 48929,C
460 POKE 48936,48+4:REM OCT + AUX_PTR (EXEC)
470 A=A+4
480 NEXT I
490 RETURN

10000 REM PROGRAMME DE TEST
10010 X=5:Y=0 : REM COORDONNEE
10020 B=0:A=20 : REM ATTRIBUTS
10030 A$="BONJOUR"
10040 GOSUB 100
10050 FOR I=1 TO LEN(A$)
10060 C=ASC(MID$(A$,I,1))
10070 GOSUB 200
10080 NEXT I

10100 REM AFFICHAGE DE CARACTERES
10110 Y=8:X=0:B=0:A=112
10120 FOR C=0 TO 127
10130 IF X>39 THEN X=0:Y=Y+1
10140 X=X+1
10150 GOSUB 300
10160 NEXT C

10200 Y=12:X=0:B=48:A=112
10210 FOR C=0 TO 31
10220 GOSUB 300
10230 X=X+1
10240 NEXT C

10300 Y=13:X=0:B=32:A=112
10310 FOR C=0 TO 127
10320 IF X>39 THEN X=0:Y=Y+1
10330 GOSUB 300
10340 X=X+1
10350 NEXT C

10400 REM COULEURS
10410 Y=17:X=0:B=32:C=127
10420 FOR A=16 TO 112 STEP 16
10430 GOSUB 300
10440 X=X+1
10450 NEXT A
10460 Y=18:X=0:B=33
10470 FOR A=16 TO 112 STEP 16
10480 GOSUB 300
10490 X=X+1
10500 NEXT A

11000 REM LECTURE DES REGISTRES INDIRECTS
11010 POKE 48936,128+8+1:REM IND + LECTURE + TGS (EXEC)
11020 T=PEEK(48929):REM LECTURE R1
11030 PRINT"TGS=";T:FOR I=0 TO 20:NEXT I
11040 POKE 48936,128+8+2:REM IND + LECTURE + MAT (EXEC)
11050 M=PEEK(48929):REM LECTURE R1
11060 PRINT"MAT=";M:FOR I=0 TO 20:NEXT I
11070 POKE 48936,128+8+3:REM IND + LECTURE + PAT (EXEC)
11080 P=PEEK(48929):REM LECTURE R1
11090 PRINT"PAT=";P:FOR I=0 TO 20:NEXT I
11110 POKE 48936,128+8+5:REM IND + LECTURE + DOR (EXEC)
11120 D=PEEK(48929):REM LECTURE R1
11130 PRINT"DOR=";D:FOR I=0 TO 20:NEXT I
11140 POKE 48936,128+8+7:REM IND + LECTURE + ROR (EXEC)
11150 R=PEEK(48929):REM LECTURE R1
11160 PRINT"ROR=";R

12300 REM CHANGE ROR POUR SCROLLING
12310 FOR I=8 TO 31
12320 POKE 48929,I:REM ECRITURE R1
12330 POKE 48936,128+0+7:REM IND + ECRITURE + ROR (EXEC)
12340 FOR J=0 TO 20:NEXT J
12350 NEXT I
12360 POKE 48929,8:REM ECRITURE R1
12370 POKE 48936,128+0+7:REM IND + ECRITURE + ROR (EXEC)

13000 REM CARACTERES REDÉFINIS
13010 DATA 28,58,28,8,127,93,93,28,54,99
13020 A=192
13030 GOSUB 400

13100 Y=20:X=0:B=128+32+16:A=112:REM GP11
13110 FOR C=0 TO 127
13120 IF X>39 THEN X=0:Y=Y+1
13125 IF C=4 THEN C=32
13130 GOSUB 300
13140 X=X+1
13150 NEXT C

14000 GOTO 14000