05 — File Formats & Original Source Insights
For the broader engine-completeness inventory across Dune II, Tiberian Dawn, Red Alert 1, Red Alert 2 / Yuri’s Revenge, the Remastered Collection, and Generals / Zero Hour, see Complete Resource Format Support Map. This page remains the narrower canonical scope for the current cnc-formats / ic-cnc-content split.
Canonical Completeness Bar
At the engine level, Iron Curtain’s resource-support bar is broader than the current cnc-formats crate surface: the engine must be able to directly load the original resource families of Dune II, Tiberian Dawn, Red Alert 1, Red Alert 2 / Yuri’s Revenge, the Remastered Collection, and Generals / Zero Hour.
This is a support requirement, not a requirement that a single parser crate owns every family. The split is:
cnc-formatsis canonical for the clean-room classic Westwood / Petroglyph 2D family and closely related standalone tooling formats.ic-cnc-contentand game-module-specific loaders own game-specific families that depend on EA-derived details or exceed the classic Westwood 2D scope.- Additional sibling parser crates are allowed when a game family is structurally distinct enough that forcing it into
cnc-formatswould reduce clarity. The current obvious candidates are Dune II-specific resource families and SAGE-family formats for Generals / Zero Hour.
So the completeness question is always: “can IC load the original resource directly?” not “did cnc-formats personally absorb every format?”
Formats to Support (cnc-formats + ic-cnc-content)
Binary Formats (from original game / OpenRA)
| Format | Purpose | Notes |
|---|---|---|
.mix | Archive container | Flat archive with CRC-based filename hashing (rotate-left-1 + add), 6-byte FileHeader + sorted SubBlock index (12 bytes each). Extended format adds Blowfish-encrypted header index + SHA-1 body digest (read-only decrypt via hardcoded symmetric key, blowfish RustCrypto crate). No per-file compression. No path traversal risk (files identified by CRC hash, not filenames). See § MIX Archive Format for full struct definitions |
.shp | Sprite sheets | Frame-based, palette-indexed (256 colors). ShapeBlock_Type container with per-frame Shape_Type headers. LCW-compressed frame data (or uncompressed via NOCOMP flag). Supports compact 16-color mode, horizontal/vertical flip, scaling, fading, shadow, ghost, and predator draw modes |
.tmp | Terrain tiles | IFF-format icon sets — collections of 24×24 palette-indexed tiles. Chunks: ICON/SINF/SSET/TRNS/MAP/RPAL/RTBL. SSET data may be LCW-compressed. RA version adds MapWidth/MapHeight/ColorMap for land type lookup. TD and RA IControl_Type structs differ — see § TMP Terrain Tile Format |
.pal | Color palettes | Raw 768 bytes (256 × RGB), no header. Components in 6-bit VGA range (0–63), not 8-bit. Convert to 8-bit via left-shift by 2. Multiple palettes per scenario (temperate, snow, interior, etc.) |
.aud | Audio | Westwood IMA ADPCM compressed. 12-byte AUDHeaderType: sample rate (Hz), compressed/uncompressed sizes, flags (stereo/16-bit), compression ID. Codec uses dual 1424-entry lookup tables (IndexTable/DiffTable) for 4-bit-nibble decoding. Read + write: Asset Studio (D040) converts .aud ↔ .wav/.ogg so modders can extract original sounds for remixing and convert custom recordings to classic AUD format |
.vqa | Video | VQ vector quantization cutscenes. Chunk-based IFF structure (WVQA/VQHD/FINF/VQFR/VQFK). Codebook blocks (4×2 or 4×4 pixels), LCW-compressed frames, interleaved audio (PCM/Westwood ADPCM/IMA ADPCM). Read + write: Asset Studio (D040) converts .vqa ↔ .mp4/.webm for campaign creators |
.vqp | VQ palette tables | VQ Palette — precomputed 256×256 color interpolation lookup tables for smooth 2× horizontal stretching of paletted VQA video at SVGA resolution. Companion sidecar to .vqa files (e.g., SIZZLE.VQA + SIZZLE.VQP). Structure: 4-byte LE count of tables, then N tables of 32,896 bytes each (lower triangle of symmetric 256×256 matrix: (256 × 257) / 2 = 32,896 entries). Lookup: interpolated_pixel = table[left_pixel][right_pixel] produces the visual average of two adjacent palette-indexed pixels. One table per palette change in the VQA. Source: EA’s released CONQUER.CPP (Load_Interpolated_Palettes, Rebuild_Interpolated_Palette) and Gordan Ugarkovic’s vqp_info.txt. Read-only — no modern use case (GPU scaling replaces palette interpolation); parsed for completeness and Classic render mode (D048) |
.wsa | Animations | Westwood Studios Animation. LCW-compressed XOR-delta frames. Used for menu backgrounds, installation screens, campaign map animations. Header with frame offsets, optional embedded palette. Loop-back delta for seamless looping. See § WSA Animation Format |
.fnt | Bitmap fonts | Westwood bitmap font format for in-game text. Header with offset/width/height tables, 4bpp nibble-packed palette-indexed glyph bitmaps (two pixels per byte, high nibble first; index 0 = transparent). Read-only — IC uses modern TTF/OTF via Bevy for runtime text; .fnt parsed for Classic render mode (D048) fidelity and Asset Studio (D040) preview. See § FNT Bitmap Font Format |
.mid | MIDI music/SFX | Standard MIDI file format (SMF Type 0 and Type 1). Intermediate format for IC’s LLM audio generation pipeline (ABC → MIDI → SoundFont → PCM) and universal standard in game audio tooling. Note: C&C (TD/RA) shipped music as .aud digital audio, not MIDI — earlier Westwood titles used synthesizer formats (.adl, XMIDI), not standard .mid. Behind midi feature flag in cnc-formats — adds midly (parser/writer), nodi (real-time MIDI playback abstraction), and rustysynth (SoundFont SF2 synthesizer). Read + write + SoundFont render: cnc-formats convert renders MID→WAV (via SoundFont) and MID→AUD (SoundFont + IMA ADPCM). WAV→MID transcription available behind transcribe + convert features (WAV decoding requires hound under convert; DSP pipeline: YIN/pYIN pitch detection, onset detection, MIDI assembly) with ML-enhanced quality via transcribe-ml feature (Spotify Basic Pitch model via ONNX). IC runtime auto-renders .mid to PCM at load time via SoundFont. See research/llm-soundtrack-generation-design.md and Transcribe Upgrade Roadmap |
.adl | AdLib music | Dune II (1992) soundtrack format — sequential OPL2 register writes driving Yamaha YM3812 FM synthesis. Not a C&C format, but direct Westwood lineage (Dune II is the predecessor to C&C). Behind adl feature flag in cnc-formats. Read-only parser: reads register write sequences into AdlFile struct. validate and inspect report register count, estimated duration, and detected instrument patches. ADL→WAV rendering requires OPL2 chip emulation — the only viable pure Rust emulator (opl-emu) is GPL-3.0, so rendering lives in ic-cnc-content, not cnc-formats. Community documentation: DOSBox source, AdPlug project |
.xmi | XMIDI music | Extended MIDI for the Miles Sound System (Miles AIL). IFF FORM:XMID container wrapping standard MIDI events with Miles-specific extensions: IFTHEN-based absolute timing (vs. standard MIDI delta-time), for-loop markers, multi-sequence files. Used by Kyrandia series and other Miles-licensed Westwood titles — not standard .mid. Behind xmi feature flag in cnc-formats (implies midi). XMI→MID conversion is clean-room (~300 lines): strip IFF wrapper, convert IFTHEN timing to delta-time, merge multi-sequence files. Once converted to MID, the existing MIDI pipeline handles SoundFont rendering to WAV/AUD. validate and inspect report sequence count, timing mode, and embedded SysEx data |
.avi | Interchange video | Tool-level interchange format for VQA ↔ video conversion (cnc-formats convert, behind convert feature). Uncompressed BGR24 video + 16-bit PCM audio. Clean-room AVI container codec with no external dependencies. This does NOT conflict with D049’s WebM recommendation — D049 targets the engine’s runtime format; AVI is the tool-level interchange format. Pipeline: .vqa → AVI (cnc-formats) → WebM (ffmpeg/user tooling). Not a game asset format — never loaded at runtime |
.cps | Screen pictures | Compressed Screen Picture — 320×200 palette-indexed fullscreen still images for title screens, loading screens, and menu backgrounds. Optional LCW compression, optional embedded 256-color palette. Used in TD and RA1 (e.g., ALIPAPER.CPS, SOVPAPER.CPS). Read-only — IC loads for Classic render mode (D048) and Asset Studio (D040) preview |
.eng/.ger/.fre | String tables | Language-specific string tables for TD/RA1 (e.g., CONQUER.ENG, CONQUER.GER). Indexed null-terminated string arrays. Used for in-game text, mission briefings, UI labels. Read-only — IC uses its own localization system; parsed for Classic compatibility, cross-engine export (D066), and Asset Studio (D040) text preview |
.lut | Lookup tables | 4096-entry color lookup table for the Chrono Vortex visual effect in Red Alert. Maps source→destination palette indices for real-time color transformation. Read-only — parsed for Classic render mode (D048) fidelity |
.dip | Installer data | Segmented control stream data from the original Westwood installer. Read-only — parsed for completeness and Asset Studio (D040) archive inspection |
Tiberian Sun / Red Alert 2 Formats
Binary format parsers for the TS/RA2 game family. All clean-room implementations in cnc-formats from community documentation (XCC Utilities, Ares, Phobos projects). These are additive to the FormatRegistry (D018) — loaded by TS/RA2 game modules, not the core engine.
| Format | Purpose | Notes |
|---|---|---|
.shp (TS/RA2) | Sprite sheets (v2) | Distinct from TD/RA1 .shp — uses scanline RLE compression (types 1–3: scanline skip, scanline RLE, LCW fallback) with independent per-frame crop rectangles. Separate ShpTsFile parser in cnc-formats (auto-detected by format sniffing). Read-only |
.vxl | Voxel models | 3D voxel geometry for TS/RA2 vehicles and units. Multi-limb structure with per-limb bounding boxes, span data, and transformation metadata. Community-documented by XCC Utilities project. Read-only |
.hva | Voxel animation | Hierarchical Voxel Animation — 3×4 affine transformation matrices per section per frame, driving .vxl model articulation (turret rotation, barrel recoil, walking animation). Companion sidecar to .vxl files. Read-only |
.csf | String tables | Compiled String Format — TS/RA2/Generals localized string tables. UTF-16LE with XOR-encoded label strings (0xA7D1A7D1... key) and optional extra value field (audio filename or macro reference). Read-only — IC uses its own localization system; parsed for import pipeline and Asset Studio (D040) preview |
Generals / Zero Hour Formats (SAGE Engine)
Binary format parsers for the Generals/ZH SAGE-era game family. Clean-room implementations in cnc-formats from EA’s GPL-released source code and community documentation (OpenSAGE project). These are additive to the FormatRegistry — loaded by Generals game modules.
| Format | Purpose | Notes |
|---|---|---|
.big | Archive container | EA’s BIG archive format used by Generals, Zero Hour, Battle for Middle-earth, and other SAGE-engine games. Header + file table + packed data. Streaming API for zero-copy member access. Clean-room parser from EA GPL source and OpenSAGE community docs. Read-only |
.w3d | 3D models | Westwood 3D mesh format — recursive IFF-style chunk structure containing meshes, hierarchies, animations, and collision data. Used for all 3D assets in Generals/ZH. Parser handles nested chunk traversal with stack depth safety limits (fuzz-hardened). Read-only |
Remastered Collection Formats (Petroglyph)
HD asset formats from the C&C Remastered Collection (EA, 2020). Format definitions derived from the GPL v3 C++ DLL source and community documentation. See D075 for full import pipeline and legal model.
| Format | Purpose | Notes |
|---|---|---|
.meg | Archive container | Petroglyph archive format (from Empire at War lineage). Header + file table + packed data. Clean-room read-only MegArchive parser in cnc-formats (Phase 2, behind meg feature flag). Community tools: OS Big Editor, OpenSage. ic-cnc-content depends on cnc-formats with meg enabled. |
.tga+.meta | HD sprite sheets | 32-bit RGBA TGA “megasheets” — all frames of a unit/building composited into one large atlas. Paired .meta JSON file provides per-frame geometry: {"size":[w,h],"crop":[x,y,w,h]}. Player colors use chroma-key green (HSV hue ~110) instead of palette indices. |
.dds | GPU textures | DirectDraw Surface (BC1/BC3/BC7). Terrain, UI chrome, effects. Convert to KTX2 or PNG at import time. |
.bk2 | HD video (Bink2) | Proprietary RAD Game Tools codec. Cutscenes and briefings. Converted to WebM (VP9) at import time — IC does not ship a Bink2 runtime decoder. |
.wav (HD) | Remixed audio | Standard WAV containers (Microsoft ADPCM). Plays natively in IC’s Kira audio pipeline. No conversion needed. |
.pgm | Map package | MEG file with different extension. Contains map + preview image + metadata. Reuses MegArchive parser from cnc-formats (meg feature flag). |
.mtd | MegaTexture data | Petroglyph format for packed UI elements (sidebar icons in MT_COMMANDBAR_COMMON variants). Custom parser in ic-cnc-content. Low priority — only needed for UI chrome import. |
.xml | GlyphX config | Standard XML. Game settings, asset mappings, sequence definitions. Parse with quick-xml crate to extract classic→HD frame correspondence tables for sprite import pipeline. |
.dat/.loc | String tables | Petroglyph localization format. Parse for completeness; IC uses its own localization system. Low priority. |
Text Formats
| Format | Purpose | Notes |
|---|---|---|
.ini (original) | Game rules | Original Red Alert format |
| MiniYAML (OpenRA) | Game rules, maps, manifests | Custom dialect, loads at runtime via auto-detection (D025); cnc-formats convert available for permanent on-disk migration |
| YAML (ours) | Game rules, maps, manifests | Standard spec-compliant YAML |
.oramap | OpenRA map package | ZIP archive containing map.yaml + terrain + actors |
Canonical Asset Format Recommendations (D049)
New Workshop content should use Bevy-native modern formats by default. C&C legacy formats are fully supported for backward compatibility but are not the recommended distribution format. The engine loads both families at runtime — no manual conversion is ever required.
| Asset Type | Recommended (new content) | Legacy (existing) | Why Recommended |
|---|---|---|---|
| Music | OGG Vorbis (128–320kbps) | .aud (cnc-formats) | Bevy default feature, stereo 44.1kHz, ~1.4MB/min. Open, patent-free, WASM-safe, security-audited by browser vendors |
| SFX | WAV (16-bit PCM) or OGG | .aud (cnc-formats) | WAV = zero decode latency for gameplay-critical sounds. OGG for larger ambient sounds |
| Voice | OGG Vorbis (96–128kbps) | .aud (cnc-formats) | Transparent quality for speech. 200+ EVA lines stay under 30MB |
| Sprites | PNG (RGBA or indexed) | .shp+.pal (cnc-formats) | Bevy-native via image crate. Lossless, universal tooling. Palette-indexed PNG preserves classic aesthetic |
| HD Textures | KTX2 (BC7/ASTC GPU-compressed) | N/A | Zero-cost GPU upload, Bevy-native. ic mod build can batch-convert PNG→KTX2 |
| Terrain | PNG tiles | .tmp+.pal (cnc-formats) | Same as sprites — theater tilesets are sprite sheets |
| Cutscenes | WebM (VP9, 720p–1080p) | .vqa (cnc-formats) | Open, royalty-free, browser-compatible (WASM), ~5MB/min at 720p |
| 3D Models | GLTF/GLB | N/A | Bevy’s native 3D format |
| Palettes | .pal (768 bytes) | .pal (cnc-formats) | Already tiny and universal in the C&C community — no change needed |
| Maps | IC YAML | .oramap (ZIP+MiniYAML) | Already designed (D025, D026) |
Why modern formats: (1) Bevy loads them natively — zero custom code, full hot-reload and async loading. (2) Security — OGG/PNG parsers are fuzz-tested and browser-audited; our custom .aud/.shp parsers are not. (3) Multi-game — non-C&C game modules (D039) won’t use .shp or .aud. (4) Tooling — every editor exports PNG/OGG/WAV/WebM; nobody’s toolchain outputs .aud. (5) WASM — modern formats work in browser builds out of the box.
The Asset Studio (D040) converts in both directions. See decisions/09e/D049-workshop-assets.md for full rationale, storage comparisons, and distribution strategy.
Crate Goals (cnc-formats + ic-cnc-content)
D076 splits format handling into two crates with distinct roles:
cnc-formats (MIT OR Apache-2.0, separate repo — Tier 1, Phase 0):
-
Clean-room parsers for C&C binary formats across three game families:
- Classic Westwood 2D (TD/RA1):
.mix,.shp,.tmp,.pal,.aud,.vqa,.vqp,.wsa,.fnt,.cps(screen pictures),.eng/.ger/.fre(string tables),.lut(color lookup tables),.dip(installer data) - Tiberian Sun / Red Alert 2:
.shpTS variant (scanline RLE, separateShpTsFileparser),.vxl(voxel models),.hva(voxel animation transforms),.csf(compiled string format) - Generals / Zero Hour (SAGE):
.big(BIG archives),.w3d(Westwood 3D mesh — recursive IFF chunk parser) - Petroglyph (Remastered):
.meg/.pgmarchives (Phase 2, behindmegfeature flag — clean-room from OS Big Editor/OpenSAGE community docs) - Audio/music: Standard MIDI
.midparsing, writing, SoundFont rendering, and real-time playback behindmidifeature flag (viamidly/nodi/rustysynth— pure Rust;midlyis Unlicense,nodiandrustysynthare MIT). Westwood-lineage audio: AdLib.adl(Dune II) parsing behindadlfeature flag; XMIDI.xmi(Kyrandia / Miles Sound System) parsing and XMI→MID conversion behindxmifeature flag (impliesmidi). WAV→MID transcription behindtranscribe+convertfeature flags (impliesmidi; WAV decoding viahoundrequiresconvert); ML-enhanced viatranscribe-mlfeature - Format detection: Content-based magic-byte sniffing (
identifyCLI) auto-detects all supported formats without relying on file extension — covers all families above plus TS/RA2/Generals variants - Streaming APIs: Zero-copy
Read-based streaming for large files — MIX, BIG, MEG, AUD, and VQA all support range-based member access without loading entire archives into memory
- Classic Westwood 2D (TD/RA1):
-
Clean-room parsers for C&C text configuration formats:
.ini(classic C&C rules, always enabled) and MiniYAML (OpenRA rules, behindminiyamlfeature flag) -
Clean-room encoders for standard algorithms — LCW compression, IMA ADPCM encoding, VQ codebook generation (median-cut quantization), SHP frame assembly, PAL writing. These use publicly documented algorithms with no EA source code references. Sufficient for community tools, round-trip conversion, and Asset Studio basic functionality.
-
Bidirectional format conversion (behind
convertfeature flag, gatespng/hound/gifdependencies):Conversion Direction Dependency SHP ↔ PNG Bidirectional pngcrateSHP ↔ GIF Bidirectional gifcratePAL → PNG (swatch) Export pngcrateTMP → PNG Export pngcrateWSA ↔ PNG (frame sequence) Bidirectional pngcrateWSA ↔ GIF (animated) Bidirectional gifcrateAUD ↔ WAV Bidirectional houndcrateMID → WAV Export midly+rustysynth(behindmidifeature)MID → AUD Export midly+rustysynth+aud::encode_adpcm()(behindmidifeature)XMI → MID Export midly(behindxmifeature, impliesmidi)XMI → WAV Export Via XMI→MID then MID→WAV SoundFont render (behind xmifeature)XMI → AUD Export Via XMI→MID→WAV→AUD pipeline (behind xmi+convertfeatures)WAV → MID Export DSP transcription pipeline (behind transcribe+convertfeatures — WAV decoding requireshoundunderconvert); ML-enhanced viatranscribe-mlfeatureVQA ↔ AVI Bidirectional custom AVI codec VQA → MKV Export custom Matroska encoder (V_UNCOMPRESSED per RFC 9559 or V_MS/VFW/FOURCC legacy codec); optional PCM audio track. Higher fidelity archival than AVI FNT → PNG Export pngcratecnc-formats convertis the standalone CLI for community utility; Asset Studio (D040) provides the visual GUI viaic-cnc-content(which wrapscnc-formats). -
CLI tool with phased subcommand rollout:
- Phase 0:
identify(content-based format sniffing via magic bytes — auto-detects format type without relying on file extension; reports detected format and confidence),validate(structural correctness),inspect(dump contents/metadata,--jsonfor machine-readable output),convert(extensible--format/--toformat conversion —--torequired,--formatoverrides auto-detected source format from extension; text:--format miniyaml --to yamlbehindminiyamlfeature; binary: SHP↔PNG, SHP↔GIF, AUD↔WAV, VQA↔AVI, VQA→MKV, WSA↔PNG/GIF, TMP→PNG, PAL→PNG, FNT→PNG behindconvertfeature; MIDI: MID→WAV, MID→AUD behindmidifeature; XMIDI: XMI→MID, XMI→WAV, XMI→AUD behindxmifeature; Transcribe: WAV→MID behindtranscribe+convertfeatures — WAV decoding viahoundrequiresconvert, ML-enhanced viatranscribe-ml) - Phase 1:
extract(decompose.mixarchives to individual files;.meg/.pgmsupport added Phase 2 viamegfeature),list(quick archive inventory — filenames, sizes, types;.meg/.pgmsupport added Phase 2) - Phase 2:
check(deep integrity verification — CRC validation, truncation detection,validate --strictequivalent),diff(format-aware structural comparison of two files of the same type),fingerprint(SHA-256 canonical content hash for integrity/deduplication) - Phase 6a:
pack(create.mixarchives from directory — inverse ofextract)
CLI usage examples:
# Auto-detect format from file content (no extension needed) cnc-formats identify mystery_file.dat # Convert MiniYAML rules to standard YAML (explicit --format because .yaml is ambiguous) cnc-formats convert --format miniyaml --to yaml rules.yaml # Auto-detection works when extension is unambiguous cnc-formats convert --to yaml openra-rules.miniyaml # Explicit --format required for pipe/stdin usage cat rules.yaml | cnc-formats convert --format miniyaml --to yaml -o rules-converted.yaml # Validate any supported format cnc-formats validate main.mix cnc-formats validate rules.yaml # Inspect archive contents (human-readable) cnc-formats inspect main.mix # Machine-readable JSON output for tooling cnc-formats inspect --json conquer.mix # Extract archive to directory (Phase 1) cnc-formats extract main.mix -o assets/ # Quick archive inventory (Phase 1) cnc-formats list main.mix # Deep integrity check (Phase 2) cnc-formats check main.mix # Format-aware diff between two MIX archives (Phase 2) cnc-formats diff original.mix modded.mix # Content-hash for deduplication (Phase 2) cnc-formats fingerprint infantry.shp # MEG archive support (Phase 2, requires `meg` feature) cnc-formats list data.meg cnc-formats extract data.meg -o remastered-assets/ # Create MIX archive from directory (Phase 6a) cnc-formats pack assets/ -o custom.mix # Binary format conversions (requires `convert` feature) # Convert SHP sprites to PNG (requires palette) cnc-formats convert --format shp --to png infantry.shp --palette temperat.pal -o infantry/ # Convert PNG back to SHP cnc-formats convert --format png --to shp infantry/ --palette temperat.pal -o infantry.shp # Convert AUD audio to WAV cnc-formats convert --format aud --to wav speech.aud -o speech.wav # Convert WAV back to AUD cnc-formats convert --format wav --to aud recording.wav -o recording.aud # Render MIDI to WAV using SoundFont (requires `midi` feature) cnc-formats convert --format mid --to wav soundtrack.mid --soundfont default.sf2 -o soundtrack.wav # Render MIDI to AUD for original game engine modding (requires `midi` feature) cnc-formats convert --format mid --to aud soundtrack.mid --soundfont default.sf2 -o soundtrack.aud # Convert VQA cutscene to AVI (interchange format) cnc-formats convert --format vqa --to avi intro.vqa -o intro.avi # Convert VQA cutscene to MKV (archival quality, RFC 9559 uncompressed video) cnc-formats convert --format vqa --to mkv intro.vqa -o intro.mkv # Convert animated WSA to GIF cnc-formats convert --format wsa --to gif menu.wsa --palette temperat.pal -o menu.gif # Ambiguous format hint (TD vs RA .tmp files — use --format tmp to override auto-detection) cnc-formats convert --format tmp --to png tiles.tmp --palette temperat.pal - Phase 0:
-
Extensive tests against known-good OpenRA data
-
No EA-derived code — permissive licensing enables adoption by any C&C tool or modding project
-
Released open source as a standalone crate on day one (Phase 0 deliverable)
-
Uses
std— enablesstd::io::Readstreaming for large files (.mixarchives,.vqavideo),std::error::Errorergonomics, andHashMapwithout extra dependencies. The&[u8]parsing API remains the primary interface; streaming is an additional option. -
Serves as a clean-room feasibility proof that the engine is not technically dependent on EA’s GPL code — all formats parse and encode correctly from community docs alone (see D051 § “GPL Is a Policy Choice” and D076 rationale #6)
ic-cnc-content (GPL v3, IC monorepo):
- Thin wrapper over
cnc-formats(withminiyamlfeature enabled) — adds EA-specific details (compression tables, game-specific constants) that reference EA’s GPL-licensed C&C source (D051) - Bevy
AssetSourceintegration for IC’s asset pipeline - Remastered-specific format support (
.tga+.metamegasheet splitting,.ddsterrain import,.bk2video conversion,.mtdMegaTexture) — GPL-derived or proprietary formats that stay inic-cnc-content(see D076 § Remastered format split). Note:.meg/.pgmarchive parsing is incnc-formats(Phase 2,megfeature flag) —ic-cnc-contentdepends on it - EA-derived encoder enhancements (Phase 6a): Extends
cnc-formats’ clean-room encoders for pixel-perfect original-game-format matching where EA GPL source provides authoritative edge-case details. Encrypted.mixpacking (Blowfish key derivation + SHA-1 body digest — extendscnc-formats pack‘s unencrypted archives). Only needed when exact-match reproduction of original game file bytes is required —cnc-formats’ clean-room encoders are sufficient for all standard community workflows. Encoders reference the EA GPL source code implementations for the EA-specific enhancements only (see § Binary Format Codec Reference) - ADL→WAV rendering (OPL2 synthesis): Renders
.adlregister data to PCM audio via OPL2 chip emulation usingopl-emu(GPL-3.0, pure Rust).cnc-formatsprovides the.adlparser (behindadlfeature, permissive license);ic-cnc-contentadds the rendering step because the only viable pure Rust OPL emulator is GPL-licensed. Pipeline:.adl→ register writes → OPL2 emulation → PCM → WAV. Accessible via Asset Studio (D040) and IC SDK CLI. If a permissively-licensed pure Rust OPL2 emulator becomes available, rendering can migrate tocnc-formats
Non-C&C Format Landscape
The cnc-formats crate provides clean-room parsers for the entire C&C format family (binary codecs, .ini, and feature-gated MiniYAML); ic-cnc-content wraps it with EA-derived details and IC asset pipeline integration. But the engine (D039) supports non-C&C games via the FormatRegistry and WASM format loaders (see 04-MODDING.md § WASM Format Loader API Surface). Analysis of six major OpenRA community mods (see research/openra-mod-architecture-analysis.md) reveals the scope of formats that non-C&C total conversions require:
| Game (Mod) | Custom Formats Required | Notes |
|---|---|---|
| KKnD (OpenKrush) | .blit, .mobd, .mapd, .lvl, .son, .soun, .vbc (15+ decoders) | Entirely proprietary format family; zero overlap with C&C |
| Dune II (d2) | .icn, .cps, .shp variant, custom map format (5+) | Different .shp than C&C; incompatible parsers. Dune II reuses .wsa (same format as C&C — handled by cnc-formats). .adl music now handled by cnc-formats (behind adl feature flag) |
| Swarm Assault (OpenSA) | Custom creature sprites, terrain tiles | Format details vary by content source |
| Tiberian Dawn HD | MegV3 archives, 128×128 HD tiles (RemasterSpriteSequence) | Different archive format than .mix |
| OpenHV | None — uses PNG/WAV/OGG exclusively | Original game content avoids legacy formats entirely |
Key insight: Non-C&C games on the engine need 0–15+ custom format decoders, and there is zero format overlap with C&C. This validates the FormatRegistry design — the engine cannot hardcode any format assumption. ic-cnc-content (wrapping cnc-formats) is one format loader plugin among potentially many.
Cross-engine validation: Godot’s ResourceFormatLoader follows the same pattern — a pluggable interface where any module registers format handlers (recognized extensions, type specializations, caching modes) and the engine dispatches to the correct loader at runtime. Godot’s implementation includes threaded loading, load caching (reuse/ignore/replace), and recursive dependency resolution for complex assets. IC’s FormatRegistry via Bevy’s asset system should support the same capabilities: threaded background loading, per-format caching policy, and declared dependencies between assets (e.g., a sprite sheet depends on a palette). See research/godot-o3de-engine-analysis.md § Asset Pipeline.
Content Source Detection
Games use different distribution platforms, and each stores assets in different locations. Analysis of TiberianDawnHD (see research/openra-mod-architecture-analysis.md) shows a robust pattern for detecting installed game content:
#![allow(unused)]
fn main() {
/// Content sources — where game assets are installed.
/// Each game module defines which sources it supports.
pub enum ContentSource {
Steam { app_id: u32 }, // e.g., Steam AppId 2229870 (TD Remastered)
EaApp { registry_key: String }, // EA App (formerly Origin) — Windows registry path to install dir
Gog { game_id: String }, // GOG Galaxy game identifier
OpenRA { install_path: PathBuf }, // OpenRA installation — mods, maps, community assets
Directory { path: PathBuf }, // Manual install / disc copy
}
}
TiberianDawnHD detects Steam via AppId, EA App (formerly Origin) via Windows registry key, and GOG via standard install paths. IC should implement a ContentDetector that probes all known sources for each supported game and presents the user with detected installations at first run. The OpenRA source kind detects existing OpenRA installations to access community mods, maps, and assets. This handles the critical UX question “where are your game assets?” without requiring manual path entry — the same approach used by OpenRA, CorsixTH, and other reimplementation projects.
Phase: Content detection ships in Phase 0 — format parsing (binary + .ini + MiniYAML) in cnc-formats, IC-specific asset pipeline integration (including content source probing) in ic-cnc-content. Game module content detection in Phase 1.
Browser Asset Storage
The ContentDetector pattern above assumes filesystem access — probing Steam, Origin, GOG, and directory paths. None of this works in a browser build (WASM target). Browsers have no access to the user’s real filesystem. IC needs a dedicated browser asset storage strategy.
Browser storage APIs (in order of preference):
- OPFS (Origin Private File System): The newest browser storage API (~2023). Provides a real private filesystem with file/directory operations and synchronous access from Web Workers. Best performance for large binary assets like
.mixarchives. Primary storage backend for IC’s browser build. - IndexedDB: Async NoSQL database. Stores structured data and binary blobs. Typically 50MB–several GB (browser-dependent, user-prompted above quota). Wider browser support than OPFS. Fallback storage backend.
- localStorage: Simple key-value string store, ~5-10MB limit, synchronous. Too small for game assets — suitable only for user preferences and settings.
Storage abstraction:
#![allow(unused)]
fn main() {
/// Platform-agnostic asset storage.
/// Native builds use the filesystem directly. Browser builds use OPFS/IndexedDB.
pub trait AssetStore: Send + Sync {
fn read(&self, path: &VirtualPath) -> Result<Vec<u8>>;
fn write(&self, path: &VirtualPath, data: &[u8]) -> Result<()>;
fn exists(&self, path: &VirtualPath) -> bool;
fn list_dir(&self, path: &VirtualPath) -> Result<Vec<VirtualPath>>;
fn delete(&self, path: &VirtualPath) -> Result<()>;
fn available_space(&self) -> Result<u64>; // quota management
}
pub struct NativeStore { root: PathBuf }
pub struct BrowserStore { /* OPFS primary, IndexedDB fallback */ }
}
Browser first-run asset acquisition:
- User opens IC in a browser tab. No game assets exist in browser storage yet.
- First-run wizard presents options: (a) drag-and-drop
.mixfiles from a local RA installation, (b) paste a directory path to bulk-import, or (c) download a free content pack if legally available (e.g., freeware TD/RA releases). - Imported files are stored in the OPFS virtual filesystem under a structured directory (similar to Chrono Divide’s
📁 /layout: game archives at root, mods inmods/<modId>/, maps inmaps/, replays inreplays/). - Subsequent launches skip import — assets persist in OPFS across sessions.
Browser mod installation:
Mods are downloaded as archives (via Workshop HTTP API or direct URL), extracted in-browser (using a JS/WASM decompression library), and written to mods/<modId>/ in the virtual filesystem. The in-game mod browser triggers download and extraction. Lobby auto-download (D030) works identically — the AssetStore trait abstracts the actual storage backend.
Storage quota management:
Browsers impose per-origin storage limits (typically 1-20GB depending on browser and available disk). IC’s browser build should: (a) check available_space() before large downloads, (b) surface clear warnings when approaching quota, (c) provide a storage management UI (like Chrono Divide’s “Options → Storage”) showing per-mod and per-asset space usage, (d) allow selective deletion of cached assets.
Bevy integration: Bevy’s asset system already supports custom asset sources. The BrowserStore registers as a Bevy AssetSource so that asset_server.load("ra2.mix") transparently reads from OPFS on browser builds and from the filesystem on native builds. No game code changes required — the abstraction lives below Bevy’s asset layer.
Phase: AssetStore trait and BrowserStore implementation ship in Phase 7 (browser build). The trait definition should exist from Phase 0 so that NativeStore is used consistently — this prevents filesystem assumptions from leaking into game code. Chrono Divide’s browser storage architecture (OPFS + IndexedDB, virtual directory structure, mod folder isolation) validates this approach.
Sub-Pages
| Section | Topic | File |
|---|---|---|
| Binary Codecs | MIX, SHP, LCW, TMP, PAL, AUD, VQA, VQP, WSA, FNT, CPS, ENG, LUT, DIP codec specs; TS/RA2: SHP(TS), VXL, HVA, CSF; Generals: BIG, W3D | binary-codecs.md |
| — EA Source Insights | Architecture lessons from EA GPL source: keep/leave-behind patterns, code stats, coordinate translation | ea-source-insights.md |
| Save & Replay Formats | Save game format (.icsave) + replay file format (.icrep) | save-replay-formats.md |
| — Keyframes & Analysis | Keyframe snapshot types, delta structs, seeking algorithm, analysis event taxonomy | replay-keyframes-analysis.md |
| Backup, Screenshot & Import | Backup archive format (D061) + screenshot format + owned-source import/extraction pipeline | backup-screenshot-import.md |
| Transcribe Upgrade Roadmap | WAV/PCM-to-MIDI transcription upgrade: pYIN, SuperFlux, polyphonic, ML-enhanced (Basic Pitch) | transcribe-upgrade-roadmap.md |
| IronCutscene Container | Multi-track cutscene format (.icc) — VQA video + multi-language AUD audio + timed subtitles + chapters | cutscene-container.md |