Page de David Odin

Le Défi NES

Cette page ne devrait peut-être pas être présente dans la partie "Historique" de ce site puisque je commence à peine à programmer sur NES. Au moment où j'écris ces lignes (le 5 mars 2019), je n'ai en effet jamais programmé pour la NES. Je sais plus ou moins de quoi est capable cette machine (que je n'ai jamais possédée, honte à moi !), je ne connais l'assembleur 6502 que théoriquement, je n'ai jamais rien écrit pour cette architecture même si je connais ses limitations (trois registres utilisables : A, X et Y - peu d'instructions et de modes d'adressage). Mais je connais bien différents assembleurs (Z80, 68000, i386, ARM), et j'ai déjà travaillé sur des machines très restreintes.

Aussi, je me suis lancé un petit défi : arriver à créer un jeu pour NES (que je testerai sur tous les émulateurs que je trouverai, et pourquoi pas sur une vraie NES si j'arrive à créer une cartouche) en écrivant tout le code moi-même, en dessinant les graphismes et en composant la musique et effets sonores. En me relisant, je trouve la tâche colossale, mais bon, c'est le principe des défis.

5 mars 2019

Ma santé n'étant pas au top, je commence doucement. Mon but du jour est de trouver des émulateurs et quelques ROMs de jeux homebrew pour les tester. Je vais aussi essayer de trouver un maximum de documentation technique sur l'assembleur 6502 et les spécificités de la NES. L'analyse du code d'un émulateur open source pourrait peut-être bien aussi m'aider grandement.

J'ai trouvé deux émulateurs qui ont l'air sympa : nestopia et fceux. Les deux semblent intéressants et configurables afin d'être assez proche de la NES d'origine. Par exemple la NES est limité à 8 sprites par scanline et ces deux émulateurs permettent de garder cette restriction ou pas. J'aimerais autant que possible un émulateur qui soit aussi exigeant que la vraie console, afin de pouvoir vraiment créer une cartouche par la suite.

Je ne suis pas le seul à vouloir développer pour la NES, et ce Wiki qui regorge de plein d'info me parait très prometteur. J'y ai d'ailleurs trouvé quelques programmes exemples et démos. Une toolchain extèmement simple consiste à utiliser un assembleur nesasm qui produit directement un fichier de type .nes utilisable directement dans un émulateur.

J'avoue avoir la flemme de faire des screenshots et de fournir les liens de ce que j'ai trouvé. Mais tout ça est très encourageant. J'espère commencer l'étude de l'assembleur 6502 ce soir ou demain.

6 mars 2019

L'assembleur nommé asm6 parait plus "moderne". Déjà, j'ai trouvé sa documentation. Il est open source, supporte les macros, différents types de labels locaux, plein d'opérateurs arithmethiques et a d'autres petits avantage. Je vais essayer de me concentrer sur son utilisation.

Avec les infos que j'ai glanées à droite et à gauche, je vais pouvoir commencer mon premier programme.

Apparemment, il y a plein de formats de ROMs supportées par la NES et donc aussi par les émulateurs. Le format le plus simple étant "NROM". Ce qui correspond à une cartouche qui aurait deux eeproms de 16 ko, une pour le code et une pour les graphismes (j'avoue que je ne suis pas bien sûr de ce que j'avance, là). Beaucoup d'autres formats existent notamment pour supporter plus de mémoire en découpant les ROMs en tranches (ce qui est un coup à se mettre des associations humanitaires à dos, mais bon...) ou d'apporter des fonctionnalités supplémentaires. Je n'ai pas fait le tour des formats.

On arrive à trouver des documentations sur l'organisation de la mémoire de la NES, je ne vais pas les reproduire ici. Cependant quelques adresses vont être immédiatement utiles :

Avec tout ça, je vais pouvoir faire mon premier programme : simplement un truc qui change la palette et dont le seul effet visible est de mettre une couleur de fond. L'assembleur 6502 s'apprend très vite, il y a peu d'instructions et de registres, et la philosophie est proche du Z80 que je connais très bien. Quelques macros et définitions permettent de rendre le code plus clair (en tout cas pour moi). J'espère faire un screenshot (vide mais coloré) dès aujourd'hui !

Yes ! J'ai un premier programme qui fonctionne ! Plus exactementl compile sans le moindre problème, s'exécute correctement sur fceux en affichant simplement un fond rose (couleur 37 de la palette de la NES). Mais il ne se lance pas sur nestopia qui affiche un message assez énigmatique : "Error: Corrupt or Missing File". Le fichier existe pourtant et n'est pas si corrompu puisque fceux arrive à le lancer. Je vais enquêter sur le sujet.

J'ai failli oublier de poster un screenshot !
Premier programme NES

7 mars 2019

Mon premier programme NES fonctionne maintenant également sur nestopia qui semble plus pointilleux sur les formats des fichiers ROM.

Beaucoup de temps perdu à essayer de trouver un éditeur de tiles facilement utilisable dans mon environnement. Le plus simple semble de créer des images avec n'importe quel éditeur puis d'utiliser un script pour transformer ça dans le format ultra simple utilisable par le PPU. Je vais faire ça ou même écrire un fichier de graphismes à la main pour commencer. Ma prochaine étape sera d'afficher un fond, comme pour un jeu de plateformes. Mais ça attendra mon retour de l'hôpital...

8 mars 2019

Bon, comme prévu, j'ai écrit un petit programme en C pour créer des graphismes (juste un damier et un triangle d'une autre couleur). Pas gand chose, mais ça permet de tester le fonctionnement de tout cela sur NES. Encore une fois, ça fonctionne mieux avec fceux qu'avec nestopia. J'ai à peu près ce que je veux sur le premier (voir screenshot ci-dessous) alors que le second affiche les éléments en noir.
Premiers tests background

Prochaine étape : avoir un fond formé de plein de "tiles" différents, avant de passer à la partie scrolling.

9 mars 2019

Pas grand chose aujourd'hui. J'ai surtout lu plein de docs. Je commence à bien voir les possibilités et limitations de cette console. Il y a de quoi s'amuser.

10 mars 2019

Aujourd'hui, je me suis fait un petit programme permettant de facilement utiliser une police de caractères. Je pourrai donc facilement en changer par la suite.

Et voici donc le screenshot de l'utilisation d'une police. Ça permettra d'afficher un score ou plein d'autres trucs.
Hello, world!

11 mars 2019

Encore beaucoup de temps passé à découvrir le fonctionnement interne de la bête. Il semblerait qu'on puisse dépasser certaines limitations assez facilement finalement. Encore et toujours le même truc : on synchronise le CPU avec la partie vidéo (comme sur ZX81, ZX spectrum, C64, Atari ST) et on change certains paramètres exactement au bon moment. Il me semble possible de posititonner les tiles du background au pixel près horizontalement dans certaines conditions. La 3D n'est pas loin ;) !

En attendant que je maîtrise mieux ces choses exotiques, je me suis donné un but plus accessible : porter mon jeu favorit sur cette plateforme nouvelle pour moi. Ça n'est pas gagné puisque je continue de découvrir l'assembleur 6502, mais au moins je connais assez bien le jeu pour l'avoir codé sur pas mal de machines. La partie décor semble facile, si ce n'est que la résolution verticale de la NES n'est pas suffisante pour tout afficher à la fois. Je vais donc devoir implémenter un scrolling vertical plus rapidement que prévu !

Et voici l'habituel screenshot.
Pacman décor

12 mars 2019

Plein de nouveautés aujourd'hui !
J'arrive à afficher des sprites par dessus mon décor, et j'ai progressé en assembleur 6502. Le labyrinthe de pacman (qui s'est vu étoffé de pac-gommes), peut maintenant être visité par pacman. Ça veut dire que j'arrive à gérer les joypads et que mon niveau d'assembleur 6502 me permet de tester si pacman rentre dans un mur ou pas !
Pour mieux vous rendre compte, en plus du screenshot du jour, il y a aussi la vidéo du jour (cliquez sur l'image) :
Pacman du jour
Le jeu est beaucoup moins saccadé que la vidéo le laisse supposer. D'ailleurs, si vous disposez d'un émulateur comme fceux ou nestopia, vous pouvez le tester vous-même en cliquant sur ce lien

Bilan provisioire Compte tenu que je ne m'intéresse au développement sur NES et à l'assembleur 6502 que depuis une semaine, je suis assez content du résultat. N'hésitez pas à me contacter si vous avez besoin d'un programmeur assembleur (pour NES ou autre !)

13 mars 2019

Plein d'emmerdes personnelles aujourd'hui, du coup je n'ai pas avancé beaucoup. J'ai tout de même incorporé un début de "vrai" moteur graphique dans mon code assembleur (avec une séparation forte entre la logique et le rendu). Les limitations de l'assembleur 6502 (et mes connaissances aussi, probablement) font qu'il est assez complexe de se déplacer dans un tableau de plus de 256 octets, mais on y arrive. Cela méritera probablement une réécriture ou au moins une optimisation du code dans l'avenir. Cela a tout de même permis de mettre à jour certaines données pour effacer les pillules que pacman mange. Pacman peut aussi maintenant emprunter le tunnel dans les deux sens.

Les prochaines étapes qui me viennent en tête sont l'actualisation du score, avoir un pacman qui regarde dans la bonne direction et qui mâche, puis je passerai aux fantômes. J'ai encore de quoi m'occuper un moment !

La vidéo du jour montre que pacman dévore maintenant ses pillules préférées :
video

14 mars 2019

Ça continue d'avancer doucement. J'ai nettoyé une partie du code et ajouté quelques fonctionnalités. Mon pacman regarde maintenant dans la bonne direction !

Les pillules sont vraiment mangées correctement et rapportent 10 points chacune, comme on peut le voir dans la vidéo du jour.

video

15 mars 2019

Pacman mâche maintenant correctement sa nourriture. Pas de difficulté particulière pour l'animation de pacman, il s'agit simplement de sprites à enchaîner dans le bon ordre.

Une partie un peu plus complexe a été la mise en place d'un scrolling vertical. En effet, je voulais garder le même plan de labyrinthe que dans le jeu original, et cela ne tient pas dans l'écran de la NES. L'écran défile donc en suivant les mouvements de Pacman. Pas mal de difficultés rencontrées, même si la NES fournit un registre pour effectuer le défilement du fond (background). En effet, ce registre ne concerne pas les sprites qu'il faut donc repositionner en fonction. De plus, les informations concernant le haut et le bas du labyrinthe ne sont pas contiguë en mémoire, ce qui complexifie pas mal les choses. Sans compter que l'écran virtuel étant de plus de 256 pixels de haut, il est assez pénible de stocker les positions dans les registres 8 bits du 6502.

Mais finalement, rien d'insurmontable, et cela m'a obligé à réécrire plus proprement certaines parties du code. La gestion des sprites des fantômes ne devrait pas être rendue plus complexe avec le défilement, le gros du travail ayant été fait pour Pacman.

La vidéo du jour montre tout ça.

video

16 mars 2019

Un peu de reflexion aujourd'hui avant de se replonger dans le code.

Maintenant que Pacman se déplace bien dans le labyrinthe, il est temps de passer à l'affichage des fantômes. Voici ce que j'avais en tête pour les sprites des fantômes :

Et C'est là qu'arrivent les problèmes.

Sur NES, il y a deux façons d'afficher des graphismes : le fond et les sprites. Le fond permet d'afficher des trucs comme les murs du labyrinthe qui ne bougent pas, mais uniquement à des positions qui sont des multiples de 8. Il y a aussi d'autres limitations, mais peu importe pour le moment.

Pacman et les fantômes doivent donc être affichés via le système de sprites. La NES permet d'afficher simultanément jusqu'a 64 sprites, ce qui est amplement suffisant pour un jeu comme Pacman, même en considérant que chaque personnage "consomme" 4 sprites. Cependant, chaque sprite de 8x8 ne peut être utiliser qu'une palette parmi 4. Et chaque palette est composée de 3 couleurs plus une pour la transparence. On peut toutefois composer les palettes comme on le veut, reste à trouver comment.

Si on part de l'idée que les fantômes sont créés comme décrits précédemment, on a besoin des palettes suivantes :

Les palettes sont alors toutes utilisées, et il ne reste plus de couleur possible pour le jaune de Pacman, c'est inenviageable ! Les couleurs Noir et Blanc doivent être dupliquées dans chaque palette à cause de la limitation disant qu'un sprite donné ne peut utiliser les couleurs que d'une seule palette.

Il va donc falloir ruser.
Une idée qui m'est venue était d'utiliser des sprites avec juste les robes des fantômes par dessus lesquelles on pourrait ajouter des sprites pour les yeux, ça permet d'éviter le problème de duplication du noir et du blanc, on peut même tout faire tenir dans trois palettes de cette façon. Mais on se heurte alors à une autre limitition de la NES : sur chaque ligne horizontale (de 1 pixel), seuls 8 sprites peuvent être affichés. Si on essaie d'en mettre plus, ils ne seront tout simplement pas affichés. On peut donc afficher 64 sprites, mais uniquement s'ils sont bien répartis verticalement ! Hors, avec l'idée des robes et des yeux superposés, pour un seul fantôme, on a déjà 4 sprites sur la même ligne, et donc dès qu'on aura trois fantômes ou plus (ou deux fantômes et pacman) sur la même ligne, certains sprites ne seront pas affichés !

On ne peut donc pas vraiment utiliser l'idée des yeux dans des sprites séparés, dommage.

Idée suivante :utiliser la couleur transparente au lieu du noir pour l'iris des yeux des fantômes.

Cela présente un léger inconvénient : on voit ce qu'il y a derrière un fantôme au niveau de ces yeux. Mais bon, après tout il s'agit de fantôme, et la plupart du temps, ce qu'il y a derrière les yeux d'un fantôme, c'est le noir du fond du labyrinthe. Les pillules ne sont par au niveau des yeux, ni horizontalement ni verticalement. Le problème ne sera donc visible que si le fantôme passe au dessus d'une des 4 pac-gommes, d'un autre fantôme ou de pacman. C'est donc un inconvénient que l'on peut tolérer, surtout que cela résoud les problèmes précédents, ou presque.

En effet, si Pacman et les quatre fantômes sont sur la même ligne, on a toujours le problème de la limite des 8 sprites par ligne. Et l'un des personnages risque de disparaître. La seule solution que je vois à ça consiste à changer l'ordre d'affichage des fantômes régulièrement et assez rapidement. (Hors de question de ne pas avoir Pacman à l'écran)

Avant d'implémenter tout ça, je me suis demandé si la version officielle de Pacman sur NES souffrait des mêmes problèmes, et je me suis penché sur cette vidéo :

On peut remarquer plusieurs choses :

Même si c'est rare, je trouve perturbant qu'un fantôme puisse totalement disparaître et réapparaitre plus tard (ce qui arrive notamment un dixième de seconde avant la première image ci-dessus). C'est pourquoi je veux tester ma solution qui consiste à changer régulièrement l'ordre des fantômes. Ainsi en cas de problème les fantômes clignoteront à tour de rôle ce qui permettra de ne pas les perdre des yeux. Cela pourra cependant être gênant lorsque deux fantômes feront un bout de chemin ensemble, l'ordre de superposition changera. Reste à savoir si ces changements seront plus ou moins pénibles que de voir un fantôme disparaître totalement.

Mais je suis content de voir que le jeu officiel a le même genre solution aux contraintes imposées par la machine. Il reste tout de même à implémenter tout ça.

Je peux au moins commencer par lister les couleurs de chaque palette pour les sprites afin de pouvoir commencer à créer les graphismes des fantômes :

Palette # Couleur Utilisation
1 0 Noire Transparent
1 Jaune Pacman
2 Inutilisé
3 Inutilisé
2 0 Noire Transparent
1 Rouge Robe du Fantôme Rouge
2 Cyan Robe du Fantôme Cyan
3 Blanc Yeux des deux premiers fantômes
3 0 Noire Transparent
1 Rose Robe du Fantôme Rose
2 Orange Robe du Fantôme Orange
3 Blanc Yeux de ces deux fantômes
4 0 Noire Transparent
1 Bleu foncé Fantômes en mode pac-gomme
2 Bleu clair Contour des fantômes en mode pac-gomme
3 Inutilisé

19 mars 2019

Après deux jous sans rien pour cause de dimanche et d'anniversaire, le développement avec l'arrivée des fantômes. Le post de samedi a bien aidé à débroussailler toute la partie affichage.

Sur le screenshot du jour, on peut voir l'apparition des fantômes.
Apparition des fantômes