TVFS

From wowdev
Revision as of 19:16, 1 September 2023 by Marlamin (talk | contribs)
Jump to navigation Jump to search

TVFS (TACT Virtual File System) appeared back with the release of Warcraft III Reforged and has been used in various Call of Duty titles, Diablo 4 as well as World of Warcraft.

Its VFS manifests (from TACT's buildconfigs) are supposed to supplement or even replace the old root manifest format in some cases.

File manifest

TVFS file manifests are listed in buildconfig under vfs-* keys. Information about this format is based on CascLib's implementation.

Header

Header should always be at least 38/0x26 bytes. estTableOffset and estTableSize are optional and only set if flags & 2.

struct {
/*0x00*/  char magic[4];                // Always TVFS
/*0x04*/  char version;                 // Format version. Always 1.
/*0x05*/  char headerSize;              // Header size in bytes.
/*0x06*/  char eKeySize;                // EKey size in bytes. Should be 9.
/*0x07*/  char patchKeySize;            // PatchKey size in bytes. Should be 9.
/*0x08*/  uint32_BE_t flags;            // FileManifestFlags, see below.
/*0x0C*/  uint32_BE_t pathTableOffset;  // Offset to the path table.
/*0x10*/  uint32_BE_t pathTableSize;    // Size of the path table.
/*0x14*/  uint32_BE_t vfsTableOffset;   // Offset to the VFS table.
/*0x18*/  uint32_BE_t vfsTableSize;     // Size of the VFS table.
/*0x1C*/  uint32_BE_t cftTableOffset;   // Offset to the container file table.
/*0x20*/  uint32_BE_t cftTableSize;     // Size of the container file table.
/*0x24*/  uint16_BE_t maxDepth;         // The maximum depth of the path prefix tree stored in the path table,
/*0x26*/  uint32_BE_t estTableOffset;   // Offset to ESpec table. Only present if write support (flags & 2) is enabled.
/*0x2A*/  uint32_BE_t estTableSize;     // Size of ESpec table. Only present if write support (flags & 2) is enabled.
} FileManifestHeader;

FileManifestFlags

enum FileManifestFlags {
 INCLUDE_CKEY       =     0x1,  // Include C-key in content file record.
 WRITE_SUPPORT      =     0x2,  // Write support. Include a table of encoding specifiers. This is required for writing files to the underlying storage. This bit is implied by the patch-support bit.
 PATCH_SUPPORT      =     0x4,  // Patch support. Include patch records in the content file records.
 LOWERCASE_MANIFEST =     0x8,  // Lowercase manifest. All paths in the path table have been converted to ASCII lowercase (i.e. [A-Z] converted to [a-z]).
};

Path table

Starts with the root directory and recursively contains directories/files.

TODO structure

NodeFlags

enum NodeFlags {
 PATH_SEPARATOR_PRE  =     0x1,  // There is path separator before the name.
 PATH_SEPARATOR_POST =     0x2,  // There is path separator after the name.
 NODE_VALUE          =     0x4,  // The NodeValue in path table entry is valid.
};

Container file table

struct CftEntry
{
   int8_t PartialEKey [FileManifestHeader.eKeySize];
   int32_BE_t CompressedLength;
   int8_t EstOffset;
   int32_BE_t Length;
   int8_t CKey [16];
};

TODO

VFS table

struct VfsSpanEntry
{
   int32_BE_t ContentOffset;
   int32_BE_t ContentLength;
   int32_BE_t CftOffset;        // This is a int32_t field but the amount of bytes are determined by the CftOffsSize field calculated from the header.
                                // This is also offset to the CftEntry struct.
};

TODO

ESpec table

TODO