diff --git a/AssetStudio/AssetStudio.csproj b/AssetStudio/AssetStudio.csproj index 93d89a3..59b0e1b 100644 --- a/AssetStudio/AssetStudio.csproj +++ b/AssetStudio/AssetStudio.csproj @@ -85,6 +85,14 @@ Libraries\OpenTK.GLControl.dll False + + Libraries\SharpDX.dll + False + + + Libraries\SharpDX.D3DCompiler.dll + False + Libraries\SharpDX.Mathematics.dll False @@ -198,6 +206,7 @@ + diff --git a/AssetStudio/AssetStudioForm.cs b/AssetStudio/AssetStudioForm.cs index 1902876..5d080aa 100644 --- a/AssetStudio/AssetStudioForm.cs +++ b/AssetStudio/AssetStudioForm.cs @@ -816,11 +816,9 @@ namespace AssetStudio } case ClassIDType.Shader: { - Shader m_TextAsset = new Shader(reader); - string m_Script_Text = Encoding.UTF8.GetString(m_TextAsset.m_Script); - m_Script_Text = Regex.Replace(m_Script_Text, "(? m_MatrixParams { get; set; } + public List m_VectorParams { get; set; } + + public StructParameter(BinaryReader reader) + { + var m_NameIndex = reader.ReadInt32(); + var m_Index = reader.ReadInt32(); + var m_ArraySize = reader.ReadInt32(); + var m_StructSize = reader.ReadInt32(); + + int numVectorParams = reader.ReadInt32(); + m_VectorParams = new List(numVectorParams); + for (int i = 0; i < numVectorParams; i++) + { + m_VectorParams.Add(new VectorParameter(reader)); + } + + int numMatrixParams = reader.ReadInt32(); + m_MatrixParams = new List(numMatrixParams); + for (int i = 0; i < numMatrixParams; i++) + { + m_MatrixParams.Add(new MatrixParameter(reader)); + } + } + } + + public class SamplerParameter + { + public uint sampler { get; set; } + public int bindPoint { get; set; } + + public SamplerParameter(BinaryReader reader) + { + sampler = reader.ReadUInt32(); + bindPoint = reader.ReadInt32(); + } + } + + public class SerializedTextureProperty + { + public string m_DefaultName { get; set; } + public int m_TexDim { get; set; } + + public SerializedTextureProperty(BinaryReader reader) + { + m_DefaultName = reader.ReadAlignedString(); + m_TexDim = reader.ReadInt32(); + } + } + + public class SerializedProperty + { + public string m_Name { get; set; } + public string m_Description { get; set; } + public List m_Attributes { get; set; } + public int m_Type { get; set; } + public uint m_Flags { get; set; } + public List m_DefValue { get; set; } + public SerializedTextureProperty m_DefTexture { get; set; } + + public SerializedProperty(BinaryReader reader) + { + m_Name = reader.ReadAlignedString(); + m_Description = reader.ReadAlignedString(); + + int numAttributes = reader.ReadInt32(); + m_Attributes = new List(numAttributes); + for (int i = 0; i < numAttributes; i++) + { + m_Attributes.Add(reader.ReadAlignedString()); + } + + m_Type = reader.ReadInt32(); + m_Flags = reader.ReadUInt32(); + + int numValues = 4; + m_DefValue = new List(numValues); + for (int i = 0; i < numValues; i++) + { + m_DefValue.Add(reader.ReadSingle()); + } + + m_DefTexture = new SerializedTextureProperty(reader); + } + } + + public class SerializedProperties + { + public List m_Props { get; set; } + + public SerializedProperties(BinaryReader reader) + { + int numProps = reader.ReadInt32(); + m_Props = new List(numProps); + for (int i = 0; i < numProps; i++) + { + m_Props.Add(new SerializedProperty(reader)); + } + } + } + + public class SerializedShaderFloatValue + { + public float val { get; set; } + public string name { get; set; } + + public SerializedShaderFloatValue(BinaryReader reader) + { + val = reader.ReadSingle(); + name = reader.ReadAlignedString(); + } + } + + public class SerializedShaderRTBlendState + { + public SerializedShaderFloatValue srcBlend { get; set; } + public SerializedShaderFloatValue destBlend { get; set; } + public SerializedShaderFloatValue srcBlendAlpha { get; set; } + public SerializedShaderFloatValue destBlendAlpha { get; set; } + public SerializedShaderFloatValue blendOp { get; set; } + public SerializedShaderFloatValue blendOpAlpha { get; set; } + public SerializedShaderFloatValue colMask { get; set; } + + public SerializedShaderRTBlendState(BinaryReader reader) + { + srcBlend = new SerializedShaderFloatValue(reader); + destBlend = new SerializedShaderFloatValue(reader); + srcBlendAlpha = new SerializedShaderFloatValue(reader); + destBlendAlpha = new SerializedShaderFloatValue(reader); + blendOp = new SerializedShaderFloatValue(reader); + blendOpAlpha = new SerializedShaderFloatValue(reader); + colMask = new SerializedShaderFloatValue(reader); + } + } + + public class SerializedStencilOp + { + public SerializedShaderFloatValue pass { get; set; } + public SerializedShaderFloatValue fail { get; set; } + public SerializedShaderFloatValue zFail { get; set; } + public SerializedShaderFloatValue comp { get; set; } + + public SerializedStencilOp(BinaryReader reader) + { + pass = new SerializedShaderFloatValue(reader); + fail = new SerializedShaderFloatValue(reader); + zFail = new SerializedShaderFloatValue(reader); + comp = new SerializedShaderFloatValue(reader); + } + } + + public class SerializedShaderVectorValue + { + public SerializedShaderFloatValue x { get; set; } + public SerializedShaderFloatValue y { get; set; } + public SerializedShaderFloatValue z { get; set; } + public SerializedShaderFloatValue w { get; set; } + public string name { get; set; } + + public SerializedShaderVectorValue(BinaryReader reader) + { + x = new SerializedShaderFloatValue(reader); + y = new SerializedShaderFloatValue(reader); + z = new SerializedShaderFloatValue(reader); + w = new SerializedShaderFloatValue(reader); + name = reader.ReadAlignedString(); + } + } + + public class SerializedShaderState + { + public string m_Name { get; set; } + public SerializedShaderRTBlendState rtBlend0 { get; set; } + public SerializedShaderRTBlendState rtBlend1 { get; set; } + public SerializedShaderRTBlendState rtBlend2 { get; set; } + public SerializedShaderRTBlendState rtBlend3 { get; set; } + public SerializedShaderRTBlendState rtBlend4 { get; set; } + public SerializedShaderRTBlendState rtBlend5 { get; set; } + public SerializedShaderRTBlendState rtBlend6 { get; set; } + public SerializedShaderRTBlendState rtBlend7 { get; set; } + public bool rtSeparateBlend { get; set; } + public SerializedShaderFloatValue zClip { get; set; } + public SerializedShaderFloatValue zTest { get; set; } + public SerializedShaderFloatValue zWrite { get; set; } + public SerializedShaderFloatValue culling { get; set; } + public SerializedShaderFloatValue offsetFactor { get; set; } + public SerializedShaderFloatValue offsetUnits { get; set; } + public SerializedShaderFloatValue alphaToMask { get; set; } + public SerializedStencilOp stencilOp { get; set; } + public SerializedStencilOp stencilOpFront { get; set; } + public SerializedStencilOp stencilOpBack { get; set; } + public SerializedShaderFloatValue stencilReadMask { get; set; } + public SerializedShaderFloatValue stencilWriteMask { get; set; } + public SerializedShaderFloatValue stencilRef { get; set; } + public SerializedShaderFloatValue fogStart { get; set; } + public SerializedShaderFloatValue fogEnd { get; set; } + public SerializedShaderFloatValue fogDensity { get; set; } + public SerializedShaderVectorValue fogColor { get; set; } + public int fogMode { get; set; } + public int gpuProgramID { get; set; } + public SerializedTagMap m_Tags { get; set; } + public int m_LOD { get; set; } + public bool lighting { get; set; } + + public SerializedShaderState(ObjectReader reader) + { + var version = reader.version; + + m_Name = reader.ReadAlignedString(); + rtBlend0 = new SerializedShaderRTBlendState(reader); + rtBlend1 = new SerializedShaderRTBlendState(reader); + rtBlend2 = new SerializedShaderRTBlendState(reader); + rtBlend3 = new SerializedShaderRTBlendState(reader); + rtBlend4 = new SerializedShaderRTBlendState(reader); + rtBlend5 = new SerializedShaderRTBlendState(reader); + rtBlend6 = new SerializedShaderRTBlendState(reader); + rtBlend7 = new SerializedShaderRTBlendState(reader); + rtSeparateBlend = reader.ReadBoolean(); + reader.AlignStream(4); + if (version[0] > 2017 || (version[0] == 2017 && version[1] >= 2)) //2017.2 and up + { + zClip = new SerializedShaderFloatValue(reader); + } + zTest = new SerializedShaderFloatValue(reader); + zWrite = new SerializedShaderFloatValue(reader); + culling = new SerializedShaderFloatValue(reader); + offsetFactor = new SerializedShaderFloatValue(reader); + offsetUnits = new SerializedShaderFloatValue(reader); + alphaToMask = new SerializedShaderFloatValue(reader); + stencilOp = new SerializedStencilOp(reader); + stencilOpFront = new SerializedStencilOp(reader); + stencilOpBack = new SerializedStencilOp(reader); + stencilReadMask = new SerializedShaderFloatValue(reader); + stencilWriteMask = new SerializedShaderFloatValue(reader); + stencilRef = new SerializedShaderFloatValue(reader); + fogStart = new SerializedShaderFloatValue(reader); + fogEnd = new SerializedShaderFloatValue(reader); + fogDensity = new SerializedShaderFloatValue(reader); + fogColor = new SerializedShaderVectorValue(reader); + fogMode = reader.ReadInt32(); + gpuProgramID = reader.ReadInt32(); + m_Tags = new SerializedTagMap(reader); + m_LOD = reader.ReadInt32(); + lighting = reader.ReadBoolean(); + reader.AlignStream(4); + } + } + + public class ShaderBindChannel + { + public sbyte source { get; set; } + public sbyte target { get; set; } + + public ShaderBindChannel(BinaryReader reader) + { + source = reader.ReadSByte(); + target = reader.ReadSByte(); + } + } + + public class ParserBindChannels + { + public List m_Channels { get; set; } + public uint m_SourceMap { get; set; } + + public ParserBindChannels(BinaryReader reader) + { + int numChannels = reader.ReadInt32(); + m_Channels = new List(numChannels); + for (int i = 0; i < numChannels; i++) + { + m_Channels.Add(new ShaderBindChannel(reader)); + } + reader.AlignStream(4); + + m_SourceMap = reader.ReadUInt32(); + } + } + + public class VectorParameter + { + public int m_NameIndex { get; set; } + public int m_Index { get; set; } + public int m_ArraySize { get; set; } + public sbyte m_Type { get; set; } + public sbyte m_Dim { get; set; } + + public VectorParameter(BinaryReader reader) + { + m_NameIndex = reader.ReadInt32(); + m_Index = reader.ReadInt32(); + m_ArraySize = reader.ReadInt32(); + m_Type = reader.ReadSByte(); + m_Dim = reader.ReadSByte(); + reader.AlignStream(4); + } + } + + public class MatrixParameter + { + public int m_NameIndex { get; set; } + public int m_Index { get; set; } + public int m_ArraySize { get; set; } + public sbyte m_Type { get; set; } + public sbyte m_RowCount { get; set; } + + public MatrixParameter(BinaryReader reader) + { + m_NameIndex = reader.ReadInt32(); + m_Index = reader.ReadInt32(); + m_ArraySize = reader.ReadInt32(); + m_Type = reader.ReadSByte(); + m_RowCount = reader.ReadSByte(); + reader.AlignStream(4); + } + } + + public class TextureParameter + { + public int m_NameIndex { get; set; } + public int m_Index { get; set; } + public int m_SamplerIndex { get; set; } + public sbyte m_Dim { get; set; } + + public TextureParameter(ObjectReader reader) + { + var version = reader.version; + + m_NameIndex = reader.ReadInt32(); + m_Index = reader.ReadInt32(); + m_SamplerIndex = reader.ReadInt32(); + if (version[0] > 2017 || (version[0] == 2017 && version[1] >= 3)) //2017.3 and up + { + var m_MultiSampled = reader.ReadBoolean(); + } + m_Dim = reader.ReadSByte(); + reader.AlignStream(4); + } + } + + public class BufferBinding + { + public int m_NameIndex { get; set; } + public int m_Index { get; set; } + + public BufferBinding(BinaryReader reader) + { + m_NameIndex = reader.ReadInt32(); + m_Index = reader.ReadInt32(); + } + } + + public class ConstantBuffer + { + public int m_NameIndex { get; set; } + public List m_MatrixParams { get; set; } + public List m_VectorParams { get; set; } + public List m_StructParams { get; set; } + public int m_Size { get; set; } + + public ConstantBuffer(ObjectReader reader) + { + var version = reader.version; + + m_NameIndex = reader.ReadInt32(); + + int numMatrixParams = reader.ReadInt32(); + m_MatrixParams = new List(numMatrixParams); + for (int i = 0; i < numMatrixParams; i++) + { + m_MatrixParams.Add(new MatrixParameter(reader)); + } + + int numVectorParams = reader.ReadInt32(); + m_VectorParams = new List(numVectorParams); + for (int i = 0; i < numVectorParams; i++) + { + m_VectorParams.Add(new VectorParameter(reader)); + } + if (version[0] > 2017 || (version[0] == 2017 && version[1] >= 3)) //2017.3 and up + { + int numStructParams = reader.ReadInt32(); + m_StructParams = new List(numStructParams); + for (int i = 0; i < numStructParams; i++) + { + m_StructParams.Add(new StructParameter(reader)); + } + } + m_Size = reader.ReadInt32(); + } + } + + public class UAVParameter + { + public int m_NameIndex { get; set; } + public int m_Index { get; set; } + public int m_OriginalIndex { get; set; } + + public UAVParameter(BinaryReader reader) + { + m_NameIndex = reader.ReadInt32(); + m_Index = reader.ReadInt32(); + m_OriginalIndex = reader.ReadInt32(); + } + } + + public class SerializedSubProgram + { + public uint m_BlobIndex { get; set; } + public ParserBindChannels m_Channels { get; set; } + public List m_KeywordIndices { get; set; } + public sbyte m_ShaderHardwareTier { get; set; } + public sbyte m_GpuProgramType { get; set; } + public List m_VectorParams { get; set; } + public List m_MatrixParams { get; set; } + public List m_TextureParams { get; set; } + public List m_BufferParams { get; set; } + public List m_ConstantBuffers { get; set; } + public List m_ConstantBufferBindings { get; set; } + public List m_UAVParams { get; set; } + public List m_Samplers { get; set; } + + public SerializedSubProgram(ObjectReader reader) + { + var version = reader.version; + + m_BlobIndex = reader.ReadUInt32(); + m_Channels = new ParserBindChannels(reader); + + int numIndices = reader.ReadInt32(); + m_KeywordIndices = new List(numIndices); + for (int i = 0; i < numIndices; i++) + { + m_KeywordIndices.Add(reader.ReadUInt16()); + } + if (version[0] >= 2017) //2017 and up + { + reader.AlignStream(4); + } + m_ShaderHardwareTier = reader.ReadSByte(); + m_GpuProgramType = reader.ReadSByte(); + reader.AlignStream(4); + + int numVectorParams = reader.ReadInt32(); + m_VectorParams = new List(numVectorParams); + for (int i = 0; i < numVectorParams; i++) + { + m_VectorParams.Add(new VectorParameter(reader)); + } + + int numMatrixParams = reader.ReadInt32(); + m_MatrixParams = new List(numMatrixParams); + for (int i = 0; i < numMatrixParams; i++) + { + m_MatrixParams.Add(new MatrixParameter(reader)); + } + + int numTextureParams = reader.ReadInt32(); + m_TextureParams = new List(numTextureParams); + for (int i = 0; i < numTextureParams; i++) + { + m_TextureParams.Add(new TextureParameter(reader)); + } + + int numBufferParams = reader.ReadInt32(); + m_BufferParams = new List(numBufferParams); + for (int i = 0; i < numBufferParams; i++) + { + m_BufferParams.Add(new BufferBinding(reader)); + } + + int numConstantBuffers = reader.ReadInt32(); + m_ConstantBuffers = new List(numConstantBuffers); + for (int i = 0; i < numConstantBuffers; i++) + { + m_ConstantBuffers.Add(new ConstantBuffer(reader)); + } + + int numConstantBufferBindings = reader.ReadInt32(); + m_ConstantBufferBindings = new List(numConstantBufferBindings); + for (int i = 0; i < numConstantBufferBindings; i++) + { + m_ConstantBufferBindings.Add(new BufferBinding(reader)); + } + + int numUAVParams = reader.ReadInt32(); + m_UAVParams = new List(numUAVParams); + for (int i = 0; i < numUAVParams; i++) + { + m_UAVParams.Add(new UAVParameter(reader)); + } + + if (version[0] >= 2017) //2017 and up + { + int numSamplers = reader.ReadInt32(); + m_Samplers = new List(numSamplers); + for (int i = 0; i < numSamplers; i++) + { + m_Samplers.Add(new SamplerParameter(reader)); + } + } + if (version[0] > 2017 || (version[0] == 2017 && version[1] >= 2)) //2017.2 and up + { + var m_ShaderRequirements = reader.ReadInt32(); + } + } + } + + public class SerializedProgram + { + public List m_SubPrograms { get; set; } + + public SerializedProgram(ObjectReader reader) + { + int numSubPrograms = reader.ReadInt32(); + m_SubPrograms = new List(numSubPrograms); + for (int i = 0; i < numSubPrograms; i++) + { + m_SubPrograms.Add(new SerializedSubProgram(reader)); + } + } + } + + public class SerializedPass + { + public List> m_NameIndices { get; set; } + public int m_Type { get; set; } + public SerializedShaderState m_State { get; set; } + public uint m_ProgramMask { get; set; } + public SerializedProgram progVertex { get; set; } + public SerializedProgram progFragment { get; set; } + public SerializedProgram progGeometry { get; set; } + public SerializedProgram progHull { get; set; } + public SerializedProgram progDomain { get; set; } + public bool m_HasInstancingVariant { get; set; } + public string m_UseName { get; set; } + public string m_Name { get; set; } + public string m_TextureName { get; set; } + public SerializedTagMap m_Tags { get; set; } + + public SerializedPass(ObjectReader reader) + { + var version = reader.version; + + int numIndices = reader.ReadInt32(); + m_NameIndices = new List>(numIndices); + for (int i = 0; i < numIndices; i++) + { + m_NameIndices.Add(new KeyValuePair(reader.ReadAlignedString(), reader.ReadInt32())); + } + + m_Type = reader.ReadInt32(); + m_State = new SerializedShaderState(reader); + m_ProgramMask = reader.ReadUInt32(); + progVertex = new SerializedProgram(reader); + progFragment = new SerializedProgram(reader); + progGeometry = new SerializedProgram(reader); + progHull = new SerializedProgram(reader); + progDomain = new SerializedProgram(reader); + m_HasInstancingVariant = reader.ReadBoolean(); + if (version[0] >= 2018) //2018 and up + { + var m_HasProceduralInstancingVariant = reader.ReadBoolean(); + } + reader.AlignStream(4); + m_UseName = reader.ReadAlignedString(); + m_Name = reader.ReadAlignedString(); + m_TextureName = reader.ReadAlignedString(); + m_Tags = new SerializedTagMap(reader); + } + } + + public class SerializedTagMap + { + public List> tags { get; set; } + + public SerializedTagMap(BinaryReader reader) + { + int numTags = reader.ReadInt32(); + tags = new List>(numTags); + for (int i = 0; i < numTags; i++) + { + tags.Add(new KeyValuePair(reader.ReadAlignedString(), reader.ReadAlignedString())); + } + } + } + + public class SerializedSubShader + { + public List m_Passes { get; set; } + public SerializedTagMap m_Tags { get; set; } + public int m_LOD { get; set; } + + public SerializedSubShader(ObjectReader reader) + { + int numPasses = reader.ReadInt32(); + m_Passes = new List(numPasses); + for (int i = 0; i < numPasses; i++) + { + m_Passes.Add(new SerializedPass(reader)); + } + + m_Tags = new SerializedTagMap(reader); + m_LOD = reader.ReadInt32(); + } + } + + public class SerializedShaderDependency + { + public string from { get; set; } + public string to { get; set; } + + public SerializedShaderDependency(BinaryReader reader) + { + from = reader.ReadAlignedString(); + to = reader.ReadAlignedString(); + } + } + + public class SerializedShader + { + public SerializedProperties m_PropInfo { get; set; } + public List m_SubShaders { get; set; } + public string m_Name { get; set; } + public string m_CustomEditorName { get; set; } + public string m_FallbackName { get; set; } + public List m_Dependencies { get; set; } + public bool m_DisableNoSubshadersMessage { get; set; } + + public SerializedShader(ObjectReader reader) + { + m_PropInfo = new SerializedProperties(reader); + + int numSubShaders = reader.ReadInt32(); + m_SubShaders = new List(numSubShaders); + for (int i = 0; i < numSubShaders; i++) + { + m_SubShaders.Add(new SerializedSubShader(reader)); + } + + m_Name = reader.ReadAlignedString(); + m_CustomEditorName = reader.ReadAlignedString(); + m_FallbackName = reader.ReadAlignedString(); + + int numDependencies = reader.ReadInt32(); + m_Dependencies = new List(numDependencies); + for (int i = 0; i < numDependencies; i++) + { + m_Dependencies.Add(new SerializedShaderDependency(reader)); + } + + m_DisableNoSubshadersMessage = reader.ReadBoolean(); + reader.AlignStream(4); + } + } + + public class Shader : NamedObject { public byte[] m_Script; + //5.3 - 5.4 + public uint decompressedSize; + public byte[] m_SubProgramBlob; + //5.5 and up + public SerializedShader m_ParsedForm; + public List platforms; + public List offsets; + public List compressedLengths; + public List decompressedLengths; + public byte[] compressedBlob; public Shader(ObjectReader reader) : base(reader) { - if (version[0] == 5 && version[1] >= 5 || version[0] > 5) //5.5.0 and up + if (version[0] == 5 && version[1] >= 5 || version[0] > 5) //5.5 and up { - var str = reader.Dump(); - m_Script = Encoding.UTF8.GetBytes(str ?? "Serialized Shader can't be read"); + m_ParsedForm = new SerializedShader(reader); + int numPlatforms = reader.ReadInt32(); + platforms = new List(numPlatforms); + for (int i = 0; i < numPlatforms; i++) + { + platforms.Add(reader.ReadUInt32()); + } + + int numOffsets = reader.ReadInt32(); + offsets = new List(numOffsets); + for (int i = 0; i < numOffsets; i++) + { + offsets.Add(reader.ReadUInt32()); + } + + int numCompressedLengths = reader.ReadInt32(); + compressedLengths = new List(numCompressedLengths); + for (int i = 0; i < numCompressedLengths; i++) + { + compressedLengths.Add(reader.ReadUInt32()); + } + + int numDecompressedLengths = reader.ReadInt32(); + decompressedLengths = new List(numDecompressedLengths); + for (int i = 0; i < numDecompressedLengths; i++) + { + decompressedLengths.Add(reader.ReadUInt32()); + } + + compressedBlob = reader.ReadBytes(reader.ReadInt32()); } else { m_Script = reader.ReadBytes(reader.ReadInt32()); + reader.AlignStream(4); + var m_PathName = reader.ReadAlignedString(); if (version[0] == 5 && version[1] >= 3) //5.3 - 5.4 { - reader.AlignStream(4); - var m_PathName = reader.ReadAlignedString(); - var decompressedSize = reader.ReadUInt32(); - var m_SubProgramBlob = reader.ReadBytes(reader.ReadInt32()); - var decompressedBytes = new byte[decompressedSize]; - using (var decoder = new Lz4DecoderStream(new MemoryStream(m_SubProgramBlob))) - { - decoder.Read(decompressedBytes, 0, (int)decompressedSize); - } - - m_Script = m_Script.Concat(decompressedBytes.ToArray()).ToArray(); + decompressedSize = reader.ReadUInt32(); + m_SubProgramBlob = reader.ReadBytes(reader.ReadInt32()); } } } diff --git a/AssetStudio/Libraries/SharpDX.D3DCompiler.dll b/AssetStudio/Libraries/SharpDX.D3DCompiler.dll new file mode 100644 index 0000000..bd4f26c Binary files /dev/null and b/AssetStudio/Libraries/SharpDX.D3DCompiler.dll differ diff --git a/AssetStudio/Libraries/SharpDX.Mathematics.dll b/AssetStudio/Libraries/SharpDX.Mathematics.dll index 4c0da9c..75bbb0d 100644 Binary files a/AssetStudio/Libraries/SharpDX.Mathematics.dll and b/AssetStudio/Libraries/SharpDX.Mathematics.dll differ diff --git a/AssetStudio/Libraries/SharpDX.dll b/AssetStudio/Libraries/SharpDX.dll index baa26ad..e06ed56 100644 Binary files a/AssetStudio/Libraries/SharpDX.dll and b/AssetStudio/Libraries/SharpDX.dll differ diff --git a/AssetStudio/StudioClasses/Exporter.cs b/AssetStudio/StudioClasses/Exporter.cs index 72d48d4..1557f4c 100644 --- a/AssetStudio/StudioClasses/Exporter.cs +++ b/AssetStudio/StudioClasses/Exporter.cs @@ -86,7 +86,8 @@ namespace AssetStudio var exportFullName = exportPath + reader.exportName + ".shader"; if (ExportFileExists(exportFullName)) return false; - File.WriteAllBytes(exportFullName, m_Shader.m_Script); + var str = ShaderConverter.Convert(m_Shader); + File.WriteAllText(exportFullName, str ?? "Serialized Shader can't be read"); return true; } diff --git a/AssetStudio/StudioClasses/ShaderConverter.cs b/AssetStudio/StudioClasses/ShaderConverter.cs new file mode 100644 index 0000000..50088a2 --- /dev/null +++ b/AssetStudio/StudioClasses/ShaderConverter.cs @@ -0,0 +1,229 @@ +using System; +using System.IO; +using System.Text; +using System.Text.RegularExpressions; +using Lz4; +using SharpDX.D3DCompiler; + +namespace AssetStudio +{ + public static class ShaderConverter + { + public static string Convert(Shader shader) + { + if (shader.m_SubProgramBlob != null) //5.3 - 5.4 + { + var decompressedBytes = new byte[shader.decompressedSize]; + using (var decoder = new Lz4DecoderStream(new MemoryStream(shader.m_SubProgramBlob))) + { + decoder.Read(decompressedBytes, 0, (int)shader.decompressedSize); + } + using (var blobReader = new BinaryReader(new MemoryStream(decompressedBytes))) + { + var program = new ShaderProgram(blobReader); + return program.Export(Encoding.UTF8.GetString(shader.m_Script)); + } + } + + if (shader.compressedBlob != null) //5.5 and up + { + //TODO + /*for (var i = 0; i < shader.platforms.Count; i++) + { + var compressedBytes = new byte[shader.compressedLengths[i]]; + Array.Copy(shader.compressedBlob, shader.offsets[i], compressedBytes, 0, shader.compressedLengths[i]); + var decompressedBytes = new byte[shader.decompressedLengths[i]]; + using (var decoder = new Lz4DecoderStream(new MemoryStream(compressedBytes))) + { + decoder.Read(decompressedBytes, 0, (int)shader.decompressedLengths[i]); + } + using (var blobReader = new BinaryReader(new MemoryStream(decompressedBytes))) + { + new ShaderProgram(blobReader); + } + }*/ + return shader.reader.Dump(); + } + return Encoding.UTF8.GetString(shader.m_Script); + } + } + + public class ShaderProgram + { + public ShaderSubProgram[] m_SubPrograms; + + public ShaderProgram(BinaryReader reader) + { + var subProgramsCapacity = reader.ReadInt32(); + m_SubPrograms = new ShaderSubProgram[subProgramsCapacity]; + for (int i = 0; i < subProgramsCapacity; i++) + { + reader.BaseStream.Position = 4 + i * 8; + var offset = reader.ReadInt32(); + reader.BaseStream.Position = offset; + m_SubPrograms[i] = new ShaderSubProgram(reader); + } + } + + public string Export(string shader) + { + var evaluator = new MatchEvaluator(match => + { + var index = int.Parse(match.Groups[1].Value); + return m_SubPrograms[index].Export(); + }); + shader = Regex.Replace(shader, "GpuProgramIndex (.+)", evaluator); + return shader; + } + } + + public class ShaderSubProgram + { + private int magic; + public ShaderGpuProgramType m_ProgramType; + public string[] m_Keywords; + 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 + magic = reader.ReadInt32(); + m_ProgramType = (ShaderGpuProgramType)reader.ReadInt32(); + reader.BaseStream.Position += 12; + if (magic >= 201608170) //5.5.0 and up + { + reader.BaseStream.Position += 4; + } + var keywordCount = reader.ReadInt32(); + m_Keywords = new string[keywordCount]; + for (int i = 0; i < keywordCount; i++) + { + m_Keywords[i] = reader.ReadAlignedString(); + } + m_ProgramCode = reader.ReadBytes(reader.ReadInt32()); + reader.AlignStream(4); + + //TODO + } + + public string Export() + { + var sb = new StringBuilder(); + if (m_Keywords.Length > 0) + { + sb.Append("Keywords { "); + foreach (string keyword in m_Keywords) + { + sb.Append($"\"{keyword}\" "); + } + sb.Append("}\n"); + } + + sb.Append("\"\n"); + if (m_ProgramCode.Length > 0) + { + switch (m_ProgramType) + { + case ShaderGpuProgramType.kShaderGpuProgramGLLegacy: + case ShaderGpuProgramType.kShaderGpuProgramGLES31AEP: + case ShaderGpuProgramType.kShaderGpuProgramGLES31: + case ShaderGpuProgramType.kShaderGpuProgramGLES3: + case ShaderGpuProgramType.kShaderGpuProgramGLES: + case ShaderGpuProgramType.kShaderGpuProgramGLCore32: + case ShaderGpuProgramType.kShaderGpuProgramGLCore41: + case ShaderGpuProgramType.kShaderGpuProgramGLCore43: + sb.Append(Encoding.UTF8.GetString(m_ProgramCode)); + break; + case ShaderGpuProgramType.kShaderGpuProgramDX9VertexSM20: + case ShaderGpuProgramType.kShaderGpuProgramDX9VertexSM30: + case ShaderGpuProgramType.kShaderGpuProgramDX9PixelSM20: + case ShaderGpuProgramType.kShaderGpuProgramDX9PixelSM30: + { + var shaderBytecode = new ShaderBytecode(m_ProgramCode); + sb.Append(shaderBytecode.Disassemble()); + break; + } + case ShaderGpuProgramType.kShaderGpuProgramDX10Level9Vertex: + case ShaderGpuProgramType.kShaderGpuProgramDX10Level9Pixel: + case ShaderGpuProgramType.kShaderGpuProgramDX11VertexSM40: + case ShaderGpuProgramType.kShaderGpuProgramDX11VertexSM50: + case ShaderGpuProgramType.kShaderGpuProgramDX11PixelSM40: + case ShaderGpuProgramType.kShaderGpuProgramDX11PixelSM50: + case ShaderGpuProgramType.kShaderGpuProgramDX11GeometrySM40: + case ShaderGpuProgramType.kShaderGpuProgramDX11GeometrySM50: + case ShaderGpuProgramType.kShaderGpuProgramDX11HullSM50: + case ShaderGpuProgramType.kShaderGpuProgramDX11DomainSM50: + { + int start = 6; + if (magic == 201509030) // 5.3 + { + start = 5; + } + var buff = new byte[m_ProgramCode.Length - start]; + Buffer.BlockCopy(m_ProgramCode, start, buff, 0, buff.Length); + var shaderBytecode = new ShaderBytecode(buff); + sb.Append(shaderBytecode.Disassemble()); + break; + } + case ShaderGpuProgramType.kShaderGpuProgramMetalVS: + case ShaderGpuProgramType.kShaderGpuProgramMetalFS: + using (var reader = new BinaryReader(new MemoryStream(m_ProgramCode))) + { + var fourCC = reader.ReadUInt32(); + if (fourCC == 0xf00dcafe) + { + int offset = reader.ReadInt32(); + reader.BaseStream.Position = offset; + } + var entryName = reader.ReadStringToNull(); + var buff = reader.ReadBytes((int)(reader.BaseStream.Length - reader.BaseStream.Position)); + sb.Append(Encoding.UTF8.GetString(buff)); + } + break; + default: + sb.Append($"/*Unsupported program data {m_ProgramType}*/"); + break; + } + } + sb.Append('"'); + return sb.ToString(); + } + } + + public enum ShaderGpuProgramType + { + kShaderGpuProgramUnknown = 0, + kShaderGpuProgramGLLegacy = 1, + kShaderGpuProgramGLES31AEP = 2, + kShaderGpuProgramGLES31 = 3, + kShaderGpuProgramGLES3 = 4, + kShaderGpuProgramGLES = 5, + kShaderGpuProgramGLCore32 = 6, + kShaderGpuProgramGLCore41 = 7, + kShaderGpuProgramGLCore43 = 8, + kShaderGpuProgramDX9VertexSM20 = 9, + kShaderGpuProgramDX9VertexSM30 = 10, + kShaderGpuProgramDX9PixelSM20 = 11, + kShaderGpuProgramDX9PixelSM30 = 12, + kShaderGpuProgramDX10Level9Vertex = 13, + kShaderGpuProgramDX10Level9Pixel = 14, + kShaderGpuProgramDX11VertexSM40 = 15, + kShaderGpuProgramDX11VertexSM50 = 16, + kShaderGpuProgramDX11PixelSM40 = 17, + kShaderGpuProgramDX11PixelSM50 = 18, + kShaderGpuProgramDX11GeometrySM40 = 19, + kShaderGpuProgramDX11GeometrySM50 = 20, + kShaderGpuProgramDX11HullSM50 = 21, + kShaderGpuProgramDX11DomainSM50 = 22, + kShaderGpuProgramMetalVS = 23, + kShaderGpuProgramMetalFS = 24, + kShaderGpuProgramSPIRV = 25, + kShaderGpuProgramConsole = 26, + }; +} diff --git a/AssetStudio/StudioClasses/Studio.cs b/AssetStudio/StudioClasses/Studio.cs index 7d3deab..1fb80dd 100644 --- a/AssetStudio/StudioClasses/Studio.cs +++ b/AssetStudio/StudioClasses/Studio.cs @@ -203,25 +203,36 @@ namespace AssetStudio var m_Texture2D = new Texture2D(objectReader, false); if (!string.IsNullOrEmpty(m_Texture2D.path)) assetItem.FullSize = objectReader.byteSize + m_Texture2D.size; - goto case ClassIDType.NamedObject; + assetItem.Text = m_Texture2D.m_Name; + exportable = true; + break; } case ClassIDType.AudioClip: { var m_AudioClip = new AudioClip(objectReader, false); if (!string.IsNullOrEmpty(m_AudioClip.m_Source)) assetItem.FullSize = objectReader.byteSize + m_AudioClip.m_Size; - goto case ClassIDType.NamedObject; + assetItem.Text = m_AudioClip.m_Name; + exportable = true; + break; } case ClassIDType.VideoClip: { var m_VideoClip = new VideoClip(objectReader, false); if (!string.IsNullOrEmpty(m_VideoClip.m_OriginalPath)) assetItem.FullSize = objectReader.byteSize + (long)m_VideoClip.m_Size; - goto case ClassIDType.NamedObject; + assetItem.Text = m_VideoClip.m_Name; + exportable = true; + break; } - case ClassIDType.NamedObject: - case ClassIDType.Mesh: case ClassIDType.Shader: + { + var m_Shader = new Shader(objectReader); + assetItem.Text = m_Shader.m_ParsedForm?.m_Name ?? m_Shader.m_Name; + exportable = true; + break; + } + case ClassIDType.Mesh: case ClassIDType.TextAsset: case ClassIDType.AnimationClip: case ClassIDType.Font: