Hola a todos, tras algunos años de ausencia he decidido volver al foro (https://foro.elhacker.net/foro_libre/presentacion-t521505.0.html;msg2278764#msg2278764), y qué mejor manera de hacerlo que ensuciándonos un poco las manos destripando cartuchos de Game Boy.
En este thread voy a compartirles un proyecto didáctico en el que estuve trabajando para explicar las bases de Game Hacking a usuarios que se acercaban al tema por primera vez.
Introducción
Seguramente muchos de ustedes ya han experimentado en su época con Cheat Engine, o incluso habrán llegado a conocer los llamados "game enhancers" como Game Genie o Game Shark. Algunos venían en formato CD (Game Shark para PSX) y otros eran un dispositivo de hardware dedicado que interconectaba la consola con el cartucho que quisieramos "mejorar" (Game Shark para Game Boy).
Estos "mejoradores" de juegos nos permitían activar "cheats" o "trucos" de una forma simple y efectiva: modificando los valores almacenados en memoria (ya sea una sola vez, por ejemplo para agregarnos dinero o items; o permanentemente evitando su modificación, por ejemplo para evitar perder puntos de salud y ser inmortales).
Acá les dejo una foto del mío, un GameShark para Game Boy que apareció en Uruguay sellado y con sus plásticos originales.
Hoy en día los propios emuladores traen plugins para cumplir la función de un GameShark (o Game Genie), por lo que decidí programar un cartucho de pruebas para - como mencioné al principio - poder explicar de forma virtual y simple los conceptos básicos de game hacking para cualquier interesado, y evitar que se pierda esta hermosa costumbre de destripar cosas para aprender cómo funcionan.
Game hacking en Game Boy
Como este proyecto apunta mayormente a la manipulación de registros de memoria (el "qué" - contenido - y el "dónde" - posición de memoria) no vi una necesidad imperiosa de incursionar en frameworks de desarrollo como gbdk o GBASM (el "cómo", en este caso), por lo que decidí utilizar GBStudio para ahorrar tiempo (y salud mental). Llamé a este proyecto "DVHR" (Damn Vulnerable Hack Rom), y decidí agregarle varios sprites para que sea tan didáctico como fuese posible. La emulación fue hecha con VisualBoyAdvance, el cual trae integrado un emulador de Game Shark.
El cartucho representa el viaje de un personaje desconocido por tres escenarios (desafíos) hasta llegar a reunirse con otros personajes desconocidos. La idea de esta premisa tan genérica es poder adaptar la narrativa a cualquier público que esté siguiendo el tutorial.
El primer escenario representa un problema clásico para toda aventura: la necesidad de fondos para emprenderla. Si miramos los indicadores superiores en la siguiente captura, veremos que nuestra bolsa está vacía (valor "0") y de no solucionar este inconveniente, no podemos avanzar al siguiente escenario.
En la esquina inferior izquierda el cartucho nos sopla la solución: 0101 98CB ¿pero qué significa esta cadena?
Este es un código Game Shark, a grandes rasgos:
0101 representa un valor.
98CB representa una posición de memoria.
Este código colocará los valores "0101" en la posición "98CB". Si espiaramos esa posición de la memoria en el cartucho en ese preciso momento, veríamos que el valor es "0". Esa posición está guardando el valor de nuestro dinero, por lo cual modificarla nos permitirá "mejorar" nuestra experiencia de juego.
Utilizando el plugin de Game Shark de VisualBoyAdvance podemos ingresar este "cheat" e incluso guardarlo con un nombre amigable (como en los Game Shark originales).
Al colocar este código el juego dará por concluído el desafío y nos llevará al siguiente escenario, donde un Goblin nos cortará el paso.
Para resolver este escenario deberemos modificar dos registros, uno donde se almacena el "Escudo" (y colocarlo en 1) y otro donde se almacenan los puntos de Salud del Goblin (colocándolos en 0 para... "mejorar" nuestra experiencia de juego).
Nuevamente el juego nos sopla dos cadenas, que nos ayudarán a entender mejor la estructura de los códigos Game Shark:
0101 9ACB: Colocar el valor "0101" en la posición "9ACB".
0100 9CCB: Colocar el valor "0100" en la posición "9CCB".
De acá podemos inducir dos cosas importantes (de nuevo, a muy grandes rasgos):
- Del primer sector de la cadena (los primeros 4 dígitos), los últimos dos son los que modifican el valor de las variables. En el primer caso vamos a colocar el valor en "01" (Escudo) y en el segundo en "00" (HP del Goblin), a pesar que ambos empiezan por "01".
- Hasta ahora, todas las posiciones de memoria que estamos modificando terminan en "CB", por lo que si bien no son contiguas, comparten un espacio acotado y relativamente cercano. Esto también podemos saberlo leyendo los documentos técnicos sobre manejo de memoria de la consola y la documentación de los MBC (Memory Bank Controllers). Pero un recién interesado en el tema claramente no disfrutará haciéndolo.
Agregando estos dos códigos nos haremos con un nuevo escudo, una piel de Goblin y un nuevo desafío. O mejor dicho... dos.
Esta vez tenemos dos enemigos que nos cortan el paso: una Serpiente y un Murciélago, pero ya no hay soluciones disponibles. Al parecer, los puntos de Salud (HP) de la Serpiente oscilan entre 2 y 4 (y tenemos que bajarlos a 0) y los del Murciélago oscilan entre 6 y 8 (y claramente, también hay que bajarlos a 0).
Tenemos la siguiente estructura de códigos:
0100 ??CB: Colocar el valor "0100" en la posición "??CB".
0100 ??CB: Colocar el valor "0100" en la posición "??CB".
Sabemos que hay que colocar en "00" dos valores ubicados en la misma "vecindad" (espacio) de memoria donde vinimos trabajando hasta el momento. Parece que se nos ha agotado la suerte pero no, es hora de aprender a buscar cheats como en la vieja escuela... rompiendo.
Un feature que tenían los Game Sharks (no todos, sino algunas versiones) es la capacidad de "buscar" trucos... ¿cómo funciona? buscando un valor específico a lo largo de la memoria y siguiendo eventuales cambios para aislar e identificar posibles posiciones de memoria de interés.
En palabras más simples, supongamos que nuestro personaje tiene un valor específico de "Oro", por ejemplo, 151. Mapeamos el valor 151 y nuestro "mejorador" de juegos va a darle seguimiento, dándonos una lista de todas las posiciones de memoria del juego que estén guardando ese valor (que podrían ser muchísimas). Gastamos 1 de Oro y el valor ya no es 151, sino 150. Ahora no buscamos "qué posición tiene en este momento el valor 150", sino "qué posición tiene en este momento el valor 150 y anteriormente tenía el valor 151". Esto desencadena un proceso de eliminación que nos irá arrojando cada vez menos candidatos hasta identificar la posición específica que queremos manipular. Una suerte de "Adivina quién" pero con un depurador.
El "Game Shark" integrado en la mayoría de los emuladores permite este comportamiento, así que vamos a buscar valores de interés. Comencemos por el valor "techo" del HP de la Serpiente: 4.
Aparentemente, ninguna posición de memoria está guardando ese valor, por lo que sabemos que no es el que estamos buscando. Repitamos el proceso para el valor "techo" del HP del Murciélago: 8.
Bingo, encontramos varios candidatos y uno está en la vecindad que buscamos ("CB").
Acá es donde varios habrán notado algo extraño: la notación de la dirección de memoria está "al revés" ("CB" está primero que "A0"). Esta diferencia en la notación es común, a veces ciertas instrucciones o direcciones se representarán "al revés" según el programa (o plug-in) que estmos utilizando. Los que en algún momento de sus carreras hayan usado debug.exe en Windows para programar en ASM sabrán a lo que me refiero.
Vamos a colocar ese valor en "0", y continuamos repitiendo el proceso con los demás valores (2 y 3 para la Serpiente) hasta aislar las posiciones de memoria sospechosas.
Acá es donde viene útil una advertencia amistosa: cuando estén buscando cheats o manipulando la memoria de un programa en general, es muy común que a veces identifiquemos mal una dirección, alteremos su valor y suframos consecuencias inesperadas. En los cartuchos de Game Boy el peor escenario posible es un Kernel Panic, nada que no se resuelva reiniciando la consola o el emulador. Pero es ideal tener sumo cuidado cuando se manipula la memoria de algún otro proceso "más serio" que no esté aislado por un emulador ni sea un simple juego didáctico.
Ejemplo de un Kernel Panic en Game Boy:
Una vez que aislamos las posiciones de memoria sospechosas y cambiamos los valores necesarios, lograremos resolver el desafío.
Si prestan atención verán debajo la solución del mismo. Si prestan aún más atención, verán que el cheat resaltado en el Game Shark no se corresponde a esas soluciones, sino que fue un error de mi parte al intentar aislar e identificar la posición de memoria (y afortunadamente, no causó un Panic).
Finalmente nuestro personaje llegó al final de su aventura (sea cual sea su objetivo) y pudimos explicar de forma didáctica una introducción básica a cómo funciona el Game Hacking de la vieja escuela.
Outro
Espero que el hilo no se haya hecho tedioso ni extenso. Desde ya es un gusto estar de vuelta con ustedes, y cualquier crítica constructiva siempre es bien recibida.
Espero que les haya gustado, nos vemos en la próxima.
Referencias y links de interés
- Tweet con las fotos originales: https://twitter.com/MauroEldritch/status/1591444536152449024
- Una historia de cartuchos piratas: https://twitter.com/MauroEldritch/status/1740129623814414704
- Descargar una copia de DVHR: https://mega.nz/file/Jc0kTITD#v8PQbbZojCN1yuoPhtFqoQ9HxLyHb6CH4IyUjuUEO9I
- GBStudio: https://www.gbstudio.dev/es/
- VisualBoy: https://visualboyadvance.org/
Ningún Goblin fue lastimado durante la producción de este artículo.