Problema de Alineación

De Wiki Tales Translations

Tabla de contenidos

¿En qué consiste?

En ocasiones, al hacer romhacking y traducciones, se modifican punteros o textos que luego van a parar a memoria. En ciertas ocasiones hay datos que tienen que tener una cierta alineación en memoria. Si no están alineados correctamente pueden "colgar" el hardware real (la consola) aunque funcionen correctamente en un emulador.

En esta página trataré el problema de la alineación en la PSX/PSX y mas concretamente en el Tales of Destiny II/Eternia que es el caso concreto en el que hemos trabajado.

¿Qué operaciones/modificaciones provocan problemas de alineación?

Inicialmente el problema de alineación ocurre al modificar punteros a datos de 2 y 4 bytes (short *) y (int *) punteros a datos de 16 y 32 bits conocidos en los procesadores MIPS como "Half" y "Word" respectivamente. En general cualquier operación relacionada con las instrucciones LH y LW (Load Hald y Load Word).

¿En qué consiste que una dirección esté alineada?

Una dirección está alineada a 2 bytes cuando dicha dirección es:

  • múltiplo de 2
  • dirección % 2 == 0
  • la dirección es par
  • Bit menos significativo == 0
  • dirección & 1 == 0

Las 5 definiciones son equivalentes.

Una dirección está alineada a 4 bytes cuando dicha dirección es:

  • múltiplo de 4
  • dirección % 4 == 0
  • Dos bits menos significativos == 0
  • Dirección & 3 == 0

Las 4 definiciones son equivalentes

Copia de datos rápida

Al copiar datos de forma rápida se usan punteros a 32 bits y la instrucción LW en cuyo caso las direcciones de memoria usadas deben estar alineadas a 32 bits y tener una longitud múltiplo de 4.

En el Tales of Eternia; los datos de las habitaciones estaban empaquetados por habitaciones y en cada habitación había diversos "ficheros" que tenían una alineación de 32 bits.

Lectura de valores de 2 y 4 bytes

Los datos de tipo short e int deben estar alineados a 2 y 4 bytes. Los compiladores lo que suelen hacer es alinear TODOS los datos a 4 bytes en el ejecutable para que al cargar en memoria sigan alineados y se puedan acceder igualmente.

Este hecho tiene implicaciones muy importantes a tener en cuenta:

- A la hora de buscar punteros, bastante con buscar números en las direcciones múltiples de 4. - Las "stringz" cadenas terminadas en \0 estarán alineadas a 4 bytes dejando bytes \0 libres para la alineación. Suponiendo que las cadenas se lean mediante LB (Load Byte) como suele ser normal, se podrá disponer de espacio adicional.

Centinelas

En ciertas circunstancias se usan centinelas de 16 y 32 bits para determinar cuándo termina una secuencia.

En el Tales of Eternia los textos con scripts tenían inserciones de variables o códigos especiales. Escribir un texto mas rápido o mas lento. Escribir el nombre de un personaje. La cantidad de dinero u otras variables. Activar el flag de negrita para escribir el texto en negrita...

Estos códigos especiales empiezan por un código de control <= 0x20 y tienen una longitud par. Dicho código puede tener una longitud variable y se utiliza un centinela (una secuencia fija de bytes para conocer el fin de una sucesión). El centinela pese a ser una sucesión de 32 bits se comprueba cada 16 bits usando LH un (short *) en C. Para solucionar este problema, en el juego antes de un código de control se usa el caracter 0x1f (caracter dummy) para alinear el texto si la dirección de memoria es impar (no está alineado a 2 bytes.

¿Existe algún emulador de PSX que compruebe la alineación?

Hay una modificación del Emulador PCSX con Debugger integrado que permite comprobar los dos tipos de alineaciones en PSX para saber qué fallaría en el hardware real.

Herramientas personales