The container file format used by Star Wars: Empire at War is called MegaFiles. It uses the file extension MEG or .MEG. Other container file formats are ZIP and RAR, for example. However, the MEG file format does not use compression; all files are stored uncompressed inside the MEG file. A game typically consists of thousands or tens of thousands files, and by placing them into a single file, the installation times of games can be decreased. Also, the loading times of games will decrease because a single big file will be stored in a consecutive area on the hard disk, instead of the random placement that could occur with thousands of small files.
Last update: March 22nd, 2006
Technical details
The file format consists of four parts: the MEG header, the filenames, the file information and the actual file data.
MEG Header
The MEG header contains the number of files in the MEG file. It is stored twice, and it appears they are always equal. However, the first refers to the number of filenames that will follow this record, and the second refers to the number of FileInfo records there are.
MEGHeader: record FilenameCount: unsigned int32; {Number of filenames in the MEG file} FileInfoCount: unsigned int32; {Number of file information records in the MEG file} end;
Filenames
Immediately after the MEGHeader are filenames. There are FilenameCount consecutive filename records. These filenames is stored in an array called FilenameArray which starts at index 0, for the sake of this explanation.
FilenameRecord: record FilenameLength: unsigned int16; {Number of characters in the filename (type also known as unsigned short)} Filename: String[1..FilenameLength]; {Actual filename: a string with length FilenameLength} end;
File information
After the filenames is information about all the files. There are FileInfoCount consecutive FileInfo records.
FileInfo: record CRC32: unsigned int32; { CRC32 checksum of the filename of this file } FileIndex: unsigned int32; { Index of this file, counts from 0..FileInfoCount-1 } FileSize: unsigned int32; { Size in bytes of this file } FileOffset: unsigned int32; { Offset in the MEG where this file is stored }this file FilenameIndex: unsigned int32; { Index into the list of filenames (e.g. into FilenameArray) } end;
Using the FilenameIndex field is crucial, because the filenames are stored in a different order from the FileInfo records!
Actual files
Following all the file information, the actual files are stored. These can be located by using the FileOffset and FileSize fields of the FileInfo record.
Example code
Example code in Python is available for parsing the MegaFiles format. Once you have Python installed on your machine, use the program by running "megafiles.py Cinematics.MEG list" to obtain a file list of the MEG file Cinematics.MEG. You can extract all files using "megafiles.py Cinematics.MEG dump". In order to keep the example simple, all names like DATA\FOO.XML will be converted into DATA_FOO.XML: the directory structure is not built, but instead put in to the filenames.
Example code: megafiles.py
Credits
Created by Koen van de Sande
Mike Lankamp deserves credit for thinking of CRC32 for the filename - this is actually very similar to the MIX files of the old C&C: Tiberian Dawn and Red Alert 1 MIX files, who only stored a checksum for the filename.