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