Un moddeur restaure une ROM de jeu à partir du son de crash d’une GBA
(arstechnica.com)- TheZZAZZGlitch montre qu’en enregistrant le son de crash d’une Game Boy Advance, il est possible d’identifier les données de jeu contenues dans la cartouche et, au final, de restaurer la même ROM
- Le principe consiste à interpréter l’audio émis après le crash comme des données de ROM, mais cela nécessite de nombreux ajustements selon le format source, ce qui rend l’approche difficile à utiliser comme outil de dump universel
- Sur plus de 4 heures d’enregistrement, une forme d’onde caractéristique apparaît vers 1 h 50, puis les sons d’instruments et les échantillons audio du jeu se font entendre successivement
- Avec un script Python et une correction d’alignement, il atteint 99,76 % de précision, mais la ROM ne démarre pas ; en fusionnant 3 enregistrements avec un algorithme de vote majoritaire, la précision monte à 99,979 %
- Après fusion de 7 enregistrements et filtrage des espaces vides, il obtient une correspondance à 100 %, confirmant la possibilité expérimentale de restaurer une ROM GBA uniquement à partir du son de crash
Une expérience qui lit les données ROM dans le son de crash
- TheZZAZZGlitch démontre que le son émis par une GBA après un crash logiciel peut contenir des données de jeu
- Une GBA crashée peut continuer à produire des sons basés sur les données internes de la cartouche, et l’analyse de cet audio avec du matériel et du code spécialisés permet d’identifier de quel jeu il s’agit
- Cette méthode n’est toutefois pas un moyen simple de dumper les données d’une cartouche, ni une solution prête à l’emploi
- Elle demande beaucoup de réglages adaptés aux différents formats sources
Une forme d’onde révélée dans un long enregistrement
- Après avoir fait crasher la GBA et enregistré pendant plus de 4 heures, une forme d’onde caractéristique apparaît vers 1 h 50
- Dans les segments suivants, on entend dans l’ordre de véritables sons d’instruments et échantillons audio inclus dans le jeu
- Le reste des données s’entend comme des données 8 bits à 13 100 Hz, avec certains passages au rendu très étrange
Script Python et première tentative de restauration
- TheZZAZZGlitch prépare, « après 2 jours de correction de bugs », un script Python capable de lire un enregistrement propre d’un dump de crash de GBA
- Les données de la ROM contiennent de grandes zones d’octets nuls, qui apparaissent comme du silence et sont difficiles à parser depuis l’audio
- Après avoir exécuté un script séparé pour réaligner les sections selon leur position dans la ROM d’origine, la ROM restaurée atteint 99,76 % de précision
- Cette ROM ne démarre toujours pas, et la méthode, qui utilise des données de ROM connues pour révéler les données inconnues, relève techniquement de la « triche »
- Même en procédant entièrement à l’aveugle, certaines hypothèses et estimations resteraient applicables
Fusionner plusieurs enregistrements pour améliorer la précision
- L’étape suivante se concentre sur l’amélioration de la qualité d’enregistrement
- En fusionnant 3 enregistrements avec un algorithme de « vote majoritaire », la précision monte à 99,979 %
- La ROM produite parvient à démarrer, mais le texte est corrompu et un crash survient sur l’écran titre
- En combinant ensuite 7 enregistrements et en filtrant les espaces vides, il obtient une correspondance à 100 %
Matériel physique et expériences supplémentaires
- Dans la seconde moitié de la vidéo, il vérifie aussi comment cette méthode fonctionne sur du matériel physique
- Il expérimente également avec d’autres jeux, tout en enquêtant sur un mystère lié au code ARM présent dans une cartouche clone
- Des méthodes pour obtenir de meilleurs enregistrements sont également essayées
- L’une d’elles consiste à utiliser un « cursed adapter » qui effectue un mixdown grossier sur un seul canal
1 commentaires
Avis de Hacker News
Le problème lorsque 0x00 se répète longuement est lié à la récupération d’horloge (clock recovery)
Certains flux de données numériques, en particulier les données brutes des têtes magnétiques de lecteurs de disque ou les communications série à haut débit comme Ethernet, sont transmis sans signal d’horloge séparé
Le récepteur crée une horloge à partir d’une référence de fréquence approximative, puis aligne la phase de cette horloge sur les transitions du flux de données au moyen d’une boucle à verrouillage de phase (PLL)
Pour que cette méthode fonctionne, les transitions de données doivent se produire assez souvent pour corriger la dérive de l’oscillateur de la PLL ; la durée pendant laquelle on peut tenir sans transition est appelée dans la spécification nombre maximal consécutif identique (CID)
https://en.wikipedia.org/wiki/Clock_recovery
Par la suite, on est passé à des méthodes comme le 64/66b, qui ajoutent un court en-tête à de gros blocs de bits pour garantir des transitions d’horloge, puis font passer l’ensemble dans un brouilleur pseudo-aléatoire
Même avec une horloge parfaitement synchronisée, sur de longues séquences, un signal presque entièrement composé de 1 et un signal presque entièrement composé de 0 finissent par devenir identiques
L’audio est analogique, il faut un DAC pour le décoder en flux binaire, et il est transmis à une fréquence fixe comme 44,1 kHz ou 48 kHz, sans synchronisation particulière
https://en.wikipedia.org/wiki/Wireless_Set_Number_10
Cela me rappelle le hack iPodLinux original, il y a près de 20 ans, qui avait dumpé le firmware de l’iPod de 4e génération via le haut-parleur piézoélectrique
https://web.archive.org/web/20140810083116/http://www.newscientist.com/article/dn7085
Par coïncidence, cela a ensuite aussi permis de faire tourner des jeux GBA sur iPod, mais jouer à Doom avec la click wheel et regarder des vidéos en noir et blanc était déjà largement satisfaisant
J’ai encore un iPod Classic, et après avoir amélioré la batterie, j’y ai mis quatre cartes MicroSD de 256 Go
J’ai récemment vu un mod qui ajoute le Bluetooth, mais comme il faut remplacer la coque arrière, je ne pense pas aller jusque-là
Il y a quelque chose d’intemporel dans son design, et aussi dans le fait de posséder directement des copies de ses fichiers musicaux
Content que cela reçoive davantage d’attention ici
C’était déjà passé il y a quelques jours, mais c’était passé inaperçu : https://news.ycombinator.com/item?id=39037104
La vidéo originale contient beaucoup d’éléments absents de ce court article, dont un adaptateur sur mesure bricolé par le hacker lui-même pour obtenir une qualité audio correcte sur la DS
https://www.youtube.com/watch?v=0-7PSmYYHF0
Zzazz organise chaque année un concours/événement du 1er avril, qui implique généralement une certaine dose de hacking rétro ou de rétro-ingénierie
Je recommande d’y participer
Les éditions précédentes sont sur GitHub
L’architecture audio de Nintendo m’a toujours paru intéressante
À l’origine, la NES avait un générateur d’échantillons capable de produire des formes d’onde arbitraires, et il pouvait être piloté de deux façons
L’une consistait à lui fournir une adresse mémoire : il lisait les bits et les traitait comme une forme d’onde très simple, où 1 signifiait « augmenter la valeur de un » et 0 « diminuer la valeur de un », si bien que pour produire une forme d’onde plate, il fallait répéter quelque chose comme 10101010
L’autre consistait à ce que le CPU fournisse directement en continu une « valeur initiale » pour piloter la puce, ce qui, en pratique, était plus rapide que de faire lire les bits en RAM par le pilote audio
Le problème, c’est que cette méthode accaparait tous les cycles CPU et ne pouvait donc être utilisée que lorsque rien d’autre ne se passait
Des jeux comme Battletoads s’en servaient pour jouer des coups de batterie de meilleure qualité pendant que l’action était à l’arrêt : sur l’écran-titre, lors de l’effet « croustillant » où toute l’action s’interrompt brièvement au moment de porter le coup final à un ennemi, et dans la mémorable musique de pause
Voici une démo dans laquelle le jeu bascule entre le mode de pilotage direct et le mode où la puce lit les échantillons. Retro Game Audio a publié une vidéo modifiée avec un émulateur, qui montre le moment où l’on entre dans la sous-routine de pilotage direct : https://www.youtube.com/watch?v=JGT0FM3yh-w
Je me demande pourquoi ce genre de chose arrive à la base
Est-ce courant que ces jeux « déversent » leur état sous forme audio ? Est-ce un outil de débogage intentionnel pour les développeurs de jeux ?
En gros, le son de la GBA streame l’audio depuis un tampon en RAM, et une interruption doit indiquer au matériel de relire depuis le début du tampon
Mais si l’interruption ne se produit pas, comme quand le jeu plante, le flux audio dépasse le tampon et se met à lire d’autres zones de la mémoire
[1] https://www.youtube.com/watch?v=wSWNkpqjtQY&t=361s
En théorie, la GBA aurait pu « arrêter » l’architecture quand un jeu plante, ou avoir un watchdog qui lie une mise à jour d’état devant s’exécuter périodiquement à une interruption non masquable et redémarre si cette mise à jour s’arrête
Mais ce genre de fonction aurait coûté plus cher, donc la GBA n’en a pas
Nintendo a en quelque sorte choisi l’approche traditionnelle des anciens fabricants de cartouches de jeu : « si notre jeu n’a pas de bug, nous n’avons pas à nous soucier du comportement d’un état matériel indéfini »
Ainsi, quand un jeu GBA se retrouve dans un état de plantage comme une boucle infinie avec les interruptions désactivées, la puce audio ne sait pas que le système a planté et continue simplement à lire des bits consécutifs de la RAM pour les convertir en son
Comme les routines de nettoyage qui géraient les lectures en fonctionnement normal ont disparu, elle continue à lire jusqu’à finir par atteindre les bits représentant les valeurs de la ROM de la cartouche
C’est vraiment absurdement impressionnant
J’ai l’impression que des techniques comme l’algorithme de vote majoritaire utilisé ici sont probablement sous-exploitées dans de nombreux secteurs
Les supports de stockage magnétiques fonctionnent fondamentalement sur le même principe que ce hack
https://en.wikipedia.org/wiki/Partial-response_maximum-likelihood
On pourrait appliquer la même idée ici, puisque le contenu d’une ROM GBA aura de forts biais
Le vote majoritaire gaspille beaucoup d’informations
Il suffit de superposer toutes les photos puis de ne garder que la médiane pour chaque pixel[1]
[1]: https://patdavid.net/2013/05/noise-removal-in-photos-with-median_6/
On lit l’image disque en boucle et on applique une décision par quorum, puis quand on obtient un résultat qui passe la somme de contrôle, on regarde si ça fonctionne correctement
S’il existe des sommes de contrôle de plus haut niveau, comme des signatures de fichiers, c’est encore mieux pour une validation supplémentaire
C’est aussi utilisé dans certaines applications aérospatiales
Comme on travaille avec des copies d’exploitation potentiellement endommagées plutôt qu’avec un master pristine, utiliser plusieurs exemplaires pour supprimer les rayures et autres défauts pourrait réduire énormément le temps de retouche manuelle en postproduction
Le fait que 0xFF devienne 0x00 peut être dû à un condensateur de blocage du courant continu ou à un filtrage passe-haut
Les circuits audio ne sont pas vraiment adaptés aux contenus non audibles
Avec un peu de chance, connecter directement un oscilloscope numérique à la sortie audio de la puce améliorerait la précision de la capture, mais obtenir malgré tout une image amorçable reste assez impressionnant
C’est pour ça qu’il a passé des heures à répéter les captures pour moyenner les erreurs, au lieu d’utiliser un véritable oscilloscope d’acquisition de données
Même un schéma simple comme le codage Manchester aiderait beaucoup
Si ça ne suffit pas, du NRZ, voire un codage convolutif, est aussi possible
Il faut aussi envoyer une sinusoïde, ou à défaut au moins rendre la fréquence de l’onde carrée assez élevée pour ne pas être avalée par le condensateur de couplage AC
Dans tout ça, ce qui m’impressionne le plus personnellement, c’est la manière dont les pirates ont modifié le code pour exécuter les jeux depuis une mémoire flash inscriptible au lieu d’une ROM + mémoire volatile de sauvegarde
En fait, créer ce genre de patch n’est pas si difficile
Les pirates rétro-ingénierent légèrement l’endroit où le code du jeu sauvegarde, puis écrivent un patch propre à chaque jeu pour flusher les sauvegardes vers la flash inscriptible
Cela dit, les jeux GBA officiels utilisent toujours les fonctions du SDK Nintendo pour sauvegarder ; en hookant ces fonctions, il devient assez simple de créer un patch universel qui permet de sauvegarder n’importe quel jeu GBA sur une cartouche clone sans batterie
J’ai écrit un patcheur qui fait ça, visible ici
https://github.com/metroid-maniac/gba-auto-batteryless-patcher
Quelqu’un sait ce qui se passe en interne quand l’émulateur de TheZZAZZGlitch signale que le jeu essaie de sauter à une mauvaise adresse ?
Je ne connais pas bien le processeur ARM7 utilisé dans la Game Boy Advance, mais j’ai du mal à imaginer comment il est possible de construire un appel de saut vers une valeur invalide
Je me demande aussi ce qui se passerait si l’une des ROM mal restaurées par TheZZAZZGlitch était exécutée sur une vraie Game Boy
bxpermet de sauter vers une adresse arbitraire stockée dans un registreEt si on exécute la ROM mal restaurée sur une vraie Game Boy, elle plantera, puis finira par commencer à jouer la ROM dans le haut-parleur
C’est tout l’intérêt de la vidéo :)
Sur le vrai matériel, ce qui se passerait… qui sait :)