From 16dcbe8c74bd88b3bb860323fdaf5f402541729c Mon Sep 17 00:00:00 2001 From: kd-11 Date: Fri, 14 Sep 2018 12:25:40 +0300 Subject: [PATCH] rsx/vp: Fix ARL opcode properly - NOTE: The address swizzle index is only for use as src. The address registers are only used one channel at a time. - When the destination of ARL, the encoding is the same as the other temp registers --- .../RSX/Common/VertexProgramDecompiler.cpp | 51 ++++++++++--------- .../Emu/RSX/Common/VertexProgramDecompiler.h | 1 - 2 files changed, 27 insertions(+), 25 deletions(-) diff --git a/rpcs3/Emu/RSX/Common/VertexProgramDecompiler.cpp b/rpcs3/Emu/RSX/Common/VertexProgramDecompiler.cpp index 724fd205dd..8a181f150b 100644 --- a/rpcs3/Emu/RSX/Common/VertexProgramDecompiler.cpp +++ b/rpcs3/Emu/RSX/Common/VertexProgramDecompiler.cpp @@ -40,24 +40,43 @@ std::string VertexProgramDecompiler::GetScaMask() std::string VertexProgramDecompiler::GetDST(bool isSca) { std::string ret; - std::string mask = GetMask(isSca); + // ARL writes to special integer registers + const bool is_address_reg = !isSca && (d1.vec_opcode == RSX_VEC_OPCODE_ARL); + switch ((isSca && d3.sca_dst_tmp != 0x3f) ? 0x1f : d3.dst) { case 0x1f: - ret += m_parr.AddParam(PF_PARAM_NONE, getFloatTypeName(4), std::string("tmp") + std::to_string(isSca ? d3.sca_dst_tmp : d0.dst_tmp)) + mask; + { + const std::string reg_type = (is_address_reg) ? getIntTypeName(4) : getFloatTypeName(4); + const std::string reg_sel = (is_address_reg) ? "a" : "tmp"; + ret += m_parr.AddParam(PF_PARAM_NONE, reg_type, reg_sel + std::to_string(isSca ? d3.sca_dst_tmp : d0.dst_tmp)) + mask; break; - + } default: + { + if (is_address_reg) + { + LOG_ERROR(RSX, "ARL opcode writing to output register!"); + } + if (d3.dst > 15) + { LOG_ERROR(RSX, "dst index out of range: %u", d3.dst); + } + ret += m_parr.AddParam(PF_PARAM_OUT, getFloatTypeName(4), std::string("dst_reg") + std::to_string(d3.dst), d3.dst == 0 ? getFloatTypeName(4) + "(0.0f, 0.0f, 0.0f, 1.0f)" : getFloatTypeName(4) + "(0.0, 0.0, 0.0, 0.0)") + mask; - // Handle double destination register as 'dst_reg = tmp' + if (d0.dst_tmp != 0x3f) + { + // Handle double destination register as 'dst_reg = tmp' ret += " = " + m_parr.AddParam(PF_PARAM_NONE, getFloatTypeName(4), std::string("tmp") + std::to_string(d0.dst_tmp)) + mask; + } + break; } + } return ret; } @@ -205,10 +224,7 @@ std::string VertexProgramDecompiler::Format(const std::string& code) { "$1", std::bind(std::mem_fn(&VertexProgramDecompiler::GetSRC), this, 1) }, { "$2", std::bind(std::mem_fn(&VertexProgramDecompiler::GetSRC), this, 2) }, { "$s", std::bind(std::mem_fn(&VertexProgramDecompiler::GetSRC), this, 2) }, - { "$awm", std::bind(std::mem_fn(&VertexProgramDecompiler::AddAddrRegWithoutMask), this) }, - { "$am", std::bind(std::mem_fn(&VertexProgramDecompiler::AddAddrMask), this) }, { "$a", std::bind(std::mem_fn(&VertexProgramDecompiler::AddAddrReg), this) }, - { "$vm", std::bind(std::mem_fn(&VertexProgramDecompiler::GetVecMask), this) }, { "$t", std::bind(std::mem_fn(&VertexProgramDecompiler::GetTex), this) }, { "$ifcond ", [this]() -> std::string { @@ -343,22 +359,11 @@ void VertexProgramDecompiler::AddCodeCond(const std::string& dst, const std::str } } - -std::string VertexProgramDecompiler::AddAddrMask() -{ - static const char f[] = { 'x', 'y', 'z', 'w' }; - return std::string(".") + f[d0.addr_swz]; -} - std::string VertexProgramDecompiler::AddAddrReg() { static const char f[] = { 'x', 'y', 'z', 'w' }; - return m_parr.AddParam(PF_PARAM_NONE, getIntTypeName(4), "a" + std::to_string(d0.addr_reg_sel_1), getIntTypeName(4) + "(0, 0, 0, 0)") + AddAddrMask(); -} - -std::string VertexProgramDecompiler::AddAddrRegWithoutMask() -{ - return m_parr.AddParam(PF_PARAM_NONE, getIntTypeName(4), "a" + std::to_string(d0.addr_reg_sel_1), getIntTypeName(4) + "(0, 0, 0, 0)"); + const auto mask = std::string(".") + f[d0.addr_swz]; + return m_parr.AddParam(PF_PARAM_NONE, getIntTypeName(4), "a" + std::to_string(d0.addr_reg_sel_1), getIntTypeName(4) + "(0, 0, 0, 0)") + mask; } std::string VertexProgramDecompiler::AddCondReg() @@ -617,9 +622,7 @@ std::string VertexProgramDecompiler::Decompile() case RSX_VEC_OPCODE_MAX: SetDSTVec("max($0, $1)"); break; case RSX_VEC_OPCODE_SLT: SetDSTVec(getFloatTypeName(4) + "(" + compareFunction(COMPARE::FUNCTION_SLT, "$0", "$1") + ")"); break; case RSX_VEC_OPCODE_SGE: SetDSTVec(getFloatTypeName(4) + "(" + compareFunction(COMPARE::FUNCTION_SGE, "$0", "$1") + ")"); break; - // Note: ARL uses the vec mask to determine channels and ignores the src input mask - // Tested with SH3, BLES00574 (G-Force) and NPUB90415 (Dead Space 2 Demo) - case RSX_VEC_OPCODE_ARL: AddCode("$ifcond $awm$vm = " + getIntTypeName(4) + "($0)$vm;"); break; + case RSX_VEC_OPCODE_ARL: SetDSTVec(getIntTypeName(4) + "($0)"); break; case RSX_VEC_OPCODE_FRC: SetDSTVec(getFunction(FUNCTION::FUNCTION_FRACT)); break; case RSX_VEC_OPCODE_FLR: SetDSTVec("floor($0)"); break; case RSX_VEC_OPCODE_SEQ: SetDSTVec(getFloatTypeName(4) + "(" + compareFunction(COMPARE::FUNCTION_SEQ, "$0", "$1") + ")"); break; @@ -677,7 +680,7 @@ std::string VertexProgramDecompiler::Decompile() AddCode("$ifcond //BRA"); AddCode("{"); m_cur_instr->open_scopes++; - AddCode("jump_position = $a$am;"); + AddCode("jump_position = $a;"); AddCode("continue;"); m_cur_instr->close_scopes++; AddCode("}"); diff --git a/rpcs3/Emu/RSX/Common/VertexProgramDecompiler.h b/rpcs3/Emu/RSX/Common/VertexProgramDecompiler.h index 38e022e18c..3ddb9e1b70 100644 --- a/rpcs3/Emu/RSX/Common/VertexProgramDecompiler.h +++ b/rpcs3/Emu/RSX/Common/VertexProgramDecompiler.h @@ -70,7 +70,6 @@ struct VertexProgramDecompiler std::string GetOptionalBranchCond(); //Conditional branch expression modified externally at runtime std::string AddAddrMask(); std::string AddAddrReg(); - std::string AddAddrRegWithoutMask(); std::string AddCondReg(); u32 GetAddr(); std::string Format(const std::string& code);