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));
        }
Beispiel #2
0
        private void WriteInstruction(D3D9Instruction instruction)
        {
            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.Else:
                indent = indent.Substring(0, indent.Length - 1);
                WriteLine("} else {");
                indent += "\t";
                break;

            case Opcode.Endif:
                indent = indent.Substring(0, indent.Length - 1);
                WriteLine("}");
                break;

            case Opcode.EndLoop:
            case Opcode.EndRep:
                indent = indent.Substring(0, indent.Length - 1);
                WriteLine("}");
                _loopVariableIndex--;
                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 += "\t";
                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 += "\t";
                break;

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

            case Opcode.Loop:
                ConstantIntRegister intRegister = _registers.FindConstantIntRegister(instruction.GetParamRegisterNumber(1));
                uint end    = intRegister.Value[0];
                uint start  = intRegister.Value[1];
                uint stride = intRegister.Value[2];
                _loopVariableIndex++;
                string loopVariable = "i" + _loopVariableIndex;
                if (stride == 1)
                {
                    WriteLine("for (int {2} = {0}; {2} < {1}; {2}++) {{", start, end, loopVariable);
                }
                else
                {
                    WriteLine("for (int {3} = {0}; {3} < {1}; {3} += {2}) {{", start, end, stride, loopVariable);
                }
                indent += "\t";
                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.Rep:
                ConstantIntRegister loopRegister = _registers.FindConstantIntRegister(instruction.GetParamRegisterNumber(0));
                _loopVariableIndex++;
                WriteLine("for (int {1} = 0; {1} < {0}; {1}++) {{", loopRegister[0], "i" + _loopVariableIndex);
                indent += "\t";
                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.TexKill:
                WriteLine("clip({0});", GetDestinationName(instruction));
                break;

            case Opcode.Def:
            case Opcode.DefB:
            case Opcode.DefI:
            case Opcode.Dcl:
            case Opcode.Comment:
            case Opcode.End:
                break;

            default:
                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);
            }
        }