The PACK format is used to emulate a Unix directory arborescence, and to avoid putting some hundreds of files on the user's disk. It is not a compressed format, and it's very similar to the WAD format of DOOM.
The PACK file starts with a header, that indicates where to find the directory, and the size of that directory. The number of entries can be deduced by dividing by sizeof(pakentry_t) = 0x40
typedef struct
{ u_char magic[4]= "PACK"; // Name of the new WAD format
long diroffset; // Position of WAD directory from start of file
long dirsize; // Number of entries * 0x40 (64 char)
} pakheader_t;
The PACK directory is made of a list of consecutive entries, each with the following format:
typedef struct
{ u_char filename[0x38]; // Name of the file, Unix style, with extension,
// 50 chars, padded with '\0'.
long offset; // Position of the entry in PACK file
long size; // Size of the entry in PACK file
} pakentry_t;
At offset diroffset in the PACK file, you will find:
pakentry_t dir[dirsize/sizeof(pakentry_t)]; // Directory
The directory is preferably placed at the end of the PACK file, but it could actually be anywhere. The entries could also be scattered all around the PACK file, leaving large gaps. If you write a PACK hacking utility, you must take care not to introduce too many empty space. Also, you should never assume that the entries are stored in the same order as in the directory (they could be in reverse order, for example). If you want to add some data after the last entry, make sure that you are really at the end of the file.
Since PACK files are a bit like WAD, it is possible to use the same tricks that were used by tools such as DeuSF and NWT to modify the PACK file reversibly. It is hoped, however, that Quake is flexible enough so that this trick is not needed.
Contrary to the WAD2 files, there is no tag giving the type of each entry. However, they can be safely recognized by the extension, and it's the method used by Quake itself.
|
Those files are ordinary Text, in Unix format (LF only, no CR), so they won't display correctly under DOS if you are using an old editor. They contain only settings and definitions.
The sound files are ordinary 16-bit RIFF WAVE files (the format commonly used under Microsoft Windows, and now supported by many utilities under different operating systems).
The .DAT file contains some semi-compiled machine independent P-code, instead of the Quake programming language .QC files.
This file contains the behavior associated to each of the entities. For instance, this file contains the frame table that defines how and when each frame of the Alias Models must be displayed.
This file also contains the light styles used to animate the Faces of the BSP models. Those light styles can be found as strings, among the other character strings.
Here is a very partial description of that data lump. Since the source of the Quake C compiler was released, you had better directly look at pr_comp.h for all the details about the structure of a compiled .DAT lump.
the only interesting part is the list of text strings, because it gives the names of possible spawning sequences for the Entities.
// addapted from pr_comp.h
typedef struct
{ long version; // 6
long crc; // CRC over progdefs.h
long ofs_statements; // table of code statements.
long num_statements; // number of statements
long ofs_globaldefs; // table of definitions of global variables
long num_globaldefs; // number of definitions
long ofs_fielddefs; // table of definitions of fields
long num_fielddefs; // number of definitions
long ofs_functions; // Table of functions definitions
long num_functions; // number of functions
long ofs_strings; // Character strings, separated by '\0'. First one is \0
long size_strings; // total size of string data
long ofs_globals; // Unstructured list of Constants and variable
long num_globals; // num_globals*4 = total size of global data
int entityfields; // total size of entity definition
} dprograms_t;
// table of statements
typedef struct
{ u_short op; // operation code
short a; //
short b; // operation dependend parameters
short c; //
} statement;
// table of definitions
typedef struct // globaldef and fielddef
{ u_short type; // type of value stored in table
u_short offset; // offset to value, in the global table
long s_name; // offset to name, in string table
} def;
// table of functions
typedef struct
{
long first_statement; // offset to the first statement, in the statements table
// negative numbers indicate builtin functions
long parm_start; // start of parameters
long locals; // total size of parmeters and all local variable
long profile; // counter incremented at runtime, for each call
long s_name; // index to name, in the string table
long s_file; // pointer to the source file name, in the string table
long numparms; // number of parameters
uchar parm_size[8]; // size of each parameter in memory
}function [ functions.size];
The CRC in the header is not a protection against possible corruption, it's a protection against misuse. As a matter of fact, since part of the definitions in defs.qc are shared between Quake and the PROGS.DAT, and allocated statically in Quake, running a PROGS.DAT with an incompatible version of Quake could cause serious crashes. Having the same CRC values (calculated over progdefs.h) ensures that the PROGS.DAT and Quake are compatible.
There are three kinds of lumps: Palette, colormap, pictures.
This is the game the color palette:
struct { u_char Red, u_char Green, u_char Blue} Palette[256];
This is the precalculated color map, made of 32 tables. each table contains 256 indexes to the actual colors in the colormap.
u_char ColorIndex[32][256];
When light level is light and the color is color,
the games uses the color index:
c = ColorIndex[ ((light>>3)&0x1F)][color].
These are simple flat pictures, with indication of width and height, that are used for menus, status bar and the like.
typedef struct
{ long width;
long height;
u_char Color[width*height];
} picture_t;
A classical DOS text screen, 80x25 with color tags. Same as the end screen in DOOM.
A simple text file, that contains the default configuration of keys.