Painkiller PAK

From XentaxWiki
Revision as of 20:32, 29 March 2022 by Ikskoks (talk | contribs) (Supported by Programs)

(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search

Back to index

Choose archive extension:


Format Specifications

byte {1}     - IsArchiveCompressed - determines if archive files are Zlib compressed. 0 - uncompressed, not zero - compressed
uint32 {4}   - position to seek to get the file list described below

// File list
uint32 {4}   - Number Of Entries

// for each entry

uint32 {4} - ns, Name length
char {ns} - Filename encrypted (directory or file in Painkiller), takes as many bytes as previously read length. String has no termination, length directly depends on ns. See the C++ function to crypt filenames.
uint32 {4} - UncompressedFileSize, size of original file
uint32 {4} - CompressedFileSize, how much of space it takes inside PAK archive
uint32 {4} - file offset

// end of loop

Must-read: Notes and Comments


Filenames are encrypted

EncryptedStringCharacter(n) = OriginalStringCharacter XOR FileIndex + NameLength % 5 + 2 * (n + NameLength);

(Where n starts at character position 0)

C++ function to crypt (decrypt or encrypt) file names:

Two-way algorithm. Encoding a string two times will leave it decoded.
void CryptFilename(char *EntryName, BYTE NameLength, char FileIndex)
	BYTE n = 0;

	while ( n < NameLength )
	EntryName[n++] ^= FileIndex + NameLength % 5 + 2 * (n + NameLength);

MultiEx BMS

  • A plugin processes these archives

Notes and Comments

If uncompressed file size is 0, then it's directory reserved for entries such as "Classes/Entities/". Files may be compressed using Zlib library. If archive is uncompressed - compressed and uncompressed file sizes are equal. In that case you can directly read content of file by seeking into file offset and reading as many bytes as specified in CompressedFileSize or UncompressedFileSize (they are equal anyway). If archive is compressed - read content of file with size CompressedFileSize and decompress it using ZLib inflate function. CompressedFileSize will be useful in such a condition when you plan to allocate memory (malloc) to read input file from PAK archive. UncompressedFileSize will be useful if you allocate memory to decompress file.

Supported by Programs