mirror of
https://github.com/dmolony/DiskBrowser.git
synced 2024-09-29 22:54:45 +00:00
161 lines
3.5 KiB
Java
161 lines
3.5 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 ();
|
||
|
|
||
|
bitOffset = 0;
|
||
|
|
||
|
int a = 0;
|
||
|
int y = 0;
|
||
|
|
||
|
while (true)
|
||
|
{
|
||
|
if (ptr > max)
|
||
|
{
|
||
|
System.out.println ("LZW3 overrun");
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
readCode (); // sets iCode
|
||
|
|
||
|
if (iCode == EOF_CODE)
|
||
|
break;
|
||
|
|
||
|
if (iCode == CLEAR_CODE)
|
||
|
{
|
||
|
initTable ();
|
||
|
readCode (); // sets iCode
|
||
|
|
||
|
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];
|
||
|
}
|
||
|
|
||
|
// a &= 0xFF; // should already be in 8 bits
|
||
|
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 void readCode ()
|
||
|
// ---------------------------------------------------------------------------------//
|
||
|
{
|
||
|
int bitIdx = bitOffset & 0x07;
|
||
|
int byteIdx = bitOffset >>> 3; // no sign extension
|
||
|
|
||
|
iCode = srcBuf[byteIdx] & 0xFF | (srcBuf[byteIdx + 1] & 0xFF) << 8
|
||
|
| (srcBuf[byteIdx + 2] & 0xFF) << 16;
|
||
|
|
||
|
iCode >>>= bitIdx;
|
||
|
iCode &= nBitMask;
|
||
|
|
||
|
bitOffset += nBitMod1;
|
||
|
}
|
||
|
|
||
|
// ---------------------------------------------------------------------------------//
|
||
|
private void addCode ()
|
||
|
// ---------------------------------------------------------------------------------//
|
||
|
{
|
||
|
hashChar[freeCode] = k;
|
||
|
hashNext[freeCode] = oldCode;
|
||
|
freeCode++;
|
||
|
}
|
||
|
}
|