XIV Docs

Formats

ZiPatch (.patch)

Note

This documentation is incomplete.

Contains various deltas to be applied on top of existing game or boot data.

I recommend reading the “ZiPatch” section on xiv.dev.

Alternative Implementations #


Texture (.tex)

Note

This documentation is incomplete.

Visual texture.

Alternative Implementations #


Skeleton (.sklb)

A Havok skeleton, used for all of the animated characters and objects in the game. FFXIV uses the Havok SDK to do most of the heavy lifting for animation, so there’s not much here.

Reading #

The first few bytes are the magic, which should be a int32_t that equals 0x736B6C62. Then, there is a uint32_t that describes which version the skeleton is.

This is used if version is 0x3132_3030:

struct SklbV1 {
    uint16_t unk_offset;
    uint16_t havok_offset;
    uint32_t body_id;
    uint32_t mapper_body_id1;
    uint32_t mapper_body_id2;
    uint32_t mapper_body_id3;
};

This is used if the version is 0x3133_3030 or 0x3133_3031:

struct SklbV2 {
    uint32_t unk_offset;
    uint32_t havok_offset;
    uint32_t _unknown;
    uint32_t body_id;
    uint32_t mapper_body_id1;
    uint32_t mapper_body_id2;
    uint32_t mapper_body_id3;
};

The rest of the file is the Havok binary tagfile format which you will probably need the Havok SDK or another method to read. The data starts at SklbV1::havok_offset or SklbV2::havok_offset and is contiguous until the end of the file.

Alternative Implementations #

None yet.


Shader Package (.shpk)

Note

This documentation is incomplete, nodes and keys are not documented yet.

A collection of vertex and pixel shaders. For example, “character.shpk” which contains shaders used for gear.

Reading #

At the beginning of the binary file is a simple header which describes what DirectX version the shader package is for, and the sizes of various structures.

struct ShaderPackageHeader {
    // Should be "ShPk" (capitalization intentional)
    uint8_t magic[4];

    // Reads "DX9\0" (\0 being a null byte) for DX9 shaders, and "DX11" for DX11 shaders
    uint8_t format[4];

    uint32_t fileLength;
    uint32_t shaderDataOffset;
    uint32_t stringsOffset;
    uint32_t vertexShaderCount;
    uint32_t pixelShaderCount;
    uint32_t materialParametersSize;
    uint32_t materialParameterCount;
    uint32_t scalarParameterCount;
    uint32_t resourceParameterCount;
    uint32_t uavParameterCount;
    uint32_t systemKeyCount;
    uint32_t sceneKeyCount;
    uint32_t materialKeyCount;
    uint32_t nodeCount;
    uint32_t nodeAliasCount;
};

Right after the header is the beginning of shader data. The process is identical between vertex and pixel shaders, and they’re read in that order (the vertex shaders are all read first, and then the pixel shaders.)

struct Shader {
    uint32_t dataOffset;
    uint32_t dataSize;

    uint16_t scalarParameterCount;
    uint16_t resourceParameterCount;
    uint16_t uavParameterCount;

    uint16_t _unknown;

    ResourceParameter scalarParameters[scalarParameterCount];
    ResourceParameter resourceParameters[resourceParameterCount];
    ResourceParameter uavParameters[uavParameterCount];
};

Resource parameters are defined like so:

struct ResourceParameter {
    uint32_t id;
    uint32_t localStringOffset;
    uint32_t stringLength;
    uint16_t slot;
    uint16_t size;
};

The shaders are stored as DXBC bytecode (the bytecode used by DirectX before DXIL.) targetted to the shader level of their respective API as described in format above. The data blob starts at ShaderPackageHeader::shaderDataOffset + Shader::dataOffset to a length of dataSize bytes. To access the ResourceParameter name, they start at ShaderPackageHeader::stringsOffset + ResourceParameter::localStringOffset to a length of stringLength bytes.

Alternative Implementations #


Model (.mdl)

Note

This documentation is incomplete.

Represents a visual model in the game, from furniture to the world, and characters.

Reading #

First read the model header, which contains some information like the data offsets:

struct ModelFileHeader {
    uint32_t version;
    uint32_t stackSize;
    uint32_t runtimeSize;

    uint16_t vertexDeclarationCount;
    uint16_t materialCount;

    uint32_t vertexOffsets[3];
    uint32_t indexOffsets[3];
    uint32_t vertexBufferSize[3];
    uint32_t indexBufferSize[3];

    uint8_t lodCount;

    uint8_t indexBufferStreamingEnabled;
    uint8_t hasEdgeGeometry;

    uint8_t _unknown1;
};

Immediately after this header begins the vertex declarations which describe how vertex data is sequenced and eventually read. These structures define the basis of the vertex declarations:

enum VertexType : uint8_t {
    Invalid = 0,
    Single3 = 2,
    Single4 = 3,
    UInt = 5,
    ByteFloat4 = 8,
    Half2 = 13,
    Half4 = 14,
};

enum VertexUsage : uint8_t {
    Position = 0,
    BlendWeights = 1,
    BlendIndices = 2,
    Normal = 3,
    UV = 4,
    Tangent = 5,
    BiTangent = 6,
    Color = 7,
};

struct VertexElement {
    uint8_t stream;
    uint8_t offset;
    VertexType vertexType;
    VertexUsage vertexUsage;
    uint8_t usageIndex;

    uint8_t unknown[3];
};

For every vertex declaration (the count in vertexDeclarationCount) first read a single VertexElement. Then keep reading a VertexElement (and keeping these in a buffer) until VertexElement::stream is 0xFF (or 255 in decimal.) This implies an “end of stream” and that’s the end of that declaration. Before reading the next declaration you need to advance your cursor 17 + 8 - (elements + 1) * 8 where elements is the amount of valid VertexElements you just read.

Alternative Implementations #


Material (.mtrl)

Note

This documentation is incomplete.

A visual material.

Alternative Implementations #


Game Data Index (.index/.index2)

Note

This documentation is incomplete.

Index files for compressed game data.

I recommend reading the “Reading Index Data” section on xiv.dev’s SqPack docs.

Alternative Implementations #


Game Data (.dat)

Note

This documentation is incomplete.

Compressed game data.

I recommend reading the “SqPack” page on xiv.dev.

Alternative Implementations #


File Info (.fiin)

I don’t know the actual purpose of this file, it seems to contain SHA1 of certain files. The filename is usually fileinfo.fiin (like in /boot) and start with a header like this:

struct FileInfoHeader {
    char magic[9];
    uint8_t dummy1[16];
    uint8_t unknown; // version? always seems to be 4
    uint8_t dummy2[2];
    uint8_t unknown1;
    uint8_t unknown2;
    uint8_t dummy[994];
};

The content of magic is always FileInfo.

To get the number of entries, calculate it like so:

int overflow = info.header.unknown2;
int extra = overflow * 256;
int first = info.header.unknown1 / 96;
int first2 = extra / 96;
int actualEntries = first + first2 + 1;

(Note: I have no idea if this is actually necessary, and it could just be a unsigned int or something)

Then each entry is located right after the header, and is structured as so:

struct FileInfoEntry {
    uint8_t dummy[8]; // length of file name in some format
    char str[64]; // simple \0 encoded string
    uint8_t dummy2[24]; // sha1
};

This file appears to have SHA1 hashes, but for what purpose I do not know.

Alternative Implementations #


Excel List (.exl)

Note

‘Excel’ here has nothing to do with Microsoft’s Excel.

I recommend reading the “Excel List” section on xiv.dev’s Excel docs.

Describes Excel sheets that exist in the game data. A good example is is exd/rool.exl which contains many references to the game data. It’s a text file containing a list of comma-separated strings, where each line is separated by a newline:

EXLT,2
Achievement,209
Action,4
content/DeepDungeon2Achievement,-1
content/DeepDungeon2Gacha,-1

With an Excel List parsed, you can then build a path to a Excel header or .exh. To do so, simply move all characters to lowercase and append .exh at the end:

Achievement,209 -> exh/achievement.exh

Alternative Implementations #


Excel Header (.exh)

Note

‘Excel’ here has nothing to do with Microsoft’s Excel.

Note

This documentation is incomplete.

I recommend reading the “Excel Header” section on xiv.dev’s Excel docs.

This is a schema file describing the column and row layout of an Excel sheet (such as Achievement). You are required to parse this before reading .exd files, as it contains important information on building a path and reading columns.

Alternative Implementations #


Excel Data (.exd)

Note

‘Excel’ here has nothing to do with Microsoft’s Excel.

Note

This documentation is incomplete.

The data file for an Excel sheet.

I recommend reading the “Excel Data” section on xiv.dev’s Excel docs.

Alternative Implementations #


Configuration File (.cfg)

A plaintext configuration file.

Structure #

The file is plaintext, which is easy to parse. The file is split into categories, which are surrounded by < and >. Within those categories are key-value pairs which are separated by tab characters (\t).

<FINAL FANTASY XIV Boot Config File>

<Version>
Version	3
Language	1
Region	2

Keep in mind that categories can exist without any key-value pairs, as shown above.

Alternative Implementations #


Chat Log (.log)

Note

This documentation is incomplete.

A binary store of recent chat logs. These are usually found in the character folder, e.g. “FFXIV_CHR/log/00000000.log”

Reading #

At the beginning of the file is a header with this content:

struct ChatLogHeader {
    uint32_t contentSize;
    uint32_t fileSize;

    uint32_t offsets[fileSize - contentSize];
};

The content of the log begins at (8 + fileSize * 4). The number of elements in offsets is also the number of messages in this log.

To read the messages, start reading at the offset described above. After seeking, read this short header:

enum EventFilter : uint8_t {
    SystemMessages = 3,
    Unknown = 20,
    ProgressionMessage = 64,
    NPCBattle = 41,
    Unknown2 = 57,
    Unknown7 = 29,
    Unknown3 = 59,
    EnemyBattle = 170,
}

enum EventChannel : uint8_t {
    System = 0,
    ServerAnnouncement = 3,
    Unknown1 = 50,
    Unknown7 = 29,
    Others = 32,
    Unknown5 = 41,
    NPCEnemy = 51,
    NPCFriendly = 59,
    Unknown4 = 64,
    Unknown6 = 170,
}

struct ChatLogEntry {
    uint32_t timestamp;
    EventFilter filter;
    EventChannel channel;
    uint32_t _garbage;
};

Then the string is ASCII(?) from the end of header to the element in offsets. The loop might look something like this:

uint32_t contentOffset = (8 + fileSize * 4);
seek(contentOffset);
for (uint32_t offset : offsets) {
    readChatLogEntry();
    message = read(cursorPos + offset);
    seek(contentOffset + offset); // ensure we always end up at the right place.
}

Alternative Implementations #


Character Creation Data (.dat)

Note

This documentation is incomplete.

This contains the data you can save and load from the character creator, used not only in the retail client but the benchmark versions too.

Reading #

The structure is very simple, it’s only a series of fields.

Version 4 #

struct CharacterData {
    // The version of the character data, the only supported version right now is 4.
    uint32_t version: u32,

    // The checksum of the data fields.
    uint32_t checksum: u32,

    uint32_t _unknown1;

    // The race of the character.
    uint8_t race: Race,

    // The gender of the character.
    uint8_t gender: Gender,

    // The age of the character. Normal = 1, Old = 3, Young = 4.
    uint8_t age: u8,

    // The height of the character.
    uint8_t height: u8,

    // The character's subrace.
    uint8_t subrace: Subrace,

    // The character's selected head.
    uint8_t head: u8,

    // The character's selected hair.
    uint8_t hair: u8,

    // If hair highlights are enabled for this character.
    uint8_t enable_highlights,

    // The character's skin tone.
    uint8_t skin_tone: u8,

    // The character's right eye color.
    uint8_t right_eye_color: u8,

    // The character's hair color.
    uint8_t hair_tone: u8,

    // The color of the hair highlights.
    uint8_t highlights: u8,

    // The selected facial features.
    uint8_t facial_features: u8,

    // If the character has limbal eyes.
    uint8_t limbal_eyes: u8,

    // The character's selected eyebrows.
    uint8_t eyebrows: u8,

    // The character's left eye color.
    uint8_t left_eye_color: u8,

    // The character's selected eyes.
    uint8_t eyes: u8,

    // The character's selected nose.
    uint8_t nose: u8,

    // The character's selected jaw.
    uint8_t jaw: u8,

    // The character's selected mouth.
    uint8_t mouth: u8,

    // The character's selected pattern.
    uint8_t lips_tone_fur_pattern: u8,

    // The character's selected tail.
    uint8_t tail: u8,

    // The character's choice of face paint.
    uint8_t face_paint: u8,

    // The size of the character's bust.
    uint8_t bust: u8,

    // The color of the face paint.
    uint8_t face_paint_color: u8,

    // The character's chosen voice.
    uint8_t voice: u8,

    uint8_t _garbage;

    // The timestamp when the preset was created.
    uint8_t timestamp[4];
};

Alternative Implementations #


Chara Make Parameters (.cmp)

Note

This documentation is incomplete.

Describes various character parameters such as minimum and maximum height.

Alternative Implementations #