protected override void WriteDataToStream(Stream stream, SharedExtractParams extractParams, bool decompress) { var reader = extractParams.Reader; uint len = this.Compressed ? this.Size : this.RealSize; reader.BaseStream.Seek((long)this.Offset, SeekOrigin.Begin); // Reset at start since value might still be in used for a bit after this.BytesWritten = 0; if (!decompress || !this.Compressed) { StreamUtils.WriteSectionToStream(reader.BaseStream, len, stream, bytesWritten => this.BytesWritten = bytesWritten); } else { CompressionUtils.Decompress(reader.BaseStream, len, stream, bytesWritten => this.BytesWritten = bytesWritten, extractParams); } }
public override ulong GetSizeInArchive(SharedExtractParams extractParams) { if (this.Archive.Type == ArchiveTypes.BSA_SE) { var reader = extractParams.Reader; ulong filesz = this.Size & 0x3fffffff; reader.BaseStream.Position = (long)Offset; if (this.Archive.ContainsFileNameBlobs) { int len = reader.ReadByte(); filesz -= (ulong)len + 1; } if (this.Size > 0 && this.Compressed) { filesz -= 4; } return(filesz); } else { return(this.Size); } }
private void WriteChunks(Stream stream, SharedExtractParams extractParams, bool decompress) { var reader = extractParams.Reader; for (int i = 0; i < (numChunks - 1); i++) { reader.BaseStream.Seek((long)this.Chunks[i].offset, SeekOrigin.Begin); if (!decompress) { ulong prev = this.BytesWritten; StreamUtils.WriteSectionToStream(reader.BaseStream, Math.Max(Chunks[i].packSz, Chunks[i].fullSz), // Lazy hack, only one should be set when not compressed stream, bytesWritten => this.BytesWritten = prev + bytesWritten); } else { ulong prev = this.BytesWritten; CompressionUtils.Decompress(reader.BaseStream, this.Chunks[i].packSz, stream, bytesWritten => this.BytesWritten = prev + bytesWritten, extractParams); } } }
protected override void WriteDataToStream(Stream stream, SharedExtractParams extractParams, bool decompress) { var reader = extractParams.Reader; reader.BaseStream.Seek((long)this.Offset, SeekOrigin.Begin); // Reset at start since value might still be in used for a bit after this.BytesWritten = 0; if (!decompress) { StreamUtils.WriteSectionToStream(reader.BaseStream, Math.Max(this.Size, this.RealSize), // Lazy hack, only one should be set when not compressed stream, bytesWritten => this.BytesWritten = bytesWritten); } else { this.WriteHeader(stream); try { CompressionUtils.Decompress(reader.BaseStream, this.Size, stream, bytesWritten => this.BytesWritten = bytesWritten, extractParams); } catch (Exception ex) { throw new Exception($"Couldn't decompress zlib texture data. Size: {this.Size}, RealSize: {this.RealSize}", ex); } } this.WriteChunks(stream, extractParams, decompress); }
/// <summary> /// Decompresses <paramref name="input"/> to <paramref name="output"/> with progress reports. /// </summary> /// <param name="input">The <see cref="Stream"/> with the data to decompress.</param> /// <param name="length">The length of the data in the <paramref name="input"/>.</param> /// <param name="output">The <see cref="Stream"/> to decompress to.</param> /// <param name="progressReport">Invokes at interval, based on <paramref name="progressInterval"/>, the amount of bytes written.</param> /// <param name="progressInterval">The interval at which to invoke <paramref name="progressReport"/>.</param> public static void Decompress(Stream input, uint length, Stream output, Action <ulong> progressReport, SharedExtractParams extractParams, long progressInterval = DefaultProgressInterval) { int count; ulong written = 0; byte[] buffer = new byte[BufferSize]; var raw = input.ReadBytes((int)length); extractParams.Inflater.Reset(); extractParams.Inflater.SetInput(raw, 0, raw.Length); var sw = Stopwatch.StartNew(); while ((count = extractParams.Inflater.Inflate(buffer)) > 0) { output.Write(buffer, 0, count); written += (ulong)count; if (sw.ElapsedMilliseconds >= progressInterval) { progressReport?.Invoke(written); sw.Restart(); } } progressReport?.Invoke(written); sw.Stop(); }
protected override void WriteDataToStream(Stream stream, SharedExtractParams extractParams, bool decompress) { var bw = new BinaryWriter(stream); var reader = extractParams.Reader; // Reset at start since value might still be in used for a bit after this.BytesWritten = 0; if (decompress && GenerateTextureHeader) { this.WriteHeader(bw); } for (int i = 0; i < numChunks; i++) { bool isCompressed = this.Chunks[i].packSz != 0; ulong prev = this.BytesWritten; reader.BaseStream.Seek((long)this.Chunks[i].offset, SeekOrigin.Begin); if (!decompress || !isCompressed) { StreamUtils.WriteSectionToStream(reader.BaseStream, Chunks[i].fullSz, stream, bytesWritten => this.BytesWritten = prev + bytesWritten); } else { CompressionUtils.Decompress(reader.BaseStream, this.Chunks[i].packSz, stream, bytesWritten => this.BytesWritten = prev + bytesWritten, extractParams); } } if (dataSizePosition > -1) { bw.WriteAt(dataSizePosition, (uint)bw.BaseStream.Length - 164); } }
public override ulong GetSizeInArchive(SharedExtractParams extractParams) => this.Compressed ? this.Size : this.RealSize;
public override ulong GetSizeInArchive(SharedExtractParams extractParams) => (ulong)Chunks.Sum(x => Compressed ? x.packSz : x.fullSz);
protected override void WriteDataToStream(Stream stream, SharedExtractParams extractParams, bool decompress) { var reader = extractParams.Reader; decompress = decompress && this.Compressed; reader.BaseStream.Position = (long)Offset; // Reset at start since value might still be in used for a bit after this.BytesWritten = 0; if (this.Archive.Type == ArchiveTypes.BSA_SE) { // Separate Skyrim Special Edition extraction ulong filesz = this.Size & 0x3fffffff; if (this.Archive.ContainsFileNameBlobs) { int len = reader.ReadByte(); filesz -= (ulong)len + 1; reader.BaseStream.Seek((long)this.Offset + 1 + len, SeekOrigin.Begin); } uint filesize = (uint)filesz; if (this.Size > 0 && this.Compressed) { filesize = reader.ReadUInt32(); filesz -= 4; } if (!decompress) { StreamUtils.WriteSectionToStream(reader.BaseStream, filesz, stream, bytesWritten => this.BytesWritten = bytesWritten); } else { CompressionUtils.DecompressLZ4(reader.BaseStream, (uint)filesz, stream, bytesWritten => this.BytesWritten = bytesWritten); } } else { // Skip ahead if (this.Archive.ContainsFileNameBlobs) { reader.BaseStream.Position += reader.ReadByte() + 1; } if (!decompress) { StreamUtils.WriteSectionToStream(reader.BaseStream, this.Size, stream, bytesWritten => this.BytesWritten = bytesWritten); } else { if (this.Compressed) { reader.ReadUInt32(); // Skip } CompressionUtils.Decompress(reader.BaseStream, this.Size - 4, stream, bytesWriten => this.BytesWritten = bytesWriten, extractParams); } } }
public override ulong GetSizeInArchive(SharedExtractParams extractParams) => Math.Max(this.Size, this.RealSize);