Skip to content

Instantly share code, notes, and snippets.

@DanielGibson
Last active April 1, 2016 19:32
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save DanielGibson/8bde6241c93e5efe8b75e5e00d0b9858 to your computer and use it in GitHub Desktop.
Save DanielGibson/8bde6241c93e5efe8b75e5e00d0b9858 to your computer and use it in GitHub Desktop.
Description of Daikatana .pak format
// Daikatana .pak format. It's similar to Quake/Quake2 format, but supports compressed files as well.
// I think that only the following file types are compressed: .tga .bmp .wal .pcx .bsp
// I wouldn't rely on this list when unpacking, but when packing, only compress those.
// the structs are based on pakextract.c from https://github.com/yquake2/pakextract
// all ints are 32bit Little Endian.
struct pak_header
{
char signature[4]; // {'P','A','C','K'}, like in Quake/Quake2
int dir_offset; // offset of the files directory within the pak file
int dir_length; // length of all directory entries in bytes (=> we have dir_length/72 directory entries)
// 72 because sizeof(directory_entry) == 72 in Daikatana (in contrast to Quake where it's 64)
};
struct directory_entry
{
char file_name[56];
int file_pos; // offset of entry's data within whole file
int file_length; // in case of is_compressed: size after decompression (else size in pak)
// the following two are new in Daikatana:
int compressed_length; // size of compressed data in the pak
int is_compressed; // 0: uncompressed, else compressed
};
Pseudocode to uncompress compressed data:
while not done:
read a byte (unsigned char) _x_.
// x is never written to output, only used to determine what to do
if x < 64:
x+1 bytes of uncompressed data follow (just read+write them as they are)
else if x < 128:
// run-length encoded zeros
write (x - 62) zero-bytes to output
else if x < 192:
// run-length encoded data
read one byte, write it (x-126) times to output
else if x < 254:
// this references previously uncompressed data
read one byte to get _offset_
read (x-190) bytes from the already uncompressed and written output data,
starting at (offset+2) bytes before the current write position
(and add them to output, of course)
else if x == 255:
you're done decompressing (used as terminator)
// but I'd also abort once compressed_length bytes are read, to be sure
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment