Un programme, deux machines

Lore of the Ember vise le STe, une machine qui sait faire glisser son image toute seule, sans effort. C'est ce confort qui porte le moteur depuis le début.

Sauf que le parc réel, ce n'est pas que du STe. Beaucoup de gens, dont je fais d'ailleurs parti ont la machine d'origine, le STf, qui ne possède pas cette aide matérielle. Et un jeu Atari ST qui refuse de démarrer sur un STf, pour une partie du public, c'est un jeu qui n'existe pas.

J'avais deux options : deux versions séparées, ou un seul programme qui reconnaît la machine au démarrage et choisit son mode d'affichage tout seul. J'ai pris la seconde. Sur STe, le scroll matériel d'origine, intact. Sur STf, un scroll que j'écris pour l'occasion. Le reste du jeu, la corruption qui se propage, les commandes, les ennemis, le boss, ne sait même pas sur quelle machine il tourne.

Ce post raconte ce second mode. Et surtout les semaines où j'ai cru que le problème était le scroll, alors que la vérité était ailleurs ...

Le STf ne sait pas scroller

Sur STf, pour faire scroller l'image, il faut tout faire à la main. Décaler le décor de quelques pixels, c'est recopier toute la zone de jeu à chaque image, et c'est lent. Si on shifte naïvement les pixels à chaque image, on tombe à moins de dix images par seconde. Injouable.

J'avais documenté ce plafond dès le départ, en regardant tourner de vrais jeux livrés sur STf. La conséquence pratique, c'est que le STf affiche deux fois moins souvent que le STe. Pour que le jeu ne tourne pas au ralenti sur STf, j'ai donc rendu toute la logique indépendante de la cadence d'affichage : la vitesse du monde reste la même, que l'écran rafraîchisse vite ou lentement. Sans ça, le STf jouerait au ralenti.

Restait à rendre le scroll horizontal abordable. La solution : le cache.

Préparer plutôt que recalculer

L'idée est la même vieille astuce que pour les sprites : ne presque rien calculer en direct. Plutôt que de retravailler le décor à chaque image, je prépare à l'avance les versions décalées des colonnes visibles, et l'affichage n'a plus qu'à recopier la bonne. Une recopie coûte bien moins cher qu'un recalcul. Quand la caméra avance, seules les colonnes qui entrent à l'écran sont préparées, le reste est déjà prêt.

Ça coûte un peu de mémoire, et la mémoire était déjà tendue. J'ai donc logé ce cache dans un espace qui dormait sur STf : sur STe, le décor du tableau de bord est préparé en plusieurs copies pour suivre le scroll matériel, mais sur STf ce scroll n'existe pas, alors la place reste libre. Elle tombait pile.

Sur le papier, c'était fini. Sur l'écran, ça ondulait.

Les vagues, premier coupable

Le décor ondulait quand le héros bougeait, surtout en haut de la zone de jeu. Une vague subtile, quelques pixels, mais bien là, et insupportable une fois qu'on l'a vue.

J'ai passé un temps déraisonnable à accuser mon cache. J'ai tout désactivé un par un, méthode bête et lente, un essai à chaque hypothèse. À chaque fois, les vagues restaient. Le vrai coupable était ailleurs : une astuce d'affichage que j'avais reprise du STe et qui ne passe tout simplement pas sur le STf. Elle perturbait l'image en plein milieu de son tracé, et ça ressemblait exactement à des vagues.

La leçon était nette : ce qui marche en matériel sur STe casse l'image sur STf. Je l'ai donc retirée sur STf. Le scroll, lui, ne vaguait plus pour cette raison.

Sauf que les vagues étaient toujours là.

Les vagues, second coupable

Une fois la première piste écartée, j'ai recroisé tous mes essais. Le décor de Lore of the Ember est vivant : l'eau s'anime, la corruption se propage et change le sol en permanence. Or mon cache, qui prépare les colonnes à l'avance, figeait ce décor au moment où il l'avait préparé. Pendant que le monde continuait de bouger, le cache montrait une version périmée. En scrollant, on pouvait voir ce décalage dans le temps comme une vague.

La correction s'appuie sur quelque chose que le moteur sait déjà faire : repérer les cases du décor qui changent et les redessiner. Il suffisait de rafraîchir aussi le cache pour ces mêmes cases, juste après. Le cache reste en phase avec le monde.

Restait un dernier piège. Quand la peste se propage, elle change d'un coup beaucoup de cases. Tout rafraîchir dans la même image, c'est un à-coup. J'étale donc ce travail sur plusieurs images et je ralentis un peu le pouls de la corruption sur STf pour que ça suive. Le cache met une seconde de plus à se mettre à jour après un gros changement, ce qui ne se voit pas en jeu, et la fluidité ne plonge jamais.

Le décor de la carrière qui défile sur les deux machines : le scroll matériel du STe d'un côté, le scroll logiciel du STf de l'autre, à la même fluidité.

Les freezes qui n'étaient pas où je croyais

Le jeu était fluide et stable. Puis deux gels d'une seconde sont apparus : un en allant à droite pour la première fois, un en tirant sur la peste. Écran noir, plus rien.

J'ai d'abord soupçonné mon cache, puis les dialogues. Faux dans les deux cas. En enquêtant proprement, j'ai vu que l'écran restait figé en plein fondu au noir. Et les fondus, ce sont les transitions entre les salles.

Le vrai coupable était une mauvaise hypothèse de départ : plusieurs séquences du moteur (fondus, transitions) avaient été écrites en supposant qu'afficher une image ne coûtait rien, ce qui est vrai sur STe mais faux sur STf. Sur STf, chaque petite étape du fondu refaisait tout le travail d'affichage, et un fondu de trois secondes en résultait. Comme le niveau est conçu pour enchaîner les salles sans couture, franchir une frontière donnait l'impression de rester au même endroit, avec un long noir au milieu.

La correction est simple : pendant un fondu, la scène est figée, il n'y a aucune raison de tout réafficher à chaque étape. Trois secondes sont devenues une fraction de seconde, et les deux gels ont disparu d'un coup.

Le bilan

Ce qui est livré : un seul programme qui démarre sur STe comme sur STf. Sur STe, le scroll matériel d'origine, intact et rapide. Sur STf, un scroll fluide écrit à la main, sans vague et sans gel, avec une logique de jeu qui tourne à la même vitesse sur les deux machines.

Ce qui reste honnêtement à faire sur STf : les dialogues. Ils s'appuyaient sur l'astuce d'affichage que j'ai dû retirer, et leur position entre en conflit avec le tableau de bord du STf. Pour l'instant, sur STf, les murmures narratifs sont sautés plutôt que de geler le jeu. Un rendu de dialogue propre au STf est le prochain chantier. Sur STe, rien n'a bougé, les dialogues sont là.

La leçon de ces semaines tient en une phrase : sur STf, tout ce que le STe fait gratuitement coûte du temps, et plusieurs morceaux du moteur avaient été écrits en présumant que l'écran se mettait à jour tout seul. Ce n'est jamais le scroll qui m'a coûté le plus de soirées. C'est tout ce qui croyait l'affichage gratuit.

Le build de ce jalon est téléchargeable ici (un seul binaire STe + STf). Lance-le dans Hatari en mode STf pour voir le scroll logiciel, ou en mode STe pour le scroll matériel : c'est le même fichier. Flèches pour bouger, fire pour nettoyer la peste. Pour la musique, prends plutôt l'archive depuis la page d'accueil, il faut le .SND à côté du binaire. Pour la version courante du jeu, voir la page d'accueil.