/*public void WriteToStream( Stream stream ) * { * WriteToStream( new BinaryWriter( stream ) ); * //WriteToStream( new StreamWriter( stream ) ); * }*/ public void SerializeTo(BinaryWriter writer, bool dispose = true) { var stream = _entry.IsCompressed ? _compressedStream : _baseStream; if (_entry.IsEncrypted) { var blockPosCount = (uint)(((int)_baseStream.Length + _blockSize - 1) / _blockSize) + 1; var blockPositions = new int[blockPosCount]; if (_entry.IsCompressed) { for (var blockIndex = 0; blockIndex < blockPosCount; blockIndex++) { using (var br = new BinaryReader(stream, new System.Text.UTF8Encoding(), true)) { for (var i = 0; i < blockPosCount; i++) { blockPositions[i] = (int)br.ReadUInt32(); } } stream.Seek(0, SeekOrigin.Begin); } } else { // untested: encryption for uncompressed files for (var blockIndex = 1; blockIndex < blockPosCount; blockIndex++) { blockPositions[blockIndex - 1] = _blockSize * blockIndex; } blockPositions[blockPosCount - 1] = (int)_baseStream.Length; } var currentOffset = 0; for (var blockIndex = _entry.IsCompressed ? 0 : 1; blockIndex < blockPosCount; blockIndex++) { var toWrite = (int)blockPositions[blockIndex] - currentOffset; var data = StormBuffer.EncryptStream(stream, (uint)(_entry.EncryptionSeed + blockIndex - 1), currentOffset, toWrite); for (var b = 0; b < data.Length; b++) { writer.Write(data[b]); } currentOffset += toWrite; } } else { WriteStreamToWriter(stream, writer); } if (dispose) { Dispose(); } }
internal Stream Transform(MpqFileFlags targetFlags, MpqCompressionType compressionType, uint targetFilePosition, int targetBlockSize) { using var memoryStream = new MemoryStream(); CopyTo(memoryStream); memoryStream.Position = 0; var fileSize = memoryStream.Length; using var compressedStream = GetCompressedStream(memoryStream, targetFlags, compressionType, targetBlockSize); var compressedSize = (uint)compressedStream.Length; var resultStream = new MemoryStream(); var blockPosCount = (uint)(((int)fileSize + targetBlockSize - 1) / targetBlockSize) + 1; if (targetFlags.HasFlag(MpqFileFlags.Encrypted) && blockPosCount > 1) { var blockPositions = new int[blockPosCount]; var singleUnit = targetFlags.HasFlag(MpqFileFlags.SingleUnit); var hasBlockPositions = !singleUnit && ((targetFlags & MpqFileFlags.Compressed) != 0); if (hasBlockPositions) { for (var blockIndex = 0; blockIndex < blockPosCount; blockIndex++) { using (var br = new BinaryReader(compressedStream, new UTF8Encoding(), true)) { for (var i = 0; i < blockPosCount; i++) { blockPositions[i] = (int)br.ReadUInt32(); } } compressedStream.Seek(0, SeekOrigin.Begin); } } else { if (singleUnit) { blockPosCount = 2; } blockPositions[0] = 0; for (var blockIndex = 2; blockIndex < blockPosCount; blockIndex++) { blockPositions[blockIndex - 1] = targetBlockSize * (blockIndex - 1); } blockPositions[blockPosCount - 1] = (int)compressedSize; } var encryptionSeed = _baseEncryptionSeed; if (targetFlags.HasFlag(MpqFileFlags.BlockOffsetAdjustedKey)) { encryptionSeed = MpqEntry.AdjustEncryptionSeed(encryptionSeed, targetFilePosition, (uint)fileSize); } var currentOffset = 0; using (var writer = new BinaryWriter(resultStream, new UTF8Encoding(false, true), true)) { for (var blockIndex = hasBlockPositions ? 0 : 1; blockIndex < blockPosCount; blockIndex++) { var toWrite = blockPositions[blockIndex] - currentOffset; var data = StormBuffer.EncryptStream(compressedStream, (uint)(encryptionSeed + blockIndex - 1), currentOffset, toWrite); writer.Write(data); currentOffset += toWrite; } } } else { compressedStream.CopyTo(resultStream); } resultStream.Position = 0; return(resultStream); }