home *** CD-ROM | disk | FTP | other *** search
- #include <stdio.h>
- #include <stdlib.h>
-
- /*
-
- Peace 4.0, (c) Daniel Lemberg August 30th 1996
-
- LZSS compression and decompression routines, with a
- Blizzard warfile extractor and inserter. Written with
- Borland C++ 4.52.
-
- Feel free to copy anything you want, so long as it isn't
- for commercial gain. If it is, talk to me first.
-
- e-mail: lemberg@bayserve.net
- URL: http://www.bayserve.net/~lemberg
-
- */
-
- void help(void);
- void list(char *infile);
- void insert(char *infile, char *insert, int index);
- void extract(char *infile, char *outfile, int index);
- void decompress(char *infile, char *outfile);
- void compress(char *infile, char *outfile);
-
- void main(int argn, char **argc) {
-
- switch (argc[1][0]) {
- case 'l':
- if(argn < 3) help();
- list(argc[2]);
- break;
- case 'e':
- if(argn < 5) help();
- extract(argc[2], argc[3], atoi(argc[4]));
- break;
- case 'i':
- if(argn < 5) help();
- insert(argc[2], argc[3], atoi(argc[4]));
- break;
- default: help();
- }
- }
-
- void help(void) {
- printf("Usage:\n\n");
- printf("\tpeace l warfile\n");
- printf("\tpeace e warfile outfile index\n");
- printf("\tpeace i warfile infile index\n");
- exit(1);
- }
-
- void list(char *infile) {
-
- long x, y, length, temp, *buf;
- char type[5];
- FILE *inf;
- int z;
-
- inf = fopen(infile, "rb");
-
- if(!inf) {
- printf("Error opening %s, aborting.\n\n", infile);
- exit(1);
- }
-
- /* read in the position indexes */
-
- fseek(inf, 8, 0);
- fread(&length, 4, 1, inf);
- length -= 8;
- type[4] = 0;
-
- (void *)buf = malloc((size_t)length);
-
- buf[0] = length + 8;
- length = length >> 2;
-
- for(z=1; z < length; z++)
- fread(&buf[z], 4, 1, inf);
-
- /* loop for each index in the file */
-
- for(z=0; z < length; z++) {
-
- /* find uncompressed file size */
-
- if (buf[z+1] > buf[z] + 4) {
- fseek(inf, buf[z], 0);
- fread(&temp, 4, 1, inf);
- if(temp & 0xff000000L) fseek(inf, 1, 1);
- fread(&type, 4, 1, inf);
- }
- else {
- temp = buf[z+1] - buf[z];
- type[0] = 0;
- }
-
- /* print basic info */
-
- printf("%d:\t%lx\t%ld\t", z, buf[z], temp & 0xffffffL);
-
- /* Guess at file type, assumes first 4 bytes of data uncompressed */
-
- if((type[0] == 'T') && (type[1] == 'Y')) printf("PUD");
- else if((type[1] == 'O') && (type[2] == 'N')) printf("FONT");
- else if((type[1] == 'O') && (type[2] == 'R')) printf("FORM");
- else if((type[0] == 'R') && (type[1] == 'I')) printf("RIFF");
- else if((type[0] == 'S') && (type[1] == 'M')) printf("BMP");
- else if((type[0] == 'I') && (type[1] == 'F')) printf("IFF");
- else if((type[0] == 'B') && (type[1] == 'M')) printf("BMP");
- else {
- x = type[1];
- y = type[3];
- x = (x << 8) + type[0];
- y = (y << 8) + type[2];
- if((x * y + 4) == (temp & 0xffffffL)) printf("Image");
- }
-
- if(temp & 0xff000000L) printf("\t(compressed)");
- printf("\n");
- }
-
- fclose(inf);
- }
-
- void insert(char *infile, char *insert, int index) {
-
- long got, length, temp, size, *pos;
- char Buf[0x1000];
- FILE *inf, *outf;
- int z;
-
- /* read in the position indexes */
-
- inf = fopen(infile, "rb");
-
- if(!inf) {
- printf("Error opening %s, aborting.\n\n", infile);
- exit(1);
- }
-
- fseek(inf, 8, 0);
- fread(&length, 4, 1, inf);
- length -= 8;
-
- (void *)pos = malloc((size_t)length);
-
- pos[0] = length + 8;
- length = length >> 2;
-
- for(z=1; z < length; z++)
- fread(&pos[z], 4, 1, inf);
-
- size = pos[index+1] - pos[index];
- fclose(inf);
-
- /* compress the file to be inserted */
-
- compress(insert, "temp2.$$$");
- printf("Inserting...\n");
-
- /* write everything before index to temp.$$$ */
-
- inf = fopen(infile, "rb");
- outf = fopen("temp.$$$", "wb");
-
- got = fread(Buf, 1, 0x1000, inf);
- while((got < pos[index]) && (!(got & 0xfff))) {
- fwrite(Buf, 0x1000, 1, outf);
- got += fread(Buf, 1, 0x1000, inf);
- }
-
- if (got & 0xfff) fwrite(Buf, (size_t)(got & 0xfff), 1, outf);
- else fwrite(Buf, (size_t)(pos[index] - got + 0x1000), 1, outf);
-
- fclose(inf);
-
- /* build the header for the compressed file to be inserted */
-
- inf = fopen(insert, "rb");
- fseek(inf, 0, 2);
- temp = ftell(inf);
- fclose(inf);
-
- temp = (temp & 0xffffffL) | 0x20000000L;
- fwrite(&temp, 4, 1, outf);
-
- /* write the compressed file to temp.$$$ */
-
- inf = fopen("temp2.$$$", "rb");
-
- got = fread(Buf, 1, 0x1000, inf);
- while(!(got & 0xfff)) {
- fwrite(Buf, 0x1000, 1, outf);
- got += fread(Buf, 1, 0x1000, inf);
- }
-
- fwrite(Buf, (size_t)(got & 0xfff), 1, outf);
- fclose(inf);
-
- /* write everything after index +1 to temp.$$$ */
-
- inf = fopen(infile, "rb");
- fseek(inf, pos[index+1], 0);
-
- got = fread(Buf, 1, 0x1000, inf);
- while(!(got & 0xfff)) {
- fwrite(Buf, 0x1000, 1, outf);
- got += fread(Buf, 1, 0x1000, inf);
- }
-
- fwrite(Buf, (size_t)(got & 0xfff), 1, outf);
-
- fclose(inf);
-
- /* update and write the position indexes */
-
- inf = fopen("temp2.$$$", "rb");
- fseek(inf, 0, 2);
- size = (ftell(inf) - size);
- fclose(inf);
-
- for(z=index+1; z < length; z++)
- pos[z] += size;
-
- fseek(outf, 8, 0);
- fwrite(pos, (size_t)(length << 2), 1, outf);
- fclose(outf);
-
- /* clean up */
-
- unlink("temp2.$$$");
- }
-
- void extract(char *infile, char *outfile, int index) {
-
- long got, length, temp;
- char Buf[0x1000], comp = 0;
- FILE *inf, *outf;
-
- inf = fopen(infile, "rb");
-
- if(!inf) {
- printf("Error opening %s, aborting.\n\n", infile);
- exit(1);
- }
-
- /* find the offset of index */
-
- fseek(inf, 8, 0);
- fread(&length, 4, 1, inf);
-
- index = (index << 2) + 8;
-
- if(index >= length) {
- printf("Index greater than number of items in file.\n\n");
- exit(1);
- }
-
- fseek(inf, index, 0);
- fread(&length, 4, 1, inf);
- fread(&temp, 4, 1, inf);
- fseek(inf, length, 0);
- length = temp - length - 4;
-
- /* check to see if index is compressed */
-
- fread(&got, 4, 1, inf);
- if(got & 0xff000000L) comp = 1;
-
- /* extract the file */
-
- if(comp) outf = fopen("temp.$$$", "wb");
- else outf = fopen(outfile, "wb");
-
- if(!outf) {
- printf("Error writing %s, aborting.\n\n", outfile);
- exit(1);
- }
-
- got = fread(Buf, 1, 0x1000, inf);
- while((got < length) && (!(got & 0xfff))) {
- fwrite(Buf, 0x1000, 1, outf);
- got += fread(Buf, 1, 0x1000, inf);
- }
-
- if (got & 0xfff) fwrite(Buf, (size_t)(got & 0xfff), 1, outf);
- else fwrite(Buf, (size_t)(length - got + 0x1000), 1, outf);
-
- fclose(outf);
- fclose(inf);
-
- /* if compressed, decompress */
-
- if(comp) {
- decompress("temp.$$$", outfile);
- unlink("temp.$$$");
- }
- }
-
- void decompress(char *infile, char *outfile) {
-
- unsigned int flags, b1pos, b2pos, got, len, where, i;
- unsigned char Buf1[0x1000], Buf2[0x1000];
- FILE *inf, *outf;
-
- inf = fopen(infile, "rb");
- outf = fopen(outfile, "wb");
-
- if(!inf) {
- printf("Error opening %s, aborting.\n\n", infile);
- exit(1);
- }
-
- if(!outf) {
- printf("Error writing %s, aborting.\n\n", outfile);
- exit(1);
- }
-
- printf("Decompressing...\n");
-
- /* clear Buf1, buffer positions, and flags */
-
- for(i=0; i < 0x1000; i++) Buf1[i] = 0;
- b1pos = b2pos = flags = 0;
-
- /* start the input cache */
-
- got = fread(Buf2, 1, 0x1000, inf);
-
- /* start decompressing */
-
- while(b2pos != got) {
-
- /* read the next flag */
-
- flags = (flags >> 1);
-
- if(!(flags & 0x100)) {
- flags = (0xFF00 | Buf2[b2pos]);
- b2pos = ((++b2pos) & 0xfff);
- if(!b2pos) got = fread(Buf2, 1, 0x1000, inf);
- }
-
- /* check for EOF */
-
- if(b2pos == got) continue;
-
- /* uncompressed byte */
-
- if((flags & 1) == 1) {
- Buf1[b1pos] = Buf2[b2pos];
- b1pos = ((++b1pos) & 0xfff);
- b2pos = ((++b2pos) & 0xfff);
- if(!b1pos) fwrite(Buf1, 0x1000, 1, outf);
- if(!b2pos) got = fread(Buf2, 1, 0x1000, inf);
- }
-
- /* pos/len pair */
-
- else {
- where = Buf2[b2pos];
- b2pos = ((++b2pos) & 0xfff);
- if(!b2pos) got = fread(Buf2, 1, 0x1000, inf);
-
- if(b2pos == got) continue;
-
- len = Buf2[b2pos];
- b2pos = ((++b2pos) & 0xfff);
- if(!b2pos) got = fread(Buf2, 1, 0x1000, inf);
-
- where = (((len & 0x0F) << 8) | where);
- len = ((len & 0xF0) >> 4) + 3 + where;
-
- for(i=where; i < len; i++) {
- Buf1[b1pos] = Buf1[i & 0xfff];;
- b1pos = ((++b1pos) & 0xfff);
- if(!b1pos) fwrite(Buf1, 0x1000, 1, outf);
- }
- }
- }
-
- /* flush the output cache */
-
- fwrite(Buf1, b1pos, 1, outf);
-
- fclose(inf);
- fclose(outf);
- }
-
- void compress(char *infile, char *outfile) {
-
- int ipos, opos, oold, got, where, i, len, y, z, flags;
- unsigned char ibuf[0x2000], obuf[0x1000];
- FILE *inf, *outf;
-
- inf = fopen(infile, "rb");
- outf = fopen(outfile, "wb");
-
- if(!inf) {
- printf("Error opening %s, aborting.\n\n", infile);
- exit(1);
- }
-
- if(!outf) {
- printf("Error writing %s, aborting.\n\n", outfile);
- exit(1);
- }
-
- printf("Compressing: ");
-
- /* clear input cache, set buffer positions and flags */
-
- for(i=0; i < 0x1000; i++) ibuf[i] = 0;
-
- flags = opos = 0;
- ipos = got = 0x1000;
-
- /* start the input cache */
-
- got = (got + fread(&ibuf[ipos], 1, 0x1000, inf)) & 0x1fff;
-
- /* compress */
-
- while(ipos != got) {
-
- oold = opos;
- opos++;
-
- /* new flagged section */
-
- for(y=0; y < 8; y++) {
-
- if(ipos == got) break;
- flags = flags >> 1;
-
- /* check for match */
-
- len = ipos;
- where = 0x1000;
-
- for(i=-4096; i < 0; i++) {
-
- z = ipos;
-
- while((ibuf[z & 0x1fff] == ibuf[(z+i) & 0x1fff])
- && (++z < ipos+18));
-
- if(z > len) {
- where = i;
- len = z;
- }
- }
-
- len -= ipos;
-
- /* match found */
-
- if(len > 2) {
-
- where = (where + ipos & 0xfff) & 0xfff;
-
- obuf[opos++] = (where & 0xff);
- obuf[opos++] = ((where & 0xf00) >> 8) + ((len - 3) << 4);
-
- for(i=0; i < len; i++) {
- ipos = ((++ipos) & 0x1fff);
- if(!(ipos & 0x7ff) && !feof(inf))
- got = (got + fread(&ibuf[(ipos+0x800) & 0x1fff], 1, 0x800, inf)) & 0x1fff;
- }
- }
-
- /* no match found */
-
- else {
- flags = flags | 0x80;
- obuf[opos++] = ibuf[ipos];
- ipos = ((++ipos) & 0x1fff);
- if(!(ipos & 0x7ff) && !feof(inf))
- got = (got + fread(&ibuf[(ipos+0x800) & 0x1fff], 1, 0x800, inf)) & 0x1fff;
- }
- }
-
- /* write the flags and test to dump output cache */
-
- if(y != 8) flags = flags >> (8 - y);
-
- obuf[oold] = flags;
-
- if(opos + 17 >= 0x1000) {
- fwrite(obuf, opos, 1, outf);
- printf("#");
- opos = 0;
- }
- }
-
- /* flush the output cache */
-
- printf("#\n");
- fwrite(obuf, opos, 1, outf);
-
- fclose(inf);
- fclose(outf);
- }
-
-