VPK archive layout and inventory
Question
How is Deadlock's content packaged on disk, and where in that packaging does gameplay data live relative to everything else?
Summary
- Deadlock's internal name is Citadel. The game mount is
citadel/; shared engine content iscore/. - All shipped content is in
citadel/pak01_*.vpk— 274 archives, 27.4 GiB, indexed by a singlepak01_dir.vpkholding 130,730 entries. - The archives are VPK version 2. The directory tree is nested extension → directory → filename, which a ~40-line stdlib parser can read without extracting anything.
- Gameplay data is a rounding error in the payload: 85
.vdata_cfiles totalling 0.8 MB against 24 GB of textures and 2.9 GB of sound. - Localization does not live in the VPKs — it is loose
.txton disk. See note 0004.
Findings
Top-level layout
game/
bin/win64/deadlock.exe, vconsole2.exe
citadel/ the game mount
pak01_000.vpk .. pak01_273.vpk content archives
pak01_dir.vpk the index (6.6 MB)
shaders_pc_*.vpk, shaders_vulkan_*.vpk
resource/localization/ loose .txt, NOT packed
gameinfo.gi, steam.inf
core/ shared engine content (6 archives)
citadel_<lang>/ per-language overlay, one small VPK each (~19 MB)
citadel/gameinfo.gi confirms the mount name and lists 17 supported languages. English is not among the citadel_<lang>/ overlay directories — it is the base content.
Content inventory (citadel/pak01_dir.vpk)
| count | size | extension | what |
|---|---|---|---|
| 79,305 | 2,903.1 MB | .vsnd_c | sounds |
| 15,569 | 52.1 MB | .vpcf_c | particles |
| 12,864 | 23,987.2 MB | .vtex_c | textures |
| 9,372 | 122.1 MB | .vnmclip_c | animation clips |
| 5,013 | 825.7 MB | .vmdl_c | models |
| 3,949 | 16.9 MB | .vmat_c | materials |
| 427 | 4.6 MB | .vcss_c | Panorama UI stylesheets |
| 419 | 1.1 MB | .vxml_c | Panorama UI layouts |
| 110 | 2.1 MB | .vrr_c | response rules (VO logic) |
| 85 | 0.8 MB | .vdata_c | gameplay data |
| 29 | 0.4 MB | .txt | loose config |
Top-level directories: sounds (79,304), models (22,931), particles (15,686), materials (6,414), panorama (3,449), scripts (203), stats (6).
Inferred: anyone after gameplay data should filter to scripts/ + .vdata_c and ignore 99.9% of the archive by volume. Extracting the whole pak is never necessary for this goal.
VPK v2 directory format
Header is signature:u32 = 0x55AA1234, version:u32, treeSize:u32, followed in v2 by four section-size u32s (file data, archive MD5, other MD5, signature) — so the tree starts at byte 28.
The tree is three nested runs of null-terminated strings, each run ended by an empty string: extension → directory → filename. Each filename is followed by a 18-byte footer:
crc32:u32 preloadBytes:u16 archiveIndex:u16 entryOffset:u32 entryLength:u32 0xFFFF:u16
then preloadBytes of inline data. A directory of " " (single space) means the archive root. archiveIndex selects which pak01_NNN.vpk holds the body.
The per-entry crc32 is what makes cross-patch diffing cheap — see the --manifest flag.
Reproduce
python tools/find_game.py
python tools/vpk_list.py
python tools/vpk_list.py --prefix scripts/ --ext vdata_c --list
Expected head of find_game.py at this build:
ClientVersion 6679 <-- verified_against
SourceRevision 10912166
VersionDate Aug 14 2026
archives 274 pak01_*.vpk (27.4 GiB)
To diff content against a later patch:
python tools/vpk_list.py --manifest > manifests/6679.txt
# after patching:
python tools/vpk_list.py --manifest > manifests/NEXT.txt
diff manifests/6679.txt manifests/NEXT.txt
Gotchas
pak01_dir.vpkalone is not enough to extract. It is only the index; bodies live in the numbered archives, so all 274 must be present. Reading the listing, however, needs only the dir file — that is whyvpk_list.pyis fast.- Sizes in the index are the compiled sizes. Decompiled output is much larger:
abilities.vdata_cis 485 KB packed and 7.0 MB as text. core/has its own pak01 set. Do not assume a path is incitadel/— engine-level assets resolve fromcore/.- Archive counts change every patch. 274 is a fact about build 6679, not a constant.
Open questions
- Not checked: whether
citadel_<lang>/overlay VPKs contain anything beyond localized audio, or whether any gameplay data differs per language. - Not checked:
shaders_*.vpkcontents at all. - Not checked: whether
--vpk_verifychecksums pass on this install. - The
.sofa(43.2 MB) and.datentries were seen in the index but not inspected.
Sources
- VPK file format — Valve Developer Community) (format description; the layout above was independently confirmed by parsing this install)