PAK (Resident Evil 1997)
From Just Solve the File Format Problem
(Redirected from .PAK (Resident Evil 1997))
This content was first retrieved from the Internet Archive's Wayback Machine for the date 2016-12-22 from the following URL: https://web.archive.org/web/20161222090005/http://rewiki.regengedanken.de/wiki/.PAK_(Resident_Evil)
The .PAK file format is used by the PC version of Resident Evil (1997). It contains a compressed TIM image, using an algorithm similar to LZW.
Structure
The file is a bitstream, without any header.
Example decompression routine
This source is partly based on LZW decoder from scummvm engine.
#include <stdio.h> #include <fcntl.h> unsigned char dstPointer[512<<10]; int dstOffset; unsigned long dstLength; unsigned char *srcPointer; int srcOffset; unsigned char srcByte; int tmpMask; #define MAX_LENGTH 35024 typedef struct { long flag; long index; long value; } re1_pack_t; re1_pack_t tmpArray2[MAX_LENGTH]; unsigned char decodeStack[MAX_LENGTH]; /* Load file in mem from filename, return buffer, update length */ char *loadFile(char *filename, int *length) { int handle; char *buffer; /* Load file */ handle = open(filename, O_RDONLY); if (handle<0) { fprintf(stderr, "Unable to open %s\n", filename); return NULL; } *length = lseek(handle, 0, SEEK_END); lseek(handle, 0, SEEK_SET); buffer = (char *)malloc(*length); if (buffer==NULL) { fprintf(stderr, "Unable to allocate %d bytes\n", length); return NULL; } read(handle, buffer, *length); close(handle); return buffer; } int re1_read_bits(int num_bits) { unsigned long value=0, mask; mask = 1<<(--num_bits); while (mask>0) { if (tmpMask == 0x80) { srcByte = srcPointer[srcOffset++]; } if ((tmpMask & srcByte)!=0) { value |= mask; } tmpMask >>= 1; mask >>= 1; if (tmpMask == 0) { tmpMask = 0x80; } } return value; } int decodeString(int decodeStackOffset, unsigned long code) { int i; for (i=0; code>255; ) { decodeStack[decodeStackOffset++] = tmpArray2[code].value; code = tmpArray2[code].index; i++; } decodeStack[decodeStackOffset] = code; return decodeStackOffset; } void re1_depack(unsigned char *src, int src_length) { int num_bits_to_read, i; int lzwnew, c, lzwold, lzwnext; srcPointer = src; srcOffset = 0; tmpMask = 0x80; srcByte = 0; dstOffset = 0; memset(tmpArray2, 0, sizeof(tmpArray2)); for(;;) { for (i=0; i<MAX_LENGTH; i++) { tmpArray2[i].flag = 0xffffffff; } lzwnext = 0x103; num_bits_to_read = 9; c = lzwold = re1_read_bits(num_bits_to_read); if (lzwold == 0x100) { break; } dstPointer[dstOffset++] = c; for(;;) { lzwnew = re1_read_bits(num_bits_to_read); if (lzwnew == 0x100) { dstLength = dstOffset; return; } if (lzwnew == 0x102) { break; } if (lzwnew == 0x101) { num_bits_to_read++; continue; } if (lzwnew >= lzwnext) { decodeStack[0] = c; i = decodeString(1, lzwold); } else { i = decodeString(0, lzwnew); } c = decodeStack[i]; while (i>=0) { dstPointer[dstOffset++] = decodeStack[i--]; } tmpArray2[lzwnext].index = lzwold; tmpArray2[lzwnext].value = c; lzwnext++; lzwold = lzwnew; } } dstLength = dstOffset; } int main(int argc, char **argv) { int length; unsigned char *fileInMem; if (argc<2) { return 1; } fileInMem = loadFile(argv[1], &length); if (fileInMem==NULL) { return 1; } re1_depack(fileInMem, length); /* Now you have the decompressed file at dstPointer */ /* and length is dstLength */ free(fileInMem); return 0; }