HexString - Dumpeador de Texto para ROMs + Guía de uso

Hola gente, quiero hacer pública una herramienta que comencé a desarrollar hace 5 meses, si bien ya era pública, no le hice mayor promoción, ya que queria pulirla lo suficiente como para atreverme a crear una guía y tutorial, a sabiendas de que muchas cosas podian salir mal. Su nombre HexString.

1. ¿Qué es HexString?

Es un volcador (dump) de texto, que nos permite extraer e insertar el texto de una ROM, facilitando en gran medida la traducción (o edición para romhacks) de un videojuego. Esta específicamente desarrollada para la edición de texto con punteros, de esta forma solo traducimos, mientras el programa se encarga de calcular el largo de los punteros, y por ende codificar completamente una tabla de punteros, para que no tener que hacerlo a "mano".

1.1 Funcionalidades.

  • Interfaz de usario con un diseño simple y fácil.
  • Extracción e Inserción de texto.
  • Cálculo automático de punteros y su inserción.
  • División de la líneas por medio del código de fin de línea.
  • Soporte a punteros de distintos tamaños (2, 3 y 4 bytes) y de distinto orden (little, big endian).
  • Soporte para punteros divididos en 2 partes.
  • Soporte para juegos con DTE/MTE, con busqueda optimizada.
  • Soporte para juegos que no tienen un código de fin de línea claro, permite dividir el texto dependiendo del largo del puntero, como tambíén su inserción.
  • Permite usar tu paréntesis favoritos, para los códigos de texto.
  • Permite guardar y cargar ficheros .json con la configuración.
  • Rellenar el espacio vacío.
  • Entre las más importantes.

1.2 No soporta.

  • Bueno como dije arriba, este programa esta hecho para juegos que tengan una tabla de punteros, si no lo tiene, pues no servirá.
  • Espacio vacío entre punteros.
  • Punteros muy desordenados (se puede pero tendrás que crear múltiples configuraciones, honestamente no es lo óptimo, aunque posible).
1.3 Interfaz.


Las opciones son:

File ->  New                Nuevo
            Open config    Abrir configuración 
            Save config    Guardar configuración

Help -> About            Acerca de

1.4 CLI

El programa incluye un archivo "console.exe" este permite hacer uso del cli o lineas de comando, útil si quieren crear bash, sin embargo considero que una característica avanzada que no trataré aquí. Para más información de su uso, leer el archivo "cli_commands.txt" incluido en el zip, o también aquí,

2. TUTORIAL

2.1 Requisitos previos.

Bien vamos al tutorial, esta herramienta requiere que el usuario tenga ciertos conocimientos, con respecto al romhacking.
  • Encontrar punteros, saber identificarlos, formato común por consola, y orden.
  • Saber que son los códigos de texto e identificarlos.
  • Saber crear tablas thingy (.tbl).
  • Saber editar las fuentes.
        Herramientas necesarias:
  • HexString (última versión aquí).
  • Un editor de texto, recomiendo Notepad++, usen siempre UTF-8.
  • Emulador del juego, MESEN 2 es un buen emulador con un buen debbug.
  • Editor hexagecimal, como Translhextion, Windhex.
  • Editor de gráficos de ROMs, Tilelayerpro, TileMoslester. o yychr.
2.2 Extracción del script.

Como ejemplo de tutorial utilizaré el juego Final Fantasy (USA) de NES (CR32: CEBD2A31). Todos los archivos ocupados estarán aquí.

Abriendo HexString.exe, veremos lo siguiente:


Para poder extraer e insertar el texto de un juego necesitamos lo siquiente:

  • El ROM
  • El archivo .tbl
  • Largo de los punteros.
  • Orden de los punteros.
  • Dirección donde Inician los punteros.
  • Dirección donde Terminan los punteros.
  • La base de los punteros (hablaré de este termino más adelante).
  • Dirección donde Inicia el texto.
  • Dirección donde Finaliza el texto.
  • Código finalizador de línea.
Nos es poco lo que necesitamos, así que comenzemos.

Bien este juego posee mucha información en internet, por ejemplo aquí en Data Cristal. Analizando la tabla que se proporciona nos damos cuenta que el juego ocupa compresión por DTE, copiamos y creamos un archivo .tbl con el nombre "Final Fantasy (USA).tbl". La tabla también debe estar en UTF-8.


Quiero hacer hincapié que $FF es un espacio (barra espacioadora), $00 es código de finalizador y $05 = código separador de líneas. Por lo tanto nuestro código finalizador de línea o "End Line" es $00

Bien, también tenemos información donde inicia y termina el texto, $28210 y $2B495 respectivamente. Luego solo queda buscar los offset donde inicia la tabla de punteros y donde termina. Para eso abrimos al juego, vamos al castillo a hablar con cualquier NPC y nos dirá:


Buscamos el texto en el editor de MESEN, cargamos nuestro archivo .tbl para poder hacer uso de la búsqueda, finalmente localizamos el texto que inicia en el offset $28E14 (NOTA: MESEN en la imágen muestra $28E04, pero este no lee la cabecera por lo cual tendremos que sumar $10 a cada offset de aquí en adelante).


Antes de continuar, debemos recordar que los punteros en la consola de NES suelen ser de 2 bytes, en formato little endian, eso quiere decir primero que solo podemos movernos dentro de un rango de 4000 bytes, y segundo a la hora de su búsqueda debemos invertirlos.

El editor de MESEN ilumina en tiempo real los bytes que están siendo leídos, normalmente la tabla de puntero se encontrará cercana a los texto, puede estar más arriba o abajo, en este caso se encuentra directamente arriba. 

Vemos iluminado 2 bytes estos son $048E como en la imágen de abajo, si hacemos el cálculo hacia donde apunta debemos invertirlo y sumar la cabecera $8E04 + $10 = $8E14,  osea coincide con los ultimos 4 bytes del la dirección donde empezaba el texto que era $28E04, estos $20000 faltantes lo corregiremos más adelante.



Encontrada la tabla de punteros, ahora solo tenemos que encontrar el primero de todos, para eso localizamos el primer texto y vemos su offset, esta información ya la tenemos y es en $28210, haciendo el proceso inverso, el puntero debería ser $0082 y este se encuentra arriba, ya solo debemos copiar los offset del inicio y del final, $28010 y $2820F respectivamente.

En "Set Pointers" tal y como dije arriba debemos dejarlo en 2 bytes, y su "Endiannes" es little endian.

Solo nos falta identificar la base de los punteros o "Pointers Base", se acuerdan de esos $20000 faltantes, pues aquí irán, pero también sumaremos la cabecera, esos $10 bytes que habíamos agregado antes, por lo tanto nos quedaría $20010.

Ya tenemos todo lo necesario, nos vamos al HexString y rellenamos todos los campos.


Y le damos al botón "Extract Script and Save", elegimos donde guardar el texto y en que formato, personalmente los trabajo en binario (.bin), pero pueden dejarlo como .txt o la extensión que deseen. Nos saldrá una ventana emergente anunciando su extracción, junto con ello la consola nos mostrará algunos datos importantes.

El tamaño del bloque de texto y el tamaño de bloque de los punteros extraídos.

Nota: No cierren el programa antes de guardar la configuración, ir a file-> Save config y guardamos la configuración.

2.3 Edición del script.

Si abrimos el archivo de salida, nos quedará algo así. Recomiendo ir a vista -> ajuste de texto.


Algunas cosas a tener en cuenta:
  • El caracter ";" al inicio de uan línea se usa para comentar y por tanto toda la línea es ignorada.
  • Si al inicio de una línea hay caracteres  "@" y "|" también son ignoradas.
  • La primera línea tiene un formato distinto, esta es una línea de control, por lo tanto nunca la modifiquen o cambien de lugar, especificamente si van utilizar la consola para crear script.

Como pueden ver las líneas se encuentran enumeradas después de @, luego tenemos la dirección donde tenemos el texto, además de una copia de la línea (es posible deshabilitar). la línea a modificar y para finalizar un "|" que indica que ese bloque de texto ha terminado. La línea que tienes que modificar es la que no empieza con nada.

A modo de ejemplo editaré la línea que mostraba el NPC, en este caso es el puntero número #50, la modificaré a "ESTO ES UNA PRUEBA DE HEXSTRING POR KODA 2025".


Guarden los cambios y listo.

2.4 Insertar el script.

Nos vamos a  HexString y ahora cargamos el archivo de texto que modificamos en "Open Script", ya solo nos queda insertarlo. Si cerraron el programa, solo deben volver a cargar la configuración, previamente guardada, para eso vamos a file-> open config .

Una vez todo listo presionamos "Insert Script to ROM", nos saldrá una ventana emergente anunciando que se ha insertado el texto.


Por cierto si vemos la consola integrada, algo llama la atención y son los bytes libres, un total 873 bytes y eso que no he borrado prácticamente nada, por lo cual inferimos que el DTE original es poco eficiente.


Recargamos el juego y comprobamos el texto hablando nuevamente con el NPC.


Todo perfecto, si comprobamos con otro NPC que tenga un diálogo posterior a la línea #50, por ejemplo la línea del puntero #73.

Está perfectamente formateado, por tanto es evidencia de la inserción a sido todo un éxito y el cálculo de los punteros posteriores también son correctos.

Nota: Más abajo en Tips dejo otro método para saber si hay errores al insertar scripts.

Ya solo queda traducir todo el script, editar las fuentes para agregar los símbolos del español, y codificarlo en el .tbl. 

2.5 Funciones avanzadas.

La herramienta cuenta con un botón de opciones avanzadas, si le hacemos click, desplegara una lista de opciones, a continuación sus efectos y sus posibles usos.


Not duplicate line as comment: Como su nombre indica, no se creará una copia de la línea como un comentario, útil si se editará en alguna otra plataforma.

Use custom brackets for raw hex code: Aquí puedes cambiar los paréntesis por defecto, que se usarán para los códigos hexagecimales no definidos en la tabla thingy (.tbl). Debes ocupar los mismos para extraer como para insertar.

Importante: por una limitación técnica no es posible asignar los caracteres para códigos para elementos dentro del archivo .tbl, ejemplo si definiste como parentesis personalizados "<" y ">" para códigos hexagecimales crudos, no podrás establecer dentro del .tbl asignaciones con eso, ya que serán ignorados, por ejemplo FF=<END>, EF=<LINE>, etc.

Fill free space when inserting with next byte: Se rellenará el espacio vacío, si es que hay con el byte definido a la derecha, útil para limpiar la rom y saber con mayor seguridad que no se está ocupando, para mover bloques del juego a otras direcciones.

Use split pointers method (2 bytes only): Algunos juegos dividen los punteros en 2 partes, una parte con los bytes menos significante (LSB), y otra con los bytes más significantes (MSB), por ejemplo: Chip 'n Dale Rescue Rangers (USA).nes


El programa tomará cada parte y lo juntará formando el puntero, el largo o size debe ser la mitad. En este caso son 40 bytes, $28 en hexagecimal, osea ocuparemos $14.

En este caso:
   
LSB: $9546   MSB: $955A   Size: $14

At extract ignore and line code until some character are decode: Algunos juegos cuentan con códigos de texto iguales al finalizador de línea, como por ejemplo star fox 2 de SNES, como podemos notar con algún texto, el código finalizador de línea es $00, genial, ocupamos hexstring y nos encontramos con esto.

El inicio de cada bloque de texto consta de 2 códigos hexagecimales, el primero es el personaje que habla, y el segundo que coincide con el finalizador de línea, es el efecto del mensaje (Si tiene que tambalearse por ejemplo), obviamente el mensaje se mostrará incompleto, tal y como se aprecia arriba, si activamos esta opción el programa ignorará hasta que algún caracter presente en el .tbl sea decodificado, quedandonos como debería.



Not use end line code for split lines (Use pointers lenght):

Esta opción deshabilita que se ocupe un codigo de fin de linea para ir dividiendo el texto, al extraer se tomará como referencia la diferencia en bytes que exista entre cada puntero, y se divide en base a este número. Útil para juegos que no tengan un código fijo o se dividan puntero en base a muchos códigos finalizadores de línea.  Ejemplo de uso: Miracle Girls (Japan) de SNES.



Importante: Al insertar cada línea del script se interpretará como un puntero. Y no con un código como es lo usual. 

Si extraes el texto con el casilla marcada, también debes usarla para insertar el texto.

2.6 Tips

Mejor visualización del largo de línea: Esto no lo mencioné, pero si usamos el end line como divisor de punteros, puedes dividir la linea dentro de sus respectivos "@" y "|" para tener una mejor idea de que largo tiene la línea, para utilizar mejor el separador de líneas, tal que así:


Importante: Si activan la casilla "No use end lines" este truco no es posible de implementar, o por lo menos van a tener que dejarlo lineal al terminar, ya que cada división será considerado como un puntero.

Comprobar siempre la reinserción: Es importante comprobar que tanto la extracción e inserción de texto se está haciendo bien, antes de comenzar un proyecto, sobretodo si este tiene mucho texto, para evitar problemas después y evitar el tiempo perdido. Como recomendación una vez extraído un script, siempre creo una copia de la ROM a traducir, y vuelvo a reinsertar el script. Asi tendremos una rom original limpia y una copia de la ROM con nuestra modificación y aquí viene la mágia, podemos usar programas incluso el mismo cmd para hacer una comparación hexagecimal entre los archivos, yo ocupo "HexCmp.exe" programa gratuito, si todo esta bien al terminar la comparación deberiamos obtener este mensaje:


Eso quiere decir que no existe ninguna diferencia, por lo tanto la inserción es correcta, solo resta traducir.

Nota: En juegos que ocupan codificación por DTE/MTE puede haber ciertas diferencias, que no necesariamente debe interpretarse como que es incorrecto. Por ejemplo: si se tiene como diccionario, "DE" y "TE", pero también "ET"

Función repetir último puntero: En algunos juegos, nos encontraremos con esto:

Como se observa 2 bloques tienen el mismo texto, esto sucede porque hay 2 punteros juntos con el mismo valor, osea apuntan a la misma caja de texto. Esto se comprueba fácil si ven el número subrayado el cual ambos coinciden. Lo que tienen que hacer es borrar la segunda línea y todas las subsiguientes (en el caso de haber muchas repeticiones) y poner el caracter "&" y el código finalizador. De esta forma el programa sabrá que tiene que repetir el último puntero.


Nota: Si activan la casilla "No use end lines" pueden ignorar el uso del código finalizador y dejar solo "&".

2 comentarios:

  1. Hola Koda, esta interesnte, muy agradecidoesto podria aydar a nuevos traductores. De mi parte quiero aprender como va esto, yo traduzco a lo cavernicola. Seria bueno un tutorial con un video .

    ResponderBorrar
    Respuestas
    1. Un gusto poder ayudar a los demás, principalmente espero que los conocimientos previos que detallo no sean tan grandes como para que cualquier persona pueda iniciarse en este humilde rubro, si quieres empezar puedes hacer uso de las configuraciones que incluyo con el programa, un saludo.

      Borrar