-
Notifications
You must be signed in to change notification settings - Fork 1
BigFile
The .DXX and .NXX file pairs form a BigFile, a type of archive. The archive format is incredibly simple. .DXX files contain the actual file contents, while .NXX files contain the file names.
The actual file extensions depend on the platform. This is not an exhaustive list for all platforms in which TotemTech (and its later adaptations), but here are some common extensions by platform:
Platform | DXX | NXX |
---|---|---|
Gamecube | .DGC | .NGC |
Playstation 2 | .DPS | .NPS |
PC | .DPC | .NPC |
This file is very simple, and only contains pairs of integers and strings in plain text. Each line in this file contains a signed integer ID and a string ID. Here is an example:
-513692128 "DB:>LEVELS>LVL_DGBA>CHM_NORM>GL_CAUTION01_017.T3DNODE"
840709501 "CYLINDER01"
0 ""
The integer IDs are not random; they are a CRC32 IEEE hash of the string. The hash of the empty string is always 0. The NGC file just pairs strings with their hash.
The DGC file contains the actual data for each file in the archive. The data is broken up into multiple, equal-sized chunks.
The entire header is 2048 bytes, the majority of which is zero-padded. The entire header can be described by the following structure:
struct BigFileHeader {
char legal[256]; // Legal information
uint32_t chunk_size; // Size of each chunk
char padding[1788]; // padding
};
The legal information for Rotfd and Jimmy are always the following string, followed by padding:
TotemTech Data v1.73 (c) 1999-2002 Kalisto Entertainment - All right reserved
The chunk size describes the size of each chunk in bytes. The chunk size is always a multiple of 2048 bytes.
Every chunk is equally sized. The size of each chunk is equivalent to the chunk size as defined in the header.
struct BigFileChunk {
uint32_t num_files; // Number of files in this chunk
char data[chunk_size-4]; // The files contained within the chunk.
};
num_files
specifies how many files are contained within this chunk. data
is the data contained within the chunk. TotemFile structures are stored within this data sequentially. Any excess data at the end of the chunk is zero-padded.
Each file in the bigfile describes a single file's data.
struct BigFileFile {
int32_t file_size; // The size of the file
int32_t type_id; // the type ID
int32_t name_id; // the name ID
int32_t subtype_id; // the subtype ID
char data[file_size - 16]; // The data
};
The file_size
defines the size of the entire structure, not just its data. So, to get the size of the data in bytes, you must subtract 16 bytes for the file's header.
The type_id
, name_id
, and subtype_id
are IDs that correspond to an ID in the NGC file, so they reference a string id by matching the integer ID in the BigFile to the integer ID in the NGC file.
The name_id
is the name of the file. It is supposed to be unique, it is unknown what happens if two files share the same name ID (if anything). Generally, this is some kind of file name, e.g. "DB:>LEVELS>LVL_DGBA>TEXTURELIB>WORLD>WORLD_039.TBITMAP". Note that directories are separated by >
, rather than /
or \
which are used by standard filesystems.
The type_id
represents the type of the file. Examples include "MATERIALANIM", "WORLD", "NODE".
The subtype_id
represents the subtype of the file. In some cases, this is equivalent to the name_id
. The reason for this is unknown.
The data
contained within the file is just the file's data. This is what will be read when a program requests a file's data.
The overall structure of a DGC file can be described as such:
BigFileHeader header;
BigFileChunk chunks[];
BigFileFile file1;
BigFileFile file2;
...