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

170 lines
4.9 KiB
Java
Raw Permalink Normal View History

2021-05-21 02:57:03 +00:00
package com.bytezone.diskbrowser.nufx;
2015-06-01 09:35:51 +00:00
import java.util.ArrayList;
import java.util.List;
2021-05-01 23:38:24 +00:00
import java.util.Objects;
2015-06-01 09:35:51 +00:00
2021-05-21 02:57:03 +00:00
import com.bytezone.diskbrowser.utilities.Utility;
2020-02-07 23:26:38 +00:00
// -----------------------------------------------------------------------------------//
2021-05-02 04:45:26 +00:00
abstract class LZW
2020-02-07 23:26:38 +00:00
// -----------------------------------------------------------------------------------//
2015-06-01 09:35:51 +00:00
{
2021-05-01 23:38:24 +00:00
static final String[] st = new String[0x1000];
static final int TRACK_LENGTH = 0x1000;
final List<byte[]> chunks = new ArrayList<> ();
int volume;
byte runLengthChar;
int crc;
int crcBase;
2021-08-20 10:04:53 +00:00
int v3eof; // LZW/2 calculates the crc without padding
2015-06-01 09:35:51 +00:00
2021-05-01 23:38:24 +00:00
private int byteBuffer; // one character buffer
2015-06-01 09:35:51 +00:00
private int bitsLeft; // unused bits left in buffer
private int ptr;
private int startPtr;
2021-05-02 04:45:26 +00:00
byte[] buffer;
boolean unpacked;
2015-06-01 09:35:51 +00:00
2020-02-07 23:26:38 +00:00
// ---------------------------------------------------------------------------------//
2015-06-01 09:35:51 +00:00
static
2020-02-07 23:26:38 +00:00
// ---------------------------------------------------------------------------------//
2015-06-01 09:35:51 +00:00
{
for (int i = 0; i < 256; i++)
st[i] = "" + (char) i;
}
2020-02-07 23:26:38 +00:00
// ---------------------------------------------------------------------------------//
2021-05-01 23:38:24 +00:00
LZW (byte[] buffer)
2020-02-07 23:26:38 +00:00
// ---------------------------------------------------------------------------------//
2015-06-01 09:35:51 +00:00
{
2021-05-02 04:45:26 +00:00
this.buffer = Objects.requireNonNull (buffer);
2015-06-01 09:35:51 +00:00
}
2021-05-02 04:45:26 +00:00
// ---------------------------------------------------------------------------------//
abstract void unpack ();
// ---------------------------------------------------------------------------------//
2020-02-07 23:26:38 +00:00
// ---------------------------------------------------------------------------------//
2021-05-01 23:38:24 +00:00
void setBuffer (int ptr)
2020-02-07 23:26:38 +00:00
// ---------------------------------------------------------------------------------//
2015-06-01 09:35:51 +00:00
{
2021-05-01 23:38:24 +00:00
startPtr = this.ptr = ptr;
bitsLeft = 0;
2015-06-01 09:35:51 +00:00
}
2020-02-07 23:26:38 +00:00
// ---------------------------------------------------------------------------------//
2021-05-01 23:38:24 +00:00
int bytesRead ()
2020-02-07 23:26:38 +00:00
// ---------------------------------------------------------------------------------//
2015-06-01 09:35:51 +00:00
{
2021-05-01 23:38:24 +00:00
return ptr - startPtr;
2015-06-01 09:35:51 +00:00
}
2020-02-07 23:26:38 +00:00
// ---------------------------------------------------------------------------------//
2017-07-28 05:41:38 +00:00
int readInt (int width)
2020-02-07 23:26:38 +00:00
// ---------------------------------------------------------------------------------//
2015-06-01 09:35:51 +00:00
{
if (width < 8 || width > 12)
throw new RuntimeException ("Illegal value of r = " + width);
int x = 0;
for (int i = 0, weight = 1; i < width; i++, weight <<= 1)
if (readBoolean ())
x |= weight;
return x;
}
2021-05-01 23:38:24 +00:00
// ---------------------------------------------------------------------------------//
private boolean readBoolean ()
// ---------------------------------------------------------------------------------//
{
if (bitsLeft == 0)
{
2021-05-02 04:45:26 +00:00
byteBuffer = buffer[ptr++] & 0xFF;
2021-05-01 23:38:24 +00:00
bitsLeft = 8;
}
bitsLeft--;
2021-08-30 06:56:43 +00:00
boolean bit = ((byteBuffer << bitsLeft) & 0x80) != 0;
2021-05-01 23:38:24 +00:00
return bit;
}
2020-02-07 23:26:38 +00:00
// ---------------------------------------------------------------------------------//
2017-07-28 05:41:38 +00:00
byte[] undoRLE (byte[] inBuffer, int inPtr, int length)
2020-02-07 23:26:38 +00:00
// ---------------------------------------------------------------------------------//
2015-06-01 09:35:51 +00:00
{
byte[] outBuffer = new byte[TRACK_LENGTH];
int outPtr = 0;
int max = inPtr + length;
while (inPtr < max)
{
byte b = inBuffer[inPtr++];
if (b == runLengthChar)
{
b = inBuffer[inPtr++];
int rpt = inBuffer[inPtr++] & 0xFF;
while (rpt-- >= 0)
outBuffer[outPtr++] = b;
}
else
outBuffer[outPtr++] = b;
}
assert outPtr == TRACK_LENGTH;
return outBuffer;
}
2021-04-15 07:27:20 +00:00
// ---------------------------------------------------------------------------------//
2021-05-01 23:38:24 +00:00
int getSize ()
2021-04-15 07:27:20 +00:00
// ---------------------------------------------------------------------------------//
{
2021-05-02 04:45:26 +00:00
if (!unpacked)
{
unpack ();
unpacked = true;
}
2021-04-15 07:27:20 +00:00
return chunks.size () * TRACK_LENGTH;
}
2020-02-07 23:26:38 +00:00
// ---------------------------------------------------------------------------------//
2021-05-01 23:38:24 +00:00
byte[] getData ()
2020-02-07 23:26:38 +00:00
// ---------------------------------------------------------------------------------//
2015-06-01 09:35:51 +00:00
{
2021-05-02 04:45:26 +00:00
if (!unpacked)
{
unpack ();
unpacked = true;
}
2021-04-17 04:41:36 +00:00
byte[] buffer = new byte[getSize ()];
2015-06-01 09:35:51 +00:00
int trackNumber = 0;
for (byte[] track : chunks)
System.arraycopy (track, 0, buffer, trackNumber++ * TRACK_LENGTH, TRACK_LENGTH);
2021-04-17 04:41:36 +00:00
int length = v3eof != 0 ? v3eof : buffer.length;
int calculatedCrc = Utility.getCRC (buffer, length, crcBase);
if (crc != calculatedCrc)
2021-04-18 03:30:50 +00:00
{
2021-04-18 10:11:26 +00:00
System.out.printf ("%n*** Thread CRC failed *** %04X %04X%n", crc, calculatedCrc);
// throw new FileFormatException ("Thread CRC failed");
2021-04-18 03:30:50 +00:00
}
2015-06-01 09:35:51 +00:00
return buffer;
}
2020-02-07 23:26:38 +00:00
// ---------------------------------------------------------------------------------//
2021-03-28 06:44:36 +00:00
int width (int maximumValue)
2020-02-07 23:26:38 +00:00
// ---------------------------------------------------------------------------------//
2015-06-01 09:35:51 +00:00
{
return 32 - Integer.numberOfLeadingZeros (maximumValue);
}
}