diff --git a/AssetStudio/SerializedFile.cs b/AssetStudio/SerializedFile.cs index 9aa28b5..3167bce 100644 --- a/AssetStudio/SerializedFile.cs +++ b/AssetStudio/SerializedFile.cs @@ -24,6 +24,7 @@ namespace AssetStudio public BuildTarget m_TargetPlatform = BuildTarget.UnknownPlatform; private bool m_EnableTypeTree = true; public List m_Types; + public List m_RefTypes; public List m_Objects; private List m_ScriptTypes; public List m_Externals; @@ -133,7 +134,6 @@ namespace AssetStudio { objectInfo.classID = reader.ReadUInt16(); objectInfo.serializedType = m_Types.Find(x => x.classID == objectInfo.typeID); - var isDestroyed = reader.ReadUInt16(); } else { @@ -141,6 +141,16 @@ namespace AssetStudio objectInfo.serializedType = type; objectInfo.classID = type.classID; } + if (header.m_Version < 11) + { + var isDestroyed = reader.ReadUInt16(); + } + if (header.m_Version >= 11 && header.m_Version < 17) + { + var m_ScriptTypeIndex = reader.ReadInt16(); + if (objectInfo.serializedType != null) + objectInfo.serializedType.m_ScriptTypeIndex = m_ScriptTypeIndex; + } if (header.m_Version == 15 || header.m_Version == 16) { var stripped = reader.ReadByte(); @@ -188,15 +198,22 @@ namespace AssetStudio m_Externals.Add(m_External); } - if (header.m_Version >= 5) + if (header.m_Version >= 20) { - //var userInformation = reader.ReadStringToNull(); + int refTypesCount = reader.ReadInt32(); + m_RefTypes = new List(refTypesCount); + for (int i = 0; i < refTypesCount; i++) + { + m_RefTypes.Add(ReadSerializedType()); + } } - if (header.m_Version >= 21) + if (header.m_Version >= 5) { - //var unknown = reader.ReadInt32(); + var userInformation = reader.ReadStringToNull(); } + + //reader.AlignStream(16); } public void SetVersion(string stringVersion) @@ -247,11 +264,7 @@ namespace AssetStudio if (header.m_Version >= 21) { - var count = reader.ReadInt32(); - if (count > 0) - { - reader.Position += 4 * count; - } + type.m_TypeDependencies = reader.ReadInt32Array(); } type.m_Nodes = typeTree; @@ -294,38 +307,33 @@ namespace AssetStudio { int numberOfNodes = reader.ReadInt32(); int stringBufferSize = reader.ReadInt32(); - - var nodeSize = 24; - if (header.m_Version >= 19) + for (int i = 0; i < numberOfNodes; i++) { - nodeSize = 32; + var typeTreeNode = new TypeTreeNode(); + typeTree.Add(typeTreeNode); + typeTreeNode.m_Version = reader.ReadUInt16(); + typeTreeNode.m_Level = reader.ReadByte(); + typeTreeNode.m_IsArray = reader.ReadBoolean() ? 1 : 0; + typeTreeNode.m_TypeStrOffset = reader.ReadUInt32(); + typeTreeNode.m_NameStrOffset = reader.ReadUInt32(); + typeTreeNode.m_ByteSize = reader.ReadInt32(); + typeTreeNode.m_Index = reader.ReadInt32(); + typeTreeNode.m_MetaFlag = reader.ReadInt32(); + if (header.m_Version >= 19) + { + typeTreeNode.m_RefTypeHash = reader.ReadUInt64(); + } } - reader.Position += numberOfNodes * nodeSize; - using (var stringBufferReader = new BinaryReader(new MemoryStream(reader.ReadBytes(stringBufferSize)))) + var m_StringBuffer = reader.ReadBytes(stringBufferSize); + + using (var stringBufferReader = new BinaryReader(new MemoryStream(m_StringBuffer))) { - reader.Position -= numberOfNodes * nodeSize + stringBufferSize; for (int i = 0; i < numberOfNodes; i++) { - var typeTreeNode = new TypeTreeNode(); - typeTree.Add(typeTreeNode); - typeTreeNode.m_Version = reader.ReadUInt16(); - typeTreeNode.m_Level = reader.ReadByte(); - typeTreeNode.m_IsArray = reader.ReadBoolean() ? 1 : 0; - typeTreeNode.m_TypeStrOffset = reader.ReadUInt32(); - typeTreeNode.m_NameStrOffset = reader.ReadUInt32(); - typeTreeNode.m_ByteSize = reader.ReadInt32(); - typeTreeNode.m_Index = reader.ReadInt32(); - typeTreeNode.m_MetaFlag = reader.ReadInt32(); - + var typeTreeNode = typeTree[i]; typeTreeNode.m_Type = ReadString(stringBufferReader, typeTreeNode.m_TypeStrOffset); typeTreeNode.m_Name = ReadString(stringBufferReader, typeTreeNode.m_NameStrOffset); - - if (header.m_Version >= 19) - { - reader.Position += 8; - } } - reader.Position += stringBufferSize; } string ReadString(BinaryReader stringBufferReader, uint value) diff --git a/AssetStudio/SerializedType.cs b/AssetStudio/SerializedType.cs index 12c16e9..a4f61f2 100644 --- a/AssetStudio/SerializedType.cs +++ b/AssetStudio/SerializedType.cs @@ -13,5 +13,6 @@ namespace AssetStudio public List m_Nodes; public byte[] m_ScriptID; //Hash128 public byte[] m_OldTypeHash; //Hash128 + public int[] m_TypeDependencies; } } diff --git a/AssetStudio/TypeTreeHelper.cs b/AssetStudio/TypeTreeHelper.cs index 8e9cb82..6f28bdf 100644 --- a/AssetStudio/TypeTreeHelper.cs +++ b/AssetStudio/TypeTreeHelper.cs @@ -31,6 +31,7 @@ namespace AssetStudio value = reader.ReadSByte(); break; case "UInt8": + case "char": value = reader.ReadByte(); break; case "short": @@ -56,6 +57,7 @@ namespace AssetStudio break; case "UInt64": case "unsigned long long": + case "FileSize": value = reader.ReadUInt64(); break; case "float": @@ -73,26 +75,6 @@ namespace AssetStudio sb.AppendFormat("{0}{1} {2} = \"{3}\"\r\n", (new string('\t', level)), varTypeStr, varNameStr, str); i += 3; break; - case "vector": - { - if ((members[i + 1].m_MetaFlag & 0x4000) != 0) - align = true; - append = false; - sb.AppendFormat("{0}{1} {2}\r\n", (new string('\t', level)), varTypeStr, varNameStr); - sb.AppendFormat("{0}{1} {2}\r\n", (new string('\t', level + 1)), "Array", "Array"); - var size = reader.ReadInt32(); - sb.AppendFormat("{0}{1} {2} = {3}\r\n", (new string('\t', level + 1)), "int", "size", size); - var vector = GetMembers(members, level, i); - i += vector.Count - 1; - vector.RemoveRange(0, 3); - for (int j = 0; j < size; j++) - { - sb.AppendFormat("{0}[{1}]\r\n", (new string('\t', level + 2)), j); - int tmp = 0; - ReadStringValue(sb, vector, reader, ref tmp); - } - break; - } case "map": { if ((members[i + 1].m_MetaFlag & 0x4000) != 0) @@ -102,12 +84,11 @@ namespace AssetStudio sb.AppendFormat("{0}{1} {2}\r\n", (new string('\t', level + 1)), "Array", "Array"); var size = reader.ReadInt32(); sb.AppendFormat("{0}{1} {2} = {3}\r\n", (new string('\t', level + 1)), "int", "size", size); - var map = GetMembers(members, level, i); + var map = GetMembers(members, i); i += map.Count - 1; - map.RemoveRange(0, 4); - var first = GetMembers(map, map[0].m_Level, 0); - map.RemoveRange(0, first.Count); - var second = map; + var first = GetMembers(map, 4); + var next = 4 + first.Count; + var second = GetMembers(map, next); for (int j = 0; j < size; j++) { sb.AppendFormat("{0}[{1}]\r\n", (new string('\t', level + 2)), j); @@ -131,20 +112,37 @@ namespace AssetStudio } default: { - if (i != members.Count && members[i + 1].m_Type == "Array") + if (i < members.Count - 1 && members[i + 1].m_Type == "Array") //Array { - goto case "vector"; + if ((members[i + 1].m_MetaFlag & 0x4000) != 0) + align = true; + append = false; + sb.AppendFormat("{0}{1} {2}\r\n", (new string('\t', level)), varTypeStr, varNameStr); + sb.AppendFormat("{0}{1} {2}\r\n", (new string('\t', level + 1)), "Array", "Array"); + var size = reader.ReadInt32(); + sb.AppendFormat("{0}{1} {2} = {3}\r\n", (new string('\t', level + 1)), "int", "size", size); + var vector = GetMembers(members, i); + i += vector.Count - 1; + for (int j = 0; j < size; j++) + { + sb.AppendFormat("{0}[{1}]\r\n", (new string('\t', level + 2)), j); + int tmp = 3; + ReadStringValue(sb, vector, reader, ref tmp); + } + break; } - append = false; - sb.AppendFormat("{0}{1} {2}\r\n", (new string('\t', level)), varTypeStr, varNameStr); - var @class = GetMembers(members, level, i); - @class.RemoveAt(0); - i += @class.Count; - for (int j = 0; j < @class.Count; j++) + else //Class { - ReadStringValue(sb, @class, reader, ref j); + append = false; + sb.AppendFormat("{0}{1} {2}\r\n", (new string('\t', level)), varTypeStr, varNameStr); + var @class = GetMembers(members, i); + i += @class.Count - 1; + for (int j = 1; j < @class.Count; j++) + { + ReadStringValue(sb, @class, reader, ref j); + } + break; } - break; } } if (append) @@ -168,7 +166,6 @@ namespace AssetStudio private static object ReadValue(List members, BinaryReader reader, ref int i) { var member = members[i]; - var level = member.m_Level; var varTypeStr = member.m_Type; object value; var align = (member.m_MetaFlag & 0x4000) != 0; @@ -178,6 +175,7 @@ namespace AssetStudio value = reader.ReadSByte(); break; case "UInt8": + case "char": value = reader.ReadByte(); break; case "short": @@ -203,6 +201,7 @@ namespace AssetStudio break; case "UInt64": case "unsigned long long": + case "FileSize": value = reader.ReadUInt64(); break; case "float": @@ -222,14 +221,13 @@ namespace AssetStudio { if ((members[i + 1].m_MetaFlag & 0x4000) != 0) align = true; + var map = GetMembers(members, i); + i += map.Count - 1; + var first = GetMembers(map, 4); + var next = 4 + first.Count; + var second = GetMembers(map, next); var size = reader.ReadInt32(); var dic = new List>(size); - var map = GetMembers(members, level, i); - i += map.Count - 1; - map.RemoveRange(0, 4); - var first = GetMembers(map, map[0].m_Level, 0); - map.RemoveRange(0, first.Count); - var second = map; for (int j = 0; j < size; j++) { int tmp1 = 0; @@ -248,18 +246,17 @@ namespace AssetStudio } default: { - if (i != members.Count && members[i + 1].m_Type == "Array") //Array + if (i < members.Count - 1 && members[i + 1].m_Type == "Array") //Array { if ((members[i + 1].m_MetaFlag & 0x4000) != 0) align = true; + var vector = GetMembers(members, i); + i += vector.Count - 1; var size = reader.ReadInt32(); var list = new List(size); - var vector = GetMembers(members, level, i); - i += vector.Count - 1; - vector.RemoveRange(0, 3); for (int j = 0; j < size; j++) { - int tmp = 0; + int tmp = 3; list.Add(ReadValue(vector, reader, ref tmp)); } value = list; @@ -267,11 +264,10 @@ namespace AssetStudio } else //Class { - var @class = GetMembers(members, level, i); - @class.RemoveAt(0); - i += @class.Count; + var @class = GetMembers(members, i); + i += @class.Count - 1; var obj = new UType(); - for (int j = 0; j < @class.Count; j++) + for (int j = 1; j < @class.Count; j++) { var classmember = @class[j]; var name = classmember.m_Name; @@ -287,10 +283,11 @@ namespace AssetStudio return value; } - private static List GetMembers(List members, int level, int index) + private static List GetMembers(List members, int index) { var member2 = new List(); - member2.Add(members[0]); + member2.Add(members[index]); + var level = members[index].m_Level; for (int i = index + 1; i < members.Count; i++) { var member = members[i]; @@ -303,140 +300,5 @@ namespace AssetStudio } return member2; } - - public static byte[] WriteUType(UType obj, List members) - { - var stream = new MemoryStream(); - var write = new BinaryWriter(stream); - for (int i = 0; i < members.Count; i++) - { - var member = members[i]; - var varNameStr = member.m_Name; - WriteValue(obj[varNameStr], members, write, ref i); - } - return stream.ToArray(); - } - - private static void WriteValue(object value, List members, BinaryWriter write, ref int i) - { - var member = members[i]; - var level = member.m_Level; - var varTypeStr = member.m_Type; - var align = (member.m_MetaFlag & 0x4000) != 0; - switch (varTypeStr) - { - case "SInt8": - write.Write((sbyte)value); - break; - case "UInt8": - write.Write((byte)value); - break; - case "short": - case "SInt16": - write.Write((short)value); - break; - case "UInt16": - case "unsigned short": - write.Write((ushort)value); - break; - case "int": - case "SInt32": - write.Write((int)value); - break; - case "UInt32": - case "unsigned int": - case "Type*": - write.Write((uint)value); - break; - case "long long": - case "SInt64": - write.Write((long)value); - break; - case "UInt64": - case "unsigned long long": - write.Write((ulong)value); - break; - case "float": - write.Write((float)value); - break; - case "double": - write.Write((double)value); - break; - case "bool": - write.Write((bool)value); - break; - case "string": - write.WriteAlignedString((string)value); - i += 3; - break; - case "map": - { - if ((members[i + 1].m_MetaFlag & 0x4000) != 0) - align = true; - var dic = (List>)value; - var size = dic.Count; - write.Write(size); - var map = GetMembers(members, level, i); - i += map.Count - 1; - map.RemoveRange(0, 4); - var first = GetMembers(map, map[0].m_Level, 0); - map.RemoveRange(0, first.Count); - var second = map; - for (int j = 0; j < size; j++) - { - int tmp1 = 0; - int tmp2 = 0; - WriteValue(dic[j].Key, first, write, ref tmp1); - WriteValue(dic[j].Value, second, write, ref tmp2); - } - break; - } - case "TypelessData": - { - var bytes = ((object[])value).Cast().ToArray(); - var size = bytes.Length; - write.Write(size); - write.Write(bytes); - i += 2; - break; - } - default: - { - if (i != members.Count && members[i + 1].m_Type == "Array") //Array - { - if ((members[i + 1].m_MetaFlag & 0x4000) != 0) - align = true; - var list = (List)value; - var size = list.Count; - write.Write(size); - var vector = GetMembers(members, level, i); - i += vector.Count - 1; - vector.RemoveRange(0, 3); - for (int j = 0; j < size; j++) - { - int tmp = 0; - WriteValue(list[j], vector, write, ref tmp); - } - break; - } - else //Class - { - var @class = GetMembers(members, level, i); - @class.RemoveAt(0); - i += @class.Count; - var obj = (UType)value; - for (int j = 0; j < @class.Count; j++) - { - var classmember = @class[j]; - var name = classmember.m_Name; - WriteValue(obj[name], @class, write, ref j); - } - break; - } - } - } - if (align) - write.AlignStream(4); - } } } diff --git a/AssetStudio/TypeTreeNode.cs b/AssetStudio/TypeTreeNode.cs index bf022d4..642612e 100644 --- a/AssetStudio/TypeTreeNode.cs +++ b/AssetStudio/TypeTreeNode.cs @@ -11,11 +11,12 @@ namespace AssetStudio public string m_Name; public int m_ByteSize; public int m_Index; - public int m_IsArray; + public int m_IsArray; //m_TypeFlags public int m_Version; public int m_MetaFlag; public int m_Level; public uint m_TypeStrOffset; public uint m_NameStrOffset; + public ulong m_RefTypeHash; } } diff --git a/AssetStudio/UType.cs b/AssetStudio/UType.cs index d153889..2b7902a 100644 --- a/AssetStudio/UType.cs +++ b/AssetStudio/UType.cs @@ -9,73 +9,37 @@ namespace AssetStudio public class UType : IDictionary { private List keys; - private List values; + private IDictionary values; public UType() { keys = new List(); - values = new List(); - } - - private int GetValueIndex(string name) - { - for (int i = 0, n = keys.Count; i < n; i++) - { - if (string.Equals(keys[i], name, StringComparison.Ordinal)) - { - return i; - } - } - return -1; - } - - public bool TryGetValue(string key, out T value) - { - var index = GetValueIndex(key); - if (index != -1) - { - value = (T)values[index]; - return true; - } - else - { - value = default(T); - return false; - } + values = new Dictionary(); } public object this[string key] { get { - var index = GetValueIndex(key); - if (index != -1) - { - return values[index]; - } - else + if (!values.ContainsKey(key)) { return null; } + return values[key]; } set { - var index = GetValueIndex(key); - if (index == -1) + if (!values.ContainsKey(key)) { keys.Add(key); - values.Add(value); - } - else - { - values[index] = value; } + values[key] = value; } } public ICollection Keys => keys; - public ICollection Values => values; + public ICollection Values => values.Values; public int Count => keys.Count; @@ -84,13 +48,13 @@ namespace AssetStudio public void Add(string key, object value) { keys.Add(key); - values.Add(value); + values.Add(key, value); } public void Add(KeyValuePair item) { keys.Add(item.Key); - values.Add(item.Value); + values.Add(item); } public void Clear() @@ -101,55 +65,44 @@ namespace AssetStudio public bool Contains(KeyValuePair item) { - throw new NotImplementedException(); + return values.Contains(item); } public bool ContainsKey(string key) { - return GetValueIndex(key) != -1; + return values.ContainsKey(key); } public void CopyTo(KeyValuePair[] array, int arrayIndex) { - throw new NotImplementedException(); + values.CopyTo(array, arrayIndex); } public IEnumerator> GetEnumerator() { - for (int i = 0, n = keys.Count; i < n; i++) - { - yield return new KeyValuePair(keys[i], values[i]); - } + return values.GetEnumerator(); } public bool Remove(string key) { - throw new NotImplementedException(); + keys.Remove(key); + return values.Remove(key); } public bool Remove(KeyValuePair item) { - throw new NotImplementedException(); + keys.Remove(item.Key); + return values.Remove(item); } public bool TryGetValue(string key, out object value) { - var index = GetValueIndex(key); - if (index != -1) - { - value = values[index]; - return true; - } - else - { - value = null; - return false; - } + return values.TryGetValue(key, out value); } IEnumerator IEnumerable.GetEnumerator() { - return GetEnumerator(); + return values.GetEnumerator(); } } }