Contenido
Introducción
Las letras Yaz0 se encuentran muy frecuentemente entre los juegos de Nintendo. En el caso de Super Mario Galaxy estas letras se encuentran, en su mayoria, en la cabecera de los archivos ARC en las diferentes carpetas del juego. Yaz0 hace referencia a un algoritmo de compresión. Afortunadamente, es un algoritmo sencillo (es fácil de decodificar) y existen múltiples implementaciones del mismo dado su uso extendido en múltiples juegos. Esta página almacena información acerca de lo que he aprendido de Yaz0 viendo los archivos de Super Mario Galaxy.
Archivo ObjectData/CubeBubbleExPlanetA.arc visto en ImHex
Funcionamiento
Yaz0 es un algoritmo de compresión que usa los datos ya codificados/leídos para reconstruir el archivo original hacia adelante. Es decir, es un algoritmo que se basa en la repetición de patrones de bytes ya procesados para comprimir/reducir el tamaño de un archivo binario.
Esto lo hace guardando bloques de datos que "apuntan" hacia secuencias de bytes pasadas (cuando sea posible guardarlas). Estos bloques también guardan la información de cuantos bytes copiar de esa dirección. En el proceso de descompresión, los bytes especificados por la instrucción de copiado se colocan al frente de los bytes ya recuperados del archivo (en un contenedor aparte). El resultado es que poco a poco se va escribiendo el archivo de nuevamente.
Ejemplo visual y simplificado de la forma de compresión Yaz0
Se puede ver a través de la imagen que Yaz0 es sólo un conjunto de instrucciones en secuencia (que se leen de izquierda a derecha) que indican como reconstruir los datos de un archivo.
El formato binario de Yaz0 es un poco más complejo que lo que se muestra en la figura, pero ésta debería ayudar a dar una idea general de como funciona. En la siguiente sección se explicaran los detalles.
Definiciones
Yaz0 define 2 instrucciones de copiado:
0o Copia [número] de bytes localizados [número] de bytes atrás: Esta instrucción leída del archivo comprimido dice que "se copien [número] de bytes que se encuentran un [número] de posiciones atrás respecto a la última posición de escritura del archivo en reconstrucción". De otra forma, "desde la última posición escrita en el contenedor en el que se recuperan los bytes originales del archivo comprimido, desplázate hacia atrás unas posiciones y copia cierto número de bytes". Este desplazamiento tiene que ser mayor o igual a 1.1o Copia directamente el próximo byte: Esta instrucción dice que el próximo byte que se lea del archivo comprimido se coloque directamente en la última posición escrita del archivo en reconstrucción. Esta instrucción es la que naturalmente se dá cuando no hay ninguna repetición de bytes a la que se pueda hacer referencia hacia atrás.
Yaz0 almacena el identificador de estas instrucciones en paquetes de 8. En un byte se almacenan 8 instrucciones y el orden de ellas (de izquierda a derecha) especifica cómo se interpretan los siguientes bytes del archivo comprimido. A este byte lo denomino byte de instrucciones.
Paquete de 8 instrucciones, byte de instrucciones
Los datos que manejan las instrucciones 0 y 1 que vienen después de un byte de instrucciones se almacenan binariamente de la siguiente forma:
-
Instrucción
0-
Si el número de bytes a copiar o
nse encuentra entre0x3y0x11(inclusivo):- A
nse le resta0x2y se almacena en los 4 bits más significativos de un entero sin signo de 16 bits. - Al desplazamiento hacia atrás de los bytes a copiar o
seekbackse le resta 1 y se almacena en los 12 bits restantes del entero sin signo de 16 bits. - El entero sin signo de 16 bits se escribe en Big Endian en el archivo comprimido.
- La información de copiado queda almacenada en 2 bytes.
- A
-
Si el número de bytes a copiar o
nes mayor o igual a0x12:- A
seekbackse le resta 1 y se almacena en los 12 bits menos significativos de un entero sin signo de 16 bits. Los 4 bits más significativos quedan en 0. - El entero sin signo de 16 bits se escribe en Big Endian en el archivo comprimido.
- A
nse le resta0x12y se guarda en el siguiente byte del archivo comprimido, después del entero sin signo de 16 bits. - La información de copiado queda almacenada en 3 bytes.
- A
-
-
Instrucción
1El siguiente byte del archivo a comprimir se añade directamente al archivo comprimido.
Ejemplo visual simple de un byte de instrucciones y sus bytes siguientes
De aquí puede verse que seekback puede tener valores entre 0x1 y 0xFFF + 0x1, y, n puede tener valores entre 0x3 y 0xFF + 0x12 (IMPORTANTE!).
Estructura
La estructura del archivo descrita aquí es la estructura que se ha conseguido en los archivos originales de SMG. Esta información no significa que la estructura tenga que ser exactamente como se describe en la página.
Encabezado
| Nombre | Tamaño | Descripción |
|---|---|---|
| Magia | 4 bytes | La cadena ASCII Yaz0. |
| Tamaño del archivo sin comprimir | 4 bytes | Almacenado en Big Endian. Es importante saber que el proceso de descompresión se detiene solamente cuando el tamaño del archivo reconstruído es mayor o igual a este tamaño. |
| Relleno | 8 bytes | Compuesto por 0x00. |
Conjunto de tamaño no determinado de bytes de instrucciones
| Nombre | Tamaño | Descripción | ||||||
|---|---|---|---|---|---|---|---|---|
| Inicio: Arreglo de instrucciones de compresión (explicado arriba) | ||||||||
|
||||||||
| Final: Arreglo de instrucciones de compresión | ||||||||
| Relleno | No mayor a 32 bytes | Rellena con 0x00 hasta que el tamaño del archivo sea múltiplo de 0x20. |
||||||
Ejemplo
Estructura coloreada de ObjectData/CubeBubbleExPlanetA.arc
En la imagen se muestran los bytes de instrucción en rojo, los bytes directamente copiados en azul y los copiados de bytes en verde. El resto de las variables estan en otros colores.
Notas
-
Un archivo comprimido Yaz0 no tiene una forma sencilla de chequearse:
- Si el tamaño del archivo original es mayor de lo que debería entonces va a ocurrir un error al leer al archivo comprimido ya que no van a haber suficientes intrucciones. Se va a intentar leer más allá de los límites del archivo.
- Si un
seekbackleído se va más allá del inicio del archivo va a ocurrir un error de lectura.
Al descomprimir un archivo uno está confiando en que no existen esos errores.
-
2 implementaciones de Yaz0 que generan archivos comprimidos Yaz0 equivalentes a los que se consiguen en Super Mario Galaxy:
- No importa si el sistema es Big/Little Endian, la información siempre se guardará en Big Endian.
- La implementación original del algoritmo de compresión Yaz0 se mantuvo igual por muchos años. Desde Ocarina of Time (N64) hasta Super Mario Galaxy (Wii). En Super Mario Galaxy 3D All-Stars cambió a otro tipo de implementación (ver las implementaciones de Yaz0 arriba).