Skip to main content

Disrupt material.bin Format Specification

Status: Decoder verified across WD1 (11,384 bins), WDL (70 bins), and leak compiled (12,959 bins). 0 decode errors, 0 shader mismatches against leak XMLs.

Authoritative source: 010 Editor template material.bin.bt (ConvertMaterials/res/).

Format Overview (little-endian)​

Header (17 × u32 = 68 bytes)​

OffsetFieldNotes
0x00magic`0x004D4154` ("TAM\0")
0x04version**7** = WD1, **15** = WDL/Leak
0x08–0x40header blockVersion-dependent size/offset fields

Name​

u32 nameSize
char name[nameSize]
byte pad[(4 - nameSize % 4) % 4]

ShaderSetting​

u32 shaderNameSize
char shader[shaderNameSize]
byte mod = (4 - shaderNameSize % 4) % 4
if mod >= 2: origMod = mod, mod -= 2 // InitSettings includes extra 2 bytes
byte pad[mod]

// InitSettings
u16 unk0
byte unk_extra[2] // ONLY if origMod >= 2
u8 unk2
u8 unk3
u32 unk4
i32 unk5
i32 unk6
i32 unk7

Parameters​

u8 unk74
u8 unk75
u16 parameterCount

per parameter:
// Alignment (CRITICAL: type byte sits at CURRENT position, may be misaligned)
byte pad = 4 - (currentOffset % 4) - 1
u8 type // read at current (misaligned) position
if currentOffset % 4 == 0:
skip 4 // skip alignment bytes
skip pad

if (type - 1) <= 10:
u32 nameID // = zlib CRC32(parameter name)

// Values by type
type 1: u32
type 2: vec2 (2 × u32)
type 3: vec3 (3 × u32)
type 4: vec4 (4 × u32)
type 5: i32
type 6: u8 (bool: 0 or 1)
type 7: u32
type 8: u32 size, char string[size]
type 9: u32 size, char string[size]
type 10: u32 size, char string[size]
type 11: u32

Gradient Block​

// Align to 4-byte boundary first
u32 bUseGradient
if bUseGradient == 1:
i32 grad_vec // count of gradient vectors
vec4 vecs[grad_vec] // 4 × u32 each
u32 grad_id
u32 unk1
u8 unk2

EOF​

u32 eof // always 0
byte trailing[] // variable: 0–16 bytes of zero padding

Key Findings​

nameID = zlib CRC32​

Standard zlib CRC32 of the UTF-8 parameter name. Verified 6/6:

ParameterCRC32
DiffuseColor0x9015351F
Opacity0x8C4054FA
AmbientColor0xDC05433D
HeightScaleColor0xAFD746E7
IgnoreMapEffect0x62E3EAB4
DiffuseTexture0State0xA94DD2BF

Enum/state values are also CRC32-hashed: "ColorWrap" → 0x13371135

Type System​

TypeNameStored AsNotes
1u32Raw u32 bitsFloat as bit pattern
2vec22 × u32Float pair as bit patterns
3vec33 × u32Float triple as bit patterns
4vec44 × u32Float quad as bit patterns
5i32Signed int—
6boolSingle byte0 or 1
7u32Raw u32 bitsEnum as CRC32 hash
8stringu32 len + bytesTexture paths, etc.
9stringu32 len + bytes—
10stringu32 len + bytes—
11u32Raw u32 bits—

Critical Gotcha: Misaligned Type Byte​

The type byte is read at the current stream position, which may NOT be 4-byte aligned (after bool params = 1 byte, or string params = variable length). The alignment calculation pad = 4 - (off % 4) - 1 accounts for this, but the type byte itself sits in the potentially misaligned position.

Gradient Block​

When bUseGradient == 1, the gradient block follows immediately after the last parameter (with 4-byte alignment). It contains a count, that many 16-byte gradient vectors, and 3 trailing fields. This was the root cause of earlier 12–20 byte gaps in WD1 files.

Trailing Padding​

Files may have 0–16 bytes of zero padding after the EOF field. The decoder tolerates any all-zero trailing bytes.

Version Differences​

FieldWD1 (v7)WDL/Leak (v15)
Header size68 bytes68 bytes
Init settings6 × u32 (cmd_count in high 16 bits of last)u16 + conditional + u8×2 + u32 + i32×3
Param layoutu8 type, u8 sub_type, align, name_hash, datapad, type byte (misaligned), align skip, pad skip, nameID, data
GradientPresent if bUseGradient=1Same
Shader countMultiple shader familiesMultiple shader families

Validation Results​

Leak Compiled vs Dev XML (12,959 files)​

  • Decode: 12,959/12,959 OK (0 errors)
  • Shader: 0 mismatches
  • Params: 1,308,621 total; mismatches only on enum strings (CRC32 vs "ColorWrap") and texture paths (.xbt vs .png)

Leak Compiled vs Retail WDL (69 matched files)​

  • Identical: 44/69 byte-for-byte identical
  • Diffs: 25/69 differ in header offset fields (16B padding) and parameter value tuning (artist changes, not format changes)

WDL Retail vs Leak XML (66 matched files)​

  • 58 numeric differences = retail tuning (EmissiveIntensity, AlphaTestValue normalized to [0,1], face blend params)

WD1 (11,384 files)​

  • 11,384/11,384 decode OK
  • 479,136 params total, 314 unknown (0.07%) = 35 WD1-specific hashes
  • 20 shader types (DriverGeneric, DriverCloth, Unlit, DriverCarPaint, Character, etc.)

Shader Families​

Known shaders across all games: DriverGeneric, DriverCloth, Unlit, DriverCarPaint, Character, DriverBuilding, DriverGlass, DriverHair, NeonSign, WindowLight, DriverCarGeneric, DriverVegetation, DriverMinimap, RealTreeDriverLeaf, RealTreeDriverTrunk, DriverEye, DriverNexusmon, WaterFlow, DriverWater, DriverWaterDecal, WD2Generic, WD2Emissive, WD2Minimap

Data Sources​

SourcePathCount
WD1 bins11,384
WDL bins (retail)the game install directory70
Leak compiled13,048
Leak dev XMLs24,082
Name dictionarymaterialNames.txt916

Community Notes​

  • Disrupt Editor material converter (fan-made) has bugs: wrong file length on roundtrip, float precision loss.
  • Texture paths use backslash: graphics\_textures\_plastic\plasticpanel_01_d.xbt
  • textureHistory field lists previously assigned textures.
  • selMaterialOverridesId = enum from material "Name" binhex → unsigned long (Intel byte order).
  • Leak .NET editor (Disrupt.Materials.Editor.dll) is XML-only — no binary read/write. Binary format is handled by native C++ engine.
  • Leak TexCompiler_r64.dll strings confirm XBT = header + DDS, NVTT compression, per-platform mip writers.