/* This file is part of libmspack. * (C) 2003-2013 Stuart Caie. * * The LZX method was created by Jonathan Forbes and Tomi Poutanen, adapted * by Microsoft Corporation. * * libmspack is free software { get; set; } 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 { public class LZXDStream : CompressionStream { /// /// Number of bytes actually output /// public long Offset { get; set; } /// /// Overall decompressed length of stream /// public long Length { get; set; } /// /// Decoding window /// public byte[] Window { get; set; } /// /// Window size /// public uint WindowSize { get; set; } /// /// LZX DELTA reference data size /// public uint ReferenceDataSize { get; set; } /// /// Number of match_offset entries in table /// public uint NumOffsets { get; set; } /// /// Decompression offset within window /// public uint WindowPosition { get; set; } /// /// Current frame offset within in window /// public uint FramePosition { get; set; } /// /// The number of 32kb frames processed /// public uint Frame { get; set; } /// /// Which frame do we reset the compressor? /// public uint ResetInterval { get; set; } /// /// For the LRU offset system /// public uint R0 { get; set; } /// /// For the LRU offset system /// public uint R1 { get; set; } /// /// For the LRU offset system /// public uint R2 { get; set; } /// /// Uncompressed length of this LZX block /// public uint BlockLength { get; set; } /// /// Uncompressed bytes still left to decode /// public uint BlockRemaining { get; set; } /// /// Magic header value used for transform /// public int IntelFileSize { get; set; } /// /// Has intel E8 decoding started? /// public bool IntelStarted { get; set; } /// /// Type of the current block /// public LZXBlockType BlockType { get; set; } /// /// Have we started decoding at all yet? /// public byte HeaderRead { get; set; } /// /// Does stream follow LZX DELTA spec? /// public bool IsDelta { get; set; } #region Huffman code lengths public byte[] PRETREE_len { get; set; } = new byte[LZX.LZX_PRETREE_MAXSYMBOLS + LZX.LZX_LENTABLE_SAFETY]; public byte[] MAINTREE_len { get; set; } = new byte[LZX.LZX_MAINTREE_MAXSYMBOLS + LZX.LZX_LENTABLE_SAFETY]; public byte[] LENGTH_len { get; set; } = new byte[LZX.LZX_LENGTH_MAXSYMBOLS + LZX.LZX_LENTABLE_SAFETY]; public byte[] ALIGNED_len { get; set; } = new byte[LZX.LZX_ALIGNED_MAXSYMBOLS + LZX.LZX_LENTABLE_SAFETY]; #endregion #region Huffman decoding tables public ushort[] PRETREE_table { get; set; } = new ushort[(1 << LZX.LZX_PRETREE_TABLEBITS) + (LZX.LZX_PRETREE_MAXSYMBOLS * 2)]; public ushort[] MAINTREE_table { get; set; } = new ushort[(1 << LZX.LZX_MAINTREE_TABLEBITS) + (LZX.LZX_MAINTREE_MAXSYMBOLS * 2)]; public ushort[] LENGTH_table { get; set; } = new ushort[(1 << LZX.LZX_LENGTH_TABLEBITS) + (LZX.LZX_LENGTH_MAXSYMBOLS * 2)]; public ushort[] ALIGNED_table { get; set; } = new ushort[(1 << LZX.LZX_ALIGNED_TABLEBITS) + (LZX.LZX_ALIGNED_MAXSYMBOLS * 2)]; #endregion public byte LENGTH_empty { get; set; } // This is used purely for doing the intel E8 transform public byte[] e8_buf { get; set; } = new byte[LZX.LZX_FRAME_SIZE]; public override Error READ_BYTES(ref int i_ptr, ref int i_end, ref uint bitsLeft, ref uint bitBuffer) { Error error = READ_IF_NEEDED(ref i_ptr, ref i_end); if (error != Error.MSPACK_ERR_OK) return error; byte b0 = InputBuffer[i_ptr++]; error = READ_IF_NEEDED(ref i_ptr, ref i_end); if (error != Error.MSPACK_ERR_OK) return error; byte b1 = InputBuffer[i_ptr++]; INJECT_BITS((uint)((b1 << 8) | b0), 16, ref bitsLeft, ref bitBuffer); return Error.MSPACK_ERR_OK; } public override int HUFF_ERROR() => (int)(Error = Error.MSPACK_ERR_DECRUNCH); } }