¡Muy buenas a todos! Sed bienvenidos a esta segunda edición de las GlowCuriosidades.
En esta ocasión os hablaré del reto que supuso llevar a cabo el proyecto de Last Bible. Abarcaré varios temas que tocarán todas las etapas del proceso de traducción: romhacking del título, restauración de su terminología, arreglo de bugs…
Hoy me centraré únicamente en el proceso de romhacking, ya que abarcar todo el trabajo realizado en el proyecto sería demasiado para una sola entrada. En las siguientes ediciones trataré el resto de temas para que todo quede lo más claro posible.
Como esta entrada no sería una nueva entrega de GlowCuriosidades si no tuviese una buena música de fondo para acompañar la lectura, aquí os dejo Blues in Velvet Room de Persona 3.
1º Parte: romhacking
Antes de nada, me gustaría agradecerle a Saispai (Orden) todo el apoyo y enseñanzas que me brindó desde el minuto cero, cuando yo aún no sabía nada de cómo funcionaba la Game Boy Color.
Herramientas usadas en este artículo:
1.1º Búsqueda inicial de texto
Este fue el primer paso que di: si no tenemos los textos, ¿cómo vamos a traducir el juego?
Lo primero que hice fue buscar el texto a traducir. Inicié el juego para intentar encontrar una primera frase a partir de la que iniciar todo el proceso de romhacking. No escogí ninguna de la introducción, por miedo a que fuera un gráfico; avancé hasta el primer diálogo.
Abrí mi programa favorito de tratamiento de archivos binarios, HxD, y luego la ROM. Lo primero que hice fue buscar la frase mediante una cadena de texto (string), a ver si había suerte…
Pero no hubo ni una pizca.
Me puse a buscar como un loco por toda la ROM hasta que encontré esto:
Como podéis ver, las letras están codificadas en ASCII. No obstante, en la ROM aparecen en mayúsculas, mientras que en el juego son minúsculas. Por ello no se aprecian simple vista las mayúsculas del juego.
Eso me dio una pista importante, ya que me indicó que el juego funcionaba bajo una tabla. Nueva misión: tenía que buscar la fuente para ver si encontraba algo más.
1.2º Buscando la fuente y entendiéndola
Para buscar los gráficos del juego usé un programa muy conocido llamado Tile Molester, que trata los gráficos de los juegos de las consolas antiguas.
Antes de comenzar la búsqueda de la fuente, no obstante, es importante tener en cuenta la codificación de dicha fuente. Hay varias formas de poder comprobarla. Yo opté por usar el emulador BGB de la Game Boy, cuyo potente depurador me facilitó bastante la tarea.
Así pues, abrí el juego, avancé hasta el primer diálogo e inicié el depurador de la VRAM:
Como podéis ver, se apreciaban a simple vista todos los gráficos usados en el juego y también la fuente.
Me situé en el tile de una letra coloreada. A la derecha se ve el dibujo y abajo unos parámetros; no obstante, lo que me interesaba era la tercera casilla, que mostraba la paleta que usaba.
Por lo que me fui a la pestaña de «Palettes» y busqué la paleta «BG 7»:
Ahí se ven claramente los cuatro colores usados por el juego. Se trata de una paleta de 2bpp (Bytes Per Pixel).
Una vez supe que usaba una codificación de 2bpp, tenía claro el siguiente paso: buscar la fuente por la ROM. No tenía ninguna pista de dónde se alojaba, por lo que tuve que mirar de pe a pa todo el archivo.
Inicié Tile Molester, abrí la ROM, y busqué como un loco hasta que encontré esto:
¿Por qué se veía rara la fuente si en el emulador se veía bien a 2bpp? Esta pregunta estuvo rondando mi cabeza un buen rato, hasta que me di cuenta de un detalle importante:
En el dibujo solamente se veían dos colores, pero si me situaba en otro tile, se veían cuatro colores.
Esto era un signo inequívoco de que dos colores de la paleta no se estaban usando en la fuente. Los dos restantes que no se ven en la fuente se usan en los bordes del cuadro de diálogos, por lo que cambié la codificación a 1bpp y…
¡Bingo! En este punto las letras ya casi se entendían. Como el marrón me destrozaba los ojos, cambié el color del marrón por blanco.
Avancé los bytes de la posición que tenían en ese momento hasta que se viese con claridad la fuente.
Una vez pude ver con claridad la fuente, me decidí a analizarla. Pasé un buen rato pensando, sin dar con la clave. Le terminé preguntando a mi compañero Saispai. Cuando le enseñé lo que había averiguado acerca de los textos y de la fuente, me dio la solución casi al instante:
«La fuente sigue un orden del 00 al 7F a simple vista. El valor 00 le corresponde a 0; al 01, el 1; al 02, el 2; al 0A, el A y al 45, el e… En resumidas cuentas, vas contando y vas asignando la letra/número que corresponda.»
Un ejemplo gráfico del mapeo de la fuente sería este:
Sacando la tabla entera, se quedaría así:
00=0
01=1
02=2
03=3
04=4
05=5
06=6
07=7
08=8
09=9
0A=A
0B=B
0C=C
0D=D
0E=E
0F=F
10=G
11=H
12=I
13=J
14=K
15=L
16=M
17=N
18=O
19=P
1A=Q
1B=R
1C=S
1D=T
1E=U
1F=V
20=W
… (no la voy a poner al completo porque sería demasiado grande)
Y ya por fin tenía la tabla.
1.3º Aplicando caracteres especiales y encontrando los códigos de control
1.3.1º Comprobando si la tabla funciona correctamente
El siguiente paso fue abrir de nuevo la ROM, pero con la tabla aplicada.
En este caso, HxD no me servía, pues no tenía la capacidad de cargar «Tablas thingy». Saispai me recomendó usar WindHex, que es otro editor hexadecimal que sí tiene esta capacidad:
Entonces ya pude encontrar la primera frase del juego y modificarla.
¡Bingo! Modifiqué únicamente la primera frase para ver cómo se veía en el juego:
Ya se veía correctamente, pero me escamaba que no hubiese ningún tipo de carácter especial. Es por eso que decidí que mi siguiente paso sería insertarlos.
1.3.2º Insertando caracteres especiales al juego
Este paso es muy importante, ya que gracias a él podemos leer en español la traducción de Last Bible.
Una traducción sin caracteres especiales no es una traducción, sino una basura que solo sirve para dañar la vista.
Volví a analizar la fuente y me fijé que la gran cantidad de huecos blancos que había:
Dibuje en el primer tile que había en blanco la á y lo escribí en la tabla.
Como iba después de la z, el número hexadecimal que le correspondía era la 5B.
Lo puse en la ROM para probar y…
¡Funcionó! El juego no usaba originalmente estos huecos, por lo que pude poner los caracteres especiales sin problemas:
Ya tenía la fuente totalmente editada y funcional.
1.3.3º Códigos de control y búsqueda de punteros
Mientras editaba la fuente, Saispai identificó casi todos los códigos de control y los punteros y procedió a explicármelo:
«El juego tiene diversos códigos de control. Por ejemplo, los saltos de línea, ya que el juego no mete saltos automáticamente. Si te excedes del cuadro, el texto no se ve, pues escribes en la interfaz y en el mapa del juego, haciendo que el juego se vuelva loco.»
«Otros códigos de control son el nombre de los personajes, el fin de línea, el tiempo de espera para que pulses un botón… Lo he apuntado todo en tu tabla para que lo puedas visualizar en el windhex.»
Los códigos son:
F0=[LINESCROLL]
F3=[WAIT]
F5=[ALLY]
F8=[ENEMY]
FD00=[HERO]
FD01=[FRIEND]
FD02=[HEROINE]
FE=[LINE]
FF=[END]
Para empezar a sacar los textos investigué el funcionamiento de los punteros de la Game Boy, pues el modo que usan es genérico en muchos juegos. Aquí lo explican muy bien: https://datacrystal.romhacking.net/wiki/Pointer#Game_Boy_Pointers.
Casi todos los textos del juego están divididos en cuatro bloques de texto. El principio del bloque contiene todos los punteros de texto comprendidos en dos bytes cada uno. Dependiendo del bloque tiene un cálculo distinto, pero funcionan de igual manera en todas:
- Se toma de base la posición del primer puntero (0x38000, por ejemplo).
- Se lee el puntero, como en este caso es Little Endian, y se le da la
vuelta (por ejemplo, si el puntero es BC42, dado la vuelta sería 42BC). - Se elimina el primer dígito del puntero leído anteriormente (Por ejemplo, 0x42BC se quedaría en 0x2BC).
- Se suma la base tomada anteriormente con el valor obtenido (0x38000+0x2BC=0x382BC).
- Te diriges a esa posición y verás que es el inicio de la frase que lee el juego.
Para leer ese bloque de texto hay que leer todos los bytes que haya hasta el 0xFF, que es de fin de diálogo. Si no tiene ese byte, el juego seguirá leyendo hasta encontrarlo.
1.4 Exportado e importado de los bloques de texto con Atlas y Cartographer.
1.4.1 Cartographer
Cartographer es el programa que extrae el texto del juego en formato legible mediante tablas de caracteres.
Necesita tres cosas: la ROM, la tabla de caracteres y el archivo de comandos. Este último dicta dónde debe buscar el texto y cómo.
La descarga de Cartographer incluye un archivo de comandos del primer Final Fantasy como ejemplo que puede tomarse como base para crear el archivo de comandos de otro juego.
Se puede escribir un bloque de comandos por cada bloque del texto de la ROM en el mismo archivo de comandos para extraer todo el texto del juego a la vez.
Los comandos son:
#GAME NAME: el nombre del juego. No afecta en nada a la extracción.
#BLOCK NAME: el nombre del bloque a extraer. No afecta en nada a la extracción.
#TYPE: por lo general es NORMAL, con la tabla de caracteres
controlando cuándo acaba una cadena de texto. Existen otros tipos para
bloques de texto con cadenas de longitud fija (como es el caso de la
lista de los nombres de los demonios en Last Bible).
#METHOD: la forma en que Cartographer encontrará el texto. En Last Bible
y la mayoría de los juegos de NES, GB y SNES suele ser
POINTER_RELATIVE, con punteros relativos al mismo banco de datos, pero
también puede ser POINTER para punteros absolutos que pueden apuntar a
cualquier dirección de la ROM.
También se puede usar RAW para extraer directamente bloques de texto
indicando dónde empiezan y acaban sin basarse en los punteros, lo cual
no es útil si se piensa reinsertarlos luego en Atlas.
#POINTER ENDIAN: el orden de lectura de los punteros. Como ya se comentó antes, es LITTLE.
#POINTER TABLE START: la dirección donde empieza la tabla de punteros.
#POINTER TABLE STOP: la dirección donde empieza el último puntero de la tabla.
#POINTER SIZE: el tamaño de los punteros. Como ya se dijo, los punteros de Last Bible son de 2 bytes (80 00, por ejemplo), así que hay que escribir $02.
#POINTER SPACE: el espacio entre los punteros. Los de Last Bible y la mayoría de los juegos van seguidos, así que en este caso es $00.
#ATLAS PTRS: en caso de poner Yes, las cadenas de texto extraídas
vendrán precedidas por un comando con el puntero del texto para
reinsertarlos fácilmente en Atlas.
#BASE POINTER: el valor que hay que sumar a los punteros para encontrar la dirección del texto.
#TABLE: el nombre del archivo de la tabla de caracteres que se usará para extraer el texto. Debe estar en la misma carpeta.
#COMMENTS: en caso de poner “Yes“, las cadenas de texto
extraídas vendrán precedidas por //, lo que hace que Atlas las
interprete como comentarios o notas y no las inserte. Muy útil a la hora
de traducir editando directamente el dump de Cartographer, ya que así se puede escribir el texto traducido bajo el original para tenerlo como referencia.
#END BLOCK: necesario al final de cada bloque del archivo de comandos.
Para mayor comodidad, es recomendable poner Cartographer, la ROM, la tabla de caracteres y el archivo de comandos en la misma carpeta.
Para usar Cartographer hay que abrir la ventana de comandos de Windows, ir a la carpeta donde se encuentran los archivos y escribir:
Cartographer.exe [rom] [comandos] [nombre de archivo de los dumps]
En este caso sería así:
Cartographer.exe lastbible.gbc lb_commands.txt lb_script
Esto extraerá cada bloque de texto como lb_script_000, lb_script_001, lb_script_002…
Alternativamente se puede escribir esto en un bloc de notas y guardarlo como un archivo .bat, lo cual es más útil y rápido a la larga:
cartographer lastbible.gbc lb_commands.txt lb_script -m
pause
Y este es el script para exportar los textos de la ROM
#GAME NAME: Revelations: The Demon Slayer (GBC)
#BLOCK NAME: Diálogos 1
#TYPE: NORMAL
#METHOD: POINTER_RELATIVE
#POINTER ENDIAN: LITTLE
#POINTER TABLE START: $38000
#POINTER TABLE STOP: $382BC
#POINTER SIZE: $02
#POINTER SPACE: $00
#ATLAS PTRS: Yes
#BASE POINTER: $34000
#TABLE: lbatlas.tbl
#COMMENTS: No
#END BLOCK#BLOCK NAME: Diálogos 2
#TYPE: NORMAL
#METHOD: POINTER_RELATIVE
#POINTER ENDIAN: LITTLE
#POINTER TABLE START: $80000
#POINTER TABLE STOP: $80168
#POINTER SIZE: $02
#POINTER SPACE: $00
#ATLAS PTRS: Yes
#BASE POINTER: $7C000
#TABLE: lbatlas.tbl
#COMMENTS: No
#END BLOCK#BLOCK NAME: Diálogos 3
#TYPE: NORMAL
#METHOD: POINTER_RELATIVE
#POINTER ENDIAN: LITTLE
#POINTER TABLE START: $84000
#POINTER TABLE STOP: $8421C
#POINTER SIZE: $02
#POINTER SPACE: $00
#ATLAS PTRS: Yes
#BASE POINTER: $80000
#TABLE: lbatlas.tbl
#COMMENTS: No
#END BLOCK#BLOCK NAME: Diálogos 4
#TYPE: NORMAL
#METHOD: POINTER_RELATIVE
#POINTER ENDIAN: LITTLE
#POINTER TABLE START: $88000
#POINTER TABLE STOP: $881B2
#POINTER SIZE: $02
#POINTER SPACE: $00
#ATLAS PTRS: Yes
#BASE POINTER: $84000
#TABLE: lbatlas.tbl
#COMMENTS: No
#END BLOCK
1.4.2 Atlas
Atlas es el programa que inserta el texto generado por Cartographer en la ROM.
Para reinsertar el texto con Atlas hay que añadir una serie de comandos a los archivos donde se extrajo el texto, que en este caso son lb_script_000 y demases.
En cualquier parte antes del primer puntero se añaden los siguientes comandos:
#SMA(“GB”) – Tipo de ROM para calcular direcciones.
#VAR(dialogue, TABLE) – Variables a usar. El nombre de “dialogue” puede ser cualquier otro siempre y cuando se mantenga en los dos siguientes.
#ADDTBL(“lbatlas.tbl”, dialogue) – Se pone el nombre de archivo de la tabla de caracteres, y se le asigna la variable anterior.
#ACTIVETBL(dialogue) – Se determina cuál es la tabla activa, en este caso la que asociamos a la variable “dialogue”.
#HDR($4000) – Aunque esto técnicamente se usa para indicar el
tamaño del header y así restarlo de los cálculos, lo he puesto así por
comodidad para calcular el valor que hay que añadir a los punteros al
insertar el texto.
#JMP($382BC) – La dirección donde se empieza a insertar el texto.
Una vez hecho esto, para abrir Atlas se hace casi lo mismo que con Cartographer:
Atlas.exe [rom] [archivo]
En este caso:
Atlas.exe lastbible.gbc lb_script_000.txt
Esto son los scripts que se han usado:
Diálogos 1
#SMA(“GB”)
#VAR(dialogue, TABLE)
#ADDTBL(“lbatlas.tbl”, dialogue)
#ACTIVETBL(dialogue)
#HDR($4000)#JMP($382BC)
Diálogos 2
#SMA(“GB”)
#VAR(dialogue, TABLE)
#ADDTBL(“lbatlas.tbl”, dialogue)
#ACTIVETBL(dialogue)
#HDR($-4000)#JMP($80168)
Diálogos 3
#SMA(“GB”)
#VAR(dialogue, TABLE)
#ADDTBL(“lbatlas.tbl”, dialogue)
#ACTIVETBL(dialogue)
#HDR($10000)#JMP($8421C)
Diálogos 4
#SMA(“GB”)
#VAR(dialogue, TABLE)
#ADDTBL(“lbatlas.tbl”, dialogue)
#ACTIVETBL(dialogue)
#HDR($4000)#JMP($881CE)
1.5 Localizando y traduciendo los textos que no se pueden alterar su tamaño.
Por desgracia, hay muchos elementos que no se pueden traducir usando de Atlas y Cartographer, como los objetos, habilidades y la interfaz del juego.
Todos esos textos están repartidos por toda la ROM, pero hay un problema a la hora de traducirlos, que tienen un tamaño fijo e inalterable (se puede alterar, pero eso requiere conocimientos muy avanzados de ASM y no nos hace falta por ahora llegar a ese punto).
Afortunadamente, los tamaños son los adecuados para realizar traducciones en condiciones, ya que se asemejan al tamaño que ofrece la interfaz, por lo que que me puse manos a la obra.
Por ejemplo, para empezar con el menú principal, tuve que ir buscando los textos que aparecían en pantalla.
Los bytes 0x40 se repetían bastante, pues son el espacio que escribe el juego en la RAM
Me puse a modificar esos textos con cuidado ya que, si me pasaba, podría cargarme la interfaz.
Lo traduje correctamente y lo comprobé en el juego:
Con los objetos del juego ocurría lo mismo con la interfaz, pues tenía un tamaño límite a seguir.
El tamaño era fijo y los espacios que daba el juego eran el valor 8F.
Traduje un ejemplo sin pasarme de la raya:
¡Un problema menos!
1.6 Modificando el teclado del juego.
Cuando le das a nueva partida, el juego te dice que introduzcas los nombres de los protagonistas.
Pero al localizar el primer texto de introducir el nombre y mirar un poco más abajo:
Pude ver que las posiciones de las letras y su orden coincidían con los mostrados en el teclado del juego.
Si modificaba ciertos valores que no se usaban, ordenaba un poco el teclado y añadía las palabras más comunes…
Ya tenía las tildes insertadas en el teclado.
Extra: El juego también guarda los nombres por defectos de los personajes en ese bloque, por lo que si los cambiamos, se muestran los que hemos introducido:
1.7 Edición de gráficos
Y este es la parte final de la entrada. Editar gráficos en este juego fue bastante sencillo, pero tuve que tener en cuenta ciertas cosas.
Los gráficos (no) tienen cierta optimización, por eso vamos a ver algunos casos que los tiles están repartidos por ciertas zonas.
Esto ocurre cuando se quiere ahorrar espacio y memoria, ya que las consolas antiguas no tienen la misma capacidad que las consolas actuales (aunque en este caso el juego duplica ciertos gráficos. tanto optimizados como no).
Para que lo entendáis mejor os dejo aquí este vídeo, que lo explica bastante bien:
Había varios Inn repartidos por toda la ROM:
En este caso, como las Inn son en el juego hostales donde te alojas para recuperar energías y resucitar a tus aliados, las puse con una H de hostal.
Pacientemente, edité los gráficos a mano, para respetar la paleta y el estilo de dibujo, de forma que se viese bien en el juego.
El resultado fue este:
Lo siguiente que edité fue el gráfico «FRONT», usado en los hostales cuando te diriges al mostrador.
Debería haber puesto «Mostrador», pero como era demasiado largo, lo dejé como «Hostal»
Lo guardé y lo probé en el juego para ver cómo se veía.
Y así terminé de editar los gráficos.
Si tenéis alguna duda sobre algún paso de la entrada podéis preguntar en los comentarios y os responderé cuando pueda.
Espero que os haya gustado y hayáis aprendido bastante en esta entrada. ¡Nos vemos en la siguiente!
Gracias a Erena, por corregir el artículo.