mirror of
https://github.com/SabreTools/BinaryObjectScanner.git
synced 2026-09-23 15:24:45 +00:00
Partially fix CAB decompression
This commit is contained in:
175
BurnOutSharp/External/libmspack/CAB/Decompressor.cs
vendored
175
BurnOutSharp/External/libmspack/CAB/Decompressor.cs
vendored
@@ -357,7 +357,6 @@ namespace LibMSPackSharp.CAB
|
||||
}
|
||||
|
||||
// Seek to start of data blocks
|
||||
// TODO: For LZX, they seem to start 8 bytes after the offset for some reason?
|
||||
if (!System.Seek(State.InputFileHandle, file.Folder.Data.Offset, SeekMode.MSPACK_SYS_SEEK_START))
|
||||
return Error = Error.MSPACK_ERR_SEEK;
|
||||
|
||||
@@ -553,85 +552,74 @@ namespace LibMSPackSharp.CAB
|
||||
/// use. will read data blocks (and merge split blocks) from the cabinet
|
||||
/// and serve the read bytes to the decompressors
|
||||
/// </summary>
|
||||
internal static int SysRead(object file, byte[] buffer, int pointer, int bytes)
|
||||
internal int SysRead(object file, byte[] buffer, int pointer, int bytes)
|
||||
{
|
||||
if (file is Decompressor self)
|
||||
int avail, todo, outlen = 0;
|
||||
|
||||
bool ignore_cksum = Salvage ||
|
||||
(FixMSZip &&
|
||||
((State.CompressionType & CompressionType.COMPTYPE_MASK) == CompressionType.COMPTYPE_MSZIP));
|
||||
bool ignore_blocksize = Salvage;
|
||||
|
||||
todo = bytes;
|
||||
while (todo > 0)
|
||||
{
|
||||
SystemImpl sys = self.System;
|
||||
avail = State.InputEnd - State.InputPointer;
|
||||
|
||||
int avail, todo, outlen = 0;
|
||||
|
||||
bool ignore_cksum = self.Salvage ||
|
||||
(self.FixMSZip &&
|
||||
((self.State.CompressionType & CompressionType.COMPTYPE_MASK) == CompressionType.COMPTYPE_MSZIP));
|
||||
bool ignore_blocksize = self.Salvage;
|
||||
|
||||
todo = bytes;
|
||||
while (todo > 0)
|
||||
// If out of input data, read a new block
|
||||
if (avail != 0)
|
||||
{
|
||||
avail = self.State.InputEnd - self.State.InputPointer;
|
||||
// Copy as many input bytes available as possible
|
||||
if (avail > todo)
|
||||
avail = todo;
|
||||
|
||||
// If out of input data, read a new block
|
||||
if (avail != 0)
|
||||
Array.Copy(State.Input, State.InputPointer, buffer, pointer, avail);
|
||||
State.InputPointer += avail;
|
||||
pointer += avail;
|
||||
todo -= avail;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Out of data, read a new block
|
||||
|
||||
// Check if we're out of input blocks, advance block counter
|
||||
if (State.Block++ >= State.Folder.Header.NumBlocks)
|
||||
{
|
||||
// Copy as many input bytes available as possible
|
||||
if (avail > todo)
|
||||
avail = todo;
|
||||
if (!Salvage)
|
||||
ReadError = Error.MSPACK_ERR_DATAFORMAT;
|
||||
else
|
||||
Console.WriteLine("Ran out of CAB input blocks prematurely");
|
||||
|
||||
Array.Copy(self.State.Input, self.State.InputPointer, buffer, pointer, avail);
|
||||
self.State.InputPointer += avail;
|
||||
pointer += avail;
|
||||
todo -= avail;
|
||||
break;
|
||||
}
|
||||
else
|
||||
|
||||
// Read a block
|
||||
ReadError = SysReadBlock(ref outlen, ignore_cksum, ignore_blocksize);
|
||||
if (ReadError != Error.MSPACK_ERR_OK)
|
||||
return -1;
|
||||
|
||||
State.Outlen += outlen;
|
||||
|
||||
// Special Quantum hack -- trailer byte to allow the decompressor
|
||||
// to realign itself. CAB Quantum blocks, unlike LZX blocks, can have
|
||||
// anything from 0 to 4 trailing null bytes.
|
||||
if ((State.CompressionType & CompressionType.COMPTYPE_MASK) == CompressionType.COMPTYPE_QUANTUM)
|
||||
State.Input[State.InputEnd++] = 0xFF;
|
||||
|
||||
// Is this the last block?
|
||||
if (State.Block >= State.Folder.Header.NumBlocks)
|
||||
{
|
||||
// Out of data, read a new block
|
||||
|
||||
// Check if we're out of input blocks, advance block counter
|
||||
if (self.State.Block++ >= self.State.Folder.Header.NumBlocks)
|
||||
if ((State.CompressionType & CompressionType.COMPTYPE_MASK) == CompressionType.COMPTYPE_LZX)
|
||||
{
|
||||
if (!self.Salvage)
|
||||
self.ReadError = Error.MSPACK_ERR_DATAFORMAT;
|
||||
else
|
||||
Console.WriteLine("Ran out of CAB input blocks prematurely");
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
// Read a block
|
||||
self.ReadError = SysReadBlock(sys, self.State, ref outlen, ignore_cksum, ignore_blocksize);
|
||||
if (self.ReadError != Error.MSPACK_ERR_OK)
|
||||
return -1;
|
||||
|
||||
self.State.Outlen += outlen;
|
||||
|
||||
// Special Quantum hack -- trailer byte to allow the decompressor
|
||||
// to realign itself. CAB Quantum blocks, unlike LZX blocks, can have
|
||||
// anything from 0 to 4 trailing null bytes.
|
||||
if ((self.State.CompressionType & CompressionType.COMPTYPE_MASK) == CompressionType.COMPTYPE_QUANTUM)
|
||||
self.State.Input[self.State.InputEnd++] = 0xFF;
|
||||
|
||||
// Is this the last block?
|
||||
if (self.State.Block >= self.State.Folder.Header.NumBlocks)
|
||||
{
|
||||
if ((self.State.CompressionType & CompressionType.COMPTYPE_MASK) == CompressionType.COMPTYPE_LZX)
|
||||
{
|
||||
// Special LZX hack -- on the last block, inform LZX of the
|
||||
// size of the output data stream.
|
||||
(self.State.DecompressorState as LZX).SetOutputLength(self.State.Outlen);
|
||||
}
|
||||
// Special LZX hack -- on the last block, inform LZX of the
|
||||
// size of the output data stream.
|
||||
(State.DecompressorState as LZX).SetOutputLength(State.Outlen);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return bytes - todo;
|
||||
}
|
||||
else if (file is FileStream impl)
|
||||
{
|
||||
return SystemImpl.DefaultSystem.Read(impl, buffer, pointer, bytes);
|
||||
}
|
||||
|
||||
return -1;
|
||||
return bytes - todo;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -640,50 +628,35 @@ namespace LibMSPackSharp.CAB
|
||||
/// sys.write() function, or does nothing with the data when
|
||||
/// self.State.OutputFileHandle == null. advances self.State.Offset
|
||||
/// </summary>
|
||||
internal static int SysWrite(object file, byte[] buffer, int pointer, int bytes)
|
||||
internal int SysWrite(object file, byte[] buffer, int pointer, int bytes)
|
||||
{
|
||||
// Null output file means skip those bytes
|
||||
if (file == null)
|
||||
{
|
||||
return bytes;
|
||||
}
|
||||
else if (file is Decompressor self)
|
||||
{
|
||||
self.State.Offset += (uint)bytes;
|
||||
if (self.State.OutputFileHandle != null)
|
||||
return self.System.Write(self.State.OutputFileHandle, buffer, pointer, bytes);
|
||||
State.Offset += (uint)bytes;
|
||||
if (State.OutputFileHandle != null)
|
||||
return System.Write(State.OutputFileHandle, buffer, pointer, bytes);
|
||||
|
||||
return bytes;
|
||||
}
|
||||
else if (file is FileStream impl)
|
||||
{
|
||||
return SystemImpl.DefaultSystem.Write(impl, buffer, pointer, bytes);
|
||||
}
|
||||
|
||||
// Unknown file to write to
|
||||
return 0;
|
||||
return bytes;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads a whole data block from a cab file. The block may span more than
|
||||
/// one cab file, if it does then the fragments will be reassembled
|
||||
/// </summary>
|
||||
private static Error SysReadBlock(SystemImpl sys, DecompressState d, ref int output, bool ignore_cksum, bool ignore_blocksize)
|
||||
private Error SysReadBlock(ref int output, bool ignore_cksum, bool ignore_blocksize)
|
||||
{
|
||||
byte[] hdr = new byte[_DataBlockHeader.Size];
|
||||
int full_len;
|
||||
|
||||
// Reset the input block pointer and end of block pointer
|
||||
d.InputPointer = d.InputEnd = 0;
|
||||
State.InputPointer = State.InputEnd = 0;
|
||||
|
||||
do
|
||||
{
|
||||
// Read the block header
|
||||
if (SystemImpl.DefaultSystem.Read(d.InputFileHandle, hdr, 0, _DataBlockHeader.Size) != _DataBlockHeader.Size)
|
||||
if (SystemImpl.DefaultSystem.Read(State.InputFileHandle, hdr, 0, _DataBlockHeader.Size) != _DataBlockHeader.Size)
|
||||
return Error.MSPACK_ERR_READ;
|
||||
|
||||
// Skip any reserved block headers
|
||||
if (d.Data.Cab.Header.HeaderReserved != 0 && !sys.Seek(d.InputFileHandle, d.Data.Cab.Header.HeaderReserved, SeekMode.MSPACK_SYS_SEEK_CUR))
|
||||
if (State.Data.Cab.Header.DataReserved != 0 && !System.Seek(State.InputFileHandle, State.Data.Cab.Header.DataReserved, SeekMode.MSPACK_SYS_SEEK_CUR))
|
||||
return Error.MSPACK_ERR_SEEK;
|
||||
|
||||
// Create a block header from the data
|
||||
@@ -692,7 +665,7 @@ namespace LibMSPackSharp.CAB
|
||||
return err;
|
||||
|
||||
// Blocks must not be over CAB_INPUTMAX in size
|
||||
full_len = (d.InputEnd - d.InputPointer) + dataBlockHeader.CompressedSize; // Include cab-spanning blocks
|
||||
full_len = (State.InputEnd - State.InputPointer) + dataBlockHeader.CompressedSize; // Include cab-spanning blocks
|
||||
if (full_len > CAB_INPUTMAX)
|
||||
{
|
||||
Console.WriteLine($"Block size {full_len} > CAB_INPUTMAX");
|
||||
@@ -711,24 +684,24 @@ namespace LibMSPackSharp.CAB
|
||||
}
|
||||
|
||||
// Read the block data
|
||||
if (SystemImpl.DefaultSystem.Read(d.InputFileHandle, d.Input, d.InputEnd, dataBlockHeader.CompressedSize) != dataBlockHeader.CompressedSize)
|
||||
if (SystemImpl.DefaultSystem.Read(State.InputFileHandle, State.Input, State.InputEnd, dataBlockHeader.CompressedSize) != dataBlockHeader.CompressedSize)
|
||||
return Error.MSPACK_ERR_READ;
|
||||
|
||||
// Perform checksum test on the block (if one is stored)
|
||||
if (dataBlockHeader.CheckSum != 0)
|
||||
{
|
||||
uint sum2 = Checksum(d.Input, d.InputEnd, dataBlockHeader.CompressedSize, 0);
|
||||
uint sum2 = Checksum(State.Input, State.InputEnd, dataBlockHeader.CompressedSize, 0);
|
||||
if (Checksum(hdr, 4, 4, sum2) != dataBlockHeader.CheckSum)
|
||||
{
|
||||
if (!ignore_cksum)
|
||||
return Error.MSPACK_ERR_CHECKSUM;
|
||||
|
||||
sys.Message(d.InputFileHandle, "WARNING; bad block checksum found");
|
||||
System.Message(State.InputFileHandle, "WARNING; bad block checksum found");
|
||||
}
|
||||
}
|
||||
|
||||
// Advance end of block pointer to include newly read data
|
||||
d.InputEnd += dataBlockHeader.CompressedSize;
|
||||
State.InputEnd += dataBlockHeader.CompressedSize;
|
||||
|
||||
// Uncompressed size == 0 means this block was part of a split block
|
||||
// and it continues as the first block of the next cabinet in the set.
|
||||
@@ -742,23 +715,23 @@ namespace LibMSPackSharp.CAB
|
||||
// Otherwise, advance to next cabinet
|
||||
|
||||
// Close current file handle
|
||||
sys.Close(d.InputFileHandle);
|
||||
d.InputFileHandle = null;
|
||||
System.Close(State.InputFileHandle);
|
||||
State.InputFileHandle = null;
|
||||
|
||||
// Advance to next member in the cabinet set
|
||||
if ((d.Data = d.Data.Next) == null)
|
||||
if ((State.Data = State.Data.Next) == null)
|
||||
{
|
||||
sys.Message(d.InputFileHandle, "WARNING; ran out of cabinets in set. Are any missing?");
|
||||
System.Message(State.InputFileHandle, "WARNING; ran out of cabinets in set. Are any missing?");
|
||||
return Error.MSPACK_ERR_DATAFORMAT;
|
||||
}
|
||||
|
||||
// Open next cab file
|
||||
d.InputCabinet = d.Data.Cab;
|
||||
if ((d.InputFileHandle = sys.Open(d.InputCabinet.Filename, OpenMode.MSPACK_SYS_OPEN_READ)) == null)
|
||||
State.InputCabinet = State.Data.Cab;
|
||||
if ((State.InputFileHandle = System.Open(State.InputCabinet.Filename, OpenMode.MSPACK_SYS_OPEN_READ)) == null)
|
||||
return Error.MSPACK_ERR_OPEN;
|
||||
|
||||
// Seek to start of data blocks
|
||||
if (!sys.Seek(d.InputFileHandle, d.Data.Offset, SeekMode.MSPACK_SYS_SEEK_START))
|
||||
if (!System.Seek(State.InputFileHandle, State.Data.Offset, SeekMode.MSPACK_SYS_SEEK_START))
|
||||
return Error.MSPACK_ERR_SEEK;
|
||||
} while (true);
|
||||
}
|
||||
|
||||
@@ -321,7 +321,7 @@ namespace LibMSPackSharp.Compression
|
||||
while (Frame < end_frame)
|
||||
{
|
||||
// Have we reached the reset interval? (if there is one?)
|
||||
if (ResetInterval != 0 && ((Frame & ResetInterval) == 0))
|
||||
if (ResetInterval != 0 && ((Frame % ResetInterval) == 0))
|
||||
{
|
||||
if (BlockRemaining != 0)
|
||||
{
|
||||
@@ -800,9 +800,29 @@ namespace LibMSPackSharp.Compression
|
||||
return Error.MSPACK_ERR_OK;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Use the cleaned up code for decompression based on wimlib
|
||||
/// </summary>
|
||||
private void ResetState()
|
||||
{
|
||||
R[0] = 1;
|
||||
R[1] = 1;
|
||||
R[2] = 1;
|
||||
HeaderRead = 0;
|
||||
BlockRemaining = 0;
|
||||
BlockType = LZXBlockType.LZX_BLOCKTYPE_INVALID0;
|
||||
|
||||
// Initialise tables to 0 (because deltas will be applied to them)
|
||||
for (int i = 0; i < LZX_MAINTREE_MAXSYMBOLS; i++)
|
||||
{
|
||||
MAINTREE_len[i] = 0;
|
||||
}
|
||||
|
||||
for (int i = 0; i < LZX_LENGTH_MAXSYMBOLS; i++)
|
||||
{
|
||||
LENGTH_len[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
#region wimlib
|
||||
|
||||
public Error DecompressNew(long out_bytes)
|
||||
{
|
||||
int warned = 0;
|
||||
@@ -1012,56 +1032,6 @@ namespace LibMSPackSharp.Compression
|
||||
return Error.MSPACK_ERR_OK;
|
||||
}
|
||||
|
||||
private Error BUILD_TABLE(ushort[] table, byte[] lengths, int tablebits, int maxsymbols)
|
||||
{
|
||||
if (!MakeDecodeTableMSB(maxsymbols, tablebits, lengths, table))
|
||||
{
|
||||
Console.WriteLine($"Failed to build table");
|
||||
return Error = Error.MSPACK_ERR_DECRUNCH;
|
||||
}
|
||||
|
||||
return Error = Error.MSPACK_ERR_OK;
|
||||
}
|
||||
|
||||
private Error BUILD_TABLE_MAYBE_EMPTY()
|
||||
{
|
||||
LENGTH_empty = 0;
|
||||
if (!MakeDecodeTableMSB(LZX_LENGTH_MAXSYMBOLS, LZX_LENGTH_TABLEBITS, LENGTH_len, LENGTH_table))
|
||||
{
|
||||
for (int i = 0; i < LZX_LENGTH_MAXSYMBOLS; i++)
|
||||
{
|
||||
if (LENGTH_len[i] > 0)
|
||||
{
|
||||
Console.WriteLine("Failed to build table");
|
||||
return Error = Error.MSPACK_ERR_DECRUNCH;
|
||||
}
|
||||
}
|
||||
|
||||
// Empty tree - allow it, but don't decode symbols with it
|
||||
LENGTH_empty = 1;
|
||||
}
|
||||
|
||||
return Error = Error.MSPACK_ERR_OK;
|
||||
}
|
||||
|
||||
private Error READ_LENGTHS(byte[] lengths, uint first, uint last)
|
||||
{
|
||||
int i_ptr = InputPointer;
|
||||
int i_end = InputEnd;
|
||||
uint bit_buffer = BitBuffer;
|
||||
int bits_left = BitsLeft;
|
||||
|
||||
if (ReadLens(lengths, first, last) != Error.MSPACK_ERR_OK)
|
||||
return Error;
|
||||
|
||||
InputPointer = i_ptr;
|
||||
InputEnd = i_end;
|
||||
BitBuffer = bit_buffer;
|
||||
BitsLeft = bits_left;
|
||||
|
||||
return Error = Error.MSPACK_ERR_OK;
|
||||
}
|
||||
|
||||
private Error Copy(uint match_offset, int match_len, ref int this_run)
|
||||
{
|
||||
// Copy match
|
||||
@@ -1399,101 +1369,6 @@ namespace LibMSPackSharp.Compression
|
||||
return Error = Error.MSPACK_ERR_OK;
|
||||
}
|
||||
|
||||
private Error ReadLens(byte[] lens, uint first, uint last)
|
||||
{
|
||||
uint x, y;
|
||||
int z;
|
||||
|
||||
// Read lengths for pretree (20 symbols, lengths stored in fixed 4 bits)
|
||||
for (x = 0; x < LZX_PRETREE_MAXSYMBOLS; x++)
|
||||
{
|
||||
y = (uint)READ_BITS_MSB(4);
|
||||
PRETREE_len[x] = (byte)y;
|
||||
}
|
||||
|
||||
BUILD_TABLE(PRETREE_table, PRETREE_len, LZX_PRETREE_TABLEBITS, LZX_PRETREE_MAXSYMBOLS);
|
||||
if (Error != Error.MSPACK_ERR_OK)
|
||||
return Error;
|
||||
|
||||
for (x = first; x < last;)
|
||||
{
|
||||
z = (int)READ_HUFFSYM_MSB(PRETREE_table, PRETREE_len, LZX_PRETREE_TABLEBITS, LZX_PRETREE_MAXSYMBOLS);
|
||||
switch (z)
|
||||
{
|
||||
// Code = 17, run of ([read 4 bits]+4) zeros
|
||||
case 17:
|
||||
y = (uint)READ_BITS_MSB(4);
|
||||
y += 4;
|
||||
while (y-- != 0)
|
||||
{
|
||||
lens[x++] = 0;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
// Code = 18, run of ([read 5 bits]+20) zeros
|
||||
case 18:
|
||||
y = (uint)READ_BITS_MSB(5);
|
||||
y += 20;
|
||||
while (y-- != 0)
|
||||
{
|
||||
lens[x++] = 0;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
// Code = 19, run of ([read 1 bit]+4) [read huffman symbol]
|
||||
case 19:
|
||||
y = (uint)READ_BITS_MSB(1);
|
||||
y += 4;
|
||||
|
||||
z = (int)READ_HUFFSYM_MSB(PRETREE_table, PRETREE_len, LZX_PRETREE_TABLEBITS, LZX_PRETREE_MAXSYMBOLS);
|
||||
z = lens[x] - z;
|
||||
if (z < 0)
|
||||
z += 17;
|
||||
|
||||
while (y-- != 0)
|
||||
{
|
||||
lens[x++] = (byte)z;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
// Code = 0 to 16, delta current length entry
|
||||
default:
|
||||
z = lens[x] - z;
|
||||
if (z < 0)
|
||||
z += 17;
|
||||
|
||||
lens[x++] = (byte)z;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return Error.MSPACK_ERR_OK;
|
||||
}
|
||||
|
||||
private void ResetState()
|
||||
{
|
||||
R[0] = 1;
|
||||
R[1] = 1;
|
||||
R[2] = 1;
|
||||
HeaderRead = 0;
|
||||
BlockRemaining = 0;
|
||||
BlockType = LZXBlockType.LZX_BLOCKTYPE_INVALID0;
|
||||
|
||||
// Initialise tables to 0 (because deltas will be applied to them)
|
||||
for (int i = 0; i < LZX_MAINTREE_MAXSYMBOLS; i++)
|
||||
{
|
||||
MAINTREE_len[i] = 0;
|
||||
}
|
||||
|
||||
for (int i = 0; i < LZX_LENGTH_MAXSYMBOLS; i++)
|
||||
{
|
||||
LENGTH_len[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
private void UndoE8Preprocessing(int data, long out_bytes)
|
||||
{
|
||||
int p8 = data;
|
||||
@@ -1540,5 +1415,7 @@ namespace LibMSPackSharp.Compression
|
||||
} while (p8 < p8_end);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,11 +10,146 @@
|
||||
* For further details, see the file COPYING.LIB distributed with libmspack
|
||||
*/
|
||||
|
||||
using System;
|
||||
using static LibMSPackSharp.Compression.Constants;
|
||||
|
||||
namespace LibMSPackSharp.Compression
|
||||
{
|
||||
public partial class LZX : CompressionStream
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public override Error HUFF_ERROR() => Error.MSPACK_ERR_DECRUNCH;
|
||||
|
||||
/// <summary>
|
||||
/// BUILD_TABLE(tbl) builds a huffman lookup table from code lengths
|
||||
/// </summary>
|
||||
private Error BUILD_TABLE(ushort[] table, byte[] lengths, int tablebits, int maxsymbols)
|
||||
{
|
||||
if (!MakeDecodeTableMSB(maxsymbols, tablebits, lengths, table))
|
||||
{
|
||||
Console.WriteLine("Failed to build table");
|
||||
return Error = Error.MSPACK_ERR_DECRUNCH;
|
||||
}
|
||||
|
||||
return Error = Error.MSPACK_ERR_OK;
|
||||
}
|
||||
|
||||
private Error BUILD_TABLE_MAYBE_EMPTY()
|
||||
{
|
||||
LENGTH_empty = 0;
|
||||
if (!MakeDecodeTableMSB(LZX_LENGTH_MAXSYMBOLS, LZX_LENGTH_TABLEBITS, LENGTH_len, LENGTH_table))
|
||||
{
|
||||
for (int i = 0; i < LZX_LENGTH_MAXSYMBOLS; i++)
|
||||
{
|
||||
if (LENGTH_len[i] > 0)
|
||||
{
|
||||
Console.WriteLine("Failed to build table");
|
||||
return Error = Error.MSPACK_ERR_DECRUNCH;
|
||||
}
|
||||
}
|
||||
|
||||
// Empty tree - allow it, but don't decode symbols with it
|
||||
LENGTH_empty = 1;
|
||||
}
|
||||
|
||||
return Error = Error.MSPACK_ERR_OK;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// READ_LENGTHS(tablename, first, last) reads in code lengths for symbols
|
||||
/// first to last in the given table. The code lengths are stored in their
|
||||
/// own special LZX way.
|
||||
/// </summary>
|
||||
private Error READ_LENGTHS(byte[] lengths, uint first, uint last)
|
||||
{
|
||||
int i_ptr = InputPointer;
|
||||
int i_end = InputEnd;
|
||||
uint bit_buffer = BitBuffer;
|
||||
int bits_left = BitsLeft;
|
||||
|
||||
if (ReadLens(lengths, first, last) != Error.MSPACK_ERR_OK)
|
||||
return Error;
|
||||
|
||||
InputPointer = i_ptr;
|
||||
InputEnd = i_end;
|
||||
BitBuffer = bit_buffer;
|
||||
BitsLeft = bits_left;
|
||||
|
||||
return Error = Error.MSPACK_ERR_OK;
|
||||
}
|
||||
|
||||
private Error ReadLens(byte[] lens, uint first, uint last)
|
||||
{
|
||||
uint x, y;
|
||||
int z;
|
||||
|
||||
// Read lengths for pretree (20 symbols, lengths stored in fixed 4 bits)
|
||||
for (x = 0; x < LZX_PRETREE_MAXSYMBOLS; x++)
|
||||
{
|
||||
y = (uint)READ_BITS_MSB(4);
|
||||
PRETREE_len[x] = (byte)y;
|
||||
}
|
||||
|
||||
BUILD_TABLE(PRETREE_table, PRETREE_len, LZX_PRETREE_TABLEBITS, LZX_PRETREE_MAXSYMBOLS);
|
||||
if (Error != Error.MSPACK_ERR_OK)
|
||||
return Error;
|
||||
|
||||
for (x = first; x < last;)
|
||||
{
|
||||
z = (int)READ_HUFFSYM_MSB(PRETREE_table, PRETREE_len, LZX_PRETREE_TABLEBITS, LZX_PRETREE_MAXSYMBOLS);
|
||||
switch (z)
|
||||
{
|
||||
// Code = 17, run of ([read 4 bits]+4) zeros
|
||||
case 17:
|
||||
y = (uint)READ_BITS_MSB(4);
|
||||
y += 4;
|
||||
while (y-- != 0)
|
||||
{
|
||||
lens[x++] = 0;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
// Code = 18, run of ([read 5 bits]+20) zeros
|
||||
case 18:
|
||||
y = (uint)READ_BITS_MSB(5);
|
||||
y += 20;
|
||||
while (y-- != 0)
|
||||
{
|
||||
lens[x++] = 0;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
// Code = 19, run of ([read 1 bit]+4) [read huffman symbol]
|
||||
case 19:
|
||||
y = (uint)READ_BITS_MSB(1);
|
||||
y += 4;
|
||||
|
||||
z = (int)READ_HUFFSYM_MSB(PRETREE_table, PRETREE_len, LZX_PRETREE_TABLEBITS, LZX_PRETREE_MAXSYMBOLS);
|
||||
z = lens[x] - z;
|
||||
if (z < 0)
|
||||
z += 17;
|
||||
|
||||
while (y-- != 0)
|
||||
{
|
||||
lens[x++] = (byte)z;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
// Code = 0 to 16, delta current length entry
|
||||
default:
|
||||
z = lens[x] - z;
|
||||
if (z < 0)
|
||||
z += 17;
|
||||
|
||||
lens[x++] = (byte)z;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return Error.MSPACK_ERR_OK;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user