AssetStudio/UnityStudio/StudioClasses/BundleFile.cs

218 lines
9.1 KiB
C#
Raw Normal View History

2017-04-09 19:13:08 +00:00
using System.Collections.Generic;
2015-10-30 02:41:37 +00:00
using System.IO;
using Lz4;
2017-04-09 19:13:08 +00:00
using SevenZip.Compression.LZMA;
2015-10-30 02:41:37 +00:00
namespace UnityStudio
2015-10-30 02:41:37 +00:00
{
2018-03-04 18:35:53 +00:00
public class MemoryFile
{
public string fileName;
public MemoryStream stream;
}
public class BundleFile
2015-10-30 02:41:37 +00:00
{
public int format;
public string versionPlayer;
public string versionEngine;
2018-03-04 18:35:53 +00:00
public List<MemoryFile> fileList = new List<MemoryFile>();
2015-10-30 02:41:37 +00:00
2018-02-28 19:42:43 +00:00
public BundleFile(EndianBinaryReader bundleReader)
{
2018-02-28 19:42:43 +00:00
var signature = bundleReader.ReadStringToNull();
2017-11-09 19:36:08 +00:00
switch (signature)
2015-10-30 02:41:37 +00:00
{
2017-11-09 19:36:08 +00:00
case "UnityWeb":
case "UnityRaw":
case "\xFA\xFA\xFA\xFA\xFA\xFA\xFA\xFA":
{
2018-02-28 19:42:43 +00:00
format = bundleReader.ReadInt32();
versionPlayer = bundleReader.ReadStringToNull();
versionEngine = bundleReader.ReadStringToNull();
2017-11-09 19:36:08 +00:00
if (format < 6)
{
2018-02-28 19:42:43 +00:00
int bundleSize = bundleReader.ReadInt32();
2017-11-09 19:36:08 +00:00
}
else if (format == 6)
{
2018-02-28 19:42:43 +00:00
ReadFormat6(bundleReader, true);
2017-11-09 19:36:08 +00:00
return;
}
2018-02-28 19:42:43 +00:00
short dummy2 = bundleReader.ReadInt16();
int offset = bundleReader.ReadInt16();
int dummy3 = bundleReader.ReadInt32();
int lzmaChunks = bundleReader.ReadInt32();
2015-10-30 02:41:37 +00:00
2017-11-09 19:36:08 +00:00
int lzmaSize = 0;
long streamSize = 0;
2015-10-30 02:41:37 +00:00
2017-11-09 19:36:08 +00:00
for (int i = 0; i < lzmaChunks; i++)
2015-10-30 02:41:37 +00:00
{
2018-02-28 19:42:43 +00:00
lzmaSize = bundleReader.ReadInt32();
streamSize = bundleReader.ReadInt32();
2015-10-30 02:41:37 +00:00
}
2017-11-09 19:36:08 +00:00
2018-02-28 19:42:43 +00:00
bundleReader.Position = offset;
2017-11-09 19:36:08 +00:00
switch (signature)
2015-10-30 02:41:37 +00:00
{
2017-11-09 19:36:08 +00:00
case "\xFA\xFA\xFA\xFA\xFA\xFA\xFA\xFA": //.bytes
case "UnityWeb":
{
2018-02-28 19:42:43 +00:00
var lzmaBuffer = bundleReader.ReadBytes(lzmaSize);
2017-11-09 19:36:08 +00:00
using (var lzmaStream = new EndianBinaryReader(SevenZipHelper.StreamDecompress(new MemoryStream(lzmaBuffer))))
{
2018-02-28 19:42:43 +00:00
GetAssetsFiles(lzmaStream, 0);
2017-11-09 19:36:08 +00:00
}
break;
}
case "UnityRaw":
{
2018-02-28 19:42:43 +00:00
GetAssetsFiles(bundleReader, offset);
2017-11-09 19:36:08 +00:00
break;
}
2015-10-30 02:41:37 +00:00
}
2017-11-09 19:36:08 +00:00
break;
}
case "UnityFS":
2018-02-28 19:42:43 +00:00
format = bundleReader.ReadInt32();
versionPlayer = bundleReader.ReadStringToNull();
versionEngine = bundleReader.ReadStringToNull();
2017-11-09 19:36:08 +00:00
if (format == 6)
{
2018-02-28 19:42:43 +00:00
ReadFormat6(bundleReader);
2017-11-09 19:36:08 +00:00
}
break;
2017-02-16 07:30:11 +00:00
}
}
2018-02-28 19:42:43 +00:00
private void GetAssetsFiles(EndianBinaryReader reader, int offset)
2017-02-16 07:30:11 +00:00
{
2018-02-28 19:42:43 +00:00
int fileCount = reader.ReadInt32();
2017-02-16 07:30:11 +00:00
for (int i = 0; i < fileCount; i++)
{
2018-03-04 18:35:53 +00:00
var file = new MemoryFile();
file.fileName = reader.ReadStringToNull();
2018-02-28 19:42:43 +00:00
int fileOffset = reader.ReadInt32();
2017-02-16 07:30:11 +00:00
fileOffset += offset;
2018-02-28 19:42:43 +00:00
int fileSize = reader.ReadInt32();
long nextFile = reader.Position;
reader.Position = fileOffset;
var buffer = reader.ReadBytes(fileSize);
2018-03-04 18:35:53 +00:00
file.stream = new MemoryStream(buffer);
fileList.Add(file);
2018-02-28 19:42:43 +00:00
reader.Position = nextFile;
2017-02-16 07:30:11 +00:00
}
}
2018-02-28 19:42:43 +00:00
private void ReadFormat6(EndianBinaryReader bundleReader, bool padding = false)
2017-02-16 07:30:11 +00:00
{
2018-02-28 19:42:43 +00:00
var bundleSize = bundleReader.ReadInt64();
int compressedSize = bundleReader.ReadInt32();
int uncompressedSize = bundleReader.ReadInt32();
int flag = bundleReader.ReadInt32();
2017-02-16 07:30:11 +00:00
if (padding)
2018-02-28 19:42:43 +00:00
bundleReader.ReadByte();
2017-02-16 07:30:11 +00:00
byte[] blocksInfoBytes;
if ((flag & 0x80) != 0)//at end of file
{
2018-02-28 19:42:43 +00:00
var position = bundleReader.Position;
bundleReader.Position = bundleReader.BaseStream.Length - compressedSize;
blocksInfoBytes = bundleReader.ReadBytes(compressedSize);
bundleReader.Position = position;
2017-02-16 07:30:11 +00:00
}
else
{
2018-02-28 19:42:43 +00:00
blocksInfoBytes = bundleReader.ReadBytes(compressedSize);
2017-02-16 07:30:11 +00:00
}
2017-11-09 19:36:08 +00:00
MemoryStream blocksInfoStream;
2017-02-16 07:30:11 +00:00
switch (flag & 0x3F)
{
2017-04-09 19:13:08 +00:00
default://None
{
2017-11-09 19:36:08 +00:00
blocksInfoStream = new MemoryStream(blocksInfoBytes);
2017-02-16 07:30:11 +00:00
break;
}
2017-02-16 07:30:11 +00:00
case 1://LZMA
{
2017-11-09 19:36:08 +00:00
blocksInfoStream = SevenZipHelper.StreamDecompress(new MemoryStream(blocksInfoBytes));
2017-02-16 07:30:11 +00:00
break;
}
2017-02-16 07:30:11 +00:00
case 2://LZ4
case 3://LZ4HC
{
byte[] uncompressedBytes = new byte[uncompressedSize];
2018-03-04 18:35:53 +00:00
using (var decoder = new Lz4DecoderStream(new MemoryStream(blocksInfoBytes)))
2017-02-16 07:30:11 +00:00
{
decoder.Read(uncompressedBytes, 0, uncompressedSize);
}
2017-11-09 19:36:08 +00:00
blocksInfoStream = new MemoryStream(uncompressedBytes);
2017-02-16 07:30:11 +00:00
break;
}
//case 4:LZHAM?
}
2017-11-09 19:36:08 +00:00
using (var blocksInfo = new EndianBinaryReader(blocksInfoStream))
2017-02-16 07:30:11 +00:00
{
blocksInfo.Position = 0x10;
int blockcount = blocksInfo.ReadInt32();
var assetsDataStream = new MemoryStream();
for (int i = 0; i < blockcount; i++)
{
uncompressedSize = blocksInfo.ReadInt32();
compressedSize = blocksInfo.ReadInt32();
flag = blocksInfo.ReadInt16();
2018-02-28 19:42:43 +00:00
var compressedBytes = bundleReader.ReadBytes(compressedSize);
2016-10-15 11:53:51 +00:00
switch (flag & 0x3F)
{
2017-04-09 19:13:08 +00:00
default://None
{
2017-02-16 07:30:11 +00:00
assetsDataStream.Write(compressedBytes, 0, compressedSize);
2016-10-15 11:53:51 +00:00
break;
}
case 1://LZMA
{
2017-02-16 07:30:11 +00:00
var uncompressedBytes = new byte[uncompressedSize];
using (var mstream = new MemoryStream(compressedBytes))
{
2017-04-09 19:13:08 +00:00
var decoder = SevenZipHelper.StreamDecompress(mstream, uncompressedSize);
2017-02-16 07:30:11 +00:00
decoder.Read(uncompressedBytes, 0, uncompressedSize);
decoder.Dispose();
}
assetsDataStream.Write(uncompressedBytes, 0, uncompressedSize);
2016-10-15 11:53:51 +00:00
break;
}
2016-10-15 11:53:51 +00:00
case 2://LZ4
case 3://LZ4HC
{
2017-02-16 07:30:11 +00:00
var uncompressedBytes = new byte[uncompressedSize];
2018-03-04 18:35:53 +00:00
using (var decoder = new Lz4DecoderStream(new MemoryStream(compressedBytes)))
{
decoder.Read(uncompressedBytes, 0, uncompressedSize);
}
2017-02-16 07:30:11 +00:00
assetsDataStream.Write(uncompressedBytes, 0, uncompressedSize);
2016-10-15 11:53:51 +00:00
break;
}
2017-02-16 07:30:11 +00:00
//case 4:LZHAM?
2016-10-15 11:53:51 +00:00
}
2017-02-16 07:30:11 +00:00
}
2018-02-28 19:42:43 +00:00
using (var assetsDataReader = new EndianBinaryReader(assetsDataStream))
2017-02-16 07:30:11 +00:00
{
var entryinfo_count = blocksInfo.ReadInt32();
for (int i = 0; i < entryinfo_count; i++)
2016-10-15 11:53:51 +00:00
{
2018-03-04 18:35:53 +00:00
var file = new MemoryFile();
2017-02-16 07:30:11 +00:00
var entryinfo_offset = blocksInfo.ReadInt64();
var entryinfo_size = blocksInfo.ReadInt64();
2018-02-28 19:42:43 +00:00
flag = blocksInfo.ReadInt32();
2018-03-04 18:35:53 +00:00
file.fileName = Path.GetFileName(blocksInfo.ReadStringToNull());
2018-02-28 19:42:43 +00:00
assetsDataReader.Position = entryinfo_offset;
var buffer = assetsDataReader.ReadBytes((int)entryinfo_size);
2018-03-04 18:35:53 +00:00
file.stream = new MemoryStream(buffer);
fileList.Add(file);
}
}
}
2015-10-30 02:41:37 +00:00
}
}
}