private void Parse(AssetsReader reader) { //basic header stuff signature = reader.ReadCStr(); if (signature != "UnityFS") { throw new NotSupportedException("Stream is not UnityFS"); } fileVersion = reader.ReadBEInt32(); if (fileVersion != 6) { throw new NotSupportedException("File version is not supported"); } PlayerVersion = reader.ReadCStr(); EngineVersion = reader.ReadCStr(); BundleSize = reader.ReadBEInt64(); //header info int compressedSize = reader.ReadBEInt32(); int decompressedSize = reader.ReadBEInt32(); flags = reader.ReadBEUInt32(); if (IsDirectoryAtEnd(flags)) { var start = (int)reader.BaseStream.Position; reader.Seek((int)reader.BaseStream.Length - compressedSize); infoBytes = reader.ReadBytes(compressedSize); reader.Seek(start); } else { infoBytes = reader.ReadBytes(compressedSize); } Stream blockInfoStream = null; try { switch (CompressionMode(flags)) { case UnityFSCompressionMode.LZ4: case UnityFSCompressionMode.LZ4HC: blockInfoStream = new MemoryStream(LZ4.LZ4Codec.Decode(infoBytes, 0, infoBytes.Length, decompressedSize)); break; case UnityFSCompressionMode.NoCompression: blockInfoStream = new MemoryStream(infoBytes); break; case UnityFSCompressionMode.LZMA: // TODO Better way of encoding/decoding blockInfoStream = new MemoryStream(LZMADecode(infoBytes, decompressedSize)); break; } using (AssetsReader infoReader = new AssetsReader(blockInfoStream, false)) ParseDirectory(infoReader); } finally { if (blockInfoStream != null) { blockInfoStream.Dispose(); } } MemoryStream outputStream = new MemoryStream(); foreach (var blockInfo in BlockInfos) { byte[] blockData = null; switch (blockInfo.CompressionMode) { case UnityFSCompressionMode.LZ4: case UnityFSCompressionMode.LZ4HC: blockData = LZ4.LZ4Codec.Decode(reader.ReadBytes((int)blockInfo.CompressedSize), 0, (int)blockInfo.CompressedSize, (int)blockInfo.UncompressedSize); break; case UnityFSCompressionMode.NoCompression: blockData = reader.ReadBytes((int)blockInfo.UncompressedSize); break; case UnityFSCompressionMode.LZMA: blockData = LZMADecode(reader.BaseStream, (int)blockInfo.CompressedSize, (int)blockInfo.UncompressedSize); break; } outputStream.Write(blockData, 0, blockData.Length); } using (outputStream) { foreach (var entry in Entries) { outputStream.Seek(entry.Offset, SeekOrigin.Begin); entry.Data = outputStream.ReadBytes((int)entry.Size); } } }
protected virtual void ParseBase(AssetsReader reader) { reader.Seek(ObjectInfo.DataOffset); }