398 lines
11 KiB
C#
398 lines
11 KiB
C#
|
using System.Collections;
|
|||
|
using System.Collections.Generic;
|
|||
|
using System.IO;
|
|||
|
using UnityEngine;
|
|||
|
using static UnityFS.UnityBinUtils;
|
|||
|
|
|||
|
namespace UnityFS
|
|||
|
{
|
|||
|
public struct FileHeader
|
|||
|
{
|
|||
|
public const int kSize = 20;
|
|||
|
|
|||
|
public uint dataSize => fileSize - metadataSize;
|
|||
|
|
|||
|
public uint metadataSize;
|
|||
|
public uint fileSize;
|
|||
|
public uint version;
|
|||
|
public uint dataOffset;
|
|||
|
public byte endianess;
|
|||
|
|
|||
|
public void LoadFromStream(BinaryReader br)
|
|||
|
{
|
|||
|
long startPos = br.BaseStream.Position;
|
|||
|
metadataSize = br.ReadUInt32();
|
|||
|
fileSize = br.ReadUInt32();
|
|||
|
version = br.ReadUInt32();
|
|||
|
dataOffset = br.ReadUInt32();
|
|||
|
endianess = br.ReadByte();
|
|||
|
br.BaseStream.Position = startPos + kSize;
|
|||
|
|
|||
|
SwapEndianess();
|
|||
|
}
|
|||
|
|
|||
|
public long SaveToStream(BinaryWriter bw)
|
|||
|
{
|
|||
|
SwapEndianess();
|
|||
|
|
|||
|
long startPos = bw.BaseStream.Position;
|
|||
|
bw.Write(metadataSize);
|
|||
|
bw.Write(fileSize);
|
|||
|
bw.Write(version);
|
|||
|
bw.Write(dataOffset);
|
|||
|
bw.Write(endianess);
|
|||
|
bw.BaseStream.Position = startPos + kSize;
|
|||
|
return kSize;
|
|||
|
}
|
|||
|
|
|||
|
void SwapEndianess()
|
|||
|
{
|
|||
|
SwapUInt(ref metadataSize);
|
|||
|
SwapUInt(ref fileSize);
|
|||
|
SwapUInt(ref version);
|
|||
|
SwapUInt(ref dataOffset);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
public struct MetaData
|
|||
|
{
|
|||
|
public long dataStartPos;
|
|||
|
|
|||
|
public string version;
|
|||
|
public uint platform;
|
|||
|
public bool enableTypeTree;
|
|||
|
public int typeCount;
|
|||
|
public ObjectType[] types;
|
|||
|
public int objectCount;
|
|||
|
public Dictionary<long, ObjectInfo> objects;
|
|||
|
public int scriptTypeCount;
|
|||
|
public ScriptType[] scriptTypes;
|
|||
|
public int externalsCount;
|
|||
|
public ExternalInfo[] externals;
|
|||
|
|
|||
|
#if UNITY_2019_2_OR_NEWER
|
|||
|
public int refTypeCount;
|
|||
|
public ObjectType[] refTypes;
|
|||
|
#endif
|
|||
|
public string dummyStr;
|
|||
|
|
|||
|
public void LoadFromStream(BinaryReader br, uint dataOffset)
|
|||
|
{
|
|||
|
long startPos = br.BaseStream.Position;
|
|||
|
dataStartPos = startPos;
|
|||
|
|
|||
|
version = br.ReadRawString();
|
|||
|
platform = br.ReadUInt32();
|
|||
|
enableTypeTree = br.ReadBoolean();
|
|||
|
typeCount = br.ReadInt32();
|
|||
|
types = new ObjectType[typeCount];
|
|||
|
|
|||
|
for (int i = 0; i < typeCount; i++)
|
|||
|
{
|
|||
|
types[i].LoadFromStream(br);
|
|||
|
}
|
|||
|
|
|||
|
objectCount = br.ReadInt32();
|
|||
|
objects = new Dictionary<long, ObjectInfo>();
|
|||
|
for(int i = 0; i < objectCount; i++)
|
|||
|
{
|
|||
|
long id = br.AlignedReadInt64();
|
|||
|
ObjectInfo objInfo = new ObjectInfo();
|
|||
|
objInfo.LoadFromStream(br);
|
|||
|
objInfo.realPos = objInfo.dataPos + dataOffset;
|
|||
|
|
|||
|
objects.Add(id, objInfo);
|
|||
|
}
|
|||
|
|
|||
|
scriptTypeCount = br.ReadInt32();
|
|||
|
scriptTypes = new ScriptType[scriptTypeCount];
|
|||
|
for(int i = 0; i < scriptTypeCount; i++)
|
|||
|
{
|
|||
|
scriptTypes[i].LoadFromStream(br);
|
|||
|
}
|
|||
|
|
|||
|
externalsCount = br.ReadInt32();
|
|||
|
externals = new ExternalInfo[externalsCount];
|
|||
|
for(int i = 0; i < externalsCount; i++)
|
|||
|
{
|
|||
|
externals[i].LoadFromStream(br);
|
|||
|
}
|
|||
|
|
|||
|
#if UNITY_2019_2_OR_NEWER
|
|||
|
refTypeCount = br.ReadInt32();
|
|||
|
refTypes = new ObjectType[refTypeCount];
|
|||
|
for(int i = 0; i < refTypeCount; i++)
|
|||
|
{
|
|||
|
refTypes[i].LoadFromStream(br);
|
|||
|
}
|
|||
|
#endif
|
|||
|
dummyStr = br.ReadRawString();
|
|||
|
}
|
|||
|
|
|||
|
public long SaveToStream(BinaryWriter bw)
|
|||
|
{
|
|||
|
long startPos = bw.BaseStream.Position;
|
|||
|
bw.WriteRawString(version);
|
|||
|
bw.Write(platform);
|
|||
|
bw.Write(enableTypeTree);
|
|||
|
|
|||
|
bw.Write(typeCount);
|
|||
|
foreach(var type in types)
|
|||
|
type.SaveToStream(bw);
|
|||
|
|
|||
|
bw.Write(objectCount);
|
|||
|
foreach (var kv in objects)
|
|||
|
{
|
|||
|
bw.AlignedWriteInt64(kv.Key);
|
|||
|
kv.Value.SaveToStream(bw);
|
|||
|
}
|
|||
|
|
|||
|
bw.Write(scriptTypeCount);
|
|||
|
foreach(var st in scriptTypes)
|
|||
|
st.SaveToStream(bw);
|
|||
|
|
|||
|
bw.Write(externalsCount);
|
|||
|
foreach(var external in externals)
|
|||
|
external.SaveToStream(bw);
|
|||
|
|
|||
|
#if UNITY_2019_2_OR_NEWER
|
|||
|
bw.Write(refTypeCount);
|
|||
|
foreach(var refT in refTypes)
|
|||
|
refT.SaveToStream(bw);
|
|||
|
#endif
|
|||
|
|
|||
|
bw.WriteRawString(dummyStr);
|
|||
|
|
|||
|
return bw.BaseStream.Position - startPos;
|
|||
|
}
|
|||
|
|
|||
|
public ScriptsData GetScriptData(BinaryReader br)
|
|||
|
{
|
|||
|
ObjectInfo objInfo = objects[UnityBinFile.kMonoManagerIdx];
|
|||
|
br.BaseStream.Seek(objInfo.realPos, SeekOrigin.Begin);
|
|||
|
|
|||
|
ScriptsData data = new ScriptsData();
|
|||
|
data.LoadFromStream(br);
|
|||
|
return data;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
public struct ObjectType
|
|||
|
{
|
|||
|
public int typeID;
|
|||
|
public bool isStriped;
|
|||
|
public short scriptTypeIndex;
|
|||
|
|
|||
|
public bool needReadScriptHash; // dont save
|
|||
|
|
|||
|
public Hash scriptSigHash;
|
|||
|
public Hash typeHash;
|
|||
|
|
|||
|
public void LoadFromStream(BinaryReader br)
|
|||
|
{
|
|||
|
typeID = br.ReadInt32();
|
|||
|
isStriped = br.ReadBoolean();
|
|||
|
scriptTypeIndex = br.ReadInt16();
|
|||
|
|
|||
|
needReadScriptHash = typeID == -1 || typeID == 0x72;
|
|||
|
if(needReadScriptHash)
|
|||
|
scriptSigHash.LoadFromStream(br);
|
|||
|
|
|||
|
typeHash.LoadFromStream(br);
|
|||
|
|
|||
|
// GlobalManagers does not has TypeTrees
|
|||
|
}
|
|||
|
|
|||
|
public long SaveToStream(BinaryWriter bw)
|
|||
|
{
|
|||
|
long startPos = bw.BaseStream.Position;
|
|||
|
bw.Write(typeID);
|
|||
|
bw.Write(isStriped);
|
|||
|
bw.Write(scriptTypeIndex);
|
|||
|
|
|||
|
if(needReadScriptHash)
|
|||
|
scriptSigHash.SaveToStream(bw);
|
|||
|
|
|||
|
typeHash.SaveToStream(bw);
|
|||
|
return bw.BaseStream.Position - startPos;
|
|||
|
}
|
|||
|
|
|||
|
public int Size()
|
|||
|
{
|
|||
|
int ret = 0;
|
|||
|
ret += sizeof(int);
|
|||
|
ret += sizeof(bool);
|
|||
|
ret += sizeof(short);
|
|||
|
|
|||
|
if (needReadScriptHash)
|
|||
|
ret += Hash.kSize;
|
|||
|
|
|||
|
ret += Hash.kSize;
|
|||
|
return ret;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
public struct ObjectInfo
|
|||
|
{
|
|||
|
public const int kSize = 12;
|
|||
|
|
|||
|
public uint dataPos;
|
|||
|
public uint size;
|
|||
|
public uint typeID;
|
|||
|
|
|||
|
public uint realPos; // dataPos + Header.dataOffset; // dont save
|
|||
|
|
|||
|
public void LoadFromStream(BinaryReader br)
|
|||
|
{
|
|||
|
dataPos = br.ReadUInt32();
|
|||
|
size = br.ReadUInt32();
|
|||
|
typeID = br.ReadUInt32();
|
|||
|
}
|
|||
|
|
|||
|
public long SaveToStream(BinaryWriter bw)
|
|||
|
{
|
|||
|
bw.Write(dataPos);
|
|||
|
bw.Write(size);
|
|||
|
bw.Write(typeID);
|
|||
|
return kSize;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
public struct ScriptType
|
|||
|
{
|
|||
|
public int localFileIndex;
|
|||
|
public long localIdentifierOfBin;
|
|||
|
|
|||
|
public void LoadFromStream(BinaryReader br)
|
|||
|
{
|
|||
|
localFileIndex = br.ReadInt32();
|
|||
|
localIdentifierOfBin = br.AlignedReadInt64();
|
|||
|
}
|
|||
|
|
|||
|
public long SaveToStream(BinaryWriter bw)
|
|||
|
{
|
|||
|
long startPos = bw.BaseStream.Position;
|
|||
|
bw.Write(localFileIndex);
|
|||
|
bw.AlignedWriteInt64(localIdentifierOfBin);
|
|||
|
return bw.BaseStream.Position - startPos;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
public struct ExternalInfo
|
|||
|
{
|
|||
|
public string dummy;
|
|||
|
public Hash guid;
|
|||
|
public int type;
|
|||
|
public string name;
|
|||
|
|
|||
|
public void LoadFromStream(BinaryReader br)
|
|||
|
{
|
|||
|
dummy = br.ReadRawString();
|
|||
|
guid.LoadFromStream(br);
|
|||
|
type = br.ReadInt32();
|
|||
|
name = br.ReadRawString();
|
|||
|
}
|
|||
|
|
|||
|
public long SaveToStream(BinaryWriter bw)
|
|||
|
{
|
|||
|
long startPos = bw.BaseStream.Position;
|
|||
|
bw.WriteRawString(dummy);
|
|||
|
guid.SaveToStream(bw);
|
|||
|
bw.Write(type);
|
|||
|
bw.WriteRawString(name);
|
|||
|
return bw.BaseStream.Position - startPos;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
public struct ScriptsData
|
|||
|
{
|
|||
|
public ScriptID[] scriptIDs;
|
|||
|
public List<string> dllNames;
|
|||
|
public List<int> dllTypes; // 16 is user type
|
|||
|
|
|||
|
public void LoadFromStream(BinaryReader br)
|
|||
|
{
|
|||
|
{
|
|||
|
int count = br.ReadInt32();
|
|||
|
scriptIDs = new ScriptID[count];
|
|||
|
for(int i = 0; i < count; i++)
|
|||
|
scriptIDs[i].LoadFromStream(br);
|
|||
|
}
|
|||
|
{
|
|||
|
int count = br.ReadInt32();
|
|||
|
dllNames = new List<string>(count);
|
|||
|
for (var i = 0; i < count; i++)
|
|||
|
dllNames.Add(br.ReadSizeString());
|
|||
|
}
|
|||
|
{
|
|||
|
int count = br.ReadInt32();
|
|||
|
dllTypes = new List<int>(count);
|
|||
|
for(var i = 0; i < count; i++)
|
|||
|
dllTypes.Add(br.ReadInt32());
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
public long SaveToStream(BinaryWriter bw)
|
|||
|
{
|
|||
|
long startPos = bw.BaseStream.Position;
|
|||
|
bw.Write(scriptIDs.Length);
|
|||
|
for(int i = 0; i < scriptIDs.Length; i++)
|
|||
|
scriptIDs[i].SaveToStream(bw);
|
|||
|
|
|||
|
bw.Write(dllNames.Count);
|
|||
|
for(int i = 0, imax = dllNames.Count; i < imax; i++)
|
|||
|
bw.WriteSizeString(dllNames[i]);
|
|||
|
|
|||
|
bw.Write(dllTypes.Count);
|
|||
|
for(int i = 0, imax = dllTypes.Count; i < imax; i++)
|
|||
|
bw.Write(dllTypes[i]);
|
|||
|
|
|||
|
return bw.BaseStream.Position - startPos;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
public struct ScriptID
|
|||
|
{
|
|||
|
public int fileID;
|
|||
|
public long pathID; // localIdentifier
|
|||
|
|
|||
|
public void LoadFromStream(BinaryReader br)
|
|||
|
{
|
|||
|
fileID = br.ReadInt32();
|
|||
|
pathID = br.ReadInt64();
|
|||
|
}
|
|||
|
|
|||
|
public long SaveToStream(BinaryWriter bw)
|
|||
|
{
|
|||
|
bw.Write(fileID);
|
|||
|
bw.Write(pathID);
|
|||
|
return 4 + 8;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
public struct Hash
|
|||
|
{
|
|||
|
public const int kSize = 16;
|
|||
|
|
|||
|
public int[] data;
|
|||
|
|
|||
|
public void LoadFromStream(BinaryReader br)
|
|||
|
{
|
|||
|
data = new int[4];
|
|||
|
for(int i = 0; i < data.Length; i++)
|
|||
|
{
|
|||
|
data[i] = br.ReadInt32();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
public long SaveToStream(BinaryWriter bw)
|
|||
|
{
|
|||
|
for(int i = 0; i < data.Length; i++)
|
|||
|
{
|
|||
|
bw.Write(data[i]);
|
|||
|
}
|
|||
|
return kSize;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|