Skip to content

Commit fac7eb9

Browse files
committed
Add support for zstd compressed depot chunks
1 parent ad531d9 commit fac7eb9

File tree

3 files changed

+50
-1
lines changed

3 files changed

+50
-1
lines changed

SteamKit2/SteamKit2/Steam/CDN/DepotChunk.cs

+5-1
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,11 @@ public static int Process( DepotManifest.ChunkData info, ReadOnlySpan<byte> data
5555
var written = aes.DecryptCbc( data[ iv.Length.. ], iv, buffer, PaddingMode.PKCS7 );
5656
var decryptedStream = new MemoryStream( buffer, 0, written );
5757

58-
if ( buffer.Length > 1 && buffer[ 0 ] == 'V' && buffer[ 1 ] == 'Z' )
58+
if ( buffer[ 0 ] == 'V' && buffer[ 1 ] == 'S' && buffer[ 2 ] == 'Z' && buffer[ 3 ] == 'a' ) // Zstd
59+
{
60+
writtenDecompressed = VZstdUtil.Decompress( buffer.AsSpan( 0, written ), destination );
61+
}
62+
else if ( buffer.Length > 1 && buffer[ 0 ] == 'V' && buffer[ 1 ] == 'Z' )
5963
{
6064
writtenDecompressed = VZipUtil.Decompress( decryptedStream, destination, verifyChecksum: false );
6165
}

SteamKit2/SteamKit2/SteamKit2.csproj

+1
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@
5555
</PackageReference>
5656
<PackageReference Include="protobuf-net" Version="3.2.46" />
5757
<PackageReference Include="System.IO.Hashing" Version="9.0.1" />
58+
<PackageReference Include="ZstdSharp.Port" Version="0.8.4" />
5859
</ItemGroup>
5960

6061
</Project>

SteamKit2/SteamKit2/Util/VZstdUtil.cs

+44
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
using System;
2+
using System.Buffers;
3+
using System.IO;
4+
using System.Runtime.InteropServices;
5+
6+
namespace SteamKit2
7+
{
8+
static class VZstdUtil
9+
{
10+
private const uint VZstdHeader = 0x56535A61;
11+
12+
public static int Decompress( ReadOnlySpan<byte> buffer, byte[] destination )
13+
{
14+
if ( MemoryMarshal.Read<uint>( buffer ) != VZstdHeader )
15+
{
16+
throw new InvalidDataException( "Expecting VZstdHeader at start of stream" );
17+
}
18+
19+
var sizeCompressed = MemoryMarshal.Read<int>( buffer[ ^15.. ] ); // TODO: I am not convinced this is correct -- maybe its the frame size
20+
var sizeDecompressed = MemoryMarshal.Read<int>( buffer[ ^11.. ] );
21+
22+
if ( buffer[ ^3 ] != 'z' || buffer[ ^2 ] != 's' || buffer[ ^1 ] != 'v' )
23+
{
24+
throw new InvalidDataException( "Expecting VZstdFooter at end of stream" );
25+
}
26+
27+
if ( destination.Length < sizeDecompressed )
28+
{
29+
throw new ArgumentException( "The destination buffer is smaller than the decompressed data size.", nameof( destination ) );
30+
}
31+
32+
using var zstdDecompressor = new ZstdSharp.Decompressor();
33+
34+
var input = buffer[ 4..^12 ];
35+
36+
if ( !zstdDecompressor.TryUnwrap( input, destination, out var sizeWritten ) || sizeDecompressed != sizeWritten )
37+
{
38+
throw new InvalidDataException( $"Failed to decompress Zstd (expected {sizeDecompressed} bytes, got {sizeWritten})." );
39+
}
40+
41+
return sizeDecompressed;
42+
}
43+
}
44+
}

0 commit comments

Comments
 (0)