drs files are archives containing other files, like a tar archive, but much simpler. Helpfully, the format is sequential in nature, which helps speed up decoding time.
A DRS file starts with its main header:
Length | Type | Description | Example |
---|---|---|---|
40 bytes | string | Copyright info | Copyright (c) 1997 Ensemble Studios\032. |
4 bytes | string | File version | 1.00 |
12 bytes | string | File type | tribe |
4 bytes | int32 | Number of tables | 4, 0x00000004 |
4 bytes | int32 | Offset of 1st file | 2188, 0x0000088C |
struct drs_header {
char copyright[40];
char version[4];
char ftype[12];
int32 table_count;
int32 file_offset;
};
Python format: Struct("< 40s 4s 12s i i")
- It is important to note that in later versions of the DRS format
(used for SW:GB), it appears that
copyright
has a length of 60 instead of the usual 40. copyright
,version
&ftype
seem to always have the same value.table_count
stores how manydrs_table_info
structs will follow the main header.file_offset
is the offset of the first actual file in the DRS.
One drs_table_info
struct is stored for each file type (Possible file
extensions are bina
, slp
, wav
).
Length | Type | Description | Example |
---|---|---|---|
4 bytes | string | File extension | 'anib', ' pls' |
4 bytes | int32 | Table offset | 112, 0x00000070 |
4 bytes | int32 | Number of files | 71, 0x00000047 |
struct drs_table_info {
char file_extension[4];
int32 file_info_offset;
int32 num_files;
};
Python format: Struct("< 4s i i")
-
file_extension
is reversed and padded by spaces (0x20
) to reach 4 bytes. Internally, Age of Empires does something like this when reading files from a DRS archive:read_drs_file('bina', 50500);
Note how it uses a C char with multiple bytes. This is stored on disk as a little-endian integer, so the 'a' byte ends up at the lowest address, and the 'b' byte ends up at the highest address.
-
file_info_offset
holds the offset where the actual table resides. -
num_files
contains the amount of files in the table.
The drs_table_info
tells us, how many files are stored for the file_type
.
Each table contains entries for the files in it. The table entry consists of: the unique integer identifier of the embedded file, the offset of the embedded file and the size of the embedded file.
drs_file_info
tables start at position
drs_table_info->file_info_offset
for the corresponding table:
Length | Type | Description | Example |
---|---|---|---|
4 bytes | int32 | File id | 50001, 0x0000C351 |
4 bytes | int32 | File offset | 2188, 0x0000088C |
4 bytes | int32 | File size | 625, 0x00000271 |
struct drs_file_info {
int32 file_id;
int32 file_data_offset;
int32 file_size;
};
Python format: Struct("< i i i")
For every file, the offset in the .drs
is stored, and also its size.
The file's ID can be assumed to be its name.
DRS files that come with the base AoK game.
Contains random map scripts (RMS), as well as AI scripts and some graphic files.
Random Map scripts describe how the builtin maps should be generated.
AI scripts tell the computer what to do, such as build units, gather resources,
and generally make it "smart". These are all bina
files.
The graphic files (slp
) are described below.
Contains almost every graphic you see in the game. This includes units,
buildings, resources, animals, cliffs and shadows. These are all slp
graphic
(animation) files.
Contains the main interface graphics of the game.
All of the the borders, buttons, logos, main game screen, etc you see when
entering the game to starting one can be found within this file as slp
graphics. The drawing color palettes are also stored in this file as bina
.
Finally there's a bunch of wav
sounds, too.
Contains every sound in Age of Kings. These are all wav
files.
Contains all the terrain, in diamond shaped pieces. For each terrain, there are
100 pieces. These are all slp
files.