コード例 #1
0
        public static DebugConstantDeclaration Parse(DebugBytecodeReader reader, DebugBytecodeReader decReader)
        {
            var result     = new DebugConstantDeclaration();
            var nameOffset = decReader.ReadUInt32("NameOffset");

            result.RegisterSet   = decReader.ReadEnum16 <RegisterSet>("RegisterSet");
            result.RegisterIndex = decReader.ReadUInt16("RegisterIndex");
            result.RegisterCount = decReader.ReadUInt16("RegisterCount");
            decReader.ReadUInt16("Reserved");
            var typeInfoOffset     = decReader.ReadUInt32("TypeInfoOffset");
            var defaultValueOffset = decReader.ReadUInt32("DefaultValueOffset");

            var nameReader = reader.CopyAtOffset("NameReader", decReader, (int)nameOffset);

            result.Name = nameReader.ReadString("Name");

            var typeReader = reader.CopyAtOffset("TypeReader", decReader, (int)typeInfoOffset);

            result.Type = DebugConstantType.Parse(reader, typeReader);

            if (defaultValueOffset != 0)
            {
                //Note: thre are corrisponding def instructions. TODO: check that they are the same
                var defaultValueReader = reader.CopyAtOffset("DefaultValueReader", decReader, (int)defaultValueOffset);
                var elementCount       = result.Type.GetSize() / 4;
                for (int i = 0; i < elementCount; i++)
                {
                    result.DefaultValue.Add(defaultValueReader.ReadSingle($"DefaultValue {i}"));
                }
            }

            return(result);
        }
コード例 #2
0
        public static DebugConstantType Parse(DebugBytecodeReader reader, DebugBytecodeReader typeReader)
        {
            var result = new DebugConstantType();

            result.ParameterClass = typeReader.ReadEnum16 <ParameterClass>("ParameterClass");
            result.ParameterType  = typeReader.ReadEnum16 <ParameterType>("ParameterType");
            result.Rows           = typeReader.ReadUInt16("Rows");
            result.Columns        = typeReader.ReadUInt16("Columns");
            result.Elements       = typeReader.ReadUInt16("Elements");
            result.MemberCount    = typeReader.ReadUInt16("Members");
            var memberInfoOffset = typeReader.ReadUInt32("MemberInfoOffset");

            if (memberInfoOffset != 0)
            {
                var memberInfoReader = reader.CopyAtOffset("MemberReader", typeReader, (int)memberInfoOffset);
                for (int i = 0; i < result.MemberCount; i++)
                {
                    var nameOffset = memberInfoReader.ReadUInt32($"Member{i}NameOffset");
                    var nameReader = reader.CopyAtOffset($"Member{i}NameReader", memberInfoReader, (int)nameOffset);
                    nameReader.ReadString("Name");
                    var typeOffset       = memberInfoReader.ReadUInt32($"Member{i}TypeOffset");
                    var memberTypeReader = reader.CopyAtOffset($"Member{i}TypeReader", memberInfoReader, (int)typeOffset);
                    result.Members.Add(DebugConstantType.Parse(reader, memberTypeReader));
                }
            }
            return(result);
        }
コード例 #3
0
        public static DebugLoopRegisterMapping Parse(DebugBytecodeReader reader)
        {
            var result = new DebugLoopRegisterMapping();

            result.Buffer    = reader.ReadUInt16("Buffer");
            result.SourceReg = reader.ReadUInt16("SourceReg");
            result.Component = reader.ReadUInt16("Component");
            result.TargetReg = reader.ReadUInt16("TargetReg");
            return(result);
        }
コード例 #4
0
 public static DebugMSInfo Parse(DebugBytecodeReader reader)
 {
     return(new DebugMSInfo()
     {
         GroupSharedBytesUsed = reader.ReadUInt32("GroupSharedBytesUsed"),
         GroupSharedBytesDependentOnViewID = reader.ReadUInt32("GroupSharedBytesDependentOnViewID"),
         PayloadSizeInBytes = reader.ReadUInt32("PayloadSizeInBytes"),
         MaxOutputVertices = reader.ReadUInt16("MaxOutputVertices"),
         MaxOutputPrimitives = reader.ReadUInt16("MaxOutputPrimitives"),
     });
 }
コード例 #5
0
        public static DebugClassType Parse(DebugBytecodeReader reader, DebugBytecodeReader classTypeReader)
        {
            var nameOffset = classTypeReader.ReadUInt32("nameOffset");
            var nameReader = reader.CopyAtOffset("nameReader", classTypeReader, (int)nameOffset);

            return(new DebugClassType
            {
                Name = nameReader.ReadString("Name"),
                ID = classTypeReader.ReadUInt16("ID"),
                ConstantBufferStride = classTypeReader.ReadUInt16("ConstantBufferStride"),
                Texture = classTypeReader.ReadUInt16("Texture"),
                Sampler = classTypeReader.ReadUInt16("Sampler")
            });
        }
コード例 #6
0
        public static DebugDebugNameChunk Parse(DebugBytecodeReader reader, uint chunkSize)
        {
            var result     = new DebugDebugNameChunk();
            var flags      = reader.ReadUInt16("Flags");        //Currently unused
            var nameLength = reader.ReadUInt16("NameLength");

            result.Name = reader.ReadString("Name");
            var padding = 4 - (nameLength + 1) % 4;             //Aligned to 4 byte boundary

            if (padding > 0)
            {
                reader.ReadBytes("Padding", padding);
            }
            return(result);
        }
コード例 #7
0
        public static DebugConstantBufferMapping Parse(DebugBytecodeReader reader)
        {
            var result = new DebugConstantBufferMapping();

            result.Buffer    = reader.ReadUInt16("Buffer");
            result.StartReg  = reader.ReadUInt16("StartReg");
            result.RegCount  = reader.ReadUInt16("RegCount");
            result.TargetReg = reader.ReadUInt16("TargetReg");
            for (int i = 0; i < 4; i++)
            {
                var type = reader.ReadEnum8 <DataConversionType>("DataConversionType");
                result.DataConversion[i] = type;
            }
            return(result);
        }
コード例 #8
0
        public static DebugRuntimeConstantMapping Parse(DebugBytecodeReader reader)
        {
            var result = new DebugRuntimeConstantMapping();

            result.ConstantDescription = reader.ReadEnum16 <RuntimeConstantDescription>("ConstantDescription");
            result.TargetReg           = reader.ReadUInt16("TargetReg");
            return(result);
        }
コード例 #9
0
        public static DebugClassInstance Parse(DebugBytecodeReader reader, DebugBytecodeReader classInstanceReader)
        {
            var nameOffset = classInstanceReader.ReadUInt32("NameOffset");
            var nameReader = reader.CopyAtOffset("nameReader", classInstanceReader, (int)nameOffset);
            var name       = nameReader.ReadString("nameReader");

            var type    = classInstanceReader.ReadUInt16("type");
            var unknown = classInstanceReader.ReadUInt16("ClassInstanceUnknown");

            return(new DebugClassInstance
            {
                Name = name,
                Type = type,
                ConstantBuffer = classInstanceReader.ReadUInt16("ConstantBuffer"),
                ConstantBufferOffset = classInstanceReader.ReadUInt16("ConstantBufferOffset"),
                Texture = classInstanceReader.ReadUInt16("Texture"),
                Sampler = classInstanceReader.ReadUInt16("Sampler")
            });
        }
コード例 #10
0
        public static DebugShaderType Parse(DebugBytecodeReader reader, DebugBytecodeReader typeReader, DebugShaderVersion target,
                                            int indent, bool isFirst, uint parentOffset)
        {
            var result = new DebugShaderType(indent, isFirst)
            {
                VariableClass = typeReader.ReadEnum16 <ShaderVariableClass>("VariableClass"),
                VariableType  = typeReader.ReadEnum16 <ShaderVariableType>("VariableType"),
                Rows          = typeReader.ReadUInt16("Rows"),
                Columns       = typeReader.ReadUInt16("Columns"),
                ElementCount  = typeReader.ReadUInt16("ElementCount")
            };

            var memberCount  = typeReader.ReadUInt16("memberCount");
            var memberOffset = typeReader.ReadUInt32("memberOffset");

            if (target.MajorVersion >= 5)
            {
                var subTypeOffset = typeReader.ReadInt32("subTypeOffset");                 // Guessing
                if (subTypeOffset != 0)
                {
                    var parentInterfaceReader = reader.CopyAtOffset("subtypeReader", typeReader, (int)subTypeOffset);
                    result.SubType = DebugShaderType.Parse(reader, parentInterfaceReader, target,
                                                           indent + 4, true, parentOffset);
                }

                var baseClassOffset = typeReader.ReadUInt32("baseClassOffset");
                if (baseClassOffset != 0)
                {
                    var baseClassReader = reader.CopyAtOffset("baseClassReader", typeReader, (int)baseClassOffset);
                    result.BaseClass = DebugShaderType.Parse(reader, baseClassReader, target,
                                                             indent + 4, true, parentOffset);
                }

                result.NumberOfInterfaces = typeReader.ReadUInt32("NumberOfInterfaces");

                var interfaceSectionOffset = typeReader.ReadUInt32("InterfaceSectionOffset");
                if (interfaceSectionOffset != 0)
                {
                    var interfaceSectionReader = reader.CopyAtOffset("interfaceSectionReader", typeReader, (int)interfaceSectionOffset);
                    for (int i = 0; i < result.NumberOfInterfaces; i++)
                    {
                        var interfaceTypeOffset = interfaceSectionReader.ReadUInt32($"UnkInterface{i}");
                        var interfaceReader     = reader.CopyAtOffset($"InterfaceReader {i}", typeReader, (int)interfaceTypeOffset);
                        result.Interfaces.Add(DebugShaderType.Parse(reader, interfaceReader,
                                                                    target, indent + 4, i == 0, parentOffset));
                    }
                }

                var parentNameOffset = typeReader.ReadUInt32("parentNameOffset");
                if (parentNameOffset > 0)
                {
                    var parentNameReader = reader.CopyAtOffset("parentNameOffset", typeReader, (int)parentNameOffset);
                    result.BaseTypeName = parentNameReader.ReadString("BaseTypeName");
                }
            }

            if (memberCount > 0)
            {
                var memberReader = reader.CopyAtOffset("memberReader", typeReader, (int)memberOffset);
                for (int i = 0; i < memberCount; i++)
                {
                    memberReader.AddIndent($"Member {i}");
                    result.Members.Add(DebugShaderTypeMember.Parse(reader, memberReader, target, indent + 4, i == 0,
                                                                   parentOffset));
                    memberReader.RemoveIndent();
                }
            }

            if (target.ProgramType == ProgramType.LibraryShader && target.MajorVersion == 4)
            {
                var unk1           = typeReader.ReadUInt32("Unk1");
                var unk2           = typeReader.ReadUInt32("Unk2");
                var unk3           = typeReader.ReadUInt32("Unk3");
                var unk4           = typeReader.ReadUInt32("Unk4");
                var typeNameOffset = typeReader.ReadUInt32("typeNameoffset");
                var typeNameReader = reader.CopyAtOffset("TypeNameReader", typeReader, (int)typeNameOffset);
                typeNameReader.ReadString("TypeName");
                Debug.Assert(unk1 == 0, $"ShaderType.Unk1={unk1}");
                Debug.Assert(unk2 == 0, $"ShaderType.Unk2={unk2}");
                Debug.Assert(unk3 == 0, $"ShaderType.Unk3={unk3}");
                Debug.Assert(unk4 == 0, $"ShaderType.Unk4={unk4}");
            }

            return(result);
        }
コード例 #11
0
ファイル: Program.cs プロジェクト: swordlegend/DXDecompiler
        static void Main(string[] args)
        {
            args = new string[]
            {
                "-O",
                "test.html",
                "-h",
                @"C:\Files\KM\ShaderStudio\src\UnityTests\bin\Debug\Blob\outer_wilds\Assets\Shader\SpritesDefault\VS_BF58DDF502C51FEB5145F1D0310B4327.o"
            };
            var options = new Options();

            for (int i = 0; i < args.Length; i++)
            {
                switch (args[i])
                {
                case "-O":
                    if (args.Length <= i + 1)
                    {
                        Console.Error.WriteLine("No output path specified");
                        return;
                    }
                    options.DestPath = args[i + 1];
                    i += 1;
                    break;

                case "-a":
                    options.Mode = DecompileMode.Dissassemble;
                    break;

                case "-d":
                    options.Mode = DecompileMode.Debug;
                    break;

                case "-h":
                    options.Mode = DecompileMode.DebugHtml;
                    break;

                default:
                    options.SourcePath = args[i];
                    break;
                }
            }
            if (string.IsNullOrEmpty(options.SourcePath))
            {
                Console.Error.WriteLine("No source path specified");
                Environment.Exit(1);
            }

            byte[] data = null;
            try
            {
                data = File.ReadAllBytes(options.SourcePath);
            } catch (Exception ex) {
                Console.Error.WriteLine("Error reading source");
                Console.Error.WriteLine(ex);
                Environment.Exit(1);
            }
            var programType = GetProgramType(data);

            using (var sw = GetStream(options))
            {
                if (programType == ProgramType.Unknown)
                {
                    Console.Error.WriteLine($"Unable to identify shader object format");
                    Environment.Exit(1);
                }
                else if (programType == ProgramType.DXBC)
                {
                    if (options.Mode == DecompileMode.Dissassemble)
                    {
                        var container = new BytecodeContainer(data);
                        sw.Write(container.ToString());
                    }
                    else if (options.Mode == DecompileMode.Decompile)
                    {
                        var hlsl = DXDecompiler.Decompile(data);
                        sw.Write(hlsl);
                    }
                    else if (options.Mode == DecompileMode.Debug)
                    {
                        sw.WriteLine(string.Join(" ", args));
                        var shaderBytecode = DebugBytecodeContainer.Parse(data);
                        var result         = shaderBytecode.Dump();
                        sw.Write(result);
                    }
                    else if (options.Mode == DecompileMode.DebugHtml)
                    {
                        var shaderBytecode = DebugBytecodeContainer.Parse(data);
                        var result         = shaderBytecode.DumpHTML();
                        sw.Write(result);
                    }
                }
                else if (programType == ProgramType.DX9)
                {
                    if (options.Mode == DecompileMode.Dissassemble)
                    {
                        var disasm = SlimShader.DX9Shader.AsmWriter.Disassemble(data);
                        sw.Write(disasm);
                    }
                    else if (options.Mode == DecompileMode.Decompile)
                    {
                        var hlsl = SlimShader.DX9Shader.HlslWriter.Decompile(data);
                        sw.Write(hlsl);
                    }
                    else if (options.Mode == DecompileMode.Debug)
                    {
                        sw.WriteLine(string.Join(" ", args));
                        var shaderType = (SlimShader.DX9Shader.ShaderType)BitConverter.ToUInt16(data, 2);
                        if (shaderType == SlimShader.DX9Shader.ShaderType.Effect)
                        {
                            var    reader = new DebugBytecodeReader(data, 0, data.Length);
                            string error  = "";
                            try
                            {
                                reader.ReadByte("minorVersion");
                                reader.ReadByte("majorVersion");
                                reader.ReadUInt16("shaderType");
                                DebugEffectChunk.Parse(reader, (uint)(data.Length - 4));
                            }
                            catch (Exception ex)
                            {
                                error = ex.ToString();
                            }
                            var dump = reader.DumpStructure();
                            if (!string.IsNullOrEmpty(error))
                            {
                                dump += "\n" + error;
                            }
                            sw.Write(dump);
                        }
                        else
                        {
                            var    reader = new DebugBytecodeReader(data, 0, data.Length);
                            string error  = "";
                            try
                            {
                                DebugShaderModel.Parse(reader);
                            }
                            catch (Exception ex)
                            {
                                error = ex.ToString();
                            }
                            var dump = reader.DumpStructure();
                            if (!string.IsNullOrEmpty(error))
                            {
                                dump += "\n" + error;
                            }
                            sw.Write(dump);
                        }
                    }
                    else if (options.Mode == DecompileMode.DebugHtml)
                    {
                        var shaderType = (SlimShader.DX9Shader.ShaderType)BitConverter.ToUInt16(data, 2);
                        if (shaderType == SlimShader.DX9Shader.ShaderType.Effect)
                        {
                            var    reader = new DebugBytecodeReader(data, 0, data.Length);
                            string error  = "";
                            try
                            {
                                reader.ReadByte("minorVersion");
                                reader.ReadByte("majorVersion");
                                reader.ReadUInt16("shaderType");
                                DebugEffectChunk.Parse(reader, (uint)(data.Length - 4));
                            }
                            catch (Exception ex)
                            {
                                error = ex.ToString();
                            }
                            var dump = reader.DumpHtml();
                            if (!string.IsNullOrEmpty(error))
                            {
                                dump += "\n" + error;
                            }
                            sw.Write(dump);
                        }
                        else
                        {
                            var    reader = new DebugBytecodeReader(data, 0, data.Length);
                            string error  = "";
                            try
                            {
                                DebugShaderModel.Parse(reader);
                            }
                            catch (Exception ex)
                            {
                                error = ex.ToString();
                            }
                            var dump = reader.DumpHtml();
                            if (!string.IsNullOrEmpty(error))
                            {
                                dump += "\n" + error;
                            }
                            sw.Write(dump);
                        }
                    }
                }
            }
        }
コード例 #12
0
        public static DebugLevel9ShaderChunk Parse(DebugBytecodeReader chunkContentReader, uint chunkSize)
        {
            var  result     = new DebugLevel9ShaderChunk();
            uint chunkSize2 = chunkContentReader.ReadUInt32("chunkSize2");

            result.Version = DebugShaderVersion.ParseAon9(chunkContentReader);
            uint shaderSize                   = chunkContentReader.ReadUInt32("shaderSize");
            var  shaderOffset                 = chunkContentReader.ReadUInt32("shaderOffset");
            var  cbMappingCount               = chunkContentReader.ReadUInt16("cbMappingCount");
            var  cbMappingOffset              = chunkContentReader.ReadUInt16("cbMappingOffset");
            var  loopRegisterMappingCount     = chunkContentReader.ReadUInt16("loopRegisterMappingCount");
            var  loopRegisterMappingOffset    = chunkContentReader.ReadUInt16("loopRegisterMappingOffset");
            var  unk0MappingCount             = chunkContentReader.ReadUInt16("unk0MappingCount");
            var  unk0MappingOffset            = chunkContentReader.ReadUInt16("unk0MappingOffset");
            var  samplerMappingCount          = chunkContentReader.ReadUInt16("samplerMappingCount");
            var  samplerMappingOffset         = chunkContentReader.ReadUInt16("samplerMappingOffset");
            var  runtimeConstantMappingCount  = chunkContentReader.ReadUInt16("runtimeConstantMappingCount");
            var  runtimeConstantMappingOffset = chunkContentReader.ReadUInt16("runtimeConstantMappingOffset");

            if (cbMappingCount > 0)
            {
                var mappingReader = chunkContentReader.CopyAtOffset("mappingReader", chunkContentReader, cbMappingOffset);
                for (int i = 0; i < cbMappingCount; i++)
                {
                    result.ConstantBufferMappings.Add(DebugConstantBufferMapping.Parse(mappingReader));
                }
            }
            if (loopRegisterMappingCount > 0)
            {
                var mappingReader = chunkContentReader.CopyAtOffset("mappingReader", chunkContentReader, loopRegisterMappingOffset);
                for (int i = 0; i < loopRegisterMappingCount; i++)
                {
                    result.LoopRegisterMappings.Add(DebugLoopRegisterMapping.Parse(mappingReader));
                }
            }
            if (unk0MappingCount > 0)
            {
                var mappingReader = chunkContentReader.CopyAtOffset("mappingReader", chunkContentReader, unk0MappingOffset);
                for (int i = 0; i < unk0MappingCount; i++)
                {
                    result.Unknown0Mappings.Add(DebugUnknown1Mapping.Parse(mappingReader));
                }
            }
            if (samplerMappingCount > 0)
            {
                var mappingReader = chunkContentReader.CopyAtOffset("mappingReader", chunkContentReader, samplerMappingOffset);
                for (int i = 0; i < samplerMappingCount; i++)
                {
                    result.SamplerMappings.Add(DebugSamplerMapping.Parse(mappingReader));
                }
                // FXC dissassembly sorts sampler mappings
                result.SamplerMappings = result.SamplerMappings
                                         .OrderBy(s => s.TargetSampler)
                                         .ToList();
            }
            if (runtimeConstantMappingCount > 0)
            {
                var mappingReader = chunkContentReader.CopyAtOffset("mappingReader", chunkContentReader, runtimeConstantMappingOffset);
                for (int i = 0; i < runtimeConstantMappingCount; i++)
                {
                    result.RuntimeConstantMappings.Add(DebugRuntimeConstantMapping.Parse(mappingReader));
                }
            }
            var shaderChunkReader = chunkContentReader.CopyAtOffset("shaderChunkReader", chunkContentReader, (int)shaderOffset);
            var byteCode          = shaderChunkReader.ReadBytes("bytecode", (int)shaderSize);

            return(result);
        }
コード例 #13
0
        public static DebugSignatureParameterDescription Parse(DebugBytecodeReader reader, DebugBytecodeReader parameterReader,
                                                               ChunkType chunkType, SignatureElementSize size, ProgramType programType)
        {
            uint stream = 0;

            if (size == SignatureElementSize._7 || size == SignatureElementSize._8)
            {
                stream = parameterReader.ReadUInt32("Stream");
            }
            uint nameOffset = parameterReader.ReadUInt32("NameOffset");
            var  nameReader = reader.CopyAtOffset("NameReader", parameterReader, (int)nameOffset);

            var result = new DebugSignatureParameterDescription
            {
                SemanticName    = nameReader.ReadString("SemanticName"),
                SemanticIndex   = parameterReader.ReadUInt32("SemanticIndex"),
                SystemValueType = parameterReader.ReadEnum32 <Name>("SystemValueType"),
                ComponentType   = parameterReader.ReadEnum32 <RegisterComponentType>("ComponentType"),
                Register        = parameterReader.ReadUInt32("Register"),
                Stream          = stream,
            };

            result.Mask          = parameterReader.ReadEnum8 <ComponentMask>("Mask");
            result.ReadWriteMask = parameterReader.ReadEnum8 <ComponentMask>("ReadWriteMask");
            parameterReader.ReadUInt16("MaskPadding");

            if (size == SignatureElementSize._8)
            {
                MinPrecision minPrecision = parameterReader.ReadEnum32 <MinPrecision>("MinPrecision");
                result.MinPrecision = minPrecision;
            }

            // This is my guesswork, but it works so far...
            if (chunkType == ChunkType.Osg5 ||
                chunkType == ChunkType.Osgn ||
                chunkType == ChunkType.Osg1 ||
                (chunkType == ChunkType.Pcsg && programType == ProgramType.HullShader))
            {
                result.ReadWriteMask = (ComponentMask)(ComponentMask.All - result.ReadWriteMask);
            }

            // Vertex and pixel shaders need special handling for SystemValueType in the output signature.
            if ((programType == ProgramType.PixelShader || programType == ProgramType.VertexShader) &&
                (chunkType == ChunkType.Osg5 || chunkType == ChunkType.Osgn || chunkType == ChunkType.Osg1))
            {
                if (result.Register == 0xffffffff)
                {
                    switch (result.SemanticName.ToUpper())
                    {
                    case "SV_DEPTH":
                        result.SystemValueType = Name.Depth;
                        break;

                    case "SV_COVERAGE":
                        result.SystemValueType = Name.Coverage;
                        break;

                    case "SV_DEPTHGREATEREQUAL":
                        result.SystemValueType = Name.DepthGreaterEqual;
                        break;

                    case "SV_DEPTHLESSEQUAL":
                        result.SystemValueType = Name.DepthLessEqual;
                        break;

                    case "SV_STENCILREF":
                        result.SystemValueType = Name.StencilRef;
                        break;
                    }
                }
                else if (programType == ProgramType.PixelShader)
                {
                    result.SystemValueType = Name.Target;
                }
            }

            return(result);
        }