*** WRA, WR3 (WRAptor compressed files, and version 3.0 files)
*** Document revision: 1.4
*** Last updated: March 11, 2004
*** Contributors/sources: Todd Elliott,
Fender Tucker & Doreen Horne (Loadstar)
Written by Bill Lucier (copyright 1995), distributed by Loadstar (on disk
and from the website), and fixed/updated by Doreen Horne, this is an
uncommon compression format as it is a relatively new program. It handles
PRG, SEQ, USR and GEOS files (Sequential and VLIR), but not REL files. As
of this writing, the latest bug fixed version was 3.0B. It is the support
for compressing GEOS files which makes this program special.
Many thanks to Fender Tucker (from Loadstar) and Doreen Horne for their
support on the Wraptor format, as well as authorizing the release of the
source code, and subsequent documentation of the format. I hope this
prolongs the life and usefulness of Wraptor.
Wraptor utilizes a variant of the LZSS (Lempel-Ziv) compression
algorithm, starting at 9 bits per code. The following is a dump of a sample
WRA file. The four bytes at the beginning of the file, "FF 42 4C FF" are
the signature, and preceed each compressed file in the archive. The "42 4C"
are the authors initials, "BL".
00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F ASCII
----------------------------------------------- ----------------
0000: FF 42 4C FF 50 4F 4F 59 41 4E 00 02 00 82 04 60 ?BL?POOYAN?.??.`
0010: 80 50 01 16 41 59 0C 14 F0 81 0C 47 49 31 11 40 ?P..AY..??.GI1.@
0020: 9E 4F 2C 90 49 C2 E2 61 3C 82 44 22 94 84 42 C1 ?O,?I+?a<?D"??B+
0030: C0 B0 62 00 21 82 02 90 62 0C 61 63 19 43 D4 4D +?b?!?.?b.ac.C?M
0040: 20 92 49 D1 F3 13 41 01 E0 02 78 68 37 1C 0D 40 ??I??.A.?.xh7..@
0050: 14 E1 40 00 DD 0B FF 42 4C FF 50 4F 4F 59 41 4E .?@??.?BL?POOYAN
0060: 2E 4D 41 49 4E 00 02 7E 0C 0A B0 31 31 00 08 00 .MAIN?.~..?11?.?
0070: 00 09 40 00 05 2A 00 02 A5 54 3C 81 10 88 00 08 ??@?.*?.?T<?.??.
Byte: $00-03: FF 42 4C FF - Compressed file signature "?BL?"
04-xx: 50 4F 4F 59 41 4E 00 - File name "POOYAN", terminated with
a $00 (null) byte
02 - File type
01 = SEQ
02 = PRG
03 = USR
04 = GEOS
What follows the filetype is compressed file data, up until two bytes
before the next signature, or two bytes to the end of the file, whichever
comes first. The two bytes at the end comprise the 16-bit CRC value.
The Wraptor format does not include information in the header that would
normally be considered important for generic decompression, such as:
1. No original or compressed file sizes
2. No offset to show where the next compressed file starts
3. No version# info, to know if the decompressor you have is the correct
type to uncompress the file. This is determined by the file extension,
with WR3 being the newest. WRA represents version 1.x and 2.x.
The original release of Wraptor (version 1.x) contained a few bugs,
specifically dealing with the compression and decompression of certain GEOS
filetypes, with all of the other file types (PRG, SEQ, USR) being fine.
Version 2.x was released, but more bugs with GEOS files were found. Thus
version 3.x was released.
As of version 3.x, the earlier WRA files are no longer supported, only
the WR3 files. To decode WRA files, you can either use a pre-3.0 version of
Wraptor, or rename the files to end with WR3 and see if version 3 will
unwrap them. If they contain a faulty compressed GEOS file, the file might
not decompress properly.
You can get a list of files contained in a WRA/WR3 file by using one of
the following two methods:
1. Decompress each file in succession, a tedious task at the best of
times. This *is* the method WRAptor uses to display and decompress
files in its archives, and it is very slow!
2. Scan the whole file for the "FF 42 4C FF" signature preceeding each
file, and store the starting offsets. There may be the possibility
that this signature will show up in the normal compressed data, but
the odds are very low.
The Wraptor compression on PRG, SEQ and USR files is very simple to
decode. GEOS files are the exception as they need to be reconstructed
exactly as they were, VLIR chains and all. The following C program explains
how basic decompression works, but not for GEOS:
---------------------------------------------------------------------------
/*
The following code assumes you have already read in the signature,
filename+NULL and filetype byte, and simply want to decode the data.
There is no provision made to decode the GEOS data, or actually show how
to calculate the CRC
*/
void main(void)
{
FILE *readfile, *writefile;
int i;
char data, type, tmp, rep_length, read_bitsize;
unsigned buff_pointer, dict_offset;
/* Output stream buffer */
char buffer[(unsigned)32768];
/* Compressed file to decode */
readfile=fopen("compress.wra","rb");
/* Uncompressed output stream */
writefile=fopen("uncompressed","wb");
/* Initial bitsize of the dictionary lookup */
read_bitsize=8;
/* Clear buffer pointer */
buff_pointer=0;
while(1)
{
/* Get compressed yes/no flag (single bit) from the input stream */
type=get_bits(1);
/* Normal unencoded data, preceeded by a zero bit */
if(!type)
{
/* Get normal 8-bit byte */
data=get_bits(8);
/* Add data to output buffer */
buffer[buff_pointer]=data;
/* Calculate the CRC as we read in the data */
calc_crc(data);
/* Move pointer for next data byte */
buff_pointer++;
/* Has the output buffer filled up? */
if(buff_pointer>=(unsigned)32768)
{
/* Write out the buffer to the output file */
/* Here is where we would decode the GEOS file structure */
fwrite(buffer, 1, buff_pointer, writefile);
/* Reset buffer pointer for another block of data */
buff_pointer=0;
}
}
/* Encoded data, preceeded by a one bit */
else
{
/* Get dictionary offset */
dict_offset=get_bits(read_bitsize);
/* A "0" offset, either an EOF or increase read_bitsize by one */
if(!dict_offset)
{
/* Check next bit */
tmp=get_bits(1);
/* If next bit clear, we are at the end of the compressed file */
if(!tmp)
{
/* Write output buffer to the output file */
/* Here is where we would decode the GEOS file structure */
fwrite(buffer, 1, buff_pointer,writefile);
buff_pointer=0;
break;
}
/* If next bit set, increase read_bitsize by one */
else
{
read_bitsize++;
}
}
/* We have a valid offset, get the length */
else
{
/* Length of the stored string, 5 bits */
rep_length=get_bits(5);
/*
Copy the data from in the buffer at the dict_offset position to
the end of the buffer
*/
for(i=0;i<rep_length;i++)
{
buffer[buff_pointer]=buffer[dict_offset-1+i];
buff_pointer++;
/* Write buffer to output file */
/* Here is where we would decode the GEOS file structure */
if(buff_pointer>=(unsigned)32768)
{
fwrite(buffer, 1, buff_pointer,writefile);
buff_pointer=0;
}
}
}
}
}
/* Get the two-byte CRC which follows the compressed data stream */
get_crc();
/* Make sure the CRC you read matches the one you calculated */
check_crc();
fclose(readfile);
fclose(writefile);
}
|