It has a 16 byte header.
First is an int, usually 6. Then it's another int for filesize (excluding the header) and then a 32bit checksum followed by 0s.
Following the header is a large chunk of signed ints; essentially all of the ints present in the CML file only without the tags or element IDs. Specifically all the data from the DOC, FIGR, COLR and SLCT tags. However unlike the CML format (and because there are no tags or IDs), the order of each element is fixed. So it is always FIGR[1,2,3..] then COLR[1,2,3..] then SLCT[1,2,3..] whereas I've seen CML files go FIGR[20,1,2] SLCT, SLCT, SLCT, SLCT, COLR...
Like the CML format, it isn't 100% understood. There are still some odd quirks I've seen the format do that I don't yet understand (such as a set of colour sliders that duplicates itself for some reason)
File Names
The filename is related to the character's sex and race.
The first letter is f or m, for female or male.
The second letter is h, n, c or d, for human, newman, cast and dewman respectively.
Replace the xx with these two letters and you get the complete filename (example, fdp for a female dewman).
Note that the file contains race and sex data, so just editing the filename won't be enough to make a race change.
Data Structure
This section details the locations of each part of the character, mapped from the cml in part. As such it may not be 100% accurate, but judging by the consistency of Parser results it seems to be.
Offsets are inclusive of the header.
Note that CML tags are included for labelling convenience, they're not present in the file.
- Code: Select all
DOC (ints)
10 - Race
14 - Sex
18 - Unknown
FIGR (3 ints each)
1C - Main Body
28 - Arm
34 - Leg
40 - Bust
4C - Unknown
58 - Face Shape
64 - Eye Shape
70 - Nose Height
7C - Nose Shape
88 - Mouth
94 - Ears
A0 - Neck
AC - Waist
B8 - Main Body2
C4 - Arm2
D0 - Leg2
DC - Bust2
E4 - Unknown
E8 - Neck2
F4 - Waist2
Note: Main Body2, Arm2 etc appear to be for having multiple proportions. This may be for allowing characters to have one set of proportion for cast parts and another for outfits.
COLR (3 ints each)
170 - Unknown - Changed to a copy of 184 on changing body part
178 - Costume Color
184 - Main Color
190 - Sub1
19C - Skin/Sub2
1A8 - Left Eye/Sub3
1B4 - Right Eye/Eyes
1C0 - Hair
1C8 - Unknown
SLCT (1 int each)
244 - costume/body
248 - bodypaint
24C - sticker
250 - Right Eye
254 - eyebrow
258 - eyelash
25C - facetype
260 - unknown
264 - Makeup1
268 - hairstyle
26C - acc1
270 - acc2
274 - acc3
278 - Makeup2
27C - Leg Part
280 - Arm Part
284* - acc4
288 - Basewear
28C - Innerwear
290 - bodypaint2
It's still missing a value for the 2nd hair colour because I have yet to actually see what this data looks like. I don't have any dual haircolour files to test this with.
Accessory Values
Unlike the CML files, xxP files contain a section near the end that holds accessory position data (for transform, rotation and scale). Like the rest of the data, it's slider data rather than actual transforms, but unlike the rest of the data it is not stored as a series of ints.
It's stored as a series of signed Nybbles (so it runs from -8 to 7). Play with one of the sliders, you'll see it moves in these fixed steps. The way it's stored is kind of all over the place. This is still being studied and honestly I'm not really sure of a good way to represent it. Here's an attempt anyway:
- Code: Select all
accessory adjustment: 2C4 - 2D5 (One Nybble per slider)
nybble in decimal offset relative to 2C4
Format nXy where n = accessory number, X is either P, R or S for position, rotation and scale, y is axis.
Still under construction.
1Px - 3
1Py - 0
1Pz - 1
1Rx - 15
1Ry - 12
1Rz - 13
1Sx - 27
1Sy - 24
1Sz - 25
2Px - 7
2Py - 4
2Pz - 5
2Rx - 19
2Ry - 16
2Rz - 17
2Sx - 29
2Sy - 26
2Sz - 27
3Px - 10
3Py - 18
3Pz - 14
3Rx -
3Ry -
3Rz -
3Sx -
3Sy -
3Sz -
4Px -
4Py -
4Pz -
4Rx -
4Ry -
4Rz -
4Sx -
4Sy -
4Sz -
End of file
At the end of the file is about 0x16 bytes of unknown stuff! Typically it's two numbers but it always seems to be 2 (short) and 1 (short) followed by nothing but 0s.