mirror of
https://github.com/SabreTools/BinaryObjectScanner.git
synced 2026-04-27 08:40:35 +00:00
Less static methods
This commit is contained in:
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
46
BurnOutSharp/External/libmspack/Compression/None.Decompress.cs
vendored
Normal file
46
BurnOutSharp/External/libmspack/Compression/None.Decompress.cs
vendored
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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; }
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user