- TheZZAZZGlitch zeigt, dass sich durch das Aufzeichnen von Crash-Sounds des Game Boy Advance die Spieldaten in einer Cartridge identifizieren und schließlich dasselbe ROM rekonstruieren lassen
- Der Kern besteht darin, den nach dem Absturz ausgegebenen Ton als ROM-Daten zu interpretieren; wegen vieler nötiger Anpassungen je nach Quellformat ist das aber schwer als allgemeines Dumping-Tool nutzbar
- In einer mehr als vierstündigen Aufnahme erschien nach etwa 1 Stunde und 50 Minuten eine charakteristische Wellenform; anschließend waren nacheinander die Instrumentenklänge und Audio-Samples des Spiels zu hören
- Mit Python-Skripten und Korrekturen der Ausrichtung wurden bis zu 99,76 % Genauigkeit erreicht, das ROM bootete jedoch nicht; durch Zusammenführen von drei Aufnahmen per Mehrheitsalgorithmus stieg der Wert auf 99,979 %
- Nach dem Zusammenführen von sieben Aufnahmen und dem Filtern leerer Bereiche wurde eine 100%ige Übereinstimmung erzielt; damit wurde experimentell bestätigt, dass sich ein GBA-ROM allein aus Crash-Sounds rekonstruieren lässt
Experiment: ROM-Daten aus Crash-Sounds auslesen
- TheZZAZZGlitch demonstriert, dass die Geräusche, die ein GBA nach einem Software-Crash ausgibt, Spieldaten enthalten können
- Ein abgestürzter GBA kann weiterhin Töne ausgeben, die auf den Daten in der Cartridge basieren; mit spezieller Hardware und Code lässt sich dieses Audio analysieren und das Spiel identifizieren
- Diese Methode ist allerdings keine einfache Möglichkeit, Cartridge-Daten zu dumpen, und auch keine sofort einsetzbare Lösung
- Sie erfordert viel Tuning für unterschiedliche Quellformate
Wellenform in einer langen Aufnahme sichtbar
- Nachdem der GBA zum Absturz gebracht worden war, wurde über 4 Stunden lang aufgenommen; nach etwa 1 Stunde und 50 Minuten erschien eine charakteristische Wellenform
- In den folgenden Abschnitten waren die tatsächlich im Spiel enthaltenen Instrumentenklänge und Audio-Samples der Reihe nach zu hören
- Die übrigen Daten klingen wie 8-Bit-Daten mit 13.100 Hz, wobei manche Passagen sehr seltsam klingen
Python-Skript und erster Rekonstruktionsversuch
- TheZZAZZGlitch erstellte nach „2 Tagen Bugfixing“ ein Python-Skript, das saubere Aufnahmen eines GBA-Crash-Dumps einlesen kann
- In den ROM-Daten gibt es große Bereiche mit Null-Bytes; diese erscheinen wie Stille und sind aus dem Audio schwer zu parsen
- Nach dem Ausführen eines separaten Skripts, das die Abschnitte anhand ihrer Position im Original-ROM neu ausrichtete, erreichte das rekonstruierte ROM 99,76 % Genauigkeit
- Dieses ROM bootete weiterhin nicht, und da bekannte ROM-Daten genutzt wurden, um unbekannte Daten offenzulegen, zählt das technisch gesehen als „Cheating“
- Auch bei einem vollständig blinden Vorgehen bleiben jedoch Annahmen und Schätzungen, die sich anwenden lassen
Genauigkeit durch Zusammenführen mehrerer Aufnahmen erhöhen
- Im nächsten Schritt lag der Fokus auf der Verbesserung der Aufnahmequalität
- Durch Zusammenführen von drei Aufnahmen mit einem „Mehrheits“-Algorithmus stieg die Genauigkeit auf 99,979 %
- Dieses Ausgabe-ROM bootete zwar, zeigte aber beschädigten Text und stürzte auf dem Titelscreen ab
- Nach dem Kombinieren von sieben Aufnahmen und dem Filtern leerer Bereiche wurde eine 100%ige Übereinstimmung erreicht
Physische Hardware und weitere Experimente
- Im späteren Teil des Videos wird geprüft, wie diese Methode auf physischer Hardware funktioniert
- Es werden auch Experimente mit anderen Spielen durchgeführt und ein Rätsel rund um ARM-Code in einer Repro-Cartridge verfolgt
- Zudem wurden Wege ausprobiert, bessere Aufnahmen zu erhalten
- Einer davon ist die Nutzung eines „cursed adapter“, der grob auf einen Kanal heruntermischt
1 Kommentare
Kommentare auf Hacker News
Das Problem bei langen Folgen von 0x00 hat mit Clock Recovery zu tun.
Manche digitalen Datenströme, insbesondere Rohdaten von Magnetköpfen in Laufwerken oder serielle Hochgeschwindigkeitskommunikation wie Ethernet, werden ohne separates Taktsignal übertragen.
Der Empfänger erzeugt anhand einer groben Frequenzreferenz einen Takt und richtet die Taktphase mit einer Phasenregelschleife (PLL) an den Übergängen im Datenstrom aus.
Damit das funktioniert, müssen Datenübergänge häufig genug auftreten, um die Drift des PLL-Oszillators zu korrigieren; die Angabe dazu, wie lange man ohne Übergänge auskommt, nennt sich maximale Consecutive Identical Digits (CID).
https://en.wikipedia.org/wiki/Clock_recovery
Später wechselte man zu Verfahren wie 64/66b, bei denen große Bitblöcke mit einem kurzen Header versehen werden, um Taktübergänge zu garantieren, und das Ganze durch einen Pseudozufalls-Scrambler läuft.
Selbst wenn der Takt perfekt synchronisiert ist, werden über lange Abschnitte ein Signal, das fast nur aus Einsen besteht, und eines, das fast nur aus Nullen besteht, am Ende gleich.
Audio ist analog, zum Dekodieren als Bitstream braucht man einen DAC, und es wird ohne besondere Synchronisation mit einer festen Frequenz wie 44,1 kHz oder 48 kHz übertragen.
https://en.wikipedia.org/wiki/Wireless_Set_Number_10
Das erinnert mich an den ursprünglichen iPodLinux-Hack, bei dem vor fast 20 Jahren die Firmware eines iPod der 4. Generation über den Piezo-Lautsprecher gedumpt wurde.
https://web.archive.org/web/20140810083116/http://www.newscientist.com/article/dn7085
Zufällig konnte man dadurch auch GBA-Spiele auf dem iPod laufen lassen, aber Doom mit dem Click Wheel zu spielen und Schwarzweißvideos anzusehen, war schon zufriedenstellend genug.
Ich habe immer noch einen iPod Classic, habe den Akku aufgerüstet und vier 256-GB-MicroSD-Karten eingebaut.
Kürzlich habe ich auch einen Mod gesehen, der Bluetooth hinzufügt, aber dafür müsste man das Rückgehäuse austauschen, so weit werde ich wohl nicht gehen.
Sowohl das Design als auch die Tatsache, dass man eigene Kopien seiner Musikdateien besitzt, haben etwas Zeitloses.
Schön, dass das hier mehr Aufmerksamkeit bekommt.
Es wurde schon vor ein paar Tagen gepostet, ging aber unter: https://news.ycombinator.com/item?id=39037104
Das Originalvideo enthält vieles, was in diesem kurzen Beitrag fehlt, darunter auch einen maßgeschneiderten Adapter, den der Hacker selbst zurechtgeschnitten und zusammengebaut hat, um aus dem DS eine brauchbare Audioqualität herauszuholen.
https://www.youtube.com/watch?v=0-7PSmYYHF0
Zzazz veranstaltet jedes Jahr einen Aprilscherz-Wettbewerb bzw. ein Event, bei dem üblicherweise ein gewisses Maß an Retro-Hacking oder Reverse Engineering vorkommt.
Teilnahme empfohlen.
Die vergangenen Wettbewerbe sind auf GitHub zu finden.
Nintendos Audioarchitektur fand ich immer interessant.
Schon das ursprüngliche NES hatte einen Sample-Generator, der beliebige Wellenformen erzeugen konnte und auf zwei Arten angesteuert werden konnte.
Bei der einen Methode übergab man eine Speicheradresse, woraufhin Bits gelesen und als sehr einfache Wellenform verarbeitet wurden: Eine 1 bedeutete „Wert um eins erhöhen“, eine 0 „Wert um eins verringern“, sodass man für eine flache Wellenform etwas wie 10101010 wiederholen musste.
Bei der anderen Methode schrieb die CPU ständig direkt einen „Startwert“ hinein und steuerte den Chip damit unmittelbar; in der Praxis war das schneller, als wenn der Audiotreiber Bits aus dem RAM las.
Das Problem war, dass diese Methode sämtliche CPU-Zyklen verschlang und daher nur genutzt werden konnte, wenn sonst nichts anderes lief.
Spiele wie Battletoads nutzten das, um während angehaltener Action höherwertige Drum-Hits abzuspielen; es wurde auf dem Titelbildschirm, für den „knackigen“ Effekt, bei dem kurz alle Action stoppt, wenn man einem Gegner den letzten Treffer verpasst, und für die einprägsame Pausenmusik verwendet.
Hier gibt es eine Demo, in der das Spiel zwischen dem Direct-Drive-Modus und dem Modus umschaltet, in dem der Chip Samples liest. Retro Game Audio hat ein mit einem Emulator bearbeitetes Video hochgeladen, das den Moment zeigt, in dem die Direct-Drive-Subroutine betreten wird: https://www.youtube.com/watch?v=JGT0FM3yh-w
Ich frage mich, warum so etwas überhaupt passiert.
Ist es üblich, dass solche Spiele ihren Zustand als Audio dumpen? Ist das ein absichtliches Debugging-Tool für Spieleentwickler?
Im Grunde streamt der GBA-Sound Audio aus einem Puffer im RAM, und ein Interrupt muss der Hardware mitteilen, dass sie wieder am Anfang des Puffers lesen soll.
Wenn aber kein Interrupt auftritt, etwa wenn das Spiel abgestürzt ist, liest der Audiostream über den Puffer hinaus in andere Speicherbereiche.
[1] https://www.youtube.com/watch?v=wSWNkpqjtQY&t=361s
Theoretisch hätte der GBA die Architektur beim Absturz eines Spiels „anhalten“ können, oder einen Watchdog haben können, der regelmäßig auszuführende Zustandsaktualisierungen an einen nicht maskierbaren Interrupt koppelt und neu startet, wenn diese Aktualisierung ausbleibt.
Solche Funktionen hätten aber mehr gekostet, deshalb hat der GBA sie nicht.
Nintendo hat sich im Grunde für den traditionellen Ansatz alter Hersteller von Spiele-Cartridges entschieden: „Wenn unser Spiel keine Bugs hat, müssen wir uns auch nicht um das Verhalten undefinierter Hardwarezustände kümmern.“
Wenn ein GBA-Spiel also in einen Crash-Zustand wie eine Endlosschleife mit deaktivierten Interrupts gerät, weiß der Audiochip nicht, dass das System abgestürzt ist, und macht einfach weiter seine simple Arbeit: fortlaufende Bits aus dem RAM lesen und in Ton umwandeln.
Die Aufräumroutine, die im Normalbetrieb die Lesevorgänge verwalten würde, ist dann weg, sodass weitergelesen wird, bis schließlich auch Bits erreicht werden, die Werte aus dem Cartridge-ROM repräsentieren.
Wirklich absurd beeindruckend.
Techniken wie der hier verwendete Mehrheitsentscheidungs-Algorithmus werden vermutlich in vielen Branchen noch viel zu wenig genutzt.
Magnetische Speichermedien funktionieren im Prinzip nach demselben Prinzip wie dieser Hack.
https://en.wikipedia.org/wiki/Partial-response_maximum-likelihood
Dieselbe Idee ließe sich auch hier anwenden, weil der Inhalt eines GBA-ROMs stark voreingenommen sein dürfte.
Mehrheitsentscheidungen verschwenden viele Informationen.
Man legt alle Fotos übereinander und behält für jedes Pixel nur den Medianwert[1].
[1]: https://patdavid.net/2013/05/noise-removal-in-photos-with-median_6/
Man liest ein Disk-Image immer wieder aus und lässt eine Quorumsentscheidung laufen, bis ein Ergebnis herauskommt, das die Prüfsumme besteht, und schaut dann, ob es korrekt funktioniert.
Wenn es Prüfsummen auf höherer Ebene gibt, etwa Dateisignaturen, ist das für zusätzliche Verifikation noch besser.
In einigen Anwendungen der Luft- und Raumfahrt wird das ebenfalls eingesetzt.
Da man dort nicht mit einem makellosen Master arbeitet, sondern mit möglicherweise beschädigten Kinokopien, könnte die Nutzung mehrerer Kopien zum Entfernen von Kratzern usw. die Zeit für manuelle Nachbearbeitung enorm reduzieren.
Dass 0xFF zu 0x00 wird, könnte an einem Gleichstrom-Sperrkondensator oder an Hochpassfilterung liegen.
Audioschaltungen sind für nicht hörbare Inhalte nicht besonders geeignet.
Mit etwas Glück ließe sich die Erfassungsgenauigkeit verbessern, wenn man ein digitales Oszilloskop direkt an den Audioausgang des Chips anschließt; trotzdem ist es ziemlich beeindruckend, dass daraus ein bootfähiges Image entstanden ist.
Deshalb wurden statt eines ordentlichen Datenlogging-Oszilloskops über Stunden wiederholte Captures gemacht, um die Fehler herauszumitteln.
Schon etwas Einfaches wie Manchester-Codierung hilft enorm.
Wenn das nicht reicht, wären NRZ oder sogar Faltungscodierung möglich.
Außerdem sollte man eine Sinuswelle senden – oder, falls das nicht geht, zumindest die Frequenz der Rechteckwelle hoch genug wählen, damit sie nicht vom AC-Koppelkondensator verschluckt wird.
Das Beeindruckendste an alledem ist für mich persönlich, wie die Raubkopierer den Code so geändert haben, dass das Spiel aus beschreibbarem Flash läuft statt aus ROM plus flüchtigem Speichermedium.
Tatsächlich ist es gar nicht so schwer, solche Patches zu erstellen.
Die Raubkopierer haben ein wenig reverse-engineered, wohin der Spielcode speichert, und dann spielspezifische Patches geschrieben, die die Speicherstände in beschreibbares Flash flushen.
Offizielle GBA-Spiele verwenden zum Speichern allerdings immer Funktionen aus dem Nintendo SDK; wenn man diese Funktionen hookt, wird ein universeller Patch, der beliebige GBA-Spiele auch auf batterielosen Klon-Cartridges speichern lässt, ziemlich einfach.
Ich habe einen Patcher dafür geschrieben, hier zu finden:
https://github.com/metroid-maniac/gba-auto-batteryless-patcher
Weiß jemand, was intern passiert, wenn TheZZAZZGlitchs Emulator meldet, dass das Spiel versucht, zu einer ungültigen Adresse zu springen?
Ich bin mit dem ARM7-Prozessor im GameBoy Advance nicht vertraut, kann mir aber kaum vorstellen, wie man einen Jump-Aufruf auf einen ungültigen Wert zusammenbauen kann.
Außerdem frage ich mich, was passieren würde, wenn man eines der fehlerhaft wiederhergestellten ROMs von TheZZAZZGlitch auf einem echten GameBoy ausführt.
bxkann man zu einer beliebigen Adresse springen, die in einem Register gespeichert ist.Und wenn man ein fehlerhaft wiederhergestelltes ROM auf einem echten GameBoy ausführt, stürzt es ab und beginnt schließlich, das ROM über den Lautsprecher abzuspielen.
Genau darum geht es im Video. :)
Was auf echter Hardware passieren würde … wer weiß. :)