26 Juillet 2019
J'ai fait une démo "Axelay" sur NES (voir ce thread twitter) mais je n'avais pas encore pris le temps d'expliquer plus en détails comment ça fonctionne. Je vais donc profiter de ce billet plus global sur la question du scrolling vertical pour en parler et évoquer aussi ce que j'ai pu découvrir sur les pratiques et difficultés de l'époque au travers de quelques jeux. Expliquer aussi pourquoi cette démo n’était pas faisable a l'époque ou n'est pas faisable sur Master System.
Cette démo Axelay s'inscrit dans la continuité de mes précédentes expérimentations sur le scrolling (scrolling au pixel sur Colecovision ou scrolling parallaxe sur Master System. Cliquez pour voir les vidéos) mais avait aussi pour fonction d'expliquer que l'effet rouleau de Axelay sur SNES n’était pas du mode 7 comme on l'entend très souvent mais simplement un effet parmi d'autre que permet le scrolling hardware vertical et donc accessible à un certain nombre de machine de l'époque.
Mais avant d'expliquer comment fonctionne cet effet rouleau il faut revenir sur la notion de scrolling hardware. Pour résumer simplement on peut dire que le scrolling hardware c'est la fonction hardware qui permet d'appliquer automatiquement un décalage sur l'image affiché juste en modifiant 2 valeurs X et Y contenu dans des registres internes au chip graphique. Si je met la valeur 10 dans le registre X ça décale horizontalement l'image de 10 pixels. Si je met 100 dans Y ça décale verticalement de 100 pixels. C'est a dire qu'au lieu de devoir déplacer un par un en VRAM chaque pixel qui compose l'image (des dizaines de milliers de pixels) pour la déplacer, on obtient le même résultat juste en modifiant une valeur. C'est donc très efficace et économique en ressource. C'est pas le seul critère pour pouvoir vraiment parler de scrolling hardware mais c'est le principal. La NES était la première console à nous apporter dans le salon un support complet du scrolling hardware.
Mais pour comprendre tout le potentiel du scrolling hardware il faut combiner ça avec la notion de "Raster Effect". Le principe du raster effect est simple. Ca consiste a modifier les paramètres hardwares de l'affichage pendant le balayage de l'image sur l'écran. C'est quelque chose qu'on n'est pas censé faire en situation normal mais qui permet de produire toute sorte d'effet sur l'image. On peut par exemple modifier la palette pendant le balayage mais le raster effect le plus commun c'est sans doute l'effet de parallaxe bien connu de tous et qui consiste donc à modifier le registre X du scrolling hardware pendant le balayage de l'écran et ainsi crée une rupture dans le scrolling horizontal, un décalage, et avoir ainsi des bandes de scrolling à différentes vitesses. L'effet de parallaxe est une forme de "tearing" mais contrôlé plutôt que subit. Les effets de parallaxe sont très présents même dans les jeux des consoles 8bit. Ca demande juste un bon timing pour fixer la rupture a l'endroit que l'on souhaite. Voici quelques exemples 8bit parmi beaucoup d'autres.
Mais ici ce sont donc des raster effects sur le scrolling horizontal. Alors a cet instant vous vous demandez sans doute quid des raster effects sur le scrolling vertical? Et vous vous dites peut être que ça permet tout simplement de faire des bandes de parallaxe verticale?
Pas du tout car le balayage de l'écran CRT est vertical, il se fait de haut un bas, donc l'effet des raster effects sur le scrolling n'est pas un effet symétrique pour le scrolling horizontal et vertical. Ce sont des problématiques différentes. C'est beaucoup plus compliqué de faire des bandes de parallaxe verticale à cause de cela. Au point que ça nécessite des fonctions hardwares dédiées comme c'est le cas sur Megadrive ou SNES.
Donc il n'en est pas question pour les consoles 8bit (heureusement il existe d'autres moyens de simuler des parallaxes verticales) mais ça ne veut pas dire pour autant qu'il n'y a pas d'autres utilités possibles à un raster effect sur le scrolling vertical.
Les raster effect sur le scrolling vertical s'accompagnent d'une autre difficulté car modifier le registre Y du scrolling hardware pendant le balayage de l'écran n'a pas forcément d'effet selon la machine. Le chip graphique n'a besoin en théorie de lire ce registre qu'une seule fois en début de balayage, donc le modifier pendant le balayage peut n'avoir aucun effet immédiat, et donc pas de raster effect possible, et c'est le cas sur Master System. On parle alors de "Vlock". Le scrolling vertical sur Master System est donc verrouillé pendant le balayage vertical. On ne peut pas agir dessus et faire des raster effect avec. C'est ce qui implique que ma démo Axelay et tous les autres raster effect sur le scrolling vertical que je vais évoquer à partir de maintenant ne sont pas faisables sur Master System. Ce qui était aussi l'une des motivations de cette démo: Exploiter un point fort de la NES comme pour mes autres démo.
Je vais donc maintenant partager quelques exemples d'usages de raster effect sur le scrolling vertical dans des jeux NES. Beaucoup de ces effets nécessitent un raster effect sur NES parce qu'on est sur 8bit et qu'il n'y a qu'un seul layer, un seul plan, pour le background. Ca serait moins utile sur consoles 16bit.
Le premier usage qui est le plus discret, mais le plus fréquent, est tout simplement de combiner sur le même écran un gros HUD fixe tout en autorisant un scrolling vertical dans le jeu. Pour ça il faut une rupture dans le scrolling vertical pour dissocier la partie fixe du background (le HUD) du reste du jeu comme ici dans Super Mario Bros 3.
En l'absence de raster effect sur le scrolling vertical on serait alors condamné à faire un HUD avec des sprites ou bien à bidouiller comme dans Shinobi Master System par exemple qui s'inflige un scrolling vertical en software en déplaçant les tuiles une à une au CPU mais pour un résultat évidemment très saccadé.
Ca peut expliquer aussi le choix par exemple de retirer le scrolling multidirectionnel dans le portage Master System de Fantasy Zone ou Alien Syndrome qui est préservée dans les versions NES.
Un autre usage très classique de raster effect sur le scrolling vertical consiste à utiliser le background comme un gros sprite pour les boss. Si on veut déplacer verticalement ce gros "sprite" (et pas seulement horizontalement) tout en affichant un environnement qui utilise donc le même layer que le boss (puisque sur console 8bit il n'y a qu'un seul layer background) alors ça demande une rupture dans le scrolling vertical. Super C en fait un usage massif. On retrouve l'usage de ce raster effect pour 5 de ses boss (sur 8). Un des plus bel exemple c'est le boss final de Ninja Gaiden 3 qui est énorme avec une belle dynamique en plus d'afficher le sol + un HUD dans la partie supérieur tout ça avec le même layer background. Ça peut même être utilisé parfois sur le joueur lui-même (Punch Out).
Si on ne peut pas faire de raster effect sur le scrolling vertical mais qu'on veut quand même un gros boss qui bouge verticalement alors on est obligé de faire comme sur Master System avec les boss de Fantasy Zone, Alien Syndrome ou Time Soldiers. C'est à dire se contenter d'un aplat de couleur sans environnement (on voit même le HUD disparaître pendant les phases de boss dans Fantasy Zone).
Un autre usage vraiment spécifique a ce type de raster effect sur le scrolling vertical et qu'on retrouve assez souvent sur NES c'est l'effet de presse. Il s'agit cette fois d'un effet au service du level design pour varier les situations de jeu. Ca consiste encore une fois a dissocier l’écran en plusieurs parties. Une partie fixe et une partie qui scroll verticalement avec donc une rupture entre les 2. Voici quelques exemples avec encore Super C mais aussi Megaman 5, Power blade 2, Batman return of the Joker ou encore Super Mario Bros 3.
Dans le même esprit des raster effects au service du level design il y a l'effet ascenseur tout aussi rependu dans les jeux NES que l'effet presse. Je vous met qu'un seul exemple avec Batman Return of the Joker car j'y reviendrais plus loin avec pleins d'autres exemples pour soulever une question et un mystère que j'ai pu résoudre grâce a mon expérience sur la démo Axelay.
Dans cette continuité toujours au service du level design on trouve aussi le raster effect sur le scrolling vertical qui produit un effet d'inondation tel que celui qu'on trouve dans Castlevania 3 ou dans Power Blade 2. C'est un usage plus rare.
Ou cet effet intermédiaire entre l'effet ascenseur et l'effet inondation dans Ninja Gaiden 3.
Une autre fonction incontournable du raster effect sur le scrolling vertical est de pouvoir produire du relief sur la route des jeux de course, dans Rade Racer par exemple. Un relief qui est ici plein de nuance et à 60fps la ou dans un Outrun Master System en l'absence de cette possibilité ça nécessitera de précalculer ces changements de relief qui sont alors très saccadés.
Quelques autres usages de raster effect sur le scrolling vertical: L'écran titre avec le rideau qui se lève dans Super Mario Bros 3. Le passage ingénieux des colonnes destructibles dans Megaman 5. L'effet de vague dans le proto de Sunman. Le découpage laser ou la presse dans Zen Intergalactic Ninja. Le pont dans Super Spy Hunter (notez pour ces 2 derniers gif la bande noire sous le pressoir et sous le pont, j'y reviendrais plus loin...).
Vous avez maintenant une idée plus exhaustive de ce que permet la manipulation du scrolling vertical au raster. Ça ne fait pas des bandes de parallaxe mais c'est quand même bien utile surtout sur 8bit ou l'on a qu'un seul layer de background.
On va donc pouvoir maintenant entrer un peu plus dans le dure en se posant la question de ce qu'il serait possible de faire si on poussait au maximum le concept de raster effect sur le scrolling vertical.
Jusqu’à maintenant les exemples que j'ai cité consistaient à modifier seulement une à deux fois le scrolling vertical pendant la phase de balayage de l'image sur l'écran. Mais si maintenant on pouvait modifier le scrolling vertical à chaque ligne tracé sur l'écran qu'est ce qu'on pourrait faire?
Imaginons le canon à électron sur le point de tracer une ligne du background sur l'écran. Si je modifie le registre Y du scrolling vertical avant qu'il ne commence à tracer la prochaine ligne et que je décale l'image d'une ligne vers le bas, je vais pouvoir obliger l'écran à retracer une seconde fois la ligne qu'il vient de tracer. J'ai en quelque sorte doublé l'épaisseur de cette ligne du background. Et si j'avais décalé dans l'autre sens j'aurais obligé l'écran à sauter une ligne du background qui ne serait donc pas apparu à l'écran.
Cela signifie plus simplement qu'en poussant au maximum ce raster effect on peut avoir l'équivalent d'une fonction de scaling vertical sur le background et cela sur console 8 bit. Je peux étirer verticalement le background (en doublant, triplant etc... l'affichage des lignes) ou le compresser (en sautant des lignes) à ma guise. Bien sur comme c'est limité à la dimension verticale et qu'il n'est pas possible d'en faire autant sur l'horizontal (toujours à cause du sens du balayage de l'écran) ça rend cette possibilité de scaling du background peu utile mais ça permet tout de même de pouvoir par exemple faire cet effet dans Batman et Robin sur Megadrive. Le rideau qui se lève est une forme de scaling, de compression verticale, du background.
Mais vous vous demandez peut être pourquoi je ne vous montre pas plutôt un exemple sur NES ou pourquoi par exemple l'écran titre de Super Mario Bros 3 que j'ai montré plus haut et qui reproduit la même scène de levé de rideau n'utilise pas cet effet avancé?
Et bien parce qu'à l'époque ou la NES était en pleine vie les développeurs n'avaient pas trouvé comment maîtriser complètement les raster effects sur le scrolling vertical. Et vous me voyez sans doute venir mais cette possibilité de scaling vertical sur le background c'est ce dont on a besoin pour faire l'effet rouleau de Axelay qui consiste justement à compresser le background à certains endroits et l'étirer à d'autres (de façon non-linéaire). C'est donc pour cette même raison qu'on a jamais vu cet effet à l’époque sur NES alors qu'il est bien faisable.
En réalité modifier le scrolling vertical pendant le balayage de l'image ce n'est pas simple du tout sur NES, c'est même assez tordu car finalement pas tellement plus prévu que sur Master System. Mais en passant par des moyens indirects, en exploitant des sortes de failles, on peut y arriver.
Quand les émulateurs sont apparus et qu'il a fallu émuler de plus en plus précisément une machine comme la NES cela a demandé d'accumuler un maximum de connaissance, que ce soit en épluchant les docs de l'époque ou de façon empirique, par du reverse engineering, voir même par la micrographie qui a consisté à prendre en photo le moindre transistor qui compose les processeurs de la NES, de les vectoriser et de faire des simulations "transistor level". Toutes ces années d'accumulation d'information font qu'aujourd'hui on a une connaissance et une documentation très poussée de la NES et notamment du fonctionnement interne des processeurs qui n'était pas connu des développeurs de l'époque. C'est à partir de ces connaissances plus pointues qu'on peut aujourd'hui contrôler le scrolling vertical de la NES comme on le souhaite et obtenir des effets tels que sur cette démo "Axelay".
Mais ce constat reste quand même inattendu. Quand j'ai commencé ma démo Axelay il était acquis pour moi que les raster effects sur le scrolling vertical étaient parfaitement maîtrisés à l'époque comme le reste et pour cause, j'avais déjà en tête tout ces exemples que je vous ai présenté. Mais une fois la démo terminé j'ai voulu faire quelque chose que je fais souvent, c'est a dire tenter de reconstruire la chronologie de ce type d'effet en analysant un maximum de jeux du catalogue NES, à quelle époque et par quel jeu c'est apparu et comment cela a muté, et c'est la que les surprises ont commencées.
J'ai d'abord dû constater que les raster effects sur le scrolling vertical sont apparus quasiment dès les tout premiers jeux de la Famicom malgré qu'ils soient relativement complexes à faire. Le premier à en faire usage étant Devil World en 1984. Le tout premier jeu de Miyamoto sur Famicom, et aussi le deuxième seulement à proposer un scrolling sur la machine. C'était une surprise. Je ne pensais pas remonter si loin dans mes recherches. Mais en même temps ça confortait plutôt un à priori que j'avais et qui s'était déjà confirmé plusieurs fois. Celui que tous les tricks ,même bien tordu, étaient déjà utilisés très tôt dans la vie de la NES. Il faut imaginer à l'époque des centaines ou milliers de gens qui programment sur NES et qui passent chacun des milliers d'heures, jours et nuits, à expérimenter du code sur la NES. Même si tout ça se fait de façon très empirique c'est difficile de laisser passer quelque chose au travers des mailles d'un filet comme ça et tout devrait avoir déjà été découvert à l'époque. Et pourtant mon second constat va contredire cela et ça sera ma plus grosse surprise.
Le second constat que j'ai rapidement fait c'est que la méthode de raster effect utilisé sur Devil World est une méthode incomplète. Elle ne permet pas de contrôler complètement le scrolling vertical pendant le balayage. Jusque la rien de très surprenant, Devil World c'est 1984, mais de fils en aiguilles j'ai surtout constaté que c'est bien cette même méthode incomplète qui a été utilisé du début à la fin de la vie de la NES, de Devil World à Kirby, et ça c'est beaucoup plus surprenant et va à l'encontre de ce que j’imaginais. Pendant ces 10 années, personnes n'a donc trouvé la bonne méthode qui est pourtant très proche de celle qu'ils utilisaient mais qui pourrait leur sembler irrationnelle ou absurde si on n'a pas les informations sur le fonctionnement interne du chip graphique.
Cette méthode d'époque était incomplète car elle ne permettait pas un contrôle total du scrolling vertical. Pour résumer simplement, le registre Y du scrolling vertical est en quelque sorte un registre 9 bit qui peut donc prendre 512 valeurs possibles ce qui permet de décaler l'image d'une amplitude de 0 à 511 pixels (en réalité de 0 à 479 qui est la taille vertical de 2 écrans mais c'est pas important). Mais on a pas d'accès direct à ce registre. La méthode de modification du scrolling vertical au raster tel que pratiqué à l'époque ne permettait pas d'agir sur l'un des 9 bit de ce registre. Plus exactement le 3ème bit de ce registre était bloqué sur 0 et semblait inaccessible pendant le balayage écran. C'est pour ça qu'on peut dire que cette méthode était incomplète (8 bit sur 9). On ne pouvait pas contrôler totalement le scrolling vertical à cause de ce 3ème bit incorruptible qui rendait inaccessible certaines valeurs. Et c'est en me replongeant dans tous les exemples d'époques que je vous ai montré en gif que j'ai réalisé effectivement que cette lacune était bien présente mais qu'ils la cachaient ou la contournaient ingénieusement de différente façon ce qui explique que je n'avais jamais réalisé qu'elle était incomplète à l’époque.
Mieux que ça. Ça m'a même permis de résoudre certain mystères qui m'intriguaient depuis longtemps. Par exemple dans Devil World le scrolling horizontal est au pixel mais le scrolling vertical est saccadé, il se fait tuile par tuile. Je le comprend maintenant très bien. Ils ont eu besoin de faire un raster effect sur le scrolling vertical pour dissocier les parties supérieur et inférieur de l’écran, qui sont fixes, de la partie centrale qui scroll, mais ils l'ont fait avec la méthode incomplète d'où ce scrolling saccadé pour contourner le blocage du 3ème bit.
Mais avec un peu d'astuce les gars de l'époque arrivaient à contourner partiellement cette contrainte de façon astucieuse. Et c'est le cas notamment pour l'effet ascenseur. Je vous ai dit que je reviendrais sur ce cas et c'est le moment. Effectivement l'effet ascenseur est assez récurent dans les jeux NES et il y a un truc étrange que j'avais observé. A chaque fois il y avait une bande noire sous la plateforme de l’ascenseur.
J'ai longtemps pensé que c’était juste pour faire un effet d'ombrage mais je trouvais ça bizarre comme choix. Et surtout la récurrence de cette bande noire dans des jeux différents était très louche. Maintenant je sais pourquoi. Cette bande noire sert à cacher un trick utilisé pour contourner justement les lacunes de la méthode incomplète de l'époque.
Prolonger le scrolling sous la plateforme était problématique pour l'époque à cause du blocage du bit 3. Le mieux qu'ils auraient pu obtenir c'est un scrolling saccadé tuile par tuile comme dans Devil World. J'ai fait un hack juste pour illustrer ce que cela aurait donné:
Et donc pour éviter ce scrolling grossier le trick de l'époque consiste à retarder le raster effect et donc l’affichage du background sous la plateforme. Un retard qui va varier entre 0 et 7 lignes selon la frame. Et c’est ce retard d’affichage qui permet de compenser les saccades en décalant progressivement le background sous la plateforme pour simuler un scrolling fluide malgré que celui ci se fasse bien tuile par tuile. Voila ce que ça donne une fois ajouté ce retard volontaire et contrôlé du raster effect:
Ensuite il ne reste plus qu'à cacher le trick avec une grosse bande noire (ce n'est pas si facile non plus, ils font ça avec du bank switching) et ça donne le résultat final de l'époque qui est plutôt correct. L'illusion fonctionne:
Mais maintenant que j'ai une bonne maîtrise du scrolling NES j'en ai alors profité pour pousser un peu plus loin mon hack de super C et corriger l'effet pour obtenir une version propre, sans bande noire, tel qu'on aurait pu l'avoir à l'époque s'ils avaient eu les connaissances qu'on a aujourd'hui ( je me suis quand même emmerdé plusieurs heures juste pour faire ce gif! ):
Cette astuce, utilisée pour compenser les lacunes de l'époque, est un palliatif intéressant dans certain cas mais pour l'effet rouleau de Axelay (ou l'effet rideau de Batman et Robin Megadrive) il n'y a pas de palliatif possible. Il n'y a pas d'autre choix que de maîtriser complètement le scrolling vertical comme on sait maintenant le faire.
Dans le cas de ma démo Axelay cela consiste à modifier le scrolling vertical avant le balayage de chaque ligne avec donc le bon timing et une précision au pixel. Ça veut dire modifier le scrolling vertical 210 fois par frame ou 12 600 fois par seconde. Ça demande donc une certaine quantité de ressources CPU d'autant que la procédure pour manipuler ce registre Y (qui n'existe pas vraiment sous cette forme) comme on le souhaite, est un peu complexe. Il faut une bonne grosse moitié des ressources CPU pour être exacte. C'est aussi ce qui différencie l'usage d'un effet comme cela sur NES et le même sur SNES qui profite d'une fonction hardware (HDMA) dédié aux raster effects qui permet au chip graphique de faire cela de façon autonome sans solliciter le CPU moyennant l'usage d'une table dédié à cette fonction ( qui elle pompe quand même un peu de ressource CPU ).
Si vous voulez avoir une maîtrise total du scrolling NES suffit de lire en boucle cette page du wiki Nesdev.com des dizaines de fois pour s’imprégner de la moindre subtilité et comprendre vraiment comment les choses se passent en interne. C'est vraiment le privilège que l'on a aujourd'hui. Le scrolling de la NES n'aura alors plus aucun secret pour vous et l'impossible sera alors possible :)