CDMW Archive Lite is a standalone, read-only Windows desktop application for browsing Crimson Desert PAMT/PAZ archives. It can search, inspect, preview, and export archive content without modifying the source archives.
The application is self-contained in this repository and keeps archive queries, decoding, media conversion, and mesh rendering outside the UI process.
- Browse large archives through a folder tree or a flat list, with an optional category navigator, paging, filters, sorting, and persistent indexes.
- Search text across archives or loose folders with cancellation, result limits, and in-file navigation.
- Find known items by localized name and follow exact or related archive links.
- Preview text, XML, images, DDS textures, supported media including the sounds a Wwise
.bnkembeds, archive metadata, and read-only PAC/PAM/PAMLOD/PAT geometry. - Export a mesh as OBJ, GLB or FBX, byte-identical to what the full CDMW workbench writes. A skinned character carries its skeleton and its per-vertex weights into GLB and FBX, so it arrives posable rather than as a frozen shell.
- Discover and export associated assets without altering game data.
- Run as a portable Windows application or a single self-extracting executable.
- Switch the interface between the fourteen languages Crimson Desert itself ships; every one but English is machine translated and unreviewed.
- Keep settings, caches, logs, and crash reports isolated from the full CDMW workbench.
Archive Lite has no archive-write, replacement, patching, backup, restore, or mod-building authority. PAMT, PAZ, and PATHC sources are opened read-only, and exports are written to a separate destination selected by the user.
The repository does not contain game archives, extracted game assets, or other local game data.
- Windows 11 x64
- .NET 10 SDK
- CMake 3.24 or newer
- Visual Studio 2022 Build Tools with the Desktop C++ workload
- PowerShell
Pinned third-party sources are documented in DEPENDENCY-SOURCES.md.
First run the focused nonvisual gate:
.\scripts\test_archive_lite.ps1 -Configuration DebugThen launch the desktop application:
dotnet run --project .\src\Cdmw.ArchiveLite.App\Cdmw.ArchiveLite.App.csproj -c DebugThe launch command opens a visible desktop window and is intentionally separate from automated validation.
For a fresh standalone executable, run:
BUILD-FRESH-EXE.bat
For the complete verified Release package:
.\scripts\build_archive_lite.ps1Build outputs are written beneath the ignored artifacts/ directory. On a clean checkout, pinned native dependencies are downloaded into the ignored .tools/ directory.
flowchart TD
UI["App"]
W["Worker"]
MESH["Mesh viewport"]
CORE["Archive core"]
HELP["Native helpers"]
CONTENT["Content library"]
UI -->|named pipe| W
UI -->|child process| MESH
W --> CORE
W --> HELP
W --> CONTENT
| node | process or library | responsibility |
|---|---|---|
| App | CdmwArchiveLite.exe |
WPF presentation and selection state |
| Worker | CdmwArchiveLite.Worker.exe |
archive queries, search, preview, export |
| Mesh viewport | cdmw-mesh-dotnet-editor.exe |
read-only Vortice D3D11 rendering |
| Archive core | cdmw-archive-core.dll |
read-only PAMT / PAZ / PATHC decoding |
| Native helpers | helper processes | indexing, DDS, model and media preparation |
| Content library | managed | semantic archive documents |
The named pipe carries request IDs and cancellation. The UI owns presentation; long-running work stays cancellable in the worker or a dedicated native process, and the renderer runs in its own child process.
A model preview is assembled from the geometry, its material sidecar, and the textures those materials name. Crimson packs surface response into one map, so the preview reads the channels rather than guessing from a filename.
flowchart LR
PAC["geometry"] --> P["Preview core"]
XML["materials"] --> P
DDS["textures"] --> P
P --> A["Adapter"] --> R["Renderer"]
.pac geometry, the .pac_xml material sidecar, and the .dds textures it names go to the preview core, which assigns each binding a role, selects a slot per submesh, and resolves colour layers. The adapter turns that into channels, packed components, and layer bindings; the renderer samples them.
| suffix | role | notes |
|---|---|---|
X.dds |
albedo | the part's own colour |
X_n.dds |
normal | two-channel BC5; Z is rebuilt |
X_sp.dds |
surface response | G roughness, B metalness |
X_ma.dds |
colour-blending mask | selects among colour layers, not a response map |
X_emi.dds |
emissive intensity | single-channel BC4; the colour is authored, not sampled |
X_disp.dds |
height | |
X_f.dds |
strand direction | orients the anisotropic hair highlight |
Preview output is checked against the assets themselves rather than by eye. PREVIEW-MATERIAL-AUDIT.md records the method, what is confirmed authored, and which explanations were refuted.
| measured over | result |
|---|---|
| brightness reproduced vs. the asset's own textures | 0.982 (1.000 = exact) |
| colour reproduced vs. the asset's own textures | 0.926 |
| lighting preserves albedo, lit/unlit over 728 assets | 0.97 – 1.01 |
| equipment assets rendered and compared | ~5,400 |
| whole-corpus scans of all 12,340 equipment PACs | 4 |
A mesh exports as OBJ, GLB or binary FBX. The vertices, their order and the part names are byte-identical to what the full CDMW workbench writes, so a mesh exported here and one exported there can be joined as shape keys without moving a vertex.
| OBJ | GLB | FBX | |
|---|---|---|---|
| geometry, in the archive's own units and order | yes | yes | yes |
| material names, and a material library | .mtl |
material per part | material per part |
| armature and per-vertex weights | — | yes | yes |
| bones written | — | those the mesh uses, plus their ancestors | the whole skeleton |
| round-trip sidecar naming the source entry | .obj.meta.json |
— | — |
Geometry is in game units, and a game unit is a metre: a character body measures 1.84 tall in all three. The FBX declares this rather than leaving an importer to assume centimetres.
Only a skinned .pac carries a rig. A rigidly bound mesh — a prop, an accessory, a vehicle — puts
its whole weight on one influence and records no bone anywhere in the file, so the bone it follows
is not the mesh's to state; it exports unrigged. So does a smooth-skinned mesh whose bone palette
no skeleton named by its own path accounts for, which is most NPC and monster gear. The preview
package records which of those cases it found and why.
scripts/blender/ holds a headless script that imports an export, checks every vertex is weighted
and sums to 1.0, poses a bone and asserts the vertices that moved are the ones near it. It is not
part of the focused gate, since it needs Blender and licensed game assets.
These are asserted by the focused gate, not measured by hand. scripts/test_archive_lite.ps1 -Configuration Debug reproduces them.
| focused scenarios | 53, covering archive, preview, export, worker lifetime and cache eviction |
| model preview, cold cache | ~100 ms |
| model preview, warm cache | ~1 ms, and warm across sessions |
| renderer | headless GPU soak, production D3D11 backend, windows stay hidden |
| archive access | read-only; export is contained, atomic and manifested |
src/— WPF application, worker, shared contracts, and managed archive servicesnative/— read-only archive and preview implementationstools/— repository-owned helper and renderer projectstests/— managed regression coverage and synthetic fixturesscripts/— focused validation and packaging entry pointsschemas/— versioned repository-owned data contracts.github/— GitHub Actions, dependency update configuration, and collaboration templates
Portable builds keep settings, caches, logs, and crash reports beside the executable. The single-file launcher extracts its verified runtime beneath %LocalAppData%\CDMW\CDMWArchiveLite\standalone\; it does not place user settings, game data, or exports there.
These paths and all build outputs are excluded from version control.
Neither package is code-signed. The standalone launcher unpacks its runtime — 990 files, 978 of them DLLs and EXEs — and then starts it, and that sequence is what scanners react to: Microsoft Defender's machine-learning heuristic has flagged a fresh release as Trojan:Win32/Wacatac.B!ml, VirusTotal carries generic packed-executable names such as Trojan.Win64.Crypt, and its sandbox reports the PEs written as executable creation and the asynchronous write handles bound to I/O completion ports as Data Encrypted for Impact (T1486). All are false positives, and nothing already on the disk is read, changed or deleted. Each release lists the SHA-256 of both packages, and the portable zip carries the same application as ordinary files rather than as a self-extracting executable.
- TESTING.md - validation matrix and proof boundaries
- PREVIEW-MATERIAL-AUDIT.md - how a preview is checked against its source, what is confirmed authored, and which explanations were refuted
- CONTRIBUTING.md - development and review expectations
- SECURITY.md - supported versions and private reporting
- CHANGELOG.md - notable version changes
- THIRD-PARTY-NOTICES.md - bundled component notices
MIT. Bundled third-party components keep their own licences, listed in THIRD-PARTY-NOTICES.md.
Archive Lite reads game files that it never ships. It contains no Crimson Desert content, and the archives it opens stay read-only. Whatever you export from your own installation remains subject to the game's own terms.