Example #1
0
        private static void BlockDecompress(Stream stream, byte[] outData)
        {
            while (stream.Position < stream.Length)
            {
                var header = BinaryHelpers.ReadStruct <CIPHeader>(stream);

                if (header.Magic != 0x55441122)
                {
                    throw new InvalidDataException($"Invalid magic! Expected 0x55441122, got 0x{header.Magic:X8}");
                }

                var data         = new byte[header.CSize - 24];
                var decompressed = new byte[header.USize];

                if (stream.Read(data, 0, data.Length) != data.Length)
                {
                    throw new InvalidDataException($"Failed to read {data.Length} bytes from stream");
                }

                Compression.Decompress(data, decompressed);

                Array.ConstrainedCopy(
                    decompressed,
                    0,
                    outData,
                    header.UPos,
                    decompressed.Length);
            }
        }
Example #2
0
        private static void WriteBlocksInternal(List <CompressedBlock> blocksSorted, BinaryWriter bw)
        {
            foreach (var compressedBlock in blocksSorted)
            {
                var cbh = new CIPHeader();
                cbh.Magic = 0x55441122;
                cbh.CPos  = compressedBlock.CPos;
                cbh.USize = compressedBlock.DataRaw.Length;
                cbh.CSize = 24 + compressedBlock.DataComp.Length;
                cbh.UPos  = compressedBlock.UPos;

                BinaryHelpers.WriteStruct(bw, cbh);
                bw.Write(compressedBlock.DataComp);
            }
        }
Example #3
0
        /// <summary>
        /// Reads a compressed-in-place file. This involves reading a header and then
        /// proceeding to a shared routine for decompression.
        /// </summary>
        /// <param name="stream"></param>
        /// <returns></returns>
        public static byte[] ReadBlockFile(Stream stream)
        {
            var br         = new BinaryReader(stream);
            var fileHeader = BinaryHelpers.ReadStruct <CIPFileHeader>(br);

            if (fileHeader.Magic != 0x66113388)
            {
                throw new InvalidDataException("Invalid header");
            }

            var data = new byte[fileHeader.USize];

            BlockDecompress(stream, data);

            return(data);
        }
Example #4
0
        /// <summary>
        /// Writes a compressed-in-place file. Compresses the input data as blocks,
        /// then writes a header followed by the blocks.
        /// </summary>
        /// <param name="stream"></param>
        /// <param name="data"></param>
        /// <param name="blockSize"></param>
        public static void WriteBlockFile(Stream stream, IEnumerable <byte> data, int blockSize = 32768)
        {
            if ((blockSize & (blockSize - 1)) != 0)
            {
                throw new ArgumentException("blockSize must be a power of two!");
            }

            var blocksSorted = BlockCompress(data, blockSize);

            using (var bw = new BinaryWriter(stream))
            {
                var header = new CIPFileHeader();
                header.Magic   = 0x66113388;
                header.CSize   = blocksSorted.Sum(b => b.DataComp.Length + 24);
                header.USize   = blocksSorted.Sum(b => b.DataRaw.Length);
                header.Unknown = 0;

                BinaryHelpers.WriteStruct(bw, header);

                WriteBlocksInternal(blocksSorted, bw);
            }
        }