Daikatana pak files
-------------------
Differences with quake pak files


The directory entry's
---------------------
The structure has changed to support compressed files
every entry now has the followig structure:

typedef struct packfile_s
{
	char	name[MAX_QPATH];
	int		filepos, filelen;
	int     compresslen, compresstype;

} packfile_t;

Compressed files
----------------
If compresstype > 0 then the file is compressed with simple run length
encoding to decompress a file use the following code.

compress_type = pak->files[index].compresstype;
compress_length = pak->files[index].compresslen;
	if (compress_type) {

		unsigned char  code;
		int  src_pos = 0;
		int  dst_pos = 0;
		int  i;
		char *src_data;
		char *dst_data;

		src_data = (char*)X_Malloc(compress_length, MEM_TAG_FILE);
		dst_data = (char*)X_Malloc(len, MEM_TAG_FILE);

		FS_Read (src_data, compress_length, h);
		fclose (h);

		for (;;) {

			code = ((unsigned char*)src_data)[src_pos];
			src_pos++;

			// terminator
			if (code == 255) {
				break;

			} else if (code < 64) {

				// uncompressed block

				for (i = -1; i < (int)code; i++) {

					dst_data[dst_pos] = src_data[src_pos];
					dst_pos++;
					src_pos++;
				}

			} else if (code < 128) {

				// rlz

				for (i = 62; i < (int)code; i++) {

					dst_data[dst_pos] = 0;
					dst_pos++;
				}

			} else if (code < 192) {

				// run length encode

				for (i = 126; i < (int)code; i++) {

					dst_data[dst_pos] = src_data[src_pos];
					dst_pos++;
				}
				src_pos++;

			} else if (code < 254) {

				// reference previous data

				int  offset;

				offset = ((unsigned char*)src_data)[src_pos];
				src_pos++;

				for (i = 190; i < (int)code; i++) {

					dst_data[dst_pos] = dst_data[dst_pos - offset - 2];
					dst_pos++;
				}
			}
		}

		X_Free(src_data);
		*buffer = dst_data;
		return len;

	} else {
		buf = (byte *)X_Malloc(len, MEM_TAG_FILE);
		*buffer = buf;
		FS_Read (buf, len, h);
		fclose (h);
		return len;
	}

That's the only difference with quake files.

--Original email on pak files from John Romero----------------------------------------

typedef struct packfile_s
{
	char	name[MAX_QPATH];
	int		filepos, filelen;
	int     compresslen, compresstype;

} packfile_t;

// If compresstype is >0, it's compressed

compress_type = pak->files[index].compresstype;
compress_length = pak->files[index].compresslen;


// Here's the actual code that decompresses a chunk of data

	if (compress_type) {

		unsigned char  code;
		int  src_pos = 0;
		int  dst_pos = 0;
		int  i;
		char *src_data;
		char *dst_data;
//		int  size = len;

		src_data = (char*)X_Malloc(compress_length, MEM_TAG_FILE);
		dst_data = (char*)X_Malloc(len, MEM_TAG_FILE);

		FS_Read (src_data, compress_length, h);
		fclose (h);

		for (;;) {

			code = ((unsigned char*)src_data)[src_pos];
			src_pos++;

			// terminator
			if (code == 255) {
				break;

			} else if (code < 64) {

				// uncompressed block

				for (i = -1; i < (int)code; i++) {

					dst_data[dst_pos] =
src_data[src_pos];
					dst_pos++;
					src_pos++;
				}

			} else if (code < 128) {

				// rlz

				for (i = 62; i < (int)code; i++) {

					dst_data[dst_pos] = 0;
					dst_pos++;
				}

			} else if (code < 192) {

				// run length encode

				for (i = 126; i < (int)code; i++) {

					dst_data[dst_pos] =
src_data[src_pos];
					dst_pos++;
				}
				src_pos++;

			} else if (code < 254) {

				// reference previous data

				int  offset;

				offset = ((unsigned
char*)src_data)[src_pos];
				src_pos++;

				for (i = 190; i < (int)code; i++) {

					dst_data[dst_pos] = dst_data[dst_pos
- offset - 2];
					dst_pos++;
				}
			}
		}

		X_Free(src_data);
		*buffer = dst_data;
		return len;

	} else {
		buf = (byte *)X_Malloc(len, MEM_TAG_FILE);
		*buffer = buf;
		FS_Read (buf, len, h);
		fclose (h);
		return len;
	}





John Romero
Ion Storm - 64m3 D3516n3r
Daikatana: Done!
romero@ionstorm.com, romero@apple2.com
http://www.romerocreek.com

   ==______________
   ||   /  |   /   |
  [||______|_______|]
   /_____ooooo_____\
   [._\O|||||||O/_.]
   [w|$\_u===u_/$|w]
   [w]/         \[w]
   [w]           [w]



> -----Original Message-----
> From: Pentagram XIII [mailto:c_hollemeersch@hotmail.com]
> Sent: Thursday, April 27, 2000 3:14 PM
> To: romero@ionstorm.com
> Subject:
>
>
> Hello
>
> I found different posts of people wanting a "pakextracter" so
> I decided to
> modify my (quake2) pak library for Daikatana but the file
> system doen't seem
> to be exactly the same.
> I found out that every dir entry is 72 bytes long instead of
> the 64 bytes of
> quake but can you give me some information on what those 8
> extra bytes are
> used for? If I just ignore those 8 bytes the file size
> doesn't seem to be
> right. The extracted files can not be read by my graphics
> editor.(ASCII
> Script files seem to be ok)So I used the following structure
> to hold the
> entrys:
>
> type TpakEntry = packed record
>   filename    : array[0..55] of char;
>   offset      : longint
>   oldsize     : longint;//i use the next longint that way the offset
> adresses fit with the filesize but what is tis used for then?
>   size        : longint;
>   secoffset   : word;   // is this a second file offset?
>   moredata    : word;   // what is this for?
>   end;
>
> I currently add secoffset to offset before extracting my
> files that way the
> file seems to extract normally but my graphics editor still
> doesn't read it.
>   Is the data compressed and encrypted or someting?
> I understand that you may not able to give me this
> information because of
> leagal problems with editing extracting copyrighted data.
>
> Thank you
> Charles Hollemeersch
> ps: Daikatana is a really good game but my hardware is to slow :(
>
> You can find the Delphi source of my project at
> http://users.pandora.be/hollemeersch/daipak/


