Skip to content
This repository was archived by the owner on Jun 30, 2025. It is now read-only.

danielsreichenbach/mopaq

mopaq

A high-performance, safe Rust implementation of the MPQ (Mo'PaQ) archive format used by Blizzard Entertainment games.

This project is moving into a new collection of crates to deal with WoW 1.x to 5.x file formats.

See warcraft-rs!

License License

Features

  • 🚀 Full MPQ Format Support: Implements all MPQ versions (v1-v4) with complete feature parity
  • 🔒 Security First: Safe Rust implementation with comprehensive error handling
  • High Performance: Memory-mapped I/O, zero-copy operations, and efficient caching
  • 🔧 StormLib Compatible: Drop-in replacement via FFI bindings (in development)
  • 🗜️ Compression Support: Multiple compression methods (zlib, bzip2, LZMA, sparse, PKWare DCL, IMA ADPCM)
  • 🔐 Encryption Support: Full encryption/decryption for protected archives
  • 📚 HET/BET Tables: Support for v3+ hash/block extended tables used in WoW 4.3.4+
  • 🛠️ Rich CLI Tool: Comprehensive command-line interface with debugging capabilities
  • 📊 Well Tested: Extensive test suite with fuzzing and benchmarks
  • 🦀 Pure Rust: No system dependencies required (using lzma-rs for LZMA support)

Project Structure

  • mopaq: Core MPQ library (named after the original Mo'PaQ format)
  • storm-ffi: StormLib-compatible C API bindings (in development)
  • storm-cli: Command-line tool for MPQ operations

Installation

As a Rust Library

[dependencies]
mopaq = "0.1"

CLI Tool

cargo install storm-cli

C/C++ FFI

The storm-ffi crate provides a StormLib-compatible C API (currently in development). See the FFI documentation for integration details.

Quick Start

Rust API

use mopaq::{Archive, OpenOptions};

fn main() -> mopaq::Result<()> {
    // Open an existing MPQ archive
    let mut archive = Archive::open("StarCraft.mpq")?;

    // List all files
    for entry in archive.list()? {
        println!("{} ({} bytes)", entry.name, entry.size);
    }

    // Extract a specific file
    let data = archive.read_file("unit\\terran\\marine.grp")?;
    std::fs::write("marine.grp", data)?;

    // Create a new archive
    let mut new_archive = OpenOptions::new()
        .version(mopaq::FormatVersion::V2)
        .create("my_archive.mpq")?;

    // Note: Use ArchiveBuilder for adding files (see below)

    Ok(())
}

Archive Creation

use mopaq::{ArchiveBuilder, FormatVersion, ListfileOption};

fn main() -> mopaq::Result<()> {
    // Create a new archive with files
    ArchiveBuilder::new()
        .version(FormatVersion::V2)
        .add_file("readme.txt", "readme.txt")
        .add_file_data(b"Hello, MPQ!".to_vec(), "greeting.txt")
        .default_compression(mopaq::compression::flags::ZLIB)
        .build("my_archive.mpq")?;

    Ok(())
}

Encrypted Archive Creation

use mopaq::{ArchiveBuilder, FormatVersion};

fn main() -> mopaq::Result<()> {
    // Create an archive with encrypted files and CRC protection
    ArchiveBuilder::new()
        .version(FormatVersion::V3)  // V3 includes HET/BET tables
        .generate_crcs(true)  // Enable sector CRC generation
        .add_file_with_encryption(
            "secret.dat",
            "data/secret.dat",
            mopaq::compression::flags::ZLIB,
            true,  // use_fix_key
            0,     // locale
        )
        .add_file("readme.txt", "readme.txt")  // Unencrypted file
        .build("encrypted.mpq")?;

    Ok(())
}

Advanced V3 Archive with Compressed Tables

use mopaq::{ArchiveBuilder, FormatVersion, compression::flags};

fn main() -> mopaq::Result<()> {
    // Create a V3 archive with compressed HET/BET tables for space efficiency
    ArchiveBuilder::new()
        .version(FormatVersion::V3)
        .compress_tables(true)  // Enable HET/BET table compression
        .table_compression(flags::ZLIB)  // Use zlib for table compression
        .default_compression(flags::LZMA)  // Use LZMA for file compression
        .generate_crcs(true)  // Enable sector CRC generation
        .add_file("data/large_file.bin", "game/assets/large_file.bin")
        .add_file("scripts/main.lua", "scripts/main.lua")
        .build("optimized.mpq")?;

    // The resulting archive will have:
    // - Compressed files using LZMA
    // - Compressed HET/BET tables using zlib
    // - Sector CRC validation
    // - Efficient storage for large file counts

    Ok(())
}

Crypto Example

use mopaq::crypto::{encrypt_block, decrypt_block};

// Encrypt some data
let mut data = vec![0x12345678, 0x9ABCDEF0];
let key = 0xDEADBEEF;

encrypt_block(&mut data, key);
println!("Encrypted: {:08X?}", data);

decrypt_block(&mut data, key);
println!("Decrypted: {:08X?}", data);

Attributes Example

use mopaq::Archive;

fn main() -> mopaq::Result<()> {
    let mut archive = Archive::open("game.mpq")?;

    // Load attributes if present
    archive.load_attributes()?;

    // Get attributes for a specific file
    if let Some(entry) = archive.find_file("units\\human\\footman.mdx")? {
        if let Some(attrs) = archive.get_file_attributes(entry.block_index) {
            if let Some(crc32) = attrs.crc32 {
                println!("CRC32: 0x{:08X}", crc32);
            }
            if let Some(md5) = attrs.md5 {
                println!("MD5: {:02X?}", md5);
            }
            if let Some(timestamp) = attrs.filetime {
                println!("Timestamp: {}", timestamp);
            }
        }
    }

    Ok(())
}

Hash Example

use mopaq::hash::{hash_string, hash_type};

// Generate hash values for file lookup
let filename = "units\\human\\footman.mdx";
let hash_a = hash_string(filename, hash_type::NAME_A);
let hash_b = hash_string(filename, hash_type::NAME_B);
let table_index = hash_string(filename, hash_type::TABLE_OFFSET);

println!("Hash A: 0x{:08X}", hash_a);
println!("Hash B: 0x{:08X}", hash_b);
println!("Table Index: 0x{:08X}", table_index);

Digital Signature Verification

use mopaq::Archive;

fn main() -> mopaq::Result<()> {
    let mut archive = Archive::open("signed_archive.mpq")?;

    // Verify digital signature (checks both weak and strong signatures)
    match archive.verify_signature()? {
        mopaq::archive::SignatureStatus::None => {
            println!("Archive has no digital signature");
        }
        mopaq::archive::SignatureStatus::WeakValid => {
            println!("✅ Weak signature is valid (512-bit RSA + MD5)");
        }
        mopaq::archive::SignatureStatus::WeakInvalid => {
            println!("❌ Weak signature is invalid");
        }
        mopaq::archive::SignatureStatus::StrongValid => {
            println!("✅ Strong signature is valid (2048-bit RSA + SHA-1)");
        }
        mopaq::archive::SignatureStatus::StrongInvalid => {
            println!("❌ Strong signature is invalid");
        }
        mopaq::archive::SignatureStatus::StrongNoKey => {
            println!("Strong signature found but no public key available");
        }
    }

    Ok(())
}

CLI Usage

storm-cli supports tab completion for bash, zsh, fish, and PowerShell.

# List files in an archive
storm-cli file list StarCraft.mpq

# Extract files
storm-cli file extract StarCraft.mpq --output ./extracted

# Create a new archive
storm-cli archive create my_mod.mpq ./mod_files

# Verify archive integrity
storm-cli archive verify WarCraft3.w3m

# Show archive information (including compressed table sizes for v3+ archives)
storm-cli archive info Diablo2.mpq

# Display table contents
storm-cli table show Diablo2.mpq --table-type hash

# Generate hash values for debugging
storm-cli hash generate "(listfile)" --all

# Compare hashes to check for collisions
storm-cli hash compare "file1.txt" "file2.txt"

# Analyze compression methods used in archives
storm-cli archive analyze WoW.mpq --show-stats
storm-cli archive analyze WoW.mpq --by-extension --detailed
storm-cli archive analyze WoW.mpq --unsupported-only

Compression Analysis

The analyze command provides detailed insights into compression method usage across MPQ archives, helping prioritize which algorithms to implement for maximum compatibility:

# Comprehensive analysis with statistics
storm-cli archive analyze archive.mpq --show-stats --by-extension

# Focus on unsupported compression methods
storm-cli archive analyze archive.mpq --unsupported-only --detailed

# Export analysis data for scripting
storm-cli archive analyze archive.mpq --output json > analysis.json

Key Findings from Real-World Archive Analysis:

  • WoW 1.x-3.x archives: All compression methods supported ✅
  • WoW 4.x+ archives: Contains unsupported compression combinations in HET/BET table metadata:
    • ADPCM + Implode compression (prevents archive opening)
    • ADPCM + PKWare combinations
    • Complex ADPCM combinations (flag 0xC9)
  • Most file content: Uses "None" compression with format-level compression (e.g., .ogg, .jpg)

Current Status - StormLib Compatibility: ~90%

Overall Project Completion:

  • 📖 Archive Reading: 98% complete (excellent)
  • 🔧 Archive Creation: 90% complete (very good)
  • ✏️ Archive Modification: 0% complete (major gap)
  • 🗜️ Compression: 85% complete (missing 3 algorithms)
  • 🔐 Cryptography: 95% complete (missing signature creation)
  • 📊 Advanced Features: 70% complete (missing patches, protection)
  • 🔌 StormLib FFI: 70% complete (core functions done)
  • 🧪 Testing: 95% complete (comprehensive coverage)

Implemented ✅

  • Archive Reading

    • ✅ All MPQ versions (v1-v4) header parsing
    • ✅ Hash table and block table reading
    • ✅ Hi-block table support for large archives
    • ✅ HET/BET table reading (v3+) with compression support
    • ✅ File extraction with all supported compression methods
    • ✅ Encryption/decryption with key calculation
    • ✅ Sector-based file reading
    • ✅ CRC validation (100% validation success rate across 2,613 WoW files)
    • ✅ Archive integrity verification
    • ✅ Digital signature verification (100% StormLib compatible)
      • ✅ Weak signatures (512-bit RSA with MD5, v1+) - Complete with StormLib-compatible hash calculation
      • ✅ Strong signatures (2048-bit RSA with SHA-1, v2+) - Detection and parsing complete
      • ❌ Signature creation/generation (missing for both weak and strong)
    • ✅ (attributes) file parsing
      • CRC32 checksums, MD5 hashes, timestamps, patch indicators
    • ✅ Enhanced file enumeration with hash information
  • Archive Creation

    • ✅ Create new archives (v1-v3)
    • ✅ Add files with compression (all supported algorithms)
    • ✅ Automatic hash table sizing (power-of-two validation)
    • ✅ Listfile generation
    • ✅ Multi-sector file support
    • ✅ File encryption with FIX_KEY support
    • ✅ Sector CRC generation and validation
    • ✅ Hi-block table writing for large archives (v2+)
    • ✅ HET/BET table creation (v3+) - 100% complete with full bit-packing
    • ✅ HET/BET table compression (v3+) with configurable algorithms
    • ✅ Archive creation from disk files and in-memory data
    • In-place file operations (add/remove/rename to existing archives)
    • Archive compacting (remove deleted entries)
  • Compression (85% complete)

    • ✅ Zlib/Deflate (compression + decompression)
    • ✅ BZip2 (compression + decompression)
    • ✅ LZMA (compression + decompression, using pure Rust lzma-rs)
    • ✅ Sparse/RLE (compression + decompression)
    • ✅ PKWare DCL (compression + decompression)
    • ✅ IMA ADPCM Mono/Stereo (compression + decompression with channel validation)
    • 🔨 Huffman (decompression only - can read but not create)
    • 🔨 PKWare Implode (decompression only - can read but not create)
    • ✅ Multi-compression: ADPCM + one other algorithm
    • ❌ Multi-compression: 3+ algorithms in sequence
    • ✅ Automatic decompression of all supported formats
  • Cryptography (95% complete)

    • ✅ Encryption table generation (compile-time constants)
    • ✅ File encryption/decryption (single-unit and multi-sector)
    • ✅ Table encryption/decryption
    • ✅ Key calculation algorithms with FIX_KEY support
    • ✅ Jenkins hash for HET tables
    • ✅ All MPQ hash types (table offset, name hashes, file keys)
    • Digital signature verification (weak and strong)
    • Digital signature creation/generation
    • ✅ Sector CRC generation and validation
  • CLI Tool

    • ✅ Archive operations: list, extract, find, verify, create
    • ✅ Enhanced file listing:
      • --all shows ALL table entries, not just listfile contents
      • --show-hashes displays MPQ name hashes for file mapping
      • Verbose mode shows sizes, compression ratios, and flags
      • Very verbose mode includes compression statistics
    • ✅ Digital signature verification display with color coding
    • ✅ Comprehensive debug commands (info, crypto, hash, tables)
    • ✅ Hash calculation and collision detection
    • ✅ Table inspection (hash, block, HET/BET)
    • ✅ Multiple output formats (Text, JSON, CSV)

In Progress 🚧

  • 🚧 v4 format creation with MD5 checksums (header structure complete, MD5 calculation in progress)
  • 🚧 StormLib FFI compatibility layer (70% complete - core functions implemented)
  • 🚧 Strong signature verification (detection complete, full verification in progress)

Planned 📋 (Missing Features for 100% StormLib Compatibility)

High Priority (Required for StormLib Parity):

  • 📋 In-place archive modification - Add/remove/rename files in existing archives
  • 📋 Complete compression support:
    • Huffman compression (decompression works, compression not implemented)
    • PKWare Implode compression (decompression works, compression not implemented)
    • Multiple compression combinations (3+ algorithms in sequence)
  • 📋 Digital signature generation - Create weak and strong signatures (verification is complete)
  • 📋 Streaming API - Support for large file operations with progress callbacks
  • 📋 Archive compacting - Remove deleted entries and optimize layout

Medium Priority (Advanced Features):

  • 📋 Patch archive support - Base/patch archive chaining
  • 📋 Protected MPQ handling - Copy-protected archive support
  • 📋 Advanced locale/platform support - Multi-language file handling
  • 📋 Memory-mapped file support - Better performance for large archives
  • 📋 Comprehensive archive verification - Beyond basic signature verification

Low Priority (Optimizations):

  • 📋 Parallel compression support - Multi-threaded compression
  • 📋 Unicode filename support - Enhanced UTF-8 handling
  • 📋 Archive optimization tools - Repair and optimization utilities

Supported Games

  • Diablo (1996)
  • StarCraft (1998)
  • Diablo II (2000)
  • WarCraft III (2002)
  • World of Warcraft (2004-present)
  • StarCraft II (2010)
  • Heroes of the Storm
  • And other Blizzard games using MPQ format

Performance

mopaq is designed for high performance:

  • Memory-mapped I/O for large archives
  • Zero-copy operations where possible
  • Efficient hash table lookups with caching
  • Parallel decompression support (planned)

See benchmarks for detailed performance comparisons.

Architecture

The project consists of three main components:

  1. mopaq - Core library with pure Rust implementation
  2. storm-ffi - C-compatible FFI bindings for StormLib compatibility
  3. storm-cli - Feature-rich command-line tool

See architecture documentation for details.

Contributing

Contributions are welcome! Please see CONTRIBUTING.md for guidelines.

Development Setup

# Clone the repository
git clone https://github.com/danielsreichenbach/mopaq
cd mopaq

# Run tests
cargo test --all

# Run benchmarks
cargo bench

# Build everything
cargo build --all

# Run the CLI tool
cargo run --bin storm-cli -- file list test.mpq

Testing

The project includes comprehensive tests:

# Run all tests
cargo test --all

# Run specific test suites
cargo test -p mopaq compression  # Compression tests
cargo test -p mopaq crypto       # Cryptography tests
cargo test -p mopaq hash         # Hash function tests
cargo test -p mopaq builder      # Archive creation tests

# Run with logging
RUST_LOG=debug cargo test

License

Licensed under either of:

at your option.

Acknowledgments

  • Ladislav Zezula for the original StormLib implementation
  • The wowdev community for format documentation
  • All contributors to MPQ format reverse engineering efforts

Related Projects

About

Merged into warcraft-rs !!! MPQ (Mo'PaQ) archive implementation in Rust

Topics

Resources

License

Apache-2.0, MIT licenses found

Licenses found

Apache-2.0
LICENSE-APACHE
MIT
LICENSE-MIT

Code of conduct

Contributing

Security policy

Stars

Watchers

Forks

Languages