예제 #1
0
        /// <summary>
        /// Reads data from a file at the specified offset, of specified size into a stream and returns the stream. If no stream is specified, a new memory stream is created.
        /// </summary>
        /// <param name="filePath"></param>
        /// <param name="offset"></param>
        /// <param name="size"></param>
        /// <returns></returns>
        public static Stream ReadExternalData(string filePath, long offset, int size, Stream outStream = null)
        {
            if (!File.Exists(filePath))
            {
                return(null);
            }

            using Stream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read);
            if (offset + size > fs.Length)
            {
                return(null); //invalid pointer, outside bounds
            }
            outStream ??= new MemoryStream();
            fs.Seek(offset, SeekOrigin.Begin);
            var startPos = outStream.Position;

            fs.CopyToEx(outStream, size);
            outStream.Position = startPos;
            return(outStream);
        }
예제 #2
0
        public MemoryStream DecompressEntry(int index)
        {
            MemoryStream    result = MixinHandler.MixinMemoryStreamManager.GetStream();
            FileEntryStruct e      = Files[index];
            uint            count  = 0;

            byte[]     inputBlock;
            byte[]     outputBlock = new byte[Header.MaxBlockSize];
            long       left        = e.RealUncompressedSize;
            FileStream fs          = new FileStream(FileName, FileMode.Open, FileAccess.Read);

            fs.Seek(e.BlockOffsets[0], SeekOrigin.Begin);
            //byte[] buff;
            if (e.BlockSizeIndex == 0xFFFFFFFF)
            {
                fs.CopyToEx(result, (int)e.RealUncompressedSize);
                //buff = new byte[e.RealUncompressedSize];
                //fs.Read(buff, 0, buff.Length);
                //result.Write(buff, 0, buff.Length);
            }
            else
            {
                while (left > 0)
                {
                    uint compressedBlockSize = e.BlockSizes[count];
                    if (compressedBlockSize == 0)
                    {
                        compressedBlockSize = Header.MaxBlockSize;
                    }
                    if (compressedBlockSize == Header.MaxBlockSize || compressedBlockSize == left)
                    {
                        fs.CopyToEx(result, (int)compressedBlockSize);

                        //buff = new byte[compressedBlockSize];
                        //fs.Read(buff, 0, buff.Length);
                        //result.Write(buff, 0, buff.Length);
                        left -= compressedBlockSize;
                    }
                    else
                    {
                        var uncompressedBlockSize = (uint)Math.Min(left, Header.MaxBlockSize);
                        if (compressedBlockSize < 5)
                        {
                            throw new Exception("SFAR compressed block size smaller than 5 bytes");
                        }
                        inputBlock = new byte[compressedBlockSize];
                        fs.Read(inputBlock, 0, (int)compressedBlockSize);
                        uint actualUncompressedBlockSize = uncompressedBlockSize;
                        uint actualCompressedBlockSize   = compressedBlockSize;
                        outputBlock = SevenZipHelper.LZMA.Decompress(inputBlock, actualUncompressedBlockSize);
                        if (outputBlock.Length != actualUncompressedBlockSize)
                        {
                            throw new Exception("SFAR decompression error");
                        }
                        result.Write(outputBlock, 0, (int)actualUncompressedBlockSize);
                        left -= uncompressedBlockSize;
                    }
                    count++;
                }
            }
            fs.Close();
            result.Position = 0;
            return(result);
        }