L’Adaptive Tile Refresh de Commander Keen
(fabiensanglard.net)- Adaptive Tile Refresh (ATR) est la technique de défilement utilisée dans Commander Keen 1 à 3 pour éviter le rafraîchissement plein écran trop lent de l’EGA, en ne redessinant que les tuiles modifiées au lieu de toute l’image
- Le mode EGA
Dhstocke un affichage 320x200 en 16 couleurs dans 4 plans (C0àC3) et, si l’on écrit les 32 Kio de l’écran complet à chaque frame via le bus ISA, on tombe à environ 5 fps, ce qui rend un rafraîchissement à 60 Hz difficile - ATR gère les déplacements verticaux et horizontaux dans un écran virtuel via les registres
CRTC_START,OFFSETetPEL, puis lorsqu’on atteint un bord, effectue un jolt pour recentrer la référence de l’écran avant de réécrire uniquement les tuiles nécessaires en VRAM - Le coût d’un jolt dépend du nombre de tuiles à redessiner ; dans l’exemple de Commander Keen 1, seules 40 tuiles sur 250 changent, soit seulement 16 % de l’écran, et les performances dépendent donc fortement d’une conception de carte riche en tuiles répétées
- Commander Keen 4 à 6 abandonnent ATR au profit d’un défilement continu exploitant le wraparound de l’ouverture VRAM de 64 Kio, où seules les bandes de bord nouvellement révélées sont dessinées ; certaines cartes Super VGA ont cependant posé des problèmes de compatibilité en faisant entrer l’affichage dans de la mémoire non initialisée
Les limites de bande passante rencontrées sur EGA
- Commander Keen fonctionnait au mieux sur les PC équipés d’une EGA (Enhanced Graphics Adapter), où la programmation graphique passait par des registres de configuration et une fenêtre mémoire de 64 Kio mappée sur la VRAM
- L’EGA stocke ses données internes dans 4 plans
C0,C1,C2,C3C0contient le bit de poids faible (LSB) de chaque valeur de pixel sur 4 bitsC3contient le bit de poids fort (MSB)- Chaque plan comprend 200 lignes de 40 octets chacune
- Cette architecture en 4 banques a été conçue pour fournir la bande passante nécessaire afin de suivre l’affichage CRT, le CRTC lisant 4 octets en parallèle
- Le mode EGA
Dhutilisé par Commander Keen offre une résolution de 320x200 en 16 couleurs- Il n’utilise pas la méthode du mode
10h, qui recompose l’encre à partir de 64 valeurs de couleur - Même en mode
Dh, il est possible de modifier les couleurs de la palette parmi les 16 couleurs de base, ce qui sert aux effets simples de fondu d’entrée/sortie dans Commander Keen
- Il n’utilise pas la méthode du mode
Comment l’Adaptive Tile Refresh évite le redessin complet de l’écran
- Le principal goulet d’étranglement résolu par ATR est la bande passante
- Écrire à chaque frame les valeurs 4 bits des 320x200 pixels, soit environ 32 Kio, impose une charge excessive au bus ISA
- Une boucle naïve qui rafraîchit l’écran complet à chaque fois plafonne à environ 5 images par seconde
- L’EGA permet aussi certaines écritures simultanées sur les 4 banques, utiles pour effacer l’écran ou dupliquer les colonnes dans Wolfenstein 3D, mais peu adaptées au problème de défilement de Commander Keen
Un défilement fluide construit avec des registres
- ATR commence par créer en VRAM un écran virtuel plus grand que la zone affichée, puis déplace cette fenêtre visible en modifiant
CRTC_START, qui détermine l’endroit où le CRTC commence sa lecture - Le défilement vertical est relativement simple
- En ajoutant 16 lignes au-dessus et au-dessous de l’écran visible, on utilise
40 x 232 = 9 280octets par plan - Pour déplacer l’écran d’une ligne vers le haut, on augmente
CRTC_STARTde 40 octets - Pour déplacer l’écran d’une ligne vers le bas, on diminue
CRTC_STARTde 40 octets
- En ajoutant 16 lignes au-dessus et au-dessous de l’écran visible, on utilise
- Le défilement horizontal utilise conjointement les registres
OFFSETetPEL- En réglant
OFFSETà 2, on ajoute 16 octets de padding entre les lignes, ce qui laisse une marge de 16 pixels à gauche et à droite de l’écran virtuel - Si l’on augmente
CRTC_STARTde 1, la structure en plans fait bouger l’écran par pas de 8 pixels, ce qui est trop grossier - Le
Horizontal Pel Panning, c’est-à-dire le registrePEL, permet de sauter jusqu’à 7 bits aprèsCRTC_START, rendant possible un défilement horizontal au pixel près
- En réglant
- En pratique, le déplacement horizontal consiste à ajuster
CRTC_STARTavec la coordonnée divisée par 8, puis à réglerPELavec le reste (% 8)
Le jolt et les mises à jour partielles par tuiles
- Quand on atteint le bord de l’écran virtuel, ATR effectue un jolt pour recentrer l’écran virtuel
- Comme un redessin complet prend environ 200 ms et fait chuter l’affichage à 5 fps, le jolt ne redessine pas tout l’écran, mais réécrit uniquement les tuiles modifiées
- Les niveaux de Commander Keen sont construits en tuiles 16x16
- L’artiste dessine les tuiles, puis le système de build attribue un identifiant unique à chacune
- Le level designer place ces identifiants de tuiles dans un éditeur 2D pour construire la carte
- Le moteur suit quels identifiants de tuiles sont présents dans l’écran virtuel
- Au moment du jolt, il compare les identifiants de tuiles de l’état actuel de l’écran virtuel avec ceux de l’état cible une fois recentré
- Les tuiles identiques sont ignorées
- Seules les tuiles différentes sont réécrites en VRAM
- L’efficacité du jolt est inversement proportionnelle au nombre de tuiles à redessiner ; les game designers devaient donc construire des tilemaps contenant beaucoup de tuiles répétées
- Dans l’exemple de Commander Keen 1, après un déplacement fluide vers la droite qui amène l’écran virtuel à sa limite, un jolt de 16 pixels vers la gauche ne modifie que 40 tuiles sur 250
- La part redessinée ne représente que 16 % de l’écran
- Au-dessus du fond est dessiné un calque de sprites
- Le moteur conserve une liste des coordonnées des tuiles salies par l’écrasement des sprites
- À chaque nouvelle frame, il parcourt cette liste de zones sales pour restaurer les tuiles de fond avant de redessiner les sprites
Double buffering et drifting dans la seconde trilogie
- Pour éviter les artefacts visuels, l’ensemble du système est dupliqué avec deux framebuffers
- Pendant que le CRTC lit l’un, on peut écrire dans l’autre ailleurs en VRAM
- Chaque buffer utilise
(320 + 32) * (200 + 32) * 4 / 8 = 40,832octets - Le double buffer complet occupe
40,832 * 2 = 81,664octets, au-delà des 64 Kio de la carte EGA IBM d’origine
- Selon VileR, seule la carte EGA IBM d’origine était équipée de 64 Kio ; la plupart des clones EGA apparus vers 1986-1987 embarquaient 256 K, et au moment de la sortie de Commander Keen, les cartes EGA de moins de 256 K étaient devenues rares
- Dans Commander Keen 1 à 3, les motifs répétitifs exigés par ATR sont très visibles à l’écran, contrairement à Commander Keen 4 à 6 où cette caractéristique est beaucoup moins marquée
- La seconde trilogie Keen exploite le comportement de wraparound qui fait revenir
CRTC_STARTau début du bloc une fois la fin du bloc de 64 Kio atteinte- L’écran peut continuer à se déplacer, et seules les rangées de tuiles de bord nouvellement visibles sont dessinées
- Le jolt disparaît, ce qui réduit le besoin de créer de grands champs répétitifs de couleur similaire
- Il ne s’agit pas tant d’une nouvelle fonctionnalité que d’une amélioration supprimant le jolt
- Les deux éléments du double buffer dérivent dans l’espace VRAM à la même vitesse, ce qui les empêche de se recouvrir
- Dans la plupart des cas, cela fonctionne très bien
- Certaines cartes Super VGA ont toutefois posé problème
- Sur des cartes à l’implémentation non standard et disposant de davantage de mémoire, l’affichage pouvait ne pas revenir au début en wraparound, mais entrer dans de la mémoire réelle non initialisée
- Plutôt que de gérer séparément chaque carte non standard, Carmack a choisi une solution plus simple : accepter un hitch à la fin de l’écran et recopier tout l’écran vers le haut
- Cette technique de drifting a peut-être empêché de stocker tuiles et sprites en VRAM afin d’utiliser des copies rapides de VRAM à VRAM, mais comme la quantité à dessiner à chaque frame restait très faible, cela n’a probablement pas eu de gros impact
1 commentaires
Avis de Hacker News
La fluidité du défilement dans Commander Keen 4 à 6 est restée sans équivalent sur PC pendant des années, même après le passage des jeux aux graphismes en 256 couleurs
Grâce au travail technique impressionnant de John Carmack et aux illustrations en palette 16 couleurs d’Adrian Carmack, id a en quelque sorte créé, pendant une partie des années 1990, les jeux de plateforme les plus beaux sur PC
Adrian Carmack n’a aucun lien de parenté avec le Carmack le plus célèbre, mais je le considère comme un maître méconnu de la palette 16 couleurs
Le rythme des progrès graphiques et de gameplay était vraiment énorme
L’évolution depuis le premier jeu : https://en.wikipedia.org/wiki/Commander_Keen_in_Invasion_of_...
L’évolution jusqu’au dernier jeu : https://en.wikipedia.org/wiki/Commander_Keen_in_Goodbye,_Gal...
J’y ai joué moi-même enfant à l’époque, et j’avais oublié à quel point tout était allé vite
Ce n’est pas pour dénigrer Commander Keen, mais les visuels et les mécaniques de jeu de PoP me semblaient sans équivalent pour l’époque
Quand j’y ai joué pour la première fois vers 7 ans, ça m’a paru magique, et comme c’est encore aujourd’hui mon jeu de plateforme préféré, je suis forcément biaisé
Bien sûr, PoP n’a absolument aucun défilement, et c’est là que Commander Keen relève de la magie noire
« La mémoire est lente, donc ne redessinons que ce qui a changé » est aujourd’hui une idée presque évidente
Cela dit, les optimisations des épisodes 4 à 6 sont intéressantes. Dans les épisodes 1 à 3, ils faisaient tout le travail en supposant que le tampon ne revenait pas au début, mais en réalité il le faisait, ce qui rendait ce travail inutile — c’est aussi un point fascinant
J’ai déjà créé un jeu à base de tuiles sous Windows 98 avec DirectX 5, et au départ j’avais implémenté une approche proche de celle décrite dans cet article
L’écran ne défilait pas, mais comme il pouvait falloir redessiner beaucoup de tuiles, la situation était un peu plus simple
J’ai fini par retirer tout ce code, parce qu’en profilant le coût du rendu plein écran sur une carte RIVA TnT, le temps pris était si faible qu’il était même impossible à mesurer
Je suis content d’avoir raté l’époque EGA dans le développement PC. À cette époque-là, je crois que je n’aurais jamais rien terminé
Optimiser avec des décalages de bits au lieu de multiplications, écrire le code critique en assembleur, puis, à mesure que les processeurs progressaient, écrire 16 ou 32 bits à la fois
J’avais peu de ressources, alors je continuais à apprendre avec des livres de la bibliothèque locale et des disquettes remplies de fichiers txt
J’étais trop jeune et trop inexpérimenté pour terminer quoi que ce soit, mais j’avais réussi un défilement vertical fluide, presque fait fonctionner le défilement horizontal, et implémenté le double buffering d’un cube 3D en rotation. Ça incluait même le tampon de profondeur, les maths et le dessin de polygones ligne par ligne
Puis DirectX est arrivé, le contact direct avec la machine a disparu, et faire tourner un cube 3D est devenu si facile que ce n’était plus amusant
Le bus passait de 8 bits à 16/32 bits, les cartes graphiques prenaient en charge les écritures différées (posted writes), ce qui faisait moins attendre le CPU, et les CPU devenaient aussi plus rapides, si bien que les systèmes rapides pouvaient écrire un écran 640x480x256 à plus de 300 images par seconde
Dans ce cas, il s’agissait peut-être d’un tampon en mémoire système mise en cache avec copie DMA, ou bien le blitter se chargeait du dessin. Mais même à l’époque de Windows 98, certaines cartes 3D bas de gamme avaient un accès CPU très lent, à peine meilleur que celui de vieilles cartes sur bus ISA
Avec la hausse énorme des résolutions d’écran, on observe aujourd’hui une sorte de retour en arrière partiel. Même si l’on peut redessiner un plein écran 4K à 60 images par seconde, on peut difficilement dire que ce soit efficace
Les jeux redessinent généralement toujours tout, mais les compositeurs de bureau font pas mal d’optimisations, par exemple en affectant dynamiquement des couches à des plans matériels pour réduire les zones à redessiner
Je travaillais à la même époque dans une autre société de jeux, et j’avais trouvé moi-même une technique de défilement similaire à la deuxième approche
Je ne pense pas que ce soit si extraordinaire. Si l’on résolvait le même problème à l’époque, on serait probablement arrivé à une conclusion semblable
J’avais aussi créé mon propre pilote audio PWM pour jouer des échantillons sonores sur le haut-parleur PC, et il semble que tout le monde faisait pareil
Le PC n’a pas reçu assez d’amour avant que nous passions tous aux consoles. Des démos comme 8088 MPH de Hornet me donnent encore des frissons
Ce n’est pas une condition indispensable pour qu’un jeu soit amusant, mais la fluidité montrée par Keen, surtout sur du matériel modeste à moins de 10 MHz, était vraiment spectaculaire pour l’époque
Il a dû exister d’innombrables grandes inventions restées inconnues pendant des millénaires
Moi aussi, j’ai « inventé » quelque chose de similaire à LinkedIn dix ans avant son arrivée, mais je n’ai pas réussi à le commercialiser. Je pense que la plupart des inventions ne deviennent jamais largement connues
C’est pour cela que beaucoup de startups démarrent à deux personnes : un expert et un commercial
Donc ce n’est pas faux. Cette invention n’a peut-être rien d’exceptionnel en soi, mais elle l’est devenue par la combinaison de la nouveauté, de l’utilité et d’une commercialisation réussie
L’excellent livre Masters of Doom explique que Keen était un jeu à la Mario, c’est-à-dire à défilement horizontal.
id avait proposé cette technologie à Nintendo comme option pour porter Mario sur PC, mais Nintendo a refusé, et c’est ainsi que Keen est né.
Ce fut un énorme bond en avant pour le jeu PC, et cela a ouvert une nouvelle ère du jeu sur PC.
Ce que je ne comprends toujours pas très bien, en revanche, c’est ce qui différenciait tellement les technologies de la NES et du PC pour que Nintendo ait pu implémenter le défilement horizontal plusieurs années avant le PC.
En mode graphique EGA, on peut dessiner arbitrairement ce qu’on veut — des lignes, des cercles, des pixels individuels, etc. — et c’était conçu pour être utilisé ainsi.
Mais le scrolling n’est pas gratuit. Il faut copier directement de la mémoire, et comme le montre l’article lié, si l’on force brutalement la chose, la limite de bande passante du bus ISA fait qu’on n’obtient qu’environ 5 images par seconde.
La NES et les autres consoles 8/16 bits n’étaient pas conçues pour dessiner n’importe quoi. Elles étaient conçues pour rendre des tuiles.
Il suffisait de définir une grille de tuiles d’arrière-plan et de fournir un offset de défilement. Les sprites fonctionnent de manière similaire, mais peuvent se déplacer indépendamment. Tout cela est fourni gratuitement à 60 images par seconde.
L’inconvénient, c’est qu’il n’est pas facile de rendre des éléments arbitraires. Par exemple, colorier un seul pixel quelque part demande des contournements assez lourds.
Ce n’est pas tant que Nintendo aurait « découvert » le problème avant IBM : IBM a conçu un système graphique généraliste adapté aux ordinateurs polyvalents et aux graphismes statiques, offrant un contrôle fin sur chaque pixel. Quand on regarde une carte EGA, c’est un dispositif assez massif, avec beaucoup de silicium.
À l’inverse, Nintendo a conçu un système graphique dédié beaucoup plus simple, optimisé pour faire glisser des tuiles.
Quand Nintendo n’a pas accepté, ils ont créé de nouveaux assets, qui sont devenus plus tard Keen.
La vidéo du portage est ici : https://youtu.be/1YWD6Y9FUuw
Pour la NES, https://www.nesdev.org/wiki/PPU semble être un bon point de départ.
Le cœur du défi n’était pas « trouver comment faire du défilement horizontal » en soi, mais adapter un moteur de jeu à défilement horizontal pour qu’il fonctionne bien malgré l’espace mémoire et les contraintes de bande passante d’un système complètement différent.
Comme les jeux étaient construits autour de sprites avec des couches, cette façon d’« accélérer » la 2D avait pas mal de sens.
Dans l’interview de John Carmack par Lex Fridman, ils passent en revue toutes les grandes innovations de chaque jeu.
C’est un épisode vraiment passionnant, que je recommande fortement si vous avez le temps. Il dure environ 5 heures.
Je recommande aussi deux de ses autres interviews.
Todd Howard : https://www.youtube.com/watch?v=H9AAnV59ddE
Guido van Rossum : https://www.youtube.com/watch?v=-DVyjdw4t9I
Je me souviens encore de l’époque où je croyais connaître presque tous les secrets de Commander Keen Goodbye Galaxy.
Des camarades de classe me demandaient de leur révéler les secrets des niveaux auxquels ils jouaient sur les ordinateurs de l’école après les cours.
Quand je vois fabiensanglard.net, je recommande immédiatement.
Si quelqu’un connaît d’autres blogs de jeux rétro avec une vraie profondeur technique, j’aimerais qu’il les partage.
https://nicole.express/ et https://sudden-desu.net/ font aussi partie de mes favoris.
J’ai compris comment le défilement vertical fonctionne quand on ajuste le point de départ du framebuffer par scanline, mais au début je ne voyais pas clairement comment le défilement horizontal pouvait être possible sans tordre fortement le framebuffer.
En y réfléchissant un peu plus, j’ai réalisé que c’était un peu comme dessiner une image sur le côté d’un cylindre. Peu importe où l’on dessine le bord gauche de l’image : en faisant tourner le cylindre et en réglant les registres CRTC_START et PEL, il existe toujours un moyen de voir l’image entière nettement.
Le passage disant qu’« une fois arrivé au bord de l’écran, la solution simple consistait à accepter un à-coup et à copier tout l’écran vers le haut » est également intéressant.
Je me souviens qu’au lancement de Keen, un message du genre « VGA compatibility mode enabled » apparaissait généralement, et je me suis toujours demandé ce que cela signifiait.
Commander Keen était vraiment un petit jeu adorable
Il faut que je trouve un moyen de le relancer
Mais comment faire au mieux ? Je n’ai pas utilisé Windows depuis environ 20 ans, depuis que je suis devenu « adulte » ; comment puis-je y jouer sous Debian ?
À l’époque, les ordinateurs coûtaient environ 10 fois plus cher que les consoles, donc c’était généralement parce que les adultes avaient des idées bien arrêtées sur ce que l’enfant devait faire
Comparé aux jeux NES et Genesis, il manque d’âme. Je l’aimais bien à l’époque, mais en y rejouant récemment dans DosBox, j’ai clairement senti qu’il ne tenait pas la comparaison
Il y a quelques années, j’ai implémenté la deuxième méthode, mais même en ne dessinant que le bord avant, c’était très lent
Cela dit, c’était écrit en C, et je n’ai jamais vraiment appris la programmation en assembleur
https://github.com/geon/kate/blob/master/src/platform/dos/eg...