public async ValueTask <DataSegment> ReadEntryAsync(PakEntry entry, CancellationToken cancellationToken = default) { var firstSegment = new DataSegment(await ProcessEntryAsync(entry).ConfigureAwait(false)); var segments = firstSegment; for (var ent = entry.LinkedEntry; ent is not null; ent = ent.LinkedEntry) { segments = segments.Append(await ProcessEntryAsync(ent).ConfigureAwait(false)); } return(firstSegment); }
private async ValueTask <IMemoryOwner <byte> > ProcessEntryAsync(PakEntry entry, CancellationToken cancellationToken = default) { var data = await entry.ReadAsync(SourceStream, cancellationToken); if (entry.IsEncrypted) { if (_aesProvider is null) { throw new PakEncryptedException("Pak file contains encrypted entries. AES encryption key is necessary for reading this asset."); } _aesProvider.Decrypt(data.Memory); } return(entry.IsCompressed ? await UnrealCompression.DecompressAsync(data, entry) : data); }
public static IMemoryOwner <byte> Decompress(Memory <byte> compressed, PakEntry entry) { var decompressed = PakMemoryPool.Shared.Rent((int)entry.UncompressedSize); if (MemoryMarshal.TryGetArray <byte>(compressed, out var src) && MemoryMarshal.TryGetArray <byte>(decompressed.Memory, out var dst)) { Decompress(src.Array !, src.Offset, src.Count, dst.Array !, dst.Offset, dst.Count, entry); } else { decompressed.Dispose(); throw new NotImplementedException(); //Decompress(data.Memory.ToArray(), 0, data.Memory.Length, buffer, compressionBlocks); } return(decompressed); }
private IMemoryOwner <byte> ProcessEntry(PakEntry entry) { var data = entry.Read(SourceStream); if (entry.IsEncrypted) { if (_aesProvider is null) { throw new PakEncryptedException("Pak file contains encrypted entries. AES encryption key is necessary for reading this asset."); } // decrypts data inplace _aesProvider.Decrypt(data.Memory); } return(entry.IsCompressed ? UnrealCompression.Decompress(data, entry) : data); }
private void ProcessIndex(FArchive reader) { FString?mountPoint = default; int entryCount = 0; reader.Read(ref mountPoint) .Read(ref entryCount); MountPoint = mountPoint.ToString().Replace("../../../", null); AbsoluteIndex = new Dictionary <string, PakEntry>(entryCount); for (var i = 0; i < entryCount; i++) { FString?fileName = default; reader.Read(ref fileName); var filePath = Path.Combine(MountPoint, fileName.ToString()); var entry = new PakEntry(this, Path.GetFileName(filePath)); entry.Serialize(reader); AbsoluteIndex.Add(filePath, entry); } // TODO: Change this to something working better foreach (var kv in AbsoluteIndex) { var val = kv.Value; if (kv.Value.IsCompressed) { val.CompressionBlocks.OffsetBy((int)val.EntryHeaderSize); } if (kv.Key.EndsWith(".uasset")) { var expPath = Path.ChangeExtension(kv.Key, ".uexp"); if (AbsoluteIndex.TryGetValue(expPath, out var exports)) { val.LinkedEntry = exports; var bulkPath = Path.ChangeExtension(kv.Key, ".ubulk"); if (AbsoluteIndex.TryGetValue(bulkPath, out var bulk)) { exports.LinkedEntry = bulk; } } } } }
public DataSegment ReadEntry(PakEntry entry) { DataSegment firstSegment = null !, segments = null; for (var ent = entry; ent is not null; ent = ent.LinkedEntry) { var entryData = ProcessEntry(ent); if (segments is null) { segments = firstSegment = new DataSegment(entryData); } else { segments = segments.Append(entryData); } segments.Tag(Path.GetExtension(ent.FileName)); } return(firstSegment); }
private static async ValueTask DecompressEntryAsync(MemoryStream mem, byte[] destination, int dstOffset, int dstCount, PakEntry entry, int progress = 0, CancellationToken cancellationToken = default) { foreach (var block in entry.CompressionBlocks) { mem.Seek(block.Start, SeekOrigin.Begin); using var stream = GetDecompressStream(mem, entry.CompressionMethod); var read = 0; do { read = await stream.ReadAsync(destination, dstOffset + progress, dstCount - progress, cancellationToken).ConfigureAwait(false); progress += read; } while (read > 0); } }
public static async ValueTask DecompressAsync(byte[] source, int srcOffset, int srcCount, byte[] destination, int dstOffset, int dstCount, PakEntry entry, CancellationToken cancellationToken = default) { using var mem = new MemoryStream(source, srcOffset, srcCount); await DecompressEntryAsync(mem, destination, dstOffset, dstCount, entry, cancellationToken : cancellationToken).ConfigureAwait(false); }
public static async ValueTask <IMemoryOwner <byte> > DecompressAsync(Memory <byte> compressed, PakEntry entry, CancellationToken cancellationToken = default) { var decompressed = PakMemoryPool.Shared.Rent((int)entry.UncompressedSize); if (MemoryMarshal.TryGetArray <byte>(compressed, out var src) && MemoryMarshal.TryGetArray <byte>(decompressed.Memory, out var dst)) { await DecompressAsync(src.Array !, src.Offset, src.Count, dst.Array !, dst.Offset, dst.Count, entry, cancellationToken).ConfigureAwait(false); } else { decompressed.Dispose(); throw new NotImplementedException(); } return(decompressed); }
public static async ValueTask <IMemoryOwner <byte> > DecompressAsync(IMemoryOwner <byte> compressedData, PakEntry entry) { using var data = compressedData; return(await DecompressAsync(data.Memory, entry)); }
private static void DecompressEntry(MemoryStream mem, byte[] destination, int dstOffset, int dstCount, PakEntry entry, int progress = 0) { foreach (var block in entry.CompressionBlocks) { mem.Seek(block.Start, SeekOrigin.Begin); using var stream = GetDecompressStream(mem, entry.CompressionMethod); var read = 0; do { read = stream.Read(destination, dstOffset + progress, dstCount - progress); progress += read; } while (read > 0); } }
public static void Decompress(byte[] source, int srcOffset, int srcCount, byte[] destination, int dstOffset, int dstCount, PakEntry entry) { using var mem = new MemoryStream(source, srcOffset, srcCount); DecompressEntry(mem, destination, dstOffset, dstCount, entry); }
public static void Decompress(byte[] source, byte[] destination, PakEntry entry) => Decompress(source, 0, source.Length, destination, 0, destination.Length, entry);
public static IMemoryOwner <byte> Decompress(IMemoryOwner <byte> compressedData, PakEntry entry) { using var data = compressedData; return(Decompress(data.Memory, entry)); }