Airwolf Reloaded
Il revient, et il n'est pas content !
Combien d'Amstradiens ont ragé devant de la difficulté
retorse et la maniabilité hasardeuse d'Airwolf sur Amstrad CPC ?
Combien de joueurs ont été pris de convulsions en découvrant, après avoir sué
eau et sang,
qu'il était en réalité impossible de dépasser le premier niveau ?
Bien trop...
Mais aujourd'hui est un nouveau jour !
Cramponnez-vous au manche de votre joystick pour prendre votre revanche, et
décollez à nouveau à bord du célèbre hélico... désormais INVULNERABLE !
Le Projet
Ce n'est un secret pour personne : la version Amstrad
CPC d'Airwolf est une odieuse purge...
Sa jouabilité catastrophique combinée aux bugs de programmation l'a érigé en
véritable désastre vidéoludique.
Il faut dire que manoeuvrer au pixel près un imposant (mais fragile) hélicoptère
dans un mouchoir de poche tout en étant soumis à la gravité et aux ennemis ne
constitue pas une formule très excitante... d'autant plus lorsqu'enfin arrivé au
bout du premier niveau, le jeu plante immanquablement !
Mais un jour de mars 2022, le programmeur Alain Le Guirec se met en tête
d'explorer le code du jeu dans le but de le rendre un peu plus jouable.
C'est ainsi que voit le jour une version hackée, dans laquelle il est possible
de tricher pour alléger un peu sa souffrance !
Baptisée "Airwolf Reloaded", cette version arrive, par
ailleurs, avec quelques petits bonus.
1) Un menu permettant de tricher :
Grâce à ce menu (qui se charge au démarrage), la gravité
peut être coupée, ce qui rend l'hélicoptère totalement stable.
Le décompte du temps peut être figé, ce qui octroie tout le temps nécessaire
pour accomplir la mission
Les collisions peuvent être supprimées, ce qui permet de jouer les
passe-muraille (et ainsi naviguer à sa convenance dans le labyrinthe)
Grâce à ce trainer, fini les parois assassines, les déplacements étriqués
dans un environnement impraticable et les ennemis irritants !
2) Des graphismes supplémentaires :
Pour l'occasion, j'aligne quelques pixels afin de donner à cette version l'écran-titre, ainsi que les écrans d'ordre de mission et de victoire que le jeu original n'a jamais eu.
Ci-dessous, les deux écrans-titres affichés de façon aléatoire par le programme :
Pour les curieux, voici le dessin préparatoire :
Ci-dessous, l'écran d'ordre de mission (avec la photo sur laquelle je me suis appuyé pour le réaliser):
Ci-dessous, l'écran de victoire :
3) Une musique supplémentaire :
Cyrille Gouret (Ayor61) fournit quant à lui une version Arkos Tracker du célèbre et entêtant thème de la série "SuperCopter" :
Mais l'histoire n'allait pas s'arrêter là...
En effet, continuant sur sa lancée, Alain décide alors de réaliser un Reverse
Engineering complet du programme afin d'en prendre le contrôle. L'idée est de
réaliser une nouvelle version revue et corrigée du jeu original !
Notre ambition est à ce moment très claire : redorer le blason du jeu d'Elite en corrigeant ses bugs, en améliorant sa jouabilité, en lui octroyant une nouvelle esthétique et même, pourquoi pas, en créant un second niveau...
Mais pour cela, le haking doit s'opérer de façon bien
plus profonde dans le programme.
Et nous n'allons pas être au bout de nos surprises (et de nos découvertes !)
Le Hacking et le Modding
Durant l'exploration du code d'Airwolf, Alain a découvert beaucoup secrets...
vraiment beaucoup...
1) Les Tiles (tuiles) :
Conformément à la norme en vigueur à l'époque, tous les graphismes
d'Airwolf sont construits à partir de tuiles (tiles).
Ces tuiles sont de petites portions de graphisme qui, judicieusement accolés les unes
aux autres, permettent de créer à l'écran des décors complets et des protagonistes
(sprites).
Voici, ci-dessous, la planche de toutes les tuiles utilisées par Airwolf, à
savoir :
188 tuiles pour les décors/ennemis/Hud, 10
tuiles pour l'explosion de l'hélicoptère et 7 tuiles pour
l'animation de notre Airwolf.
Et oui, L'INTEGRALITE des graphismes du jeu sont construits UNIQUEMENT à partir
de cette simple planche de tuiles !
Cette technique, consistant à stocker seulement quelques bouts de graphismes
plutôt qu'un écran complet, permettait d'épargner énormément de mémoire.
La contre-partie, était bien évidemment de risquer d'engendrer une pauvreté visuelle
à l'écran du fait de la redondance des tuiles...
Ainsi, comme illustré ci-dessous :
- (1) Le programme pioche les tuiles dont il a
besoin au sein de la planche
- (2) Puis il les assemble et agence
correctement pour former un
graphisme désiré (ici une fusée)
Afin de leur redonner un petit coup de jeune, je me suis
amusé à redessiné les tuiles de ce niveau :
Votre oeil perçant et votre sens de l'observation aiguisé aura certainement
remarqué que certaines tuiles se sont transformées, au passage, en cases jaunes
unies ...
N'y voyez aucune quelconque fainéantise de ma part : c'est juste que ces tuiles
précises, ne sont, en réalité, pas du tout utilisées par le jeu original !
Oui, vous avez bien compris : des graphismes présents dans le programme original ne sont
finalement pas exploités dans le jeu sorti en 1985 !
Voici d'ailleurs, ci-dessous, quelques-unes de ces tuiles inutilisées par le jeu
original : on peut notamment y
voir le sprite du scientifique délivré (car muni d'un Jet-Pack) à droite., ainsi
qu'un ennemi rose, à gauche.
Voilà un indice supplémentaire qui tend à donner encore un peu plus de crédit à
la thèse de la sortie précipitée du jeu à l'époque...
Par conséquent, je me dis que l'on pourrait peut-être remplacer ces tuiles
non utilisées par de nouvelles tuiles flambant neuves !
Je réalise ainsi des tuiles permettant de créer un décor "bucolique" (avec
l'idée en tête de, produire la matière première pour un hypothétique second
niveau) :
2) Les graphismes :
Une fois les tuiles redessinées par mes soins, nous les remplaçons dans le
programme afin de procurer un nouveau design au jeu.
Voici, ci-dessous, un comparatif Avant/Après (à gauche les graphismes originaux
et à droite les nouveaux) :
A partir de ce moment, nous nous disons qu'il serait également sympa de
faire subir une petite cure de jouvence au HUD (l'interface au sommet de
l'écran).
Il suffirait ainsi de charger la nouvelle image de ce HUD en RAM et de
l'afficher en lieu et place de l'ancien (qui, lui, est conçu sommairement à partir de tuiles).
Voici, ci-dessous, le HUD original (en haut) et son remplaçant (en bas)
:
Et puis tant qu'on y est, pourquoi ne pas aussi habiller aussi la base de l'écran afin d'obtenir un HUD vraiment complet :
Enfin, je réalise une petite image de Game Over.
Histoire
d'opérer un petit rappel, je m'appuie sur l'écran-titre.
On y voit ainsi un Supercopter en difficulté après avoir hurté une paroi.
3) Niveaux Supplémentaires :
Souvenez-vous, juste un peu plus haut, je mentionnais notre intention
d'envisager un éventuel second niveau.
Pour cela, j'avais commencé à réalisé quelques nouvelles tuiles à l'aspect
"bucoliques".
Nous pensions alors simplement profiter des tuiles inutilisées pour créer un
niveau suplémentaire.
Mais c'était sans compter sur le talent d'Alain qui après avoir réussi a
effectuer le reverse engineering complet du programme, propose alors de ne plus
se cantonner à une seule et unique planche de tuiles pour tout le jeu, mais
plutot de créer des planches de tuiles différentes pour chaque nouveau niveau.
Vous l'avez compris, cela signifie que nous allons disposer de 188 nouvelles
tuiles pour chaque nouveaux niveau !
A ce stade, et au regard des possibilités qui viennent de se libérer, l'idée est
alors de produire au moins un niveau supplémentaire complet sur le thèmes des
ruines inca.
Voici donc, ci-dessous, les tuiles que je dessine pour ce second niveau :
Ainsi qu'un petit mockup :
Et si vous vous demandez quelle méthode j'emploie pour dessiner les différents
éléments de ce niveau inca, voici un exemple du cheminement créatif :
Je pars tout d'abord d'une illustration réelle que je reproduis en adaptant
l'esthétique au Mode 0 de l'Amstrad CPC
Ensuite je réduit petit à petit le graph afin qu'il tienne dans le moins de
tuiles possible :
Beaucoup de joueurs se sont questionnés à l'époque sur la raison qui avait fait
que notre Supercopter s'était retrouvé dans une grotte... totalement démunie
d'entrée !
C'est vrai que ce n'est pas très logique...
D'autant plus que dans le générique de la série, on le voit sortir d'une
cavitée souterraine plutôt qu'y entrer.
Par conséquent, on s'est dit qu'introduire un niveau préambule dans lequel on
comprendrait comment notre hélico en est arrivé là serait le bienvenue !
Dans ce petit niveau, qui servira aussi de tutoriel permettant au joueur de
saisir les principales mécaniques du jeu, nous avons choisi d'opter pour un
espace plus libre : le désert.
Voici, ci-dessous, quelques tuiles réalisées pour ce niveau :
Ainsi qu'un petit mockup :
Enfin, comme toute aventure à une fin, je me suis dit qu'un petit écran
ponctuant la victoire serait le bienvenu.
Pour créer mon graph (à droite), je me suis basé sur une illustration existante
(à gauche) :
4) Les autres petits secrets :
La palette réduite
Durant notre voyage au coeur du code original, nous avons
également compris pourquoi la palette de couleurs était si réduite et comportait
autant de doublons.
En effet, tandis qu'elle pourrait offrir 16 couleurs différentes (Mode 0
oblige), la palette employée contient contre toute attente, 2 oranges, 2 cyans, 2 noirs et
même 3 blancs... ce qui réduit drastiquement l'éventail chromatique !
Alors pourquoi un tel choix ?
Tout simplement parce que pour le tir, le programme teste
directement l'index de la couleur afin de déterminer si on touche un objet ou
non.
Petite explication technique :
En Mode 0, les pixels sont décrits par des index dans une palette.
Un index de 16 couleurs tient sur 4 bits.
Un octet fait 8 bits.
On a donc deux pixels par octet.
Le code du tir lit un octet et le compare avec une valeur prédéfinie.
Si c'est pareil, il considère que c'est une cloison et efface le byte, soit les
deux pixels.
C'est pour cette raison que la cloison s'efface à moitié, car elle fait 4 pixels
de large.
Le problème, c'est que cela oblige toutes les tuiles à ne pas utiliser deux
pixels cyan sous peine de se faire détruire comme une cloison.
Par conséquent, les 3 blancs s'expliquent de la manière suivante : un pour le décor, un pour les murs (= disparait) et un pour le bouton (= code spécial). Les deux oranges conduisent donc à penser que les petits robots (qui sont oranges) avaient certainement été prévus, à l'origine, pour être destructibles ! Mais comme ce n'est finalement pas le cas dans le jeu final, cela expliquerait pourquoi certains passages dans le jeu sont quasi impossibles à passer à cause de ces robots qui barrent la route.
Ci-dessous, la palette employée pour le jeu original :
Ci-dessous, la nouvelle palette employée pour les nouveaux graphismes de la version Reloaded :
Le fonctionnement et les mécaniques du tir
Lors d'un tir, le programme teste si le projectyle envoyé
par l'hélico rencontre une suite de deux pixels de couleur cyan (bleu clair).
Si c'est le cas, le programme considère que le projectyle a touché un élément
destructible et il efface ces deux pixels.
C'est pour cette raison que les colonnes destrucibles sont composées de blocs de
2 pixels cyans :
Et il en est de même pour le sommet des boutons qu'il faut détruire tout au long du jeu :
Ce qui est amusant, c'est qu'aux yeux du programme,
n'importe quel élément composé de deux pixels cyans consécutifs devient
destructible.
De ce fait, il ne fait aucune distinction entre les éléments réellement destinés à
être détruits et les zones du décors qui ne devraient pas l'être.
C'est, par exemple, le cas des barrières électromagnétiques dont le champ
contient des pixels cyans consécutifs.
Ci-dessous, on peut voir qu'il est possible de détruire une partie du champs
(pixels cyans effacés sur l'image 2 suite à un tir):
Suivant cette logique simpliste, il est ainsi possible,
par exemple, de carrément détruire la partie du décor
représentant le canon électromagnétique.
Comme on le voit ci-dessous, le champ "flotte" alors dans les airs, sans avoir été affecté par la
l'élimination des canons qui le génère...
ce qui prouve que ce cas de figure n'était certainement pas prévu à l'origine.
Pour éviter cette situation, il aurait fallu ne jamais juxtaposer deux pixels
cyans dans le décor.
Les niveaux perdus
Nous pouvons également affirmer que, contrairement à ce qui était annoncé sur la notice, il n'y a pas 5, mais bien un seul et unique niveau présent sur la disquette.
Par contre, des traces
révèlent qu'un hypothétique second niveau pourrait tout de même avoir été
envisagé à l'époque...
Et la plus évidente se situe au niveau de la Tilemap.
En effet, lorsqu'on déploie la map dans son ensemble, on s'apperçoit qu'il y a
un grand espace vide inutile (à droite) qui aurait très certainement dû
accueillir (au moins) un second niveau :
Cet espace vide est assez révelateur car si un seul et
unique niveau avait réellement été prévu dès le départ, le programmeur n'aurait
certainement pas perdu autant d'octet pour rien.
C'est une des preuves qui tendent à penser que le développement n'a pas pu aller
jusqu'à son terme avant la commercialisation du jeu.
Le timer énigmatique
Le bug du Timer qui décrémente les secondes de
manière erratique durant une partie, est la conséquence de l'utilisation d'un nombre
erroné
d'unités.
Explication :
En temps normal, lorsqu'on décompte un nombre, les unités passent de 9 à 0 puis
reviennent à 9.
On utilise donc 10 symboles d'unités au total (9, 8, 7, 6, 5, 4, 3, 2, 1 et 0)
tel que ci-dessous
:
29 - 28 - 27 - 26 - 25 - 24 - 23 - 22 - 21 - 20 puis 19 - 18 - 17 - 16 - 15 - 14
- 13 - 12 - 11 - 10
Or, dans Airwolf, le décompte se fait avec 11 unités !
En effet, lorsque le compteur passe ses unités au-dessous de 9, le code
d'Airwolf ne remet pas un 0, mais une onzième unité imaginaire.
Pour gérer cela, le programme se voit alors obligé de piocher la tuile située
juste après le 9... et le résultat parait alors complètement illogique.
Ainsi, dans Airwolf, le timer affiche :
55:55 - 55:54 - 55:53 - 55:52 - 55:51 - 55:50 - 54:5# - 54:59 -
etc...
Des glitchs et des sprites
Les sprites ont un bug dans leur
toute première frame d'animation.
En effet, il faut être très attentif pour l'apercevoir, mais lorsque
l'hélicoptère fait son entrée dans un nouveau décor, tous les sprites animés qui
s'affichent ne sont pas les bons !
Ce problème ne dure que quelques dixièmes de seconde avant que l'animation ne
soit ensuite rétablie.
L'explication est très simple : le programme vient piocher, par erreur, la tuile
qui précède celle qui aurait dû être normalement sélectionnée.
Les screenshots ci-dessous illustrent bien le phénomène :
Le screenshot de gauche montre l'état de l'affichage dès les premiers instants
où l'hélicoptère fait son entrée dans le niveau.
On voit bien que les sprites ennemis ne sont pas corrects à gauche (un radar
dans le mauvais sens et un angle du HUD qui flotte dans les airs)
Le screenshot de droite montre ce même niveau après quelques instants : tout est
rétabli ! Le radar est à présent dans le bon sens et le coin du HUD a laissé sa
place à un robot.
A présent, si l'on jette un oeil à la planche de tuiles, on s'aperçoit que les
tuiles affichées sur l'écran de gauche correspondent aux tuiles se situant
physiquement juste avant celles qui auraient du être choisies par le programme.
Ce bug a d'ailleurs eu une certaine conséquence à l'époque puisque lorsque le joueur arrivait dans le niveau des missiles russes, c'est la tuile du savant à délivrer qui s'affichait subliminalement à la place des flammes ! La surprise de découvrir le savant dans le dernier niveau du jeu se voyait donc légèrement gâchée !
Big is (not) beautiful
La taille imposante de l'hélicoptère fait que lorsqu'il
heurte un mur, son animation de rotation le renvoie systématiquement dans ce
même mur...
La jauge d'énergie déscend alors irrémédiablement jusqu'à la destruction, sans
que le joueur puisse faire quelque chose pour l'éviter.
Il s'agit en fait d'un problème de design : pour éviter cette situation, il faudrait
simplement que l'animation de rotation de l'hélicoptère se joue à l'envers après
avoir heurté une paroi.
Un cachot inviolable
Le dernier bouton sensé ouvrir la prison du scientifique est régi par une
fonction qui n'est jamais appelée dans le programme.
Et cette fonction active des variables qui ne sont pas utilisées dans le code.
De toute façon, le programme ne sait gérer qu'un seul bouton par écran... or cet
écran final en contient deux !
Bref, tout est en place pour que jamais ne fonctionne ce bouton.
Vous reprendrez bien encore un peu de Sprite ?
Lorsque l'on rentre dans le détail des animations des sprites ennemis, on
s'aperçoit qu'elles n'ont pas fait l'objet d'une économie de mémoire.
En effet, ces animations sont constituées de frames superflues dont on aurait pu
facilement se passer et qui auraient ainsi pu être utilisées pour autre chose.
Comme le montre l'animation du sprite ci-dessous, le programme contient 4 frames
différentes.
Ces frames sont jouées en respectant simplement la séquence 1-2-3-4, puis
l'animation boucle pour repartir du début et ainsi de suite.
Grace à ce cycle, nous obtenons ainsi à l'écran un cylindre bleu dont le
l'anneau blanc effectue un mouvement de haut en bas.
Or, on s'aperçoit que les frames 2 et 4 sont identiques : il aurait alors
simplement fallu gérer un va-et-vient entre les frame 1-2-3 pour éviter cette
situation.
Pour économiser une frame, il aurait ainsi plutôt falku opter pour une animation
de type 1-2-3 -2- 1-2-3 -2- 1-2-3 -2- 1-2-3 -2- ...etc...
(Ceci sera corrigé dans notre version Reloaded)
Code résiduel
Lorsque l'on se promène dans le petit listing BASIC du
loader du jeu, on peut voir une section de programme commençant sa numérotation
à 10000.
Cette partie du programme est totalement indépendante du fonctionnement du jeu
et pour l'exécuter il faut volontairement lancer l'exécution à 10000 (par un
RUN 10000)
Ce bout de programme semblait permettre au programmeur de sauvegarder, à
volonté, les modifications qu'il apportait au jeu au fil du développement.
Ce bout de code n'aurait jamais dû se retrouver dans la version commerciale du
jeu... encore un indice qui appuie la thèse d'une sortie précipitée, sans que le
programmeur ait eu le temps de nettoyer le programme.
Cordes vocales muettes
La musique a bien trois canaux, mais n'en utilise que
deux.
En effet, comme le montre le bout de code ci-dessous, les lignes
d'incrémentation de HL (l'adresse qui pointe sur la musique) "INC HL" ignorent
la 3eme piste.
Ainsi, le tracker veut lire les 3 pistes, mais finalement il ignore
volontairement la 3eme.
La 3eme piste audio est
réservée aux bruitages... mais il n'y a qu'un seul et même bruitage pour tout le
jeu !
Ainsi, que ce soit pour une collision ou un tir, c'est exactement le même bruit
qui est généré.
Il est codé pour ne durer que le temps d'une frame d'animation, soit 16 ms : il
boucle ensuite sur lui-même si la frame suivante le requiert.
La seule fantasie est réservée au bruit de l'explosion de l'hélicoptère qui
bénificie d'une variation aléatoire de la période de ce même son.
Bugs, vous avez dit bugs ?
Le bug qui fige l'écran au moment de délivrer le scientifique captif est généré par une boucle infinie, volontairement placée afin de couper l'effet du dernier interrupteur.
Une partie du code semble provenir d'un autre
logiciel.
Lorsque le programme se lance, il charge un très grand
nombre de données dont il ne se sert ensuite jamais.
Un petit "ménage" dans le code pourrait l'alléger d'environ 20%
La gravité est appliquée sur l'hélicoptère en faisant croire au code que le
joystick bas a été appuyé.
Le code s'appuie sur deux compteurs 8 bits : le premier temporise l'application
du joystick bas pour qu'il se fasse une frame sur "n", et le second définit ce
"n".
Par conséquent, la gravité accélère jusqu'à atteindre la vitesse de descente
d'une frame sur deux.
Cela permet au joueur de toujours pouvoir accélérer la descente avec le
joystick.
Lorsque l'on appuie sur la barre d'espace durant une
partie, cela a pour effet de figer l'écran et de bloquer le jeu.
Ce bug est dû à une étrange fonction qui est affectée à la touche espace dans le
code.
En effet, cette fonction attend que joystick ne reçoive plus de commande puis
fait un Return alors que l'on se trouve dans une boucle qui a écrasé le pointeur
de pile dans un but d'optimisation.
Par conséquent, le pointeur de code part aux fraises et exécute les datas
graphiques : c'est le plantage !
Pour éliminer ce bug, il suffit de supprimer la barre espace du code.
Mais pourquoi avoir laissé un tel bug si facilement corrigible dans le jeu final
?
Peut-être que l'appui sur la barre d'espace était destiné à opérer une pause
dans le jeu.
Mais, visiblement, cette fonction n'a pas été testée ou sa suppression a tout
simplement été omise...
Élémentaire, mon cher Watson !
A la lumière de tous ces éléments, il apparait très
clairement que la thèse de la sortie précipitée d'Airwolf sur Amstrad CPC
devient un fait prouvé.
La fin du premier niveau a indiscutablement été volontairement "sabotée" pour
qu'aucun joueur ne puisse aller au-delà.
Tout converge : l'absence de tilemap pour un second niveau, l'absence de code
loading, l'absence de code de collision pour le scientifique, la présence de la
boucle infinie en guise de bug, le code hyper specifique à la map pour les
boutons, l'absence de table d'animation pour les ennemis, les raccourcis de
programmation minimalistes, le manque d'optimisation générale, les bugs non
corrigés (timer, première apparence des tuiles ennemies...).
Plus de secrets prochainement, soyez patients.... ;)
5) Le DSK de la version "Reloaded" :
Vous trouverez en téléchargement libre dans ce
paragraphe, toutes les versions (au format DSK) de notre projet "Airwolf
Reloaded".
Etant donné que celui-ci est toujours en cours de développement, nous ne sommes
pas encore en mesure de proposer sa version finale.
- Version 1.0 (avec Trainer, musique d'intro, 2 écrans titres et ordre de mission) :
Version 1.1 (avec Trainer, musique d'intro, 2 écrans titres, ordre de mission et nouveaux graphismes) :
- Version 2.0 (avec Trainer, musique d'intro, 2 écrans titres, ordre de mission, nouveaux design et niveaux supplémentaires) : prochainement...
Notez que le jeu se lance par un RUN"AIRWOLF" et que le joystick y est obligatoire.
6) Le mot de la fin
Maintes fois mis à l'index, boudé, raillé... Airwolf sur
Amstrad CPC n'a clairement pas été épargné par la critique durant ces 35
dernières années...
Pourtant, lorsqu'on replonge dans les entrailles de son code, on se rend
rapidement compte que son auteur, Richard J. Chappells, a malgré tout fait
preuve de beaucoup d'ingéniosité dans sa conception. On oublie trop souvent le
nombre de contraintes auxquelles il a du faire face et toutes les astuces qu'il
a dû trouver pour y faire face.
La sortie du jeu dans l'urgence a
certainement été motivée par des raisons précises... et il y a de fortes chances
pour que l'auteur du jeu ait dû la subir, à contre-coeur et avec résignation...
Alors on peut clairement dire que si c'est effectivement le cas, il a su trouver
maintes parades pour sortir un jeu "commercialisable" malgré les délais
drastiques imposés.
On ne comprend vraiment l'autre que lorsqu'on se met à sa place ("Try walking in
my shoes" comme dirait Depeche Mode).
Notre projet nous a permis de nous mettre à la place de Richard l'espace d'un
instant et cette expérience nous a appris à faire désormais preuve d'indulgence
envers Airwolf... ;)