01Pour commencer
Ce guide explique le fonctionnement de HARAPEKO SHIROHEBI, des commandes du joueur aux pixels affichés. Le jeu est une création de DAISUKE OBA. Il faut manger des grenades pour faire grandir le serpent blanc, tout en évitant les mines et son propre corps. Le programme fourni, les ressources originales et ce guide sont distribués sous licence MIT.
L’écran mesure 160 × 144 pixels. Une même ROM prend en charge le Game Boy d’origine (DMG) et le Game Boy Color (CGB) ; le mode couleur est choisi à l’exécution. La cartouche utilise un MBC5, 64 KiB de ROM et 8 KiB de RAM sauvegardée par pile. La version jouable est disponible sur la page itch.io du jeu.
Parcours conseillé : commencez par le schéma d’exécution, puis lisez ensemble les sections sur la tête et le suivi du corps. Le tableau des bibliothèques relie chaque technique au code à consulter. Dans les identifiants, Apple désigne la grenade affichée à l’écran et Block désigne la mine.
02Compilation et organisation des fichiers
Rust 1.85 ou ultérieur permet de construire le compilateur et tous les outils auxiliaires pour Windows, Linux, macOS ARM et macOS Intel. Les exécutables natifs ne nécessitent pas .NET ; les outils de ressources fonctionnent aussi sans Python ni Pillow.
Les scripts PowerShell utilisent l'exécutable Windows à la racine. Sous Linux/macOS, transmettez les mêmes sources C et options au compilateur natif, ou utilisez PowerShell 7. Les graphismes CHR et le source C sont des entrées distinctes ; font.chr conserve la police des exemples.
powershell -NoProfile -ExecutionPolicy Bypass -File .\apps\harapeko_shirohebi\build.ps1
Le script assemble 17 fragments de code C dans un ordre précis. La musique, les ressources exportées et les fichiers enveloppes qui sélectionnent les banques sont des entrées de compilation distinctes. La compilation utilise lib/ dans le dépôt ; aucun projet graphique privé ni outil d’export de ressources n’est nécessaire. N’ajoutez pas les fragments séparément à un projet C ordinaire : ils partagent leurs déclarations dans l’unité de traduction assemblée.
| Option / fichier produit | Rôle |
|---|---|
-KitaqgbRoot | Sélectionne le répertoire contenant kitaqgb.exe et lib/. Cette option est facultative avec l’organisation prévue par le dépôt. |
-OutputDirectory | Choisit le répertoire de sortie ; par défaut, il s’agit de out/ dans le répertoire du jeu. |
-KeepBuildFiles | Conserve le code assemblé, les adaptations audio temporaires et les diagnostics du compilateur après une compilation réussie. |
shirohebi.gb | ROM produite par cette compilation. Après un échec, ne prenez pas une ancienne ROM pour le résultat courant. |
shirohebi.map | Adresses des symboles pour déboguer précisément cette compilation. |
build_manifest.json | Empreintes du compilateur et de la ROM, taille du fichier produit et adresse du vecteur d’interruption. |
Pourquoi une étape de traitement suit la compilation
Le code de l’interruption musicale VBlank doit rester accessible quelle que soit la banque ROM commutable sélectionnée. Le script vérifie que quatre symboles liés à l’interruption se trouvent dans la banque fixe 0, installe un JP à l’adresse $0040 et recalcule les deux sommes de contrôle de la cartouche. Il refuse un vecteur inattendu. Une copie temporaire du code audio désactive le service musical ordinaire, afin que la boucle principale et l’interruption ne fassent pas avancer la musique toutes les deux. Une autre copie temporaire place les fonctions audio auxiliaires et utilise un saut absolu dont la destination est accessible. Les bibliothèques du dépôt ne sont pas modifiées.
Consultez build.ps1 pour l’ordre complet des entrées et les options du compilateur. Options principales : --profile=release --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5_ram_battery --romsize=64k --ramsize=8k.
03Déroulement et états du programme
| Transition d’état | Déclenchement et effet |
|---|---|
| TITLE → READY → PLAY | START lance une partie. Le déplacement commence après l’animation d’introduction START. |
| PLAY ⇄ PAUSE | START met en pause ou reprend la partie. La physique et le suivi du corps s’arrêtent pendant la pause. |
| PAUSE → RETURN_CONFIRM | SELECT ouvre la confirmation de retour au titre, avec NO sélectionné par défaut. Annuler ramène à la même partie en pause ; YES revient à TITLE. |
| PLAY → MISS | Une collision avec une mine ou avec le corps déclenche l’animation correspondante. |
| MISS → NAME_ENTRY / GAMEOVER | Un score admissible au classement ouvre la saisie du nom. Les autres scores mènent directement à la proposition de rejouer. Confirmer le nom le sauvegarde puis ouvre cette proposition. |
| GAMEOVER → READY / TITLE | YES lance une nouvelle partie ; NO revient au titre. |
| TITLE ⇄ ERASE | SELECT+START ouvre la confirmation d’effacement des scores. A confirme ; B ou START annule. Le choix initial est NO. |
Le mécanisme d’attente du relâchement ignore les entrées jusqu’à ce que tous les boutons soient relâchés, y compris lors du passage où ce relâchement est constaté. Ainsi, le bouton qui ouvre un écran ne confirme pas immédiatement l’action suivante. Le mode démonstration remplace les commandes de direction et réutilise le même code de déplacement et de collision. L’inactivité sur le titre se compte en 900 passages dans la boucle principale ; la démonstration dure 1 800 occurrences de VBlank. Aucun de ces compteurs ne garantit une durée réelle précise.
04Déplacement de la tête : virgule fixe et direction
Seule la tête est un KQBody2D. Son KQWorld2D contient un unique corps actif, avec une gravité nulle et aucune itération du solveur de contacts. Le jeu effectue lui-même les tests de collision après le déplacement. En coordonnées Q4, 16 unités entières représentent un pixel : 160 représente donc 10 pixels. Les déplacements inférieurs au pixel sont ainsi conservés sans calcul en virgule flottante.
base = 8 + 2 * min(score / 5, 10) // Q4 component limit
first UP update: limit = base + (base >> 2)
held UP: limit += max(base >> 2, 1), capped at 2 * base
released UP: limit -= max(base >> 2, 1), floored at base
pixel_center = (q4_position + 8) >> 4
La limite de base des composantes de vitesse varie de 0,5 à 1,75 pixel par mise à jour. Les 16 directions suivent le sens horaire : droite (0), bas (4), gauche (8), haut (12). LEFT et RIGHT décalent la direction visée d’un secteur. Un appui maintenu utilise un décompte initial de 8, puis un décompte de répétition de 4 ; LEFT et RIGHT pressés ensemble annulent la rotation.
La vitesse cible utilise des composantes valant la limite entière, ses trois quarts, son quart ou zéro. Chaque composante réelle se rapproche de sa cible d’au plus 3 unités Q4 par mise à jour. Ces approximations entières sont peu coûteuses, mais ne forment pas des vecteurs trigonométriques normalisés. L’orientation affichée peut donc changer avant que la vitesse ait fini de s’aligner.
Après kq2d_step, le centre de la tête passe d’un bord à l’autre : X inférieur à 4 devient 156, X supérieur à 156 devient 4 ; Y utilise de même les limites 4 et 140. Les coordonnées sont ensuite arrondies une seule fois en pixels, pour l’affichage comme pour les collisions. Cette règle propre à la tête diffère du bouclage modulo 160/144 utilisé par le corps.
Code à consulter : shirohebi_snake.c / shirohebi_flow.c.
05Comment le corps suit la tête
ChainBody pointe directement vers SND_TraceX, SND_TraceY et SND_TraceDir. Ces tableaux contiennent la position et l’orientation actuelles de chaque segment, pas un historique du trajet de la tête. Les collisions et l’affichage lisent les mêmes tableaux. Le serpent commence avec une tête et trois segments de corps ; sa longueur maximale est de 31 segments, tête comprise.
Sur un écran étroit, faites défiler le schéma horizontalement.
- Écrire la position en pixels et la direction de la tête à l’indice 0 ; affecter cette direction à
pull. - Pour le segment
i, conserver son ancienne direction. Soustraire au prédécesseur déjà mis à jour un petit décalage dépendant de la direction, afin d’obtenir la position cible. - Calculer le déplacement X/Y le plus court en tenant compte du bouclage. Déplacer chaque axe de 0, 1 ou 2 pixels selon le tableau ci-dessous.
- Affecter
pullà la direction du segment, ramener sa nouvelle position dans la zone par bouclage et transmettre l’ancienne direction conservée au segmenti + 1.
| Déplacement signé d | Correction sur chaque axe |
|---|---|
| d > 4 | +2 |
| 0 < d ≤ 4 | +1 |
| d = 0 | 0 |
| −4 ≤ d < 0 | −1 |
| d < −4 | −2 |
Les décalages X des directions 0 à 15 sont [4,4,3,1,0,-1,-3,-4,-4,-4,-3,-1,0,1,3,4] ; Y utilise les mêmes valeurs avec un décalage d’indice de 12 secteurs. Les coordonnées bouclent dans une zone de 160 × 144 pixels. Pour un axe de longueur W, on retranche W à un déplacement supérieur à W/2 et on ajoute W s’il est inférieur à −W/2 ; un déplacement égal à la moitié de la zone conserve son signe.
Exemple de calcul au bord de l’écran
Un segment précédent situé en (2, 50) et orienté à droite place la cible du suivant quatre pixels derrière lui : X cible = (2 − 4) mod 160 = 158. Si le suivant se trouve en X=156, le déplacement vaut +2 : il avance donc de +1 et atteint X=157. Depuis X=0, le déplacement le plus court vaut −2 ; il rejoint alors X=159. Il suit ainsi son prédécesseur à travers le bord, sans traverser tout l’écran.
Pour grandir, le jeu duplique la position et l’orientation de la queue, puis augmente le nombre de segments actifs. Les mises à jour suivantes écartent progressivement le nouveau segment. L’ancienne queue est mise en évidence pendant 20 mises à jour. Le fichier enveloppe de la bibliothèque place le suivi et ses fonctions auxiliaires ensemble dans la banque 2, ce qui évite de changer de banque pour chaque segment.
/* Excerpt: the game owns these arrays for the entire run. */
chain_body_init(&SND_ChainBody, SND_TraceX, SND_TraceY, SND_TraceDir,
SND_MAX_SEGMENTS, SND_SCREEN_W, SND_SCREEN_H);
chain_body_reset(&SND_ChainBody, SND_Length,
SND_HeadX, SND_HeadY, SND_Facing);
/* Once per PLAY update, after integrating and rounding the head. */
SND_ChainBody.count = SND_Length;
chain_body_step(&SND_ChainBody, SND_HeadX, SND_HeadY, SND_Facing);
/* On fruit collection, within capacity. */
chain_body_grow(&SND_ChainBody);
SND_Length = SND_ChainBody.count;
Cet extrait illustre la durée de vie des tableaux et l’ordre des appels ; le jeu complet vérifie aussi si l’ajout d’un segment a réussi et déclenche sa mise en évidence. Sources : shirohebi_snake.c / shirohebi_chain.c / chain.c.
06Fruits, collisions et animations de défaite
Une mise à jour PLAY suit cet ordre : accélération → direction → physique de la tête → passage des bords et arrondi de la tête → suivi du corps → mines → collision avec soi-même → fruit → fin de la mise en évidence. Lors d’une même mise à jour, une collision fatale est prioritaire sur la collecte d’un fruit.
| Test | Règle appliquée |
|---|---|
| Mines | Le centre de chaque segment est testé dans des rectangles aux limites incluses : X=46…58 ou 102…114, Y=62…74. |
| Collision avec le corps | La tête est comparée aux segments à partir de l’indice 2 : les distances minimales avec bouclage doivent vérifier |dx| < 3 et |dy| < 3. Le segment immédiatement derrière la tête est exclu. |
| Fruit | Entre la tête et le centre du fruit, les distances ordinaires, sans bouclage, doivent vérifier |dx| < 7 et |dy| < 7. Le jeu ajoute un point, tente d’allonger le corps et choisit la position suivante. |
Ces tests utilisent des seuils séparés sur les axes, pas une distance circulaire. Les 16 positions possibles du fruit sont examinées dans un ordre déterministe. La distance minimale aux mines, mesurée en tuiles, diminue avec le score : 4, 3, 2 et 1 pour les scores 0, 10, 20 et 30. Une position sur la même tuile qu’une mine est toujours rejetée. La recherche essaie au maximum 16 positions. Le score tient sur 8 bits : ce n’est pas un compteur sans limite.
Une collision avec le corps fige sa pose et la fait disparaître progressivement. Une mine disperse les segments avec des vitesses en virgule fixe, une gravité retardée et des explosions décalées, puis laisse un cratère. À la fin du délai de défaite, un score admissible mène à la saisie du nom ; les autres mènent à la proposition de rejouer. Les effets utilisent les couleurs sur CGB et les palettes de nuances sur DMG.
07Affichage : tuiles et ordre des sprites
L’initialisation attend une phase d’affichage sûre, éteint le LCD, efface la VRAM, charge les tuiles, les caractères et les palettes, puis active l’affichage. Le chemin CGB fournit les attributs du fond et les palettes couleur ; le chemin DMG règle les registres de nuances. Le fond exporté contient 20 tuiles par ligne, mais la carte matérielle en utilise 32 : leurs indices ne sont pas interchangeables.
À chaque passage dans la boucle, le jeu prépare une copie de l’OAM en RAM. Les coordonnées de chaque sprite incluent les décalages matériels X+8 et Y+16. Après system_wait_vblank(), les données OAM sont transférées. Le serpent occupe les emplacements 0 à 30 ; le texte utilise les autres. Les entrées inutilisées sont effacées.
Les six premiers segments conservent un ordre de priorité OAM fixe. L’ordre des suivants tourne selon une phase augmentée de quatre à chaque affichage. Cela répartit entre les segments arrière les effets de la limite matérielle de dix sprites par ligne ; cela ne supprime ni cette limite ni des segments du corps. Toute modification de la longueur maximale demande de vérifier à la fois la capacité des tableaux et l’affectation des 40 emplacements OAM.
Les textes superposés START et PAUSE mémorisent l’état souhaité, l’état affiché et la nécessité de redessiner. Pour retirer un texte, le jeu restaure chaque case en tenant d’abord compte du fruit courant, puis du fond si nécessaire. Remplir toute la zone avec une seule tuile effacerait un fruit placé dessous. Les masques de caractères, formés de huit lignes à un bit par pixel, sont convertis en seize octets de tuiles à deux bits par pixel ; les pixels du caractère ont priorité sur le motif du fond.
shirohebi_render.c / shirohebi_display.c / shirohebi_pause.c
08Musique et rôle du VBlank
audio_vblank.c lit le flux musical situé dans la banque fixe. Chaque enregistrement ordinaire suit l’ordre délai, CH1, CH2, CH3, CH4 : impulsion avec balayage de fréquence, impulsion, onde, puis bruit. Les canaux suivent donc l’ordre physique du matériel. La musique se contrôle avec AudioVBlank_PlayMusic, AudioVBlank_Stop et AudioVBlank_SetEnabled.
Le pilote ordinaire audio.c traite les effets sonores du jeu. Sa partie musicale est exclue par une définition temporaire lors de la compilation. Les effets utilisent __bankof pour sélectionner la banque de leurs données et sont soumis à des priorités ; l’effet de mine utilise aussi directement le bruit CH4. La pause coordonne musique et effets. Les appels à SND_AudioServiceWork dans la boucle principale sont volontairement sans effet : traiter davantage de segments ne doit pas faire avancer l’horloge musicale.
AudioVBlank_FrameHook appelle SND_DemoVBlankHook, placé dans la banque fixe du jeu. Cette fonction incrémente un compteur de démonstration de 8 bits et lit le groupe des boutons système en conservant la sélection P1. Lorsque la fonction correspondante est activée, elle mémorise SELECT+START au titre et SELECT en pause, afin qu’un appui bref ne soit pas perdu quand la boucle principale est occupée. Elle ne dessine rien et n’appelle aucune fonction d’une banque commutable.
/* Excerpt from initialization, after shared state has been set up. */
SND_AudioInit();
AudioVBlank_FrameHook = SND_DemoVBlankHook;
AudioVBlank_EnableIrq();
09Scores et saisie du nom
L’emplacement 0 contient 42 octets de données applicatives : la signature 0x53, la version 2, dix scores d’un octet et trente caractères de noms. La bibliothèque de sauvegarde vérifie la longueur et la somme de contrôle de l’enveloppe. Le chargement reconnaît également les formats de scores de 5 et 15 octets ; l’écriture utilise toujours le format de 42 octets.
Un score non nul admissible est inséré par ordre décroissant. La comparaison étant strictement supérieure, un score égal se place après les entrées existantes. Les noms suivent leurs scores. Une nouvelle entrée reçoit d’abord AAA en RAM ; la SRAM n’est écrite que lorsque le joueur confirme son nom de trois caractères. Abandonner un résultat en attente recharge le classement sauvegardé au lieu d’enregistrer ce résultat.
UP et DOWN choisissent une lettre de A à Z ou un point. RIGHT et SELECT passent au caractère suivant avec retour au début ; LEFT recule avec retour à la fin. B ne recule que si le curseur n’est pas sur le premier caractère. A avance, ou confirme depuis le dernier caractère ; START confirme depuis n’importe quelle position. L’attente du relâchement empêche cette confirmation de choisir aussi de rejouer.
10Utilisation des bibliothèques KITAQGB
Utilisez ensemble la bibliothèque et son en-tête présents dans le dépôt. Les fichiers enveloppes et les réglages propres au jeu font partie de l’exemple, notamment le placement dans les banques et la coordination audio.
| Bibliothèque | Points d’entrée et rôle | Exemple dans les sources |
|---|---|---|
system.c | system_init, system_wait_vblankInitialisation de l’état système et synchronisation de l’affichage. La fonction appelée par l’IRQ audio est installée séparément. | shirohebi_main.c |
chain.c | chain_body_init, chain_body_reset, chain_body_step, chain_body_growAssociation de tableaux persistants, création de la pose, suivi de la tête et ajout d’un segment de queue. L’API Chain à historique circulaire n’est pas utilisée. | shirohebi_snake.c |
physics2d.c | kq2d_world_init, kq2d_stepIntégration du seul corps Q4 de la tête, avec une gravité nulle et aucune itération du solveur de contacts. | shirohebi_snake.c |
sprite.c | sprite_init ; kq_sprite_oam et état associéInitialisation et utilisation de la copie OAM en RAM. Le jeu remplit directement les entrées, puis les transfère ; les règles de coordonnées et d’emplacements restent à respecter. | shirohebi_render.c |
audio_vblank.c | AudioVBlank_Init, PlayMusic, Stop, SetEnabled, EnableIrq, FrameHookLecture du flux musical résident et rappel du jeu pendant l’interruption. Le code et les données IRQ doivent rester dans la ROM fixe. Les noms abrégés après le premier portent tous le préfixe AudioVBlank_. | shirohebi_audio.c |
audio.c | Audio_Init, Audio_Update, Audio_PlaySFXBanked, Audio_StopSfx, Audio_SetPausedLecture, priorité et pause des effets, en coordination avec le pilote musical VBlank. | shirohebi_audio.c |
save.c | save_exists, save_read, save_writeLecture et écriture du classement avec numéro de version dans l’emplacement 0. save_read indique un succès ou un échec après vérification de la longueur exacte demandée et de la somme de contrôle ; le jeu vérifie aussi sa propre signature. | shirohebi_save.c |
cgb_palette.c | cgb_bg_palette, cgb_obj_paletteConfiguration des couleurs CGB ; les registres de palettes DMG sont réglés explicitement à part. | shirohebi_display.c |
map.c | map_load et descripteur map_t exportéPrise en charge de la fonction de carte du fichier de ressources ; le jeu restaure lui-même les cases une par une. | shirohebi_assets.c |
fixed.c | support du calcul en virgule fixeCode de support lié au programme ; le déplacement de la tête repose sur physics2d et sur les calculs entiers Q4. | shirohebi_common.c |
audio_hwregs_gb.c | définitions partagées des registres audioDéfinitions des registres matériels Game Boy nécessaires aux deux traitements audio. | shirohebi_audio.c |
Fonctions intrinsèques du compilateur utilisées avec les bibliothèques
__readpadex(previous) renvoie les boutons maintenus dans l’octet faible et ceux nouvellement pressés dans l’octet fort. __cgb_is_cgb() sélectionne le traitement couleur. Les fonctions intrinsèques de tuiles et d’attributs, telles que __settile et __settileattr, modifient les cases du fond ; __bankof fournit la banque ROM des données d’un effet. Ces fonctions sont fournies par le compilateur : il n’y a pas d’implémentation C supplémentaire à copier dans le jeu.
11Repères dans le code et points à vérifier
| Fichier | Responsabilité |
|---|---|
shirohebi_common.c | Types, constantes, état partagé et déclarations anticipées. Commencez ici pour retrouver un symbole. |
shirohebi_main.c | Démarrage et boucle entrées → mise à jour → affichage → VBlank. |
shirohebi_flow.c | Sélection du traitement selon l’état : options du titre, READY, PLAY, pause, défaite, saisie du nom et nouvelle partie. |
shirohebi_input.c | Attente du relâchement, raccourci du titre et confirmation de retour au titre. |
shirohebi_snake.c | Physique de la tête, accélération, rotation relative, passage des bords et initialisation, mise à jour et allongement du corps. |
shirohebi_chain.c | Fichier enveloppe de la banque 2, qui inclut toute l’implémentation partagée de chain. |
shirohebi_collision.c | Collisions avec les mines et le corps, classification de l’impact et dispersion animée des segments. |
shirohebi_apples.c | Choix de la position de la grenade, collecte, score et allongement. Apple est l’identifiant interne. |
shirohebi_demo.c | Direction en mode démonstration, pose du long serpent et comptage du temps écoulé à partir du compteur VBlank. |
shirohebi_render.c | Préparation de l’OAM en RAM, tuiles de tête, de corps et de queue, rotation des priorités et effets de défaite. |
shirohebi_display.c | Initialisation du LCD et de la VRAM, chargement des palettes et des caractères, disposition du titre et du classement. |
shirohebi_background.c | Cases du fond de jeu, mines et restauration des cases recouvertes. |
shirohebi_pause.c | Textes superposés START/PAUSE, avec état demandé, affiché et à redessiner. |
shirohebi_text.c | Conversion des caractères en tuiles, chaînes de texte, scores numériques et curseurs de menus. |
shirohebi_save.c | Validation du classement, insertion, noms de trois caractères et stockage en SRAM. |
shirohebi_audio.c | Initialisation musique/effets, démarrage et arrêt, options, pause et coordination des canaux. |
music.c | Enregistrements musicaux VBlank résidents de longueur fixe pour le jingle de départ, le morceau principal et celui de fin de partie. |
sfx.c | Flux d’octets des effets choisis par les fonctions audio du jeu. |
text_tiles.c | Masques de caractères et conversion en lignes de tuiles Game Boy à deux bits par pixel. |
shirohebi_assets.c | Tuiles, carte, attributs et tables de collisions/événements exportés ; descripteur de carte et fonctions auxiliaires. |
shirohebi_input_shared.h | Déclarations des indicateurs d’entrée en WRAM et du rappel en banque fixe partagés avec l’interruption. |
shirohebi_lib_bank0.c | Rappel VBlank d’entrée et d’horloge en banque fixe, indicateurs WRAM partagés et sélection de la banque 0 pour les entrées de compilation système/audio suivantes. |
shirohebi_lib_bank1.c | Sélection de la banque 1 pour les entrées de compilation des bibliothèques de support suivantes. |
Points à vérifier lors d’une modification
- Vitesse et direction : après modification des constantes Q4, vérifiez les virages lents et l’accélération avec UP. Le secteur vers lequel regarde la tête n’est pas la direction exacte de sa vitesse.
- Longueur : adaptez ensemble la capacité des tableaux, celle de la chaîne et les emplacements OAM réservés. Vérifiez les collisions de la queue avec les mines ou la tête, ainsi que la limite de sprites par ligne.
- Graphismes : préservez les numéros de tuiles, le pas des lignes de la carte et les attributs CGB. En retirant un texte superposé, restaurez le contenu actuel de la case sous-jacente.
- Audio : conservez le code d’interruption dans la banque fixe et une seule source d’avancement de l’horloge musicale. Testez la pause et la reprise, en plus de la lecture normale.
- Sauvegarde : changez la version du format lorsque sa disposition change ; vérifiez la longueur avant tout accès par indice et testez une SRAM neuve ou invalide.
Après recompilation, utilisez le fichier d’adresses généré par cette compilation. Vérifiez le titre, l’introduction START, les déplacements, les virages, les fruits, les collisions avec le corps et les mines, la pause et la reprise, la confirmation de retour et le classement dans les deux modes matériels. Une compilation réussie ne prouve à elle seule ni le bon fonctionnement de ces parcours ni celui du jeu sur une console réelle.