Les cartes graphiques/Les cartes d'affichage des anciens PC
Dans cette section, nous allons parler rapidement des cartes graphiques des anciens PC, qui étaient des systèmes à framebuffer. Les standards graphiques sur PC étaient le MDA, le CGA, l'EGA et le VGA, dans l'ordre chronologique. C'était les standards les plus communs, qui ont été introduits par les cartes graphiques suivantes :
- IBM Color/Graphics Display Adapter (CGA)
- IBM Monochrome Display and Printer Adapter (MDA or sometimes MDPA)
- IBM Enhanced Graphics Adapter with Graphics Memory Expansion Card (EGA)
- IBM PS/2 Display Adapter (VGA)
Le MDA et le CGA utilisaient des framebuffer compacts, alors que l'EGA et le VGA utilisaient des framebuffer planaires. Cependant, par souci de compatibilité, l'EGA et le VGA supportent les résolutions du CGA et du MDA, avec un framebuffer compact. La mémoire vidéo des cartes graphiques EGA et VGA pouvaient être utilisées soit de manière à avoir un framebuffer planaire ou compact, elle servait pour les deux.
Les cartes graphiques concurrentes étaient la Hercules Graphics Card, la Tandy Video II Graphic Adapter, la Multi-Color Graphics Array (MCGA) et quelques autres. Mais elles étaient peu disponibles et eurent peu de succès, à l'exception de la carte Hercules qui a été supportée dans quelques jeux vidéo.
Les standards MDA et CGA
[modifier | modifier le wikicode]Les tout premiers IBM PC, utilisaient la carte graphique IBM Monochrome Display Adapter (MDA), qui était toujours connectée à un écran 5151 IBM PC Display, que nous appellerons IBM 5151 dans ce qui suit. La carte CGA (Color Graphics Adapter) étaient disponibles en même temps que la carte MDA, mais les écrans CRT qui pouvaient utiliser ses fonctionnalités ont mis un peu de temps avant d'arriver, ce qui fait qu'on considère parfois à tort que la carte MDA est arrivée avant la CGA. La carte MDA ne gérait que le mode texte, en monochrome, alors que la carte CGA gérait jusqu'à 16 couleurs avec un système de palette indicée.
| Modes graphiques | |
|---|---|
| 320 par 200 pixels | 4 couleurs par pixel |
| 640 par 200 pixels | 2 couleurs par pixel |
| Modes texte | |
| 320 par 200 pixels | 40 par 25 caractères |
| 640 par 200 pixels | 80 par 25 caractères |
Les cartes MDA et CGA avaient un hardware très semblable vu de loin. La carte MDA incorporait 4 kilo-octets de RAM vidéo, la carte CGA en avait 16 kilo-octets. Les deux incorporaient un VDC Motorola 6845, qui ne gérait que le mode texte. Les cartes CGA (Color Graphics Adapter) ont trouvé un moyen de supporter le mode graphique avec ce VDC, grâce à des circuits qui entouraient le VDC. Beaucoup de bidouilles étaient nécessaires pour lui faire afficher des graphismes pixel par pixel.
Il était possible d'utiliser une carte MDA en complément d'une carte CGA, dans le même PC. Les deux pouvaient être utilisées pour alimenter deux écrans : un écran monochrome pour la MDA et un écran couleur pour la CGA. Mais elles pouvaient aussi être utilisées pour alimenter un seul écran, la carte CGA se chargeant des calculs graphiques et la MDA pour afficher du texte.
Les alternatives aux cartes MDA/CGA étaient assez nombreuses. La quasi-totalité utilisait cependant le même VDC et un hardware très similaire. On parlait d'ailleurs de clones MDA/CGA. Elles se contentaient souvent d'ajouter des fonctionnalités, plus de mémoire vidéo, etc. Par exemple, la carte Hercules était totalement compatible avec la carte MDA, si ce n'est pour l'ajout d'un mode de résolution graphique capable de faire du pixel par pixel. Il y a cependant quelques exceptions comme la Professional Graphics Controller qui intégrait un processeur Intel 8088 en guise de VDC.
Une description détaille des cartes CGA, avec leurs registres de configuration, est disponible via ce lien. Je n'en conseille pas la lecture maintenant :
Le standard EGA
[modifier | modifier le wikicode]Par la suite, les cartes graphiques MDA et CGA ont été remplacées par les cartes EGA. De nombreuses cartes graphiques sensiblement identiques à l'EGA, des clones hardware, ont envahi le marché, transformant l'EGA en standard de facto. Elles géraient entre 4 et 16 couleurs, suivant la résolution, avec un système de palette indicée.
Les cartes EGA ont remplacé le framebuffer compact des anciennes cartes MDA/CGA par un framebuffer planaire. La mémoire vidéo de la carte EGA était composée de 4 banques, chaque banque étant un bitplane. En clair, les modes gérant 16 couleurs codaient un pixel sur 4 bits, avec un bit par bitplane/banque. Cependant, la résolution 640 par 350 pixels n'utilisait que deux couleurs et utilisait un framebuffer compact. Le choix entre un framebuffer planaire et compact était réalisé en configurant un bit dans le registre de configuration adéquat, à savoir le registre Sequencer Memory Mode Register , faisant partie du Sequence Controller. Le bit nommé Chain 4 Bit valait 0 pour un framebuffer planaire, 1 pour un framebuffer compact.
| Résolution | Couleurs par pixel | Framebuffer |
|---|---|---|
| 320 par 200 pixels | 16 couleurs par pixel | framebuffer planaire |
| 640 par 200 pixels | 16 couleurs par pixel | |
| 640 par 350 pixels | 16 couleurs par pixel | |
| Mode nécessitant la carte d'extension mémoire | ||
| 640 par 350 pixels | 2 couleurs par pixel | framebuffer compact |
L'architecture d'une carte EGA
[modifier | modifier le wikicode]Une carte EGA était composée de 4 circuits, chacun ayant ses propres registres : le CRT Controller (CRTC), le Sequence Controller (SC), l'Attribute Controller (AC) et le Graphics Controller (GC).
- Le CRTC est un CRTC basique mais ce n'est pas le MC6845 des cartes CGA/MDA, bien que la compatibilité entre eux soit garantie.
- L'Attribute Controller est un RAMDAC amélioré.
- Le Sequence Controller communique avec le RAMDAC et le CRTC pour accéder à la mémoire vidéo.
- Le circuit restant, le Graphics Controller, sert d'interface entre le bus et la mémoire vidéo.
Les quatre composants précédents sont collés entre eux par un paquet de circuits qui servent d'interface entre eux. Une carte EGA contient de nombreux registres, multiplexeurs et autres circuits. Voici ce que donne l'ensemble en schéma :

Les cartes EGA intégraient 64 kilo-octets de mémoire vidéo sur la carte elle-même, mais on pouvait ajouter une seconde carte d'extension pour passer à 256 kilo-octets. Certaines résolutions ne fonctionnaient que si cette carte d'extension mémoire était présente.
Le multi-GPU EGA/CGA
[modifier | modifier le wikicode]Les cartes EGA pouvaient fonctionner de concert avec une seconde carte CGA, MDA ou Hercules. Un PC de l'époque pouvait avoir une carte EGA sur un port d'extension, et une carte MDA/CGA sur un autre. Quand une carte CGA est installée, la carte EGA ne fonctionne qu'en mode monochrome. Par contre, quand la seconde carte est une carte MDA ou Hercules, la carte EGA ne fonctionne qu'avec les résolutions à 4 ou 16 couleurs. En clair, elle prend en charge l'affichage monochrome avec les cartes CGA (polychromes), coloré avec les cartes MDA monochromes.
L'utilisation d'une carte EGA avec une autre carte MDA/CGA s'explique par une histoire d'entrée-sorties mappées en mémoire. Pour rappel, des adresses mémoires, censées adresser la mémoire RAM, sont détournées pour adresser la mémoire vidéo. Il en est de même pour les registres de configuration de la carte graphique : des adresses mémoire sont détournées pour pointer vers ces registres. Si on regarde l'ensemble des adresses gérées par le processeur, certaines pointent vers la RAM, d'autres vers la carte graphique, d'autres vers des périphériques, d'autres vers le BIOS, etc. Les cartes EGA et les cartes MDA/CGA détournent des adresses différentes. La mémoire des PC de l'époque était découpée en blocs de 64 kilo-octets, que le système d'exploitation DOS allouait comme suit :
| Numéro du bloc | Contenu du bloc |
|---|---|
| 0 | Mémoire RAM, mémoire conventionnelle |
| 1 | |
| 2 | |
| 3 | |
| 4 | |
| 5 | |
| 6 | |
| 7 | |
| 8 | |
| 9 | |
| 10 | Mémoire vidéo des cartes EGA |
| 11 | Mémoire vidéo des cartes MDA ou CGA |
| 12 | ROM d'extension des périphériques (XT, EGA, 3270 PC) |
| 13 | Autre, non-réservé |
| 14 | Autre, non-réservé |
| 15 | ROM du BIOS |
Le standard VGA
[modifier | modifier le wikicode]Le standard VGA fait suite au standard EGA et gère des résolutions jusqu'à 640 par 480. Il intègre aussi un support du double buffering, à savoir qu'il gère deux framebuffers séparés. Mais le double buffering n'est possible que dans les basses résolutions, car il n'y a pas assez de mémoire vidéo pour les deux framebuffers dans les hautes résolutions. Le VGA intègre aussi d'autres fonctionnalités qui seront détaillées dans le chapitre suivant, notamment pour ce qui est du défilement horizontal/vertical.
Les résolutions supportées par le VGA
[modifier | modifier le wikicode]Le standard VGA décrit plusieurs modes de fonctionnement, chacun correspondant à une résolution avec un nombre de couleur associé. Ils sont numérotés en hexadécimal, les modes 1 à 16 (0xFh) correspondent aux résolutions supportées par les cartes MDA, CGA et EGA, les quatre modes restants sont spécifiques au VGA. D'autres modes non-standards sont supportés par la majorité des cartes VGA, comme le mode X, un mode non-officiel qui définit une résolution de 320 par 240 pixels, avec 256 couleurs par pixel.
Suivant le mode utilisé, le framebuffer sera soit de type compact, soit de type planaire ! Les modes gérant 256 couleurs par pixel utilisent un framebuffer compact, avec un octet par pixel. Par contre, les modes 16 couleurs codent un pixel sur 4 bits, ce qui colle mieux avec un framebuffer planaire à quatre bitplanes. Les modes 16 couleurs sont surtout utilisés avec des résolutions élevées, alors que les modes 256 utilisent des résolutions basses, pour des raisons de mémoire vidéo. Par exemple, une résolution de 640 par 480 fait qu'une image contient 307 200 pixels, ce qui prend au minimum 300 kilo-octets en mode 256 couleurs ! Or, les cartes graphiques VGA disposaient de seulement 256 kilo-octets de mémoire vidéo. Vous devinez que la carte graphique ne supportait pas 256 couleurs par pixels dans cette résolution, mais qu'elle codait un pixel sur moins d'un octet.
Le mode le plus utilisé est le mode 13h, d'une résolution de 320 par 200 pixels pour 256 couleurs par pixel. Il a été utilisé par la grosse majorité des jeux vidéos de l'époque, car son framebuffer compact était beaucoup plus pratique pour les programmeurs, malgré des performances moindres que les autres modes VGA. Quelques jeux vidéos ont cependant utilisé le mode 11h avec son framebuffer planaire, comme l'a fait DOOM 1 et sa suite DOOM 2. Cependant, les autres jeux basés sur le même moteur utilisaient le mode 13h, l'exemple typique étant celui des FPS Heretic et Hexen de Raven Software.
| Mode | Résolution | Couleurs par pixel | Framebuffer |
|---|---|---|---|
| mode 10h | 640 par 350 pixels | 4 à 16 couleurs par pixel (dépend de la RAM vidéo installée) | framebuffer planaire |
| mode 11h | 640 par 480 pixels | Monochrome, 2 couleurs par pixel | framebuffer planaire |
| mode 12h | 640 par 480 pixels | 16 couleurs par pixel | framebuffer planaire |
| mode 13h | 320 par 200 pixels | 256 couleurs par pixel | framebuffer compact |
L'organisation du framebuffer
[modifier | modifier le wikicode]La mémoire vidéo fait 256 kilo-octets, répartis dans 4 mémoires RAM de 64 kibioctets chacune. En mode framebuffer compact, un pixel fait un octet. Chaque octet d'une banque correspond à un pixel.
| Octet banque 1 | Pixel 1, codé sur 8 bits |
|---|---|
| Octet banque 2 | Pixel 2, codé sur 8 bits |
| Octet banque 3 | Pixel 3, codé sur 8 bits |
| Octet banque 4 | Pixel 4, codé sur 8 bits |
Avec un framebuffer planaire, les pixels sont codés sur 4 bits. Idéalement, chaque bitplane doit être une mémoire bit-adressable, à savoir que chaque adresse mémoire sélectionne un bit. Mais il s'agit là d'un cas idéal que les cartes VGA en respectaient pas. A la place, chaque bitplane est une mémoire adressable par octet, et non par bit. Heureusement, elles intégraient des circuits pour simuler une mémoire bit-adressable à partir d'une mémoire adressable par octet.
Les quatre banques sont accessibles en parallèles, ce qui permet de lire/écrire 4 octets en même temps, un octet par banque. Dans le mode framebuffer planaire, les 4 octets lus sont découpés en 8 pixels de 4 bits d'un coup. Le DAC situé en aval de la mémoire vidéo recevait 8 pixels de 4 bits chacun, et mémorisait le tout dans une petite mémoire tampon. Il fournissait, en sortie un pixel par cycle d'horloge. Une seule lecture dans la mémoire vidéo permettait au DAC d'afficher 8 pixels pour une seule lecture en mémoire vidéo.
| Pixel 1 | Pixel 2 | Pixel 3 | Pixel 4 | Pixel 5 | Pixel 6 | Pixel 7 | Pixel 8 | |
|---|---|---|---|---|---|---|---|---|
| Octet banque 1 | 0 | 0 | 1 | 1 | 0 | 0 | 1 | 1 |
| Octet banque 2 | 1 | 1 | 1 | 1 | 1 | 0 | 1 | 1 |
| Octet banque 3 | 0 | 1 | 1 | 1 | 0 | 0 | 0 | 0 |
| Octet banque 4 | 0 | 0 | 1 | 0 | 1 | 0 | 1 | 1 |
Le registre intermédiaire : les VGA latches
[modifier | modifier le wikicode]Pour gérer au mieux les lectures et écritures, une carte VGA intègre un registre intermédiaire de 32 bits qui sert d'intermédiaire pour les lectures et écritures. Lors d'une lecture, un octet est lu dans chaque bitplane et les 4 octets lus sont alors enregistrés dans ce registre intermédiaire. Là, les 32 bits sont alors soit envoyé au RAMDAC pour être affichés à l'écran, soit envoyés au processeur lors d'une lecture.

Pour les écritures, le registre intermédiaire est utilisé pour diverses opérations. Par exemple, supposez que le programmeur ne veut modifier qu'un seul pixel codé sur 4 bits. Dans ce cas, il doit lire 32 bits, ne modifier que le pixel dans ces 32 bits, et écrire le résultat en mémoire vidéo. Les bits à modifier sont précisés dans un registre de masque, le Bit Mask Register. Il fait 32 bits, soit la même taille que le registre intermédiaire, et chaque bit du registre de masque correspond à un bit du registre intermédiaire. Si le bit en question est à 1, le bit à écrire provient du registre intermédiaire. Sinon, il vient du pixel envoyé par le CPU.
Pour appliquer le masque, le registre intermédiaire est complété par un circuit de masquage, qui permettent de ne modifier que certains bits dans les 32 bits. Le circuit de masquage est concrètement un ensemble de multiplexeurs qui permettent de choisir, pour chaque bit à écrire dans une bitplane, s'il vient du registre intermédiaire, ou des données envoyées par le processeur. Les multiplexeurs sont commandés par un registre de masque.
Le VGA fournit deux modes de lecture et quatre modes d'écriture. Pour les écritures, il y a quatre modes nommés mode 0, 1, 2 et 3, que nous détaillerons dans la suite. L'utilisation des circuits de masquage dépend du mode d'écriture. Pour simplifier, il y a trois cas distincts.
- Dans le mode d'écriture numéro 0, le processeur envoie un nouveau pixel par cycle. Le masque est mémorisé dans un registre et est stable d'une écriture sur l'autre. Il s'agit du fonctionnement intuitif, où le processeur écrit dans le framebuffer.
- Dans le mode d'écriture numéro 3, c'est l'inverse. Le processeur envoie un nouveau masque par cycle, alors que le pixel à écrire est mémorisé dans un registre et reste le même d'une écriture sur l'autre. Ce mode sert à remplir une zone de l'écran avec une même couleur, que ce soit pour tracer des lignes, colorier une figure géométrique, remettre à zéro le framebuffer.
- Dans le mode d'écriture numéro 1, le circuit de masquage est configuré pour recopier le registre intermédiaire dans la RAM directement. Il sert pour les copies mémoire-mémoire, à savoir copier des données de la mémoire vidéo vers un autre endroit.

Les circuits annexes : ALU, SET/RESET et barrel shifter
[modifier | modifier le wikicode]Les circuits de masquage en question sont complétés par une petite unité de calcul 32 bits, séparée du circuit de masquage, qui gère les opérations logiques OR, AND, XOR. La différence est que le circuit de masquage combine un masque stocké dans un registre dédié avec le registre intermédiaire, alors que l'ALU combine les données envoyées par le CPU et le registre intermédiaire.
Toute carte VGA permet aux écritures de n'écrire que dans certaines bitplanes/banques et de laisser les autres tranquilles. Pour cela, il incorpore un registre de 4 bits, le Map Mask register, qui indique quelles banques doivent être activées lors d'une écriture. Il y a un bit par banque, qui indique si elle est éteinte ou allumée lors d'une écriture, seules les banques allumées se font écrire dedans. Notons qu'avec cette technique, les bitplanes désactivées conservent les données précédentes. Ce n'est pas un problème si on souhaite appliquer des effets graphiques bien précis après avoir rendu une image complète dans le framebuffer planaire : on calcule une image, puis on applique l'effet en manipulant une ou deux bitplanes. Mais cela pose problème dans d'autres situations. Si jamais une image a été rendue précédemment, ses pixels resteront dans les bitplanes. Désactiver les écritures lors du rendu de l'image suivante donnera un mélange entre image précédente et image nouvelle.
Pour éviter cela, il faut ajouter une fonctionnalité qui remet à 0 le framebuffer, octet par octet. La remise à zéro en question peut effacer totalement le framebuffer, à savoir les quatre bitplanes, en remplissant ses octets avec la valeur 0000 0000. Il est aussi, possible de réinitialiser le framebuffer en mettant chaque octet à 1111 1111. Mais il est aussi intéressant de ne réinitialiser qu'une partie des bitplanes, par exemple seulement une, deux ou trois bitplanes. Pour cela, la carte VGA incorpore un circuit de SET/RESET avant l'ALU. Il agit sur les octets envoyés par le processeur et destinés aux bitplanes, à savoir qu'il peut les mettre soit à 0000 0000, soit à 1111 1111, soit ne pas les modifier. La commande de ce circuit est réalisée par deux registres dédiés.
Enfin, cartes VGA intègrent un barrel shifter, qui fait des opérations de rotations sur l'octet envoyé par le processeur (les décalages ne sont pas supportés). Il était rarement utilisé pour aligner les données au pixel près, plutôt qu'à l'octet près. Mais il était peu utilisé, car le processeur sait faire ce genre d'opérations nativement. L'ALU et le barell shifter sont commandés par un registre unique, le Data Rotate register, qui indique quelle opérations ils doivent faire. Le contenu de ce registre est découpés en deux champs : un qui dit au barell shifter de combien de rangs il faut rotater, et quelle opération l'ALU doit faire.
Les modes d'écriture VGA
[modifier | modifier le wikicode]La différence entre les modes d'écriture 0, 1, 2 et 3 tient à l'activation ou non des circuits de SET/RESET, de masquage, et autres.
Le mode d'écriture 0 est celui où tous les circuits sont utilisables. Ils ne sont pas forcément tous utilisés, mais peuvent l'être. Les données envoyées par le CPU sont rotatées (ou non), puis passent par le circuit de SET/RESET (qui peut ne rien faire), puis dans l'ALU pour être combinées avec le registre intermédiaire (qui peut simplement recopier l'octet qu'elle recoit), le résultat est masqué (ou non) et enregistré dans les bitplanes actives, certaines pouvant être désactivées.

Le mode d'écriture numéro 1 est utilisé pour faire des copies en mémoire vidéo, de la mémoire vidéo vers elle-même. Ce mode d'écriture se contente de recopier le contenu du registre intermédiaire en mémoire vidéo, les octets envoyés par le processeur ne sont pas utilisés s'ils sont présents. On peut l'émuler à partir du mode 0 en configurant les circuits de masquage proprement.
Il faut noter que le registre intermédiaire maintien une donnée indéfiniment et quelques jeux vidéos ou applications utilisaient cette propriété. Par exemple, cela permet de remplir un framebuffer avec un arrière-plan, avant de re-dessiner dessus. L'idée est d'écrire le motif d'arrière-plan en mémoire vidéo, de le lire pour charger le registre intermédiaire avec, et de lancer une série d'écriture en mode 1 pour recopier le motif dans les adresses mémoires voulues.

Le mode d'écriture numéro 2 est lui un mode de remplissage. Il permet d'écrire une couleur dans plusieurs pixels consécutifs, dans un framebuffer planaire. Au lieu de modifier chaque pixel un par un, avec des opérations de masquage, l'idée est alors de modifier plusieurs pixels consécutifs en une seule fois. On peut modifier jusqu'à 8 bits consécutifs en mémoire vidéo, vu que les bitplanes sont des mémoires adressables à l'octet. C'est très utile pour remplir le framebuffer avec une couleur par défaut, pour le réinitialiser/effacer, ou encore pour tracer des segments/lignes horizontales ou diagonales, par exemple.
Dans ce mode d'écriture, les circuits de SET/RESET sont au premier plan. Pour comprendre pourquoi, regardons ce qui se passe quand on écrit une même couleur dans 8 pixels consécutifs. Pour simplifier, on part du principe que les 8 pixels sont tous dans le même octet, on dit qu'ils sont alignés sur un octet. La couleur écrite est codée naturellement sur 4 bits, et vaut 0101.
| Pixel | Pixel 1 | Pixel 2 | Pixel 3 | Pixel 4 | Pixel 5 | Pixel 6 | Pixel 7 | Pixel 8 | |
|---|---|---|---|---|---|---|---|---|---|
| Octet banque 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
| Octet banque 2 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 |
| Octet banque 3 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
| Octet banque 4 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 |
On voit que chaque bit du pixel a été recopié à l'identique dans un octet. Les octets écrits dans le framebuffer planaire valent donc soit 0000 0000, soit 1111 1111. Vous aurez deviné que c'est un cas parfait pour utiliser les circuits de SET/RESET, qui fournissent naturellement les octets 0000 0000 et 1111 1111 sur leur sortie. En clair, chaque bit d'un pixel commande l'octet envoyé sur la bitplane correspondante. Par exemple, si le bit de poids faible vaut 0, alors l'octet à écrire dans la bitplane associée vaut 0000 0000. Pour le dire autrement, l'octet envoyé par le processeur, le pixel envoyé, commande des circuits de SET/RESET : ses 4 bits de poids faible indiquent quels bitplanes sont à mettre à 0000 0000 et celles à mettre à 1111 1111.
Les octets mis à 0000 0000 ou 1111 1111 passent ensuite dans l'ALU et les circuits de masquage et sont enregistrés dans les bitplane actives. Les circuits de masquage sont actifs au cas où certaines zones de l'image ne doivent pas être remplies avec le pixel. Par exemple, imaginez qu'on souhaite remplir un carré avec une couleur par défaut, en utilisant le mode d'écriture 2. Dans ce cas, le masque désigne quels pixels sont dans le carré et ceux en-dehors.

Le mode d'écriture numéro 3 est lui aussi utile pour faire du remplissage ou pour tracer des lignes, mais aussi pour écrire du texte transparent. Son principe est le suivant : on écrit une couleur par défaut dans le framebuffer dans certains pixels seulement, un masque décrit quels bits/pixels modifier pour ne pas effacer ce qui doit l'être. La différence est qu'avec le mode 3, chaque octet provenant du processeur est un nouveau masque à appliquer. Le mode 2 précise la couleur des pixels à modifier avec un masque préconfiguré, le mode 3 précise quel masque utiliser avec une couleur par défaut préconfigurée.
Là-encore, les circuits de SET/RESET sont programmés pour dessiner une couleur par défaut. Sauf que cette fois-ci, la couleur est précisée en configurant les registres adéquats, elle n'est pas fournie par l'octet provenant du processeur. Là encore, les circuits de masquage permettent de choisir entre ce qui est déjà dans le framebuffer planaire, et la couleur par défaut. La différence est que le masque est fournit par l'octet envoyé par le processeur.
Pour donner un exemple d'utilisation, prenez le cas où on veut écrire du texte au-dessus d'une image déjà calculée dans le framebuffer. L'écriture du texte se fait caractère par caractère, chaque caractère étant un octet envoyé par le processeur à la carte VGA. Le processeur lit d'abord les pixels sur lesquels écrire le caractère, afin de les copier dans le registre intermédiaire. Puis, il écrit le caractère avec le mode 3 : le calcul du masque donne les pixels à modifier.

Précisons cependant que le masque n'est pas l'octet envoyé par le processeur. A la place, le masque est calculé en prenant le masque présent dans le registre de masque, puis en faisant un ET logique avec l'octet envoyé par le processeur. L'octet est potentiellement rotaté avant, pour l'aligner au pixel près, mais c'est facultatif.

Les modes de lectures VGA
[modifier | modifier le wikicode]Pour la lecture deux modes sont possibles : un plutôt associé à un framebuffer planaire, le second adapté à un framebuffer compact.
Le premier mode de lecture, le read mode 0 lit les octets d'une bitplane un par un. La bitplane en question est sélectionnée en configurant deux bits du Read Map register : 2 bits, 4 valeurs, 4 bitplanes. Le processeur configure ce registre et peut adresser la bitplane directement. Par contre, il n'accède qu'à une bitplane à la fois. Lire un pixel entier demande de changer de bitplane quatre fois de suite, ce qui a un cout en performance très important. Le cout pour lire 8 pixels est le même, ce qui amorti la situation, mais sans faire de miracles.
Idéalement, il faudrait un mode de lecture qui simule un framebuffer compact, par exemple un mode qui permette de lire un pixel en allant piocher dans les 4 bitplanes, voire un mode qui permette de lire 8 pixels d'un seul coup. Mais les cartes VGA ne fournissent pas de mode de lecture aussi pratique. Par contre, ils ont un mode plus limité, appelé le read mode 1.
Il lit 8 pixels dans un framebuffer planaire et les compare à une couleur de référence, stockée dans le registre Color Compare Register. Le résultat est un groupe de 8 bits, chacun stockant le résultat de la comparaison pour un pixel. Lors de la comparaison, il est possible de désactiver des bitplanes. Un registre, le Color Don’t Care register, permet de configurer quelles bitplanesa activer ou désactiver. Il contient un bit par bitplane, qui permet d'activer la bitrplane s'il est à 1, la désactiver s'ils est à 0.
Le RAMDAC des cartes VGA
[modifier | modifier le wikicode]Les cartes VGA utilisent un système de palette indicée et fournissent en sortie une couleur analogique. Pour cela, elles incorporent une mémoire SRAM pour mémoriser la palette indicée, ainsi qu'un convertisseur numérique vers analogique pour traduire le tout en signaux analogiques pour l'écran. Les deux circuits sont regroupés en un seul, dans un circuit unique appelé un RAMDAC, pour rappel. Le RAMDAC d'une carte VGA est cependant plus complexe qu'un RAMDAC normal, et ce pour une raison simple : le nombre de couleurs dépend de la résolution. Il est de 2, 4, 16, 256 couleurs. Les résolutions à 2, 4 et 16 couleurs sont gérés à par du mode 256 couleurs, et une partie est liée à la compatibilité EGA.
Pour commencer, regardons d'abord le mode 256 couleurs. Dans ce mode, la mémoire vidéo fournit un octet, qui indique quelle couleur afficher. L'octet est alors envoyé à un RAMDAC principal, qui convertit cette couleur 8 bits en signaux analogiques RGB. La conversion se fait en deux temps. La première étape est le passage par une palette indicée, qui traduit l'octet en entrée en une couleur codée sur 18 bits : 6 bits pour le rouge, 6 pour le vert, 6 pour le bleu. La SRAM de la palette indicée prend un octet sur l'entrée d'adresse et contient 256 registres de 18 bits. Les 18 bits sont alors envoyés aux circuits de conversion analogique, pour obtenir la couleur finale. Il y a donc un RAMDAC 8 bits, qui sert de RAMDAC principal.
La gestion des modes 2, 4, 16 couleurs se fait en utilisant le RAMDAC 8 bits. Avec ces modes, la couleur est codée sur 4 bits, et est lue depuis un framebuffer planaire. Les 4 bits sont alors étendus pour passer vers 8 bits, qui sont ensuite envoyés au RAMDAC 8 bits. La conversion vers l'analogique se fait donc en deux étapes : une première étape traduit un pixel de 4 bits en un octet, la seconde étape prend cet octet et le transforme en signaux analogiques. Le passage de 4 à 8 bits se fait en gardant la compatibilité avec les résolutions des cartes EGA, qui utilisaient une palette indicée spécifique.
Les cartes EGA avaient une palette indicée très simple, qui contenait 16 registres, chacun contenant une couleur codée sur 6 bits. Elle prenait en entrée un pixel codé sur 4 bits, qui adressait un des 16 registres de couleur. Il est possible d'émuler ce système en envoyant les 4 bits du pixels directement dans le RAMDAC 8 bits, en remplacant les 4 bits de poids fort manquant par des zéros. Une solution alternative découpe la palette de 256 couleurs du RAMDAC en 16 sous-palettes de 16 couleurs. Les 4 bits de poids fort décident quelle sous-palette utiliser, les 4 de poids fiable sélectionne une couleur dans la palette choisie. Les 4 bits pour sélectionner la palette proviennent du d'un registre appelé le Color Control Register

Néanmoins, il s'agit d'une émulation de la palette EGA. Les cartes VGA gérent un mode de compatibilité EGA avec un système de color paging qu'on va décrire ci-dessous. Les cartes VGA conservent la palette EGA, ce qui fait qu'il y a une première phase qui transforme un pixel en 6 bits, ce qui permet de coder 64 couleurs différentes. Pour obtenir l'octet à envoyer au RAMDAC 8 bits, les cartes VGA rajoutent deux bits à la couleur EGA, qui proviennent du Color Control Register.
Pour implémenter les deux modes d'écrit plus haut, les cartes VGA se débrouillent avec le système suivant. Les 4 bits de poids faible proviennent de la platte indicée, toujours. Les deux bits de poids fort proviennent du color control register. Les deux bits entre les deux viennent soit du color control register, soit de la palette EGA, un MUX choisit entre les deux. Le choix entre les deux dépend du bit 7 du registre de configuration AC Mode Register. Dans le cas où les deux bits de poids fort sont remplacés par le color control register, la palette du RAMDAC est découpée en 16 palettes indicées de 4 bits.

Le mode écran divisé (splitscreen)
[modifier | modifier le wikicode]Les cartes VGA incorporent des optimisations pour supporter l'affichage en splitscreen, appelé en français affichage en "écran divisé", ou affichage divisé. Le standard VGA ne supportait qu'un affichage divisé simple : l'écran était coupé en deux à l'horizontale, avec une moitié haute et une moitié basse. L'écran n'était pas forcément coupé en deux parties égales, la ligne de démarcation entre les deux écrans était configurable. Prenons l'exemple d'une résolution de 320 par 200 pixels, soit 200 pixels de haut. Le premier écran pouvait, par exemple, faire 56 pixels de hauteur, le second 144 pixels.
Dans le chapitre "Les systèmes à framebuffer", nous avions vu comment un splitscreen de ce type est optimisé sur certains CRTC. Les cartes VGA utilisent des techniques similaires, mais avec cependant quelques différences. L'implémentation du splitscreeen demande d'avoir deux framebuffers : un pour la moitié haute de l'écran, un pour la moitié basse. Le standard VGA/EGA impose que le framebuffer de la moitié basse démarre à l'adresse zéro en mémoire vidéo. Le framebuffer pour la moitié haute est lui placé plus loin en mémoire vidéo. C'est contreintuitif, mais c'est en réalité tout à fait normal.
L'idée se comprend bien quand on se rappelle de ceci : le CRTC parcours le framebuffer en partant d'une adresse de base, qui lui est fournie dans un registre dédié. Le parcours du framebuffer se fait grâce à l'aide de deux registres, un compteur de ligne et un compteur de colonne. Les trois registres sont utilisés pour calculer l'adresse du pixel à afficher. L'idée est que quand la ligne de démarcation est atteinte, les trois registres sont réinitialisés, ils sont tous trois mis à zéro. Ce qui fait re-démarrer l'affichage à partir de l'adresse zéro. Et cela implique que la moitié basse de l'écran commence à l'adresse 0. La moitié haute doit donc être placée plus loin en mémoire, assez loin pour laisser assez de place à la moitié basse.
La ligne de démarcation est censée être mémorisée dans un registre de splitscreen, qui indique à quelle ligne il faut commuter de framebuffer. Mais les cartes EGA et VGA n'ont pas de registre dédié pour. A la place, les différents bits de ce registre sont dispersés dans plusieurs registres séparés. Les cartes EGA utilisaient une valeur de 9 bits dispersée dans deux registres : les bits 7 à 0 sont dans le Line Compare register (CRTC register 18H), le 9ème bit est dans le registre Overflow register (CRTC register 7). Les cartes VGA rajoutent un 10ème bit, qui est dans le registre Maximum Scan Line register (CRTC register 9). Toute modification de ces registres a un effet immédiat, contrairement à une modification de la plupart des autres registres du CRTC.
Le support du splitscreen était présent pour toutes les résolutions officielles, mais quelques cartes VGA le supportaient aussi pour les résolutions non-officielles. Il fonctionne aussi en mode texte ! En mode texte, le passage d'une moitié d'écran à l'autre a le bon ton d'ajouter un saut de ligne automatique, ce qui fait que le texte du second écran reprend au bon endroit, au tout début d'une ligne. Pour cela, le compteur de ligne est réinitialisé à zéro.
Le PC-98 de NEC
[modifier | modifier le wikicode]Les ordinateurs PC-98 sont une gamme d'ordinateurs japonais qui a grandement évolué dans le temps. Ils s'inspiraient grandement des PC IBM et étaient centrés autour d'un processeur x86. Le standard IBM PC était globalement respecté sur les PC-98 et le PC_98 tournait sur MS-DOS, mais il y avait cependant de nombreuses différences avec les PC x86. La carte d'affichage était totalement différente, le bus ISA était remplacé par un C-bus, le BIOS était différent, les adresses des périphériques étaient différentes, etc.
Les PC-98 ont été déclinés en plusieurs versions, chacune ayant un processeur de plus en plus puissant, plus de mémoire RAM, plus de mémoire vidéo, etc. La première génération utilisait un processeur x86 8086 d'Intel, c'était celle du PC-9801. La seconde génération a démarré avec le PC-9801VM. Leurs capacités graphiques étaient différentes, comme on va le voir.
Le support des caractères japonais
[modifier | modifier le wikicode]Le support des caractères japonais demande beaucoup de contraintes. Afficher des Kanjis demande d'utiliser une mémoire de caractère très grosse, capable de mémoriser plusieurs centaines ou milliers de caractères, dont des Kanjis, hiragana et katakana. Concrètement, la mémoire de caractère des PC-98 mémorisait près de 700 caractères, qui suivaient les standards JIS X 0201 et JIS X 0208.
De plus, afficher des kanjis demande d'utiliser des hautes résolutions, au moins 640 par 400, pour que les kanjis soient lisibles. La mémoire vidéo devait être compatible avec de tells résolution. Sur les PC_98, la mémoire vidéo faisait entre 12 et 256 kilo-octets, ce qui était beaucoup pour l'époque, mais était nécessaire pour supporter les hautes résolutions.

Le double rendu texte-graphique
[modifier | modifier le wikicode]
Le framebuffer graphique était de type planaire et intégrait 4 bitplanes, comme le VGA. A partir du PC-9801VM ajoutait de quoi lire/écrire en parallèle dans plusieurs bitplanes, grâce à l'ajout d'un circuit nommé Graphics Charger. C'est aussi à partir de ce modèle que la mémoire de caractère et une palette indicée reconfigurable ont été ajoutés. Le PC-9801VX améliora le Graphic Charger pour ajouter un blitter.
En général, une carte d'affichage fonctionne soit en mode texte, soit en mode graphique, pas les deux. Les ordinateurs de la gamme PC-98 permettaient de fusionner les deux. Pour cela, ils étaient structurés autour de deux VDC NEC μPD7220 : un qui fonctionnait en mode texte, un autre en mode graphique. Les deux VDC lisaient dans des mémoires vidéos séparées. Le VDC fonctionnant en mode graphique était relié à une mémoire vidéo dédiée, le VDC en mode texte était quant à lui relié à une text RAM qui servait de tampon de texte. La text RAM faisait entre 8 et 12 kilo-octets, suivant les modèles, alors que la mémoire vidéo faisait 96, 192 ou 256 kilo-octets. Le framebuffer était d'abord rendu en mode graphique, et le second VDC pouvait superposer du texte au-dessus.
