1 puntos por GN⁺ 2024-01-23 | 1 comentarios | Compartir por WhatsApp
  • TheZZAZZGlitch demostró que, al grabar el sonido de cuelgue de una Game Boy Advance, se pueden identificar los datos del juego dentro del cartucho y, finalmente, restaurar la misma ROM
  • La clave es interpretar el audio emitido tras el cuelgue como datos de la ROM, pero requiere muchos ajustes según el formato de origen, por lo que es difícil usarlo como una herramienta universal de volcado
  • En una grabación de más de 4 horas apareció una forma de onda característica alrededor de 1 hora y 50 minutos, y luego se escucharon secuencialmente los sonidos de instrumentos y muestras de audio del juego
  • Con un script en Python y correcciones de alineación alcanzó una precisión del 99.76%, pero no logró arrancar; al fusionar 3 grabaciones con un algoritmo de voto mayoritario, mejoró hasta 99.979%
  • Tras fusionar 7 grabaciones y filtrar espacios vacíos, logró una coincidencia del 100%, confirmando la posibilidad experimental de restaurar una ROM de GBA usando solo el sonido del cuelgue

Experimento para leer datos de ROM desde el sonido de un cuelgue

  • TheZZAZZGlitch demostró que el sonido que emite una GBA después de un cuelgue de software puede contener datos del juego
  • Una GBA colgada puede seguir produciendo sonido basado en los datos internos del cartucho y, si se analiza ese audio con hardware y código especiales, es posible identificar de qué juego se trata
  • Sin embargo, este método no es una forma sencilla de volcar los datos del cartucho ni una solución lista para usar
    • Requiere muchos ajustes adaptados a distintos formatos de origen

La forma de onda revelada en una grabación larga

  • Tras provocar un cuelgue en la GBA y grabar durante más de 4 horas, apareció una forma de onda característica alrededor de 1 hora y 50 minutos
  • En los tramos posteriores se escuchan, en orden, los sonidos de instrumentos y muestras de audio reales incluidos en el juego
  • El resto de los datos suena como datos de 8 bits a 13,100 Hz, y algunas secciones suenan muy extrañas

Script en Python y primer intento de restauración

  • TheZZAZZGlitch preparó un script en Python que lee una grabación limpia de volcado por cuelgue de GBA “después de corregir bugs durante 2 días”
  • En los datos de la ROM existen grandes secciones de bytes en cero, y esas partes aparecen como silencio, lo que dificulta parsearlas desde el audio
  • Después de ejecutar otro script que realinea las secciones según su posición en la ROM original, la ROM restaurada alcanzó una precisión del 99.76%
  • Esta ROM todavía no arrancaba, y como el método usa datos conocidos de la ROM para revelar los datos desconocidos, técnicamente equivale a “hacer trampa”
    • Incluso si se realizara de forma completamente a ciegas, seguirían existiendo supuestos e inferencias aplicables

Aumentar la precisión fusionando varias grabaciones

  • En la siguiente etapa se concentró en mejorar la calidad de la grabación
  • Al fusionar los resultados de 3 grabaciones con un algoritmo de “voto mayoritario”, la precisión subió hasta 99.979%
  • Esa ROM de salida logró arrancar, pero el texto aparecía corrupto y se producía un crash en la pantalla de título
  • Más adelante, al combinar 7 grabaciones y filtrar espacios vacíos, logró una coincidencia del 100%

Hardware físico y experimentos adicionales

  • En la parte final del video también se verifica cómo funciona este método en hardware físico
  • También se experimenta con otros juegos y se investiga un misterio relacionado con código ARM dentro de un cartucho clon
  • Además, se probaron métodos para obtener mejores grabaciones
    • Uno de ellos fue usar un “cursed adapter” que hace un mixdown tosco a un solo canal

1 comentarios

 
GN⁺ 2024-01-23
Opiniones en Hacker News
  • El problema cuando hay una larga secuencia de 0x00 está relacionado con la recuperación de reloj (clock recovery).
    Algunos flujos de datos digitales, especialmente los datos en crudo del cabezal magnético de una unidad de disco o las comunicaciones seriales de alta velocidad como Ethernet, se transmiten sin una señal de reloj separada.
    El receptor crea un reloj a partir de una referencia de frecuencia aproximada y, mediante un bucle de enganche de fase (PLL), ajusta la fase del reloj a las transiciones del flujo de datos.
    Para que este método funcione, las transiciones de datos deben aparecer con suficiente frecuencia como para corregir la deriva del oscilador del PLL, y la especificación de cuánto tiempo puede aguantar sin transiciones se llama máximo de dígitos idénticos consecutivos (CID).
    https://en.wikipedia.org/wiki/Clock_recovery

    • Antes era bueno que se garantizara la posibilidad de recuperar el reloj y se evitaran los problemas de capacitancia de la línea mediante un ingenioso método de codebook, como 8b/10b, que manejaba con cuidado intervalos cortos de bits.
      Después se pasó a métodos como 64/66b, que agregan un encabezado corto a bloques grandes de bits para garantizar transiciones de reloj y luego pasan todo por un scrambler seudoaleatorio.
    • Otra preocupación es cuando alguna parte de la forma de onda está acoplada en CA (AC coupling) y no deja pasar la corriente continua.
      Aunque el reloj esté perfectamente sincronizado, en tramos largos una señal compuesta casi por completo de 1 y una compuesta casi por completo de 0 terminan volviéndose iguales.
    • En este caso no parece ser muy relevante.
      El audio es analógico y, para decodificarlo como bitstream, se necesita un DAC; además se transmite a una frecuencia fija como 44,1 kHz o 48 kHz, sin sincronización especial.
    • En esa página encontré un artículo muy interesante llamado Wireless Set Number 10.
      https://en.wikipedia.org/wiki/Wireless_Set_Number_10
  • Me recuerda al hack original de iPodLinux, que hace casi 20 años volcó el firmware de un iPod de 4.ª generación usando un parlante piezoeléctrico.
    https://web.archive.org/web/20140810083116/http://www.newscientist.com/article/dn7085
    Casualmente, gracias a eso también se pudieron correr juegos de GBA en el iPod, aunque jugar Doom con la click wheel y ver videos en blanco y negro ya era bastante satisfactorio.

    • Qué buenos recuerdos.
      Todavía tengo un iPod Classic y, después de mejorarle la batería, le puse cuatro tarjetas MicroSD de 256 GB.
      Hace poco también vi una modificación para agregar Bluetooth, pero requiere cambiar la carcasa trasera, así que creo que no llegaré tan lejos.
      Hay algo atemporal tanto en el diseño como en el hecho de poseer directamente copias de los archivos de música.
  • Me alegra que esto reciba más atención aquí.
    También se publicó hace unos días, pero quedó enterrado: https://news.ycombinator.com/item?id=39037104
    El video original tiene mucho contenido que no aparece en este breve artículo, incluido un adaptador personalizado que el hacker armó cortando y pegando por su cuenta para obtener una calidad de audio adecuada desde la DS.

  • Zzazz organiza todos los años un concurso/evento del Día de los Inocentes y normalmente incluye cierto grado de hacking retro o ingeniería inversa.
    Recomiendo participar.
    Los concursos anteriores están en GitHub.

  • La arquitectura de audio de Nintendo siempre me pareció interesante.
    La NES original tenía un generador de muestras capaz de producir formas de onda arbitrarias, y se podía manejar de dos maneras.
    Una consistía en pasarle una dirección de memoria para que leyera bits y los procesara como una forma de onda muy simple: un 1 significaba “subir el valor en uno” y un 0, “bajar el valor en uno”, así que para crear una forma de onda plana había que repetir algo como 10101010.
    La otra consistía en que la CPU escribiera continuamente el “valor inicial” de forma directa, controlando el chip directamente; en la práctica, eso era más rápido que hacer que el driver de audio leyera bits desde la RAM.
    El problema era que este método consumía todos los ciclos de CPU, así que solo podía usarse cuando no se estaba haciendo nada más.
    Juegos como Battletoads lo aprovecharon para reproducir golpes de batería con mayor calidad mientras la acción estaba detenida, en la pantalla de título, en el efecto “crujiente” cuando toda la acción se pausa brevemente al dar el golpe final a un enemigo, y en la memorable música de pausa.
    Aquí hay una demo de un juego alternando entre el modo de control directo y el modo en que el chip lee muestras. Retro Game Audio subió un video modificado con un emulador que muestra el momento en que se entra a la subrutina de control directo: https://www.youtube.com/watch?v=JGT0FM3yh-w

  • Me da curiosidad por qué pasa algo así en primer lugar.
    ¿Es común que estos juegos vuelquen su estado como audio? ¿Es una herramienta de depuración intencional para desarrolladores de juegos?

    • Un video anterior del autor[1] explica los detalles técnicos de este comportamiento.
      Básicamente, el sonido del GBA transmite audio desde un búfer en RAM, y una interrupción debe indicarle al hardware que vuelva a leer desde el inicio del búfer.
      Pero si no se produce la interrupción, como cuando el juego se cuelga, el flujo de audio se pasa del búfer y empieza a leer otras zonas de la memoria.
      [1] https://www.youtube.com/watch?v=wSWNkpqjtQY&t=361s
    • Es algo bastante raro y tampoco es una herramienta de depuración intencional.
      En teoría, el GBA podría haber “detenido” la arquitectura cuando el juego se colgaba, o podría haber tenido un watchdog que vinculara a una interrupción no enmascarable una actualización de estado que debía ejecutarse periódicamente, y reiniciara el sistema si esa actualización se detenía.
      Pero esas funciones cuestan más, así que el GBA no las tiene.
      Nintendo básicamente optó por el enfoque tradicional de los viejos fabricantes de cartuchos: “si nuestro juego no tiene bugs, tampoco tenemos que preocuparnos por el comportamiento de estados de hardware indefinidos”.
      Así que, cuando un juego de GBA entra en un estado de cuelgue, como un bucle infinito con las interrupciones deshabilitadas, el chip de audio no sabe que el sistema se colgó y sigue haciendo su tarea simple: leer bits consecutivos de la RAM y convertirlos en sonido.
      Al desaparecer la rutina de limpieza que administraba esas lecturas durante el funcionamiento normal, sigue leyendo hasta que finalmente llega a bits que representan valores de la ROM del cartucho.
  • Es realmente absurdamente impresionante.
    Siento que técnicas como el algoritmo de mayoría usado aquí probablemente están subutilizadas en varias industrias.

    • Si te interesa, las técnicas sofisticadas de recuperación de señales con ruido ya llevan acumulándose casi 100 años.
      Los medios de almacenamiento magnético funcionan básicamente con el mismo principio que este hack.
      https://en.wikipedia.org/wiki/Partial-response_maximum-likelihood
      La misma idea podría aplicarse aquí, porque el contenido de una ROM de GBA tendrá un sesgo fuerte.
      La votación por mayoría desperdicia mucha información.
    • Una aplicación interesante de elegir el valor que aparece más veces, o más en general la mediana, es eliminar ruido o personas de varias fotos tomadas desde el mismo punto.
      Basta con superponer todas las fotos y conservar solo la mediana para cada píxel[1].
      [1]: https://patdavid.net/2013/05/noise-removal-in-photos-with-median_6/
    • Es bastante común en recuperación de datos.
      Se leen imágenes de disco una y otra vez y se aplica una decisión por quórum hasta obtener un resultado que pase la suma de verificación, y entonces se ve si funciona correctamente.
      Si hay sumas de verificación de más alto nivel, como firmas de archivo, sirven mejor para validación adicional.
      También se usa en algunas aplicaciones aeroespaciales.
    • Pensé que podría usarse en escaneo de película, especialmente en proyectos de fans como 4K77.
      Como trabajan con copias de exhibición en cines que pueden estar dañadas, no con un máster pristine, si pudieran usar varias copias para eliminar rayones y cosas así, podrían reducir muchísimo el tiempo de retoque manual en posproducción.
  • Que 0xFF se convierta en 0x00 podría deberse a un capacitor de bloqueo de corriente continua o a un filtrado pasaaltas.
    Los circuitos de audio no son muy adecuados para contenido no audible.
    Con suerte, conectar un osciloscopio digital directamente a la salida de audio del chip podría mejorar la precisión de captura, pero aun así es bastante impresionante que hayan obtenido una imagen booteable.

    • Recuerdo haber leído en los comentarios del video de YouTube que el objetivo era hacerlo con equipo básico en la medida de lo posible.
      Por eso, en vez de usar un osciloscopio real con registro de datos, pasaron horas repitiendo capturas para promediar los errores.
    • Exacto, hay que crear una señal sin sesgo de corriente continua.
      Incluso algo tan simple como la codificación Manchester ayudaría mucho.
      Si eso no alcanza, también se podría usar NRZ o incluso codificación convolucional.
      Además habría que enviar una onda sinusoidal o, si no se puede, al menos hacer que la frecuencia de la onda cuadrada sea lo bastante alta para que no se la coma el capacitor de acoplamiento de CA.
  • Lo que más me impresiona de todo esto, personalmente, es la forma en que los piratas modificaron el código para ejecutar el juego desde flash escribible en vez de ROM + memoria volátil de guardado.

    • Es una técnica muy común en juegos pirata de Game Boy y Game Boy Advance para ahorrarse unos centavos del costo de la batería.
      De hecho, crear esos parches no es tan difícil.
      Los piratas hacen un poco de ingeniería inversa para ver dónde guarda datos el código del juego, crean parches específicos para cada juego y vuelcan los datos guardados a la flash escribible.
      Sin embargo, los juegos oficiales de GBA siempre guardan usando funciones del SDK de Nintendo, así que si se enganchan esas funciones, se vuelve bastante sencillo crear un parche universal que permita guardar cualquier juego de GBA en cartuchos clon sin batería.
      Escribí un parcheador que hace eso y se puede ver aquí:
      https://github.com/metroid-maniac/gba-auto-batteryless-patcher
  • ¿Alguien sabe qué ocurre internamente cuando el emulador de TheZZAZZGlitch informa que el juego está intentando saltar a una dirección inválida?
    No estoy familiarizado con el procesador ARM7 usado en el GameBoy Advance, pero me cuesta imaginar cómo es posible armar una llamada de salto con un valor inválido.
    También me da curiosidad qué pasaría si se ejecutara en un GameBoy real una de las ROM restauradas incorrectamente por TheZZAZZGlitch.

    • Con la instrucción bx se puede saltar a una dirección arbitraria almacenada en un registro.
      Y si ejecutas una ROM restaurada incorrectamente en un GameBoy real, se va a colgar y, al final, empezará a reproducir la ROM por el altavoz.
      Ese es el punto central del video :)
    • Es probable que el emulador solo emule accesos a regiones válidas del mapa de memoria del GBA y lance ese error cuando se accede a una región inválida.
      En hardware real, qué pasaría… quién sabe :)