diff --git a/rpcs3/Emu/RSX/Common/FragmentProgramDecompiler.cpp b/rpcs3/Emu/RSX/Common/FragmentProgramDecompiler.cpp index 870501355d..4a4a0c79b5 100644 --- a/rpcs3/Emu/RSX/Common/FragmentProgramDecompiler.cpp +++ b/rpcs3/Emu/RSX/Common/FragmentProgramDecompiler.cpp @@ -186,6 +186,11 @@ std::string FragmentProgramDecompiler::AddType3() return m_parr.AddParam(PF_PARAM_NONE, getFloatTypeName(4), "src3", getFloatTypeName(4) + "(1., 1., 1., 1.)"); } +std::string FragmentProgramDecompiler::AddX2d() +{ + return m_parr.AddParam(PF_PARAM_NONE, getFloatTypeName(4), "x2d", getFloatTypeName(4) + "(0., 0., 0., 0.)"); +} + //Both of these were tested with a trace SoulCalibur IV title screen //Failure to catch causes infinite values since theres alot of rcp(0) std::string FragmentProgramDecompiler::NotZero(const std::string& code) @@ -233,7 +238,7 @@ bool FragmentProgramDecompiler::DstExpectsSca() return (writes == 1); } -std::string FragmentProgramDecompiler::Format(const std::string& code) +std::string FragmentProgramDecompiler::Format(const std::string& code, bool ignore_redirects) { const std::pair> repl_list[] = { @@ -255,6 +260,20 @@ std::string FragmentProgramDecompiler::Format(const std::string& code) { "$_c", std::bind(std::mem_fn(&FragmentProgramDecompiler::AddConst), this) } }; + if (!ignore_redirects) + { + //Special processing redirects + if (dst.opcode == RSX_FP_OPCODE_TEXBEM) + { + //Redirect parameter 0 to the x2d temp register for TEXBEM + //TODO: Organize this a little better + std::pair repl[] = { { "$0", "x2d" } }; + std::string result = fmt::replace_all(code, repl); + + return fmt::replace_all(code, repl_list); + } + } + return fmt::replace_all(code, repl_list); } @@ -573,8 +592,9 @@ bool FragmentProgramDecompiler::handle_tex_srb(u32 opcode) case RSX_FP_OPCODE_NRM: SetDst("normalize($0.xyz)"); return true; case RSX_FP_OPCODE_BEM: SetDst("$0.xyxy + $1.xxxx * $2.xzxz + $1.yyyy * $2.ywyw"); return true; case RSX_FP_OPCODE_TEXBEM: - //treat as TEX for now - LOG_ERROR(RSX, "Unimplemented TEX_SRB instruction: TEXBEM"); + //Untested, should be x2d followed by TEX + AddX2d(); + AddCode(Format("x2d = $0.xyxy + $1.xxxx * $2.xzxz + $1.yyyy * $2.ywyw", true)); case RSX_FP_OPCODE_TEX: switch (m_prog.get_texture_dimension(dst.tex_num)) { diff --git a/rpcs3/Emu/RSX/Common/FragmentProgramDecompiler.h b/rpcs3/Emu/RSX/Common/FragmentProgramDecompiler.h index 7eeffc9a50..89abd9b54f 100644 --- a/rpcs3/Emu/RSX/Common/FragmentProgramDecompiler.h +++ b/rpcs3/Emu/RSX/Common/FragmentProgramDecompiler.h @@ -126,11 +126,14 @@ class FragmentProgramDecompiler std::string AddConst(); std::string AddTex(); void AddFlowOp(std::string code); - std::string Format(const std::string& code); + std::string Format(const std::string& code, bool ignore_redirects = false); //Technically a temporary workaround until we know what type3 is std::string AddType3(); + //Support the transform-2d temp result for use with TEXBEM + std::string AddX2d(); + //Prevent division by zero by catching denormals //Simpler variant where input and output are expected to be positive std::string NotZero(const std::string& code);