public string GetSourceName(D3D9Instruction instruction, int srcIndex)
        {
            string sourceRegisterName;

            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();
                }
                int registerNumber       = instruction.GetParamRegisterNumber(srcIndex);
                ConstantDeclaration decl = FindConstant(parameterType, registerNumber);
                if (decl == null)
                {
                    // Constant register not found in def statements nor the constant table
                    throw new NotImplementedException();
                }

                if ((decl.ParameterClass == ParameterClass.MatrixRows && ColumnMajorOrder) ||
                    (decl.ParameterClass == ParameterClass.MatrixColumns && !ColumnMajorOrder))
                {
                    int row = registerNumber - decl.RegisterIndex;
                    sourceRegisterName = $"{decl.Name}[{row}]";
                }
                else if ((decl.ParameterClass == ParameterClass.MatrixColumns && ColumnMajorOrder) ||
                         (decl.ParameterClass == ParameterClass.MatrixRows && !ColumnMajorOrder))
                {
                    int column = registerNumber - decl.RegisterIndex;
                    sourceRegisterName = $"transpose({decl.Name})[{column}]";
                }
                else
                {
                    sourceRegisterName = decl.Name;
                }
                break;

            default:
                RegisterKey registerKey = instruction.GetParamRegisterKey(srcIndex);
                sourceRegisterName = GetRegisterName(registerKey);
                break;
            }

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

            sourceRegisterName += GetRelativeAddressingName(instruction, srcIndex);
            sourceRegisterName += instruction.GetSourceSwizzleName(srcIndex);
            return(ApplyModifier(instruction.GetSourceModifier(srcIndex), sourceRegisterName));
        }
        public static void Verify(D3D9Instruction instruction)
        {
            //Assert(currentInstruction.Modifier == 0);
            Assert(!instruction.Predicated);

            switch (instruction.Opcode)
            {
            case Opcode.Dcl:
                // https://msdn.microsoft.com/en-us/library/windows/hardware/ff549176(v=vs.85).aspx
                Assert(instruction.Params.Count == 2);
                uint param0 = instruction.Params[0];
                switch (instruction.GetParamRegisterType(1))
                {
                case RegisterType.Sampler:
                    Assert((param0 & 0x07FFFFFF) == 0);
                    break;

                case RegisterType.Input:
                case RegisterType.Output:
                case RegisterType.Texture:
                    Assert((param0 & 0x0000FFF0) == 0);
                    Assert((param0 & 0x7FF00000) == 0);
                    break;
                }
                Assert((param0 & 0x80000000) != 0);
                break;

            case Opcode.Def:
            {
                Assert(instruction.Params.Count == 5);
                var registerType = instruction.GetParamRegisterType(0);
                Assert(
                    registerType == RegisterType.Const ||
                    registerType == RegisterType.Const2 ||
                    registerType == RegisterType.Const3 ||
                    registerType == RegisterType.Const4);
            }
            break;

            case Opcode.DefI:
            {
                Assert(instruction.Params.Count == 5);
                var registerType = instruction.GetParamRegisterType(0);
                Assert(registerType == RegisterType.ConstInt);
            }
            break;

            case Opcode.IfC:
                IfComparison comp = (IfComparison)instruction.Modifier;
                Assert(
                    comp == IfComparison.GT ||
                    comp == IfComparison.EQ ||
                    comp == IfComparison.GE ||
                    comp == IfComparison.LT ||
                    comp == IfComparison.NE ||
                    comp == IfComparison.LE);
                break;

            default:
                //throw new NotImplementedException();
                break;
            }
        }
        private string GetSourceConstantName(D3D9Instruction instruction, int srcIndex)
        {
            var registerType   = instruction.GetParamRegisterType(srcIndex);
            int registerNumber = instruction.GetParamRegisterNumber(srcIndex);

            switch (registerType)
            {
            case RegisterType.ConstBool:
                //throw new NotImplementedException();
                return(null);

            case RegisterType.ConstInt:
            {
                var constantInt = _constantIntDefinitions.FirstOrDefault(x => x.RegisterIndex == registerNumber);
                if (constantInt == null)
                {
                    return(null);
                }
                byte[] swizzle  = instruction.GetSourceSwizzleComponents(srcIndex);
                uint[] constant =
                {
                    constantInt[swizzle[0]],
                    constantInt[swizzle[1]],
                    constantInt[swizzle[2]],
                    constantInt[swizzle[3]]
                };

                switch (instruction.GetSourceModifier(srcIndex))
                {
                case SourceModifier.None:
                    break;

                case SourceModifier.Negate:
                    throw new NotImplementedException();

                    /*
                     * for (int i = 0; i < 4; i++)
                     * {
                     *  constant[i] = -constant[i];
                     * }*/
                    break;

                default:
                    throw new NotImplementedException();
                }

                int destLength = instruction.GetDestinationMaskLength();
                switch (destLength)
                {
                case 1:
                    return(constant[0].ToString());

                case 2:
                    if (constant[0] == constant[1])
                    {
                        return(constant[0].ToString());
                    }
                    return($"int2({constant[0]}, {constant[1]})");

                case 3:
                    if (constant[0] == constant[1] && constant[0] == constant[2])
                    {
                        return(constant[0].ToString());
                    }
                    return($"int3({constant[0]}, {constant[1]}, {constant[2]})");

                case 4:
                    if (constant[0] == constant[1] && constant[0] == constant[2] && constant[0] == constant[3])
                    {
                        return(constant[0].ToString());
                    }
                    return($"int4({constant[0]}, {constant[1]}, {constant[2]}, {constant[3]})");

                default:
                    throw new InvalidOperationException();
                }
            }

            case RegisterType.Const:
            case RegisterType.Const2:
            case RegisterType.Const3:
            case RegisterType.Const4:
            {
                var constantRegister = _constantDefinitions.FirstOrDefault(x => x.RegisterIndex == registerNumber);
                if (constantRegister == null)
                {
                    return(null);
                }

                byte[]  swizzle  = instruction.GetSourceSwizzleComponents(srcIndex);
                float[] constant =
                {
                    constantRegister[swizzle[0]],
                    constantRegister[swizzle[1]],
                    constantRegister[swizzle[2]],
                    constantRegister[swizzle[3]]
                };

                switch (instruction.GetSourceModifier(srcIndex))
                {
                case SourceModifier.None:
                    break;

                case SourceModifier.Negate:
                    for (int i = 0; i < 4; i++)
                    {
                        constant[i] = -constant[i];
                    }
                    break;

                default:
                    throw new NotImplementedException();
                }

                int destLength;
                if (instruction.HasDestination)
                {
                    destLength = instruction.GetDestinationMaskLength();
                }
                else
                {
                    if (instruction is D3D9Instruction d3D9Instruction &&
                        (d3D9Instruction.Opcode == Opcode.If || d3D9Instruction.Opcode == Opcode.IfC))
                    {
                        // TODO
                    }
                    destLength = 4;
                }
                switch (destLength)
                {
                case 1:
                    return(constant[0].ToString(_culture));

                case 2:
                    if (constant[0] == constant[1])
                    {
                        return(constant[0].ToString(_culture));
                    }
                    return(string.Format("float2({0}, {1})",
                                         constant[0].ToString(_culture),
                                         constant[1].ToString(_culture)));

                case 3:
                    if (constant[0] == constant[1] && constant[0] == constant[2])
                    {
                        return(constant[0].ToString(_culture));
                    }
                    return(string.Format("float3({0}, {1}, {2})",
                                         constant[0].ToString(_culture),
                                         constant[1].ToString(_culture),
                                         constant[2].ToString(_culture)));

                case 4:
                    if (constant[0] == constant[1] && constant[0] == constant[2] && constant[0] == constant[3])
                    {
                        return(constant[0].ToString(_culture));
                    }
                    return(string.Format("float4({0}, {1}, {2}, {3})",
                                         constant[0].ToString(_culture),
                                         constant[1].ToString(_culture),
                                         constant[2].ToString(_culture),
                                         constant[3].ToString(_culture)));

                default:
                    throw new InvalidOperationException();
                }
            }

            default:
                return(null);
            }
        }