CRTC 6845
5 mai 2024

Identifier le CRTC en… BASIC !

Par Claire CheshireCat

Jusqu’à maintenant, j’avais toujours considéré l’identification logicielle du processeur graphique du CPC comme un truc un peu mystérieux, compliqué. J’avais trouvé sur Internet un source de 80 lignes d’assembleur qui semblait faire le job et je l’utilisais sans me poser plus de question. Mais le CRTC Compendium de Longshot a remis les pendules à l’heure : Il y a une partie du document dédiée à l’identification du CRTC. Et j’ai été surprise de voir à quel point il était simple d’identifier ce composant. Tellement simple qu’un simple programme en BASIC est tout à fait capable de le reconnaître ! Je vous explique comment.

Tout d’abord, voyons comment le Basic permet d’interroger directement les composants du CPC. Il faut savoir que chaque composant est branché sur un bus d’entrée sortie. Un boulevard à octets, où chacun a son (ou ses adresses). On a juste à connaître le numéro du composant (généralement noté en hexadécimal) pour poster notre donnée au bon endroit. Et éventuellement lire des réponses. Pour le CRTC, les adresses qui nous intéressent sont &BC00, &BD00 et &BF00.

Le CRTC est doté d’un certain nombre de registres, qu’on peut assimiler à des variables pour faire simple. Si tous les registres peuvent être modifiés, un certain nombre ne peuvent pas être lus. Comme si en basic on pouvait faire a=50, mais que « print a » répondait invariablement zéro, quelle que soit la valeur de a. C’est sur cette subtilité qu’on va baser notre identification, les CRTCs ayant différents comportements lorsqu’on essaye de lire la valeur des registres.

Lire un registre

Avant la lecture proprement dite, on va devoir informer que CRTC de la donnée à laquelle on veut accéder. On va donc lui envoyer le numéro de registre, par exemple pour le registre 12 il suffit de taper « Out &bc00,12 ». Il ne se passe rien de spécial, et c’est normal ! On lui a dit de nous mettre à disposition la valeur du registre 12, mais ça ne change en rien son fonctionnement de génération de l’écran. En gros, il a mis sa valeur en attente dans sa boite à message, à nous d’aller la chercher au bon endroit. Et c’est un « INP &BF00 » qui fait le job.

Donc en Basic, on pourra faire : « out &bc00,12 : print inp(&bf00) »

… Et c’est là où ça se corse

Certains lecteurs vont répondre « Ouais mais Claire ton programme il est moisi, ça affiche juste un 0 ». Et d’autres vont rebondir « Ah bah non, moi j’ai un 48 ! ». Ne vous avais-je dit que certains registres étaient accessibles en lecture, et d’autres non ? Et bien voilà, on est en plein dedans !

Sur les CRTCs 1 et 2, le registre 12 n’est pas accessible, alors que les CRTC 0, 3 et 4 ne feront pas d’histoire pour vous fournir la valeur !

On vient donc de séparer nos cinq CRTCs en deux groupes distincts. Reste à trouver un moyen de distinguer le 1 du 2 et le 3/4 du 0

Différencier le CRTC1 et le CRTC2

C’est la même chose que la fois précédente : Seul le CRTC1 possède un registre numéro 31. C’est une sorte de registre d’information qui ne nous servira pas à grand-chose (Je vous renvoie au Compendium, chapitre « Registres en Lecture » si vous voulez en savoir plus).

Rien de mystérieux, « out &bc00,31:print inp(&bf00) » renverra une valeur nulle si vous êtes sur CRTC2 (Pas de registre 31 accessible en lecture), et une valeur différente de zéro si vous êtes sur CRTC1. Différencier le CRTC0 des CRTCs 3 et 4 est bien plus amusant !

A l’assaut du CRTC0 !

Toujours dans le Compendium, quand on compare les CRTCs 0 et 4 (Je ne parlerai plus que du 4, mais mes remarques sont valables aussi pour le 3) on voit que ce dernier possède deux registres en lecture de plus que le CRTC0. Mais ces registres sont liés à l’affichage écran, ils changent constamment et rien ne dit que par un malencontreux hasard on ne va pas lire ces registres pile au moment où ils seront à 0, ce qui nous feront prendre (à tort) un CRTC4 pour un zéro. Ce ne serait pas sérieux.

Heureusement il y a une autre différence qui va nous permettre de nous en sortir : Le CRTC0 considère seulement les 5 premiers bits pour la désignation du registre en lecture, alors que le 4 n’en prend en compte que 3. En pratique ça veut dire quoi ? Le CRTC0 fait un modulo 32 sur le numéro de registre avant d’envoyer le résultat. Le registre 12 est donc accessible en lecture en tant que registre 12, mais 12+32, 12+32+32, 12+32+32+32… Renverront aussi le même résultat. Pour le CRTC4, c’est pire, c’est un modulo 8 qui est effectué ! On peut donc dire que demander la valeur du registre 12+8 sur CRTC 0 renverra 0 (le registre 12+8=20 est un registre non disponible en lecture), alors que sur CRTC 4, lire ce même registre renverra la valeur du registre 12 (qui sera en réalité le registre 4 de son point de vue, mais le résultat est le même) ! « out &bc00,20:print inp(&bf00) » renverra donc une valeur nulle sur CRTC0, et la valeur du registre 12 sur CRTC 4.

On a fini ?

Si on veut faire un programme compatible tous CPCs (Et donc ne pas faire un programme compatible uniquement avec le CPC+), on a fini ! Si vous voulez faire un programme qui utilise les fonctions étendues de l’ASIC il reste une petite vérification supplémentaire, qui consisterait à délocker l’Asic. Mais ça n’a pas grand intérêt dans le cadre de cet article.

Il ne vous reste donc plus qu’à tapoter le programme présenté avec cet article pour mettre un doigt dans l’engrenage et vous lancer dans la programmation système !

Plaintext
10 MODE 1:' On reinitialise l'ecran
20 OUT &BC00,12:IF INP(&BF00)=0 THEN GOTO 80
30 ' Si on est ici on a soit un CRTC0, soit un 4
40 OUT &BC00,20:IF INP(&BF00)=0 THEN GOTO 60
50 PRINT"crtc 4":END
60 PRINT"crtc 0":END
70 ' Si on est ici on a soit un CRTC1, soit un 2
80 OUT &BC00,31:IF INP(&BF00)=0 THEN GOTO 100
90 PRINT"crtc 1":END
100 PRINT"crtc 2":END

Cet article est auparavant paru dans le fanzine ùCPM, et peut être également consulté sur le site web ASMTRAD CPC.