Le format de sauvegarde Gen 1 : Pokémon Rouge, Bleue & Jaune
Où se trouve quoi dans une sauvegarde Génération 1 de 32 Kio : adresses, sommes de contrôle, structure d'un Pokémon, boîtes du PC et encodage du texte. Vérifié sur les désassemblages pret et sur de vraies cartouches.
Une sauvegarde de Génération 1, c’est 32 Kio de SRAM sauvegardée par pile, et presque tout y est vide. Ce qui compte tient dans trois régions, protégées par trois sommes de contrôle, et une fois qu’on sait où elles sont le fichier cesse d’être opaque.
Tout ce qui suit est vérifié sur les désassemblages pret
de Rouge, Bleue et Jaune — ram/sram.asm et ram/wram.asm — puis confronté à
de vrais dumps de cartouches françaises et anglaises. Les tableaux sont générés
à partir des constantes que l’analyseur de ce site utilise pour lire vos
imports : ils ne peuvent donc pas se démoder en silence, puisque toute
modification du code se répercute ici.
Le fichier
Une cartouche Gen 1 embarque 32 Kio de SRAM, répartis en quatre banques de $2000 octets. Une sauvegarde en est le décalque linéaire, dans l’ordre : une adresse dans le fichier est une adresse dans la SRAM, sans conversion.
Trois de ces banques servent à quelque chose :
- La banque 1 contient les données principales — qui vous êtes, ce que vous avez capturé, votre équipe, et la boîte du PC actuellement sélectionnée.
- Les banques 2 et 3 contiennent les douze boîtes du PC, six par banque.
- La banque 0 est un brouillon : rien d’exploitable.
Un fichier de 32 768 octets exactement est le cas normal. Les fichiers plus gros sont fréquents et généralement sains : certains lecteurs de cartouche lisent le maximum de SRAM adressable par le MBC au lieu de la taille annoncée dans l’en-tête, ce qui donne 128 Kio pour le MBC5 de Jaune, la vraie sauvegarde occupant les 32 premiers Kio. Tout ce qui dépasse $8000 peut être ignoré.
Où se trouve quoi
Les adresses sont des positions absolues dans le fichier. La colonne des symboles donne le nom de la région dans le désassemblage, utile si vous recoupez avec les sources pret.
| Adresse | Octets | Symbole | Champ |
|---|---|---|---|
| 0x2598 | 11 | wPlayerName |
Nom du joueur, terminé par un marqueur |
| 0x25A3 | 19 | wPokedexOwned |
Pokédex, Pokémon possédés : un bit par espèce |
| 0x25B6 | 19 | wPokedexSeen |
Pokédex, Pokémon vus : un bit par espèce |
| 0x25C9 | 42 | wNumBagItems |
Sac : nombre d’objets, puis paires (identifiant, quantité) |
| 0x25F3 | 3 | wPlayerMoney |
Argent, en décimal codé binaire |
| 0x2602 | 1 | wObtainedBadges |
Badges, un bit chacun dans l’ordre des arènes |
| 0x2605 | 2 | wPlayerID |
Identifiant de dresseur, 16 bits, fixé au lancement |
| 0x260A | 1 | wCurMap |
Identifiant de la carte courante |
| 0x260D | 1 | wYCoord |
Position Y du joueur, en pas de marche |
| 0x260E | 1 | wXCoord |
Position X du joueur, en pas de marche |
| 0x27E6 | 102 | wNumBoxItems |
Objets déposés au PC : nombre, puis paires (identifiant, quantité) |
| 0x284C | 1 | wCurrentBoxNum |
Boîte sélectionnée, sur les 7 bits de poids faible, à partir de 0 |
| 0x2852 | 32 | wToggleableObjectFlags |
Drapeaux du décor : un bit par objet au sol ou sprite escamotable |
| 0x299C | 14 | wObtainedHiddenItemsFlags |
Drapeaux des objets cachés, un bit par emplacement |
| 0x29F3 | 320 | wEventFlags |
Drapeaux d’événements : chaque dresseur battu, chaque action unique |
| 0x2CED | 5 | wPlayTimeHours |
Temps de jeu : heures, drapeau de saturation, minutes, secondes, images |
| 0x2F2C | 404 | wPartyCount |
Équipe : comptage, liste d’espèces, 6 structures, noms de dresseurs, surnoms |
| 0x30C0 | 1122 | wBoxCount |
La boîte du PC sélectionnée, copie de référence |
| 0x3523 | 1 | wMainDataCheckSum |
Somme de contrôle principale, sur 0x2598-0x3522 |
La somme de contrôle principale
La banque 1 est protégée par un octet unique en 0x3523. C’est le complément à
un de la somme de tous les octets de 0x2598 à 0x3522 inclus, tronquée à huit
bits :
somme = 0
pour adresse de 0x2598 à 0x3522 :
somme = (somme + octet[adresse]) & 0xFF
controle = (~somme) & 0xFF
Le jeu refuse une sauvegarde dont la somme ne tombe pas juste, et vous devriez en faire autant. C’est aussi pourquoi on ne modifie pas une sauvegarde en changeant un octet dans un éditeur hexadécimal : toute retouche dans cette plage oblige à recalculer cet octet.
Regardez bien ce que la plage couvre. Elle commence au nom du joueur et s’arrête juste avant la somme elle-même : elle inclut donc l’équipe et la boîte du PC sélectionnée — mais pas les onze autres, qui vivent dans leurs propres banques avec leurs propres sommes.
Les boîtes du PC
Les douze boîtes se répartissent sur deux banques : les boîtes 1 à 6 commencent
en 0x4000, les boîtes 7 à 12 en 0x6000. Chaque boîte occupe 0x462 octets,
disposés comme la région de l’équipe mais avec de la place pour vingt Pokémon au
lieu de six.
Chaque banque porte sa propre somme de contrôle, calculée comme la principale,
sur les six boîtes de la banque et rangée dans l’octet qui les suit
immédiatement — soit 0x4000 + 6 × 0x462 pour la première. Sur une sauvegarde
où le joueur n’a jamais ouvert le PC, ces banques ne sont pas initialisées et
leurs sommes ne tombent pas juste : il faut y lire « pas de boîtes ici » et non
« fichier corrompu ».
Un piège mérite d’être signalé. La boîte sélectionnée existe en
double : une fois dans sa banque, une fois en 0x30C0 dans la banque 1.
C’est la seconde qui fait foi. Le jeu ne réécrit la copie de banque qu’au
changement de boîte, si bien que sur une sauvegarde prise en cours de partie
les deux peuvent diverger, et c’est la copie de banque qui est périmée. Lisez
la boîte active — son numéro tient dans les sept bits de poids faible de
0x284C, plus un — depuis 0x30C0, et les onze autres depuis leurs banques.
Comment un Pokémon est rangé
Les régions de boîte et celle de l’équipe partagent une disposition : un octet
de comptage, une liste d’index d’espèces close par un terminateur 0xFF, les
structures, les noms des dresseurs d’origine, puis les surnoms. Chaque champ
de nom fait onze octets, rempli ou non.
La structure fait 33 octets en boîte et 44 dans l’équipe. Les 33 premiers sont identiques ; les onze octets supplémentaires de l’équipe contiennent les PV actuels, le statut, le niveau et les cinq statistiques calculées — que le jeu recalcule de toute façon. Les octets 5 et 6 sont les deux octets de type de l’espèce, copiés depuis ses statistiques de base — les valeurs qui indexent la table des types de première génération.
| Décalage | Octets | Champ |
|---|---|---|
| +0x00 | 1 | Espèce, sous forme d’index interne |
| +0x03 | 1 | Niveau, copie partagée — sert à restaurer un Pokémon en boîte |
| +0x08 | 4 | Identifiants des attaques, un octet chacun |
| +0x0E | 3 | Expérience, sur 24 bits |
| +0x11 | 10 | Expérience de stats : PV, Attaque, Défense, Vitesse, Spécial, 16 bits chacune |
| +0x1B | 2 | DV, quatre quartets : Attaque, Défense, Vitesse, Spécial |
| +0x21 | 1 | Niveau, équipe seulement — celui qui fait autorité |
Deux détails piègent régulièrement.
L’octet d’espèce n’est pas le numéro du Pokédex. La Gen 1 range un index
interne, héritage d’un ordre de développement sans rapport avec le Pokédex
national. Mew vaut 0x15, Bulbizarre 0x99. Il faut une table de
correspondance dans les deux sens ; le désassemblage la fournit dans
constants/pokemon_constants.asm.
Il y a deux octets de niveau. L’un en +0x03, dans les 33 octets partagés,
l’autre en +0x21, propre à l’équipe. C’est +0x21 qui fait autorité pour un
Pokémon de l’équipe, et +0x03 qui sert à restaurer un Pokémon sorti d’une
boîte. Écrivez les deux.
DV et expérience de statistiques
Les DV — les ancêtres Gen 1 des IV — sont rangés en quatre quartets sur deux octets
à partir de +0x1B : Attaque et Défense dans le premier, Vitesse et Spécial
dans le second, poids fort puis poids faible. Chacun va de 0 à 15.
Le DV de PV n’est stocké nulle part. Il se déduit du bit de poids faible des quatre autres :
dv_pv = ((atq & 1) << 3) | ((def & 1) << 2) | ((vit & 1) << 1) | (spe & 1)
D’où le fait qu’un Pokémon dont les quatre DV valent 15 a aussi un DV de PV parfait, et qu’on ne peut pas régler les PV indépendamment du reste.
L’expérience de statistiques — ce que les générations suivantes ont remplacé par
les EV — tient en cinq valeurs de 16 bits, poids fort en tête, à partir de +0x11,
dans l’ordre PV, Attaque, Défense, Vitesse, Spécial. Chacune monte à 65 535 et
apporte floor(ceil(sqrt(ev)) / 4) à la statistique calculée.
Le texte
La Gen 1 n’utilise pas l’ASCII, mais un encodage maison décrit dans
constants/charmap.asm :
0x80–0x99pourAàZ0xA0–0xB9pouraàz0xF6–0xFFpour0à90x7Fpour l’espace0x50termine une chaîne
Le reste, c’est la ponctuation et les glyphes propres au jeu : 0xE1 et 0xE2
forment les deux moitiés de la ligature Pk/Mn, 0xEF et 0xF5 sont les
symboles mâle et femelle, et deux codes distincts s’affichent tous deux comme un
point.
Un champ de nom fait onze octets terminateur compris, soit dix caractères utiles. Les octets qui suivent le terminateur contiennent ce qui s’y trouvait avant : ne les supposez pas remis à zéro.
Les cartouches non anglaises utilisent la même disposition. Une sauvegarde française, allemande ou espagnole range ses régions exactement aux mêmes adresses ; seul le texte diffère, ces ROM attribuant les caractères accentués à des codes que la table anglaise n’utilise pas. Les espèces étant numériques, un outil anglophone lit une sauvegarde française sans la moindre conversion. Seuls les noms ressortent abîmés, et seulement s’ils portent un accent.
Jaune ne fait pas exception : la comparaison de sram.asm entre les
désassemblages Rouge/Bleue et Jaune ne donne aucune différence. Un analyseur
écrit pour Rouge lit une sauvegarde Jaune sans la moindre modification.
Ce que la sauvegarde ne contient pas
Aucun champ n’indique quel jeu l’a écrite. Rien, dans une sauvegarde Gen 1, ne dit Rouge, Bleue ou Jaune. La chose surprend, et mieux vaut l’annoncer franchement : on peut y perdre beaucoup de temps.
On suggère en général de déduire la version du starter, mais le starter n’est pas rangé en tant que tel — seuls les Pokémon le sont, et quand une sauvegarde devient intéressante, le starter d’origine a pu être échangé, avoir évolué ou être rangé derrière onze autres Pokémon. Se fonder sur les drapeaux du Pokédex ne vaut pas mieux : une sauvegarde assez précoce pour être distinctive est une sauvegarde presque vide.
Pour distinguer deux sauvegardes, servez-vous du nom du dresseur associé à son
identifiant sur 16 bits, en 0x2605. Cet identifiant est fixé au lancement de
la partie et ne bouge plus jamais, ce qui fait du couple une identité fiable
pour une cartouche, valable pour toutes les sauvegardes qu’elle produira. C’est
ce que ce site utilise pour reconnaître à quelle cartouche appartient un import.
En vrac
L’argent occupe trois octets en décimal codé binaire en 0x25F3 : 0x00
0x99 0x99 vaut donc 9 999 ₽, et le jeu plafonne son affichage à 999 999 ₽.
Les badges tiennent dans un champ de bits en 0x2602, un bit par badge,
dans l’ordre des arènes : Roche, Cascade, Foudre, Prisme, Âme, Marais, Volcan,
Terre. Compter les bits à 1 donne le nombre de badges affiché sur la carte de
dresseur.
Le Pokédex occupe deux champs de bits de dix-neuf octets — les Pokémon
possédés en 0x25A3, ceux vus en 0x25B6. Le bit n de l’octet m désigne le
numéro m × 8 + n + 1, poids faible en premier. Dix-neuf octets offrent 152 bits
pour 151 espèces : le bit de poids fort du dernier octet ne sert pas. Un Pokémon
peut être vu sans être possédé, l’inverse n’a pas de sens, et le jeu imprime
volontiers un diplôme dès que tous les bits « possédé » sont mis, quelle que
soit la manière dont ils y sont arrivés — c’est précisément ce qui rend
possibles les 151 sur une seule cartouche,
alors qu’aucune version ne permet de tous les attraper.
Le temps de jeu occupe cinq octets en 0x2CED : les heures, un drapeau
signalant le compteur saturé, puis les minutes, les secondes et les images.
Votre position tient dans l’identifiant de carte en 0x260A et les
coordonnées en 0x260D et 0x260E, comptées en pas de seize pixels depuis le
coin supérieur gauche de la carte courante, et non en pixels.