Less static methods

This commit is contained in:
Matt Nadareski
2022-05-24 17:05:34 -07:00
parent 15c05c65e7
commit 54a48e0729
10 changed files with 267 additions and 269 deletions

View File

@@ -7,7 +7,7 @@
* For further details, see the file COPYING.LIB distributed with libmspack
*/
using System;
using LibMSPackSharp.Compression;
namespace LibMSPackSharp.CAB
{
@@ -43,11 +43,6 @@ namespace LibMSPackSharp.CAB
/// </summary>
public CompressionType CompressionType { get; set; }
/// <summary>
/// Decompressor code
/// </summary>
public Func<object, long, Error> Decompress { get; set; }
/// <summary>
/// Decompressor state
/// </summary>
@@ -72,5 +67,29 @@ namespace LibMSPackSharp.CAB
/// One input block of data
/// </summary>
public byte[] Input { get; set; } = new byte[Constants.CAB_INPUTBUF];
/// <summary>
/// Decompressor code
/// </summary>
public Error Decompress(object o, long bytes)
{
switch (CompressionType & CompressionType.COMPTYPE_MASK)
{
case CompressionType.COMPTYPE_NONE:
return (o as None)?.Decompress(bytes) ?? Error.MSPACK_ERR_ARGS;
case CompressionType.COMPTYPE_MSZIP:
return (o as MSZIP)?.Decompress(bytes) ?? Error.MSPACK_ERR_ARGS;
case CompressionType.COMPTYPE_QUANTUM:
return (o as QTM)?.Decompress(bytes) ?? Error.MSPACK_ERR_ARGS;
case CompressionType.COMPTYPE_LZX:
return (o as LZX)?.Decompress(bytes) ?? Error.MSPACK_ERR_ARGS;
default:
return Error = Error.MSPACK_ERR_DATAFORMAT;
}
}
}
}

View File

@@ -465,22 +465,18 @@ namespace LibMSPackSharp.CAB
switch (ct & CompressionType.COMPTYPE_MASK)
{
case CompressionType.COMPTYPE_NONE:
State.Decompress = None.Decompress;
State.DecompressorState = None.Init(State.System, State.InputFileHandle, State.OutputFileHandle, BufferSize);
break;
case CompressionType.COMPTYPE_MSZIP:
State.Decompress = MSZIP.Decompress;
State.DecompressorState = MSZIP.Init(State.System, State.InputFileHandle, State.OutputFileHandle, BufferSize, FixMSZip);
break;
case CompressionType.COMPTYPE_QUANTUM:
State.Decompress = QTM.Decompress;
State.DecompressorState = QTM.Init(State.System, State.InputFileHandle, State.OutputFileHandle, ((ushort)ct >> 8) & 0x1f, BufferSize);
break;
case CompressionType.COMPTYPE_LZX:
State.Decompress = LZX.Decompress;
State.DecompressorState = LZX.Init(State.System, State.InputFileHandle, State.OutputFileHandle, ((ushort)ct >> 8) & 0x1f, 0, BufferSize, 0, false);
break;
@@ -521,7 +517,6 @@ namespace LibMSPackSharp.CAB
if (State?.DecompressorState == null)
return;
State.Decompress = null;
State.DecompressorState = null;
}

View File

@@ -404,13 +404,13 @@ namespace LibMSPackSharp.CHM
State.OutputFileHandle = null;
long bytes;
if ((bytes = file.Offset - State.Offset) != 0)
Error = LZX.Decompress(State.State, bytes);
Error = State.State.Decompress(bytes);
// If getting to the correct offset was error free, unpack file
if (Error == Error.MSPACK_ERR_OK)
{
State.OutputFileHandle = fh;
Error = LZX.Decompress(State.State, file.Length);
Error = State.State.Decompress(file.Length);
}
// Save offset in input source stream, in case there is a section 0

View File

@@ -285,241 +285,237 @@ namespace LibMSPackSharp.Compression
/// <param name="o">LZX decompression state, as allocated by lzxd_init().</param>
/// <param name="out_bytes">the number of bytes of data to decompress.</param>
/// <returns>an error code, or MSPACK_ERR_OK if successful</returns>
public static Error Decompress(object o, long out_bytes)
public Error Decompress(long out_bytes)
{
LZX lzx = o as LZX;
if (lzx == null)
return Error.MSPACK_ERR_ARGS;
int warned = 0;
byte[] buf = new byte[12];
// Easy answers
if (lzx == null || (out_bytes < 0))
if (out_bytes < 0)
return Error.MSPACK_ERR_ARGS;
if (lzx.Error != Error.MSPACK_ERR_OK)
return lzx.Error;
if (Error != Error.MSPACK_ERR_OK)
return Error;
// Flush out any stored-up bytes before we begin
int leftover_bytes = lzx.OutputEnd - lzx.OutputPointer;
int leftover_bytes = OutputEnd - OutputPointer;
if (leftover_bytes > out_bytes)
leftover_bytes = (int)out_bytes;
if (leftover_bytes != 0)
{
try { lzx.System.Write(lzx.OutputFileHandle, lzx.OutputIsE8 ? lzx.E8Buffer : lzx.Window, lzx.OutputPointer, leftover_bytes); }
catch { return lzx.Error = Error.MSPACK_ERR_WRITE; }
try { System.Write(OutputFileHandle, OutputIsE8 ? E8Buffer : Window, OutputPointer, leftover_bytes); }
catch { return Error = Error.MSPACK_ERR_WRITE; }
lzx.OutputPointer += leftover_bytes;
lzx.Offset += leftover_bytes;
OutputPointer += leftover_bytes;
Offset += leftover_bytes;
out_bytes -= leftover_bytes;
}
if (out_bytes == 0)
return Error.MSPACK_ERR_OK;
uint end_frame = (uint)((lzx.Offset + out_bytes) / LZX_FRAME_SIZE) + 1;
uint end_frame = (uint)((Offset + out_bytes) / LZX_FRAME_SIZE) + 1;
while (lzx.Frame < end_frame)
while (Frame < end_frame)
{
// Have we reached the reset interval? (if there is one?)
if (lzx.ResetInterval != 0 && ((lzx.Frame % lzx.ResetInterval) == 0))
if (ResetInterval != 0 && ((Frame % ResetInterval) == 0))
{
if (lzx.BlockRemaining != 0)
if (BlockRemaining != 0)
{
// This is a file format error, we can make a best effort to extract what we can
Console.WriteLine($"{lzx.BlockRemaining} bytes remaining at reset interval");
Console.WriteLine($"{BlockRemaining} bytes remaining at reset interval");
if (warned == 0)
{
lzx.System.Message(null, "WARNING; invalid reset interval detected during LZX decompression");
System.Message(null, "WARNING; invalid reset interval detected during LZX decompression");
warned++;
}
}
// Re-read the intel header and reset the huffman lengths
lzx.ResetState();
ResetState();
}
// LZX DELTA format has chunk_size, not present in LZX format
if (lzx.IsDelta)
if (IsDelta)
{
lzx.ENSURE_BITS(16);
lzx.REMOVE_BITS_MSB(16);
ENSURE_BITS(16);
REMOVE_BITS_MSB(16);
}
//// Read header if necessary
//if (lzx.HeaderRead == 0)
//if (HeaderRead == 0)
//{
// // Read 1 bit. If bit=0, intel_filesize = 0.
// // If bit=1, read intel filesize (32 bits)
// int j = 0;
// int i = (int)lzx.READ_BITS_MSB(1, state);
// int i = (int)READ_BITS_MSB(1, state);
// if (i != 0)
// {
// i = (int)lzx.READ_BITS_MSB(16, state);
// j = (int)lzx.READ_BITS_MSB(16, state);
// i = (int)READ_BITS_MSB(16, state);
// j = (int)READ_BITS_MSB(16, state);
// }
// lzx.IntelFileSize = (i << 16) | j;
// lzx.HeaderRead = 1;
// IntelFileSize = (i << 16) | j;
// HeaderRead = 1;
//}
// Calculate size of frame: all frames are 32k except the final frame
// which is 32kb or less. this can only be calculated when lzx.Length
// which is 32kb or less. this can only be calculated when Length
// has been filled in.
uint frame_size = LZX_FRAME_SIZE;
if (lzx.Length != 0 && (lzx.Length - lzx.Offset) < frame_size)
frame_size = (uint)(lzx.Length - lzx.Offset);
if (Length != 0 && (Length - Offset) < frame_size)
frame_size = (uint)(Length - Offset);
// Decode until one more frame is available
int bytes_todo = (int)(lzx.FramePosition + frame_size - lzx.WindowPosition);
int bytes_todo = (int)(FramePosition + frame_size - WindowPosition);
while (bytes_todo > 0)
{
// Realign if previous block was an odd-sized UNCOMPRESSED block
if ((lzx.BlockType == LZXBlockType.LZX_BLOCKTYPE_UNCOMPRESSED) && (lzx.BlockLength & 1) != 0)
if ((BlockType == LZXBlockType.LZX_BLOCKTYPE_UNCOMPRESSED) && (BlockLength & 1) != 0)
{
lzx.READ_IF_NEEDED();
if (lzx.Error != Error.MSPACK_ERR_OK)
return lzx.Error;
READ_IF_NEEDED();
if (Error != Error.MSPACK_ERR_OK)
return Error;
lzx.InputPointer++;
InputPointer++;
}
lzx.ReadBlockHeader(buf);
if (lzx.Error != Error.MSPACK_ERR_OK)
return lzx.Error;
ReadBlockHeader(buf);
if (Error != Error.MSPACK_ERR_OK)
return Error;
// Decode more of the block:
int this_run = Math.Min(lzx.BlockRemaining, bytes_todo);
int this_run = Math.Min(BlockRemaining, bytes_todo);
// Assume we decode exactly this_run bytes, for now
bytes_todo -= this_run;
lzx.BlockRemaining -= this_run;
BlockRemaining -= this_run;
// Decode at least this_run bytes
switch (lzx.BlockType)
switch (BlockType)
{
case LZXBlockType.LZX_BLOCKTYPE_ALIGNED:
case LZXBlockType.LZX_BLOCKTYPE_VERBATIM:
lzx.DecompressBlock(ref this_run);
if (lzx.Error != Error.MSPACK_ERR_OK)
return lzx.Error;
DecompressBlock(ref this_run);
if (Error != Error.MSPACK_ERR_OK)
return Error;
// If the literal 0xE8 is anywhere in the block...
if (lzx.MAINTREE_len[0xE8] != 0)
lzx.IntelStarted = true;
if (MAINTREE_len[0xE8] != 0)
IntelStarted = true;
break;
case LZXBlockType.LZX_BLOCKTYPE_UNCOMPRESSED:
// As this_run is limited not to wrap a frame, this also means it
// won't wrap the window (as the window is a multiple of 32k)
int rundest = lzx.WindowPosition;
lzx.WindowPosition += this_run;
int rundest = WindowPosition;
WindowPosition += this_run;
while (this_run > 0)
{
int i = lzx.InputEnd - lzx.InputPointer;
int i = InputEnd - InputPointer;
if (i == 0)
{
lzx.READ_IF_NEEDED();
if (lzx.Error != Error.MSPACK_ERR_OK)
return lzx.Error;
READ_IF_NEEDED();
if (Error != Error.MSPACK_ERR_OK)
return Error;
}
else
{
if (i > this_run)
i = this_run;
Array.Copy(lzx.InputBuffer, lzx.InputPointer, lzx.Window, rundest, i);
Array.Copy(InputBuffer, InputPointer, Window, rundest, i);
rundest += i;
lzx.InputPointer += i;
InputPointer += i;
this_run -= i;
}
}
// Because we can't assume otherwise
lzx.IntelStarted = true;
IntelStarted = true;
break;
default:
return lzx.Error = Error.MSPACK_ERR_DECRUNCH; // Might as well
return Error = Error.MSPACK_ERR_DECRUNCH; // Might as well
}
// Did the final match overrun our desired this_run length?
if (this_run < 0)
{
if ((uint)(-this_run) > lzx.BlockRemaining)
if ((uint)(-this_run) > BlockRemaining)
{
Console.WriteLine($"Overrun went past end of block by {-this_run} ({lzx.BlockRemaining} remaining)");
return lzx.Error = Error.MSPACK_ERR_DECRUNCH;
Console.WriteLine($"Overrun went past end of block by {-this_run} ({BlockRemaining} remaining)");
return Error = Error.MSPACK_ERR_DECRUNCH;
}
lzx.BlockRemaining -= -this_run;
BlockRemaining -= -this_run;
}
}
// Streams don't extend over frame boundaries
if ((lzx.WindowPosition - lzx.FramePosition) != frame_size)
if ((WindowPosition - FramePosition) != frame_size)
{
Console.WriteLine($"Decode beyond output frame limits! {lzx.WindowPosition - lzx.FramePosition} != {frame_size}");
return lzx.Error = Error.MSPACK_ERR_DECRUNCH;
Console.WriteLine($"Decode beyond output frame limits! {WindowPosition - FramePosition} != {frame_size}");
return Error = Error.MSPACK_ERR_DECRUNCH;
}
// Re-align input bitstream
if (lzx.BitsLeft > 0)
lzx.ENSURE_BITS(16);
if ((lzx.BitsLeft & 15) != 0)
lzx.REMOVE_BITS_MSB(lzx.BitsLeft & 15);
if (BitsLeft > 0)
ENSURE_BITS(16);
if ((BitsLeft & 15) != 0)
REMOVE_BITS_MSB(BitsLeft & 15);
// Check that we've used all of the previous frame first
if (lzx.OutputPointer != lzx.OutputEnd)
if (OutputPointer != OutputEnd)
{
Console.WriteLine($"{lzx.OutputEnd - lzx.OutputPointer} avail bytes, new {frame_size} frame");
return lzx.Error = Error.MSPACK_ERR_DECRUNCH;
Console.WriteLine($"{OutputEnd - OutputPointer} avail bytes, new {frame_size} frame");
return Error = Error.MSPACK_ERR_DECRUNCH;
}
// Does this intel block _really_ need decoding?
if (lzx.IntelStarted && lzx.IntelFileSize != 0 && (lzx.Frame < 32768) && (frame_size > 10))
if (IntelStarted && IntelFileSize != 0 && (Frame < 32768) && (frame_size > 10))
{
lzx.UndoE8Preprocessing(frame_size);
UndoE8Preprocessing(frame_size);
}
else
{
lzx.OutputIsE8 = false;
lzx.OutputPointer = (int)lzx.FramePosition;
OutputIsE8 = false;
OutputPointer = (int)FramePosition;
}
lzx.OutputEnd = (int)(lzx.OutputPointer + frame_size);
OutputEnd = (int)(OutputPointer + frame_size);
// Write a frame
int new_out_bytes = (int)((out_bytes < frame_size) ? out_bytes : frame_size);
try { lzx.System.Write(lzx.OutputFileHandle, lzx.OutputIsE8 ? lzx.E8Buffer : lzx.Window, lzx.OutputPointer, new_out_bytes); }
catch { return lzx.Error = Error.MSPACK_ERR_WRITE; }
try { System.Write(OutputFileHandle, OutputIsE8 ? E8Buffer : Window, OutputPointer, new_out_bytes); }
catch { return Error = Error.MSPACK_ERR_WRITE; }
lzx.OutputPointer += new_out_bytes;
lzx.Offset += new_out_bytes;
OutputPointer += new_out_bytes;
Offset += new_out_bytes;
out_bytes -= new_out_bytes;
// Advance frame start position
lzx.FramePosition += frame_size;
lzx.Frame++;
FramePosition += frame_size;
Frame++;
// Wrap window / frame position pointers
if (lzx.WindowPosition == lzx.WindowSize)
lzx.WindowPosition = 0;
if (lzx.FramePosition == lzx.WindowSize)
lzx.FramePosition = 0;
if (WindowPosition == WindowSize)
WindowPosition = 0;
if (FramePosition == WindowSize)
FramePosition = 0;
}
if (out_bytes != 0)
{
Console.WriteLine("Bytes left to output");
return lzx.Error = Error.MSPACK_ERR_DECRUNCH;
return Error = Error.MSPACK_ERR_DECRUNCH;
}
return Error.MSPACK_ERR_OK;

View File

@@ -84,32 +84,28 @@ namespace LibMSPackSharp.Compression
/// mszipd_init(). This will continue until system.read() returns 0 bytes,
/// or an error.
/// </summary>
public static Error Decompress(object o, long out_bytes)
public Error Decompress(long out_bytes)
{
MSZIP zip = o as MSZIP;
if (zip == null)
return Error.MSPACK_ERR_ARGS;
int i, readState;
Error error;
// Easy answers
if (zip == null || (out_bytes < 0))
if (out_bytes < 0)
return Error.MSPACK_ERR_ARGS;
if (zip.Error != Error.MSPACK_ERR_OK)
return zip.Error;
if (Error != Error.MSPACK_ERR_OK)
return Error;
// Flush out any stored-up bytes before we begin
i = zip.OutputEnd - zip.OutputPointer;
i = OutputEnd - OutputPointer;
if (i > out_bytes)
i = (int)out_bytes;
if (i != 0)
{
if (zip.System.Write(zip.OutputFileHandle, zip.Window, zip.OutputPointer, i) != i)
return zip.Error = Error.MSPACK_ERR_WRITE;
if (System.Write(OutputFileHandle, Window, OutputPointer, i) != i)
return Error = Error.MSPACK_ERR_WRITE;
zip.OutputPointer += i;
OutputPointer += i;
out_bytes -= i;
}
@@ -119,15 +115,15 @@ namespace LibMSPackSharp.Compression
while (out_bytes > 0)
{
// Skip to next read 'CK' header
i = zip.BitsLeft & 7;
i = BitsLeft & 7;
// Align to bytestream
zip.REMOVE_BITS_LSB(i);
REMOVE_BITS_LSB(i);
readState = 0;
do
{
i = (int)zip.READ_BITS_LSB(8);
i = (int)READ_BITS_LSB(8);
if (i == 'C')
readState = 1;
@@ -138,52 +134,52 @@ namespace LibMSPackSharp.Compression
} while (readState != 2);
// Inflate a block, repair and realign if necessary
zip.WindowPosition = 0;
zip.BytesOutput = 0;
WindowPosition = 0;
BytesOutput = 0;
if ((error = zip.Inflate()) != Error.MSPACK_ERR_OK)
if ((error = Inflate()) != Error.MSPACK_ERR_OK)
{
Console.WriteLine($"Inflate error {error}");
if (zip.RepairMode)
if (RepairMode)
{
// Recover partially-inflated buffers
if (zip.BytesOutput == 0 && zip.WindowPosition > 0)
zip.FlushWindow(zip.WindowPosition);
if (BytesOutput == 0 && WindowPosition > 0)
FlushWindow(WindowPosition);
zip.System.Message(null, $"MSZIP error, {MSZIP_FRAME_SIZE - zip.BytesOutput} bytes of data lost.");
for (i = zip.BytesOutput; i < MSZIP_FRAME_SIZE; i++)
System.Message(null, $"MSZIP error, {MSZIP_FRAME_SIZE - BytesOutput} bytes of data lost.");
for (i = BytesOutput; i < MSZIP_FRAME_SIZE; i++)
{
zip.Window[i] = 0x00;
Window[i] = 0x00;
}
zip.BytesOutput = MSZIP_FRAME_SIZE;
BytesOutput = MSZIP_FRAME_SIZE;
}
else
{
return zip.Error = error;
return Error = error;
}
}
zip.OutputPointer = 0;
zip.OutputEnd = zip.BytesOutput;
OutputPointer = 0;
OutputEnd = BytesOutput;
// Write a frame
i = (out_bytes < zip.BytesOutput) ? (int)out_bytes : zip.BytesOutput;
if (zip.System.Write(zip.OutputFileHandle, zip.Window, zip.OutputPointer, i) != i)
return zip.Error = Error.MSPACK_ERR_WRITE;
i = (out_bytes < BytesOutput) ? (int)out_bytes : BytesOutput;
if (System.Write(OutputFileHandle, Window, OutputPointer, i) != i)
return Error = Error.MSPACK_ERR_WRITE;
// mspack errors (i.e. read errors) are fatal and can't be recovered
if ((error > 0) && zip.RepairMode)
if ((error > 0) && RepairMode)
return error;
zip.OutputPointer += i;
OutputPointer += i;
out_bytes -= i;
}
if (out_bytes != 0)
{
Console.WriteLine($"Bytes left to output: {out_bytes}");
return zip.Error = Error.MSPACK_ERR_DECRUNCH;
return Error = Error.MSPACK_ERR_DECRUNCH;
}
return Error.MSPACK_ERR_OK;

View File

@@ -0,0 +1,46 @@
/* This file is part of libmspack.
* (C) 2003-2018 Stuart Caie.
*
* libmspack is free software; you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License (LGPL) version 2.1
*
* For further details, see the file COPYING.LIB distributed with libmspack
*/
using System.IO;
namespace LibMSPackSharp.Compression
{
public partial class None
{
public static None Init(SystemImpl sys, FileStream input, FileStream output, int bufsize)
{
return new None()
{
System = sys,
InputFileHandle = input,
OutputFileHandle = output,
Buffer = new byte[bufsize],
BufferSize = bufsize,
};
}
public Error Decompress(long bytes)
{
int run;
while (bytes > 0)
{
run = (bytes > BufferSize) ? BufferSize : (int)bytes;
if (System.Read(InputFileHandle, Buffer, 0, run) != run)
return Error.MSPACK_ERR_READ;
if (System.Write(OutputFileHandle, Buffer, 0, run) != run)
return Error.MSPACK_ERR_WRITE;
bytes -= run;
}
return Error.MSPACK_ERR_OK;
}
}
}

View File

@@ -7,44 +7,15 @@
* For further details, see the file COPYING.LIB distributed with libmspack
*/
using System.IO;
namespace LibMSPackSharp.Compression
{
public class None
/// <summary>
/// The "not compressed" method decompressor
/// </summary>
public partial class None : BaseDecompressState
{
public static NoneState Init(SystemImpl sys, FileStream input, FileStream output, int bufsize)
{
return new NoneState()
{
System = sys,
InputFileHandle = input,
OutputFileHandle = output,
Buffer = new byte[bufsize],
BufferSize = bufsize,
};
}
public byte[] Buffer { get; set; }
public static Error Decompress(object s, long bytes)
{
NoneState state = (NoneState)s;
if (state == null)
return Error.MSPACK_ERR_ARGS;
int run;
while (bytes > 0)
{
run = (bytes > state.BufferSize) ? state.BufferSize : (int)bytes;
if (state.System.Read(state.InputFileHandle, state.Buffer, 0, run) != run)
return Error.MSPACK_ERR_READ;
if (state.System.Write(state.OutputFileHandle, state.Buffer, 0, run) != run)
return Error.MSPACK_ERR_WRITE;
bytes -= run;
}
return Error.MSPACK_ERR_OK;
}
public int BufferSize { get; set; }
}
}

View File

@@ -1,21 +0,0 @@
/* This file is part of libmspack.
* (C) 2003-2018 Stuart Caie.
*
* libmspack is free software; you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License (LGPL) version 2.1
*
* For further details, see the file COPYING.LIB distributed with libmspack
*/
namespace LibMSPackSharp.Compression
{
/// <summary>
/// The "not compressed" method decompressor
/// </summary>
public class NoneState : BaseDecompressState
{
public byte[] Buffer { get; set; }
public int BufferSize { get; set; }
}
}

View File

@@ -119,12 +119,8 @@ namespace LibMSPackSharp.Compression
/// qtmd_init(). This will continue until system.read() returns 0 bytes,
/// or an error.
/// </summary>
public static Error Decompress(object o, long out_bytes)
public Error Decompress(long out_bytes)
{
QTM qtm = o as QTM;
if (qtm == null)
return Error.MSPACK_ERR_ARGS;
uint frame_todo, frame_end, window_posn, match_offset, range;
byte[] window;
int runsrc, rundest;
@@ -132,23 +128,23 @@ namespace LibMSPackSharp.Compression
ushort H, L, C, symf;
// Easy answers
if (qtm == null || (out_bytes < 0))
if (out_bytes < 0)
return Error.MSPACK_ERR_ARGS;
if (qtm.Error != Error.MSPACK_ERR_OK)
return qtm.Error;
if (Error != Error.MSPACK_ERR_OK)
return Error;
// Flush out any stored-up bytes before we begin
i = qtm.OutputEnd - qtm.OutputPointer;
i = OutputEnd - OutputPointer;
if (i > out_bytes)
i = (int)out_bytes;
if (i != 0)
{
if (qtm.System.Write(qtm.OutputFileHandle, qtm.Window, qtm.OutputPointer, i) != i)
return qtm.Error = Error.MSPACK_ERR_WRITE;
if (System.Write(OutputFileHandle, Window, OutputPointer, i) != i)
return Error = Error.MSPACK_ERR_WRITE;
qtm.OutputPointer += i;
OutputPointer += i;
out_bytes -= i;
}
@@ -156,36 +152,36 @@ namespace LibMSPackSharp.Compression
return Error.MSPACK_ERR_OK;
// Restore local state
window = qtm.Window;
window_posn = qtm.WindowPosition;
frame_todo = qtm.FrameTODO;
H = qtm.High;
L = qtm.Low;
C = qtm.Current;
window = Window;
window_posn = WindowPosition;
frame_todo = FrameTODO;
H = High;
L = Low;
C = Current;
// While we do not have enough decoded bytes in reserve
while ((qtm.OutputEnd - qtm.OutputPointer) < out_bytes)
while ((OutputEnd - OutputPointer) < out_bytes)
{
// Read header if necessary. Initialises H, L and C
if (qtm.HeaderRead != 0)
if (HeaderRead != 0)
{
H = 0xFFFF;
L = 0;
C = (ushort)qtm.READ_BITS_MSB(16);
qtm.HeaderRead = 1;
C = (ushort)READ_BITS_MSB(16);
HeaderRead = 1;
}
// Decode more, up to the number of bytes needed, the frame boundary,
// or the window boundary, whichever comes first
frame_end = (uint)(window_posn + (out_bytes - (qtm.OutputEnd - qtm.OutputPointer)));
frame_end = (uint)(window_posn + (out_bytes - (OutputEnd - OutputPointer)));
if ((window_posn + frame_todo) < frame_end)
frame_end = window_posn + frame_todo;
if (frame_end > qtm.WindowSize)
frame_end = qtm.WindowSize;
if (frame_end > WindowSize)
frame_end = WindowSize;
while (window_posn < frame_end)
{
selector = qtm.GET_SYMBOL(qtm.Model7, ref H, ref L, ref C);
selector = GET_SYMBOL(Model7, ref H, ref L, ref C);
if (selector < 4)
{
// Literal byte
@@ -193,24 +189,24 @@ namespace LibMSPackSharp.Compression
switch (selector)
{
case 0:
mdl = qtm.Model0;
mdl = Model0;
break;
case 1:
mdl = qtm.Model1;
mdl = Model1;
break;
case 2:
mdl = qtm.Model2;
mdl = Model2;
break;
case 3:
default:
mdl = qtm.Model3;
mdl = Model3;
break;
}
sym = qtm.GET_SYMBOL(mdl, ref H, ref L, ref C);
sym = GET_SYMBOL(mdl, ref H, ref L, ref C);
window[window_posn++] = (byte)sym;
frame_todo--;
}
@@ -221,35 +217,35 @@ namespace LibMSPackSharp.Compression
{
// Selector 4 = fixed length match (3 bytes)
case 4:
sym = qtm.GET_SYMBOL(qtm.Model4, ref H, ref L, ref C);
extra = (int)qtm.READ_MANY_BITS_MSB(QTMExtraBits[sym]);
sym = GET_SYMBOL(Model4, ref H, ref L, ref C);
extra = (int)READ_MANY_BITS_MSB(QTMExtraBits[sym]);
match_offset = (uint)(QTMPositionBase[sym] + extra + 1);
match_length = 3;
break;
// Selector 5 = fixed length match (4 bytes)
case 5:
sym = qtm.GET_SYMBOL(qtm.Model5, ref H, ref L, ref C);
extra = (int)qtm.READ_MANY_BITS_MSB(QTMExtraBits[sym]);
sym = GET_SYMBOL(Model5, ref H, ref L, ref C);
extra = (int)READ_MANY_BITS_MSB(QTMExtraBits[sym]);
match_offset = (uint)(QTMPositionBase[sym] + extra + 1);
match_length = 4;
break;
// Selector 6 = variable length match
case 6:
sym = qtm.GET_SYMBOL(qtm.Model6Len, ref H, ref L, ref C);
extra = (int)qtm.READ_MANY_BITS_MSB(QTMLengthExtra[sym]);
sym = GET_SYMBOL(Model6Len, ref H, ref L, ref C);
extra = (int)READ_MANY_BITS_MSB(QTMLengthExtra[sym]);
match_length = QTMLengthBase[sym] + extra + 5;
sym = qtm.GET_SYMBOL(qtm.Model6, ref H, ref L, ref C);
extra = (int)qtm.READ_MANY_BITS_MSB(QTMExtraBits[sym]);
sym = GET_SYMBOL(Model6, ref H, ref L, ref C);
extra = (int)READ_MANY_BITS_MSB(QTMExtraBits[sym]);
match_offset = (uint)(QTMPositionBase[sym] + extra + 1);
break;
default:
// Should be impossible, model7 can only return 0-6
Console.WriteLine($"Got {selector} from selector");
return qtm.Error = Error.MSPACK_ERR_DECRUNCH;
return Error = Error.MSPACK_ERR_DECRUNCH;
}
rundest = (int)window_posn;
@@ -258,19 +254,19 @@ namespace LibMSPackSharp.Compression
// Does match destination wrap the window? This situation is possible
// where the window size is less than the 32k frame size, but matches
// must not go beyond a frame boundary
if ((window_posn + match_length) > qtm.WindowSize)
if ((window_posn + match_length) > WindowSize)
{
// Copy first part of match, before window end
i = (int)(qtm.WindowSize - window_posn);
i = (int)(WindowSize - window_posn);
j = (int)(window_posn - match_offset);
while (i-- != 0)
{
window[rundest++] = window[j++ & (qtm.WindowSize - 1)];
window[rundest++] = window[j++ & (WindowSize - 1)];
}
// Flush currently stored data
i = (int)(qtm.WindowSize - qtm.OutputPointer);
i = (int)(WindowSize - OutputPointer);
// This should not happen, but if it does then this code
// can't handle the situation (can't flush up to the end of
@@ -279,25 +275,25 @@ namespace LibMSPackSharp.Compression
if (i > out_bytes)
{
Console.WriteLine($"During window-wrap match; {i} bytes to flush but only need {out_bytes}");
return qtm.Error = Error.MSPACK_ERR_DECRUNCH;
return Error = Error.MSPACK_ERR_DECRUNCH;
}
if (qtm.System.Write(qtm.OutputFileHandle, window, qtm.OutputPointer, i) != i)
return qtm.Error = Error.MSPACK_ERR_WRITE;
if (System.Write(OutputFileHandle, window, OutputPointer, i) != i)
return Error = Error.MSPACK_ERR_WRITE;
out_bytes -= i;
qtm.OutputPointer = 0;
qtm.OutputEnd = 0;
OutputPointer = 0;
OutputEnd = 0;
// Copy second part of match, after window wrap
rundest = 0;
i = (int)(match_length - (qtm.WindowSize - window_posn));
i = (int)(match_length - (WindowSize - window_posn));
while (i-- != 0)
{
window[rundest++] = window[j++ & (qtm.WindowSize - 1)];
window[rundest++] = window[j++ & (WindowSize - 1)];
}
window_posn = (uint)(window_posn + match_length - qtm.WindowSize);
window_posn = (uint)(window_posn + match_length - WindowSize);
break; // Because "window_posn < frame_end" has now failed
}
@@ -311,13 +307,13 @@ namespace LibMSPackSharp.Compression
{
// j = length from match offset to end of window
j = (int)(match_offset - window_posn);
if (j > (int)qtm.WindowSize)
if (j > (int)WindowSize)
{
Console.WriteLine("Match offset beyond window boundaries");
return qtm.Error = Error.MSPACK_ERR_DECRUNCH;
return Error = Error.MSPACK_ERR_DECRUNCH;
}
runsrc = (int)(qtm.WindowSize - j);
runsrc = (int)(WindowSize - j);
if (j < i)
{
// If match goes over the window edge, do two copy runs
@@ -349,52 +345,52 @@ namespace LibMSPackSharp.Compression
}
}
qtm.OutputEnd = (int)window_posn;
OutputEnd = (int)window_posn;
// If we subtracted too much from frame_todo, it will
// wrap around past zero and go above its max value
if (frame_todo > QTM_FRAME_SIZE)
{
Console.WriteLine("Overshot frame alignment");
return qtm.Error = Error.MSPACK_ERR_DECRUNCH;
return Error = Error.MSPACK_ERR_DECRUNCH;
}
// Another frame completed?
if (frame_todo == 0)
{
// Re-align input
if ((qtm.BitsLeft & 7) != 0)
qtm.REMOVE_BITS_MSB(qtm.BitsLeft & 7);
if ((BitsLeft & 7) != 0)
REMOVE_BITS_MSB(BitsLeft & 7);
// Special Quantum hack -- cabd.c injects a 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.
do
{
i = (int)qtm.READ_BITS_MSB(8);
i = (int)READ_BITS_MSB(8);
} while (i != 0xFF);
qtm.HeaderRead = 0;
HeaderRead = 0;
frame_todo = QTM_FRAME_SIZE;
}
// Window wrap?
if (window_posn == qtm.WindowSize)
if (window_posn == WindowSize)
{
// Flush all currently stored data
i = (qtm.OutputEnd - qtm.OutputPointer);
i = (OutputEnd - OutputPointer);
// Break out if we have more than enough to finish this request
if (i >= out_bytes)
break;
if (qtm.System.Write(qtm.OutputFileHandle, window, qtm.OutputPointer, i) != i)
return qtm.Error = Error.MSPACK_ERR_WRITE;
if (System.Write(OutputFileHandle, window, OutputPointer, i) != i)
return Error = Error.MSPACK_ERR_WRITE;
out_bytes -= i;
qtm.OutputPointer = 0;
qtm.OutputEnd = 0;
OutputPointer = 0;
OutputEnd = 0;
window_posn = 0;
}
@@ -404,18 +400,18 @@ namespace LibMSPackSharp.Compression
{
i = (int)out_bytes;
if (qtm.System.Write(qtm.OutputFileHandle, window, qtm.OutputPointer, i) != i)
return qtm.Error = Error.MSPACK_ERR_WRITE;
if (System.Write(OutputFileHandle, window, OutputPointer, i) != i)
return Error = Error.MSPACK_ERR_WRITE;
qtm.OutputPointer += i;
OutputPointer += i;
}
// Store local state
qtm.WindowPosition = window_posn;
qtm.FrameTODO = frame_todo;
qtm.High = H;
qtm.Low = L;
qtm.Current = C;
WindowPosition = window_posn;
FrameTODO = frame_todo;
High = H;
Low = L;
Current = C;
return Error.MSPACK_ERR_OK;
}

View File

@@ -167,7 +167,7 @@ namespace LibMSPackSharp.OAB
return ret;
}
ret = LZX.Decompress(lzx, blk_dsize);
ret = lzx.Decompress(blk_dsize);
if (ret != Error.MSPACK_ERR_OK)
{
System.Close(outfh);
@@ -357,7 +357,7 @@ namespace LibMSPackSharp.OAB
return ret;
}
ret = LZX.Decompress(lzx, blk_dsize);
ret = lzx.Decompress(blk_dsize);
if (ret != Error.MSPACK_ERR_OK)
{
System.Close(outfh);