/* Program: unlznp.c Author: Nick Pelling Function: Decompresses an LZNP-compressed file Note: Copyright (c) 1993-1994 Nick Pelling. All rights reserved. */ /* Notes: The basic procedure is: (a) Read a control byte, and examine each bit in turn, LSB...MSB (b) if bit is clear, copy a byte from input stream (c) ...else read another byte in. if >= 0x60, this means "copy a pair from nearby" (d) ...else split it up into a length, and high 4 bits of offset (e) read the low order 8 bits, and merge to form (-ve) offset (f) if (offset == 0), then exit: this terminates decompression (g) if length is maximum length, read superlength from next byte (h) copy length bytes from (-ve) offset. Note: this may overlap! (i) If no more bits in control byte, read another control byte (j) Loop. ...and that's it. */ #include "lznp.h" #define SMALLEST_LEN 2 /* smallest len usable at all */ #define MIN_LEN 3 /* smallest short length encodable */ #define MAX_LEN (MIN_LEN + 6-2) /* largest short length encodable */ #define MIN_SUPERLEN (MIN_LEN + 6-1) /* shortest long length encodable */ #define MAX_SUPERLEN (MIN_SUPERLEN + 254) /* largest long length encodable */ #define SUPERLEN_CODE (MIN_SUPERLEN - MIN_LEN) /* means "read superlength" */ typedef unsigned char UBYTE; /* just for convenience */ int LZNP_Decode(UBYTE *in, UBYTE *out) { int i, j; unsigned int flags; /* now works with 16-bit ints */ UBYTE * OriginalOut=out; for (flags=0;;) { if (((flags >>= 1) & 0xff00) == 0) { flags = (*in++) | 0xff00; /* uses higher byte cleverly */ } /* (to count eight) */ if (!(flags & 1)) { *out++ = *in++; } else { i = *in++; if (i >= 0x60) { i = 0x100 - i; /* i = copy offset */ j = SMALLEST_LEN; /* j = copy length */ } else { j = i >> 4; i = (i & 0x0F) << 8; i |= *in++; if (i == 0) /* offset of zero terminates LZNP data */ break; if (j != SUPERLEN_CODE) j += MIN_LEN; else j = MIN_SUPERLEN + (*in++); } for (i=-i,j++; --j; out++) { out[0] = out[i]; } } } /* Return size */ return(out-OriginalOut); }