private void GenInst1u(ShaderProgram Program, uint InstOp) { ShaderOpCode OpCode = (ShaderOpCode)(InstOp >> 26); ShaderInst1 Inst = new ShaderInst1(InstOp); string Dest = GetDstReg(Program, Inst.Dest); string Src1 = GetSrcReg(Program, Inst.Src1, Inst.Idx1); SHBin.GetSwizzles( Inst.Desc, out string SDst, out string[] SSrc, out string[] SSrcM); string[] Signs = SHBin.GetSrcSigns(Inst.Desc); Src1 = Signs[0] + Src1; switch (OpCode) { case ShaderOpCode.Ex2: Append($"{Dest}.{SDst} = exp2({Src1}.{SSrcM[0]});"); break; case ShaderOpCode.Lg2: Append($"{Dest}.{SDst} = log2({Src1}.{SSrcM[0]});"); break; case ShaderOpCode.LitP: GenLitP(Src1, Dest); break; case ShaderOpCode.Flr: Append($"{Dest}.{SDst} = floor({Src1}.{SSrcM[0]});"); break; case ShaderOpCode.Rcp: Append($"{Dest}.{SDst} = {GetVecCtor("1", SDst.Length)} / {Src1}.{SSrcM[0]};"); break; case ShaderOpCode.RSq: Append($"{Dest}.{SDst} = inversesqrt({Src1}.{SSrcM[0]});"); break; case ShaderOpCode.MovA: GenMovA(Src1, SSrcM[0], SDst); break; case ShaderOpCode.Mov: Append($"{Dest}.{SDst} = {Src1}.{SSrcM[0]};"); break; } }
private void GenInst3(ShaderProgram Program, uint InstOp) { ShaderOpCode OpCode = (ShaderOpCode)(InstOp >> 26); ShaderInst3 Inst = new ShaderInst3(InstOp); switch (OpCode) { case ShaderOpCode.IfU: GenIfU(Program, Inst); break; case ShaderOpCode.CallU: GenCallU(Program, Inst); break; case ShaderOpCode.Loop: GenLoop(Program, Inst); break; case ShaderOpCode.JmpU: GenJmpU(Program, Inst); break; } }
private void GenInst2(ShaderProgram Program, uint InstOp) { ShaderOpCode OpCode = (ShaderOpCode)(InstOp >> 26); ShaderInst2 Inst = new ShaderInst2(InstOp); switch (OpCode) { case ShaderOpCode.BreakC: GenBreakC(Program, Inst); break; case ShaderOpCode.Call: GenCall(Program, Inst); break; case ShaderOpCode.CallC: GenCallC(Program, Inst); break; case ShaderOpCode.IfC: GenIfC(Program, Inst); break; case ShaderOpCode.JmpC: GenJmpC(Program, Inst); break; } }
private void GenInst1i(ShaderProgram Program, uint InstOp) { ShaderOpCode OpCode = (ShaderOpCode)(InstOp >> 26); ShaderInst1i Inst = new ShaderInst1i(InstOp); string Dest = GetDstReg(Program, Inst.Dest); string Src1 = GetSrcReg(Program, Inst.Src1); string Src2 = GetSrcReg(Program, Inst.Src2, Inst.Idx2); SHBin.GetSwizzles( Inst.Desc, out string SDst, out string[] SSrc, out string[] SSrcM); string[] Signs = SHBin.GetSrcSigns(Inst.Desc); Src1 = Signs[0] + Src1; Src2 = Signs[1] + Src2; switch (OpCode) { case ShaderOpCode.DPHI: GenDPH(Src1, Src2, SSrc[0], SSrc[1], Dest, SDst); break; case ShaderOpCode.DstI: Append($"{Dest} = vec4(1, {Src1}.y * {Src1}.y, {Src1}.z, {Src2}.w);"); break; case ShaderOpCode.SGEI: GenSGE(Src1, Src1, SSrcM[0], SSrcM[1], Dest, SDst); break; case ShaderOpCode.SLTI: GenSLT(Src1, Src1, SSrcM[0], SSrcM[1], Dest, SDst); break; } }
public GFShader(BinaryReader Reader) : this() { uint MagicNumber = Reader.ReadUInt32(); uint ShaderCount = Reader.ReadUInt32(); GFSection.SkipPadding(Reader.BaseStream); GFSection ShaderSection = new GFSection(Reader); Name = Reader.ReadPaddedString(0x40); uint Hash = Reader.ReadUInt32(); uint Count = Reader.ReadUInt32(); GFSection.SkipPadding(Reader.BaseStream); uint CommandsLength = Reader.ReadUInt32(); uint CommandsCount = Reader.ReadUInt32(); uint CommandsHash = Reader.ReadUInt32(); uint Padding = Reader.ReadUInt32(); string FileName = Reader.ReadPaddedString(0x40); uint[] Commands = new uint[CommandsLength >> 2]; for (int Index = 0; Index < Commands.Length; Index++) { Commands[Index] = Reader.ReadUInt32(); } uint[] OutMap = new uint[7]; List <uint> ShaderExecutable = new List <uint>(); List <ulong> ShaderSwizzles = new List <ulong>(); PICACommandReader CmdReader = new PICACommandReader(Commands); while (CmdReader.HasCommand) { PICACommand Cmd = CmdReader.GetCommand(); uint Param = Cmd.Parameters[0]; int Stage = ((int)Cmd.Register >> 3) & 7; if (Stage >= 6) { Stage -= 2; } switch (Cmd.Register) { /* Shader */ case PICARegister.GPUREG_SH_OUTMAP_O0: OutMap[0] = Param; break; case PICARegister.GPUREG_SH_OUTMAP_O1: OutMap[1] = Param; break; case PICARegister.GPUREG_SH_OUTMAP_O2: OutMap[2] = Param; break; case PICARegister.GPUREG_SH_OUTMAP_O3: OutMap[3] = Param; break; case PICARegister.GPUREG_SH_OUTMAP_O4: OutMap[4] = Param; break; case PICARegister.GPUREG_SH_OUTMAP_O5: OutMap[5] = Param; break; case PICARegister.GPUREG_SH_OUTMAP_O6: OutMap[6] = Param; break; /* Fragment Shader */ case PICARegister.GPUREG_TEXENV0_SOURCE: case PICARegister.GPUREG_TEXENV1_SOURCE: case PICARegister.GPUREG_TEXENV2_SOURCE: case PICARegister.GPUREG_TEXENV3_SOURCE: case PICARegister.GPUREG_TEXENV4_SOURCE: case PICARegister.GPUREG_TEXENV5_SOURCE: TexEnvStages[Stage].Source = new PICATexEnvSource(Param); break; case PICARegister.GPUREG_TEXENV0_OPERAND: case PICARegister.GPUREG_TEXENV1_OPERAND: case PICARegister.GPUREG_TEXENV2_OPERAND: case PICARegister.GPUREG_TEXENV3_OPERAND: case PICARegister.GPUREG_TEXENV4_OPERAND: case PICARegister.GPUREG_TEXENV5_OPERAND: TexEnvStages[Stage].Operand = new PICATexEnvOperand(Param); break; case PICARegister.GPUREG_TEXENV0_COMBINER: case PICARegister.GPUREG_TEXENV1_COMBINER: case PICARegister.GPUREG_TEXENV2_COMBINER: case PICARegister.GPUREG_TEXENV3_COMBINER: case PICARegister.GPUREG_TEXENV4_COMBINER: case PICARegister.GPUREG_TEXENV5_COMBINER: TexEnvStages[Stage].Combiner = new PICATexEnvCombiner(Param); break; case PICARegister.GPUREG_TEXENV0_COLOR: case PICARegister.GPUREG_TEXENV1_COLOR: case PICARegister.GPUREG_TEXENV2_COLOR: case PICARegister.GPUREG_TEXENV3_COLOR: case PICARegister.GPUREG_TEXENV4_COLOR: case PICARegister.GPUREG_TEXENV5_COLOR: TexEnvStages[Stage].Color = new RGBA(Param); break; case PICARegister.GPUREG_TEXENV0_SCALE: case PICARegister.GPUREG_TEXENV1_SCALE: case PICARegister.GPUREG_TEXENV2_SCALE: case PICARegister.GPUREG_TEXENV3_SCALE: case PICARegister.GPUREG_TEXENV4_SCALE: case PICARegister.GPUREG_TEXENV5_SCALE: TexEnvStages[Stage].Scale = new PICATexEnvScale(Param); break; case PICARegister.GPUREG_TEXENV_UPDATE_BUFFER: PICATexEnvStage.SetUpdateBuffer(TexEnvStages, Param); break; case PICARegister.GPUREG_TEXENV_BUFFER_COLOR: TexEnvBufferColor = new RGBA(Param); break; /* Geometry Shader */ case PICARegister.GPUREG_GSH_ENTRYPOINT: if (GeoShader == null) { GeoShader = new ShaderProgram(); } GeoShader.MainOffset = Param & 0xffff; break; /* Vertex Shader */ case PICARegister.GPUREG_VSH_CODETRANSFER_DATA0: case PICARegister.GPUREG_VSH_CODETRANSFER_DATA1: case PICARegister.GPUREG_VSH_CODETRANSFER_DATA2: case PICARegister.GPUREG_VSH_CODETRANSFER_DATA3: case PICARegister.GPUREG_VSH_CODETRANSFER_DATA4: case PICARegister.GPUREG_VSH_CODETRANSFER_DATA5: case PICARegister.GPUREG_VSH_CODETRANSFER_DATA6: case PICARegister.GPUREG_VSH_CODETRANSFER_DATA7: ShaderExecutable.AddRange(Cmd.Parameters); break; case PICARegister.GPUREG_VSH_OPDESCS_DATA0: case PICARegister.GPUREG_VSH_OPDESCS_DATA1: case PICARegister.GPUREG_VSH_OPDESCS_DATA2: case PICARegister.GPUREG_VSH_OPDESCS_DATA3: case PICARegister.GPUREG_VSH_OPDESCS_DATA4: case PICARegister.GPUREG_VSH_OPDESCS_DATA5: case PICARegister.GPUREG_VSH_OPDESCS_DATA6: case PICARegister.GPUREG_VSH_OPDESCS_DATA7: for (int i = 0; i < Cmd.Parameters.Length; i++) { ShaderSwizzles.Add(Cmd.Parameters[i]); } break; case PICARegister.GPUREG_VSH_ENTRYPOINT: if (VtxShader == null) { VtxShader = new ShaderProgram(); } VtxShader.MainOffset = Param & 0xffff; break; } } Executable = ShaderExecutable.ToArray(); Swizzles = ShaderSwizzles.ToArray(); for (int i = 0; i < OutMap.Length; i++) { if (OutMap[i] == 0) { continue; } ShaderOutputReg Reg = new ShaderOutputReg(); for (int j = 0; j < 4; j++) { uint Value = (OutMap[i] >> j * 8) & 0x1f; if (Value != 0x1f) { Reg.Mask |= 1u << j; if (Value < 0x4) { Reg.Name = ShaderOutputRegName.Position; } else if (Value < 0x8) { Reg.Name = ShaderOutputRegName.QuatNormal; } else if (Value < 0xc) { Reg.Name = ShaderOutputRegName.Color; } else if (Value < 0xe) { Reg.Name = ShaderOutputRegName.TexCoord0; } else if (Value < 0x10) { Reg.Name = ShaderOutputRegName.TexCoord1; } else if (Value < 0x11) { Reg.Name = ShaderOutputRegName.TexCoord0W; } else if (Value < 0x12) { Reg.Name = ShaderOutputRegName.Generic; } else if (Value < 0x16) { Reg.Name = ShaderOutputRegName.View; } else if (Value < 0x18) { Reg.Name = ShaderOutputRegName.TexCoord2; } else { Reg.Name = ShaderOutputRegName.Generic; } } } if (VtxShader != null) { VtxShader.OutputRegs[i] = Reg; } if (GeoShader != null) { GeoShader.OutputRegs[i] = Reg; } } HashSet <uint> Dsts = new HashSet <uint>(); uint LblId = 0; for (uint i = 0; i < Executable.Length; i++) { ShaderOpCode OpCode = (ShaderOpCode)(Executable[i] >> 26); if (OpCode == ShaderOpCode.Call || OpCode == ShaderOpCode.CallC || OpCode == ShaderOpCode.CallU || OpCode == ShaderOpCode.JmpC || OpCode == ShaderOpCode.JmpU) { uint Dst = (Executable[i] >> 10) & 0xfff; if (!Dsts.Contains(Dst)) { Dsts.Add(Dst); string Name = "label_" + Dst.ToString("x4"); ShaderLabel Label = new ShaderLabel() { Id = LblId++, Offset = Dst, Length = 0, Name = Name }; if (VtxShader != null) { VtxShader.Labels.Add(Label); } if (GeoShader != null) { GeoShader.Labels.Add(Label); } } } } MakeArray(VtxShader?.Vec4Uniforms, "v_c"); MakeArray(GeoShader?.Vec4Uniforms, "g_c"); FindProgramEnd(VtxShader, Executable); FindProgramEnd(GeoShader, Executable); VtxShaderUniforms = CmdReader.GetAllVertexShaderUniforms(); GeoShaderUniforms = CmdReader.GetAllGeometryShaderUniforms(); }
private void GenInst1(ShaderProgram Program, uint InstOp) { ShaderOpCode OpCode = (ShaderOpCode)(InstOp >> 26); ShaderInst1 Inst = new ShaderInst1(InstOp); string Dest = GetDstReg(Program, Inst.Dest); string Src1 = GetSrcReg(Program, Inst.Src1, Inst.Idx1); string Src2 = GetSrcReg(Program, Inst.Src2); SHBin.GetSwizzles( Inst.Desc, out string SDst, out string[] SSrc, out string[] SSrcM); string[] Signs = SHBin.GetSrcSigns(Inst.Desc); Src1 = Signs[0] + Src1; Src2 = Signs[1] + Src2; switch (OpCode) { case ShaderOpCode.Add: Append($"{Dest}.{SDst} = {Src1}.{SSrcM[0]} + {Src2}.{SSrcM[1]};"); break; case ShaderOpCode.DP3: GenDP3(Src1, Src2, SSrc[0], SSrc[1], Dest, SDst); break; case ShaderOpCode.DP4: Append($"{Dest}.{SDst} = {GetVecCtor($"dot({Src1}.{SSrc[0]}, {Src2}.{SSrc[1]})", SDst.Length)};"); break; case ShaderOpCode.DPH: GenDPH(Src1, Src2, SSrc[0], SSrc[1], Dest, SDst); break; case ShaderOpCode.Dst: Append($"{Dest} = vec4(1, {Src1}.y * {Src1}.y, {Src1}.z, {Src2}.w);"); break; case ShaderOpCode.Mul: Append($"{Dest}.{SDst} = {Src1}.{SSrcM[0]} * {Src2}.{SSrcM[1]};"); break; case ShaderOpCode.SGE: GenSGE(Src1, Src1, SSrcM[0], SSrcM[1], Dest, SDst); break; case ShaderOpCode.SLT: GenSLT(Src1, Src1, SSrcM[0], SSrcM[1], Dest, SDst); break; case ShaderOpCode.Max: Append($"{Dest}.{SDst} = max({Src1}.{SSrcM[0]}, {Src2}.{SSrcM[1]});"); break; case ShaderOpCode.Min: Append($"{Dest}.{SDst} = min({Src1}.{SSrcM[0]}, {Src2}.{SSrcM[1]});"); break; } }