Voy a empezar a cobrarte. El formato es pseudo-sencillo... me explico: el juego tiene (sin contar ejecutables ni pollables) dos tipos de archivo: *.00x (donde x es un número, sería más correcto *.xxx) y *.vga (en Rise of the Dragon, en otros tiene otra extensión pero y debo mirarlo):
*.00x --- Contienen los archivos del juego.
*.vga --- Contiene la FAT de los archivos *.00x (una FAT es una tabla de localización de archivos, File Allocation Table).
El archivo *.vga contiene una salt (¿qué es la sal? Lo que le echas a la ensalada, subnor) que son 4 bytes que mediante un algoritmo y el nombre del archivo (el del archivo contenido en *.00x) da un valor entero (int32) único. Similar a un CRC aunque aquí lo llamamos hash (¡qué coño, fumémonos una L!). Como en principio no se van a tocar los nombres de los archivos, creo que no es necesario meternos en esto (aunque debería desarrollar una función porsiaca, ya veremos). Después de la salt, hay un valor de 2 bytes que indica el número de volúmenes que hay.
Después, por cada volumen, hay que hacer lo siguiente. Primero viene el nombre del volumen, con un tamaño de 12 caracteres (modelo DOS: 8 del nombre, 1 del punto, 3 de la extensión), un separador que es el byte 0x2e y luego dos bytes que indican el número de archivos. Entonces, en cada volumen y por cada archivo, hay 4 bytes que son el hash del archivo y 4 bytes que son el offset del mismo.
Bueno, pues lo que acabas de leer es solo la FAT, y la tengo ya programada.
El archivo *.00x contiene una serie de archivos. Cada archivo tiene una cabecera genérica que es el nombre del archivo con un tamaño de 12 caracteres (recuerda el modelo DOS: 8 del nombre, 1 del punto, 3 de la extensión), un separador que es un byte 0x6e y 4 bytes que indican el tamaño del archivo (sin contar estos bytes de la cabecera). Cada uno de estos archivos yo lo llamo CHUNK (porque KENDO ya estaba registrado no sé por quién) y cada uno de estos chunks es un tipo (imagen, texto, paleta, fuente, etc.). Eso habrá que mirarlo de forma individual.
Código fuente (WIP):
fat.cs
using System;
using System.Collections.Generic;
namespace Format
{
public class FAT
{
private byte[] salt;
private List<Volume> volume;
public List<Volume> Volume { get { return volume; } }
public int Count { get { return volume.Count; } }
public FAT(byte[] _salt) { reset(); salt = _salt; }
private void reset()
{
salt = new byte[]{};
volume = new List<Volume>();
}
public void addVolume(char[] _volName) { volume.Add(new Volume(_volName)); }
}
}
volume.cs
using System;
using System.Collections.Generic;
namespace Format
{
public class Volume
{
private char[] name;
private List<Chunk> chunk;
public List<Chunk> Chunk { get{ return chunk; } }
public int Count { get { return chunk.Count; } }
public Volume(char[] _name) { reset(); name = _name; }
private void reset()
{
name = new char[]{};
chunk = new List<Chunk>();
}
public void addChunk(int _hash, uint _offset) { chunk.Add(new Chunk(_hash, _offset)); }
}
}
chunk.cs
using System;
namespace Format
{
public class Chunk
{
private int hash;
private uint offset;
private char[] name;
private byte[] data;
public int Hash { get { return hash; } }
public uint Offset { get { return offset; } }
public Chunk(int _hash, uint _offset) { reset(); hash = _hash; offset = _offset; }
private void reset()
{
hash = 0;
offset = 0;
name = new char[]{};
data = new byte[]{};
}
public void addContent(char[] _name, byte[] _data) { name = _name; data = _data; }
}
}
unpack.cs
using System;
using System.IO;
using Format;
namespace Lib
{
public static class Unpack
{
public static FAT FAT(string _filename)
{
const byte FILENAME_MAX = 12;
FAT tmpFAT = null;
MemoryStream data = new MemoryStream(File.ReadAllBytes(_filename));
ushort nVolumes, nChunks;
using (BinaryReader reader = new BinaryReader(data))
{
tmpFAT = new FAT(reader.ReadBytes(4));
nVolumes = reader.ReadUInt16();
for (int lVolume = 0; lVolume < nVolumes; lVolume++)
{
tmpFAT.addVolume(reader.ReadChars(FILENAME_MAX));
reader.BaseStream.Position++;
nChunks = reader.ReadUInt16();
for (int lChunk = 0; lChunk < nChunks; lChunk++)
{
tmpFAT.Volume[lVolume].addChunk(reader.ReadInt32(), reader.ReadUInt32());
}
}
}
return tmpFAT;
}
}
}
¡Mejor fistros!
(http://4.bp.blogspot.com/-5lAbnkqnH3c/TYy_fnQryHI/AAAAAAAAAEA/kYd-umccP9w/s1600/fistros.jpg)