mirror of
https://github.com/holub/mame
synced 2025-06-30 16:00:01 +03:00
Fixed GTE GPL & DCPL opcodes by porting over some changes from an old tree [smf]
This commit is contained in:
parent
cec306dbdf
commit
478bfd6391
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* PlayStation Geometry Transformation Engine emulator
|
* PlayStation Geometry Transformation Engine emulator
|
||||||
*
|
*
|
||||||
* Copyright 2003-2011 smf
|
* Copyright 2003-2013 smf
|
||||||
*
|
*
|
||||||
* divider reverse engineering by pSXAuthor.
|
* divider reverse engineering by pSXAuthor.
|
||||||
*
|
*
|
||||||
@ -279,17 +279,17 @@ void gte::setcp2cr( UINT32 pc, int reg, UINT32 value )
|
|||||||
m_cp2cr[ reg ].d = value;
|
m_cp2cr[ reg ].d = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
INT64 gte::BOUNDS( INT64 n_value, INT64 n_max, int n_maxflag, INT64 n_min, int n_minflag )
|
INT64 gte::BOUNDS( INT64 value, INT64 max, int max_flag, INT64 min, int min_flag )
|
||||||
{
|
{
|
||||||
if( n_value > n_max )
|
if( value > max )
|
||||||
{
|
{
|
||||||
FLAG |= n_maxflag;
|
FLAG |= max_flag;
|
||||||
}
|
}
|
||||||
else if( n_value < n_min )
|
else if( value < min )
|
||||||
{
|
{
|
||||||
FLAG |= n_minflag;
|
FLAG |= min_flag;
|
||||||
}
|
}
|
||||||
return n_value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const UINT16 reciprocals[ 32768 ]=
|
static const UINT16 reciprocals[ 32768 ]=
|
||||||
@ -2365,18 +2365,61 @@ INLINE UINT32 gte_divide( INT16 numerator, UINT16 denominator )
|
|||||||
return 0xffffffff;
|
return 0xffffffff;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
INLINE INT64 gte_shift( INT64 a, int sf )
|
||||||
|
{
|
||||||
|
if( sf > 0 )
|
||||||
|
{
|
||||||
|
return a >> 12;
|
||||||
|
}
|
||||||
|
else if( sf < 0 )
|
||||||
|
{
|
||||||
|
return a << 12;
|
||||||
|
}
|
||||||
|
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
/* Setting bits 12 & 19-22 in FLAG does not set bit 31 */
|
/* Setting bits 12 & 19-22 in FLAG does not set bit 31 */
|
||||||
|
|
||||||
#define A1( a ) BOUNDS( ( a ), 0x7fffffff, ( 1 << 31 ) | ( 1 << 30 ), -(INT64)0x80000000, ( 1 << 31 ) | ( 1 << 27 ) )
|
INT64 gte::A1( INT64 a ) { return BOUNDS( ( a ), U64(0x7ffffffffff), ( 1 << 31 ) | ( 1 << 30 ), U64(-0x80000000000), ( 1 << 31 ) | ( 1 << 27 ) ); }
|
||||||
#define A2( a ) BOUNDS( ( a ), 0x7fffffff, ( 1 << 31 ) | ( 1 << 29 ), -(INT64)0x80000000, ( 1 << 31 ) | ( 1 << 26 ) )
|
INT64 gte::A2( INT64 a ) { return BOUNDS( ( a ), U64(0x7ffffffffff), ( 1 << 31 ) | ( 1 << 29 ), U64(-0x80000000000), ( 1 << 31 ) | ( 1 << 26 ) ); }
|
||||||
#define A3( a ) BOUNDS( ( a ), 0x7fffffff, ( 1 << 31 ) | ( 1 << 28 ), -(INT64)0x80000000, ( 1 << 31 ) | ( 1 << 25 ) )
|
INT64 gte::A3( INT64 a ) { return BOUNDS( ( a ), U64(0x7ffffffffff), ( 1 << 31 ) | ( 1 << 28 ), U64(-0x80000000000), ( 1 << 31 ) | ( 1 << 25 ) ); }
|
||||||
#define Lm_B1( a, l ) LIM( ( a ), 0x7fff, -0x8000 * !l, ( 1 << 31 ) | ( 1 << 24 ) )
|
INT32 gte::Lm_B1( INT32 a, int lm ) { return LIM( ( a ), 0x7fff, -0x8000 * !lm, ( 1 << 31 ) | ( 1 << 24 ) ); }
|
||||||
#define Lm_B2( a, l ) LIM( ( a ), 0x7fff, -0x8000 * !l, ( 1 << 31 ) | ( 1 << 23 ) )
|
INT32 gte::Lm_B2( INT32 a, int lm ) { return LIM( ( a ), 0x7fff, -0x8000 * !lm, ( 1 << 31 ) | ( 1 << 23 ) ); }
|
||||||
#define Lm_B3( a, l ) LIM( ( a ), 0x7fff, -0x8000 * !l, ( 1 << 22 ) )
|
INT32 gte::Lm_B3( INT32 a, int lm ) { return LIM( ( a ), 0x7fff, -0x8000 * !lm, ( 1 << 22 ) ); }
|
||||||
#define Lm_C1( a ) LIM( ( a ), 0x00ff, 0x0000, ( 1 << 21 ) )
|
|
||||||
#define Lm_C2( a ) LIM( ( a ), 0x00ff, 0x0000, ( 1 << 20 ) )
|
INT32 gte::Lm_B3_sf( INT64 value, int sf, int lm )
|
||||||
#define Lm_C3( a ) LIM( ( a ), 0x00ff, 0x0000, ( 1 << 19 ) )
|
{
|
||||||
#define Lm_D( a ) LIM( ( a ), 0xffff, 0x0000, ( 1 << 31 ) | ( 1 << 18 ) )
|
INT32 value_sf = gte_shift( value, sf );
|
||||||
|
INT32 value_12 = gte_shift( value, 1 );
|
||||||
|
int max = 0x7fff;
|
||||||
|
int min = 0;
|
||||||
|
if( lm == 0 )
|
||||||
|
{
|
||||||
|
min = -0x8000;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( value_12 < -0x8000 || value_12 > 0x7fff )
|
||||||
|
{
|
||||||
|
FLAG |= ( 1 << 22 );
|
||||||
|
}
|
||||||
|
|
||||||
|
if( value_sf > max )
|
||||||
|
{
|
||||||
|
return max;
|
||||||
|
}
|
||||||
|
else if( value_sf < min )
|
||||||
|
{
|
||||||
|
return min;
|
||||||
|
}
|
||||||
|
|
||||||
|
return value_sf;
|
||||||
|
}
|
||||||
|
|
||||||
|
INT32 gte::Lm_C1( INT32 a ) { return LIM( ( a ), 0x00ff, 0x0000, ( 1 << 21 ) ); }
|
||||||
|
INT32 gte::Lm_C2( INT32 a ) { return LIM( ( a ), 0x00ff, 0x0000, ( 1 << 20 ) ); }
|
||||||
|
INT32 gte::Lm_C3( INT32 a ) { return LIM( ( a ), 0x00ff, 0x0000, ( 1 << 19 ) ); }
|
||||||
|
INT32 gte::Lm_D( INT32 a ) { return LIM( ( a ), 0xffff, 0x0000, ( 1 << 31 ) | ( 1 << 18 ) ); }
|
||||||
|
|
||||||
UINT32 gte::Lm_E( UINT32 result )
|
UINT32 gte::Lm_E( UINT32 result )
|
||||||
{
|
{
|
||||||
@ -2389,49 +2432,78 @@ UINT32 gte::Lm_E( UINT32 result )
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define F( a ) BOUNDS( ( a ), 0x7fffffff, ( 1 << 31 ) | ( 1 << 16 ), -(INT64)0x80000000, ( 1 << 31 ) | ( 1 << 15 ) )
|
INT64 gte::F( INT64 a ) { return BOUNDS( ( a ), U64(0x7fffffff), ( 1 << 31 ) | ( 1 << 16 ), U64(-0x80000000), ( 1 << 31 ) | ( 1 << 15 ) ); }
|
||||||
#define Lm_G1( a ) LIM( ( a ), 0x3ff, -0x400, ( 1 << 31 ) | ( 1 << 14 ) )
|
INT32 gte::Lm_G1( INT32 a ) { return LIM( ( a ), 0x3ff, -0x400, ( 1 << 31 ) | ( 1 << 14 ) ); }
|
||||||
#define Lm_G2( a ) LIM( ( a ), 0x3ff, -0x400, ( 1 << 31 ) | ( 1 << 13 ) )
|
INT32 gte::Lm_G2( INT32 a ) { return LIM( ( a ), 0x3ff, -0x400, ( 1 << 31 ) | ( 1 << 13 ) ); }
|
||||||
#define Lm_H( a ) LIM( ( a ), 0xfff, 0x000, ( 1 << 12 ) )
|
|
||||||
|
INT32 gte::Lm_H( INT64 value, int sf )
|
||||||
|
{
|
||||||
|
INT64 value_sf = gte_shift( value, sf );
|
||||||
|
INT32 value_12 = gte_shift( value, 1 );
|
||||||
|
int max = 0x1000;
|
||||||
|
int min = 0x0000;
|
||||||
|
|
||||||
|
if( value_sf < min || value_sf > max )
|
||||||
|
{
|
||||||
|
FLAG |= ( 1 << 12 );
|
||||||
|
}
|
||||||
|
|
||||||
|
if( value_12 > max )
|
||||||
|
{
|
||||||
|
return max;
|
||||||
|
}
|
||||||
|
else if( value_12 < min )
|
||||||
|
{
|
||||||
|
return min;
|
||||||
|
}
|
||||||
|
|
||||||
|
return value_12;
|
||||||
|
}
|
||||||
|
|
||||||
int gte::docop2( UINT32 pc, int gteop )
|
int gte::docop2( UINT32 pc, int gteop )
|
||||||
{
|
{
|
||||||
int shift;
|
int sf;
|
||||||
int v;
|
int v;
|
||||||
int lm;
|
int lm;
|
||||||
int cv;
|
int cv;
|
||||||
int mx;
|
int mx;
|
||||||
INT32 h_over_sz3;
|
INT32 h_over_sz3;
|
||||||
INT64 mac0;
|
INT64 mac0;
|
||||||
|
INT64 mac1;
|
||||||
|
INT64 mac2;
|
||||||
|
INT64 mac3;
|
||||||
|
|
||||||
switch( GTE_FUNCT( gteop ) )
|
switch( GTE_FUNCT( gteop ) )
|
||||||
{
|
{
|
||||||
case 0x01:
|
case 0x01:
|
||||||
if( gteop == 0x0180001 )
|
GTELOG( pc, "%08x RTPS", gteop );
|
||||||
{
|
FLAG = 0;
|
||||||
GTELOG( pc, "%08x RTPS", gteop );
|
|
||||||
FLAG = 0;
|
|
||||||
|
|
||||||
MAC1 = A1( ( ( (INT64) TRX << 12 ) + ( R11 * VX0 ) + ( R12 * VY0 ) + ( R13 * VZ0 ) ) >> 12 );
|
sf = GTE_SF( gteop );
|
||||||
MAC2 = A2( ( ( (INT64) TRY << 12 ) + ( R21 * VX0 ) + ( R22 * VY0 ) + ( R23 * VZ0 ) ) >> 12 );
|
lm = GTE_LM( gteop );
|
||||||
MAC3 = A3( ( ( (INT64) TRZ << 12 ) + ( R31 * VX0 ) + ( R32 * VY0 ) + ( R33 * VZ0 ) ) >> 12 );
|
|
||||||
IR1 = Lm_B1( MAC1, 0 );
|
mac1 = A1( ( (INT64) TRX << 12 ) + ( R11 * VX0 ) + ( R12 * VY0 ) + ( R13 * VZ0 ) );
|
||||||
IR2 = Lm_B2( MAC2, 0 );
|
mac2 = A2( ( (INT64) TRY << 12 ) + ( R21 * VX0 ) + ( R22 * VY0 ) + ( R23 * VZ0 ) );
|
||||||
IR3 = Lm_B3( MAC3, 0 );
|
mac3 = A3( ( (INT64) TRZ << 12 ) + ( R31 * VX0 ) + ( R32 * VY0 ) + ( R33 * VZ0 ) );
|
||||||
SZ0 = SZ1;
|
MAC1 = gte_shift( mac1, sf );
|
||||||
SZ1 = SZ2;
|
MAC2 = gte_shift( mac2, sf );
|
||||||
SZ2 = SZ3;
|
MAC3 = gte_shift( mac3, sf );
|
||||||
SZ3 = Lm_D( MAC3 );
|
IR1 = Lm_B1( MAC1, lm );
|
||||||
h_over_sz3 = Lm_E( gte_divide( H, SZ3 ) );
|
IR2 = Lm_B2( MAC2, lm );
|
||||||
SXY0 = SXY1;
|
IR3 = Lm_B3_sf( mac3, sf, lm );
|
||||||
SXY1 = SXY2;
|
SZ0 = SZ1;
|
||||||
SX2 = Lm_G1( F( (INT64) OFX + ( (INT64) IR1 * h_over_sz3 ) ) >> 16 );
|
SZ1 = SZ2;
|
||||||
SY2 = Lm_G2( F( (INT64) OFY + ( (INT64) IR2 * h_over_sz3 ) ) >> 16 );
|
SZ2 = SZ3;
|
||||||
MAC0 = F( (INT64) DQB + ( (INT64) DQA * h_over_sz3 ) );
|
SZ3 = Lm_D( gte_shift( mac3, 1 ) );
|
||||||
IR0 = Lm_H( MAC0 >> 12 );
|
h_over_sz3 = Lm_E( gte_divide( H, SZ3 ) );
|
||||||
return 1;
|
SXY0 = SXY1;
|
||||||
}
|
SXY1 = SXY2;
|
||||||
break;
|
SX2 = Lm_G1( F( (INT64) OFX + ( (INT64) IR1 * h_over_sz3 ) ) >> 16 );
|
||||||
|
SY2 = Lm_G2( F( (INT64) OFY + ( (INT64) IR2 * h_over_sz3 ) ) >> 16 );
|
||||||
|
mac0 = F( (INT64) DQB + ( (INT64) DQA * h_over_sz3 ) );
|
||||||
|
MAC0 = mac0;
|
||||||
|
IR0 = Lm_H( mac0, 1 );
|
||||||
|
return 1;
|
||||||
|
|
||||||
case 0x06:
|
case 0x06:
|
||||||
GTELOG( pc, "%08x NCLIP", gteop );
|
GTELOG( pc, "%08x NCLIP", gteop );
|
||||||
@ -2444,12 +2516,15 @@ int gte::docop2( UINT32 pc, int gteop )
|
|||||||
GTELOG( pc, "%08x OP", gteop );
|
GTELOG( pc, "%08x OP", gteop );
|
||||||
FLAG = 0;
|
FLAG = 0;
|
||||||
|
|
||||||
shift = 12 * GTE_SF( gteop );
|
sf = GTE_SF( gteop );
|
||||||
lm = GTE_LM( gteop );
|
lm = GTE_LM( gteop );
|
||||||
|
|
||||||
MAC1 = A1( ( (INT64) ( R22 * IR3 ) - ( R33 * IR2 ) ) >> shift );
|
mac1 = A1( (INT64) ( R22 * IR3 ) - ( R33 * IR2 ) );
|
||||||
MAC2 = A2( ( (INT64) ( R33 * IR1 ) - ( R11 * IR3 ) ) >> shift );
|
mac2 = A2( (INT64) ( R33 * IR1 ) - ( R11 * IR3 ) );
|
||||||
MAC3 = A3( ( (INT64) ( R11 * IR2 ) - ( R22 * IR1 ) ) >> shift );
|
mac3 = A3( (INT64) ( R11 * IR2 ) - ( R22 * IR1 ) );
|
||||||
|
MAC1 = gte_shift( mac1, sf );
|
||||||
|
MAC2 = gte_shift( mac2, sf );
|
||||||
|
MAC3 = gte_shift( mac3, sf );
|
||||||
IR1 = Lm_B1( MAC1, lm );
|
IR1 = Lm_B1( MAC1, lm );
|
||||||
IR2 = Lm_B2( MAC2, lm );
|
IR2 = Lm_B2( MAC2, lm );
|
||||||
IR3 = Lm_B3( MAC3, lm );
|
IR3 = Lm_B3( MAC3, lm );
|
||||||
@ -2459,12 +2534,15 @@ int gte::docop2( UINT32 pc, int gteop )
|
|||||||
GTELOG( pc, "%08x DPCS", gteop );
|
GTELOG( pc, "%08x DPCS", gteop );
|
||||||
FLAG = 0;
|
FLAG = 0;
|
||||||
|
|
||||||
shift = 12 * GTE_SF( gteop );
|
sf = GTE_SF( gteop );
|
||||||
lm = GTE_LM( gteop );
|
lm = GTE_LM( gteop );
|
||||||
|
|
||||||
MAC1 = ( ( R << 16 ) + ( IR0 * Lm_B1( A1( (INT64) RFC - ( R << 4 ) ) << ( 12 - shift ), 0 ) ) ) >> shift;
|
mac1 = ( ( R << 16 ) + ( IR0 * Lm_B1( gte_shift( A1( ( (INT64) RFC << 12 ) - ( R << 16 ) ), sf ), 0 ) ) );
|
||||||
MAC2 = ( ( G << 16 ) + ( IR0 * Lm_B2( A2( (INT64) GFC - ( G << 4 ) ) << ( 12 - shift ), 0 ) ) ) >> shift;
|
mac2 = ( ( G << 16 ) + ( IR0 * Lm_B2( gte_shift( A2( ( (INT64) GFC << 12 ) - ( G << 16 ) ), sf ), 0 ) ) );
|
||||||
MAC3 = ( ( B << 16 ) + ( IR0 * Lm_B3( A3( (INT64) BFC - ( B << 4 ) ) << ( 12 - shift ), 0 ) ) ) >> shift;
|
mac3 = ( ( B << 16 ) + ( IR0 * Lm_B3( gte_shift( A3( ( (INT64) BFC << 12 ) - ( B << 16 ) ), sf ), 0 ) ) );
|
||||||
|
MAC1 = gte_shift( mac1, sf );
|
||||||
|
MAC2 = gte_shift( mac2, sf );
|
||||||
|
MAC3 = gte_shift( mac3, sf );
|
||||||
IR1 = Lm_B1( MAC1, lm );
|
IR1 = Lm_B1( MAC1, lm );
|
||||||
IR2 = Lm_B2( MAC2, lm );
|
IR2 = Lm_B2( MAC2, lm );
|
||||||
IR3 = Lm_B3( MAC3, lm );
|
IR3 = Lm_B3( MAC3, lm );
|
||||||
@ -2480,12 +2558,15 @@ int gte::docop2( UINT32 pc, int gteop )
|
|||||||
GTELOG( pc, "%08x INTPL", gteop );
|
GTELOG( pc, "%08x INTPL", gteop );
|
||||||
FLAG = 0;
|
FLAG = 0;
|
||||||
|
|
||||||
shift = 12 * GTE_SF( gteop );
|
sf = GTE_SF( gteop );
|
||||||
lm = GTE_LM( gteop );
|
lm = GTE_LM( gteop );
|
||||||
|
|
||||||
MAC1 = ( ( IR1 << 12 ) + ( IR0 * Lm_B1( A1( (INT64) RFC - IR1 ) << ( 12 - shift ), 0 ) ) ) >> shift;
|
mac1 = ( ( IR1 << 12 ) + ( IR0 * Lm_B1( gte_shift( A1( ( (INT64) RFC << 12 ) - ( IR1 << 12 ) ), sf ), 0 ) ) );
|
||||||
MAC2 = ( ( IR2 << 12 ) + ( IR0 * Lm_B2( A2( (INT64) GFC - IR2 ) << ( 12 - shift ), 0 ) ) ) >> shift;
|
mac2 = ( ( IR2 << 12 ) + ( IR0 * Lm_B2( gte_shift( A2( ( (INT64) GFC << 12 ) - ( IR2 << 12 ) ), sf ), 0 ) ) );
|
||||||
MAC3 = ( ( IR3 << 12 ) + ( IR0 * Lm_B3( A3( (INT64) BFC - IR3 ) << ( 12 - shift ), 0 ) ) ) >> shift;
|
mac3 = ( ( IR3 << 12 ) + ( IR0 * Lm_B3( gte_shift( A3( ( (INT64) BFC << 12 ) - ( IR3 << 12 ) ), sf ), 0 ) ) );
|
||||||
|
MAC1 = gte_shift( mac1, sf );
|
||||||
|
MAC2 = gte_shift( mac2, sf );
|
||||||
|
MAC3 = gte_shift( mac3, sf );
|
||||||
IR1 = Lm_B1( MAC1, lm );
|
IR1 = Lm_B1( MAC1, lm );
|
||||||
IR2 = Lm_B2( MAC2, lm );
|
IR2 = Lm_B2( MAC2, lm );
|
||||||
IR3 = Lm_B3( MAC3, lm );
|
IR3 = Lm_B3( MAC3, lm );
|
||||||
@ -2498,27 +2579,25 @@ int gte::docop2( UINT32 pc, int gteop )
|
|||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
case 0x12:
|
case 0x12:
|
||||||
if( GTE_OP( gteop ) == 0x04 )
|
GTELOG( pc, "%08x MVMVA", gteop );
|
||||||
{
|
FLAG = 0;
|
||||||
GTELOG( pc, "%08x MVMVA", gteop );
|
|
||||||
shift = 12 * GTE_SF( gteop );
|
|
||||||
mx = GTE_MX( gteop );
|
|
||||||
v = GTE_V( gteop );
|
|
||||||
cv = GTE_CV( gteop );
|
|
||||||
lm = GTE_LM( gteop );
|
|
||||||
|
|
||||||
FLAG = 0;
|
mx = GTE_MX( gteop );
|
||||||
|
v = GTE_V( gteop );
|
||||||
|
cv = GTE_CV( gteop );
|
||||||
|
sf = GTE_SF( gteop );
|
||||||
|
lm = GTE_LM( gteop );
|
||||||
|
|
||||||
MAC1 = A1( ( ( (INT64) CV1( cv ) << 12 ) + ( MX11( mx ) * VX( v ) ) + ( MX12( mx ) * VY( v ) ) + ( MX13( mx ) * VZ( v ) ) ) >> shift );
|
mac1 = A1( ( (INT64) CV1( cv ) << 12 ) + ( MX11( mx ) * VX( v ) ) + ( MX12( mx ) * VY( v ) ) + ( MX13( mx ) * VZ( v ) ) );
|
||||||
MAC2 = A2( ( ( (INT64) CV2( cv ) << 12 ) + ( MX21( mx ) * VX( v ) ) + ( MX22( mx ) * VY( v ) ) + ( MX23( mx ) * VZ( v ) ) ) >> shift );
|
mac2 = A2( ( (INT64) CV2( cv ) << 12 ) + ( MX21( mx ) * VX( v ) ) + ( MX22( mx ) * VY( v ) ) + ( MX23( mx ) * VZ( v ) ) );
|
||||||
MAC3 = A3( ( ( (INT64) CV3( cv ) << 12 ) + ( MX31( mx ) * VX( v ) ) + ( MX32( mx ) * VY( v ) ) + ( MX33( mx ) * VZ( v ) ) ) >> shift );
|
mac3 = A3( ( (INT64) CV3( cv ) << 12 ) + ( MX31( mx ) * VX( v ) ) + ( MX32( mx ) * VY( v ) ) + ( MX33( mx ) * VZ( v ) ) );
|
||||||
|
MAC1 = gte_shift( mac1, sf );
|
||||||
IR1 = Lm_B1( MAC1, lm );
|
MAC2 = gte_shift( mac2, sf );
|
||||||
IR2 = Lm_B2( MAC2, lm );
|
MAC3 = gte_shift( mac3, sf );
|
||||||
IR3 = Lm_B3( MAC3, lm );
|
IR1 = Lm_B1( MAC1, lm );
|
||||||
return 1;
|
IR2 = Lm_B2( MAC2, lm );
|
||||||
}
|
IR3 = Lm_B3( MAC3, lm );
|
||||||
break;
|
return 1;
|
||||||
|
|
||||||
case 0x13:
|
case 0x13:
|
||||||
if( gteop == 0x0e80413 )
|
if( gteop == 0x0e80413 )
|
||||||
@ -2710,85 +2789,98 @@ int gte::docop2( UINT32 pc, int gteop )
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x20:
|
case 0x20:
|
||||||
if( gteop == 0x0d80420 )
|
GTELOG( pc, "%08x NCT", gteop );
|
||||||
{
|
|
||||||
GTELOG( pc, "%08x NCT", gteop );
|
|
||||||
FLAG = 0;
|
|
||||||
|
|
||||||
for( v = 0; v < 3; v++ )
|
|
||||||
{
|
|
||||||
MAC1 = A1( ( ( (INT64) L11 * VX( v ) ) + ( L12 * VY( v ) ) + ( L13 * VZ( v ) ) ) >> 12 );
|
|
||||||
MAC2 = A2( ( ( (INT64) L21 * VX( v ) ) + ( L22 * VY( v ) ) + ( L23 * VZ( v ) ) ) >> 12 );
|
|
||||||
MAC3 = A3( ( ( (INT64) L31 * VX( v ) ) + ( L32 * VY( v ) ) + ( L33 * VZ( v ) ) ) >> 12 );
|
|
||||||
IR1 = Lm_B1( MAC1, 1 );
|
|
||||||
IR2 = Lm_B2( MAC2, 1 );
|
|
||||||
IR3 = Lm_B3( MAC3, 1 );
|
|
||||||
MAC1 = A1( ( ( (INT64) RBK << 12 ) + ( LR1 * IR1 ) + ( LR2 * IR2 ) + ( LR3 * IR3 ) ) >> 12 );
|
|
||||||
MAC2 = A2( ( ( (INT64) GBK << 12 ) + ( LG1 * IR1 ) + ( LG2 * IR2 ) + ( LG3 * IR3 ) ) >> 12 );
|
|
||||||
MAC3 = A3( ( ( (INT64) BBK << 12 ) + ( LB1 * IR1 ) + ( LB2 * IR2 ) + ( LB3 * IR3 ) ) >> 12 );
|
|
||||||
IR1 = Lm_B1( MAC1, 1 );
|
|
||||||
IR2 = Lm_B2( MAC2, 1 );
|
|
||||||
IR3 = Lm_B3( MAC3, 1 );
|
|
||||||
RGB0 = RGB1;
|
|
||||||
RGB1 = RGB2;
|
|
||||||
CD2 = CODE;
|
|
||||||
R2 = Lm_C1( MAC1 >> 4 );
|
|
||||||
G2 = Lm_C2( MAC2 >> 4 );
|
|
||||||
B2 = Lm_C3( MAC3 >> 4 );
|
|
||||||
}
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 0x28:
|
|
||||||
GTELOG( pc, "%08x SQR", gteop );
|
|
||||||
FLAG = 0;
|
FLAG = 0;
|
||||||
|
|
||||||
shift = 12 * GTE_SF( gteop );
|
sf = GTE_SF( gteop );
|
||||||
lm = GTE_LM( gteop );
|
lm = GTE_LM( gteop );
|
||||||
|
|
||||||
MAC1 = A1( ( IR1 * IR1 ) >> shift );
|
for( v = 0; v < 3; v++ )
|
||||||
MAC2 = A2( ( IR2 * IR2 ) >> shift );
|
|
||||||
MAC3 = A3( ( IR3 * IR3 ) >> shift );
|
|
||||||
IR1 = Lm_B1( MAC1, lm );
|
|
||||||
IR2 = Lm_B2( MAC2, lm );
|
|
||||||
IR3 = Lm_B3( MAC3, lm );
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
case 0x29:
|
|
||||||
if( gteop == 0x0680029 )
|
|
||||||
{
|
{
|
||||||
GTELOG( pc, "%08x DPCL", gteop );
|
mac1 = A1( (INT64) ( L11 * VX( v ) ) + ( L12 * VY( v ) ) + ( L13 * VZ( v ) ) );
|
||||||
FLAG = 0;
|
mac2 = A2( (INT64) ( L21 * VX( v ) ) + ( L22 * VY( v ) ) + ( L23 * VZ( v ) ) );
|
||||||
|
mac3 = A3( (INT64) ( L31 * VX( v ) ) + ( L32 * VY( v ) ) + ( L33 * VZ( v ) ) );
|
||||||
MAC1 = A1( ( ( ( (INT64) R << 4 ) * IR1 ) + ( IR0 * Lm_B1( RFC - ( ( R * IR1 ) >> 8 ), 0 ) ) ) >> 12 );
|
MAC1 = gte_shift( mac1, sf );
|
||||||
MAC2 = A2( ( ( ( (INT64) G << 4 ) * IR2 ) + ( IR0 * Lm_B2( GFC - ( ( G * IR2 ) >> 8 ), 0 ) ) ) >> 12 );
|
MAC2 = gte_shift( mac2, sf );
|
||||||
MAC3 = A3( ( ( ( (INT64) B << 4 ) * IR3 ) + ( IR0 * Lm_B3( BFC - ( ( B * IR3 ) >> 8 ), 0 ) ) ) >> 12 );
|
MAC3 = gte_shift( mac3, sf );
|
||||||
IR1 = Lm_B1( MAC1, 1 );
|
IR1 = Lm_B1( MAC1, lm );
|
||||||
IR2 = Lm_B2( MAC2, 1 );
|
IR2 = Lm_B2( MAC2, lm );
|
||||||
IR3 = Lm_B3( MAC3, 1 );
|
IR3 = Lm_B3( MAC3, lm );
|
||||||
|
mac1 = A1( ( (INT64) RBK << 12 ) + ( LR1 * IR1 ) + ( LR2 * IR2 ) + ( LR3 * IR3 ) );
|
||||||
|
mac2 = A2( ( (INT64) GBK << 12 ) + ( LG1 * IR1 ) + ( LG2 * IR2 ) + ( LG3 * IR3 ) );
|
||||||
|
mac3 = A3( ( (INT64) BBK << 12 ) + ( LB1 * IR1 ) + ( LB2 * IR2 ) + ( LB3 * IR3 ) );
|
||||||
|
MAC1 = gte_shift( mac1, sf );
|
||||||
|
MAC2 = gte_shift( mac2, sf );
|
||||||
|
MAC3 = gte_shift( mac3, sf );
|
||||||
|
IR1 = Lm_B1( MAC1, lm );
|
||||||
|
IR2 = Lm_B2( MAC2, lm );
|
||||||
|
IR3 = Lm_B3( MAC3, lm );
|
||||||
RGB0 = RGB1;
|
RGB0 = RGB1;
|
||||||
RGB1 = RGB2;
|
RGB1 = RGB2;
|
||||||
CD2 = CODE;
|
CD2 = CODE;
|
||||||
R2 = Lm_C1( MAC1 >> 4 );
|
R2 = Lm_C1( MAC1 >> 4 );
|
||||||
G2 = Lm_C2( MAC2 >> 4 );
|
G2 = Lm_C2( MAC2 >> 4 );
|
||||||
B2 = Lm_C3( MAC3 >> 4 );
|
B2 = Lm_C3( MAC3 >> 4 );
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
break;
|
return 1;
|
||||||
|
|
||||||
|
case 0x28:
|
||||||
|
GTELOG( pc, "%08x SQR", gteop );
|
||||||
|
FLAG = 0;
|
||||||
|
|
||||||
|
sf = GTE_SF( gteop );
|
||||||
|
lm = GTE_LM( gteop );
|
||||||
|
|
||||||
|
mac1 = A1( IR1 * IR1 );
|
||||||
|
mac2 = A2( IR2 * IR2 );
|
||||||
|
mac3 = A3( IR3 * IR3 );
|
||||||
|
MAC1 = gte_shift( mac1, sf );
|
||||||
|
MAC2 = gte_shift( mac2, sf );
|
||||||
|
MAC3 = gte_shift( mac3, sf );
|
||||||
|
IR1 = Lm_B1( MAC1, lm );
|
||||||
|
IR2 = Lm_B2( MAC2, lm );
|
||||||
|
IR3 = Lm_B3( MAC3, lm );
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
case 0x29:
|
||||||
|
GTELOG( pc, "%08x DPCL", gteop );
|
||||||
|
FLAG = 0;
|
||||||
|
|
||||||
|
sf = GTE_SF( gteop );
|
||||||
|
lm = GTE_LM( gteop );
|
||||||
|
|
||||||
|
mac1 = ( ( ( R << 4 ) * IR1 ) + ( IR0 * Lm_B1( gte_shift( A1( ( (INT64) RFC << 12 ) - ( ( R << 4 ) * IR1 ) ), sf ), 0 ) ) );
|
||||||
|
mac2 = ( ( ( G << 4 ) * IR2 ) + ( IR0 * Lm_B2( gte_shift( A2( ( (INT64) GFC << 12 ) - ( ( G << 4 ) * IR2 ) ), sf ), 0 ) ) );
|
||||||
|
mac3 = ( ( ( B << 4 ) * IR3 ) + ( IR0 * Lm_B3( gte_shift( A3( ( (INT64) BFC << 12 ) - ( ( B << 4 ) * IR3 ) ), sf ), 0 ) ) );
|
||||||
|
MAC1 = gte_shift( mac1, sf );
|
||||||
|
MAC2 = gte_shift( mac2, sf );
|
||||||
|
MAC3 = gte_shift( mac3, sf );
|
||||||
|
IR1 = Lm_B1( MAC1, lm );
|
||||||
|
IR2 = Lm_B2( MAC2, lm );
|
||||||
|
IR3 = Lm_B3( MAC3, lm );
|
||||||
|
RGB0 = RGB1;
|
||||||
|
RGB1 = RGB2;
|
||||||
|
CD2 = CODE;
|
||||||
|
R2 = Lm_C1( MAC1 >> 4 );
|
||||||
|
G2 = Lm_C2( MAC2 >> 4 );
|
||||||
|
B2 = Lm_C3( MAC3 >> 4 );
|
||||||
|
return 1;
|
||||||
|
|
||||||
case 0x2a:
|
case 0x2a:
|
||||||
GTELOG( pc, "%08x DPCT", gteop );
|
GTELOG( pc, "%08x DPCT", gteop );
|
||||||
FLAG = 0;
|
FLAG = 0;
|
||||||
|
|
||||||
shift = 12 * GTE_SF( gteop );
|
sf = GTE_SF( gteop );
|
||||||
lm = GTE_LM( gteop );
|
lm = GTE_LM( gteop );
|
||||||
|
|
||||||
for( v = 0; v < 3; v++ )
|
for( v = 0; v < 3; v++ )
|
||||||
{
|
{
|
||||||
MAC1 = ( ( R0 << 16 ) + ( IR0 * Lm_B1( A1( (INT64) RFC - ( R0 << 4 ) ) << ( 12 - shift ), 0 ) ) ) >> shift;
|
mac1 = ( ( R0 << 16 ) + ( IR0 * Lm_B1( gte_shift( A1( ( (INT64) RFC << 12 ) - ( R0 << 16 ) ), sf ), 0 ) ) );
|
||||||
MAC2 = ( ( G0 << 16 ) + ( IR0 * Lm_B2( A2( (INT64) GFC - ( G0 << 4 ) ) << ( 12 - shift ), 0 ) ) ) >> shift;
|
mac2 = ( ( G0 << 16 ) + ( IR0 * Lm_B2( gte_shift( A2( ( (INT64) GFC << 12 ) - ( G0 << 16 ) ), sf ), 0 ) ) );
|
||||||
MAC3 = ( ( B0 << 16 ) + ( IR0 * Lm_B3( A3( (INT64) BFC - ( B0 << 4 ) ) << ( 12 - shift ), 0 ) ) ) >> shift;
|
mac3 = ( ( B0 << 16 ) + ( IR0 * Lm_B3( gte_shift( A3( ( (INT64) BFC << 12 ) - ( B0 << 16 ) ), sf ), 0 ) ) );
|
||||||
|
MAC1 = gte_shift( mac1, sf );
|
||||||
|
MAC2 = gte_shift( mac2, sf );
|
||||||
|
MAC3 = gte_shift( mac3, sf );
|
||||||
IR1 = Lm_B1( MAC1, lm );
|
IR1 = Lm_B1( MAC1, lm );
|
||||||
IR2 = Lm_B2( MAC2, lm );
|
IR2 = Lm_B2( MAC2, lm );
|
||||||
IR3 = Lm_B3( MAC3, lm );
|
IR3 = Lm_B3( MAC3, lm );
|
||||||
@ -2805,62 +2897,66 @@ int gte::docop2( UINT32 pc, int gteop )
|
|||||||
GTELOG( pc, "%08x AVSZ3", gteop );
|
GTELOG( pc, "%08x AVSZ3", gteop );
|
||||||
FLAG = 0;
|
FLAG = 0;
|
||||||
|
|
||||||
mac0 = F( (INT64) ( ZSF3 * SZ1 ) + ( ZSF3 * SZ2 ) + ( ZSF3 * SZ3 ) );
|
mac0 = F( (INT64)( ZSF3 * SZ1 ) + ( ZSF3 * SZ2 ) + ( ZSF3 * SZ3 ) );
|
||||||
OTZ = Lm_D( mac0 >> 12 );
|
|
||||||
|
|
||||||
MAC0 = mac0;
|
MAC0 = mac0;
|
||||||
|
OTZ = Lm_D( mac0 >> 12 );
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
case 0x2e:
|
case 0x2e:
|
||||||
GTELOG( pc, "%08x AVSZ4", gteop );
|
GTELOG( pc, "%08x AVSZ4", gteop );
|
||||||
FLAG = 0;
|
FLAG = 0;
|
||||||
|
|
||||||
mac0 = F( (INT64) ( ZSF4 * SZ0 ) + ( ZSF4 * SZ1 ) + ( ZSF4 * SZ2 ) + ( ZSF4 * SZ3 ) );
|
mac0 = F( (INT64)( ZSF4 * SZ0 ) + ( ZSF4 * SZ1 ) + ( ZSF4 * SZ2 ) + ( ZSF4 * SZ3 ) );
|
||||||
OTZ = Lm_D( mac0 >> 12 );
|
|
||||||
|
|
||||||
MAC0 = mac0;
|
MAC0 = mac0;
|
||||||
|
OTZ = Lm_D( mac0 >> 12 );
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
case 0x30:
|
case 0x30:
|
||||||
if( gteop == 0x0280030 )
|
GTELOG( pc, "%08x RTPT", gteop );
|
||||||
{
|
FLAG = 0;
|
||||||
GTELOG( pc, "%08x RTPT", gteop );
|
|
||||||
FLAG = 0;
|
|
||||||
|
|
||||||
for( v = 0; v < 3; v++ )
|
sf = GTE_SF( gteop );
|
||||||
{
|
lm = GTE_LM( gteop );
|
||||||
MAC1 = A1( ( ( (INT64) TRX << 12 ) + ( R11 * VX( v ) ) + ( R12 * VY( v ) ) + ( R13 * VZ( v ) ) ) >> 12 );
|
|
||||||
MAC2 = A2( ( ( (INT64) TRY << 12 ) + ( R21 * VX( v ) ) + ( R22 * VY( v ) ) + ( R23 * VZ( v ) ) ) >> 12 );
|
for( v = 0; v < 3; v++ )
|
||||||
MAC3 = A3( ( ( (INT64) TRZ << 12 ) + ( R31 * VX( v ) ) + ( R32 * VY( v ) ) + ( R33 * VZ( v ) ) ) >> 12 );
|
{
|
||||||
IR1 = Lm_B1( MAC1, 0 );
|
mac1 = A1( ( (INT64) TRX << 12 ) + ( R11 * VX( v ) ) + ( R12 * VY( v ) ) + ( R13 * VZ( v ) ) );
|
||||||
IR2 = Lm_B2( MAC2, 0 );
|
mac2 = A2( ( (INT64) TRY << 12 ) + ( R21 * VX( v ) ) + ( R22 * VY( v ) ) + ( R23 * VZ( v ) ) );
|
||||||
IR3 = Lm_B3( MAC3, 0 );
|
mac3 = A3( ( (INT64) TRZ << 12 ) + ( R31 * VX( v ) ) + ( R32 * VY( v ) ) + ( R33 * VZ( v ) ) );
|
||||||
SZ0 = SZ1;
|
MAC1 = gte_shift( mac1, sf );
|
||||||
SZ1 = SZ2;
|
MAC2 = gte_shift( mac2, sf );
|
||||||
SZ2 = SZ3;
|
MAC3 = gte_shift( mac3, sf );
|
||||||
SZ3 = Lm_D( MAC3 );
|
IR1 = Lm_B1( MAC1, lm );
|
||||||
h_over_sz3 = Lm_E( gte_divide( H, SZ3 ) );
|
IR2 = Lm_B2( MAC2, lm );
|
||||||
SXY0 = SXY1;
|
IR3 = Lm_B3_sf( mac3, sf, lm );
|
||||||
SXY1 = SXY2;
|
SZ0 = SZ1;
|
||||||
SX2 = Lm_G1( F( ( (INT64) OFX + ( (INT64) IR1 * h_over_sz3 ) ) >> 16 ) );
|
SZ1 = SZ2;
|
||||||
SY2 = Lm_G2( F( ( (INT64) OFY + ( (INT64) IR2 * h_over_sz3 ) ) >> 16 ) );
|
SZ2 = SZ3;
|
||||||
MAC0 = F( (INT64) DQB + ( (INT64) DQA * h_over_sz3 ) );
|
SZ3 = Lm_D( gte_shift( mac3, 1 ) );
|
||||||
IR0 = Lm_H( MAC0 >> 12 );
|
h_over_sz3 = Lm_E( gte_divide( H, SZ3 ) );
|
||||||
}
|
SXY0 = SXY1;
|
||||||
return 1;
|
SXY1 = SXY2;
|
||||||
|
SX2 = Lm_G1( F( (INT64) OFX + ( (INT64) IR1 * h_over_sz3 ) ) >> 16 );
|
||||||
|
SY2 = Lm_G2( F( (INT64) OFY + ( (INT64) IR2 * h_over_sz3 ) ) >> 16 );
|
||||||
|
mac0 = F( (INT64) DQB + ( (INT64) DQA * h_over_sz3 ) );
|
||||||
|
MAC0 = mac0;
|
||||||
|
IR0 = Lm_H( mac0, 1 );
|
||||||
}
|
}
|
||||||
break;
|
return 1;
|
||||||
|
|
||||||
case 0x3d:
|
case 0x3d:
|
||||||
GTELOG( pc, "%08x GPF", gteop );
|
GTELOG( pc, "%08x GPF", gteop );
|
||||||
FLAG = 0;
|
FLAG = 0;
|
||||||
|
|
||||||
shift = 12 * GTE_SF( gteop );
|
sf = GTE_SF( gteop );
|
||||||
lm = GTE_LM( gteop );
|
lm = GTE_LM( gteop );
|
||||||
|
|
||||||
MAC1 = A1( IR0 * IR1 ) >> shift;
|
mac1 = A1( IR0 * IR1 );
|
||||||
MAC2 = A2( IR0 * IR2 ) >> shift;
|
mac2 = A2( IR0 * IR2 );
|
||||||
MAC3 = A3( IR0 * IR3 ) >> shift;
|
mac3 = A3( IR0 * IR3 );
|
||||||
|
MAC1 = gte_shift( mac1, sf );
|
||||||
|
MAC2 = gte_shift( mac2, sf );
|
||||||
|
MAC3 = gte_shift( mac3, sf );
|
||||||
IR1 = Lm_B1( MAC1, lm );
|
IR1 = Lm_B1( MAC1, lm );
|
||||||
IR2 = Lm_B2( MAC2, lm );
|
IR2 = Lm_B2( MAC2, lm );
|
||||||
IR3 = Lm_B3( MAC3, lm );
|
IR3 = Lm_B3( MAC3, lm );
|
||||||
@ -2873,27 +2969,28 @@ int gte::docop2( UINT32 pc, int gteop )
|
|||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
case 0x3e:
|
case 0x3e:
|
||||||
if( GTE_OP( gteop ) == 0x1a )
|
GTELOG( pc, "%08x GPL", gteop );
|
||||||
{
|
FLAG = 0;
|
||||||
GTELOG( pc, "%08x GPL", gteop );
|
|
||||||
shift = 12 * GTE_SF( gteop );
|
|
||||||
FLAG = 0;
|
|
||||||
|
|
||||||
MAC1 = A1( ( ( (INT64) MAC1 << shift ) + ( IR0 * IR1 ) ) >> shift );
|
sf = GTE_SF( gteop );
|
||||||
MAC2 = A2( ( ( (INT64) MAC2 << shift ) + ( IR0 * IR2 ) ) >> shift );
|
lm = GTE_LM( gteop );
|
||||||
MAC3 = A3( ( ( (INT64) MAC3 << shift ) + ( IR0 * IR3 ) ) >> shift );
|
|
||||||
IR1 = Lm_B1( MAC1, 0 );
|
mac1 = A1( gte_shift( MAC1, -sf ) + ( IR0 * IR1 ) );
|
||||||
IR2 = Lm_B2( MAC2, 0 );
|
mac2 = A2( gte_shift( MAC2, -sf ) + ( IR0 * IR2 ) );
|
||||||
IR3 = Lm_B3( MAC3, 0 );
|
mac3 = A3( gte_shift( MAC3, -sf ) + ( IR0 * IR3 ) );
|
||||||
RGB0 = RGB1;
|
MAC1 = gte_shift( mac1, sf );
|
||||||
RGB1 = RGB2;
|
MAC2 = gte_shift( mac2, sf );
|
||||||
CD2 = CODE;
|
MAC3 = gte_shift( mac3, sf );
|
||||||
R2 = Lm_C1( MAC1 >> 4 );
|
IR1 = Lm_B1( MAC1, lm );
|
||||||
G2 = Lm_C2( MAC2 >> 4 );
|
IR2 = Lm_B2( MAC2, lm );
|
||||||
B2 = Lm_C3( MAC3 >> 4 );
|
IR3 = Lm_B3( MAC3, lm );
|
||||||
return 1;
|
RGB0 = RGB1;
|
||||||
}
|
RGB1 = RGB2;
|
||||||
break;
|
CD2 = CODE;
|
||||||
|
R2 = Lm_C1( MAC1 >> 4 );
|
||||||
|
G2 = Lm_C2( MAC2 >> 4 );
|
||||||
|
B2 = Lm_C3( MAC3 >> 4 );
|
||||||
|
return 1;
|
||||||
|
|
||||||
case 0x3f:
|
case 0x3f:
|
||||||
if( gteop == 0x108043f ||
|
if( gteop == 0x108043f ||
|
||||||
|
@ -39,7 +39,22 @@ public:
|
|||||||
protected:
|
protected:
|
||||||
INT32 LIM( INT32 value, INT32 max, INT32 min, UINT32 flag );
|
INT32 LIM( INT32 value, INT32 max, INT32 min, UINT32 flag );
|
||||||
INT64 BOUNDS( INT64 n_value, INT64 n_max, int n_maxflag, INT64 n_min, int n_minflag );
|
INT64 BOUNDS( INT64 n_value, INT64 n_max, int n_maxflag, INT64 n_min, int n_minflag );
|
||||||
|
INT64 A1( INT64 a );
|
||||||
|
INT64 A2( INT64 a );
|
||||||
|
INT64 A3( INT64 a );
|
||||||
|
INT32 Lm_B1( INT32 a, int lm );
|
||||||
|
INT32 Lm_B2( INT32 a, int lm );
|
||||||
|
INT32 Lm_B3( INT32 a, int lm );
|
||||||
|
INT32 Lm_B3_sf( INT64 value, int sf, int lm );
|
||||||
|
INT32 Lm_C1( INT32 a );
|
||||||
|
INT32 Lm_C2( INT32 a );
|
||||||
|
INT32 Lm_C3( INT32 a );
|
||||||
|
INT32 Lm_D( INT32 a );
|
||||||
UINT32 Lm_E( UINT32 result );
|
UINT32 Lm_E( UINT32 result );
|
||||||
|
INT64 F( INT64 a );
|
||||||
|
INT32 Lm_G1( INT32 a );
|
||||||
|
INT32 Lm_G2( INT32 a );
|
||||||
|
INT32 Lm_H( INT64 value, int sf );
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
Reference in New Issue
Block a user