diff --git a/UnityAsset.NET/Compression/LZ4.cs b/UnityAsset.NET/Compression/LZ4.cs index 9cb34d4..d7822a3 100644 --- a/UnityAsset.NET/Compression/LZ4.cs +++ b/UnityAsset.NET/Compression/LZ4.cs @@ -106,8 +106,10 @@ public static int EncodeFast(ReadOnlySpan source, Span target) } int literalLen = (int) (s - anchor); int matchLen = 4; - while (s + matchLen < sourceEnd && *(s + matchLen) == *(sourceOffset + matchLen)) + while (s + matchLen < sourceEnd) { + if (*(s + matchLen) != *(sourceOffset + matchLen)) + break; matchLen++; } int token = Math.Min(literalLen, 15) << 4 | Math.Min(matchLen - 4, 15); diff --git a/UnityAsset.NET/Hash128.cs b/UnityAsset.NET/Hash128.cs new file mode 100644 index 0000000..affbd96 --- /dev/null +++ b/UnityAsset.NET/Hash128.cs @@ -0,0 +1,49 @@ +using System.Text; +using UnityAsset.NET.IO; + +namespace UnityAsset.NET; + +public struct Hash128 +{ + public byte[] data; //16 bytes + + public Hash128(byte[] data) + { + this.data = data; + } + public Hash128(AssetReader reader) + { + data = reader.ReadBytes(16); + } + + public bool IsZero() + { + if (data == null) + return true; + + for (int i = 0; i < data.Length; i++) + { + if (data[i] != 0) + return false; + } + + return true; + } + + public override string ToString() + { + StringBuilder hex = new StringBuilder(data.Length * 2); + + foreach (byte b in data) + { + hex.AppendFormat("{0:x2}", b); + } + + return hex.ToString(); + } + + public static Hash128 NewBlankHash() + { + return new Hash128() { data = new byte[16] }; + } +} \ No newline at end of file diff --git a/UnityAsset.NET/SerializedFile/SerializedFileHeader.cs b/UnityAsset.NET/SerializedFile/SerializedFileHeader.cs index 0ab4353..f6af819 100644 --- a/UnityAsset.NET/SerializedFile/SerializedFileHeader.cs +++ b/UnityAsset.NET/SerializedFile/SerializedFileHeader.cs @@ -1,4 +1,5 @@ -using UnityAsset.NET.Enums; +using System.Text; +using UnityAsset.NET.Enums; using UnityAsset.NET.IO; namespace UnityAsset.NET.SerializedFile; @@ -6,10 +7,10 @@ namespace UnityAsset.NET.SerializedFile; public sealed class SerializedFileHeader { public uint MetadataSize; - public long FileSize; + public ulong FileSize; public SerializedFileFormatVersion Version; - public long DataOffset; - public byte Endianess; + public ulong DataOffset; + public bool Endianess; public SerializedFileHeader(AssetReader reader) { @@ -20,25 +21,31 @@ public SerializedFileHeader(AssetReader reader) if (Version < SerializedFileFormatVersion.Unknown_9) { - throw new Exception("Unsupported version."); + throw new Exception($"Unsupported version: {Version}"); } - Endianess = reader.ReadByte(); + Endianess = reader.ReadBoolean(); reader.ReadBytes(3);// unused bytes if (Version >= SerializedFileFormatVersion.LargeFilesSupport) { MetadataSize = reader.ReadUInt32(); - FileSize = reader.ReadUInt32(); - DataOffset = reader.ReadUInt32(); + FileSize = reader.ReadUInt64(); + DataOffset = reader.ReadUInt64(); reader.ReadInt64(); // unknown } - reader.BigEndian = Endianess == 1; + reader.BigEndian = Endianess; } public override string ToString() { - return $"MetadataSize: 0x{MetadataSize:X8} | FileSize: 0x{FileSize:X8} | Version: {Version} | DataOffset: 0x{DataOffset:X8} | Endianness: {(EndianType)Endianess}"; + StringBuilder sb = new StringBuilder(); + sb.AppendFormat("MetadataSize: 0x{0:X8} | ", MetadataSize); + sb.AppendFormat("FileSize: 0x{0:X8} | ", FileSize); + sb.AppendFormat("Version: {0} | ", Version); + sb.AppendFormat("DataOffset: 0x{0:X8} | ", DataOffset); + sb.AppendFormat("Endianness: {0}", Endianess ? "BigEndian" : "LittleEndian"); + return sb.ToString(); } } \ No newline at end of file diff --git a/UnityAsset.NET/SerializedFile/SerializedFileMetadata.cs b/UnityAsset.NET/SerializedFile/SerializedFileMetadata.cs index 4a48540..b00faeb 100644 --- a/UnityAsset.NET/SerializedFile/SerializedFileMetadata.cs +++ b/UnityAsset.NET/SerializedFile/SerializedFileMetadata.cs @@ -1,10 +1,11 @@ -using UnityAsset.NET.Enums; +using System.Text; +using UnityAsset.NET.Enums; using UnityAsset.NET.IO; namespace UnityAsset.NET.SerializedFile; -public class SerializedFileMetadata +public sealed class SerializedFileMetadata { public string UnityVersion; @@ -16,7 +17,7 @@ public class SerializedFileMetadata public SerializedFileMetadata(AssetReader reader, SerializedFileFormatVersion version) { - UnityVersion = reader.ReadStringToNull(); + UnityVersion = reader.ReadNullTerminated(); Platform = (BuildTarget)reader.ReadUInt32(); if (version >= SerializedFileFormatVersion.HasTypeTreeHashes) { @@ -29,5 +30,18 @@ public SerializedFileMetadata(AssetReader reader, SerializedFileFormatVersion ve { Types.Add(new SerializedType(reader, version, TypeTreeEnabled, false)); } + + int assetCount = reader.ReadInt32(); + reader.AlignStream(4); + } + + public override string ToString() + { + StringBuilder sb = new StringBuilder(); + sb.AppendFormat("UnityVersion: {0} | ", UnityVersion); + sb.AppendFormat("Platform: {0} | ", Platform); + sb.AppendFormat("TypeTreeEnabled: {0} | ", TypeTreeEnabled); + sb.AppendFormat("Types: {0}", Types.Count); + return sb.ToString(); } } \ No newline at end of file diff --git a/UnityAsset.NET/SerializedFile/SerializedType.cs b/UnityAsset.NET/SerializedFile/SerializedType.cs index a69b18a..7c47b6c 100644 --- a/UnityAsset.NET/SerializedFile/SerializedType.cs +++ b/UnityAsset.NET/SerializedFile/SerializedType.cs @@ -4,7 +4,7 @@ namespace UnityAsset.NET.SerializedFile; -public class SerializedType +public sealed class SerializedType { public int ClassID; @@ -12,6 +12,20 @@ public class SerializedType public short ScriptTypeIndex; + public Hash128 ScriptIdHash; + + public Hash128 TypeHash; + + public bool IsRefType; + + public List Nodes; + + public byte[] StringBufferBytes; + + public int[] TypeDependencies; + + public SerializedTypeReference TypeReference; + public SerializedType(AssetReader reader, SerializedFileFormatVersion version, bool typeTreeEnabled, bool isRefType) { ClassID = reader.ReadInt32(); @@ -34,7 +48,39 @@ public SerializedType(AssetReader reader, SerializedFileFormatVersion version, b (version >= RefactorTypeData && ClassID == (int)AssetClassID.MonoBehaviour) || (isRefType && ScriptTypeIndex > 0)) { - //ScriptIdHash = new Hash128(reader); + ScriptIdHash = new Hash128(reader); + } + + TypeHash = new Hash128(reader); + IsRefType = isRefType; + + if (typeTreeEnabled) + { + int typeTreeNodeCount = reader.ReadInt32(); + int stringBufferLen = reader.ReadInt32(); + Nodes = new List(typeTreeNodeCount); + for (int i = 0; i < typeTreeNodeCount; i++) + { + Nodes.Add(new SerializedType(reader, version, typeTreeEnabled, false)); + } + StringBufferBytes = reader.ReadBytes(stringBufferLen); + if (version >= StoresTypeDependencies) + { + if (!isRefType) + { + int dependenciesCount = reader.ReadInt32(); + TypeDependencies = new int[dependenciesCount]; + for (int i = 0; i < dependenciesCount; i++) + { + TypeDependencies[i] = reader.ReadInt32(); + } + } + else + { + TypeReference = new SerializedTypeReference(); + TypeReference.ReadMetadata(reader); + } + } } } } \ No newline at end of file diff --git a/UnityAsset.NET/SerializedFile/SerializedTypeReference.cs b/UnityAsset.NET/SerializedFile/SerializedTypeReference.cs new file mode 100644 index 0000000..328cb21 --- /dev/null +++ b/UnityAsset.NET/SerializedFile/SerializedTypeReference.cs @@ -0,0 +1,28 @@ +using UnityAsset.NET.IO; + +namespace UnityAsset.NET.SerializedFile; + +public class SerializedTypeReference +{ + public string ClassName; + + public string Namespace; + + public string AsmName; + + public SerializedTypeReference() { } + + public SerializedTypeReference(string className, string nameSpace, string asmName) + { + ClassName = className; + Namespace = nameSpace; + AsmName = asmName; + } + + public void ReadMetadata(AssetReader reader) + { + ClassName = reader.ReadNullTerminated(); + Namespace = reader.ReadNullTerminated(); + AsmName = reader.ReadNullTerminated(); + } +} \ No newline at end of file diff --git a/UnityAsset.NET/UnityAsset.NET.csproj b/UnityAsset.NET/UnityAsset.NET.csproj index dbb6c32..d1cec10 100644 --- a/UnityAsset.NET/UnityAsset.NET.csproj +++ b/UnityAsset.NET/UnityAsset.NET.csproj @@ -6,14 +6,14 @@ enable AXiX A .NET library for reading and modifying Unity assets and bundles. - 0.0.3 + 0.0.4-beta.1 UnityAsset.NET AXiX https://github.com/AXiX-official/UnityAsset.NET https://github.com/AXiX-official/UnityAsset.NET true - 0.0.3 - 0.0.3 + 0.0.4.1 + 0.0.4.1 True README.md Unity