-
Notifications
You must be signed in to change notification settings - Fork 1
File format
Each model used in WOTB is made up of two files: SCG and SC2; SCG files only contain geometry like index buffers and model vertices (coordinates, UVs etc...) whilst SC2 files contain scene and hierarchy data that ties it all together. Both formats are based upon a custom data structures called "Keyed archives" which encodes a JSON-like structure with key/value pairs but in binary form.
Keyed archives are JSON-like binary structures that can hold key/value pairs. There are 2 version with 4 total variants:
Version | Description |
---|---|
1.0 | Oldest version, used in SCG and old SC2 versions |
2.0 | Keys are all encoded using the fastname system |
2.1 | This is only used for KAs that are children of version 2.0, relies on the fastname table of the root KA |
2.255 | This is always empty |
struct KA
{
char signature[2]; // "KA"
short version;
// version specific data
KA1Body body; // Only if version == 0x0001
KA2Body body; // Only if version == 0x0002
KA2_1Body body; // Only if version == 0x0102
KA2_255Body body; // Only if version == 0xff02
};
KA supports a wide range of data types:
enum KADatatype
{
NONE = 0,
BOOLEAN = 1,
INT32 = 2,
FLOAT = 3,
STRING = 4,
WIDE_STRING = 5,
BYTE_ARRAY = 6,
UINT32 = 7,
KEYED_ARCHIVE = 8,
INT64 = 9,
UINT64 = 10,
VECTOR2 = 11,
VECTOR3 = 12,
VECTOR4 = 13,
MATRIX2 = 14,
MATRIX3 = 15,
MATRIX4 = 16,
COLOR = 17,
FASTNAME = 18,
AABBOX3 = 19,
FILEPATH = 20,
FLOAT64 = 21,
INT8 = 22,
UINT8 = 23,
INT16 = 24,
UINT16 = 25,
ARRAY = 27,
TRANSFORM = 29,
};
Version 1 KA data, this is the simplest version.
struct KA1Body
{
int nodeCount;
struct {
char keyDatatype;
void* key;
char valueDatatype;
void* value;
} children[nodeCount]; // this encodes {key: value}
};
Version 2 KA data, uses the fastname
system for key names.
struct KA2Body
{
int fastnameCount;
struct {
short stringLength;
char string[stringLength];
} fastnames[fastnameCount];
int fastnameIDs[fastnameCount];
int nodeCount;
struct {
int keyID; // Corresponds to a value in fastnameIDs, the index of the ID in fastnameIDs is the index of the string inside fastnames
char valueDatatype;
void* value;
} children[nodeCount]; // this encode {key: value}
};
Version 2 KA data, this variant is always a child of a version 2.0 or 2.1 node.
struct KA2_1Body
{
int nodeCount;
struct {
int keyID; // Corresponds to a value in root node's fastnameIDs, the index of the ID in fastnameIDs is the index of the string inside fastnames
char valueDatatype;
void* value;
} children[nodeCount]; // this encode {key: value}
};
This variant is empty, contains no data.
Only stores geometry data.
struct SCG
{
char signature[4]; // "SCPG"
int version; // 1, at time of writing
int nodeCount;
int nodeCountCopy; // Should be identical to nodeCount
KA nodes[nodeCount]; // Keyed archives should be version 1
};
Stores scene data but can also store geometry data and is usually paired with a matching SCG file (unless the SC2 already contains its own geometry).
struct SC2
{
char signature[4]; // "SFV2"
int version;
int nodeCount;
KA versionTags;
int descriptorLength;
char descriptorBytes[length];
KA nodes[nodeCount]; // Should be version 2 KA
};