dmolony-DiskBrowser/src/com/bytezone/diskbrowser/nufx/LZW3.java

162 lines
3.4 KiB
Java

package com.bytezone.diskbrowser.nufx;
// DreamGraphix LZW
// code ported from CiderPress' DreamGraphix::UnpackDG()
// -----------------------------------------------------------------------------------//
public class LZW3
// -----------------------------------------------------------------------------------//
{
static final int[] bitMasks = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x1FF, 0x3FF, 0x7FF, 0xFFF };
static final int CLEAR_CODE = 256;
static final int EOF_CODE = 257;
static final int FIRST_FREE_CODE = 258;
int nBitMod1;
int nBitMask;
int finChar;
int oldCode;
int inCode;
int freeCode;
int maxCode;
int k;
int bitOffset;
int[] hashNext = new int[4096];
int[] hashChar = new int[4096];
int ptr = 0;
int iCode;
int[] stack = new int[32768];
int stackIdx = 0;
byte[] srcBuf;
byte[] dstBuf;
// ---------------------------------------------------------------------------------//
public int unpack (byte[] src, byte[] dst, int max)
// ---------------------------------------------------------------------------------//
{
assert max <= dst.length;
srcBuf = src;
dstBuf = dst;
initTable ();
int a;
int y;
bitOffset = 0;
while (true)
{
if (ptr > max)
{
System.out.println ("LZW3 overrun");
return -1;
}
iCode = readCode ();
if (iCode == EOF_CODE)
break;
if (iCode == CLEAR_CODE)
{
initTable ();
iCode = readCode ();
oldCode = iCode;
k = iCode;
finChar = iCode;
dstBuf[ptr++] = (byte) iCode;
continue;
}
a = inCode = iCode;
if (iCode >= freeCode)
{
stack[stackIdx++] = finChar;
a = oldCode;
}
while (a >= 256)
{
y = a;
a = hashChar[y];
stack[stackIdx++] = a;
a = hashNext[y];
}
finChar = a;
k = a;
y = 0;
dstBuf[ptr + y++] = (byte) a;
while (stackIdx > 0)
{
a = stack[--stackIdx];
dstBuf[ptr + y++] = (byte) a;
}
ptr += y;
addCode ();
oldCode = inCode;
if (freeCode < maxCode)
continue;
if (nBitMod1 == 12)
continue;
nBitMod1++;
nBitMask = bitMasks[nBitMod1];
maxCode <<= 1;
}
return ptr;
}
// ---------------------------------------------------------------------------------//
private void initTable ()
// ---------------------------------------------------------------------------------//
{
nBitMod1 = 9;
nBitMask = bitMasks[nBitMod1];
maxCode = 1 << nBitMod1;
freeCode = FIRST_FREE_CODE;
}
// ---------------------------------------------------------------------------------//
private int readCode ()
// ---------------------------------------------------------------------------------//
{
int bitIdx = bitOffset & 0x07;
int byteIdx = bitOffset >>> 3; // no sign extension
int iCode = srcBuf[byteIdx] & 0xFF | (srcBuf[byteIdx + 1] & 0xFF) << 8
| (srcBuf[byteIdx + 2] & 0xFF) << 16;
iCode >>>= bitIdx;
iCode &= nBitMask;
bitOffset += nBitMod1;
return iCode;
}
// ---------------------------------------------------------------------------------//
private void addCode ()
// ---------------------------------------------------------------------------------//
{
hashChar[freeCode] = k;
hashNext[freeCode] = oldCode;
freeCode++;
}
}