home *** CD-ROM | disk | FTP | other *** search
/ Collection of Hack-Phreak Scene Programs / cleanhpvac.zip / cleanhpvac / HPACK78S.ZIP / lza / unpack.c < prev   
C/C++ Source or Header  |  1992-10-04  |  6KB  |  206 lines

  1. /****************************************************************************
  2. *                                                                            *
  3. *                            HPACK Multi-System Archiver                        *
  4. *                            ===========================                        *
  5. *                                                                            *
  6. *                          HPACK Arithmetic Decode Routines                    *
  7. *                            UNPACK.C  Updated 03/06/91                        *
  8. *                                                                            *
  9. * This program is protected by copyright and as such any use or copying of    *
  10. *  this code for your own purposes directly or indirectly is highly uncool    *
  11. *                      and if you do so there will be....trubble.                *
  12. *                 And remember: We know where your kids go to school.            *
  13. *                                                                            *
  14. *        Copyright 1990, 1991  Peter C.Gutmann.  All rights reserved            *
  15. *                                                                            *
  16. ****************************************************************************/
  17.  
  18. #ifdef __MAC__
  19.   #include "defs.h"
  20.   #include "crc16.h"
  21.   #include "fastio.h"
  22.   #include "model.h"
  23. #else
  24.   #include "defs.h"
  25.   #include "crc/crc16.h"
  26.   #include "io/fastio.h"
  27.   #include "lza/model.h"
  28. #endif /* __MAC__ */
  29.  
  30. /* The following are defined in LZA.C */
  31.  
  32. extern LONG dataLen;    /* The data byte count */
  33.  
  34. /****************************************************************************
  35. *                                                                            *
  36. *                        Arithmetic Decoding Routine                            *
  37. *                                                                            *
  38. ****************************************************************************/
  39.  
  40. /* Current state of the decoding */
  41.  
  42. static WORD value;        /* Currently seen code value */
  43. static WORD low, high;    /* Ends of the current code region */
  44.  
  45. /* The bit buffer */
  46.  
  47. BYTE inBuffer;            /* Bit buffer for input */
  48. int inBitsToGo;            /* Number of bits available in buffer */
  49.  
  50. /* Start decoding a stream of symbols */
  51.  
  52. void startDecode( void )
  53.     {
  54.     /* Initialize the bit input routines.  Since this is dual-use code
  55.        we can only read in 8 bits of a possible 16.  Note that the read of
  56.        the 16-bit value must be spread over two lines since both sides of
  57.        a single-line '|' have side effects */
  58.     value = ( ( WORD ) fgetByte() ) << 8;
  59.     value |= fgetByte();
  60.     inBuffer = fgetByte();
  61.     inBitsToGo = 8;
  62.     dataLen -= 3;                /* We've read in 3 bytes so far */
  63.  
  64.     low = 0;                    /* The full code range */
  65.     high = 0xFFFF;
  66.     }
  67.  
  68. /* Loop to get rid of bits */
  69.  
  70. static void discardBits( void )
  71.     {
  72.     /* Loop to get rid of bits */
  73.     while( TRUE )
  74.         {
  75.         /* If the MS digits match, shift out the bits */
  76.         if( !( ( high ^ low ) & 0x8000 ) )
  77.             ;
  78.         else
  79.             /* If there is a danger of underflow, shift out the 2nd MS digit */
  80.             if( ( low & ~high ) & 0x4000 )
  81.                 {
  82.                 value ^= 0x4000;
  83.                 low &= 0x3FFF;
  84.                 high |= 0x4000;
  85.                 }
  86.             else
  87.                 /* We can't shift anything out, so we return */
  88.                 break;
  89.  
  90.         /* Scale up code range */
  91.         low <<= 1;
  92.         high <<= 1;
  93.         high++;
  94.  
  95.         /* Move in next input bit */
  96.         if( !inBitsToGo )
  97.             {
  98.             if( !dataLen )
  99.                 /* Out of input data, extend last bit in buffer into all of
  100.                    inBuffer */
  101.                 inBuffer = ( value & 0x01 ) ? 0xFF : 0;
  102.             else
  103.                 {
  104.                 inBuffer = fgetByte();
  105.                 dataLen--;
  106.                 }
  107.             inBitsToGo = 8;
  108.             }
  109.         value = ( value << 1 ) | ( ( inBuffer & 0x80 ) ? 1 : 0 );
  110.         inBuffer <<= 1;
  111.         inBitsToGo--;
  112.         }
  113.     }
  114.  
  115. /* Decode the next symbol (order 1) */
  116.  
  117. int decodeOrder1( void )
  118.     {
  119.     int cum;                /* Cum.freq.calculated */
  120.     int symbol;                /* Symbol decoded */
  121.     long h427;
  122.     WORD cumFreq0, h318, h172, h628;
  123.     int h198, h027;
  124.  
  125.     h387 = h246; if( h217[ h387 ] != -1 )
  126.         {
  127.         h198 = h217[ h387 ]; h628 = h528[ h198 ].h506;
  128.         h427 = ( long ) ( high - low ) + 1L;
  129.         h027 = ( ( ( long ) ( value - low ) + 1L ) * h628 - 1 ) / h427;
  130.         h198 = h528[ h198 ].h261; while( h528[ h198 ].h506 > h027 )
  131.         h198 = h528[ h198 ].h261; h318 = h528[ h528[ h198 ].h704 ].h506;
  132.         h172 = h528[ h198 ].h506; high = low + ( h427 * h318 ) / h628 - 1;
  133.         low += ( h427 * h172 ) / h628;
  134.  
  135.         /* Get rid of input bits */
  136.         discardBits();
  137.  
  138.         if( h528[ h528[ h198 ].h704 ].h462 ) {
  139.         h246 = h027 = h648[ h198 ].h506; h508( h198 );
  140.         h797( h198, PACK_MASK ); return( h027 ); } else h508( h198 );
  141.         }
  142.  
  143.     /* Get total cumFreq0 for order 0 model */
  144.     cumFreq0 = h313[ 0 ];
  145.  
  146.     /* Check for special case of range = 0x10000L */
  147.     if( !low && high == 0xFFFF )
  148.         {
  149.         /* Find cumulative frequency for value */
  150.         cum = ( ( ( long ) ( value - low ) + 1 ) * cumFreq0 - 1 ) >> 16;
  151.  
  152.         /* Then find the symbol */
  153.         for( symbol = 1; h313[ symbol ] > cum; symbol++ );
  154.  
  155.         /* Narrow the code region to that allotted to this symbol */
  156.         high = low + ( 0x10000L * h313[ symbol - 1 ] ) / cumFreq0 - 1;
  157.         low += ( 0x10000L * h313[ symbol ] ) / cumFreq0;
  158.         }
  159.     else
  160.         {
  161.         /* Find cumulative frequency for value */
  162.         WORD range = ( high - low ) + 1;
  163.  
  164.         cum = ( ( ( long ) ( value - low ) + 1 ) * cumFreq0 - 1 ) / range;
  165.  
  166.         /* Then find the symbol */
  167.         for( symbol = 1; h313[ symbol ] > cum; symbol++ );
  168.  
  169.         /* Narrow the code region to that allotted to this symbol */
  170.         high = low + ( ( long ) range * h313[ symbol - 1 ] ) / cumFreq0 - 1;
  171.         low += ( ( long ) range * h313[ symbol ] ) / cumFreq0;
  172.         }
  173.  
  174.     /* Get rid of the extra bits */
  175.     discardBits();
  176.  
  177.     /* Translate symbol to actual value */
  178.     h246 = h027 = h284[ symbol ]; h762( ( ( h387 << 4 ) & 0x0FF0 ) ^ h246 );
  179.     return( h027 );
  180.     }
  181.  
  182. /* Decode the next symbol (order 0) */
  183.  
  184. int decodeOrder0( const int *cumFreq )
  185.     {
  186.     long range;                /* Size of current code region */
  187.     int cum;                /* Cum.freq.calculated */
  188.     int symbol;                /* Symbol decoded */
  189.  
  190.     /* Find cum.freq. for value */
  191.     range = ( long ) ( high - low ) + 1;
  192.     cum = ( ( ( long ) ( value - low ) + 1 ) * cumFreq[ 0 ] - 1 ) / range;
  193.  
  194.     /* Then find the symbol */
  195.     for( symbol = 1; cumFreq[ symbol ] > cum; symbol++ );
  196.  
  197.     /* Narrow the code region to that allotted to this symbol */
  198.     high = low + ( range * cumFreq[ symbol - 1 ] ) / cumFreq[ 0 ] - 1;
  199.     low = low + ( range * cumFreq[ symbol ] ) / cumFreq[ 0 ];
  200.  
  201.     /* Get rid if input bits */
  202.     discardBits();
  203.  
  204.     return( symbol );
  205.     }
  206.