#include "stdafx.h" #include "VertexProgram.h" wxString VertexDecompilerThread::GetMask() { wxString ret = wxEmptyString; 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.IsEmpty() || ret == "xyzw" ? wxEmptyString : ("." + ret); } wxString VertexDecompilerThread::GetDST() { static const wxString reg_table[] = { "gl_Position", "col0", "col1", "bfc0", "bfc1", "fogc", "gl_Pointsize", "tc0", "tc1", "tc2", "tc3", "tc4", "tc5", "tc6", "tc7" }; wxString ret = wxEmptyString; switch(d3.dst) { case 0x0: case 0x6: ret += reg_table[d3.dst]; break; case 0x1f: ret += m_parr.AddParam(PARAM_NONE, "vec4", wxString::Format("tmp%d", 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", d3.dst); ret += m_parr.AddParam(PARAM_OUT, "vec4", "unk"); } break; } return ret; } wxString VertexDecompilerThread::GetSRC(const u32 n) { static const wxString reg_table[] = { "in_pos", "in_weight", "in_normal", "in_col0", "in_col1", "in_fogc", "in_6", "in_7", "in_tc0", "in_tc1", "in_tc2", "in_tc3", "in_tc4", "in_tc5", "in_tc6", "in_tc7" }; wxString ret = wxEmptyString; switch(src[n].reg_type) { case 1: //temp ret += m_parr.AddParam(PARAM_NONE, "vec4", wxString::Format("tmp%d", src[n].tmp_src)); break; case 2: //input if(d1.input_src < WXSIZEOF(reg_table)) { ret += m_parr.AddParam(PARAM_IN, "vec4", reg_table[d1.input_src]); } else { ConLog.Error("Bad input src num: %d", d1.input_src); ret += m_parr.AddParam(PARAM_IN, "vec4", "in_unk"); } break; case 3: //const ret += m_parr.AddParam(PARAM_CONST, "vec4", wxString::Format("vc%d", d1.const_src)); break; default: ConLog.Error("Bad src%d reg type: %d", n, src[n].reg_type); Emu.Pause(); break; } static const char f[4] = {'x', 'z', 'w', 'y'}; wxString swizzle = wxEmptyString; 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 != "xyzw") 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 = "abs(" + ret + ")"; if(src[n].neg) ret = "-" + ret; return ret; } void VertexDecompilerThread::AddCode(wxString code, bool src_mask) { if(d0.cond == 0) return; if(d0.cond != 7) { ConLog.Error("Bad cond! %d", d0.cond); Emu.Pause(); return; } code = GetDST() + GetMask() + " = " + (src_mask ? code + GetMask() : code); main += "\t" + code + ";\n"; } wxString VertexDecompilerThread::BuildCode() { wxString p = wxEmptyString; for(u32 i=0; iIsAlive()) m_decompiler_thread->Delete(); safe_delete(m_decompiler_thread); } Delete(); } void VertexProgram::Decompile() { #if 0 VertexDecompilerThread(data, shader, parr).Entry(); #else if(m_decompiler_thread) { Wait(); if(m_decompiler_thread->IsAlive()) m_decompiler_thread->Delete(); safe_delete(m_decompiler_thread); } m_decompiler_thread = new VertexDecompilerThread(data, shader, parr); m_decompiler_thread->Create(); m_decompiler_thread->Run(); #endif } void VertexProgram::Compile() { if(id) glDeleteShader(id); id = glCreateShader(GL_VERTEX_SHADER); const char* str = shader.c_str(); const int strlen = shader.Len(); glShaderSource(id, 1, &str, &strlen); glCompileShader(id); GLint r = GL_FALSE; glGetShaderiv(id, GL_COMPILE_STATUS, &r); if(r != GL_TRUE) { glGetShaderiv(id, GL_INFO_LOG_LENGTH, &r); if(r) { char* buf = new char[r+1]; GLsizei len; memset(buf, 0, r+1); glGetShaderInfoLog(id, r, &len, buf); ConLog.Error("Failed to compile vertex shader: %s", buf); free(buf); } ConLog.Write(shader); Emu.Pause(); } //else ConLog.Write("Vertex shader compiled successfully!"); } void VertexProgram::Delete() { data.Clear(); for(u32 i=0; i