160
ROMHACKING GAMEBOY PRÁCTICO Este tutorial trata de explicar cómo modificar juegos de Gameboy a través de ejemplos reales cambiando algunas características de éstos. Los aspectos que se cubren en este documento son aplicables a otros juegos en su gran mayoría y van a permitir a cualquiera adquirir los conocimientos suficientes para hacer sus propias modificaciones y buscar información en juegos de esta consola. Se va a utilizar varios juegos de Gameboy y varias técnicas. En internet hay tutoriales para hacer modificaciones en juegos de esta consola pero la mayoría se centran en pocos juegos (sobre todo los de Pokemon y Super Mario) por lo que para el resto no se encuentra mucha información. No voy a tratar sobre en este tutorial sobre los juegos de Pokemon ya que hay bastantes páginas y foros con información tanto en español como inglés sobre estos juegos. Para utilizar este manual se va a utilizar una serie de herramientas que se pueden conseguir fácilmente en internet: - BGB (Emulador de Gameboy que cuenta con un debugger). También se puede utilizar No$Gmb que es similar aunque me centraré en el anterior. - HxD (Editor hexadecimal gratuito o cualquier otro) - TilED2002 (Editor de tiles). - GBAsmEdit. - Game Genie Encoder/Decoder 0.91A - IPS Peek - IPSWin (Parchear juegos). - Hat Trick (Editor de niveles del juego “Snoopy Magic Show” para una parte del tutorial) - File Search 0.0.a (Programa propio) También voy a explicar como modificar los niveles de varios juegos de Gameboy y si alguien tiene conocimientos de programación pueda crear un editor para que cualquiera pueda modificarlo más fácilmente con una utilidad específica. Los juegos para los que tengo información y que no hay editores de niveles todavía para ellos son: - Battlebull - Block Kuzushi (SGB) - Bomb Jack - Boomer in Asmik World 2 - Kesamaru - Little Magic (GBC) - Mr. Do - Pac-Attack CONCEPTOS BÁSICOS Hexadecimal: Sistema numérico que utiliza 16 valores para representar los números para lo que utiliza (0-9, letras A-F). Decimal: Sistema numérico que utiliza 10 valores para representar los números (0-9).

ROMHACKING GAMEBOY PRÁCTICO - Todo lo que quiso saber … · ^NOP _ ^No Operation _: Esta instrucción es la que vamos a utilizar para eliminar instrucciones cuando queramos por

  • Upload
    others

  • View
    0

  • Download
    0

Embed Size (px)

Citation preview

Page 1: ROMHACKING GAMEBOY PRÁCTICO - Todo lo que quiso saber … · ^NOP _ ^No Operation _: Esta instrucción es la que vamos a utilizar para eliminar instrucciones cuando queramos por

ROMHACKING GAMEBOY PRÁCTICO

Este tutorial trata de explicar cómo modificar juegos de Gameboy a través de ejemplos reales

cambiando algunas características de éstos.

Los aspectos que se cubren en este documento son aplicables a otros juegos en su gran

mayoría y van a permitir a cualquiera adquirir los conocimientos suficientes para hacer sus

propias modificaciones y buscar información en juegos de esta consola.

Se va a utilizar varios juegos de Gameboy y varias técnicas. En internet hay tutoriales para

hacer modificaciones en juegos de esta consola pero la mayoría se centran en pocos juegos

(sobre todo los de Pokemon y Super Mario) por lo que para el resto no se encuentra mucha

información.

No voy a tratar sobre en este tutorial sobre los juegos de Pokemon ya que hay bastantes

páginas y foros con información tanto en español como inglés sobre estos juegos.

Para utilizar este manual se va a utilizar una serie de herramientas que se pueden conseguir

fácilmente en internet:

- BGB (Emulador de Gameboy que cuenta con un debugger). También se puede utilizar

No$Gmb que es similar aunque me centraré en el anterior.

- HxD (Editor hexadecimal gratuito o cualquier otro)

- TilED2002 (Editor de tiles).

- GBAsmEdit.

- Game Genie Encoder/Decoder 0.91A

- IPS Peek

- IPSWin (Parchear juegos).

- Hat Trick (Editor de niveles del juego “Snoopy Magic Show” para una parte del tutorial)

- File Search 0.0.a (Programa propio)

También voy a explicar como modificar los niveles de varios juegos de Gameboy y si alguien

tiene conocimientos de programación pueda crear un editor para que cualquiera pueda

modificarlo más fácilmente con una utilidad específica.

Los juegos para los que tengo información y que no hay editores de niveles todavía para ellos

son:

- Battlebull

- Block Kuzushi (SGB)

- Bomb Jack

- Boomer in Asmik World 2

- Kesamaru

- Little Magic (GBC)

- Mr. Do

- Pac-Attack

CONCEPTOS BÁSICOS

Hexadecimal: Sistema numérico que utiliza 16 valores para representar los números para lo

que utiliza (0-9, letras A-F).

Decimal: Sistema numérico que utiliza 10 valores para representar los números (0-9).

Page 2: ROMHACKING GAMEBOY PRÁCTICO - Todo lo que quiso saber … · ^NOP _ ^No Operation _: Esta instrucción es la que vamos a utilizar para eliminar instrucciones cuando queramos por

Binario: Sistema numérico que utiliza 2 valores para representar los números para lo que

utiliza (0-1)

Estos sistemas numéricos se pueden convertir de unos a otros utilizando la calculadora que

incluye Windows.

INSTRUCCIONES BÁSICAS

Aunque este tutorial no pretende aburrir demasiado con muchas instrucciones pero si es

bueno tener algunos conocimientos sobre todo de algunas (las más utilizadas).

“LD”

Esta es una de las más utilizadas y se utiliza tanto para leer como escribir valores en registros o

en una determinada dirección.

Por ejemplo, para cargar en el registro “A” el valor que hay en la dirección contenida en el

registro “DE” se utiliza la instrucción:

ld a,(de)

Sin embargo, para escribir el valor del registro “A” en la dirección contenida en el registro “DE”

se utiliza la instrucción:

Ld (de),a

Igual se puede utilizar el registro “DE” y “HL” para leer o escribir un valor.

También se puede utilizar para poner en el registro “A”, “B”, “C”, “D”, “E”, “H”, “L”, “AF”, “BC”,

“DE”, “HL” un determinado valor.

Por ejemplo:

Ld a,$03 (Carga en el registro “A” el valor $03)

Ld b,$05 (Carga en el registro “B” el valor $05)

Ld de,$8000 (Carga en el registro “DE” la dirección $8000)

Hay una serie de direcciones a partir de la dirección $FF00 que se pueden leer o escribir de

varias formas utilizando la instrucción “LD”.

Para cargar en el registro “a” el valor que hay en la dirección $FF41 que se encarga del estado

del LCD podemos utilizar:

21 41 FF Ld a,[$FF41]

F0 41 Ld a,[$FF00+$41]

Normalmente se utiliza la segunda forma porque se requieren 2 bytes en lugar de los 3 de la

primera instrucción pero también podemos encontrar la primera.

Esto sólo se puede utilizar para direcciones a partir de $FF00.

“LDI”

Esta instrucción es similar a la anterior. Se suele utilizar de la siguiente forma:

Ldi [hl],a

Pone el valor del registro “a” en la dirección contenida en “hl” e incrementa “hl”.

Por ejemplo:

A=$00, HL=$C000.

Esta instrucción pondría el valor $00 en $C000 e incrementa el registro “hl” con lo que valdría

$C001. Se suele utilizar para continuar escribiendo en la siguiente dirección.

“INC”, “DEC

Esta instrucción se utiliza para incrementar o disminuir los valores que hay en un determinado

registro.

Son importantes ya que se utilizará para incrementar o disminuir valores de la RAM como

puede ser vidas, energía,...

Page 3: ROMHACKING GAMEBOY PRÁCTICO - Todo lo que quiso saber … · ^NOP _ ^No Operation _: Esta instrucción es la que vamos a utilizar para eliminar instrucciones cuando queramos por

“NOP”

“No Operation”: Esta instrucción es la que vamos a utilizar para eliminar instrucciones cuando

queramos por ejemplo tener vidas o energía infinita.

Esta instrucción equivale a no hacer nada y se corresponde con el valor hexadecimal $00. Si

tenemos una instrucción que disminuye un valor podemos sustituirla por una o varias

instrucciones “nop” dependiendo del número de bytes que ocupe la instrucción que queramos

eliminar y conseguiremos si se trata de “DEC” que no disminuya ese valor.

USO DEL EMULADOR BGB

El emulador que vamos a utilizar en este manual es “BGB” que tiene una gran cantidad de

opciones tales como debugger, VRAM viewer,…

El emulador “NO$GMB” también tiene muchas opciones como las del “BGB” y su

funcionamiento es parecido a éste por lo que también podrían utilizarlo para modificar juegos

de Gameboy.

Uno de las opciones más interesantes que tiene el debugger de BGB es la de poner

breakpoints.

Los breakpoints permiten hacer que el emulador se pare cuando se lea o escriba un

determinado valor en una dirección o cuando se lea o ejecute parte de la información

contenida en el juego.

Para mostrar el debugger una vez cargado el juego podemos pulsar la tecla “Esc” (Escape) del

teclado o a través de la opción “Debugger” del menú “Other” que aparece al pulsar el botón

derecho del ratón sobre el emulador.

En esta pantalla obtenemos bastante información interesante del juego en la ventana.

Page 4: ROMHACKING GAMEBOY PRÁCTICO - Todo lo que quiso saber … · ^NOP _ ^No Operation _: Esta instrucción es la que vamos a utilizar para eliminar instrucciones cuando queramos por

En la parte izquierda nos aparece el código fuente del juego con los offsets (los que empiezan

por ROM), a continuación los códigos que representan cada instrucción y a continuación la

instrucción.

Tal y como aparece en la captura aparece marcado en azul la línea de código que corresponde

a la dirección $00:0040 del juego (offset) que contiene la instrucción “jp 200A” y que se

codifica con los bytes “C3 0A 20”.

Cada instrucción se codifica con una serie de bytes variable dependiendo de la que sea. En este

caso se utiliza el byte “C3” para indicar la orden “jp” (jump: salto a una dirección) y los

siguientes 2 bytes representan la dirección en formato hexadecimal inverso ($200A, se

representa como “0A”, “20”).

A la derecha vemos los registros de la consola y sus valores actuales cuando se hizo la captura.

En este caso el registro “AF” tiene el valor $00A0. Este registro es de 16 bits (o 2 bytes) ya que

tiene 4 dígitos.

El registro “AF” se puede dividir en 2 registros de 8 bits (1 byte). El registro “A” que tiene el

valor $00, y el registro “F” que tiene el valor $A0.

Igual ocurre con el resto de registros de 16 bits: BC, DE, HL.

Estos registros los utiliza la consolar para escribir información y poner datos.

El registro SP (stack de la pila) se utiliza para poner la dirección donde se guardan datos

(aunque éste no lo veremos en el tutorial).

El registro “PC” indica la dirección actual que como se ve es la $0040.

Otro valor interesante es el que aparece con el nombre “rom” y que indica el banco actual y es

importante ya que no es lo mismo la dirección dependiendo de este valor.

Por ejemplo, si encontramos la siguiente instrucción:

“ld hl,$4523”

Esta instrucción lo que hace es cargar en hl la dirección $4523. Sin embargo, los juegos suelen

estar divididos en banco de 16 kbs. y debemos saber el banco que aparece en “rom”.

Si en “rom” aparece el valor “1” se estará cargando en hl la dirección $01:4523 y si estuviera el

valor “2” sería la dirección $02:4523.

A la derecha del todo de los registros aparecen los valores de los flags de carry “c”,

Debajo encontramos los valores de algunas direcciones de HRAM (High RAM), ROM,…

En la parte inferior izquierda aparece en formato hexadecimal la ROM, High RAM,… como si

fuera un editor hexadecimal.

Una de las utilidades del Debugger y que es interesante es la obtención del código fuente del

juego para lo cual podemos situarnos sobre el inicio del juego utilizando “Go to…” y poniendo

la dirección “00:0000” para irnos al inicio.

Nos situamos en el menú “File” y seleccionamos “save asm” para que nos aparezca una

ventana para seleccionar donde vamos a guardar el código fuente y el nombre del fichero.

Page 5: ROMHACKING GAMEBOY PRÁCTICO - Todo lo que quiso saber … · ^NOP _ ^No Operation _: Esta instrucción es la que vamos a utilizar para eliminar instrucciones cuando queramos por

En mi caso le he puesto el nombre “Battle Bull (U) [¡] Banco 00.txt” para saber el juego del que

es el código y el banco que contiene.

En la pantalla que nos aparece a continuación nos aparece la dirección inicial que vamos a

dejar igual que nos aparece.

Al pulsar en “OK” nos aparece otra ventana en la que ponemos el número de bytes a guardar

en el fichero de código fuente que cambiamos a “4000” para guardar el banco 0 al completo.

Cada banco ocupa $4000 bytes.

Page 6: ROMHACKING GAMEBOY PRÁCTICO - Todo lo que quiso saber … · ^NOP _ ^No Operation _: Esta instrucción es la que vamos a utilizar para eliminar instrucciones cuando queramos por

Podemos hacer lo mismos para el resto de bancos del juego para obtener ficheros de cada uno

de ellos para lo cual para el banco $01 cambiaríamos en “Go to…” la dirección por “01:4000”

para el banco 1, “02:4000” para el banco 2, y así sucesivamente dependiendo del número de

bancos del juego.

Cada 16 kilobytes son 1 banco por lo que un juego de 32 kbs. tendrá 2 bancos (banco 0 y 1),

uno de 64 kbs. tendrá 4 bancos (banco 0, 1, 2 y 3).

El banco 0 empieza en la dirección $00:0000 y el resto en la dirección $xx:4000 donde xx es el

número de banco.

Con esto ya tendríamos todo el código del juego aunque el debugger trata todo como si fuera

instrucciones y sin embargo aquí hay también datos del juego, música del juego, tiles, textos,

punteros,… y debemos analizar el código para ver que es cada cosa lo que es el proceso más

complicado.

También podemos obtener códigos fuentes parciales (a partir de una dirección en concreto y

un número de bytes determinado).

Analizar un juego completo para averiguar todos los aspectos del mismo es casi imposible y

requiere mucho tiempo y comprender muy bien cómo funciona la consola Gameboy, los

registros, instrucciones,…. sobre todo si incluye información comprimida.

Otra opción interesante es guardar parte de la memoria en un fichero que se puede guardar y

abrir con un editor hexadecimal.

Lo más interesante para guardar de la memoria son los tiles del juego, la RAM y la High RAM

(aunque esto menos).

Para guardar los tiles del juego seleccionamos la opción “save memory dump…” del menú

“File” con lo que nos guarda un fichero con el nombre del juego y con extensión “.dump”

aunque podemos ponerle el nombre que queramos.

Igual que ocurría antes debemos ponerle la dirección de inicio y el número de bytes que

queremos guardar en formato hexadecimal.

En el caso de los tiles dependiendo de lo que aparezca en el “BGB VRAM Viewer” podemos

seleccionar una dirección u otra.

Por ejemplo, si el juego tiene muchos tiles y aparece la pantalla completa del “BGB VRAM

Viewer” podemos poner la dirección $8000 como inicial y $1800 como número de bytes a

guardar en el fichero con lo que guardaríamos los datos que hay entre las direcciones $8000-

$97FF que corresponden a todos los tiles del juego.

Los tiles del juego se almacenan en las direcciones $8000-$87FF, $8800-$8FFF y $9000-$97FF.

Page 7: ROMHACKING GAMEBOY PRÁCTICO - Todo lo que quiso saber … · ^NOP _ ^No Operation _: Esta instrucción es la que vamos a utilizar para eliminar instrucciones cuando queramos por

Si no estuviera llena la pantalla de “BGB VRAM Viewer” podemos poner otra dirección y otro

número de bytes.

También es interesante grabar la pantalla del juego como si fueran datos para buscar esta

información en el juego y ver donde está almacenada en la ROM para modificarla si queremos

a nuestro gusto.

En Gameboy disponemos de 2 direcciones (como si se tratara de 2 pantallas) donde podemos

poner información y que aparezca en la consola.

Por ejemplo, en una podemos poner la pantalla del nivel y en otra varias líneas con

información tales como puntos, tiempo, energía que aparecería a la vez en la pantalla del

juego pero que está en dos áreas de memoria diferente.

Estas direcciones donde se almacenan datos de las pantallas se denominan Map Address

encontrándonos un área en las direcciones $9800-$9BFF y en $9C00-$9FFF (con $0400 bytes

cada una).

Page 8: ROMHACKING GAMEBOY PRÁCTICO - Todo lo que quiso saber … · ^NOP _ ^No Operation _: Esta instrucción es la que vamos a utilizar para eliminar instrucciones cuando queramos por

Tal y como vemos en la pantalla vemos como en la pantalla del “BGB VRAM Viewer” tenemos

en la pestaña “BG Map” información de la pantalla.

En la parte izquierda aparece la pantalla tal y como aparece en la consola. Como vemos hay

una gran parte en verde y que corresponde a zonas no visibles y que pueden tener tiles para

poner zonas no visibles en la pantalla que al hacer scroll aparecerían en la pantalla del juego.

En la parte derecha en el recuadro superior aparecería el tile en formato gráfico tal y como se

representa en la pantalla y debajo detalles del mismo tales como coordenada X e Y en pantalla,

el número de tile que será $00-$FF. La Map Address donde está el tile en pantalla, la Tile

Address donde están los datos que representan el tile,…

Por defecto, “Map” y “Tiles” está puesto en “Auto” pero se puede cambiar el valor de “Map”

por “9800” o “9C00”. Cambiando esto podemos ver las 2 áreas de pantalla que juntas se

muestran en la pantalla del juego tal y como se ve en las siguientes capturas:

Pantalla donde se dibuja el nivel ($9800-$9BFF)

Page 9: ROMHACKING GAMEBOY PRÁCTICO - Todo lo que quiso saber … · ^NOP _ ^No Operation _: Esta instrucción es la que vamos a utilizar para eliminar instrucciones cuando queramos por

Pantalla donde se pone información de puntos, tiempo y energía ($9C00-$9FFF):

Page 10: ROMHACKING GAMEBOY PRÁCTICO - Todo lo que quiso saber … · ^NOP _ ^No Operation _: Esta instrucción es la que vamos a utilizar para eliminar instrucciones cuando queramos por

Pantalla de juego en el emulador donde aparecen ambas pantallas:

En ninguna de las anteriores pantallas aparecían los sprites del personaje que movemos ni de

los enemigos cuya información aparece en la OAM donde están los datos de cada uno de los

tiles que lo componen y sus datos.

Los 4 primeros conjuntos de valores se utilizan para dibujar el personaje que movemos en el

juego que unidos forman el sprite.

Page 11: ROMHACKING GAMEBOY PRÁCTICO - Todo lo que quiso saber … · ^NOP _ ^No Operation _: Esta instrucción es la que vamos a utilizar para eliminar instrucciones cuando queramos por

En X-loc, Y-loc aparecen las coordenadas X e Y de cada tile, el número de tile y su atributo.

También aparece la dirección “OAM addr” donde están dichos datos que para el tercer tile que

hemos seleccionado con el ratón corresponde a la dirección $FE08.

Cada tile ocupa 4 bytes en la OAM (Y-loc, X-loc, Tile No y Atributo). Los datos de la OAM

empiezan en la dirección $FE00.

Poniendo la dirección $9800 en la dirección y $0400 como número de bytes a guardar

generamos un fichero .dump con la información de una de las pantallas y con $9C00 y $0400

guardamos la otra pantalla en un fichero .dump.

La utilidad de esto es para encontrar donde están los datos para dibujar la pantalla y poder

localizarla.

Sin embargo, en los juegos podemos encontrar muchas formas diferentes de poner la pantalla

del juego siendo de mayor utilidad cuando se dibuja la pantalla en su totalidad dibujando las

18 líneas de la pantalla con los 20 tiles que forman cada línea o cuando se dibujan las 18 líneas

de la pantalla con 32 tiles que ocupa la pantalla completa incluyendo la parte no visible.

Esto ocurre en algunos juegos de Gameboy pero no es el caso del juego “Battle Bull” donde la

pantalla de título se dibuja de forma diferente.

En este caso podemos utilizar también otra opción del emulador BGB y un editor hexadecimal

para encontrar donde están los datos para dibujar la pantalla de título.

Para ello en el Debugger nos situamos sobre la dirección $9840 por ejemplo, porque en esta

línea aparece la parte superior del rótulo “BULL” en negro (el primer tile está en la dirección

$984A y corresponde al tile $2C.

Page 12: ROMHACKING GAMEBOY PRÁCTICO - Todo lo que quiso saber … · ^NOP _ ^No Operation _: Esta instrucción es la que vamos a utilizar para eliminar instrucciones cuando queramos por

Podemos seleccionar “Copy data” sobre la dirección $9840 y seleccionar en el número de

bytes 16 aunque los que realmente nos interesan son los 3 que tienen valores distintos de 00

($2C, $34, $3B).

Si abrimos el juego con un editor hexadecimal y buscamos la cadena hexadecimal “2C343B” lo

encontramos en la dirección $29E5-$29E7.

Ya hemos encontrado donde están los datos que buscamos y vemos como sólo aparecen los

valores buscados y no los valores 00 que aparecen antes y después de estos en pantalla. Esto

es debido a que sólo se ponen en pantalla en la zona correspondiente una serie de tiles para

dibujar la pantalla y el resto tiene el valor $00.

Page 13: ROMHACKING GAMEBOY PRÁCTICO - Todo lo que quiso saber … · ^NOP _ ^No Operation _: Esta instrucción es la que vamos a utilizar para eliminar instrucciones cuando queramos por

Es como llenar la pantalla con el valor $00 y luego situar los tiles correspondientes para dibujar

los elementos que forman el rótulo del título “BATLLE BULL” en la pantalla.

Si nos fijamos en la dirección $29E2 vemos algo que nos es conocido y es el valor $98 seguido

por $4A que juntos forman la dirección $984A=Map Address donde se ponen los 3 tiles en la

pantalla del juego (tal y como aparece en la pantalla de más arriba del “BGB VRAM Viewer”

donde está la pantalla de título.

En $29E4 aparece el valor $03 que es precisamente el número de tiles que pone en la pantalla

a partir de la dirección $984A.

En $29E8 encontramos la dirección $9851=Map Address donde pone tiles en pantalla, y en

$29EA encontramos $02 que indica el número de tiles a poner en pantalla y en $29EB los

valores $5B, $63 que son los tiles que dibuja y así sucesivamente para ir dibujando el rótulo

“BATTLE BULL”.

La última parte que se utiliza para dibujar el rótulo se ponen en la dirección $992E donde se

ponen $04 tiles con los valores $4C, $53, $5A, $62 que aparecen en las direcciones $2A44-

$2A47.

En la dirección $2A48 encontramos el valor $00 que puede indicar el fin de los datos para

dibujar el rótulo.

Como las direcciones están entre $0000 y $4000 vemos que corresponden al banco $00 por lo

que los datos para dibujar el rótulo están entre las direcciones $00:29E2 y $00:2A48.

Puede parecer un proceso complejo pero realmente no lo es y haciendo el proceso con otros

juegos puedes comprobarlo.

En ocasiones la dirección Map Address no aparece como aquí sino que está en orden inverso

(en lugar de $98, $4A, podemos encontrar los valores $4A, $98).

En algunos juegos nos podemos encontrar que no aparece la dirección Map Address donde se

ponen los tiles en pantalla sino que están las coordenadas X e Y donde se ponen los tiles en

pantalla y a partir de ellas calcula la Map Address para dibujar los tiles.

En este caso los 3 primeros tiles que hemos encontrado para dibujar el rótulo se ponen en la

coordenada X=$0A (10 decimal) y coordenada Y=$02. La parte superior izquierda de la pantalla

corresponde a las coordenadas (0,0) que para esta pantalla corresponde a la dirección

$9800=Map Address.

El tile que se pone en la coordenada X=$01 e Y=$00 tiene la Map Address=$9801 y así

sucesivamente.

Cada línea son $20 (32 en decimal) tiles con lo que la línea con coordenada Y=0 comienza en la

dirección $9800 y termina en $981F.

La línea con Y=$01 corresponde a la Map Address entre $9820-$983F. La línea con Y=$02

corresponde a la Map Address entre $9840-$985F.

De los $20 tiles que componen cada línea sólo los $14 primeros son visibles en la pantalla de la

consola, el resto no son visibles.

La fórmula para pasar de coordenadas a dirección de la Map Address son las siguientes:

Page 14: ROMHACKING GAMEBOY PRÁCTICO - Todo lo que quiso saber … · ^NOP _ ^No Operation _: Esta instrucción es la que vamos a utilizar para eliminar instrucciones cuando queramos por

$9800+X+$20*Y para la pantalla que comienza en $9800.

El tile X=$0A, Y=$02 corresponde a la dirección $9800+$0A+$02*20=$9800+$0A+$40=$984A.

$9C00+X*$20*Y para la pantalla que comienza en $9C00.

Una vez que hemos localizado donde están los datos de la pantalla ($00:29E2) podemos buscar

este valor sin el número de banco en el código fuente que podemos obtener con el emulador

BGB con lo que encontramos lo siguiente:

ROM0:279D 21 E2 29 ld hl,29E2

ROM0:27A0 11 00 D3 ld de,D300

ROM0:27A3 01 1A 00 ld bc,001A

ROM0:27A6 CD 14 04 call 0414

ROM0:27A9 3E 01 ld a,01

ROM0:27AB EA 52 C1 ld (C152),a

ROM0:27AE 01 01 00 ld bc,0001

ROM0:27B1 CD DE 05 call 05DE

ROM0:27B4 21 FC 29 ld hl,29FC

ROM0:27B7 11 00 D3 ld de,D300

ROM0:27BA 01 17 00 ld bc,0017

ROM0:27BD CD 14 04 call 0414

ROM0:27C0 3E 01 ld a,01

ROM0:27C2 EA 52 C1 ld (C152),a

ROM0:27C5 01 01 00 ld bc,0001

ROM0:27C8 CD DE 05 call 05DE

ROM0:27CB 21 13 2A ld hl,2A13

ROM0:27CE 11 00 D3 ld de,D300

ROM0:27D1 01 1B 00 ld bc,001B

ROM0:27D4 CD 14 04 call 0414

ROM0:27D7 3E 01 ld a,01

ROM0:27D9 EA 52 C1 ld (C152),a

ROM0:27DC 01 01 00 ld bc,0001

ROM0:27DF CD DE 05 call 05DE

ROM0:27E2 21 2E 2A ld hl,2A2E

ROM0:27E5 11 00 D3 ld de,D300

Page 15: ROMHACKING GAMEBOY PRÁCTICO - Todo lo que quiso saber … · ^NOP _ ^No Operation _: Esta instrucción es la que vamos a utilizar para eliminar instrucciones cuando queramos por

ROM0:27E8 01 1B 00 ld bc,001B

ROM0:27EB CD 14 04 call 0414

ROM0:27EE 3E 01 ld a,01

ROM0:27F0 EA 52 C1 ld (C152),a

ROM0:27F3 01 01 00 ld bc,0001

ROM0:27F6 CD DE 05 call 05DE

ROM0:27F9 C9 ret

En la primera línea de este código vemos que aparece la dirección $29E2 que corresponde a

(ROM0:279D).

El código guardado contiene cada línea el texto “ROM” y a continuación el número de banco

que en este caso es el 0 y la dirección que es $279D.

ROM0:279D 21 E2 29 ld hl,29E2

Esta instrucción carga en hl la dirección $00:29E2 donde empiezan los datos para dibujar el

rótulo.

En la siguiente línea encontramos lo siguiente:

ROM0:27A0 11 00 D3 ld de,D300

Esto lo que hace es cargar en el registro “de” la dirección $D300 que corresponde a la RAM.

Las líneas siguientes:

ROM0:27A3 01 1A 00 ld bc,001A

ROM0:27A6 CD 14 04 call 0414

Cargan en el registro “bc” el valor $001A (1ª línea) y la siguiente llama a una subrutina que se

encuentra en la dirección $00:0414.

Esta utilización de los registros es algo habitual en todos los juegos de Gameboy donde se

pone en hl y de las direcciones de carga y escritura. En bc se pasa el número de bytes a

leer/copiar y se llama a la subrutina que lee de una dirección y la pone en otra dirección.

En el resto de código aparecen otras direcciones donde hay datos para dibujar el rótulo y

donde se pone en la RAM.

La rutina que llama en la dirección $00:0414 tiene las siguientes líneas:

ROM0:0414 2A ldi a,(hl)

ROM0:0415 12 ld (de),a

ROM0:0416 13 inc de

ROM0:0417 0B dec bc

ROM0:0418 78 ld a,b

ROM0:0419 B1 or c

Page 16: ROMHACKING GAMEBOY PRÁCTICO - Todo lo que quiso saber … · ^NOP _ ^No Operation _: Esta instrucción es la que vamos a utilizar para eliminar instrucciones cuando queramos por

ROM0:041A 20 F8 jr nz,0414

ROM0:041C C9 ret

Lo que hace es que carga los datos que hay en hl (datos del rótulo) y los pone en de (RAM). En

bc se le pasa el número de bytes.

Se utiliza ldi que carga en a el valor que hay en la dirección contenida en hl que sería $00:29E2

para el primer tile que tiene el valor $98 e incrementa hl con lo que hl=$00:29E3).

Se utiliza “ldi” para incrementar a la vez que se carga la dirección hl. A veces aunque no es lo

normal se puede utilizar “ld a,(hl)” aunque luego debe incluirse la instrucción “inc hl” para

incrementar la dirección “hl”. Por eso se suele utilizar “ldi a,(hl)” para ahorrarse una

instrucción (“inc hl”).

A continuación pone el valor de a que es $98 (el valor que hay en la dirección $00:29E2 en la

dirección contenida en de=$D300).

Seguidamente aparece “inc de” que incrementa la dirección contenida en de con lo que pasa a

ser $D301 y luego con “dec bc” disminuye el valor de bc (o sea el número de bytes que quedan

por leer y escribir.

Las 2 siguientes son operaciones que aparecen y que no hace falta que comprendan. Luego

aparece “jr nz,$0414” que lo que hace es comprobar si ya no quedan bytes por leer/escribir

cuando bc vale $00 y si no es el caso (“nz” ) salta a la dirección $00:0414 que es el inicio de la

rutina para seguir leyendo y escribiendo bytes.

En caso de que se hubieran leído y escrito todos los bytes en lugar de saltar a la dirección

$00:0414 se ejecutaría la instrucción en la dirección $00:041C (que regresaría a la dirección

que llamó a esta subrutina una vez que se han leído y escrito todos los bytes).

“Ret” es la abreviatura de “Return” (Regresar).

La posición donde se encuentra la instrucción de carga de datos también la podríamos haber

encontrado con el editor hexadecimal buscando los dígitos hexadecimales $E292 aunque luego

habría que ir a esa posición en el código fuente.

Para modificar la pantalla de título podríamos cambiar las direcciones Map Address donde

situamos los tiles con lo que se puede situar el rótulo en una posición distinta. También se

puede modificar los tiles y hacer otros propios para hacer una pantalla de título

completamente distinta.

Hemos localizado los datos del rótulo, el fragmento de carga de datos y los ponen en RAM y

una rutina de uso general que carga datos de una dirección y la pone en otra.

Además de esto aparecen los textos “HISCORE-” y “SCORE-” con las puntuaciones y varios

textos del menú principal del juego que no hemos localizado todavía.

Si buscamos “HISCORE-” con un editor hexadecimal como texto no encontraremos nada pero

si buscamos los dígitos hexadecimales “E8 E9 F3 E3 EF F2 E5 CD” lo encontraremos en la

dirección $2A5C-$2A63 ($00:2A5C-$00:2A63).

En la dirección $00:2A59-$00:2A5A encontramos la dirección $9802 que es la Map Address

donde pone el texto en pantalla y en $00:2A5B encontramos $08 que es el número de tiles

para poner el texto “HISCORE-”.

Page 17: ROMHACKING GAMEBOY PRÁCTICO - Todo lo que quiso saber … · ^NOP _ ^No Operation _: Esta instrucción es la que vamos a utilizar para eliminar instrucciones cuando queramos por

En $00:2A64-$00:2A6C encontramos los datos para poner “SCORE” en pantalla y termina con

$00 para indicar el fin del texto. A continuación encontramos los textos del menú principal.

En $00:2A64 tenemos: 98 24 (Map Address=$9824)

$00:2A66: 06 (Nº de tiles=$06)

$00:2A67: F3 E3 EF F2 E5 CD (Texto “SCORE-”)

Vamos a hacer una modificación para ver el proceso cambiando el texto “SCORE-“ por el texto

“PUNTOS” para traducirlo al español sin poner el símbolo “-“ que ocupa 6 tiles también.

Si observamos la pantalla de “BGB VRAM Viewer” para ver los tiles que corresponden a cada

letra vemos que los valores son los siguientes:

“P”: $F0

“U”: $F5

“N”: $EE

“T”: $F4

“O”: $EF

“S”: $F3

Poniendo estos valores con un el editor hexadecimal HxD a partir de la dirección $00:2A67

obtenemos la siguiente pantalla en el emulador con lo que vemos como hemos hecho una

modificación sencilla del juego.

Si cambiamos además el byte que aparece en la dirección $00:2A65 que tiene el valor $24 por

$22 cambiamos la Map Address a $9822 con lo que la pantalla ahora quedaría como en la

captura siguiente:

Page 18: ROMHACKING GAMEBOY PRÁCTICO - Todo lo que quiso saber … · ^NOP _ ^No Operation _: Esta instrucción es la que vamos a utilizar para eliminar instrucciones cuando queramos por

Así hemos conseguido situar el texto en otra posición diferente en la pantalla de título.

El problema puede surgir cuando queramos poner un texto con más tiles en la pantalla ya que

no tenemos espacio para situar el texto en la posición donde está pero podemos buscar alguna

zona donde haya espacio en blanco en el juego.

En los juegos normalmente aparecen secuencias de valores $00 o con $FF para rellenar el

espacio en blanco ya que las ROMs de los juegos se tenían que adaptar a tamaños de 32, 64,

128,… kilobytes y para completar se añadía estos valores.

Debemos asegurarnos que la secuencia corresponde realmente a espacio en blanco porque

puede tratarse de un tile o a datos. Normalmente si son más de 16 bytes seguidos puede

tratarse de espacio.

En las direcciones $00:0061-$00:00FF encontramos un área de bytes con el valor $FF

suficientemente grande para poner datos. Normalmente esta zona suele estar vacía o con

fragmentos de rutinas.

Podemos empezar si queremos en la dirección $00:0063 donde vamos a poner los bytes:

98 02 08 E8 E9 F3 E3 EF F2 E5 CD 98 2E 07 F0 F5 EE F4 EF F3 CD 00

Aquí hemos dejado el texto “HISCORE-“ igual que estaba pero hemos puesto en lugar de

“SCORE-“ el texto “PUNTOS-“ que en lugar de 6 tiles tiene 7 tiles. También se ha cambiado la

Map Address $9824 por $9823 para posicionar el texto en pantalla de forma correcta.

Pero si cargamos el juego no se vería la modificación ya que todavía se cargan los textos que

empiezan en la dirección $00:2A59 que son los originales del juego por lo que debemos buscar

los valores hexadecimales 592A en el editor hexadecimal para ver dónde está este valor que

encontramos en $2A4B-$2A4C.

Aquí cambiamos 592A (para la dirección $00:2A59) por 6300 (para la dirección $00:0063)

donde hemos puesto ahora los textos cambiados. En la dirección donde estaban los textos

originales podríamos utilizarlos para otra cosa si no los utilizamos.

Page 19: ROMHACKING GAMEBOY PRÁCTICO - Todo lo que quiso saber … · ^NOP _ ^No Operation _: Esta instrucción es la que vamos a utilizar para eliminar instrucciones cuando queramos por

Ya con ambas modificaciones la pantalla de título del juego quedaría como:

Ya está hecha bien la modificación. Igualmente podríamos cambiar el texto “HISCORE” por

otro texto como “MAXPUNTOS” y el resto de textos de la pantalla de título.

Con la modificación anterior todavía nos han quedado los bytes $00:0079-$00:00FF sin

modificar lo que hace un total de $87 bytes=135 bytes para poner algunos textos más si

quisiéramos.

Otra opción que se podría haber utilizado es crear nuestros propios tiles aunque requiere más

trabajo para hacer varios tiles que pongan el texto que queramos intentando utilizar un

tamaño más chico de la fuente para poner con menos tiles más texto.

Esto requiere más experiencia y supone mucha más complicación. Para ello podemos buscar

donde están por ejemplo los datos de los tiles $BB-$BF que aparecen en blanco según aparece

en el “BGB VRAM Viewer”.

Hemos buscado en el banco $00 que es donde estaba el texto original para evitarnos

complicaciones de cambios de bancos. De todas formas, aunque el texto original hubiese

estado en otro banco podríamos haber utilizado el banco $00 ya que al estar en la dirección

$00:0063 no hay problemas.

Si un texto está en la dirección $00:0063 si se pasara en hl la dirección no habría que

especificar banco, lo que no ocurre cuando la dirección está comprendida entre $4000-$7FFF

que si hay que especificarlo.

No es lo mismo $01:4000 que $02:4000, $03:4000. Cuando no se especifica nada se supone

que el banco es el mismo que el del banco donde se encuentra la instrucción.

Por ejemplo, si encontramos en la dirección $01:4000 la siguiente instrucción:

Ld hl,$4036

Se supone que se carga en hl la dirección $01:4036.

Page 20: ROMHACKING GAMEBOY PRÁCTICO - Todo lo que quiso saber … · ^NOP _ ^No Operation _: Esta instrucción es la que vamos a utilizar para eliminar instrucciones cuando queramos por

También si se encuentra en el banco $00 se supone que corresponde al banco $01. Si

quisiéramos cargar un texto de otro banco tendríamos que añadir un fragmento de código

para seleccionar el banco y la cosa se complica.

Para seleccionar un banco se escribe el valor del banco entre la dirección $2000-$3FFF.

Normalmente se utiliza en la mayoría de juegos la dirección $2000 aunque se puede utilizar

cualquiera del intervalo anterior.

Si ponemos:

Ld a,$03

Ld (2000),a

Ld hl,$4036

Se carga en a el valor $03 y se selecciona el banco $03 poniendo este valor en la dirección

$2000. En hl se pone la dirección $4036 con lo que se carga en hl la dirección $03:4036.

Esto es para que vean la complicación que puede surgir si tienen que cambiar de bancos los

textos o rutinas.

Alternativamente para localizar los textos podríamos haber utilizado otra herramienta

(Translhextion) que permite la búsqueda relativa de textos.

La búsqueda comparativa permite encontrar textos que no aparecen como tales sino en

formato de tiles independientemente del valor que tenga cada letra pero esto se ve mejor con

un ejemplo.

Si abrimos con el programa el juego “Battle Bull” que hemos utilizado antes podemos buscar el

texto “HISCORE” que aparece en él y que antes localicemos.

Aparentemente es un editor hexadecimal aunque incluye esta opción de búsqueda relativa

además de la búsqueda normal.

Page 21: ROMHACKING GAMEBOY PRÁCTICO - Todo lo que quiso saber … · ^NOP _ ^No Operation _: Esta instrucción es la que vamos a utilizar para eliminar instrucciones cuando queramos por

Seleccionando la opción “Scan Relative” del menú “Search” nos aparece un cuadro de diálogo

donde ponemos el texto a buscar.

Como se ve en la captura lo encuentra en la dirección $2A5C-$2A62 tal y como habíamos visto

anteriormente. En amarillo aparece marcado el texto encontrado que como vemos no se

parece nada al texto sino que representa los tiles para poner dicho texto.

En esta ventana si se ha encontrado el texto nos permite guardar los resultados o generar una

tabla (“Generate Table”).

Podemos guardar la tabla con los valores de los tiles que corresponden a cada letra con el

nombre del juego (“battle bull.tbl”).

Si abrimos el fichero creado con el bloc de notas podemos comprobar que se trata de un

fichero normal y corriente sólo que tiene la extensión .tbl y que podemos modificar a nuestro

gusto.

Page 22: ROMHACKING GAMEBOY PRÁCTICO - Todo lo que quiso saber … · ^NOP _ ^No Operation _: Esta instrucción es la que vamos a utilizar para eliminar instrucciones cuando queramos por

Podemos ver como al valor “E1” le corresponde la letra “A” (el tile $E1=”A”), al valor “E2” le

corresponde la letra “B”,….

Si vemos en el “BGB VRAM Viewer” la pestaña “Tiles” en la pantalla de título del juego

podemos comprobar que estos datos están bien pero faltan algunos números y símbolos.

$D0=”0”, $D1=”1”,…, $D9=”9”, $DA=”:”, $DB=”;”,… que podemos añadir incluyéndolos en el

fichero “battle bull.tbl”.

D0=0

D1=1

Una vez hecho esto y guardada la tabla podemos abrir el fichero de tabla creada con el

programa utilizando la opción “Open Thingy Table…” del menú “Script”.

Page 23: ROMHACKING GAMEBOY PRÁCTICO - Todo lo que quiso saber … · ^NOP _ ^No Operation _: Esta instrucción es la que vamos a utilizar para eliminar instrucciones cuando queramos por

Yo he incluido los números y símbolos en el fichero de tabla lo que hace un total de 62

elementos tal y como se ve en la captura.

He marcado en el recuadro “Table Toolbar” la opción “Thingy View Active” para que utilice la

tabla con sus equivalencias con lo que ya vemos en la parte derecha los textos.

También marcando los textos podemos guardar el script (un fichero con todos los textos) para

lo cual los seleccionamos y pulsamos con el botón derecho para que nos aparezca un menú.

En este menú seleccionamos la opción “Dump Script…” y nos aparece una ventana donde

seleccionamos en “Dump bytes to” la opción “File” para guardarlo en un fichero.

Este fichero tiene el siguiente contenido:

Page 24: ROMHACKING GAMEBOY PRÁCTICO - Todo lo que quiso saber … · ^NOP _ ^No Operation _: Esta instrucción es la que vamos a utilizar para eliminar instrucciones cuando queramos por

{98}{02}{08}HISCORE-{98}{24}{06}SCORE-

{00}{99}{45}{0A}PUSH{C0}START{99}{67}{07}1PLAYER{99}{87}{08}2PLAYERS{99}{A7}{08}PASSW

ORD{00}{99}${0A}{6B}{6D}{6F}{71}{73}{75}{77}{79}{7B}{7B}{99}D{0A}{6C}{6E}{70}{72}{74}{76}{7

8}{7A}{7A}{7C}{00}{9A}{00}{14}LICENSED{C0}BY{C0}NINTENDO{00}{02}{00}{01}{00}{00}{01}{02}

{01}{01}{02}{00}{02}{66}{99}{86}{99}{A6}{99}{0E}{00}I{2A}{0E}{00}W{2A}{99}{45}{0A}GAME{C0}

START{00}{99}{45}{0A}{C0}{C0}{C0}{C0}{C0}{C0}{C0}{C0}{C0}{C0}

También nos da la opción de reemplazar el script que lo que hace es cargar un fichero de script

con formato similar al anterior y cambiar por el anterior.

Por ejemplo si modificamos en el script creado el texto “SCORE-“ por “PUNTOS” tal y como

aparece a continuación en el script:

{98}{02}{08}HISCORE-

{98}{24}{06}PUNTOS{00}{99}{45}{0A}PUSH{C0}START{99}{67}{07}1PLAYER{99}{87}{08}2PLAYER

S{99}{A7}{08}PASSWORD{00}{99}${0A}{6B}{6D}

{6F}{71}{73}{75}{77}{79}{7B}{7B}{99}D{0A}{6C}{6E}{70}{72}{74}{76}{78}{7A}{7A}{7C}{00}{9A}{00

}{14}LICENSED{C0}BY{C0}NINTENDO{00}{02}{00}{01}{00}{00}

{01}{02}{01}{01}{02}{00}{02}{66}{99}{86}{99}{A6}{99}{0E}{00}I{2A}{0E}{00}W{2A}{99}{45}{0A}G

AME{C0}START{00}{99}{45}{0A}{C0}{C0}{C0}{C0}{C0}{C0}{C0}

{C0}{C0}{C0}

Ahora debemos seleccionar el fichero con el script cambiado para que nos cambie el texto que

hemos modificado.

Page 25: ROMHACKING GAMEBOY PRÁCTICO - Todo lo que quiso saber … · ^NOP _ ^No Operation _: Esta instrucción es la que vamos a utilizar para eliminar instrucciones cuando queramos por

“RST”: UN BYTE PARA DOMINAR EL MUNDO

Esto es una broma pero hay una instrucción “RST” que es bastante útil para saltar a unas

determinadas posiciones del juego con un único byte.

Por ejemplo, la instrucción “jp 0008” equivale a saltar a la dirección $0008 y que se

representa con los bytes C3 08 00.

La instrucción “call 0008” equivale a llamar a la subrutina que hay en la dirección $0008 y

que se representa con los bytes CD 08 00.

Pero hay una instrucción “RST $08” que se representa con el byte $CF (1 byte) y que equivale a

la instrucción anterior “call 0008” pero ocupando sólo un byte con lo que nos ahorramos 2

bytes y podemos ponerla cuando no tenemos espacio para poner otra instrucción.

Hay una serie de instrucciones RST (RST $00, $08, $10, $18, $20, $28, $30, $38) que podemos

utilizar y otras que hacen referencia a rutinas de la consola.

RST $40: Dirección de la interrupción Vertical Blank (VBlank)

RST $48: Dirección de la interrupción de LCDC Status

RST $50: Dirección de la interrupción de Timer Overflow

RST $58: Dirección de la interrupción de Serial Transfer Completion

RST $60: Dirección de la interrupción de High-to-Low de P10-P13

Podemos utilizar el inicio de la ROM para poner rutinas siempre que no haya código en esta

área (esté llena de valores $00 o $FF indicando espacio en blanco).

Si está en blanco podemos poner fragmento de código como puede ser salto a subrutinas,…

Esto se puede ver de una forma más fácil con un ejemplo de su utilidad para lo cual vamos a

utilizar el juego “Boulder Dash”.

Si buscamos el fragmento de código donde se ponen las vidas iniciales del jugador 1 y 2 lo

encontramos en el fragmento:

ROM0:027B 3E 03 ld a,03

Page 26: ROMHACKING GAMEBOY PRÁCTICO - Todo lo que quiso saber … · ^NOP _ ^No Operation _: Esta instrucción es la que vamos a utilizar para eliminar instrucciones cuando queramos por

ROM0:027D EA 62 D7 ld (D762),a

ROM0:0280 EA 63 D7 ld (D763),a

Supongamos que quisiéramos que el jugador 2 empiece con 7 vidas y el jugador 1 con 03 tal y

como aparecía.

Aquí no tenemos espacio para poner un fragmento de código para que el jugador 2 empiece

con 7 vidas que sería:

3E 07 ld a,07

EA 63 D7 ld (D763),a

La modificación que podríamos hacer sería:

ROM0:0280 3E 07 ld a,07

ROM0:0282 E7 rst 20

Esto lo que hace es poner en el registro “a” el valor $07 y la siguiente instrucción “rst 20”

equivale a llamar a la rutina que hay en la dirección $00:0020 que está en blanco (está llena de

valores $FF).

En $0020 es donde debemos poner lo que nos falta para poner este valor $07 en la dirección

donde se ponen las vidas del jugador 2 ($D763).

ROM0:0020 EA 63 D7 ld (D763),a

ROM0:0023 C9 ret

La última instrucción “ret” lo que hace es regresar a la siguiente instrucción que aparece

después del “rst 20” que se encuentra en $00:0283 para continuar con el proceso.

Otro juego que podemos modificar para utilizar esta instrucción puede ser el “Magical Chase”

de Gameboy Color que dispone de un truco que permite mostrar una opción adicional en el

menu principal para seleccionar el nivel donde empezar el juego.

Esto se consigue con la combinación de botones Arriba, Abajo, Arriba, Abajo, B, B, B, B,

Izquierda, Derecha, Izquierda, Derecha, A.

Los primeros $40 bytes del juego tienen el valor $00 con lo que podemos utilizarlos para poner

fragmentos de código.

Page 27: ROMHACKING GAMEBOY PRÁCTICO - Todo lo que quiso saber … · ^NOP _ ^No Operation _: Esta instrucción es la que vamos a utilizar para eliminar instrucciones cuando queramos por

El botón pulsado se guarda en las direcciones de la RAM $C0BA y $C0BB . En la dirección

$D829 se pone el valor $00 (cheat no active) y $01 (cheat active cuando se ha pulsado la

combinación de botones para activar el truco).

Si ponemos un breakpoint en la dirección $D829 para comprobar cuando se escribe en esa

dirección el emulador se para en el fragmento:

ROM0:084F 21 00 C0 ld hl,C000

ROM0:0852 AF xor a

ROM0:0853 47 ld b,a

ROM0:0854 0E 20 ld c,20

ROM0:0856 22 ldi (hl),a

ROM0:0857 05 dec b

ROM0:0858 20 FC jr nz,0856

ROM0:085A 0D dec c

ROM0:085B 20 F9 jr nz,0856

ROM0:085D C9 ret

Sin embargo, aquí no se pone el valor $00 sólo en $D829 sino desde $C000 en adelante

llenando la RAM con este valor.

Si se hubiese puesto sólo el valor $00 en la dirección $D829 podríamos haber modificado la

instrucción para poner $01 en su lugar con lo que se activaría el cheat pero aquí no podemos

hacerlo.

Podemos hacer una modificación cambiando la instrucción en $00:085D por:

ROM0:085D C7 rst $00

También tenemos que poner un fragmento en la dirección $00:0000:

ROM0:0000 3E 01 ld a,01

ROM0:0002 EA 29 D8 ld (D829),a

ROM0:0005 C9 ret

Esto lo que hace es una vez que se ha llenado la RAM con el valor $00 se utiliza “RST $00” para

llamar a la rutina en $00:0000 donde se pone el valor $01 en la dirección $D829 para que el

cheat esté activo independientemente del botón o botones pulsados. Finalmente cómo

habíamos quitado la instrucción “RET” en $00:085D tenemos que ponerla para que regrese de

la subrutina.

Se puede jugar el juego y comprobar que esta modificación realmente tiene el efecto buscado

y que todo funciona correctamente igual que en el juego original.

Esta modificación no es la única que podemos utilizar para que funcione el cheat de forma

automatic sin pulsar ningún botón. Podemos localizar el fragmento de código que comprueba

Page 28: ROMHACKING GAMEBOY PRÁCTICO - Todo lo que quiso saber … · ^NOP _ ^No Operation _: Esta instrucción es la que vamos a utilizar para eliminar instrucciones cuando queramos por

la combinación de botones y pone el valor $01 si es correcto poniendo un breakpoint cuando

se escriba el valor $D829 en $01.

Esto ocurre en $06:5F5C donde se pone este valor y un poco más arriba encontramos:

ROM6:5F23 21 6F DA ld hl,DA6F

ROM6:5F26 2A ldi a,(hl)

ROM6:5F27 CB 57 bit 2,a

ROM6:5F29 C8 ret z

ROM6:5F2A 2A ldi a,(hl)

ROM6:5F2B CB 5F bit 3,a

ROM6:5F2D C8 ret z

ROM6:5F2E 2A ldi a,(hl)

ROM6:5F2F CB 57 bit 2,a

ROM6:5F31 C8 ret z

ROM6:5F32 2A ldi a,(hl)

ROM6:5F33 CB 5F bit 3,a

ROM6:5F35 C8 ret z

ROM6:5F36 2A ldi a,(hl)

ROM6:5F37 CB 6F bit 5,a

ROM6:5F39 C8 ret z

ROM6:5F3A 2A ldi a,(hl)

ROM6:5F3B CB 6F bit 5,a

ROM6:5F3D C8 ret z

ROM6:5F3E 2A ldi a,(hl)

ROM6:5F3F CB 6F bit 5,a

ROM6:5F41 C8 ret z

ROM6:5F42 2A ldi a,(hl)

ROM6:5F43 CB 6F bit 5,a

ROM6:5F45 C8 ret z

ROM6:5F46 2A ldi a,(hl)

ROM6:5F47 CB 4F bit 1,a

ROM6:5F49 C8 ret z

Page 29: ROMHACKING GAMEBOY PRÁCTICO - Todo lo que quiso saber … · ^NOP _ ^No Operation _: Esta instrucción es la que vamos a utilizar para eliminar instrucciones cuando queramos por

ROM6:5F4A 2A ldi a,(hl)

ROM6:5F4B CB 47 bit 0,a

ROM6:5F4D C8 ret z

ROM6:5F4E 2A ldi a,(hl)

ROM6:5F4F CB 4F bit 1,a

ROM6:5F51 C8 ret z

ROM6:5F52 2A ldi a,(hl)

ROM6:5F53 CB 47 bit 0,a

ROM6:5F55 C8 ret z

ROM6:5F56 2A ldi a,(hl)

ROM6:5F57 CB 67 bit 4,a

ROM6:5F59 C8 ret z

ROM6:5F5A 3E 01 ld a,01

ROM6:5F5C EA 29 D8 ld (D829),a

ROM6:5F5F C9 ret

En la primera instrucción $06:5F23 se carga la dirección $DA6F que es también donde se

guarda la combinación de botones que introducimos ($DA6F-$DA7B).

Se comprueba el bit 2 (Arriba), el bit 3 (Abajo), el bit 5 (B) cuatro veces seguidas, el bit 1

(Izquierda), el bit 0 (Derecha) y el bit 4 (A). También podríamos cambiar la combinación de

botones para el cheat cambiando estas comprobaciones.

Podemos buscar donde se llama a esta rutina lo que se encuentra en $06:5F1A:

ROM6:5F1A CD 23 5F call 5F23

Si sustituimos esta instrucción por:

ROM6:5F1A CD 5A 5F call 5F5A

Se salta la rutina de comprobación y va directamente a la dirección $06:5F5A donde se pone el

valor $01 en $D829.

Aquí tendremos que pulsar algún botón para que funcione.

Buscando esto encontré un segundo cheat que te da 99999 orbs, invulnerabilidad y la opción

de seleccionar el nivel con lo que aparece la cuarta opción del menú y en la pantalla de nivel

aparecen 2 opciones extras:

Page 30: ROMHACKING GAMEBOY PRÁCTICO - Todo lo que quiso saber … · ^NOP _ ^No Operation _: Esta instrucción es la que vamos a utilizar para eliminar instrucciones cuando queramos por

Esto puede ser accesible poniendo el valor $02 en la dirección $D829 por lo que si queremos

tener este menú ampliado podríamos haber cambiado el fragmento que pusimos en $00:0000

para poner el valor $02 en lugar de $01.

El fragmento que comprueba la combinación de botones para activar este nuevo cheat lo

encontramos en $06:5F60-$06:5FAC:

ROM6:5F60 21 6B DA ld hl,DA6B

ROM6:5F63 2A ldi a,(hl)

ROM6:5F64 CB 57 bit 2,a

ROM6:5F66 C8 ret z

ROM6:5F67 2A ldi a,(hl)

ROM6:5F68 CB 5F bit 3,a

ROM6:5F6A C8 ret z

ROM6:5F6B 2A ldi a,(hl)

ROM6:5F6C CB 57 bit 2,a

ROM6:5F6E C8 ret z

ROM6:5F6F 2A ldi a,(hl)

ROM6:5F70 CB 5F bit 3,a

ROM6:5F72 C8 ret z

ROM6:5F73 2A ldi a,(hl)

ROM6:5F74 CB 77 bit 6,a

ROM6:5F76 C8 ret z

ROM6:5F77 2A ldi a,(hl)

ROM6:5F78 CB 4F bit 1,a

ROM6:5F7A C8 ret z

ROM6:5F7B 2A ldi a,(hl)

Page 31: ROMHACKING GAMEBOY PRÁCTICO - Todo lo que quiso saber … · ^NOP _ ^No Operation _: Esta instrucción es la que vamos a utilizar para eliminar instrucciones cuando queramos por

ROM6:5F7C CB 6F bit 5,a

ROM6:5F7E C8 ret z

ROM6:5F7F 2A ldi a,(hl)

ROM6:5F80 CB 6F bit 5,a

ROM6:5F82 C8 ret z

ROM6:5F83 2A ldi a,(hl)

ROM6:5F84 CB 57 bit 2,a

ROM6:5F86 C8 ret z

ROM6:5F87 2A ldi a,(hl)

ROM6:5F88 CB 5F bit 3,a

ROM6:5F8A C8 ret z

ROM6:5F8B 2A ldi a,(hl)

ROM6:5F8C CB 57 bit 2,a

ROM6:5F8E C8 ret z

ROM6:5F8F 2A ldi a,(hl)

ROM6:5F90 CB 5F bit 3,a

ROM6:5F92 C8 ret z

ROM6:5F93 2A ldi a,(hl)

ROM6:5F94 CB 77 bit 6,a

ROM6:5F96 C8 ret z

ROM6:5F97 2A ldi a,(hl)

ROM6:5F98 CB 47 bit 0,a

ROM6:5F9A C8 ret z

ROM6:5F9B 2A ldi a,(hl)

ROM6:5F9C CB 6F bit 5,a

ROM6:5F9E C8 ret z

ROM6:5F9F 2A ldi a,(hl)

ROM6:5FA0 CB 6F bit 5,a

ROM6:5FA2 C8 ret z

ROM6:5FA3 2A ldi a,(hl)

ROM6:5FA4 CB 67 bit 4,a

Page 32: ROMHACKING GAMEBOY PRÁCTICO - Todo lo que quiso saber … · ^NOP _ ^No Operation _: Esta instrucción es la que vamos a utilizar para eliminar instrucciones cuando queramos por

ROM6:5FA6 C8 ret z

ROM6:5FA7 3E 02 ld a,02

ROM6:5FA9 EA 29 D8 ld (D829),a

ROM6:5FAC C9 ret

Si analizamos el código podemos hallar la combinación de botones que activa el cheat viendo

los bits que comprueba: 2 (Arriba), 3 (Abajo), 2 (Arriba), 3 (Abajo), 6 (Select), 1 (Izquierda), 5

(B), 5 (B), 2 (Arriba), 3 (Abajo), 2 (Arriba), 3 (Abajo), 6 (Select), 0 (Derecha), 5 (B), 5 (B), 4 (A)

según parece.

Podemos activar este cheat también introduciendo en la pantalla de cheats la dirección $D829

y el valor $02.

Como se ha visto el uso de la instrucción “RST” no es posible cuando hay código en esta parte

del juego pero también se podría hacer aunque es más complicado ya que hay que mover más

código.

A veces también se aprovecha espacio en blanco para poner ahí rutinas introduciendo saltos a

estas rutinas que colocamos en áreas con valores $00 o $FF. En este caso debemos

asegurarnos que se trata de espacio en blanco realmente.

PASSWORDS DE LOS JUEGOS

Hay algunos juegos que tienen un sistema de passwords para empezar en un nivel

determinado.

En estos juegos los passwords pueden estar como tales en la ROM en formato texto, en

formato tile, o con alguna codificación.

En otras ocasiones no hay passwords en la ROM sino que hay una rutina para comprobar si el

password introducido es correcto y en los que es más complicado localizar la rutina y obtener

los passwords válidos.

A través de ejemplos se va a tratar varias de las opciones que nos podremos encontrar en

juegos de Gameboy.

Para el caso de passwords en el juego en formato texto vamos a utilizar el juego “Judge

Dredd”.

Page 33: ROMHACKING GAMEBOY PRÁCTICO - Todo lo que quiso saber … · ^NOP _ ^No Operation _: Esta instrucción es la que vamos a utilizar para eliminar instrucciones cuando queramos por

Este juego permite la introducción de 8 letras para el password del juego. Podemos

encontrarnos con el caso de que no conozcamos ningún password y tendríamos que partir de

cero localizando tanto los passwords como la rutina.

También puede darse el caso de que conozcamos los passwords del juego y baste con

localizarlos en el juego (que es tan simple como buscar el password en formato texto) en el

fichero del juego (ROM) utilizando un editor hexadecimal. Posteriormente podemos localizar la

rutina de comprobación de passwords.

Suponiendo que no conocemos ninguna password del juego vamos a localizar donde se

almacena las letras del password que vamos introduciendo en la RAM para lo cual vamos a

utilizar el buscador de cheats que incluye el emulador BGB.

El proceso es simple basta con poner por ejemplo, la letra “A” en la primera letra del password

e iniciar la búsqueda de cheats utilizando la opción “Cheat searcher” del menú “Other” y

pulsar el botón “Start”.

Page 34: ROMHACKING GAMEBOY PRÁCTICO - Todo lo que quiso saber … · ^NOP _ ^No Operation _: Esta instrucción es la que vamos a utilizar para eliminar instrucciones cuando queramos por

Aquí aparecen las 8319 direcciones posibles de la RAM donde están almacenadas las letras que

introducimos para el password.

Ahora sin cerrar esta ventana podemos ir cambiando la primera letra del password poniendo

“B” y pulsando “above” en la pantalla de arriba y luego “Search” con lo que se buscan

direcciones de la RAM en las que ha aumentado el valor que incluyen con lo disminuye el

número de direcciones de la RAM que en mi caso se queda sólo en 22.

Podemos poner “C” y darle otra vez a “Search” con lo que a mí me quedan 9 direcciones sólo y

una de ellas es donde se guarda la 1ª letra introducida del password.

Repetiendo el proceso nos quedamos con 3 direcciones posibles:

DB90=06, DEE6=46, DEEA=46.

Para asegurarnos cuál de las 3 es la verdadera podemos hacer el mismo proceso con la 2ª letra

para lo cual anotadas las anteriores pulsamos “Start” para iniciar la búsqueda con las 8319

direcciones de la RAM.

Al hacer esto nos encontramos con las 3 direcciones posibles para la 2ª letra del password:

DB91=06, DEE6=46, DEEA=46.

Si comparamos ambos grupos de direcciones vemos que DEE6 y DEEA aparecen en las dos y

corresponden a la letra actual del password que estamos introduciendo en formato ASCII. El

código 46 corresponde a la letra “F” pero estas direcciones no son donde se almacenan las

letras del password introducidas.

Page 35: ROMHACKING GAMEBOY PRÁCTICO - Todo lo que quiso saber … · ^NOP _ ^No Operation _: Esta instrucción es la que vamos a utilizar para eliminar instrucciones cuando queramos por

Si nos fijamos en las 2 que nos quedan y que no se repiten son las que buscamos. La de arriba

DB90=06 corresponde a la 1ª letra del password, DB91=06 corresponde a la 2ª letra del

password, con lo que las siguientes son DB92, DB93, DB94, DB95, DB96 y DB97 (ya que hay 8

letras en el password).

Los valores que toman estas direcciones son $01=”A”, $02=”B”, $03=”C”, $04=”D”, $05=”E”,

$06=”F”,…., $1A=”Z”.

Por lo tanto, debe haber una rutina que comprueba los valores que hemos introducido que

están almacenadas en las direcciones de la RAM comprendidas entre DB90-DB97 con las que

hay en el juego.

Para averiguarlo vamos a introducir el password que queramos dando igual que sea incorrecto

y una vez hecho esto antes de pulsar “Start” para que compruebe si el password es correcto

vamos a poner un breakpoint por ejemplo en la dirección $DB90 (1ª letra del password) pero

en lugar de cuando se escribe (“w”) debemos ver cuando se lee la dirección $DB90 ya que la

rutina lo que hace es leer las letras del password.

Seleccionamos la opción “Access breakpoints” del menú “Debug” y lo dejamos tal y como se ve

en la siguiente imagen:

Donde pone la dirección “DB90” podemos poner un rango de direcciones (como “DB90-DB97”

pero ponemos sólo una dirección). En “value” podemos poner un valor para que se pare el

emulador cuando se escriba o lea esa dirección y coincida con ese valor.

“on write” se selecciona cuando se quiere ver cuando se escribe en esa dirección, “on execute”

cuando se ejecuta una determinada dirección y “on jump” para saltos a una dirección.

Si ahora pulsamos el botón “Start” (que hayamos configurado en el emulador que corresponde

a ese botón de la consola) haremos que se pare el emulador porque se lee la dirección $DB90.

Page 36: ROMHACKING GAMEBOY PRÁCTICO - Todo lo que quiso saber … · ^NOP _ ^No Operation _: Esta instrucción es la que vamos a utilizar para eliminar instrucciones cuando queramos por

Si nos fijamos en la pantalla del Debugger del emulador vemos como se ha parado en la

dirección $03:6256 que contiene la instrucción “cp (hl)”.

En realidad es “cp a,(hl)” que compara el valor de a con el que hay en la dirección contenida en

hl que como vemos en la parte derecha donde están los valores de los registros tiene “hl=

DB90”.

Si nos fijamos un poco más arriba vemos como en $03:624E se pone en el registro “de” el valor

$42EB por lo que en “de” se pone la dirección $03:42EB donde está uno de los passwords del

juego (“SENTENCE”). En el fichero de la ROM si lo abrimos con el editor hexadecimal HxD la

encontramos a partir de C2EB ya que se trata del banco $03 que comienza en $C000.

Banco $03:4000 corresponde a $C000 y por tanto $03:42EB corresponde a $C2EB y que

podemos modificar al estar en formato texto por cualquier cadena de 8 letras con lo que

modificaríamos el primer password (“SENTENCE”) por otra.

Si ponemos “SENCILLO” que tiene 8 letras al poner este password el juego lo daría como

correcto y empezaríamos en el nivel que corresponda.

La rutina de comprobación completa es la siguiente y podemos guardarla en un fichero para

analizarla:

ROM3:624B 21 90 DB ld hl,DB90

ROM3:624E 11 EB 42 ld de,42EB

ROM3:6251 06 08 ld b,08

ROM3:6253 1A ld a,(de)

ROM3:6254 D6 40 sub a,40

ROM3:6256 BE cp (hl)

Page 37: ROMHACKING GAMEBOY PRÁCTICO - Todo lo que quiso saber … · ^NOP _ ^No Operation _: Esta instrucción es la que vamos a utilizar para eliminar instrucciones cuando queramos por

ROM3:6257 C2 63 62 jp nz,6263

ROM3:625A 13 inc de

ROM3:625B 23 inc hl

ROM3:625C 05 dec b

ROM3:625D C2 53 62 jp nz,6253

ROM3:6260 C3 9C 62 jp 629C

ROM3:6263 21 90 DB ld hl,DB90

ROM3:6266 11 F7 42 ld de,42F7

ROM3:6269 06 08 ld b,08

ROM3:626B 1A ld a,(de)

ROM3:626C D6 40 sub a,40

ROM3:626E BE cp (hl)

ROM3:626F C2 7B 62 jp nz,627B

ROM3:6272 13 inc de

ROM3:6273 23 inc hl

ROM3:6274 05 dec b

ROM3:6275 C2 6B 62 jp nz,626B

ROM3:6278 C3 A2 62 jp 62A2

ROM3:627B 21 90 DB ld hl,DB90

ROM3:627E 11 03 43 ld de,4303

ROM3:6281 06 08 ld b,08

ROM3:6283 1A ld a,(de)

ROM3:6284 D6 40 sub a,40

ROM3:6286 BE cp (hl)

ROM3:6287 C2 93 62 jp nz,6293

ROM3:628A 13 inc de

ROM3:628B 23 inc hl

ROM3:628C 05 dec b

ROM3:628D C2 83 62 jp nz,6283

ROM3:6290 C3 A8 62 jp 62A8

ROM3:6293 11 EB 41 ld de,41EB

Page 38: ROMHACKING GAMEBOY PRÁCTICO - Todo lo que quiso saber … · ^NOP _ ^No Operation _: Esta instrucción es la que vamos a utilizar para eliminar instrucciones cuando queramos por

ROM3:6296 CD B2 5E call 5EB2

ROM3:6299 C3 D9 60 jp 60D9

Básicamente lo que hace en primer lugar es poner en el registro “hl” la dirección que

corresponde a la 1ª letra del password en RAM y en el registro “de” se ponen las direcciones

donde están los passwords reales del juego que son ($03:42EB, $03:42F7 y $03:4303):

“SENTENCE”, “SOFTWARE” y “ANDERSON”.

En el registro “b” se pone el número de letras que tiene el password que es $08.

Los passwords que están en el juego se leen y se disminuye el valor de cada letra que hay en la

ROM en $40 para convertirlo al formato que está en la RAM para así poder compararlo.

En la ROM el password “SENTENCE” está almacenado como 53 45 4E 54 45 4E 43 45 pero en la

RAM está almacenada como 13 05 0E 14 05 0E 03 05.

Así al restarle a los primeros valores $40 obtendríamos los segundos para lo cual el programa

utiliza la instrucción “sub a,40”.

Los passwords terminan con el valor $FF para indicar que se ha acabado y antes de ellos

aparecen los dígitos hexadecimales 16 0C 12 que todavía no he comprobado si tienen alguna

utilidad.

Las instrucciones “inc hl” e “inc de” se utilizan para incrementar las direcciones donde están

las letras del password en RAM y en el juego y así ir comparando cada una de las letras. La

instrucción “dec b” disminuye el número de letras que quedan por comprobar del password.

Si eliminamos la primera instrucción “sub a,40” que se encuentra la dirección $03:6254

($E254) que se codifica como “D6 40” cambiandólo por “00 00” que equivale a 2 instrucciones

“nop” (NOt oPeration: No hace nada) conseguimos que no se disminuya el valor de cada una

de las letras del password.

Sin embargo, ahora si introducimos el password “SENTENCE” con esta modificación no

aceptará el password como correcto para ello tendríamos que cambiar el texto “SENTENCE”

(53 45 4E 54 45 4E 43 45 en hexadecimal en la ROM) que encontramos en la dirección

$03:42EB-03:42F2 ($C2EB-$C2F2) por los valores hexadecimales que se ponen la RAM (13 05

0E 14 05 0E 03 05).

Ahora si aceptaría este password como correcto y tendría un sistema híbrido de passwords (el

primero con una codificación sin restar $40 que no está en formato de texto y las otras dos

passwords en formato texto y que restan $40 para comprobarlas).

Esta modificación es para trastear un poco en la ROM y ver hasta qué punto podemos

modificarla. Los programadores del juego podrían haberlo hecho así si hubieran querido sin

tener que utilizar 3 veces la instrucción “sub a,40” con lo que se habrían ahorrado 6 bytes de

espacio (lo que en realidad no es mucho) pero también podría haber supuesto un pequeño de

ahorro de tiempo de proceso al no tener que ejecutar esta instrucción.

Podríamos convertir las otras dos passwords al formato que aparece en la RAM eliminando las

otras instrucciones “sub a,40” que aparecen si quisíeramos.

Page 39: ROMHACKING GAMEBOY PRÁCTICO - Todo lo que quiso saber … · ^NOP _ ^No Operation _: Esta instrucción es la que vamos a utilizar para eliminar instrucciones cuando queramos por

En otros juegos no se ponen las diferentes direcciones donde están los passwords del juego

sino que están todos los passwords juntos y se va incrementando la dirección que hay en “de”

hasta que se llega al final de los passwords. Si se llega al final es porque el password es

incorrecto y si coincide se coge un contador que se pone en otro registro para saber a que

nivel corresponde ese password.

La rutina de comprobación acaba con la instrucción en $03:6290 pero un poco más adelante

encontramos lo siguiente:

ROM3:629C 3E 03 ld a,03

ROM3:629E EA 30 DB ld (DB30),a

ROM3:62A1 C9 ret

ROM3:62A2 3E 04 ld a,04

ROM3:62A4 EA 30 DB ld (DB30),a

ROM3:62A7 C9 ret

ROM3:62A8 3E 06 ld a,06

ROM3:62AA EA 30 DB ld (DB30),a

ROM3:62AD C9 ret

En esta dirección ($DB30) se almacena el valor del nivel que tiene el valor $00 para el nivel

inicial, el valor $03 para el nivel con password “SENTENCE”, el valor $04 para el nivel con

password “SOFTWARE”y $06 para el nivel con password “ANDERSON”.

En la dirección $03:6260 toma como válido el password “SENTENCE” y salta a $03:629C para

poner el valor $03 en $DB30, en $03:6278 toma como válido el password “SOFTWARE” y salta

a $03:62A2 para poner el valor $04 en $DB30 y en $03:6290 toma como válido el password

“ANDERSON” y salta a la dirección $03:62A8 para poner el valor $06 en la dirección $DB30.

Con la búsqueda de los passwords del juego hemos localizado éstos, la rutina de password y

donde se almacena el número de nivel en la RAM.

Pero podríamos conocer algo más como es el fragmento de código que se encarga de cambiar

la posición sobre la que está el cursor del password y cambiar la letra actual y ponerla en la

pantalla.

Si utilizamos el “bgb cheat searcher” para averiguar la dirección de la RAM donde se guarda la

posición sobre la que está el cursor del password basta con situarnos en la primera raya que

aparece para poner letras e ir avanzando viendo cómo va cambiando el valor en la RAM.

Al hacer esto comprobamos que se guarda en la dirección $D93D de la RAM con los valores

$00 (1ª letra), $01 (2ª letra),…, $07 (8ª letra).

Es decir, si el cursor que aparece en la pantalla de introducción de password está sobre la 5ª

letra del password tendrá la dirección $D93D el valor $04 por lo que poniendo un breakpoint

en esta dirección cuando se escribe podemos se pone el valor inicial (que es $00, ya que al

inicio se sitúa sobre la 1ª letra) y donde se aumenta o disminuye este valor.

En el siguiente fragmento se pone el valor inicial:

Page 40: ROMHACKING GAMEBOY PRÁCTICO - Todo lo que quiso saber … · ^NOP _ ^No Operation _: Esta instrucción es la que vamos a utilizar para eliminar instrucciones cuando queramos por

ROM3:6228 AF xor a

ROM3:6229 EA 3D D9 ld (D93D),a

La instrucción “xor a” (o “xor a,a”) equivale a “a=$00) con lo que se pone el valor de a=$00=1ª

letra password en la dirección $D93D=Posición letra password.

En este fragmento se encuentra el código que cambia la posición de la letra del password

(cuando se incrementa o disminuye el valor que hay en la dirección $D93D) y también el que

cambia la letra que vamos poniendo en el password ($DB90-$DB97) en la RAM:

ROM3:6322 FA 3D D9 ld a,(D93D)

ROM3:6325 A7 and a

ROM3:6326 C8 ret z

ROM3:6327 3D dec a

ROM3:6328 EA 3D D9 ld (D93D),a

ROM3:632B 3E 1E ld a,1E

ROM3:632D CD 35 23 call 2335

ROM3:6330 C3 AE 62 jp 62AE

ROM3:6333 FA 3D D9 ld a,(D93D)

ROM3:6336 FE 07 cp a,07

ROM3:6338 C8 ret z

ROM3:6339 3C inc a

ROM3:633A EA 3D D9 ld (D93D),a

ROM3:633D 3E 1E ld a,1E

ROM3:633F CD 35 23 call 2335

ROM3:6342 C3 AE 62 jp 62AE

ROM3:6345 FA 3D D9 ld a,(D93D)

ROM3:6348 6F ld l,a

ROM3:6349 26 00 ld h,00

ROM3:634B 11 90 DB ld de,DB90

ROM3:634E 19 add hl,de

ROM3:634F 7E ld a,(hl)

ROM3:6350 3C inc a

ROM3:6351 FE 1B cp a,1B

ROM3:6353 20 01 jr nz,6356

Page 41: ROMHACKING GAMEBOY PRÁCTICO - Todo lo que quiso saber … · ^NOP _ ^No Operation _: Esta instrucción es la que vamos a utilizar para eliminar instrucciones cuando queramos por

ROM3:6355 AF xor a

ROM3:6356 77 ld (hl),a

ROM3:6357 3E 1E ld a,1E

ROM3:6359 C3 35 23 jp 2335

ROM3:635C FA 3D D9 ld a,(D93D)

ROM3:635F 6F ld l,a

ROM3:6360 26 00 ld h,00

ROM3:6362 11 90 DB ld de,DB90

ROM3:6365 19 add hl,de

ROM3:6366 7E ld a,(hl)

ROM3:6367 3D dec a

ROM3:6368 FE FF cp a,FF

ROM3:636A 20 02 jr nz,636E

ROM3:636C 3E 1A ld a,1A

ROM3:636E 77 ld (hl),a

ROM3:636F 3E 1E ld a,1E

ROM3:6371 C3 35 23 jp 2335

ROM3:6374 CD DD 1E call 1EDD

ROM3:6377 CD 78 1C call 1C78

En la dirección $03:6351 se comprueba si el valor de la letra actual del password es $1B y en

caso afirmativo se pone el valor $00 cuando se incrementa la letra.

En la dirección $03:6368 se comprueba si el valor de la letra actual del password es $FF cuando

se disminuye este valor y en caso afirmativo se pone el valor $1A=”Z”.

Vamos a avanzar un poco más para localizar el fragmento donde se pone el password inicial “--

------“ en pantalla y se va poniendo también el pasword que vamos introduciendo en la

pantalla.

Si abrimos el “BGB VRAM Viewer” en la pestaña “BG map” podemos comprobar como en las

direcciones $9A06-$9A0D=Map Address se pone el tile $E4 que corresponde al símbolo “-“ por

lo que ponemos un breakpoint en la dirección $9A06 con el valor $E4 cuando se escriba en

esta dirección.

Esta parte es bastante más difícil en este juego pero al poner el breakpoint el emulador se para

en la dirección $03:5F2B donde encontramos la siguiente rutina:

ROM3:5EFD D5 push de

ROM3:5EFE 6F ld l,a

Page 42: ROMHACKING GAMEBOY PRÁCTICO - Todo lo que quiso saber … · ^NOP _ ^No Operation _: Esta instrucción es la que vamos a utilizar para eliminar instrucciones cuando queramos por

ROM3:5EFF 26 40 ld h,40

ROM3:5F01 7E ld a,(hl)

ROM3:5F02 C6 C8 add a,C8

ROM3:5F04 5F ld e,a

ROM3:5F05 FA 4E D9 ld a,(D94E)

ROM3:5F08 D6 03 sub a,03

ROM3:5F0A 6F ld l,a

ROM3:5F0B 26 00 ld h,00

ROM3:5F0D 29 add hl,hl

ROM3:5F0E 29 add hl,hl

ROM3:5F0F 29 add hl,hl

ROM3:5F10 29 add hl,hl

ROM3:5F11 29 add hl,hl

ROM3:5F12 01 00 98 ld bc,9800

ROM3:5F15 09 add hl,bc

ROM3:5F16 FA 4D D9 ld a,(D94D)

ROM3:5F19 D6 06 sub a,06

ROM3:5F1B 4F ld c,a

ROM3:5F1C 06 00 ld b,00

ROM3:5F1E 09 add hl,bc

ROM3:5F1F F0 41 ld a,(ff00+41)

ROM3:5F21 E6 02 and a,02

ROM3:5F23 28 FA jr z,5F1F

ROM3:5F25 F0 41 ld a,(ff00+41)

ROM3:5F27 E6 02 and a,02

ROM3:5F29 20 FA jr nz,5F25

ROM3:5F2B 73 ld (hl),e

ROM3:5F2C FA 4D D9 ld a,(D94D)

ROM3:5F2F 3C inc a

ROM3:5F30 EA 4D D9 ld (D94D),a

ROM3:5F33 D1 pop de

Page 43: ROMHACKING GAMEBOY PRÁCTICO - Todo lo que quiso saber … · ^NOP _ ^No Operation _: Esta instrucción es la que vamos a utilizar para eliminar instrucciones cuando queramos por

ROM3:5F34 C9 ret

Como se muestra el código realiza muchas operaciones y utiliza los registros para poner los

datos en la pantalla.

En la dirección $03:5F2B está lo que buscamos y es que pone el valor que hay en el registro “e”

en la dirección contenida en el registro “hl” (que contiene la Map Address donde pone los

passwords en pantalla). Este fragmento pone tanto el password inicial como se encarga de

poner el password que vamos introduciendo.

El registro “de” tiene el valor $41E4 donde el registro “e”=$E4=Tile “-“ y el registro “d” tiene el

valor $41 que puede hacer referencia a la dirección $03:4100 ($C100) donde están en la ROM

las posibles letras que podemos seleccionar para poner el password “-

ABCDEFGHIJKLMNOPQRSTUVWXYZ”.

En $03:5F1F encontramos la instrucción “ld a,(ff00+41)” que carga en a el valor que hay en la

dirección $FF41=LCD Status y la siguiente instrucción “and a,02” es una operación lógica en la

que coge el valor que hay en a y se queda con el bit marcado en x (000000x0).

Esto lo hace para comprobar V-Blank para poner datos en pantalla.

KID DRACULA PASSWORDS

Este juego utiliza un sistema de passwords en el que tenemos que introducir 4 dígitos

numéricos y en los que los passwords del juego están almacenados en formato tile teniendo

los valores de cada dígito siguientes:

“1”: $A2, “2”: $A3, “3”: $A4, “4”: $A5, “5”: $A6, “6”: $A7, “7”: $A8, “8”: $A9, “9”: $AA.

Las direcciones de la RAM donde se guardan los dígitos que vamos introduciendo están en las

direcciones $CDA2-$CDA5.

Page 44: ROMHACKING GAMEBOY PRÁCTICO - Todo lo que quiso saber … · ^NOP _ ^No Operation _: Esta instrucción es la que vamos a utilizar para eliminar instrucciones cuando queramos por

Encontramos estos passwords desde la dirección $3137D-$313D3 ($0C:537D-$0C:53D3)

incluidas y aparecen dos veces seguidas cada password.

Poniendo un breakpoint cuando se lea entre las direcciones $0C:537D-$0C:53D3 encontramos

que el emulador se para en la dirección $00:16DD donde se van comparando cada uno de los

dígitos del password donde encontramos:

ROM0:16BE 21 C3 C9 ld hl,C9C3

ROM0:16C1 35 dec (hl)

ROM0:16C2 C0 ret nz

ROM0:16C3 3E 10 ld a,10

ROM0:16C5 EA CE C8 ld (C8CE),a

ROM0:16C8 C3 37 1E jp 1E37

ROM0:16CB 1E 00 ld e,00

ROM0:16CD CD 93 2C call 2C93

ROM0:16D0 21 7D 53 ld hl,537D

ROM0:16D3 01 A2 CD ld bc,CDA2

ROM0:16D6 16 04 ld d,04

ROM0:16D8 7B ld a,e

ROM0:16D9 87 add a

ROM0:16DA 87 add a

ROM0:16DB EF rst 28

ROM0:16DC 0A ld a,(bc)

ROM0:16DD BE cp (hl)

ROM0:16DE 23 inc hl

ROM0:16DF 20 2C jr nz,170D

ROM0:16E1 0C inc c

ROM0:16E2 15 dec d

ROM0:16E3 20 F7 jr nz,16DC

En el registro “hl” se pone la dirección $0C:537D donde están los passwords del juego, en el

registro “bc” se pone la dirección $CDA2=1º dígito del password y en el registro “d” se pone el

valor $04=Nº de dígitos del password y que se va disminuyendo una vez que se compara cada

dígito.

Sin embargo, aquí no encontramos aparentemente ninguna referencia que nos indique que el

banco sea $0C pero en la dirección $00:16CD encontramos una llamada a la dirección

$00:2C93:

Page 45: ROMHACKING GAMEBOY PRÁCTICO - Todo lo que quiso saber … · ^NOP _ ^No Operation _: Esta instrucción es la que vamos a utilizar para eliminar instrucciones cuando queramos por

ROM0:16CD CD 93 2C call 2C93

En esta dirección encontramos una rutina donde se selecciona el banco $0C poniendo este

valor en la dirección $2345:

ROM0:2C93 3E 0C ld a,0C

ROM0:2C95 EA 45 23 ld (2345),a

ROM0:2C98 C9 ret

PAC-ATTACK PASSWORDS

El anterior juego tenía un sistema basado en letras en las que las passwords están en el juego

en formato texto y ahora vamos a ver otro juego en el que los passwords no aparecen en

formato texto sino con otra codificación.

Buscando con el “bgb cheat searcher” encontramos que el password se guarda en la RAM en

las direcciones $C3E8-$C3EA.

Este juego tiene un sistema de 3 letras para formar el password de las que aparecen en la

tabla.

Poniendo un breakpoint en la dirección $C3EA al leer el emulador se para en la dirección

$00:1333 donde encontramos lo siguiente:

Page 46: ROMHACKING GAMEBOY PRÁCTICO - Todo lo que quiso saber … · ^NOP _ ^No Operation _: Esta instrucción es la que vamos a utilizar para eliminar instrucciones cuando queramos por

ROM0:130D 0E 00 ld c,00

ROM0:130F 21 BA 1C ld hl,1CBA

ROM0:1312 2A ldi a,(hl)

ROM0:1313 EA 42 C3 ld (C342),a

ROM0:1316 2A ldi a,(hl)

ROM0:1317 EA 44 C3 ld (C344),a

ROM0:131A 2A ldi a,(hl)

ROM0:131B EA 46 C3 ld (C346),a

ROM0:131E 23 inc hl

ROM0:131F FA E8 C3 ld a,(C3E8)

ROM0:1322 47 ld b,a

ROM0:1323 FA 42 C3 ld a,(C342)

ROM0:1326 90 sub b

ROM0:1327 20 2D jr nz,1356

ROM0:1329 FA E9 C3 ld a,(C3E9)

ROM0:132C 47 ld b,a

ROM0:132D FA 44 C3 ld a,(C344)

ROM0:1330 90 sub b

ROM0:1331 20 23 jr nz,1356

ROM0:1333 FA EA C3 ld a,(C3EA)

ROM0:1336 47 ld b,a

ROM0:1337 FA 46 C3 ld a,(C346)

ROM0:133A 90 sub b

ROM0:133B 20 19 jr nz,1356

ROM0:133D 79 ld a,c

ROM0:133E EA A7 C3 ld (C3A7),a

ROM0:1341 AF xor a

ROM0:1342 EA E7 C3 ld (C3E7),a

ROM0:1345 EA E6 C3 ld (C3E6),a

ROM0:1348 EA 8E C3 ld (C38E),a

ROM0:134B 3E 0B ld a,0B

Page 47: ROMHACKING GAMEBOY PRÁCTICO - Todo lo que quiso saber … · ^NOP _ ^No Operation _: Esta instrucción es la que vamos a utilizar para eliminar instrucciones cuando queramos por

ROM0:134D EA 8D C3 ld (C38D),a

ROM0:1350 3E 78 ld a,78

ROM0:1352 EA A9 C3 ld (C3A9),a

ROM0:1355 C9 ret

----

ROM0:1356 0C inc c

ROM0:1357 79 ld a,c

ROM0:1358 FE 66 cp a,66

ROM0:135A 38 0C jr c,1368

ROM0:135C AF xor a

ROM0:135D EA E7 C3 ld (C3E7),a

ROM0:1360 FA 8E C3 ld a,(C38E)

ROM0:1363 3D dec a

ROM0:1364 EA 8E C3 ld (C38E),a

ROM0:1367 C9 ret

En la primera línea se pone en el registro “c” el valor $00 con lo que se inicia el contador donde

se va a poner el número de nivel en caso de que sea correcto y en la siguiente línea

encontramos “ld hl,1CBA” que pone en hl la dirección $00:1CBA donde están los passwords

del juego pero no en formato texto.

Más en concreto en la dirección $00:1CBE-$00:1CC0 encontramos los valores 0E 0F 0D.

Si tomamos la letra “B” que es la primera con el valor $00 podemos numerar las siguientes

letras que aparecen en la pantalla de password con lo que el código anterior corresponde al

password “ STR” que es el que corresponde al nivel 1 del modo “PUZZLE MODE”.

Si nos vamos a esa dirección con el editor hexadecimal vemos como a continuación de estos

códigos hexadecimales aparece un código hexadecimal y a continuación va la siguiente

password.

La rutina va recorriendo la lista de passwords para comprobar la que introducimos con las del

juego y se va incrementando el registro “c” en la dirección $00:1356 para poner el número de

nivel que se pone en la dirección de la RAM $C3A7.

Aquí la posición de la letra del password la encontramos en la dirección $C3E7 y toma los

valores $00 (1ª letra), $01 (2ª letra) y $02 (3ª letra).

El siguiente fragmento lo que hace es incrementar la posición de la letra:

ROM0:1306 E5 push hl

ROM0:1307 21 E7 C3 ld hl,C3E7

ROM0:130A 34 inc (hl)

Page 48: ROMHACKING GAMEBOY PRÁCTICO - Todo lo que quiso saber … · ^NOP _ ^No Operation _: Esta instrucción es la que vamos a utilizar para eliminar instrucciones cuando queramos por

ROM0:130B E1 pop hl

ROM0:130C C9 ret

En el registro “hl” se pone la dirección $C3E7=Posición de la letra, y en la siguiente línea se

incrementa el valor que hay en la dirección contenida en hl.

Una vez que se llega a la tercera letra se debe pasar a la primera posición con lo que se ejecuta

lo siguiente para poner el valor $00 en la dirección $C3E7 que corresponde a la 1ª letra:

ROM0:135C AF xor a

ROM0:135D EA E7 C3 ld (C3E7),a

La operación “xor a” o “xor a,a” equivale a la expresión “a=$00”.

En la parte inferior donde están las posibles letras que podemos elegir tenemos otro cursor y

que también tiene una dirección de la RAM donde se guarda la posición de dicho cursor según

la letra. En nuestro caso se trata de la dirección $C3E6 que se puede obtener fácilmente

utilizando el “bgb cheat searcher”.

En este caso se utiliza sólo esta dirección pero en algún juego se utilizan dos direcciones

independientes que corresponden una a la fila y la otra a la columna de la posición del cursor.

En este caso es única y toma los valores $00=”B”,…,$14=”Z”.

La posición inicial donde se pone el cursor de las letras de abajo que se situa sobre la letra “B”

($00) se pone en la dirección $00:0650 en un fragmento de código donde además se ponen en

otras direcciones también el valor $00.

ROM0:061F AF xor a

ROM0:0620 EA 99 C5 ld (C599),a

ROM0:0623 EA 9A C5 ld (C59A),a

ROM0:0626 EA 9B C5 ld (C59B),a

ROM0:0629 EA 9C C5 ld (C59C),a

ROM0:062C EA 9D C5 ld (C59D),a

ROM0:062F EA 5E C4 ld (C45E),a

ROM0:0632 EA 90 C5 ld (C590),a

ROM0:0635 EA 92 C5 ld (C592),a

ROM0:0638 EA 91 C5 ld (C591),a

ROM0:063B EA 93 C5 ld (C593),a

ROM0:063E EA 8B C3 ld (C38B),a

ROM0:0641 EA 89 C3 ld (C389),a

ROM0:0644 EA 8A C3 ld (C38A),a

ROM0:0647 EA 45 C4 ld (C445),a

Page 49: ROMHACKING GAMEBOY PRÁCTICO - Todo lo que quiso saber … · ^NOP _ ^No Operation _: Esta instrucción es la que vamos a utilizar para eliminar instrucciones cuando queramos por

ROM0:064A EA 1E C4 ld (C41E),a

ROM0:064D EA 3B C4 ld (C43B),a

ROM0:0650 EA E6 C3 ld (C3E6),a

ROM0:0653 EA 48 C4 ld (C448),a

ROM0:0656 EA 47 C4 ld (C447),a

El fragmento que se encarga de cambiar la posición del cursor inferior donde están las letras se

encuentra en el siguiente fragmento:

(Disminuir la posición):

ROM0:1A94 FA 8C FF ld a,(FF8C)

ROM0:1A97 CB 6F bit 5,a

ROM0:1A99 28 0D jr z,1AA8

ROM0:1A9B FA E6 C3 ld a,(C3E6)

ROM0:1A9E 3D dec a

ROM0:1A9F CB 7F bit 7,a

ROM0:1AA1 28 01 jr z,1AA4

ROM0:1AA3 AF xor a

ROM0:1AA4 EA E6 C3 ld (C3E6),a

ROM0:1AA7 C9 ret

-----

(Incrementar la posición):

ROM0:1AA8 CB 67 bit 4,a

ROM0:1AAA 28 0E jr z,1ABA

ROM0:1AAC FA E6 C3 ld a,(C3E6)

ROM0:1AAF 3C inc a

ROM0:1AB0 FE 15 cp a,15

ROM0:1AB2 38 02 jr c,1AB6

ROM0:1AB4 3E 14 ld a,14

ROM0:1AB6 EA E6 C3 ld (C3E6),a

ROM0:1AB9 C9 ret

-------

(Compara la posición de la letra con $07):

Page 50: ROMHACKING GAMEBOY PRÁCTICO - Todo lo que quiso saber … · ^NOP _ ^No Operation _: Esta instrucción es la que vamos a utilizar para eliminar instrucciones cuando queramos por

ROM0:1ABA CB 77 bit 6,a

ROM0:1ABC 28 0E jr z,1ACC

ROM0:1ABE FA E6 C3 ld a,(C3E6)

ROM0:1AC1 FE 07 cp a,07

ROM0:1AC3 30 01 jr nc,1AC6

ROM0:1AC5 C9 ret

--------

(Disminuye la posición a una línea anterior disminuyéndola en $07):

ROM0:1AC6 D6 07 sub a,07

ROM0:1AC8 EA E6 C3 ld (C3E6),a

ROM0:1ACB C9 ret

----------

(Compara la posición de la letra con $0E):

ROM0:1ACC CB 7F bit 7,a

ROM0:1ACE 28 0E jr z,1ADE

ROM0:1AD0 FA E6 C3 ld a,(C3E6)

ROM0:1AD3 FE 0E cp a,0E

ROM0:1AD5 38 01 jr c,1AD8

ROM0:1AD7 C9 ret

--------

(Incrementa la posición a una línea posterior incrementándola en $07):

ROM0:1AD8 C6 07 add a,07

ROM0:1ADA EA E6 C3 ld (C3E6),a

ROM0:1ADD C9 ret

ROM0:1ADE C9 ret

Además de la dirección $C3E6 que es donde se guarda la posición del cursor de la parte

inferior encontramos otra dirección en $00:1A94 que es la dirección $FF8C que corresponde a

la High RAM una parte de la memoria RAM que comienza en la dirección $FF80.

Esta dirección nos va a servir para explicar una rutina (rutina de joypad) que se encuentra en

todos o casi todos los juegos de Gameboy que es la que se encarga de leer los botones

pulsados en la consola que encontramos en el fragmento de código:

ROM0:03A7 3E 20 ld a,20

Page 51: ROMHACKING GAMEBOY PRÁCTICO - Todo lo que quiso saber … · ^NOP _ ^No Operation _: Esta instrucción es la que vamos a utilizar para eliminar instrucciones cuando queramos por

ROM0:03A9 EA 00 FF ld (FF00),a

ROM0:03AC FA 00 FF ld a,(FF00)

ROM0:03AF FA 00 FF ld a,(FF00)

ROM0:03B2 2F cpl

ROM0:03B3 E6 0F and a,0F

ROM0:03B5 CB 37 swap a

ROM0:03B7 47 ld b,a

ROM0:03B8 3E 10 ld a,10

ROM0:03BA EA 00 FF ld (FF00),a

ROM0:03BD FA 00 FF ld a,(FF00)

ROM0:03C0 FA 00 FF ld a,(FF00)

ROM0:03C3 FA 00 FF ld a,(FF00)

ROM0:03C6 FA 00 FF ld a,(FF00)

ROM0:03C9 FA 00 FF ld a,(FF00)

ROM0:03CC FA 00 FF ld a,(FF00)

ROM0:03CF 2F cpl

ROM0:03D0 E6 0F and a,0F

ROM0:03D2 B0 or b

ROM0:03D3 4F ld c,a

ROM0:03D4 FA 8B FF ld a,(FF8B)

ROM0:03D7 A9 xor c

ROM0:03D8 A1 and c

ROM0:03D9 EA 8C FF ld (FF8C),a

ROM0:03DC 79 ld a,c

ROM0:03DD EA 8B FF ld (FF8B),a

ROM0:03E0 3E 30 ld a,30

ROM0:03E2 EA 00 FF ld (FF00),a

ROM0:03E5 C9 ret

Aquí basta con que conozcan que la dirección $FF00 se encarga del joypad leyendo o

escribiendo en ella. Lo más normal aunque no siempre encontramos la dirección o direcciones

donde se guarda el botón pulsado en la consola y que en este caso corresponde a las

direcciones $FF8B y $FF8C.

Page 52: ROMHACKING GAMEBOY PRÁCTICO - Todo lo que quiso saber … · ^NOP _ ^No Operation _: Esta instrucción es la que vamos a utilizar para eliminar instrucciones cuando queramos por

¿Les suena de algo la dirección $FF8C? Es la que aparecía en el fragmento de código que

cambia la posición del cursor de la parte inferior donde están las letras y precisamente la

primera instrucción era:

ROM0:1A94 FA 8C FF ld a,(FF8C)

Esta instrucción lo que hace es carga en el registro “a” el valor que hay en la dirección

$FF8C=Botón pulsado de la consola para comprobar si se ha pulsado el botón “Derecha”,

“Izquierda”, “Arriba, “Abajo”.

Ya que conocemos que en $FF8C se guarda el botón pulsado vamos a asignar un valor a cada

botón para lo cual vamos a utilizar los valores $01, $02, $04, $08, $10, $20, $40 y $80.

El valor $00 correspondería a cuando no se ha pulsado ningún botón.

Estos valores no son al azar sino que son lo más utilizados por los juegos de Gameboy aunque

a veces se utilizan otros como $FF, $FD, …

Para conocer a que botón le corresponde el valor $01 vamos a poner un breakpoint en la

dirección $FF8C=Botón pulsado para que se pare cuando se escriba ese valor y para saber el

botón basta con ir pulsando las teclas que hayamos asignado a cada uno de los botones de la

consola Gameboy en el emulador.

Por ejemplo, si hemos asignado la tecla “Flecha derecha” al botón de la consola “Derecha”,.. la

tecla “Z” en mi caso para el botón “A” de la consola,…

Cuando se pare el emulador sabremos que ese botón se le asigna el valor $01. En el caso de

este juego se trata del botón “A”. El resumen de cada botón es:

A: $01

B: $02

Select: $04

Start: $08

Derecha: $10

Izquierda: $20

Arriba: $40

Abajo: $80

Un byte contiene 8 bits siendo el bit 0 el que corresponde a “A”, el bit 1 a “B”, el bit 2 a

“Select”, el bit 3 a “Start”, el bit 4 a “Derecha”, el bit 5 a “Izquierda”, el bit 6 a “Arriba” y el bit

7 a “Abajo”.

Es por ello por lo que la siguiente línea:

ROM0:1A97 CB 6F bit 5,a

Comprueba el bit 5 (botón “Izquierda”) con lo que disminuía la posición del cursor inferior si se

ha pulsado dicho botón.

ROM0:1AA8 CB 67 bit 4,a

Page 53: ROMHACKING GAMEBOY PRÁCTICO - Todo lo que quiso saber … · ^NOP _ ^No Operation _: Esta instrucción es la que vamos a utilizar para eliminar instrucciones cuando queramos por

Comprueba el bit 4 (botón “Derecha”) con lo que incrementa la posición del cursor inferior si

se ha pulsado dicho botón.

Igualmente se comprueba el bit 6 para comprobar si se ha pulsado el botón “Arriba” con lo

que se pasaría a la fila que haya por encima si no es la primera disminuyendo la posición en

$07. Con el bit 7 se comprueba si se ha pulsado el botón “Abajo” con lo que se pasaría a la fila

que haya por debajo sino es la última incrementando la posición en $07.

En la pantalla de password podemos buscar también donde se encuentran los textos que

aparecen en la pantalla (“ENTER PASSWORD”, “B-ENTER”, “A-MENÚ”) y el código que se

encarga de mostrarlo.

Buscando estos textos encontramos lo siguiente:

$01:5D08 98 A3 (Map Address=$98A3)

$01:5D0A 0E (Nº de tiles=$0E)

$01:5D0B 95 9E A4 95 A2 AF A0 91 A3 A3 A7 9F A2 94 (Texto “ENTER PASSWORD”)

$01:5D19 99 02 (Map Address=$9902)

$01:5D1B 10 (Nº de tiles=$10)

$01:5D1C 92 8E 95 9E A4 95 A2 AF AF AF 91 8E 9D 95 9E A5 (Texto “B-ENTER A-MENÚ”)

------

(Datos dibujar recuadro donde se ponen las letras que podemos utilizar para el password):

$01:5D2C 99 42 (Map Address=$9942)

$01:5D2E 0F (Nº de tiles=$0F)

$01:5D2F F5 F6 F6 F6 F6 F6 F6 F6 F6 F6 F6 F6 F6 F6 F7

$01:5D3E 99 62 (Map Address=$9962)

$01:5D40 0F (Nº de tiles=$0F)

$01:5D41 2B 2C 2C 2C 2C 2C 2C 2C 2C 2C 2C 2C 2C 2C 2D

$01:5D50 99 82 (Map Address=$9982)

$01:5D52 0F (Nº de tiles=$0F)

$01:5D53 2B 2C 2C 2C 2C 2C 2C 2C 2C 2C 2C 2C 2C 2C 2D

$01:5D62 99 A2 (Map Address=$99A2)

$01:5D64 0F (Nº de tiles=$0F)

$01:5D65 2B 2C 2C 2C 2C 2C 2C 2C 2C 2C 2C 2C 2C 2C 2D

$01:5D74 99 C2 (Map Address=$99C2)

$01:5D76 0F (Nº de tiles=$0F)

$01:5D77 2B 2C 2C 2C 2C 2C 2C 2C 2C 2C 2C 2C 2C 2C 2D

Page 54: ROMHACKING GAMEBOY PRÁCTICO - Todo lo que quiso saber … · ^NOP _ ^No Operation _: Esta instrucción es la que vamos a utilizar para eliminar instrucciones cuando queramos por

$01:5D86 99 E2 (Map Address=$99E2)

$01:5D88 0F (Nº de tiles=$0F)

$01:5D89 2B 50 2C 52 2C 54 2C 56 2C 58 2C 5A 2C 5C 2D

$01:5D98 9A 02 (Map Address=$9A02)

$01:5D9A 0F (Nº de tiles=$0F)

$01:5D9B 2B 51 2C 53 2C 55 2C 57 2C 59 2C 5B 2C 5D 2D

$01:5DAA 9A 22 (Map Address=$9A22)

$01:5DAC 0F (Nº de tiles=$0F)

$01:5DAD 2B 5E 2C 60 2C 62 2C 64 2C 66 2C 68 2C 6A 2D

$01:5DBC 9A 42 (Map Address=$9A42)

$01:5DBE 0F (Nº de tiles=$0F)

$01:5DBF 2B 5F 2C 61 2C 63 2C 65 2C 67 2C 69 2C 6B 2D

$01:5DCE 9A 62 (Map Address=$9A62)

$01:5DD0 0F (Nº de tiles=$0F)

$01:5DD1 2B 6C 2C 6E 2C 70 2C 72 2C 74 2C 76 2C 78 2D

$01:5DE0 9A 82 (Map Address=$9A82)

$01:5DE2 0F (Nº de tiles=$0F)

$01:5DE3 2B 6D 2C 6F 2C 71 2C 73 2C 75 2C 77 2C 79 2D

$01:5DF2 9A A2 (Map Address=$9AA2)

$01:5DF4 0F (Nº de tiles=$0F)

$01:5DF5 2E 2F 2F 2F 2F 2F 2F 2F 2F 2F 2F 2F 2F 2F 30

Antes de éstos textos también encontramos una gran cantidad de textos a partir de la

dirección $01:5C41-$01:5D07.

Buscando el valor hexadecimal 415C lo encontramos en la dirección $01:5B0E donde se

encuentran una serie de direcciones que son punteros a textos del juego entre los que se

encuentran los que corresponden a los textos que he enumerado y que terminan en la

dirección $01:5B6B.

Normalmente hay direcciones (punteros) que apuntan a datos (textos, datos de nivel,…) y que

se leen a través de una rutina.

Si se busca 0E5B que corresponde a la dirección donde están los punteros en formato inverso,

lo encontramos en la dirección $01:400A-$01:400B. Desde la dirección $01:4002-$01:400B

encontramos punteros que apuntan a los otros punteros y a datos.

Normalmente, se suele leer los punteros poniendo en el registro “hl” o en “de” la dirección

donde están estos.

Page 55: ROMHACKING GAMEBOY PRÁCTICO - Todo lo que quiso saber … · ^NOP _ ^No Operation _: Esta instrucción es la que vamos a utilizar para eliminar instrucciones cuando queramos por

Si buscamos, los tiles que representan los ladrillos que hay en el fondo en la pantalla de

selección de password poniendo un breakpoint en la dirección $9800=Map Address cuando se

escribe el valor $AF salta el emuladore en la dirección $00:03FF.

En este punto el valor de los registros es:

“af”=AF80 (a=80), “de”=9800, “bc”=$0400”, hl=$4044”, rom=4.

Aquí encontramos una rutina de uso general y que encontramos en la mayoría de los juegos de

Gameboy:

ROM0:03FE 2A ldi a,(hl)

ROM0:03FF 12 ld (de),a

ROM0:0400 13 inc de

ROM0:0401 0B dec bc

ROM0:0402 78 ld a,b

ROM0:0403 B1 or c

ROM0:0404 20 F8 jr nz,03FE

ROM0:0406 C9 ret

Básicamente lo que hace es leer los datos que hay en la dirección contenida en hl=$04:4043

(datos para dibujar el fondo de la pantalla de password) y los pone en la dirección contenida

en de=$9800=Map Address (en pantalla). En bc=$0400 se pone el número de bytes que hay

que leer o escribir.

La instrucción “dec bc” disminuye el número de bytes que queda por leer/escribir hasta ya no

queden bytes.

El registro “bc” es de 16 bits por lo que puede tomar valores entre $0000-$FFFF (0-65535) con

lo que se puede leer/escribir una gran cantidad de bytes. A veces cuando el número de bytes

no es muy grande se utiliza el registro “c” de 8 bits que puede tomar valores entre $00-$FF (0-

255 bytes).

Lo que encontramos en la dirección $04:4043-$04:4442 ($10000-$10442) son los datos para

dibujar el fondo de los ladrillos con el rótulo “RECORDS” y sin los textos de “ENTER

PASSWORD”,… ni el recuadro donde se pone el passwords y las letras posibles.

Page 56: ROMHACKING GAMEBOY PRÁCTICO - Todo lo que quiso saber … · ^NOP _ ^No Operation _: Esta instrucción es la que vamos a utilizar para eliminar instrucciones cuando queramos por

El rótulo “RECORDS” no se ve demasiado en la imagen pero se encuentra encima del texto

“ENTER PASSWORD”. Éste rótulo no es visible ya que está en el área no visible de la pantalla.

El área visible de la pantalla empieza en la dirección $9880 de la Map Adress.

A veces cuando se dibuja la pantalla del juego no se hace completamente como en este caso

sino que se escriben sólo $12 líneas (18 líneas) de $14 tiles (20 tiles) que es lo que corresponde

a la parte visible de la pantalla.

En este caso se ha dibujado la pantalla completa incluyendo la parte no visible, es decir $20

líneas (32 líneas) de $20 tiles (32 tiles) lo que hace un total de $0400 bytes (1024 bytes).

Si buscáramos el valor 4340 lo encontramos en la dirección $04:4002-$04:4009 ($10002-

$10009), y en la dirección $04:400A-$04:400B ($1000A-$1000B) encontramos el valor 4344 y

en $04:400C-$04:400D ($1000C-$1000D) encontramos el valor 384D.

En $04:4000 ($10000) tenemos el valor 0400 que corresponde al número de banco ($04).

Igual que hemos hecho con la pantalla de password podemos hacer con el resto de pantallas

que se encuentran en el juego.

Poniendo un breakpoint en la dirección $9800=Map Address cuando se escribe el valor $00 el

emulador se para en la misma dirección donde está la rutina de uso general pero ahora los

datos de la pantalla de “NAMCO” se encuentran en la dirección $05:7264-$05:7663 ($17264-

$17663).

Page 57: ROMHACKING GAMEBOY PRÁCTICO - Todo lo que quiso saber … · ^NOP _ ^No Operation _: Esta instrucción es la que vamos a utilizar para eliminar instrucciones cuando queramos por

Si vemos esta pantalla en el “BGB VRAM Viewer” vemos que en la zona no visible aparecen

gráficos pero que no parecen tener sentido ya que no se ve nada legible. En esta pantalla la

zona visible comienza en la dirección de la Map Address=$9800.

En esta pantalla podríamos cambiar el texto “PRODUCED” por “PRODUCIDO” y “BY” por “POR”

ya que hemos localizado donde están los datos.

El texto “PRODUCED” lo encontramos en la dirección $05:738A-$05:7391 ($1738A-$17391) y

podemos poner “PRODUCIDO” por ejemplo en la dirección $05:7389-$05:7391 ya que ocupa 1

byte más.

Igualmente podemos hace con el texto “BY” que se encuentra en la dirección $05:73CD-

$05:73CE ($173CD-$173CE) y poner en $05:73CC-$05:73CE el texto “POR” con lo que la

pantalla quedaría como:

Page 58: ROMHACKING GAMEBOY PRÁCTICO - Todo lo que quiso saber … · ^NOP _ ^No Operation _: Esta instrucción es la que vamos a utilizar para eliminar instrucciones cuando queramos por

La pantalla de título la encontramos en la dirección $01:582E-$01:5C2D del juego. En la

dirección $01:5954-$01:595E encontramos el texto “NORMAL MODE” y en $01:5994-$01:599E

el texto “PUZZLE MODE” que podemos cambiar igualmente por “MODO NORMAL” y “MODO

PUZZLE”.

Sin embargo, si quisiéramos cambiar el texto “LICENSED BY NINTENDO” por “LICENCIADO POR

NINTENDO” no podríamos hacerlo así ya que no está como texto sino que es una secuencia de

tiles la que forman el texto y no aparece lo que queremos poner en pantalla por lo que

debemos modificar los tiles $E6-$F1 (Tile Address=$8E60-$8F1F) y si es necesario tendríamos

que ver algún tile que no se use en la pantalla y que esté en blanco como el $FC y $FF (como

parece que es).

Si buscamos estos tiles los encontramos en la dirección $01:4E8E-$01:4F4D. Para hacer la

búsqueda en el debugger del emulador seleccionamos “Go to…” y ponemos la dirección $8E60

donde se encuentra el primer tile y seleccionamos “Copy data” poniendo en número de bytes

el valor 192 que corresponde a 12 tiles que van desde el $E6-$F1.

A continuación, abrimos con el editor hexadecimal HxD el juego y buscamos la secuencia de

bytes que hemos copiado con lo que la encontramos en la dirección $01:4E8E-$01:4F4D.

Page 59: ROMHACKING GAMEBOY PRÁCTICO - Todo lo que quiso saber … · ^NOP _ ^No Operation _: Esta instrucción es la que vamos a utilizar para eliminar instrucciones cuando queramos por

Para modificar los tiles podemos abrir el juego con un editor de tiles como el “TileED2002” y

modificarlos para que muestre el texto que queremos poner que en este caso es “LICENDIADO

POR NINTENDO”.

Este editor de tiles pone la dirección en decimal por lo que tendríamos que convertir la

dirección inicial $4E8E en decimal que corresponde a 20110.

Las herramientas del “Editor Control” paso a explicar a continuación aunque no suelo utilizar la

opción de guardar y recargar todos los tiles pero si el resto de opciones ya que se me bloquea

el programa y tengo que cerrarlo utilizando en su lugar el “Tile Tool”.

Page 60: ROMHACKING GAMEBOY PRÁCTICO - Todo lo que quiso saber … · ^NOP _ ^No Operation _: Esta instrucción es la que vamos a utilizar para eliminar instrucciones cuando queramos por

Para modificar los tiles vamos a utilizar las herramientas de que dispone el TilEd 2002 para lo

cual lo primero que vamos a hacer es seleccionar en la parte izquierda donde están los tiles los

que vamos a modificar y pulsar sobre ellos para que se añadan al recuadro donde pone editor

(los que aparecen en la pantalla de arriba no vamos a tener que modificarlos todos sino los

que tienen el texto “SED BY” y 2 que vamos a utilizar adicionalmente.

Una vez seleccionado puesto el tile correspondiente en el “Editor” pulsamos sobre el segundo

icono del “Editor Control” para seleccionar “Paint Mode” y poder modificarlos. Una vez hecho

esto podemos pulsar donde pone “Color Palette” para seleccionar el color con el que vamos a

dibujar en el tile e ir modificando el tile copiado a nuestro gusto.

Una vez modificado el tile que hemos copiado en el “Editor” pulsamos sobre el primer icono

que aparece en el “Tile Tool” con lo que el tile que hemos modificado se cambia por el original

que tenía el juego y repetimos el proceso con el resto de tiles que debemos modificar.

También podríamos utilizar el primer icono de la segunda fila para guardar el tile modificado

en la posición que le indiquemos.

Podemos cambiar los tiles para que ponga el texto que queremos con lo que podría quedar

algo así:

Sin embargo, todavía nos quedaría algo por hacer ya que si ejecutamos ahora el juego está

prácticamente correcto a excepción que no aparece el texto “OR” de la palabra “POR” ya que

hemos utilizado 2 tiles adicionales ($FE y $FF) que no se utilizaban para la pantalla de título.

En la dirección $01:5A52-$01:5A5D encontrabamos el texto “LICENSED BY NINTENDO” en

formato tile y debemos dejar espacio para meter 2 tiles más con lo que empezaremos a

escribir en $01:5A50.

Page 61: ROMHACKING GAMEBOY PRÁCTICO - Todo lo que quiso saber … · ^NOP _ ^No Operation _: Esta instrucción es la que vamos a utilizar para eliminar instrucciones cuando queramos por

Desde $01:5A52-$01:5A58 encontramos ahora el texto “LICENCIADO P” que corresponde a los

valores hexadecimales E6 E7 E8 E9 EA EB EC.

Debemos añadir $FE y $FF a continuación para aparezca el texto bien.

Con la modificación en la dirección $01:5A50-$01:5A5D encontraríamos ahora lo siguiente:

E6 E7 E8 E9 EA EB EC FE FF ED EE EF F0 F1

La pantalla quedaría entonces así:

Aquí podríamos cambiar también la posición de los textos “MODO NORMAL” y “MODO

PUZZLE” para que aparecieran en una posición distinta de la pantalla pero para que el icono en

forma de triángulo se situara correctamente tendríamos que hacer alguna modificación extra.

Page 62: ROMHACKING GAMEBOY PRÁCTICO - Todo lo que quiso saber … · ^NOP _ ^No Operation _: Esta instrucción es la que vamos a utilizar para eliminar instrucciones cuando queramos por

Para la opción “NORMAL MODE” del cursor los datos que se ponen en la OAM (Object Address

Memory) son “X-loc”: $28, “Y-loc”: $58, “Tile No.”: $F2 y “Attribute”: $00.

Para la opción “PUZZLE MODE” del cursor los datos son similares a excepción a “Y-loc” que

ahora toma el valor $68.

Aquí el proceso es un poco complicado ya que se utilizan varias direcciones de la RAM.

Poniendo un breakpoint cuando se escribe el valor $58 en la dirección $C00 encontramos lo

siguiente:

ROM0:059D E5 push hl

ROM0:059E 21 42 C3 ld hl,C342

ROM0:05A1 2A ldi a,(hl)

ROM0:05A2 12 ld (de),a

El registro “de” tiene el valor $C000, “hl” el valor $C342 y “a” el valor $58, con lo que se carga

el valor que hay en la dirección $C342 que es $58 y se pone en $C000.

Sin embargo, debemos retroceder para ver cuando se puso el valor $58 en la dirección $C342

para lo cual ponemos un breakpoint con lo que el emulador se para en:

ROM0:057D FA 4B C3 ld a,(C34B)

ROM0:0580 81 add c

ROM0:0581 EA 42 C3 ld (C342),a

Page 63: ROMHACKING GAMEBOY PRÁCTICO - Todo lo que quiso saber … · ^NOP _ ^No Operation _: Esta instrucción es la que vamos a utilizar para eliminar instrucciones cuando queramos por

Se carga en el registro “a” el valor que hay en la dirección $C34B y en la siguiente línea se

añade al valor de “a” el valor que hay en “c” (el registro “bc”=$C100, con lo que “c”=$00) y se

pone el resultado en la dirección $C342.

Como el valor del registro “c” es $00 debe tener a el registro “a” el valor $58 con lo que en la

dirección $C34B se debe haber puesto el valor $58 con anterioridad con lo que ponemos un

breakpoint en la dirección $C34B cuando se escriba el valor $58 y se para en la dirección

$00:056B.

ROM0:056A 2A ldi a,(hl)

ROM0:056B EA 4B C3 ld (C34B),a

Al pararse el emulador en el registro “hl” está la dirección $C1B0 pero en realidad la que

buscamos es la $C1AF ya que la instrucción en $00:056A ha aumentado ya el valor del registro

“hl”.

Ldi a,(hl): Carga en “a” el valor que hay en la dirección contenida en “hl” e incrementa “hl”.

Ahora vamos a poner un breakpoint en la dirección $C1AF cuando se ponga el valor $58 con lo

que el emulador se parará en la dirección $00:090D:

ROM0:0902 21 11 09 ld hl,0911

ROM0:0905 06 00 ld b,00

ROM0:0907 FA 3E C4 ld a,(C43E)

ROM0:090A 4F ld c,a

ROM0:090B 09 add hl,bc

ROM0:090C 7E ld a,(hl)

ROM0:090D EA AF C1 ld (C1AF),a

ROM0:0910 C9 ret

ROM0:0911 58 (Coordenada Y opción “NORMAL MODE”)

ROM0:0912 68 (Coordenada Y opción “PUZZLE MODE”)

Ha costado un poco pero a fuerza de breakpoints hemos localizado donde están estas

coordenadas y ya podríamos modificarlas a nuestro gusto para situar el cursor en las

coordenadas Y que queramos.

La primera instrucción lo que hace es poner en el registro “hl” la dirección $00:0911 donde

empiezan las coordenadas para situar el cursor y precisamente otra de las direcciones que

aparece $C43E corresponde a la opción del menú principal que podemos encontrar utilizando

el buscador de cheats del emulador (“bgb cheat searcher”).

Para la opción “NORMAL MODE” se pone el valor $00 en la dirección $C43E y para “PUZZLE

MODE” se pone el valor $01 en la dirección $C34E.

Por eso lo que hace el código es poner en el registro “b” el valor $00 y se carga en el registro

“a” el valor que hay en la dirección $C34E=Opción del menú principal. Luego se pasa al registro

“c” con lo que “c=a=Valor de la opción del menú principal).

Page 64: ROMHACKING GAMEBOY PRÁCTICO - Todo lo que quiso saber … · ^NOP _ ^No Operation _: Esta instrucción es la que vamos a utilizar para eliminar instrucciones cuando queramos por

Se le suma a continuación a la dirección contenida en el registro “hl” que es $00:0911 el valor

que hay en el registro “bc” que como “b=$00” debe ser $0000 para la opción “NORMAL

MODE” y $0001 para la opción “PUZZLE MODE” con lo que se cargaría en “hl” la dirección

$00:0911 para “NORMAL MODE” donde está la coordenada correspondiente

($00:0911+$0000) y $00:0912 para “PUZZLE MODE” donde está la coordenada

correspondiente ($00:0911+$0001).

La pantalla que nos aparece cuando seleccionamos la opción “NORMAL MODE” en el menú

principal se encuentra en la dirección $02:5022-$02:5281 ($9022-$9281) sin los textos que

aparecen:

En el inicio del segundo banco encontramos punteros entre los que se encuentra el que apunta

a los datos de esta pantalla encontrando a partir de la dirección $02:4000 ($8000) lo siguiente:

02 00 22 40 22 40 22 48 22 50 82 52 00 00 00 00

Los dos primeros bytes indican que se trata del banco $02 para poner en los punteros y el

resto son puntero (22 40=$02:4022, 22 48=$02:4822, 22 50=$02:5022, 82 52=$02:5282).

Los textos de esta pantalla los encontramos utilizando breakpoints a partir de la dirección

$01:5CBC-$01:5CEB donde encontramos lo siguiente:

01:5CBC 98 85 (Map Address=$9885)

01:5CBE 05 (Nº de tiles=$05)

Page 65: ROMHACKING GAMEBOY PRÁCTICO - Todo lo que quiso saber … · ^NOP _ ^No Operation _: Esta instrucción es la que vamos a utilizar para eliminar instrucciones cuando queramos por

01:5CBF 6B 6C 6D 6C 6B (Texto “LEVEL”)

01:5CC4 98 A5 (Map Address=$98A5)

01:5CC6 06 (Nº de tiles=$06)

01:5CC7 6E 6C 6B 6C 6F 70 (Texto “SELECT”)

01:5CCD 99 05 (Map Address=$9905)

01:5CCF 04 (Nº de tiles=$04)

01:5CD0 6C 71 6E 72 (Texto “EASY”)

01:5CD4 99 45 (Map Address=$9945)

01:5CD6 06 (Nº de tiles=$06)

01:5CD7 73 74 75 76 71 6B (Texto “NORMAL”)

01:5CDD 99 85 (Map Address=$9985)

01:5CDF 04 (Nº de tiles=$04)

01:5CE0 77 71 75 78 (Texto “HARD”)

01:5CE4 99 C5 (Map Address=$99C5)

01:5CE6 06 (Nº de tiles=$06)

01:5CE7 77 72 79 6C 75 (Texto “HYPER”)

JOYPAD Y TRUCOS

ADVENTURE ISLAND

Algunos juegos de Gameboy disponen de una combinación de botones que hay que pulsar

para activar algún truco como puede ser seleccionar nivel,… y que con unos pequeños

conocimientos podemos modificar para hacerlo más sencillo.

Vamos a utilizer el juego “Adventure Island” que tiene un truco para seleccionar nivel que

consiste en pulsar los botones Derecha, Izquierda, Derecha, Izquierda, A, B, A, B después de

que Higgins sea golpeado por un coco en la pantalla de título.

Si ponemos un breakpoint en la dirección $FF00 cuando se escribe podemos ver donde se

encuentra la rutina de joypad que se encarga de comprobar los botones pulsados y las

direcciones de la RAM donde se guardan dichos botones y que encontramos a partir de la

dirección $05:7E06-$05:7E36.

Las direcciones de la RAM donde se guarda el botón pulsado son $FF8C y $FF8D.

Los valores de los botones son los siguientes:

01: A

02: B

04: Select

Page 66: ROMHACKING GAMEBOY PRÁCTICO - Todo lo que quiso saber … · ^NOP _ ^No Operation _: Esta instrucción es la que vamos a utilizar para eliminar instrucciones cuando queramos por

08: Start

10: Derecha

20: Izquierda

40: Arriba

80: Abajo

Con lo que la combinación de botones debería ser 10 20 10 20 01 02 01 02 pero si los

buscamos con un editor hexadecimal no lo encontramos (normalmente al buscarlos si

aparecen pero no en este caso).

Podemos poner un breakpoint en la dirección $FF8D cuando se lea por ejemplo el valor $20

(Izquierda) con lo que al pulsar este botón en la pantalla de título se parará el emulador en la

dirección $01:7CAA. Un poco más arriba en el código Fuente encontramos lo siguiente:

ROM1:7C9F 04 inc b

ROM1:7CA0 05 dec b

ROM1:7CA1 04 inc b

ROM1:7CA2 05 dec b

ROM1:7CA3 00 nop

ROM1:7CA4 01 00 01 ld bc,0100

--------

ROM1:7CA7 21 8D FF ld hl,FF8D

ROM1:7CAA 7E ld a,(hl)

Lo que aparece a partir de $01:7C9F-$01:7CA6 se parece bastante (04 05 04 05 00 01 00 01) a

lo que estábamos buscando (10 20 10 20 01 02 01 02).

Si tomamos los valores $00 (A), $01 (B), $02 (Select), $03 (Start), $04 (Derecha), $05

(Izquierda), Arriba ($06), Abajo ($07) comprobamos que los valores encontrados corresponden

a la combinación de botones para activar los cheats.

ROM1:7C9F 04 05 04 05 00 01 00 01

Podemos obviar las instrucciones que aparecían a la derecha de los valores en el código fuente

ya que éstos no son instrucciones sino que son los datos que contienen la combinación de

botones para el truco.

Si quisiéramos cambiar la combinación de botones para que sea más fácil para nosotros

podríamos por ejemplo cambiar estos bytes por:

ROM1:7C9F 00 00 00 00 00 00 00 00

Con esto se activa el truco cuando pulsamos 8 veces el botón “A” (valor $00) y nos aparecería

la pantalla:

Page 67: ROMHACKING GAMEBOY PRÁCTICO - Todo lo que quiso saber … · ^NOP _ ^No Operation _: Esta instrucción es la que vamos a utilizar para eliminar instrucciones cuando queramos por

Si buscamos la opción de este menú la encontramos en la dirección $C432 que toma el valor

$00: FERN ISLAND,…, $07: DINOSAUR ISLAND y el fragmento que se encarga de cambiar dicha

opción se encuentra en el siguiente fragmento:

ROM0:0594 11 32 C4 ld de,C432

ROM0:0597 21 8D FF ld hl,FF8D

ROM0:059A CB 76 bit 6,(hl)

ROM0:059C 28 08 jr z,05A6

ROM0:059E 1A ld a,(de)

ROM0:059F A7 and a

ROM0:05A0 20 01 jr nz,05A3

ROM0:05A2 78 ld a,b

ROM0:05A3 3D dec a

ROM0:05A4 18 29 jr 05CF

ROM0:05A6 7E ld a,(hl)

ROM0:05A7 E6 84 and a,84

ROM0:05A9 C8 ret z

ROM0:05AA 1A ld a,(de)

ROM0:05AB 3C inc a

ROM0:05AC B8 cp b

ROM0:05AD 38 20 jr c,05CF

Page 68: ROMHACKING GAMEBOY PRÁCTICO - Todo lo que quiso saber … · ^NOP _ ^No Operation _: Esta instrucción es la que vamos a utilizar para eliminar instrucciones cuando queramos por

ROM0:05AF AF xor a

ROM0:05B0 18 1D jr 05CF

ROM0:05B2 11 31 C4 ld de,C431

ROM0:05B5 21 8D FF ld hl,FF8D

ROM0:05B8 CB 6E bit 5,(hl)

ROM0:05BA 28 08 jr z,05C4

ROM0:05BC 1A ld a,(de)

ROM0:05BD A7 and a

ROM0:05BE 20 01 jr nz,05C1

ROM0:05C0 79 ld a,c

ROM0:05C1 3D dec a

ROM0:05C2 18 0B jr 05CF

ROM0:05C4 7E ld a,(hl)

ROM0:05C5 E6 14 and a,14

ROM0:05C7 28 0E jr z,05D7

ROM0:05C9 1A ld a,(de)

ROM0:05CA 3C inc a

ROM0:05CB B9 cp c

ROM0:05CC 38 01 jr c,05CF

ROM0:05CE AF xor a

ROM0:05CF 12 ld (de),a

ROM0:05D0 3E 38 ld a,38

ROM0:05D2 CD 63 02 call 0263

ROM0:05D5 37 scf

ROM0:05D6 C9 ret

Como se observa en el código se pone en el registro “hl” la dirección $FF8D=Botón pulsado y

se lee para comprobar el botón y cambiar la posición del cursor según dicha opción.

Si buscamos los textos de esta pantalla podemos localizarlos a partir de la dirección $01:7D04-

$01:7D91 y buscando el valor 047D en el editor hexadecimal lo localizamos en $698-$699 que

corresponde al código:

ROM0:068F 3E 01 ld a,01

ROM0:0691 E0 99 ld (ff00+99),a

Page 69: ROMHACKING GAMEBOY PRÁCTICO - Todo lo que quiso saber … · ^NOP _ ^No Operation _: Esta instrucción es la que vamos a utilizar para eliminar instrucciones cuando queramos por

ROM0:0693 EA 00 20 ld (2000),a

ROM0:0696 21 04 7D ld hl,7D04

ROM0:0699 CD 68 03 call 0368

ROM0:069C CD 95 02 call 0295

ROM0:069F 21 D0 06 ld hl,06D0

ROM0:06A2 CD DA 05 call 05DA

ROM0:06A5 3E 01 ld a,01

ROM0:06A7 CD D8 02 call 02D8

ROM0:06AA 21 D0 06 ld hl,06D0

ROM0:06AD CD 8A 05 call 058A

Al principio se selecciona el banco $01 poniendo en “a” en la dirección $2000 y en “hl” se pone

el valor $7D04 con lo que la dirección es $01:7D04 donde están los textos. Posteriormente se

pone en el registro “hl” la dirección $00:06D0 donde encontramos:

$00:06D0 01 08

$00:06D2 00 07 (Atributo=$00, Tile=$07 del cursor para seleccionar nivel)

$00:06D4 A1 98 (Map Address=$98A1, “FERN ISLAND”)

$00:06D6 C1 98 (Map Address=$98C1, “LAKE ISLAND”)

$00:06D8 E1 98 (Map Address=$98E1, “DESERT ISLAND”)

$00:06DA 01 99 (Map Address=$9901, “ICE ISLAND”)

$00:06DC 21 99 (Map Address=$9921, “CAVE ISLAND”)

$00:06DE 41 99 (Map Address=$9941, “CLOUD ISLAND”)

$00:06E0 61 99 (Map Address=$9961, “VOLCANO ISLAND”)

$00:06E2 81 99 (Map Address=$9981, “DINOSAUR ISLAND”)

Estas son las Map Address donde pone el cursor para elegir el nivel correspondiente. Si

cambiamos el valor que hay en la dirección $00:06D3 poniendo por ejemplo $70

conseguiremos cambiar el punto del cursor por el tile $70 que corresponde al símbolo “!”.

En la dirección $C432 se guarda el nivel que seleccionamos en esta pantalla.

WE´RE BACK! A DINOSAUR STORY

Este juego tiene una serie de cheats utilizando combinaciones de botones:

Vidas infinitas: Select, A, Abajo, B, Arriba, Abajo (04, 01, 80, 02, 40, 80)

Proyectiles infinitos: B, A, Derecha, B, A, Derecha, A (02, 01, 10, 02, 01, 10, 01)

Page 70: ROMHACKING GAMEBOY PRÁCTICO - Todo lo que quiso saber … · ^NOP _ ^No Operation _: Esta instrucción es la que vamos a utilizar para eliminar instrucciones cuando queramos por

Tiempo infinito: Arriba, Abajo, Arriba, B, Izquierda, B (40, 80, 40, 02, 20, 02)

Invulnerabilidad: Derecha, A, Abajo, Derecha, A, Abajo (10, 01, 80, 10, 01, 80)

Seleccionar nivel: Select, Arriba, Arriba, Select, Izquierda, Izquierda (04, 40, 40, 04, 20, 20)

Especial 1: Arriba, B, A, Abajo, B, A (40, 02, 01, 80, 02, 01)

Especial 2: Izquierda, A, Izquierda, B, Izquierda (20, 01, 20, 02, 20)

Entre paréntesis aparecen los valores que podemos buscar para localizar las combinaciones de

botones en el juego.

En $17FA0-$17FA5 ($05:7FA0-$05:7FA5) encontramos la combinación para “Vidas infinitas”,

en $17FA7-$17FAC ($05:7FA7-$05:7FAC) encontramos la combinación para “Tiempo infinito”,

en $17FAE-$17FB3 ($05:7FAE-$05:7FB3) encontramos la combinación para “Seleccionar nivel”,

en $17FB5-$17FBA ($05:7FB5-$05:7FBA) encontramos la combinación para “Invulnerabilidad”,

en $17FBC-$17FC2 ($05:7FBC-$05:7FC2) encontramos la combinación para “Proyectiles

infinitos”, en $17FC4-$17FC9 ($05:7FC4-$05:7FC9) encontramos la combinación para “Especial

1”, en $17FCB-$17FCF encontramos la combinación para “Especial 2”.

Cada combinación de botones termina con el valor $FF para indicar el fin de los datos.

Si buscamos la secuencia A07F hexadecimal con el editor “HxD” lo encontramos a partir de la

dirección $17F68 ($05:7F68) donde encontramos además de punteros a las combinaciones de

botones otros punteros que todavía desconozco su utilidad.

$05:7F68 A1 D1 ($D1A1)

$05:7F6A 98 D1 ($D198)

$05:7F6C A0 7F ($05:7FA0=Combinación de botones)

$05:7F6E FF FF

$05:7F70 A4 D1 ($D1A4)

$05:7F72 99 D1 ($D199)

$05:7F74 A7 7F ($05:7FA7=Combinación de botones)

$05:7F76 FF FF

$05:7F78 A5 D1 ($D1A5)

$05:7F7A 9A D1 ($D19A)

$05:7F7C AE 7F ($05:7FAE=Combinación de botones)

$05:7F7E FF FF

$05:7F80 A6 D1 ($D1A6)

$05:7F82 9B D1 ($D19B)

$05:7F84 B5 7F ($05:7FB5=Combinación de botones)

$05:7F86 FF FF

Page 71: ROMHACKING GAMEBOY PRÁCTICO - Todo lo que quiso saber … · ^NOP _ ^No Operation _: Esta instrucción es la que vamos a utilizar para eliminar instrucciones cuando queramos por

$05:7F88 A9 D1 ($D1A9)

$05:7F8A 9C D1 ($D19C)

$05:7F8C BC 7F ($05:7FBC=Combinación de botones)

$05:7F8E FF FF

$05:7F90 A2 D1 ($D1A2)

$05:7F92 9D D1 ($D19D)

$05:7F94 C4 7F ($05:7FC4=Combinación de botones)

$05:7F96 FF FF

$05:7F98 A3 D1 ($D1A3)

$05:7F9A 9E D1 ($D19E)

$05:7F9C CB 7F ($05:7FCB=Combinación de botones)

$05:7F9E FF FF

La carga de estos punteros lo encontramos en el siguiente fragmento de código:

ROM5:7F07 AF xor a

ROM5:7F08 EA A0 D1 ld (D1A0),a

ROM5:7F0B 0E 07 ld c,07

ROM5:7F0D 3C inc a

ROM5:7F0E 21 68 7F ld hl,7F68

ROM5:7F11 2A ldi a,(hl)

ROM5:7F12 5F ld e,a

ROM5:7F13 2A ldi a,(hl)

ROM5:7F14 57 ld d,a

ROM5:7F15 D5 push de

ROM5:7F16 1A ld a,(de)

ROM5:7F17 B7 or a

ROM5:7F18 20 49 jr nz,7F63

ROM5:7F1A 2A ldi a,(hl)

ROM5:7F1B 5F ld e,a

ROM5:7F1C 2A ldi a,(hl)

ROM5:7F1D 57 ld d,a

ROM5:7F1E D5 push de

Page 72: ROMHACKING GAMEBOY PRÁCTICO - Todo lo que quiso saber … · ^NOP _ ^No Operation _: Esta instrucción es la que vamos a utilizar para eliminar instrucciones cuando queramos por

ROM5:7F1F E5 push hl

ROM5:7F20 2A ldi a,(hl)

ROM5:7F21 66 ld h,(hl)

ROM5:7F22 6F ld l,a

ROM5:7F23 1A ld a,(de)

ROM5:7F24 85 add l

ROM5:7F25 6F ld l,a

ROM5:7F26 8C adc h

ROM5:7F27 95 sub l

ROM5:7F28 67 ld h,a

ROM5:7F29 7E ld a,(hl)

ROM5:7F2A B8 cp b

ROM5:7F2B 28 07 jr z,7F34

ROM5:7F2D AF xor a

ROM5:7F2E 12 ld (de),a

ROM5:7F2F E1 pop hl

ROM5:7F30 D1 pop de

ROM5:7F31 D1 pop de

ROM5:7F32 18 16 jr 7F4A

ROM5:7F34 3E 01 ld a,01

ROM5:7F36 EA A0 D1 ld (D1A0),a

ROM5:7F39 23 inc hl

ROM5:7F3A 7E ld a,(hl)

ROM5:7F3B FE FF cp a,FF

ROM5:7F3D 28 13 jr z,7F52

ROM5:7F3F D1 pop de

ROM5:7F40 E1 pop hl

ROM5:7F41 34 inc (hl)

ROM5:7F42 62 ld h,d

ROM5:7F43 6B ld l,e

ROM5:7F44 D1 pop de

Page 73: ROMHACKING GAMEBOY PRÁCTICO - Todo lo que quiso saber … · ^NOP _ ^No Operation _: Esta instrucción es la que vamos a utilizar para eliminar instrucciones cuando queramos por

ROM5:7F45 3E 0F ld a,0F

ROM5:7F47 CD 49 1D call 1D49

ROM5:7F4A 23 inc hl

ROM5:7F4B 23 inc hl

ROM5:7F4C 23 inc hl

ROM5:7F4D 23 inc hl

ROM5:7F4E 0D dec c

ROM5:7F4F 20 C0 jr nz,7F11

ROM5:7F51 C9 ret

En el registro “c” se pone el valor $07 (nº de combinaciones de botones) y en “hl” la dirección

$05:7F68 donde están los punteros.

LOCALIZAR UBICACIÓN OBJETOS PARA DIBUJAR EN PANTALLA

En muchos juegos se utilizan objetos de tamaño 2*2 o de otro tamaño que se ponen en la

pantalla para dibujar el nivel, el fondo,…. Por ejemplo, en el juego “Addams Family” en la

siguiente pantalla podemos ver objetos con forma de cara:

El recuadro de las caras está formado por 2 tiles arriba y otros 2 abajo para dibujarlo (los dos

primeros tienen los valores $01, $02 y los de debajo $03 y $04).

El primer bloque con cara que aparece en la parte superior izquierda de la pantalla comienza

en la dirección $9842=Map Address tal y como se ve en la captura por lo que si ponemos un

breakpoint cuando se escriba en la dirección $9842 el valor $01.

El emulador se para en la dirección $00:1301, “pc” tiene el valor 4 y el registro “hl” tiene el

valor $5740 (con lo que corresponde a la dirección $04:5740=$11740 y en $04:573F=$1173F

Page 74: ROMHACKING GAMEBOY PRÁCTICO - Todo lo que quiso saber … · ^NOP _ ^No Operation _: Esta instrucción es la que vamos a utilizar para eliminar instrucciones cuando queramos por

tenemos los datos para dibujar el bloque 2*2) y en $04:573B ($1173B encontramos el inicio de

los datos para dibujar objetos).

El fragmento de código que dibuja objetos en la pantalla es el siguiente:

ROM0:12E6 6F ld l,a

ROM0:12E7 26 00 ld h,00

ROM0:12E9 29 add hl,hl

ROM0:12EA 29 add hl,hl

ROM0:12EB F0 BA ld a,(ff00+BA)

ROM0:12ED 85 add l

ROM0:12EE 6F ld l,a

ROM0:12EF F0 BB ld a,(ff00+BB)

ROM0:12F1 8C adc h

ROM0:12F2 67 ld h,a

ROM0:12F3 F0 41 ld a,(ff00+41)

ROM0:12F5 2F cpl

ROM0:12F6 E6 03 and a,03

ROM0:12F8 20 F9 jr nz,12F3

ROM0:12FA F0 41 ld a,(ff00+41)

ROM0:12FC E6 03 and a,03

ROM0:12FE 20 FA jr nz,12FA

ROM0:1300 2A ldi a,(hl)

ROM0:1301 12 ld (de),a

ROM0:1302 1C inc e

ROM0:1303 2A ldi a,(hl)

ROM0:1304 12 ld (de),a

ROM0:1305 3E 1F ld a,1F

ROM0:1307 83 add e

ROM0:1308 5F ld e,a

ROM0:1309 8A adc d

ROM0:130A 93 sub e

ROM0:130B 57 ld d,a

Page 75: ROMHACKING GAMEBOY PRÁCTICO - Todo lo que quiso saber … · ^NOP _ ^No Operation _: Esta instrucción es la que vamos a utilizar para eliminar instrucciones cuando queramos por

ROM0:130C 2A ldi a,(hl)

ROM0:130D 12 ld (de),a

ROM0:130E 1C inc e

ROM0:130F 7E ld a,(hl)

ROM0:1310 12 ld (de),a

ROM0:1311 1C inc e

ROM0:1312 C9 ret

Este fragmento de código se encarga de dibujar objetos en la pantalla y parece que se le pasa

la dirección Map Address a través de las direcciones $FFBA y $FFBB.

ROM0:1305 3E 1F ld a,1F

Esto lo que hace es añadir $1F para incrementar la Map Address para la parte inferior del

bloque. Para el primer bloque que hemos visto pone el valor $01 en la dirección $9842=Map

Address, luego pone el valor $02 en la dirección $9843=Map Address.

A continuación le suma $1F para obtener $9843+$1F=$9862=Map Address donde pone el valor

$03 para la parte inferior del bloque e incrementa la dirección Map Address=$9863 donde

pone el valor $04 con lo que ya está dibujado completamente el bloque.

OAM

La OAM (Object Address Memory) es una parte de la memoria donde se almacenan datos de

los sprite que se utilizan para realizer algunas animaciones en el juego como puede ser

representar el personaje que manejamos y sus diferentes posiciones y movimientos.

Esta memoria ocupa $A0 bytes (160 bytes) lo que permite almacenar los datos de 40 sprites

que como máximo puede poner en pantalla la Gameboy con lo que cada sprite ocupa 4 bytes

(1 byte para Y-loc, 1 byte para X-loc, 1 byte para Tile, 1 byte para Atributo).

Además de en este área de la pantalla los juegos de Gameboy utilizan una rutina para poner

una copia de estos datos en la memoria RAM y que tiene la siguiente estructura:

ROM0:04C2 3E DD ld a,DD

ROM0:04C4 E0 46 ld (ff00+46),a

ROM0:04C6 3E 28 ld a,28

ROM0:04C8 3D dec a

ROM0:04C9 20 FD jr nz,04C8

ROM0:04CB C9 ret

Esta es la rutina que encontramos en el juego “Kid Dracula (U) [!]” y que pone el valor $DD en

la dirección $FF46 con lo que la copia de la OAM se encuentra en la dirección $DD00-$DD9F lo

que hace un total de $A0 bytes.

Page 76: ROMHACKING GAMEBOY PRÁCTICO - Todo lo que quiso saber … · ^NOP _ ^No Operation _: Esta instrucción es la que vamos a utilizar para eliminar instrucciones cuando queramos por

Para localizar esta rutina basta con poner un breakpoint cuando se escribe en la dirección

$FF46 en cualquier juego de Gameboy. Los juegos que he visto hasta ahora cargan en “a” el

valor $28 que según un manual que hay en inglés sobre la Gameboy es la longitude del loop.

Si miramos en $DD00-$DD9F encontramos los mismos valores que aparecen en la pestaña

“OAM” del “bgb vram viewer”.

MODIFICACIONES EN JUEGOS

Las modificaciones en los juegos o ROMs son permanentes por lo que una vez cambiados

serán permanente lo que no ocurre para el caso de los cheats que se pueden activar y

desactivar en cualquier momento.

VIDAS

Esta es una de las modificaciones que podemos realizar en los juegos para cambiar el número

de vidas iniciales o lo que ocurre cuando perdemos una vida.

Para modificar las vidas tenemos primero que buscar la dirección donde se guarda en la RAM.

Para el caso del juego “Boulder Dash” lo encontramos en la dirección $D762.

Para encontrar el fragmento de código donde se ponen las vidas iniciales ponemos un

breakpoint cuando se escribe en la dirección $D762 al iniciar el juego con lo que vamos a

esperar a que se pare el emulador.

En $00:06FC se para el emulador pero no es aquí lo que buscamos con lo que se para en la

dirección $00:027D donde encontramos el fragmento que buscamos:

ROM0:027B 3E 03 ld a,03

ROM0:027D EA 62 D7 ld (D762),a

ROM0:0280 EA 63 D7 ld (D763),a

Este juego permite la opción de 2 jugadores por lo que la dirección $D762=Vidas jugador 1 y

$D763=Vidas jugador 2.

Lo que hace esto es poner el valor $03 en las direcciones $D762 y $D763 para poner las vidas

iniciales de ambos jugadores.

Cambiando la primera instrucción podemos hacer que tengamos más o menos vidas:

ROM0:027B 3E 09 ld a,09

Empezamos con 9 vidas. Podemos hacerlo cambiando el byte $27C con un editor hexadecimal.

Igualmente, se parará el emulador en la dirección $01:4026 cuando perdemos un vida donde

encontramos el fragmento de código:

ROM1:401F 21 62 D7 ld hl,D762

ROM1:4022 7E ld a,(hl)

ROM1:4023 D6 01 sub a,01

ROM1:4025 27 daa

Page 77: ROMHACKING GAMEBOY PRÁCTICO - Todo lo que quiso saber … · ^NOP _ ^No Operation _: Esta instrucción es la que vamos a utilizar para eliminar instrucciones cuando queramos por

ROM1:4026 77 ld (hl),a

En $01:4023 encontramos la instrucción “sub a,01” que lo que hace es disminuir en $01 el

número de vidas.

Si cambiamos esa instrucción:

ROM1:4023 D6 00 sub a,00

Se disminuye en $00 el valor de las vidas con lo que no cambia y tendríamos siempre el mismo

número de vidas (es decir vidas infinitas).

Otro cambio que podríamos hacer es cambiando esa instrucción por:

ROM1:4023 C6 01 add a,01

Con esto lo que hacemos es que en lugar de perder vidas en el juego cuando nos caiga una

roca encima se incrementa el número de vidas ya que se añade el valor $01 al número de

vidas.

Esto ocurre para las vidas del jugador 1 pero podemos hacerlo también para el jugador 2

poniendo un breakpoint en la dirección $D763 y viendo donde se disminuyen las vidas del

jugador 2.

ENERGÍA

Algunos juegos tienen indicadores de energía además de un indicador de vidas que va

disminuyendo conforme nos golpean los enemigos.

Para el ejemplo, podemos utilizar el juego “Addams Family: Pugsley´s Scavenger Hunt” que

cuenta con un indicador de energía.

En la dirección $C196 se guarda la energía en la memoria RAM por lo que poniendo un

breakpoint cuado se escriba en esta dirección podemos averiguar cuando se pone el valor

inicial de la energía y cuando se disminuye.

La energía inicial se pone en el siguiente fragmento de código:

ROM0:0257 FA A5 C1 ld a,(C1A5)

ROM0:025A EA 96 C1 ld (C196),a

Como se observa no se pone directamente el valor en la dirección $C196=Energía sino que se

carga el valor que hay en la dirección $C1A5 (que tiene el valor $03) y se pone este valor en la

dirección $C196=Energía.

Podríamos poner un breakpoint en la dirección $C1A5 para averiguar cuando se pone el valor

$03 que es la energía inicial en esta dirección que encontramos en el código:

ROM2:7FE8 0E 03 ld c,03

ROM2:7FEA CB 67 bit 4,a

ROM2:7FEC 28 01 jr z,7FEF

ROM2:7FEE 0C inc c

Page 78: ROMHACKING GAMEBOY PRÁCTICO - Todo lo que quiso saber … · ^NOP _ ^No Operation _: Esta instrucción es la que vamos a utilizar para eliminar instrucciones cuando queramos por

ROM2:7FEF E6 20 and a,20

ROM2:7FF1 28 01 jr z,7FF4

ROM2:7FF3 0C inc c

ROM2:7FF4 79 ld a,c

ROM2:7FF5 EA A5 C1 ld (C1A5),a

ROM2:7FF8 C9 ret

En $02:7FF4 se pone el valor del registro “c” en el registro “a” (a=c) que vale $03 y se pone

este valor en la dirección $C1A5 (en la instrucción en $02:7FF5).

Como vemos, es un proceso complicado al no poner directamente el valor de la energía en la

dirección $C196 por lo que podríamos cambiar la instrucción en $00:0257:

ROM0:0257 FA A5 C1 ld a,(C1A5)

Como ocupa 3 bytes la instrucción (FA A5 C1) podemos poner una instrucción que ocupe como

mucho ese espacio.

Si ponemos en esa dirección la instrucción:

ROM0:0257 3E 05 ld a,05

Con esto ponemos en el registro “a” el valor $05, pero ocupa sólo 2 bytes (3E 05) por lo que

nos queda 1 byte de espacio que podemos ocupar con la instrucción “nop” (00) que ocupa un

byte y que equivale a “NOt oPeration: No hace nada) con lo que quedaría como:

ROM0:0257 3E 05 ld a,05

ROM0:0259 00 nop

ROM0:025A EA 96 C1 ld (C196),a

Esta modificación lo que hace es poner el valor $05 en la dirección $C196, con lo que

empezaremos con $05 de energía inicial.

Ahora ya da igual el valor que haya en la dirección $C1A5 ya que ahora ya no se lee el valor

que hay en esa dirección y se pone directamente el valor que hemos puesto en $C196=Energía.

La instrucción “nop” es muy útil ya que nos va a permitir llenar el espacio en blanco cuando

cambiamos instrucciones que ocupan menos espacio del que había.

El código donde se disminuye la energía lo encontramos en:

ROM0:390F 21 96 C1 ld hl,C196

ROM0:3912 7E ld a,(hl)

ROM0:3913 A7 and a

ROM0:3914 C8 ret z

ROM0:3915 35 dec (hl)

ROM0:3916 CD 3A 0F call 0F3A

Page 79: ROMHACKING GAMEBOY PRÁCTICO - Todo lo que quiso saber … · ^NOP _ ^No Operation _: Esta instrucción es la que vamos a utilizar para eliminar instrucciones cuando queramos por

La instrucción en $00:3915 encontramos la instrucción que disminuye el valor que hay en la

dirección contenida en hl=$C196 (que se pone en $00:390F) con lo que disminuimos la

energía.

Eliminando esta instrucción en $00:3915 podemos conseguir tener energía infinita:

ROM0:3915 00 nop

Con este cambio en lugar de disminuir la energía, el juego no haría nada y seguiría la energía

tal cual lo que tiene el efecto de tener energía infinita.

La instrucción “nop” (Not oPeration: No operación) es muy útil para rellenar el espacio que nos

sobra cuando cambiamos instrucciones.

OBJETOS

En determinados juegos debemos coger un número de objetos para obtener una vida extra o

pasar de nivel por lo que podemos hacer algunas modificaciones en este sentido. Para el

ejemplo, vamos a utilizar el juego “Super Mario Land” donde debemos coger 100 monedas

para que nos den una vida extra.

Buscando la dirección donde se guardan las monedas en la RAM lo encontramos en la

dirección $FFFA y poniendo un breakpoint cuando se escriba en esta dirección cada vez que

cogemos las monedas el emulador se parará con lo que obtenemos:

ROM0:1C04 F0 FA ld a,(ff00+FA)

ROM0:1C06 C6 01 add a,01

ROM0:1C08 27 daa

ROM0:1C09 E0 FA ld (ff00+FA),a

Page 80: ROMHACKING GAMEBOY PRÁCTICO - Todo lo que quiso saber … · ^NOP _ ^No Operation _: Esta instrucción es la que vamos a utilizar para eliminar instrucciones cuando queramos por

En $00:1C06 encontramos la instrucción que incrementa las monedas y que podemos cambiar

por:

ROM0:1C06 C6 10 add a,10

Con esto cuando cogemos una moneda se incrementa el número de monedas que hemos

cogido en 10 en lugar de en 1. Haciendo esto con cada 10 monedas (equivalen a 100)

obtendremos una vida adicional en el juego.

Podemos situarnos con el emulador en el “bgb debugger” en la instrucción $00:1C06

seleccionado “Go to…” e introducciendo esta instrucción.

Seleccionando “Modify code/data” e introducciendo la anterior instrucción podemos ver como

afecta el cambio cuando cogemos una moneda.

Seleccionando la opción “Save ROM as…” del menu “File” podemos guardar el juego

modificado con otro nombre como “Super Mario Land (W) (V1.0) [!] facil.gb”.

También se puede hacer la modificación con el programa “GameBoy Assembly Editor”

abriendo el juego y seleccionando la opción “Goto…” del menú “Search” e introduciendo la

dirección $00:1C06.

Con el botón derecho sobre la dirección podemos seleccionar la opción “Change Instruction…”

e introducir la nueva orden “add a,10” para hacer el cambio.

Page 81: ROMHACKING GAMEBOY PRÁCTICO - Todo lo que quiso saber … · ^NOP _ ^No Operation _: Esta instrucción es la que vamos a utilizar para eliminar instrucciones cuando queramos por

Esta modificación también podemos hacerla en otros juegos como en “McDonalland” en el

que tenemos que coger 100 objetos con la letra “M” para obtener una vida adicional en el

fragmento de código:

ROM0:36B4 47 ld b,a

ROM0:36B5 FA FE D3 ld a,(D3FE)

ROM0:36B8 FE 99 cp a,99

ROM0:36BA 30 07 jr nc,36C3

ROM0:36BC 80 add b

ROM0:36BD 27 daa

ROM0:36BE EA FE D3 ld (D3FE),a

Cambiando este fragmento podemos hacer que sea mucho más fácil obtener una vida extra:

ROM0:36B4 FA FE D3 ld a,(D3FE)

ROM0:36B7 FE 99 cp a,99

ROM0:36B9 30 08 jr nc,36C3

ROM0:36BB C6 11 add a,11

ROM0:36BD 27 daa

ROM0:36BE EA FE D3 ld (D3FE),a

Con esta modificación con cada objeto “M” se incrementa el contador en $11 unidades con lo

que bastan sólo 10 para obtener una vida más.

Page 82: ROMHACKING GAMEBOY PRÁCTICO - Todo lo que quiso saber … · ^NOP _ ^No Operation _: Esta instrucción es la que vamos a utilizar para eliminar instrucciones cuando queramos por

También se puede cambiar por ejemplo, la instrucción en $00:36B8:

ROM0:36B8 FE 05 cp a,05

Con este cambio sólo necesitaríamos 5 objetos para obtener una vida más.

CÓDIGOS GAME GENIE

La consola Gameboy disponía de un accesorio llamado “Game Genie” que permitía obtener

ventajas en los juegos. El emulador “BGB” permite también la introducción de estos códigos en

la pantalla de “bgb cheats” en el apartado de “Code”.

En internet hay páginas donde podemos encontrar códigos Game Genie para una gran

variedad de juegos de Gameboy como www.bsfree.org, www.gamegenie.com,...

Por ejemplo, el juego “The Jetsons” tiene el código Game Genie 09F-16C-E66 (empezar con 9

vidas) que podemos introducer en el emulador “BGB” en la pantalla de “bgb cheats” tal y

como se ve en la imagen.

Una vez pulsado el botón “OK” nos mostrará la siguiente pantalla:

Page 83: ROMHACKING GAMEBOY PRÁCTICO - Todo lo que quiso saber … · ^NOP _ ^No Operation _: Esta instrucción es la que vamos a utilizar para eliminar instrucciones cuando queramos por

En esta pantalla en la izquierda encontramos el código Game Genie introducido (“09F-16C-

E66”) para empezar con 9 vidas y a continuación aparece “G-E” para indicar que este código

está active.

A continuación aparece “(3F16)=09<-03” que indica que la dirección $00:3F16 es el que tiene

que modificar para empezar con 9 vidas. “=09” es el valor que se pone para empezar con ese

número de vidas y “<-03” es el valor que aparece por defecto en esa dirección (ya que en este

juego el valor de vidas inicial es de 3).

El aparecer este valor $03 es para indicarle al emulador el valor a buscar ya que en el caso de

que hubiera sido una dirección entre $4000-$7FFF correspondiente a algún banco no se sabe

de que banco estamos tratando.

Así, por ejemplo, si hubiese sido la dirección $7BCA y el valor a buscar hubiese sido $03,

entonces debería el emulador mirar en los diferentes bancos en cual de ellos aparece en esa

dirección el valor $03 para cambiarlo por $09 para tener 9 vidas.

Si en $01:7BCA=$02, $02:7BCA=$03 entonces se pone el valor $09 en la dirección $02:7BCA

para tener 9 vidas.

Estos no son modificaciones en la ROM sino que son temporales y se pueden activar y

desactivar en cualquier momento igual que los que introducimos en las direcciones de la RAM.

Esta información también nos la muestra el programa “Game Genie Encoder/Decoder 0.91a”

introduciéndola tal y como se muestra en la imagen:

También nosotros con este programa podemos crear nuestros propios código Game Genie

introduciendo el valor (“Value”), la dirección (“Address”) y el valor de comparación

(“Compare”).

En el juego “Boulder Dash” veíamos como había un fragmento de código donde se ponen las

vidas iniciales del jugador 1 y 2:

ROM0:027B 3E 03 ld a,03

Page 84: ROMHACKING GAMEBOY PRÁCTICO - Todo lo que quiso saber … · ^NOP _ ^No Operation _: Esta instrucción es la que vamos a utilizar para eliminar instrucciones cuando queramos por

ROM0:027D EA 62 D7 ld (D762),a

ROM0:0280 EA 63 D7 ld (D763),a

El byte $00:027C tiene el valor $03 por lo que podemos obtener un código Game Genie para

empezar por ejemplo con 7 vidas en lugar de 3 introduciendo en el programa los datos:

Value=07

Address=027C

Compare=03

El programa nos genera el código Game Genie correspondiente (072-7CF-E66) para que los

jugadores 1 y 2 empiecen con 7 vidas.

Page 85: ROMHACKING GAMEBOY PRÁCTICO - Todo lo que quiso saber … · ^NOP _ ^No Operation _: Esta instrucción es la que vamos a utilizar para eliminar instrucciones cuando queramos por

BÚSQUEDA DE CHEATS NO TÍPICOS

Normalmente se suele buscar el número de vidas y energía cuando se buscan valores en la

RAM pero sin embargo podemos buscar cualquier cosa que se pueda almacenar en la

memoria.

Algunos casos pueden ser los siguientes entre otros muchos:

DIRECCIÓN DEL PERSONAJE

En los juegos de plataformas el personaje que manejamos se mueve hacia la derecho o

izquierda de la pantalla por lo que podemos buscar este valor que cambiará cuando cambie la

dirección de éste.

El proceso es similar a cualquier otro valor bastando con estar en una dirección e iniciar la

búsqueda para cambiar luego de posición buscando valores que no sean iguales repitiendo así

el proceso con cambios de valores cuando cambias de dirección o no cambios de valores

cuando está el personaje en la misma dirección.

Haciendo esto encontramos la dirección y los valores que aparecen en la captura.

COORDENADAS X,Y PERSONAJE Y ENEMIGOS

Otro valor que podemos buscar en los juegos son las coordenadas de los personajes que

encontramos en la pantalla del juego tal y como se ve en la siguiente captura:

Page 86: ROMHACKING GAMEBOY PRÁCTICO - Todo lo que quiso saber … · ^NOP _ ^No Operation _: Esta instrucción es la que vamos a utilizar para eliminar instrucciones cuando queramos por

Estos valores podemos activarlos para que se queden quietos los enemigos en una posición de

la pantalla o desactivarlos para que se muevan normalmente.

PUNTUACIÓN

Para los tramposos que quieran aparecer en la pantalla de High Scores de forma fácilmente

podemos buscar las direcciones donde se guarda la puntuación que tenemos en el juego y

cambiarla por el valor que queramos.

Para este caso las direcciones que se ven implicadas son $C490-$C492.

$C490: Score xx00000

$C491: Score 00xx000

$C492: Score 0000xx0

Page 87: ROMHACKING GAMEBOY PRÁCTICO - Todo lo que quiso saber … · ^NOP _ ^No Operation _: Esta instrucción es la que vamos a utilizar para eliminar instrucciones cuando queramos por

Los valores “xx” indicant el valor que ponemos en esa dirección. Por ejemplo, para los valores

$C490=$76, $C491=$32, $C492=$89 tendremos una puntuación de “763289”.

Igualmente ocurre con las direcciones donde se almacena en este juego el HI-SCORE que son

las direcciones $C4A0-$C4A2 con la misma estructura que el anterior:

$C4A0: Hi-Score xx00000

$C4A1: Hi-Score 00xx000

$C4A2: Hi-Score 0000xx0

Como se comprueba el ultimo dígito es siempre “0” y no se almacena en la RAM. Sin embargo,

esta no es la única forma que nos podemos encontrar a la hora de poner la puntuación en la

RAM.

También la forma de almacenarse los valores puede cambiar por lo que en un juego un valor

de $32 puede corresponder a “32” y para otro puede corresponder a “50”.

$32 hexadecimal=50 decimal.

En este caso, se utilizan 2 digitos por dirección de la RAM pero podemos encontrarnos una

dirección por cada dígito de la RAM y podemos encontrarnos que el ultimo dígito cambie por

lo que en este caso se utilizaría otra dirección para ese dígito.

A veces la puntuación también se puede almacenar en formato hexadecimal utilizando 2 o 3

direcciones de la RAM poniéndose el valor en formato hexadecimal normal o inverso y utilizar

o no el ultimo dígito como en este juego.

Por ejemplo, supongamos que tenemos en una dirección de la RAM el valor $12 y en la

siguiente dirección $35 donde se pone la puntuación en la RAM con lo que dependiendo de la

forma que utilice el juego la puntuación podría ser:

$1235=4661 puntos

$1235=46610 puntos (no se utiliza el último dígito y es siempre 0)

$3512=13586 puntos

$3512=135860 puntos (no se utiliza el ultimo dígito y es siempre 0)

Esta forma no es la más habitual pero también podríamos encontrárnosla en algún juego.

Otra forma que nos podemos encontrar es la que ocurre por ejemplo en el juego “Mr. Do!” en

la que cada dígito se pone en una dirección de la RAM pero en formato tile (Tile $30=”0”, Tile

$31=”1”,…,$39=”9”).

Page 88: ROMHACKING GAMEBOY PRÁCTICO - Todo lo que quiso saber … · ^NOP _ ^No Operation _: Esta instrucción es la que vamos a utilizar para eliminar instrucciones cuando queramos por

En el juego “Mr. Do!” la puntuación se guarda en las direcciones $D0D3-$D0D8 para poner los

6 dígitos.

$D0D3: Score x00000

$D0D4: Score 0x0000

$D0D5: Score 00x000

$D0D6: Score 000x00

$D0D7: Score 0000x0

$D0D8: Score 00000x

OPCIÓN MENÚ PRINCIPAL

Otro valor que podemos buscar es la opción de los menús como puede ser el menú principal (a

veces una misma dirección se utiliza para varios menús). La búsqueda de este valor se puede

utilizar más que por tener ventajas (que no se va a tener) que por conocer como funciona el

juego para localizar el fragmento de código que se encarga de poner la opción del menu

principal, situar el cursor (si lo tiene), cambiar la opción del menú,...

Este es un valor muy fácil de localizar ya que basta con situar el cursor sobre una u otra opción

y realizando búsquedas.

Así para el caso del menu principal del juego “Jurassic Park” encontramos que en la dirección

$FFAE se guarda la opción del menú principal.

Page 89: ROMHACKING GAMEBOY PRÁCTICO - Todo lo que quiso saber … · ^NOP _ ^No Operation _: Esta instrucción es la que vamos a utilizar para eliminar instrucciones cuando queramos por

Los valores que se ponen en la dirección $FFAE son los siguientes:

$00: START

$01: INFO

$02: SOUND

OBJETOS PARA PASAR DE NIVEL

En algunos juegos como “Boulder Dash” tienen un número de objetos en el nivel que tenemos

que coger para poder pasar al nivel siguiente.

Para el caso que vamos a tratar tenemos que coger diamantes y una vez hecho ésto debemos

llegar a la salida del nivel que estará active para ir al siguiente nivel.

Realizando una búsqueda del cheat viendo cuando va disminuyendo el número de diamantes

del nivel comprobamos que se guarda en la dirección $D7C9 de la RAM.

Podemos añadir un cheat en la dirección $D7C9 con el valor $01 con lo que nos quedaría 1

diamante solo para poder activar la salida del nivel. Hay que activar el cheat para que tenga el

valor $01 y una vez hecho esto desactivarlo para que se quede ese valor.

Si no lo desactivamos no podríamos pasar de nivel porque siempre quedaría un diamante. Al

desactivarlo cuando cojamos un diamante más ya no quedarán diamantes y se active la salida.

Hay veces en juegos que simplemente poniendo el valor $00 se pasar automáticamente de

nivel ya que no quedan objetos pero en este caso no. Cuando se pasa automáticamente

podemos desactivar el cheat cuando queramos o pasará todos los niveles solo.

Page 90: ROMHACKING GAMEBOY PRÁCTICO - Todo lo que quiso saber … · ^NOP _ ^No Operation _: Esta instrucción es la que vamos a utilizar para eliminar instrucciones cuando queramos por

TIEMPO

Si nos fijamos en el anterior juego (“Boulder Dash”) vemos como en la pantalla del nivel

aparece un contador del tiempo que disminuye y que podemos buscar para poner una

cantidad mayor de la que disponemos e incluso tiempo infinito.

Realizando la búsqueda cuando disminuye el valor encontramos la dirección $D7F0 donde se

pone el tiempo y puede tomar los valores entre $00 y $FF (0 y 255). El valor máximo que

podemos poner es de 255.

Si nos fijamos en un único dígito del tiempo para ver si disminuye o se incrementa

encontramos otras direcciones.

Para ello, por ejemplo si nos fijamos en el dígito de las unidades, si en la búsqueda tenemos

“94” y en la siguiente búsqueda “87” pondríamos que busque valores que han aumentado ya

que el valor de las unidades ha pasado de “4” a “7” (“keep values which are above the

previous value”).

Haciendo esto encontramos que en la dirección $D792 se pone el valor del dígito de las

unidades en formato texto o ASCII (el valor $30=”0”, $31=”1”,…,$39=”9”.

Encontramos en el juego las siguientes direcciones de la RAM:

Tiempo x00 (Texto): D790

Tiempo 0x0 (Texto): D791

Tiempo 00x (Texto): D792

Diamantes quedan x00 (Texto): D794

Page 91: ROMHACKING GAMEBOY PRÁCTICO - Todo lo que quiso saber … · ^NOP _ ^No Operation _: Esta instrucción es la que vamos a utilizar para eliminar instrucciones cuando queramos por

Diamantes quedan 0x0 (Texto): D795

Diamantes quedan 00x (Texto): D796

Diamantes nivel (?): D798-D79A (mismo formato que los anteriores)

Diamantes nivel (?): D79C-D79E (mismo format que los anteriores. Tiene el mismo valor que

las anteriores direcciones D798-D79A).

CONTADOR TIEMPO PANTALLA “CONTINUE”

Otro valor poco frecuente pero que podemos buscar es el contador de tiempo que aparece

cuando perdemos todas las vidas en algunos juegos y nos permite continuar o terminar el

juego tal y como ocurre en el juego “Boulder Dash”.

Esto no tiene demasiada utilidad salvo para a través de breakpoints conocer el fragmento de

código que pone el tiempo del contador y disminuirlo.

En este juego lo encontramos en la dirección $D7BA.

TIEMPO DE INVULNERABILIDAD

En ciertos juegos al iniciar el nivel el personaje que manejamos tiene un tiempo en el que es

invulnerable a los enemigos y durante el cual no pueden eliminarnos como ocurre en el juego

“Addams Family: Pugsley´s Scavenger Hunt”.

Podemos buscar la dirección donde se guarda este tiempo realizando búsquedas cuando el

personaje está parpadeando indicando que estamos en el tiempo de invulnerabilidad.

Debemos hacerlo más o menos rápido porque no dura mucho pero no es muy complicado.

Page 92: ROMHACKING GAMEBOY PRÁCTICO - Todo lo que quiso saber … · ^NOP _ ^No Operation _: Esta instrucción es la que vamos a utilizar para eliminar instrucciones cuando queramos por

En este caso se encuentra dicho valor en la dirección $C1C7 tomando los valores $00 cuando

está desactivado, $01 cuando está activado y si el valor es mayor a $01 el personaje puede ser

atravesado por algunos enemigos como se ve en la pantalla sin perder energía.

Si activamos el cheat no disminuirá la energía del personaje y no nos podrán eliminar los

enemigos.

ENERGÍA

Un valor habitual que se puede encontrar es la energía y podemos hacer que el personaje que

manejamos no pierda la energía cuando nos golpeen los enemigos. Para el ejemplo podemos

utilizar el juego “Addams Family: Pugsley´s Scavenger Hunt” que habíamos visto antes y que se

guardaba en la dirección $C196.

POSICIÓN ENEMIGO FINAL

En algunos juegos al final de determinados niveles tenemos un enemigo final que se va

moviendo por la pantalla y que podemos localizar la posición y dejarlo inmóvil para lo cual

podemos buscar sus coordenadas como hacíamos antes en otro juego. Aquí podemos utilizar

el juego “Addams Family”.

Page 93: ROMHACKING GAMEBOY PRÁCTICO - Todo lo que quiso saber … · ^NOP _ ^No Operation _: Esta instrucción es la que vamos a utilizar para eliminar instrucciones cuando queramos por

Buscando la coordenada X del personaje lo encontramos en la dirección $C1D9 y la

coordenada Y en la dirección $C1D7. Sin embargo, si ponemos un valor bajo en $C1D7

(Coordenada Y) veremos como la parte superior del enemigo no se muestra la parte de arriba

como si estuviera detrás de los ladrillos del fondo.

COORDENADAS X,Y OBJETO PANTALLA TÍTULO

En el juego “Adventure Island” encontramos que en la pantalla de título aparece el personaje

que manejamos siguiendo a un huevo y que podríamos buscar las coordenadas de dicho huevo

que se va moviendo por la pantalla.

Esta búsqueda es más por intentar comprender el juego que por conseguir ventaja alguna en

el juego pero es una de las muchas posibilidades que tiene la búsqueda de cheats.

Page 94: ROMHACKING GAMEBOY PRÁCTICO - Todo lo que quiso saber … · ^NOP _ ^No Operation _: Esta instrucción es la que vamos a utilizar para eliminar instrucciones cuando queramos por

Los valores donde se guardan las coordenadas son los que aparecen en la captura ($C211:

Coordenada Y Huevo y $C213: Coordenada X Huevo).

OBJETO DEL PERSONAJE O PODER

En el juego “Adventure Island” podemos coger elementos que nos dan un determinado objeto

o personaje y que buscándolo en la RAM nos daría la dirección $C428 para lo cual debemos

poner los valores que aparecen en la captura antes de que comience el juego (o el nivel creo).

ESTADO DEL PERSONAJE

En el juego “B.C. Kid” el personaje puede tomar varios estados o personajes que adopta y que

se guardan en la RAM en la dirección $C5B0.

Estos valores son:

00: Normal

01: Frankenstein

Page 95: ROMHACKING GAMEBOY PRÁCTICO - Todo lo que quiso saber … · ^NOP _ ^No Operation _: Esta instrucción es la que vamos a utilizar para eliminar instrucciones cuando queramos por

02: Punky

03: Tortuga

04: Alien

05: Patinador

También puede adopter otros valores que son mezcla de alguno de éstos pero los anteriores

son los principales.

Podemos activar con cheats cualquier de estos valores para cambiar el estado del personaje.

NIVEL

Este es uno de los valores más útiles que podemos encontrar y que nos puede permitir

empezar en cualquier nivel para lo cual debemos jugar al juego y cuando pasemos a otro nivel

buscar los valores que se han incrementado. Debemos realizar el proceso hasta que

encontremos el valor donde se almacena en la RAM que corresponde a la dirección $C413.

La primera imagen de la izquierda corresponde al inicio de “FERN ISLAND” y la de la derecha

con el valor $04 corresponde a otra area de “FERN ISLAND”. Los valores para el inicio de cada

nivel tienen los valores siguientes correspondiendo los valores intermedios a areas de cada

isla:

00: FERN ISLAND

08: LAKE ISLAND

Page 96: ROMHACKING GAMEBOY PRÁCTICO - Todo lo que quiso saber … · ^NOP _ ^No Operation _: Esta instrucción es la que vamos a utilizar para eliminar instrucciones cuando queramos por

10: DESERT ISLAND

18: ICE ISLAND

20: CAVE ISLAND

28: CLOUD ISLAND

30: VOLCANO ISLAND

38: DINOSAUR ISLAND

Podemos activar el cheat en cualquier momento aunque si estamos ya en un nivel concreto el

efecto lo notaremos cuando perdamos una vida que cambia al nivel que tengamos

seleccionado.

También cuando estemos llegando al final del nivel que hemos seleccionado podemos

desactivarlo para que pasemos al siguiente nivel.

DIRECCIÓN PERSONAJE

En el juego “Adventures of Lolo” el personaje toma 4 direcciones (de frente, de espalda,

izquierda y derecha) con lo que podemos buscar el valor de la RAM donde se guarda en la

dirección $C4B1 tal y como se ve en la captura con sus correspondientes valores:

Si activamos el cheat con uno de estos valores el personaje se moverá a lo largo de la pantalla

en la dirección que hayamos puesto.

DATOS DE LAS MÁXIMAS PUNTUACIONES EN LA RAM

En el juego “Mr. Do!” las máximas puntuaciones están en la RAM aunque esto puede no darse

en todos los juegos que tienen esta pantalla sino que estén en el juego (ROM) y se carguen

desde ahí sin ponerla en la RAM pasándose directamente desde la ROM a pantalla.

Page 97: ROMHACKING GAMEBOY PRÁCTICO - Todo lo que quiso saber … · ^NOP _ ^No Operation _: Esta instrucción es la que vamos a utilizar para eliminar instrucciones cuando queramos por

En este caso los datos están almacenados en formato texto y en formato hexadecimal.

También podríamos hacerlo con juegos que tengan textos para intentar localizar si los textos

están en la RAM.

En los juegos normalmente se utilizan las direcciones $C000-$DFFF ($2000 bytes) para

almacenar datos en la RAM aunque hay juegos que utilizan más memoria RAM sobre todo en

juegos de Gameboy Color y a partir de la dirección $FF80-$FFFF que es la High RAM donde se

ponen también datos.

En estos juegos el número de bytes de la RAM son $207F (8319 tal y como aparece cuando

iniciamos la búsqueda de cheats).

Si nos situamos en el debugger podríamos poner “Go to…” e introducir la dirección $C000 que

es el inicio de la RAM y selecionar la opción “save memory dump…” del menú “File”.

Le ponemos el nombre que queramos al fichero y de longitude podemos poner $4000 que

engloba las direcciones ($C000-$FFFF) para tener tanto la RAM como la High RAM en el

fichero.

Si abrimos el fichero con un editor hexadecimal podríamos buscar para ver si nos aparece

algún tipo de texto del que aparece en la pantalla de máximas puntuaciones o seleccionar

“Buscar” e introducir alguno de los textos de esta pantalla como “LEG” que encontramos en el

fichero creado en $1306-$1308.

Page 98: ROMHACKING GAMEBOY PRÁCTICO - Todo lo que quiso saber … · ^NOP _ ^No Operation _: Esta instrucción es la que vamos a utilizar para eliminar instrucciones cuando queramos por

Como se observa la captura va desde $1300-$135F que como la RAM empieza en la dirección

$C000 debemos sumarle a estas direcciones con lo que en $D300-$D35F tenemos estos datos

en la RAM.

Como se observan la estructura de cada línea de puntos es la siguiente:

6 bytes con la puntuación en formato texto: “147000” (31 34 37 30 30 30)

3 bytes con el nombre en formato texto: “LEG” (4C 45 47)

1 byte para el nivel en formato hexadecimal: “15” (0F)

2 bytes para el tiempo en formato hexadecimal: “08´42” (0A 02).

0A 02 corresponde a $020A hexadecimal=522 que son 8 minutos y 42 segundos.

Por tanto se utilizan 12 bytes para cada línea de la puntuación. Si buscamos toda estos valores

en el juego (ROM) lo encontramos en la dirección $00:0B2C-$00:0B8B ($B2C-$B8B).

OBTENER DATOS DE NIVEL DE UN JUEGO

BATTLE BULL

La obtención de los datos de nivel de un juego es junto con la música de los juegos de

Gameboy uno de los aspectos más complicados de localizar y modificar.

Voy a utilizar una serie de juegos a los que he encontrado dichos datos y trataré de explicar

cómo se puede obtener dicha información utilizando el emulador BGB de Gameboy.

Para el ejemplo, voy a utilizar el juego “Battle Bull” pero que igual podría funcionar para otros

juegos.

Si observamos el “BGB VRAM Viewer” donde se muestra la pantalla del nivel 1 completo

vemos que hay bloques de 2*2 para dibujarlo.

Page 99: ROMHACKING GAMEBOY PRÁCTICO - Todo lo que quiso saber … · ^NOP _ ^No Operation _: Esta instrucción es la que vamos a utilizar para eliminar instrucciones cuando queramos por

En este nivel encontramos bloques de diferentes tipos:

El primero de la parte superior izquierda se forma por los tiles $04, $06, $05, $07. (Bloque tipo

$01)

El bloque en blanco está formado por los tiles $24, $24, $24, $24 (Bloque tipo $09)

El bloque verde sólido de un color sin líneas se forma por los tiles $00, $02, $01, $03 (Bloque

tipo $00).

Podemos buscar los datos para el primer bloque (04 06 05 07) con un editor hexadecimal lo

encontramos en la dirección $C0F4-$C0F7 ($03:40F4-$03:40F7) y el bloque verde sólido (00 02

01 03) en la dirección $C0F0-$C0F3 ($03:40F0-$03:40F3).

Si miramos en la memoria RAM podemos encontrar la pantalla completa del nivel pero tal y

como se muestra en la pantalla desde la dirección $C158-$C557 ($400=1024 bytes).

Es por esto por lo que asignamos los valores de los tipos de bloques.

Bloque tipo $00: 00 02 01 03

Bloque tipo $01: 04 06 05 07

Bloque tipo $02: 08 0A 09 0B

Bloque tipo $03: 0C 0E 0D 0F

Bloque tipo $04: 10 12 11 13

Bloque tipo $05: 14 16 15 17

Page 100: ROMHACKING GAMEBOY PRÁCTICO - Todo lo que quiso saber … · ^NOP _ ^No Operation _: Esta instrucción es la que vamos a utilizar para eliminar instrucciones cuando queramos por

Bloque tipo $06: 18 1A 19 1B

Bloque tipo $07: 1C 1E 1D 1F

Bloque tipo $08: 20 22 21 23

Bloque tipo $09: 24 24 24 24

Si ponemos un breakpoint cuando se lea en la dirección $03:40F0 vemos como se para el

emulador en la dirección $00:1FC9 y se dibuja el nivel en pantalla.

Si tomamos la primera línea del nivel vemos que tenemos todos los bloques tipo $01 (16) y en

la segunda línea del nivel tenemos un bloque tipo $01, 10 bloques tipo $09, 1 bloque tipo $00,

3 bloques tipo $09 y un bloque tipo $01.

Si buscáramos la secuencia para dibujar las 2 líneas sería: 01 01 01 01 01 01 01 01 01 01 01 01

01 01 01 01 01 09 09 09 09 09 09 09 09 09 09 00 09 09 09 01.

Esta secuencia de valores hexadecimales lo encontramos en la dirección $C6C8-C6E7

($03:46C8-$03:46E7).

Si nos fijamos en la pantalla del nivel comprobamos que está formado por 16 líneas de 16

bloques cada uno lo que hace un total de 256 (como cada bloque es un bytes necesitará 256

bytes para cada nivel o $100 en hexadecimal).

Por lo que el primer nivel empieza en la dirección $C6C8 ($03:46C8) y el siguiente si van

consecutivos debe empezar $100 bytes más adelante o sea en $C7C8 ($03:47C8).

Buscando el valor C846 lo encontramos en varias posiciones de la ROM pero en $C000

($03:4000) está el valor que encontramos y en $C002 ($03:4002) encontramos C847 y en

$C004 ($03:4004) encontramos C848.

Desde la dirección $C000-$C06F están los punteros a los datos de los niveles del juego:

$03:46C8, $03:47C8, $03:48C8,…

Con esto ya hemos localizado donde están los punteros de los niveles y con esto ya tenemos

los datos para cada uno de los niveles del juego.

Modificando los bytes $03:46C8-$03:47C7 ($C6C8-$C7C7) podemos cambiar el nivel 1 del

juego a nuestro gusto.

Por ejemplo, cambiando el byte que hay en $C6C8 que tiene el valor $01 (bloque tipo $01 con

raya) por el valor $09 (sin recuadro) podemos observar como se borra el primer bloque de la

parte superior izquierda de la pantalla.

Ahora si quisiéramos podríamos hacer un programa que nos permitiera abrir cualquier nivel

del juego, mostrarlo en una pantalla, modificarlo y guardarlo en la ROM con los cambios

realizados.

Page 101: ROMHACKING GAMEBOY PRÁCTICO - Todo lo que quiso saber … · ^NOP _ ^No Operation _: Esta instrucción es la que vamos a utilizar para eliminar instrucciones cuando queramos por

En la captura vemos gráficamente dicho cambio en el nivel 1 del juego cambiando ese byte.

Igualmente si ponemos un breakpoint en la dirección $03:4000 cuando se lea se parará el

emulador en la dirección $00:1F7B.

Igualmente en otros juegos podemos buscar objetos 2*2 y buscar los datos que lo forman en la

ROM e intentar asignarle valores a cada uno de ellos e intentar localizarlos.

Aquí en la RAM se ponen 32 tiles y luego otros 32 tiles para formar la primera línea de bloques

del nivel 1.

LITTLE MAGIC (GAMEBOY COLOR)

Page 102: ROMHACKING GAMEBOY PRÁCTICO - Todo lo que quiso saber … · ^NOP _ ^No Operation _: Esta instrucción es la que vamos a utilizar para eliminar instrucciones cuando queramos por

Este juego tiene un sistema parecido al “Battle Bull” pero con una pequeña diferencia a la hora

de almacenar los objetos 2*2 para dibujar el nivel en la pantalla.

En este juego se pone el atributo y el tile correspondiente. Así por ejemplo para el árbol la

parte superior izquierda se guarda con los datos 0642 tal y como se ve en la parte derecha de

la captura con lo que se utilizan 8 bytes para cada objeto.

Para el árbol utilizaría los valores 06 42 06 43 06 52 06 53 que encontramos en las direcciones

$1224-$122B aunque voy a explicar el proceso hasta que he averiguado esta información.

En primer lugar he puesto un breakpoint en la dirección $9844=Map Address cuando se pone

el valor $42 comprobamos que el emulador se para en la dirección $00:203A donde

encontramos el fragmento de código:

ROM0:202A 44 ld b,h

ROM0:202B 4D ld c,l

ROM0:202C 21 F4 11 ld hl,11F4

ROM0:202F 09 add hl,bc

ROM0:2030 3E 01 ld a,01

ROM0:2032 E0 4F ld (ff00+4F),a

ROM0:2034 2A ldi a,(hl)

ROM0:2035 12 ld (de),a

Page 103: ROMHACKING GAMEBOY PRÁCTICO - Todo lo que quiso saber … · ^NOP _ ^No Operation _: Esta instrucción es la que vamos a utilizar para eliminar instrucciones cuando queramos por

ROM0:2036 AF xor a

ROM0:2037 E0 4F ld (ff00+4F),a

ROM0:2039 2A ldi a,(hl)

ROM0:203A 12 ld (de),a

ROM0:203B 13 inc de

El emulador cuando se para en el registro “hl” tiene el valor $1226 que corresponde a la

dirección $00:1226 donde se encuentran datos para dibujar el árbol. Esta dirección es mayor

que la de inicio de los datos ya que se ha incrementado el valor del registro “de” pero ya lo

tenemos más o menos localizado donde están los datos.

Como los tiles que forman el árbol son 42 43 52 53 vemos con el editor hexadecimal HxD que

es lo que aparece a excepción del valor $06 que aparece antes de estos valores y viendo el

“BGB VRAM Viewer” comprobamos que corresponde al atributo que también aparece en los

datos.

En el fragmento de código anterior encontramos lo siguiente:

ROM0:202C 21 F4 11 ld hl,11F4

Esta instrucción pone en el registro “hl” la dirección $00:11F4 que si vamos a esta posición

($11F4) con el editor hexadecimal comprobamos que tiene la misma estructura que para

dibujar el árbol con lo que aquí es donde empiezan los datos para dibujar los objetos que se

ponen en el nivel.

Cada objeto hemos visto que ocupa 8 bytes con lo que los objetos que encontramos son:

Objeto tipo $00 (Hierba): 06 60 06 61 06 70 06 71 ($11F4-$11FB)

Objeto tipo $01: 06 66 06 67 06 76 06 77 ($11FB-$1203)

Objeto tipo $02 (Cuadro marrón): 05 40 05 41 05 50 05 51

Objeto tipo $03: 05 64 05 65 05 74 05 75

Objeto tipo $04 (Corazón): 02 02 02 03 02 12 02 13

Objeto tipo $05 (Agua): 01 4C 01 4C 01 4C 01 4C

Objeto tipo $06 (Árbol): 06 42 06 43 06 52 06 53 ($1224-$122B)

Objeto tipo $07 (Salida): 00 22 00 23 00 32 00 33 ($122C-$1233)

Con esto ya tenemos información para buscar los posibles datos del nivel en el juego.

Si nos fijamos en la segunda línea porque tiene más variedad de valores aunque nos

podríamos haber fijado en la primera tendríamos:

02 05 06 06 06 00 00 00 06 06 06 05 02

Buscándolo lo encontramos en las direcciones $240F0-$240FC ($09:40F0-$09:40FC).

Cada línea de objetos 2*2 tiene 16 bloques por lo que se utilizan 16 bytes o $10 en

hexadecimal por lo que la primera línea si la comprobamos empieza en $240E0 ($09:24E0).

Page 104: ROMHACKING GAMEBOY PRÁCTICO - Todo lo que quiso saber … · ^NOP _ ^No Operation _: Esta instrucción es la que vamos a utilizar para eliminar instrucciones cuando queramos por

Ya tenemos localizados la ubicación de los objetos y donde están los datos para el nivel 1

aunque todavía no sabemos cuantas líneas se utilizan para cada nivel.

Podemos pasar el nivel 1 para mostrar el nivel 2 y buscar los datos de ese nivel para

encontrarlo en el juego.

La primera línea del nivel sería: 02 02 02 02 02 02 02 02 02 02 02 02 02 00 00 00

La segunda línea del nivel sería: 02 05 05 05 06 06 06 05 05 05 05 05 02 00 00 00

Buscando toda la secuencia (02 02 02 02 02 02 02 02 02 02 02 02 02 00 00 00 02 05 05 05 06

06 06 05 05 05 05 05 02 00 00 00) para asegurarnos que se trata de los datos que buscamos la

encontramos en la dirección $241C0-$241DF ($09:41C0-$09:41DF) y en $25CE0-$25CFF

($09:5CE0-$09:5CFF).

Vamos a quedarnos con las primeras direcciones. Las otras serán de otro nivel que tiene las 2

primeras líneas iguales a las del nivel 2.

Ahora tenemos la dirección donde empieza el nivel 1 ($240E0=$09:40E0) y donde empieza el

nivel 2 ($241C0=$09:41C0).

Si nos situamos en el editor hexadecimal y seleccionamos desde $240E0-$241BF (que

corresponde al nivel 1) comprobamos que se trata de $E0 bytes lo que ocupa un nivel o sea

224 bytes que dividido por 16 bytes que tiene cada línea nos da 14 líneas cada nivel.

Un nivel ocupa 224 bytes y tiene 14 líneas de 16 bytes (o 16 objetos 2*2) cada una.

Ahora podemos buscar para ver si hay punteros a donde están los datos de estos 2 niveles con

lo que buscaríamo en el editor hexadecimal los bytes E0 40 C0 41 para ver si los encontramos.

Page 105: ROMHACKING GAMEBOY PRÁCTICO - Todo lo que quiso saber … · ^NOP _ ^No Operation _: Esta instrucción es la que vamos a utilizar para eliminar instrucciones cuando queramos por

Haciendo esto comprobamos que se encuentra en los bytes $16F5-$16F8 con lo que ya

tenemos donde están los punteros a los datos de cada uno de los niveles.

Tenemos los punteros en las direcciones $16F5-$176C. A partir de la dirección $176D

encontramos también punteros.

Ya con esto tenemos las direcciones de cada uno de los niveles que componen el juego y

podemos modificarlos a nuestro gusto.

También podríamos averiguar donde está el fragmento de código que carga los punteros

poniendo un breakpoint cuando se lea la dirección $00:16F5 donde están los punteros

podemos obtener la dirección $00:0836 donde se para el emulador:

ROM0:082A AF xor a

ROM0:082B FA 28 C3 ld a,(C328)

ROM0:082E 87 add a

ROM0:082F 5F ld e,a

ROM0:0830 16 00 ld d,00

ROM0:0832 21 F5 16 ld hl,16F5

ROM0:0835 19 add hl,de

ROM0:0836 2A ldi a,(hl)

ROM0:0837 66 ld h,(hl)

ROM0:0838 6F ld l,a

ROM0:0839 11 00 98 ld de,9800

ROM0:083C CD AE 1F call 1FAE

Aquí si vemos el código tenemos como se carga en el registro “a” el valor que hay en la

dirección $C328=Nivel. En el registro “hl” se carga la dirección $00:16F5 donde están los

punteros y en el registro “de” se pone la dirección $9800=Map Address donde empieza a

dibujar el nivel en pantalla (que corresponde a la parte superior izquierda).

KESAMARU

Este juego tiene también una serie de bloques 2*2 que pone en la pantalla para dibujar el nivel

tal y como se ve en la captura correspondiente al nivel 1:

Page 106: ROMHACKING GAMEBOY PRÁCTICO - Todo lo que quiso saber … · ^NOP _ ^No Operation _: Esta instrucción es la que vamos a utilizar para eliminar instrucciones cuando queramos por

El primer recuadro que aparece en la parte superior izquierda se forma por los tiles 2C 2D 3C

3D.

Podríamos optar por buscar con un editor hexadecimal estos valores y que encontraremos en

2 direcciones de la ROM o poner un breakpoint cuando se escriba en la dirección $9946=Map

Address el valor $2C para poner el primer tile del bloque superior izquierdo para dibujar el

nivel.

La segunda opción es mejor aunque en caso de que no se encontrara lo buscado podríamos

utilizar la primera.

Al poner el breakpoint el emulador se para en la dirección $00:2AD0 donde encontramos:

ROM0:2ABA 21 77 13 ld hl,1377

ROM0:2ABD CB 27 sla a

ROM0:2ABF CB 27 sla a

ROM0:2AC1 5F ld e,a

ROM0:2AC2 16 00 ld d,00

ROM0:2AC4 19 add hl,de

ROM0:2AC5 11 40 C6 ld de,C640

ROM0:2AC8 1A ld a,(de)

ROM0:2AC9 F5 push af

Page 107: ROMHACKING GAMEBOY PRÁCTICO - Todo lo que quiso saber … · ^NOP _ ^No Operation _: Esta instrucción es la que vamos a utilizar para eliminar instrucciones cuando queramos por

ROM0:2ACA 13 inc de

ROM0:2ACB 1A ld a,(de)

ROM0:2ACC 57 ld d,a

ROM0:2ACD F1 pop af

En la primera línea se carga en el registro “hl” la dirección $00:1377 que es donde empiezas los

datos para dibujar los objetos 2*2 que se ponen en el nivel.

Realizando la búsqueda con el editor hexadecimal encontramos los valores 2C 2D 3C 3D en las

direcciones $139B-$139E y $4ADD-$4AE0.

Las primeras son las que buscabamos pero no se sabía exactamente donde empezaban los

datos de los objetos que con el breakpoint hemos encontrado de forma fácil.

Bloque tipo $00: 02 03 12 13 ($1377-$137A)

Bloque tipo $01: 04 05 14 15

Bloque tipo $02: 06 07 16 17

Bloque tipo $03: 0A 0B 1A 1B

Bloque tipo $04: 0C 0D 1C 1D

Bloque tipo $05: 0E 0F 1E 1F

Bloque tipo $06: 20 21 30 31

Bloque tipo $07: 22 23 32 33

Bloque tipo $08: 24 25 34 35

Bloque tipo $09: 2C 2D 3C 3D

Bloque tipo $0A: 2E 2F 3E 3F

Bloque tipo $0B: 68 69 78 79

Bloque tipo $0C: 6A 6B 7A 7B

Bloque tipo $0D: 6C 6D 7C 7D

Bloque tipo $0E: 6E 6F 7E 7F

Bloque tipo $0F: B0 B2 B1 B3

Si buscáramos los datos de la primera línea según los tipos de bloque que aparecen podría ser

09 09 09 04 04 0F 04 04 04 04

Aunque si buscamos estos bytes no los encontraremos por lo que deben estar almacenados los

niveles de otra forma.

En el fragmento anterior de código cuando se para el emulador en la dirección $00:2AD0 y el

registro “bc” tiene el valor $0F62 que podría corresponder a una dirección.

Page 108: ROMHACKING GAMEBOY PRÁCTICO - Todo lo que quiso saber … · ^NOP _ ^No Operation _: Esta instrucción es la que vamos a utilizar para eliminar instrucciones cuando queramos por

Si nos vamos con el editor hexadecimal en la dirección $0F62-$0F66 encontramos lo siguiente:

99 94 4F 44 44

Se parece bastante a lo que buscábamos (09 09 09 04 04 0F 04 04 04 04).

Es exactamente lo mismo pero en lugar de utilizarse 1 byte para cada bloque se utiliza 1 byte

para dibujar 2 bloques con lo que se necesitan la mitad de bytes para cada línea.

Cada línea son 10 bloques que se ponen con 5 bytes sólo y hay 8 líneas con lo que cada nivel

ocupa 40 bytes.

Con esto ya hemos encontrado los datos para dibujar el primer nivel y podemos comprobarlo

cambiando el byte en $0F62 que tenía el valor $99 (2 bloques seguidos de tipo $09).

Si ponemos el valor $44 pondríamos 2 bloques seguidos tipo $04 en la parte superior izquierda

y que corresponde al bloque blanco como los que hay en la primera línea antes y después del

bloque con una roca quedando el nivel modificado como se ve en la captura:

Como el nivel 1 empieza en la dirección $00:0F62, el nivel 2 debe empezar $28 (40 bytes) más

adelante es decir en $00:0F8A, el nivel 3 debería empezar en $00:0FB2 (aunque no ocurre),…

Si buscamos el primer valor 620F con el editor hexadecimal HxD lo localizamos en la dirección

$AC0 ($00:0AC0) y comprobamos como a continuación también aparece 8A0F que

corresponde al puntero al segundo nivel aunque el siguiente puntero DA0F ($00:0FDA) no es el

que debería corresponder al nivel 3 pero es porque están los niveles algo desordenados.

Pero con los punteros podemos conocer donde están los datos de cada nivel:

($00:0AC0):

Nivel 1: 62 0F ($00:0F62)

Nivel 2: 8A 0F ($00:0F8A)

Nivel 3: DA 0F ($00:0FDA)

Page 109: ROMHACKING GAMEBOY PRÁCTICO - Todo lo que quiso saber … · ^NOP _ ^No Operation _: Esta instrucción es la que vamos a utilizar para eliminar instrucciones cuando queramos por

Nivel 4: 6A 11 ($00:116A)

Ya tenemos aquí lo que buscábamos los punteros a los datos del nivel, los datos del nivel y los

datos para dibujar los objetos 2*2 que se ponen en pantalla.

Si pusiéramos un breakpoint cuando se lee la dirección $00:0AC0 donde están los punteros el

emulador se para en la dirección $00:0068 que es una rutina de uso general de carga de

punteros.

Este caso ha costado un poco más pero al final también lo hemos localizado.

BOOMER IN ASMIK WORLD 2

En este juego también tenemos objetos 2*2 para dibujar el nivel y vamos a intentar localizar

donde están estos objetos en la ROM.

Si nos fijamos en el objeto que hay en la parte superior de la pantalla a la derecha podemos

comprobar que se forma con los tiles AC AD BC BD pero si buscamos estos valores no lo

encontramos en el juego.

Vamos a poner un breakpoint cuando se escriba el valor $AC en la dirección $9810=Map

Address donde se pone en pantalla.

El juego se para en la dirección $00:0574 donde encontramos lo siguiente:

ROM0:0566 C5 push bc

Page 110: ROMHACKING GAMEBOY PRÁCTICO - Todo lo que quiso saber … · ^NOP _ ^No Operation _: Esta instrucción es la que vamos a utilizar para eliminar instrucciones cuando queramos por

ROM0:0567 E5 push hl

ROM0:0568 FB ei

ROM0:0569 F3 di

ROM0:056A F0 41 ld a,(ff00+41)

ROM0:056C E6 03 and a,03

ROM0:056E FE 02 cp a,02

ROM0:0570 D2 68 05 jp nc,0568

ROM0:0573 1A ld a,(de)

ROM0:0574 77 ld (hl),a

Aquí carga en el registro “a” el valor que hay en la dirección contenida en el registro “de” (que

tiene el valor $CBC1) y lo pone en la dirección contenida en el registro “hl” (que tiene el valor

$9810). La dirección $CBC1 tiene el valor $AC que es el que pone en pantalla pero esto se trata

de dirección de la RAM y no es de donde están los datos de los objetos para dibujar el nivel.

Vamos a poner un breakpoint ahora en la dirección $CBC1 cuando se escriba el valor $AC para

comprobar cuando ocurre para lo cual reinicio el juego para que comience otra vez de nuevo

ya que esto ocurrirá antes.

El emulador ahora se para en la dirección $00:2407 donde encontramos:

ROM0:2403 1A ld a,(de)

ROM0:2404 13 inc de

ROM0:2405 EE 80 xor a,80

ROM0:2407 22 ldi (hl),a

ROM0:2408 1A ld a,(de)

ROM0:2409 13 inc de

ROM0:240A EE 80 xor a,80

ROM0:240C 22 ldi (hl),a

ROM0:240D A7 and a

ROM0:240E C9 ret

Aquí encontramos como carga en el registro “a” el valor que hay en la dirección contenida en

el registro “de” (que tiene el valor $7516 y rom=1 con lo que la dirección es $01:7516).

En $00:2405 aparece la instrucción “xor a,80” que si utilizamos la calculadora con un valor

tiene el siguiente efecto:

$20 xor $80=$A0 con lo que le suma al valor que hay en el registro “a” el valor $80.

Page 111: ROMHACKING GAMEBOY PRÁCTICO - Todo lo que quiso saber … · ^NOP _ ^No Operation _: Esta instrucción es la que vamos a utilizar para eliminar instrucciones cuando queramos por

Por lo que si nos vamos a la dirección $01:7516 en el juego encontramos el valor $2D y en

$01:7515 el valor $2C que si le sumamos $80 nos da $AC que es el primer valor del objeto que

buscábamos.

Con esto ya hemos encontrado donde están los datos de este objeto en el juego y es

$01:7515-$01:7518 (7515-7518).

Si nos vamos a esta dirección en un editor hexadecimal podemos encontrar un poco antes lo

siguiente:

Hasta la dirección $74E0 inclusive encontramos el valor $FF y a continuación encontramos

valores distintos a esto.

A partir de la dirección $01:74E1 o a partir de $01:74E5 podrían estar los datos donde

comienzan los datos para dibujar el nivel.

Si tomamos la dirección $01:74E1 donde está el bloque tipo $00 podemos tener:

Bloque tipo $00: 00 00 00 00

Bloque tipo $01: 60 61 70 71

Bloque tipo $02: 68 61 70 71

Bloque tipo $03: 60 61 78 71

Bloque tipo $04: 62 63 72 73

Bloque tipo $05: 62 63 7A 73

Bloque tipo $06: 62 63 72 7B

Bloque tipo $07: 64 65 74 75

Bloque tipo $08: 64 69 74 75

Bloque tipo $09: 64 65 74 79

Bloque tipo $0A: 66 67 76 77

Bloque tipo $0B: 6A 67 76 77

Bloque tipo $0C: 66 6B 76 77

Bloque tipo $0D: 2C 2D 3C 3D

Bloque tipo $0E: 2E 2F 3E 3F

Page 112: ROMHACKING GAMEBOY PRÁCTICO - Todo lo que quiso saber … · ^NOP _ ^No Operation _: Esta instrucción es la que vamos a utilizar para eliminar instrucciones cuando queramos por

Bloque tipo $0F: 8E 8F 9E 9F

Bloque tipo $10: 85 85 95 95

Bloque tipo $11: 9C 9D 9C 9D

Bloque tipo $12: 82 85 9C 94

Bloque tipo $13: 85 86 93 9D

Bloque tipo $14: 9C 84 92 95

Bloque tipo $15: 83 9D 95 96

Bloque tipo $16: 8A 8A 9A 9A

Bloque tipo $17: 8C 8D 8C 8D

Bloque tipo $18: 87 8A 8C 99

Bloque tipo $19: 8A 8B 98 8D

Bloque tipo $1A: 8C 89 97 9A

Bloque tipo $1B: 88 8D 9A 9B

Bloque tipo $1C: 11 11 11 11

Bloque tipo $1D: 01 01 01 01

Bloque tipo $1E: 10 10 10 10

Si nos fijamos en la primera línea del nivel nos encontramos según estos datos los valores:

1E 1E 1E 1E 1E 1E 1E 1E 0D 1E

Encontramos sólo 2 tipos de bloques ($1E y $0D) para dibujar esta línea.

Cada línea tiene 10 tiles y hay 8 líneas para dibujar el nivel lo que hace un total de 80 bytes o

$50 en hexadecimal.

Estos datos de la primera línea del nivel la encontramos en las direcciones $02:4C2F-$02:4C38

($8C2F-$8C38).

El nivel 1 se encuentra en $02:4C2F-$02:4C7E y los del nivel 2 deben estar en $02:4C7F-

$02:4CCE por lo que podemos buscar el valor 2F4C7F4C en el juego con el editor hexadecimal.

Esto lo encontramos en las direcciones $02:4945-$02:4948 ($8945-$8948) donde están los

punteros pero antes parece que hay punteros que empiezan en $893F.

Con esto ya hemos localizado lo que buscabamos.

MR. DO!

En este juego debemos coger las cerezas que hay en el nivel para pasar al siguiente. En el

primer nivel encontramos 5 bloques de 8 cerezas cada uno que se muestran en la pantalla.

Page 113: ROMHACKING GAMEBOY PRÁCTICO - Todo lo que quiso saber … · ^NOP _ ^No Operation _: Esta instrucción es la que vamos a utilizar para eliminar instrucciones cuando queramos por

Para dibujar la cereza se utilizan los tiles 08 09 0A 0B.

Poniendo un breakpoint en la dirección $9840 cuando se escribe el valor $08 que corresponde

a la primera cereza de la parte superior izquierda comprobamos como se para el emulador en

la dirección $00:2C1A:

ROM0:2C10 C5 push bc

ROM0:2C11 D5 push de

ROM0:2C12 6B ld l,e

ROM0:2C13 62 ld h,d

ROM0:2C14 CD E6 2D call 2DE6

ROM0:2C17 06 08 ld b,08

ROM0:2C19 0A ld a,(bc)

ROM0:2C1A 22 ldi (hl),a

ROM0:2C1B 0C inc c

ROM0:2C1C 0A ld a,(bc)

ROM0:2C1D 22 ldi (hl),a

ROM0:2C1E 0C inc c

Page 114: ROMHACKING GAMEBOY PRÁCTICO - Todo lo que quiso saber … · ^NOP _ ^No Operation _: Esta instrucción es la que vamos a utilizar para eliminar instrucciones cuando queramos por

ROM0:2C1F 7D ld a,l

ROM0:2C20 C6 1E add a,1E

En el registro “bc” se carga la dirección donde están los datos para dibujar la cereza y se ponen

los datos en la dirección contenida en el registro “hl” (Map Address donde se pone en

pantalla).

El registro “bc” contiene la dirección $00:0840 que es donde están los datos para dibujar la

cereza.

Sin embargo, si ponemos un breakpoint cuando se lee en la dirección $00:0840 no

encontramos la dirección donde pueden estar los datos del nivel.

Para lo cual, vamos a intentar hacerlo de otra forma buscando la dirección de la RAM donde se

guarda el número de nivel en la RAM.

Para hacerlo algo más fácil podemos buscar primero el número de cerezas que quedan en el

nivel que inicialmente son 40 y que se guarda en la dirección $D0AE.

Podemos introducir un cheat poniendo el valor $01 en la dirección $D0AE con lo que

quedarían sólo 1 cereza por coger para pasar de nivel independientemente de las que

realmente queden.

Activamos el cheat y lo desactivamos porque sino no disminuyen las cerezas que quedan en el

nivel. Cuando cojamos una cereza pasaremos al siguiente nivel.

Haciendo la búsqueda encontramos que en la dirección $D0AA se guarda en la RAM el número

de nivel ($00: MAP 1, $01: MAP 2,…).

Si introducimos un cheat poniendo el valor $05 en la dirección $D0AA empezaremos en el nivel

6 o MAP 06 aunque en pantalla ponga otro valor sin embargo la ubicación de las cerezas y los

elementos del nivel son los del 6 aunque ponga 1.

Valiéndonos del cheat para pasar de nivel podemos empezar en el primer nivel y una vez

iniciado activar y desactivar el cheat del número de cerezas poniendo $01.

Ahora ponemos un breakpoint cuando se lea la dirección $D0AA (Nivel) con lo que se parará el

emulador cuando se lea dicho valor.

El hacer esto es debido a que normalmente en los juegos de Gameboy se suele leer el valor del

número de nivel para según su valor cargar unos datos u otros

Por ejemplo, si estamos en el nivel 1 debe cargar los datos del nivel 1 y si es el 2 los datos del

nivel 2.

El emulador se para en la dirección $00:2BC0 donde se lee el número de nivel ($D0AA):

ROM0:2BB5 CD 72 2B call 2B72

ROM0:2BB8 AF xor a

ROM0:2BB9 21 00 CC ld hl,CC00

ROM0:2BBC 22 ldi (hl),a

Page 115: ROMHACKING GAMEBOY PRÁCTICO - Todo lo que quiso saber … · ^NOP _ ^No Operation _: Esta instrucción es la que vamos a utilizar para eliminar instrucciones cuando queramos por

ROM0:2BBD 05 dec b

ROM0:2BBE 20 FC jr nz,2BBC

ROM0:2BC0 FA AA D0 ld a,(D0AA)

ROM0:2BC3 87 add a

ROM0:2BC4 C6 B6 add a,B6

ROM0:2BC6 6F ld l,a

ROM0:2BC7 26 08 ld h,08

ROM0:2BC9 2A ldi a,(hl)

ROM0:2BCA 66 ld h,(hl)

ROM0:2BCB 6F ld l,a

ROM0:2BCC 56 ld d,(hl)

ROM0:2BCD 23 inc hl

ROM0:2BCE 5E ld e,(hl)

ROM0:2BCF 23 inc hl

ROM0:2BD0 CD 2F 2C call 2C2F

ROM0:2BD3 CD 5C 2C call 2C5C

A partir de $00:2BC0 vemos como se lee el número de nivel que en el caso del nivel 1 tiene el

valor $00 con lo que el registro “a”=$00.

La siguiente instrucción “add a” (add a,a) equivale a “a=a+a=$00 para el nivel 1 y en la

siguiente instrucción se le suma al valor que hay en el registro “a” el valor $B6 con lo que

“a=$B6” para el nivel 1.

En la siguiente instrucción “ld l,a” esto equivale a “l=a=$B6) y a continuación “ld h,08” que

equivale a “h=$08” por lo que el registro “hl” tiene el valor $00:08B6.

Las siguientes instrucciones sirven para cargar los datos que hay en la dirección $00:08B6 en

adelante que debe corresponder a un puntero.

Esto lo que hace a continuación es poner en el registro “de” la dirección o puntero que hay a

partir de la dirección $00:08B6.

En $00:08B6-$00:08B7 encontramos el valor 35 10 que corresponde a la dirección $00:1035

donde están los datos para dibujar el primer nivel.

En $00:08B8-$00:08B9 encontramos el valor 8E 10 que corresponde a la dirección $00:108E

donde están los datos para dibujar el nivel 2 y así sucesivamente.

En $00:1035 hay datos aunque todavía tendré que analizarlo para averiguar de lo que se trata

(posiblemente cuando haya otra revisión de este documento).

Page 116: ROMHACKING GAMEBOY PRÁCTICO - Todo lo que quiso saber … · ^NOP _ ^No Operation _: Esta instrucción es la que vamos a utilizar para eliminar instrucciones cuando queramos por

Más delante de esta información tenemos los datos para dibujar las cerezas, las rocas que

caen en el nivel 1 y el objeto que aparece en mitad del nivel:

(Nivel 1. Cerezas):

ROM0:1068 0C

ROM0:1069 02 (Y=$02)

ROM0:106A 00 (X=$00)

ROM0:106B 06 (Y=$06)

ROM0:106C 00 (X=$00)

ROM0:106D 06 (Y=$06)

ROM0:106E 0C (X=$0C)

ROM0:106F 06 (Y=$06)

ROM0:1070 10 (X=$10)

ROM0:1071 08 (Y=$08)

ROM0:1072 06 (X=$06)

ROM0:1073 0C (Y=$0C)

ROM0:1074 06 (X=$06)

ROM0:1075 12 (Y=$12)

ROM0:1076 00 (X=$00)

ROM0:1077 12 (Y=$12)

ROM0:1078 04 (X=$04)

ROM0:1079 0E (Y=$0E)

ROM0:107A 10 (X=$10)

ROM0:107B 12 (Y=$12)

ROM0:107C 10 (X=$10)

ROM0:107D FF

------------------------------

(Nivel 1. Rocas):

ROM0:107E 02 (Y=$02)

ROM0:107F 04 (X=$04)

ROM0:1080 06 (Y=$06)

ROM0:1081 08 (X=$08)

Page 117: ROMHACKING GAMEBOY PRÁCTICO - Todo lo que quiso saber … · ^NOP _ ^No Operation _: Esta instrucción es la que vamos a utilizar para eliminar instrucciones cuando queramos por

ROM0:1082 0C (Y=$0C)

ROM0:1083 04 (X=$04)

ROM0:1084 0A (Y=$04)

ROM0:1085 10 (X=$10)

ROM0:1086 08 (Y=$08)

ROM0:1087 14 (X=$14)

ROM0:1088 12 (Y=$12)

ROM0:1089 0E (X=$0E)

ROM0:108A FF

-----------------------------------------

(Nivel 1. Objeto):

ROM0:108B 00

ROM0:108C 0E (Y=$0E)

ROM0:108D 0A (X=$0A)

Como vemos se ponen las coordenadas de la parte superior de un bloque de cerezas, o la

parte superior de la roca o el objeto.

El valor $0C que aparece en $00:1068 todavía no se su significado.

Page 118: ROMHACKING GAMEBOY PRÁCTICO - Todo lo que quiso saber … · ^NOP _ ^No Operation _: Esta instrucción es la que vamos a utilizar para eliminar instrucciones cuando queramos por

Estas coordenadas corresponden al primer tile del grupo de 4 cerezas y que son las que

aparecen en la “BGB RAM Viewer”.

Si cambiamos estas coordenadas podemos conseguir que los grupos de cereza estén en

diferente posición en la pantalla.

Las coordenadas de las rocas y del objeto son similares que las cerezas sólo que en lugar de

dibujar 4 objetos sólo dibuja un elemento.

Por ejemplo, el grupo superior de la parte izquierda está en las coordenadas X,Y: 0,2

ROM0:1069 02 (Y=$02)

ROM0:106A 00 (X=$00)

Si cambiamos la coordenada X que aparece en la dirección $00:106A por $18 el nivel 1

quedaría tal y como se ve en la captura:

Igualmente podemos hacer con las rocas y el objeto que hay en el nivel.

Ya tenemos los punteros donde hay datos para dibujar cada uno de los niveles para que

podamos modificarlos.

Este juego tiene una forma diferente para poner objetos en la pantalla del juego a través de

coordenadas y los agrupa en una parte los datos de las cerezas, en otro las rocas y en otro el

objeto central.

BOMB JACK

En este juego los niveles están llenos de bombas y una serie de plataformas sobre las que

puedes ponerte evitando que te cojan los enemigos.

Podemos buscar donde se encuentra la información para poner cada una de las bombas que

hay en cada nivel y también para ubicar las plataformas que aparecen.

Page 119: ROMHACKING GAMEBOY PRÁCTICO - Todo lo que quiso saber … · ^NOP _ ^No Operation _: Esta instrucción es la que vamos a utilizar para eliminar instrucciones cuando queramos por

Poniendo un breakpoint en la dirección $9802 cuando se escribe el valor $C6 que corresponde

al tile de la parte superior de la bomba que está en la izquierda en lo más alto del nivel 1

podemos comprobar como el emulador se para en la dirección $00:13A4.

ROM0:13A1 E1 pop hl

ROM0:13A2 F0 A8 ld a,(ff00+A8)

ROM0:13A4 77 ld (hl),a

ROM0:13A5 C1 pop bc

ROM0:13A6 C9 ret

Aquí se carga el valor que hay en la dirección $FFA8 que tiene el valor $C6 y se pone en la

dirección contenida en “hl” que tiene el valor $9802.

Poniendo un breakpoint cuando se escriba el valor $C6 en la dirección $FFA8 se para el

emulador un poco más arriba en la dirección $00:1391.

ROM0:138E F0 A9 ld a,(ff00+A9)

ROM0:1390 81 add c

ROM0:1391 E0 A8 ld (ff00+A8),a

Poniendo un breakpoint en la dirección $FFA9 cuando se escriba en esta dirección.

Podemos ponerlo cuando estamos en la pantalla de menú y se para antes de cargar el nivel 1

con lo que se para en la dirección $00:136F pero un poco más arriba encontramos lo que

Page 120: ROMHACKING GAMEBOY PRÁCTICO - Todo lo que quiso saber … · ^NOP _ ^No Operation _: Esta instrucción es la que vamos a utilizar para eliminar instrucciones cuando queramos por

buscamos y que hace referencia a la dirección $00:1334 donde se pone en el registro “de” la

dirección $00:2231.

ROM0:1327 F0 A3 ld a,(ff00+A3)

ROM0:1329 26 00 ld h,00

ROM0:132B 6F ld l,a

ROM0:132C 29 add hl,hl

ROM0:132D 29 add hl,hl

ROM0:132E 29 add hl,hl

ROM0:132F 29 add hl,hl

ROM0:1330 54 ld d,h

ROM0:1331 5D ld e,l

ROM0:1332 29 add hl,hl

ROM0:1333 19 add hl,de

ROM0:1334 11 31 22 ld de,2231

ROM0:1337 19 add hl,de

ROM0:1338 54 ld d,h

ROM0:1339 5D ld e,l

ROM0:133A 3E 18 ld a,18

ROM0:133C E0 A4 ld (ff00+A4),a

ROM0:133E E0 A5 ld (ff00+A5),a

En esta dirección $00:2231 están las coordenadas para situar cada una de las bombas del nivel

1.

Otra forma con la que podríamos haberlo hecho es buscando la dirección donde se pone el

número de bombas que quedan del nivel y que corresponde a la dirección de la RAM $FFA5.

Inicialmente el nivel 1 tiene 24 bombas o $18 hexadecimal con lo que si ponemos un

breakpoint cuando se escriba el valor $18 en la dirección $FFA5 el emulador se para en la

dirección $00:133E y en $00:133A encontramos como en esta instrucción se pone el número

de bombas del nivel. Un poco más arriba en $00:1334 encontramos lo que buscamos:

ROM0:1334 11 31 22 ld de,2231

Esta forma puede ser más rápida que la anterior y más sencilla para localizar esta dirección.

Para el nivel 1 los datos de cada una de las 24 bombas son los siguientes:

(Datos situación bombas en los niveles):

(Nivel 1):

Page 121: ROMHACKING GAMEBOY PRÁCTICO - Todo lo que quiso saber … · ^NOP _ ^No Operation _: Esta instrucción es la que vamos a utilizar para eliminar instrucciones cuando queramos por

00:2231 0C 0A (Y=$0C, X=$0A)

00:2233 0C 0C (Y=$0C, X=$0C)

00:2235 0C 0E (Y=$0C, X=$0E)

00:2237 00 06 (Y=$00, X=$06)

00:2239 00 04 (Y=$00, X=$04)

00:223B 00 02 (Y=$00, X=$02)

00:223D 0C 00 (Y=$0C, X=$00)

00:223F 0A 00 (Y=$0A, X=$00)

00:2241 08 00 (Y=$08, X=$00)

00:2243 06 00 (Y=$06, X=$00)

00:2245 0C 10 (Y=$0C, X=$10)

00:2247 0A 10 (Y=$0A, X=$10)

00:2249 08 10 (Y=$08, X=$10)

00:224B 06 10 (Y=$06, X=$10)

00:224D 05 0E (Y=$05, X=$0E)

00:224F 05 0C (Y=$05, X=$0C)

00:2251 05 0A (Y=$05, X=$0A)

00:2253 05 08 (Y=$05, X=$08)

00:2255 00 10 (Y=$00, X=$10)

00:2257 00 0E (Y=$00, X=$0E)

00:2259 00 0C (Y=$00, X=$0C)

00:225B 10 02 (Y=$10, X=$02)

00:225D 10 04 (Y=$10, X=$04)

00:225F 10 06 (Y=$10, X=$06)

La primera bomba que aparece en la parte superior izquierda corresponde a los datos:

00:223B 00 02 (Y=$00, X=$02)

Si cambiamos el byte que hay en $00:223B poniendo $03 en lugar de $00 conseguimos que

cambie la posición de esta bomba tal y como se ve en la captura:

Page 122: ROMHACKING GAMEBOY PRÁCTICO - Todo lo que quiso saber … · ^NOP _ ^No Operation _: Esta instrucción es la que vamos a utilizar para eliminar instrucciones cuando queramos por

En $00:2261 comienzan los datos para situar las bombas del nivel 2. Cada nivel tiene 24

bombas lo que hace un total de 48 bytes para las coordenadas de las bombas o $30.

Por tanto las direcciones de cada uno de los niveles son:

00:2231 (Nivel 1)

00:2261 (Nivel 2)

00:2291 (Nivel 3)

00:22C1 (Nivel 4)

00:22F1 (Nivel 5)

00:2321 (Nivel 6)

00:2351 (Nivel 7)

00:2381 (Nivel 8)

00:23B1 (Nivel 9)

00:23E1 (Nivel 10)

00:2411 (Nivel 11)

00:2441 (Nivel 12)

Si nos situamos en la dirección $00:2471 encontramos unos punteros a datos:

(Punteros):

00:2471 89 24 (Address $00:2489: Datos rectángulos nivel 1)

00:2473 B3 24 (Address $00:24B3: Datos rectángulos nivel 2)

00:2475 E0 24 (Address $00:24E0: Datos rectángulos nivel 3)

Page 123: ROMHACKING GAMEBOY PRÁCTICO - Todo lo que quiso saber … · ^NOP _ ^No Operation _: Esta instrucción es la que vamos a utilizar para eliminar instrucciones cuando queramos por

00:2477 04 25 (Address $00:2504: Datos rectángulos nivel 4)

00:2479 21 25 (Address $00:2521: Datos rectángulos nivel 5. No tiene este nivel)

00:247B 22 25 (Address $00:2522: Datos rectángulos nivel 6)

00:247D 51 25 (Address $00:2551: Datos rectángulos nivel 7)

00:247F 80 25 (Address $00:2580: Datos rectángulos nivel 8)

00:2481 BD 25 (Address $00:25BD: Datos rectángulos nivel 9)

00:2483 FC 25 (Address $00:25FC: Datos rectángulos nivel 10. No tiene este nivel)

00:2485 FD 25 (Address $00:25FD: Datos rectángulos nivel 11)

00:2487 34 26 (Address $00:2634: Datos rectángulos nivel 12)

Si nos ponemos en la dirección $00:2489 encontramos los datos:

(Datos dibujar rectángulos donde el personaje puede posarse en el nivel 1):

00:2489 04 09 (Y=$04, X=$09)

00:248B 00

00:248C 95 96 96 96 97 (Tiles a dibujar)

00:2491 00

00:2492 06 03 (Y=$06, X=$03)

00:2494 00

00:2495 95 96 97 (Tiles a dibujar)

00:2498 00

00:2499 0A 07 (Y=$0A, X=$07)

00:249B 00

00:249C 95 96 96 96 97 (Tiles a dibujar)

00:24A1 00

00:24A2 0C 02 (Y=$0C, X=$02)

00:24A4 00

00:24A5 95 96 97 (Tiles a dibujar)

00:24A8 00

00:24A9 0E 0A (Y=$0E, X=$0A)

00:24AB 00

00:24AC 95 96 96 96 97 (Tiles a dibujar)

00:24B1 00

Page 124: ROMHACKING GAMEBOY PRÁCTICO - Todo lo que quiso saber … · ^NOP _ ^No Operation _: Esta instrucción es la que vamos a utilizar para eliminar instrucciones cuando queramos por

00:24B2 FF (Fin de los datos)

Las primeras coordenadas corresponden a la plataforma donde puede posarse “Bomb Jack” y

que está en la parte superior del nivel.

También podríamos buscar donde están los datos para dibujar el fondo de la pirámide del nivel

1 para lo cual podemos poner un breakpoint en la dirección $98E4 cuando se escribe el valor

$01 con lo que el emulador se para en la dirección $00:13D9.

ROM0:13D1 11 00 98 ld de,9800

ROM0:13D4 06 12 ld b,12

ROM0:13D6 0E 11 ld c,11

ROM0:13D8 2A ldi a,(hl)

ROM0:13D9 12 ld (de),a

ROM0:13DA 1C inc e

ROM0:13DB 0D dec c

ROM0:13DC 20 FA jr nz,13D8

ROM0:13DE 7B ld a,e

ROM0:13DF C6 0F add a,0F

ROM0:13E1 5F ld e,a

ROM0:13E2 8A adc d

ROM0:13E3 93 sub e

ROM0:13E4 57 ld d,a

ROM0:13E5 05 dec b

ROM0:13E6 20 EE jr nz,13D6

ROM0:13E8 C9 ret

Aquí encontramos que el registro “hl” tiene el valor $2B89 cuando se para el emulador.

ROM0:13D4 06 12 ld b,12

ROM0:13D6 0E 11 ld c,11

En el registro “b” se pone el valor $12=18 líneas y en “c” el valor$11=17=Número de tiles de

cada línea.

La pantalla tiene líneas de 20 tiles pero los 3 últimos tiles de cada línea se utilizan para poner la

barra vertical con el número de vidas y puntuación.

ROM0:13DF C6 0F add a,0F

Se utiliza para incrementar la dirección de la Map Address para pasar a la siguiente línea. Por

ejemplo, en la primera línea acaba en $9810 pero se incrementará hasta $9811 y al sumarle

Page 125: ROMHACKING GAMEBOY PRÁCTICO - Todo lo que quiso saber … · ^NOP _ ^No Operation _: Esta instrucción es la que vamos a utilizar para eliminar instrucciones cuando queramos por

$0F nos da la dirección $9820=Map Address donde empieza a dibujar en la segunda línea y así

igual con las otras.

En “hl” estaba la dirección $00:2B89 (en $00:2B88 está el valor $01 que lee y pone en la

dirección $98E4). Sin embargo, la pantalla empieza en $9800 a dibujarse poniendo el valor $00

con lo que si ponemos un breakpoint en la dirección $9800 cuando se pone el valor $00

podemos comprobar cuando se para.

Para hacer esto reiniciamos el juego para hacer la búsqueda. El emulador se puede parar varias

veces pero la que nos interesa ocurre después de mostrar la pantalla del menú principal una

vez que le damos para empezar el nivel.

La dirección que nos interesa es la misma que antes $00:13D9 que es donde se paraba antes

pero ahora en “hl” tenemos $00:2B0E (que restando 1 byte nos da $00:2B0D que es donde

empiezan los datos para dibujar el fondo).

(Fondo pirámide):

00:2B0D 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 (Línea 1)

00:2B1E 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 (Línea 2)

00:2B2F 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 (Línea 3)

00:2B40 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 (Línea 4)

00:2B51 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 (Línea 5)

00:2B62 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 (Línea 6)

00:2B73 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 (Línea 7)

00:2B84 00 00 00 00 01 02 00 00 00 00 00 00 00 00 00 00 00 (Línea 8)

00:2B95 00 00 00 03 04 05 02 00 00 00 00 00 00 06 07 00 00 (Línea 9)

00:2BA6 00 00 08 09 0A 0B 0C 0D 00 00 00 0E 0F 10 11 02 00 (Línea 10)

00:2BB7 00 12 13 14 15 16 17 18 19 00 1A 1B 1C 1D 1E 1F 20 (Línea 11)

00:2BC8 21 22 23 24 25 26 27 28 29 19 2A 2B 2C 2D 2E 2F 30 (Línea 12)

00:2BD9 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F 40 41 (Línea 13)

00:2BEA 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F 50 51 52 (Línea 14)

00:2BFB 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F 60 61 62 63 (Línea 15)

00:2C0C 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 62 62 72 (Línea 16)

00:2C1D 73 74 75 76 77 78 79 7A 7B 7C 7D 7E 7F 80 81 82 83 (Línea 17)

00:2C2E 84 85 86 87 88 89 8A 8B 8C 8D 8E 8F 90 91 92 93 94 (Línea 18)

Con el editor hexadecimal podemos encontrar estos datos para dibujar el fondo entero.

Los datos para dibujar el fondo del nivel 2 se encuentra en $00:2EC7-$00:2FF8 ($132=306

bytes=18 líneas*17 tiles por línea), los del nivel 3 (castillo) se encuentra en $00:33E9-$00:351A

, los de los niveles 5 y 10 en $00:3C7D-$00:3DAE.

Page 126: ROMHACKING GAMEBOY PRÁCTICO - Todo lo que quiso saber … · ^NOP _ ^No Operation _: Esta instrucción es la que vamos a utilizar para eliminar instrucciones cuando queramos por

Si buscamos la dirección donde está el fondo del nivel 1 ($2B0D) en un editor hexademal

(0D2B) lo encontramos en la dirección $00:1E63 donde están los punteros a los diferentes

fondos:

00:1E63 0D 2B ($00:2B0D)

00:1E65 65 26 ($00:2665)

00:1E67 C7 2E ($00:2EC7)

00:1E69 3F 2C ($00:2C3F)

00:1E6B E9 33 ($00:33E9)

00:1E6D F9 2F ($00:2FF9)

00:1E6F 1B 38 ($00:381B)

00:1E71 1B 35 ($00:351B)

00:1E73 7D 3C ($00:3C7D)

00:1E75 4D 39 ($00:394D)

Igualmente podemos encontrar los datos para dibujar la barra vertical donde aparecen las

vidas y la puntuación por lo que podemos poner un breakpoint en la dirección $9811 cuando

se escribe el valor $DC con lo que el emulador se para en la dirección $00:12DB.

ROM0:12CE 21 8F 3F ld hl,3F8F

ROM0:12D1 11 11 98 ld de,9811

ROM0:12D4 06 12 ld b,12

ROM0:12D6 0E 03 ld c,03

ROM0:12D8 2A ldi a,(hl)

ROM0:12D9 C6 DC add a,DC

ROM0:12DB 12 ld (de),a

ROM0:12DC 1C inc e

ROM0:12DD 0D dec c

ROM0:12DE 20 F8 jr nz,12D8

ROM0:12E0 7B ld a,e

ROM0:12E1 C6 1D add a,1D

ROM0:12E3 5F ld e,a

ROM0:12E4 8A adc d

ROM0:12E5 93 sub e

ROM0:12E6 57 ld d,a

Page 127: ROMHACKING GAMEBOY PRÁCTICO - Todo lo que quiso saber … · ^NOP _ ^No Operation _: Esta instrucción es la que vamos a utilizar para eliminar instrucciones cuando queramos por

ROM0:12E7 05 dec b

ROM0:12E8 20 EC jr nz,12D6

ROM0:12EA C9 ret

En el registro “hl” se pone la dirección $00:3F8F donde están los datos para dibujar esta línea ,

en “de” la dirección $9811=Map Address donde empieza a dibujar en pantalla, en “b” el valor

$12=18 líneas y en “c” el valor $03=Nº de tiles por línea.

ROM0:12D9 C6 DC add a,DC

Se añade al registro “a” el valor $DC para poner el tile correspondiente.

(Datos dibujar parte derecha en el juego con vidas, puntuación,...):

00:3F8F 00 01 02 (Línea 1)

00:3F92 03 04 05 (Línea 2)

00:3F95 06 07 08 (Línea 3)

00:3F98 09 0A 0B (Línea 4)

00:3F9B 0C 0D 0E (Línea 5)

00:3F9E 0F 10 11 (Línea 6)

00:3FA1 12 13 14 (Línea 7)

00:3FA4 15 16 17 (Línea 8)

00:3FA7 18 19 1A (Línea 9)

00:3FAA 1B 1C 1D (Línea 10)

00:3FAD 0C 0D 0E (Línea 11)

00:3FB0 09 0A 0B (Línea 12)

00:3FB3 09 0A 0B (Línea 13)

00:3FB6 09 0A 0B (Línea 14)

00:3FB9 09 0A 0B (Línea 15)

00:3FBC 09 0A 0B (Línea 16)

00:3FBF 09 0A 0B (Línea 17)

00:3FC2 09 0A 0B (Línea 18)

Así la línea 1 tiene los valores:

00:3F8F00 01 02 (Línea 1)

Que corresponden a los tiles DC DD DE (se le suma $DC para poner el tile correspondiente en

pantalla).

Page 128: ROMHACKING GAMEBOY PRÁCTICO - Todo lo que quiso saber … · ^NOP _ ^No Operation _: Esta instrucción es la que vamos a utilizar para eliminar instrucciones cuando queramos por

PAC-ATTACK

Este juego tiene la opción de “PUZZLE MODE” donde podemos jugar a 100 niveles del juego y

que empiezan a partir de la dirección $03:400E o $C00E (nivel 0 sin nada en el nivel).

El primer nivel del juego empieza en $03:405C o $C05C, el nivel 2 en $C0AA, nivel 3 en

$C0F8,…

Cada nivel está formado por 13 líneas de 6 tiles cada uno lo que hace un total de 78 bytes o

$4E.

Como el nivel 0 empieza en la dirección $C05C podemos hallar una fórmula para obtener

donde empiezan estos datos que sería:

$C00E+$4E*Nº de nivel

Donde el número de nivel va a valer 1-100.

En los datos del nivel encontramos varios valores para los objetos que aparecen en el nivel:

$13: Ladrillo del fondo o sin ladrillo

$80: Fantasma

$BC: Ladrillo normal

$BD:

$BF: Ladrillo sólido

El tile $13 corresponde al ladrillo del fondo y el tile $80-$B7 corresponden a varios tiles del

fantasma para hacer la animación de éste.

Por ejemplo, para el nivel 1 los datos son:

(Nivel 1):

03:405C 13 13 13 13 13 13

03:4062 13 13 13 13 13 13

03:4068 13 13 13 13 13 13

03:406E 13 13 13 13 13 13

03:4074 13 13 13 13 13 13

03:407A 13 13 13 13 13 13

03:4080 13 13 13 13 13 13

03:4086 13 13 13 13 13 13

03:408C 13 BC BC BC 13 13

03:4092 80 80 80 80 13 13

03:4098 80 BC BC BC BC 13

03:409E 80 BC BC BC BC BC

Page 129: ROMHACKING GAMEBOY PRÁCTICO - Todo lo que quiso saber … · ^NOP _ ^No Operation _: Esta instrucción es la que vamos a utilizar para eliminar instrucciones cuando queramos por

03:40A4 80 BC BC BC BC BC

Si cambiáramos los bytes en $03:408D-$03:408F que tienen el valor $BC por $BF cambiamos el

ladrillo normal de esta línea por un ladrillo sólido tal y como se ve en la imagen:

Hace tiempo hice una utilidad escrita en Visual Basic 6 que permite leer cada uno de los 100

niveles y mostrarlos aunque no permite modificarlo. Esto es una tarea pendiente que se podría

hacer para tener nuestros propios niveles del juego.

OBTENCIÓN INFORMACIÓN HACKS

Una forma de obtener información en juegos también puede ser la ingeniería inversa o a

través de hacks creados tales como se pueden encontrar en la página “Romhacking.net” donde

Page 130: ROMHACKING GAMEBOY PRÁCTICO - Todo lo que quiso saber … · ^NOP _ ^No Operation _: Esta instrucción es la que vamos a utilizar para eliminar instrucciones cuando queramos por

hay una gran cantidad de ficheros .ips (parches) de traducciones de juegos, modificaciones

gráficas, de los niveles,…

Podemos utilizar por ejemplo, la traducción de un juego del japonés al inglés para a partir de

éste traducirlo a español de una forma más fácil.

Esto es una buena forma si no conocemos el japonés pero debemos tener en cuenta que

cualquier mala traducción que se haya hecho por parte del otro traductor nos influirá en

nuestra traducción.

La captura que aparece es una traducción del juego “DOUBLE DRAGON II” de Gameboy

realizada por Tanero y la del juego original.

Tal y como se ve se han cambiado los textos y el nombre del juego se ha traducido también.

Si no nos convenciera algún texto se podría cambiar como la última parte “AGAIN BILLY AND

JIMMY WERE READY TO TRAIN THEIR MARTIAL ARTS.”.

Podríamos poner “DE NUEVO BILLY Y JIMMY ESTAN PREPARADOS PARA ENTRENARSE EN

ARTES MARCIALES.”

Si no conociéramos donde está localizado el texto podríamos coger el parche .IPS y abrirlo con

la utilidad “IPS PEEK” para ver información de éste.

Page 131: ROMHACKING GAMEBOY PRÁCTICO - Todo lo que quiso saber … · ^NOP _ ^No Operation _: Esta instrucción es la que vamos a utilizar para eliminar instrucciones cuando queramos por

Como se ve en la captura el fichero del parche ocupa 2153 bytes de los cuales 1748 bytes

corresponden a bytes que se modifican en el juego.

Hay 102 parches y el que aparece marcado es el 91 de 104. La primera fila corresponde al ID y

la última EOF corresponde al final del fichero con lo que quedan 102 filas.

En azul viene marcado la dirección inicial donde está el texto ($01BE1A que corresponde a

$07:7E1A) y la final del texto ($01BE2C que corresponde a $07:7E2C).

El texto ocupa 19 bytes y el tamaño del texto en el parche es de 24 bytes.

Si abrimos el fichero .IPS con un editor hexadecimal antes del texto vemos antes del texto 3

bytes con la dirección donde se va a escribir el texto (01 BE 1A) y a continuación 2 bytes con el

número de bytes a escribir (00 13 que es $0013=19 decimal).

Page 132: ROMHACKING GAMEBOY PRÁCTICO - Todo lo que quiso saber … · ^NOP _ ^No Operation _: Esta instrucción es la que vamos a utilizar para eliminar instrucciones cuando queramos por

Con esto ya localizamos fácilmente los textos sin tener que complicarnos mucho aunque en

este caso el texto se encuentra fácil ya que están guardados tal y como aparecen en la pantalla

en el juego.

El texto que pretendíamos poner tiene el problema que es demasiado largo y deberíamos

localizar como se cargan los textos y si hay punteros que carguen los textos.

Es por eso que para la traducción “Tanero” ha utilizado textos con la misma longitud que los

originales.

Habría que analizar el juego con detenimiento pero ello requiere tiempo y no lo he tenido a la

hora de hacerlo por lo que esto se lo dejo como trabajo si fuera posible ya que tal vez requiera

buscar espacio adicional para el texto.

En este caso ya existía la traducción al español del juego pero muchas veces no lo estará y tal

vez lo encontremos en inglés.

OBTENCIÓN DE INFORMACIÓN CON EDITORES DE NIVEL

Otra forma de obtener información es con editores de niveles que haya de un determinado

juego aunque esto es solo para entenderlo ya que no será necesario para modificarlos

manualmente ya que contamos con estas herramientas para hacerlo.

Por ejemplo, el juego “Snoopy Magic Show” cuenta con un editor para modificar cada uno de

los niveles del juego llamado “c”.

Page 133: ROMHACKING GAMEBOY PRÁCTICO - Todo lo que quiso saber … · ^NOP _ ^No Operation _: Esta instrucción es la que vamos a utilizar para eliminar instrucciones cuando queramos por

Si cambiamos la posición de la bola que en el juego es (4,0) tal y como se ve en el editor (“Ball

1´s Start position (in tiles)”) por (5,1) podemos buscar con la ayuda del editor hexadecimal HxD

valores que hayan cambiado con respecto al original para lo cual previamente he hecho un

fichero copia del original para poder compararlo utilizando “Análisis”-“Comparar archivos”-

“Comparar…”.

Como se observa ha cambiado el valor en $7901 y en $7902 ($01:7901-$01:7902) que

corresponden a las coordenadas iniciales del nivel 1 de la bola.

Page 134: ROMHACKING GAMEBOY PRÁCTICO - Todo lo que quiso saber … · ^NOP _ ^No Operation _: Esta instrucción es la que vamos a utilizar para eliminar instrucciones cuando queramos por

El byte en $7903 tiene el valor $00 pero si se selecciona en el editor “2Balls” en lugar de

“1Ball” cambia a $60 por lo que $00: 1Ball y $60:2Balls.

Los bytes $7904 (Coordenada X) y $7905 (Coordenada Y) son las coordenadas de esa segunda

bola.

Los bytes $7907 (Coordenada X) y $7908 (Coordenada Y) de Snoopy en el nivel 1.

El byte $7909 tiene el valor $23 (35) que corresponde a “In-Level Music”.

El byte $790B (Coordenada X) y $790C (Coordenada Y) del powerup en el nivel 1 que

inicialmente está en (4,4).

Cada nivel tiene $0E bytes para poner las coordenadas de la bola, Snoopy,.. que va desde la

dirección $7900-$7C47 ($348=840 bytes).

Igual podemos hacer cambiando los tiles que aparecen en el nivel para cambiar el nivel 1 que

como se ve en la captura está formado por 8 líneas con 9 tiles cada una que hacen un total de

72 tiles que se almacenan en 72 bytes.

Con el botón izquierdo podemos cambiar el tile y con el botón derecho del ratón obtenemos

información de cada uno de los tiles que forman el nivel.

Con lo que podemos ver que el nivel 1 está formado por los datos siguientes:

60AD ($01:60AD):10 00 00 00 00 00 00 00 10

60B6 ($01:60B6):00 21 00 00 00 00 00 21 00

60BF ($01:60BF):00 00 00 00 22 00 00 00 00

60C8 ($01:60C8):00 00 00 0A 22 00 00 00 00

60D1 ($01:60D1):00 00 00 00 22 08 00 00 00

60DA ($01:60DA):00 00 00 00 22 00 00 00 00

60E3 ($01:60E3):00 21 00 00 00 00 00 21 00

60EC ($01:60EC):10 00 00 00 00 00 00 00 10

Con esto ya hemos averiguado donde se encuentran los datos del nivel 1. A continuación

encontramos los datos del nivel 2 que se encuentran en $60F5-$613C.

Los 60 niveles van desde la dirección $60AD-$718C ($10E0=4320 bytes).

Si buscamos el valor $AD60 con el editor hexadecimal lo encontramos en $4BAA-$4BAB donde

encontramos lo siguiente:

ROM1:4BA0 FA 6E C3 ld a,(C36E)

ROM1:4BA3 FE 3C cp a,3C

ROM1:4BA5 38 02 jr c,4BA9

ROM1:4BA7 D6 3C sub a,3C

ROM1:4BA9 21 AD 60 ld hl,60AD

Page 135: ROMHACKING GAMEBOY PRÁCTICO - Todo lo que quiso saber … · ^NOP _ ^No Operation _: Esta instrucción es la que vamos a utilizar para eliminar instrucciones cuando queramos por

ROM1:4BAC FE 00 cp a,00

ROM1:4BAE 28 0B jr z,4BBB

ROM1:4BB0 47 ld b,a

ROM1:4BB1 11 48 00 ld de,0048

ROM1:4BB4 19 add hl,de

ROM1:4BB5 05 dec b

ROM1:4BB6 78 ld a,b

ROM1:4BB7 FE 00 cp a,00

ROM1:4BB9 20 F6 jr nz,4BB1

ROM1:4BBB 7C ld a,h

ROM1:4BBC 57 ld d,a

ROM1:4BBD 7D ld a,l

ROM1:4BBE 5F ld e,a

ROM1:4BBF C9 ret

Con la instrucción “ld hl,60AD” se pone en el registro “hl” la dirección donde empiezan los

datos de los niveles y en el registro “de” el valor $0048 (72) que es el número de bytes que

ocupa cada nivel.

En el registro “a” se carga el valor que hay en la dirección $C36E que contiene el número de

nivel con lo que según el nivel se calcula la dirección donde están los datos.

Se compara el valor del nivel con $3C (60) ya que el juego tiene 60 niveles desde $00 (Nivel 1)

hasta $3B ($3B).

Los datos para dibujar los objetos 2*2 que dibujan en nivel se encuentran en la dirección

$3CFE-$3DA9 para los objetos $00-$26 (0-42).

El editor muestra tiles 43-55 pero que no corresponden a objetos sino a código fuente. Estos

no se pueden poner en el nivel.

Esto puede ser un fallo del editor y no debemos utilizarlos para modificar los niveles del juego.

Los tiles $43-$55 empezarían en $00:3DAA pero ahí encontramos:

ROM0:3DAA CD 22 26 call 2622

ROM0:3DAD AF xor a

ROM0:3DAE EA 9F C3 ld (C39F),a

….

COMPRESIÓN DE DATOS

Introducción

Page 136: ROMHACKING GAMEBOY PRÁCTICO - Todo lo que quiso saber … · ^NOP _ ^No Operation _: Esta instrucción es la que vamos a utilizar para eliminar instrucciones cuando queramos por

La compresión de los datos que aparecen en juegos es uno de los aspectos que nos pueden

complicar la vida a la hora de modificarlos ya que a veces no hay herramientas específicas para

ese tipo de compresión y tendremos que averiguar como funciona

Una vez averiguado deberemos descomprimirlos los datos, modificarlos y volver a

comprimirlos con la consecuente dificultad que ello conlleva. Además también puede ocurrir

que los datos modificados al comprimirlos ocupen más o menos bytes que los originales.

También va a depender de la forma como se carguen los datos si está en forma de punteros a

estos y con el tamaño comprimido,…

También podríamos crear una rutina propia para descomprimir datos con algún algoritmo

creado por nosotros para insertar en algún juego de Gameboy aunque esto ya es complicado

por sí ya que requiere conocer en profundidad el juego que se trate.

Compresiones simples

Una compresión simple se puede basar en el número de elementos diferentes de que se

disponga. Por ejemplo, si tenemos las letras del abecedario, más el espacio en blanco:

ABCDEFGHIJKLMNÑOPQRSTUVWXYZ

Aquí tenemos 28 símbolos distintos aunque podríamos ampliarlos hasta 32 por ejemplo.

Utilizando 1 byte por ejemplo para representar los datos que está formado por 8 bits

podríamos comprimir un texto con caracteres que se repiten:

00000000: Corresponde a $00 hexadecimal (1 byte).

Si a cada letra le asignamos un valor desde 00 a 27. Por ejemplo:

A=0, B=1, C=2,…, Espacio en blanco=27.

La letra “C” tiene el valor 2 que en binario es 10. Para escribir el máximo valor que es 31

(11111 en binario) se necesitan 5 bits y un byte tiene 8 con lo que nos quedan 3 bits.

Podemos utilizar 3 bits para indicar el número de veces que se repite la letra y 5 bits para

indicar la letra. En nuestro caso hemos utilizado una cantidad fija para representar cada letra

pero en algunos algoritmos más avanzados utilizan longitud variable de cada carácter

utilizando para ello la frecuencia con la que se repiten los valores utilizando menos bits para

los valores que se repiten más con la consecuente mayor compresión de los datos.

Si tenemos el texto:

“CCCCCDDD FG” podríamos codificarlo en binario como:

(100 00010) (000 00011) (000 11011) (000 00101) (000 00110)

Se utilizarán 5 bytes para codificar el texto que tiene 11 bytes con lo que se ha reducido

bastante. Esto es debido a que se repiten elementos pero si no se repitieran muchos datos no

se conseguiría mucha compresión.

Page 137: ROMHACKING GAMEBOY PRÁCTICO - Todo lo que quiso saber … · ^NOP _ ^No Operation _: Esta instrucción es la que vamos a utilizar para eliminar instrucciones cuando queramos por

El primer byte comprimido: 100 00010 equivale a 4 los 3 primeros bits que podemos

incrementar en una unidad para tener 5. Los siguientes 5 bits corresponden a la letra que tiene

el valor 2 en decimal que corresponde a “C” con lo que se ponen 5 veces la letra “C”.

El incrementar una unidad el valor de los 3 primeros bits es que 000 (0) correspondería a 0

veces la letra lo que no tiene sentido pero sí lo tendría si correspondiese a 1.

Podríamos crear un algoritmo que lea estos datos, los descomprima y ponga el texto en

pantalla.

Con este tipo de compresión se utilizaría más o menos bits dependiendo del número de

elementos distintos que haya.

Por ejemplo, podría haber compresión de este tipo 3+5 bits, 2+6 bits, 1+7 bits, 4+4 bits,…

Otra utilidad puede ser para comprimir los datos de los niveles para que ocupen menos. Por

ejemplo, en el juego “Battle Bull” que vimos había una serie de bloques para dibujar el nivel y

es límitado la cantidad de bloques distintos.

Suponiendo que hay menos de 16 bloques distintos se necesitan 4 bits para cada bloque desde

0-15 (0000=0, 1111=15).

Podríamos utilizar 4 bits para los bloques y otros 4 para el número de veces que aparece el

bloque.

La primera línea del nivel 1 es: 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01

16 veces el bloque 1 lo que se puede codificar como 1111 0001 (15+1 veces el bloque 1) con lo

que habríamos utilizado 1 byte para poner 16 bloques con el consiguiente ahorro de bytes.

La segunda línea del nivel 1 es: 01 09 09 09 09 09 09 09 09 09 09 00 09 09 09 01

Si se hubiesen utilizado 5 bits para representar el número de bloques se podría haber cogido el

primer bloque de la segunda línea que vale también 1 con lo que se pondría 17 veces el bloque

1 (16 en la primera línea y 1 al inicio de la segunda línea).

La segunda línea se codificaría como: (0000 0001) (1001 1001) (0000 0000) (0010 1001) (0000

0001)

Utilizaríamos 5 bytes para representar los 16 bloques del nivel con lo que se ha comprimido

también bastante.

Sería 1 vez el bloque tipo 1, 10 veces el bloque tipo 9, 1 vez el bloque tipo 0, 3 veces el bloque

tipo 9 y 1 vez el bloque tipo 1.

El algoritmo de compresión debe ser más o menos rápido o se ralentaría algunos procesos que

tienen lugar en el juego. Por ejemplo, si los tiles del juego están comprimidos si se utilizara un

algoritmo muy complejo y que requiere muchos ciclos del procesador de la Gameboy se

tardaría en descomprimirlos y en mostrar los gráficos del juego,…

También se tiene que tener en cuenta si merece la pena la compresión porque puede ser

mínima y requiera un algoritmo complejo. Si hay espacio suficiente en la ROM no hace falta

comprimir datos.

Page 138: ROMHACKING GAMEBOY PRÁCTICO - Todo lo que quiso saber … · ^NOP _ ^No Operation _: Esta instrucción es la que vamos a utilizar para eliminar instrucciones cuando queramos por

Datos consecutivos

A veces a la hora de dibujar objetos en pantalla cuando los tiles que aparecen son consecutivos

se puede utilizar una rutina para ello con lo que no hace falta cargar datos para ello.

Por ejemplo: Supongamos, que dibujamos un personaje que está formado por 5 líneas de 4

tiles con los valores a partir de la dirección $99A0:

Línea 1: 5D, 5E, 5F, 60

Línea 2: 61, 62, 63, 64

Línea 3: 65, 66, 67, 68

Línea 4: 69, 6A, 6B, 6C

Línea 5: 6D, 6E, 6F, 70

Una forma podría ser poner estos datos en el juego y cargarlos o bien utilizar una rutina que

dibuje el objeto sin tener que aparecer ningún dato.

Podríamos utilizar la siguiente rutina para dibujar dicho objeto en pantalla:

3E 5D ld a,5D

11 1C 00 ld de,001C

21 A0 99 ld hl,99A0

06 05 ld b,05

Salto:

0E 04 ld c,04

Salto1:

22 ldi (hl),a

3C inc a

0D dec c

20 FB jr nz,Salto1

19 add hl,de

05 dec b

20 F5 jr nz,Salto

Esta rutina pone en el registro “a” el valor inicial que en este caso es $5D, en el registro “de” se

pone la cantidad que hay que sumar a la Map Address que se pone en el registro “hl” para

pasar a la siguiente línea.

En el registro “b” se pone el número de líneas y en “c” el número de tiles que tiene cada línea.

Por regla, como entre línea y línea en pantalla hay $20 se debe cumplir que el valor que hay en

el registro “de” ($001C) más el que hay en el registro “c” ($04) debe ser igual a esa cantidad

($20).

Page 139: ROMHACKING GAMEBOY PRÁCTICO - Todo lo que quiso saber … · ^NOP _ ^No Operation _: Esta instrucción es la que vamos a utilizar para eliminar instrucciones cuando queramos por

La instrucción “ldi (hl),a” se encarga de poner el tile en pantalla e incrementar la dirección que

hay en el registro “hl”, “inc a” incrementa el tile a poner en la siguiente dirección en pantalla,

“dec b” y “dec c” disminuyen b y c para disminuir el número de líneas que quedan y el número

de tiles que quedan de la línea actual.

“add hl,de” añade a la dirección que hay contenida en “hl” la dirección contenida en “de” para

pasar a la siguiente línea.

Este fragmento de código ocupa ($15=21 bytes) que es menos de los 20 bytes+fragmento de

código que ocuparía una rutina de carga de datos desde la ROM para ponerla en pantalla.

Una rutina de este tipo podemos encontrarla en el juego “Kid Dracula” para dibujar el logotipo

de KONAMI a partir de la dirección $9943 (3 líneas de 7 tiles cada una):

ROM0:166F 21 43 99 ld hl,9943

ROM0:1672 3E 01 ld a,01

ROM0:1674 0E 03 ld c,03

ROM0:1676 11 12 00 ld de,0012

ROM0:1679 06 07 ld b,07

ROM0:167B CD CE 24 call 24CE

ROM0:167E 22 ldi (hl),a

ROM0:167F 3C inc a

ROM0:1680 22 ldi (hl),a

ROM0:1681 3C inc a

ROM0:1682 05 dec b

ROM0:1683 20 F6 jr nz,167B

ROM0:1685 19 add hl,de

ROM0:1686 0D dec c

ROM0:1687 20 F0 jr nz,1679

Page 140: ROMHACKING GAMEBOY PRÁCTICO - Todo lo que quiso saber … · ^NOP _ ^No Operation _: Esta instrucción es la que vamos a utilizar para eliminar instrucciones cuando queramos por

Datos repetidos

Algunos juegos de Gameboy utilizan para comprimir tiles escribir 2 veces cada valor como

ocurre en los que corresponden a letras.

1 tile de Gameboy ocupa 16 bytes y utilizando esta compresión se utilizarían sólo 8 bytes

ocupando la mitad de bytes.

En el juego “Flintstones, The - King Rock Treasure Island” tiene tiles comprimidos que

corresponden a las letras y números. Por ejemplo el tile $80 que corresponde al número “0” se

escribe como:

00 00 3C 3C 66 66 66 66 66 66 66 66 3C 3C 00 00

En el juego este tile está almacenado como:

07:6772 38 4C C6 C6 C6 64 38 00

Page 141: ROMHACKING GAMEBOY PRÁCTICO - Todo lo que quiso saber … · ^NOP _ ^No Operation _: Esta instrucción es la que vamos a utilizar para eliminar instrucciones cuando queramos por

Esto es utilizable sólo para algunos tiles y no siempre se puede hacer (sólo cuando se repitan 2

veces todos los bytes que componen el tile).

Si se pone en "de" la dirección donde están los datos de los tiles en la ROM, en "hl" la dirección

donde se escribe el tile (Tile Address), en "c" el valor $08 (número de bytes que ocupa el tile en

la ROM que se ampliará a los 16 que ocupa un tile).

La rutina que carga los tiles se encuentra en:

ROM0:0263 06 01 ld b,01

ROM0:0265 0E 08 ld c,08

ROM0:0267 1A ld a,(de)

ROM0:0268 13 inc de

ROM0:0269 22 ldi (hl),a

ROM0:026A 22 ldi (hl),a

ROM0:026B 0D dec c

ROM0:026C 20 F9 jr nz,0267

ROM0:026E 05 dec b

ROM0:026F 20 F4 jr nz,0265

ROM0:0271 C9 ret

Las 2 instrucciones “ldi (hl),a” lo que hacen es precisamente escribir 2 veces el valor en la

dirección de la Tile Address.

Otros juegos que utilizan esta compresión para tiles en Gameboy son:

- Altered Space

- Amazin Penguin

Page 142: ROMHACKING GAMEBOY PRÁCTICO - Todo lo que quiso saber … · ^NOP _ ^No Operation _: Esta instrucción es la que vamos a utilizar para eliminar instrucciones cuando queramos por

- Astérix

- Castlevania II: Belmont´s Revenge

En el juego “Boomer´s Adventure in Asmik World” los tiles de las letras está comprimidos. Los

datos de los tiles están en la dirección $02:4F80 y se ponen en la dirección $9500=Tile Address.

En el registro “bc” se pone el valor $0180 que es el número de bytes que ocupan los tiles

(número de bytes a leer/escribir).

Por ejemplo el tile $50 que corresponde al número “0” está formado por los bytes:

3C 00 66 00 66 00 6E 00 76 00 66 00 3C 00 00 00

Y en el juego (ROM) está almacenado como: 3C 66 66 6E 76 66 3C 00

Escribe el valor que aparece en la ROM y a continuación añade el valor $00 hasta completar los

16 bytes.

La rutina que se encarga de cargar los tiles comprimdos y ponerlos a partir de la dirección

$9500 es:

ROM0:01E2 21 00 95 ld hl,9500

ROM0:01E5 11 80 4F ld de,4F80

ROM0:01E8 01 80 01 ld bc,0180

ROM0:01EB 1A ld a,(de)

ROM0:01EC 22 ldi (hl),a

Page 143: ROMHACKING GAMEBOY PRÁCTICO - Todo lo que quiso saber … · ^NOP _ ^No Operation _: Esta instrucción es la que vamos a utilizar para eliminar instrucciones cuando queramos por

ROM0:01ED AF xor a

ROM0:01EE 22 ldi (hl),a

ROM0:01EF 13 inc de

ROM0:01F0 0B dec bc

ROM0:01F1 78 ld a,b

ROM0:01F2 B1 or c

ROM0:01F3 20 F6 jr nz,01EB

La instrucción “xor a” equivale a “a=$00” que es el valor que añade para completar los 16

bytes del tile.

“dec bc”: Disminuye bc=Nº de bytes que quedan por leer/escribir.

La rutina se repite hasta que queden bytes saltando a la dirección $00:01EB para leer/escribir

más bytes.

Compresión RLE

Este tipo de compresión utiliza códigos para indicar que se repite un determinado byte una

cantidad de veces y dependiendo del juego puede utilizar un determinado valor u otro para

ello.

Por ejemplo, el juego “3 Choume no Tama - Tama and Friends - 3 Choume Obake Panic!!”

utiliza este tipo de compresión para tiles de las letras en las que se repiten los valores.

El tile $00 que corresponde al número “0” está almacenado en $9000 como:

00 00 38 38 44 44 44 44 44 44 44 44 44 44 38 38 (16 bytes)

En el juego dichos valores están almacenados como:

Page 144: ROMHACKING GAMEBOY PRÁCTICO - Todo lo que quiso saber … · ^NOP _ ^No Operation _: Esta instrucción es la que vamos a utilizar para eliminar instrucciones cuando queramos por

05:5608 00 00 38 38 DD 44 0A 38 38 (9 bytes)

Los 4 primeros bytes aparecen tal como están en la ROM. Antes de estos bytes aparece el valor

$EE (que no se si realmente es algún código).

A continuación aparece el valor $DD que es un código de control que indica que el byte

siguiente se repite un número de veces.

44 0A es lo que aparece a continuación, con lo que se repite $0A (10 veces) el valor $44.

Luego viene 38 38 que se pone tal y como aparece.

El motivo por el que no se utiliza el código $DD para repetir los valores 00 00 y 38 38 es porque

ocuparía más ya que 00 00 (2 bytes) se pondría como DD 00 02 (3 bytes) y 38 38 (2 bytes)

como DD 38 02 (3 bytes).

Hay valores que están comprimidos y otros que no lo están.

Si ponemos un breakpoint en la dirección $9000 cuando se escribe el valor $00 para poner los

datos de los tiles que corresponden a las letras y que están comprimidos veremos como el

emulador se para en la dirección $00:10EF y con los valores de los registros: rom=5, “hl=5609”

(05:5609 aunque en realidad es $05:5608 donde empiezan los datos para el tile $00 (“0”),

“de=$9000” (Tile Address donde se guardan los tiles).

Aquí parece que se encuentra la rutina que se encarga de leer los datos de los tiles y

descomprimirlos en la Tile Address:

ROM0:108A 2A ldi a,(hl)

ROM0:108B FE BB cp a,BB

ROM0:108D 28 18 jr z,10A7

ROM0:108F FE CC cp a,CC

ROM0:1091 28 18 jr z,10AB

ROM0:1093 FE DD cp a,DD

ROM0:1095 28 19 jr z,10B0

ROM0:1097 FE AA cp a,AA

ROM0:1099 28 1F jr z,10BA

ROM0:109B FE EE cp a,EE

ROM0:109D C8 ret z

ROM0:109E FE 99 cp a,99

ROM0:10A0 20 01 jr nz,10A3

ROM0:10A2 2A ldi a,(hl)

ROM0:10A3 12 ld (de),a

ROM0:10A4 13 inc de

Page 145: ROMHACKING GAMEBOY PRÁCTICO - Todo lo que quiso saber … · ^NOP _ ^No Operation _: Esta instrucción es la que vamos a utilizar para eliminar instrucciones cuando queramos por

ROM0:10A5 18 E3 jr 108A

ROM0:10A7 AF xor a

ROM0:10A8 4E ld c,(hl)

ROM0:10A9 18 07 jr 10B2

ROM0:10AB 3E FF ld a,FF

ROM0:10AD 4E ld c,(hl)

ROM0:10AE 18 02 jr 10B2

ROM0:10B0 2A ldi a,(hl)

ROM0:10B1 4E ld c,(hl)

ROM0:10B2 12 ld (de),a

ROM0:10B3 13 inc de

ROM0:10B4 0D dec c

ROM0:10B5 20 FB jr nz,10B2

ROM0:10B7 23 inc hl

ROM0:10B8 18 D0 jr 108A

ROM0:10BA 2A ldi a,(hl)

ROM0:10BB 4F ld c,a

ROM0:10BC 2A ldi a,(hl)

ROM0:10BD E0 92 ld (ff00+92),a

ROM0:10BF 2A ldi a,(hl)

ROM0:10C0 47 ld b,a

ROM0:10C1 F0 92 ld a,(ff00+92)

ROM0:10C3 12 ld (de),a

ROM0:10C4 13 inc de

ROM0:10C5 78 ld a,b

ROM0:10C6 12 ld (de),a

ROM0:10C7 13 inc de

ROM0:10C8 0D dec c

ROM0:10C9 20 F6 jr nz,10C1

ROM0:10CB 18 BD jr 108A

ROM0:10CD 2A ldi a,(hl)

Page 146: ROMHACKING GAMEBOY PRÁCTICO - Todo lo que quiso saber … · ^NOP _ ^No Operation _: Esta instrucción es la que vamos a utilizar para eliminar instrucciones cuando queramos por

ROM0:10CE FE BB cp a,BB

ROM0:10D0 28 22 jr z,10F4

ROM0:10D2 FE CC cp a,CC

ROM0:10D4 28 22 jr z,10F8

ROM0:10D6 FE DD cp a,DD

ROM0:10D8 28 23 jr z,10FD

ROM0:10DA FE AA cp a,AA

ROM0:10DC 28 33 jr z,1111

ROM0:10DE FE EE cp a,EE

ROM0:10E0 C8 ret z

ROM0:10E1 FE 99 cp a,99

ROM0:10E3 20 01 jr nz,10E6

ROM0:10E5 2A ldi a,(hl)

ROM0:10E6 47 ld b,a

ROM0:10E7 F3 di

ROM0:10E8 F0 41 ld a,(ff00+41)

ROM0:10EA E6 03 and a,03

ROM0:10EC 20 FA jr nz,10E8

ROM0:10EE 78 ld a,b

ROM0:10EF 12 ld (de),a

ROM0:10F0 FB ei

ROM0:10F1 13 inc de

ROM0:10F2 18 D9 jr 10CD

ROM0:10F4 AF xor a

ROM0:10F5 4E ld c,(hl)

ROM0:10F6 18 07 jr 10FF

ROM0:10F8 3E FF ld a,FF

ROM0:10FA 4E ld c,(hl)

ROM0:10FB 18 02 jr 10FF

ROM0:10FD 2A ldi a,(hl)

ROM0:10FE 4E ld c,(hl)

Page 147: ROMHACKING GAMEBOY PRÁCTICO - Todo lo que quiso saber … · ^NOP _ ^No Operation _: Esta instrucción es la que vamos a utilizar para eliminar instrucciones cuando queramos por

ROM0:10FF 47 ld b,a

ROM0:1100 F3 di

ROM0:1101 F0 41 ld a,(ff00+41)

ROM0:1103 E6 03 and a,03

ROM0:1105 20 FA jr nz,1101

ROM0:1107 78 ld a,b

ROM0:1108 12 ld (de),a

ROM0:1109 FB ei

ROM0:110A 13 inc de

ROM0:110B 0D dec c

ROM0:110C 20 F1 jr nz,10FF

ROM0:110E 23 inc hl

ROM0:110F 18 BC jr 10CD

ROM0:1111 2A ldi a,(hl)

ROM0:1112 4F ld c,a

ROM0:1113 2A ldi a,(hl)

ROM0:1114 E0 92 ld (ff00+92),a

ROM0:1116 2A ldi a,(hl)

ROM0:1117 E0 93 ld (ff00+93),a

ROM0:1119 F3 di

ROM0:111A F0 92 ld a,(ff00+92)

ROM0:111C 47 ld b,a

ROM0:111D F0 41 ld a,(ff00+41)

ROM0:111F E6 03 and a,03

ROM0:1121 20 FA jr nz,111D

ROM0:1123 78 ld a,b

ROM0:1124 12 ld (de),a

ROM0:1125 FB ei

ROM0:1126 13 inc de

ROM0:1127 F0 93 ld a,(ff00+93)

ROM0:1129 47 ld b,a

Page 148: ROMHACKING GAMEBOY PRÁCTICO - Todo lo que quiso saber … · ^NOP _ ^No Operation _: Esta instrucción es la que vamos a utilizar para eliminar instrucciones cuando queramos por

ROM0:112A F3 di

ROM0:112B F0 41 ld a,(ff00+41)

ROM0:112D E6 03 and a,03

ROM0:112F 20 FA jr nz,112B

ROM0:1131 78 ld a,b

ROM0:1132 12 ld (de),a

ROM0:1133 FB ei

ROM0:1134 13 inc de

ROM0:1135 0D dec c

ROM0:1136 20 E1 jr nz,1119

ROM0:1138 18 93 jr 10CD

Según esto los valores que podrían ser de control son: 99 AA BB CC DD EE.

El código $DD ya lo hemos visto que repite el tile siguiente x veces.

El código $BB escribe x veces el valor $00.

Los tiles $00 y el $01 que aparecen en la pantalla de título se representan por los bytes:

00 00 00 00 0F 0F 1F 1F 1F 1F 1F 1F 0F 0F 00 00 (Tile $00)

00 00 00 00 80 80 E0 E0 FC FC FE FE FF FF 3F 3F (Tile $01)

Estos dos tiles se encuentran en la ROM como:

05:403C ($1403C) BB 04 0F 0F DD 1F 06 0F 0F BB 06 80 80 E0 E0 FC FC FE FE FF FF DD 3F 03

BB 04 (Escribe $04 veces el valor $00) 0F 0F

DD 1F 06 (Escribe $06 veces el valor $1F) 0F 0F

BB 06 (Escribe $06 veces el valor $00: 2 últimos bytes del tile $00 y 4 primeros bytes del tile

$01) 80 80 E0 E0 FC FC FE FE FF FF

DD 3F 03 (Escribe $03 veces el valor $3F: 2 últimos bytes del tile $01 y primer byte del tile

$02).

En este juego si buscamos la primera dirección donde encontrábamos tiles $05:5608 (0856) en

un editor hexadecimal lo encontramos en $05:4012-$05:4013 ($14012-$14013) y si buscamos

la dirección $05:403C donde están otros tiles del juego lo encontramos en $05:4000-$05:4001

($14000-$14001) por lo que aquí encontramos los punteros a tiles comprimidos del juego

(aunque no he comprobado si hay algú puntero a otro tipo de datos).

05:4000 ($14000): 3C 40 ($05:403C)

05:4002 ($14002): FF 45 ($05:45FF)

Page 149: ROMHACKING GAMEBOY PRÁCTICO - Todo lo que quiso saber … · ^NOP _ ^No Operation _: Esta instrucción es la que vamos a utilizar para eliminar instrucciones cuando queramos por

05:4004 ($14004): 4E 4F ($05:4F4E)

05:4006 ($14006): B5 4C ($05:4CB5)

05:4008 ($14008): 32 40 ($05:4032)

05:400A ($1400A): 48 53 ($05:5348)

05:400C ($1400C): DC 53 ($05:53DC)

05:400E ($1400E): D6 51 ($05:51D6)

05:4010 ($14010): B2 54 ($05:54B2)

05:4012 ($14012): 08 56 ($05:5608)

05:4014 ($14014): 6B 5C ($05:5C6B)

05:4016 ($14016): 55 63 ($05:6355)

05:4018 ($14018): 54 65 ($05:6554)

05:401A ($1401A): 28 66 ($05:6628)

05:401C ($1401C): 2B 67 ($05:672B)

05:401E ($1401E): 4E 68 ($05:684E)

05:4020 ($14020): 77 6B ($05:6B77)

05:4022 ($14022): FE 6C ($05:6CFE)

05:4024 ($14024): FA 6D ($05:6DFA)

05:4026 ($14026): 5F 72 ($05:725F)

05:4028 ($14028): 7A 73 ($05:737A)

05:402A ($1402A): EA 79 ($05:79EA)

05:402C ($1402C): FA 7A ($05:7AFA)

05:402E ($1402E): 59 7B ($05:7B59)

05:4030 ($14030): 26 7C ($05:7C26)

Compresión de textos DTE y MTE

Antes cuando hemos buscado textos en juegos de Gameboy nos hemos encontrado que un tile

corresponde a una letra pero no siempre ocurre así.

Podemos encontrar compresión DTE (Dual Tile Encoding) en algunos juegos que consiste en

que un byte corresponde a 2 tiles.

Por ejemplo, el valor $A0 puede corresponder al texto "GA", el valor $A1 puede corresponder

al texto "ME", el valor $A2 puede corresponder al texto "BO" y el valor $A3 corresponder al

texto "Y." con lo que la secuencia de bytes: A0 A1 A2 A2 corresponde al texto "GAMEBOY."

Page 150: ROMHACKING GAMEBOY PRÁCTICO - Todo lo que quiso saber … · ^NOP _ ^No Operation _: Esta instrucción es la que vamos a utilizar para eliminar instrucciones cuando queramos por

Se puede dar el caso de que algunos valores correspondan a 2 tiles y otros sólo a un tile.

La compresión MTE (Multi Tile Encoding) consiste en asignar a un byte una serie de tiles que

puede ser variable.

Por ejemplo: Si el valor $A0 corresponde al texto "GAMEBOY ", $A1 corresponde al texto

"ROMHACKING.".

La secuencia de bytes: A0 A1 corresponde al texto "GAMEBOY ROMHACKING.".

Esta compresión DTE y MTE no es específico de Gameboy sino que también se utiliza en otras

consolas.

Compresión RNC

Este tipo de compresión conocida como RNC o Rob Northen debido a su autor se encuentra en

algunos juegos de la consola Gameboy aunque también la podemos encontrar en otras

consolas tales como Atari Lynx, Megadrive, Super Nintendo y también para PC.

Para localizar datos comprimidos en un juego de Gameboy basta con buscar la cadena de texto

“RNC” tal y como aparece (con todo en mayúsculas).

Puede haber algún juego que por casualidad aparezca esta cadena pero para asegurarte que

utiliza la compresión deberá aparecer varias veces ya que los juegos que utilizan compresión

RNC suelen tener varios fragmentos de datos comprimidos.

Algunos de los juegos de Gameboy que utlizan esta compresión son:

- Addams Family: Pugsley´s Scavenger Hunt

- Alien Olimpics 2044 AD

- Amazing Spider-Man 3, The - Invasion of the Spider-Slayers

- Batman Forever

- Bubsy 2

- Bust-A-Move 4

- Dennis, the Menace

- Gremlins Unleashed (GBC)

- Inspector Gadget - Operation Madkactus (GBC)

- Jelly Boy

- Jurassic Park 2: The Chaos Continues

- Last Action Hero

- Lucky Luke

- Mortal Kombat

- Mortal Kombat II

Page 151: ROMHACKING GAMEBOY PRÁCTICO - Todo lo que quiso saber … · ^NOP _ ^No Operation _: Esta instrucción es la que vamos a utilizar para eliminar instrucciones cuando queramos por

- Mortal Kombat 3

- Mr. Nutz

- (The) Smurfs

- (The) Smurfs 2

- (The) Smurfs 3

- Spirou

- Tintin in Tibet

Los datos comprimidos en formato RNC tienen una cabecera de 18 bytes con la siguiente

estructura:

- Texto “RNC” (3 bytes)

- Método de compresión (1 byte): 1 o 2

- Tamaño datos descomprimidos (4 bytes)

- Tamaño datos comprimidos (4 bytes)

- CRC datos descomprimidos (2 bytes): Checksum de los datos originales

- CRC datos comprimidos (2 bytes): Checksum de los datos comprimidos

- Leeway (1 byte): Diferencia entre datos comprimidos y descomprimidos en pack chunk

largos

- Pack Chunks (1 byte): Cantidad de pack chunks.

Por ejemplo, en el juego “Jurassic Park 2: The Chaos Continues” encontramos datos

comprimidos en la direcciones:

$10000

$10201

$18843

$18F65

$1906D

$1922A

$192CC

$19AA8

$19C08

$19FA6

$1AEF1

$1B0A4

Page 152: ROMHACKING GAMEBOY PRÁCTICO - Todo lo que quiso saber … · ^NOP _ ^No Operation _: Esta instrucción es la que vamos a utilizar para eliminar instrucciones cuando queramos por

$1B601

$1B68E

$1B726

$1B7B8

$1B84F

$1B8E8

$1B981

$1BA0E

$1BA95

$1BB1D

$1BBA5

$1BC2C

$1BCB4

$1BD3C

$1BDC4

$24000

….

En la dirección $10000 (04:4000) encontramos:

$04:4000 52 4E 43 (“RNC”)

$04:4003 02 (Método de compresión 2)

$04:4004 00 00 03 00 (Tamaño datos descomprimidos: $00000300)

$04:4008 00 00 01 EF (Tamaño datos comprimidos: $000001EF)

$04:400C F9 3B (CRC Datos descomprimidos)

$04:400E 94 A0 (CRC Datos comprimidos)

$04:4010 04

$04:4011 01 (Pack chunk=$01)

Esto nos dice que los datos comprimidos ocupan $1EF bytes con lo que estarán desde la

dirección $04:4012-$04:4200.

Existe un programa de MS-DOS que permite descomprimir los datos en formato RNC por lo

que podemos coger los datos desde $04:4000-$04:4200 y guardarlos en un fichero (ej:

“jp2.rnc”).

Page 153: ROMHACKING GAMEBOY PRÁCTICO - Todo lo que quiso saber … · ^NOP _ ^No Operation _: Esta instrucción es la que vamos a utilizar para eliminar instrucciones cuando queramos por

El problema que surge al descomprimir es que necesitamos un ordenador con Windows XP o

utilizar el emulador DOSBOX para ejecutarlo en Windows 7 y posteriores pero no es

complicado.

Yo en mi caso tengo un ordenador con Windows 8 y el emulador DOSBOX que utilizo para

ejecutar aplicaciones antiguas de MS-DOS.

Tengo un fichero .bat que realiza el proceso y que contiene sólo una línea para descomprimir

los ficheros comprimidos en formato RNC:

PPIBM u jp2.rnc

Esto lo que hace es ejecutar el programa PPIBM con el modificador “u” para descomprimir los

datos y “jp2.rnc” es el fichero que vamos a descomprimir.

Para utilizar con el DOSBOX basta con situar en la misma carpeta el fichero .bat, los datos

comprimidos en formato RNC y los ficheros que contiene el “RNC_ProPack” que contiene los

programas para descomprimir (que incluyo junto a este manual).

Hay que arrastrar el fichero .bat al acceso directo del programa “DOSBOX” para que se ejecute

y nos aparecerá la siguiente pantalla:

Page 154: ROMHACKING GAMEBOY PRÁCTICO - Todo lo que quiso saber … · ^NOP _ ^No Operation _: Esta instrucción es la que vamos a utilizar para eliminar instrucciones cuando queramos por

Aquí nos aparece la información de los datos que ocupan 513 bytes ($201) comprimidos y 768

bytes ($300) descomprimidos. Los datos comprimidos ocupan $201=$1EF+$12 ya que hemos

incluido la cabecera de los datos.

Como se ve en la captura los datos están comprimidos al 33.20%.

Si no cogemos la cabecera nos dice el programa que no es un fichero empaquetado con RNC.

Si abrimos el fichero obtenido de 768 bytes con el TilEd 2002 podemos comprobar que se trata

de tiles del juego que están comprimidos en formato RNC.

Page 155: ROMHACKING GAMEBOY PRÁCTICO - Todo lo que quiso saber … · ^NOP _ ^No Operation _: Esta instrucción es la que vamos a utilizar para eliminar instrucciones cuando queramos por

Si quisiéramos modificar los tiles del juego tendríamos que descomprimirlos tal y como hemos

hecho. Una vez descomprimidos podemos modificarlos y volver a comprimirlos.

Tendríamos que buscar si hay punteros a los datos comprimidos por si fuera necesario

modificarlos en caso de que los nuevos datos ocupen más y tengamos que situarlo en otra

dirección de la ROM.

Modificar save states emulador BGB

El emulador BGB permite guardar hasta 10 save states o partidas que podemos recuperar en

cualquier momento y continuar el juego desde ese punto.

Aunque se pueden utilizar los cheats para tener ventajas otra opción que se puede hacer es

modificar los savestates del emulador para por ejemplo, tener más vidas de las que teníamos

cuando lo guardemos.

Esto también es aplicable para save states de otros emuladores siempre y cuando dichos save

states tengan el mismo tamaño. Hay emuladores en los que conforme avanzamos en el juego

el save state va aumentando de tamaño y no tiene un tamaño fijo.

También hay otros en los que el save state está comprimido y al descomprimirlo el fichero

obtenido es del mismo tamaño por lo que tendríamos que realizar la búsqueda en este fichero

descomprimido, modificar el valor y luego volver a comprimirlo utilizando para ello el

compresor 7zip.

En la versión 1.5 que es la que he utilizado del emulador BGB el save state ocupa 17.1 Kb

(17604 bytes).

Page 156: ROMHACKING GAMEBOY PRÁCTICO - Todo lo que quiso saber … · ^NOP _ ^No Operation _: Esta instrucción es la que vamos a utilizar para eliminar instrucciones cuando queramos por

Para el ejemplo, vamos a utilizar el juego “Batman” de Gameboy guardando 2 save states uno

con 3 vidas y otro con 2 vidas.

Para buscar en el juego vamos a utilizar un programa propio “File Search” para encontrar

donde se guardan las vidas en el save state tal y como se ve en la imagen:

El programa es sencillo, basta con abrir los 2 save states y poner los valores a buscar. El botón

“Inicilizar” sirve para iniciar una nueva búsqueda o si nos equivocamos al seleccionar alguno de

los ficheros.

Page 157: ROMHACKING GAMEBOY PRÁCTICO - Todo lo que quiso saber … · ^NOP _ ^No Operation _: Esta instrucción es la que vamos a utilizar para eliminar instrucciones cuando queramos por

Como se ve en la captura hemos encontrado 2 valores por lo que podemos comprobar cual de

los 2 es el correcto para lo cual abrimos uno de los save states y modificamos estos bytes para

ver cuál es.

Si tienen conocimientos de programación pueden hacerse un programa similar aunque éste

cumple con el objetivo buscado u optimizarlo para un emulador en concreto o una consola

específica distinta de Gameboy.

Simplemente tienen que hacer un programa que busque para el caso visto antes en un fichero

el valor $03 y en el otro el valor $02 pero en la misma posición.

Para optimizar el buscador para este emulador podríamos buscar sólo en la parte del fichero

donde se guardan los datos de la RAM ya que además cuenta con otra información que no nos

va a interesar y que según el emulador para el juego es de 8319 posibles valores lo que haría el

proceso más rápido.

Como el editor hexadecimal (HxD) o cualquier otro empieza en $0000 debemos irnos al byte

1128 decimal o $0468 hexadecimal donde en el fichero “Batman (JU) [!].sn2” (2º savestate)

encontramos el valor $02.

Este byte es donde se guardan las vidas del juego ya que si lo modificamos poniendo el valor

$09 tendremos 9 vidas.

Si cargamos el save state seguirá apareciendo 2 vidas pero cuando nos quiten esta vida

veremos como tendremos 8 vidas ahora con lo que comprobamos que funciona.

Igual que con las vidas podemos hacer con la energía,…

Esta modificación afecta al save state (partida guardada) y no al juego (ROM) que sigue sin

cambiar.

En la RAM el número de vidas se guarda en la dirección $C0C7 de la RAM, la energía en $C0C8,

la puntuación en $C0DE-$C0E0.

Podemos calcular también la relación que existe entre la RAM y el save state.

En el save state hemos modificado el byte $0468 para las vidas y en la RAM está en $C0C7 (que

quitándole $C000 nos da $C7).

Si a $0468 le quitamos $C7 nos da $3A1 hexadecimal o 929.

Save State=RAM+$03A1

Page 158: ROMHACKING GAMEBOY PRÁCTICO - Todo lo que quiso saber … · ^NOP _ ^No Operation _: Esta instrucción es la que vamos a utilizar para eliminar instrucciones cuando queramos por

Save State=RAM+929

Sin embargo ésta no es realmente la fórmula porque esta funciona para este juego pero para

otros no irá.

El problema que tiene el save state del emulador BGB es que almacena en dicho fichero el

nombre del juego de Gameboy con lo que dependiendo de que el nombre del juego sea más o

menos largo va a empezar la RAM en una posición u otra del fichero.

Si observan en $0032 está situado el nombre del fichero del juego y un poco antes en $002E

tiene el valor $12 hexadecimal o 18 decimal que corresponde al número de bytes que ocupa

dicho nombre.

Si a $3A1 le restamos $12 que es el tamaño del nombre del fichero nos da $38F con lo que nos

daría las fórmulas:

Save State BGB=RAM+$038F+tamaño nombre fichero

Save State BGB=RAM+911+tamaño nombre fichero

Esta relación existirá en los juegos de Gameboy aunque habría que ver si para juegos de Super

Gameboy o Gameboy Color se mantiene la relación ya que puede que el emulador guarde

información adicional y comience la RAM en el save state en otra posición del fichero.

Podemos hacer una modificiación interesante cambiando el nivel que se encuentra en RAM en

$C0C2 y que se encontrará en $0463 en el fichero de save state.

Si hacemos esto poniendo el valor $03 en lugar de 1 que corresponde al nivel 1-1

empezaremos en el nivel “CHEMICAL FACTORY” (1-3) pero el efecto del cambio de nivel no lo

veremos hasta que no nos quiten una vida.

Page 159: ROMHACKING GAMEBOY PRÁCTICO - Todo lo que quiso saber … · ^NOP _ ^No Operation _: Esta instrucción es la que vamos a utilizar para eliminar instrucciones cuando queramos por

Para comprobar la relación que existe entre RAM y save state podemos probar con otro juego

y ver si se cumple.

Por ejemplo, en el juego “Batle Bull” las vidas se almacenan en la dirección de la RAM $C82E.

Por lo que en el save state estará en:

Save State=RAM+$038F+tamaño nombre fichero

Save State=$82E+$038F+$16=$BD3

Modificando el valor que aparece por $09 por ejemplo, conseguiremos tener 9 vidas en el

juego “Battle Bull”.

Podríamos crear un programa para modificar los save states de un determinado juego en el

emulador BGB de forma automática sin tener que utilizar un editor hexadecimal.

Esta imagen es de un editor de save states propio escrito en Visual Basic 6 que permite

modificar “Vidas” y “Enemigos que quedan” en el nivel aunque se puede ampliar a otras

opciones tales como puntuación y el nivel en el que estamos. También le quedaría modificar el

icono que hay en la parte izquierda superior por algún otro relacionado con el juego del editor.

También podríamos hacerlo multiemulador, es decir que no sólo modificara save states del

emulador BGB sino también de otros o incluso uno que permita modificar los de varios juegos

de Gameboy.

Por ejemplo, para el juego “Battle Bull” en el emulador “gambatte_qt_win32-r550” de

Gameboy el número de vidas se guarda en el byte 26289 que en el editor hexadecimal es

26288 decimal o $66B0 hexadecimal.

Como se guardaban las vidas en la RAM en la dirección $C82E podemos obtener la relación

entre RAM y save state del emulador Gambatte restándole a $66B0 el valor $82E lo que nos da

$5E82.

Save State Gambatte=RAM+$5E82

Save State Gambatte=RAM+24194

Si cambiamos el byte en $5F49 del save state de Gambatte en el juego “Batman” conseguimos

cambiar el número de vidas en este juego con lo que se cumple la relación anterior y no

tenemos que tener en cuenta el tamaño del nombre del juego ya que esta información no la

guarda el emulador en los save states.

Igual podemos hacer con otros emuladores que tienen save states de tamaño fijo.

Para el emulador Gest 1.1.1 el número de vidas del juego “Battle Bull” se guarda en el byte

18840 que en el editor hexadecimal es 18839 o $4997 hexadecimal. Como se guardaba las

vidas en la RAM en $C82E obtenemos:

Page 160: ROMHACKING GAMEBOY PRÁCTICO - Todo lo que quiso saber … · ^NOP _ ^No Operation _: Esta instrucción es la que vamos a utilizar para eliminar instrucciones cuando queramos por

$4997-$82E=$4169

Save State Gest=RAM+$4169

Save State Gest=RAM+16745

Documentación adicional

Otros documentos que son interesantes para comprender la consola Gameboy son:

- GBCribSheet (Otaku No Gameboy) donde aparece un resumen de las direcciones,

registros, instrucciones,…

- Gameboy Programing Manual (290 páginas)

- Gameboy CPU Tutorial (139 páginas)

Webs interesantes de romhacking en general

- www.Romhacking.net

- http://wahackforo.com/

- http://datacrystal.romhacking.net/

- https://tcrf.net/ (The Cutting Room Floor)

- http://acmlm.kafuka.org/board/

- http://foro.romhackhispano.org/