From 99ea666bf2eed0deb20848df86be5f73bbfca643 Mon Sep 17 00:00:00 2001 From: O1L Date: Mon, 23 Feb 2015 16:22:30 +0400 Subject: [PATCH] Implemented binary vertex program disassembler --- rpcs3/Emu/RSX/CgBinaryFragmentProgram.cpp | 10 +- rpcs3/Emu/RSX/CgBinaryProgram.h | 29 +- rpcs3/Emu/RSX/CgBinaryVertexProgram.cpp | 450 ++++++++++++++++++++++ rpcs3/Emu/RSX/GL/GLVertexProgram.cpp | 2 +- rpcs3/Emu/RSX/RSXFragmentProgram.h | 2 +- rpcs3/Emu/RSX/RSXVertexProgram.h | 4 +- rpcs3/Gui/CgDisasm.cpp | 24 ++ rpcs3/Gui/CgDisasm.h | 5 +- rpcs3/emucore.vcxproj | 1 + rpcs3/emucore.vcxproj.filters | 5 +- 10 files changed, 520 insertions(+), 12 deletions(-) create mode 100644 rpcs3/Emu/RSX/CgBinaryVertexProgram.cpp diff --git a/rpcs3/Emu/RSX/CgBinaryFragmentProgram.cpp b/rpcs3/Emu/RSX/CgBinaryFragmentProgram.cpp index 979cb9df1c..9dfa408786 100644 --- a/rpcs3/Emu/RSX/CgBinaryFragmentProgram.cpp +++ b/rpcs3/Emu/RSX/CgBinaryFragmentProgram.cpp @@ -1,13 +1,13 @@ #include "stdafx.h" -#include "Utilities/Log.h" -#include "Emu/Memory/Memory.h" #include "Emu/System.h" +#include "Utilities/Log.h" #include "CgBinaryProgram.h" #include "Emu/RSX/RSXFragmentProgram.h" void CgBinaryDisasm::AddCodeAsm(const std::string& code) { + assert(m_opcode < 70); std::string op_name = ""; if (dst.dest_reg == 63) @@ -33,7 +33,10 @@ void CgBinaryDisasm::AddCodeAsm(const std::string& code) case RSX_FP_OPCODE_LOOP: case RSX_FP_OPCODE_NOP: case RSX_FP_OPCODE_REP: - case RSX_FP_OPCODE_RET: m_dst_reg_name = ""; break; + case RSX_FP_OPCODE_RET: + m_dst_reg_name = ""; + op_name = rsx_fp_op_names[m_opcode] + std::string(dst.fp16 ? "H" : "R"); + break; default: break; } @@ -212,6 +215,7 @@ template std::string CgBinaryDisasm::GetSrcDisAsm(T src) if (strncmp(swizzle.c_str(), f, 4) != 0) ret += "." + swizzle; if (src.neg) ret = "-" + ret; + if (src.abs) ret = "|" + ret + "|"; return ret; } diff --git a/rpcs3/Emu/RSX/CgBinaryProgram.h b/rpcs3/Emu/RSX/CgBinaryProgram.h index 789019b1ab..e8084a541d 100644 --- a/rpcs3/Emu/RSX/CgBinaryProgram.h +++ b/rpcs3/Emu/RSX/CgBinaryProgram.h @@ -130,12 +130,13 @@ private: std::vector m_loop_end_offsets; // VP members + u32 m_sca_opcode; + u32 m_vec_opcode; static const size_t m_max_instr_count = 512; size_t m_instr_count; std::vector m_data; public: - std::string GetArbShader() const { return m_arb_shader; } std::string GetGlslShader() const { return m_glsl_shader; } @@ -149,6 +150,27 @@ public: std::string GetCondDisAsm(); template std::string GetSrcDisAsm(T src); + // VP functions + std::string GetMaskDisasm(bool is_sca); + std::string GetVecMaskDisasm(); + std::string GetScaMaskDisasm(); + std::string GetDSTDisasm(bool is_sca = false); + std::string GetSRCDisasm(const u32 n); + std::string GetTexDisasm(); + std::string GetCondDisasm(); + std::string AddAddrMaskDisasm(); + std::string AddAddrRegDisasm(); + u32 GetAddrDisasm(); + std::string FormatDisasm(const std::string& code); + void AddScaCodeDisasm(const std::string& code = ""); + void AddVecCodeDisasm(const std::string& code = ""); + void AddCodeCondDisasm(const std::string& dst, const std::string& src); + void AddCodeDisasm(const std::string& code); + void SetDSTDisasm(bool is_sca, std::string value); + void SetDSTVecDisasm(const std::string& code); + void SetDSTScaDisasm(const std::string& code); + + CgBinaryDisasm(const std::string& path) : m_path(path) , m_buffer(nullptr) @@ -187,6 +209,7 @@ public: case 1064: return "float4x4"; case 1066: return "sampler2D"; case 1069: return "samplerCUBE"; + case 1091: return "float1"; default: return fmt::format("!UnkCgType(%d)", type); } @@ -356,12 +379,12 @@ public: m_data.push_back(vdata[i]); } - //TaskVP(); + TaskVP(); GLVertexDecompilerThread(m_data, m_glsl_shader, param_array).Task(); } } u32 GetData(const u32 d) const { return d << 16 | d >> 16; } void TaskFP(); - //void TaskVP(); // TODO + void TaskVP(); }; \ No newline at end of file diff --git a/rpcs3/Emu/RSX/CgBinaryVertexProgram.cpp b/rpcs3/Emu/RSX/CgBinaryVertexProgram.cpp new file mode 100644 index 0000000000..db60c95588 --- /dev/null +++ b/rpcs3/Emu/RSX/CgBinaryVertexProgram.cpp @@ -0,0 +1,450 @@ +#include "stdafx.h" + +#include "Emu/System.h" +#include "Utilities/Log.h" +#include "CgBinaryProgram.h" +#include "Emu/RSX/RSXVertexProgram.h" + +void CgBinaryDisasm::AddScaCodeDisasm(const std::string& code) +{ + assert(m_sca_opcode < 21); + m_arb_shader += rsx_vp_sca_op_names[m_sca_opcode] + code + " "; +} + +void CgBinaryDisasm::AddVecCodeDisasm(const std::string& code) +{ + assert(m_vec_opcode < 26); + m_arb_shader += rsx_vp_vec_op_names[m_vec_opcode] + code + " "; +} + +std::string CgBinaryDisasm::GetMaskDisasm(bool is_sca) +{ + std::string ret; + + if (is_sca) + { + if (d3.sca_writemask_x) ret += "x"; + if (d3.sca_writemask_y) ret += "y"; + if (d3.sca_writemask_z) ret += "z"; + if (d3.sca_writemask_w) ret += "w"; + } + else + { + if (d3.vec_writemask_x) ret += "x"; + if (d3.vec_writemask_y) ret += "y"; + if (d3.vec_writemask_z) ret += "z"; + if (d3.vec_writemask_w) ret += "w"; + } + + return ret.empty() || ret == "xyzw" ? "" : ("." + ret); +} + +std::string CgBinaryDisasm::GetVecMaskDisasm() +{ + return GetMaskDisasm(false); +} + +std::string CgBinaryDisasm::GetScaMaskDisasm() +{ + return GetMaskDisasm(true); +} + +std::string CgBinaryDisasm::GetDSTDisasm(bool isSca) +{ + std::string ret; + + switch (isSca ? 0x1f : d3.dst) + { + case 0x1f: + ret += isSca ? fmt::format("R%d", d3.sca_dst_tmp) + GetScaMaskDisasm() : fmt::format("R%d", d0.dst_tmp) + GetVecMaskDisasm(); + break; + + default: + if (d3.dst > 15) + LOG_ERROR(RSX, fmt::Format("dst index out of range: %u", d3.dst)); + + ret += fmt::format("o[%d]", d3.dst) + GetVecMaskDisasm(); + break; + } + + return ret; +} + +std::string CgBinaryDisasm::GetSRCDisasm(const u32 n) +{ + std::string ret; + + switch (src[n].reg_type) + { + case 1: //temp + ret += "R" + std::to_string(src[n].tmp_src); + break; + case 2: //input + if (d1.input_src < 16) + { + ret += fmt::format("v[%d]", d1.input_src); + } + else + { + LOG_ERROR(RSX, "Bad input src num: %d", fmt::by_value(d1.input_src)); + ret += fmt::format("v[%d] # bad src", d1.input_src); + } + break; + case 3: //const + ret += std::string("c[" + (d3.index_const ? AddAddrRegDisasm() + " + " : "") + std::to_string(d1.const_src) + "]"); + break; + + default: + LOG_ERROR(RSX, fmt::Format("Bad src%u reg type: %d", n, fmt::by_value(src[n].reg_type))); + Emu.Pause(); + break; + } + + static const std::string f = "xyzw"; + + 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]; + + if (swizzle == "xxxx") swizzle = "x"; + if (swizzle == "yyyy") swizzle = "y"; + if (swizzle == "zzzz") swizzle = "z"; + if (swizzle == "wwww") swizzle = "w"; + + if (swizzle != f) ret += '.' + swizzle; + + bool abs; + + switch (n) + { + case 0: abs = d0.src0_abs; break; + case 1: abs = d0.src1_abs; break; + case 2: abs = d0.src2_abs; break; + } + + if (abs) ret = "|" + ret + "|"; + if (src[n].neg) ret = "-" + ret; + + return ret; +} + +void CgBinaryDisasm::SetDSTDisasm(bool is_sca, std::string value) +{ + is_sca ? AddScaCodeDisasm() : AddVecCodeDisasm(); + + if (d0.cond == 0) return; + + enum + { + lt = 0x1, + eq = 0x2, + gt = 0x4 + }; + + if (d0.staturate) + { + m_arb_shader.pop_back(); + m_arb_shader += "_sat "; + } + + std::string dest; + if (d0.cond_update_enable_0 && d0.cond_update_enable_1) + { + m_arb_shader.pop_back(); + m_arb_shader += "C "; + dest = fmt::format("RC%s", GetMaskDisasm(is_sca).c_str()); + } + else if (d3.dst != 0x1f || (is_sca ? d3.sca_dst_tmp != 0x3f : d0.dst_tmp != 0x3f)) + { + dest = GetDSTDisasm(is_sca); + } + + AddCodeCondDisasm(FormatDisasm(dest), value); +} + +std::string CgBinaryDisasm::GetTexDisasm() +{ + return fmt::format("TEX%d", 0); +} + +std::string CgBinaryDisasm::FormatDisasm(const std::string& code) +{ + const std::pair> repl_list[] = + { + { "$$", []() -> std::string { return "$"; } }, + { "$0", std::bind(std::mem_fn(&CgBinaryDisasm::GetSRCDisasm), this, 0) }, + { "$1", std::bind(std::mem_fn(&CgBinaryDisasm::GetSRCDisasm), this, 1) }, + { "$2", std::bind(std::mem_fn(&CgBinaryDisasm::GetSRCDisasm), this, 2) }, + { "$s", std::bind(std::mem_fn(&CgBinaryDisasm::GetSRCDisasm), this, 2) }, + { "$am", std::bind(std::mem_fn(&CgBinaryDisasm::AddAddrMaskDisasm), this) }, + { "$a", std::bind(std::mem_fn(&CgBinaryDisasm::AddAddrRegDisasm), this) }, + { "$t", std::bind(std::mem_fn(&CgBinaryDisasm::GetTexDisasm), this) }, + { "$fa", [this]()->std::string { return std::to_string(GetAddrDisasm()); } }, + { "$ifcond ", [this]() -> std::string + { + const std::string& cond = GetCondDisasm(); + if (cond == "true") return ""; + return cond; + } + }, + { "$cond", std::bind(std::mem_fn(&CgBinaryDisasm::GetCondDisasm), this) } + }; + + return fmt::replace_all(code, repl_list); +} + +std::string CgBinaryDisasm::GetCondDisasm() +{ + 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", + "LT", "EQ", "LE", + "GT", "NE", "GE", + "ERROR" + }; + + 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]; + + if (swizzle == "xxxx") swizzle = "x"; + if (swizzle == "yyyy") swizzle = "y"; + if (swizzle == "zzzz") swizzle = "z"; + if (swizzle == "wwww") swizzle = "w"; + + swizzle = swizzle == "xyzw" ? "" : "." + swizzle; + + return fmt::Format("(%s%s)", cond_string_table[d0.cond], swizzle.c_str()); +} + +void CgBinaryDisasm::AddCodeCondDisasm(const std::string& dst, const std::string& src) +{ + enum + { + lt = 0x1, + eq = 0x2, + gt = 0x4 + }; + + if (!d0.cond_test_enable || d0.cond == (lt | gt | eq)) + { + AddCodeDisasm(dst + ", " + src + ";"); + return; + } + + if (d0.cond == 0) + { + AddCodeDisasm("# " + dst + ", " + src + ";"); + return; + } + + static const char* cond_string_table[(lt | gt | eq) + 1] = + { + "ERROR", + "LT", "EQ", "LE", + "GT", "NE", "GE", + "ERROR" + }; + + 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]; + + if (swizzle == "xxxx") swizzle = "x"; + if (swizzle == "yyyy") swizzle = "y"; + if (swizzle == "zzzz") swizzle = "z"; + if (swizzle == "wwww") swizzle = "w"; + + swizzle = swizzle == "xyzw" ? "" : "." + swizzle; + + std::string cond = fmt::Format("%s%s", cond_string_table[d0.cond], swizzle.c_str()); + AddCodeDisasm(dst + "(" + cond + ") " + ", " + src + ";"); +} + + +std::string CgBinaryDisasm::AddAddrMaskDisasm() +{ + static const char f[] = { 'x', 'y', 'z', 'w' }; + return std::string(".") + f[d0.addr_swz]; +} + +std::string CgBinaryDisasm::AddAddrRegDisasm() +{ + static const char f[] = { 'x', 'y', 'z', 'w' }; + return fmt::format("A%d", d0.addr_reg_sel_1) + AddAddrMaskDisasm(); +} + +u32 CgBinaryDisasm::GetAddrDisasm() +{ + return (d2.iaddrh << 3) | d3.iaddrl; +} + +void CgBinaryDisasm::AddCodeDisasm(const std::string& code) +{ + m_arb_shader += FormatDisasm(code) + "\n"; +} + +void CgBinaryDisasm::SetDSTVecDisasm(const std::string& code) +{ + SetDSTDisasm(false, code); +} + +void CgBinaryDisasm::SetDSTScaDisasm(const std::string& code) +{ + SetDSTDisasm(true, code); +} + +void CgBinaryDisasm::TaskVP() +{ + m_instr_count = 0; + bool is_has_BRA = false; + + for (u32 i = 1; m_instr_count < m_max_instr_count; m_instr_count++) + { + if (is_has_BRA) + { + d3.HEX = m_data[i]; + i += 4; + } + else + { + d1.HEX = m_data[i++]; + + + m_sca_opcode = d1.sca_opcode; + switch (d1.sca_opcode) + { + case 0x08: //BRA + is_has_BRA = true; + d3.HEX = m_data[++i]; + i += 4; + AddScaCodeDisasm("# WARNING"); + break; + + case 0x09: //BRI + d2.HEX = m_data[i++]; + d3.HEX = m_data[i]; + i += 2; + AddScaCodeDisasm("$ifcond # WARNING"); + break; + + default: + d3.HEX = m_data[++i]; + i += 2; + break; + } + } + + if (d3.end) + { + m_instr_count++; + + if (i < m_data.size()) + { + LOG_ERROR(RSX, "Program end before buffer end."); + } + + break; + } + } + + for (u32 i = 0; i < m_instr_count; ++i) + { + d0.HEX = m_data[i * 4 + 0]; + d1.HEX = m_data[i * 4 + 1]; + d2.HEX = m_data[i * 4 + 2]; + d3.HEX = m_data[i * 4 + 3]; + + src[0].src0l = d2.src0l; + src[0].src0h = d1.src0h; + src[1].src1 = d2.src1; + src[2].src2l = d3.src2l; + src[2].src2h = d2.src2h; + + m_sca_opcode = d1.sca_opcode; + switch (d1.sca_opcode) + { + case RSX_SCA_OPCODE_NOP: break; + case RSX_SCA_OPCODE_MOV: SetDSTScaDisasm("$s"); break; + case RSX_SCA_OPCODE_RCP: SetDSTScaDisasm("$s"); break; + case RSX_SCA_OPCODE_RCC: SetDSTScaDisasm("$s"); break; + case RSX_SCA_OPCODE_RSQ: SetDSTScaDisasm("$s"); break; + case RSX_SCA_OPCODE_EXP: SetDSTScaDisasm("$s"); break; + case RSX_SCA_OPCODE_LOG: SetDSTScaDisasm("$s"); break; + case RSX_SCA_OPCODE_LIT: SetDSTScaDisasm("$s"); break; + case RSX_SCA_OPCODE_BRA: AddScaCodeDisasm("BRA # WARNING"); break; + case RSX_SCA_OPCODE_BRI: AddCodeDisasm("$ifcond # WARNING"); break; + case RSX_SCA_OPCODE_CAL: AddCodeDisasm("$ifcond $f# WARNING"); break; + case RSX_SCA_OPCODE_CLI: AddCodeDisasm("$ifcond $f # WARNING"); break; + case RSX_SCA_OPCODE_RET: AddCodeDisasm("$ifcond # WARNING"); break; + case RSX_SCA_OPCODE_LG2: SetDSTScaDisasm("$s"); break; + case RSX_SCA_OPCODE_EX2: SetDSTScaDisasm("$s"); break; + case RSX_SCA_OPCODE_SIN: SetDSTScaDisasm("$s"); break; + case RSX_SCA_OPCODE_COS: SetDSTScaDisasm("$s"); break; + case RSX_SCA_OPCODE_BRB: SetDSTScaDisasm("# WARNING Boolean constant"); break; + case RSX_SCA_OPCODE_CLB: SetDSTScaDisasm("# WARNING Boolean constant"); break; + case RSX_SCA_OPCODE_PSH: SetDSTScaDisasm(""); break; + case RSX_SCA_OPCODE_POP: SetDSTScaDisasm(""); break; + + default: + LOG_ERROR(RSX, "Unknown vp sca_opcode 0x%x", fmt::by_value(d1.sca_opcode)); + break; + } + + m_vec_opcode = d1.vec_opcode; + switch (d1.vec_opcode) + { + case RSX_VEC_OPCODE_NOP: break; + case RSX_VEC_OPCODE_MOV: SetDSTVecDisasm("$0"); break; + case RSX_VEC_OPCODE_MUL: SetDSTVecDisasm("$0, $1"); break; + case RSX_VEC_OPCODE_ADD: SetDSTVecDisasm("$0, $2"); break; + case RSX_VEC_OPCODE_MAD: SetDSTVecDisasm("$0, $1, $2"); break; + case RSX_VEC_OPCODE_DP3: SetDSTVecDisasm("$0, $1"); break; + case RSX_VEC_OPCODE_DPH: SetDSTVecDisasm("$0, $1"); break; + case RSX_VEC_OPCODE_DP4: SetDSTVecDisasm("$0, $1"); break; + case RSX_VEC_OPCODE_DST: SetDSTVecDisasm("$0, $1"); break; + case RSX_VEC_OPCODE_MIN: SetDSTVecDisasm("$0, $1"); break; + case RSX_VEC_OPCODE_MAX: SetDSTVecDisasm("$0, $1"); break; + case RSX_VEC_OPCODE_SLT: SetDSTVecDisasm("$0, $1"); break; + case RSX_VEC_OPCODE_SGE: SetDSTVecDisasm("$0, $1"); break; + case RSX_VEC_OPCODE_ARL: AddCodeDisasm("ARL, $a, $0"); break; + case RSX_VEC_OPCODE_FRC: SetDSTVecDisasm("$0"); break; + case RSX_VEC_OPCODE_FLR: SetDSTVecDisasm("$0"); break; + case RSX_VEC_OPCODE_SEQ: SetDSTVecDisasm("$0, $1"); break; + case RSX_VEC_OPCODE_SFL: SetDSTVecDisasm("$0"); break; + case RSX_VEC_OPCODE_SGT: SetDSTVecDisasm("$0, $1"); break; + case RSX_VEC_OPCODE_SLE: SetDSTVecDisasm("$0, $1"); break; + case RSX_VEC_OPCODE_SNE: SetDSTVecDisasm("$0, $1"); break; + case RSX_VEC_OPCODE_STR: SetDSTVecDisasm("$0"); break; + case RSX_VEC_OPCODE_SSG: SetDSTVecDisasm("$0"); break; + case RSX_VEC_OPCODE_TXL: SetDSTVecDisasm("$t, $0"); break; + + default: + LOG_ERROR(RSX, "Unknown vp opcode 0x%x", fmt::by_value(d1.vec_opcode)); + break; + } + } + + m_arb_shader += "END\n"; +} \ No newline at end of file diff --git a/rpcs3/Emu/RSX/GL/GLVertexProgram.cpp b/rpcs3/Emu/RSX/GL/GLVertexProgram.cpp index f6c825aa51..7f74b7b6cd 100644 --- a/rpcs3/Emu/RSX/GL/GLVertexProgram.cpp +++ b/rpcs3/Emu/RSX/GL/GLVertexProgram.cpp @@ -735,7 +735,7 @@ void GLVertexDecompilerThread::Task() case RSX_VEC_OPCODE_SNE: SetDSTVec("vec4(notEqual($0, $1))"); break; case RSX_VEC_OPCODE_STR: SetDSTVec("vec4(equal($0, vec4(1.0)))"); break; case RSX_VEC_OPCODE_SSG: SetDSTVec("sign($0)"); break; - case RSX_VEC_OPCODE_TEX: SetDSTVec("texture($t, $0.xy)"); break; + case RSX_VEC_OPCODE_TXL: SetDSTVec("texture($t, $0.xy)"); break; default: AddCode(fmt::Format("//Unknown vp opcode 0x%x", fmt::by_value(d1.vec_opcode))); diff --git a/rpcs3/Emu/RSX/RSXFragmentProgram.h b/rpcs3/Emu/RSX/RSXFragmentProgram.h index 320c5e616a..ac2f8a69e9 100644 --- a/rpcs3/Emu/RSX/RSXFragmentProgram.h +++ b/rpcs3/Emu/RSX/RSXFragmentProgram.h @@ -68,7 +68,7 @@ enum RSX_FP_OPCODE_IFE = 0x42, // If RSX_FP_OPCODE_LOOP = 0x43, // Loop RSX_FP_OPCODE_REP = 0x44, // Repeat - RSX_FP_OPCODE_RET = 0x45, // Return + RSX_FP_OPCODE_RET = 0x45 // Return }; static union OPDEST diff --git a/rpcs3/Emu/RSX/RSXVertexProgram.h b/rpcs3/Emu/RSX/RSXVertexProgram.h index 328c617a30..f05a05749f 100644 --- a/rpcs3/Emu/RSX/RSXVertexProgram.h +++ b/rpcs3/Emu/RSX/RSXVertexProgram.h @@ -50,7 +50,7 @@ enum vec_opcode RSX_VEC_OPCODE_SNE = 0x14, RSX_VEC_OPCODE_STR = 0x15, RSX_VEC_OPCODE_SSG = 0x16, - RSX_VEC_OPCODE_TEX = 0x19 + RSX_VEC_OPCODE_TXL = 0x19 }; static union D0 @@ -187,7 +187,7 @@ static const std::string rsx_vp_vec_op_names[] = { "NOP", "MOV", "MUL", "ADD", "MAD", "DP3", "DPH", "DP4", "DST", "MIN", "MAX", "SLT", "SGE", "ARL", "FRC", "FLR", - "SEQ", "SFL", "SGT", "SLE", "SNE", "STR", "SSG", "TEX" + "SEQ", "SFL", "SGT", "SLE", "SNE", "STR", "SSG", "NULL", "NULL", "TXL" }; struct RSXVertexProgram diff --git a/rpcs3/Gui/CgDisasm.cpp b/rpcs3/Gui/CgDisasm.cpp index c56da842e8..91df818876 100644 --- a/rpcs3/Gui/CgDisasm.cpp +++ b/rpcs3/Gui/CgDisasm.cpp @@ -29,7 +29,11 @@ CgDisasm::CgDisasm(wxWindow* parent) SetMenuBar(menubar); + m_disasm_text->Bind(wxEVT_RIGHT_DOWN, &CgDisasm::OnRightClick, this); + m_glsl_text->Bind(wxEVT_RIGHT_DOWN, &CgDisasm::OnRightClick, this); + Bind(wxEVT_MENU, &CgDisasm::OpenCg, this, id_open_file); + Bind(wxEVT_MENU, &CgDisasm::OnContextMenu, this, id_clear); } void CgDisasm::OpenCg(wxCommandEvent& event) @@ -56,3 +60,23 @@ void CgDisasm::OnSize(wxSizeEvent& event) m_glsl_text->SetSize(GetSize().x - 20, GetSize().y - 85); event.Skip(); } + +void CgDisasm::OnRightClick(wxMouseEvent& event) +{ + wxMenu* menu = new wxMenu(); + menu->Append(id_clear, "&Clear"); + PopupMenu(menu); +} + +void CgDisasm::OnContextMenu(wxCommandEvent& event) +{ + switch (event.GetId()) + { + case id_clear: + m_disasm_text->Clear(); + m_glsl_text->Clear(); + break; + default: + event.Skip(); + } +} diff --git a/rpcs3/Gui/CgDisasm.h b/rpcs3/Gui/CgDisasm.h index 85f7f92dce..ed5917f5ee 100644 --- a/rpcs3/Gui/CgDisasm.h +++ b/rpcs3/Gui/CgDisasm.h @@ -4,7 +4,8 @@ enum CgDisasmIds { - id_open_file + id_open_file, + id_clear }; class CgDisasm : public wxFrame @@ -19,4 +20,6 @@ public: void OpenCg(wxCommandEvent& event); virtual void OnSize(wxSizeEvent& event); + void OnRightClick(wxMouseEvent& event); + void OnContextMenu(wxCommandEvent& event); }; \ No newline at end of file diff --git a/rpcs3/emucore.vcxproj b/rpcs3/emucore.vcxproj index 0e0cac5072..de3a9f1b0e 100644 --- a/rpcs3/emucore.vcxproj +++ b/rpcs3/emucore.vcxproj @@ -38,6 +38,7 @@ + diff --git a/rpcs3/emucore.vcxproj.filters b/rpcs3/emucore.vcxproj.filters index c59f0c4c5a..34fe92a8b4 100644 --- a/rpcs3/emucore.vcxproj.filters +++ b/rpcs3/emucore.vcxproj.filters @@ -1,4 +1,4 @@ - + @@ -857,6 +857,9 @@ Emu\CPU\ARMv7\Objects + + Emu\GPU\RSX +