Skip to content

Instantly share code, notes, and snippets.

What would you like to do?
Decoder for EA games .big-files
#, by, 2009-03-01
# decoder for .BIG-format files utilized by Red Alert 3 and C&C: Zero Hours
# among others. .big is a trivial archival format. quite frankly, this is
# probably the simplest compound file format imaginable.
# this script is written for microsoft windows. it can probably be easily
# adapted for other platforms, but i haven't tried.
# file structure:
# the file consists of a global header, an index of all the embedded
# files, and the actual file data.
# global header {
# header, charstring, 4 bytes - always BIG4 or something similiar
# total file size, unsigned integer, 4 bytes, little endian byte order
# number of embedded files, unsigned integer, 4 bytes, big endian byte order
# total size of index table in bytes, unsigned integer, 4 bytes, big endian byte order
# }, only occurs once
# index of files, follows directly after
# the global header:
# index entry {
# position of embedded file within BIG-file, unsigned integer, 4 bytes, big endian byte order
# size of embedded data, unsigned integer, 4 bytes, big endian byte order
# file name, cstring, ends with null byte
# }, repeats for each embedded file
# file data:
# raw file data at the positions specified in the index
import struct
import sys
import os
import os.path
# Define an empty class to emulate a c struct
# that can hold the data for each entry in the
# file index.
class entry:
if len(sys.argv) != 3:
print "usage: python [file] [target]"
print "BIG-file decoder by"
filePath = sys.argv[1]
targetDir = sys.argv[2]
if not os.path.exists(filePath):
print "Requested file doesn't exist."
if targetDir[-1] != "\\":
targetDir += "\\"
print "Processing " + filePath
# open the file in binary read mode.
# without the b-flag the tell-method
# returns the wrong value.
file = open(filePath, "rb")
# read global header:
# this seems to vary. zero hour uses BIGF
header =
if header != "BIG4":
print "Invalid file format."
# this seems to be the only value encoded in
# little-endian order.
(size,) = struct.unpack("I",
print "size: %d" % (size,)
(entryCount,indexSize) = struct.unpack(">II",
print "entry count: %d" % (entryCount,)
print "index size: %d" % (indexSize,)
# read the index table:
# assume that the file contains the amount of
# entries specified by the global header
entries = []
for j in xrange(0, entryCount):
(entryPos,entrySize) = struct.unpack(">II",
# the filename is stored as a cstring and
# ends with a null byte. read until we reach
# this byte.
fileName = ""
while True:
n =
if ord(n) == 0:
fileName += n
e = entry() = fileName
e.position = entryPos
e.size = entrySize
# iterate through the index entries and
# copy the data into separate files.
for i, e in enumerate(entries):
print "opening %s (size: %d, position: %d)" % (,e.size,e.position)
print "file %d of %d" % (i+1, entryCount)
# calculate the path where the file will be created
# in order to ensure that the directories needed actually
# exists
fileTargetDir = targetDir +["\\")] + "\\"
fileName =["\\")+1:]
targetPath = fileTargetDir + fileName
# create the directories if they don't exist.
if not os.path.exists(fileTargetDir):
# skip files that already exist.
if os.path.exists(targetPath):
print "%s exists. Skipping." % (targetPath,)
print "Opening %s for writing" % (targetPath,)
targetFile = open(targetPath, "wb")
print "Seeked to %d" % (e.position,)
print "Starting data transfer"
for i in xrange(0, e.size):
byte =
print "Wrote %d bytes" % (e.size,)
print "Done, closing file."
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.