Flashback, 1ère tentative

Mais on ne se bat pas dans l'espoir du succès ! Non, non c'est bien plus beau lorsque c’est inutile !

Cyrano, Edmond Rostand

Les premières lignes de code de Flashback version Apple IIgs ont été écrites en novembre 2020. Je me suis attaqué dans un premier temps à donner "vie" à Conrad (le héros du jeu), afin de le faire se déplacer, marcher, sauter, monter sur le 1er écran du jeu (L1S1). Et peu importe la méthode, l'essentiel était de le faire sortir de l'ombre. Flashback pour l'Apple IIgs, Conrad commence la découverte de son monde. Les commandes du jeu.

Flashback pour l'Apple IIgs, animation introduction (5 premiers plans) à 2.8Mhz

Flashback pour l'Apple IIgs, animation introduction (5 premiers plans) à 16Mhz

Flashback pour l'Apple IIgs, les mouvements possibles de Conrad.

Flashback pour l'Apple IIgs, Les écrans du jeu.

Flashback pour l'Apple IIgs, Credits.

Il m'a fallu près de quatre années pour y arriver tant la quantité d'informations à digérer était importante. Et mon isolement technique constituait un handicap majeur. Les principaux problèmes ont longtemps été invisibles pour moi et sont venus de mon manque de connaissance et d'expérience dans la conduite globale d'un projet de cette dimension et l'organisation d'un jeu. En particulier de celle de la structuration des données et tout ce qui en découle : boucle principale, gestion des évènements, impact sur la vitesse du jeu, son évolution...

En fait j'ai appris en marchant et ai découvert après plusieurs itérations et reprises à zéro du projet que tout est dans la structure des données et l'organisation générale. Tout. Y passer du temps est vital. Ce sont les véritables gardes-fous qui garantissent la lisibilité, maintenabilité d'un projet comme celui-ci. Y déroger est la certitude de travailler dans le vide et de tôt ou tard devoir tout reprendre. C'est pour cela que l'expérience est si importante. Elle fait gagner un temps considérable. Mais bon, comme le disait Morpheus à Néo dans Matrix "Il y a une différence entre connaître le chemin et arpenter le chemin.". L'équipe de Delphine Software comportait 14 personnes aguerries a ces pratiques (programmeur, graphistes, musiciens...), étant seul je me suis pardonné beaucoup erreurs.

Découverte de la zone Super Haute résolution
Faire bouger Conrad c'était tout d'abord pouvoir écrire dans la zone de mémoire vidéo SHR (Super High Resolution) située de $2000 à $9CFF en bank $E1 ou le mode SHR est ainsi représenté par un ensemble de 200 lignes de 320 pixels chacunes. L'Apple IIgs ne possède pas de sprites précodés en ROM, pas de raccourci magique pour pouvoir déplacer rapîdement à l'écran un objet graphique et cerise sur le gateau cette mémoire video graphique se situe dans une bank mémoire lente de 1Mhz (pour des raisons de compatibilité avec la gamme des anciens Apple II). Conscient de ce "problème" limitant considérablement la vitesse d'affichage des graphismes, les ingénieurs d'Apple ont posé le Shadowing qui permet au hardware de copier automatiquement lorsqu'il est activé les données de la banque 01 (rapide elle à 2.8Mhz) sur la banque E1 lente. C'est mieux que rien. Mais coder un graphisme sur les pages graphiques SHR de l'Apple IIgs est bien plus simple que de coder un jeu sur Apple II en double haute résolution ou la gestion des couleurs et déplacements des sprites est un cauchemard.

La Toolbox de l'Apple IIgs propose de nombreuses routines pour faciliter la vie des programmeurs et la bibliothèque QuickDraw présente en ROM, si elle possède des fonctions graphiques abouties n'est malheureusement pas compatible en terme de vitesse d'affichage avec les exigences d'un jeu de plateforme comme Flashback. Il n'y a pas d'autre manière que de dessiner manuellement (sous Fireworks CS6) tous les personnages mobiles du jeu, de les transformer ensuite en tables d'octets, de leur adjoindre un masque permettant de les afficher sans altérer l'image de fond et d'écrire enfin des routines d'affichages de ces octets simulant le mouvement des personnages (je détaillerais plus loin l'ensemble du processus).

A titre d'information Conrad seul peut réaliser plusieurs mouvements différents :
1. Position immobile profil droit ou gauche
2. Marche vers la droite ou la gauche
3. Course vers la droite ou la gauche
4. Roulade vers la droite ou la gauche
5. Petit saut vers la droite ou la gauche
6. Descente vers la droite ou la gauche
7. Descente maintenue vers la droite ou la gauche
8. Monter un étage vers la droite ou la gauche
9. Grande roulade vers la droite ou la gauche
10. Course et grand saut vers la droite ou la gauche
11. Course et saut d'un étage vers la droite ou la gauche
12. Se baisser vers la droite ou la gauche
13. Se raccrocher à un étage iinférieur vers la droite ou la gauche
14. Puis lacher et toucher le sol vers la droite ou la gauche

Et les actions suivantes :
15. De dos, parler, utiliser ou donner un objet
16. Accroupi, déposer ou ramasser un objet profil droit ou gauche
17. Lancer un objet, utiliser un ascenseur profil droit ou gauche

Avec un pistolet :
18. Sortir le pistolet profil droit ou gauche
19. Avancer avec le pistolet profil droit ou gauche
20. Mettre en joue et tirer profil droit ou gauche
21. S'agenouiller pistolet en main profil droit ou gauche
22. Roulade pistolet en main profil droit ou gauche
23. Chuter d'un étage et dégainer le pistolet profil droit ou gauche
24. Monter un étage et dégainer le pistolet profil droit ou gauche

Dans le mode SHR deux options de résolution sont possibles pour chaque ligne et activables via le SCB (Scan Line Control Bytes) :
1. le mode 320 ou chacun des 320 pixels d'une ligne est composé de 4 bits (totalisant 160 octets).
2. le mode 620 ou chacun des 640 pixels d'une ligne est composé de 2 bits (totalisant également 160 octets).

Ainsi la première ligne SHR, la ligne 0, commence en $E1/2000, la ligne 1 en $E1/20A0 ($2000+A0h qui est la valeur hexadécimale de 160d), la ligne 2 en $E1/0140...
La dernière ligne, la 199 (dernière vu qu'on commence à la ligne 0) commence en $E1/7C60, soit 160 colonnes * 199 lignes= 31840d/$7C60h et se termine en $E1/7C60+A0 (-1) soit$E1/9CFF.

Dernière petite chose avant de pouvoir allumer un pixel, il faut choisir la couleur du pixel et donc identifier la palette de couleur active et choisir une couleur parmi les 16 disponible. L'Apple IIgs propose 16 palettes de couleurs qui occupent 512 octets situés entre $E1/9E00 et $E1/9FFF.

Chaque palette comprend 16 entrées de 2 octets chacune qui permette de coder une couleur : 
$E1/9FE0= contenu de palette 15
$E1/9FC0= contenu de palette 14
$E1/9FA0= contenu de palette 13
$E1/9F80= contenu de palette 12
$E1/9F60= contenu de palette 11
$E1/9F40= contenu de palette 10
$E1/9F20= contenu de palette 9
$E1/9F00= contenu de palette 8
$E1/9EF0= contenu de palette 7
$E1/9EC0= contenu de palette 6
$E1/9EA0= contenu de palette 5
$E1/9E80= contenu de palette 4
$E1/9E60= contenu de palette 3
$E1/9E40= contenu de palette 2
$E1/9E20= contenu de palette 1
$E1/9E00= contenu de palette 0

Exemple, pour la palette 0, les 16 couleurs se présentent ainsi : 
adresse des couleurs valeurs
$E1/9000-01 couleur 0 00 00
$E1/9002-03 couleur 1 20 02
$E1/9004-05 couleur 2 42 03
$E1/9006-07 couleur 3 41 06
$E1/9008-09 couleur 4 62 05
$E1/900A-0B couleur 5 53 07
$E1/900C-0D couleur 6 66 04
$E1/900E-0F couleur 7 89 04
$E1/9010-11 couleur 8 B8 0B
$E1/9012-13 couleur 9 F0 0F
$E1/9014-15 couleur A,10 77 09
$E1/9016-17 couleur B,11 7C 07
$E1/9018-19 couleur C,12 9C 08
$E1/901A-1B couleur D,13 BB 06
$E1/901C-1D couleur E,14 B8 0A
$E1/901E-1F couleur F,15 FF 0F

Ces couleurs et leurs valeurs obéissent à un choix qui consiste à proposer 8 couleurs pour le fond d'écran, et 8 autres pour les personnages. Ainsi Conrad aura les couleurs : 3,5,8,A,B,C,E afin de rester dans la limite des 16 couleurs du mode 320. En thérie rien n'empêche d'avoir 16 couleurs différentes par ligne et donc 3200 couleurs. Le problème est alors un ralentissement très fort (euphémisme) des routines de gestion de l'affichage, 16 couleurs est presque un standard de fait pour les jeux en SHR.
Exemple, pour la palette 0, les 16 couleurs se présentent ainsi : 
adresse des couleurs valeurs
$E1/9000-01 couleur 0 00 00
$E1/9002-03 couleur 1 20 02
$E1/9004-05 couleur 2 42 03
$E1/9006-07 couleur 3 41 06
$E1/9008-09 couleur 4 62 05
$E1/900A-0B couleur 5 53 07
$E1/900C-0D couleur 6 66 04
$E1/900E-0F couleur 7 89 04
$E1/9010-11 couleur 8 B8 0B
$E1/9012-13 couleur 9 F0 0F
$E1/9014-15 couleur A,10 77 09
$E1/9016-17 couleur B,11 7C 07
$E1/9018-19 couleur C,12 9C 08
$E1/901A-1B couleur D,13 BB 06
$E1/901C-1D couleur E,14 B8 0A
$E1/901E-1F couleur F,15 FF 0F

Les valeurs des codes couleur, les 2 octets sont organisés comme suit:
Prenons la couleur 5 par exemple, dont la valeur est 53 07, elle correspond comme le 65856 gère les valeurs en Little Indian, à 07 53.

Les deux octets sont organisés par l'Apple IIGs sous la forme
bits 15 14 13 12  11 10 09 08  07 06 05 04  03 02 01 00 
     - réservé -     rouge         vert        bleu    

la valeur 07 53 correspond donc à 0 (champ réservé par Apple), 7 pour le rouge, 5 pour le vert et 3 pour le bleu. Pour voir la couleur, sous Fireworks CS6, il suffit de dessiner un simple rectangle, puis d'éditer la valeur de la couleur de remplissage en hexadécimal sera #775533 ou en mode RGB(119,85,51).

couleur #5 (53 07) : cheveux de Conrad

Pour afficher un point blanc daans le coin haut, gauche de l'écran SHR il faudrait donc écrire la valeur 0FFF en $E1/2000
LDA #$0FFF
STAL $E12000

Initialisation du programme
1. intégration des bibliothèques de Macro fournies dans Merlin32/Library
USE    4/Locator.Macs
USE    4/Mem.Macs
USE    4/Misc.Macs
USE    4/Resource.Macs
USE    4/Sound.Macs
USE    4/DOS.16.Macs
USE    4/Event.Macs
USE    4/QD.Macs
USE    4/Text.Macs         
USE    4/Flashback.Macs.s  Spécifique Flashback
USE    4/Tool222.Macs.s    NinjaTrackerPlus Player (fichier sons NTP)
USE    4/Int.Macs
USE    4/Util.Macs

2. démarrage des outils de la toolbox
_TLStartUp             Tool Locator
_MMStartUp             Memory Manager
_MTStartUp             Miscaellenous Tool
_NewHandle             Allocation mémoire en Direct Page pour les outils 
_QDStartUp             QuickDraw II
_EMStartUp             Event Manager

Puis c'est le chargement des écrans du jeu L1S0, L1S1, L1S2 dans des banks mémoire de 64Ko= FFFFh,65536d octets. Une bank contient ainsi 2 images de 32Ko (au format SCR).
→ la sauvegarde des paramètres de l'écran (couleur des bords),
→ l'activation mode SHR et shadowing,
→ l'affichage du menu principal et les commandes du jeu : Play, Controls, Quit,
→ Puis c'est la chargement des palettes des couleurs de Conrad (8 couleurs différentes dans le Level #1),
→ Et la copie inverse (mouvement vers la gauche fabriqué a partir de celui vers la droite) des SPRITES et MASK des mouvements de Conrad et des Robots, Gardes...

Et enfin la boucle principale du jeu...