mirror of
https://github.com/Dongyifengs/AssetStudio-Genshin-MoYi.git
synced 2025-04-20 11:39:20 +08:00
117 lines
3.8 KiB
C#
117 lines
3.8 KiB
C#
using System.IO;
|
|
using System.Linq;
|
|
|
|
namespace AssetStudio
|
|
{
|
|
public class FileReader : EndianBinaryReader
|
|
{
|
|
public string FullPath;
|
|
public string FileName;
|
|
public FileType FileType;
|
|
public long Length;
|
|
|
|
private static readonly byte[] gzipMagic = { 0x1f, 0x8b };
|
|
private static readonly byte[] brotliMagic = { 0x62, 0x72, 0x6F, 0x74, 0x6C, 0x69 };
|
|
private static readonly byte[] zipMagic = { 0x50, 0x4B, 0x03, 0x04 };
|
|
private static readonly byte[] zipSpannedMagic = { 0x50, 0x4B, 0x07, 0x08 };
|
|
|
|
public FileReader(string path, Game game = null) : this(path, File.Open(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite), game) { }
|
|
|
|
public FileReader(string path, Stream stream, Game game = null) : base(stream, EndianType.BigEndian, game)
|
|
{
|
|
Game = game;
|
|
FullPath = Path.GetFullPath(path);
|
|
FileName = Path.GetFileName(path);
|
|
FileType = CheckFileType();
|
|
Length = stream.Length;
|
|
|
|
}
|
|
|
|
private FileType CheckFileType()
|
|
{
|
|
if (IsSerializedFile())
|
|
{
|
|
return FileType.AssetsFile;
|
|
}
|
|
else if (Game != null)
|
|
{
|
|
return FileType.GameFile;
|
|
}
|
|
|
|
var signature = this.ReadStringToNull(20);
|
|
Position = 0;
|
|
switch (signature)
|
|
{
|
|
case "UnityWeb":
|
|
case "UnityRaw":
|
|
case "UnityArchive":
|
|
case "UnityFS":
|
|
return FileType.BundleFile;
|
|
case "UnityWebData1.0":
|
|
return FileType.WebFile;
|
|
default:
|
|
{
|
|
byte[] magic = ReadBytes(2);
|
|
Position = 0;
|
|
if (gzipMagic.SequenceEqual(magic))
|
|
{
|
|
return FileType.GZipFile;
|
|
}
|
|
Position = 0x20;
|
|
magic = ReadBytes(6);
|
|
Position = 0;
|
|
if (brotliMagic.SequenceEqual(magic))
|
|
{
|
|
return FileType.BrotliFile;
|
|
}
|
|
if (IsSerializedFile())
|
|
{
|
|
return FileType.AssetsFile;
|
|
}
|
|
magic = ReadBytes(4);
|
|
Position = 0;
|
|
if (zipMagic.SequenceEqual(magic) || zipSpannedMagic.SequenceEqual(magic))
|
|
return FileType.ZipFile;
|
|
return FileType.ResourceFile;
|
|
}
|
|
}
|
|
}
|
|
|
|
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;
|
|
}
|
|
}
|
|
}
|