public void Deserialize(Stream input)
        {
            var magic = input.ReadValueU32(Endian.Little);
            if (magic != 0x53464152 && // SFAR
                magic.Swap() != 0x53464152)
            {
                throw new FormatException();
            }
            var endian = magic == 0x53464152 ? Endian.Little : Endian.Big;

            var version = input.ReadValueU32(endian);
            if (version != 0x00010000)
            {
                throw new FormatException();
            }

            var dataOffset = input.ReadValueU32(endian);
            var fileTableOffset = input.ReadValueU32(endian);
            var fileTableCount = input.ReadValueU32(endian);
            var blockSizeTableOffset = input.ReadValueU32(endian);
            this.MaximumBlockSize = input.ReadValueU32(endian);
            this.CompressionScheme = input
                .ReadValueEnum<SFXArchive.CompressionScheme>(endian);

            if (fileTableOffset != 0x20)
            {
                throw new FormatException();
            }

            if (this.MaximumBlockSize != 0x010000)
            {
                throw new FormatException();
            }

            /*
            if (this.CompressionScheme != SFXArchive.CompressionScheme.None &&
                this.CompressionScheme != SFXArchive.CompressionScheme.LZMA &&
                this.CompressionScheme != SFXArchive.CompressionScheme.LZX)
            {
                throw new FormatException();
            }
            */

            input.Seek(blockSizeTableOffset, SeekOrigin.Begin);

            var blockSizeTableSize = dataOffset - fileTableOffset;
            var blockSizeTableCount = blockSizeTableSize / 2;
            this.BlockSizes.Clear();
            for (uint i = 0; i < blockSizeTableCount; i++)
            {
                this.BlockSizes.Add(input.ReadValueU16(endian));
            }

            input.Seek(fileTableOffset, SeekOrigin.Begin);
            for (uint i = 0; i < fileTableCount; i++)
            {
// ReSharper disable UseObjectOrCollectionInitializer
                var entry = new SFXArchive.Entry();
// ReSharper restore UseObjectOrCollectionInitializer
                entry.NameHash = input.ReadFileNameHash();
                entry.BlockSizeIndex = input.ReadValueS32(endian);
                entry.UncompressedSize = input.ReadValueU32(endian);
                entry.UncompressedSize |= ((long)input.ReadValueU8()) << 32;
                entry.Offset = input.ReadValueU32(endian);
                entry.Offset |= ((long)input.ReadValueU8()) << 32;
                this.Entries.Add(entry);
            }
        }
Example #2
0
        public void Deserialize(Stream input)
        {
            var magic = input.ReadValueU32(Endian.Little);

            if (magic != 0x53464152 && // SFAR
                magic.Swap() != 0x53464152)
            {
                throw new FormatException();
            }
            var endian = magic == 0x53464152 ? Endian.Little : Endian.Big;

            var version = input.ReadValueU32(endian);

            if (version != 0x00010000)
            {
                throw new FormatException();
            }

            var  dataOffset      = input.ReadValueU32(endian);
            bool firstDataOffset = true;
            uint minDataOffset   = dataOffset;
            //Console.WriteLine("Data Offset: {0:X8}",dataOffset);
            var fileTableOffset = input.ReadValueU32(endian);
            //Console.WriteLine("File Table Offset: {0:X8}",fileTableOffset);
            var fileTableCount = input.ReadValueU32(endian);
            //Console.WriteLine("File Table Count: {0:X8}",fileTableCount);
            var blockSizeTableOffset = input.ReadValueU32(endian);

            //Console.WriteLine("Block Size Table Offset: {0:X8}",blockSizeTableOffset);
            this.MaximumBlockSize  = input.ReadValueU32(endian);
            this.CompressionScheme = input
                                     .ReadValueEnum <SFXArchive.CompressionScheme>(endian);

            if (fileTableOffset != 0x20)
            {
                throw new FormatException();
            }

            if (this.MaximumBlockSize != 0x010000)
            {
                throw new FormatException();
            }

            /*
             * if (this.CompressionScheme != SFXArchive.CompressionScheme.None &&
             *  this.CompressionScheme != SFXArchive.CompressionScheme.LZMA &&
             *  this.CompressionScheme != SFXArchive.CompressionScheme.LZX)
             * {
             *  throw new FormatException();
             * }
             */
            input.Seek(fileTableOffset, SeekOrigin.Begin);
            for (uint i = 0; i < fileTableCount; i++)
            {
// ReSharper disable UseObjectOrCollectionInitializer
                var entry = new SFXArchive.Entry();
                entry.entryOffset = input.Position;
// ReSharper restore UseObjectOrCollectionInitializer
                entry.nameHash = input.ReadFileNameHash();
                //Console.WriteLine("FileNameHash: {0}",entry.NameHash.ToString());
                entry.blockSizeIndex = input.ReadValueS32(endian);
                //Console.WriteLine("Begin position: {0:X8}",input.Position);
                entry.uncompressedSize  = input.ReadValueU32(endian);
                entry.uncompressedSize |= ((long)input.ReadValueU8()) << 32;
                //Console.WriteLine("  End position: {0:X8}",input.Position);
                entry.dataOffset  = input.ReadValueU32(endian);
                entry.dataOffset |= ((long)input.ReadValueU8()) << 32;
                if (firstDataOffset)
                {
                    minDataOffset   = (uint)entry.dataOffset;
                    firstDataOffset = false;
                }
                else
                {
                    if (minDataOffset > entry.dataOffset)
                    {
                        minDataOffset = (uint)entry.dataOffset;
                    }
                }
                //if(entry.NameHash.Equals (fileNameListNameHash))Console.WriteLine("Offset: {0:X10}, UncSize {1:X10}",entry.Offset,entry.UncompressedSize);
                this.Entries.Add(entry);
            }
            if (minDataOffset > dataOffset)
            {
                dataOffset = minDataOffset;
            }

            input.Seek(blockSizeTableOffset, SeekOrigin.Begin);

            var blockSizeTableSize  = dataOffset - blockSizeTableOffset;
            var blockSizeTableCount = blockSizeTableSize / 2;

            //ushort aux;
            //Console.WriteLine("dataOffset: {0:X8}\nfileTableOffset: {1:X8}\nBlockSizeTableSize: {2:X8}\nblockSizeTableOffset: {3:X8}", dataOffset,fileTableOffset,blockSizeTableSize,blockSizeTableOffset);
            this.BlockSizes.Clear();
            //Console.WriteLine("initial position: {0:X8}",input.Position);
            //Console.WriteLine("blockSizeTableCount: {0}",blockSizeTableCount);
            for (uint i = 0; i < blockSizeTableCount; i++)
            {
                this.BlockSizes.Add(input.ReadValueU16(endian));
            }
            //Console.WriteLine("final position: {0:X8}",input.Position);
            //Console.WriteLine("number of repetitions: {0}",blockSizeTableCount);
            //var fileNameListNameHash = new FileNameHash(
            //        new byte[] { 0xB5, 0x50, 0x19, 0xCB, 0xF9, 0xD3, 0xDA, 0x65, 0xD5, 0x5B, 0x32, 0x1C, 0x00, 0x19, 0x69, 0x7C, });
        }
Example #3
0
        private static void DecompressEntry(
            SFXArchiveFile sfx,
            SFXArchive.Entry entry,
            Stream input,
            byte[] inputBlock,
            Stream output,
            byte[] outputBlock)
        {
            var left = entry.UncompressedSize;

            input.Seek(entry.Offset, SeekOrigin.Begin);

            if (entry.BlockSizeIndex == -1)
            {
                output.WriteFromStream(input, entry.UncompressedSize);
            }
            else
            {
                var blockSizeIndex = entry.BlockSizeIndex;
                while (left > 0)
                {
                    var compressedBlockSize = sfx.BlockSizes[blockSizeIndex];
                    if (compressedBlockSize == 0)
                    {
                        compressedBlockSize = sfx.MaximumBlockSize;
                    }

                    if (sfx.CompressionScheme == SFXArchive.CompressionScheme.None)
                    {
                        output.WriteFromStream(input, compressedBlockSize);
                        left -= compressedBlockSize;
                    }
                    else if (sfx.CompressionScheme == SFXArchive.CompressionScheme.Lzma)
                    {
                        if (compressedBlockSize == sfx.MaximumBlockSize ||
                            compressedBlockSize == left)
                        {
                            output.WriteFromStream(input, compressedBlockSize);
                            left -= compressedBlockSize;
                        }
                        else
                        {
                            var uncompressedBlockSize = (uint)Math.Min(
                                left, sfx.MaximumBlockSize);

                            if (compressedBlockSize < 5)
                            {
                                throw new InvalidOperationException();
                            }

                            var properties = input.ReadBytes(5);
                            compressedBlockSize -= 5;

                            if (input.Read(inputBlock, 0, (int)compressedBlockSize)
                                != compressedBlockSize)
                            {
                                throw new EndOfStreamException();
                            }

                            uint actualUncompressedBlockSize = uncompressedBlockSize;
                            uint actualCompressedBlockSize   = compressedBlockSize;

                            var error = LZMA.Decompress(
                                outputBlock,
                                ref actualUncompressedBlockSize,
                                inputBlock,
                                ref actualCompressedBlockSize,
                                properties,
                                (uint)properties.Length);

                            if (error != LZMA.ErrorCode.Ok ||
                                uncompressedBlockSize != actualUncompressedBlockSize ||
                                compressedBlockSize != actualCompressedBlockSize)
                            {
                                throw new InvalidOperationException();
                            }

                            output.Write(outputBlock, 0, (int)actualUncompressedBlockSize);
                            left -= uncompressedBlockSize;
                        }
                    }
                    else
                    {
                        throw new NotImplementedException();
                    }

                    blockSizeIndex++;
                }
            }
        }
Example #4
0
        public void Deserialize(Stream input)
        {
            var magic = input.ReadValueU32(Endian.Little);
            if (magic != 0x53464152 && // SFAR
                magic.Swap() != 0x53464152)
            {
                throw new FormatException();
            }
            var endian = magic == 0x53464152 ? Endian.Little : Endian.Big;

            var version = input.ReadValueU32(endian);
            if (version != 0x00010000)
            {
                throw new FormatException();
            }

            var dataOffset = input.ReadValueU32(endian);
            bool firstDataOffset = true;
            uint minDataOffset = dataOffset;
            //Console.WriteLine("Data Offset: {0:X8}",dataOffset);
            var fileTableOffset = input.ReadValueU32(endian);
            //Console.WriteLine("File Table Offset: {0:X8}",fileTableOffset);
            var fileTableCount = input.ReadValueU32(endian);
            //Console.WriteLine("File Table Count: {0:X8}",fileTableCount);
            var blockSizeTableOffset = input.ReadValueU32(endian);
            //Console.WriteLine("Block Size Table Offset: {0:X8}",blockSizeTableOffset);
            this.MaximumBlockSize = input.ReadValueU32(endian);
            this.CompressionScheme = input
                .ReadValueEnum<SFXArchive.CompressionScheme>(endian);

            if (fileTableOffset != 0x20)
            {
                throw new FormatException();
            }

            if (this.MaximumBlockSize != 0x010000)
            {
                throw new FormatException();
            }

            /*
            if (this.CompressionScheme != SFXArchive.CompressionScheme.None &&
                this.CompressionScheme != SFXArchive.CompressionScheme.LZMA &&
                this.CompressionScheme != SFXArchive.CompressionScheme.LZX)
            {
                throw new FormatException();
            }
            */
            input.Seek(fileTableOffset, SeekOrigin.Begin);
            for (uint i = 0; i < fileTableCount; i++)
            {
            // ReSharper disable UseObjectOrCollectionInitializer
                var entry = new SFXArchive.Entry();
                entry.entryOffset = input.Position;
            // ReSharper restore UseObjectOrCollectionInitializer
                entry.nameHash = input.ReadFileNameHash();
                //Console.WriteLine("FileNameHash: {0}",entry.NameHash.ToString());
                entry.blockSizeIndex = input.ReadValueS32(endian);
                //Console.WriteLine("Begin position: {0:X8}",input.Position);
                entry.uncompressedSize = input.ReadValueU32(endian);
                entry.uncompressedSize |= ((long)input.ReadValueU8()) << 32;
                //Console.WriteLine("  End position: {0:X8}",input.Position);
                entry.dataOffset = input.ReadValueU32(endian);
                entry.dataOffset |= ((long)input.ReadValueU8()) << 32;
                if(firstDataOffset)
                {
                    minDataOffset = (uint)entry.dataOffset;
                    firstDataOffset = false;
                }
                else
                {
                    if(minDataOffset > entry.dataOffset)
                        minDataOffset = (uint)entry.dataOffset;
                }
                //if(entry.NameHash.Equals (fileNameListNameHash))Console.WriteLine("Offset: {0:X10}, UncSize {1:X10}",entry.Offset,entry.UncompressedSize);
                this.Entries.Add(entry);
            }
            if(minDataOffset > dataOffset)
                dataOffset = minDataOffset;

            input.Seek(blockSizeTableOffset, SeekOrigin.Begin);

            var blockSizeTableSize = dataOffset - blockSizeTableOffset;
            var blockSizeTableCount = blockSizeTableSize / 2;
            //ushort aux;
            //Console.WriteLine("dataOffset: {0:X8}\nfileTableOffset: {1:X8}\nBlockSizeTableSize: {2:X8}\nblockSizeTableOffset: {3:X8}", dataOffset,fileTableOffset,blockSizeTableSize,blockSizeTableOffset);
            this.BlockSizes.Clear();
            //Console.WriteLine("initial position: {0:X8}",input.Position);
            //Console.WriteLine("blockSizeTableCount: {0}",blockSizeTableCount);
            for (uint i = 0; i < blockSizeTableCount; i++)
            {
                this.BlockSizes.Add(input.ReadValueU16(endian));
            }
            //Console.WriteLine("final position: {0:X8}",input.Position);
            //Console.WriteLine("number of repetitions: {0}",blockSizeTableCount);
            //var fileNameListNameHash = new FileNameHash(
            //        new byte[] { 0xB5, 0x50, 0x19, 0xCB, 0xF9, 0xD3, 0xDA, 0x65, 0xD5, 0x5B, 0x32, 0x1C, 0x00, 0x19, 0x69, 0x7C, });
        }
        public void Deserialize(Stream input)
        {
            var magic = input.ReadValueU32(Endian.Little);

            if (magic != 0x53464152 && // SFAR
                magic.Swap() != 0x53464152)
            {
                throw new FormatException();
            }
            var endian = magic == 0x53464152 ? Endian.Little : Endian.Big;

            var version = input.ReadValueU32(endian);

            if (version != 0x00010000)
            {
                throw new FormatException();
            }

            var dataOffset           = input.ReadValueU32(endian);
            var fileTableOffset      = input.ReadValueU32(endian);
            var fileTableCount       = input.ReadValueU32(endian);
            var blockSizeTableOffset = input.ReadValueU32(endian);

            this.MaximumBlockSize  = input.ReadValueU32(endian);
            this.CompressionScheme = input
                                     .ReadValueEnum <SFXArchive.CompressionScheme>(endian);

            if (fileTableOffset != 0x20)
            {
                throw new FormatException();
            }

            if (this.MaximumBlockSize != 0x010000)
            {
                throw new FormatException();
            }

            /*
             * if (this.CompressionScheme != SFXArchive.CompressionScheme.None &&
             *  this.CompressionScheme != SFXArchive.CompressionScheme.LZMA &&
             *  this.CompressionScheme != SFXArchive.CompressionScheme.LZX)
             * {
             *  throw new FormatException();
             * }
             */

            input.Seek(blockSizeTableOffset, SeekOrigin.Begin);

            var blockSizeTableSize  = dataOffset - fileTableOffset;
            var blockSizeTableCount = blockSizeTableSize / 2;

            this.BlockSizes.Clear();
            for (uint i = 0; i < blockSizeTableCount; i++)
            {
                this.BlockSizes.Add(input.ReadValueU16(endian));
            }

            input.Seek(fileTableOffset, SeekOrigin.Begin);
            for (uint i = 0; i < fileTableCount; i++)
            {
// ReSharper disable UseObjectOrCollectionInitializer
                var entry = new SFXArchive.Entry();
// ReSharper restore UseObjectOrCollectionInitializer
                entry.NameHash          = input.ReadFileNameHash();
                entry.BlockSizeIndex    = input.ReadValueS32(endian);
                entry.UncompressedSize  = input.ReadValueU32(endian);
                entry.UncompressedSize |= ((long)input.ReadValueU8()) << 32;
                entry.Offset            = input.ReadValueU32(endian);
                entry.Offset           |= ((long)input.ReadValueU8()) << 32;
                this.Entries.Add(entry);
            }
        }