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.