home *** CD-ROM | disk | FTP | other *** search
/ 5.000 Levels & Add-Ons für Warcraft II / WC5000.BIN / wartools / peace / peace.c next >
Encoding:
C/C++ Source or Header  |  1996-08-30  |  10.3 KB  |  508 lines

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3.  
  4. /*
  5.  
  6.         Peace 4.0, (c) Daniel Lemberg August 30th 1996
  7.  
  8.     LZSS compression and decompression routines, with a
  9.     Blizzard warfile extractor and inserter. Written with
  10.     Borland C++ 4.52.
  11.  
  12.     Feel free to copy anything you want, so long as it isn't
  13.     for commercial gain. If it is, talk to me first.
  14.  
  15.     e-mail:  lemberg@bayserve.net
  16.     URL:     http://www.bayserve.net/~lemberg
  17.  
  18. */
  19.  
  20. void help(void);
  21. void list(char *infile);
  22. void insert(char *infile, char *insert, int index);
  23. void extract(char *infile, char *outfile, int index);
  24. void decompress(char *infile, char *outfile);
  25. void compress(char *infile, char *outfile);
  26.  
  27. void main(int argn, char **argc) {
  28.  
  29.     switch (argc[1][0]) {
  30.         case 'l':
  31.             if(argn < 3) help();
  32.             list(argc[2]);
  33.             break;
  34.         case 'e':
  35.             if(argn < 5) help();
  36.             extract(argc[2], argc[3], atoi(argc[4]));
  37.             break;
  38.         case 'i':
  39.             if(argn < 5) help();
  40.             insert(argc[2], argc[3], atoi(argc[4]));
  41.             break;
  42.         default: help();
  43.     }
  44. }
  45.  
  46. void help(void) {
  47.     printf("Usage:\n\n");
  48.     printf("\tpeace l warfile\n");
  49.     printf("\tpeace e warfile outfile index\n");
  50.     printf("\tpeace i warfile infile index\n");
  51.     exit(1);
  52. }
  53.  
  54. void list(char *infile) {
  55.  
  56.     long x, y, length, temp, *buf;
  57.     char type[5];
  58.     FILE *inf;
  59.     int z;
  60.  
  61.     inf = fopen(infile, "rb");
  62.  
  63.     if(!inf) {
  64.         printf("Error opening %s, aborting.\n\n", infile);
  65.         exit(1);
  66.     }
  67.  
  68.     /* read in the position indexes */
  69.  
  70.     fseek(inf, 8, 0);
  71.     fread(&length, 4, 1, inf);
  72.     length -= 8;
  73.     type[4] = 0;
  74.  
  75.     (void *)buf = malloc((size_t)length);
  76.  
  77.     buf[0] = length + 8;
  78.     length = length >> 2;
  79.  
  80.     for(z=1; z < length; z++)
  81.         fread(&buf[z], 4, 1, inf);
  82.  
  83.     /* loop for each index in the file */
  84.  
  85.     for(z=0; z < length; z++) {
  86.  
  87.         /* find uncompressed file size */
  88.  
  89.         if (buf[z+1] > buf[z] + 4) {
  90.             fseek(inf, buf[z], 0);
  91.             fread(&temp, 4, 1, inf);
  92.             if(temp & 0xff000000L) fseek(inf, 1, 1);
  93.             fread(&type, 4, 1, inf);
  94.         }
  95.         else {
  96.             temp = buf[z+1] - buf[z];
  97.             type[0] = 0;
  98.         }
  99.  
  100.         /* print basic info */
  101.  
  102.         printf("%d:\t%lx\t%ld\t", z, buf[z], temp & 0xffffffL);
  103.  
  104.         /* Guess at file type, assumes first 4 bytes of data uncompressed */
  105.  
  106.         if((type[0] == 'T') && (type[1] == 'Y')) printf("PUD");
  107.         else if((type[1] == 'O') && (type[2] == 'N')) printf("FONT");
  108.         else if((type[1] == 'O') && (type[2] == 'R')) printf("FORM");
  109.         else if((type[0] == 'R') && (type[1] == 'I')) printf("RIFF");
  110.         else if((type[0] == 'S') && (type[1] == 'M')) printf("BMP");
  111.         else if((type[0] == 'I') && (type[1] == 'F')) printf("IFF");
  112.         else if((type[0] == 'B') && (type[1] == 'M')) printf("BMP");
  113.         else {
  114.             x = type[1];
  115.             y = type[3];
  116.             x = (x << 8) + type[0];
  117.             y = (y << 8) + type[2];
  118.             if((x * y + 4) == (temp & 0xffffffL)) printf("Image");
  119.         }
  120.  
  121.         if(temp & 0xff000000L) printf("\t(compressed)");
  122.         printf("\n");
  123.     }
  124.  
  125.     fclose(inf);
  126. }
  127.  
  128. void insert(char *infile, char *insert, int index) {
  129.  
  130.     long got, length, temp, size, *pos;
  131.     char Buf[0x1000];
  132.     FILE *inf, *outf;
  133.     int z;
  134.  
  135.     /* read in the position indexes */
  136.  
  137.     inf = fopen(infile, "rb");
  138.  
  139.     if(!inf) {
  140.         printf("Error opening %s, aborting.\n\n", infile);
  141.         exit(1);
  142.     }
  143.  
  144.     fseek(inf, 8, 0);
  145.     fread(&length, 4, 1, inf);
  146.     length -= 8;
  147.  
  148.     (void *)pos = malloc((size_t)length);
  149.  
  150.     pos[0] = length + 8;
  151.     length = length >> 2;
  152.  
  153.     for(z=1; z < length; z++)
  154.         fread(&pos[z], 4, 1, inf);
  155.  
  156.     size = pos[index+1] - pos[index];
  157.     fclose(inf);
  158.  
  159.     /* compress the file to be inserted */
  160.  
  161.     compress(insert, "temp2.$$$");
  162.     printf("Inserting...\n");
  163.  
  164.     /* write everything before index to temp.$$$ */
  165.  
  166.     inf = fopen(infile, "rb");
  167.     outf = fopen("temp.$$$", "wb");
  168.  
  169.     got = fread(Buf, 1, 0x1000, inf);
  170.     while((got < pos[index]) && (!(got & 0xfff))) {
  171.         fwrite(Buf, 0x1000, 1, outf);
  172.         got += fread(Buf, 1, 0x1000, inf);
  173.     }
  174.  
  175.     if (got & 0xfff) fwrite(Buf, (size_t)(got & 0xfff), 1, outf);
  176.     else fwrite(Buf, (size_t)(pos[index] - got + 0x1000), 1, outf);
  177.  
  178.     fclose(inf);
  179.  
  180.     /* build the header for the compressed file to be inserted */
  181.  
  182.     inf = fopen(insert, "rb");
  183.     fseek(inf, 0, 2);
  184.     temp = ftell(inf);
  185.     fclose(inf);
  186.  
  187.     temp = (temp & 0xffffffL) | 0x20000000L;
  188.     fwrite(&temp, 4, 1, outf);
  189.  
  190.     /* write the compressed file to temp.$$$ */
  191.  
  192.     inf = fopen("temp2.$$$", "rb");
  193.  
  194.     got = fread(Buf, 1, 0x1000, inf);
  195.     while(!(got & 0xfff)) {
  196.         fwrite(Buf, 0x1000, 1, outf);
  197.         got += fread(Buf, 1, 0x1000, inf);
  198.     }
  199.  
  200.     fwrite(Buf, (size_t)(got & 0xfff), 1, outf);
  201.     fclose(inf);
  202.  
  203.     /* write everything after index +1 to temp.$$$ */
  204.  
  205.     inf = fopen(infile, "rb");
  206.     fseek(inf, pos[index+1], 0);
  207.  
  208.     got = fread(Buf, 1, 0x1000, inf);
  209.     while(!(got & 0xfff)) {
  210.         fwrite(Buf, 0x1000, 1, outf);
  211.         got += fread(Buf, 1, 0x1000, inf);
  212.     }
  213.  
  214.     fwrite(Buf, (size_t)(got & 0xfff), 1, outf);
  215.  
  216.     fclose(inf);
  217.  
  218.     /* update and write the position indexes */
  219.  
  220.     inf = fopen("temp2.$$$", "rb");
  221.     fseek(inf, 0, 2);
  222.     size = (ftell(inf) - size);
  223.     fclose(inf);
  224.  
  225.     for(z=index+1; z < length; z++)
  226.         pos[z] += size;
  227.  
  228.     fseek(outf, 8, 0);
  229.     fwrite(pos, (size_t)(length << 2), 1, outf);
  230.     fclose(outf);
  231.  
  232.     /* clean up */
  233.  
  234.     unlink("temp2.$$$");
  235. }
  236.  
  237. void extract(char *infile, char *outfile, int index) {
  238.  
  239.     long got, length, temp;
  240.     char Buf[0x1000], comp = 0;
  241.     FILE *inf, *outf;
  242.  
  243.     inf = fopen(infile, "rb");
  244.  
  245.     if(!inf) {
  246.         printf("Error opening %s, aborting.\n\n", infile);
  247.         exit(1);
  248.     }
  249.  
  250.     /* find the offset of index */
  251.  
  252.     fseek(inf, 8, 0);
  253.     fread(&length, 4, 1, inf);
  254.  
  255.     index = (index << 2) + 8;
  256.  
  257.     if(index >= length) {
  258.         printf("Index greater than number of items in file.\n\n");
  259.         exit(1);
  260.     }
  261.  
  262.     fseek(inf, index, 0);
  263.     fread(&length, 4, 1, inf);
  264.     fread(&temp, 4, 1, inf);
  265.     fseek(inf, length, 0);
  266.     length = temp - length - 4;
  267.  
  268.     /* check to see if index is compressed */
  269.  
  270.     fread(&got, 4, 1, inf);
  271.     if(got & 0xff000000L) comp = 1;
  272.  
  273.     /* extract the file */
  274.  
  275.     if(comp) outf = fopen("temp.$$$", "wb");
  276.     else outf = fopen(outfile, "wb");
  277.  
  278.     if(!outf) {
  279.         printf("Error writing %s, aborting.\n\n", outfile);
  280.         exit(1);
  281.     }
  282.  
  283.     got = fread(Buf, 1, 0x1000, inf);
  284.     while((got < length) && (!(got & 0xfff))) {
  285.         fwrite(Buf, 0x1000, 1, outf);
  286.         got += fread(Buf, 1, 0x1000, inf);
  287.     }
  288.  
  289.     if (got & 0xfff) fwrite(Buf, (size_t)(got & 0xfff), 1, outf);
  290.     else fwrite(Buf, (size_t)(length - got + 0x1000), 1, outf);
  291.  
  292.     fclose(outf);
  293.     fclose(inf);
  294.  
  295.     /* if compressed, decompress */
  296.  
  297.     if(comp) {
  298.         decompress("temp.$$$", outfile);
  299.         unlink("temp.$$$");
  300.     }
  301. }
  302.  
  303. void decompress(char *infile, char *outfile) {
  304.  
  305.     unsigned int flags, b1pos, b2pos, got, len, where, i;
  306.     unsigned char Buf1[0x1000], Buf2[0x1000];
  307.     FILE *inf, *outf;
  308.  
  309.     inf = fopen(infile, "rb");
  310.     outf = fopen(outfile, "wb");
  311.  
  312.     if(!inf) {
  313.         printf("Error opening %s, aborting.\n\n", infile);
  314.         exit(1);
  315.     }
  316.  
  317.     if(!outf) {
  318.         printf("Error writing %s, aborting.\n\n", outfile);
  319.         exit(1);
  320.     }
  321.  
  322.     printf("Decompressing...\n");
  323.  
  324.     /* clear Buf1, buffer positions, and flags */
  325.  
  326.     for(i=0; i < 0x1000; i++) Buf1[i] = 0;
  327.     b1pos = b2pos = flags = 0;
  328.  
  329.     /* start the input cache */
  330.  
  331.     got = fread(Buf2, 1, 0x1000, inf);
  332.  
  333.     /* start decompressing */
  334.  
  335.     while(b2pos != got) {
  336.  
  337.         /* read the next flag */
  338.  
  339.         flags = (flags >> 1);
  340.  
  341.         if(!(flags & 0x100)) {
  342.             flags = (0xFF00 | Buf2[b2pos]);
  343.             b2pos = ((++b2pos) & 0xfff);
  344.             if(!b2pos) got = fread(Buf2, 1, 0x1000, inf);
  345.         }
  346.  
  347.         /* check for EOF */
  348.  
  349.         if(b2pos == got) continue;
  350.  
  351.         /* uncompressed byte */
  352.  
  353.         if((flags & 1) == 1) {
  354.             Buf1[b1pos] = Buf2[b2pos];
  355.             b1pos = ((++b1pos) & 0xfff);
  356.             b2pos = ((++b2pos) & 0xfff);
  357.             if(!b1pos) fwrite(Buf1, 0x1000, 1, outf);
  358.             if(!b2pos) got = fread(Buf2, 1, 0x1000, inf);
  359.         }
  360.  
  361.         /* pos/len pair */
  362.  
  363.         else {
  364.             where = Buf2[b2pos];
  365.             b2pos = ((++b2pos) & 0xfff);
  366.             if(!b2pos) got = fread(Buf2, 1, 0x1000, inf);
  367.  
  368.             if(b2pos == got) continue;
  369.  
  370.             len = Buf2[b2pos];
  371.             b2pos = ((++b2pos) & 0xfff);
  372.             if(!b2pos) got = fread(Buf2, 1, 0x1000, inf);
  373.  
  374.             where = (((len & 0x0F) << 8) | where);
  375.             len = ((len & 0xF0) >> 4) + 3 + where;
  376.  
  377.             for(i=where; i < len; i++) {
  378.                 Buf1[b1pos] = Buf1[i & 0xfff];;
  379.                 b1pos = ((++b1pos) & 0xfff);
  380.                 if(!b1pos) fwrite(Buf1, 0x1000, 1, outf);
  381.             }
  382.         }
  383.     }
  384.  
  385.     /* flush the output cache */
  386.  
  387.     fwrite(Buf1, b1pos, 1, outf);
  388.  
  389.     fclose(inf);
  390.     fclose(outf);
  391. }
  392.  
  393. void compress(char *infile, char *outfile) {
  394.  
  395.     int ipos, opos, oold, got, where, i, len, y, z, flags;
  396.     unsigned char ibuf[0x2000], obuf[0x1000];
  397.     FILE *inf, *outf;
  398.  
  399.     inf = fopen(infile, "rb");
  400.     outf = fopen(outfile, "wb");
  401.  
  402.     if(!inf) {
  403.         printf("Error opening %s, aborting.\n\n", infile);
  404.         exit(1);
  405.     }
  406.  
  407.     if(!outf) {
  408.         printf("Error writing %s, aborting.\n\n", outfile);
  409.         exit(1);
  410.     }
  411.  
  412.     printf("Compressing: ");
  413.  
  414.     /* clear input cache, set buffer positions and flags */
  415.  
  416.     for(i=0; i < 0x1000; i++) ibuf[i] = 0;
  417.  
  418.     flags = opos = 0;
  419.     ipos = got = 0x1000;
  420.  
  421.     /* start the input cache */
  422.  
  423.     got = (got + fread(&ibuf[ipos], 1, 0x1000, inf)) & 0x1fff;
  424.  
  425.     /* compress */
  426.  
  427.     while(ipos != got) {
  428.  
  429.         oold = opos;
  430.         opos++;
  431.  
  432.         /* new flagged section */
  433.  
  434.         for(y=0; y < 8; y++) {
  435.  
  436.             if(ipos == got) break;
  437.             flags = flags >> 1;
  438.  
  439.             /* check for match */
  440.  
  441.             len = ipos;
  442.             where = 0x1000;
  443.  
  444.             for(i=-4096; i < 0; i++) {
  445.  
  446.                 z = ipos;
  447.  
  448.                 while((ibuf[z & 0x1fff] == ibuf[(z+i) & 0x1fff])
  449.                     && (++z < ipos+18));
  450.  
  451.                 if(z > len) {
  452.                     where = i;
  453.                     len = z;
  454.                 }
  455.             }
  456.  
  457.             len -= ipos;
  458.  
  459.             /* match found */
  460.  
  461.             if(len > 2) {
  462.  
  463.                 where = (where + ipos & 0xfff) & 0xfff;
  464.  
  465.                 obuf[opos++] = (where & 0xff);
  466.                 obuf[opos++] = ((where & 0xf00) >> 8) + ((len - 3) << 4);
  467.  
  468.                 for(i=0; i < len; i++) {
  469.                     ipos = ((++ipos) & 0x1fff);
  470.                     if(!(ipos & 0x7ff) && !feof(inf))
  471.                         got = (got + fread(&ibuf[(ipos+0x800) & 0x1fff], 1, 0x800, inf)) & 0x1fff;
  472.                 }
  473.             }
  474.  
  475.             /* no match found */
  476.  
  477.             else {
  478.                 flags = flags | 0x80;
  479.                 obuf[opos++] = ibuf[ipos];
  480.                 ipos = ((++ipos) & 0x1fff);
  481.                 if(!(ipos & 0x7ff) && !feof(inf))
  482.                     got = (got + fread(&ibuf[(ipos+0x800) & 0x1fff], 1, 0x800, inf)) & 0x1fff;
  483.             }
  484.         }
  485.  
  486.         /* write the flags and test to dump output cache */
  487.  
  488.         if(y != 8) flags = flags >> (8 - y);
  489.  
  490.         obuf[oold] = flags;
  491.  
  492.         if(opos + 17 >= 0x1000) {
  493.             fwrite(obuf, opos, 1, outf);
  494.             printf("#");
  495.             opos = 0;
  496.         }
  497.     }
  498.  
  499.     /* flush the output cache */
  500.  
  501.     printf("#\n");
  502.     fwrite(obuf, opos, 1, outf);
  503.  
  504.     fclose(inf);
  505.     fclose(outf);
  506. }
  507.  
  508.