private void Parse(AssetsReader reader) { MetadataSize = reader.ReadBEInt32(); FileSize = reader.ReadBEInt32(); Version = reader.ReadBEInt32(); ObjectDataOffset = reader.ReadBEInt32(); IsBigEndian = reader.ReadBoolean(); //padding apparently reader.ReadBytes(3); }
private void ParseDirectory(AssetsReader reader) { //unknown? reader.ReadBytes(16); int numBlocks = reader.ReadBEInt32(); for (int i = 0; i < numBlocks; i++) { BlockInfos.Add(new BlockInfo(reader)); } int numEntries = reader.ReadBEInt32(); for (int i = 0; i < numEntries; i++) { Entries.Add(new DirectoryEntry(reader)); } }
private void Parse(AssetsReader reader) { //basic header stuff var signature = reader.ReadCStr(); if (signature != "UnityFS") { throw new NotSupportedException("Stream is not UnityFS"); } var 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 var compressedSize = reader.ReadBEInt32(); var decompressedSize = reader.ReadBEInt32(); var flags = reader.ReadBEUInt32(); byte[] infoBytes; 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: 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); } } }