diff --git a/Aaru.Archives/Arc/Files.cs b/Aaru.Archives/Arc/Files.cs
index 30a354919..8d53e6a65 100644
--- a/Aaru.Archives/Arc/Files.cs
+++ b/Aaru.Archives/Arc/Files.cs
@@ -150,7 +150,7 @@ public sealed partial class Arc
if((int)_entries[entryNumber].Method >= 20) return ErrorNumber.InvalidArgument;
- if(_entries[entryNumber].Method > Method.Crush) return ErrorNumber.NotSupported;
+ if(_entries[entryNumber].Method > Method.Distill) return ErrorNumber.NotSupported;
Stream stream = new OffsetStream(new NonClosableStream(_stream),
_entries[entryNumber].DataOffset,
@@ -182,6 +182,9 @@ public sealed partial class Arc
if(_entries[entryNumber].Method == Method.Crush)
stream = new CrushStream(stream, _entries[entryNumber].Uncompressed);
+ if(_entries[entryNumber].Method == Method.Distill)
+ stream = new DistillStream(stream, _entries[entryNumber].Uncompressed);
+
filter = new ZZZNoFilter();
ErrorNumber errno = filter.Open(stream);
diff --git a/Aaru.Compression/Aaru.Compression.csproj b/Aaru.Compression/Aaru.Compression.csproj
index 08709e5d0..f6dc5bb47 100644
--- a/Aaru.Compression/Aaru.Compression.csproj
+++ b/Aaru.Compression/Aaru.Compression.csproj
@@ -53,6 +53,7 @@
+
diff --git a/Aaru.Compression/Pak/DistillStream.cs b/Aaru.Compression/Pak/DistillStream.cs
new file mode 100644
index 000000000..6af7f84f7
--- /dev/null
+++ b/Aaru.Compression/Pak/DistillStream.cs
@@ -0,0 +1,108 @@
+using System;
+using System.IO;
+using System.Runtime.InteropServices;
+
+namespace Aaru.Compression.Pak;
+
+public partial class DistillStream : Stream
+{
+ readonly byte[] _decoded;
+ readonly long _length;
+ long _position;
+
+ public DistillStream(Stream compressedStream, long decompressedLength)
+ {
+ if(compressedStream == null) throw new ArgumentNullException(nameof(compressedStream));
+ if(!compressedStream.CanRead) throw new ArgumentException("Stream must be readable", nameof(compressedStream));
+ if(decompressedLength < 0) throw new ArgumentOutOfRangeException(nameof(decompressedLength));
+
+ // Read full compressed data into memory
+ compressedStream.Position = 0;
+ byte[] inBuf = new byte[compressedStream.Length];
+ compressedStream.ReadExactly(inBuf, 0, inBuf.Length);
+
+ // Allocate output buffer
+ _decoded = new byte[decompressedLength];
+ nint outLen = (nint)decompressedLength;
+
+ // Call native decompressor
+ int err = pak_decompress_distill(inBuf, inBuf.Length, _decoded, ref outLen);
+
+ if(err != 0) throw new InvalidOperationException("Distill decompression failed");
+
+ // Adjust actual length in case it differs
+ _length = outLen;
+ _position = 0;
+ }
+
+ public override bool CanRead => true;
+ public override bool CanSeek => true;
+ public override bool CanWrite => false;
+ public override long Length => _length;
+
+ public override long Position
+ {
+ get => _position;
+ set => Seek(value, SeekOrigin.Begin);
+ }
+
+ [LibraryImport("libAaru.Compression.Native")]
+ public static partial int pak_decompress_distill(byte[] in_buf, nint in_len, byte[] out_buf, ref nint out_len);
+
+ public override void Flush()
+ {
+ // no-op
+ }
+
+ ///
+ /// Reads up to bytes from the decompressed buffer
+ /// into , starting at .
+ ///
+ public override int Read(byte[] buffer, int offset, int count)
+ {
+ if(buffer == null) throw new ArgumentNullException(nameof(buffer));
+ if(offset < 0) throw new ArgumentOutOfRangeException(nameof(offset));
+ if(count < 0) throw new ArgumentOutOfRangeException(nameof(count));
+ if(offset + count > buffer.Length) throw new ArgumentException("offset+count exceeds buffer length");
+
+ long remaining = _length - _position;
+
+ if(remaining <= 0) return 0;
+
+ int toRead = (int)Math.Min(count, remaining);
+ Array.Copy(_decoded, _position, buffer, offset, toRead);
+ _position += toRead;
+
+ return toRead;
+ }
+
+ ///
+ /// Sets the current position within the decompressed buffer.
+ ///
+ public override long Seek(long offset, SeekOrigin origin)
+ {
+ long newPos = origin switch
+ {
+ SeekOrigin.Begin => offset,
+ SeekOrigin.Current => _position + offset,
+ SeekOrigin.End => _length + offset,
+ _ => throw new ArgumentException("Invalid SeekOrigin", nameof(origin))
+ };
+
+ if(newPos < 0 || newPos > _length) throw new IOException("Attempt to seek outside the buffer");
+
+ _position = newPos;
+
+ return _position;
+ }
+
+ public override void SetLength(long value)
+ {
+ throw new NotSupportedException("Cannot resize decompressed buffer");
+ }
+
+ public override void Write(byte[] buffer, int offset, int count)
+ {
+ throw new NotSupportedException("Stream is read-only");
+ }
+}
\ No newline at end of file