diff --git a/libmspack/cab.cs b/libmspack/cab.cs
new file mode 100644
index 0000000..a71792f
--- /dev/null
+++ b/libmspack/cab.cs
@@ -0,0 +1,75 @@
+namespace SabreTools.Compression.libmspack
+{
+ public static class cab
+ {
+ /* structure offsets */
+ public const byte cfhead_Signature = 0x00;
+ public const byte cfhead_CabinetSize = 0x08;
+ public const byte cfhead_FileOffset = 0x10;
+ public const byte cfhead_MinorVersion = 0x18;
+ public const byte cfhead_MajorVersion = 0x19;
+ public const byte cfhead_NumFolders = 0x1A;
+ public const byte cfhead_NumFiles = 0x1C;
+ public const byte cfhead_Flags = 0x1E;
+ public const byte cfhead_SetID = 0x20;
+ public const byte cfhead_CabinetIndex = 0x22;
+ public const byte cfhead_SIZEOF = 0x24;
+ public const byte cfheadext_HeaderReserved = 0x00;
+ public const byte cfheadext_FolderReserved = 0x02;
+ public const byte cfheadext_DataReserved = 0x03;
+ public const byte cfheadext_SIZEOF = 0x04;
+ public const byte cffold_DataOffset = 0x00;
+ public const byte cffold_NumBlocks = 0x04;
+ public const byte cffold_CompType = 0x06;
+ public const byte cffold_SIZEOF = 0x08;
+ public const byte cffile_UncompressedSize = 0x00;
+ public const byte cffile_FolderOffset = 0x04;
+ public const byte cffile_FolderIndex = 0x08;
+ public const byte cffile_Date = 0x0A;
+ public const byte cffile_Time = 0x0C;
+ public const byte cffile_Attribs = 0x0E;
+ public const byte cffile_SIZEOF = 0x10;
+ public const byte cfdata_CheckSum = 0x00;
+ public const byte cfdata_CompressedSize = 0x04;
+ public const byte cfdata_UncompressedSize = 0x06;
+ public const byte cfdata_SIZEOF = 0x08;
+
+ /* flags */
+ public const ushort cffoldCOMPTYPE_MASK = 0x000f;
+ public const ushort cffoldCOMPTYPE_NONE = 0x0000;
+ public const ushort cffoldCOMPTYPE_MSZIP = 0x0001;
+ public const ushort cffoldCOMPTYPE_QUANTUM = 0x0002;
+ public const ushort cffoldCOMPTYPE_LZX = 0x0003;
+ public const ushort cfheadPREV_CABINET = 0x0001;
+ public const ushort cfheadNEXT_CABINET = 0x0002;
+ public const ushort cfheadRESERVE_PRESENT = 0x0004;
+ public const ushort cffileCONTINUED_FROM_PREV = 0xFFFD;
+ public const ushort cffileCONTINUED_TO_NEXT = 0xFFFE;
+ public const ushort cffileCONTINUED_PREV_AND_NEXT = 0xFFFF;
+
+ /* CAB data blocks are <= 32768 bytes in uncompressed form. Uncompressed
+ * blocks have zero growth. MSZIP guarantees that it won't grow above
+ * uncompressed size by more than 12 bytes. LZX guarantees it won't grow
+ * more than 6144 bytes. Quantum has no documentation, but the largest
+ * block seen in the wild is 337 bytes above uncompressed size.
+ */
+ public const int CAB_BLOCKMAX = 32768;
+ public const int CAB_INPUTMAX = CAB_BLOCKMAX + 6144;
+
+ /* input buffer needs to be CAB_INPUTMAX + 1 byte to allow for max-sized block
+ * plus 1 trailer byte added by cabd_sys_read_block() for Quantum alignment.
+ *
+ * When MSCABD_PARAM_SALVAGE is set, block size is not checked so can be
+ * up to 65535 bytes, so max input buffer size needed is 65535 + 1
+ */
+ public const int CAB_INPUTMAX_SALVAGE = 65535;
+ public const int CAB_INPUTBUF = CAB_INPUTMAX_SALVAGE + 1;
+
+ /* There are no more than 65535 data blocks per folder, so a folder cannot
+ * be more than 32768*65535 bytes in length. As files cannot span more than
+ * one folder, this is also their max offset, length and offset+length limit.
+ */
+ public const int CAB_FOLDERMAX = 65535;
+ public const int CAB_LENGTHMAX = CAB_BLOCKMAX * CAB_FOLDERMAX;
+ }
+}
\ No newline at end of file
diff --git a/libmspack/mscab_compressor.cs b/libmspack/mscab_compressor.cs
index 3b58868..f6429a6 100644
--- a/libmspack/mscab_compressor.cs
+++ b/libmspack/mscab_compressor.cs
@@ -6,5 +6,7 @@ namespace SabreTools.Compression.libmspack
public class mscab_compressor
{
public int dummy { get; set; }
+
+ public mspack_system system { get; set; }
}
}
\ No newline at end of file
diff --git a/libmspack/mscab_decompressor.cs b/libmspack/mscab_decompressor.cs
index 1e4462a..00d380e 100644
--- a/libmspack/mscab_decompressor.cs
+++ b/libmspack/mscab_decompressor.cs
@@ -9,6 +9,22 @@ namespace SabreTools.Compression.libmspack
///
public abstract class mscab_decompressor
{
+ public mscabd_decompress_state d { get; set; }
+
+ public mspack_system system { get; set; }
+
+ public int buf_size { get; set; }
+
+ public int searchbuf_size { get; set; }
+
+ public int fix_mszip { get; set; }
+
+ public int salvage { get; set; }
+
+ public MSPACK_ERR error { get; set; }
+
+ public MSPACK_ERR read_error { get; set; }
+
///
/// Opens a cabinet file and reads its contents.
///
diff --git a/libmspack/mscabd_cabinet.cs b/libmspack/mscabd_cabinet.cs
index 01954dc..5806e92 100644
--- a/libmspack/mscabd_cabinet.cs
+++ b/libmspack/mscabd_cabinet.cs
@@ -111,5 +111,15 @@ namespace SabreTools.Compression.libmspack
///
///
public MSCAB_HDR flags { get; set; }
+
+ ///
+ /// Offset to data blocks
+ ///
+ public long blocks_off { get; set; }
+
+ ///
+ /// Reserved space in data blocks
+ ///
+ public int block_resv { get; set; }
}
}
\ No newline at end of file
diff --git a/libmspack/mscabd_decompress_state.cs b/libmspack/mscabd_decompress_state.cs
new file mode 100644
index 0000000..39e27bf
--- /dev/null
+++ b/libmspack/mscabd_decompress_state.cs
@@ -0,0 +1,85 @@
+using static SabreTools.Compression.libmspack.cab;
+
+namespace SabreTools.Compression.libmspack
+{
+ public abstract unsafe class mscabd_decompress_state
+ {
+ ///
+ /// Current folder we're extracting from
+ ///
+ public mscabd_folder folder { get; set; }
+
+ ///
+ /// Current folder split we're in
+ ///
+ public mscabd_folder_data data { get; set; }
+
+ ///
+ /// Uncompressed offset within folder
+ ///
+ public uint offset { get; set; }
+
+ ///
+ /// Which block are we decompressing?
+ ///
+ public uint block { get; set; }
+
+ ///
+ /// Cumulative sum of block output sizes
+ ///
+ public long outlen { get; set; }
+
+ ///
+ /// Special I/O code for decompressor
+ ///
+ public mspack_system sys { get; set; }
+
+ ///
+ /// Type of compression used by folder
+ ///
+ public MSCAB_COMP comp_type { get; set; }
+
+ ///
+ /// Decompressor code
+ ///
+ ///
+ ///
+ ///
+ public abstract int decompress(void* data, long offset);
+
+ ///
+ /// Decompressor state
+ ///
+ public void* state { get; set; }
+
+ ///
+ /// Cabinet where input data comes from
+ ///
+ public mscabd_cabinet incab { get; set; }
+
+ ///
+ /// Input file handle
+ ///
+ public mspack_file infh { get; set; }
+
+ ///
+ /// Output file handle
+ ///
+ public mspack_file outfh { get; set; }
+
+ ///
+ /// Input data consumed
+ ///
+ public byte* i_ptr { get; set; }
+
+ ///
+ /// Input data end
+ ///
+ public byte* i_end { get; set; }
+
+ ///
+ /// One input block of data
+ ///
+ public byte[] input { get; set; } = new byte[CAB_INPUTBUF];
+ }
+}
\ No newline at end of file
diff --git a/libmspack/mscabd_folder.cs b/libmspack/mscabd_folder.cs
index 3ee9ac4..33ccdaf 100644
--- a/libmspack/mscabd_folder.cs
+++ b/libmspack/mscabd_folder.cs
@@ -34,5 +34,20 @@ namespace SabreTools.Compression.libmspack
/// one cabinet.
///
public uint num_blocks { get; set; }
+
+ ///
+ /// Where are the data blocks?
+ ///
+ public mscabd_folder_data data { get; set; }
+
+ ///
+ /// First file needing backwards merge
+ ///
+ public mscabd_file merge_prev { get; set; }
+
+ ///
+ /// First file needing forwards merge
+ ///
+ public mscabd_file merge_next { get; set; }
}
}
\ No newline at end of file
diff --git a/libmspack/mscabd_folder_data.cs b/libmspack/mscabd_folder_data.cs
new file mode 100644
index 0000000..91a2442
--- /dev/null
+++ b/libmspack/mscabd_folder_data.cs
@@ -0,0 +1,20 @@
+namespace SabreTools.Compression.libmspack
+{
+ ///
+ /// There is one of these for every cabinet a folder spans
+ ///
+ public class mscabd_folder_data
+ {
+ public mscabd_folder_data next { get; set; }
+
+ ///
+ /// Cabinet file of this folder span
+ ///
+ public mscabd_cabinet cab { get; set; }
+
+ ///
+ /// Cabinet offset of first datablock
+ ///
+ public long offset { get; set; }
+ }
+}
\ No newline at end of file