diff --git a/Utilities/StrFmt.h b/Utilities/StrFmt.h index 9116c26227..8aa2f897b8 100644 --- a/Utilities/StrFmt.h +++ b/Utilities/StrFmt.h @@ -116,7 +116,7 @@ namespace fmt{ if (src.substr(pos, comp_length) == list[i].first) { src = (pos ? src.substr(0, pos) + list[i].second : list[i].second) + std::string(src.c_str() + pos + comp_length); - pos += list[i].second.length(); + pos += list[i].second.length() - 1; break; } } @@ -140,7 +140,7 @@ namespace fmt{ if (src.substr(pos, comp_length) == list[i].first) { src = (pos ? src.substr(0, pos) + list[i].second() : list[i].second()) + std::string(src.c_str() + pos + comp_length); - pos += list[i].second().length(); + pos += list[i].second().length() - 1; break; } } diff --git a/rpcs3/Emu/ConLog.h b/rpcs3/Emu/ConLog.h index fffb6bda73..3ec96fd81d 100644 --- a/rpcs3/Emu/ConLog.h +++ b/rpcs3/Emu/ConLog.h @@ -17,28 +17,28 @@ public: LogWriter(); template - void Write(const std::string &fmt, Arg&&... args) + void Write(const std::string &fmt, Arg... args) { std::string frmt = fmt::Format(fmt, std::forward(args)...); WriteToLog("!", frmt, 2); } - + template - void Error(const std::string &fmt, Arg&&... args) + void Error(const std::string &fmt, Arg... args) { std::string frmt = fmt::Format(fmt, std::forward(args)...); WriteToLog("E", frmt, 4); } - + template - void Warning(const std::string &fmt, Arg&&... args) + void Warning(const std::string &fmt, Arg... args) { std::string frmt = fmt::Format(fmt, std::forward(args)...); WriteToLog("W", frmt, 3); } - + template - void Success(const std::string &fmt, Arg&&... args) + void Success(const std::string &fmt, Arg... args) { std::string frmt = fmt::Format(fmt, std::forward(args)...); WriteToLog("S", frmt, 1); diff --git a/rpcs3/Emu/GS/GL/GLFragmentProgram.cpp b/rpcs3/Emu/GS/GL/GLFragmentProgram.cpp index 6c603055ea..a0813bf35e 100644 --- a/rpcs3/Emu/GS/GL/GLFragmentProgram.cpp +++ b/rpcs3/Emu/GS/GL/GLFragmentProgram.cpp @@ -8,14 +8,6 @@ void GLFragmentDecompilerThread::SetDst(std::string code, bool append_mask) { if(!src0.exec_if_eq && !src0.exec_if_gr && !src0.exec_if_lt) return; - const std::string mask = GetMask(); - std::string cond; - - if(!src0.exec_if_gr || !src0.exec_if_lt || !src0.exec_if_eq) - { - cond = "if($cond) "; - } - switch(src1.scale) { case 0: break; @@ -39,24 +31,17 @@ void GLFragmentDecompilerThread::SetDst(std::string code, bool append_mask) std::string dest; - if (dst.no_dest) + if (dst.set_cond) { - if (dst.set_cond) - { - dest = m_parr.AddParam(PARAM_NONE, "vec4", "cc" + std::to_string(src0.cond_mod_reg_index)); - } - } - else - { - dest = AddReg(dst.dest_reg, dst.fp16); - - if (dst.set_cond) - { - dest = m_parr.AddParam(PARAM_NONE, "vec4", "cc" + std::to_string(src0.cond_mod_reg_index)) + mask + " = " + dest; - } + dest += m_parr.AddParam(PARAM_NONE, "vec4", "cc" + std::to_string(src0.cond_mod_reg_index)) + "$m = "; } - AddCode(cond + (dest.length() ? dest + mask + " = " : "") + code + (append_mask ? mask : "") + ";"); + if (!dst.no_dest) + { + dest += AddReg(dst.dest_reg, dst.fp16) + "$m = "; + } + + AddCode("$ifcond " + dest + code + (append_mask ? "$m;" : ";")); } void GLFragmentDecompilerThread::AddCode(const std::string& code) @@ -122,7 +107,7 @@ std::string GLFragmentDecompilerThread::AddTex() return m_parr.AddParam(PARAM_UNIFORM, "sampler2D", std::string("tex") + std::to_string(dst.tex_num)); } -std::string GLFragmentDecompilerThread::Format(std::string code) +std::string GLFragmentDecompilerThread::Format(const std::string& code) { const std::pair> repl_list[] = { @@ -131,6 +116,14 @@ std::string GLFragmentDecompilerThread::Format(std::string code) { "$1", std::bind(std::mem_fn(&GLFragmentDecompilerThread::GetSRC), this, src1) }, { "$2", std::bind(std::mem_fn(&GLFragmentDecompilerThread::GetSRC), this, src2) }, { "$t", std::bind(std::mem_fn(&GLFragmentDecompilerThread::AddTex), this) }, + { "$m", std::bind(std::mem_fn(&GLFragmentDecompilerThread::GetMask), this) }, + { "$ifcond ", [this]() -> std::string + { + const std::string& cond = GetCond(); + if (cond == "true") return ""; + return "if(" + cond + ") "; + } + }, { "$cond", std::bind(std::mem_fn(&GLFragmentDecompilerThread::GetCond), this) }, { "$c", std::bind(std::mem_fn(&GLFragmentDecompilerThread::AddConst), this) } }; @@ -201,7 +194,7 @@ template std::string GLFragmentDecompilerThread::GetSRC(T src) static const std::string reg_table[] = { "gl_Position", - "col0", "col1", + "diff_color", "spec_color", "fogc", "tc0", "tc1", "tc2", "tc3", "tc4", "tc5", "tc6", "tc7", "tc8", "tc9", "ssa" @@ -359,7 +352,7 @@ void GLFragmentDecompilerThread::Task() case 0x1b: SetDst("inversesqrt(abs($0))"); break; // RSQ case 0x1c: SetDst("exp2($0)"); break; // EX2 case 0x1d: SetDst("log2($0)"); break; // LG2 - case 0x1e: SetDst("vec4(1.0, $0.x, ($0.x > 0 ? exp($0.w * log($0.y)) : 0.0), 1.0)"); break; // LIT (compute light coefficients) + case 0x1e: SetDst("vec4(1.0, $0.x, ($0.x > 0 ? exp2($0.w * log2($0.y)) : 0.0), 1.0)"); break; // LIT (compute light coefficients) case 0x1f: SetDst("($0 * ($1 - $2) + $2)"); break; // LRP (linear interpolation) case 0x20: SetDst("vec4(equal($0, vec4(1.0)))"); break; // STR (set on true) @@ -405,7 +398,7 @@ void GLFragmentDecompilerThread::Task() break; case 0x43: //LOOP - AddCode(fmt::Format("if($cond) for(int i%u = %u; i%u < %u; i%u += %u) //LOOP", + AddCode(fmt::Format("$ifcond for(int i%u = %u; i%u < %u; i%u += %u) //LOOP", m_loop_count, src1.rep2, m_loop_count, src1.rep1, m_loop_count, src1.rep3)); m_loop_count++; m_end_offsets.push_back(src2.end_offset << 2); diff --git a/rpcs3/Emu/GS/GL/GLFragmentProgram.h b/rpcs3/Emu/GS/GL/GLFragmentProgram.h index 3aba8fa7af..b903fd927b 100644 --- a/rpcs3/Emu/GS/GL/GLFragmentProgram.h +++ b/rpcs3/Emu/GS/GL/GLFragmentProgram.h @@ -151,7 +151,7 @@ struct GLFragmentDecompilerThread : public ThreadBase std::string AddCond(); std::string AddConst(); std::string AddTex(); - std::string Format(std::string code); + std::string Format(const std::string& code); std::string GetCond(); template std::string GetSRC(T src); diff --git a/rpcs3/Emu/GS/GL/GLGSRender.cpp b/rpcs3/Emu/GS/GL/GLGSRender.cpp index 6a3ad40d37..f5dda76c88 100644 --- a/rpcs3/Emu/GS/GL/GLGSRender.cpp +++ b/rpcs3/Emu/GS/GL/GLGSRender.cpp @@ -325,7 +325,7 @@ void GLGSRender::InitVertexData() for(u32 i=0; i 1) + return; + Bind(); const u64 texaddr = GetAddress(tex.GetOffset(), tex.GetLocation()); diff --git a/rpcs3/Emu/GS/GL/GLVertexProgram.cpp b/rpcs3/Emu/GS/GL/GLVertexProgram.cpp index a9fbd960b7..f77cd244a5 100644 --- a/rpcs3/Emu/GS/GL/GLVertexProgram.cpp +++ b/rpcs3/Emu/GS/GL/GLVertexProgram.cpp @@ -39,52 +39,32 @@ std::string GLVertexDecompilerThread::GetScaMask() std::string GLVertexDecompilerThread::GetDST(bool isSca) { - static const std::string reg_table[] = - { - "gl_Position", - "col0", "col1", - "bfc0", "bfc1", - "gl_ClipDistance[%d]", - "gl_ClipDistance[%d]", - "tc0", "tc1", "tc2", "tc3", "tc4", "tc5", "tc6", "tc7" - }; - std::string ret; - switch(isSca ? 0x1f : d3.dst) + switch(d3.dst) { - case 0x0: case 0x5: case 0x6: - ret += reg_table[d3.dst]; - break; - case 0x1f: ret += m_parr.AddParam(PARAM_NONE, "vec4", std::string("tmp") + std::to_string(isSca ? d3.sca_dst_tmp : d0.dst_tmp)); break; default: - if(d3.dst < WXSIZEOF(reg_table)) - { - ret += m_parr.AddParam(PARAM_OUT, "vec4", reg_table[d3.dst]); - } - else - { - ConLog.Error("Bad dst reg num: %d", fmt::by_value(d3.dst)); - ret += m_parr.AddParam(PARAM_OUT, "vec4", "unk"); - } + if (d3.dst > 15) + ConLog.Error("dst index out of range: %u", d3.dst); + ret += m_parr.AddParam(PARAM_NONE, "vec4", std::string("dst_reg") + std::to_string(d3.dst), d3.dst == 0 ? "vec4(0.0f, 0.0f, 0.0f, 1.0f)" : "vec4(0.0)"); break; } return ret; } -std::string GLVertexDecompilerThread::GetSRC(const u32 n, bool isSca) +std::string GLVertexDecompilerThread::GetSRC(const u32 n) { static const std::string reg_table[] = { "in_pos", "in_weight", "in_normal", - "in_col0", "in_col1", - "in_fogc", - "in_6", "in_7", + "in_diff_color", "in_spec_color", + "in_fog", + "in_point_size", "in_7", "in_tc0", "in_tc1", "in_tc2", "in_tc3", "in_tc4", "in_tc5", "in_tc6", "in_tc7" }; @@ -94,7 +74,7 @@ std::string GLVertexDecompilerThread::GetSRC(const u32 n, bool isSca) switch(src[n].reg_type) { case 1: //temp - ret += m_parr.AddParam(PARAM_NONE, "vec4", std::string("tmp") + std::to_string(src[n].tmp_src)); + ret += m_parr.AddParam(PARAM_NONE, "vec4", "tmp" + std::to_string(src[n].tmp_src)); break; case 2: //input if(d1.input_src < WXSIZEOF(reg_table)) @@ -108,7 +88,8 @@ std::string GLVertexDecompilerThread::GetSRC(const u32 n, bool isSca) } break; case 3: //const - ret += m_parr.AddParam(PARAM_UNIFORM, "vec4", std::string("vc") + std::to_string(d1.const_src)); + m_parr.AddParam(PARAM_UNIFORM, "vec4", std::string("vc[468]")); + ret += std::string("vc[") + std::to_string(d1.const_src) + (d3.index_const ? " + " + AddAddrReg() : "") + "]"; break; default: @@ -119,26 +100,14 @@ std::string GLVertexDecompilerThread::GetSRC(const u32 n, bool isSca) static const std::string f = "xyzw"; - if (isSca) - { - assert(src[n].swz_x == src[n].swz_y); - assert(src[n].swz_z == src[n].swz_w); - assert(src[n].swz_x == src[n].swz_z); + std::string swizzle; - ret += '.'; - ret += f[src[n].swz_x]; - } - else - { - std::string swizzle; + swizzle += f[src[n].swz_x]; + swizzle += f[src[n].swz_y]; + swizzle += f[src[n].swz_z]; + swizzle += f[src[n].swz_w]; - swizzle += f[src[n].swz_x]; - swizzle += f[src[n].swz_y]; - swizzle += f[src[n].swz_z]; - swizzle += f[src[n].swz_w]; - - if(swizzle != f) ret += '.' + swizzle; - } + if(swizzle != f) ret += '.' + swizzle; bool abs; @@ -155,10 +124,10 @@ std::string GLVertexDecompilerThread::GetSRC(const u32 n, bool isSca) return ret; } -void GLVertexDecompilerThread::AddCode(bool is_sca, const std::string& pCode, bool src_mask, bool set_dst, bool set_cond) +void GLVertexDecompilerThread::SetDST(bool is_sca, std::string value) { - std::string code = pCode; if(d0.cond == 0) return; + enum { lt = 0x1, @@ -166,6 +135,99 @@ void GLVertexDecompilerThread::AddCode(bool is_sca, const std::string& pCode, bo gt = 0x4, }; + std::string mask = GetMask(is_sca); + + value += mask; + + if(is_sca && d0.vec_result) + { + value = "vec4(" + value + ")" + mask; + } + + if(d0.staturate) + { + value = "clamp(" + value + ", 0.0, 1.0)"; + } + + std::string dest; + + if (d0.cond_update_enable_0 && d0.cond_update_enable_1) + { + dest += m_parr.AddParam(PARAM_NONE, "vec4", "cc" + std::to_string(d0.cond_reg_sel_1), "vec4(0.0)") + mask + " = "; + } + + if (d3.dst != 0x1f || (is_sca ? d3.sca_dst_tmp != 0x3f : d0.dst_tmp != 0x3f)) + { + dest += GetDST(is_sca) + mask + " = "; + } + + std::string code; + + if (d0.cond_test_enable) + code += "$ifcond "; + + code += dest + value; + + AddCode(code + ";"); +} + +std::string GLVertexDecompilerThread::GetFunc() +{ + std::string name = "func$a"; + + for(uint i=0; i> repl_list[] = + { + { "$$", []() -> std::string { return "$"; } }, + { "$0", std::bind(std::mem_fn(&GLVertexDecompilerThread::GetSRC), this, 0) }, + { "$1", std::bind(std::mem_fn(&GLVertexDecompilerThread::GetSRC), this, 1) }, + { "$2", std::bind(std::mem_fn(&GLVertexDecompilerThread::GetSRC), this, 2) }, + { "$s", std::bind(std::mem_fn(&GLVertexDecompilerThread::GetSRC), this, 2) }, + { "$am", std::bind(std::mem_fn(&GLVertexDecompilerThread::AddAddrMask), this) }, + { "$a", std::bind(std::mem_fn(&GLVertexDecompilerThread::AddAddrReg), this) }, + + { "$fa", [this]()->std::string {return std::to_string(GetAddr()); } }, + { "$f()", std::bind(std::mem_fn(&GLVertexDecompilerThread::GetFunc), this) }, + { "$ifcond ", [this]() -> std::string + { + const std::string& cond = GetCond(); + if (cond == "true") return ""; + return "if(" + cond + ") "; + } + }, + { "$cond", std::bind(std::mem_fn(&GLVertexDecompilerThread::GetCond), this) } + }; + + return fmt::replace_all(code, repl_list); +} + +std::string GLVertexDecompilerThread::GetCond() +{ + enum + { + lt = 0x1, + eq = 0x2, + gt = 0x4, + }; + + if (d0.cond == 0) return "false"; + if (d0.cond == (lt | gt | eq)) return "true"; + static const char* cond_string_table[(lt | gt | eq) + 1] = { "error", @@ -178,102 +240,51 @@ void GLVertexDecompilerThread::AddCode(bool is_sca, const std::string& pCode, bo "error" }; - std::string cond; + static const char f[4] = { 'x', 'y', 'z', 'w' }; - if((set_cond || d0.cond_test_enable) && d0.cond != (lt | gt | eq)) - { - static const char f[4] = {'x', 'y', 'z', 'w'}; + std::string swizzle; + swizzle += f[d0.mask_x]; + swizzle += f[d0.mask_y]; + swizzle += f[d0.mask_z]; + swizzle += f[d0.mask_w]; - std::string swizzle; - swizzle += f[d0.mask_x]; - swizzle += f[d0.mask_y]; - swizzle += f[d0.mask_z]; - swizzle += f[d0.mask_w]; + swizzle = swizzle == "xyzw" ? "" : "." + swizzle; - swizzle = swizzle == "xyzw" ? "" : "." + swizzle; - - cond = fmt::Format("if(any(%s(rc%s, vec4(0.0)%s))) ", cond_string_table[d0.cond], swizzle.c_str(), swizzle.c_str()); - } - - std::string mask = GetMask(is_sca); - std::string value = src_mask ? code + mask : code; - - if(is_sca && d0.vec_result) - { - value = "vec4(" + value + ")" + mask; - } - - if(d0.staturate) - { - value = "clamp(" + value + ", 0.0, 1.0)"; - } - - if(set_dst) - { - std::string dest; - if(d0.cond_update_enable_0) - { - dest = m_parr.AddParam(PARAM_NONE, "vec4", "rc", "vec4(0.0)") + mask; - } - else if(d3.dst == 5 || d3.dst == 6) - { - if(d3.vec_writemask_x) - { - dest = m_parr.AddParam(PARAM_OUT, "vec4", "fogc") + mask; - } - else - { - int num = d3.dst == 5 ? 0 : 3; - - //if(d3.vec_writemask_y) num += 0; - if(d3.vec_writemask_z) num += 1; - else if(d3.vec_writemask_w) num += 2; - - dest = fmt::Format(GetDST(is_sca) + "/*" + mask + "*/", num); - } - } - else - { - dest = GetDST(is_sca) + mask; - } - - code = cond + dest + " = " + value; - } - else - { - code = cond + value; - } - - m_body.push_back(code + ";"); + return fmt::Format("any(%s(cc%d%s, vec4(0.0)%s))", cond_string_table[d0.cond], d0.cond_reg_sel_1, swizzle.c_str(), swizzle.c_str()); } -std::string GLVertexDecompilerThread::GetFunc() + +std::string GLVertexDecompilerThread::AddAddrMask() { - u32 offset = (d2.iaddrh << 3) | d3.iaddrl; - std::string name = fmt::Format("func%u", offset); - - for(uint i=0; ibody.push_back(Format(code)); +} + +void GLVertexDecompilerThread::SetDSTVec(const std::string& code) +{ + SetDST(false, code); +} + +void GLVertexDecompilerThread::SetDSTSca(const std::string& code) +{ + SetDST(true, code); } std::string GLVertexDecompilerThread::BuildFuncBody(const FuncInfo& func) @@ -309,26 +320,112 @@ std::string GLVertexDecompilerThread::BuildFuncBody(const FuncInfo& func) std::string GLVertexDecompilerThread::BuildCode() { + struct reg_info + { + std::string name; + bool need_declare; + std::string src_reg; + std::string src_reg_mask; + bool need_cast; + }; + + static const reg_info reg_table[] = + { + { "gl_Position", false, "dst_reg0", "", false }, + { "diff_color", true, "dst_reg1", "", false }, + { "spec_color", true, "dst_reg2", "", false }, + { "front_diff_color", true, "dst_reg3", "", false }, + { "front_spec_color", true, "dst_reg4", "", false }, + { "fogc", true, "dst_reg5", ".x", true }, + { "gl_ClipDistance[0]", false, "dst_reg5", ".y", false }, + { "gl_ClipDistance[1]", false, "dst_reg5", ".z", false }, + { "gl_ClipDistance[2]", false, "dst_reg5", ".w", false }, + { "gl_PointSize", false, "dst_reg6", ".x", false }, + { "gl_ClipDistance[3]", false, "dst_reg6", ".y", false }, + { "gl_ClipDistance[4]", false, "dst_reg6", ".z", false }, + { "gl_ClipDistance[5]", false, "dst_reg6", ".w", false }, + { "tc0", true, "dst_reg7", "", false }, + { "tc1", true, "dst_reg8", "", false }, + { "tc2", true, "dst_reg9", "", false }, + { "tc3", true, "dst_reg10", "", false }, + { "tc4", true, "dst_reg11", "", false }, + { "tc5", true, "dst_reg12", "", false }, + { "tc6", true, "dst_reg13", "", false }, + { "tc7", true, "dst_reg14", "", false }, + { "tc8", true, "dst_reg15", "", false }, + { "tc9", true, "dst_reg6", "", false } + }; + + std::string f; + + for (auto &i : reg_table) + { + if (m_parr.HasParam(PARAM_NONE, "vec4", i.src_reg)) + { + if (i.need_declare) + { + m_parr.AddParam(PARAM_OUT, "vec4", i.name); + } + + if (i.need_cast) + { + f += "\t" + i.name + " = vec4(" + i.src_reg + i.src_reg_mask + ");\n"; + } + else + { + f += "\t" + i.name + " = " + i.src_reg + i.src_reg_mask + ";\n"; + } + } + } + std::string p; - for(u32 i=0; i0; --i) + for (int i = m_funcs.size() - 1; i>0; --i) { fp += fmt::Format("void %s();\n", m_funcs[i].name.c_str()); } - std::string f; + f = fmt::Format("void %s()\n{\n\t%s();\n%s\tgl_Position = gl_Position * scaleOffsetMat;\n}\n", + m_funcs[0].name.c_str(), m_funcs[1].name.c_str(), f.c_str()); - f += fmt::Format("void %s()\n{\n\tgl_Position = vec4(0.0f, 0.0f, 0.0f, 1.0f);\n\t%s();\n\tgl_Position = gl_Position * scaleOffsetMat;\n}\n", - m_funcs[0].name.c_str(), m_funcs[1].name.c_str()); + std::string main_body; + for (uint i = 0, lvl = 1; i < m_instr_count; i++) + { + lvl -= m_instructions[i].close_scopes; + if (lvl < 1) lvl = 1; + //assert(lvl >= 1); + for (uint j = 0; j < m_instructions[i].put_close_scopes; ++j) + { + --lvl; + if (lvl < 1) lvl = 1; + main_body.append(lvl, '\t') += "}\n"; + } - for(uint i=1; i 0) ? pow(max(0.0, " + GetSRC(2, true) + ".y), " + GetSRC(2, true) + ".z) : 0), 1.0)"); break; // LIT - case 0x08: AddScaCode("{ /*BRA*/ " + GetFunc() + "; return; }", false, true); break; // BRA - case 0x09: AddScaCode("{ " + GetFunc() + "; return; }", false, true); break; // BRI : works differently (BRI o[1].x(TR) L0;) - case 0x0a: AddScaCode("/*CAL*/ " + GetFunc(), false, true); break; // CAL : works same as BRI - case 0x0b: AddScaCode("/*CLI*/ " + GetFunc(), false, true); break; // CLI : works same as BRI - case 0x0c: AddScaCode("return", false, true); break; // RET : works like BRI but shorter (RET o[1].x(TR);) - case 0x0d: AddScaCode("log2(" + GetSRC(2, true) + ")"); break; // LG2 - case 0x0e: AddScaCode("exp2(" + GetSRC(2, true) + ")"); break; // EX2 - case 0x0f: AddScaCode("sin(" + GetSRC(2, true) + ")"); break; // SIN - case 0x10: AddScaCode("cos(" + GetSRC(2, true) + ")"); break; // COS + case 0x01: SetDSTSca("$s"); break; // MOV + case 0x02: SetDSTSca("(1.0 / $s)"); break; // RCP + case 0x03: SetDSTSca("clamp(1.0 / $s, 5.42101e-20, 1.884467e19)"); break; // RCC + case 0x04: SetDSTSca("inversesqrt(abs($s))"); break; // RSQ + case 0x05: SetDSTSca("exp($s)"); break; // EXP + case 0x06: SetDSTSca("log($s)"); break; // LOG + case 0x07: SetDSTSca("vec4(1.0, $s.x, ($s.x > 0 ? exp2($s.w * log2($s.y)) : 0.0), 1.0)"); break; // LIT + //case 0x08: break; // BRA + case 0x09: // BRI : works differently (BRI o[1].x(TR) L0;) + //AddCode("$ifcond { $f(); return; }"); + if (GetAddr() > m_instr_count) + { + AddCode("if(!$cond)"); + AddCode("{"); + m_cur_instr->open_scopes++; + m_instructions[GetAddr()].put_close_scopes++; + } + else + { + AddCode("} while ($cond);"); + m_cur_instr->close_scopes++; + m_instructions[GetAddr()].do_count++; + } + break; + //case 0x0a: AddCode("$ifcond $f(); //CAL"); break; // CAL : works same as BRI + case 0x0b: AddCode("$ifcond $f(); //CLI"); break; // CLI : works same as BRI + case 0x0c: AddCode("$ifcond return;"); break; // RET : works like BRI but shorter (RET o[1].x(TR);) + case 0x0d: SetDSTSca("log2($s)"); break; // LG2 + case 0x0e: SetDSTSca("exp2($s)"); break; // EX2 + case 0x0f: SetDSTSca("sin($s)"); break; // SIN + case 0x10: SetDSTSca("cos($s)"); break; // COS //case 0x11: break; // BRB : works differently (BRB o[1].x !b0, L0;) //case 0x12: break; // CLB : works same as BRB //case 0x13: break; // PSH : works differently (PSH o[1].x A0;) @@ -400,28 +518,28 @@ void GLVertexDecompilerThread::Task() switch(d1.vec_opcode) { case 0x00: break; //NOP - case 0x01: AddVecCode(GetSRC(0)); break; //MOV - case 0x02: AddVecCode("(" + GetSRC(0) + " * " + GetSRC(1) + ")"); break; //MUL - case 0x03: AddVecCode("(" + GetSRC(0) + " + " + GetSRC(2) + ")"); break; //ADD - case 0x04: AddVecCode("(" + GetSRC(0) + " * " + GetSRC(1) + " + " + GetSRC(2) + ")"); break; //MAD - case 0x05: AddVecCode("vec2(dot(" + GetSRC(0) + ".xyz, " + GetSRC(1) + ".xyz), 0).xxxx"); break; //DP3 - case 0x06: AddVecCode("vec2(dot(vec4(" + GetSRC(0) + ".xyz, 1), " + GetSRC(1) + "), 0).xxxx"); break; //DPH - case 0x07: AddVecCode("vec2(dot(" + GetSRC(0) + ", " + GetSRC(1) + "), 0).xxxx"); break; //DP4 - case 0x08: AddVecCode("vec2(distance(" + GetSRC(0) + ", " + GetSRC(1) + "), 0).xxxx"); break; //DST - case 0x09: AddVecCode("min(" + GetSRC(0) + ", " + GetSRC(1) + ")"); break; //MIN - case 0x0a: AddVecCode("max(" + GetSRC(0) + ", " + GetSRC(1) + ")"); break; //MAX - case 0x0b: AddVecCode("vec4(lessThan(" + GetSRC(0) + ", " + GetSRC(1) + "))"); break; //SLT - case 0x0c: AddVecCode("vec4(greaterThanEqual(" + GetSRC(0) + ", " + GetSRC(1) + "))"); break; //SGE - //case 0x0d: break; - case 0x0e: AddVecCode("fract(" + GetSRC(0) + ")"); break; //FRC - case 0x0f: AddVecCode("floor(" + GetSRC(0) + ")"); break; //FLR - case 0x10: AddVecCode("vec4(equal(" + GetSRC(0) + ", " + GetSRC(1) + "))"); break; //SEQ - case 0x11: AddVecCode("vec4(equal(" + GetSRC(0) + ", vec4(0)))"); break; //SFL - case 0x12: AddVecCode("vec4(greaterThan(" + GetSRC(0) + ", " + GetSRC(1) + "))"); break; //SGT - case 0x13: AddVecCode("vec4(lessThanEqual(" + GetSRC(0) + ", " + GetSRC(1) + "))"); break; //SLE - case 0x14: AddVecCode("vec4(notEqual(" + GetSRC(0) + ", " + GetSRC(1) + "))"); break; //SNE - case 0x15: AddVecCode("vec4(equal(" + GetSRC(0) + ", vec4(1)))"); break; //STR - case 0x16: AddVecCode("sign(" + GetSRC(0) + ")"); break; //SSG + case 0x01: SetDSTVec("$0"); break; //MOV + case 0x02: SetDSTVec("($0 * $1)"); break; //MUL + case 0x03: SetDSTVec("($0 + $2)"); break; //ADD + case 0x04: SetDSTVec("($0 * $1 + $2)"); break; //MAD + case 0x05: SetDSTVec("vec2(dot($0.xyz, $1.xyz), 0.0).xxxx"); break; //DP3 + case 0x06: SetDSTVec("vec2(dot(vec4($0.xyz, 1.0), $1), 0.0).xxxx"); break; //DPH + case 0x07: SetDSTVec("vec2(dot($0, $1), 0.0).xxxx"); break; //DP4 + case 0x08: SetDSTVec("vec2(distance($0, $1), 0.0).xxxx"); break; //DST + case 0x09: SetDSTVec("min($0, $1)"); break; //MIN + case 0x0a: SetDSTVec("max($0, $1)"); break; //MAX + case 0x0b: SetDSTVec("vec4(lessThan($0, $1))"); break; //SLT + case 0x0c: SetDSTVec("vec4(greaterThanEqual($0, $1))"); break; //SGE + case 0x0d: AddCode("$ifcond $a = ivec4($0)$am;"); break; //ARL + case 0x0e: SetDSTVec("fract($0)"); break; //FRC + case 0x0f: SetDSTVec("floor($0)"); break; //FLR + case 0x10: SetDSTVec("vec4(equal($0, $1))"); break; //SEQ + case 0x11: SetDSTVec("vec4(equal($0, vec4(0.0)))"); break; //SFL + case 0x12: SetDSTVec("vec4(greaterThan($0, $1))"); break; //SGT + case 0x13: SetDSTVec("vec4(lessThanEqual($0, $1))"); break; //SLE + case 0x14: SetDSTVec("vec4(notEqual($0, $1))"); break; //SNE + case 0x15: SetDSTVec("vec4(equal($0, vec4(1.0)))"); break; //STR + case 0x16: SetDSTVec("sign($0)"); break; //SSG default: m_body.push_back(fmt::Format("//Unknown vp opcode 0x%x", fmt::by_value(d1.vec_opcode))); @@ -432,6 +550,8 @@ void GLVertexDecompilerThread::Task() if(d3.end) { + m_instr_count++; + if(i < m_data.size()) ConLog.Error("Program end before buffer end."); diff --git a/rpcs3/Emu/GS/GL/GLVertexProgram.h b/rpcs3/Emu/GS/GL/GLVertexProgram.h index a74a2cd066..1a0c41c922 100644 --- a/rpcs3/Emu/GS/GL/GLVertexProgram.h +++ b/rpcs3/Emu/GS/GL/GLVertexProgram.h @@ -133,6 +133,26 @@ struct GLVertexDecompilerThread : public ThreadBase std::string name; }; + struct Instruction + { + std::vector body; + int open_scopes; + int close_scopes; + int put_close_scopes; + int do_count; + + void reset() + { + body.clear(); + put_close_scopes = open_scopes = close_scopes = do_count = 0; + } + }; + + static const size_t m_max_instr_count = 512; + Instruction m_instructions[m_max_instr_count]; + Instruction* m_cur_instr; + size_t m_instr_count; + std::vector m_body; std::vector m_funcs; @@ -161,11 +181,18 @@ struct GLVertexDecompilerThread : public ThreadBase std::string GetVecMask(); std::string GetScaMask(); std::string GetDST(bool is_sca = false); - std::string GetSRC(const u32 n, bool is_sca = false); + std::string GetSRC(const u32 n); std::string GetFunc(); - void AddCode(bool is_sca, const std::string& code, bool src_mask = true, bool set_dst = true, bool set_cond = true); - void AddVecCode(const std::string& code, bool src_mask = true, bool set_dst = true); - void AddScaCode(const std::string& code, bool set_dst = true, bool set_cond = true); + std::string GetCond(); + std::string AddAddrMask(); + std::string AddAddrReg(); + u32 GetAddr(); + std::string Format(const std::string& code); + + void AddCode(const std::string& code); + void SetDST(bool is_sca, std::string value); + void SetDSTVec(const std::string& code); + void SetDSTSca(const std::string& code); std::string BuildFuncBody(const FuncInfo& func); std::string BuildCode(); diff --git a/rpcs3/Emu/GS/RSXThread.cpp b/rpcs3/Emu/GS/RSXThread.cpp index 5b3c18a2e2..b22e60c47f 100644 --- a/rpcs3/Emu/GS/RSXThread.cpp +++ b/rpcs3/Emu/GS/RSXThread.cpp @@ -1893,8 +1893,10 @@ void RSXThread::Task() if(cmd == 0) { - ConLog.Error("null cmd: addr=0x%x, put=0x%x, get=0x%x", Memory.RSXIOMem.GetStartAddr() + get, m_ctrl->put, get); - Emu.Pause(); + //HACK! We couldn't be here + //ConLog.Error("null cmd: addr=0x%x, put=0x%x, get=0x%x", Memory.RSXIOMem.GetStartAddr() + get, m_ctrl->put, get); + //Emu.Pause(); + m_ctrl->get = get + (count + 1) * 4; continue; }