Skip to content

MIX archives

Formats

Changed in 0.2.0

Stores named game files in CRC-indexed archive members.

Format
Kind
Binary format
Extension
.MIX
Role
Archive

Once the game mounts a MIX archive, each of its members opens by name like a file on disk. A loose file with the same name takes precedence over the member, so a loose file can override archive content. The exception is a file the game reads only from cached archives, which Caching lists. Archive members are read-only; a file opened for writing is always a file on disk.

The game searches archives in the order it mounted them. The first archive that holds a member of the requested name supplies it, so an archive mounted earlier overrides that name in every archive mounted after it. Names are matched without regard to case.

Startup mounts these archives in this order:

OrderArchiveRequiredCached
1PATCH.MIXNoNo
2PCACHE.MIXNoYes
3EXPAND99.MIX down to EXPAND00.MIXNoNo
4ECACHE99.MIX down to ECACHE00.MIXNoYes
5TIBSUN.MIXNoNo
6CACHE.MIXYesYes
7LOCAL.MIXNoNo
8CONQUER.MIXYesYes
9Every MAPS*.MIX, in alphabetical orderNoNo
10MULTI.MIXNoNo
11SOUNDS01.MIXWhere the Firestorm expansion is installedYes, when audio is available
12SOUNDS.MIXYesYes, when audio is available
13SCORES.MIX, then SCORES01.MIXNoNo
14Every MOVIES*.MIX, in alphabetical orderNoNo

PATCH.MIX and the EXPAND archives are mounted only as loose files, never as members of another archive.

If a required archive is missing or cannot be cached, the game stops during startup. An optional archive that is missing is skipped, and later lookups do not search it. A deployment can therefore keep the maps and the multiplayer content loose or in other archives.

A music track or movie whose file is not found in any archive or folder is skipped.

Archives mounted after startup are searched after every startup archive.

When a scenario or saved game uses a different theater from the one last loaded, the game drops the previous theater’s archives and mounts the new theater’s. These are <Root>.MIX and <Suffix>.MIX, both cached, then <IsoRoot>.MIX, not cached. Root, Suffix and IsoRoot are set per theater.

Each time a scenario or saved game loads, the game drops the previous side’s archives and mounts those of the player’s side. The two-digit side number <nn> is the side’s position in the side list: 01 for the first side, 02 for the second. The archives are mounted in this order:

  1. E99SC<nn>.MIX down to E00SC<nn>.MIX, cached, only while an expansion is enabled.
  2. SIDEC<nn>.MIX, cached. Required.
  3. E99SNC<nn>.MIX down to E00SNC<nn>.MIX, not cached, only while an expansion is enabled.
  4. SIDENC<nn>.MIX, not cached. Optional.
  5. In a campaign only, one CD archive, not cached. Optional.

For the CD archive, a campaign mission first tries E<xx>SCD<nn>.MIX while an expansion is enabled, where <xx> is the mission’s RequiredAddOn number: a Firestorm mission tries E01SCD01.MIX or E01SCD02.MIX. Without that archive it mounts SIDECD<nn>.MIX, so an installation that keeps the expansion’s members in the base archive still plays the expansion’s campaign.

A campaign that finds neither CD archive still starts. The stock CD archives hold the score screen’s picture and movie and the map selection’s artwork, palettes and voice lines, so these must then come from another archive or folder:

  • A score picture or score movie that is not found is left out.
  • Map selection between missions cannot open without its artwork and palettes. The game reports “Unable to initiate Map Selection!” and replays the mission just won, unless that mission sets SkipMapSelect=yes.

Outside a match the game mounts the no-side archives in the same place: E99SC00.MIX down to E00SC00.MIX and SIDEC00.MIX, cached, then E99SNC00.MIX down to E00SNC00.MIX and SIDENC00.MIX, not cached. The expansion copies are mounted only while an expansion is enabled, and every one of these archives is optional. They are mounted at startup, give way to the player’s side when a scenario or saved game loads, and are mounted again when a match ends and the menus return. UI files describes how a mod uses them for side-dependent interface files.

If a required side archive is missing, the game mounts the first side’s archives instead. If those are missing too, the scenario or saved game fails to load, and a scenario reports that it cannot be read.

Speech archives follow the same pattern for the player’s side, or in a campaign for the mission’s SpeechSide: E<xx>VOX<nn>.MIX for each enabled expansion, then SPEECH<nn>.MIX, which is required. A missing SPEECH<nn>.MIX falls back to the first side’s in the same way. None of the speech archives is cached.

A cached archive holds all of its member data in memory from the moment it is cached. An uncached archive stays on disk, and a member is read from it when opened. The tables and lists above say which archives the game caches. Every archive’s index is read when the archive is mounted, whether or not it is cached.

Whether an archive is cached decides how its members can be read:

  • Many files are read only from cached archives. They include the shapes of object and animation types that are not demand-loaded, the game fonts, the theater palettes and the mouse cursor. A loose copy of such a file, or a copy in an archive mounted without caching, is not found.
  • Any file the game opens by name can come from either kind of archive.

To replace a file of the first kind, put the replacement in PCACHE.MIX or an ECACHE archive. Do not also put a copy in an uncached archive that the game searches earlier: PATCH.MIX for a file in PCACHE.MIX, or PATCH.MIX or any EXPAND archive for a file in an ECACHE archive. The game finds that uncached copy first and treats the file as missing.

An archive may carry a digest of its member data. The game checks it when caching the archive and leaves the archive uncached if the digest does not match.

An archive starts with a header, then its index, then the member data:

PartContents
FlagsOptional. Two zero bytes, then a 16-bit field: bit 0 set means a digest follows the data, bit 1 set means the header and index are encrypted. An archive that does not start with two zero bytes has neither.
HeaderThe number of members, a 16-bit integer, then the size of the member data in bytes, a 32-bit integer.
IndexOne 12-byte entry per member: the checksum of the member’s name, the member’s offset from the start of the data, and its size in bytes, each a 32-bit integer.
DataThe members’ contents. Member data is never encrypted.
DigestPresent only when flag bit 0 is set. A 20-byte SHA-1 digest of the data.

The checksum is computed from the member’s name in upper case, without a path. Keep the index sorted by checksum in ascending order, compared as signed 32-bit integers. The game finds a member by binary search over the index, so an entry out of order may not be found. The order of the members in the data does not matter.

Source files

Linked at revision 51b52aa38392.

History

  1. Changed0.2.0In development

    Fall back to the base side archive when the expansion's is absent

  2. Changed0.2.0In development

    Mount no-side archives outside a match

  3. Changed0.2.0In development

    Stop requiring the map and multiplayer archives

  4. Changed0.2.0In development

    Stop requiring the score and movie archives

  5. Changed0.2.0In development

    Start a campaign without its side CD archive