So, meesbaker and I schemed about this for a little while. I verified via Akari's source how to pull palettes:
int offset_to_clut = GetU32LE( 0xc ) + face_id * 32;
So, looking at a decompressed copy of FIELD.TDB, if I grab the 32-bit little-endian value at 0xC (0x0000FE10), and add (face_id * 32), I'll get 0x0000FE10 (Cloud's face id is zero, and zero times 32 equals zero). That means Cloud's CLUT data should be at 0x0000FE10.
Doing the same for Cid, if his ID is 05, would yield 0x0000FE10 + (5d * 32d = 160d = 0xA0) = 0x0000FEB0.
...but his source confuses me when it comes to actual face image data:
for( int i = 1; i < face_row[ face_id ].size(); ++i )
int offset_to_image = GetU32LE( 0x8 ) + face_row[ face_id ][ i ] * 512;
So, we started looking at actual offsets for face image data, and the offset we expected via 0x10 + (face_id * 0x200). For example:
Cloud face id is 0x0 or 0d
offset 0x0010
should be 0x10
difference is 0.
Tifa's face id is 0x03 or 3d
offset 0x3010
should be 0x610
difference is 2A00
cid 0x5 or 5d
offset 0x5010
should be 0xA10
difference 4600
Zack 0x9 or 9d
offset 0x9010
should be 0x1210
difference 7e00
sephiroth's face 0x15 or 21d
offset - 0xCC10
should be 0x2a10
difference is a200
difference between a200 and 7e00 is 2400.
2400 divided by 200(512d) equals 12.
12 is the number of models between Seph (21d) and Zack (9d).
So, every model increase, the difference between the supposed offset and the real offset increases by 0x200 (512d).
But, it turned out this didn't hold up for models before Zach.
A few more attempts at figuring out what was going on yielded this:
The first 10 models (0x0 - 0x9) are at offsets of 0x1000 bytes each. To get any of those, simply multiply 0x1000 * face_id, and add 0x10 for the header at the beginning. Cid is face_id 5, so 0x1000 * 0x5 = 0x5000, + 0x10 = 0x5010.
But after model 0x9, each model is only 0x400 bytes after the last. To get any of these, simply multiply 0x400 * (face_id - 0xA), and add 0xA010. Sephiroth is face_id 0x15, so (0x400 * (0x15 - 0xA = 0xB) = 0x2C00, + 0xA010 = 0xCC10.
It should be noted that we're still not clear exactly what data is in between.
What's interesting about this is that the first 10 models are all main characters, who have BCX files, etc...except Zach. This seems to imply that when they were making FIELD.TDB, they still considered Zach to be a main character.
meesbaker: I'm pretty tired, so let me know if I've missed anything.