From 8946a4fba50f3a45aa81f50926341fb05df0ae27 Mon Sep 17 00:00:00 2001 From: Perfare Date: Thu, 18 Apr 2019 10:46:06 +0800 Subject: [PATCH] 2019.1 support --- AssetStudio/AssetStudio.csproj | 1 + AssetStudio/Classes/Avatar.cs | 2 + AssetStudio/Classes/Mesh.cs | 33 +++++- AssetStudio/Classes/Shader.cs | 15 ++- AssetStudio/Classes/Sprite.cs | 26 ++++- AssetStudio/CommonString.cs | 6 +- AssetStudio/SerializedFile.cs | 66 ++++++----- AssetStudio/TypeTreeHelper.cs | 120 ++++++++++---------- AssetStudio/TypeTreeNode.cs | 2 + AssetStudio/UType.cs | 155 ++++++++++++++++++++++++++ AssetStudioUtility/ShaderConverter.cs | 47 +++++--- 11 files changed, 360 insertions(+), 113 deletions(-) create mode 100644 AssetStudio/UType.cs diff --git a/AssetStudio/AssetStudio.csproj b/AssetStudio/AssetStudio.csproj index d1aa770..9781fef 100644 --- a/AssetStudio/AssetStudio.csproj +++ b/AssetStudio/AssetStudio.csproj @@ -65,6 +65,7 @@ + diff --git a/AssetStudio/Classes/Avatar.cs b/AssetStudio/Classes/Avatar.cs index 842b43e..97505ab 100644 --- a/AssetStudio/Classes/Avatar.cs +++ b/AssetStudio/Classes/Avatar.cs @@ -300,6 +300,8 @@ namespace AssetStudio { m_TOS[i] = new KeyValuePair(reader.ReadUInt32(), reader.ReadAlignedString()); } + + //HumanDescription m_HumanDescription 2019 and up } public string FindBonePath(uint hash) diff --git a/AssetStudio/Classes/Mesh.cs b/AssetStudio/Classes/Mesh.cs index 9e8e0a6..7bf2dac 100644 --- a/AssetStudio/Classes/Mesh.cs +++ b/AssetStudio/Classes/Mesh.cs @@ -1,10 +1,23 @@ using System; using System.Collections; using System.Collections.Generic; +using System.IO; using System.Linq; namespace AssetStudio { + public class MinMaxAABB + { + public Vector3 m_Min; + public Vector3 m_Max; + + public MinMaxAABB(BinaryReader reader) + { + m_Min = reader.ReadVector3(); + m_Max = reader.ReadVector3(); + } + } + public class CompressedMesh { public PackedFloatVector m_Vertices; @@ -490,8 +503,20 @@ namespace AssetStudio var m_RootBoneNameHash = reader.ReadUInt32(); } - if (version[0] > 2 || (version[0] == 2 && version[1] >= 6)) //2.6.0 and later + if (version[0] > 2 || (version[0] == 2 && version[1] >= 6)) //2.6.0 and up { + if (version[0] >= 2019) //2019 and up + { + var m_BonesAABBSize = reader.ReadInt32(); + var m_BonesAABB = new MinMaxAABB[m_BonesAABBSize]; + for (int i = 0; i < m_BonesAABBSize; i++) + { + m_BonesAABB[i] = new MinMaxAABB(reader); + } + + var m_VariableBoneCountWeights = reader.ReadUInt32Array(); + } + var m_MeshCompression = reader.ReadByte(); if (version[0] >= 4) { @@ -719,7 +744,7 @@ namespace AssetStudio int[] componentsIntArray = null; float[] componentsFloatArray = null; - if (m_Channel.format == 11) + if (m_Channel.format == 10 || m_Channel.format == 11) componentsIntArray = MeshHelper.BytesToIntArray(componentBytes); else componentsFloatArray = MeshHelper.BytesToFloatArray(componentBytes, componentByteSize); @@ -1075,6 +1100,10 @@ namespace AssetStudio return 1u; case 3: //kChannelFormatByte return 1u; + case 4: //kChannelFormatUInt32 + return 4u; + case 10: //kChannelFormatInt32 + return 4u; case 11: //kChannelFormatInt32 return 4u; default: diff --git a/AssetStudio/Classes/Shader.cs b/AssetStudio/Classes/Shader.cs index 5c658e6..8c98b3a 100644 --- a/AssetStudio/Classes/Shader.cs +++ b/AssetStudio/Classes/Shader.cs @@ -473,11 +473,22 @@ namespace AssetStudio m_BlobIndex = reader.ReadUInt32(); m_Channels = new ParserBindChannels(reader); - m_KeywordIndices = reader.ReadUInt16Array(); - if (version[0] >= 2017) //2017 and up + if (version[0] >= 2019) //2019 and up { + var m_GlobalKeywordIndices = reader.ReadUInt16Array(); + reader.AlignStream(); + var m_LocalKeywordIndices = reader.ReadUInt16Array(); reader.AlignStream(); } + else + { + m_KeywordIndices = reader.ReadUInt16Array(); + if (version[0] >= 2017) //2017 and up + { + reader.AlignStream(); + } + } + m_ShaderHardwareTier = reader.ReadSByte(); m_GpuProgramType = (ShaderGpuProgramType)reader.ReadSByte(); reader.AlignStream(); diff --git a/AssetStudio/Classes/Sprite.cs b/AssetStudio/Classes/Sprite.cs index 7500a52..8083908 100644 --- a/AssetStudio/Classes/Sprite.cs +++ b/AssetStudio/Classes/Sprite.cs @@ -1,9 +1,22 @@ using System; using System.Collections.Generic; using System.Drawing; +using System.IO; namespace AssetStudio { + public class SecondarySpriteTexture + { + public PPtr texture; + public string name; + + public SecondarySpriteTexture(ObjectReader reader) + { + texture = new PPtr(reader); + name = reader.ReadStringToNull(); + } + } + public enum SpritePackingRotation { kSPRNone = 0, @@ -27,7 +40,7 @@ namespace AssetStudio public SpritePackingMode packingMode; public SpritePackingRotation packingRotation; - public SpriteSettings(ObjectReader reader) + public SpriteSettings(BinaryReader reader) { settingsRaw = reader.ReadUInt32(); @@ -61,6 +74,7 @@ namespace AssetStudio { public PPtr texture; public PPtr alphaTexture; + public SecondarySpriteTexture[] secondaryTextures; public SubMesh[] m_SubMeshes; public byte[] m_IndexBuffer; public VertexData m_VertexData; @@ -85,6 +99,16 @@ namespace AssetStudio alphaTexture = new PPtr(reader); } + if (version[0] >= 2019) //2019 and up + { + var secondaryTexturesSize = reader.ReadInt32(); + secondaryTextures = new SecondarySpriteTexture[secondaryTexturesSize]; + for (int i = 0; i < secondaryTexturesSize; i++) + { + secondaryTextures[i] = new SecondarySpriteTexture(reader); + } + } + if (version[0] > 5 || (version[0] == 5 && version[1] >= 6)) //5.6 and up { var m_SubMeshesSize = reader.ReadInt32(); diff --git a/AssetStudio/CommonString.cs b/AssetStudio/CommonString.cs index 0fc0d60..965c3da 100644 --- a/AssetStudio/CommonString.cs +++ b/AssetStudio/CommonString.cs @@ -4,7 +4,7 @@ namespace AssetStudio { public static class CommonString { - public static readonly Dictionary StringBuffer = new Dictionary + public static readonly Dictionary StringBuffer = new Dictionary { {0, "AABB"}, {5, "AnimationClip"}, @@ -110,7 +110,9 @@ namespace AssetStudio {1057, "int2_storage"}, {1070, "int3_storage"}, {1083, "BoundsInt"}, - {1093, "m_CorrespondingSourceObject"} + {1093, "m_CorrespondingSourceObject"}, + {1121, "m_PrefabInstance"}, + {1138, "m_PrefabAsset"} }; } } diff --git a/AssetStudio/SerializedFile.cs b/AssetStudio/SerializedFile.cs index 53c8302..c1fa189 100644 --- a/AssetStudio/SerializedFile.cs +++ b/AssetStudio/SerializedFile.cs @@ -227,11 +227,11 @@ namespace AssetStudio return type; } - private void ReadTypeTree(List typeTree, int depth = 0) + private void ReadTypeTree(List typeTree, int level = 0) { var typeTreeNode = new TypeTreeNode(); typeTree.Add(typeTreeNode); - typeTreeNode.m_Level = depth; + typeTreeNode.m_Level = level; typeTreeNode.m_Type = reader.ReadStringToNull(); typeTreeNode.m_Name = reader.ReadStringToNull(); typeTreeNode.m_ByteSize = reader.ReadInt32(); @@ -253,7 +253,7 @@ namespace AssetStudio int childrenCount = reader.ReadInt32(); for (int i = 0; i < childrenCount; i++) { - ReadTypeTree(typeTree, depth + 1); + ReadTypeTree(typeTree, level + 1); } } @@ -262,10 +262,15 @@ namespace AssetStudio int numberOfNodes = reader.ReadInt32(); int stringBufferSize = reader.ReadInt32(); - reader.Position += numberOfNodes * 24; + var nodeSize = 24; + if (header.m_Version > 17) + { + nodeSize = 32; + } + reader.Position += numberOfNodes * nodeSize; using (var stringBufferReader = new BinaryReader(new MemoryStream(reader.ReadBytes(stringBufferSize)))) { - reader.Position -= numberOfNodes * 24 + stringBufferSize; + reader.Position -= numberOfNodes * nodeSize + stringBufferSize; for (int i = 0; i < numberOfNodes; i++) { var typeTreeNode = new TypeTreeNode(); @@ -273,37 +278,38 @@ namespace AssetStudio typeTreeNode.m_Version = reader.ReadUInt16(); typeTreeNode.m_Level = reader.ReadByte(); typeTreeNode.m_IsArray = reader.ReadBoolean() ? 1 : 0; - - var m_TypeStrOffset = reader.ReadUInt16(); - var temp = reader.ReadUInt16(); - if (temp == 0) - { - stringBufferReader.BaseStream.Position = m_TypeStrOffset; - typeTreeNode.m_Type = stringBufferReader.ReadStringToNull(); - } - else - { - typeTreeNode.m_Type = CommonString.StringBuffer.ContainsKey(m_TypeStrOffset) ? CommonString.StringBuffer[m_TypeStrOffset] : m_TypeStrOffset.ToString(); - } - - var m_NameStrOffset = reader.ReadUInt16(); - temp = reader.ReadUInt16(); - if (temp == 0) - { - stringBufferReader.BaseStream.Position = m_NameStrOffset; - typeTreeNode.m_Name = stringBufferReader.ReadStringToNull(); - } - else - { - typeTreeNode.m_Name = CommonString.StringBuffer.ContainsKey(m_NameStrOffset) ? CommonString.StringBuffer[m_NameStrOffset] : m_NameStrOffset.ToString(); - } - + 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 > 17) + { + reader.Position += 8; + } + + typeTreeNode.m_Type = ReadString(stringBufferReader, typeTreeNode.m_TypeStrOffset); + typeTreeNode.m_Name = ReadString(stringBufferReader, typeTreeNode.m_NameStrOffset); } reader.Position += stringBufferSize; } + + string ReadString(BinaryReader stringBufferReader, uint value) + { + var isOffset = (value & 0x80000000) == 0; + if (isOffset) + { + stringBufferReader.BaseStream.Position = value; + return stringBufferReader.ReadStringToNull(); + } + var offset = value & 0x7FFFFFFF; + if (CommonString.StringBuffer.TryGetValue(offset, out var str)) + { + return str; + } + return offset.ToString(); + } } } } diff --git a/AssetStudio/TypeTreeHelper.cs b/AssetStudio/TypeTreeHelper.cs index bbfedec..8e9cb82 100644 --- a/AssetStudio/TypeTreeHelper.cs +++ b/AssetStudio/TypeTreeHelper.cs @@ -153,10 +153,10 @@ namespace AssetStudio reader.AlignStream(); } - public static Dictionary ReadBoxingType(List members, BinaryReader reader) + public static UType ReadUType(List members, BinaryReader reader) { - var obj = new Dictionary(); - for (int i = 0; i < members.Count; i++) + var obj = new UType(); + for (int i = 1; i < members.Count; i++) { var member = members[i]; var varNameStr = member.m_Name; @@ -218,23 +218,6 @@ namespace AssetStudio value = reader.ReadAlignedString(); i += 3; break; - case "vector": - { - if ((members[i + 1].m_MetaFlag & 0x4000) != 0) - align = true; - 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; - list.Add(ReadValue(vector, reader, ref tmp)); - } - value = list; - break; - } case "map": { if ((members[i + 1].m_MetaFlag & 0x4000) != 0) @@ -265,22 +248,38 @@ namespace AssetStudio } default: { - if (i != members.Count && members[i + 1].m_Type == "Array") + if (i != members.Count && members[i + 1].m_Type == "Array") //Array { - goto case "vector"; + if ((members[i + 1].m_MetaFlag & 0x4000) != 0) + align = true; + 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; + list.Add(ReadValue(vector, reader, ref tmp)); + } + value = list; + break; } - var @class = GetMembers(members, level, i); - @class.RemoveAt(0); - i += @class.Count; - var obj = new Dictionary(); - for (int j = 0; j < @class.Count; j++) + else //Class { - var classmember = @class[j]; - var name = classmember.m_Name; - obj[name] = ReadValue(@class, reader, ref j); + var @class = GetMembers(members, level, i); + @class.RemoveAt(0); + i += @class.Count; + var obj = new UType(); + for (int j = 0; j < @class.Count; j++) + { + var classmember = @class[j]; + var name = classmember.m_Name; + obj[name] = ReadValue(@class, reader, ref j); + } + value = obj; + break; } - value = obj; - break; } } if (align) @@ -305,7 +304,7 @@ namespace AssetStudio return member2; } - public static byte[] WriteBoxingType(Dictionary obj, List members) + public static byte[] WriteUType(UType obj, List members) { var stream = new MemoryStream(); var write = new BinaryWriter(stream); @@ -370,23 +369,6 @@ namespace AssetStudio write.WriteAlignedString((string)value); i += 3; break; - case "vector": - { - 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; - } case "map": { if ((members[i + 1].m_MetaFlag & 0x4000) != 0) @@ -420,21 +402,37 @@ namespace AssetStudio } default: { - if (i != members.Count && members[i + 1].m_Type == "Array") + if (i != members.Count && members[i + 1].m_Type == "Array") //Array { - goto case "vector"; + 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; } - var @class = GetMembers(members, level, i); - @class.RemoveAt(0); - i += @class.Count; - var obj = (Dictionary)value; - for (int j = 0; j < @class.Count; j++) + else //Class { - var classmember = @class[j]; - var name = classmember.m_Name; - WriteValue(obj[name], @class, write, ref j); + 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; } - break; } } if (align) diff --git a/AssetStudio/TypeTreeNode.cs b/AssetStudio/TypeTreeNode.cs index 644cfe4..bf022d4 100644 --- a/AssetStudio/TypeTreeNode.cs +++ b/AssetStudio/TypeTreeNode.cs @@ -15,5 +15,7 @@ namespace AssetStudio public int m_Version; public int m_MetaFlag; public int m_Level; + public uint m_TypeStrOffset; + public uint m_NameStrOffset; } } diff --git a/AssetStudio/UType.cs b/AssetStudio/UType.cs new file mode 100644 index 0000000..d153889 --- /dev/null +++ b/AssetStudio/UType.cs @@ -0,0 +1,155 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace AssetStudio +{ + public class UType : IDictionary + { + private List keys; + private List 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; + } + } + + public object this[string key] + { + get + { + var index = GetValueIndex(key); + if (index != -1) + { + return values[index]; + } + else + { + return null; + } + } + set + { + var index = GetValueIndex(key); + if (index == -1) + { + keys.Add(key); + values.Add(value); + } + else + { + values[index] = value; + } + } + } + + public ICollection Keys => keys; + + public ICollection Values => values; + + public int Count => keys.Count; + + public bool IsReadOnly => false; + + public void Add(string key, object value) + { + keys.Add(key); + values.Add(value); + } + + public void Add(KeyValuePair item) + { + keys.Add(item.Key); + values.Add(item.Value); + } + + public void Clear() + { + keys.Clear(); + values.Clear(); + } + + public bool Contains(KeyValuePair item) + { + throw new NotImplementedException(); + } + + public bool ContainsKey(string key) + { + return GetValueIndex(key) != -1; + } + + public void CopyTo(KeyValuePair[] array, int arrayIndex) + { + throw new NotImplementedException(); + } + + public IEnumerator> GetEnumerator() + { + for (int i = 0, n = keys.Count; i < n; i++) + { + yield return new KeyValuePair(keys[i], values[i]); + } + } + + public bool Remove(string key) + { + throw new NotImplementedException(); + } + + public bool Remove(KeyValuePair item) + { + throw new NotImplementedException(); + } + + 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; + } + } + + IEnumerator IEnumerable.GetEnumerator() + { + return GetEnumerator(); + } + } +} diff --git a/AssetStudioUtility/ShaderConverter.cs b/AssetStudioUtility/ShaderConverter.cs index 3dc6a5e..4dbf268 100644 --- a/AssetStudioUtility/ShaderConverter.cs +++ b/AssetStudioUtility/ShaderConverter.cs @@ -30,7 +30,7 @@ namespace AssetStudio return ConvertMultiple(shader)[0]; } - return Encoding.UTF8.GetString(shader.m_Script); + return header + Encoding.UTF8.GetString(shader.m_Script); } public static string[] ConvertMultiple(Shader shader) @@ -51,7 +51,7 @@ namespace AssetStudio { var program = new ShaderProgram(blobReader); var m_Script = ConvertSerializedShader(shader.m_ParsedForm, shader.platforms[i]); - strs[i] = program.Export(m_Script); + strs[i] = header + program.Export(m_Script); } } @@ -544,6 +544,12 @@ namespace AssetStudio return "unknown"; } } + + private static string header = "//////////////////////////////////////////\n" + + "//\n" + + "// NOTE: This is *not* a valid shader file\n" + + "//\n" + + "///////////////////////////////////////////\n"; } public class ShaderProgram @@ -577,33 +583,44 @@ namespace AssetStudio public class ShaderSubProgram { - private int magic; + private int m_Version; public ShaderGpuProgramType m_ProgramType; public string[] m_Keywords; + public string[] m_LocalKeywords; public byte[] m_ProgramCode; public ShaderSubProgram(BinaryReader reader) { //LoadGpuProgramFromData - // 201509030 - Unity 5.3 - // 201510240 - Unity 5.4 - // 201608170 - Unity 5.5 - // 201609010 - Unity 5.6, 2017.1 & 2017.2 - // 201708220 - Unity 2017.3, Unity 2017.4 & Unity 2018.1 - // 201802150 - Unity 2018.2 & Unity 2018.3 - magic = reader.ReadInt32(); + //201509030 - Unity 5.3 + //201510240 - Unity 5.4 + //201608170 - Unity 5.5 + //201609010 - Unity 5.6, 2017.1 & 2017.2 + //201708220 - Unity 2017.3, Unity 2017.4 & Unity 2018.1 + //201802150 - Unity 2018.2 & Unity 2018.3 + //201806140 - Unity 2019.1 + m_Version = reader.ReadInt32(); m_ProgramType = (ShaderGpuProgramType)reader.ReadInt32(); reader.BaseStream.Position += 12; - if (magic >= 201608170) //5.5.0 and up + if (m_Version >= 201608170) { reader.BaseStream.Position += 4; } - var keywordCount = reader.ReadInt32(); - m_Keywords = new string[keywordCount]; - for (int i = 0; i < keywordCount; i++) + var m_KeywordsSize = reader.ReadInt32(); + m_Keywords = new string[m_KeywordsSize]; + for (int i = 0; i < m_KeywordsSize; i++) { m_Keywords[i] = reader.ReadAlignedString(); } + if (m_Version >= 201806140) + { + var m_LocalKeywordsSize = reader.ReadInt32(); + m_LocalKeywords = new string[m_LocalKeywordsSize]; + for (int i = 0; i < m_LocalKeywordsSize; i++) + { + m_LocalKeywords[i] = reader.ReadAlignedString(); + } + } m_ProgramCode = reader.ReadBytes(reader.ReadInt32()); reader.AlignStream(); @@ -660,7 +677,7 @@ namespace AssetStudio case ShaderGpuProgramType.kShaderGpuProgramDX11DomainSM50: { int start = 6; - if (magic == 201509030) // 5.3 + if (m_Version == 201509030) // 5.3 { start = 5; }