2
Fork 0
Code Activity
Var Dump:
dumpVar: only available in dev mode
Mailing List

Add existing templates

This commit is contained in:
Lucas Schwiderski 2024-10-30 13:40:15 +01:00
parent e7385aa3b0
commit 6175784bfa
Signed by: lucas
GPG key ID: AA12679AAA6DF4D8
24 changed files with 1845 additions and 0 deletions

1
.gitignore vendored Normal file
View file

@ -0,0 +1 @@
Repository/

54
dt_bundle.bt Normal file
View file

@ -0,0 +1,54 @@
//------------------------------------------------
//--- 010 Editor v12.0.1 Binary Template
//
// File:
// Authors:
// Version:
// Purpose:
// Category:
// File Mask:
// ID Bytes:
// History:
//------------------------------------------------
typedef struct {
uint64 extension <format=hex>;
uint64 name <format=hex>;
uint32 flags <format=binary>;
} FileMeta;
uint32 format <format=hex>;
uint32 unknown_1 <format=hex>;
Assert(unknown_1 == 3);
uint32 num_entries;
uint64 properties[32] <format=hex>;
FileMeta file_meta[num_entries];
uint32 num_chunks;
uint32 chunk_sizes[num_chunks];
local int padding_size = 16 - (FTell() % 16);
if (padding_size < 16) {
byte padding[padding_size];
}
uint32 unpacked_size;
uint32 unknown_3;
local int chunk_index;
for (chunk_index = 0; chunk_index < num_chunks; chunk_index++) {
struct Chunk {
uint32 size <bgcolor=0x0015FF>;
local int padding_size = 16 - (FTell() % 16);
if (padding_size < 16) {
byte padding[padding_size];
}
byte data[chunk_sizes[chunk_index]] <bgcolor=0xFF1500>;
};
Chunk chunks;
}

84
dt_bundle_database.bt Normal file
View file

@ -0,0 +1,84 @@
//------------------------------------------------
//--- 010 Editor v12.0.1 Binary Template
//
// File: dt_bundle_database.dt
// Authors:
// Version:
// Purpose:
// Category: Darktide
// File Mask: bundle_database.data
// ID Bytes:
// History:
//------------------------------------------------
uint32 format <format=hex>;
uint32 num_entries;
typedef struct {
uint32 version;
Assert(version == 0x4);
uint32 len_name;
char name[len_name];
uint32 len_stream;
char stream[len_stream];
byte platform_specific; // boolean
// byte buffer[20] <bgcolor=0x3399ff>;
byte buffer[20];
local int is_0 = true;
local int i = 0;
for (i = 0; i < 15; i++) {
if (buffer[i] != 0) {
is_0 = false;
}
}
if (!is_0) {
Warning("Unknown 20-byte buffer is not 0");
}
uint64 file_time; // win32 FILETIME
} File;
typedef struct {
uint64 hash <format=hex>;
uint32 num_files;
File files[num_files] <optimize=false>;
} Entry;
Entry entries[num_entries] <optimize=false>;
uint32 num_hashes;
typedef struct {
uint64 bundle <format=hex>;
uint64 resource_hash <format=hex>;
} ResourceHash;
ResourceHash hashes[num_hashes];
if (format <= 5) {
return;
}
uint32 num_contents;
typedef struct {
uint64 extension <format=hex>;
uint64 name <format=hex>;
} Filename;
typedef struct {
uint64 hash <format=hex>;
uint32 num_files;
Filename files[num_files];
} BundleContents;
BundleContents contents[num_contents] <optimize=false>;

85
dt_bundle_decompressed.bt Normal file
View file

@ -0,0 +1,85 @@
//------------------------------------------------
//--- 010 Editor v12.0.1 Binary Template
//
// File: dt_bundle_decompressed.bt
// Authors: Lucas Schwiderski
// Version:
// Purpose:
// Category: Darktide
// File Mask:
// ID Bytes:
// History:
//------------------------------------------------
typedef struct {
uint64 extension <format=hex>;
uint64 name <format=hex>;
uint32 flags <format=binary>;
} FileMeta;
typedef struct {
uint32 lang <format=binary>;
byte is_data_file <comment="If 1, data chunk will be a file name in data/">;
uint32 size;
byte unknown_2;
// If > 0, data chunk will be followed by a string of that length, which is an auxiliary/extension file
// to the data in the data chunk.
// Example: `.wwise_stream` only contains 12 bytes of data in the bundle, which includes an offset and a length.
// The extra file then contains the actual data.
uint32 len_data_file_name;
if (is_data_file == 1) {
if (size > 40) {
Warning("is_data_file == true, but size is too big for a simple file name: size = %d", size);
}
if (len_data_file_name > 0) {
Warning("is_data_file == true, but we also got len_data_file_name > 0");
}
}
if (unknown_2 != 1) {
Assert("Expected '1' for 'unknown_2', got '%x'", unknown_2);
}
} FileHeader;
typedef struct {
uint64 extension <format=hex>;
uint64 name <format=hex>;
uint32 header_count;
uint32 unknown_1;
FileHeader headers[header_count];
local int i = 0;
for (i = 0; i < header_count; i++) {
if (headers[i].is_data_file) {
char data_file[headers[i].size];
} else {
byte data[headers[i].size];
char data_file[headers[i].len_data_file_name];
}
}
} File;
uint32 version <format=hex>;
uint32 unknown_1;
Assert(unknown_1 == 3);
uint32 num_entries;
uint64 properties[32] <format=hex>;
FileMeta file_meta[num_entries];
uint32 num_chunks;
uint32 chunk_sizes[num_chunks];
local int padding_size = 16 - (FTell() % 16);
if (padding_size < 16) {
byte padding[padding_size];
}
uint32 unpacked_size <bgcolor=0x0015FF>;
uint32 unknown_3;
File files[num_entries] <optimize=false>;

21
dt_chunk.bt Normal file
View file

@ -0,0 +1,21 @@
//------------------------------------------------
//--- 010 Editor v12.0.1 Binary Template
//
// File: dt_chunk.dt
// Authors:
// Version:
// Purpose:
// Category:
// File Mask:
// ID Bytes:
// History:
//------------------------------------------------
uint64 extension_hash <format=hex>;
uint64 name_hash <format=hex>;
// Probably a count, could be the number of file
uint32 unknown_3;
// Until eof?
// Probably not, because many bundles, even when uncompressed, end with the same/similar trailer
byte data;

68
dt_dds_image.bt Executable file
View file

@ -0,0 +1,68 @@
//------------------------------------------------
//--- 010 Editor v12.0.1 Binary Template
//
// File:
// Authors:
// Version:
// Purpose:
// Category:
// File Mask:
// ID Bytes:
// History:
//------------------------------------------------
// ========
// Typedefs
// ========
typedef struct {
unsigned int dxgiFormat;
unsigned int resourceDimension;
unsigned int miscFlag;
unsigned int arraySize;
unsigned int miscFlags2;
} stingray::image::DDSImage::DDS_DX10_HEADER;
typedef struct {
unsigned int dwSize;
unsigned int dwFlags;
unsigned int dwFourCC;
unsigned int dwRGBBitCount;
unsigned int dwRBitMask;
unsigned int dwGBitMask;
unsigned int dwBBitMask;
unsigned int dwABitMask;
} stingray::image::DDSImage::DDS_PIXELFORMAT;
typedef struct
{
unsigned int dwSize;
unsigned int dwHeaderFlags;
unsigned int dwHeight;
unsigned int dwWidth;
unsigned int dwPitchOrLinearSize;
unsigned int dwDepth;
unsigned int dwMipMapCount;
unsigned int dwReserved1[11];
stingray::image::DDSImage::DDS_PIXELFORMAT ddspf;
unsigned int dwCaps;
unsigned int dwCaps2;
unsigned int dwReserved2[3];
} stingray::image::DDSImage::DDS_HEADER;
// =========
// Structure
// =========
uint32 skip_1;
stingray::image::DDSImage::DDS_HEADER header;
if (header.ddspf.dwFourCC == 0x30315844) {
stingray::image::DDSImage::DDS_DX10_HEADER dx10_header;
}
// TODO: Lots of calculations and value checking is done in the code
// before it's determined how to read the next section.
// Though it does look like there are only two ways that it does end up proceeding.
// In the first case, `header.dwDepth` plays a role

22
dt_package.bt Normal file
View file

@ -0,0 +1,22 @@
//------------------------------------------------
//--- 010 Editor v12.0.1 Binary Template
//
// File:
// Authors:
// Version:
// Purpose:
// Category:
// File Mask:
// ID Bytes:
// History:
//------------------------------------------------
uint32 version;
uint32 num_entries;
typedef struct Entry {
uint64 type <format=hex>;
uint64 name <format=hex>;
};
Entry entries[num_entries];

22
dt_strings.bt Normal file
View file

@ -0,0 +1,22 @@
//------------------------------------------------
//--- 010 Editor v12.0.1 Binary Template
//
// File: dt_strings.bt
// Authors: Lucas Schwiderski
// Version: 1.0
// Purpose: Darktide Strings
// Category: Darktide
// File Mask: *.strings
// ID Bytes:
// History:
//------------------------------------------------
uint32 header <hidden=true>;
uint32 count;
typedef struct {
uint32 name_hash <format=hex>;
uint32 address <format=hex>;
} Entry;
Entry entries[count];

19
dt_texture.bt Normal file
View file

@ -0,0 +1,19 @@
//------------------------------------------------
//--- 010 Editor v12.0.1 Binary Template
//
// File:
// Authors:
// Version:
// Purpose:
// Category:
// File Mask:
// ID Bytes:
// History:
//------------------------------------------------
uint32 type;
uint32 compressed_size;
uint32 decompressed_size;
byte data[compressed_size];

95
dt_texture_compressed.bt Normal file
View file

@ -0,0 +1,95 @@
//------------------------------------------------
//--- 010 Editor v12.0.1 Binary Template
//
// File: dt_texture_compressed.dt
// Authors: Lucas Schwiderski
// Version:
// Purpose:
// Category: Darktide
// File Mask:
// ID Bytes:
// History:
//------------------------------------------------
// The game does ship with two decompression options, but it I've only seen Oodle in the game files
// so far.
// I'd guess `0` is uncompressed, which would only happen in the dev releases, and likely be stripped by `#if`s.
// The compression method does not affect the rest of the data structure
typedef enum {
Oodle = 1,
Custom = 2,
} CompressionType;
CompressionType compression_type;
uint32 compressed_size;
uint32 uncompressed_size;
byte compressed_buffer[compressed_size] <format=hex, bgcolor=0x888545>;
// Skipped by the decompiled binary's code.
// Doesn't fit to be a length of a later data section. It doesn't match anything, and it's an uneven number.
uint32 unknown_1 <comment="Always 67 (0x43), so maybe a format/type specifier.">;
Assert(unknown_1 == 0x43);
typedef struct {
uint32 offset;
uint32 size;
} MipInfo;
typedef struct {
// Checked bits:
// >> 1: Some extra calculations are done with the next three fields around mipmaps
// Also determines if `unknown_2` is saved into `TextureImage`
// => Presumable means "has mipmaps" or VT2's "is streamable"
// >> 2: So far, I haven't found a line of code that actually uses this bit.
// But there is a line that assigns `flags & 3`, indicating that this bit
// does get used somewhere else.
// >> 8: TextureFormat.srgb, probably.
uint32 flags <format=binary, comment="Some bitflags.">;
// Does not match with the number of pairs in `mip_infos`.
uint32 n_streamable_mips;
uint32 width;
uint32 height;
// Offset and size of mip maps stored in the `.stream` file
// Though it seems that they don't align with mipmaps properly.
// The first size sometimes doesn't include enough data for a full texture
// and it would end up with a black section.
MipInfo mip_infos[16] <bgcolor=0x9b86d3, fgcolor=0xb2dbeb>;
uint32 meta_size;
} TextureHeader;
TextureHeader texture_header;
// If there is an associated `.stream` file, its content is compressed with Oodle,
// and the numbers in `chunks` below specify the size of each chunk.
// I.e. the `comp_buf_size`, while the `raw_buf_size` is always `0x1000`.
if (texture_header.meta_size > 0) {
uint32 num_chunks;
Assert((num_chunks * 4) + 8 == texture_header.meta_size);
uint16 unknown_6 <hidden=true>;
Assert(unknown_6 == 0);
// Always the same as `num_chunks`, but it's weird that this is a u16.
// So probably a different meaning that just happens to be the same value in most/all cases.
uint16 num_chunks_2 <hidden=true>;
Assert(num_chunks == num_chunks_2);
uint32 chunks[num_chunks];
}
// A key to look up a value in the engine's internal render quality settings.
// Specifically, a value that VT2 calls `mip_drop`.
// See `user_settings.conf` -> `texture_settings`
uint32 category <format=hex, comment="An IdString32">;
// Shortcuts to get to compile this:
// - `flags = 0` -> skips most of the mipmap stuff in the bundle file
// - `width = 0`, `height = 0` -> also skips some of the mipmap stuff
// - `n_streamable_mipmaps = 0` -> seems to be an intended value to only rely on DDS mipmaps
// It does force `srgb` on through setting a special value for `flags`, though. So if that produces issues, I might
// need to fake it s

33
dt_wwise_bank.bt Normal file
View file

@ -0,0 +1,33 @@
//------------------------------------------------
//--- 010 Editor v12.0.1 Binary Template
//
// File: dt_wwise_bank.bt
// Authors: Lucas Schwiderski
// Version:
// Purpose:
// Category: Darktide
// File Mask: *.wwise_bank
// ID Bytes:
// History:
//------------------------------------------------
uint32 version <format=hex>;
Assert(version == 0x1b);
uint32 length;
// A section of values that don't belong the actual Wwise bank
struct {
uint32 unknown1;
Assert(unknown1 == 0x0);
// Matches the file itself
uint64 this_file <format=hex>;
uint32 unknown2;
Assert(unknown2 == 0x20);
uint32 unknown3;
Assert(unknown3 == 0x0);
} header;
struct bnk
{
#include "bnk.bt";
} wwise_bank <open=true>;

68
dt_wwise_event.bt Normal file
View file

@ -0,0 +1,68 @@
//------------------------------------------------
//--- 010 Editor v12.0.1 Binary Template
//
// File: dt_wwise_event.bt
// Authors: Lucas Schwiderski
// Version:
// Purpose:
// Category: Darktide
// File Mask: *.wwise_event
// ID Bytes:
// History:
//------------------------------------------------
/***********************************************************************
File Definition:
***********************************************************************/
uint32 version <format=hex>;
Assert(version == 0x1b);
uint32 length;
// A section of values that don't belong the actual Wwise bank
struct {
uint32 unknown1;
Assert(unknown1 == 0x0);
// Matches the file itself
uint64 this_file <format=hex>;
uint32 unknown2;
Assert(unknown2 == 0x40);
uint32 unknown3;
Assert(unknown3 == 0x0);
// The following hash-like values will probably define some of these values:
// - name of the event
// - Wwise bus the event runs on
// Corresponds to the `id` value of a HIRC object of type "event" later on in the file
uint32 hirc_event_id <format=hex>;
// No particularly clear value.
// Sometimes when interpreted as `float`, it produces whole numbers.
// Sometimes, it's very close to `0xFFFFFFFF`.
uint32 unknown4;
// Following two usually look like hashes.
// Also often reasonably looking floats close to `1`. Could be something like volume.
// Would still fit with it sometimes showing up elsewhere in a `.wwise_bank`: It's not unreasonable
// for the bnk to have volume values as well.
// In at least one instance, shows up in `MotionBus`/`MotionFX` sections in a `.wwise_bank`.
uint32 unknown5 <format=hex, comment="Looks like a short hash">;
// At least in one instance, this was identical with `unknown6`
uint32 unknown6 <format=hex, comment="Looks like a short hash">;
uint32 unknown7;
Assert(unknown7 == 0x0 || unknown7 == 0x1);
uint32 unknown8;
Assert(unknown8 == 0x0 || unknown8 == 0x1);
uint32 unknown9;
Assert(unknown9 == 0x0);
uint32 unknown10;
Assert(unknown10 == 0x0);
} header;
struct bnk
{
#include "bnk.bt";
} wwise_bank <open=true>;

22
dt_wwise_stream.bt Executable file
View file

@ -0,0 +1,22 @@
//------------------------------------------------
//--- 010 Editor v12.0.1 Binary Template
//
// File: dt_wwise_stream.bt
// Authors: Lucas Schwiderski
// Version:
// Purpose:
// Category: Darktide
// File Mask: *.wwise_stream
// ID Bytes:
// History:
//------------------------------------------------
// Could be the version, but 27 different versions of a file that only contains an offset seems unlikely
uint32 unknown1;
Assert(unknown1 == 0x1b);
// Offset and length of the section within the `.stream` file.
// Since all `.wwise_stream` files seem to get their own `.stream` file, `offset` always ends up being `0`,
// and `length` always ends up matching the `.stream` file's size.
uint32 offset;
uint32 length;

47
vt2_bundle.bt Normal file
View file

@ -0,0 +1,47 @@
//------------------------------------------------
//--- 010 Editor v10.0 Binary Template
//
// File:
// Authors:
// Version:
// Purpose: Vermintide 2 Decompressed Bundle
// Category: Vermintide 2
// File Mask:
// ID Bytes:
// History:
//------------------------------------------------
typedef struct {
uint64 type <format=hex,bgcolor=0x0015FF>;
uint64 name <format=hex,bgcolor=0x0010BF>;
uint32 padding;
// Data size for all versions combined
uint32 data_size;
} Metadata;
typedef struct {
uint32 lang;
uint32 size;
uint32 stream_size;
} FileVersion;
typedef struct {
uint64 type <format=hex,bgcolor=0x0015FF>;
uint64 name <format=hex,bgcolor=0x0010BF>;
uint32 version_count;
uint32 stream_offset;
FileVersion versions[version_count];
local int i = 0;
for (i = 0; i < version_count; i++) {
struct FileData {
uchar data[versions[i].size];
} file_data;
}
} File;
uint32 item_count;
uint64 properties[32] <format=hex>;
Metadata items[item_count];
File files[item_count] <optimize=false>;

38
vt2_compressed_bundle.bt Normal file
View file

@ -0,0 +1,38 @@
//------------------------------------------------
//--- 010 Editor v10.0 Binary Template
//
// File:
// Authors:
// Version:
// Purpose: Vermintide 2 Compressed Bundle
// Category: Vermintide 2
// File Mask:
// ID Bytes:
// History:
//------------------------------------------------
uint32 format <format=hex>;
uint32 inflate_size;
uint32 padding <hidden=true>;
typedef struct {
uint32 block_size;
uchar data[block_size];
} Block <read=ReadBlock>;
string ReadBlock(Block &block)
{
if(exists(block.block_size)) {
string s;
SPrintf(s, "%lg", block.block_size);
return s;
} else {
return "";
}
}
// No clue how to do "until there is nothing left" with this, so I'll just make up a number
// This is good enough to show the concept anyways
local uint block_count = 100;
Block blocks[block_count] <optimize=false>;

126
vt2_level.bt Normal file
View file

@ -0,0 +1,126 @@
//------------------------------------------------
//--- 010 Editor v12.0.1 Binary Template
//
// File: vt2_level.bt
// Authors: Lucas Schwiderski
// Version:
// Purpose:
// Category: Vermintide 2
// File Mask: *.level
// ID Bytes: B5 00 00 00
// History:
//------------------------------------------------
// See <https://gitlab.com/IstotI/vtextract/-/blob/master/Assets%20Types/Converters/LevelConversion.cs>
typedef struct {
float x;
float y;
float z;
} Vector3;
typedef struct {
float x;
float y;
float z;
float w;
} Quaternion;
typedef struct {
uint32 unknown_1 <format=hex>;
uint32 unknown_2 <format=hex>;
// unknown before this
// maps directly to the keys of the same name, as murmur64 hashes
uint64 id_hash <format=hex>; // has to be there
uint64 name_hash <format=hex>; // Will be `0x0` when no name was given
uint64 type_hash <format=hex>; // has to be there
uint64 material_hash <format=hex>; // will be `0x0` when not given
// defaults to 0, 0, 0
Vector3 pos;
// defaults to 0, 0, 0, 0
Quaternion rot;
// Not sure why they felt the need to abbreviate "scale". Defaults to 1, 1, 1
Vector3 scl;
// unknown after this
} Unit;
typedef struct {
uint32 name <format=hex>; // murmur64-half
uint64 resource <format=hex>; // murmur64
} Material;
typedef struct {
uint32 unit_id;
uint32 num_materials;
Material materials[num_materials];
} UnitMaterials;
// File Parsing
uint32 version <format=hex>; // correct
uint32 num_units; // correct
uint32 num_background_units; // correct
uint32 section_address_unit_data <format=hex>; //Unit Data & Level Settings
uint32 section_address_unknown1 <format=hex>;
uint32 section_address_prototypes <format=hex>;
uint32 section_address_prototypes_data_size <format=hex>; //Or adress to prototypes collision
uint32 section_address_unknown2 <format=hex>;
uint32 section_address_unknown3 <format=hex>;
uint32 section_address_unknown4 <format=hex>;
uint32 section_address_unknown5 <format=hex>;
uint32 section_address_unknown6 <format=hex>;
uint32 section_address_unknown7 <format=hex>;
uint32 section_address_unknown8 <format=hex>;
uint32 section_address_level_settings <format=hex>;
uint32 particles_count;
uint32 section_address_particles <format=hex>;
uint32 section_address_unknown12 <format=hex>;
uint32 section_address_unknown13 <format=hex>;
uint32 section_address_unknown14 <format=hex>;
uint32 section_address_unknown15 <format=hex>;
uint32 section_address_unknown16 <format=hex>;
uint32 section_address_unknown17 <format=hex>;
uint32 section_address_unknown18 <format=hex>;
uint32 section_address_unknown19 <format=hex>;
uint32 section_address_unknown20 <format=hex>;
uint32 section_address_unknown21 <format=hex>;
uint32 section_address_unknown22 <format=hex>;
uint32 section_address_stories <format=hex>;
uint32 section_address_unknown24 <format=hex>;
uint32 section_address_unknown25 <format=hex>;
uint32 section_address_unknown26 <format=hex>;
uint32 section_address_unknown27 <format=hex>;
uint32 section_address_unknown28 <format=hex>;
uint32 section_address_unknown29 <format=hex>;
uint32 section_address_unit_materials <format=hex>;
uint32 section_address_unknown31 <format=hex>;
uint32 section_address_unknown32 <format=hex>;
uint32 section_address_unknown33 <format=hex>;
uint32 num_settings_entries;
// section start: unit, position unknown:
Unit units[num_units];
FSeek(section_address_unit_materials);
uint32 num_unit_materials;
UnitMaterials unit_materials[num_unit_materials];
// section end
uint32 len_sound_environment; // position unknown
byte sound_environment[len_sound_environment];
if (len_sound_environment < 4) {
byte padding_1[4 - (len_sound_environment % 4)]; // guess
}
byte unknown_3[3 * 4];
uint32 len_timpani_sound_environment; // position unknown
byte timpani_sound_environment[len_timpani_sound_environment];
if (len_timpani_sound_environment < 4) {
byte padding_2[4 - (len_timpani_sound_environment % 4)]; // guess
}

101
vt2_nav_data.bt Normal file
View file

@ -0,0 +1,101 @@
//------------------------------------------------
//--- 010 Editor v11.0.1 Binary Template
//
// File: vt2_nav_data.bt
// Authors: Lucas Schwiderski
// Version:
// Purpose:
// Category: Vermintide 2
// File Mask: *.(NavData|nav_data)
// ID Bytes: 42 6C 6F 62 41 67 67 46 69 6C 65 00
// History:
//------------------------------------------------
string file_type;
uint32 unknown_1;
if (unknown_1 != 0)
return "Unexpected value";
// Equals `02` for empty.level, `03` for all others so far
// The empty level was missing a section, so that's likely the count for it
uint32 count_sections;
// TODO: Create an enum for section types and make this section stuff proper
struct {
uint32 section_1_type;
if (section_1_type != 0x0500)
return "Unexpected value";
uint32 unknown_4;
if (unknown_4 != 0)
return "Unexpected value";
// Both always `0x28`
uint32 unknown_5;
uint32 unknown_6;
uint32 build_string_length;
// Always `0x04`
uint32 unknown_8;
char build_string[build_string_length];
// Padding to get `build_string_length` to divide by 4 (technically `sizeof(uint32)`)
if (build_string_length % 4 != 0) {
byte build_string_padding[4 - (build_string_length % 4)];
}
} Header;
uint32 section_2_type;
if (section_2_type == 0x01) {
uint32 count_nav_meshes;
struct NavMesh {
uint32 data_length;
// Could be length of the following section
uint32 section_length;
byte data[data_length];
} nav_meshes[count_nav_meshes] <optimize=false>;
uint32 section_3_type;
}
uint32 unknown_12;
// For any non-empty navdata, this seems to increas by 4
uint32 unknown_13;
// Seems to be always the same as `unknown_13`
uint32 unknown_14;
uint32 unknown_15;
uint32 unknown_16;
uint32 unknown_17;
uint32 unknown_18;
uint32 unknown_19;
uint32 unknown_20;
uint32 unknown_21;
uint32 unknown_22;
// Not actually null-terminated
char header_sector_descriptor[16];
struct SectorDescriptor{
uint32 unknown_1;
uint32 sector_name_header_length;
uint32 unknown_3;
uint32 sector_name_value_length;
uint32 generator_type_name_length;
uint32 unknown_6;
uint32 unknown_7;
uint32 unknown_8;
uint32 unknown_9;
} sector_descriptor;
// Terminated by two! nulls
char header_sector_name[sector_descriptor.sector_name_header_length];
// Padding to get string length to divide by 4 (technically `sizeof(uint32)`)
byte header_sector_name_padding[4 - (sector_descriptor.sector_name_header_length % 4)];
string sector_name;

40
vt2_network_config.bt Normal file
View file

@ -0,0 +1,40 @@
//------------------------------------------------
//--- 010 Editor v11.0.1 Binary Template
//
// File: vt2_network_config.bt
// Authors: Lucas Schwiderski
// Version:
// Purpose:
// Category: Vermintide 2
// File Mask: *.network_config
// ID Bytes: 20 00 00 00
// History:
//------------------------------------------------
typedef enum<UINT32> {
PeerToPeer,
ClientServer
} NetworkType;
typedef enum<BYTE> {
Int = 0x01,
Int64 = 0x07,
GamerObjectId = 0x34
} Primitive;
typedef struct {
Primitive primitive;
uint16 bits;
uint32 padding;
uint32 name_hash;
uint32 tolerance;
uint32 min; // Possibly 'min' for number values
uint32 max;
} Type;
uint32 version;
NetworkType network_type;
uint32 reliable_send_buffer_size;
uint32 reliable_receive_buffer_size;
uint32 num_types <hidden=true>;
Type types[num_types];

92
vt2_network_config_new.bt Normal file
View file

@ -0,0 +1,92 @@
//------------------------------------------------
//--- 010 Editor v11.0.1 Binary Template
//
// File: vt2_network_config_new.bt
// Authors: Lucas Schwiderski
// Version:
// Purpose:
// Category: Vermintide 2
// File Mask: *.network_config
// ID Bytes: 23 00 00 00
// History:
//------------------------------------------------
typedef enum<BYTE> {
Bool,
Int,
Float,
Vector3,
Quaternion,
String,
Int64 = 0x07,
Array,
GamerObjectId = 0x34
} Primitive;
typedef struct {
uint32 name_hash;
uint32 padding;
uint32 data_1;
Primitive primitive;
uint16 bits;
byte unknown_1;
uint32 min; // Possibly 'min' for number values
uint32 max;
} Type;
typedef struct {
uint32 index;
} ObjectField;
typedef struct {
uint32 index;
} ObjectFieldType;
typedef struct {
uint32 name;
} ObjectFieldName;
typedef struct {
uint32 name_hash;
uint32 unknown_1;
uint32 unknown_2;
float priority;
float update_rate;
uint32 num_field_types <hidden=true>;
ObjectFieldType object_field_types[num_field_types];
uint32 num_field_names <hidden=true>;
if (num_field_names != num_field_types)
return "Number of objects types and names doesn't match";
ObjectFieldName object_field_names[num_field_names];
} Object;
// Templates don't support defining an array of null-terminated strings,
// so we need to wrap it into a struct
typedef struct {
string name;
} ObjectName;
uint32 version;
uint32 reliable_send_buffer_size;
uint32 reliable_receive_buffer_size;
uint32 num_types <hidden=true>;
Type types[num_types];
uint32 num_object_names <hidden=true>;
uint16 object_start_positions[num_object_names] <hidden=true>;
uint32 total_names_length <hidden=true>;
// By default the array would be optimized to truncate every entry
// to the length of the first one.
ObjectName object_names[num_object_names] <optimize=false, open=false, hidden=true>;
uint32 padding_length <hidden=true>;
FSkip(padding_length);
uint32 num_objects <hidden=false>;
if (num_object_names != num_objects)
return "Number of objects and names doesn't match";
Object objects[num_objects] <optimize=false, open=false>;

22
vt2_strings.bt Normal file
View file

@ -0,0 +1,22 @@
//------------------------------------------------
//--- 010 Editor v10.0 Binary Template
//
// File: vt2_strings.bt
// Authors: Lucas Schwiderski
// Version: 1.0
// Purpose: Vermintide 2 Strings
// Category: Vermintide 2
// File Mask: *.strings
// ID Bytes: AE F3 85 3E
// History:
//------------------------------------------------
uint32 header <hidden=true>;
uint32 count;
typedef struct {
uint32 name_hash <format=hex>;
uint32 address <format=hex>;
} A;
A a[count];

466
vt2_unit.bt Normal file
View file

@ -0,0 +1,466 @@
//------------------------------------------------
//--- 010 Editor v11.0.1 Binary Template
//
// File: vt2_unit.bt
// Authors: Lucas Schwiderski
// Version:
// Purpose:
// Category: Vermintide 2
// File Mask: *.unit
// ID Bytes: BA 00 00 00
// History:
//------------------------------------------------
// See <https://gitlab.com/IstotI/vtextract/-/blob/master/Assets%20Types/Converters/UnitConversion.cs>
// Type Definitions
// 16 byte
typedef struct {
float row_1[4];
float row_2[4];
float row_3[4];
float row_4[4];
} Matrix4x4;
// 3 byte
typedef struct {
float x;
float y;
float z;
} Vector3;
// 7 byte
typedef struct {
float lx;
float ly;
float lz;
float ux;
float uy;
float uz;
byte unknown[4];
} Bounds;
// 21 byte
typedef struct {
uint32 data_size;
byte data[data_size];
uint32 unknown_1;
uint32 unknown_2;
uint32 num_elements;
uint32 element_size;
} MeshSection;
typedef struct {
uint32 name;
uint32 type;
uint32 unknown_1;
uint32 index;
byte unknown_2;
} MeshChannelDefinition;
// 4 + (x * 21) byte
typedef struct {
uint32 num_streams;
struct Stream {
uint32 data_size;
hfloat data[data_size / 2];
uint32 unknown_1;
uint32 unknown_2;
uint32 num_elements;
uint32 element_size;
} streams[num_streams] <optimize=false>;
uint32 num_streams_2 <hidden=true>;
struct StreamMeta {
uint32 name;
uint32 type;
uint32 unknown_1;
uint32 index;
byte unknown_2;
} stream_meta[num_streams] <optimize=false>;
uint32 unknown_1;
uint32 unknown_2;
// Apparently the number of vertices with position values
// that don't fit in a single short/uint16
// When > 0, indicates that following data should be read as uint32
// instead
uint32 unknown_3;
uint32 num_index_stream_data;
uint32 size_index_stream_data;
// this means each entrie's size is `size_stream_data / num_stream_data`
if (size_index_stream_data / num_index_stream_data == 2) {
uint16 index_stream_data[num_index_stream_data];
} else {
byte index_stream_data[size_index_stream_data];
}
uint32 num_materials;
struct Material {
uint32 id;
uint32 tri_array_start;
uint32 tri_count;
uint32 unknown;
} materials[num_materials];
Bounds bounds;
uint32 num_materials_2 <hidden=true>;
uint32 material_names[num_materials_2];
} Geometry;
// 4 + (x * 16) + (x * 4) byte
typedef struct {
uint32 num_bones;
Matrix4x4 matrix[num_bones];
uint32 bone_ids[num_bones];
} Skin;
// 15 byte
typedef struct {
Vector3 localXAxis;
Vector3 localYAxis;
Vector3 localZAxis;
Vector3 localPosition;
Vector3 localScale;
} NodeLocal;
// 4 byte
typedef struct {
uint16 unknown;
// Index into `num_nodes`
uint16 parent_id;
} NodeExtra;
enum <uint32> NodeFlags {
// Rarely set, since renderables with this value aren't included
// for compilation by default
VIEWPORT_VISIBLE=1,
SHADOW_CASTER=2,
CULLING_DISABLED=4,
};
// 27 byte
typedef struct {
uint32 parent;
uint32 name;
uint32 num_geometries;
uint32 geometry_name[num_geometries];
uint32 unknown_1;
uint32 unknown_2;
uint32 unknown_3;
// Flags set in the .unit file
// Usually set to `1`, since hidden renderables are skipped
// during compilation by default
uint32 viewport_visible : 1;
uint32 shadow_caster : 1;
// Need to check if this is really defined as a negative, as implied by the name
// Usually, you should name booleans after the positive value to minimize confusion.
uint32 culling_disabled : 1;
uint32 occluder : 1;
uint32 surface_queries : 1;
uint32 always_keep : 1;
Bounds bounds;
} Node;
// 12 byte
//typedef struct {
// uint32 name;
// uint64 resource;
//} Material;
enum <uint32> ActorShapeType {
Sphere,
Box,
Capsule,
MESH,
Convex,
};
// 32 + x + (1, 2, 3, ?) byte
typedef struct {
ActorShapeType type;
uint32 material;
uint32 template;
Matrix4x4 pose;
uint32 physx_data_size;
byte physx_data[physx_data_size];
switch (type) {
case 0:
byte shape_shpere_radius;
break;
case 1:
byte shape_box_half_size_x;
byte shape_box_half_size_y;
byte shape_box_half_size_z;
break;
case 2:
byte shape_capsule_radius;
byte shape_capsule_length;
break;
case 3:
return "ActorShapeType.MESH not implemented";
break;
case 4:
return "ActorShapeType.Convex not implemented";
break;
}
} Shape;
// 17 + (x * (32 + y + (1, 2, 3, ?))) byte
typedef struct {
uint32 name;
uint32 template;
uint32 node;
byte mass;
uint32 num_shapes;
Shape shapes[num_shapes] <optimize=false>;
} Actor;
// 15 byte
typedef struct {
uint32 name;
uint32 unknown_1;
byte near_range;
byte far_range;
byte vertical_fov;
uint32 unknown_2;
} Camera;
enum <uint32> LightType {
Omni,
Spot,
BOX,
Directional,
};
typedef byte boolean;
// 35 + (6, 8) byte
typedef struct {
uint32 name;
uint32 node_id;
byte color_r;
byte color_g;
byte color_b;
// Should both be 1
byte check_1;
byte check_2;
LightType type;
switch (type) {
case 0: // Fallthrough
case 1:
byte falloff_start;
byte falloff_end;
byte unknown_1;
byte spot_angle_start;
byte spot_angle_end;
byte unknown_2;
break;
case 2:
byte box_min_x;
byte box_min_y;
byte box_min_z;
byte box_max_x;
byte box_max_y;
byte box_max_z;
break;
case 3:
uint unknown_1;
}
boolean cast_shadows;
byte bs[17];
} Light;
// 21 byte
typedef struct {
byte step_end;
byte step_start;
uint32 num_renderables;
uint32 renderable_id[num_renderables];
Bounds bounding_volume;
uint32 unknown_flags;
} LODSteps;
// 12 + (x * 21) byte
typedef struct {
uint32 name;
uint32 orientation;
uint32 num_steps;
LODSteps steps[num_steps];
} LOD;
// 19 byte
typedef struct {
uint32 name;
byte height;
byte radius;
uint32 collision_filter;
byte slope_limit;
byte ffx8[8];
} Mover;
// 8 + (x * 4)
typedef struct {
uint32 name;
uint32 num_members;
uint32 renderable_ids[num_members];
} VisibilityGroup;
// File Parsing
uint32 version;
// ===================
// Meshes
// ===================
uint32 num_geometries;
Geometry geometries[num_geometries] <optimize=false>;
// ===================
// Skins
// ===================
uint32 num_skins;
Skin skins[num_skins] <optimize=false>;
uint32 size_unknown_1;
byte unknown_1[size_unknown_1];
uint32 num_unknown_2;
uint32 unknown_2[num_unknown_2];
// ===================
// Nodes
// ===================
uint32 num_nodes;
NodeLocal node_locals[num_nodes];
Matrix4x4 node_world_poses[num_nodes];
// Should be 0
uint32 unknown_3;
// ===================
// Renderables
// ===================
uint32 num_nodes;
Node nodes[num_nodes] <optimize=false>;
// ===================
// Physics
// ===================
uint32 num_actors;
Actor actors[num_actors] <optimize=false>;
// ===================
// Cameras
// ===================
uint32 num_cameras;
Camera cameras[num_cameras];
// ===================
// Lights
// ===================
uint32 num_lights;
Light lights[num_lights];
// ===================
// LOD
// ===================
uint32 num_lods;
LOD lods[num_lods];
// Should both be 0. Sections I don't know yet?
uint32 unknown_4;
uint32 unknown_5;
// ===================
// Movers
// ===================
uint32 num_movers;
Mover movers[num_movers];
// Should be 0. Section I don't know yet?
uint32 unknown_6;
boolean unknown_has_animation_blender_bones;
uint32 str_length;
char str[str_length];
// ===================
// Script Data
// ===================
uint32 script_data_size;
byte script_data[script_data_size];
// ===================
// Visibility Group
// ===================
uint32 num_visibility_groups;
VisibilityGroup visibility_groups[num_visibility_groups];
// ===================
// Unknown
// ===================
// Probably related to scripting/Flow
// When there is data, it contains strings that look like function calls
uint32 size_flow_data_1;
byte flow_data_1[size_flow_data_1];
uint32 size_flow_data_2;
byte flow_data_2[size_flow_data_2];
// ===================
// Materials
// ===================
uint32 size_material_definition;
uint32 num_materials;
struct MaterialDefinition {
// Probably the index into the other material section
uint32 unknown_1;
uint32 num_primitives;
uint32 unknown_2;
uint32 num_primitives_2;
uint32 unknown_3;
// Fits for the 6 vectors, but not for the last `unknown`.
Bounds bounds;
uint32 num_primitives_3;
uint32 primitives[num_primitives_3];
} material_definitions[num_materials] <optimize=false>;
// Should be 0. Sections I don't know yet?
uint32 unknown_7;
uint32 unknown_8;
uint32 unknown_9;
uint32 unknown_10;
// Apparently doesn't have to match the previous `num_materials`
uint32 num_materials_2;
struct MaterialResources {
uint32 name;
uint64 resource;
} material_resources[num_materials_2];
// Should be 0. Sections I don't know yet?
uint32 unknown_11;
uint32 unknown_12;
uint32 unknown_13;
uint32 unknown_14;

51
vt2_unit_186 Normal file
View file

@ -0,0 +1,51 @@
//------------------------------------------------
//--- 010 Editor v11.0.1 Binary Template
//
// File: vt2_unit_186.bt
// Authors: Lucas Schwiderski
// Version:
// Purpose:
// Category: Vermintide 2
// File Mask: *.unit
// ID Bytes: BA 00 00 00
// History:
//------------------------------------------------
// =============
// Mesh Geometry
// =============
typedef struct {
int32 data_length;
char data[data_length];
uint32 validity;
uint32 stream_type;
uint32 count;
uint32 stride;
} VertexBuffer;
typedef struct {
int32 buffer_count;
VertexBuffer vertex_buffers[buffer_count];
} MeshGeometry;
// TODO: vertex buffers
// TODO: index buffers
// TODO: batch range
// TODO: bounding volume
// TODO: materials
// TODO: skin data
// TODO: simple animation
// TODO: simple animation groups
// TODO: scene graph
// TODO: mesh objects
// ====
// File
// ====
uint version;
MeshGeometry mesh_geometry;

205
vt2_unit_186.bt Normal file
View file

@ -0,0 +1,205 @@
//------------------------------------------------
//--- 010 Editor v11.0.1 Binary Template
//
// File: vt2_unit_186.bt
// Authors: Lucas Schwiderski
// Version:
// Purpose:
// Category: Vermintide 2
// File Mask: *.unit
// ID Bytes: BA 00 00 00
// History:
//------------------------------------------------
typedef uint32 Murmur32 <format=hex>;
typedef uint64 Murmur64 <format=hex>;
typedef struct {
float x;
float y;
float z;
} Vector3;
typedef struct {
float x;
float y;
float z;
float w;
} Quaternion;
typedef struct {
float m11;
float m12;
float m13;
float m14;
float m21;
float m22;
float m23;
float m24;
float m31;
float m32;
float m33;
float m34;
} Matrix3x3;
typedef struct {
float m11;
float m12;
float m13;
float m14;
float m21;
float m22;
float m23;
float m24;
float m31;
float m32;
float m33;
float m34;
float m41;
float m42;
float m43;
float m44;
} Matrix4x4;
typedef struct {
uint32 len_data <hidden=true>;
hfloat data[len_data / 2];
uint32 validity;
uint32 stream_type;
uint32 count;
uint32 stride;
} VertexBuffer;
typedef struct {
uint32 vertex_component;
uint32 type;
uint32 set;
uint32 stream;
byte is_instance;
} Channel;
typedef struct {
uint32 validity;
uint32 stream_type;
uint32 index_format;
uint32 index_count;
uint32 len_indices <hidden=true>;
char indices[len_indices];
} IndexBuffer;
typedef struct {
uint32 material_index;
uint32 start;
uint32 end;
uint32 bone_set;
} BatchRange;
typedef struct {
Vector3 lower_bounds;
Vector3 upper_bounds;
float radius;
} BoundingVolume;
typedef struct {
uint32 num_buffers <hidden=true>;
VertexBuffer vertex_buffers[num_buffers] <optimize=false>;
uint32 num_channels <hidden=true>;
if (num_buffers != num_channels)
return "Buffer count and Channel count don't match";
Channel channels[num_channels];
IndexBuffer index_buffer;
uint32 num_batch_ranges <hidden=true>;
BatchRange batch_ranges[num_batch_ranges] <optimize=false>;
BoundingVolume bounding_volume;
uint32 num_materials <hidden=true>;
Murmur32 materials[num_materials];
} MeshGeometry;
typedef struct {
uint32 num_index_sets <hidden=true>;
uint32 index_sets[num_index_sets];
} MatrixIndexSet;
typedef struct {
uint32 num_inverse_bind_matrices <hidden=true>;
Matrix4x4 inverse_bind_matrices[num_inverse_bind_matrices];
uint32 num_node_indices <hidden=true>;
uint32 node_indices[num_node_indices];
uint32 num_matrix_index_sets <hidden=true>;
MatrixIndexSet matrix_index_sets[num_matrix_index_sets];
} SkinData;
typedef struct {
// TODO: Murmur32?
uint32 id;
uint32 num_data <hidden=true>;
int32 data[num_data];
} SimpleAnimationGroup;
typedef struct {
uint32 num_nodes <hidden=true>;
struct LocalTransform {
Vector3 x;
Vector3 y;
Vector3 z;
Vector3 position;
Vector3 scale;
} local_transform[num_nodes];
Matrix4x4 world_transform[num_nodes];
struct ParentNode {
uint16 parent_type;
uint16 parent_index;
} parent_node[num_nodes];
Murmur32 name[num_nodes];
} SceneGraph;
typedef struct {
Murmur32 name;
uint32 node_index;
uint32 geometry_index;
uint32 skin_index;
uint32 flags;
BoundingVolume bounding_volume;
} MeshObject;
// ====
// File
// ====
uint32 version;
uint32 num_mesh_geometries <hidden=true>;
MeshGeometry mesh_geometry[num_mesh_geometries] <optimize=false>;
uint32 num_skins <hidden=true>;
SkinData skins[num_skins];
uint32 len_simple_animation <hidden=true>;
char simple_animation[len_simple_animation] <optimize=false>;
uint32 num_simple_animation_groups <hidden=true>;
SimpleAnimationGroup simple_animation_groups[num_simple_animation_groups] <optimize=false>;
SceneGraph scene_graph;
uint32 num_mesh_objects <hidden=true>;
MeshObject mesh_objects[num_mesh_objects];

63
vt2_unit_new.bt Normal file
View file

@ -0,0 +1,63 @@
//------------------------------------------------
//--- 010 Editor v11.0.1 Binary Template
//
// File: vt2_unit_new.bt
// Authors: Lucas Schwiderski
// Version:
// Purpose:
// Category: Vermintide 2
// File Mask: *.unit
// ID Bytes: BA 00 00 00
// History:
//------------------------------------------------
uint32 version;
// Assuming "MeshGeometry" based on stot's "vkextract"
uint32 num_geometries;
typedef struct {
uint32 num_index_streams;
// One potential content for such a stream is vertex data: 4 half floats.
struct IndexStream {
uint32 data_size;
hfloat data[data_size / 2];
uint32 unknown_1;
uint32 unknown_2;
uint32 size;
uint32 stride;
} index_streams[num_index_streams] <optimize=false>;
uint32 num_streams;
struct Stream {
// One of the unknown uint32 is probably the `index` from .bsi
uint32 unknown_1;
// `0x11` -> "CT_FLOAT3", `0x0F` -> "CT_FLOAT2"
uint32 channel_type;
uint32 unknown_2;
// Probably the index into `index_streams`
uint32 index;
byte unknown_3;
} streams[num_streams];
struct StreamData {
uint32 unknown_1;
uint32 unknown_2;
// Apparently the number of vertices with position values
// that don't fit in a single short/uint16
// When > 0, indicates that following data should be read as uint32
// instead
uint32 unknown_3;
uint32 num_stream_data;
uint32 size_stream_data;
// this means each entrie's size is `size_stream_data / num_stream_data`
if (size_stream_data / num_stream_data == 2) {
uint16 stream_data[num_stream_data];
} else {
byte stream_data[size_stream_data];
}
} stream_data[num_streams];
} Geometry;
Geometry geometries[num_geometries] <optimize=false>;