diff --git a/libmspack/CAB/CABSystem.cs b/libmspack/CAB/CABSystem.cs index 5af446b..81d9b30 100644 --- a/libmspack/CAB/CABSystem.cs +++ b/libmspack/CAB/CABSystem.cs @@ -1,3 +1,4 @@ +using static SabreTools.Compression.libmspack.macros; using static SabreTools.Compression.libmspack.CAB.Constants; namespace SabreTools.Compression.libmspack.CAB @@ -103,17 +104,17 @@ namespace SabreTools.Compression.libmspack.CAB /// private static MSPACK_ERR ReadBlock(mspack_system sys, mscabd_decompress_state d, ref int @out, int ignore_cksum, int ignore_blocksize) { - byte[] hdr = new byte[cfdata_SIZEOF]; + FixedArray hdr = new FixedArray(cfdata_SIZEOF); uint cksum; int len, full_len; // Reset the input block pointer and end of block pointer - d.i_ptr = d.i_end = &d.input[0]; + d.i_ptr = d.i_end = (byte*)d.input.Pointer; do { // Read the block header - if (sys.read(d.infh, &hdr[0], cfdata_SIZEOF) != cfdata_SIZEOF) + if (sys.read(d.infh, (byte*)hdr.Pointer, cfdata_SIZEOF) != cfdata_SIZEOF) { return MSPACK_ERR.MSPACK_ERR_READ; } @@ -126,7 +127,7 @@ namespace SabreTools.Compression.libmspack.CAB } // Blocks must not be over CAB_INPUTMAX in size - len = System.BitConverter.ToUInt16(hdr, cfdata_CompressedSize); + len = EndGetI16(hdr, cfdata_CompressedSize); full_len = (int)(d.i_end - d.i_ptr + len); // Include cab-spanning blocks */ if (full_len > CAB_INPUTMAX) { @@ -139,7 +140,7 @@ namespace SabreTools.Compression.libmspack.CAB } // Blocks must not expand to more than CAB_BLOCKMAX - if (System.BitConverter.ToUInt16(hdr, cfdata_UncompressedSize) > CAB_BLOCKMAX) + if (EndGetI16(hdr, cfdata_UncompressedSize) > CAB_BLOCKMAX) { System.Console.Error.WriteLine("block size > CAB_BLOCKMAX"); if (ignore_blocksize == 0) return MSPACK_ERR.MSPACK_ERR_DATAFORMAT; @@ -152,10 +153,10 @@ namespace SabreTools.Compression.libmspack.CAB } // Perform checksum test on the block (if one is stored) - if ((cksum = System.BitConverter.ToUInt32(hdr, cfdata_CheckSum)) != 0) + if ((cksum = EndGetI32(hdr, cfdata_CheckSum)) != 0) { uint sum2 = Checksum(d.i_end, (uint)len, 0); - if (Checksum(&hdr[4], 4, sum2) != cksum) + if (Checksum(hdr, 4, 4, sum2) != cksum) { if (ignore_cksum == 0) return MSPACK_ERR.MSPACK_ERR_CHECKSUM; sys.message(d.infh, "WARNING; bad block checksum found"); @@ -171,7 +172,7 @@ namespace SabreTools.Compression.libmspack.CAB // reading needs to be done. // EXIT POINT OF LOOP -- uncompressed size != 0 - if ((@out = System.BitConverter.ToInt16(hdr, cfdata_UncompressedSize)) != 0) + if ((@out = EndGetI16(hdr, cfdata_UncompressedSize)) != 0) { return MSPACK_ERR.MSPACK_ERR_OK; } @@ -207,20 +208,20 @@ namespace SabreTools.Compression.libmspack.CAB return MSPACK_ERR.MSPACK_ERR_OK; } - private static uint Checksum(byte* data, uint bytes, uint cksum) + private static uint Checksum(FixedArray data, int ptr, uint bytes, uint cksum) { uint len, ul = 0; - for (len = bytes >> 2; len-- > 0; data += 4) + for (len = bytes >> 2; len-- > 0; ptr += 4) { - cksum ^= System.BitConverter.ToInt32(data, 0); + cksum ^= EndGetI32(data, ptr); } switch (bytes & 3) { - case 3: ul |= (uint)(*data++ << 16); goto case 2; - case 2: ul |= (uint)(*data++ << 8); goto case 1; - case 1: ul |= *data; break; + case 3: ul |= (uint)(data[ptr++] << 16); goto case 2; + case 2: ul |= (uint)(data[ptr++] << 8); goto case 1; + case 1: ul |= data[ptr]; break; } cksum ^= ul; diff --git a/libmspack/CAB/Decompressor.cs b/libmspack/CAB/Decompressor.cs index 96aba8f..f96c1f9 100644 --- a/libmspack/CAB/Decompressor.cs +++ b/libmspack/CAB/Decompressor.cs @@ -1,4 +1,5 @@ using static SabreTools.Compression.libmspack.cab; +using static SabreTools.Compression.libmspack.macros; using static SabreTools.Compression.libmspack.CAB.Constants; namespace SabreTools.Compression.libmspack.CAB @@ -216,7 +217,7 @@ namespace SabreTools.Compression.libmspack.CAB MSPACK_ERR err; mscabd_folder fol, linkfol = null; mscabd_file file, linkfile = null; - byte[] buf = new byte[64]; + FixedArray buf = new FixedArray(64); // Initialise pointers cab.next = null; @@ -235,24 +236,24 @@ namespace SabreTools.Compression.libmspack.CAB } // Read in the CFHEADER - if (sys.read(fh, &buf[0], cfhead_SIZEOF) != cfhead_SIZEOF) + if (sys.read(fh, (byte*)buf.Pointer, cfhead_SIZEOF) != cfhead_SIZEOF) { return MSPACK_ERR.MSPACK_ERR_READ; } // Check for "MSCF" signature - if (System.BitConverter.ToInt32(buf, cfhead_Signature) != 0x4643534D) + if (EndGetI32(buf, cfhead_Signature) != 0x4643534D) { return MSPACK_ERR.MSPACK_ERR_SIGNATURE; } // Some basic header fields - cab.length = System.BitConverter.ToUInt32(buf, cfhead_CabinetSize); - cab.set_id = System.BitConverter.ToUInt16(buf, cfhead_SetID); - cab.set_index = System.BitConverter.ToUInt16(buf, cfhead_CabinetIndex); + cab.length = EndGetI32(buf, cfhead_CabinetSize); + cab.set_id = EndGetI16(buf, cfhead_SetID); + cab.set_index = EndGetI16(buf, cfhead_CabinetIndex); // Get the number of folders - num_folders = System.BitConverter.ToInt16(buf, cfhead_NumFolders); + num_folders = EndGetI16(buf, cfhead_NumFolders); if (num_folders == 0) { if (quiet == 0) sys.message(fh, "No folders in cabinet."); @@ -260,7 +261,7 @@ namespace SabreTools.Compression.libmspack.CAB } // Get the number of files - num_files = System.BitConverter.ToInt16(buf, cfhead_NumFiles); + num_files = EndGetI16(buf, cfhead_NumFiles); if (num_files == 0) { if (quiet == 0) sys.message(fh, "no files in cabinet."); @@ -274,15 +275,15 @@ namespace SabreTools.Compression.libmspack.CAB } // Read the reserved-sizes part of header, if present - cab.flags = (MSCAB_HDR)System.BitConverter.ToInt16(buf, cfhead_Flags); + cab.flags = (MSCAB_HDR)EndGetI16(buf, cfhead_Flags); if (cab.flags.HasFlag(MSCAB_HDR.MSCAB_HDR_RESV)) { - if (sys.read(fh, &buf[0], cfheadext_SIZEOF) != cfheadext_SIZEOF) + if (sys.read(fh, (byte*)buf.Pointer, cfheadext_SIZEOF) != cfheadext_SIZEOF) { return MSPACK_ERR.MSPACK_ERR_READ; } - cab.header_resv = System.BitConverter.ToUInt16(buf, cfheadext_HeaderReserved); + cab.header_resv = EndGetI16(buf, cfheadext_HeaderReserved); folder_resv = buf[cfheadext_FolderReserved]; cab.block_resv = buf[cfheadext_DataReserved]; @@ -328,7 +329,7 @@ namespace SabreTools.Compression.libmspack.CAB // Read folders for (i = 0; i < num_folders; i++) { - if (sys.read(fh, &buf[0], cffold_SIZEOF) != cffold_SIZEOF) + if (sys.read(fh, (byte*)buf.Pointer, cffold_SIZEOF) != cffold_SIZEOF) { return MSPACK_ERR.MSPACK_ERR_READ; } @@ -343,11 +344,11 @@ namespace SabreTools.Compression.libmspack.CAB fol = new mscabd_folder(); fol.next = null; - fol.comp_type = (MSCAB_COMP)System.BitConverter.ToInt16(buf, cffold_CompType); - fol.num_blocks = (uint)System.BitConverter.ToInt16(buf, cffold_NumBlocks); + fol.comp_type = (MSCAB_COMP)EndGetI16(buf, cffold_CompType); + fol.num_blocks = (uint)EndGetI16(buf, cffold_NumBlocks); fol.data.next = null; fol.data.cab = cab; - fol.data.offset = offset + (long)((uint)System.BitConverter.ToInt32(buf, cffold_DataOffset)); + fol.data.offset = offset + (long)((uint)EndGetI32(buf, cffold_DataOffset)); fol.merge_prev = null; fol.merge_next = null; @@ -360,7 +361,7 @@ namespace SabreTools.Compression.libmspack.CAB // Read files for (i = 0; i < num_files; i++) { - if (sys.read(fh, &buf[0], cffile_SIZEOF) != cffile_SIZEOF) + if (sys.read(fh, (byte*)buf.Pointer, cffile_SIZEOF) != cffile_SIZEOF) { return MSPACK_ERR.MSPACK_ERR_READ; } @@ -368,12 +369,12 @@ namespace SabreTools.Compression.libmspack.CAB file = new mscabd_file(); file.next = null; - file.length = System.BitConverter.ToUInt32(buf, cffile_UncompressedSize); - file.attribs = (MSCAB_ATTRIB)System.BitConverter.ToInt16(buf, cffile_Attribs); - file.offset = System.BitConverter.ToUInt32(buf, cffile_FolderOffset); + file.length = EndGetI32(buf, cffile_UncompressedSize); + file.attribs = (MSCAB_ATTRIB)EndGetI16(buf, cffile_Attribs); + file.offset = EndGetI32(buf, cffile_FolderOffset); // Set folder pointer - fidx = System.BitConverter.ToInt16(buf, cffile_FolderIndex); + fidx = EndGetI16(buf, cffile_FolderIndex); if (fidx < cffileCONTINUED_FROM_PREV) { /* normal folder index; count up to the correct folder */ @@ -416,13 +417,13 @@ namespace SabreTools.Compression.libmspack.CAB } // Get time - x = System.BitConverter.ToInt16(buf, cffile_Time); + x = EndGetI16(buf, cffile_Time); file.time_h = (char)(x >> 11); file.time_m = (char)((x >> 5) & 0x3F); file.time_s = (char)((x << 1) & 0x3E); // Get date - x = System.BitConverter.ToInt16(buf, cffile_Date); + x = EndGetI16(buf, cffile_Date); file.date_d = (char)(x & 0x1F); file.date_m = (char)((x >> 5) & 0xF); file.date_y = (x >> 9) + 1980; @@ -465,7 +466,7 @@ namespace SabreTools.Compression.libmspack.CAB int len, i, ok; // Read up to 256 bytes */ - if ((len = sys.read(fh, &buf[0], 256)) <= 0) + if ((len = sys.read(fh, (byte*)buf.Pointer, 256)) <= 0) { error = MSPACK_ERR.MSPACK_ERR_READ; return null; @@ -492,7 +493,7 @@ namespace SabreTools.Compression.libmspack.CAB } char[] strchr = new char[len]; - sys.copy(&buf[0], &strchr[0], len); + sys.copy((byte*)buf.Pointer, &strchr[0], len); str = new string(strchr); error = MSPACK_ERR.MSPACK_ERR_OK; return str; @@ -617,13 +618,13 @@ namespace SabreTools.Compression.libmspack.CAB } // FAQ avoidance strategy - if ((offset == 0) && (System.BitConverter.ToInt32(buf, 0) == 0x28635349)) + if ((offset == 0) && (EndGetI32(buf, 0) == 0x28635349)) { sys.message(fh, "WARNING; found InstallShield header. Use unshield (https://github.com/twogood/unshield) to unpack this file"); } // Read through the entire buffer. - for (p = &buf[0], pend = &buf[length]; p < pend;) + for (p = (byte*)buf.Pointer, pend = &buf[length]; p < pend;) { switch (state) { @@ -659,7 +660,7 @@ namespace SabreTools.Compression.libmspack.CAB foffset_u32 |= (uint)(*p++ << 24); // Now we have recieved 20 bytes of potential cab header. work out // the offset in the file of this potential cabinet */ - caboff = offset + (p - &buf[0]) - 20; + caboff = offset + (p - (byte*)buf.Pointer) - 20; // Should reading cabinet fail, restart search just after 'MSCF' offset = caboff + 4; diff --git a/libmspack/CAB/mscabd_decompress_state.cs b/libmspack/CAB/mscabd_decompress_state.cs index bfc1143..de01f6d 100644 --- a/libmspack/CAB/mscabd_decompress_state.cs +++ b/libmspack/CAB/mscabd_decompress_state.cs @@ -73,7 +73,7 @@ namespace SabreTools.Compression.libmspack /// /// One input block of data /// - public byte[] input { get; set; } = new byte[CAB_INPUTBUF]; + public FixedArray input { get; set; } = new FixedArray(CAB_INPUTBUF); /// /// Decompressor code diff --git a/libmspack/FixedArray.cs b/libmspack/FixedArray.cs index 522780e..052d622 100644 --- a/libmspack/FixedArray.cs +++ b/libmspack/FixedArray.cs @@ -30,5 +30,17 @@ namespace SabreTools.Compression.libmspack { Marshal.FreeHGlobal(Pointer); } + + /// + public bool SequenceEqual(T[] arr) + { + for (int i = 0; i < arr.Length; i++) + { + if (!this[i].Equals(arr[i])) + return false; + } + + return true; + } } } \ No newline at end of file diff --git a/libmspack/None/State.cs b/libmspack/None/State.cs index 5e86557..3d7f401 100644 --- a/libmspack/None/State.cs +++ b/libmspack/None/State.cs @@ -20,7 +20,7 @@ namespace SabreTools.Compression.libmspack.None this.InternalSystem = sys; this.Input = infh; this.Output = outfh; - this.Buffer = system.CreateArray(bufsize); + this.Buffer = (byte*)new FixedArray(bufsize).Pointer; this.BufferSize = bufsize; } diff --git a/libmspack/OAB/Decompressor.cs b/libmspack/OAB/Decompressor.cs index 8a54dfe..bff36d9 100644 --- a/libmspack/OAB/Decompressor.cs +++ b/libmspack/OAB/Decompressor.cs @@ -1,3 +1,4 @@ +using static SabreTools.Compression.libmspack.macros; using static SabreTools.Compression.libmspack.oab; namespace SabreTools.Compression.libmspack.OAB @@ -67,15 +68,15 @@ namespace SabreTools.Compression.libmspack.OAB goto outlbl; } - if (System.BitConverter.ToInt32(hdrbuf, oabhead_VersionHi) != 3 || - System.BitConverter.ToInt32(hdrbuf, oabhead_VersionLo) != 1) + if (EndGetI32(hdrbuf, oabhead_VersionHi) != 3 || + EndGetI32(hdrbuf, oabhead_VersionLo) != 1) { ret = MSPACK_ERR.MSPACK_ERR_SIGNATURE; goto outlbl; } - block_max = System.BitConverter.ToUInt32(hdrbuf, oabhead_BlockMax); - target_size = System.BitConverter.ToUInt32(hdrbuf, oabhead_TargetSize); + block_max = EndGetI32(hdrbuf, oabhead_BlockMax); + target_size = EndGetI32(hdrbuf, oabhead_TargetSize); outfh = sys.open(output, MSPACK_SYS_OPEN.MSPACK_SYS_OPEN_WRITE); if (outfh == null) @@ -110,10 +111,10 @@ namespace SabreTools.Compression.libmspack.OAB ret = MSPACK_ERR.MSPACK_ERR_READ; goto outlbl; } - blk_flags = System.BitConverter.ToInt32(buf, oabblk_Flags); - blk_csize = System.BitConverter.ToInt32(buf, oabblk_CompSize); - blk_dsize = System.BitConverter.ToInt32(buf, oabblk_UncompSize); - blk_crc = System.BitConverter.ToInt32(buf, oabblk_CRC); + blk_flags = EndGetI32(buf, oabblk_Flags); + blk_csize = EndGetI32(buf, oabblk_CompSize); + blk_dsize = EndGetI32(buf, oabblk_UncompSize); + blk_crc = EndGetI32(buf, oabblk_CRC); if (blk_dsize > block_max || blk_dsize > target_size || blk_flags > 1) { @@ -224,22 +225,22 @@ namespace SabreTools.Compression.libmspack.OAB goto outlbl; } - byte[] hdrbuf = new byte[patchhead_SIZEOF]; - if (sys.read(infh, &hdrbuf[0], patchhead_SIZEOF) != patchhead_SIZEOF) + FixedArray hdrbuf = new FixedArray(patchhead_SIZEOF); + if (sys.read(infh, (byte*)hdrbuf.Pointer, patchhead_SIZEOF) != patchhead_SIZEOF) { ret = MSPACK_ERR.MSPACK_ERR_READ; goto outlbl; } - if (System.BitConverter.ToInt32(hdrbuf, patchhead_VersionHi) != 3 || - System.BitConverter.ToInt32(hdrbuf, patchhead_VersionLo) != 2) + if (EndGetI32(hdrbuf, patchhead_VersionHi) != 3 || + EndGetI32(hdrbuf, patchhead_VersionLo) != 2) { ret = MSPACK_ERR.MSPACK_ERR_SIGNATURE; goto outlbl; } - uint block_max = System.BitConverter.ToUInt32(hdrbuf, patchhead_BlockMax); - uint target_size = System.BitConverter.ToUInt32(hdrbuf, patchhead_TargetSize); + uint block_max = EndGetI32(hdrbuf, patchhead_BlockMax); + uint target_size = EndGetI32(hdrbuf, patchhead_TargetSize); // We use it for reading block headers too if (block_max < patchblk_SIZEOF) @@ -284,10 +285,10 @@ namespace SabreTools.Compression.libmspack.OAB goto outlbl; } - uint blk_csize = System.BitConverter.ToInt32(buf, patchblk_PatchSize); - uint blk_dsize = System.BitConverter.ToInt32(buf, patchblk_TargetSize); - uint blk_ssize = System.BitConverter.ToInt32(buf, patchblk_SourceSize); - uint blk_crc = System.BitConverter.ToInt32(buf, patchblk_CRC); + uint blk_csize = EndGetI32(buf, patchblk_PatchSize); + uint blk_dsize = EndGetI32(buf, patchblk_TargetSize); + uint blk_ssize = EndGetI32(buf, patchblk_SourceSize); + uint blk_crc = EndGetI32(buf, patchblk_CRC); if (blk_dsize > block_max || blk_dsize > target_size || blk_ssize > block_max) diff --git a/libmspack/SZDD/Decompressor.cs b/libmspack/SZDD/Decompressor.cs index 23e6976..6ff5f09 100644 --- a/libmspack/SZDD/Decompressor.cs +++ b/libmspack/SZDD/Decompressor.cs @@ -1,4 +1,5 @@ using System.Linq; +using static SabreTools.Compression.libmspack.macros; using static SabreTools.Compression.libmspack.SZDD.Constants; namespace SabreTools.Compression.libmspack.SZDD @@ -108,10 +109,10 @@ namespace SabreTools.Compression.libmspack.SZDD /// private static MSPACK_ERR ReadHeaders(mspack_system sys, mspack_file fh, msszddd_header hdr) { - byte[] buf = new byte[8]; + FixedArray buf = new FixedArray(8); // Read and check signature - if (sys.read(fh, buffer: &buf[0], 8) != 8) return MSPACK_ERR.MSPACK_ERR_READ; + if (sys.read(fh, (byte*)buf.Pointer, 8) != 8) return MSPACK_ERR.MSPACK_ERR_READ; if (buf.SequenceEqual(szdd_signature_expand)) { @@ -119,18 +120,18 @@ namespace SabreTools.Compression.libmspack.SZDD hdr.format = MSSZDD_FMT.MSSZDD_FMT_NORMAL; // Read the rest of the header - if (sys.read(fh, &buf[0], 6) != 6) return MSPACK_ERR.MSPACK_ERR_READ; + if (sys.read(fh, (byte*)buf.Pointer, 6) != 6) return MSPACK_ERR.MSPACK_ERR_READ; if (buf[0] != 0x41) return MSPACK_ERR.MSPACK_ERR_DATAFORMAT; hdr.missing_char = (char)buf[1]; - hdr.length = System.BitConverter.ToInt32(buf, 2); + hdr.length = EndGetI32(buf, 2); } else if (buf.SequenceEqual(szdd_signature_qbasic)) { // Special QBasic SZDD hdr.format = MSSZDD_FMT.MSSZDD_FMT_QBASIC; - if (sys.read(fh, &buf[0], 4) != 4) return MSPACK_ERR.MSPACK_ERR_READ; + if (sys.read(fh, (byte*)buf.Pointer, 4) != 4) return MSPACK_ERR.MSPACK_ERR_READ; hdr.missing_char = '\0'; - hdr.length = System.BitConverter.ToInt32(buf, 0); + hdr.length = EndGetI32(buf, 0); } else { diff --git a/libmspack/macros.cs b/libmspack/macros.cs new file mode 100644 index 0000000..311a76a --- /dev/null +++ b/libmspack/macros.cs @@ -0,0 +1,35 @@ +namespace SabreTools.Compression.libmspack +{ + public static class macros + { + private static uint __egi32(FixedArray a, int n) + { + return (uint)((a[n + 3] << 24) | (a[n + 2] << 16) | (a[n + 1] << 8) | (a[n + 0])); + } + + public static ulong EndGetI64(FixedArray a, int n) + { + return (__egi32(a, n + 4) << 32) | __egi32(a, n + 0); + } + + public static uint EndGetI32(FixedArray a, int n) + { + return __egi32(a, n + 0); + } + + public static ushort EndGetI16(FixedArray a, int n) + { + return (ushort)((a[n + 1] << 8) | a[n + 0]); + } + + public static uint EndGetM32(FixedArray a, int n) + { + return (uint)((a[n + 0] << 24) | (a[n + 1] << 16) | (a[n + 2] << 8) | (a[n + 3])); + } + + public static ushort EndGetM16(FixedArray a, int n) + { + return (ushort)((a[n + 0] << 8) | a[n + 1]); + } + } +} \ No newline at end of file diff --git a/libmspack/mspack_default_system.cs b/libmspack/mspack_default_system.cs index d33d37a..8d25cb2 100644 --- a/libmspack/mspack_default_system.cs +++ b/libmspack/mspack_default_system.cs @@ -120,7 +120,7 @@ namespace SabreTools.Compression.libmspack /// public override unsafe void* alloc(int bytes) { - return system.CreateArray(bytes); + return (void*)new FixedArray(bytes).Pointer; } /// diff --git a/libmspack/system.cs b/libmspack/system.cs index fe39040..e272f61 100644 --- a/libmspack/system.cs +++ b/libmspack/system.cs @@ -38,11 +38,5 @@ namespace SabreTools.Compression.libmspack return MSPACK_ERR.MSPACK_ERR_OK; } - - public static T* CreateArray(int length) - { - T[] buf = new T[length]; - return &buf[0]; - } } } \ No newline at end of file