public void Export(BasePakEntry uasset, BasePakEntry uexp, BasePakEntry ubulk) { if (uasset == null || uexp == null) { return; } var assetStream = new FPakFile(Reader, uasset, Aes).GetStream(); var expStream = new FPakFile(Reader, uexp, Aes).GetStream(); var bulkStream = ubulk == null ? null : new FPakFile(Reader, ubulk, Aes).GetStream(); try { var exports = new AssetReader(assetStream, expStream, bulkStream).Exports; if (exports[0] is Texture2D) { var tex = exports[0] as Texture2D; tex.GetImage(); } } catch (IndexOutOfRangeException) { } catch (NotImplementedException) { } catch (IOException) { } catch (Exception e) { DebugHelper.WriteException(e, "thrown in PakReader.cs by Export"); } }
public Stream GetPackageStream(BasePakEntry entry) { lock (Reader) { return(new FPakFile(Reader, entry, Aes).GetStream()); } }
const int EncryptedBufferSize = 256; //?? TODO: check - may be value 16 will be better for performance public FPakFile(BinaryReader Reader, BasePakEntry Info, byte[] key = null) { Reader.BaseStream.Seek(Info.Pos + Info.StructSize, SeekOrigin.Begin); if (Info.Encrypted) { long encSize = (Info.Size & 15) == 0 ? Info.Size : ((Info.Size / 16) + 1) * 16; byte[] encBuffer = Reader.ReadBytes((int)encSize); data = AESDecryptor.DecryptAES(encBuffer, (int)encSize, key, key.Length).SubArray(0, (int)Info.UncompressedSize); if (encSize != Info.Size) { data = data.SubArray(0, (int)Info.UncompressedSize); } } else { data = Reader.ReadBytes((int)Info.UncompressedSize); } //File.WriteAllBytes(Path.GetFileName(info.Name), data); /* * if (info.CompressionMethod != 0) * { * Console.WriteLine("compressed"); * while (size > 0) * { * if ((UncompressedBuffer == null) || (ArPos < UncompressedBufferPos) || (ArPos >= UncompressedBufferPos + Info.CompressionBlockSize)) * { * // buffer is not ready * if (UncompressedBuffer == null) * { * UncompressedBuffer = new byte[Info.CompressionBlockSize]; * } * // prepare buffer * int BlockIndex = ArPos / Info.CompressionBlockSize; * UncompressedBufferPos = Info.CompressionBlockSize * BlockIndex; * * FPakCompressedBlock Block = Info.CompressionBlocks[BlockIndex]; * int CompressedBlockSize = (int)(Block.CompressedEnd - Block.CompressedStart); * int UncompressedBlockSize = Math.Min(Info.CompressionBlockSize, (int)Info.UncompressedSize - UncompressedBufferPos); // don't pass file end * * byte[] CompressedData; * if (Info.bEncrypted == 0) * { * Reader.BaseStream.Seek(Block.CompressedStart, SeekOrigin.Begin); * CompressedData = Reader.ReadBytes(CompressedBlockSize); * } * else * { * int EncryptedSize = Align(CompressedBlockSize, EncryptionAlign); * Reader.BaseStream.Seek(Block.CompressedStart, SeekOrigin.Begin); * CompressedData = Reader.ReadBytes(EncryptedSize); * CompressedData = AESDecryptor.DecryptAES(CompressedData, EncryptedSize, key, key.Length); * } * // appDecompress(CompressedData, CompressedBlockSize, UncompressedBuffer, UncompressedBlockSize, Info.CompressionMethod); * // https://github.com/gildor2/UModel/blob/39641f9e58cb4c286dde5f191e5db9a24b19f503/Unreal/UnCoreCompression.cpp#L183 * throw new NotImplementedException("Decompressing of files aren't written yet"); * } * * // data is in buffer, copy it * int BytesToCopy = UncompressedBufferPos + Info.CompressionBlockSize - ArPos; // number of bytes until end of the buffer * if (BytesToCopy > size) BytesToCopy = size; * if (BytesToCopy <= 0) * { * throw new ArgumentOutOfRangeException("Bytes to copy is invalid"); * } * * // copy uncompressed data * int OffsetInBuffer = ArPos - UncompressedBufferPos; * Buffer.BlockCopy(UncompressedBuffer, OffsetInBuffer, data, dataOffset, BytesToCopy); * * // advance pointers * * // ArPos += BytesToCopy; * size -= BytesToCopy; * dataOffset += BytesToCopy; * } * throw new NotImplementedException("Decompressing of files aren't written yet"); * } * else if (Info.bEncrypted != 0) * { * Console.WriteLine("Encrypted"); * // Uncompressed encrypted data. Reuse compression fields to handle decryption efficiently * if (UncompressedBuffer == null) * { * UncompressedBuffer = new byte[EncryptedBufferSize]; * UncompressedBufferPos = 0x40000000; // some invalid value * } * * while (size > 0) * { * if ((ArPos < UncompressedBufferPos) || (ArPos >= UncompressedBufferPos + EncryptedBufferSize)) * { * // Should fetch block and decrypt it. * // Note: AES is block encryption, so we should always align read requests for correct decryption. * UncompressedBufferPos = ArPos & ~(EncryptionAlign - 1); * Reader.BaseStream.Seek(Info.Pos + Info.StructSize + UncompressedBufferPos, SeekOrigin.Begin); * int RemainingSize = (int)Info.Size; * if (RemainingSize >= 0) * { * if (RemainingSize > EncryptedBufferSize) * RemainingSize = EncryptedBufferSize; * RemainingSize = Align(RemainingSize, EncryptionAlign); // align for AES, pak contains aligned data * UncompressedBuffer = Reader.ReadBytes(RemainingSize); * UncompressedBuffer = AESDecryptor.DecryptAES(UncompressedBuffer, RemainingSize, key, key.Length); * } * } * * // Now copy decrypted data from UncompressedBuffer (code is very similar to those used in decompression above) * int BytesToCopy = UncompressedBufferPos + EncryptedBufferSize - ArPos; // number of bytes until end of the buffer * if (BytesToCopy > size) BytesToCopy = size; * if (BytesToCopy <= 0) * { * throw new ArgumentOutOfRangeException("Bytes to copy is invalid"); * } * * // copy uncompressed data * int OffsetInBuffer = ArPos - UncompressedBufferPos; * Buffer.BlockCopy(UncompressedBuffer, OffsetInBuffer, data, dataOffset, BytesToCopy); * * // advance pointers * * // ArPos += BytesToCopy; * size -= BytesToCopy; * dataOffset += BytesToCopy; * } * throw new NotImplementedException("Decryption of files aren't written yet"); * } * else * { * // Pure data * // seek every time in a case if the same 'Reader' was used by different FPakFile * // (this is a lightweight operation for buffered FArchive) * Reader.BaseStream.Seek(Info.Pos + Info.StructSize, SeekOrigin.Begin); * data = Reader.ReadBytes(size); * // ArPos += size; * }*/ }