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... ;)