home *** CD-ROM | disk | FTP | other *** search
/ ANews 1 / AnewsCD01.iso / Indispensables / Compression / xad / Developer / Sources / clients / LZX.c < prev    next >
C/C++ Source or Header  |  1999-08-09  |  26KB  |  990 lines

  1. #ifndef XADMASTER_LZX_C
  2. #define XADMASTER_LZX_C
  3.  
  4. /* Programmheader
  5.  
  6.     Name:        LZX.c
  7.     Main:        xadmaster
  8.     Versionstring:    $VER: LZX.c 1.3 (29.06.1999)
  9.     Author:        SDI, David Tritscher
  10.     Distribution:    Freeware
  11.     Description:    LZX file archiver client
  12.  
  13.  1.0   09.02.99 : first working version
  14.  1.1   13.03.99 : now uses register parameters
  15.  1.2   20.06.99 : removed exec.library calls
  16.  1.3   29.06.99 : now uses master free stuff
  17. */
  18.  
  19. /* The decrunch routines of this client are based on unlzx sources code made
  20.    by David Tritscher. Thanks guy, was a big help. A made the routines
  21.    reentrant (using a parameter structure) and developed the XAD interface
  22.    functions. */
  23.  
  24. #include <proto/xadmaster.h>
  25. #include <exec/memory.h>
  26. #include <dos/dos.h>
  27. #include "SDI_compiler.h"
  28. #define SDI_TO_ANSI
  29. #include "SDI_ASM_STD_protos.h"
  30.  
  31. #ifndef XADMASTERFILE
  32. #define LZX_Client        FirstClient
  33. #define NEXTCLIENT        0
  34. UBYTE version[] = "$VER: LZX 1.3 (29.06.1999) Freeware";
  35. #endif
  36. #define LZX_VERSION        1
  37. #define LZX_REVISION        3
  38.  
  39. /* ---------------------------------------------------------------------- */
  40.  
  41. #define LZXINFO_DAMAGE_PROTECT 1
  42. #define LZXINFO_FLAG_LOCKED 2
  43.  
  44. struct LZXInfo_Header
  45. {
  46.   UBYTE ID[3];            /* "LZX" */
  47.   UBYTE Flags;            /* LZXINFO_FLAG_#? */
  48.   UBYTE Unknown[6];        
  49. };
  50.  
  51. #define LZXHDR_FLAG_MERGED    (1<<0)
  52.  
  53. #define LZXHDR_PROT_READ    (1<<0)
  54. #define LZXHDR_PROT_WRITE    (1<<1)
  55. #define LZXHDR_PROT_DELETE    (1<<2)
  56. #define LZXHDR_PROT_EXECUTE    (1<<3)
  57. #define LZXHDR_PROT_ARCHIVE    (1<<4)
  58. #define LZXHDR_PROT_HOLD    (1<<5)
  59. #define LZXHDR_PROT_SCRIPT    (1<<6)
  60. #define LZXHDR_PROT_PURE    (1<<7)
  61.  
  62. #define LZXHDR_TYPE_MSDOS    0
  63. #define LZXHDR_TYPE_WINDOWS    1
  64. #define LZXHDR_TYPE_OS2        2
  65. #define LZXHDR_TYPE_AMIGA    10
  66. #define LZXHDR_TYPE_UNIX    20
  67.  
  68. #define LZXHDR_PACK_STORE    0
  69. #define LZXHDR_PACK_NORMAL    2
  70. #define LZXHDR_PACK_EOF        32
  71.  
  72. struct LZXArc_Header
  73. {
  74.   UBYTE Attributes;        /*  0 - LZXHDR_PROT_#? */
  75.   UBYTE pad1;            /*  1 */
  76.   ULONG FileSize;        /*  2 (little endian) */
  77.   ULONG CrSize;            /*  6 (little endian) */
  78.   UBYTE MachineType;        /* 10 - LZXHDR_TYPE_#? */
  79.   UBYTE PackMode;        /* 11 - LZXHDR_PACK_#? */
  80.   UBYTE Flags;            /* 12 - LZXHDR_FLAG_#? */
  81.   UBYTE pad2;            /* 13 */
  82.   UBYTE CommentSize;        /* 14 - length (0-79) */
  83.   UBYTE ExtractVersion;        /* 15 - version needed to extract */
  84.   UBYTE pad3;            /* 16 */
  85.   UBYTE pad4;            /* 17 */
  86.   ULONG Date;            /* 18 - Packed_Date */
  87.   ULONG DataCRC;        /* 22 (little endian) */
  88.   ULONG HeaderCRC;        /* 26 (little endian) */
  89.   UBYTE FilenameSize;        /* 30 - filename length */
  90. }; /* SIZE = 31 */
  91.  
  92. /* Header CRC includes filename and comment. */
  93.  
  94. #define LZXHEADERSIZE    31
  95.  
  96. /* Packed date [4 BYTES, bit 0 is MSB, 31 is LSB]
  97.   bit  0 -  4    Day
  98.        5 -  8    Month    (January is 0)
  99.        9 - 14    Year    (start 1970)
  100.       15 - 19    Hour
  101.       20 - 25    Minute
  102.       26 - 31    Second
  103. */
  104.  
  105. struct LZXEntryData {
  106.   ULONG CRC;        /* CRC of uncrunched data */
  107.   ULONG PackMode;    /* CrunchMode */
  108.   ULONG ArchivePos;    /* Position is source file */
  109.   ULONG DataStart;    /* Position in merged buffer */
  110. };
  111.  
  112. #define LZXPE(a)    ((struct LZXEntryData *) ((a)->xfi_PrivateInfo))
  113. #define LZXDD(a)    ((struct LZXDecrData *) ((a)->xai_PrivateClient))
  114. struct LZXDecrData {
  115.   ULONG ArchivePos;    /* The Archive-Pos to detect if it is correct buffer */
  116.   ULONG DataPos;    /* must be lower or equal to current entry or reinit is necessary */
  117.  
  118.   UBYTE *source;
  119.   UBYTE *destination;
  120.   UBYTE *source_end;
  121.   UBYTE *destination_end;
  122.   UBYTE *pos;
  123.  
  124.   ULONG decrunch_method;
  125.   ULONG decrunch_length;
  126.   ULONG pack_size;
  127.   ULONG last_offset;
  128.   ULONG control;
  129.   LONG  shift;
  130.  
  131.   UBYTE offset_len[8];
  132.   UWORD offset_table[128];
  133.   UBYTE huffman20_len[20];
  134.   UWORD huffman20_table[96];
  135.   UBYTE literal_len[768];
  136.   UWORD literal_table[5120];
  137.  
  138.   UBYTE read_buffer[16384];        /* have a reasonable sized read buffer */
  139.   UBYTE decrunch_buffer[258+65536+258];    /* allow overrun for speed */
  140. };
  141.  
  142. static ULONG LZXConvEnd32(ULONG a)
  143. {
  144.   ULONG b = 0, i;
  145.   
  146.   for(i = 0; i <= 24; i += 8)
  147.     b += ((UBYTE)(a >> i))<<(24-i);
  148.   return b;
  149. }
  150.  
  151. ASM(BOOL) LZX_RecogData(REG(d0, ULONG size), REG(a0, STRPTR data),
  152. REG(a6, struct xadMasterBase *xadMasterBase))
  153. {
  154.   if(data[0] == 'L' && data[1] == 'Z' && data[2] == 'X')
  155.     return 1;
  156.   else
  157.     return 0;
  158. }
  159.  
  160. ASM(LONG) LZX_GetInfo(REG(a0, struct xadArchiveInfo *ai),
  161. REG(a6, struct xadMasterBase *xadMasterBase))
  162. {
  163.   LONG err, num = 1;
  164.   ULONG bufpos = 0;
  165.   struct xadFileInfo *fi = 0, *fi2, *fig = 0; /* fig - first grouped ptr */
  166.   struct LZXArc_Header head;
  167.  
  168.   if(!(err = xadHookAccess(XADAC_INPUTSEEK, sizeof(struct LZXInfo_Header), 0, ai)))
  169.   {
  170.     while(!err && ai->xai_InPos < ai->xai_InSize)
  171.     {
  172.       if(!(err = xadHookAccess(XADAC_READ, LZXHEADERSIZE, &head, ai)))
  173.       {
  174.     ULONG i, j, k, l, crc;
  175.         i = head.CommentSize;
  176.         j = head.FilenameSize;
  177.         k = LZXConvEnd32(head.HeaderCRC);
  178.         head.HeaderCRC = 0; /* clear for CRC check */
  179.  
  180.         if(!(fi2 = (struct xadFileInfo *) xadAllocObject(XADOBJ_FILEINFO,
  181.         XAD_OBJNAMESIZE, j+1, i ? XAD_OBJCOMMENTSIZE : TAG_IGNORE, i+1,
  182.         XAD_OBJPRIVINFOSIZE, sizeof(struct LZXEntryData), TAG_DONE)))
  183.           err = XADERR_NOMEMORY;
  184.         else if(!(err = xadHookAccess(XADAC_READ, j, fi2->xfi_FileName, ai)) &&
  185.         (!i || !(err = xadHookAccess(XADAC_READ, i, fi2->xfi_Comment, ai))))
  186.         {
  187.           l = LZXConvEnd32(head.CrSize);
  188.  
  189.           if(!l || !(err = xadHookAccess(XADAC_INPUTSEEK, l, 0, ai)))
  190.           {
  191.             crc = xadCalcCRC32(XADCRC32_ID1, ~0, LZXHEADERSIZE, (STRPTR) &head);
  192.             crc = xadCalcCRC32(XADCRC32_ID1, crc, j, fi2->xfi_FileName);
  193.             if(i)
  194.               crc = xadCalcCRC32(XADCRC32_ID1, crc, i, fi2->xfi_Comment);
  195.  
  196.             if(~crc != k)
  197.               err = XADERR_CHECKSUM;
  198.             else
  199.             {
  200.               if(!fig)
  201.               {
  202.                 fig = fi2; bufpos = 0;
  203.               }
  204.           fi2->xfi_Size = LZXConvEnd32(head.FileSize);
  205.           fi2->xfi_EntryNumber = num++;
  206.           if(!l && !fi2->xfi_Size && fi2->xfi_FileName[--j] == '/')
  207.           {
  208.             fi2->xfi_FileName[j] = 0;
  209.             fi2->xfi_Flags |= XADFIF_DIRECTORY;
  210.           }
  211.  
  212.           i = head.Attributes;
  213.           j = 0;
  214.  
  215.           if(!(i & LZXHDR_PROT_READ))
  216.             j |= FIBF_READ;
  217.           if(!(i & LZXHDR_PROT_WRITE))
  218.             j |= FIBF_WRITE;
  219.           if(!(i & LZXHDR_PROT_DELETE))
  220.             j |= FIBF_DELETE;
  221.           if(!(i & LZXHDR_PROT_EXECUTE))
  222.             j |= FIBF_EXECUTE;
  223.           j |= (i & (LZXHDR_PROT_ARCHIVE|LZXHDR_PROT_SCRIPT));
  224.           if(i & LZXHDR_PROT_PURE)
  225.             j |= FIBF_PURE;
  226.           if(i & LZXHDR_PROT_HOLD)
  227.             j |= (1<<7);    /* not defined in <dos/dos.h> */
  228.           fi2->xfi_Protection = j;
  229.  
  230.           { /* Make the date */
  231.             struct xadDate d;
  232.             j = head.Date;
  233.             d.xd_Second = j & 63;
  234.             j >>= 6;
  235.             d.xd_Minute = j & 63;
  236.             j >>= 6;
  237.             d.xd_Hour = j & 31;
  238.             j >>= 5;
  239.             d.xd_Year = 1970 + (j & 63);
  240.             j >>= 6;
  241.             d.xd_Month = 1 + (j & 15);
  242.             j >>= 4;
  243.             d.xd_Day = j;
  244.             d.xd_Micros = 0;
  245.                 xadConvertDates(XAD_DATEXADDATE, &d, XAD_GETDATEXADDATE,
  246.                 &fi2->xfi_Date, TAG_DONE);
  247.           }
  248.           LZXPE(fi2)->CRC = LZXConvEnd32(head.DataCRC);
  249.           LZXPE(fi2)->DataStart = bufpos;
  250.           bufpos += fi2->xfi_Size;
  251.           if(head.Flags & LZXHDR_FLAG_MERGED)
  252.           {
  253.             fi2->xfi_Flags |= XADFIF_GROUPED;
  254.             if(l)
  255.             {
  256.               fi2->xfi_Flags |= XADFIF_ENDOFGROUP;
  257.               fi2->xfi_GroupCrSize = l;
  258.             }
  259.           }
  260.           else
  261.             fi2->xfi_CrunchSize = l;
  262.           
  263.           if(l)
  264.           {
  265.             LZXPE(fi2)->ArchivePos = ai->xai_InPos-l;
  266.             LZXPE(fi2)->PackMode = head.PackMode;
  267.             while(fig)
  268.             {
  269.               fig->xfi_GroupCrSize = l;
  270.               LZXPE(fig)->ArchivePos = ai->xai_InPos-l;
  271.               LZXPE(fig)->PackMode = head.PackMode;
  272.                   fig = fig->xfi_Next;
  273.                 }
  274.               }
  275.  
  276.               if(!fi)
  277.                 ai->xai_FileInfo = fi2;
  278.               else
  279.                 fi->xfi_Next = fi2;
  280.               fi = fi2;
  281.               fi2 = 0;
  282.             } /* skip crunched data */
  283.           } /* get filename and comment */
  284.           if(fi2)
  285.             xadFreeObjectA(fi2,0);
  286.         } /* xadFileInfo Allocation */
  287.       } /* READ header */
  288.     } /* while loop */
  289.   } /* INPUTSEEK 3 bytes */
  290.  
  291.   if(err && ai->xai_FileInfo)
  292.   {
  293.     ai->xai_Flags |= XADAIF_FILECORRUPT;
  294.     ai->xai_LastError = err;
  295.     err = 0;
  296.   }
  297.  
  298.   return err;
  299. }
  300.  
  301. /* ---------------------------------------------------------------------- */
  302.  
  303. static const UBYTE LZXtable_one[32]=
  304. {
  305.  0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13,14,14
  306. };
  307.  
  308. static const ULONG LZXtable_two[32]=
  309. {
  310.  0,1,2,3,4,6,8,12,16,24,32,48,64,96,128,192,256,384,512,768,1024,
  311.  1536,2048,3072,4096,6144,8192,12288,16384,24576,32768,49152
  312. };
  313.  
  314. static const ULONG LZXtable_three[16]=
  315. {
  316.  0,1,3,7,15,31,63,127,255,511,1023,2047,4095,8191,16383,32767
  317. };
  318.  
  319. static const UBYTE LZXtable_four[34]=
  320. {
  321.  0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,
  322.  0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16
  323. };
  324.  
  325. /* ---------------------------------------------------------------------- */
  326.  
  327. /* Build a fast huffman decode table from the symbol bit lengths.         */
  328. /* There is an alternate algorithm which is faster but also more complex. */
  329.  
  330. static LONG LZXmake_decode_table(LONG number_symbols, LONG LZXtable_size,
  331.                       UBYTE *length, unsigned short *table)
  332. {
  333.  register UBYTE bit_num = 0;
  334.  register LONG symbol;
  335.  ULONG leaf; /* could be a register */
  336.  ULONG LZXtable_mask, bit_mask, pos, fill, next_symbol, reverse;
  337.  LONG abort = 0;
  338.  
  339.  pos = 0; /* consistantly used as the current position in the decode table */
  340.  
  341.  bit_mask = LZXtable_mask = 1 << LZXtable_size;
  342.  
  343.  bit_mask >>= 1; /* don't do the first number */
  344.  bit_num++;
  345.  
  346.  while((!abort) && (bit_num <= LZXtable_size))
  347.  {
  348.   for(symbol = 0; symbol < number_symbols; symbol++)
  349.   {
  350.    if(length[symbol] == bit_num)
  351.    {
  352.     reverse = pos; /* reverse the order of the position's bits */
  353.     leaf = 0;
  354.     fill = LZXtable_size;
  355.     do /* reverse the position */
  356.     {
  357.      leaf = (leaf << 1) + (reverse & 1);
  358.      reverse >>= 1;
  359.     } while(--fill);
  360.     if((pos += bit_mask) > LZXtable_mask)
  361.     {
  362.      abort = 1;
  363.      break; /* we will overrun the table! abort! */
  364.     }
  365.     fill = bit_mask;
  366.     next_symbol = 1 << bit_num;
  367.     do
  368.     {
  369.      table[leaf] = symbol;
  370.      leaf += next_symbol;
  371.     } while(--fill);
  372.    }
  373.   }
  374.   bit_mask >>= 1;
  375.   bit_num++;
  376.  }
  377.  
  378.  if((!abort) && (pos != LZXtable_mask))
  379.  {
  380.   for(symbol = pos; symbol < LZXtable_mask; symbol++) /* clear the rest of the table */
  381.   {
  382.    reverse = symbol; /* reverse the order of the position's bits */
  383.    leaf = 0;
  384.    fill = LZXtable_size;
  385.    do /* reverse the position */
  386.    {
  387.     leaf = (leaf << 1) + (reverse & 1);
  388.     reverse >>= 1;
  389.    } while(--fill);
  390.    table[leaf] = 0;
  391.   }
  392.   next_symbol = LZXtable_mask >> 1;
  393.   pos <<= 16;
  394.   LZXtable_mask <<= 16;
  395.   bit_mask = 32768;
  396.  
  397.   while((!abort) && (bit_num <= 16))
  398.   {
  399.    for(symbol = 0; symbol < number_symbols; symbol++)
  400.    {
  401.     if(length[symbol] == bit_num)
  402.     {
  403.      reverse = pos >> 16; /* reverse the order of the position's bits */
  404.      leaf = 0;
  405.      fill = LZXtable_size;
  406.      do /* reverse the position */
  407.      {
  408.       leaf = (leaf << 1) + (reverse & 1);
  409.       reverse >>= 1;
  410.      } while(--fill);
  411.      for(fill = 0; fill < bit_num - LZXtable_size; fill++)
  412.      {
  413.       if(table[leaf] == 0)
  414.       {
  415.        table[(next_symbol << 1)] = 0;
  416.        table[(next_symbol << 1) + 1] = 0;
  417.        table[leaf] = next_symbol++;
  418.       }
  419.       leaf = table[leaf] << 1;
  420.       leaf += (pos >> (15 - fill)) & 1;
  421.      }
  422.      table[leaf] = symbol;
  423.      if((pos += bit_mask) > LZXtable_mask)
  424.      {
  425.       abort = 1;
  426.       break; /* we will overrun the table! abort! */
  427.      }
  428.     }
  429.    }
  430.    bit_mask >>= 1;
  431.    bit_num++;
  432.   }
  433.  }
  434.  if(pos != LZXtable_mask) abort = 1; /* the table is incomplete! */
  435.  
  436.  return(abort);
  437. }
  438.  
  439. /* ---------------------------------------------------------------------- */
  440. /* Read and build the decrunch tables. There better be enough data in the */
  441. /* source buffer or it's stuffed. */
  442.  
  443. static LONG LZX_read_literal_table(struct LZXDecrData *decr)
  444. {
  445.  register ULONG control;
  446.  register LONG shift;
  447.  ULONG temp; /* could be a register */
  448.  ULONG symbol, pos, count, fix, max_symbol;
  449.  UBYTE *source;
  450.  LONG abort = 0;
  451.  
  452.  source = decr->source;
  453.  control = decr->control;
  454.  shift = decr->shift;
  455.  
  456.  if(shift < 0) /* fix the control word if necessary */
  457.  {
  458.   shift += 16;
  459.   control += *source++ << (8 + shift);
  460.   control += *source++ << shift;
  461.  }
  462.  
  463. /* read the decrunch method */
  464.  
  465.  decr->decrunch_method = control & 7;
  466.  control >>= 3;
  467.  if((shift -= 3) < 0)
  468.  {
  469.   shift += 16;
  470.   control += *source++ << (8 + shift);
  471.   control += *source++ << shift;
  472.  }
  473.  
  474. /* Read and build the offset huffman table */
  475.  
  476.  if((!abort) && (decr->decrunch_method == 3))
  477.  {
  478.   for(temp = 0; temp < 8; temp++)
  479.   {
  480.    decr->offset_len[temp] = control & 7;
  481.    control >>= 3;
  482.    if((shift -= 3) < 0)
  483.    {
  484.     shift += 16;
  485.     control += *source++ << (8 + shift);
  486.     control += *source++ << shift;
  487.    }
  488.   }
  489.   abort = LZXmake_decode_table(8, 7, decr->offset_len, decr->offset_table);
  490.  }
  491.  
  492. /* read decrunch length */
  493.  
  494.  if(!abort)
  495.  {
  496.   decr->decrunch_length = (control & 255) << 16;
  497.   control >>= 8;
  498.   if((shift -= 8) < 0)
  499.   {
  500.    shift += 16;
  501.    control += *source++ << (8 + shift);
  502.    control += *source++ << shift;
  503.   }
  504.   decr->decrunch_length += (control & 255) << 8;
  505.   control >>= 8;
  506.   if((shift -= 8) < 0)
  507.   {
  508.    shift += 16;
  509.    control += *source++ << (8 + shift);
  510.    control += *source++ << shift;
  511.   }
  512.   decr->decrunch_length += (control & 255);
  513.   control >>= 8;
  514.   if((shift -= 8) < 0)
  515.   {
  516.    shift += 16;
  517.    control += *source++ << (8 + shift);
  518.    control += *source++ << shift;
  519.   }
  520.  }
  521.  
  522. /* read and build the huffman literal table */
  523.  
  524.  if((!abort) && (decr->decrunch_method != 1))
  525.  {
  526.   pos = 0;
  527.   fix = 1;
  528.   max_symbol = 256;
  529.  
  530.   do
  531.   {
  532.    for(temp = 0; temp < 20; temp++)
  533.    {
  534.     decr->huffman20_len[temp] = control & 15;
  535.     control >>= 4;
  536.     if((shift -= 4) < 0)
  537.     {
  538.      shift += 16;
  539.      control += *source++ << (8 + shift);
  540.      control += *source++ << shift;
  541.     }
  542.    }
  543.    abort = LZXmake_decode_table(20, 6, decr->huffman20_len, decr->huffman20_table);
  544.  
  545.    if(abort) break; /* argh! table is corrupt! */
  546.  
  547.    do
  548.    {
  549.     if((symbol = decr->huffman20_table[control & 63]) >= 20)
  550.     {
  551.      do /* symbol is longer than 6 bits */
  552.      {
  553.       symbol = decr->huffman20_table[((control >> 6) & 1) + (symbol << 1)];
  554.       if(!shift--)
  555.       {
  556.        shift += 16;
  557.        control += *source++ << 24;
  558.        control += *source++ << 16;
  559.       }
  560.       control >>= 1;
  561.      } while(symbol >= 20);
  562.      temp = 6;
  563.     }
  564.     else
  565.     {
  566.      temp = decr->huffman20_len[symbol];
  567.     }
  568.     control >>= temp;
  569.     if((shift -= temp) < 0)
  570.     {
  571.      shift += 16;
  572.      control += *source++ << (8 + shift);
  573.      control += *source++ << shift;
  574.     }
  575.     switch(symbol)
  576.     {
  577.      case 17:
  578.      case 18:
  579.      {
  580.       if(symbol == 17)
  581.       {
  582.        temp = 4;
  583.        count = 3;
  584.       }
  585.       else /* symbol == 18 */
  586.       {
  587.        temp = 6 - fix;
  588.        count = 19;
  589.       }
  590.       count += (control & LZXtable_three[temp]) + fix;
  591.       control >>= temp;
  592.       if((shift -= temp) < 0)
  593.       {
  594.        shift += 16;
  595.        control += *source++ << (8 + shift);
  596.        control += *source++ << shift;
  597.       }
  598.       while((pos < max_symbol) && (count--))
  599.        decr->literal_len[pos++] = 0;
  600.       break;
  601.      }
  602.      case 19:
  603.      {
  604.       count = (control & 1) + 3 + fix;
  605.       if(!shift--)
  606.       {
  607.        shift += 16;
  608.        control += *source++ << 24;
  609.        control += *source++ << 16;
  610.       }
  611.       control >>= 1;
  612.       if((symbol = decr->huffman20_table[control & 63]) >= 20)
  613.       {
  614.        do /* symbol is longer than 6 bits */
  615.        {
  616.         symbol = decr->huffman20_table[((control >> 6) & 1) + (symbol << 1)];
  617.         if(!shift--)
  618.         {
  619.          shift += 16;
  620.          control += *source++ << 24;
  621.          control += *source++ << 16;
  622.         }
  623.         control >>= 1;
  624.        } while(symbol >= 20);
  625.        temp = 6;
  626.       }
  627.       else
  628.       {
  629.        temp = decr->huffman20_len[symbol];
  630.       }
  631.       control >>= temp;
  632.       if((shift -= temp) < 0)
  633.       {
  634.        shift += 16;
  635.        control += *source++ << (8 + shift);
  636.        control += *source++ << shift;
  637.       }
  638.       symbol = LZXtable_four[decr->literal_len[pos] + 17 - symbol];
  639.       while((pos < max_symbol) && (count--))
  640.        decr->literal_len[pos++] = symbol;
  641.       break;
  642.      }
  643.      default:
  644.      {
  645.       symbol = LZXtable_four[decr->literal_len[pos] + 17 - symbol];
  646.       decr->literal_len[pos++] = symbol;
  647.       break;
  648.      }
  649.     }
  650.    } while(pos < max_symbol);
  651.    fix--;
  652.    max_symbol += 512;
  653.   } while(max_symbol == 768);
  654.  
  655.   if(!abort)
  656.    abort = LZXmake_decode_table(768, 12, decr->literal_len, decr->literal_table);
  657.  }
  658.  
  659.  decr->control = control;
  660.  decr->shift = shift;
  661.  decr->source = source;
  662.  return(abort);
  663. }
  664.  
  665. /* ---------------------------------------------------------------------- */
  666.  
  667. /* Fill up the decrunch buffer. Needs lots of overrun for both destination */
  668. /* and source buffers. Most of the time is spent in this routine so it's  */
  669. /* pretty damn optimized. */
  670. static void LZXdecrunch(struct LZXDecrData *decr)
  671. {
  672.  register ULONG control;
  673.  register LONG shift;
  674.  ULONG temp; /* could be a register */
  675.  ULONG symbol, count;
  676.  UBYTE *string, *source, *destination;
  677.  
  678.  control = decr->control;
  679.  shift = decr->shift;
  680.  source = decr->source;
  681.  destination = decr->destination;
  682.  
  683.  do
  684.  {
  685.   if((symbol = decr->literal_table[control & 4095]) >= 768)
  686.   {
  687.    control >>= 12;
  688.    if((shift -= 12) < 0)
  689.    {
  690.     shift += 16;
  691.     control += *source++ << (8 + shift);
  692.     control += *source++ << shift;
  693.    }
  694.    do /* literal is longer than 12 bits */
  695.    {
  696.     symbol = decr->literal_table[(control & 1) + (symbol << 1)];
  697.     if(!shift--)
  698.     {
  699.      shift += 16;
  700.      control += *source++ << 24;
  701.      control += *source++ << 16;
  702.     }
  703.     control >>= 1;
  704.    } while(symbol >= 768);
  705.   }
  706.   else
  707.   {
  708.    temp = decr->literal_len[symbol];
  709.    control >>= temp;
  710.    if((shift -= temp) < 0)
  711.    {
  712.     shift += 16;
  713.     control += *source++ << (8 + shift);
  714.     control += *source++ << shift;
  715.    }
  716.   }
  717.   if(symbol < 256)
  718.   {
  719.    *destination++ = symbol;
  720.   }
  721.   else
  722.   {
  723.    symbol -= 256;
  724.    count = LZXtable_two[temp = symbol & 31];
  725.    temp = LZXtable_one[temp];
  726.    if((temp >= 3) && (decr->decrunch_method == 3))
  727.    {
  728.     temp -= 3;
  729.     count += ((control & LZXtable_three[temp]) << 3);
  730.     control >>= temp;
  731.     if((shift -= temp) < 0)
  732.     {
  733.      shift += 16;
  734.      control += *source++ << (8 + shift);
  735.      control += *source++ << shift;
  736.     }
  737.     count += (temp = decr->offset_table[control & 127]);
  738.     temp = decr->offset_len[temp];
  739.    }
  740.    else
  741.    {
  742.     count += control & LZXtable_three[temp];
  743.     if(!count) count = decr->last_offset;
  744.    }
  745.    control >>= temp;
  746.    if((shift -= temp) < 0)
  747.    {
  748.     shift += 16;
  749.     control += *source++ << (8 + shift);
  750.     control += *source++ << shift;
  751.    }
  752.    decr->last_offset = count;
  753.  
  754.    count = LZXtable_two[temp = (symbol >> 5) & 15] + 3;
  755.    temp = LZXtable_one[temp];
  756.    count += (control & LZXtable_three[temp]);
  757.    control >>= temp;
  758.    if((shift -= temp) < 0)
  759.    {
  760.     shift += 16;
  761.     control += *source++ << (8 + shift);
  762.     control += *source++ << shift;
  763.    }
  764.    string = (decr->decrunch_buffer + decr->last_offset < destination) ?
  765.             destination - decr->last_offset : destination + 65536 - decr->last_offset;
  766.    do
  767.    {
  768.     *destination++ = *string++;
  769.    } while(--count);
  770.   }
  771.  } while((destination < decr->destination_end) && (source < decr->source_end));
  772.  
  773.  decr->control = control;
  774.  decr->shift = shift;
  775.  decr->source = source;
  776.  decr->destination = destination;
  777. }
  778.  
  779. /* ---------------------------------------------------------------------- */
  780.  
  781. static LONG LZXextract(struct xadArchiveInfo *ai, struct xadMasterBase *xadMasterBase,
  782. ULONG unpack_size, ULONG rescrc)
  783. {
  784.   UBYTE *temp;
  785.   ULONG count, crc = ~0;
  786.   LONG err;
  787.   struct LZXDecrData *decr;
  788.  
  789.   decr = (struct LZXDecrData *) ai->xai_PrivateClient;
  790.  
  791.   while(unpack_size > 0)
  792.   {
  793.     if(decr->pos == decr->destination) /* time to fill the buffer? */
  794.     {
  795.       /* check if we have enough data and read some if not */
  796.       if(decr->source >= decr->source_end) /* have we exhausted the current read buffer? */
  797.       {
  798.         temp = decr->read_buffer;
  799.         if(count = temp - decr->source + 16384)
  800.         {
  801.           do /* copy the remaining overrun to the start of the buffer */
  802.           {
  803.             *temp++ = *(decr->source++);
  804.           } while(--count);
  805.         }
  806.         decr->source = decr->read_buffer;
  807.         count = decr->source - temp + 16384;
  808.  
  809.         if(decr->pack_size < count)
  810.           count = decr->pack_size; /* make sure we don't read too much */
  811.  
  812.         if((err = xadHookAccess(XADAC_READ, count, temp, ai)))
  813.           return err;
  814.         decr->pack_size -= count;
  815.  
  816.         temp += count;
  817.         if(decr->source >= temp)
  818.           return XADERR_DECRUNCH; /* argh! no more data! */
  819.       } /* if(decr->source >= decr->source_end) */
  820.  
  821.     /* check if we need to read the tables */
  822.     if(decr->decrunch_length <= 0)
  823.     {
  824.       if(LZX_read_literal_table(decr))
  825.         return XADERR_DECRUNCH; /* argh! can't make huffman tables! */
  826.     }
  827.  
  828.     /* unpack some data */
  829.     if(decr->destination >= decr->decrunch_buffer + 258 + 65536)
  830.     {
  831.       if(count = decr->destination - decr->decrunch_buffer - 65536)
  832.       {
  833.         temp = (decr->destination = decr->decrunch_buffer) + 65536;
  834.         do /* copy the overrun to the start of the buffer */
  835.         {
  836.           *(decr->destination++) = *temp++;
  837.         } while(--count);
  838.       }
  839.       decr->pos = decr->destination;
  840.     }
  841.     decr->destination_end = decr->destination + decr->decrunch_length;
  842.     if(decr->destination_end > decr->decrunch_buffer + 258 + 65536)
  843.       decr->destination_end = decr->decrunch_buffer + 258 + 65536;
  844.     temp = decr->destination;
  845.  
  846.     LZXdecrunch(decr);
  847.  
  848.     decr->decrunch_length -= (decr->destination - temp);
  849.    }
  850.  
  851. /* calculate amount of data we can use before we need to fill the buffer again */
  852.    count = decr->destination - decr->pos;
  853.    if(count > unpack_size)
  854.      count = unpack_size; /* take only what we need */
  855.  
  856.    if(rescrc) /* when no CRC given, then skip writing */
  857.    {
  858.      crc = xadCalcCRC32(XADCRC32_ID1, crc, count, decr->pos);
  859.      if((err = xadHookAccess(XADAC_WRITE, count, decr->pos, ai)))
  860.        return err;
  861.    }
  862.    unpack_size -= count;
  863.    decr->pos += count;
  864.    decr->DataPos += count;
  865.  }
  866.  
  867.  if(rescrc && ~crc != rescrc)
  868.    return XADERR_CHECKSUM;
  869.  
  870.  return 0;
  871. }
  872.  
  873. /* ---------------------------------------------------------------------- */
  874.  
  875. ASM(LONG) LZX_UnArchive(REG(a0, struct xadArchiveInfo *ai),
  876. REG(a6, struct xadMasterBase *xadMasterBase))
  877. {
  878.   struct xadFileInfo *fi;
  879.   LONG ret = 0, crc;
  880.  
  881.   fi = ai->xai_CurFile;
  882.   if(!ai->xai_PrivateClient || LZXDD(ai)->ArchivePos != LZXPE(fi)->ArchivePos
  883.   || LZXDD(ai)->DataPos > LZXPE(fi)->DataStart)
  884.   {
  885.     if(ai->xai_PrivateClient) /* free the unneeded client */
  886.     {
  887.       xadFreeObjectA(ai->xai_PrivateClient, 0);
  888.       ai->xai_PrivateClient = 0;
  889.     }
  890.     if((crc = LZXPE(fi)->ArchivePos - ai->xai_InPos))
  891.     {
  892.       if((ret = xadHookAccess(XADAC_INPUTSEEK, crc, 0, ai)))
  893.         return ret;
  894.     }
  895.   }
  896.  
  897.   switch(LZXPE(fi)->PackMode)
  898.   {
  899.   case LZXHDR_PACK_STORE:
  900.     {
  901.       ULONG bufsize, data;
  902.       APTR buf;
  903.     
  904.       crc = ~0;
  905.       data = fi->xfi_Size;
  906.         
  907.       if((bufsize = data) > 51200)
  908.         bufsize = 51200;
  909.       if((buf = xadAllocVec(bufsize, MEMF_PUBLIC)))
  910.       {
  911.         while(data && !ret)
  912.         {
  913.           if(data < bufsize)
  914.             bufsize = data;
  915.       if(!(ret = xadHookAccess(XADAC_READ, bufsize, buf, ai)))
  916.       {
  917.         crc = xadCalcCRC32(XADCRC32_ID1, crc, bufsize, buf);
  918.             ret = xadHookAccess(XADAC_WRITE, bufsize, buf, ai);
  919.       }
  920.       data -= bufsize;
  921.     }
  922.         xadFreeObjectA(buf,0);
  923.       }
  924.       else
  925.         ret = XADERR_NOMEMORY;
  926.       if(!ret && ~crc != LZXPE(fi)->CRC)
  927.         ret = XADERR_CHECKSUM;
  928.     }
  929.     break;
  930.   case LZXHDR_PACK_NORMAL:
  931.     {
  932.       struct LZXDecrData *decr = 0;
  933.  
  934.       if(!ai->xai_PrivateClient && !(decr = (struct LZXDecrData *)
  935.       xadAllocVec(sizeof(struct LZXDecrData), MEMF_PUBLIC|MEMF_CLEAR)))
  936.         ret = XADERR_NOMEMORY;
  937.       else
  938.       {
  939.         if(decr)
  940.         {
  941.           decr->ArchivePos = LZXPE(fi)->ArchivePos;
  942.           decr->DataPos = 0;
  943.           decr->shift = -16;
  944.           decr->last_offset = 1;
  945.           decr->source_end = (decr->source = decr->read_buffer + 16384) - 1024;
  946.           decr->pos = decr->destination_end = decr->destination = decr->decrunch_buffer + 258 + 65536;
  947.           decr->pack_size = fi->xfi_Flags & XADFIF_GROUPED ?
  948.           fi->xfi_GroupCrSize : fi->xfi_CrunchSize;
  949.           ai->xai_PrivateClient = decr;
  950.         }
  951.  
  952.     if((crc = LZXPE(fi)->DataStart - LZXDD(ai)->DataPos))
  953.       ret = LZXextract(ai, xadMasterBase, crc, 0);
  954.     
  955.     if(!ret)
  956.       ret = LZXextract(ai, xadMasterBase, fi->xfi_Size, LZXPE(fi)->CRC);
  957.  
  958.         /* free no longer needed temporary buffer and stuff structure */
  959.         if(ret || !(fi->xfi_Flags & XADFIF_GROUPED) || (fi->xfi_Flags & XADFIF_ENDOFGROUP))
  960.         {
  961.           xadFreeObjectA(ai->xai_PrivateClient, 0);
  962.           ai->xai_PrivateClient = 0;
  963.         }
  964.       }
  965.     }
  966.     break;
  967.   default: ret = XADERR_DECRUNCH; break;
  968.   }
  969.  
  970.   return ret;
  971. }
  972.  
  973. ASM(void) LZX_Free(REG(a0, struct xadArchiveInfo *ai),
  974. REG(a6, struct xadMasterBase *xadMasterBase))
  975. {
  976.   if(ai->xai_PrivateClient) /* decrunch buffer */
  977.   {
  978.     xadFreeObjectA(ai->xai_PrivateClient, 0);
  979.     ai->xai_PrivateClient = 0;
  980.   }
  981. }
  982.  
  983. struct xadClient LZX_Client = {
  984. NEXTCLIENT, XADCLIENT_VERSION, 2, LZX_VERSION, LZX_REVISION,
  985. 10, XADCF_FILEARCHIVER|XADCF_FREEFILEINFO, XADCID_LZX, "LZX",
  986. (BOOL (*)()) LZX_RecogData, (LONG (*)()) LZX_GetInfo,
  987. (LONG (*)()) LZX_UnArchive, (void (*)()) LZX_Free};
  988.  
  989. #endif /* XADASTER_LZX_C */
  990.