Skip to content

Commit

Permalink
refactor the file reading part
Browse files Browse the repository at this point in the history
  • Loading branch information
Perfare committed Jul 1, 2021
1 parent 4345885 commit 7ab2cda
Show file tree
Hide file tree
Showing 7 changed files with 175 additions and 159 deletions.
77 changes: 38 additions & 39 deletions AssetStudio/AssetsManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ public class AssetsManager
{
public string SpecifyUnityVersion;
public List<SerializedFile> assetsFileList = new List<SerializedFile>();

internal Dictionary<string, int> assetsFileIndexCache = new Dictionary<string, int>(StringComparer.OrdinalIgnoreCase);
internal Dictionary<string, BinaryReader> resourceFileReaders = new Dictionary<string, BinaryReader>(StringComparer.OrdinalIgnoreCase);

Expand Down Expand Up @@ -60,43 +61,43 @@ private void Load(string[] files)

private void LoadFile(string fullName)
{
switch (CheckFileType(fullName, out var reader))
var reader = new FileReader(fullName);
switch (reader.FileType)
{
case FileType.AssetsFile:
LoadAssetsFile(fullName, reader);
LoadAssetsFile(reader);
break;
case FileType.BundleFile:
LoadBundleFile(fullName, reader);
LoadBundleFile(reader);
break;
case FileType.WebFile:
LoadWebFile(fullName, reader);
LoadWebFile(reader);
break;
}
}

private void LoadAssetsFile(string fullName, EndianBinaryReader reader)
private void LoadAssetsFile(FileReader reader)
{
var fileName = Path.GetFileName(fullName);
if (!assetsFileListHash.Contains(fileName))
if (!assetsFileListHash.Contains(reader.FileName))
{
Logger.Info($"Loading {fileName}");
Logger.Info($"Loading {reader.FileName}");
try
{
var assetsFile = new SerializedFile(this, fullName, reader);
var assetsFile = new SerializedFile(reader, this);
CheckStrippedVersion(assetsFile);
assetsFileList.Add(assetsFile);
assetsFileListHash.Add(assetsFile.fileName);

foreach (var sharedFile in assetsFile.m_Externals)
{
var sharedFilePath = Path.Combine(Path.GetDirectoryName(fullName), sharedFile.fileName);
var sharedFileName = sharedFile.fileName;

if (!importFilesHash.Contains(sharedFileName))
{
var sharedFilePath = Path.Combine(Path.GetDirectoryName(reader.FullPath), sharedFileName);
if (!File.Exists(sharedFilePath))
{
var findFiles = Directory.GetFiles(Path.GetDirectoryName(fullName), sharedFileName, SearchOption.AllDirectories);
var findFiles = Directory.GetFiles(Path.GetDirectoryName(reader.FullPath), sharedFileName, SearchOption.AllDirectories);
if (findFiles.Length > 0)
{
sharedFilePath = findFiles[0];
Expand All @@ -113,7 +114,7 @@ private void LoadAssetsFile(string fullName, EndianBinaryReader reader)
}
catch (Exception e)
{
Logger.Error($"Error while reading assets file {fileName}", e);
Logger.Error($"Error while reading assets file {reader.FileName}", e);
reader.Dispose();
}
}
Expand All @@ -123,14 +124,13 @@ private void LoadAssetsFile(string fullName, EndianBinaryReader reader)
}
}

private void LoadAssetsFromMemory(string fullName, EndianBinaryReader reader, string originalPath, string unityVersion = null)
private void LoadAssetsFromMemory(FileReader reader, string originalPath, string unityVersion = null)
{
var fileName = Path.GetFileName(fullName);
if (!assetsFileListHash.Contains(fileName))
if (!assetsFileListHash.Contains(reader.FileName))
{
try
{
var assetsFile = new SerializedFile(this, fullName, reader);
var assetsFile = new SerializedFile(reader, this);
assetsFile.originalPath = originalPath;
if (!string.IsNullOrEmpty(unityVersion) && assetsFile.header.m_Version < SerializedFileFormatVersion.kUnknown_7)
{
Expand All @@ -142,26 +142,25 @@ private void LoadAssetsFromMemory(string fullName, EndianBinaryReader reader, st
}
catch (Exception e)
{
Logger.Error($"Error while reading assets file {fileName} from {Path.GetFileName(originalPath)}", e);
resourceFileReaders.Add(fileName, reader);
Logger.Error($"Error while reading assets file {reader.FileName} from {Path.GetFileName(originalPath)}", e);
resourceFileReaders.Add(reader.FileName, reader);
}
}
}

private void LoadBundleFile(string fullName, EndianBinaryReader reader, string parentPath = null)
private void LoadBundleFile(FileReader reader, string originalPath = null)
{
var fileName = Path.GetFileName(fullName);
Logger.Info("Loading " + fileName);
Logger.Info("Loading " + reader.FileName);
try
{
var bundleFile = new BundleFile(reader, fullName);
var bundleFile = new BundleFile(reader);
foreach (var file in bundleFile.fileList)
{
var subReader = new EndianBinaryReader(file.stream);
if (SerializedFile.IsSerializedFile(subReader))
var dummyPath = Path.Combine(Path.GetDirectoryName(reader.FullPath), file.fileName);
var subReader = new FileReader(dummyPath, file.stream);
if (subReader.FileType == FileType.AssetsFile)
{
var dummyPath = Path.GetDirectoryName(fullName) + Path.DirectorySeparatorChar + file.fileName;
LoadAssetsFromMemory(dummyPath, subReader, parentPath ?? fullName, bundleFile.m_Header.unityRevision);
LoadAssetsFromMemory(subReader, originalPath ?? reader.FullPath, bundleFile.m_Header.unityRevision);
}
else
{
Expand All @@ -171,10 +170,10 @@ private void LoadBundleFile(string fullName, EndianBinaryReader reader, string p
}
catch (Exception e)
{
var str = $"Error while reading bundle file {fileName}";
if (parentPath != null)
var str = $"Error while reading bundle file {reader.FileName}";
if (originalPath != null)
{
str += $" from {Path.GetFileName(parentPath)}";
str += $" from {Path.GetFileName(originalPath)}";
}
Logger.Error(str, e);
}
Expand All @@ -184,36 +183,36 @@ private void LoadBundleFile(string fullName, EndianBinaryReader reader, string p
}
}

private void LoadWebFile(string fullName, EndianBinaryReader reader)
private void LoadWebFile(FileReader reader)
{
var fileName = Path.GetFileName(fullName);
Logger.Info("Loading " + fileName);
Logger.Info("Loading " + reader.FileName);
try
{
var webFile = new WebFile(reader);
foreach (var file in webFile.fileList)
{
var dummyPath = Path.Combine(Path.GetDirectoryName(fullName), file.fileName);
switch (CheckFileType(file.stream, out var fileReader))
var dummyPath = Path.Combine(Path.GetDirectoryName(reader.FullPath), file.fileName);
var subReader = new FileReader(dummyPath, file.stream);
switch (subReader.FileType)
{
case FileType.AssetsFile:
LoadAssetsFromMemory(dummyPath, fileReader, fullName);
LoadAssetsFromMemory(subReader, reader.FullPath);
break;
case FileType.BundleFile:
LoadBundleFile(dummyPath, fileReader, fullName);
LoadBundleFile(subReader, reader.FullPath);
break;
case FileType.WebFile:
LoadWebFile(dummyPath, fileReader);
LoadWebFile(subReader);
break;
case FileType.ResourceFile:
resourceFileReaders[file.fileName] = fileReader; //TODO
resourceFileReaders[file.fileName] = subReader; //TODO
break;
}
}
}
catch (Exception e)
{
Logger.Error($"Error while reading web file {fileName}", e);
Logger.Error($"Error while reading web file {reader.FileName}", e);
}
finally
{
Expand Down
14 changes: 7 additions & 7 deletions AssetStudio/BundleFile.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ public class Node

public StreamFile[] fileList;

public BundleFile(EndianBinaryReader reader, string path)
public BundleFile(FileReader reader)
{
m_Header = new Header();
m_Header.signature = reader.ReadStringToNull();
Expand All @@ -59,19 +59,19 @@ public BundleFile(EndianBinaryReader reader, string path)
goto case "UnityFS";
}
ReadHeaderAndBlocksInfo(reader);
using (var blocksStream = CreateBlocksStream(path))
using (var blocksStream = CreateBlocksStream(reader.FullPath))
{
ReadBlocksAndDirectory(reader, blocksStream);
ReadFiles(blocksStream, path);
ReadFiles(blocksStream, reader.FullPath);
}
break;
case "UnityFS":
ReadHeader(reader);
ReadBlocksInfoAndDirectory(reader);
using (var blocksStream = CreateBlocksStream(path))
using (var blocksStream = CreateBlocksStream(reader.FullPath))
{
ReadBlocks(reader, blocksStream);
ReadFiles(blocksStream, path);
ReadFiles(blocksStream, reader.FullPath);
}
break;
}
Expand Down Expand Up @@ -120,7 +120,7 @@ private Stream CreateBlocksStream(string path)
var uncompressedSizeSum = m_BlocksInfo.Sum(x => x.uncompressedSize);
if (uncompressedSizeSum >= int.MaxValue)
{
/*var memoryMappedFile = MemoryMappedFile.CreateNew(Path.GetFileName(path), uncompressedSizeSum);
/*var memoryMappedFile = MemoryMappedFile.CreateNew(null, uncompressedSizeSum);
assetsDataStream = memoryMappedFile.CreateViewStream();*/
blocksStream = new FileStream(path + ".temp", FileMode.Create, FileAccess.ReadWrite, FileShare.None, 4096, FileOptions.DeleteOnClose);
}
Expand Down Expand Up @@ -175,7 +175,7 @@ public void ReadFiles(Stream blocksStream, string path)
file.fileName = Path.GetFileName(node.path);
if (node.size >= int.MaxValue)
{
/*var memoryMappedFile = MemoryMappedFile.CreateNew(file.fileName, entryinfo_size);
/*var memoryMappedFile = MemoryMappedFile.CreateNew(null, entryinfo_size);
file.stream = memoryMappedFile.CreateViewStream();*/
var extractPath = path + "_unpacked" + Path.DirectorySeparatorChar;
Directory.CreateDirectory(extractPath);
Expand Down
98 changes: 98 additions & 0 deletions AssetStudio/FileReader.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
using System.IO;
using System.Linq;

namespace AssetStudio
{
public class FileReader : EndianBinaryReader
{
public string FullPath;
public string FileName;
public FileType FileType;

public FileReader(string path) : this(path, File.Open(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) { }

public FileReader(string path, Stream stream) : base(stream, EndianType.BigEndian)
{
FullPath = Path.GetFullPath(path);
FileName = Path.GetFileName(path);
CheckFileType();
}

private void CheckFileType()
{
var signature = this.ReadStringToNull(20);
Position = 0;
switch (signature)
{
case "UnityWeb":
case "UnityRaw":
case "UnityArchive":
case "UnityFS":
FileType = FileType.BundleFile;
break;
case "UnityWebData1.0":
FileType = FileType.WebFile;
break;
default:
var magic = ReadBytes(2);
Position = 0;
if (WebFile.gzipMagic.SequenceEqual(magic))
{
FileType = FileType.WebFile;
}
Position = 0x20;
magic = ReadBytes(6);
Position = 0;
if (WebFile.brotliMagic.SequenceEqual(magic))
{
FileType = FileType.WebFile;
}
if (IsSerializedFile())
{
FileType = FileType.AssetsFile;
}
else
{
FileType = FileType.ResourceFile;
}
break;
}
}

private bool IsSerializedFile()
{
var fileSize = BaseStream.Length;
if (fileSize < 20)
{
return false;
}
var m_MetadataSize = ReadUInt32();
long m_FileSize = ReadUInt32();
var m_Version = ReadUInt32();
long m_DataOffset = ReadUInt32();
var m_Endianess = ReadByte();
var m_Reserved = ReadBytes(3);
if (m_Version >= 22)
{
if (fileSize < 48)
{
Position = 0;
return false;
}
m_MetadataSize = ReadUInt32();
m_FileSize = ReadInt64();
m_DataOffset = ReadInt64();
}
Position = 0;
if (m_FileSize != fileSize)
{
return false;
}
if (m_DataOffset > fileSize)
{
return false;
}
return true;
}
}
}
16 changes: 16 additions & 0 deletions AssetStudio/FileType.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace AssetStudio
{
public enum FileType
{
AssetsFile,
BundleFile,
WebFile,
ResourceFile
}
}
Loading

0 comments on commit 7ab2cda

Please sign in to comment.