Skip to main content

Watch Dogs: Legion — Game Engine & Modding Reference

Technical reference for WDL's engine internals, derived from DLL RE, shader analysis, and format documentation.


1. Shader System

1.1 Shader Object Layout​

engine/shaders/
├── obj/ # DX11-style compiled shader objects (.cso / .vso)
├── obj_d3d12/ # D3D12 variant (primary modding target)
├── obj_vulkan_dxc/ # Vulkan via DXC (vestigial — PC only ships DX11/D3D12)
├── fastinitdata.bin # Precompiled shader blob (DX11)
├── fastinitdata_d3d12.bin # Precompiled D3D12 blob
├── fastinitdata_vulkan_dxc.bin
└── shaders.crc # 4-byte CRC checksum

Each obj*/ has 128 hash buckets (h00–h7f). File naming: <stage>_<hash64>.<ext> (e.g. compute_132c5d0cc6f1be00.cso).

Base counts: 54,821 D3D12 shaders. Patch override: 43,065 (zero hash overlap with base — all new shaders).

1.2 DXIL Format (D3D12/Vulkan)​

Both obj_d3d12/ and obj_vulkan_dxc/ files have a 0x38-byte wrapper before the standard DXBC container. Inside the DXBC is DXIL (Shader Model 6.0+). The DXBC checksum is invalid — the game bypasses validation.

Strip the header:

dd if=input.cso bs=1 skip=56 of=stripped.cso

Key properties:

  • All cbuffer reads use cbufferLoadLegacy (opcode 59), zero scalar cbufferLoad (opcode 58) — early SM 6.0 scalar-CBV layout
  • float[N] arrays have ArrayStride 4 (tightly packed, not vec4-aligned)
  • HLSL cannot express stride-4 arrays → requires flattened cbuffer fallback

1.3 Shader Decompilation Pipeline​

input.cso → strip 0x38 header → dxil-spirv → patched spirv-cross → .hlsl
ToolPurpose
dd bs=1 skip=56Strip D3D12/Vulkan wrapper
dxil-spirv (YYadorigi v0.6)DXIL → SPIR-V
spirv-cross (patched)SPIR-V → HLSL SM 6.0, with cbuffer stride-4 fix
dxc (v1.9)DXIL disassembly / HLSL recompilation

Result: 53,545/53,551 base D3D12 shaders decompiled (99.99%). The 6 failures are non-shader files (index.*, a8e8da7e1e9c3506).

The patched spirv-cross falls back to uniform float4 _name[size] for non-packoffset-compatible arrays (SPIRV-Cross issue #2658 is wontfix upstream).

1.4 Cbuffer Member-Name Recovery​

DXIL binaries retain original HLSL cbuffer member names as a string table at the end of the module. Pairing with dxc -dumpbin struct types (%dx.alignment.legacy.*) reconstructs: member name → byte offset → float4 register slot.

This is the highest-fidelity source of shader variable names — the game strips reflection names, but the string table + struct types survive.

Tools:

  • cbuf_names.py — extracts <name, reg, comp, byte_offset> per cbuffer member
  • rewrite_cbuffers.py — rewrites flattened float4 Viewport_c[854] → named struct
python3 rewrite_cbuffers.py <shader.cso> <decompiled/*.hlsl> <output.hlsl>

Full batch: 53,545 base shaders rewritten → decompiled_cb/. 100/100 random sample compiles via dxc -T [vs|ps|cs]_6_0 -E main.

1.5 Patch Shader Set​

The patch .dat/.fat pair overrides base archives at runtime:

  • Effective runtime set = base stage files + patch index (superset) + patch fastinitdata blobs
  • obj_vulkan_dxc/ absent from patch — base retained entirely
  • Patch index: 271,744 entries (vs 235,801 base) — ~65K new hashes
  • Patch fastinitdata_d3d12.bin: 2,382,067 bytes (vs 2,092,388 base)

Content changes:

  • New cbuffer layouts: 540-float4 lookup buffer in ~67% of patch compute shaders
  • Skinning matrices 3066→3075, new 268/1024-size buffers
  • RT reflection shaders reworked: PerInstanceData/PerInstanceAddData → single PerMaterialData buffer
  • Cloth closest-hit +1,157 lines fp math, water +616, skin/hair +284

Total decompiled: 95,777 .hlsl (53,545 base + 42,232 patch).

1.6 RenderDoc Capture​

The best way to get readable HLSL from live shaders:

renderdoccmd capture <Steam library>/steamapps/common/WatchDogs_Legion/bin/WatchDogsLegion.exe

Captures shaders used in a given scene (not all 170K), but is the most practical approach for modding-specific shader investigation.


2. GLM Model Format

SportBoat_01.glm example — 31 meshes, each with 4 LOD levels:

MeshLOD0 vertsLOD0 facesLOD3 vertsLOD3 faces
Chassis_LOD3,53159985550
SteeringWheels_LOD3206417279
EngineBoat_81_LOD7111,163103119
TopRack_Boat_LOD1342493928
SportRack_LOD9741,736240172
CoverTop_LOD6910180
Inboard_LOD70141416
Bayliner_Glass_01_LOD41322614
Bayliner_Glass_02_LOD41322614

LOD naming: MeshName_LOD0 (highest detail) through MeshName_LOD3 (lowest). Glass parts have only 2 LODs. Export applies -90° X-axis rotation for Blender compatibility.


3. TAM Material Library

Materials are stored in .material.bin packs (TAM v15). Each material declares:

  • Shader binding (e.g. KODOCarGeneric, KODOCarPaint, KODOGlass)
  • Texture parameters with FNV-1 hashes
  • 56 declared parameters per material (typical)

Shader Types​

ShaderRole
KODOCarGenericStandard vehicle surfaces (body, rims, panels)
KODOCarPaintPainted surfaces with clearcoat
KODOGlassTransparent surfaces (interior + exterior)

Texture Bindings (KODOCarGeneric example)​

SlotHashPurpose
colour0xF95881AFAlbedo/diffuse
specular0x260A3CFESpecular/roughness
normal0x045829E2Normal map
damage_specular0x146C808BDamage overlay
emissive0x4E0D5E9Emissive glow

Texture paths follow: graphics\vehicles_nexus\land_textures\wd2\glob*

Material archive paths reference hashed names: paulmaidens-m-9223372094509408844.material.bin


4. Vehicle Handling Format

.handling.bin files encode vehicle physics as indexed float/uint parameters. Parsed by the game's drive handling system.

Parameter Format​

Each parameter: <index> <type> <value> <name>

IndexTypeNameExample
3floatLength0.3
14floatPitch-20.0 (on ground)
15floatPitch9643.5
17floatRoll3500.0
19floatMax Spring Force Front-1.0
25floatFront Offset0.0
26floatRear Offset0.8
27floatCamber Effect0.0
35floatUnderground Length0.25
50floatStiffness2500.0
110uintEnable low rider0
115floatSuspension Speed0.3
140floatOn Ground-20.0
141floatWhen Airborne-20.0
505floatStiffness - Rear Scale0.85
587floatProgressivity0.6
761floatRaycast Extrapolation0.0
764floatWall Riding Scalar0.1

XML roundtrip: Bin → XML → edit → XML → Bin via the WDL Studio tools.


5. Wwise Audio (WEM Format)

Sound files use Wwise (WEM) format. The game's sound directory contains WEM files indexed by numeric IDs (e.g. 1028811276.wem).

PropertyValue
FormatWwise (0xFFFF header)
Channels2 (stereo)
Sample rate48,000 Hz
Typical size1–3 MB per file

Tools: vgmstream (bundled with WDL Studio), wav2wem for re-encoding. Swap workflow: drop WAV/MP3/FLAC/OGG/WEM onto highlighted clip → encode & swap.

Sound library index files map IDs to WEM files within soundbinary/.


6. Engine Path Reference

Key paths inside the game's virtual filesystem:

PathContents
engine/scripts/Lua scripts (domino engine)
engine/scripts/MissionTools.luaMission scripting API
engine/settings/XML config (engine, network, threading, launch)
engine/settings/defaultrenderconfig.xmlRender settings (RT, resolution, quality)
engine/shaders/Shader objects (see §2)
engine/shaders/Textures/SkyResource.binSky LUT
engine/shaders/Textures/PuddleHeight.binPuddle height map
engine/gamemodes/GameModesConfig.xml
data_win64/Archive root (.dat/.fat pairs)
data_win64/shadersobj.datShader archive
data_win64/commonengine.datCommon engine data

Archives are split by category. filelist.txt maps paths to archives.


7. Lua Scripting

The game uses Lua 5.1.5 with a custom "domino" visual scripting layer. Scripts are compiled to Lua bytecode but decompile cleanly (no variable/function names lost — the visual scripting tool generates standard Lua).

Globals​

globals.lua contains a live dump of the _G table: 1,181 function names (e.g. SetItem, RemoveImmunity, SetNetworkVariableBool). Of these, 766 are string-locatable in the DLL (the rest are runtime-registered or packed).

LoaderWDL Integration​

LoaderWDL hooks lua_pcall and luaL_loadbuffer at known RVAs (see pdb_build/build_pdb_yaml.py lines 75–82 for the dx12 offsets). The hook captures lua_state and enables injecting Lua scripts at runtime.

Console output pattern:

[UI/menu] DirectX 12 detected
[UI/d3d12] Starting d3d12 hook
Captured lua_state from pcall!
[Lua] running script...

WLU Files​

WLU (compiled Lua) files require exactly 2 null bytes appended after the FCB portion or the game crashes.


8. Archive Extraction / Repacking

ToolUse
BE_LegionExtract.exe / BE_LegionPack.exeGUI pack/unpack (Wine)
Gibbed.WatchDogsLegion.Unpack.exe / Pack.exeCommand-line alternative

Archives: <Steam library>/steamapps/common/WatchDogs_Legion/data_win64/

info.xml with UseCombineMode="true" enables merge installation (overlay without full archive replacement).


9. Disrupt Engine Toolchain (from source leak)

Source: ubisoft_leak_contents.txt — 2020 Ubisoft source code leak directory listing.

The leak contains the full Disrupt engine internal toolchain used to build WDL.

Core Tools​

ToolPurposeKey DLLs
WolfskinMain Disrupt engine editor (WPF)Wolfskin.dll, WolfskinStandalone.exe, Disrupt.Core.dll, Disrupt.Controls.dll, Disrupt.Materials.Editor.dll, Disrupt.SourceControl.dll
Wolfskin Max/Maya3ds Max + Maya DCC pluginsWolfskinMax2015.dll, WolfskinMax2017.dll, WolfskinMaya2015.nll.dll
VEditVehicle handling editorSee §10.1
WatchBoxData inspectorWatchBox.dll, WatchBase.dll, WatchDomino.dll
PainkillerTool (WPF-based)Painkiller.Core.dll, Painkiller.DisruptModule.dll
RulesmithVisual scripting editor (93MB)RulesmithEditor.exe, uses D3D + OpenGL ES
BlackBoxGame launcherContains Painkiller modules

Shader Pipeline​

ToolPlatformsPurpose
bin/DXC/PC/PCDXC — DXIL compiler (SM 6.0+)
bin/DXC/XboxOne/Xbox OneDXC for Xbox
bin/DXC/Scarlett/Xbox SeriesDXC for Scarlett
bin/DXC/SPIRV/VulkanDXC → SPIRV cross-compilation
bin/FXC/PC/PCFXC — FX compiler (SM 5.0 and below)
bin/FXC/XboxOne/Xbox OneFXC for Xbox

Asset Pipeline​

ToolPurpose
OasisExporterAsset export pipeline (Win32 + Win64 libs)
PakViewerArchive (.dat/.fat) inspection
ArchiveDifferDiff two archive versions
MaterialEditorStandaloneMaterial editing (standalone)
StringIDToolString hash/ID mapping
StreamingPNGStreaming texture pipeline
VideoCompilerCutscene video compilation
VideoEncoderffmpeg/ffprobe for video encoding

Audio Pipeline​

ToolPurpose
WwiseAuthoringWwise audio authoring (full project with plugins, skins, data)
WwiseBinarizerWwise → binary conversion for runtime
AudioToolAudio inspection/editing

Other Tools​

ToolPurpose
Havok/StandaloneFilterManagerPhysics filter configuration
lua/Lua tooling
FSMExportFinite state machine export
Memory/MemoryHUD, MemGraphViewer, MemoryService, EvilCorp, SecretService, Spy
MapExplorerPDB/map exploration
ExcelImporterData import from spreadsheets
FileRenamerBatch file renaming (uses Disrupt.SourceControl.dll)
MosaicTile/asset mosaicking
DemographicPaintNPC population painting
toolframework/Shared tool framework plugins

Disrupt DLLs (from bin/)​

DLLPurpose
Disrupt.Core.dllCore engine runtime
Disrupt.Controls.dllEditor UI controls
Disrupt.Materials.Editor.dllMaterial editor
Disrupt.SourceControl.dllPerforce integration
Disrupt.AssetsHelpers.dllAsset pipeline helpers
Disrupt.ApplicationModel.dllApplication framework
Disrupt.Services.Metadata.dllMetadata services
RulesmithServices_r64.dllRulesmith backend (dx11)
RulesmithServices_r64_dx12.dllRulesmith backend (dx12)

9.1 VEdit — Vehicle Handling Editor​

VEdit is the Disrupt engine's vehicle dynamics editor. It contains documentation, parameter definitions, and UI layouts for car and helicopter handling.

Data Structure​

VEdit/
├── Data/
│ ├── Contexts/Car/ # Chassis, Engine, Transmission contexts
│ ├── Controls/Car/ # Car UI controls
│ ├── Controls/Helicopter/ # Helicopter UI controls
│ ├── Controls/DesignSettings/
│ ├── Graphs/ # Handling curves/graphs
│ ├── Layouts/ # UI layouts
│ ├── Parameters/Car/ # Parameter definitions
│ ├── Simulation/ # Physics simulation config
│ │ ├── DefaultHandlings/
│ │ ├── Measurement/
│ │ ├── ParameterDefinitions/
│ │ └── TelemetryDefinitions/
│ └── Windows/Car/ # Editor windows
│ └── TestBezier/
├── Documentation/
│ └── html/CarHandling/ # Full handling documentation
│ ├── brakes/ + diagrams
│ ├── cameras/ + diagrams
│ ├── chassis/ + diagrams
│ ├── drag/ + diagrams
│ ├── drivetrain/ + diagrams
│ ├── engine/ + diagrams
│ ├── gearbox/ + diagrams
│ ├── graphics/
│ ├── loadtransfer/ + diagrams
│ ├── steering/ + diagrams
│ ├── surface/ + diagrams
│ ├── suspension/ + diagrams
│ ├── tutorial/
│ └── tyres/ + diagrams
└── Tool/
└── locales/ # Multi-language support

Handling Parameters (from handling.bin)​

Vehicle physics are stored as indexed float/uint parameters in .handling.bin files. Categories from VEdit documentation:

CategoryKey Parameters
ChassisMass, centre of gravity, inertia tensor, dimensions
SuspensionLength, stiffness, damping, ride height, travel, progressivity
SteeringLock angle, speed sensitivity, assist curve
EngineTorque curve, RPM limits, power, flywheel inertia
GearboxGear ratios, shift times, final drive
DrivetrainFWD/RWD/AWD, differential locking, torque distribution
BrakesMax torque, bias front/rear, ABS threshold
TyresGrip curve (slip angle vs friction), load sensitivity, rolling resistance
DragAerodynamic drag coefficient, downforce
SurfaceTerrain grip multipliers (asphalt, dirt, grass, etc.)
Load TransferWeight transfer during braking/acceleration/cornering
CamerasChase cam position, FOV, spring damping

VEdit's Documentation/html/CarHandling/ contains detailed HTML docs with diagrams for each category — the authoritative reference for handling.bin parameter semantics.