Crates.io | wow-mpq |
lib.rs | wow-mpq |
version | 0.3.2 |
created_at | 2025-06-14 01:34:05.112195+00 |
updated_at | 2025-08-29 03:59:31.217283+00 |
description | High-performance parser for World of Warcraft MPQ archives with parallel processing support |
homepage | https://github.com/wowemulation-dev/warcraft-rs |
repository | https://github.com/wowemulation-dev/warcraft-rs |
max_upload_size | |
id | 1712018 |
size | 1,156,332 |
A high-performance, safe Rust implementation of the MPQ (Mo'PaQ) archive format used by World of Warcraft and other Blizzard Entertainment games.
Production Ready - Feature-complete MPQ implementation with 100% StormLib bidirectional compatibility
MPQ archives are used by World of Warcraft (versions 1.x through 5.x) to store game assets including models, textures, sounds, and data files. This crate provides a pure Rust implementation for reading, creating, and managing MPQ archives with comprehensive support for all format versions and features.
Add to your Cargo.toml
:
[dependencies]
wow-mpq = "0.3.0"
Or use cargo add:
cargo add wow-mpq
use wow_mpq::{Archive, ArchiveBuilder, MutableArchive, AddFileOptions};
// Read an existing archive
let mut archive = Archive::open("Data/common.MPQ")?;
// List all files
for entry in archive.list()? {
println!("{}: {} bytes", entry.name, entry.size);
}
// Extract a file
let data = archive.read_file("Interface\\FrameXML\\GlobalStrings.lua")?;
// Create a new archive
ArchiveBuilder::new()
.add_file_data(b"Hello, Azeroth!".to_vec(), "readme.txt")
.version(wow_mpq::FormatVersion::V2)
.build("my_addon.mpq")?;
// Modify an existing archive
let mut mutable = MutableArchive::open("my_addon.mpq")?;
mutable.add_file_data(b"Updated content".as_ref(), "changelog.txt", AddFileOptions::default())?;
mutable.remove_file("old_file.txt")?;
mutable.rename_file("readme.txt", "README.txt")?;
mutable.flush()?; // Save all changes
Handle World of Warcraft's patch archive system with automatic priority-based file resolution:
use wow_mpq::PatchChain;
let mut chain = PatchChain::new();
chain.add_archive("Data/common.MPQ", 0)?; // Base priority
chain.add_archive("Data/patch.MPQ", 100)?; // Patch priority
chain.add_archive("Data/patch-2.MPQ", 200)?; // Higher priority
// Automatically gets the highest priority version
let data = chain.read_file("DBFilesClient\\Spell.dbc")?;
Optimize and upgrade archives with comprehensive rebuild options:
use wow_mpq::{RebuildOptions, rebuild_archive};
let options = RebuildOptions::new()
.target_version(FormatVersion::V4) // Upgrade to v4
.compression(CompressionType::Zlib) // Change compression
.remove_signatures(true) // Strip signatures
.progress_callback(|current, total| { // Track progress
println!("Progress: {}/{}", current, total);
});
rebuild_archive("old.mpq", "optimized.mpq", &options)?;
Verify and generate archive signatures for integrity protection:
use wow_mpq::crypto::{generate_weak_signature, SignatureInfo, WEAK_SIGNATURE_FILE_SIZE};
// Verify existing signatures
let archive = Archive::open("signed.mpq")?;
match archive.verify_signature()? {
SignatureStatus::None => println!("No signature"),
SignatureStatus::Weak => println!("Weak signature (512-bit RSA)"),
SignatureStatus::Strong => println!("Strong signature (2048-bit RSA)"),
SignatureStatus::Invalid => println!("Invalid signature!"),
}
// Generate new weak signature
let archive_data = std::fs::read("archive.mpq")?;
let sig_info = SignatureInfo::new_weak(
0, // Archive start
archive_data.len() as u64, // Archive size
archive_data.len() as u64, // Signature position
WEAK_SIGNATURE_FILE_SIZE as u64, // Signature file size
vec![],
);
let signature = generate_weak_signature(
std::io::Cursor::new(&archive_data),
&sig_info
)?;
The crate includes debug utilities for analyzing MPQ archives (requires
debug-utils
feature):
use wow_mpq::{Archive, debug};
// Enable the feature in Cargo.toml:
// wow-mpq = { version = "0.3.0", features = ["debug-utils"] }
let mut archive = Archive::open("example.mpq")?;
// Dump archive structure and metadata
debug::dump_archive_structure(&mut archive)?;
// Analyze compression methods used
debug::analyze_compression_methods(&mut archive)?;
// Dump table contents (hash table, block table)
debug::dump_hash_table(&archive)?;
debug::dump_block_table(&archive)?;
// Trace file extraction with detailed debugging
let config = debug::ExtractionTraceConfig {
show_raw_data: true,
show_decryption: true,
show_decompression: true,
max_raw_bytes: 256,
};
debug::trace_file_extraction(
&mut archive, "example.txt", &config
)?
// Create hex dumps of binary data
let data = archive.read_file("binary.dat")?;
let hex_config = debug::HexDumpConfig::default();
println!("{}", debug::hex_dump(&data, &hex_config));
Run the debug example to analyze any MPQ archive:
# Basic analysis
cargo run --example debug_archive --features debug-utils -- archive.mpq
# Trace specific file extraction
cargo run --example debug_archive --features debug-utils -- archive.mpq "(listfile)"
# Show detailed table dumps
SHOW_TABLES=1 cargo run --example debug_archive --features debug-utils -- archive.mpq
The crate includes comprehensive benchmarks showing excellent performance:
The crate includes numerous examples demonstrating real-world usage:
create_archive
- Basic archive creationpatch_chain_demo
- Working with WoW patch archiveswotlk_patch_chain_demo
- Complete WotLK patch handlingpatch_analysis
- Analyze patch archive contentssignature_demo
- Digital signature generation and verificationdebug_archive
- Debug utilities for analyzing MPQ internalsRun examples with:
cargo run --example patch_chain_demo
While achieving 100% StormLib compatibility for core functionality, the following performance and specialized features are not implemented:
Blizzard's MPQ implementation has some quirks that this library handles gracefully:
\
) as path separators. While
this library accepts forward slashes for convenience, they are automatically converted
to backslashes internally.Licensed under either of
at your option.