Here goes the brain dump of what I've found so far. At the moment I'm only interested in getting the prince character so I've not been looking to build a generic file exporter and have targeted particular data blocks to try and get skeleton, mesh and animations.
I’m looking at the Prince of Persia: The Two Thrones game at the moment.
I use the PersianRug tool from Turfster so I have to give a nod of thanks for that.
Here is the link for anyone that’s interested.
http://prince.turfster.be/
If you run PersianRug once it creates an entry in the windows registry. If you add a registry value called Debug to HKEY_CURRENT_USER\Software\Turfster\PersianRug then it unlocks an option to expand .bin files to their uncompressed format. Expanded files can be saved and end up with a .binexpanded extension. Very useful
It’s these expanded files I’ve been using to get the data from.
Here is a link to files that I’m looking at.
http://www.sendspace.com/file/1n0jxo
Each BIN file consists of a number of blocks. Each block has the following format:
struct BLOCK_HEADER
{
Uint32 dataSize; // number of bytes after block header that contain data
Uint32 blockTag; // always 99 CO FF EE
Uint32 blockID;
};
The data section of each block starts immediately after the header.
The last block has the ID 0x0FF7C0DE.
Skeleton
========
File: PrinceFinal_Shape_wow_ff051dec.binexpanded
Block ID: 0x51002324
numberOfBones = blockHeader.dataSize / 4;
boneIDs - numberOfBones * 4 bytes
- Bones
=====
Each block in the bones list has the following format:
Block data
“.gao” – 4 bytes
Unknown – 4 bytes
nameLength – uint32
name – nameLength bytes
unknown – 10 bytes
transform matrix – 16 floats [4 bytes per float]
unknown – 52 bytes
parentID – uint32 [blockID of parent bone]
Mesh Data
=========
File: PrinceFinal_Shape_wow_ff051dec.binexpanded
Block ID: 0x51002324
Unknown - 16 bytes
positionDataCount – uint32
unknown – 4 bytes [another count?]
unknown – 4 bytes
UVDataCount – uint32
primitiveCount – uint32
unknown – 4 bytes [float?]
unknown – 2 bytes
chunkCount – uint16 [not sure what these chunks are for]
For each chunk
blockID? – uint16
valuesCount – uint16
transform matrix? – 16 floats [not sure if this actually a matrix]
unknown – 4 bytes
For each value
value – float
End For
End For
Unknown – 4 bytes
For each position
position – 3 floats [x,y,z]
End For
For each normal [normalCount seems to be same as positionCount]
normal – 3 floats [x,y,z]
End For
For each uv
uv – 2 floats [u, v]
End For
For each primitive
numTriangles – uint32 [triangles per primitive]
primitiveID? – uint32
End For
triangleData – totalNumTriangles * 16 bytes [I think these are indices for position, normal, uvs]
unknown – 8 bytes
numIndexBuffers – uint32
For each indexBuffer
Unknown – 4 bytes
numTriangles – 4 bytes [triangles per index buffer]
End For
Unknown – 8 bytes
numVertices – uint32 [start of VertexBuffer]
vertexSize – uint32 [size in bytes of each vertex]
vertexData – numVertices*vertexSize
indexBufferSize – uint32 [size of index data in bytes] [start of IndexBuffer data]
For each IndexBuffer
indexData – numTriangles*3*uint16
End For
I used the the VertexBuffer and IndexBuffer to extract the mesh data.
Each vertex had the following structure:
Position – 3 floats
Normal – 3 floats
BoneIndices – 4 shorts [4 * 2 bytes]
BoneWeights – 3 floats
UV – 2 floats
I’m not sure how the bone indices and weights are used as some of the indices seem a lot higher that the number of bones in model.
Animation
=========
File: Dynamic_Actions_Drink_wow_ff0e0dc0.binexpanded
Block ID: 0x33000068
There are a number of keyframe chunks that make up this block. At the moment I just keep reading keyframe chunks and stop when the start of the next chunk doesn’t start with 0x03 0xFA.
Unknown – 76 bytes [There is probably data is here to indicate animation length and number of key frame blocks]
For each keyframe chunk
Start – 2 bytes [always 0x03 0xFA]
BoneID – 2bytes
Unknown – 4 bytes
keyCount – uint32
unknown – 3 bytes [seems to always be 0x01 0x80 0x00]
keyType – 1 byte
unknown – 2 bytes
FOR each key
IF keyType == 0x80 THEN
[translation data]
keyDuration – 1 byte
translation – 3*float [x,y,z]
END IF
IF keyType == 0x10 THEN
[rotation data]
keyDuration – 1 byte
rotation – 4 bytes [no idea how this breaks down]
END IF
End For
End For
ACCURACY DISCLAIMER
: I don’t think I’ve missed anything in my description of the data, but there is always the chance. If you do find I’ve said something that doesn’t match up, please let me know.