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); } }
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, }); }
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++; } } }
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); } }