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