Beispiel #1
0
        string GetSourceName(InstructionToken instruction, int srcIndex)
        {
            string sourceRegisterName = instruction.GetParamRegisterName(srcIndex);

            sourceRegisterName  = ApplyModifier(instruction.GetSourceModifier(srcIndex), sourceRegisterName);
            sourceRegisterName += instruction.GetSourceSwizzleName(srcIndex);
            if (instruction.IsRelativeAddressMode(srcIndex))
            {
                sourceRegisterName += $"[{GetSourceName(instruction, srcIndex + 1)}]";
            }
            return(sourceRegisterName);
        }
        public string GetDestinationName(InstructionToken instruction)
        {
            int         destIndex   = instruction.GetDestinationParamIndex();
            RegisterKey registerKey = instruction.GetParamRegisterKey(destIndex);

            string registerName = GetRegisterName(registerKey);

            registerName = registerName ?? instruction.GetParamRegisterName(destIndex);
            var    registerLength = GetRegisterFullLength(registerKey);
            string writeMaskName  = instruction.GetDestinationWriteMaskName(registerLength, true);

            return(string.Format("{0}{1}", registerName, writeMaskName));
        }
Beispiel #3
0
        string GetDestinationName(InstructionToken instruction)
        {
            var resultModifier = instruction.GetDestinationResultModifier();

            int destIndex = instruction.GetDestinationParamIndex();

            string    registerName    = instruction.GetParamRegisterName(destIndex);
            const int registerLength  = 4;
            string    writeMaskName   = instruction.GetDestinationWriteMaskName(registerLength, false);
            string    destinationName = $"{registerName}{writeMaskName}";

            if (resultModifier != ResultModifier.None)
            {
                //destinationName += "TODO:Modifier!!!";
            }
            return(destinationName);
        }
Beispiel #4
0
        string GetSourceName(InstructionToken instruction, int srcIndex, bool isLogicalIndex = true)
        {
            int dataIndex;

            if (isLogicalIndex)
            {
                // compute the actual data index, which might be different from logical index
                // because of relative addressing mode.

                // TODO: Handle relative addressing mode in a better way,
                // by using `InstructionToken.Operands`:
                // https://github.com/spacehamster/DXDecompiler/pull/6#issuecomment-782958769

                // if instruction has destination, then source starts at the index 1
                // here we assume destination won't have relative addressing,
                // so we assume destination will only occupy 1 slot,
                // that is, the start index for sources will be 1 if instruction.HasDestination is true.
                var begin = instruction.HasDestination ? 1 : 0;
                dataIndex = begin;
                while (srcIndex > begin)
                {
                    if (instruction.IsRelativeAddressMode(dataIndex))
                    {
                        ++dataIndex;
                    }
                    ++dataIndex;
                    --srcIndex;
                }
            }
            else
            {
                dataIndex = srcIndex;
            }
            string sourceRegisterName = instruction.GetParamRegisterName(dataIndex);

            sourceRegisterName = ApplyModifier(instruction.GetSourceModifier(dataIndex), sourceRegisterName);
            if (instruction.IsRelativeAddressMode(dataIndex))
            {
                sourceRegisterName += $"[{GetSourceName(instruction, dataIndex + 1, isLogicalIndex: false)}]";
            }
            sourceRegisterName += instruction.GetSourceSwizzleName(dataIndex);
            return(sourceRegisterName);
        }
Beispiel #5
0
        private void WriteInstruction(InstructionToken instruction)
        {
            if (RemoveIndentInstruction(instruction))
            {
                Indent--;
            }
            if (instruction.Opcode != Opcode.Comment && instruction.Opcode != Opcode.End)
            {
                WriteIndent();
            }
            if (AddIndentInstruction(instruction))
            {
                Indent++;
            }
            switch (instruction.Opcode)
            {
            case Opcode.Abs:
                WriteLine("abs{0} {1}, {2}",
                          GetInstructionModifier(instruction),
                          GetDestinationName(instruction), GetSourceName(instruction, 1));
                break;

            case Opcode.Add:
                WriteLine("add{0} {1}, {2}, {3}",
                          GetInstructionModifier(instruction), GetDestinationName(instruction),
                          GetSourceName(instruction, 1), GetSourceName(instruction, 2));
                break;

            case Opcode.Cmp:
                WriteLine("cmp{0} {1}, {2}, {3}, {4}",
                          GetInstructionModifier(instruction), GetDestinationName(instruction),
                          GetSourceName(instruction, 1), GetSourceName(instruction, 2), GetSourceName(instruction, 3));
                break;

            case Opcode.Dcl:
                string dclInstruction = "dcl";
                var    registerType   = instruction.GetParamRegisterType(1);
                if (ShouldDeclareSemantics(instruction, registerType))
                {
                    dclInstruction += "_" + instruction.GetDeclSemantic().ToLower();
                }
                WriteLine("{0}{1} {2}", dclInstruction, GetInstructionModifier(instruction), GetDestinationName(instruction));
                break;

            case Opcode.Def:
            {
                string modifier          = GetInstructionModifier(instruction);
                string constRegisterName = instruction.GetParamRegisterName(0);
                string constValue0       = SingleToString(instruction.GetParamBytes(1));
                string constValue1       = SingleToString(instruction.GetParamBytes(2));
                string constValue2       = SingleToString(instruction.GetParamBytes(3));
                string constValue3       = SingleToString(instruction.GetParamBytes(4));
                WriteLine("def{0} {1}, {2}, {3}, {4}, {5}", modifier, constRegisterName, constValue0, constValue1, constValue2, constValue3);
            }
            break;

            case Opcode.DefI:
            {
                string constRegisterName = instruction.GetParamRegisterName(0);
                WriteLine("defi{0} {1}, {2}, {3}, {4}, {5}",
                          GetInstructionModifier(instruction), constRegisterName,
                          instruction.Data[1], instruction.Data[2], instruction.Data[3], instruction.Data[4]);
            }
            break;

            case Opcode.DP2Add:
                WriteLine("dp2add{0} {1}, {2}, {3}, {4}",
                          GetInstructionModifier(instruction), GetDestinationName(instruction),
                          GetSourceName(instruction, 1), GetSourceName(instruction, 2), GetSourceName(instruction, 3));
                break;

            case Opcode.Dp3:
                WriteLine("dp3{0} {1}, {2}, {3}",
                          GetInstructionModifier(instruction), GetDestinationName(instruction),
                          GetSourceName(instruction, 1), GetSourceName(instruction, 2));
                break;

            case Opcode.Dp4:
                WriteLine("dp4{0} {1}, {2}, {3}",
                          GetInstructionModifier(instruction), GetDestinationName(instruction),
                          GetSourceName(instruction, 1), GetSourceName(instruction, 2));
                break;

            case Opcode.Else:
                WriteLine("else");
                break;

            case Opcode.Endif:
                WriteLine("endif");
                break;

            case Opcode.Exp:
                WriteLine("exp{0} {1}, {2}",
                          GetInstructionModifier(instruction), GetDestinationName(instruction),
                          GetSourceName(instruction, 1));
                break;

            case Opcode.Frc:
                WriteLine("frc{0} {1}, {2}",
                          GetInstructionModifier(instruction), GetDestinationName(instruction), GetSourceName(instruction, 1));
                break;

            case Opcode.If:
                WriteLine("if {0}", GetSourceName(instruction, 0));
                break;

            case Opcode.IfC:
                WriteLine("if_{0} {1}, {2}",
                          ((IfComparison)instruction.Modifier).ToString().ToLower(),
                          GetSourceName(instruction, 0), GetSourceName(instruction, 1));
                break;

            case Opcode.Log:
                WriteLine("log{0} {1}, {2}",
                          GetInstructionModifier(instruction), GetDestinationName(instruction),
                          GetSourceName(instruction, 1));
                break;

            case Opcode.Lrp:
                WriteLine("lrp{0} {1}, {2}, {3}, {4}",
                          GetInstructionModifier(instruction), GetDestinationName(instruction),
                          GetSourceName(instruction, 1), GetSourceName(instruction, 2), GetSourceName(instruction, 3));
                break;

            case Opcode.Mad:
                WriteLine("mad{0} {1}, {2}, {3}, {4}",
                          GetInstructionModifier(instruction), GetDestinationName(instruction),
                          GetSourceName(instruction, 1), GetSourceName(instruction, 2), GetSourceName(instruction, 3));
                break;

            case Opcode.Max:
                WriteLine("max{0} {1}, {2}, {3}",
                          GetInstructionModifier(instruction), GetDestinationName(instruction),
                          GetSourceName(instruction, 1), GetSourceName(instruction, 2));
                break;

            case Opcode.Min:
                WriteLine("min{0} {1}, {2}, {3}",
                          GetInstructionModifier(instruction), GetDestinationName(instruction),
                          GetSourceName(instruction, 1), GetSourceName(instruction, 2));
                break;

            case Opcode.Mov:
                WriteLine("mov{0} {1}, {2}",
                          GetInstructionModifier(instruction), GetDestinationName(instruction), GetSourceName(instruction, 1));
                break;

            case Opcode.MovA:
                WriteLine("mova{0} {1}, {2}",
                          GetInstructionModifier(instruction), GetDestinationName(instruction), GetSourceName(instruction, 1));
                break;

            case Opcode.Mul:
                WriteLine("mul{0} {1}, {2}, {3}",
                          GetInstructionModifier(instruction), GetDestinationName(instruction),
                          GetSourceName(instruction, 1), GetSourceName(instruction, 2));
                break;

            case Opcode.Nop:
                WriteLine("nop");
                break;

            case Opcode.Nrm:
                WriteLine("nrm{0} {1}, {2}",
                          GetInstructionModifier(instruction), GetDestinationName(instruction), GetSourceName(instruction, 1));
                break;

            case Opcode.Pow:
                WriteLine("pow{0} {1}, {2}, {3}",
                          GetInstructionModifier(instruction), GetDestinationName(instruction),
                          GetSourceName(instruction, 1), GetSourceName(instruction, 2));
                break;

            case Opcode.Rcp:
                WriteLine("rcp{0} {1}, {2}",
                          GetInstructionModifier(instruction),
                          GetDestinationName(instruction), GetSourceName(instruction, 1));
                break;

            case Opcode.Rsq:
                WriteLine("rsq{0} {1}, {2}",
                          GetInstructionModifier(instruction), GetDestinationName(instruction), GetSourceName(instruction, 1));
                break;

            case Opcode.Sge:
                WriteLine("sge{0} {1}, {2}, {3}",
                          GetInstructionModifier(instruction), GetDestinationName(instruction),
                          GetSourceName(instruction, 1), GetSourceName(instruction, 2));
                break;

            case Opcode.Slt:
                WriteLine("slt{0} {1}, {2}, {3}",
                          GetInstructionModifier(instruction), GetDestinationName(instruction),
                          GetSourceName(instruction, 1), GetSourceName(instruction, 2));
                break;

            case Opcode.SinCos:
                if (shader.MajorVersion >= 3)
                {
                    WriteLine("sincos {0}, {1}", GetDestinationName(instruction),
                              GetSourceName(instruction, 1));
                }
                else
                {
                    WriteLine("sincos {0}, {1}, {2}, {3}", GetDestinationName(instruction),
                              GetSourceName(instruction, 1), GetSourceName(instruction, 2), GetSourceName(instruction, 3));
                }
                break;

            case Opcode.Sub:
                WriteLine("sub{0} {1}, {2}, {3}",
                          GetInstructionModifier(instruction), GetDestinationName(instruction),
                          GetSourceName(instruction, 1), GetSourceName(instruction, 2));
                break;

            case Opcode.Tex:
                if ((shader.MajorVersion == 1 && shader.MinorVersion >= 4) || (shader.MajorVersion > 1))
                {
                    WriteLine("texld {0}, {1}, {2}", GetDestinationName(instruction),
                              GetSourceName(instruction, 1), GetSourceName(instruction, 2));
                }
                else
                {
                    WriteLine("tex {0}", GetDestinationName(instruction));
                }
                break;

            case Opcode.TexLDL:
                WriteLine("texldl {0}, {1}, {2}", GetDestinationName(instruction),
                          GetSourceName(instruction, 1), GetSourceName(instruction, 2));
                break;

            case Opcode.TexKill:
                WriteLine("texkill {0}", GetDestinationName(instruction));
                break;

            case Opcode.Rep:
                WriteLine("rep {0}",
                          GetDestinationName(instruction));
                break;

            case Opcode.EndRep:
                WriteLine("endrep");
                break;

            case Opcode.DSX:
                WriteLine("dsx{0} {1}, {2}",
                          GetInstructionModifier(instruction), GetDestinationName(instruction), GetSourceName(instruction, 1));
                break;

            case Opcode.DSY:
                WriteLine("dsy{0} {1}, {2}",
                          GetInstructionModifier(instruction), GetDestinationName(instruction), GetSourceName(instruction, 1));
                break;

            case Opcode.TexLDD:
                WriteLine("texldd {0}, {1}, {2}, {3}, {4}", GetDestinationName(instruction), GetSourceName(instruction, 1),
                          GetSourceName(instruction, 2), GetSourceName(instruction, 3),
                          GetSourceName(instruction, 4));
                break;

            case Opcode.BreakC:
                WriteLine("break_{0} {1}, {2}",
                          ((IfComparison)instruction.Modifier).ToString().ToLower(),
                          GetSourceName(instruction, 0),
                          GetSourceName(instruction, 1));
                break;

            //TODO: Add tests for Loop, and Lit
            case Opcode.Loop:
                WriteLine("loop {0}, {1}",
                          GetSourceName(instruction, 0),
                          GetSourceName(instruction, 1));
                break;

            case Opcode.EndLoop:
                WriteLine("endloop");
                break;

            case Opcode.Lit:
                WriteLine("lit{0} {1}, {2}",
                          GetInstructionModifier(instruction), GetDestinationName(instruction),
                          GetSourceName(instruction, 1));
                break;

            case Opcode.ExpP:
                WriteLine("expp{0} {1}, {2}",
                          GetInstructionModifier(instruction), GetDestinationName(instruction),
                          GetSourceName(instruction, 1));
                break;

            case Opcode.LogP:
                WriteLine("logp{0} {1}, {2}",
                          GetInstructionModifier(instruction), GetDestinationName(instruction),
                          GetSourceName(instruction, 1));
                break;

            case Opcode.M4x4:
                WriteLine("m4x4{0} {1}, {2}, {3}",
                          GetInstructionModifier(instruction), GetDestinationName(instruction),
                          GetSourceName(instruction, 1), GetSourceName(instruction, 2));
                break;

            case Opcode.M4x3:
                WriteLine("m4x3{0} {1}, {2}, {3}",
                          GetInstructionModifier(instruction), GetDestinationName(instruction),
                          GetSourceName(instruction, 1), GetSourceName(instruction, 2));
                break;

            case Opcode.M3x3:
                WriteLine("m3x3{0} {1}, {2}, {3}",
                          GetInstructionModifier(instruction), GetDestinationName(instruction),
                          GetSourceName(instruction, 1), GetSourceName(instruction, 2));
                break;

            case Opcode.Call:
                WriteLine("call {0}",
                          GetSourceName(instruction, 0));
                break;

            case Opcode.Ret:
                WriteLine("ret");
                break;

            case Opcode.Label:
                WriteLine("label", GetSourceName(instruction, 0));
                break;

            case Opcode.Comment:
            case Opcode.End:
                break;

            default:
                WriteLine(instruction.Opcode.ToString());
                //WriteLine("// Warning - Not Implemented");
                throw new NotImplementedException($"Instruction not implemented {instruction.Opcode}");
            }
        }
        private void WriteInstruction(InstructionToken instruction)
        {
            WriteIndent();
            WriteLine($"// {instruction}");
            switch (instruction.Opcode)
            {
            case Opcode.Def:
            case Opcode.DefI:
            case Opcode.Dcl:
            case Opcode.End:
                return;

            // these opcodes doesn't need indents:
            case Opcode.Else:
                Indent--;
                WriteIndent();
                WriteLine("} else {");
                Indent++;
                return;

            case Opcode.Endif:
                Indent--;
                WriteIndent();
                WriteLine("}");
                return;

            case Opcode.EndRep:
                Indent--;
                _iterationDepth--;
                WriteIndent();
                WriteLine("}");
                return;
            }
            WriteIndent();
            switch (instruction.Opcode)
            {
            case Opcode.Abs:
                WriteLine("{0} = abs({1});", GetDestinationName(instruction),
                          GetSourceName(instruction, 1));
                break;

            case Opcode.Add:
                WriteLine("{0} = {1} + {2};", GetDestinationName(instruction),
                          GetSourceName(instruction, 1), GetSourceName(instruction, 2));
                break;

            case Opcode.Cmp:
                // TODO: should be per-component
                WriteLine("{0} = ({1} >= 0) ? {2} : {3};", GetDestinationName(instruction),
                          GetSourceName(instruction, 1), GetSourceName(instruction, 2), GetSourceName(instruction, 3));
                break;

            case Opcode.DP2Add:
                WriteLine("{0} = dot({1}, {2}) + {3};", GetDestinationName(instruction),
                          GetSourceName(instruction, 1), GetSourceName(instruction, 2), GetSourceName(instruction, 3));
                break;

            case Opcode.Dp3:
                WriteLine("{0} = dot({1}, {2});", GetDestinationName(instruction),
                          GetSourceName(instruction, 1), GetSourceName(instruction, 2));
                break;

            case Opcode.Dp4:
                WriteLine("{0} = dot({1}, {2});", GetDestinationName(instruction),
                          GetSourceName(instruction, 1), GetSourceName(instruction, 2));
                break;

            case Opcode.Exp:
                WriteLine("{0} = exp2({1});", GetDestinationName(instruction), GetSourceName(instruction, 1));
                break;

            case Opcode.Frc:
                WriteLine("{0} = frac({1});", GetDestinationName(instruction), GetSourceName(instruction, 1));
                break;

            case Opcode.If:
                WriteLine("if ({0}) {{", GetSourceName(instruction, 0));
                Indent++;
                break;

            case Opcode.IfC:
                if ((IfComparison)instruction.Modifier == IfComparison.GE &&
                    instruction.GetSourceModifier(0) == SourceModifier.AbsAndNegate &&
                    instruction.GetSourceModifier(1) == SourceModifier.Abs &&
                    instruction.GetParamRegisterName(0) + instruction.GetSourceSwizzleName(0) ==
                    instruction.GetParamRegisterName(1) + instruction.GetSourceSwizzleName(1))
                {
                    WriteLine("if ({0} == 0) {{", instruction.GetParamRegisterName(0) + instruction.GetSourceSwizzleName(0));
                }
                else if ((IfComparison)instruction.Modifier == IfComparison.LT &&
                         instruction.GetSourceModifier(0) == SourceModifier.AbsAndNegate &&
                         instruction.GetSourceModifier(1) == SourceModifier.Abs &&
                         instruction.GetParamRegisterName(0) + instruction.GetSourceSwizzleName(0) ==
                         instruction.GetParamRegisterName(1) + instruction.GetSourceSwizzleName(1))
                {
                    WriteLine("if ({0} != 0) {{", instruction.GetParamRegisterName(0) + instruction.GetSourceSwizzleName(0));
                }
                else
                {
                    string ifComparison;
                    switch ((IfComparison)instruction.Modifier)
                    {
                    case IfComparison.GT:
                        ifComparison = ">";
                        break;

                    case IfComparison.EQ:
                        ifComparison = "==";
                        break;

                    case IfComparison.GE:
                        ifComparison = ">=";
                        break;

                    case IfComparison.LE:
                        ifComparison = "<=";
                        break;

                    case IfComparison.NE:
                        ifComparison = "!=";
                        break;

                    case IfComparison.LT:
                        ifComparison = "<";
                        break;

                    default:
                        throw new InvalidOperationException();
                    }
                    WriteLine("if ({0} {2} {1}) {{", GetSourceName(instruction, 0), GetSourceName(instruction, 1), ifComparison);
                }
                Indent++;
                break;

            case Opcode.Log:
                WriteLine("{0} = log2({1});", GetDestinationName(instruction), GetSourceName(instruction, 1));
                break;

            case Opcode.Lrp:
                WriteLine("{0} = lerp({2}, {3}, {1});", GetDestinationName(instruction),
                          GetSourceName(instruction, 1), GetSourceName(instruction, 2), GetSourceName(instruction, 3));
                break;

            case Opcode.Mad:
                WriteLine("{0} = {1} * {2} + {3};", GetDestinationName(instruction),
                          GetSourceName(instruction, 1), GetSourceName(instruction, 2), GetSourceName(instruction, 3));
                break;

            case Opcode.Max:
                WriteLine("{0} = max({1}, {2});", GetDestinationName(instruction),
                          GetSourceName(instruction, 1), GetSourceName(instruction, 2));
                break;

            case Opcode.Min:
                WriteLine("{0} = min({1}, {2});", GetDestinationName(instruction),
                          GetSourceName(instruction, 1), GetSourceName(instruction, 2));
                break;

            case Opcode.Mov:
                WriteLine("{0} = {1};", GetDestinationName(instruction), GetSourceName(instruction, 1));
                break;

            case Opcode.MovA:
                WriteLine("{0} = {1};", GetDestinationName(instruction), GetSourceName(instruction, 1));
                break;

            case Opcode.Mul:
                WriteLine("{0} = {1} * {2};", GetDestinationName(instruction),
                          GetSourceName(instruction, 1), GetSourceName(instruction, 2));
                break;

            case Opcode.Nrm:
                WriteLine("{0} = normalize({1});", GetDestinationName(instruction), GetSourceName(instruction, 1));
                break;

            case Opcode.Pow:
                WriteLine("{0} = pow({1}, {2});", GetDestinationName(instruction),
                          GetSourceName(instruction, 1), GetSourceName(instruction, 2));
                break;

            case Opcode.Rcp:
                WriteLine("{0} = 1 / {1};", GetDestinationName(instruction), GetSourceName(instruction, 1));
                break;

            case Opcode.Rsq:
                WriteLine("{0} = 1 / sqrt({1});", GetDestinationName(instruction), GetSourceName(instruction, 1));
                break;

            case Opcode.Sge:
                if (instruction.GetSourceModifier(1) == SourceModifier.AbsAndNegate &&
                    instruction.GetSourceModifier(2) == SourceModifier.Abs &&
                    instruction.GetParamRegisterName(1) + instruction.GetSourceSwizzleName(1) ==
                    instruction.GetParamRegisterName(2) + instruction.GetSourceSwizzleName(2))
                {
                    WriteLine("{0} = ({1} == 0) ? 1 : 0;", GetDestinationName(instruction),
                              instruction.GetParamRegisterName(1) + instruction.GetSourceSwizzleName(1));
                }
                else
                {
                    WriteLine("{0} = ({1} >= {2}) ? 1 : 0;", GetDestinationName(instruction), GetSourceName(instruction, 1),
                              GetSourceName(instruction, 2));
                }
                break;

            case Opcode.Slt:
                WriteLine("{0} = ({1} < {2}) ? 1 : 0;", GetDestinationName(instruction), GetSourceName(instruction, 1),
                          GetSourceName(instruction, 2));
                break;

            case Opcode.SinCos:
                WriteLine("sincos({1}, {0}, {0});", GetDestinationName(instruction), GetSourceName(instruction, 1));
                break;

            case Opcode.Sub:
                WriteLine("{0} = {1} - {2};", GetDestinationName(instruction),
                          GetSourceName(instruction, 1), GetSourceName(instruction, 2));
                break;

            case Opcode.Tex:
                if ((_shader.MajorVersion == 1 && _shader.MinorVersion >= 4) || (_shader.MajorVersion > 1))
                {
                    WriteLine("{0} = tex2D({2}, {1});", GetDestinationName(instruction),
                              GetSourceName(instruction, 1), GetSourceName(instruction, 2));
                }
                else
                {
                    WriteLine("{0} = tex2D();", GetDestinationName(instruction));
                }
                break;

            case Opcode.TexLDL:
                WriteLine("{0} = tex2Dlod({2}, {1});", GetDestinationName(instruction),
                          GetSourceName(instruction, 1), GetSourceName(instruction, 2));
                break;

            case Opcode.Comment:
            {
                byte[] bytes = new byte[instruction.Data.Length * sizeof(uint)];
                Buffer.BlockCopy(instruction.Data, 0, bytes, 0, bytes.Length);
                var ascii = FormatUtil.BytesToAscii(bytes);
                WriteLine($"// Comment: {ascii}");
                break;
            }

            case Opcode.Rep:
                WriteLine("for (int it{0} = 0; it{0} < {1}; ++it{0}) {{", _iterationDepth, GetSourceName(instruction, 0));
                _iterationDepth++;
                Indent++;
                break;

            case Opcode.TexKill:
                WriteLine("clip({0});", GetDestinationName(instruction));
                break;

            default:
                throw new NotImplementedException(instruction.Opcode.ToString());
            }
        }
        public string GetSourceName(InstructionToken instruction, int srcIndex)
        {
            string      sourceRegisterName;
            RegisterKey registerKey  = instruction.GetParamRegisterKey(srcIndex);
            var         registerType = instruction.GetParamRegisterType(srcIndex);

            switch (registerType)
            {
            case RegisterType.Const:
            case RegisterType.Const2:
            case RegisterType.Const3:
            case RegisterType.Const4:
            case RegisterType.ConstBool:
            case RegisterType.ConstInt:
                sourceRegisterName = GetSourceConstantName(instruction, srcIndex);
                if (sourceRegisterName != null)
                {
                    return(sourceRegisterName);
                }

                ParameterType parameterType;
                switch (registerType)
                {
                case RegisterType.Const:
                case RegisterType.Const2:
                case RegisterType.Const3:
                case RegisterType.Const4:
                    parameterType = ParameterType.Float;
                    break;

                case RegisterType.ConstBool:
                    parameterType = ParameterType.Bool;
                    break;

                case RegisterType.ConstInt:
                    parameterType = ParameterType.Int;
                    break;

                default:
                    throw new NotImplementedException();
                }
                var registerNumber       = instruction.GetParamRegisterNumber(srcIndex);
                ConstantDeclaration decl = FindConstant(registerNumber);
                if (decl == null)
                {
                    // Constant register not found in def statements nor the constant table
                    //TODO:
                    return($"Error {registerType}{registerNumber}");
                    //throw new NotImplementedException();
                }
                var totalOffset      = registerNumber - decl.RegisterIndex;
                var data             = decl.GetRegisterTypeByOffset(totalOffset);
                var offsetFromMember = registerNumber - data.RegisterIndex;
                sourceRegisterName = decl.GetMemberNameByOffset(totalOffset);
                if (data.Type.ParameterClass == ParameterClass.MatrixRows)
                {
                    sourceRegisterName = string.Format("{0}[{1}]", decl.Name, offsetFromMember);
                }
                else if (data.Type.ParameterClass == ParameterClass.MatrixColumns)
                {
                    sourceRegisterName = string.Format("transpose({0})[{1}]", decl.Name, offsetFromMember);
                }
                break;

            default:
                sourceRegisterName = GetRegisterName(registerKey);
                break;
            }

            sourceRegisterName = sourceRegisterName ?? instruction.GetParamRegisterName(srcIndex);

            sourceRegisterName += instruction.GetSourceSwizzleName(srcIndex, true);
            return(ApplyModifier(instruction.GetSourceModifier(srcIndex), sourceRegisterName));
        }