A fast, cross-platform explorer for CASC (Content-Addressable Storage Container) archives, written entirely in Rust.
Rusty Demon is the first tool of any kind, proprietary or open source, that can read the Steam-distribution CASC static container format used by Diablo IV. Neither CascLib nor the original TACTLib implementation handles the full Steam D4 layout (key-layout flags, zlib VFS roots, meta.dat / payload.dat distinction); rustydemon does. See Steam D4 Support below.
For personal and educational use only.
Three-panel layout: archive tree (left) · search results (centre) · file details with live 3D preview (right). Shown here previewing a WoW M2 character model.
| About modal | D4 .tex texture |
|---|---|
![]() |
![]() |
D4 .pow skill data |
WoW .m2 model |
|---|---|
![]() |
![]() |
- Regedit-style global search - searches every entry in the archive manifest, not just the currently selected folder
- File tree navigation - browse archives by folder with expand/collapse, Expand All / Collapse All
- Pluggable preview panel - formats register themselves through a
PreviewPlugintrait. Built-in plugins cover BLP textures (WoW),.texBC textures (D4),.powskill data (D4),.vidBink Video 2 movies (D4), and a generic UTF-8 text fallback. Add a format by dropping one file intorustydemon/src/preview/. - Pluggable export buttons - each preview plugin can register its own export actions (e.g. Export As PNG for textures, Export As BK2 for movies). Raw export is always available as a fallback.
- Deep search - optionally search inside container files via a parallel
ContentSearcherplug-in interface (.powD4 skill data supported out of the box). - Glob path search - search bar and CLI accept literal paths or glob
patterns (
*.wmo,textures/*.tex,**/cinematics/*.vid); matching is case-insensitive and**/is auto-prepended for convenience. - Headless CLI exporter (
rustydemon-cli) - batch-extract files from a local CASC install without launching the GUI. Supports path/glob/FDID selection, parallel workers, dry-run, flatten, and overwrite. See CLI below. - Auto product detection - reads
.build.infoso you never need to know internal product codes (fenris,wow, etc.) - Cross-platform - Windows · macOS · Linux · Steam Deck (touch-ready via egui)
- Steam Diablo IV support - first-ever reader for the Steam-distribution
static container format (no
.build.info, no encoding file, location encoded directly in each EKey) - Diablo II: Resurrected support - reads D2R 3.1.2's TVFS-based layout,
including the multi-storage
Data/data+Data/ecachesplit and archive-style.indexfiles, with an optional CDN fallback fetcher (behind thecdncargo feature).
Rusty Demon is, to the best of our knowledge, the first publicly-available tool, free, paid, or otherwise, that can open the Steam distribution of Diablo IV's CASC archives. The Steam build ships with a fundamentally different storage layout than the Battle.net client:
| Battle.net D4 | Steam D4 | |
|---|---|---|
| Manifest entry point | .build.info |
Data/.build.config |
| Archive files | data.NNN |
{chunk}/0x{archive}-{meta,payload}.dat |
| Location lookup | *.idx index files |
Bits inside each EKey |
| Encoding table | encoding file |
(none -CKey ≡ EKey) |
| VFS root wrapper | BLTE | Raw zlib (espec = z) |
| Data header | 30-byte prefix | None |
Rustydemon auto-detects which layout is in use and picks the right backend.
Point File → Open Game Directory… at either
C:\Program Files (x86)\Diablo IV (Battle.net) or
…/steamapps/common/Diablo IV (Steam) and it just works.
Neither CascLib nor the TACTLib
StaticContainerHandlerimplements the full Steam D4 format: TACTLib's handler hard-codes a singledata.{chunk}.{archive}path layout used only by Overwatch, ignores the 4th (flags) value inkey-layout-*, and doesn't handle the zlib-compressed VFS root. Rustydemon'sstatic_containermodule inrustydemon-libis a clean-room implementation that verified all of these against a real Steam installation.
| Platform | Requirement |
|---|---|
| All | Rust stable toolchain (1.80+) |
| Linux / Steam Deck | libgtk-3-dev (or equivalent) - see below |
| Windows / macOS | Nothing extra; eframe bundles everything |
Linux / Steam Deck system deps:
# Debian / Ubuntu / Kali
sudo apt install libgtk-3-dev libxcb-render0-dev libxcb-shape0-dev \
libxcb-xfixes0-dev libxkbcommon-dev libssl-dev
# Arch / Steam Deck
# Note: Just try to run rustydemon first. SteamOS probably has these already.
# If not, you'll have to `sudo steamos-readonly disable`, install, then
# `sudo steamos-readonly enable` immediately after the install is done.
sudo pacman -S gtk3 libxcb xkbcommon openssl
# Fedora
sudo dnf install gtk3-devel libxcb-devel libxkbcommon-devel openssl-develSteam Deck (Desktop Mode): SteamOS has very limited space outside
/home, so install Homebrew,rustup, andgccto your SD card rather than the internal drive. Once Rust is available, install the Arch deps above viapacmanand build normally. Game files live at/home/deck/.steam/steam/steamapps/common/<Game>- point File → Open Game Directory… there.
git clone https://github.com/jabberwock/rustydemon.git
cd rustydemon
cargo run --release -p rustydemonThe first build downloads and compiles all dependencies (~3–5 minutes). Subsequent builds are incremental and much faster.
File → Open Game Directory… and select your game's installation root
(the folder that contains .build.info for Battle.net installs, or
Data/.build.config for Steam installs).
The product UID is detected automatically:
| Game | Detected as |
|---|---|
| World of Warcraft | wow |
| Diablo IV | fenris |
| Diablo II: Resurrected | osi |
| Diablo III | d3 |
| Hearthstone | hs |
| Heroes of the Storm | hero |
| StarCraft II | s2 |
| Overwatch | pro |
Without a listfile, files are shown by hash only. With one, the full virtual path is resolved and the tree is populated.
File → Load Listfile… and pick a community listfile (CSV or plain text). A maintained listfile can be downloaded from the wowdev community listfile project.
Type a filename fragment in the search bar and press Enter or click Search. Results are drawn from the entire root manifest, every locale and content variant, so nothing is hidden behind an unexpanded folder.
The query can be a literal substring or a glob: *.wmo, textures/*.tex,
**/cinematics/*.vid. Matching is case-insensitive, and **/ is
auto-prepended unless the pattern already anchors at / or **/.
Check Deep search and click 🔍 Find All (Deep Search) to also search inside supported container files:
| Format | What is indexed |
|---|---|
.pow |
D4 skill/power definitions, SF names, damage formulas |
| (more formats via the plug-in interface) |
Click any file in the tree or search results to load it into the preview panel.
- BLP textures render inline
- All other files show a hex dump of the first 256 bytes
- Export As PNG saves a decoded BLP to disk via a native dialog
rustydemon-cli is a headless batch exporter for scripting and
server-side extraction. The GUI binary remains the way to browse
interactively.
cargo run --release -p rustydemon-cli -- \
--archive "/home/deck/.steam/steam/steamapps/common/Diablo IV" \
--path "base/meta/Sound" \
--output ./outKey flags:
| Flag | Purpose |
|---|---|
-a, --archive <DIR> |
Game install root (Battle.net or Steam) |
-p, --path <PATH> |
Literal folder, literal file, or glob (*.wmo, **/cinematics/*.vid) |
--fdid <N> |
Extract a single WoW file by FileDataID (no listfile needed) |
-l, --listfile <FILE> |
Listfile for WoW (required to resolve paths) |
-o, --output <DIR> |
Host directory; created if missing |
--flat |
Drop files into --output instead of mirroring virtual dirs |
--dry-run |
Print matches without writing |
--overwrite |
Replace existing files (default: skip) |
-j, --parallel <N> |
Worker thread count (defaults to CPU cores) |
-q, --quiet |
Suppress progress bar |
D4 and other TVFS-based archives self-describe, so --listfile is not
needed there. For WoW, pass either --listfile or --fdid.
rustydemon/
├── rustydemon-blp2/ BLP0/1/2 texture decoder (palette, DXT1/3/5, ARGB, JPEG)
├── rustydemon-lib/ CASC library (config, index, encoding, BLTE, root, search)
├── rustydemon-cli/ Headless batch exporter (clap + rayon)
└── rustydemon/ egui/eframe GUI application
- Fork and create a feature branch
cargo test --workspacemust passcargo fmt --allandcargo clippy --workspace -- -D warningsmust be clean- Open a PR - CI runs fmt, clippy, tests, and a RustSec security audit automatically
Listfile improvements and new deep-search plug-ins are especially welcome.
Built on the shoulders of the CASC reverse-engineering community:
- CascLib by Ladislav Zezula - the C library for reading CASC archives and our primary reference for BLTE, encoding, root manifests, MNDX/MARR, and more.
- CASC Explorer by the WoW-Tools team - the original .NET GUI for browsing CASC archives. Rusty Demon's UI takes cues from CASC Explorer's design.
- TACTLib by the Overtools team - a C# CASC implementation whose TVFS and static-container work was a useful reference.
- SereniaBLPLib by Xalcon -
BLP texture parsing and DXT decompression in
rustydemon-blp2are derived from this MIT-licensed C# library (seerustydemon-blp2/CREDITS). - wowdev.wiki and the datamining community - for documenting CASC/TACT formats and maintaining the community listfiles.
Source licensed under AGPL-3.0 with the Commons Clause - free to read, build, and use for personal and educational purposes.
Commercial distribution (e.g. Steam store builds) is reserved to the maintainers under a separate proprietary license. See COMMERCIAL.md for the dual-licensing details and the contributor license grant that applies to pull requests.



