hybridclr_unity/Editor/3rds/UnityFS/UnityBinFileDefines.cs

398 lines
11 KiB
C#
Raw Normal View History

2022-09-22 08:56:07 +08:00
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;
}
}
}