2012-11-15 00:39:56 +01:00
# include "stdafx.h"
2013-11-09 22:29:49 +01:00
# include "GLVertexProgram.h"
2012-11-15 00:39:56 +01:00
2013-11-09 22:29:49 +01:00
wxString GLVertexDecompilerThread : : GetMask ( bool is_sca )
2012-11-15 00:39:56 +01:00
{
wxString ret = wxEmptyString ;
2013-08-10 23:56:24 +02:00
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 " ;
}
2012-11-15 00:39:56 +01:00
2013-11-19 11:30:58 +01:00
return ret . IsEmpty ( ) | | ret = = " xyzw " ? wxString ( wxEmptyString ) : ( " . " + ret ) ;
2012-11-15 00:39:56 +01:00
}
2013-11-09 22:29:49 +01:00
wxString GLVertexDecompilerThread : : GetVecMask ( )
2013-06-30 10:46:29 +02:00
{
2013-08-10 23:56:24 +02:00
return GetMask ( false ) ;
}
2013-06-30 10:46:29 +02:00
2013-11-09 22:29:49 +01:00
wxString GLVertexDecompilerThread : : GetScaMask ( )
2013-08-10 23:56:24 +02:00
{
return GetMask ( true ) ;
2013-06-30 10:46:29 +02:00
}
2013-11-09 22:29:49 +01:00
wxString GLVertexDecompilerThread : : GetDST ( bool isSca )
2012-11-15 00:39:56 +01:00
{
2013-11-27 20:16:19 +01:00
static const std : : string reg_table [ ] =
2012-11-15 00:39:56 +01:00
{
" gl_Position " ,
" col0 " , " col1 " ,
" bfc0 " , " bfc1 " ,
2013-08-26 16:18:59 +02:00
" gl_ClipDistance[%d] " ,
" gl_ClipDistance[%d] " ,
2012-11-15 00:39:56 +01:00
" tc0 " , " tc1 " , " tc2 " , " tc3 " , " tc4 " , " tc5 " , " tc6 " , " tc7 "
} ;
wxString ret = wxEmptyString ;
2013-08-10 23:56:24 +02:00
switch ( isSca ? 0x1f : d3 . dst )
2012-11-15 00:39:56 +01:00
{
2013-08-26 16:18:59 +02:00
case 0x0 : case 0x5 : case 0x6 :
2013-08-10 23:56:24 +02:00
ret + = reg_table [ d3 . dst ] ;
2012-11-15 00:39:56 +01:00
break ;
case 0x1f :
2013-11-27 20:16:19 +01:00
ret + = m_parr . AddParam ( PARAM_NONE , " vec4 " , std : : string ( " tmp " ) + std : : to_string ( isSca ? d3 . sca_dst_tmp : d0 . dst_tmp ) ) ;
2012-11-15 00:39:56 +01:00
break ;
default :
2013-08-10 23:56:24 +02:00
if ( d3 . dst < WXSIZEOF ( reg_table ) )
2012-11-15 00:39:56 +01:00
{
2013-08-10 23:56:24 +02:00
ret + = m_parr . AddParam ( PARAM_OUT , " vec4 " , reg_table [ d3 . dst ] ) ;
2012-11-15 00:39:56 +01:00
}
else
{
2013-08-10 23:56:24 +02:00
ConLog . Error ( " Bad dst reg num: %d " , d3 . dst ) ;
2012-11-15 00:39:56 +01:00
ret + = m_parr . AddParam ( PARAM_OUT , " vec4 " , " unk " ) ;
}
break ;
}
return ret ;
}
2013-11-09 22:29:49 +01:00
wxString GLVertexDecompilerThread : : GetSRC ( const u32 n , bool isSca )
2012-11-15 00:39:56 +01:00
{
2013-11-27 20:16:19 +01:00
static const std : : string reg_table [ ] =
2012-11-15 00:39:56 +01:00
{
" 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
2013-11-27 20:16:19 +01:00
ret + = m_parr . AddParam ( PARAM_NONE , " vec4 " , std : : string ( " tmp " ) + std : : to_string ( src [ n ] . tmp_src ) ) ;
2012-11-15 00:39:56 +01:00
break ;
case 2 : //input
if ( d1 . input_src < WXSIZEOF ( reg_table ) )
{
2013-06-30 10:46:29 +02:00
ret + = m_parr . AddParam ( PARAM_IN , " vec4 " , reg_table [ d1 . input_src ] , d1 . input_src ) ;
2012-11-15 00:39:56 +01:00
}
else
{
ConLog . Error ( " Bad input src num: %d " , d1 . input_src ) ;
2013-06-30 10:46:29 +02:00
ret + = m_parr . AddParam ( PARAM_IN , " vec4 " , " in_unk " , d1 . input_src ) ;
2012-11-15 00:39:56 +01:00
}
break ;
case 3 : //const
2013-11-27 20:16:19 +01:00
ret + = m_parr . AddParam ( PARAM_UNIFORM , " vec4 " , std : : string ( " vc " ) + std : : to_string ( d1 . const_src ) ) ;
2012-11-15 00:39:56 +01:00
break ;
default :
2013-08-26 16:18:59 +02:00
ConLog . Error ( " Bad src%u reg type: %d " , n , src [ n ] . reg_type ) ;
2012-11-15 00:39:56 +01:00
Emu . Pause ( ) ;
break ;
}
2013-08-26 16:18:59 +02:00
static const wxString f = " xyzw " ;
2012-11-15 00:39:56 +01:00
2013-06-30 10:46:29 +02:00
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 ) ;
2012-11-15 00:39:56 +01:00
2013-08-26 16:18:59 +02:00
ret + = ' . ' ;
ret + = f [ src [ n ] . swz_x ] ;
2013-06-30 10:46:29 +02:00
}
else
{
2013-08-26 16:18:59 +02:00
wxString swizzle = wxEmptyString ;
2013-06-30 10:46:29 +02:00
swizzle + = f [ src [ n ] . swz_x ] ;
swizzle + = f [ src [ n ] . swz_y ] ;
swizzle + = f [ src [ n ] . swz_z ] ;
swizzle + = f [ src [ n ] . swz_w ] ;
2013-08-26 16:18:59 +02:00
if ( swizzle ! = f ) ret + = ' . ' + swizzle ;
2013-06-30 10:46:29 +02:00
}
2012-11-15 00:39:56 +01:00
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 ;
}
2014-01-31 19:40:18 +01:00
void GLVertexDecompilerThread : : AddCode ( bool is_sca , wxString code , bool src_mask , bool set_dst , bool set_cond )
2013-06-30 10:46:29 +02:00
{
if ( d0 . cond = = 0 ) return ;
2013-08-10 23:56:24 +02:00
enum
2013-06-30 10:46:29 +02:00
{
2013-08-10 23:56:24 +02:00
lt = 0x1 ,
eq = 0x2 ,
gt = 0x4 ,
} ;
2014-01-31 19:40:18 +01:00
static const char * cond_string_table [ ( lt | gt | eq ) + 1 ] =
{
" error " ,
" lessThan " ,
" equal " ,
" lessThanEqual " ,
" greaterThan " ,
" notEqual " ,
" greaterThanEqual " ,
" error "
} ;
2013-08-10 23:56:24 +02:00
wxString cond ;
2014-01-31 19:40:18 +01:00
if ( ( set_cond | | d0 . cond_test_enable ) & & d0 . cond ! = ( lt | gt | eq ) )
2013-08-10 23:56:24 +02:00
{
2014-01-31 19:40:18 +01:00
static const char f [ 4 ] = { ' x ' , ' y ' , ' z ' , ' w ' } ;
2013-08-10 23:56:24 +02:00
2014-01-31 19:40:18 +01:00
std : : string swizzle ;
swizzle + = f [ d0 . mask_x ] ;
swizzle + = f [ d0 . mask_y ] ;
swizzle + = f [ d0 . mask_z ] ;
swizzle + = f [ d0 . mask_w ] ;
2013-08-10 23:56:24 +02:00
2014-01-31 19:40:18 +01:00
swizzle = swizzle = = " xyzw " ? " " : " . " + swizzle ;
2014-02-13 17:59:13 +01:00
cond = wxString : : Format ( " if(all(%s(rc%s, vec4(0.0)%s))) " , wxString ( cond_string_table [ d0 . cond ] ) . wx_str ( ) , wxString ( swizzle ) . wx_str ( ) , wxString ( swizzle ) . wx_str ( ) ) ;
2013-06-30 10:46:29 +02:00
}
2014-01-31 19:40:18 +01:00
wxString mask = GetMask ( is_sca ) ;
wxString value = src_mask ? code + mask : code ;
if ( is_sca & & d0 . vec_result )
{
value = " vec4( " + value + " ) " + mask ;
}
2013-08-17 00:22:26 +02:00
if ( d0 . staturate )
{
value = " clamp( " + value + " , 0.0, 1.0) " ;
}
2014-01-07 21:11:02 +01:00
if ( set_dst )
2013-08-26 16:18:59 +02:00
{
2014-01-07 21:11:02 +01:00
wxString dest ;
if ( d0 . cond_update_enable_0 )
2013-08-26 16:18:59 +02:00
{
2014-01-31 19:40:18 +01:00
dest = m_parr . AddParam ( PARAM_NONE , " vec4 " , " rc " , " vec4(0.0) " ) + mask ;
2013-08-26 16:18:59 +02:00
}
2014-01-07 21:11:02 +01:00
else if ( d3 . dst = = 5 | | d3 . dst = = 6 )
{
if ( d3 . vec_writemask_x )
{
2014-01-31 21:54:26 +01:00
dest = m_parr . AddParam ( PARAM_OUT , " vec4 " , " fogc " ) + mask ;
2014-01-07 21:11:02 +01:00
}
2014-01-31 19:40:18 +01:00
else
{
int num = d3 . dst = = 5 ? 0 : 3 ;
2013-08-26 16:18:59 +02:00
2014-01-31 19:40:18 +01:00
//if(d3.vec_writemask_y) num += 0;
if ( d3 . vec_writemask_z ) num + = 1 ;
else if ( d3 . vec_writemask_w ) num + = 2 ;
2014-01-07 21:11:02 +01:00
2014-01-31 19:40:18 +01:00
dest = wxString : : Format ( GetDST ( is_sca ) + " /* " + mask + " */ " , num ) ;
}
2014-01-07 21:11:02 +01:00
}
else
{
2014-01-31 19:40:18 +01:00
dest = GetDST ( is_sca ) + mask ;
2014-01-07 21:11:02 +01:00
}
2013-08-26 16:18:59 +02:00
2014-01-07 21:11:02 +01:00
code = cond + dest + " = " + value ;
2013-08-26 16:18:59 +02:00
}
else
{
2014-01-07 21:11:02 +01:00
code = cond + value ;
}
2014-01-31 19:40:18 +01:00
m_body . Add ( code + " ; " ) ;
2014-01-07 21:11:02 +01:00
}
wxString GLVertexDecompilerThread : : GetFunc ( )
{
u32 offset = ( d2 . iaddrh < < 3 ) | d3 . iaddrl ;
wxString name = wxString : : Format ( " func%u " , offset ) ;
for ( uint i = 0 ; i < m_funcs . GetCount ( ) ; + + i )
{
if ( m_funcs [ i ] . name . Cmp ( name ) = = 0 )
return name + " () " ;
2013-08-26 16:18:59 +02:00
}
2014-01-07 21:11:02 +01:00
uint idx = m_funcs . Add ( new FuncInfo ( ) ) ;
m_funcs [ idx ] . offset = offset ;
m_funcs [ idx ] . name = name ;
2013-06-30 10:46:29 +02:00
2014-01-07 21:11:02 +01:00
return name + " () " ;
2013-06-30 10:46:29 +02:00
}
2014-01-07 21:11:02 +01:00
void GLVertexDecompilerThread : : AddVecCode ( const wxString & code , bool src_mask , bool set_dst )
2012-11-15 00:39:56 +01:00
{
2014-01-07 21:11:02 +01:00
AddCode ( false , code , src_mask , set_dst ) ;
2013-08-10 23:56:24 +02:00
}
2012-11-15 00:39:56 +01:00
2014-01-31 19:40:18 +01:00
void GLVertexDecompilerThread : : AddScaCode ( const wxString & code , bool set_dst , bool set_cond )
2013-08-10 23:56:24 +02:00
{
2014-01-31 19:40:18 +01:00
AddCode ( true , code , false , set_dst , set_cond ) ;
2014-01-07 21:11:02 +01:00
}
wxString GLVertexDecompilerThread : : BuildFuncBody ( const FuncInfo & func )
{
wxString result ;
for ( uint i = func . offset ; i < m_body . GetCount ( ) ; + + i )
{
if ( i ! = func . offset )
{
uint call_func = - 1 ;
for ( uint j = 0 ; j < m_funcs . GetCount ( ) ; + + j )
{
if ( m_funcs [ j ] . offset = = i )
{
call_func = j ;
break ;
}
}
if ( call_func ! = - 1 )
{
result + = ' \t ' + m_funcs [ call_func ] . name + " (); \n " ;
break ;
}
}
result + = ' \t ' + m_body [ i ] + ' \n ' ;
}
return result ;
2012-11-15 00:39:56 +01:00
}
2013-11-09 22:29:49 +01:00
wxString GLVertexDecompilerThread : : BuildCode ( )
2012-11-15 00:39:56 +01:00
{
wxString p = wxEmptyString ;
for ( u32 i = 0 ; i < m_parr . params . GetCount ( ) ; + + i )
{
2013-06-30 10:46:29 +02:00
p + = m_parr . params [ i ] . Format ( ) ;
2012-11-15 00:39:56 +01:00
}
2014-01-07 21:11:02 +01:00
wxString fp = wxEmptyString ;
2014-01-31 19:40:18 +01:00
for ( int i = m_funcs . GetCount ( ) - 1 ; i > 0 ; - - i )
2014-01-07 21:11:02 +01:00
{
2014-02-10 13:53:09 +01:00
fp + = wxString : : Format ( " void %s(); \n " , m_funcs [ i ] . name . wx_str ( ) ) ;
2014-01-07 21:11:02 +01:00
}
wxString f = wxEmptyString ;
2014-02-17 22:05:59 +01:00
f + = wxString : : Format ( " void %s() \n { \n \t gl_Position = vec4(0.0f, 0.0f, 0.0f, 1.0f); \n %s \t gl_Position = gl_Position * scaleOffsetMat; \n } \n " , m_funcs [ 0 ] . name . wx_str ( ) , BuildFuncBody ( m_funcs [ 0 ] ) . wx_str ( ) ) ;
2014-01-07 21:11:02 +01:00
for ( uint i = 1 ; i < m_funcs . GetCount ( ) ; + + i )
{
2014-02-10 13:53:09 +01:00
f + = wxString : : Format ( " \n void %s() \n { \n %s} \n " , m_funcs [ i ] . name . wx_str ( ) , BuildFuncBody ( m_funcs [ i ] ) . wx_str ( ) ) ;
2014-01-07 21:11:02 +01:00
}
2012-11-15 00:39:56 +01:00
static const wxString & prot =
2013-06-30 10:46:29 +02:00
" #version 330 \n "
2012-11-15 00:39:56 +01:00
" \n "
2014-02-10 16:57:32 +01:00
" uniform mat4 scaleOffsetMat = mat4(1.0); \n "
2012-11-15 00:39:56 +01:00
" %s \n "
2014-01-07 21:11:02 +01:00
" %s \n "
" %s " ;
2012-11-15 00:39:56 +01:00
2014-02-10 13:53:09 +01:00
return wxString : : Format ( prot , p . wx_str ( ) , fp . wx_str ( ) , f . wx_str ( ) ) ;
2012-11-15 00:39:56 +01:00
}
2013-11-09 22:29:49 +01:00
void GLVertexDecompilerThread : : Task ( )
2012-11-15 00:39:56 +01:00
{
2014-01-31 21:54:26 +01:00
m_parr . params . Clear ( ) ;
2014-02-17 22:05:59 +01:00
for ( u32 i = 0 , intsCount = 0 ; ; intsCount + + )
2012-11-15 00:39:56 +01:00
{
d0 . HEX = m_data [ i + + ] ;
d1 . HEX = m_data [ i + + ] ;
d2 . HEX = m_data [ i + + ] ;
d3 . HEX = m_data [ i + + ] ;
2013-08-10 23:56:24 +02:00
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 ;
2012-11-15 00:39:56 +01:00
2013-06-30 10:46:29 +02:00
switch ( d1 . sca_opcode )
{
case 0x00 : break ; // NOP
case 0x01 : AddScaCode ( GetSRC ( 2 , true ) ) ; break ; // MOV
2014-01-31 19:40:18 +01:00
case 0x02 : AddScaCode ( " 1.0 / " + GetSRC ( 2 , true ) ) ; break ; // RCP
case 0x03 : AddScaCode ( " clamp(1.0 / " + GetSRC ( 2 , true ) + " , 5.42101e-20, 1.884467e19) " ) ; break ; // RCC
2013-06-30 10:46:29 +02:00
case 0x04 : AddScaCode ( " inversesqrt( " + GetSRC ( 2 , true ) + " ) " ) ; break ; // RSQ
case 0x05 : AddScaCode ( " exp( " + GetSRC ( 2 , true ) + " ) " ) ; break ; // EXP
case 0x06 : AddScaCode ( " log( " + GetSRC ( 2 , true ) + " ) " ) ; break ; // LOG
//case 0x07: break; // LIT
2014-02-17 22:05:59 +01:00
case 0x08 : AddScaCode ( " { /*BRA*/ " + GetFunc ( ) + " ; " + wxString ( m_funcs . GetCount ( ) = = 1 | | m_funcs [ 1 ] . offset > intsCount ? " gl_Position = gl_Position * scaleOffsetMat; " : " " ) + " return; } " , false , true ) ; break ; // BRA
case 0x09 : AddScaCode ( " { " + GetFunc ( ) + " ; " + wxString ( m_funcs . GetCount ( ) = = 1 | | m_funcs [ 1 ] . offset > intsCount ? " gl_Position = gl_Position * scaleOffsetMat; " : " " ) + " return; } " , false , true ) ; break ; // BRI : works differently (BRI o[1].x(TR) L0;)
2014-01-31 19:40:18 +01:00
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
2014-02-17 22:05:59 +01:00
case 0x0c : AddScaCode ( " { " + wxString ( m_funcs . GetCount ( ) = = 1 | | m_funcs [ 1 ] . offset > intsCount ? " gl_Position = gl_Position * scaleOffsetMat; " : " " ) + " return; } " , false , true ) ; break ; // RET : works like BRI but shorter (RET o[1].x(TR);)
2013-06-30 10:46:29 +02:00
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 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;)
//case 0x14: break; // POP : works differently (POP o[1].x;)
default :
2014-01-07 21:11:02 +01:00
m_body . Add ( wxString : : Format ( " //Unknown vp sca_opcode 0x%x " , d1 . sca_opcode ) ) ;
2013-06-30 10:46:29 +02:00
ConLog . Error ( " Unknown vp sca_opcode 0x%x " , d1 . sca_opcode ) ;
Emu . Pause ( ) ;
break ;
}
2012-11-15 00:39:56 +01:00
switch ( d1 . vec_opcode )
{
case 0x00 : break ; //NOP
2013-06-30 10:46:29 +02:00
case 0x01 : AddVecCode ( GetSRC ( 0 ) ) ; break ; //MOV
case 0x02 : AddVecCode ( " ( " + GetSRC ( 0 ) + " * " + GetSRC ( 1 ) + " ) " ) ; break ; //MUL
2013-08-10 23:56:24 +02:00
case 0x03 : AddVecCode ( " ( " + GetSRC ( 0 ) + " + " + GetSRC ( 2 ) + " ) " ) ; break ; //ADD
2013-06-30 10:46:29 +02:00
case 0x04 : AddVecCode ( " ( " + GetSRC ( 0 ) + " * " + GetSRC ( 1 ) + " + " + GetSRC ( 2 ) + " ) " ) ; break ; //MAD
2013-11-03 20:23:16 +01:00
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
2013-06-30 10:46:29 +02:00
case 0x09 : AddVecCode ( " min( " + GetSRC ( 0 ) + " , " + GetSRC ( 1 ) + " ) " ) ; break ; //MIN
case 0x0a : AddVecCode ( " max( " + GetSRC ( 0 ) + " , " + GetSRC ( 1 ) + " ) " ) ; break ; //MAX
2013-08-10 23:56:24 +02:00
case 0x0b : AddVecCode ( " vec4(lessThan( " + GetSRC ( 0 ) + " , " + GetSRC ( 1 ) + " )) " ) ; break ; //SLT
case 0x0c : AddVecCode ( " vec4(greaterThanEqual( " + GetSRC ( 0 ) + " , " + GetSRC ( 1 ) + " )) " ) ; break ; //SGE
2013-06-30 10:46:29 +02:00
case 0x0e : AddVecCode ( " fract( " + GetSRC ( 0 ) + " ) " ) ; break ; //FRC
case 0x0f : AddVecCode ( " floor( " + GetSRC ( 0 ) + " ) " ) ; break ; //FLR
2013-08-10 23:56:24 +02:00
case 0x10 : AddVecCode ( " vec4(equal( " + GetSRC ( 0 ) + " , " + GetSRC ( 1 ) + " )) " ) ; break ; //SEQ
2013-11-03 20:23:16 +01:00
//case 0x11: AddVecCode("vec4(equal(" + GetSRC(0) + ", vec4(0, 0, 0, 0)))"); break; //SFL
2013-08-10 23:56:24 +02:00
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
2013-11-03 20:23:16 +01:00
//case 0x15: AddVecCode("vec4(notEqual(" + GetSRC(0) + ", vec4(0, 0, 0, 0)))"); break; //STR
2013-08-10 23:56:24 +02:00
case 0x16 : AddVecCode ( " sign( " + GetSRC ( 0 ) + " ) " ) ; break ; //SSG
2012-11-15 00:39:56 +01:00
default :
2014-01-07 21:11:02 +01:00
m_body . Add ( wxString : : Format ( " //Unknown vp opcode 0x%x " , d1 . vec_opcode ) ) ;
2012-11-15 00:39:56 +01:00
ConLog . Error ( " Unknown vp opcode 0x%x " , d1 . vec_opcode ) ;
Emu . Pause ( ) ;
break ;
}
2014-01-07 21:11:02 +01:00
if ( d3 . end )
{
if ( i < m_data . GetCount ( ) )
ConLog . Error ( " Program end before buffer end. " ) ;
break ;
}
2012-11-15 00:39:56 +01:00
}
m_shader = BuildCode ( ) ;
2013-08-17 00:22:26 +02:00
2014-01-07 21:11:02 +01:00
m_body . Clear ( ) ;
m_funcs . RemoveAt ( 1 , m_funcs . GetCount ( ) - 1 ) ;
2012-11-15 00:39:56 +01:00
}
2013-11-09 22:29:49 +01:00
GLVertexProgram : : GLVertexProgram ( )
2013-08-10 23:56:24 +02:00
: m_decompiler_thread ( nullptr )
2012-11-15 00:39:56 +01:00
, id ( 0 )
{
}
2013-11-09 22:29:49 +01:00
GLVertexProgram : : ~ GLVertexProgram ( )
2012-11-15 00:39:56 +01:00
{
if ( m_decompiler_thread )
{
Wait ( ) ;
2013-06-30 10:46:29 +02:00
if ( m_decompiler_thread - > IsAlive ( ) )
{
m_decompiler_thread - > Stop ( ) ;
}
delete m_decompiler_thread ;
m_decompiler_thread = nullptr ;
2012-11-15 00:39:56 +01:00
}
Delete ( ) ;
}
2013-11-09 22:29:49 +01:00
void GLVertexProgram : : Decompile ( RSXVertexProgram & prog )
2012-11-15 00:39:56 +01:00
{
#if 0
2013-11-09 22:29:49 +01:00
GLVertexDecompilerThread ( data , shader , parr ) . Entry ( ) ;
2012-11-15 00:39:56 +01:00
# else
if ( m_decompiler_thread )
{
Wait ( ) ;
2013-06-30 10:46:29 +02:00
if ( m_decompiler_thread - > IsAlive ( ) )
{
m_decompiler_thread - > Stop ( ) ;
}
delete m_decompiler_thread ;
m_decompiler_thread = nullptr ;
2012-11-15 00:39:56 +01:00
}
2013-11-09 22:29:49 +01:00
m_decompiler_thread = new GLVertexDecompilerThread ( prog . data , shader , parr ) ;
2013-06-30 10:46:29 +02:00
m_decompiler_thread - > Start ( ) ;
2012-11-15 00:39:56 +01:00
# endif
}
2013-11-09 22:29:49 +01:00
void GLVertexProgram : : Compile ( )
2012-11-15 00:39:56 +01:00
{
if ( id ) glDeleteShader ( id ) ;
id = glCreateShader ( GL_VERTEX_SHADER ) ;
2014-02-10 19:51:03 +01:00
const char * str = shader . mb_str ( ) ;
2012-11-15 00:39:56 +01:00
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 ) ;
2014-02-10 19:51:03 +01:00
ConLog . Error ( " Failed to compile vertex shader: %s " , wxString ( buf ) . wx_str ( ) ) ;
2013-06-30 10:46:29 +02:00
delete [ ] buf ;
2012-11-15 00:39:56 +01:00
}
ConLog . Write ( shader ) ;
Emu . Pause ( ) ;
}
//else ConLog.Write("Vertex shader compiled successfully!");
}
2013-11-09 22:29:49 +01:00
void GLVertexProgram : : Delete ( )
2012-11-15 00:39:56 +01:00
{
parr . params . Clear ( ) ;
shader . Clear ( ) ;
if ( id )
{
glDeleteShader ( id ) ;
id = 0 ;
}
}