Logo Search packages:      
Sourcecode: xdms version File versions  Download package

u_heavy.c

/*
 *     xDMS  v1.3  -  Portable DMS archive unpacker  -  Public Domain
 *     Written by     Andre Rodrigues de la Rocha  <adlroc@usa.net>
 *
 *     Lempel-Ziv-Huffman decompression functions used in Heavy 1 & 2 
 *     compression modes. Based on LZH decompression functions from
 *     UNIX LHA made by Masaru Oki
 *
 */


#include "cdata.h"
#include "u_heavy.h"
#include "getbits.h"
#include "maketbl.h"


#define NC 510
#define NPT 20
#define N1 510
#define OFFSET 253

USHORT left[2 * NC - 1], right[2 * NC - 1 + 9];
static UCHAR c_len[NC], pt_len[NPT];
static USHORT c_table[4096], pt_table[256];
static USHORT lastlen, np;
USHORT heavy_text_loc;


static USHORT read_tree_c(void);
static USHORT read_tree_p(void);
INLINE USHORT decode_c(void);
INLINE USHORT decode_p(void);



USHORT Unpack_HEAVY(UCHAR *in, UCHAR *out, UCHAR flags, USHORT origsize){
      USHORT j, i, c, bitmask;
      UCHAR *outend;

      /*  Heavy 1 uses a 4Kb dictionary,  Heavy 2 uses 8Kb  */

      if (flags & 8) {
            np = 15;
            bitmask = 0x1fff;
      } else {
            np = 14;
            bitmask = 0x0fff;
      }

      initbitbuf(in);

      if (flags & 2) {
            if (read_tree_c()) return 1;
            if (read_tree_p()) return 2;
      }

      outend = out+origsize;

      while (out<outend) {
            c = decode_c();
            if (c < 256) {
                  *out++ = text[heavy_text_loc++ & bitmask] = (UCHAR)c;
            } else {
                  j = (USHORT) (c - OFFSET);
                  i = (USHORT) (heavy_text_loc - decode_p() - 1);
                  while(j--) *out++ = text[heavy_text_loc++ & bitmask] = text[i++ & bitmask];
            }
      }

      return 0;
}



INLINE USHORT decode_c(void){
      USHORT i, j, m;

      j = c_table[GETBITS(12)];
      if (j < N1) {
            DROPBITS(c_len[j]);
      } else {
            DROPBITS(12);
            i = GETBITS(16);
            m = 0x8000;
            do {
                  if (i & m) j = right[j];
                  else              j = left [j];
                  m >>= 1;
            } while (j >= N1);
            DROPBITS(c_len[j] - 12);
      }
      return j;
}



INLINE USHORT decode_p(void){
      USHORT i, j, m;

      j = pt_table[GETBITS(8)];
      if (j < np) {
            DROPBITS(pt_len[j]);
      } else {
            DROPBITS(8);
            i = GETBITS(16);
            m = 0x8000;
            do {
                  if (i & m) j = right[j];
                  else             j = left [j];
                  m >>= 1;
            } while (j >= np);
            DROPBITS(pt_len[j] - 8);
      }

      if (j != np-1) {
            if (j > 0) {
                  j = (USHORT)(GETBITS(i=(USHORT)(j-1)) | (1U << (j-1)));
                  DROPBITS(i);
            }
            lastlen=j;
      }

      return lastlen;

}



static USHORT read_tree_c(void){
      USHORT i,n;

      n = GETBITS(9);
      DROPBITS(9);
      if (n>0){
            for (i=0; i<n; i++) {
                  c_len[i] = (UCHAR)GETBITS(5);
                  DROPBITS(5);
            }
            for (i=n; i<510; i++) c_len[i] = 0;
            if (make_table(510,c_len,12,c_table)) return 1;
      } else {
            n = GETBITS(9);
            DROPBITS(9);
            for (i=0; i<510; i++) c_len[i] = 0;
            for (i=0; i<4096; i++) c_table[i] = n;
      }
      return 0;
}



static USHORT read_tree_p(void){
      USHORT i,n;

      n = GETBITS(5);
      DROPBITS(5);
      if (n>0){
            for (i=0; i<n; i++) {
                  pt_len[i] = (UCHAR)GETBITS(4);
                  DROPBITS(4);
            }
            for (i=n; i<np; i++) pt_len[i] = 0;
            if (make_table(np,pt_len,8,pt_table)) return 1;
      } else {
            n = GETBITS(5);
            DROPBITS(5);
            for (i=0; i<np; i++) pt_len[i] = 0;
            for (i=0; i<256; i++) pt_table[i] = n;
      }
      return 0;
}



Generated by  Doxygen 1.6.0   Back to index