2010-04-25 00:31:27 +00:00
/*
2009-02-09 21:15:56 +00:00
* Copyright ( C ) 2007 - 2009 Gabest
* http : //www.gabest.org
*
* This Program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation ; either version 2 , or ( at your option )
* any later version .
2010-04-25 00:31:27 +00:00
*
2009-02-09 21:15:56 +00:00
* This Program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
2010-04-25 00:31:27 +00:00
*
2009-02-09 21:15:56 +00:00
* You should have received a copy of the GNU General Public License
* along with GNU Make ; see the file COPYING . If not , write to
2012-09-09 18:16:11 +00:00
* the Free Software Foundation , Inc . , 51 Franklin Street , Fifth Floor , Boston , MA 02110 - 1301 , USA USA .
2009-02-09 21:15:56 +00:00
* http : //www.gnu.org/copyleft/gpl.html
*
*/
# include "stdafx.h"
# include "GSState.h"
2012-01-08 17:10:00 +00:00
# include "GSdx.h"
2009-02-09 21:15:56 +00:00
2011-05-09 01:36:57 +00:00
//#define Offset_ST // Fixes Persona3 mini map alignment which is off even in software rendering
2010-05-14 14:05:39 +00:00
2015-06-04 16:52:58 +00:00
static int s_crc_hack_level = 3 ;
2012-01-19 04:53:36 +00:00
GSState : : GSState ( )
2011-02-18 01:56:05 +00:00
: m_version ( 6 )
, m_mt ( false )
2009-09-18 19:54:56 +00:00
, m_irq ( NULL )
2009-02-09 21:15:56 +00:00
, m_path3hack ( 0 )
2014-05-02 21:03:02 +00:00
, m_init_read_fifo_supported ( false )
2013-06-28 17:32:37 +00:00
, m_q ( 1.0f )
, m_texflush ( true )
, m_vt ( this )
2011-02-18 01:56:05 +00:00
, m_regs ( NULL )
, m_crc ( 0 )
, m_options ( 0 )
2009-02-09 21:15:56 +00:00
, m_frameskip ( 0 )
2015-06-17 21:25:43 +00:00
, m_crcinited ( false )
2009-02-09 21:15:56 +00:00
{
2015-09-21 20:26:00 +00:00
m_nativeres = theApp . GetConfig ( " upscale_multiplier " , 1 ) = = 1 ;
2015-08-04 11:27:08 +00:00
m_mipmap = ! ! theApp . GetConfig ( " mipmap " , 1 ) ;
2012-01-08 17:10:00 +00:00
2015-05-31 15:38:52 +00:00
s_n = 0 ;
s_dump = ! ! theApp . GetConfig ( " dump " , 0 ) ;
s_save = ! ! theApp . GetConfig ( " save " , 0 ) ;
2015-05-01 11:35:21 +00:00
s_savet = ! ! theApp . GetConfig ( " savet " , 0 ) ;
GSdx:
- changed the KH2 fix in GetTextureMinMax to my taste, should give the same results, when the used texture rect is to the left/above the clamped area, it returns [min, min+1], and [max-1, max] for right/below
- m_mem.m_clut.Read32 was returned to its original place from GetAlphaMinMax
- UserHacks_WildHack was moved up to GSState, special UV handlers are only used when this setting is active
- updated xbyak to the latest available (avx2 seems incomplete, the 256-bit promoted old instructions are missing)
- changed vtune's include path to the 2013 edition
Some other not yet commited changes from a year ago:
- WriteImageX overflow crash-fix
- moved colclamp after dithering (sw mode), it makes more sense, no visible changes noticed
- Gif_Tag::analyzeTag(), there was a conditional I didn't like, split the loop into two parts
git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5649 96395faa-99c1-11dd-bbfe-3dabce05a288
2013-06-06 11:36:01 +00:00
s_savez = ! ! theApp . GetConfig ( " savez " , 0 ) ;
2015-05-31 15:38:52 +00:00
s_savef = ! ! theApp . GetConfig ( " savef " , 0 ) ;
2015-06-03 07:31:52 +00:00
s_saven = theApp . GetConfig ( " saven " , 0 ) ;
s_savel = theApp . GetConfig ( " savel " , 5000 ) ;
2015-02-21 12:51:06 +00:00
# ifdef __linux__
if ( s_dump ) {
2015-09-26 11:41:44 +00:00
GSmkdir ( " /tmp/GS_HW_dump " ) ;
GSmkdir ( " /tmp/GS_SW_dump " ) ;
2015-02-21 12:51:06 +00:00
}
# endif
GSdx:
- changed the KH2 fix in GetTextureMinMax to my taste, should give the same results, when the used texture rect is to the left/above the clamped area, it returns [min, min+1], and [max-1, max] for right/below
- m_mem.m_clut.Read32 was returned to its original place from GetAlphaMinMax
- UserHacks_WildHack was moved up to GSState, special UV handlers are only used when this setting is active
- updated xbyak to the latest available (avx2 seems incomplete, the 256-bit promoted old instructions are missing)
- changed vtune's include path to the 2013 edition
Some other not yet commited changes from a year ago:
- WriteImageX overflow crash-fix
- moved colclamp after dithering (sw mode), it makes more sense, no visible changes noticed
- Gif_Tag::analyzeTag(), there was a conditional I didn't like, split the loop into two parts
git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5649 96395faa-99c1-11dd-bbfe-3dabce05a288
2013-06-06 11:36:01 +00:00
2014-09-16 03:37:06 +00:00
//s_dump = 1;
//s_save = 1;
//s_savez = 1;
2015-08-02 18:21:49 +00:00
//s_savet = 1;
//s_savef = 1;
2015-08-05 17:10:55 +00:00
//s_saven = 0;
//s_savel = 0;
2014-09-16 03:37:06 +00:00
GSdx:
- changed the KH2 fix in GetTextureMinMax to my taste, should give the same results, when the used texture rect is to the left/above the clamped area, it returns [min, min+1], and [max-1, max] for right/below
- m_mem.m_clut.Read32 was returned to its original place from GetAlphaMinMax
- UserHacks_WildHack was moved up to GSState, special UV handlers are only used when this setting is active
- updated xbyak to the latest available (avx2 seems incomplete, the 256-bit promoted old instructions are missing)
- changed vtune's include path to the 2013 edition
Some other not yet commited changes from a year ago:
- WriteImageX overflow crash-fix
- moved colclamp after dithering (sw mode), it makes more sense, no visible changes noticed
- Gif_Tag::analyzeTag(), there was a conditional I didn't like, split the loop into two parts
git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5649 96395faa-99c1-11dd-bbfe-3dabce05a288
2013-06-06 11:36:01 +00:00
UserHacks_WildHack = ! ! theApp . GetConfig ( " UserHacks " , 0 ) ? theApp . GetConfig ( " UserHacks_WildHack " , 0 ) : 0 ;
2015-06-04 16:52:58 +00:00
m_crc_hack_level = theApp . GetConfig ( " crc_hack_level " , 3 ) ;
s_crc_hack_level = m_crc_hack_level ;
GSdx:
- changed the KH2 fix in GetTextureMinMax to my taste, should give the same results, when the used texture rect is to the left/above the clamped area, it returns [min, min+1], and [max-1, max] for right/below
- m_mem.m_clut.Read32 was returned to its original place from GetAlphaMinMax
- UserHacks_WildHack was moved up to GSState, special UV handlers are only used when this setting is active
- updated xbyak to the latest available (avx2 seems incomplete, the 256-bit promoted old instructions are missing)
- changed vtune's include path to the 2013 edition
Some other not yet commited changes from a year ago:
- WriteImageX overflow crash-fix
- moved colclamp after dithering (sw mode), it makes more sense, no visible changes noticed
- Gif_Tag::analyzeTag(), there was a conditional I didn't like, split the loop into two parts
git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5649 96395faa-99c1-11dd-bbfe-3dabce05a288
2013-06-06 11:36:01 +00:00
2012-01-05 02:40:24 +00:00
memset ( & m_v , 0 , sizeof ( m_v ) ) ;
memset ( & m_vertex , 0 , sizeof ( m_vertex ) ) ;
memset ( & m_index , 0 , sizeof ( m_index ) ) ;
2012-01-21 04:44:04 +00:00
m_v . RGBAQ . Q = 1.0f ;
2012-01-05 02:40:24 +00:00
GrowVertexBuffer ( ) ;
2009-02-09 21:15:56 +00:00
m_sssize = 0 ;
2010-04-25 00:31:27 +00:00
2009-02-09 21:15:56 +00:00
m_sssize + = sizeof ( m_version ) ;
m_sssize + = sizeof ( m_env . PRIM ) ;
m_sssize + = sizeof ( m_env . PRMODE ) ;
m_sssize + = sizeof ( m_env . PRMODECONT ) ;
m_sssize + = sizeof ( m_env . TEXCLUT ) ;
m_sssize + = sizeof ( m_env . SCANMSK ) ;
m_sssize + = sizeof ( m_env . TEXA ) ;
m_sssize + = sizeof ( m_env . FOGCOL ) ;
m_sssize + = sizeof ( m_env . DIMX ) ;
m_sssize + = sizeof ( m_env . DTHE ) ;
m_sssize + = sizeof ( m_env . COLCLAMP ) ;
m_sssize + = sizeof ( m_env . PABE ) ;
m_sssize + = sizeof ( m_env . BITBLTBUF ) ;
m_sssize + = sizeof ( m_env . TRXDIR ) ;
m_sssize + = sizeof ( m_env . TRXPOS ) ;
m_sssize + = sizeof ( m_env . TRXREG ) ;
2009-04-18 09:34:25 +00:00
m_sssize + = sizeof ( m_env . TRXREG ) ; // obsolete
2010-04-25 00:31:27 +00:00
2009-02-09 21:15:56 +00:00
for ( int i = 0 ; i < 2 ; i + + )
{
m_sssize + = sizeof ( m_env . CTXT [ i ] . XYOFFSET ) ;
m_sssize + = sizeof ( m_env . CTXT [ i ] . TEX0 ) ;
m_sssize + = sizeof ( m_env . CTXT [ i ] . TEX1 ) ;
m_sssize + = sizeof ( m_env . CTXT [ i ] . TEX2 ) ;
m_sssize + = sizeof ( m_env . CTXT [ i ] . CLAMP ) ;
m_sssize + = sizeof ( m_env . CTXT [ i ] . MIPTBP1 ) ;
m_sssize + = sizeof ( m_env . CTXT [ i ] . MIPTBP2 ) ;
m_sssize + = sizeof ( m_env . CTXT [ i ] . SCISSOR ) ;
m_sssize + = sizeof ( m_env . CTXT [ i ] . ALPHA ) ;
m_sssize + = sizeof ( m_env . CTXT [ i ] . TEST ) ;
m_sssize + = sizeof ( m_env . CTXT [ i ] . FBA ) ;
m_sssize + = sizeof ( m_env . CTXT [ i ] . FRAME ) ;
m_sssize + = sizeof ( m_env . CTXT [ i ] . ZBUF ) ;
}
m_sssize + = sizeof ( m_v . RGBAQ ) ;
m_sssize + = sizeof ( m_v . ST ) ;
m_sssize + = sizeof ( m_v . UV ) ;
2012-01-08 17:10:00 +00:00
m_sssize + = sizeof ( m_v . FOG ) ;
2009-02-09 21:15:56 +00:00
m_sssize + = sizeof ( m_v . XYZ ) ;
2012-01-08 17:10:00 +00:00
m_sssize + = sizeof ( GIFReg ) ; // obsolete
2009-02-09 21:15:56 +00:00
2009-04-18 09:34:25 +00:00
m_sssize + = sizeof ( m_tr . x ) ;
m_sssize + = sizeof ( m_tr . y ) ;
2009-02-09 21:15:56 +00:00
m_sssize + = m_mem . m_vmsize ;
2011-02-07 01:59:05 +00:00
m_sssize + = ( sizeof ( m_path [ 0 ] . tag ) + sizeof ( m_path [ 0 ] . reg ) ) * countof ( m_path ) ;
2012-01-23 04:11:24 +00:00
m_sssize + = sizeof ( m_q ) ;
2009-02-09 21:15:56 +00:00
PRIM = & m_env . PRIM ;
// CSR->rREV = 0x20;
m_env . PRMODECONT . AC = 1 ;
Reset ( ) ;
ResetHandlers ( ) ;
}
GSState : : ~ GSState ( )
{
2012-01-05 02:40:24 +00:00
if ( m_vertex . buff ) _aligned_free ( m_vertex . buff ) ;
if ( m_index . buff ) _aligned_free ( m_index . buff ) ;
2009-02-09 21:15:56 +00:00
}
2009-09-18 19:54:56 +00:00
void GSState : : SetRegsMem ( uint8 * basemem )
2009-09-18 18:45:37 +00:00
{
ASSERT ( basemem ) ;
2011-02-07 01:59:05 +00:00
2009-09-18 18:45:37 +00:00
m_regs = ( GSPrivRegSet * ) basemem ;
}
2009-09-18 19:54:56 +00:00
void GSState : : SetIrqCallback ( void ( * irq ) ( ) )
{
m_irq = irq ;
}
2011-02-07 01:59:05 +00:00
void GSState : : SetMultithreaded ( bool mt )
2009-09-18 19:54:56 +00:00
{
// Some older versions of PCSX2 didn't properly set the irq callback to NULL
// in multithreaded mode (possibly because ZeroGS itself would assert in such
// cases), and didn't bind them to a dummy callback either. PCSX2 handles all
// IRQs internally when multithreaded anyway -- so let's ignore them here:
2010-04-25 00:31:27 +00:00
2011-02-07 01:59:05 +00:00
m_mt = mt ;
if ( mt )
2009-09-18 19:54:56 +00:00
{
2011-02-07 01:59:05 +00:00
m_fpGIFRegHandlers [ GIF_A_D_REG_SIGNAL ] = & GSState : : GIFRegHandlerNull ;
m_fpGIFRegHandlers [ GIF_A_D_REG_FINISH ] = & GSState : : GIFRegHandlerNull ;
m_fpGIFRegHandlers [ GIF_A_D_REG_LABEL ] = & GSState : : GIFRegHandlerNull ;
2009-09-18 19:54:56 +00:00
}
else
{
2011-02-07 01:59:05 +00:00
m_fpGIFRegHandlers [ GIF_A_D_REG_SIGNAL ] = & GSState : : GIFRegHandlerSIGNAL ;
m_fpGIFRegHandlers [ GIF_A_D_REG_FINISH ] = & GSState : : GIFRegHandlerFINISH ;
m_fpGIFRegHandlers [ GIF_A_D_REG_LABEL ] = & GSState : : GIFRegHandlerLABEL ;
2010-08-17 04:38:49 +00:00
}
}
void GSState : : SetFrameSkip ( int skip )
{
if ( m_frameskip = = skip ) return ;
2011-02-07 01:59:05 +00:00
2010-08-17 04:38:49 +00:00
m_frameskip = skip ;
if ( skip )
2011-02-18 01:56:05 +00:00
{
2011-02-07 01:59:05 +00:00
m_fpGIFPackedRegHandlers [ GIF_REG_XYZF2 ] = & GSState : : GIFPackedRegHandlerNOP ;
m_fpGIFPackedRegHandlers [ GIF_REG_XYZ2 ] = & GSState : : GIFPackedRegHandlerNOP ;
m_fpGIFPackedRegHandlers [ GIF_REG_XYZF3 ] = & GSState : : GIFPackedRegHandlerNOP ;
m_fpGIFPackedRegHandlers [ GIF_REG_XYZ3 ] = & GSState : : GIFPackedRegHandlerNOP ;
m_fpGIFRegHandlers [ GIF_A_D_REG_XYZF2 ] = & GSState : : GIFRegHandlerNOP ;
m_fpGIFRegHandlers [ GIF_A_D_REG_XYZ2 ] = & GSState : : GIFRegHandlerNOP ;
m_fpGIFRegHandlers [ GIF_A_D_REG_XYZF3 ] = & GSState : : GIFRegHandlerNOP ;
m_fpGIFRegHandlers [ GIF_A_D_REG_XYZ3 ] = & GSState : : GIFRegHandlerNOP ;
2012-01-21 04:44:04 +00:00
m_fpGIFPackedRegHandlersC [ GIF_REG_STQRGBAXYZF2 ] = & GSState : : GIFPackedRegHandlerNOP ;
2012-01-21 12:34:36 +00:00
m_fpGIFPackedRegHandlersC [ GIF_REG_STQRGBAXYZ2 ] = & GSState : : GIFPackedRegHandlerNOP ;
2010-08-17 04:38:49 +00:00
}
else
{
2012-01-08 17:10:00 +00:00
UpdateVertexKick ( ) ;
2009-09-18 19:54:56 +00:00
}
}
2009-09-18 18:45:37 +00:00
2009-02-09 21:15:56 +00:00
void GSState : : Reset ( )
{
2012-04-17 17:55:51 +00:00
//printf("GSdx info: GS reset\n");
2012-01-18 11:47:31 +00:00
2012-01-19 04:53:36 +00:00
// FIXME: memset(m_mem.m_vm8, 0, m_mem.m_vmsize); // bios logo not shown cut in half after reset, missing graphics in GoW after first FMV
2011-02-07 01:59:05 +00:00
memset ( & m_path [ 0 ] , 0 , sizeof ( m_path [ 0 ] ) * countof ( m_path ) ) ;
2009-02-09 21:15:56 +00:00
memset ( & m_v , 0 , sizeof ( m_v ) ) ;
// PRIM = &m_env.PRIM;
// m_env.PRMODECONT.AC = 1;
m_env . Reset ( ) ;
2012-05-02 16:27:23 +00:00
PRIM = ! m_env . PRMODECONT . AC ? ( GIFRegPRIM * ) & m_env . PRMODE : & m_env . PRIM ;
UpdateContext ( ) ;
UpdateVertexKick ( ) ;
m_env . UpdateDIMX ( ) ;
for ( size_t i = 0 ; i < 2 ; i + + )
{
m_env . CTXT [ i ] . UpdateScissor ( ) ;
m_env . CTXT [ i ] . offset . fb = m_mem . GetOffset ( m_env . CTXT [ i ] . FRAME . Block ( ) , m_env . CTXT [ i ] . FRAME . FBW , m_env . CTXT [ i ] . FRAME . PSM ) ;
m_env . CTXT [ i ] . offset . zb = m_mem . GetOffset ( m_env . CTXT [ i ] . ZBUF . Block ( ) , m_env . CTXT [ i ] . FRAME . FBW , m_env . CTXT [ i ] . ZBUF . PSM ) ;
m_env . CTXT [ i ] . offset . tex = m_mem . GetOffset ( m_env . CTXT [ i ] . TEX0 . TBP0 , m_env . CTXT [ i ] . TEX0 . TBW , m_env . CTXT [ i ] . TEX0 . PSM ) ;
m_env . CTXT [ i ] . offset . fzb = m_mem . GetPixelOffset ( m_env . CTXT [ i ] . FRAME , m_env . CTXT [ i ] . ZBUF ) ;
m_env . CTXT [ i ] . offset . fzb4 = m_mem . GetPixelOffset4 ( m_env . CTXT [ i ] . FRAME , m_env . CTXT [ i ] . ZBUF ) ;
}
UpdateScissor ( ) ;
2012-01-05 02:40:24 +00:00
m_vertex . head = 0 ;
m_vertex . tail = 0 ;
2012-01-06 00:17:52 +00:00
m_vertex . next = 0 ;
2012-01-05 02:40:24 +00:00
m_index . tail = 0 ;
2012-02-08 16:57:14 +00:00
m_texflush = true ;
2009-02-09 21:15:56 +00:00
}
void GSState : : ResetHandlers ( )
{
2011-02-18 01:56:05 +00:00
for ( size_t i = 0 ; i < countof ( m_fpGIFPackedRegHandlers ) ; i + + )
2009-02-09 21:15:56 +00:00
{
m_fpGIFPackedRegHandlers [ i ] = & GSState : : GIFPackedRegHandlerNull ;
}
2011-02-18 01:56:05 +00:00
m_fpGIFPackedRegHandlers [ GIF_REG_PRIM ] = ( GIFPackedRegHandler ) ( GIFRegHandler ) & GSState : : GIFRegHandlerPRIM ;
2011-02-07 01:59:05 +00:00
m_fpGIFPackedRegHandlers [ GIF_REG_RGBA ] = & GSState : : GIFPackedRegHandlerRGBA ;
m_fpGIFPackedRegHandlers [ GIF_REG_STQ ] = & GSState : : GIFPackedRegHandlerSTQ ;
GSdx:
- changed the KH2 fix in GetTextureMinMax to my taste, should give the same results, when the used texture rect is to the left/above the clamped area, it returns [min, min+1], and [max-1, max] for right/below
- m_mem.m_clut.Read32 was returned to its original place from GetAlphaMinMax
- UserHacks_WildHack was moved up to GSState, special UV handlers are only used when this setting is active
- updated xbyak to the latest available (avx2 seems incomplete, the 256-bit promoted old instructions are missing)
- changed vtune's include path to the 2013 edition
Some other not yet commited changes from a year ago:
- WriteImageX overflow crash-fix
- moved colclamp after dithering (sw mode), it makes more sense, no visible changes noticed
- Gif_Tag::analyzeTag(), there was a conditional I didn't like, split the loop into two parts
git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5649 96395faa-99c1-11dd-bbfe-3dabce05a288
2013-06-06 11:36:01 +00:00
m_fpGIFPackedRegHandlers [ GIF_REG_UV ] = ! UserHacks_WildHack ? & GSState : : GIFPackedRegHandlerUV : & GSState : : GIFPackedRegHandlerUV_Hack ;
2011-02-18 01:56:05 +00:00
m_fpGIFPackedRegHandlers [ GIF_REG_TEX0_1 ] = ( GIFPackedRegHandler ) ( GIFRegHandler ) & GSState : : GIFRegHandlerTEX0 < 0 > ;
m_fpGIFPackedRegHandlers [ GIF_REG_TEX0_2 ] = ( GIFPackedRegHandler ) ( GIFRegHandler ) & GSState : : GIFRegHandlerTEX0 < 1 > ;
m_fpGIFPackedRegHandlers [ GIF_REG_CLAMP_1 ] = ( GIFPackedRegHandler ) ( GIFRegHandler ) & GSState : : GIFRegHandlerCLAMP < 0 > ;
m_fpGIFPackedRegHandlers [ GIF_REG_CLAMP_2 ] = ( GIFPackedRegHandler ) ( GIFRegHandler ) & GSState : : GIFRegHandlerCLAMP < 1 > ;
2011-02-07 01:59:05 +00:00
m_fpGIFPackedRegHandlers [ GIF_REG_FOG ] = & GSState : : GIFPackedRegHandlerFOG ;
m_fpGIFPackedRegHandlers [ GIF_REG_A_D ] = & GSState : : GIFPackedRegHandlerA_D ;
m_fpGIFPackedRegHandlers [ GIF_REG_NOP ] = & GSState : : GIFPackedRegHandlerNOP ;
2011-02-18 01:56:05 +00:00
2012-01-08 17:10:00 +00:00
# define SetHandlerXYZ(P) \
m_fpGIFPackedRegHandlerXYZ [ P ] [ 0 ] = & GSState : : GIFPackedRegHandlerXYZF2 < P , 0 > ; \
m_fpGIFPackedRegHandlerXYZ [ P ] [ 1 ] = & GSState : : GIFPackedRegHandlerXYZF2 < P , 1 > ; \
m_fpGIFPackedRegHandlerXYZ [ P ] [ 2 ] = & GSState : : GIFPackedRegHandlerXYZ2 < P , 0 > ; \
m_fpGIFPackedRegHandlerXYZ [ P ] [ 3 ] = & GSState : : GIFPackedRegHandlerXYZ2 < P , 1 > ; \
m_fpGIFRegHandlerXYZ [ P ] [ 0 ] = & GSState : : GIFRegHandlerXYZF2 < P , 0 > ; \
m_fpGIFRegHandlerXYZ [ P ] [ 1 ] = & GSState : : GIFRegHandlerXYZF2 < P , 1 > ; \
m_fpGIFRegHandlerXYZ [ P ] [ 2 ] = & GSState : : GIFRegHandlerXYZ2 < P , 0 > ; \
m_fpGIFRegHandlerXYZ [ P ] [ 3 ] = & GSState : : GIFRegHandlerXYZ2 < P , 1 > ; \
2012-01-18 11:47:31 +00:00
m_fpGIFPackedRegHandlerSTQRGBAXYZF2 [ P ] = & GSState : : GIFPackedRegHandlerSTQRGBAXYZF2 < P > ; \
2012-01-21 12:34:36 +00:00
m_fpGIFPackedRegHandlerSTQRGBAXYZ2 [ P ] = & GSState : : GIFPackedRegHandlerSTQRGBAXYZ2 < P > ; \
2012-01-08 17:10:00 +00:00
SetHandlerXYZ ( GS_POINTLIST ) ;
SetHandlerXYZ ( GS_LINELIST ) ;
SetHandlerXYZ ( GS_LINESTRIP ) ;
SetHandlerXYZ ( GS_TRIANGLELIST ) ;
SetHandlerXYZ ( GS_TRIANGLESTRIP ) ;
SetHandlerXYZ ( GS_TRIANGLEFAN ) ;
SetHandlerXYZ ( GS_SPRITE ) ;
SetHandlerXYZ ( GS_INVALID ) ;
2011-02-18 01:56:05 +00:00
for ( size_t i = 0 ; i < countof ( m_fpGIFRegHandlers ) ; i + + )
2009-02-09 21:15:56 +00:00
{
m_fpGIFRegHandlers [ i ] = & GSState : : GIFRegHandlerNull ;
}
2011-02-07 01:59:05 +00:00
m_fpGIFRegHandlers [ GIF_A_D_REG_PRIM ] = & GSState : : GIFRegHandlerPRIM ;
m_fpGIFRegHandlers [ GIF_A_D_REG_RGBAQ ] = & GSState : : GIFRegHandlerRGBAQ ;
m_fpGIFRegHandlers [ GIF_A_D_REG_ST ] = & GSState : : GIFRegHandlerST ;
GSdx:
- changed the KH2 fix in GetTextureMinMax to my taste, should give the same results, when the used texture rect is to the left/above the clamped area, it returns [min, min+1], and [max-1, max] for right/below
- m_mem.m_clut.Read32 was returned to its original place from GetAlphaMinMax
- UserHacks_WildHack was moved up to GSState, special UV handlers are only used when this setting is active
- updated xbyak to the latest available (avx2 seems incomplete, the 256-bit promoted old instructions are missing)
- changed vtune's include path to the 2013 edition
Some other not yet commited changes from a year ago:
- WriteImageX overflow crash-fix
- moved colclamp after dithering (sw mode), it makes more sense, no visible changes noticed
- Gif_Tag::analyzeTag(), there was a conditional I didn't like, split the loop into two parts
git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5649 96395faa-99c1-11dd-bbfe-3dabce05a288
2013-06-06 11:36:01 +00:00
m_fpGIFRegHandlers [ GIF_A_D_REG_UV ] = ! UserHacks_WildHack ? & GSState : : GIFRegHandlerUV : & GSState : : GIFRegHandlerUV_Hack ;
2011-02-07 01:59:05 +00:00
m_fpGIFRegHandlers [ GIF_A_D_REG_TEX0_1 ] = & GSState : : GIFRegHandlerTEX0 < 0 > ;
m_fpGIFRegHandlers [ GIF_A_D_REG_TEX0_2 ] = & GSState : : GIFRegHandlerTEX0 < 1 > ;
m_fpGIFRegHandlers [ GIF_A_D_REG_CLAMP_1 ] = & GSState : : GIFRegHandlerCLAMP < 0 > ;
m_fpGIFRegHandlers [ GIF_A_D_REG_CLAMP_2 ] = & GSState : : GIFRegHandlerCLAMP < 1 > ;
m_fpGIFRegHandlers [ GIF_A_D_REG_FOG ] = & GSState : : GIFRegHandlerFOG ;
m_fpGIFRegHandlers [ GIF_A_D_REG_NOP ] = & GSState : : GIFRegHandlerNOP ;
m_fpGIFRegHandlers [ GIF_A_D_REG_TEX1_1 ] = & GSState : : GIFRegHandlerTEX1 < 0 > ;
m_fpGIFRegHandlers [ GIF_A_D_REG_TEX1_2 ] = & GSState : : GIFRegHandlerTEX1 < 1 > ;
m_fpGIFRegHandlers [ GIF_A_D_REG_TEX2_1 ] = & GSState : : GIFRegHandlerTEX2 < 0 > ;
m_fpGIFRegHandlers [ GIF_A_D_REG_TEX2_2 ] = & GSState : : GIFRegHandlerTEX2 < 1 > ;
m_fpGIFRegHandlers [ GIF_A_D_REG_XYOFFSET_1 ] = & GSState : : GIFRegHandlerXYOFFSET < 0 > ;
m_fpGIFRegHandlers [ GIF_A_D_REG_XYOFFSET_2 ] = & GSState : : GIFRegHandlerXYOFFSET < 1 > ;
m_fpGIFRegHandlers [ GIF_A_D_REG_PRMODECONT ] = & GSState : : GIFRegHandlerPRMODECONT ;
m_fpGIFRegHandlers [ GIF_A_D_REG_PRMODE ] = & GSState : : GIFRegHandlerPRMODE ;
m_fpGIFRegHandlers [ GIF_A_D_REG_TEXCLUT ] = & GSState : : GIFRegHandlerTEXCLUT ;
m_fpGIFRegHandlers [ GIF_A_D_REG_SCANMSK ] = & GSState : : GIFRegHandlerSCANMSK ;
m_fpGIFRegHandlers [ GIF_A_D_REG_MIPTBP1_1 ] = & GSState : : GIFRegHandlerMIPTBP1 < 0 > ;
m_fpGIFRegHandlers [ GIF_A_D_REG_MIPTBP1_2 ] = & GSState : : GIFRegHandlerMIPTBP1 < 1 > ;
m_fpGIFRegHandlers [ GIF_A_D_REG_MIPTBP2_1 ] = & GSState : : GIFRegHandlerMIPTBP2 < 0 > ;
m_fpGIFRegHandlers [ GIF_A_D_REG_MIPTBP2_2 ] = & GSState : : GIFRegHandlerMIPTBP2 < 1 > ;
m_fpGIFRegHandlers [ GIF_A_D_REG_TEXA ] = & GSState : : GIFRegHandlerTEXA ;
m_fpGIFRegHandlers [ GIF_A_D_REG_FOGCOL ] = & GSState : : GIFRegHandlerFOGCOL ;
m_fpGIFRegHandlers [ GIF_A_D_REG_TEXFLUSH ] = & GSState : : GIFRegHandlerTEXFLUSH ;
m_fpGIFRegHandlers [ GIF_A_D_REG_SCISSOR_1 ] = & GSState : : GIFRegHandlerSCISSOR < 0 > ;
m_fpGIFRegHandlers [ GIF_A_D_REG_SCISSOR_2 ] = & GSState : : GIFRegHandlerSCISSOR < 1 > ;
m_fpGIFRegHandlers [ GIF_A_D_REG_ALPHA_1 ] = & GSState : : GIFRegHandlerALPHA < 0 > ;
m_fpGIFRegHandlers [ GIF_A_D_REG_ALPHA_2 ] = & GSState : : GIFRegHandlerALPHA < 1 > ;
m_fpGIFRegHandlers [ GIF_A_D_REG_DIMX ] = & GSState : : GIFRegHandlerDIMX ;
m_fpGIFRegHandlers [ GIF_A_D_REG_DTHE ] = & GSState : : GIFRegHandlerDTHE ;
m_fpGIFRegHandlers [ GIF_A_D_REG_COLCLAMP ] = & GSState : : GIFRegHandlerCOLCLAMP ;
m_fpGIFRegHandlers [ GIF_A_D_REG_TEST_1 ] = & GSState : : GIFRegHandlerTEST < 0 > ;
m_fpGIFRegHandlers [ GIF_A_D_REG_TEST_2 ] = & GSState : : GIFRegHandlerTEST < 1 > ;
m_fpGIFRegHandlers [ GIF_A_D_REG_PABE ] = & GSState : : GIFRegHandlerPABE ;
m_fpGIFRegHandlers [ GIF_A_D_REG_FBA_1 ] = & GSState : : GIFRegHandlerFBA < 0 > ;
m_fpGIFRegHandlers [ GIF_A_D_REG_FBA_2 ] = & GSState : : GIFRegHandlerFBA < 1 > ;
m_fpGIFRegHandlers [ GIF_A_D_REG_FRAME_1 ] = & GSState : : GIFRegHandlerFRAME < 0 > ;
m_fpGIFRegHandlers [ GIF_A_D_REG_FRAME_2 ] = & GSState : : GIFRegHandlerFRAME < 1 > ;
m_fpGIFRegHandlers [ GIF_A_D_REG_ZBUF_1 ] = & GSState : : GIFRegHandlerZBUF < 0 > ;
m_fpGIFRegHandlers [ GIF_A_D_REG_ZBUF_2 ] = & GSState : : GIFRegHandlerZBUF < 1 > ;
m_fpGIFRegHandlers [ GIF_A_D_REG_BITBLTBUF ] = & GSState : : GIFRegHandlerBITBLTBUF ;
m_fpGIFRegHandlers [ GIF_A_D_REG_TRXPOS ] = & GSState : : GIFRegHandlerTRXPOS ;
m_fpGIFRegHandlers [ GIF_A_D_REG_TRXREG ] = & GSState : : GIFRegHandlerTRXREG ;
m_fpGIFRegHandlers [ GIF_A_D_REG_TRXDIR ] = & GSState : : GIFRegHandlerTRXDIR ;
m_fpGIFRegHandlers [ GIF_A_D_REG_HWREG ] = & GSState : : GIFRegHandlerHWREG ;
SetMultithreaded ( m_mt ) ;
2009-02-09 21:15:56 +00:00
}
2009-05-14 16:41:52 +00:00
GSVector4i GSState : : GetDisplayRect ( int i )
2009-02-09 21:15:56 +00:00
{
2009-05-14 16:41:52 +00:00
if ( i < 0 ) i = IsEnabled ( 1 ) ? 1 : 0 ;
2016-01-19 19:00:19 +00:00
int height = ( m_regs - > DISP [ i ] . DISPLAY . DH + 1 ) / ( m_regs - > DISP [ i ] . DISPLAY . MAGV + 1 ) ;
int width = ( m_regs - > DISP [ i ] . DISPLAY . DW + 1 ) / ( m_regs - > DISP [ i ] . DISPLAY . MAGH + 1 ) ;
2009-05-14 16:41:52 +00:00
GSVector4i r ;
2009-02-09 21:15:56 +00:00
2015-06-06 19:24:10 +00:00
//Some games (such as Pool Paradise) use alternate line reading and provide a massive height which is really half.
2016-01-25 12:43:37 +00:00
if ( height > 640 & & ! Vmode_VESA )
2015-06-06 19:24:10 +00:00
{
height / = 2 ;
}
2009-05-14 16:41:52 +00:00
r . left = m_regs - > DISP [ i ] . DISPLAY . DX / ( m_regs - > DISP [ i ] . DISPLAY . MAGH + 1 ) ;
r . top = m_regs - > DISP [ i ] . DISPLAY . DY / ( m_regs - > DISP [ i ] . DISPLAY . MAGV + 1 ) ;
2016-01-19 19:00:19 +00:00
r . right = r . left + width ;
r . bottom = r . top + height ;
2016-01-19 22:59:23 +00:00
// Useful for debugging games:
//printf("DW: %d , DH: %d , left: %d , right: %d , top: %d , down: %d , MAGH: %d , MAGV: %d\n", m_regs->DISP[i].DISPLAY.DW, m_regs->DISP[i].DISPLAY.DH, r.left, r.right, r.top, r.bottom , m_regs->DISP[i].DISPLAY.MAGH,m_regs->DISP[i].DISPLAY.MAGV);
2009-05-14 16:41:52 +00:00
return r ;
2009-02-09 21:15:56 +00:00
}
2012-01-18 15:44:14 +00:00
// There's a problem when games expand/shrink and relocate the visible area since GSdx doesn't support
2015-12-01 20:36:23 +00:00
// moving the output area. (Disgaea 2 intro FMV when upscaling is used).
2009-05-14 16:41:52 +00:00
GSVector4i GSState : : GetFrameRect ( int i )
2009-02-09 21:15:56 +00:00
{
2015-12-01 20:36:23 +00:00
if ( i < 0 ) i = IsEnabled ( 1 ) ? 1 : 0 ;
2009-02-09 21:15:56 +00:00
2009-05-14 16:41:52 +00:00
GSVector4i r = GetDisplayRect ( i ) ;
2009-02-09 21:15:56 +00:00
2009-05-14 16:41:52 +00:00
int w = r . width ( ) ;
int h = r . height ( ) ;
2009-02-09 21:15:56 +00:00
2016-01-10 08:47:04 +00:00
// NTSC: Saturate higher height values for games which have CRTC width lower than 640.
// Some NTSC mode games request higher height values for accurate display size / position when width is 640
// Testcases : PS logo (640x512) , Resident Evil:CVX (640x480). potentially more test cases...
2016-01-25 12:43:37 +00:00
if ( Vmode_NTSC & & h > 448 & & w < 640 )
2015-11-08 12:59:11 +00:00
h = 448 ;
2009-02-09 21:15:56 +00:00
2016-01-10 08:47:04 +00:00
if ( m_regs - > SMODE2 . INT & & m_regs - > SMODE2 . FFMD & & h > 1 )
h > > = 1 ;
2015-12-01 20:36:23 +00:00
//watch Disgaea2 FMV borders when changing
2009-05-14 16:41:52 +00:00
r . left = m_regs - > DISP [ i ] . DISPFB . DBX ;
r . top = m_regs - > DISP [ i ] . DISPFB . DBY ;
r . right = r . left + w ;
r . bottom = r . top + h ;
2015-12-01 20:36:23 +00:00
2012-01-18 15:44:14 +00:00
/*static GSVector4i old_r = (GSVector4i) 0;
if ( ( old_r . left ! = r . left ) | | ( old_r . right ! = r . right ) | | ( old_r . top ! = r . top ) | | ( old_r . right ! = r . right ) ) {
2015-12-01 20:36:23 +00:00
printf ( " w %d h %d left %d top %d right %d bottom %d \n " , w , h , r . left , r . top , r . right , r . bottom ) ;
2012-01-18 15:44:14 +00:00
}
old_r = r ; */
2009-05-14 16:41:52 +00:00
return r ;
2009-02-09 21:15:56 +00:00
}
2009-05-20 15:35:31 +00:00
GSVector2i GSState : : GetDeviceSize ( int i )
2009-02-09 21:15:56 +00:00
{
2012-01-21 12:34:36 +00:00
// TODO: return (m_regs->SMODE1.CMOD & 1) ? GSVector2i(640, 576) : GSVector2i(640, 480);
2009-02-09 21:15:56 +00:00
// TODO: other params of SMODE1 should affect the true device display size
// TODO2: pal games at 60Hz
2009-05-14 16:41:52 +00:00
if ( i < 0 ) i = IsEnabled ( 1 ) ? 1 : 0 ;
GSVector4i r = GetDisplayRect ( i ) ;
2009-02-09 21:15:56 +00:00
2009-05-14 16:41:52 +00:00
int w = r . width ( ) ;
int h = r . height ( ) ;
2009-10-23 14:32:01 +00:00
/*if(h == 2 * 416 || h == 2 * 448 || h == 2 * 512)
2009-02-09 21:15:56 +00:00
{
2009-05-14 16:41:52 +00:00
h / = 2 ;
2009-02-09 21:15:56 +00:00
}
else
{
2009-05-14 16:41:52 +00:00
h = ( m_regs - > SMODE1 . CMOD & 1 ) ? 512 : 448 ;
2009-10-23 14:32:01 +00:00
} */
2010-04-25 00:31:27 +00:00
2009-10-23 14:32:01 +00:00
//Fixme : Just slightly better than the hack above
2011-06-25 16:53:13 +00:00
if ( m_regs - > SMODE2 . INT & & m_regs - > SMODE2 . FFMD & & h > 1 )
2011-04-25 13:47:29 +00:00
{
if ( IsEnabled ( 0 ) | | IsEnabled ( 1 ) )
{
h > > = 1 ;
}
}
//Fixme: These games elude the code above, worked with the old hack
else if ( m_game . title = = CRC : : SilentHill2 | | m_game . title = = CRC : : SilentHill3 )
{
h / = 2 ;
2009-02-09 21:15:56 +00:00
}
2009-05-20 15:35:31 +00:00
return GSVector2i ( w , h ) ;
2009-02-09 21:15:56 +00:00
}
bool GSState : : IsEnabled ( int i )
{
ASSERT ( i > = 0 & & i < 2 ) ;
2010-04-25 00:31:27 +00:00
if ( i = = 0 & & m_regs - > PMODE . EN1 )
2009-02-09 21:15:56 +00:00
{
2009-03-31 03:19:21 +00:00
return m_regs - > DISP [ 0 ] . DISPLAY . DW | | m_regs - > DISP [ 0 ] . DISPLAY . DH ;
2009-02-09 21:15:56 +00:00
}
2010-04-25 00:31:27 +00:00
else if ( i = = 1 & & m_regs - > PMODE . EN2 )
2009-02-09 21:15:56 +00:00
{
2009-03-31 03:19:21 +00:00
return m_regs - > DISP [ 1 ] . DISPLAY . DW | | m_regs - > DISP [ 1 ] . DISPLAY . DH ;
2009-02-09 21:15:56 +00:00
}
return false ;
}
2015-09-18 01:07:58 +00:00
float GSState : : GetTvRefreshRate ( )
2009-02-09 21:15:56 +00:00
{
2016-01-10 08:47:04 +00:00
// TODO: Frequencies for VESA / DTV : http://users.neoscientists.org/~blue/ps2videomodes.txt
// SMODE1 PLL Loop divider (LC) could be used for detection of other video modes. CMOD's only useful for NTSC/PAL.(2/3)
2016-01-25 12:43:37 +00:00
return ( Vmode_PAL ) ? 50 : ( 60 / 1.001f ) ;
2009-02-09 21:15:56 +00:00
}
// GIFPackedRegHandler*
2012-01-08 17:10:00 +00:00
void GSState : : GIFPackedRegHandlerNull ( const GIFPackedReg * RESTRICT r )
2009-02-09 21:15:56 +00:00
{
// ASSERT(0);
}
2012-01-08 17:10:00 +00:00
void GSState : : GIFPackedRegHandlerRGBA ( const GIFPackedReg * RESTRICT r )
2009-02-09 21:15:56 +00:00
{
# if _M_SSE >= 0x301
GSVector4i mask = GSVector4i : : load ( 0x0c080400 ) ;
GSVector4i v = GSVector4i : : load < false > ( r ) . shuffle8 ( mask ) ;
2011-02-07 01:59:05 +00:00
2009-05-14 16:41:52 +00:00
m_v . RGBAQ . u32 [ 0 ] = ( uint32 ) GSVector4i : : store ( v ) ;
2009-02-09 21:15:56 +00:00
2012-01-21 04:44:04 +00:00
# else
2009-02-09 21:15:56 +00:00
GSVector4i v = GSVector4i : : load < false > ( r ) & GSVector4i : : x000000ff ( ) ;
2011-02-07 01:59:05 +00:00
2009-05-14 16:41:52 +00:00
m_v . RGBAQ . u32 [ 0 ] = v . rgba32 ( ) ;
2009-02-09 21:15:56 +00:00
# endif
2012-01-23 04:11:24 +00:00
m_v . RGBAQ . Q = m_q ;
2009-02-09 21:15:56 +00:00
}
2012-01-08 17:10:00 +00:00
void GSState : : GIFPackedRegHandlerSTQ ( const GIFPackedReg * RESTRICT r )
2009-02-09 21:15:56 +00:00
{
2015-08-04 01:34:46 +00:00
GSVector4i st = GSVector4i : : loadl ( & r - > u64 [ 0 ] ) ;
2012-02-14 19:26:04 +00:00
GSVector4i q = GSVector4i : : loadl ( & r - > u64 [ 1 ] ) ;
2009-02-09 21:15:56 +00:00
2015-08-04 01:34:46 +00:00
GSVector4i : : storel ( & m_v . ST , st ) ;
2009-02-09 21:15:56 +00:00
2015-08-04 01:34:46 +00:00
q = q . blend8 ( GSVector4i : : cast ( GSVector4 : : m_one ) , q = = GSVector4i : : zero ( ) ) ; // character shadow in Vexx, q = 0 (st also 0 on the first 16 vertices), setting it to 1.0f to avoid div by zero later
2012-02-14 19:26:04 +00:00
* ( int * ) & m_q = GSVector4i : : store ( q ) ;
2015-08-03 09:26:48 +00:00
2015-07-19 14:24:55 +00:00
ASSERT ( ! std : : isnan ( m_q ) ) ; // See GIFRegHandlerRGBAQ
2015-07-20 17:34:42 +00:00
ASSERT ( ! std : : isnan ( m_v . ST . S ) ) ; // See GIFRegHandlerRGBAQ
ASSERT ( ! std : : isnan ( m_v . ST . T ) ) ; // See GIFRegHandlerRGBAQ
2011-05-09 01:36:57 +00:00
# ifdef Offset_ST
GIFRegTEX0 TEX0 = m_context - > TEX0 ;
m_v . ST . S - = 0.02f * m_q / ( 1 < < TEX0 . TW ) ;
m_v . ST . T - = 0.02f * m_q / ( 1 < < TEX0 . TH ) ;
# endif
2009-02-09 21:15:56 +00:00
}
2012-01-08 17:10:00 +00:00
void GSState : : GIFPackedRegHandlerUV ( const GIFPackedReg * RESTRICT r )
2009-02-09 21:15:56 +00:00
{
GSVector4i v = GSVector4i : : loadl ( r ) & GSVector4i : : x00003fff ( ) ;
GSdx:
- changed the KH2 fix in GetTextureMinMax to my taste, should give the same results, when the used texture rect is to the left/above the clamped area, it returns [min, min+1], and [max-1, max] for right/below
- m_mem.m_clut.Read32 was returned to its original place from GetAlphaMinMax
- UserHacks_WildHack was moved up to GSState, special UV handlers are only used when this setting is active
- updated xbyak to the latest available (avx2 seems incomplete, the 256-bit promoted old instructions are missing)
- changed vtune's include path to the 2013 edition
Some other not yet commited changes from a year ago:
- WriteImageX overflow crash-fix
- moved colclamp after dithering (sw mode), it makes more sense, no visible changes noticed
- Gif_Tag::analyzeTag(), there was a conditional I didn't like, split the loop into two parts
git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5649 96395faa-99c1-11dd-bbfe-3dabce05a288
2013-06-06 11:36:01 +00:00
m_v . UV = ( uint32 ) GSVector4i : : store ( v . ps32 ( v ) ) ;
}
void GSState : : GIFPackedRegHandlerUV_Hack ( const GIFPackedReg * RESTRICT r )
{
GSVector4i v = GSVector4i : : loadl ( r ) & GSVector4i : : x00003fff ( ) ;
2012-01-08 17:10:00 +00:00
m_v . UV = ( uint32 ) GSVector4i : : store ( v . ps32 ( v ) ) ;
2012-03-08 17:18:22 +00:00
isPackedUV_HackFlag = true ;
2009-02-09 21:15:56 +00:00
}
2012-01-08 17:10:00 +00:00
template < uint32 prim , uint32 adc >
void GSState : : GIFPackedRegHandlerXYZF2 ( const GIFPackedReg * RESTRICT r )
2009-02-09 21:15:56 +00:00
{
2012-01-08 17:10:00 +00:00
/*
2009-02-09 21:15:56 +00:00
m_v . XYZ . X = r - > XYZF2 . X ;
m_v . XYZ . Y = r - > XYZF2 . Y ;
m_v . XYZ . Z = r - > XYZF2 . Z ;
2012-01-08 17:10:00 +00:00
m_v . FOG = r - > XYZF2 . F ;
*/
GSVector4i xy = GSVector4i : : loadl ( & r - > u64 [ 0 ] ) ;
GSVector4i zf = GSVector4i : : loadl ( & r - > u64 [ 1 ] ) ;
2013-06-17 04:11:10 +00:00
xy = xy . upl16 ( xy . srl < 4 > ( ) ) . upl32 ( GSVector4i : : load ( ( int ) m_v . UV ) ) ;
2012-01-08 17:10:00 +00:00
zf = zf . srl32 ( 4 ) & GSVector4i : : x00ffffff ( ) . upl32 ( GSVector4i : : x000000ff ( ) ) ;
2009-02-09 21:15:56 +00:00
2012-01-08 17:10:00 +00:00
m_v . m [ 1 ] = xy . upl32 ( zf ) ;
VertexKick < prim > ( adc ? 1 : r - > XYZF2 . Skip ( ) ) ;
2009-02-09 21:15:56 +00:00
}
2012-01-08 17:10:00 +00:00
template < uint32 prim , uint32 adc >
void GSState : : GIFPackedRegHandlerXYZ2 ( const GIFPackedReg * RESTRICT r )
2009-02-09 21:15:56 +00:00
{
2012-01-08 17:10:00 +00:00
/*
2009-02-09 21:15:56 +00:00
m_v . XYZ . X = r - > XYZ2 . X ;
m_v . XYZ . Y = r - > XYZ2 . Y ;
m_v . XYZ . Z = r - > XYZ2 . Z ;
2012-01-08 17:10:00 +00:00
*/
GSVector4i xy = GSVector4i : : loadl ( & r - > u64 [ 0 ] ) ;
GSVector4i z = GSVector4i : : loadl ( & r - > u64 [ 1 ] ) ;
GSVector4i xyz = xy . upl16 ( xy . srl < 4 > ( ) ) . upl32 ( z ) ;
2009-02-09 21:15:56 +00:00
2012-01-08 17:10:00 +00:00
m_v . m [ 1 ] = xyz . upl64 ( GSVector4i : : loadl ( & m_v . UV ) ) ;
VertexKick < prim > ( adc ? 1 : r - > XYZ2 . Skip ( ) ) ;
2009-02-09 21:15:56 +00:00
}
2012-01-08 17:10:00 +00:00
void GSState : : GIFPackedRegHandlerFOG ( const GIFPackedReg * RESTRICT r )
2009-02-09 21:15:56 +00:00
{
2012-01-08 17:10:00 +00:00
m_v . FOG = r - > FOG . F ;
2009-02-09 21:15:56 +00:00
}
2012-01-08 17:10:00 +00:00
void GSState : : GIFPackedRegHandlerA_D ( const GIFPackedReg * RESTRICT r )
2009-02-09 21:15:56 +00:00
{
2009-05-14 16:41:52 +00:00
( this - > * m_fpGIFRegHandlers [ r - > A_D . ADDR ] ) ( & r - > r ) ;
2009-02-09 21:15:56 +00:00
}
2012-01-08 17:10:00 +00:00
void GSState : : GIFPackedRegHandlerNOP ( const GIFPackedReg * RESTRICT r )
2009-02-09 21:15:56 +00:00
{
}
2012-01-18 11:47:31 +00:00
template < uint32 prim >
void GSState : : GIFPackedRegHandlerSTQRGBAXYZF2 ( const GIFPackedReg * RESTRICT r , uint32 size )
{
ASSERT ( size > 0 & & size % 3 = = 0 ) ;
const GIFPackedReg * RESTRICT r_end = r + size ;
while ( r < r_end )
{
2015-08-04 01:34:46 +00:00
GSVector4i st = GSVector4i : : loadl ( & r [ 0 ] . u64 [ 0 ] ) ;
2012-01-18 11:47:31 +00:00
GSVector4i q = GSVector4i : : loadl ( & r [ 0 ] . u64 [ 1 ] ) ;
GSVector4i rgba = ( GSVector4i : : load < false > ( & r [ 1 ] ) & GSVector4i : : x000000ff ( ) ) . ps32 ( ) . pu16 ( ) ;
2013-06-17 04:11:10 +00:00
/*
GSVector4i rg = GSVector4i : : loadl ( & r [ 1 ] . u64 [ 0 ] ) ;
GSVector4i ba = GSVector4i : : loadl ( & r [ 1 ] . u64 [ 1 ] ) ;
GSVector4i rbga = rg . upl8 ( ba ) ;
GSVector4i rgba = rbga . upl8 ( rbga . zzzz ( ) ) ;
*/
2012-02-14 19:26:04 +00:00
q = q . blend8 ( GSVector4i : : cast ( GSVector4 : : m_one ) , q = = GSVector4i : : zero ( ) ) ; // see GIFPackedRegHandlerSTQ
2015-08-04 01:34:46 +00:00
m_v . m [ 0 ] = st . upl64 ( rgba . upl32 ( q ) ) ; // TODO: only store the last one
2012-01-18 11:47:31 +00:00
GSVector4i xy = GSVector4i : : loadl ( & r [ 2 ] . u64 [ 0 ] ) ;
GSVector4i zf = GSVector4i : : loadl ( & r [ 2 ] . u64 [ 1 ] ) ;
2013-06-17 04:11:10 +00:00
xy = xy . upl16 ( xy . srl < 4 > ( ) ) . upl32 ( GSVector4i : : load ( ( int ) m_v . UV ) ) ;
2012-01-18 11:47:31 +00:00
zf = zf . srl32 ( 4 ) & GSVector4i : : x00ffffff ( ) . upl32 ( GSVector4i : : x000000ff ( ) ) ;
2012-01-21 04:44:04 +00:00
m_v . m [ 1 ] = xy . upl32 ( zf ) ; // TODO: only store the last one
2012-01-18 11:47:31 +00:00
VertexKick < prim > ( r [ 2 ] . XYZF2 . Skip ( ) ) ;
r + = 3 ;
}
2012-01-23 04:11:24 +00:00
m_q = r [ - 3 ] . STQ . Q ; // remember the last one, STQ outputs this to the temp Q each time
2012-01-21 04:44:04 +00:00
}
2012-01-18 11:47:31 +00:00
2012-01-21 12:34:36 +00:00
template < uint32 prim >
void GSState : : GIFPackedRegHandlerSTQRGBAXYZ2 ( const GIFPackedReg * RESTRICT r , uint32 size )
{
ASSERT ( size > 0 & & size % 3 = = 0 ) ;
const GIFPackedReg * RESTRICT r_end = r + size ;
while ( r < r_end )
{
2015-08-04 01:34:46 +00:00
GSVector4i st = GSVector4i : : loadl ( & r [ 0 ] . u64 [ 0 ] ) ;
2012-01-21 12:34:36 +00:00
GSVector4i q = GSVector4i : : loadl ( & r [ 0 ] . u64 [ 1 ] ) ;
GSVector4i rgba = ( GSVector4i : : load < false > ( & r [ 1 ] ) & GSVector4i : : x000000ff ( ) ) . ps32 ( ) . pu16 ( ) ;
2013-06-17 04:11:10 +00:00
/*
GSVector4i rg = GSVector4i : : loadl ( & r [ 1 ] . u64 [ 0 ] ) ;
GSVector4i ba = GSVector4i : : loadl ( & r [ 1 ] . u64 [ 1 ] ) ;
GSVector4i rbga = rg . upl8 ( ba ) ;
GSVector4i rgba = rbga . upl8 ( rbga . zzzz ( ) ) ;
*/
2012-02-14 19:26:04 +00:00
q = q . blend8 ( GSVector4i : : cast ( GSVector4 : : m_one ) , q = = GSVector4i : : zero ( ) ) ; // see GIFPackedRegHandlerSTQ
2015-08-04 01:34:46 +00:00
m_v . m [ 0 ] = st . upl64 ( rgba . upl32 ( q ) ) ; // TODO: only store the last one
2012-01-21 12:34:36 +00:00
GSVector4i xy = GSVector4i : : loadl ( & r [ 2 ] . u64 [ 0 ] ) ;
GSVector4i z = GSVector4i : : loadl ( & r [ 2 ] . u64 [ 1 ] ) ;
GSVector4i xyz = xy . upl16 ( xy . srl < 4 > ( ) ) . upl32 ( z ) ;
m_v . m [ 1 ] = xyz . upl64 ( GSVector4i : : loadl ( & m_v . UV ) ) ; // TODO: only store the last one
VertexKick < prim > ( r [ 2 ] . XYZ2 . Skip ( ) ) ;
r + = 3 ;
}
2012-01-23 04:11:24 +00:00
m_q = r [ - 3 ] . STQ . Q ; // remember the last one, STQ outputs this to the temp Q each time
2012-01-21 12:34:36 +00:00
}
2012-01-21 04:44:04 +00:00
void GSState : : GIFPackedRegHandlerNOP ( const GIFPackedReg * RESTRICT r , uint32 size )
{
2012-01-18 11:47:31 +00:00
}
2009-02-09 21:15:56 +00:00
// GIFRegHandler*
2011-12-20 14:33:28 +00:00
void GSState : : GIFRegHandlerNull ( const GIFReg * RESTRICT r )
2009-02-09 21:15:56 +00:00
{
// ASSERT(0);
}
2012-01-27 11:56:49 +00:00
__forceinline void GSState : : ApplyPRIM ( uint32 prim )
2009-02-09 21:15:56 +00:00
{
// ASSERT(r->PRIM.PRIM < 7);
2012-01-27 11:56:49 +00:00
if ( GSUtil : : GetPrimClass ( m_env . PRIM . PRIM ) = = GSUtil : : GetPrimClass ( prim & 7 ) ) // NOTE: assume strips/fans are converted to lists
2009-02-09 21:15:56 +00:00
{
2012-01-27 11:56:49 +00:00
if ( ( m_env . PRIM . u32 [ 0 ] ^ prim ) & 0x7f8 ) // all fields except PRIM
2009-02-09 21:15:56 +00:00
{
Flush ( ) ;
}
}
else
{
Flush ( ) ;
}
2012-01-27 11:56:49 +00:00
m_env . PRIM . u32 [ 0 ] = prim ;
m_env . PRMODE . _PRIM = prim ;
2009-02-09 21:15:56 +00:00
2012-01-09 08:41:33 +00:00
UpdateContext ( ) ;
2009-02-09 21:15:56 +00:00
2011-02-07 01:59:05 +00:00
UpdateVertexKick ( ) ;
2012-01-06 00:17:52 +00:00
ASSERT ( m_index . tail = = 0 | | m_index . buff [ m_index . tail - 1 ] + 1 = = m_vertex . next ) ;
2012-01-09 08:41:33 +00:00
if ( m_index . tail = = 0 )
{
m_vertex . next = 0 ;
}
2012-01-06 00:17:52 +00:00
m_vertex . head = m_vertex . tail = m_vertex . next ; // remove unused vertices from the end of the vertex buffer
2009-02-09 21:15:56 +00:00
}
2011-12-20 14:33:28 +00:00
void GSState : : GIFRegHandlerPRIM ( const GIFReg * RESTRICT r )
2010-08-17 04:38:49 +00:00
{
2011-02-24 04:55:35 +00:00
ALIGN_STACK ( 32 ) ;
2012-01-27 11:56:49 +00:00
ApplyPRIM ( r - > PRIM . u32 [ 0 ] ) ;
2010-08-17 04:38:49 +00:00
}
2012-01-08 17:10:00 +00:00
void GSState : : GIFRegHandlerRGBAQ ( const GIFReg * RESTRICT r )
2009-02-09 21:15:56 +00:00
{
2012-02-14 19:26:04 +00:00
GSVector4i rgbaq = ( GSVector4i ) r - > RGBAQ ;
2015-08-03 12:35:47 +00:00
GSVector4i q = rgbaq . blend8 ( GSVector4i : : cast ( GSVector4 : : m_one ) , rgbaq = = GSVector4i : : zero ( ) ) . yyyy ( ) ; // see GIFPackedRegHandlerSTQ
// Silent Hill output a nan in Q to emulate the flash light. Unfortunately it
// breaks GSVertexTrace code that rely on min/max.
2012-02-14 19:26:04 +00:00
2015-08-03 12:35:47 +00:00
q = GSVector4i : : cast ( GSVector4 : : cast ( q ) . replace_nan ( GSVector4 : : m_max ) ) ;
2015-08-03 09:26:48 +00:00
2015-08-03 12:35:47 +00:00
m_v . RGBAQ = rgbaq . upl32 ( q ) ;
/*
2015-07-20 17:34:42 +00:00
// Silent Hill output a nan in Q to emulate the flash light. Unfortunately it
// breaks GSVertexTrace code that rely on min/max.
2015-08-03 12:35:47 +00:00
if ( std : : isnan ( m_v . RGBAQ . Q ) )
2015-08-03 09:26:48 +00:00
{
2015-07-19 14:24:55 +00:00
m_v . RGBAQ . Q = std : : numeric_limits < float > : : max ( ) ;
}
2015-08-03 12:35:47 +00:00
*/
2009-02-09 21:15:56 +00:00
}
2012-01-08 17:10:00 +00:00
void GSState : : GIFRegHandlerST ( const GIFReg * RESTRICT r )
2009-02-09 21:15:56 +00:00
{
m_v . ST = ( GSVector4i ) r - > ST ;
2015-08-03 09:26:48 +00:00
2015-07-20 17:34:42 +00:00
ASSERT ( ! std : : isnan ( m_v . ST . S ) ) ; // See GIFRegHandlerRGBAQ
ASSERT ( ! std : : isnan ( m_v . ST . T ) ) ; // See GIFRegHandlerRGBAQ
2011-05-09 01:36:57 +00:00
# ifdef Offset_ST
GIFRegTEX0 TEX0 = m_context - > TEX0 ;
m_v . ST . S - = 0.02f * m_q / ( 1 < < TEX0 . TW ) ;
m_v . ST . T - = 0.02f * m_q / ( 1 < < TEX0 . TH ) ;
# endif
2009-02-09 21:15:56 +00:00
}
2012-01-08 17:10:00 +00:00
void GSState : : GIFRegHandlerUV ( const GIFReg * RESTRICT r )
GSdx:
- changed the KH2 fix in GetTextureMinMax to my taste, should give the same results, when the used texture rect is to the left/above the clamped area, it returns [min, min+1], and [max-1, max] for right/below
- m_mem.m_clut.Read32 was returned to its original place from GetAlphaMinMax
- UserHacks_WildHack was moved up to GSState, special UV handlers are only used when this setting is active
- updated xbyak to the latest available (avx2 seems incomplete, the 256-bit promoted old instructions are missing)
- changed vtune's include path to the 2013 edition
Some other not yet commited changes from a year ago:
- WriteImageX overflow crash-fix
- moved colclamp after dithering (sw mode), it makes more sense, no visible changes noticed
- Gif_Tag::analyzeTag(), there was a conditional I didn't like, split the loop into two parts
git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5649 96395faa-99c1-11dd-bbfe-3dabce05a288
2013-06-06 11:36:01 +00:00
{
m_v . UV = r - > UV . u32 [ 0 ] & 0x3fff3fff ;
}
void GSState : : GIFRegHandlerUV_Hack ( const GIFReg * RESTRICT r )
2009-02-09 21:15:56 +00:00
{
2012-03-08 17:18:22 +00:00
m_v . UV = r - > UV . u32 [ 0 ] & 0x3fff3fff ;
isPackedUV_HackFlag = false ;
2009-02-09 21:15:56 +00:00
}
2012-01-08 17:10:00 +00:00
template < uint32 prim , uint32 adc >
2011-12-20 14:33:28 +00:00
void GSState : : GIFRegHandlerXYZF2 ( const GIFReg * RESTRICT r )
2009-02-09 21:15:56 +00:00
{
/*
m_v . XYZ . X = r - > XYZF . X ;
m_v . XYZ . Y = r - > XYZF . Y ;
m_v . XYZ . Z = r - > XYZF . Z ;
m_v . FOG . F = r - > XYZF . F ;
*/
2012-01-08 17:10:00 +00:00
/*
2009-05-14 16:41:52 +00:00
m_v . XYZ . u32 [ 0 ] = r - > XYZF . u32 [ 0 ] ;
m_v . XYZ . u32 [ 1 ] = r - > XYZF . u32 [ 1 ] & 0x00ffffff ;
2012-01-08 17:10:00 +00:00
m_v . FOG = r - > XYZF . u32 [ 1 ] > > 24 ;
*/
GSVector4i xyzf = GSVector4i : : loadl ( & r - > XYZF ) ;
GSVector4i xyz = xyzf & ( GSVector4i : : xffffffff ( ) . upl32 ( GSVector4i : : x00ffffff ( ) ) ) ;
2013-06-17 04:11:10 +00:00
GSVector4i uvf = GSVector4i : : load ( ( int ) m_v . UV ) . upl32 ( xyzf . srl32 ( 24 ) . srl < 4 > ( ) ) ;
2012-01-08 17:10:00 +00:00
m_v . m [ 1 ] = xyz . upl64 ( uvf ) ;
2009-02-09 21:15:56 +00:00
2012-01-08 17:10:00 +00:00
VertexKick < prim > ( adc ) ;
2009-02-09 21:15:56 +00:00
}
2012-01-08 17:10:00 +00:00
template < uint32 prim , uint32 adc >
2011-12-20 14:33:28 +00:00
void GSState : : GIFRegHandlerXYZ2 ( const GIFReg * RESTRICT r )
2009-02-09 21:15:56 +00:00
{
2012-01-08 17:10:00 +00:00
// m_v.XYZ = (GSVector4i)r->XYZ;
2009-02-09 21:15:56 +00:00
2012-01-08 17:10:00 +00:00
m_v . m [ 1 ] = GSVector4i : : load ( & r - > XYZ , & m_v . UV ) ;
VertexKick < prim > ( adc ) ;
2009-02-09 21:15:56 +00:00
}
2012-01-08 17:10:00 +00:00
template < int i > void GSState : : ApplyTEX0 ( GIFRegTEX0 & TEX0 )
2009-02-09 21:15:56 +00:00
{
// even if TEX0 did not change, a new palette may have been uploaded and will overwrite the currently queued for drawing
2010-07-19 15:49:30 +00:00
bool wt = m_mem . m_clut . WriteTest ( TEX0 , m_env . TEXCLUT ) ;
2009-02-09 21:15:56 +00:00
2011-12-27 09:15:35 +00:00
// clut loading already covered with WriteTest, for drawing only have to check CPSM and CSA (MGS3 intro skybox would be drawn piece by piece without this)
uint64 mask = 0x1f78001c3fffffffull ; // TBP0 TBW PSM TW TCC TFX CPSM CSA
if ( wt | | PRIM - > CTXT = = i & & ( ( TEX0 . u64 ^ m_env . CTXT [ i ] . TEX0 . u64 ) & mask ) )
2009-02-09 21:15:56 +00:00
{
2010-04-25 00:31:27 +00:00
Flush ( ) ;
2009-02-09 21:15:56 +00:00
}
2010-07-19 15:49:30 +00:00
TEX0 . CPSM & = 0xa ; // 1010b
2009-02-09 21:15:56 +00:00
2010-07-19 15:49:30 +00:00
if ( ( TEX0 . u32 [ 0 ] ^ m_env . CTXT [ i ] . TEX0 . u32 [ 0 ] ) & 0x3ffffff ) // TBP0 TBW PSM
2009-02-09 21:15:56 +00:00
{
2010-07-19 15:49:30 +00:00
m_env . CTXT [ i ] . offset . tex = m_mem . GetOffset ( TEX0 . TBP0 , TEX0 . TBW , TEX0 . PSM ) ;
2009-02-09 21:15:56 +00:00
}
2010-08-17 04:38:49 +00:00
m_env . CTXT [ i ] . TEX0 = ( GSVector4i ) TEX0 ;
2009-07-22 03:55:28 +00:00
2009-02-09 21:15:56 +00:00
if ( wt )
{
2011-12-18 21:57:48 +00:00
GIFRegBITBLTBUF BITBLTBUF ;
2012-01-21 04:44:04 +00:00
GSVector4i r ;
2011-12-18 21:57:48 +00:00
2012-01-27 11:56:49 +00:00
if ( TEX0 . CSM = = 0 )
{
BITBLTBUF . SBP = TEX0 . CBP ;
BITBLTBUF . SBW = 1 ;
BITBLTBUF . SPSM = TEX0 . CSM ;
r . left = 0 ;
r . top = 0 ;
r . right = GSLocalMemory : : m_psm [ TEX0 . CPSM ] . bs . x ;
r . bottom = GSLocalMemory : : m_psm [ TEX0 . CPSM ] . bs . y ;
int blocks = 4 ;
if ( GSLocalMemory : : m_psm [ TEX0 . CPSM ] . bpp = = 16 )
{
blocks > > = 1 ;
}
if ( GSLocalMemory : : m_psm [ TEX0 . PSM ] . bpp = = 4 )
{
blocks > > = 1 ;
}
2011-12-18 21:57:48 +00:00
2012-02-06 18:16:49 +00:00
for ( int j = 0 ; j < blocks ; j + + , BITBLTBUF . SBP + + )
2012-01-27 11:56:49 +00:00
{
InvalidateLocalMem ( BITBLTBUF , r , true ) ;
}
}
else
{
BITBLTBUF . SBP = TEX0 . CBP ;
BITBLTBUF . SBW = m_env . TEXCLUT . CBW ;
BITBLTBUF . SPSM = TEX0 . CSM ;
r . left = m_env . TEXCLUT . COU ;
r . top = m_env . TEXCLUT . COV ;
r . right = r . left + GSLocalMemory : : m_psm [ TEX0 . CPSM ] . pal ;
r . bottom = r . top + 1 ;
InvalidateLocalMem ( BITBLTBUF , r , true ) ;
}
2011-12-18 21:57:48 +00:00
2009-02-09 21:15:56 +00:00
m_mem . m_clut . Write ( m_env . CTXT [ i ] . TEX0 , m_env . TEXCLUT ) ;
}
}
2011-12-20 14:33:28 +00:00
template < int i > void GSState : : GIFRegHandlerTEX0 ( const GIFReg * RESTRICT r )
2010-07-19 15:49:30 +00:00
{
GIFRegTEX0 TEX0 = r - > TEX0 ;
2012-02-15 18:57:52 +00:00
int tw = ( int ) TEX0 . TW ;
int th = ( int ) TEX0 . TH ;
2012-01-23 05:26:07 +00:00
2012-02-15 18:57:52 +00:00
if ( tw > 10 ) tw = 10 ;
if ( th > 10 ) th = 10 ;
if ( PRIM - > FST )
{
// Tokyo Xtreme Racer Drift 2, TW/TH == 0
// Just setting the max texture size to make the texture cache allocate some surface.
// The vertex trace will narrow the updated area down to the minimum, upper-left 8x8
// for a single letter, but it may address the whole thing if it wants to.
if ( tw = = 0 ) tw = 10 ;
if ( th = = 0 ) th = 10 ;
}
else
{
// Yakuza, TW/TH == 0
// The minimap is drawn using solid colors, the texture is really a 1x1 white texel,
// modulated by the vertex color. Cannot change the dimension because S/T are normalized.
}
TEX0 . TW = tw ;
TEX0 . TH = th ;
2010-07-19 15:49:30 +00:00
2012-01-13 18:10:05 +00:00
if ( ( TEX0 . TBW & 1 ) & & ( TEX0 . PSM = = PSM_PSMT8 | | TEX0 . PSM = = PSM_PSMT4 ) )
{
2014-12-12 21:31:31 +00:00
ASSERT ( TEX0 . TBW = = 1 ) ; // TODO // Bouken Jidai Katsugeki Goemon
2012-01-13 18:10:05 +00:00
TEX0 . TBW & = ~ 1 ; // GS User 2.6
}
2012-01-08 17:10:00 +00:00
ApplyTEX0 < i > ( TEX0 ) ;
2011-03-12 22:10:58 +00:00
if ( m_env . CTXT [ i ] . TEX1 . MTBA )
{
2011-04-04 11:05:54 +00:00
// NOTE 1: TEX1.MXL must not be automatically set to 3 here.
// NOTE 2: Mipmap levels are tightly packed, if (tbw << 6) > (1 << tw) then the left-over space to the right is used. (common for PSM_PSMT4)
// NOTE 3: Non-rectangular textures are treated as rectangular when calculating the occupied space (height is extended, not sure about width)
uint32 bp = TEX0 . TBP0 ;
uint32 bw = TEX0 . TBW ;
uint32 w = 1u < < TEX0 . TW ;
uint32 h = 1u < < TEX0 . TH ;
2011-03-12 22:10:58 +00:00
uint32 bpp = GSLocalMemory : : m_psm [ TEX0 . PSM ] . bpp ;
2011-04-04 11:05:54 +00:00
if ( h < w ) h = w ;
2011-03-12 22:10:58 +00:00
2011-04-04 11:05:54 +00:00
bp + = ( ( w * h * bpp > > 3 ) + 255 ) > > 8 ;
bw = std : : max < uint32 > ( bw > > 1 , 1 ) ;
w = std : : max < uint32 > ( w > > 1 , 1 ) ;
h = std : : max < uint32 > ( h > > 1 , 1 ) ;
2011-03-12 22:10:58 +00:00
2011-04-04 11:05:54 +00:00
m_env . CTXT [ i ] . MIPTBP1 . TBP1 = bp ;
m_env . CTXT [ i ] . MIPTBP1 . TBW1 = bw ;
2011-03-12 22:10:58 +00:00
2011-04-04 11:05:54 +00:00
bp + = ( ( w * h * bpp > > 3 ) + 255 ) > > 8 ;
bw = std : : max < uint32 > ( bw > > 1 , 1 ) ;
w = std : : max < uint32 > ( w > > 1 , 1 ) ;
h = std : : max < uint32 > ( h > > 1 , 1 ) ;
2011-03-12 22:10:58 +00:00
2011-04-04 11:05:54 +00:00
m_env . CTXT [ i ] . MIPTBP1 . TBP2 = bp ;
m_env . CTXT [ i ] . MIPTBP1 . TBW2 = bw ;
2011-03-12 22:10:58 +00:00
2011-04-04 11:05:54 +00:00
bp + = ( ( w * h * bpp > > 3 ) + 255 ) > > 8 ;
bw = std : : max < uint32 > ( bw > > 1 , 1 ) ;
w = std : : max < uint32 > ( w > > 1 , 1 ) ;
h = std : : max < uint32 > ( h > > 1 , 1 ) ;
2011-03-12 22:10:58 +00:00
2011-04-04 11:05:54 +00:00
m_env . CTXT [ i ] . MIPTBP1 . TBP3 = bp ;
m_env . CTXT [ i ] . MIPTBP1 . TBW3 = bw ;
2011-03-12 22:10:58 +00:00
// printf("MTBA\n");
}
2010-07-19 15:49:30 +00:00
}
2011-12-20 14:33:28 +00:00
template < int i > void GSState : : GIFRegHandlerCLAMP ( const GIFReg * RESTRICT r )
2009-02-09 21:15:56 +00:00
{
2009-05-20 15:35:31 +00:00
if ( PRIM - > CTXT = = i & & r - > CLAMP ! = m_env . CTXT [ i ] . CLAMP )
2009-02-09 21:15:56 +00:00
{
Flush ( ) ;
}
m_env . CTXT [ i ] . CLAMP = ( GSVector4i ) r - > CLAMP ;
}
2011-12-20 14:33:28 +00:00
void GSState : : GIFRegHandlerFOG ( const GIFReg * RESTRICT r )
2009-02-09 21:15:56 +00:00
{
2012-01-08 17:10:00 +00:00
m_v . FOG = r - > FOG . F ;
2009-02-09 21:15:56 +00:00
}
2011-12-20 14:33:28 +00:00
void GSState : : GIFRegHandlerNOP ( const GIFReg * RESTRICT r )
2009-02-09 21:15:56 +00:00
{
}
2011-12-20 14:33:28 +00:00
template < int i > void GSState : : GIFRegHandlerTEX1 ( const GIFReg * RESTRICT r )
2009-02-09 21:15:56 +00:00
{
2009-05-20 15:35:31 +00:00
if ( PRIM - > CTXT = = i & & r - > TEX1 ! = m_env . CTXT [ i ] . TEX1 )
2009-02-09 21:15:56 +00:00
{
Flush ( ) ;
}
m_env . CTXT [ i ] . TEX1 = ( GSVector4i ) r - > TEX1 ;
}
2011-12-20 14:33:28 +00:00
template < int i > void GSState : : GIFRegHandlerTEX2 ( const GIFReg * RESTRICT r )
2009-02-09 21:15:56 +00:00
{
// m_env.CTXT[i].TEX2 = r->TEX2; // not used
2010-07-19 15:49:30 +00:00
// TEX2 is a masked write to TEX0, for performing CLUT swaps (palette swaps).
// It only applies the following fields:
// CLD, CSA, CSM, CPSM, CBP, PSM.
// It ignores these fields (uses existing values in the context):
// TFX, TCC, TH, TW, TBW, and TBP0
2011-02-18 01:56:05 +00:00
uint64 mask = 0xFFFFFFE003F00000ull ; // TEX2 bits
2011-12-27 09:15:35 +00:00
2010-07-19 15:49:30 +00:00
GIFRegTEX0 TEX0 ;
2011-12-27 09:15:35 +00:00
2010-07-19 15:49:30 +00:00
TEX0 . u64 = ( m_env . CTXT [ i ] . TEX0 . u64 & ~ mask ) | ( r - > u64 & mask ) ;
2009-02-09 21:15:56 +00:00
2012-01-08 17:10:00 +00:00
ApplyTEX0 < i > ( TEX0 ) ;
2009-02-09 21:15:56 +00:00
}
2011-12-20 14:33:28 +00:00
template < int i > void GSState : : GIFRegHandlerXYOFFSET ( const GIFReg * RESTRICT r )
2009-02-09 21:15:56 +00:00
{
2015-08-04 01:34:46 +00:00
GSVector4i o = ( GSVector4i ) r - > XYOFFSET & GSVector4i : : x0000ffff ( ) ;
2009-02-09 21:15:56 +00:00
2015-08-04 01:34:46 +00:00
if ( ! o . eq ( m_env . CTXT [ i ] . XYOFFSET ) )
2009-02-09 21:15:56 +00:00
{
Flush ( ) ;
}
2015-08-04 01:34:46 +00:00
m_env . CTXT [ i ] . XYOFFSET = o ;
2009-02-09 21:15:56 +00:00
m_env . CTXT [ i ] . UpdateScissor ( ) ;
2012-01-09 08:41:33 +00:00
UpdateScissor ( ) ;
2009-02-09 21:15:56 +00:00
}
2011-12-20 14:33:28 +00:00
void GSState : : GIFRegHandlerPRMODECONT ( const GIFReg * RESTRICT r )
2009-02-09 21:15:56 +00:00
{
2009-05-20 15:35:31 +00:00
if ( r - > PRMODECONT ! = m_env . PRMODECONT )
2009-02-09 21:15:56 +00:00
{
Flush ( ) ;
}
m_env . PRMODECONT . AC = r - > PRMODECONT . AC ;
PRIM = m_env . PRMODECONT . AC ? & m_env . PRIM : ( GIFRegPRIM * ) & m_env . PRMODE ;
2009-06-03 12:09:04 +00:00
// if(PRIM->PRIM == 7) printf("Invalid PRMODECONT/PRIM\n");
2009-02-09 21:15:56 +00:00
2012-01-09 08:41:33 +00:00
UpdateContext ( ) ;
2011-02-07 01:59:05 +00:00
UpdateVertexKick ( ) ;
2009-02-09 21:15:56 +00:00
}
2011-12-20 14:33:28 +00:00
void GSState : : GIFRegHandlerPRMODE ( const GIFReg * RESTRICT r )
2009-02-09 21:15:56 +00:00
{
if ( ! m_env . PRMODECONT . AC )
{
Flush ( ) ;
}
2009-05-14 16:41:52 +00:00
uint32 _PRIM = m_env . PRMODE . _PRIM ;
2009-02-09 21:15:56 +00:00
m_env . PRMODE = ( GSVector4i ) r - > PRMODE ;
m_env . PRMODE . _PRIM = _PRIM ;
2012-01-09 08:41:33 +00:00
UpdateContext ( ) ;
2011-02-07 01:59:05 +00:00
UpdateVertexKick ( ) ;
2009-02-09 21:15:56 +00:00
}
2011-12-20 14:33:28 +00:00
void GSState : : GIFRegHandlerTEXCLUT ( const GIFReg * RESTRICT r )
2009-02-09 21:15:56 +00:00
{
2009-05-20 15:35:31 +00:00
if ( r - > TEXCLUT ! = m_env . TEXCLUT )
2009-02-09 21:15:56 +00:00
{
Flush ( ) ;
}
m_env . TEXCLUT = ( GSVector4i ) r - > TEXCLUT ;
}
2011-12-20 14:33:28 +00:00
void GSState : : GIFRegHandlerSCANMSK ( const GIFReg * RESTRICT r )
2009-02-09 21:15:56 +00:00
{
2009-05-20 15:35:31 +00:00
if ( r - > SCANMSK ! = m_env . SCANMSK )
2009-02-09 21:15:56 +00:00
{
Flush ( ) ;
}
m_env . SCANMSK = ( GSVector4i ) r - > SCANMSK ;
}
2011-12-20 14:33:28 +00:00
template < int i > void GSState : : GIFRegHandlerMIPTBP1 ( const GIFReg * RESTRICT r )
2009-02-09 21:15:56 +00:00
{
2009-05-20 15:35:31 +00:00
if ( PRIM - > CTXT = = i & & r - > MIPTBP1 ! = m_env . CTXT [ i ] . MIPTBP1 )
2009-02-09 21:15:56 +00:00
{
Flush ( ) ;
}
m_env . CTXT [ i ] . MIPTBP1 = ( GSVector4i ) r - > MIPTBP1 ;
}
2011-12-20 14:33:28 +00:00
template < int i > void GSState : : GIFRegHandlerMIPTBP2 ( const GIFReg * RESTRICT r )
2009-02-09 21:15:56 +00:00
{
2009-05-20 15:35:31 +00:00
if ( PRIM - > CTXT = = i & & r - > MIPTBP2 ! = m_env . CTXT [ i ] . MIPTBP2 )
2009-02-09 21:15:56 +00:00
{
Flush ( ) ;
}
m_env . CTXT [ i ] . MIPTBP2 = ( GSVector4i ) r - > MIPTBP2 ;
}
2011-12-20 14:33:28 +00:00
void GSState : : GIFRegHandlerTEXA ( const GIFReg * RESTRICT r )
2009-02-09 21:15:56 +00:00
{
2009-05-20 15:35:31 +00:00
if ( r - > TEXA ! = m_env . TEXA )
2009-02-09 21:15:56 +00:00
{
Flush ( ) ;
}
m_env . TEXA = ( GSVector4i ) r - > TEXA ;
}
2011-12-20 14:33:28 +00:00
void GSState : : GIFRegHandlerFOGCOL ( const GIFReg * RESTRICT r )
2009-02-09 21:15:56 +00:00
{
2009-05-20 15:35:31 +00:00
if ( r - > FOGCOL ! = m_env . FOGCOL )
2009-02-09 21:15:56 +00:00
{
Flush ( ) ;
}
m_env . FOGCOL = ( GSVector4i ) r - > FOGCOL ;
}
2011-12-20 14:33:28 +00:00
void GSState : : GIFRegHandlerTEXFLUSH ( const GIFReg * RESTRICT r )
2009-02-09 21:15:56 +00:00
{
2012-02-08 16:57:14 +00:00
m_texflush = true ;
2009-02-09 21:15:56 +00:00
}
2011-12-20 14:33:28 +00:00
template < int i > void GSState : : GIFRegHandlerSCISSOR ( const GIFReg * RESTRICT r )
2009-02-09 21:15:56 +00:00
{
2009-05-20 15:35:31 +00:00
if ( PRIM - > CTXT = = i & & r - > SCISSOR ! = m_env . CTXT [ i ] . SCISSOR )
2009-02-09 21:15:56 +00:00
{
Flush ( ) ;
}
m_env . CTXT [ i ] . SCISSOR = ( GSVector4i ) r - > SCISSOR ;
m_env . CTXT [ i ] . UpdateScissor ( ) ;
2012-01-09 08:41:33 +00:00
UpdateScissor ( ) ;
2009-02-09 21:15:56 +00:00
}
2011-12-20 14:33:28 +00:00
template < int i > void GSState : : GIFRegHandlerALPHA ( const GIFReg * RESTRICT r )
2009-02-09 21:15:56 +00:00
{
ASSERT ( r - > ALPHA . A ! = 3 ) ;
ASSERT ( r - > ALPHA . B ! = 3 ) ;
ASSERT ( r - > ALPHA . C ! = 3 ) ;
ASSERT ( r - > ALPHA . D ! = 3 ) ;
2009-05-20 15:35:31 +00:00
if ( PRIM - > CTXT = = i & & r - > ALPHA ! = m_env . CTXT [ i ] . ALPHA )
2009-02-09 21:15:56 +00:00
{
Flush ( ) ;
}
m_env . CTXT [ i ] . ALPHA = ( GSVector4i ) r - > ALPHA ;
// A/B/C/D == 3? => 2
2009-05-14 16:41:52 +00:00
m_env . CTXT [ i ] . ALPHA . u32 [ 0 ] = ( ( ~ m_env . CTXT [ i ] . ALPHA . u32 [ 0 ] > > 1 ) | 0xAA ) & m_env . CTXT [ i ] . ALPHA . u32 [ 0 ] ;
2009-02-09 21:15:56 +00:00
}
2011-12-20 14:33:28 +00:00
void GSState : : GIFRegHandlerDIMX ( const GIFReg * RESTRICT r )
2009-02-09 21:15:56 +00:00
{
2009-02-11 07:05:44 +00:00
bool update = false ;
2009-05-20 15:35:31 +00:00
if ( r - > DIMX ! = m_env . DIMX )
2009-02-09 21:15:56 +00:00
{
Flush ( ) ;
2009-02-11 07:05:44 +00:00
update = true ;
2009-02-09 21:15:56 +00:00
}
m_env . DIMX = ( GSVector4i ) r - > DIMX ;
2009-02-11 07:05:44 +00:00
if ( update )
{
m_env . UpdateDIMX ( ) ;
}
2009-02-09 21:15:56 +00:00
}
2011-12-20 14:33:28 +00:00
void GSState : : GIFRegHandlerDTHE ( const GIFReg * RESTRICT r )
2009-02-09 21:15:56 +00:00
{
2009-05-20 15:35:31 +00:00
if ( r - > DTHE ! = m_env . DTHE )
2009-02-09 21:15:56 +00:00
{
Flush ( ) ;
}
m_env . DTHE = ( GSVector4i ) r - > DTHE ;
}
2011-12-20 14:33:28 +00:00
void GSState : : GIFRegHandlerCOLCLAMP ( const GIFReg * RESTRICT r )
2009-02-09 21:15:56 +00:00
{
2009-05-20 15:35:31 +00:00
if ( r - > COLCLAMP ! = m_env . COLCLAMP )
2009-02-09 21:15:56 +00:00
{
Flush ( ) ;
}
m_env . COLCLAMP = ( GSVector4i ) r - > COLCLAMP ;
2010-03-12 22:47:59 +00:00
# ifdef DISABLE_COLCLAMP
m_env . COLCLAMP . CLAMP = 1 ;
# endif
2009-02-09 21:15:56 +00:00
}
2011-12-20 14:33:28 +00:00
template < int i > void GSState : : GIFRegHandlerTEST ( const GIFReg * RESTRICT r )
2009-02-09 21:15:56 +00:00
{
2009-05-20 15:35:31 +00:00
if ( PRIM - > CTXT = = i & & r - > TEST ! = m_env . CTXT [ i ] . TEST )
2009-02-09 21:15:56 +00:00
{
Flush ( ) ;
}
m_env . CTXT [ i ] . TEST = ( GSVector4i ) r - > TEST ;
2010-05-14 14:05:39 +00:00
# ifdef DISABLE_DATE
m_env . CTXT [ i ] . TEST . DATE = 0 ;
# endif
2009-02-09 21:15:56 +00:00
}
2011-12-20 14:33:28 +00:00
void GSState : : GIFRegHandlerPABE ( const GIFReg * RESTRICT r )
2009-02-09 21:15:56 +00:00
{
2009-05-20 15:35:31 +00:00
if ( r - > PABE ! = m_env . PABE )
2009-02-09 21:15:56 +00:00
{
Flush ( ) ;
}
m_env . PABE = ( GSVector4i ) r - > PABE ;
}
2011-12-20 14:33:28 +00:00
template < int i > void GSState : : GIFRegHandlerFBA ( const GIFReg * RESTRICT r )
2009-02-09 21:15:56 +00:00
{
2009-05-20 15:35:31 +00:00
if ( PRIM - > CTXT = = i & & r - > FBA ! = m_env . CTXT [ i ] . FBA )
2009-02-09 21:15:56 +00:00
{
Flush ( ) ;
}
m_env . CTXT [ i ] . FBA = ( GSVector4i ) r - > FBA ;
}
2011-12-20 14:33:28 +00:00
template < int i > void GSState : : GIFRegHandlerFRAME ( const GIFReg * RESTRICT r )
2009-02-09 21:15:56 +00:00
{
2009-05-20 15:35:31 +00:00
if ( PRIM - > CTXT = = i & & r - > FRAME ! = m_env . CTXT [ i ] . FRAME )
2009-02-09 21:15:56 +00:00
{
Flush ( ) ;
}
2009-07-22 03:55:28 +00:00
if ( ( m_env . CTXT [ i ] . FRAME . u32 [ 0 ] ^ r - > FRAME . u32 [ 0 ] ) & 0x3f3f01ff ) // FBP FBW PSM
{
m_env . CTXT [ i ] . offset . fb = m_mem . GetOffset ( r - > FRAME . Block ( ) , r - > FRAME . FBW , r - > FRAME . PSM ) ;
m_env . CTXT [ i ] . offset . zb = m_mem . GetOffset ( m_env . CTXT [ i ] . ZBUF . Block ( ) , r - > FRAME . FBW , m_env . CTXT [ i ] . ZBUF . PSM ) ;
2012-01-18 11:47:31 +00:00
m_env . CTXT [ i ] . offset . fzb = m_mem . GetPixelOffset ( r - > FRAME , m_env . CTXT [ i ] . ZBUF ) ;
m_env . CTXT [ i ] . offset . fzb4 = m_mem . GetPixelOffset4 ( r - > FRAME , m_env . CTXT [ i ] . ZBUF ) ;
2009-07-22 03:55:28 +00:00
}
2011-08-30 07:14:22 +00:00
2009-02-09 21:15:56 +00:00
m_env . CTXT [ i ] . FRAME = ( GSVector4i ) r - > FRAME ;
2013-07-01 21:28:58 +00:00
2010-03-12 22:47:59 +00:00
# ifdef DISABLE_BITMASKING
m_env . CTXT [ i ] . FRAME . FBMSK = GSVector4i : : store ( GSVector4i : : load ( ( int ) m_env . CTXT [ i ] . FRAME . FBMSK ) . eq8 ( GSVector4i : : xffffffff ( ) ) ) ;
# endif
2009-02-09 21:15:56 +00:00
}
2011-12-20 14:33:28 +00:00
template < int i > void GSState : : GIFRegHandlerZBUF ( const GIFReg * RESTRICT r )
2009-02-09 21:15:56 +00:00
{
2010-07-19 15:49:30 +00:00
GIFRegZBUF ZBUF = r - > ZBUF ;
2011-03-08 01:48:15 +00:00
2010-07-19 15:49:30 +00:00
if ( ZBUF . u32 [ 0 ] = = 0 )
2009-02-09 21:15:56 +00:00
{
// during startup all regs are cleared to 0 (by the bios or something), so we mask z until this register becomes valid
2012-03-15 12:44:18 +00:00
// edit: breaks Grandia Xtreme and sounds like a bad idea generally. What was the intend?
GSdx:
- changed the KH2 fix in GetTextureMinMax to my taste, should give the same results, when the used texture rect is to the left/above the clamped area, it returns [min, min+1], and [max-1, max] for right/below
- m_mem.m_clut.Read32 was returned to its original place from GetAlphaMinMax
- UserHacks_WildHack was moved up to GSState, special UV handlers are only used when this setting is active
- updated xbyak to the latest available (avx2 seems incomplete, the 256-bit promoted old instructions are missing)
- changed vtune's include path to the 2013 edition
Some other not yet commited changes from a year ago:
- WriteImageX overflow crash-fix
- moved colclamp after dithering (sw mode), it makes more sense, no visible changes noticed
- Gif_Tag::analyzeTag(), there was a conditional I didn't like, split the loop into two parts
git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5649 96395faa-99c1-11dd-bbfe-3dabce05a288
2013-06-06 11:36:01 +00:00
// edit2: should be set only before any serious drawing happens, grandia extreme nulls out this register throughout the whole game,
// I already forgot what it fixed, that game never masked the zbuffer, but assumed it was set by default
2012-03-15 12:44:18 +00:00
//ZBUF.ZMSK = 1;
2009-02-09 21:15:56 +00:00
}
2010-07-19 15:49:30 +00:00
ZBUF . PSM | = 0x30 ;
2009-02-09 21:15:56 +00:00
2010-07-19 15:49:30 +00:00
if ( ZBUF . PSM ! = PSM_PSMZ32
& & ZBUF . PSM ! = PSM_PSMZ24
& & ZBUF . PSM ! = PSM_PSMZ16
& & ZBUF . PSM ! = PSM_PSMZ16S )
2009-07-22 03:55:28 +00:00
{
2010-07-19 15:49:30 +00:00
ZBUF . PSM = PSM_PSMZ32 ;
2009-07-22 03:55:28 +00:00
}
2010-07-19 15:49:30 +00:00
if ( PRIM - > CTXT = = i & & ZBUF ! = m_env . CTXT [ i ] . ZBUF )
2009-02-09 21:15:56 +00:00
{
Flush ( ) ;
}
2010-07-19 15:49:30 +00:00
if ( ( m_env . CTXT [ i ] . ZBUF . u32 [ 0 ] ^ ZBUF . u32 [ 0 ] ) & 0x3f0001ff ) // ZBP PSM
2009-02-09 21:15:56 +00:00
{
2010-07-19 15:49:30 +00:00
m_env . CTXT [ i ] . offset . zb = m_mem . GetOffset ( ZBUF . Block ( ) , m_env . CTXT [ i ] . FRAME . FBW , ZBUF . PSM ) ;
2012-01-18 11:47:31 +00:00
m_env . CTXT [ i ] . offset . fzb = m_mem . GetPixelOffset ( m_env . CTXT [ i ] . FRAME , ZBUF ) ;
m_env . CTXT [ i ] . offset . fzb4 = m_mem . GetPixelOffset4 ( m_env . CTXT [ i ] . FRAME , ZBUF ) ;
2009-02-09 21:15:56 +00:00
}
2009-07-22 03:55:28 +00:00
2010-07-19 15:49:30 +00:00
m_env . CTXT [ i ] . ZBUF = ( GSVector4i ) ZBUF ;
2009-02-09 21:15:56 +00:00
}
2011-12-20 14:33:28 +00:00
void GSState : : GIFRegHandlerBITBLTBUF ( const GIFReg * RESTRICT r )
2009-02-09 21:15:56 +00:00
{
2009-05-20 15:35:31 +00:00
if ( r - > BITBLTBUF ! = m_env . BITBLTBUF )
2009-02-09 21:15:56 +00:00
{
FlushWrite ( ) ;
}
m_env . BITBLTBUF = ( GSVector4i ) r - > BITBLTBUF ;
if ( ( m_env . BITBLTBUF . SBW & 1 ) & & ( m_env . BITBLTBUF . SPSM = = PSM_PSMT8 | | m_env . BITBLTBUF . SPSM = = PSM_PSMT4 ) )
{
m_env . BITBLTBUF . SBW & = ~ 1 ;
}
if ( ( m_env . BITBLTBUF . DBW & 1 ) & & ( m_env . BITBLTBUF . DPSM = = PSM_PSMT8 | | m_env . BITBLTBUF . DPSM = = PSM_PSMT4 ) )
{
m_env . BITBLTBUF . DBW & = ~ 1 ; // namcoXcapcom: 5, 11, refered to as 4, 10 in TEX0.TBW later
}
}
2011-12-20 14:33:28 +00:00
void GSState : : GIFRegHandlerTRXPOS ( const GIFReg * RESTRICT r )
2009-02-09 21:15:56 +00:00
{
2009-05-20 15:35:31 +00:00
if ( r - > TRXPOS ! = m_env . TRXPOS )
2009-02-09 21:15:56 +00:00
{
FlushWrite ( ) ;
}
m_env . TRXPOS = ( GSVector4i ) r - > TRXPOS ;
}
2011-12-20 14:33:28 +00:00
void GSState : : GIFRegHandlerTRXREG ( const GIFReg * RESTRICT r )
2009-02-09 21:15:56 +00:00
{
2009-05-20 15:35:31 +00:00
if ( r - > TRXREG ! = m_env . TRXREG )
2009-02-09 21:15:56 +00:00
{
FlushWrite ( ) ;
}
m_env . TRXREG = ( GSVector4i ) r - > TRXREG ;
}
2011-12-20 14:33:28 +00:00
void GSState : : GIFRegHandlerTRXDIR ( const GIFReg * RESTRICT r )
2009-02-09 21:15:56 +00:00
{
Flush ( ) ;
m_env . TRXDIR = ( GSVector4i ) r - > TRXDIR ;
switch ( m_env . TRXDIR . XDIR )
{
case 0 : // host -> local
2009-04-18 09:34:25 +00:00
m_tr . Init ( m_env . TRXPOS . DSAX , m_env . TRXPOS . DSAY ) ;
2009-02-09 21:15:56 +00:00
break ;
case 1 : // local -> host
2009-04-18 09:34:25 +00:00
m_tr . Init ( m_env . TRXPOS . SSAX , m_env . TRXPOS . SSAY ) ;
2009-02-09 21:15:56 +00:00
break ;
case 2 : // local -> local
Move ( ) ;
break ;
2010-04-25 00:31:27 +00:00
case 3 :
2009-02-09 21:15:56 +00:00
ASSERT ( 0 ) ;
break ;
2011-12-20 14:33:28 +00:00
default :
__assume ( 0 ) ;
2009-02-09 21:15:56 +00:00
}
}
2011-12-20 14:33:28 +00:00
void GSState : : GIFRegHandlerHWREG ( const GIFReg * RESTRICT r )
2009-02-09 21:15:56 +00:00
{
ASSERT ( m_env . TRXDIR . XDIR = = 0 ) ; // host => local
2009-07-01 21:14:12 +00:00
Write ( ( uint8 * ) r , 8 ) ; // haunting ground
2009-02-09 21:15:56 +00:00
}
2011-12-20 14:33:28 +00:00
void GSState : : GIFRegHandlerSIGNAL ( const GIFReg * RESTRICT r )
2009-02-09 21:15:56 +00:00
{
2009-03-31 03:19:21 +00:00
m_regs - > SIGLBLID . SIGID = ( m_regs - > SIGLBLID . SIGID & ~ r - > SIGNAL . IDMSK ) | ( r - > SIGNAL . ID & r - > SIGNAL . IDMSK ) ;
2009-02-09 21:15:56 +00:00
2009-03-31 03:19:21 +00:00
if ( m_regs - > CSR . wSIGNAL ) m_regs - > CSR . rSIGNAL = 1 ;
if ( ! m_regs - > IMR . SIGMSK & & m_irq ) m_irq ( ) ;
2009-02-09 21:15:56 +00:00
}
2011-12-20 14:33:28 +00:00
void GSState : : GIFRegHandlerFINISH ( const GIFReg * RESTRICT r )
2009-02-09 21:15:56 +00:00
{
2009-03-31 03:19:21 +00:00
if ( m_regs - > CSR . wFINISH ) m_regs - > CSR . rFINISH = 1 ;
if ( ! m_regs - > IMR . FINISHMSK & & m_irq ) m_irq ( ) ;
2009-02-09 21:15:56 +00:00
}
2011-12-20 14:33:28 +00:00
void GSState : : GIFRegHandlerLABEL ( const GIFReg * RESTRICT r )
2009-02-09 21:15:56 +00:00
{
2009-03-31 03:19:21 +00:00
m_regs - > SIGLBLID . LBLID = ( m_regs - > SIGLBLID . LBLID & ~ r - > LABEL . IDMSK ) | ( r - > LABEL . ID & r - > LABEL . IDMSK ) ;
2009-02-09 21:15:56 +00:00
}
//
void GSState : : Flush ( )
{
FlushWrite ( ) ;
FlushPrim ( ) ;
}
void GSState : : FlushWrite ( )
{
2009-04-18 09:34:25 +00:00
int len = m_tr . end - m_tr . start ;
2009-02-09 21:15:56 +00:00
2009-04-18 09:34:25 +00:00
if ( len < = 0 ) return ;
2009-02-09 21:15:56 +00:00
2011-12-16 19:13:58 +00:00
GSVector4i r ;
r . left = m_env . TRXPOS . DSAX ;
r . top = m_env . TRXPOS . DSAY ;
r . right = r . left + m_env . TRXREG . RRW ;
r . bottom = r . top + m_env . TRXREG . RRH ;
InvalidateVideoMem ( m_env . BITBLTBUF , r ) ;
//int y = m_tr.y;
2009-02-09 21:15:56 +00:00
2009-04-18 09:34:25 +00:00
GSLocalMemory : : writeImage wi = GSLocalMemory : : m_psm [ m_env . BITBLTBUF . DPSM ] . wi ;
2009-02-09 21:15:56 +00:00
2009-04-18 09:34:25 +00:00
( m_mem . * wi ) ( m_tr . x , m_tr . y , & m_tr . buff [ m_tr . start ] , len , m_env . BITBLTBUF , m_env . TRXPOS , m_env . TRXREG ) ;
2009-02-09 21:15:56 +00:00
2009-04-18 09:34:25 +00:00
m_tr . start + = len ;
2009-02-09 21:15:56 +00:00
2009-04-18 09:34:25 +00:00
m_perfmon . Put ( GSPerfMon : : Swizzle , len ) ;
2009-02-09 21:15:56 +00:00
2011-12-16 19:13:58 +00:00
/*
2009-05-14 16:41:52 +00:00
GSVector4i r ;
2010-04-25 00:31:27 +00:00
2009-04-18 09:34:25 +00:00
r . left = m_env . TRXPOS . DSAX ;
r . top = y ;
r . right = r . left + m_env . TRXREG . RRW ;
2009-07-04 15:14:04 +00:00
r . bottom = std : : min < int > ( r . top + m_env . TRXREG . RRH , m_tr . x = = r . left ? m_tr . y : m_tr . y + 1 ) ;
2009-02-09 21:15:56 +00:00
2009-04-18 09:34:25 +00:00
InvalidateVideoMem ( m_env . BITBLTBUF , r ) ;
2011-12-16 19:13:58 +00:00
*/
2009-02-09 21:15:56 +00:00
/*
2009-04-18 09:34:25 +00:00
static int n = 0 ;
2009-05-11 08:18:00 +00:00
string s ;
2010-04-25 00:31:27 +00:00
s = format ( " c: \\ temp1 \\ [%04d]_%05x_%d_%d_%d_%d_%d_%d.bmp " ,
n + + , ( int ) m_env . BITBLTBUF . DBP , ( int ) m_env . BITBLTBUF . DBW , ( int ) m_env . BITBLTBUF . DPSM ,
2009-04-18 09:34:25 +00:00
r . left , r . top , r . right , r . bottom ) ;
2009-05-11 08:18:00 +00:00
m_mem . SaveBMP ( s , m_env . BITBLTBUF . DBP , m_env . BITBLTBUF . DBW , m_env . BITBLTBUF . DPSM , r . right , r . bottom ) ;
2009-02-09 21:15:56 +00:00
*/
}
2012-01-05 02:40:24 +00:00
void GSState : : FlushPrim ( )
{
if ( m_index . tail > 0 )
{
2012-01-19 04:53:36 +00:00
GSVertex buff [ 2 ] ;
2012-01-08 17:10:00 +00:00
2012-01-05 04:40:47 +00:00
size_t head = m_vertex . head ;
size_t tail = m_vertex . tail ;
2012-01-09 08:41:33 +00:00
size_t next = m_vertex . next ;
2012-01-13 18:10:05 +00:00
size_t unused = 0 ;
2012-01-09 08:41:33 +00:00
2012-01-08 17:10:00 +00:00
if ( tail > head )
2012-01-05 04:40:47 +00:00
{
2012-01-08 17:10:00 +00:00
switch ( PRIM - > PRIM )
{
2012-01-09 08:41:33 +00:00
case GS_POINTLIST :
2012-01-13 18:10:05 +00:00
ASSERT ( 0 ) ;
2012-01-09 08:41:33 +00:00
break ;
case GS_LINELIST :
2012-01-08 17:10:00 +00:00
case GS_LINESTRIP :
2012-01-09 08:41:33 +00:00
case GS_SPRITE :
case GS_TRIANGLELIST :
2012-01-08 17:10:00 +00:00
case GS_TRIANGLESTRIP :
2012-01-13 18:10:05 +00:00
unused = tail - head ;
2012-01-19 04:53:36 +00:00
memcpy ( buff , & m_vertex . buff [ head ] , sizeof ( GSVertex ) * unused ) ;
2012-01-08 17:10:00 +00:00
break ;
case GS_TRIANGLEFAN :
2012-01-19 04:53:36 +00:00
buff [ 0 ] = m_vertex . buff [ head ] ; unused = 1 ;
if ( tail - 1 > head ) { buff [ 1 ] = m_vertex . buff [ tail - 1 ] ; unused = 2 ; }
2012-01-08 17:10:00 +00:00
break ;
case GS_INVALID :
break ;
default :
__assume ( 0 ) ;
}
2012-01-13 18:10:05 +00:00
2015-10-22 17:51:03 +00:00
ASSERT ( ( int ) unused < GSUtil : : GetVertexCount ( PRIM - > PRIM ) ) ;
2012-01-05 04:40:47 +00:00
}
2012-01-05 02:40:24 +00:00
if ( GSLocalMemory : : m_psm [ m_context - > FRAME . PSM ] . fmt < 3 & & GSLocalMemory : : m_psm [ m_context - > ZBUF . PSM ] . fmt < 3 )
{
// FIXME: berserk fpsm = 27 (8H)
2012-01-19 04:53:36 +00:00
m_vt . Update ( m_vertex . buff , m_index . buff , m_index . tail , GSUtil : : GetPrimClass ( PRIM - > PRIM ) ) ;
2012-01-08 17:10:00 +00:00
2012-01-05 02:40:24 +00:00
Draw ( ) ;
m_perfmon . Put ( GSPerfMon : : Draw , 1 ) ;
m_perfmon . Put ( GSPerfMon : : Prim , m_index . tail / GSUtil : : GetVertexCount ( PRIM - > PRIM ) ) ;
}
2012-01-09 08:41:33 +00:00
m_index . tail = 0 ;
2012-01-08 17:10:00 +00:00
m_vertex . head = 0 ;
2012-01-06 00:17:52 +00:00
2012-01-13 18:10:05 +00:00
if ( unused > 0 )
2012-01-05 04:40:47 +00:00
{
2012-01-19 04:53:36 +00:00
memcpy ( m_vertex . buff , buff , sizeof ( GSVertex ) * unused ) ;
2012-01-05 04:40:47 +00:00
2012-01-13 18:10:05 +00:00
m_vertex . tail = unused ;
2012-01-09 08:41:33 +00:00
m_vertex . next = next > head ? next - head : 0 ;
}
2012-01-13 18:10:05 +00:00
else
{
m_vertex . tail = 0 ;
m_vertex . next = 0 ;
}
2012-01-05 04:40:47 +00:00
}
2012-01-05 02:40:24 +00:00
}
2009-02-09 21:15:56 +00:00
//
2010-07-19 15:49:30 +00:00
void GSState : : Write ( const uint8 * mem , int len )
2009-02-09 21:15:56 +00:00
{
2009-04-18 09:34:25 +00:00
int w = m_env . TRXREG . RRW ;
int h = m_env . TRXREG . RRH ;
2009-02-09 21:15:56 +00:00
2009-06-05 15:15:02 +00:00
const GSLocalMemory : : psm_t & psm = GSLocalMemory : : m_psm [ m_env . BITBLTBUF . DPSM ] ;
2009-02-09 21:15:56 +00:00
2009-06-05 15:15:02 +00:00
// printf("Write len=%d DBP=%05x DBW=%d DPSM=%d DSAX=%d DSAY=%d RRW=%d RRH=%d\n", len, m_env.BITBLTBUF.DBP, m_env.BITBLTBUF.DBW, m_env.BITBLTBUF.DPSM, m_env.TRXPOS.DSAX, m_env.TRXPOS.DSAY, m_env.TRXREG.RRW, m_env.TRXREG.RRH);
if ( ! m_tr . Update ( w , h , psm . trbpp , len ) )
2009-02-09 21:15:56 +00:00
{
2009-04-18 09:34:25 +00:00
return ;
2009-02-09 21:15:56 +00:00
}
2015-06-26 16:02:51 +00:00
GL_CACHE ( " Write! ... => 0x%x W:%d F:%d (DIR %d%d), dPos(%d %d) size(%d %d) " ,
m_env . BITBLTBUF . DBP , m_env . BITBLTBUF . DBW , m_env . BITBLTBUF . DPSM ,
m_env . TRXPOS . DIRX , m_env . TRXPOS . DIRY ,
m_env . TRXPOS . DSAX , m_env . TRXPOS . DSAY , w , h ) ;
2009-04-18 09:34:25 +00:00
if ( PRIM - > TME & & ( m_env . BITBLTBUF . DBP = = m_context - > TEX0 . TBP0 | | m_env . BITBLTBUF . DBP = = m_context - > TEX0 . CBP ) ) // TODO: hmmmm
2009-02-09 21:15:56 +00:00
{
2009-04-18 09:34:25 +00:00
FlushPrim ( ) ;
2009-02-09 21:15:56 +00:00
}
2010-04-25 00:31:27 +00:00
if ( m_tr . end = = 0 & & len > = m_tr . total )
2009-02-09 21:15:56 +00:00
{
2009-06-05 15:15:02 +00:00
// received all data in one piece, no need to buffer it
// printf("%d >= %d\n", len, m_tr.total);
GSVector4i r ;
2010-04-25 00:31:27 +00:00
2009-06-05 15:15:02 +00:00
r . left = m_env . TRXPOS . DSAX ;
r . top = m_env . TRXPOS . DSAY ;
r . right = r . left + m_env . TRXREG . RRW ;
r . bottom = r . top + m_env . TRXREG . RRH ;
InvalidateVideoMem ( m_env . BITBLTBUF , r ) ;
2011-12-16 19:13:58 +00:00
( m_mem . * psm . wi ) ( m_tr . x , m_tr . y , mem , m_tr . total , m_env . BITBLTBUF , m_env . TRXPOS , m_env . TRXREG ) ;
m_tr . start = m_tr . end = m_tr . total ;
m_perfmon . Put ( GSPerfMon : : Swizzle , len ) ;
2012-01-13 18:10:05 +00:00
/*
static int n = 0 ;
string s ;
s = format ( " c: \\ temp1 \\ [%04d]_%05x_%d_%d_%d_%d_%d_%d.bmp " ,
n + + , ( int ) m_env . BITBLTBUF . DBP , ( int ) m_env . BITBLTBUF . DBW , ( int ) m_env . BITBLTBUF . DPSM ,
r . left , r . top , r . right , r . bottom ) ;
m_mem . SaveBMP ( s , m_env . BITBLTBUF . DBP , m_env . BITBLTBUF . DBW , m_env . BITBLTBUF . DPSM , r . right , r . bottom ) ;
*/
2009-06-05 15:15:02 +00:00
}
else
{
// printf("%d += %d (%d)\n", m_tr.end, len, m_tr.total);
memcpy ( & m_tr . buff [ m_tr . end ] , mem , len ) ;
m_tr . end + = len ;
if ( m_tr . end > = m_tr . total )
{
FlushWrite ( ) ;
}
2009-02-09 21:15:56 +00:00
}
m_mem . m_clut . Invalidate ( ) ;
}
2014-05-02 21:03:02 +00:00
void GSState : : InitReadFIFO ( uint8 * mem , int len )
2009-02-09 21:15:56 +00:00
{
2009-04-18 09:34:25 +00:00
if ( len < = 0 ) return ;
2014-05-02 21:03:02 +00:00
// Allow to keep compatibility with older PCSX2
m_init_read_fifo_supported = true ;
2009-04-18 09:34:25 +00:00
int sx = m_env . TRXPOS . SSAX ;
int sy = m_env . TRXPOS . SSAY ;
int w = m_env . TRXREG . RRW ;
int h = m_env . TRXREG . RRH ;
2009-02-09 21:15:56 +00:00
2009-06-05 15:15:02 +00:00
// printf("Read len=%d SBP=%05x SBW=%d SPSM=%d SSAX=%d SSAY=%d RRW=%d RRH=%d\n", len, (int)m_env.BITBLTBUF.SBP, (int)m_env.BITBLTBUF.SBW, (int)m_env.BITBLTBUF.SPSM, sx, sy, w, h);
2009-02-09 21:15:56 +00:00
2009-04-18 09:34:25 +00:00
if ( ! m_tr . Update ( w , h , GSLocalMemory : : m_psm [ m_env . BITBLTBUF . SPSM ] . trbpp , len ) )
2009-02-09 21:15:56 +00:00
{
2009-04-18 09:34:25 +00:00
return ;
2009-02-09 21:15:56 +00:00
}
2009-04-18 09:34:25 +00:00
if ( m_tr . x = = sx & & m_tr . y = = sy )
{
2009-05-14 16:41:52 +00:00
InvalidateLocalMem ( m_env . BITBLTBUF , GSVector4i ( sx , sy , sx + w , sy + h ) ) ;
2009-04-18 09:34:25 +00:00
}
2014-05-02 21:03:02 +00:00
}
void GSState : : Read ( uint8 * mem , int len )
{
if ( len < = 0 ) return ;
int sx = m_env . TRXPOS . SSAX ;
int sy = m_env . TRXPOS . SSAY ;
int w = m_env . TRXREG . RRW ;
int h = m_env . TRXREG . RRH ;
// printf("Read len=%d SBP=%05x SBW=%d SPSM=%d SSAX=%d SSAY=%d RRW=%d RRH=%d\n", len, (int)m_env.BITBLTBUF.SBP, (int)m_env.BITBLTBUF.SBW, (int)m_env.BITBLTBUF.SPSM, sx, sy, w, h);
if ( ! m_tr . Update ( w , h , GSLocalMemory : : m_psm [ m_env . BITBLTBUF . SPSM ] . trbpp , len ) )
{
return ;
}
2014-09-15 13:49:16 +00:00
if ( ! m_init_read_fifo_supported )
{
2014-05-02 21:03:02 +00:00
if ( m_tr . x = = sx & & m_tr . y = = sy )
{
InvalidateLocalMem ( m_env . BITBLTBUF , GSVector4i ( sx , sy , sx + w , sy + h ) ) ;
}
}
2009-02-09 21:15:56 +00:00
2009-04-18 09:34:25 +00:00
m_mem . ReadImageX ( m_tr . x , m_tr . y , mem , len , m_env . BITBLTBUF , m_env . TRXPOS , m_env . TRXREG ) ;
2009-02-09 21:15:56 +00:00
}
void GSState : : Move ( )
{
// ffxii uses this to move the top/bottom of the scrolling menus offscreen and then blends them back over the text to create a shading effect
// guitar hero copies the far end of the board to do a similar blend too
int sx = m_env . TRXPOS . SSAX ;
int sy = m_env . TRXPOS . SSAY ;
2009-04-18 09:34:25 +00:00
int dx = m_env . TRXPOS . DSAX ;
2009-02-09 21:15:56 +00:00
int dy = m_env . TRXPOS . DSAY ;
int w = m_env . TRXREG . RRW ;
int h = m_env . TRXREG . RRH ;
2015-06-26 16:02:51 +00:00
GL_CACHE ( " Move! 0x%x W:%d F:%d => 0x%x W:%d F:%d (DIR %d%d), sPos(%d %d) dPos(%d %d) size(%d %d) " ,
2015-06-04 20:10:04 +00:00
m_env . BITBLTBUF . SBP , m_env . BITBLTBUF . SBW , m_env . BITBLTBUF . SPSM ,
m_env . BITBLTBUF . DBP , m_env . BITBLTBUF . DBW , m_env . BITBLTBUF . DPSM ,
m_env . TRXPOS . DIRX , m_env . TRXPOS . DIRY ,
sx , sy , dx , dy , w , h ) ;
2009-05-14 16:41:52 +00:00
InvalidateLocalMem ( m_env . BITBLTBUF , GSVector4i ( sx , sy , sx + w , sy + h ) ) ;
InvalidateVideoMem ( m_env . BITBLTBUF , GSVector4i ( dx , dy , dx + w , dy + h ) ) ;
2009-02-09 21:15:56 +00:00
2009-04-18 09:34:25 +00:00
int xinc = 1 ;
int yinc = 1 ;
2009-05-20 15:35:31 +00:00
if ( m_env . TRXPOS . DIRX ) { sx + = w - 1 ; dx + = w - 1 ; xinc = - 1 ; }
if ( m_env . TRXPOS . DIRY ) { sy + = h - 1 ; dy + = h - 1 ; yinc = - 1 ; }
/*
2010-04-25 00:31:27 +00:00
printf ( " %05x %d %d => %05x %d %d (%d%d), %d %d %d %d %d %d \n " ,
2009-05-20 15:35:31 +00:00
m_env . BITBLTBUF . SBP , m_env . BITBLTBUF . SBW , m_env . BITBLTBUF . SPSM ,
m_env . BITBLTBUF . DBP , m_env . BITBLTBUF . DBW , m_env . BITBLTBUF . DPSM ,
m_env . TRXPOS . DIRX , m_env . TRXPOS . DIRY ,
sx , sy , dx , dy , w , h ) ;
*/
2009-04-02 21:22:37 +00:00
/*
GSLocalMemory : : readPixel rp = GSLocalMemory : : m_psm [ m_env . BITBLTBUF . SPSM ] . rp ;
GSLocalMemory : : writePixel wp = GSLocalMemory : : m_psm [ m_env . BITBLTBUF . DPSM ] . wp ;
2009-02-09 21:15:56 +00:00
for ( int y = 0 ; y < h ; y + + , sy + = yinc , dy + = yinc , sx - = xinc * w , dx - = xinc * w )
for ( int x = 0 ; x < w ; x + + , sx + = xinc , dx + = xinc )
( m_mem . * wp ) ( dx , dy , ( m_mem . * rp ) ( sx , sy , m_env . BITBLTBUF . SBP , m_env . BITBLTBUF . SBW ) , m_env . BITBLTBUF . DBP , m_env . BITBLTBUF . DBW ) ;
2009-04-02 21:22:37 +00:00
*/
const GSLocalMemory : : psm_t & spsm = GSLocalMemory : : m_psm [ m_env . BITBLTBUF . SPSM ] ;
const GSLocalMemory : : psm_t & dpsm = GSLocalMemory : : m_psm [ m_env . BITBLTBUF . DPSM ] ;
2009-05-22 01:22:52 +00:00
// TODO: unroll inner loops (width has special size requirement, must be multiples of 1 << n, depending on the format)
2009-07-22 03:55:28 +00:00
GSOffset * RESTRICT spo = m_mem . GetOffset ( m_env . BITBLTBUF . SBP , m_env . BITBLTBUF . SBW , m_env . BITBLTBUF . SPSM ) ;
GSOffset * RESTRICT dpo = m_mem . GetOffset ( m_env . BITBLTBUF . DBP , m_env . BITBLTBUF . DBW , m_env . BITBLTBUF . DPSM ) ;
2009-07-04 15:14:04 +00:00
2009-05-20 15:35:31 +00:00
if ( spsm . trbpp = = dpsm . trbpp & & spsm . trbpp > = 16 )
{
2009-07-22 03:55:28 +00:00
int * RESTRICT scol = & spo - > pixel . col [ 0 ] [ sx ] ;
int * RESTRICT dcol = & dpo - > pixel . col [ 0 ] [ dx ] ;
2009-05-20 15:35:31 +00:00
if ( spsm . trbpp = = 32 )
{
2009-07-06 16:35:06 +00:00
if ( xinc > 0 )
2009-05-20 15:35:31 +00:00
{
2009-07-06 16:35:06 +00:00
for ( int y = 0 ; y < h ; y + + , sy + = yinc , dy + = yinc )
2009-05-20 15:35:31 +00:00
{
2009-07-22 03:55:28 +00:00
uint32 * RESTRICT s = & m_mem . m_vm32 [ spo - > pixel . row [ sy ] ] ;
uint32 * RESTRICT d = & m_mem . m_vm32 [ dpo - > pixel . row [ dy ] ] ;
2009-07-06 16:35:06 +00:00
for ( int x = 0 ; x < w ; x + + ) d [ dcol [ x ] ] = s [ scol [ x ] ] ;
}
}
else
{
for ( int y = 0 ; y < h ; y + + , sy + = yinc , dy + = yinc )
{
2009-07-22 03:55:28 +00:00
uint32 * RESTRICT s = & m_mem . m_vm32 [ spo - > pixel . row [ sy ] ] ;
uint32 * RESTRICT d = & m_mem . m_vm32 [ dpo - > pixel . row [ dy ] ] ;
2009-07-06 16:35:06 +00:00
for ( int x = 0 ; x > - w ; x - - ) d [ dcol [ x ] ] = s [ scol [ x ] ] ;
2009-05-20 15:35:31 +00:00
}
}
}
else if ( spsm . trbpp = = 24 )
{
2009-07-06 16:35:06 +00:00
if ( xinc > 0 )
2009-05-20 15:35:31 +00:00
{
2009-07-06 16:35:06 +00:00
for ( int y = 0 ; y < h ; y + + , sy + = yinc , dy + = yinc )
2009-05-20 15:35:31 +00:00
{
2009-07-22 03:55:28 +00:00
uint32 * RESTRICT s = & m_mem . m_vm32 [ spo - > pixel . row [ sy ] ] ;
uint32 * RESTRICT d = & m_mem . m_vm32 [ dpo - > pixel . row [ dy ] ] ;
2009-07-06 16:35:06 +00:00
for ( int x = 0 ; x < w ; x + + ) d [ dcol [ x ] ] = ( d [ dcol [ x ] ] & 0xff000000 ) | ( s [ scol [ x ] ] & 0x00ffffff ) ;
}
}
else
{
for ( int y = 0 ; y < h ; y + + , sy + = yinc , dy + = yinc )
{
2009-07-22 03:55:28 +00:00
uint32 * RESTRICT s = & m_mem . m_vm32 [ spo - > pixel . row [ sy ] ] ;
uint32 * RESTRICT d = & m_mem . m_vm32 [ dpo - > pixel . row [ dy ] ] ;
2009-07-06 16:35:06 +00:00
for ( int x = 0 ; x > - w ; x - - ) d [ dcol [ x ] ] = ( d [ dcol [ x ] ] & 0xff000000 ) | ( s [ scol [ x ] ] & 0x00ffffff ) ;
2009-05-20 15:35:31 +00:00
}
}
}
else // if(spsm.trbpp == 16)
{
2009-07-06 16:35:06 +00:00
if ( xinc > 0 )
{
for ( int y = 0 ; y < h ; y + + , sy + = yinc , dy + = yinc )
{
2009-07-22 03:55:28 +00:00
uint16 * RESTRICT s = & m_mem . m_vm16 [ spo - > pixel . row [ sy ] ] ;
uint16 * RESTRICT d = & m_mem . m_vm16 [ dpo - > pixel . row [ dy ] ] ;
2009-07-06 16:35:06 +00:00
for ( int x = 0 ; x < w ; x + + ) d [ dcol [ x ] ] = s [ scol [ x ] ] ;
}
}
else
2009-05-20 15:35:31 +00:00
{
2009-07-06 16:35:06 +00:00
for ( int y = 0 ; y < h ; y + + , sy + = yinc , dy + = yinc )
2009-05-20 15:35:31 +00:00
{
2009-07-22 03:55:28 +00:00
uint16 * RESTRICT s = & m_mem . m_vm16 [ spo - > pixel . row [ sy ] ] ;
uint16 * RESTRICT d = & m_mem . m_vm16 [ dpo - > pixel . row [ dy ] ] ;
2009-07-06 16:35:06 +00:00
for ( int x = 0 ; x > - w ; x - - ) d [ dcol [ x ] ] = s [ scol [ x ] ] ;
2009-05-20 15:35:31 +00:00
}
}
}
}
else if ( m_env . BITBLTBUF . SPSM = = PSM_PSMT8 & & m_env . BITBLTBUF . DPSM = = PSM_PSMT8 )
{
2009-07-07 13:04:56 +00:00
if ( xinc > 0 )
2009-05-20 15:35:31 +00:00
{
2009-07-07 13:04:56 +00:00
for ( int y = 0 ; y < h ; y + + , sy + = yinc , dy + = yinc )
{
2009-07-22 03:55:28 +00:00
uint8 * RESTRICT s = & m_mem . m_vm8 [ spo - > pixel . row [ sy ] ] ;
uint8 * RESTRICT d = & m_mem . m_vm8 [ dpo - > pixel . row [ dy ] ] ;
2009-05-20 15:35:31 +00:00
2009-07-22 03:55:28 +00:00
int * RESTRICT scol = & spo - > pixel . col [ sy & 7 ] [ sx ] ;
int * RESTRICT dcol = & dpo - > pixel . col [ dy & 7 ] [ dx ] ;
2009-07-06 16:35:06 +00:00
2009-07-07 13:04:56 +00:00
for ( int x = 0 ; x < w ; x + + ) d [ dcol [ x ] ] = s [ scol [ x ] ] ;
}
}
else
{
for ( int y = 0 ; y < h ; y + + , sy + = yinc , dy + = yinc )
2009-05-20 15:35:31 +00:00
{
2009-07-22 03:55:28 +00:00
uint8 * RESTRICT s = & m_mem . m_vm8 [ spo - > pixel . row [ sy ] ] ;
uint8 * RESTRICT d = & m_mem . m_vm8 [ dpo - > pixel . row [ dy ] ] ;
2009-07-07 13:04:56 +00:00
2009-07-22 03:55:28 +00:00
int * RESTRICT scol = & spo - > pixel . col [ sy & 7 ] [ sx ] ;
int * RESTRICT dcol = & dpo - > pixel . col [ dy & 7 ] [ dx ] ;
2009-07-07 13:04:56 +00:00
2011-02-07 01:59:05 +00:00
for ( int x = 0 ; x > - w ; x - - ) d [ dcol [ x ] ] = s [ scol [ x ] ] ;
2009-05-20 15:35:31 +00:00
}
}
}
else if ( m_env . BITBLTBUF . SPSM = = PSM_PSMT4 & & m_env . BITBLTBUF . DPSM = = PSM_PSMT4 )
2009-04-02 21:22:37 +00:00
{
2009-07-07 13:04:56 +00:00
if ( xinc > 0 )
2009-04-02 21:22:37 +00:00
{
2009-07-07 13:04:56 +00:00
for ( int y = 0 ; y < h ; y + + , sy + = yinc , dy + = yinc )
2009-04-02 21:22:37 +00:00
{
2009-07-22 03:55:28 +00:00
uint32 sbase = spo - > pixel . row [ sy ] ;
uint32 dbase = dpo - > pixel . row [ dy ] ;
2009-07-06 16:35:06 +00:00
2009-07-22 03:55:28 +00:00
int * RESTRICT scol = & spo - > pixel . col [ sy & 7 ] [ sx ] ;
int * RESTRICT dcol = & dpo - > pixel . col [ dy & 7 ] [ dx ] ;
2010-04-25 00:31:27 +00:00
2009-07-07 13:04:56 +00:00
for ( int x = 0 ; x < w ; x + + ) m_mem . WritePixel4 ( dbase + dcol [ x ] , m_mem . ReadPixel4 ( sbase + scol [ x ] ) ) ;
}
}
else
{
for ( int y = 0 ; y < h ; y + + , sy + = yinc , dy + = yinc )
{
2009-07-22 03:55:28 +00:00
uint32 sbase = spo - > pixel . row [ sy ] ;
uint32 dbase = dpo - > pixel . row [ dy ] ;
2009-07-06 16:35:06 +00:00
2009-07-22 03:55:28 +00:00
int * RESTRICT scol = & spo - > pixel . col [ sy & 7 ] [ sx ] ;
int * RESTRICT dcol = & dpo - > pixel . col [ dy & 7 ] [ dx ] ;
2010-04-25 00:31:27 +00:00
2009-07-07 13:04:56 +00:00
for ( int x = 0 ; x > - w ; x - - ) m_mem . WritePixel4 ( dbase + dcol [ x ] , m_mem . ReadPixel4 ( sbase + scol [ x ] ) ) ;
2009-04-02 21:22:37 +00:00
}
}
}
else
{
2009-07-07 13:04:56 +00:00
if ( xinc > 0 )
2009-04-02 21:22:37 +00:00
{
2009-07-07 13:04:56 +00:00
for ( int y = 0 ; y < h ; y + + , sy + = yinc , dy + = yinc )
{
2009-07-22 03:55:28 +00:00
uint32 sbase = spo - > pixel . row [ sy ] ;
uint32 dbase = dpo - > pixel . row [ dy ] ;
2009-04-02 21:22:37 +00:00
2009-07-22 03:55:28 +00:00
int * RESTRICT scol = & spo - > pixel . col [ sy & 7 ] [ sx ] ;
int * RESTRICT dcol = & dpo - > pixel . col [ dy & 7 ] [ dx ] ;
2010-04-25 00:31:27 +00:00
2009-07-07 13:04:56 +00:00
for ( int x = 0 ; x < w ; x + + ) ( m_mem . * dpsm . wpa ) ( dbase + dcol [ x ] , ( m_mem . * spsm . rpa ) ( sbase + scol [ x ] ) ) ;
}
}
else
{
for ( int y = 0 ; y < h ; y + + , sy + = yinc , dy + = yinc )
2009-04-02 21:22:37 +00:00
{
2009-07-22 03:55:28 +00:00
uint32 sbase = spo - > pixel . row [ sy ] ;
uint32 dbase = dpo - > pixel . row [ dy ] ;
2009-07-07 13:04:56 +00:00
2009-07-22 03:55:28 +00:00
int * RESTRICT scol = & spo - > pixel . col [ sy & 7 ] [ sx ] ;
int * RESTRICT dcol = & dpo - > pixel . col [ dy & 7 ] [ dx ] ;
2010-04-25 00:31:27 +00:00
2009-07-07 13:04:56 +00:00
for ( int x = 0 ; x > - w ; x - - ) ( m_mem . * dpsm . wpa ) ( dbase + dcol [ x ] , ( m_mem . * spsm . rpa ) ( sbase + scol [ x ] ) ) ;
2009-04-02 21:22:37 +00:00
}
}
}
2009-02-09 21:15:56 +00:00
}
2011-02-07 01:59:05 +00:00
2009-05-14 16:41:52 +00:00
void GSState : : SoftReset ( uint32 mask )
2009-02-09 21:15:56 +00:00
{
2010-07-11 04:38:33 +00:00
if ( mask & 1 )
{
memset ( & m_path [ 0 ] , 0 , sizeof ( GIFPath ) ) ;
memset ( & m_path [ 3 ] , 0 , sizeof ( GIFPath ) ) ;
}
2011-02-18 01:56:05 +00:00
2009-02-09 21:15:56 +00:00
if ( mask & 2 ) memset ( & m_path [ 1 ] , 0 , sizeof ( GIFPath ) ) ;
if ( mask & 4 ) memset ( & m_path [ 2 ] , 0 , sizeof ( GIFPath ) ) ;
m_env . TRXDIR . XDIR = 3 ; //-1 ; set it to invalid value
2012-01-23 04:11:24 +00:00
m_q = 1.0f ;
2009-02-09 21:15:56 +00:00
}
2009-05-14 16:41:52 +00:00
void GSState : : ReadFIFO ( uint8 * mem , int size )
2009-02-09 21:15:56 +00:00
{
2011-12-22 01:48:16 +00:00
GSPerfMonAutoTimer pmat ( & m_perfmon ) ;
2009-02-09 21:15:56 +00:00
Flush ( ) ;
size * = 16 ;
Read ( mem , size ) ;
if ( m_dump )
{
m_dump . ReadFIFO ( size ) ;
}
}
2010-07-19 15:49:30 +00:00
template void GSState : : Transfer < 0 > ( const uint8 * mem , uint32 size ) ;
template void GSState : : Transfer < 1 > ( const uint8 * mem , uint32 size ) ;
template void GSState : : Transfer < 2 > ( const uint8 * mem , uint32 size ) ;
template void GSState : : Transfer < 3 > ( const uint8 * mem , uint32 size ) ;
2009-02-09 21:15:56 +00:00
2010-07-19 15:49:30 +00:00
template < int index > void GSState : : Transfer ( const uint8 * mem , uint32 size )
2009-02-09 21:15:56 +00:00
{
2011-12-22 01:48:16 +00:00
GSPerfMonAutoTimer pmat ( & m_perfmon ) ;
2009-02-09 21:15:56 +00:00
2010-07-19 15:49:30 +00:00
const uint8 * start = mem ;
2009-02-09 21:15:56 +00:00
GIFPath & path = m_path [ index ] ;
while ( size > 0 )
{
2009-05-09 08:37:02 +00:00
if ( path . nloop = = 0 )
2009-02-09 21:15:56 +00:00
{
path . SetTag ( mem ) ;
mem + = sizeof ( GIFTag ) ;
size - - ;
2009-05-09 08:37:02 +00:00
if ( path . nloop > 0 ) // eeuser 7.2.2. GIFtag: "... when NLOOP is 0, the GIF does not output anything, and values other than the EOP field are disregarded."
2009-02-09 21:15:56 +00:00
{
2012-01-23 04:11:24 +00:00
m_q = 1.0f ;
2009-02-09 21:15:56 +00:00
2009-06-10 17:03:23 +00:00
// ASSERT(!(path.tag.PRE && path.tag.FLG == GIF_FLG_REGLIST)); // kingdom hearts
2009-05-29 06:26:46 +00:00
2011-03-08 01:48:15 +00:00
if ( path . tag . PRE & & path . tag . FLG = = GIF_FLG_PACKED )
2009-02-09 21:15:56 +00:00
{
2012-01-27 11:56:49 +00:00
ApplyPRIM ( path . tag . PRIM ) ;
2009-02-09 21:15:56 +00:00
}
}
}
2009-04-17 01:06:27 +00:00
else
2009-02-09 21:15:56 +00:00
{
2012-01-08 17:10:00 +00:00
uint32 total ;
2009-02-09 21:15:56 +00:00
switch ( path . tag . FLG )
{
case GIF_FLG_PACKED :
2012-01-08 17:10:00 +00:00
// get to the start of the loop
2009-02-09 21:15:56 +00:00
2012-01-08 17:10:00 +00:00
if ( path . reg ! = 0 )
2009-02-09 21:15:56 +00:00
{
2009-05-09 08:37:02 +00:00
do
{
2012-01-08 17:10:00 +00:00
( this - > * m_fpGIFPackedRegHandlers [ path . GetReg ( ) ] ) ( ( GIFPackedReg * ) mem ) ;
2009-02-09 21:15:56 +00:00
2009-05-09 08:37:02 +00:00
mem + = sizeof ( GIFPackedReg ) ;
2012-01-08 17:10:00 +00:00
size - - ;
2009-05-09 08:37:02 +00:00
}
2012-01-08 17:10:00 +00:00
while ( path . StepReg ( ) & & size > 0 & & path . reg ! = 0 ) ;
}
// all data available? usually is
total = path . nloop * path . nreg ;
if ( size > = total )
{
size - = total ;
2012-01-18 11:47:31 +00:00
switch ( path . type )
2012-01-08 17:10:00 +00:00
{
2012-01-18 11:47:31 +00:00
case GIFPath : : TYPE_UNKNOWN :
2012-01-08 17:10:00 +00:00
{
2012-01-18 11:47:31 +00:00
uint32 reg = 0 ;
2012-01-08 17:10:00 +00:00
2012-01-18 11:47:31 +00:00
do
{
( this - > * m_fpGIFPackedRegHandlers [ path . GetReg ( reg + + ) ] ) ( ( GIFPackedReg * ) mem ) ;
mem + = sizeof ( GIFPackedReg ) ;
reg = reg & ( ( int ) ( reg - path . nreg ) > > 31 ) ; // resets reg back to 0 when it becomes equal to path.nreg
}
while ( - - total > 0 ) ;
2012-01-08 17:10:00 +00:00
}
2012-01-18 11:47:31 +00:00
break ;
case GIFPath : : TYPE_ADONLY : // very common
2012-01-08 17:10:00 +00:00
do
{
2012-01-18 11:47:31 +00:00
( this - > * m_fpGIFRegHandlers [ ( ( GIFPackedReg * ) mem ) - > A_D . ADDR ] ) ( & ( ( GIFPackedReg * ) mem ) - > r ) ;
2012-01-08 17:10:00 +00:00
mem + = sizeof ( GIFPackedReg ) ;
}
while ( - - total > 0 ) ;
2012-01-18 11:47:31 +00:00
break ;
case GIFPath : : TYPE_STQRGBAXYZF2 : // majority of the vertices are formatted like this
( this - > * m_fpGIFPackedRegHandlersC [ GIF_REG_STQRGBAXYZF2 ] ) ( ( GIFPackedReg * ) mem , total ) ;
mem + = total * sizeof ( GIFPackedReg ) ;
break ;
2012-01-21 12:34:36 +00:00
case GIFPath : : TYPE_STQRGBAXYZ2 :
( this - > * m_fpGIFPackedRegHandlersC [ GIF_REG_STQRGBAXYZ2 ] ) ( ( GIFPackedReg * ) mem , total ) ;
mem + = total * sizeof ( GIFPackedReg ) ;
break ;
2012-01-18 11:47:31 +00:00
default :
__assume ( 0 ) ;
2012-01-08 17:10:00 +00:00
}
path . nloop = 0 ;
2009-02-09 21:15:56 +00:00
}
else
{
2009-05-09 08:37:02 +00:00
do
2009-02-09 21:15:56 +00:00
{
2011-02-07 01:59:05 +00:00
( this - > * m_fpGIFPackedRegHandlers [ path . GetReg ( ) ] ) ( ( GIFPackedReg * ) mem ) ;
2009-05-09 08:37:02 +00:00
mem + = sizeof ( GIFPackedReg ) ;
size - - ;
2009-02-09 21:15:56 +00:00
}
2009-05-09 08:37:02 +00:00
while ( path . StepReg ( ) & & size > 0 ) ;
2009-02-09 21:15:56 +00:00
}
break ;
case GIF_FLG_REGLIST :
2012-01-08 17:10:00 +00:00
// TODO: do it similar to packed operation
2009-02-09 21:15:56 +00:00
size * = 2 ;
2009-05-09 08:37:02 +00:00
do
2009-02-09 21:15:56 +00:00
{
( this - > * m_fpGIFRegHandlers [ path . GetReg ( ) ] ) ( ( GIFReg * ) mem ) ;
mem + = sizeof ( GIFReg ) ;
2009-05-09 08:37:02 +00:00
size - - ;
2009-02-09 21:15:56 +00:00
}
2009-05-09 08:37:02 +00:00
while ( path . StepReg ( ) & & size > 0 ) ;
2010-04-25 00:31:27 +00:00
2009-02-09 21:15:56 +00:00
if ( size & 1 ) mem + = sizeof ( GIFReg ) ;
size / = 2 ;
break ;
2014-02-22 20:04:32 +00:00
case GIF_FLG_IMAGE2 : // hmmm // Fall through here fixes a crash in Wallace and Gromit Project Zoo
// and according to Pseudonym we shouldn't even land in this code. So hmm indeed. (rama)
/*ASSERT(0);
2009-02-09 21:15:56 +00:00
2009-05-09 08:37:02 +00:00
path . nloop = 0 ;
2009-02-09 21:15:56 +00:00
2014-02-22 20:04:32 +00:00
break ; */
2009-02-09 21:15:56 +00:00
case GIF_FLG_IMAGE :
2009-05-11 08:18:00 +00:00
2009-02-09 21:15:56 +00:00
{
2009-05-09 08:37:02 +00:00
int len = ( int ) min ( size , path . nloop ) ;
2009-02-09 21:15:56 +00:00
//ASSERT(!(len&3));
switch ( m_env . TRXDIR . XDIR )
{
case 0 :
Write ( mem , len * 16 ) ;
break ;
2010-04-25 00:31:27 +00:00
case 1 :
2010-07-19 15:49:30 +00:00
// This can't happen; downloads can not be started or performed as part of
// a GIFtag operation. They're an entirely separate process that can only be
// done through the ReverseFIFO transfer (aka ReadFIFO). --air
2011-02-20 22:33:22 +00:00
ASSERT ( 0 ) ;
2010-07-19 15:49:30 +00:00
//Read(mem, len * 16);
2009-02-09 21:15:56 +00:00
break ;
2010-04-25 00:31:27 +00:00
case 2 :
2009-02-09 21:15:56 +00:00
Move ( ) ;
break ;
2010-04-25 00:31:27 +00:00
case 3 :
2009-02-09 21:15:56 +00:00
ASSERT ( 0 ) ;
break ;
2010-04-25 00:31:27 +00:00
default :
2009-02-09 21:15:56 +00:00
__assume ( 0 ) ;
}
mem + = len * 16 ;
2009-05-09 08:37:02 +00:00
path . nloop - = len ;
2009-02-09 21:15:56 +00:00
size - = len ;
}
break ;
2010-04-25 00:31:27 +00:00
default :
2009-02-09 21:15:56 +00:00
__assume ( 0 ) ;
}
}
2010-07-19 15:49:30 +00:00
if ( index = = 0 )
2009-02-09 21:15:56 +00:00
{
2009-05-09 08:37:02 +00:00
if ( path . tag . EOP & & path . nloop = = 0 )
2009-04-17 01:06:27 +00:00
{
break ;
}
2010-07-19 15:49:30 +00:00
}
2009-02-09 21:15:56 +00:00
}
2009-04-17 01:06:27 +00:00
if ( m_dump & & mem > start )
{
m_dump . Transfer ( index , start , mem - start ) ;
}
2009-02-09 21:15:56 +00:00
2010-07-02 14:31:50 +00:00
if ( index = = 0 )
2009-02-09 21:15:56 +00:00
{
2009-05-09 08:37:02 +00:00
if ( size = = 0 & & path . nloop > 0 )
2009-02-09 21:15:56 +00:00
{
2009-04-17 01:06:27 +00:00
if ( m_mt )
{
2011-02-20 22:33:22 +00:00
// Hackfix for BIOS, which sends an incomplete packet when it does an XGKICK without
2011-03-08 01:48:15 +00:00
// having an EOP specified anywhere in VU1 memory. Needed until PCSX2 is fixed to
2010-07-02 14:31:50 +00:00
// handle it more properly (ie, without looping infinitely).
2009-02-09 21:15:56 +00:00
2009-05-09 08:37:02 +00:00
path . nloop = 0 ;
2009-04-17 01:06:27 +00:00
}
else
{
2011-02-20 22:33:22 +00:00
// Unused in 0.9.7 and above, but might as well keep this for now; allows GSdx
2010-07-02 14:31:50 +00:00
// to work with legacy editions of PCSX2.
2011-02-20 22:33:22 +00:00
2009-04-17 01:06:27 +00:00
Transfer < 0 > ( mem - 0x4000 , 0x4000 / 16 ) ;
}
2009-02-09 21:15:56 +00:00
}
2010-07-02 14:31:50 +00:00
}
2009-02-09 21:15:56 +00:00
}
2009-05-14 16:41:52 +00:00
template < class T > static void WriteState ( uint8 * & dst , T * src , size_t len = sizeof ( T ) )
2009-02-09 21:15:56 +00:00
{
memcpy ( dst , src , len ) ;
dst + = len ;
}
2009-05-14 16:41:52 +00:00
template < class T > static void ReadState ( T * dst , uint8 * & src , size_t len = sizeof ( T ) )
2009-02-09 21:15:56 +00:00
{
memcpy ( dst , src , len ) ;
src + = len ;
}
int GSState : : Freeze ( GSFreezeData * fd , bool sizeonly )
{
if ( sizeonly )
{
fd - > size = m_sssize ;
return 0 ;
}
2010-04-25 00:31:27 +00:00
2009-02-09 21:15:56 +00:00
if ( ! fd - > data | | fd - > size < m_sssize )
{
return - 1 ;
}
Flush ( ) ;
2009-05-14 16:41:52 +00:00
uint8 * data = fd - > data ;
2009-02-09 21:15:56 +00:00
WriteState ( data , & m_version ) ;
WriteState ( data , & m_env . PRIM ) ;
WriteState ( data , & m_env . PRMODE ) ;
WriteState ( data , & m_env . PRMODECONT ) ;
WriteState ( data , & m_env . TEXCLUT ) ;
WriteState ( data , & m_env . SCANMSK ) ;
WriteState ( data , & m_env . TEXA ) ;
WriteState ( data , & m_env . FOGCOL ) ;
WriteState ( data , & m_env . DIMX ) ;
WriteState ( data , & m_env . DTHE ) ;
WriteState ( data , & m_env . COLCLAMP ) ;
WriteState ( data , & m_env . PABE ) ;
WriteState ( data , & m_env . BITBLTBUF ) ;
WriteState ( data , & m_env . TRXDIR ) ;
WriteState ( data , & m_env . TRXPOS ) ;
WriteState ( data , & m_env . TRXREG ) ;
2009-04-18 09:34:25 +00:00
WriteState ( data , & m_env . TRXREG ) ; // obsolete
2009-02-09 21:15:56 +00:00
for ( int i = 0 ; i < 2 ; i + + )
{
WriteState ( data , & m_env . CTXT [ i ] . XYOFFSET ) ;
WriteState ( data , & m_env . CTXT [ i ] . TEX0 ) ;
WriteState ( data , & m_env . CTXT [ i ] . TEX1 ) ;
WriteState ( data , & m_env . CTXT [ i ] . TEX2 ) ;
WriteState ( data , & m_env . CTXT [ i ] . CLAMP ) ;
WriteState ( data , & m_env . CTXT [ i ] . MIPTBP1 ) ;
WriteState ( data , & m_env . CTXT [ i ] . MIPTBP2 ) ;
WriteState ( data , & m_env . CTXT [ i ] . SCISSOR ) ;
WriteState ( data , & m_env . CTXT [ i ] . ALPHA ) ;
WriteState ( data , & m_env . CTXT [ i ] . TEST ) ;
WriteState ( data , & m_env . CTXT [ i ] . FBA ) ;
WriteState ( data , & m_env . CTXT [ i ] . FRAME ) ;
WriteState ( data , & m_env . CTXT [ i ] . ZBUF ) ;
}
WriteState ( data , & m_v . RGBAQ ) ;
WriteState ( data , & m_v . ST ) ;
WriteState ( data , & m_v . UV ) ;
WriteState ( data , & m_v . FOG ) ;
2012-01-08 17:10:00 +00:00
WriteState ( data , & m_v . XYZ ) ;
data + = sizeof ( GIFReg ) ; // obsolite
2009-04-18 09:34:25 +00:00
WriteState ( data , & m_tr . x ) ;
WriteState ( data , & m_tr . y ) ;
2009-02-09 21:15:56 +00:00
WriteState ( data , m_mem . m_vm8 , m_mem . m_vmsize ) ;
2011-02-18 01:56:05 +00:00
for ( size_t i = 0 ; i < countof ( m_path ) ; i + + )
2009-02-09 21:15:56 +00:00
{
2009-05-09 08:37:02 +00:00
m_path [ i ] . tag . NREG = m_path [ i ] . nreg ;
m_path [ i ] . tag . NLOOP = m_path [ i ] . nloop ;
2012-01-27 11:56:49 +00:00
m_path [ i ] . tag . REGS = 0 ;
for ( size_t j = 0 ; j < countof ( m_path [ i ] . regs . u8 ) ; j + + )
{
m_path [ i ] . tag . u32 [ 2 + ( j > > 3 ) ] | = m_path [ i ] . regs . u8 [ j ] < < ( ( j & 7 ) < < 2 ) ;
}
2009-05-09 08:37:02 +00:00
2009-02-09 21:15:56 +00:00
WriteState ( data , & m_path [ i ] . tag ) ;
2009-05-09 08:37:02 +00:00
WriteState ( data , & m_path [ i ] . reg ) ;
2009-02-09 21:15:56 +00:00
}
2012-01-23 04:11:24 +00:00
WriteState ( data , & m_q ) ;
2009-02-09 21:15:56 +00:00
return 0 ;
}
int GSState : : Defrost ( const GSFreezeData * fd )
{
2010-04-25 00:31:27 +00:00
if ( ! fd | | ! fd - > data | | fd - > size = = 0 )
2009-02-09 21:15:56 +00:00
{
return - 1 ;
}
2010-04-25 00:31:27 +00:00
if ( fd - > size < m_sssize )
2009-02-09 21:15:56 +00:00
{
return - 1 ;
}
2009-05-14 16:41:52 +00:00
uint8 * data = fd - > data ;
2009-02-09 21:15:56 +00:00
int version ;
ReadState ( & version , data ) ;
if ( version > m_version )
{
2011-02-18 01:56:05 +00:00
printf ( " GSdx: Savestate version is incompatible. Load aborted. \n " ) ;
2009-02-09 21:15:56 +00:00
return - 1 ;
}
Flush ( ) ;
Reset ( ) ;
ReadState ( & m_env . PRIM , data ) ;
ReadState ( & m_env . PRMODE , data ) ;
ReadState ( & m_env . PRMODECONT , data ) ;
ReadState ( & m_env . TEXCLUT , data ) ;
ReadState ( & m_env . SCANMSK , data ) ;
ReadState ( & m_env . TEXA , data ) ;
ReadState ( & m_env . FOGCOL , data ) ;
ReadState ( & m_env . DIMX , data ) ;
ReadState ( & m_env . DTHE , data ) ;
ReadState ( & m_env . COLCLAMP , data ) ;
ReadState ( & m_env . PABE , data ) ;
ReadState ( & m_env . BITBLTBUF , data ) ;
ReadState ( & m_env . TRXDIR , data ) ;
ReadState ( & m_env . TRXPOS , data ) ;
ReadState ( & m_env . TRXREG , data ) ;
2009-04-18 09:34:25 +00:00
ReadState ( & m_env . TRXREG , data ) ; // obsolete
2009-02-09 21:15:56 +00:00
for ( int i = 0 ; i < 2 ; i + + )
{
ReadState ( & m_env . CTXT [ i ] . XYOFFSET , data ) ;
ReadState ( & m_env . CTXT [ i ] . TEX0 , data ) ;
ReadState ( & m_env . CTXT [ i ] . TEX1 , data ) ;
ReadState ( & m_env . CTXT [ i ] . TEX2 , data ) ;
ReadState ( & m_env . CTXT [ i ] . CLAMP , data ) ;
ReadState ( & m_env . CTXT [ i ] . MIPTBP1 , data ) ;
ReadState ( & m_env . CTXT [ i ] . MIPTBP2 , data ) ;
ReadState ( & m_env . CTXT [ i ] . SCISSOR , data ) ;
ReadState ( & m_env . CTXT [ i ] . ALPHA , data ) ;
ReadState ( & m_env . CTXT [ i ] . TEST , data ) ;
ReadState ( & m_env . CTXT [ i ] . FBA , data ) ;
ReadState ( & m_env . CTXT [ i ] . FRAME , data ) ;
ReadState ( & m_env . CTXT [ i ] . ZBUF , data ) ;
m_env . CTXT [ i ] . XYOFFSET . OFX & = 0xffff ;
m_env . CTXT [ i ] . XYOFFSET . OFY & = 0xffff ;
if ( version < = 4 )
{
2010-04-25 00:31:27 +00:00
data + = sizeof ( uint32 ) * 7 ; // skip
2009-02-09 21:15:56 +00:00
}
}
ReadState ( & m_v . RGBAQ , data ) ;
ReadState ( & m_v . ST , data ) ;
ReadState ( & m_v . UV , data ) ;
ReadState ( & m_v . FOG , data ) ;
2012-01-08 17:10:00 +00:00
ReadState ( & m_v . XYZ , data ) ;
data + = sizeof ( GIFReg ) ; // obsolite
2009-04-18 09:34:25 +00:00
ReadState ( & m_tr . x , data ) ;
ReadState ( & m_tr . y , data ) ;
2009-02-09 21:15:56 +00:00
ReadState ( m_mem . m_vm8 , data , m_mem . m_vmsize ) ;
2009-04-18 09:34:25 +00:00
m_tr . total = 0 ; // TODO: restore transfer state
2011-02-18 01:56:05 +00:00
for ( size_t i = 0 ; i < countof ( m_path ) ; i + + )
2009-02-09 21:15:56 +00:00
{
ReadState ( & m_path [ i ] . tag , data ) ;
2009-05-09 08:37:02 +00:00
ReadState ( & m_path [ i ] . reg , data ) ;
2009-02-09 21:15:56 +00:00
m_path [ i ] . SetTag ( & m_path [ i ] . tag ) ; // expand regs
}
2012-01-23 04:11:24 +00:00
ReadState ( & m_q , data ) ;
2009-02-09 21:15:56 +00:00
PRIM = ! m_env . PRMODECONT . AC ? ( GIFRegPRIM * ) & m_env . PRMODE : & m_env . PRIM ;
2012-01-09 08:41:33 +00:00
UpdateContext ( ) ;
2009-02-09 21:15:56 +00:00
2011-02-07 01:59:05 +00:00
UpdateVertexKick ( ) ;
2009-02-11 07:05:44 +00:00
m_env . UpdateDIMX ( ) ;
2011-02-18 01:56:05 +00:00
for ( size_t i = 0 ; i < 2 ; i + + )
2009-07-22 03:55:28 +00:00
{
m_env . CTXT [ i ] . UpdateScissor ( ) ;
m_env . CTXT [ i ] . offset . fb = m_mem . GetOffset ( m_env . CTXT [ i ] . FRAME . Block ( ) , m_env . CTXT [ i ] . FRAME . FBW , m_env . CTXT [ i ] . FRAME . PSM ) ;
m_env . CTXT [ i ] . offset . zb = m_mem . GetOffset ( m_env . CTXT [ i ] . ZBUF . Block ( ) , m_env . CTXT [ i ] . FRAME . FBW , m_env . CTXT [ i ] . ZBUF . PSM ) ;
m_env . CTXT [ i ] . offset . tex = m_mem . GetOffset ( m_env . CTXT [ i ] . TEX0 . TBP0 , m_env . CTXT [ i ] . TEX0 . TBW , m_env . CTXT [ i ] . TEX0 . PSM ) ;
2012-01-18 11:47:31 +00:00
m_env . CTXT [ i ] . offset . fzb = m_mem . GetPixelOffset ( m_env . CTXT [ i ] . FRAME , m_env . CTXT [ i ] . ZBUF ) ;
m_env . CTXT [ i ] . offset . fzb4 = m_mem . GetPixelOffset4 ( m_env . CTXT [ i ] . FRAME , m_env . CTXT [ i ] . ZBUF ) ;
2009-07-22 03:55:28 +00:00
}
2009-02-09 21:15:56 +00:00
2012-01-09 08:41:33 +00:00
UpdateScissor ( ) ;
2009-02-09 21:15:56 +00:00
m_perfmon . SetFrame ( 5000 ) ;
return 0 ;
}
2009-05-14 16:41:52 +00:00
void GSState : : SetGameCRC ( uint32 crc , int options )
2009-02-09 21:15:56 +00:00
{
m_crc = crc ;
m_options = options ;
2015-06-17 21:41:16 +00:00
m_game = CRC : : Lookup ( m_crc_hack_level ? crc : 0 ) ;
2009-02-09 21:15:56 +00:00
}
2012-01-05 02:40:24 +00:00
//
2012-01-09 08:41:33 +00:00
void GSState : : UpdateContext ( )
{
m_context = & m_env . CTXT [ PRIM - > CTXT ] ;
UpdateScissor ( ) ;
}
void GSState : : UpdateScissor ( )
{
2013-06-17 04:11:10 +00:00
m_scissor = m_context - > scissor . ex ;
2012-01-09 08:41:33 +00:00
m_ofxy = m_context - > scissor . ofxy ;
}
2012-01-05 02:40:24 +00:00
void GSState : : UpdateVertexKick ( )
{
2012-01-21 12:34:36 +00:00
if ( m_frameskip ) return ;
2012-01-08 17:10:00 +00:00
uint32 prim = PRIM - > PRIM ;
m_fpGIFPackedRegHandlers [ GIF_REG_XYZF2 ] = m_fpGIFPackedRegHandlerXYZ [ prim ] [ 0 ] ;
m_fpGIFPackedRegHandlers [ GIF_REG_XYZF3 ] = m_fpGIFPackedRegHandlerXYZ [ prim ] [ 1 ] ;
m_fpGIFPackedRegHandlers [ GIF_REG_XYZ2 ] = m_fpGIFPackedRegHandlerXYZ [ prim ] [ 2 ] ;
m_fpGIFPackedRegHandlers [ GIF_REG_XYZ3 ] = m_fpGIFPackedRegHandlerXYZ [ prim ] [ 3 ] ;
m_fpGIFRegHandlers [ GIF_A_D_REG_XYZF2 ] = m_fpGIFRegHandlerXYZ [ prim ] [ 0 ] ;
m_fpGIFRegHandlers [ GIF_A_D_REG_XYZF3 ] = m_fpGIFRegHandlerXYZ [ prim ] [ 1 ] ;
m_fpGIFRegHandlers [ GIF_A_D_REG_XYZ2 ] = m_fpGIFRegHandlerXYZ [ prim ] [ 2 ] ;
m_fpGIFRegHandlers [ GIF_A_D_REG_XYZ3 ] = m_fpGIFRegHandlerXYZ [ prim ] [ 3 ] ;
2012-01-18 11:47:31 +00:00
m_fpGIFPackedRegHandlersC [ GIF_REG_STQRGBAXYZF2 ] = m_fpGIFPackedRegHandlerSTQRGBAXYZF2 [ prim ] ;
2012-01-21 12:34:36 +00:00
m_fpGIFPackedRegHandlersC [ GIF_REG_STQRGBAXYZ2 ] = m_fpGIFPackedRegHandlerSTQRGBAXYZ2 [ prim ] ;
2012-01-05 02:40:24 +00:00
}
void GSState : : GrowVertexBuffer ( )
{
int maxcount = std : : max < int > ( m_vertex . maxcount * 3 / 2 , 10000 ) ;
2013-06-17 04:11:10 +00:00
GSVertex * vertex = ( GSVertex * ) _aligned_malloc ( sizeof ( GSVertex ) * maxcount , 32 ) ;
uint32 * index = ( uint32 * ) _aligned_malloc ( sizeof ( uint32 ) * maxcount * 3 , 32 ) ; // worst case is slightly less than vertex number * 3
2012-01-05 02:40:24 +00:00
2014-09-15 13:49:16 +00:00
if ( vertex = = NULL | | index = = NULL )
2014-01-25 19:14:28 +00:00
{
2016-01-22 08:58:10 +00:00
printf ( " GSdx: failed to allocate %d bytes for verticles and %d for indices. \n " , ( int ) sizeof ( GSVertex ) * maxcount , ( int ) sizeof ( uint32 ) * maxcount * 3 ) ;
2014-01-25 19:14:28 +00:00
throw GSDXError ( ) ;
}
2014-09-15 13:49:16 +00:00
if ( m_vertex . buff ! = NULL )
2012-01-05 02:40:24 +00:00
{
2012-01-19 04:53:36 +00:00
memcpy ( vertex , m_vertex . buff , sizeof ( GSVertex ) * m_vertex . tail ) ;
2012-01-05 02:40:24 +00:00
_aligned_free ( m_vertex . buff ) ;
}
2014-09-15 13:49:16 +00:00
if ( m_index . buff ! = NULL )
2012-01-05 02:40:24 +00:00
{
memcpy ( index , m_index . buff , sizeof ( uint32 ) * m_index . tail ) ;
_aligned_free ( m_index . buff ) ;
}
m_vertex . buff = vertex ;
2012-01-08 21:02:42 +00:00
m_vertex . maxcount = maxcount - 3 ; // -3 to have some space at the end of the buffer before DrawingKick can grow it
2012-01-05 02:40:24 +00:00
m_index . buff = index ;
}
2012-01-06 00:17:52 +00:00
template < uint32 prim >
2012-01-08 17:10:00 +00:00
__forceinline void GSState : : VertexKick ( uint32 skip )
2012-01-05 02:40:24 +00:00
{
2013-06-23 10:46:24 +00:00
ASSERT ( m_vertex . tail < m_vertex . maxcount + 3 ) ;
2012-01-08 21:02:42 +00:00
2012-01-06 00:17:52 +00:00
size_t head = m_vertex . head ;
size_t tail = m_vertex . tail ;
size_t next = m_vertex . next ;
2012-01-08 17:10:00 +00:00
size_t xy_tail = m_vertex . xy_tail ;
// callers should write XYZUVF to m_v.m[1] in one piece to have this load store-forwarded, either by the cpu or the compiler when this function is inlined
GSVector4i v0 ( m_v . m [ 0 ] ) ;
GSVector4i v1 ( m_v . m [ 1 ] ) ;
2012-01-19 04:53:36 +00:00
GSVector4i * RESTRICT tailptr = ( GSVector4i * ) & m_vertex . buff [ tail ] ;
2012-01-08 17:10:00 +00:00
tailptr [ 0 ] = v0 ;
tailptr [ 1 ] = v1 ;
2013-06-24 01:11:00 +00:00
GSVector4i xy = v1 . xxxx ( ) . u16to32 ( ) . sub32 ( m_ofxy ) ;
2013-06-17 04:11:10 +00:00
2013-06-24 01:11:00 +00:00
# if _M_SSE >= 0x401
GSVector4i : : storel ( & m_vertex . xy [ xy_tail & 3 ] , xy . blend16 < 0xf0 > ( xy . sra32 ( 4 ) ) . ps32 ( ) ) ;
2013-06-17 04:11:10 +00:00
# else
2013-06-24 01:11:00 +00:00
GSVector4i : : storel ( & m_vertex . xy [ xy_tail & 3 ] , xy . upl64 ( xy . sra32 ( 4 ) . zwzw ( ) ) . ps32 ( ) ) ;
2013-06-17 04:11:10 +00:00
# endif
2012-01-08 17:10:00 +00:00
m_vertex . tail = + + tail ;
m_vertex . xy_tail = + + xy_tail ;
2012-01-06 00:17:52 +00:00
size_t n = 0 ;
2012-01-05 02:40:24 +00:00
2012-01-06 00:17:52 +00:00
switch ( prim )
2012-01-05 02:40:24 +00:00
{
2012-01-06 00:17:52 +00:00
case GS_POINTLIST : n = 1 ; break ;
case GS_LINELIST : n = 2 ; break ;
case GS_LINESTRIP : n = 2 ; break ;
case GS_TRIANGLELIST : n = 3 ; break ;
case GS_TRIANGLESTRIP : n = 3 ; break ;
case GS_TRIANGLEFAN : n = 3 ; break ;
case GS_SPRITE : n = 2 ; break ;
case GS_INVALID : n = 1 ; break ;
2012-01-05 02:40:24 +00:00
}
2012-01-06 00:17:52 +00:00
size_t m = tail - head ;
if ( m < n )
{
return ;
}
2012-01-08 17:10:00 +00:00
if ( skip = = 0 & & ( prim ! = GS_TRIANGLEFAN | | m < = 4 ) ) // m_vertex.xy only knows about the last 4 vertices, head could be far behind for fan
2012-01-06 00:17:52 +00:00
{
2013-06-17 04:11:10 +00:00
GSVector4i v0 , v1 , v2 , v3 , pmin , pmax ;
2012-01-06 00:17:52 +00:00
2013-06-17 04:11:10 +00:00
v0 = GSVector4i : : loadl ( & m_vertex . xy [ ( xy_tail + 1 ) & 3 ] ) ; // T-3
v1 = GSVector4i : : loadl ( & m_vertex . xy [ ( xy_tail + 2 ) & 3 ] ) ; // T-2
v2 = GSVector4i : : loadl ( & m_vertex . xy [ ( xy_tail + 3 ) & 3 ] ) ; // T-1
v3 = GSVector4i : : loadl ( & m_vertex . xy [ ( xy_tail - m ) & 3 ] ) ; // H
2012-01-06 00:17:52 +00:00
2013-06-17 04:11:10 +00:00
GSVector4 cross ;
2012-01-06 00:17:52 +00:00
switch ( prim )
{
case GS_POINTLIST :
2012-01-08 17:10:00 +00:00
pmin = v2 ;
pmax = v2 ;
2012-01-06 00:17:52 +00:00
break ;
case GS_LINELIST :
case GS_LINESTRIP :
case GS_SPRITE :
2013-06-17 04:11:10 +00:00
pmin = v2 . min_i16 ( v1 ) ;
pmax = v2 . max_i16 ( v1 ) ;
2012-01-08 17:10:00 +00:00
break ;
case GS_TRIANGLELIST :
case GS_TRIANGLESTRIP :
2013-06-17 04:11:10 +00:00
pmin = v2 . min_i16 ( v1 . min_i16 ( v0 ) ) ;
pmax = v2 . max_i16 ( v1 . max_i16 ( v0 ) ) ;
2012-01-08 17:10:00 +00:00
break ;
case GS_TRIANGLEFAN :
2013-06-17 04:11:10 +00:00
pmin = v2 . min_i16 ( v1 . min_i16 ( v3 ) ) ;
pmax = v2 . max_i16 ( v1 . max_i16 ( v3 ) ) ;
2012-01-08 17:10:00 +00:00
break ;
2014-07-12 14:00:10 +00:00
default :
break ;
2012-01-08 17:10:00 +00:00
}
2013-06-17 04:11:10 +00:00
GSVector4i test = pmax . lt16 ( m_scissor ) | pmin . gt16 ( m_scissor . zwzwl ( ) ) ;
2012-01-08 17:10:00 +00:00
switch ( prim )
{
case GS_TRIANGLELIST :
case GS_TRIANGLESTRIP :
case GS_TRIANGLEFAN :
case GS_SPRITE :
2013-06-17 04:11:10 +00:00
test | = m_nativeres ? pmin . eq16 ( pmax ) . zwzwl ( ) : pmin . eq16 ( pmax ) ;
2012-01-06 00:17:52 +00:00
break ;
2014-07-12 14:00:10 +00:00
default :
break ;
2012-01-08 17:10:00 +00:00
}
switch ( prim )
{
2012-01-06 00:17:52 +00:00
case GS_TRIANGLELIST :
case GS_TRIANGLESTRIP :
2013-06-17 04:11:10 +00:00
// TODO: any way to do a 16-bit integer cross product?
2013-06-23 10:46:24 +00:00
// cross product is zero most of the time because either of the vertices are the same
/*
2013-06-17 04:11:10 +00:00
cross = GSVector4 ( v2 . xyxyl ( ) . i16to32 ( ) . sub32 ( v0 . upl32 ( v1 ) . i16to32 ( ) ) ) ; // x20, y20, x21, y21
cross = cross * cross . wzwz ( ) ; // x20 * y21, y20 * x21
test | = GSVector4i : : cast ( cross = = cross . yxwz ( ) ) ;
2013-06-23 10:46:24 +00:00
*/
test = ( test | v0 = = v1 ) | ( v1 = = v2 | v0 = = v2 ) ;
2012-01-06 00:17:52 +00:00
break ;
case GS_TRIANGLEFAN :
2013-06-23 10:46:24 +00:00
/*
2013-06-17 04:11:10 +00:00
cross = GSVector4 ( v2 . xyxyl ( ) . i16to32 ( ) . sub32 ( v3 . upl32 ( v1 ) . i16to32 ( ) ) ) ; // x23, y23, x21, y21
cross = cross * cross . wzwz ( ) ; // x23 * y21, y23 * x21
test | = GSVector4i : : cast ( cross = = cross . yxwz ( ) ) ;
2013-06-23 10:46:24 +00:00
*/
2013-06-23 12:13:40 +00:00
test = ( test | v3 = = v1 ) | ( v1 = = v2 | v3 = = v2 ) ;
2012-01-06 00:17:52 +00:00
break ;
2014-07-12 14:00:10 +00:00
default :
break ;
2012-01-06 00:17:52 +00:00
}
2012-01-08 17:10:00 +00:00
2013-06-17 04:11:10 +00:00
skip | = test . mask ( ) & 15 ;
2012-01-06 00:17:52 +00:00
}
if ( skip ! = 0 )
2012-01-05 02:40:24 +00:00
{
switch ( prim )
{
case GS_POINTLIST :
case GS_LINELIST :
case GS_TRIANGLELIST :
case GS_SPRITE :
case GS_INVALID :
2012-01-08 21:02:42 +00:00
m_vertex . tail = head ; // no need to check or grow the buffer length
2012-01-05 02:40:24 +00:00
break ;
case GS_LINESTRIP :
case GS_TRIANGLESTRIP :
2012-01-06 00:17:52 +00:00
m_vertex . head = head + 1 ;
2012-01-08 21:02:42 +00:00
// fall through
2012-01-05 02:40:24 +00:00
case GS_TRIANGLEFAN :
2012-01-08 21:02:42 +00:00
if ( tail > = m_vertex . maxcount ) GrowVertexBuffer ( ) ; // in case too many vertices were skipped
2012-01-05 02:40:24 +00:00
break ;
default :
__assume ( 0 ) ;
}
return ;
}
2012-01-08 21:02:42 +00:00
if ( tail > = m_vertex . maxcount ) GrowVertexBuffer ( ) ;
2012-01-05 02:40:24 +00:00
uint32 * RESTRICT buff = & m_index . buff [ m_index . tail ] ;
switch ( prim )
{
case GS_POINTLIST :
buff [ 0 ] = head + 0 ;
m_vertex . head = head + 1 ;
2012-01-06 00:17:52 +00:00
m_vertex . next = head + 1 ;
2012-01-05 02:40:24 +00:00
m_index . tail + = 1 ;
break ;
case GS_LINELIST :
buff [ 0 ] = head + 0 ;
buff [ 1 ] = head + 1 ;
m_vertex . head = head + 2 ;
2012-01-06 00:17:52 +00:00
m_vertex . next = head + 2 ;
2012-01-05 02:40:24 +00:00
m_index . tail + = 2 ;
break ;
case GS_LINESTRIP :
2012-01-19 04:53:36 +00:00
if ( next < head )
{
m_vertex . buff [ next + 0 ] = m_vertex . buff [ head + 0 ] ;
m_vertex . buff [ next + 1 ] = m_vertex . buff [ head + 1 ] ;
head = next ;
m_vertex . tail = next + 2 ;
}
2012-01-05 02:40:24 +00:00
buff [ 0 ] = head + 0 ;
buff [ 1 ] = head + 1 ;
m_vertex . head = head + 1 ;
2012-01-06 00:17:52 +00:00
m_vertex . next = head + 2 ;
2012-01-05 02:40:24 +00:00
m_index . tail + = 2 ;
break ;
case GS_TRIANGLELIST :
buff [ 0 ] = head + 0 ;
buff [ 1 ] = head + 1 ;
buff [ 2 ] = head + 2 ;
m_vertex . head = head + 3 ;
2012-01-06 00:17:52 +00:00
m_vertex . next = head + 3 ;
2012-01-05 02:40:24 +00:00
m_index . tail + = 3 ;
break ;
2012-01-06 00:17:52 +00:00
case GS_TRIANGLESTRIP :
2012-01-19 04:53:36 +00:00
if ( next < head )
{
m_vertex . buff [ next + 0 ] = m_vertex . buff [ head + 0 ] ;
m_vertex . buff [ next + 1 ] = m_vertex . buff [ head + 1 ] ;
m_vertex . buff [ next + 2 ] = m_vertex . buff [ head + 2 ] ;
head = next ;
m_vertex . tail = next + 3 ;
}
2012-01-05 02:40:24 +00:00
buff [ 0 ] = head + 0 ;
buff [ 1 ] = head + 1 ;
buff [ 2 ] = head + 2 ;
m_vertex . head = head + 1 ;
2012-01-06 00:17:52 +00:00
m_vertex . next = head + 3 ;
2012-01-05 02:40:24 +00:00
m_index . tail + = 3 ;
break ;
case GS_TRIANGLEFAN :
2012-01-08 17:10:00 +00:00
// TODO: remove gaps, next == head && head < tail - 3 || next > head && next < tail - 2 (very rare)
2012-01-05 02:40:24 +00:00
buff [ 0 ] = head + 0 ;
buff [ 1 ] = tail - 2 ;
buff [ 2 ] = tail - 1 ;
2012-01-06 00:17:52 +00:00
m_vertex . next = tail ;
m_index . tail + = 3 ;
2012-01-05 02:40:24 +00:00
break ;
2012-01-06 00:17:52 +00:00
case GS_SPRITE :
2012-01-05 02:40:24 +00:00
buff [ 0 ] = head + 0 ;
buff [ 1 ] = head + 1 ;
m_vertex . head = head + 2 ;
2012-01-06 00:17:52 +00:00
m_vertex . next = head + 2 ;
2012-01-05 02:40:24 +00:00
m_index . tail + = 2 ;
break ;
2012-01-19 04:53:36 +00:00
case GS_INVALID :
2012-01-05 02:40:24 +00:00
m_vertex . tail = head ;
break ;
default :
__assume ( 0 ) ;
}
}
void GSState : : GetTextureMinMax ( GSVector4i & r , const GIFRegTEX0 & TEX0 , const GIFRegCLAMP & CLAMP , bool linear )
{
2015-08-05 17:10:55 +00:00
// TODO: some of the +1s can be removed if linear == false
2012-01-05 02:40:24 +00:00
int tw = TEX0 . TW ;
int th = TEX0 . TH ;
int w = 1 < < tw ;
int h = 1 < < th ;
GSVector4i tr ( 0 , 0 , w , h ) ;
int wms = CLAMP . WMS ;
int wmt = CLAMP . WMT ;
int minu = ( int ) CLAMP . MINU ;
int minv = ( int ) CLAMP . MINV ;
int maxu = ( int ) CLAMP . MAXU ;
int maxv = ( int ) CLAMP . MAXV ;
GSVector4i vr = tr ;
switch ( wms )
{
case CLAMP_REPEAT :
break ;
case CLAMP_CLAMP :
break ;
case CLAMP_REGION_CLAMP :
if ( vr . x < minu ) vr . x = minu ;
if ( vr . z > maxu + 1 ) vr . z = maxu + 1 ;
break ;
case CLAMP_REGION_REPEAT :
vr . x = maxu ;
vr . z = vr . x + ( minu + 1 ) ;
break ;
default :
__assume ( 0 ) ;
}
switch ( wmt )
{
case CLAMP_REPEAT :
break ;
case CLAMP_CLAMP :
break ;
case CLAMP_REGION_CLAMP :
if ( vr . y < minv ) vr . y = minv ;
if ( vr . w > maxv + 1 ) vr . w = maxv + 1 ;
break ;
case CLAMP_REGION_REPEAT :
vr . y = maxv ;
vr . w = vr . y + ( minv + 1 ) ;
break ;
default :
__assume ( 0 ) ;
}
2013-04-10 15:57:21 +00:00
if ( wms ! = CLAMP_REGION_REPEAT | | wmt ! = CLAMP_REGION_REPEAT )
2012-01-05 02:40:24 +00:00
{
2015-08-04 01:34:46 +00:00
GSVector4 st = m_vt . m_min . t . xyxy ( m_vt . m_max . t ) ;
2012-01-05 02:40:24 +00:00
if ( linear )
{
2015-08-04 01:34:46 +00:00
st + = GSVector4 ( - 0.5f , 0.5f ) . xxyy ( ) ;
2012-01-05 02:40:24 +00:00
}
2015-08-04 01:34:46 +00:00
GSVector4i uv = GSVector4i ( st . floor ( ) ) ;
2012-01-05 02:40:24 +00:00
GSVector4i u , v ;
int mask = 0 ;
2013-04-10 15:57:21 +00:00
// See commented code below for the meaning of mask
2015-08-04 11:27:08 +00:00
2012-01-05 02:40:24 +00:00
if ( wms = = CLAMP_REPEAT | | wmt = = CLAMP_REPEAT )
{
u = uv & GSVector4i : : xffffffff ( ) . srl32 ( 32 - tw ) ;
v = uv & GSVector4i : : xffffffff ( ) . srl32 ( 32 - th ) ;
GSVector4i uu = uv . sra32 ( tw ) ;
GSVector4i vv = uv . sra32 ( th ) ;
mask = ( uu . upl32 ( vv ) = = uu . uph32 ( vv ) ) . mask ( ) ;
}
GSdx:
- changed the KH2 fix in GetTextureMinMax to my taste, should give the same results, when the used texture rect is to the left/above the clamped area, it returns [min, min+1], and [max-1, max] for right/below
- m_mem.m_clut.Read32 was returned to its original place from GetAlphaMinMax
- UserHacks_WildHack was moved up to GSState, special UV handlers are only used when this setting is active
- updated xbyak to the latest available (avx2 seems incomplete, the 256-bit promoted old instructions are missing)
- changed vtune's include path to the 2013 edition
Some other not yet commited changes from a year ago:
- WriteImageX overflow crash-fix
- moved colclamp after dithering (sw mode), it makes more sense, no visible changes noticed
- Gif_Tag::analyzeTag(), there was a conditional I didn't like, split the loop into two parts
git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5649 96395faa-99c1-11dd-bbfe-3dabce05a288
2013-06-06 11:36:01 +00:00
uv = uv . rintersect ( tr ) ;
2012-01-05 02:40:24 +00:00
switch ( wms )
{
case CLAMP_REPEAT :
2013-04-10 15:57:21 +00:00
// This commented code cannot be used directly because it needs uv before the intersection
/*if (uv_.x >> tw == uv_.z >> tw)
{
vr . x = max ( vr . x , ( uv_ . x & ( ( 1 < < tw ) - 1 ) ) ) ;
vr . z = min ( vr . z , ( uv_ . z & ( ( 1 < < tw ) - 1 ) ) + 1 ) ;
} */
2012-01-05 02:40:24 +00:00
if ( mask & 0x000f ) { if ( vr . x < u . x ) vr . x = u . x ; if ( vr . z > u . z + 1 ) vr . z = u . z + 1 ; }
break ;
case CLAMP_CLAMP :
case CLAMP_REGION_CLAMP :
GSdx:
- changed the KH2 fix in GetTextureMinMax to my taste, should give the same results, when the used texture rect is to the left/above the clamped area, it returns [min, min+1], and [max-1, max] for right/below
- m_mem.m_clut.Read32 was returned to its original place from GetAlphaMinMax
- UserHacks_WildHack was moved up to GSState, special UV handlers are only used when this setting is active
- updated xbyak to the latest available (avx2 seems incomplete, the 256-bit promoted old instructions are missing)
- changed vtune's include path to the 2013 edition
Some other not yet commited changes from a year ago:
- WriteImageX overflow crash-fix
- moved colclamp after dithering (sw mode), it makes more sense, no visible changes noticed
- Gif_Tag::analyzeTag(), there was a conditional I didn't like, split the loop into two parts
git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5649 96395faa-99c1-11dd-bbfe-3dabce05a288
2013-06-06 11:36:01 +00:00
if ( vr . x > uv . z ) vr . z = vr . x + 1 ;
else if ( vr . z < uv . x ) vr . x = vr . z - 1 ;
else
{
if ( vr . x < uv . x ) vr . x = uv . x ;
if ( vr . z > uv . z + 1 ) vr . z = uv . z + 1 ;
}
2012-01-05 02:40:24 +00:00
break ;
case CLAMP_REGION_REPEAT :
break ;
default :
__assume ( 0 ) ;
}
switch ( wmt )
{
case CLAMP_REPEAT :
2013-04-10 15:57:21 +00:00
/*if (uv_.y >> th == uv_.w >> th)
{
vr . y = max ( vr . y , ( uv_ . y & ( ( 1 < < th ) - 1 ) ) ) ;
vr . w = min ( vr . w , ( uv_ . w & ( ( 1 < < th ) - 1 ) ) + 1 ) ;
} */
2012-01-05 02:40:24 +00:00
if ( mask & 0xf000 ) { if ( vr . y < v . y ) vr . y = v . y ; if ( vr . w > v . w + 1 ) vr . w = v . w + 1 ; }
break ;
case CLAMP_CLAMP :
case CLAMP_REGION_CLAMP :
GSdx:
- changed the KH2 fix in GetTextureMinMax to my taste, should give the same results, when the used texture rect is to the left/above the clamped area, it returns [min, min+1], and [max-1, max] for right/below
- m_mem.m_clut.Read32 was returned to its original place from GetAlphaMinMax
- UserHacks_WildHack was moved up to GSState, special UV handlers are only used when this setting is active
- updated xbyak to the latest available (avx2 seems incomplete, the 256-bit promoted old instructions are missing)
- changed vtune's include path to the 2013 edition
Some other not yet commited changes from a year ago:
- WriteImageX overflow crash-fix
- moved colclamp after dithering (sw mode), it makes more sense, no visible changes noticed
- Gif_Tag::analyzeTag(), there was a conditional I didn't like, split the loop into two parts
git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5649 96395faa-99c1-11dd-bbfe-3dabce05a288
2013-06-06 11:36:01 +00:00
if ( vr . y > uv . w ) vr . w = vr . y + 1 ;
else if ( vr . w < uv . y ) vr . y = vr . w - 1 ;
else
{
if ( vr . y < uv . y ) vr . y = uv . y ;
if ( vr . w > uv . w + 1 ) vr . w = uv . w + 1 ;
}
2012-01-05 02:40:24 +00:00
break ;
case CLAMP_REGION_REPEAT :
break ;
default :
__assume ( 0 ) ;
}
}
2012-01-08 17:10:00 +00:00
vr = vr . rintersect ( tr ) ;
2013-04-10 15:57:21 +00:00
// This really shouldn't happen now except with the clamping region set entirely outside the texture,
// special handling should be written for that case.
2015-08-04 01:34:46 +00:00
2012-01-08 17:10:00 +00:00
if ( vr . rempty ( ) )
{
// NOTE: this can happen when texcoords are all outside the texture or clamping area is zero, but we can't
// let the texture cache update nothing, the sampler will still need a single texel from the border somewhere
// examples:
// - THPS (no visible problems)
// - NFSMW (strange rectangles on screen, might be unrelated)
2015-08-04 01:34:46 +00:00
// - Lupin 3rd (huge problems, textures sizes seem to be randomly specified)
2012-01-08 17:10:00 +00:00
vr = ( vr + GSVector4i ( - 1 , + 1 ) . xxyy ( ) ) . rintersect ( tr ) ;
}
r = vr ;
2012-01-05 02:40:24 +00:00
}
void GSState : : GetAlphaMinMax ( )
{
2012-01-19 04:53:36 +00:00
if ( m_vt . m_alpha . valid )
2012-01-05 02:40:24 +00:00
{
return ;
}
const GSDrawingEnvironment & env = m_env ;
const GSDrawingContext * context = m_context ;
2012-01-19 04:53:36 +00:00
GSVector4i a = m_vt . m_min . c . uph32 ( m_vt . m_max . c ) . zzww ( ) ;
2012-01-05 02:40:24 +00:00
if ( PRIM - > TME & & context - > TEX0 . TCC )
{
2012-06-19 01:57:13 +00:00
switch ( GSLocalMemory : : m_psm [ context - > TEX0 . PSM ] . fmt )
2012-01-05 02:40:24 +00:00
{
case 0 :
a . y = 0 ;
a . w = 0xff ;
break ;
case 1 :
a . y = env . TEXA . AEM ? 0 : env . TEXA . TA0 ;
a . w = env . TEXA . TA0 ;
break ;
case 2 :
a . y = env . TEXA . AEM ? 0 : min ( env . TEXA . TA0 , env . TEXA . TA1 ) ;
a . w = max ( env . TEXA . TA0 , env . TEXA . TA1 ) ;
break ;
2012-06-19 01:57:13 +00:00
case 3 :
m_mem . m_clut . GetAlphaMinMax32 ( a . y , a . w ) ;
break ;
2012-01-05 02:40:24 +00:00
default :
__assume ( 0 ) ;
}
switch ( context - > TEX0 . TFX )
{
case TFX_MODULATE :
a . x = ( a . x * a . y ) > > 7 ;
a . z = ( a . z * a . w ) > > 7 ;
if ( a . x > 0xff ) a . x = 0xff ;
if ( a . z > 0xff ) a . z = 0xff ;
break ;
case TFX_DECAL :
a . x = a . y ;
a . z = a . w ;
break ;
case TFX_HIGHLIGHT :
a . x = a . x + a . y ;
a . z = a . z + a . w ;
if ( a . x > 0xff ) a . x = 0xff ;
if ( a . z > 0xff ) a . z = 0xff ;
break ;
case TFX_HIGHLIGHT2 :
a . x = a . y ;
a . z = a . w ;
break ;
default :
__assume ( 0 ) ;
}
}
2012-01-19 04:53:36 +00:00
m_vt . m_alpha . min = a . x ;
m_vt . m_alpha . max = a . z ;
m_vt . m_alpha . valid = true ;
2012-01-05 02:40:24 +00:00
}
bool GSState : : TryAlphaTest ( uint32 & fm , uint32 & zm )
{
const GSDrawingContext * context = m_context ;
bool pass = true ;
if ( context - > TEST . ATST = = ATST_NEVER )
{
pass = false ;
}
else if ( context - > TEST . ATST ! = ATST_ALWAYS )
{
GetAlphaMinMax ( ) ;
2012-01-19 04:53:36 +00:00
int amin = m_vt . m_alpha . min ;
int amax = m_vt . m_alpha . max ;
2012-01-05 02:40:24 +00:00
int aref = context - > TEST . AREF ;
switch ( context - > TEST . ATST )
{
case ATST_NEVER :
pass = false ;
break ;
case ATST_ALWAYS :
pass = true ;
break ;
case ATST_LESS :
if ( amax < aref ) pass = true ;
else if ( amin > = aref ) pass = false ;
else return false ;
break ;
case ATST_LEQUAL :
if ( amax < = aref ) pass = true ;
else if ( amin > aref ) pass = false ;
else return false ;
break ;
case ATST_EQUAL :
if ( amin = = aref & & amax = = aref ) pass = true ;
else if ( amin > aref | | amax < aref ) pass = false ;
else return false ;
break ;
case ATST_GEQUAL :
if ( amin > = aref ) pass = true ;
else if ( amax < aref ) pass = false ;
else return false ;
break ;
case ATST_GREATER :
if ( amin > aref ) pass = true ;
else if ( amax < = aref ) pass = false ;
else return false ;
break ;
case ATST_NOTEQUAL :
if ( amin = = aref & & amax = = aref ) pass = false ;
else if ( amin > aref | | amax < aref ) pass = true ;
else return false ;
break ;
default :
__assume ( 0 ) ;
}
}
if ( ! pass )
{
switch ( context - > TEST . AFAIL )
{
case AFAIL_KEEP : fm = zm = 0xffffffff ; break ;
case AFAIL_FB_ONLY : zm = 0xffffffff ; break ;
case AFAIL_ZB_ONLY : fm = 0xffffffff ; break ;
case AFAIL_RGB_ONLY : fm | = 0xff000000 ; zm = 0xffffffff ; break ;
default : __assume ( 0 ) ;
}
}
return true ;
}
bool GSState : : IsOpaque ( )
{
if ( PRIM - > AA1 )
{
return false ;
}
if ( ! PRIM - > ABE )
{
return true ;
}
const GSDrawingContext * context = m_context ;
int amin = 0 , amax = 0xff ;
if ( context - > ALPHA . A ! = context - > ALPHA . B )
{
if ( context - > ALPHA . C = = 0 )
{
GetAlphaMinMax ( ) ;
2012-01-19 04:53:36 +00:00
amin = m_vt . m_alpha . min ;
amax = m_vt . m_alpha . max ;
2012-01-05 02:40:24 +00:00
}
else if ( context - > ALPHA . C = = 1 )
{
if ( context - > FRAME . PSM = = PSM_PSMCT24 | | context - > FRAME . PSM = = PSM_PSMZ24 )
{
amin = amax = 0x80 ;
}
}
else if ( context - > ALPHA . C = = 2 )
{
amin = amax = context - > ALPHA . FIX ;
}
}
return context - > ALPHA . IsOpaque ( amin , amax ) ;
}
2015-08-04 11:27:08 +00:00
bool GSState : : IsMipMapActive ( )
{
return m_mipmap & & m_context - > TEX1 . MXL > 0 & & m_context - > TEX1 . MMIN > = 2 & & m_context - > TEX1 . MMIN < = 5 & & m_vt . m_lod . y > 0 ;
}
2009-04-18 09:34:25 +00:00
// GSTransferBuffer
GSState : : GSTransferBuffer : : GSTransferBuffer ( )
{
x = y = 0 ;
2015-10-22 14:03:34 +00:00
overflow = false ;
2009-04-18 09:34:25 +00:00
start = end = total = 0 ;
2011-02-07 01:59:05 +00:00
buff = ( uint8 * ) _aligned_malloc ( 1024 * 1024 * 4 , 32 ) ;
2009-04-18 09:34:25 +00:00
}
GSState : : GSTransferBuffer : : ~ GSTransferBuffer ( )
{
_aligned_free ( buff ) ;
}
void GSState : : GSTransferBuffer : : Init ( int tx , int ty )
{
x = tx ;
y = ty ;
total = 0 ;
}
bool GSState : : GSTransferBuffer : : Update ( int tw , int th , int bpp , int & len )
{
if ( total = = 0 )
{
start = end = 0 ;
2011-03-08 01:48:15 +00:00
total = std : : min < int > ( ( tw * bpp > > 3 ) * th , 1024 * 1024 * 4 ) ;
2009-04-18 09:34:25 +00:00
overflow = false ;
}
int remaining = total - end ;
if ( len > remaining )
{
if ( ! overflow )
{
overflow = true ;
// printf("GS transfer overflow\n");
}
len = remaining ;
}
return len > 0 ;
}
2009-02-09 21:15:56 +00:00
// hacks
2015-06-04 16:52:58 +00:00
# define Aggresive (s_crc_hack_level > 3)
2015-06-04 17:12:07 +00:00
# define Dx_only (s_crc_hack_level > 2)
2009-02-09 21:15:56 +00:00
struct GSFrameInfo
{
2009-05-14 16:41:52 +00:00
uint32 FBP ;
uint32 FPSM ;
uint32 FBMSK ;
uint32 TBP0 ;
uint32 TPSM ;
2010-02-26 14:38:13 +00:00
uint32 TZTST ;
2009-02-09 21:15:56 +00:00
bool TME ;
} ;
typedef bool ( * GetSkipCount ) ( const GSFrameInfo & fi , int & skip ) ;
2011-07-29 18:11:22 +00:00
CRC : : Region g_crc_region = CRC : : NoRegion ;
2009-02-09 21:15:56 +00:00
2015-07-11 13:14:11 +00:00
bool GSC_Okami ( const GSFrameInfo & fi , int & skip ) // DX ONLY
2009-02-09 21:15:56 +00:00
{
if ( skip = = 0 )
{
if ( fi . TME & & fi . FBP = = 0x00e00 & & fi . FPSM = = PSM_PSMCT32 & & fi . TBP0 = = 0x00000 & & fi . TPSM = = PSM_PSMCT32 )
{
skip = 1000 ;
}
}
else
{
if ( fi . TME & & fi . FBP = = 0x00e00 & & fi . FPSM = = PSM_PSMCT32 & & fi . TBP0 = = 0x03800 & & fi . TPSM = = PSM_PSMT4 )
{
skip = 0 ;
}
}
return true ;
}
bool GSC_MetalGearSolid3 ( const GSFrameInfo & fi , int & skip )
{
2015-06-30 08:11:13 +00:00
// Game requires sub RT support (texture cache limitation)
2009-02-09 21:15:56 +00:00
if ( skip = = 0 )
{
if ( fi . TME & & fi . FBP = = 0x02000 & & fi . FPSM = = PSM_PSMCT32 & & ( fi . TBP0 = = 0x00000 | | fi . TBP0 = = 0x01000 ) & & fi . TPSM = = PSM_PSMCT24 )
{
skip = 1000 ; // 76, 79
}
else if ( fi . TME & & fi . FBP = = 0x02800 & & fi . FPSM = = PSM_PSMCT24 & & ( fi . TBP0 = = 0x00000 | | fi . TBP0 = = 0x01000 ) & & fi . TPSM = = PSM_PSMCT32 )
{
skip = 1000 ; // 69
}
}
2010-04-25 00:31:27 +00:00
else
2009-02-09 21:15:56 +00:00
{
if ( ! fi . TME & & ( fi . FBP = = 0x00000 | | fi . FBP = = 0x01000 ) & & fi . FPSM = = PSM_PSMCT32 )
{
skip = 0 ;
}
2011-08-11 12:54:57 +00:00
else if ( ! fi . TME & & fi . FBP = = fi . TBP0 & & fi . TBP0 = = 0x2000 & & fi . FPSM = = PSM_PSMCT32 & & fi . TPSM = = PSM_PSMCT24 )
2011-05-07 18:14:07 +00:00
{
2011-07-29 18:11:22 +00:00
if ( g_crc_region = = CRC : : US | | g_crc_region = = CRC : : JP | | g_crc_region = = CRC : : KO )
{
skip = 119 ; //ntsc
}
else
{
skip = 136 ; //pal
}
2011-05-07 18:14:07 +00:00
}
2009-02-09 21:15:56 +00:00
}
return true ;
}
bool GSC_DBZBT2 ( const GSFrameInfo & fi , int & skip )
{
if ( skip = = 0 )
{
2011-07-05 12:25:31 +00:00
if ( fi . TME & & /*fi.FBP == 0x00000 && fi.FPSM == PSM_PSMCT16 &&*/ ( fi . TBP0 = = 0x01c00 | | fi . TBP0 = = 0x02000 ) & & fi . TPSM = = PSM_PSMZ16 )
2009-02-09 21:15:56 +00:00
{
2011-07-05 12:25:31 +00:00
skip = 26 ; //27
2009-02-09 21:15:56 +00:00
}
2011-07-05 12:25:31 +00:00
else if ( ! fi . TME & & ( fi . FBP = = 0x02a00 | | fi . FBP = = 0x03000 ) & & fi . FPSM = = PSM_PSMCT16 )
2009-02-09 21:15:56 +00:00
{
skip = 10 ;
}
}
return true ;
}
bool GSC_DBZBT3 ( const GSFrameInfo & fi , int & skip )
{
if ( skip = = 0 )
{
2011-05-20 22:29:25 +00:00
if ( fi . TME & & fi . FBP = = 0x01c00 & & fi . FPSM = = PSM_PSMCT32 & & ( fi . TBP0 = = 0x00000 | | fi . TBP0 = = 0x00e00 | | fi . TBP0 = = 0x01000 ) & & fi . TPSM = = PSM_PSMT8H )
2009-02-09 21:15:56 +00:00
{
2011-05-20 22:29:25 +00:00
//not needed anymore?
//skip = 24; // blur
2009-02-09 21:15:56 +00:00
}
2011-05-21 02:53:15 +00:00
else if ( fi . TME & & ( fi . FBP = = 0x00000 | | fi . FBP = = 0x00e00 | | fi . FBP = = 0x01000 ) & & fi . FPSM = = PSM_PSMCT32 & & fi . TPSM = = PSM_PSMT8H )
2009-02-09 21:15:56 +00:00
{
2011-05-21 02:53:15 +00:00
if ( fi . FBMSK = = 0x00000 )
{
skip = 28 ; // outline
}
2011-06-12 22:07:59 +00:00
if ( fi . FBMSK = = 0x00FFFFFF )
2011-05-21 02:53:15 +00:00
{
skip = 1 ;
}
2009-02-09 21:15:56 +00:00
}
2011-06-12 22:07:59 +00:00
else if ( fi . TME & & ( fi . FBP = = 0x00000 | | fi . FBP = = 0x00e00 | | fi . FBP = = 0x01000 ) & & fi . FPSM = = PSM_PSMCT16 & & fi . TPSM = = PSM_PSMZ16 )
2011-05-20 22:29:25 +00:00
{
2015-06-30 08:11:13 +00:00
// Texture shuffling must work on openGL
if ( Dx_only )
skip = 5 ;
else
return false ;
2011-06-12 22:07:59 +00:00
}
else if ( fi . TME & & fi . FPSM = = fi . TPSM & & fi . TBP0 = = 0x03f00 & & fi . TPSM = = PSM_PSMCT32 )
{
if ( fi . FBP = = 0x03400 )
{
skip = 1 ; //PAL
}
if ( fi . FBP = = 0x02e00 )
{
skip = 3 ; //NTSC
}
2011-05-20 22:29:25 +00:00
}
2011-05-21 02:53:15 +00:00
}
2011-06-12 22:07:59 +00:00
return true ;
2009-02-09 21:15:56 +00:00
}
2015-07-11 13:14:11 +00:00
bool GSC_SFEX3 ( const GSFrameInfo & fi , int & skip ) // DX ONLY
2009-02-09 21:15:56 +00:00
{
if ( skip = = 0 )
{
2009-05-23 23:52:53 +00:00
if ( fi . TME & & fi . FBP = = 0x00500 & & fi . FPSM = = PSM_PSMCT16 & & fi . TBP0 = = 0x00f00 & & fi . TPSM = = PSM_PSMCT16 )
2009-02-09 21:15:56 +00:00
{
2009-05-23 23:52:53 +00:00
skip = 2 ; // blur
2009-02-09 21:15:56 +00:00
}
}
return true ;
}
2015-07-11 13:14:11 +00:00
bool GSC_Bully ( const GSFrameInfo & fi , int & skip ) // DX ONLY
2009-02-09 21:15:56 +00:00
{
if ( skip = = 0 )
{
if ( fi . TME & & ( fi . FBP = = 0x00000 | | fi . FBP = = 0x01180 ) & & ( fi . TBP0 = = 0x00000 | | fi . TBP0 = = 0x01180 ) & & fi . FBP = = fi . TBP0 & & fi . FPSM = = PSM_PSMCT32 & & fi . FPSM = = fi . TPSM )
{
return false ; // allowed
}
if ( fi . TME & & ( fi . FBP = = 0x00000 | | fi . FBP = = 0x01180 ) & & fi . FPSM = = PSM_PSMCT16S & & fi . TBP0 = = 0x02300 & & fi . TPSM = = PSM_PSMZ16S )
{
skip = 6 ;
}
}
2010-04-25 00:31:27 +00:00
else
2009-02-09 21:15:56 +00:00
{
if ( ! fi . TME & & ( fi . FBP = = 0x00000 | | fi . FBP = = 0x01180 ) & & fi . FPSM = = PSM_PSMCT32 )
{
skip = 0 ;
}
}
return true ;
}
bool GSC_BullyCC ( const GSFrameInfo & fi , int & skip )
{
if ( skip = = 0 )
{
if ( fi . TME & & ( fi . FBP = = 0x00000 | | fi . FBP = = 0x01180 ) & & ( fi . TBP0 = = 0x00000 | | fi . TBP0 = = 0x01180 ) & & fi . FBP = = fi . TBP0 & & fi . FPSM = = PSM_PSMCT32 & & fi . FPSM = = fi . TPSM )
{
return false ; // allowed
}
if ( ! fi . TME & & fi . FBP = = 0x02800 & & fi . FPSM = = PSM_PSMCT24 )
{
skip = 9 ;
}
}
return true ;
}
2015-06-04 16:52:58 +00:00
2009-02-09 21:15:56 +00:00
bool GSC_SoTC ( const GSFrameInfo & fi , int & skip )
{
2011-08-30 07:14:22 +00:00
// Not needed anymore? What did it fix anyway? (rama)
if ( skip = = 0 )
{
2015-06-04 16:52:58 +00:00
if ( Aggresive & & fi . TME /*&& fi.FBP == 0x03d80*/ & & fi . FPSM = = 0 & & fi . TBP0 = = 0x03fc0 & & fi . TPSM = = 1 )
2011-08-30 07:14:22 +00:00
{
skip = 48 ; //removes sky bloom
}
/*
if ( fi . TME & & fi . FBP = = 0x02b80 & & fi . FPSM = = PSM_PSMCT24 & & fi . TBP0 = = 0x01e80 & & fi . TPSM = = PSM_PSMCT24 )
{
skip = 9 ;
}
else if ( fi . TME & & fi . FBP = = 0x01c00 & & fi . FPSM = = PSM_PSMCT32 & & fi . TBP0 = = 0x03800 & & fi . TPSM = = PSM_PSMCT32 )
{
skip = 8 ;
}
else if ( fi . TME & & fi . FBP = = 0x01e80 & & fi . FPSM = = PSM_PSMCT32 & & fi . TBP0 = = 0x03880 & & fi . TPSM = = PSM_PSMCT32 )
{
skip = 8 ;
} */
}
2009-02-09 21:15:56 +00:00
return true ;
}
2015-07-11 13:14:11 +00:00
bool GSC_OnePieceGrandAdventure ( const GSFrameInfo & fi , int & skip ) // DX ONLY
2009-02-09 21:15:56 +00:00
{
if ( skip = = 0 )
{
2009-07-17 23:45:32 +00:00
if ( fi . TME & & fi . FBP = = 0x02d00 & & fi . FPSM = = PSM_PSMCT16 & & ( fi . TBP0 = = 0x00000 | | fi . TBP0 = = 0x00e00 | | fi . TBP0 = = 0x00f00 ) & & fi . TPSM = = PSM_PSMCT16 )
2009-02-09 21:15:56 +00:00
{
2009-07-17 23:45:32 +00:00
skip = 4 ;
2009-02-09 21:15:56 +00:00
}
}
return true ;
}
2015-07-11 13:14:11 +00:00
bool GSC_OnePieceGrandBattle ( const GSFrameInfo & fi , int & skip ) // DX ONLY
2009-07-05 12:58:59 +00:00
{
if ( skip = = 0 )
{
if ( fi . TME & & fi . FBP = = 0x02d00 & & fi . FPSM = = PSM_PSMCT16 & & ( fi . TBP0 = = 0x00000 | | fi . TBP0 = = 0x00f00 ) & & fi . TPSM = = PSM_PSMCT16 )
{
skip = 4 ;
}
}
return true ;
}
2009-02-09 21:15:56 +00:00
bool GSC_ICO ( const GSFrameInfo & fi , int & skip )
{
if ( skip = = 0 )
{
if ( fi . TME & & fi . FBP = = 0x00800 & & fi . FPSM = = PSM_PSMCT32 & & fi . TBP0 = = 0x03d00 & & fi . TPSM = = PSM_PSMCT32 )
{
skip = 3 ;
}
else if ( fi . TME & & fi . FBP = = 0x00800 & & fi . FPSM = = PSM_PSMCT32 & & fi . TBP0 = = 0x02800 & & fi . TPSM = = PSM_PSMT8H )
{
skip = 1 ;
}
2015-06-04 16:52:58 +00:00
else if ( Aggresive & & fi . TME & & fi . FBP = = 0x0800 & & ( fi . TBP0 = = 0x2800 | | fi . TBP0 = = 0x2c00 ) & & fi . TPSM = = 0 & & fi . FBMSK = = 0 )
2012-05-18 16:51:18 +00:00
{
2012-06-19 01:02:52 +00:00
skip = 1 ;
2012-05-18 16:51:18 +00:00
}
2009-02-09 21:15:56 +00:00
}
else
{
if ( fi . TME & & fi . TBP0 = = 0x00800 & & fi . TPSM = = PSM_PSMCT32 )
{
skip = 0 ;
}
}
return true ;
}
bool GSC_GT4 ( const GSFrameInfo & fi , int & skip )
{
2015-06-30 08:11:13 +00:00
// Game requires to extract source from RT (block boundary) (texture cache limitation)
2009-02-09 21:15:56 +00:00
if ( skip = = 0 )
{
2011-07-29 18:11:22 +00:00
if ( fi . TME & & fi . FBP > = 0x02f00 & & fi . FPSM = = PSM_PSMCT32 & & ( fi . TBP0 = = 0x00000 | | fi . TBP0 = = 0x01180 /*|| fi.TBP0 == 0x01a40*/ ) & & fi . TPSM = = PSM_PSMT8 ) //TBP0 0x1a40 progressive
2009-02-09 21:15:56 +00:00
{
2011-07-29 18:11:22 +00:00
skip = 770 ; //ntsc, progressive 1540
}
if ( g_crc_region = = CRC : : EU & & fi . TME & & fi . FBP > = 0x03400 & & fi . FPSM = = PSM_PSMCT32 & & ( fi . TBP0 = = 0x00000 | | fi . TBP0 = = 0x01400 ) & & fi . TPSM = = PSM_PSMT8 )
{
skip = 880 ; //pal
2009-02-09 21:15:56 +00:00
}
else if ( fi . TME & & ( fi . FBP = = 0x00000 | | fi . FBP = = 0x01400 ) & & fi . FPSM = = PSM_PSMCT24 & & fi . TBP0 > = 0x03420 & & fi . TPSM = = PSM_PSMT8 )
{
// TODO: removes gfx from where it is not supposed to (garage)
// skip = 58;
}
}
return true ;
}
2011-04-14 15:12:06 +00:00
bool GSC_GT3 ( const GSFrameInfo & fi , int & skip )
{
2015-06-30 08:11:13 +00:00
// Same issue as GSC_GT4 ???
2011-04-14 15:12:06 +00:00
if ( skip = = 0 )
{
if ( fi . TME & & fi . FBP > = 0x02de0 & & fi . FPSM = = PSM_PSMCT32 & & ( fi . TBP0 = = 0x00000 | | fi . TBP0 = = 0x01180 ) & & fi . TPSM = = PSM_PSMT8 )
{
skip = 770 ;
}
}
return true ;
}
bool GSC_GTConcept ( const GSFrameInfo & fi , int & skip )
{
2015-06-30 08:11:13 +00:00
// Same issue as GSC_GT4 ???
2011-04-14 15:12:06 +00:00
if ( skip = = 0 )
{
if ( fi . TME & & fi . FBP > = 0x03420 & & fi . FPSM = = PSM_PSMCT32 & & ( fi . TBP0 = = 0x00000 | | fi . TBP0 = = 0x01400 ) & & fi . TPSM = = PSM_PSMT8 )
{
skip = 880 ;
}
}
return true ;
}
2010-07-24 00:04:54 +00:00
bool GSC_WildArms4 ( const GSFrameInfo & fi , int & skip )
{
if ( skip = = 0 )
{
if ( fi . TME & & fi . FBP = = 0x03100 & & fi . FPSM = = PSM_PSMZ32 & & fi . TBP0 = = 0x01c00 & & fi . TPSM = = PSM_PSMZ32 )
{
skip = 100 ;
}
}
else
{
if ( fi . TME & & fi . FBP = = 0x00e00 & & fi . FPSM = = PSM_PSMCT32 & & fi . TBP0 = = 0x02a00 & & fi . TPSM = = PSM_PSMCT32 )
{
skip = 1 ;
}
}
return true ;
}
2009-02-09 21:15:56 +00:00
bool GSC_WildArms5 ( const GSFrameInfo & fi , int & skip )
{
if ( skip = = 0 )
{
if ( fi . TME & & fi . FBP = = 0x03100 & & fi . FPSM = = PSM_PSMZ32 & & fi . TBP0 = = 0x01c00 & & fi . TPSM = = PSM_PSMZ32 )
{
skip = 100 ;
}
}
else
{
if ( fi . TME & & fi . FBP = = 0x00e00 & & fi . FPSM = = PSM_PSMCT32 & & fi . TBP0 = = 0x02a00 & & fi . TPSM = = PSM_PSMCT32 )
{
skip = 1 ;
}
}
return true ;
}
bool GSC_Manhunt2 ( const GSFrameInfo & fi , int & skip )
{
if ( skip = = 0 )
{
if ( fi . TME & & fi . FBP = = 0x03c20 & & fi . FPSM = = PSM_PSMCT32 & & fi . TBP0 = = 0x01400 & & fi . TPSM = = PSM_PSMT8 )
{
skip = 640 ;
}
}
return true ;
}
bool GSC_CrashBandicootWoC ( const GSFrameInfo & fi , int & skip )
{
if ( skip = = 0 )
{
2011-04-12 14:11:03 +00:00
if ( fi . TME & & ( fi . FBP = = 0x00000 | | fi . FBP = = 0x008c0 | | fi . FBP = = 0x00a00 ) & & ( fi . TBP0 = = 0x00000 | | fi . TBP0 = = 0x008c0 | | fi . TBP0 = = 0x00a00 ) & & fi . FBP = = fi . TBP0 & & fi . FPSM = = PSM_PSMCT32 & & fi . FPSM = = fi . TPSM )
2009-02-09 21:15:56 +00:00
{
return false ; // allowed
}
2011-04-12 14:11:03 +00:00
if ( fi . TME & & ( fi . FBP = = 0x01e40 | | fi . FBP = = 0x02200 ) & & fi . FPSM = = PSM_PSMZ24 & & ( fi . TBP0 = = 0x01180 | | fi . TBP0 = = 0x01400 ) & & fi . TPSM = = PSM_PSMZ24 )
2009-02-09 21:15:56 +00:00
{
2011-04-12 14:11:03 +00:00
skip = 42 ;
2009-02-09 21:15:56 +00:00
}
}
else
{
2011-04-12 14:11:03 +00:00
if ( fi . TME & & ( fi . FBP = = 0x00000 | | fi . FBP = = 0x008c0 | | fi . FBP = = 0x00a00 ) & & fi . FPSM = = PSM_PSMCT32 & & fi . TBP0 = = 0x03c00 & & fi . TPSM = = PSM_PSMCT32 )
2009-02-09 21:15:56 +00:00
{
skip = 0 ;
}
2011-04-12 14:11:03 +00:00
else if ( ! fi . TME & & ( fi . FBP = = 0x00000 | | fi . FBP = = 0x008c0 | | fi . FBP = = 0x00a00 ) )
2009-02-09 21:15:56 +00:00
{
skip = 0 ;
}
}
return true ;
}
bool GSC_ResidentEvil4 ( const GSFrameInfo & fi , int & skip )
{
if ( skip = = 0 )
{
if ( fi . TME & & fi . FBP = = 0x03100 & & fi . FPSM = = PSM_PSMCT32 & & fi . TBP0 = = 0x01c00 & & fi . TPSM = = PSM_PSMZ24 )
{
skip = 176 ;
}
2015-06-30 08:11:13 +00:00
else if ( fi . TME & & fi . FBP = = 0x03100 & & ( fi . TBP0 = = 0x2a00 | | fi . TBP0 = = 0x3480 ) & & fi . TPSM = = PSM_PSMCT32 & & fi . FBMSK = = 0 )
2012-05-18 16:51:18 +00:00
{
2012-06-19 01:02:52 +00:00
skip = 1 ;
2012-05-18 16:51:18 +00:00
}
2009-02-09 21:15:56 +00:00
}
return true ;
}
2013-07-23 13:55:38 +00:00
bool GSC_SacredBlaze ( const GSFrameInfo & fi , int & skip )
{
//Fix Sacred Blaze rendering glitches
if ( skip = = 0 )
{
2015-06-30 08:11:13 +00:00
if ( fi . TME & & ( fi . FBP = = 0x0000 | | fi . FBP = = 0x0e00 ) & & ( fi . TBP0 = = 0x2880 | | fi . TBP0 = = 0x2a80 ) & & fi . FPSM = = fi . TPSM & & fi . TPSM = = PSM_PSMCT32 & & fi . FBMSK = = 0x0 )
2013-07-23 13:55:38 +00:00
{
skip = 1 ;
}
}
return true ;
}
2015-06-01 23:27:48 +00:00
template < uptr state_addr >
bool GSC_SMTNocturneDDS ( const GSFrameInfo & fi , int & skip )
{
// stop the motion blur on the main character and
// smudge filter from being drawn on USA versions of
// Nocturne, Digital Devil Saga 1 and Digital Devil Saga 2
2015-06-14 08:24:11 +00:00
if ( Aggresive & & g_crc_region = = CRC : : US & & skip = = 0 & & fi . TBP0 = = 0xE00 & & fi . TME )
2015-06-01 23:27:48 +00:00
{
2015-06-14 08:24:11 +00:00
// Note: it will crash if the core doesn't allocate the EE mem in 0x2000_0000 (unlikely but possible)
// Aggresive hacks are evil anyway
// Nocturne:
// -0x5900($gp), ref at 0x100740
const int state = * ( int * ) ( state_addr ) ;
if ( state = = 23 | | state = = 24 | | state = = 25 )
skip = 1 ;
2015-06-01 23:27:48 +00:00
}
return true ;
}
2009-02-09 21:15:56 +00:00
bool GSC_Spartan ( const GSFrameInfo & fi , int & skip )
{
if ( skip = = 0 )
{
2015-05-07 08:49:43 +00:00
if ( g_crc_region = = CRC : : EU & & fi . TME & & fi . FBP = = 0x02000 & & fi . FPSM = = PSM_PSMCT32 & & fi . TBP0 = = 0x00000 & & fi . TPSM = = PSM_PSMCT32 )
2009-02-09 21:15:56 +00:00
{
skip = 107 ;
}
2012-05-18 16:51:18 +00:00
if ( g_crc_region = = CRC : : JP & & fi . TME & & fi . FBP = = 0x02180 & & fi . FPSM = = PSM_PSMCT32 & & fi . TBP0 = = 0x2180 & & fi . TPSM = = PSM_PSMCT32 )
{
skip = 3 ;
}
else
{
if ( fi . TME )
{
// depth textures (bully, mgs3s1 intro, Front Mission 5)
if ( ( fi . TPSM = = PSM_PSMZ32 | | fi . TPSM = = PSM_PSMZ24 | | fi . TPSM = = PSM_PSMZ16 | | fi . TPSM = = PSM_PSMZ16S ) | |
// General, often problematic post processing
( GSUtil : : HasSharedBits ( fi . FBP , fi . FPSM , fi . TBP0 , fi . TPSM ) ) )
{
skip = 1 ;
}
}
}
2009-02-09 21:15:56 +00:00
}
return true ;
}
bool GSC_AceCombat4 ( const GSFrameInfo & fi , int & skip )
{
if ( skip = = 0 )
{
if ( fi . TME & & fi . FBP = = 0x02a00 & & fi . FPSM = = PSM_PSMZ24 & & fi . TBP0 = = 0x01600 & & fi . TPSM = = PSM_PSMZ24 )
{
skip = 71 ; // clouds (z, 16-bit)
}
else if ( fi . TME & & fi . FBP = = 0x02900 & & fi . FPSM = = PSM_PSMCT32 & & fi . TBP0 = = 0x00000 & & fi . TPSM = = PSM_PSMCT24 )
{
skip = 28 ; // blur
}
}
return true ;
}
bool GSC_Tekken5 ( const GSFrameInfo & fi , int & skip )
{
if ( skip = = 0 )
{
2011-04-21 02:32:59 +00:00
if ( fi . TME & & ( fi . FBP = = 0x02d60 | | fi . FBP = = 0x02d80 | | fi . FBP = = 0x02ea0 | | fi . FBP = = 0x03620 ) & & fi . FPSM = = fi . TPSM & & fi . TBP0 = = 0x00000 & & fi . TPSM = = PSM_PSMCT32 )
2009-02-09 21:15:56 +00:00
{
skip = 95 ;
}
2011-04-21 02:32:59 +00:00
else if ( fi . TME & & ( fi . FBP = = 0x02bc0 | | fi . FBP = = 0x02be0 | | fi . FBP = = 0x02d00 ) & & fi . FPSM = = fi . TPSM & & fi . TBP0 = = 0x00000 & & fi . TPSM = = PSM_PSMCT32 )
2011-04-09 10:26:56 +00:00
{
skip = 2 ;
}
2012-05-18 16:51:18 +00:00
else if ( fi . TME )
2011-04-21 02:32:59 +00:00
{
2012-05-18 16:51:18 +00:00
if ( ( fi . TPSM = = PSM_PSMZ32 | | fi . TPSM = = PSM_PSMZ24 | | fi . TPSM = = PSM_PSMZ16 | | fi . TPSM = = PSM_PSMZ16S ) | |
( GSUtil : : HasSharedBits ( fi . FBP , fi . FPSM , fi . TBP0 , fi . TPSM ) ) )
{
skip = 24 ;
}
2011-04-21 02:32:59 +00:00
}
2009-02-09 21:15:56 +00:00
}
2011-04-21 02:32:59 +00:00
2009-02-09 21:15:56 +00:00
return true ;
}
bool GSC_IkkiTousen ( const GSFrameInfo & fi , int & skip )
{
if ( skip = = 0 )
{
if ( fi . TME & & fi . FBP = = 0x00a80 & & fi . FPSM = = PSM_PSMZ24 & & fi . TBP0 = = 0x01180 & & fi . TPSM = = PSM_PSMZ24 )
{
skip = 1000 ; // shadow (result is broken without depth copy, also includes 16 bit)
}
else if ( fi . TME & & fi . FBP = = 0x00700 & & fi . FPSM = = PSM_PSMZ24 & & fi . TBP0 = = 0x01180 & & fi . TPSM = = PSM_PSMZ24 )
{
skip = 11 ; // blur
}
}
else if ( skip > 7 )
{
if ( fi . TME & & fi . FBP = = 0x00700 & & fi . FPSM = = PSM_PSMCT16 & & fi . TBP0 = = 0x00700 & & fi . TPSM = = PSM_PSMCT16 )
{
skip = 7 ; // the last steps of shadow drawing
}
}
return true ;
}
2015-07-11 13:14:11 +00:00
bool GSC_GodOfWar ( const GSFrameInfo & fi , int & skip ) // DX ONLY
2009-02-09 21:15:56 +00:00
{
if ( skip = = 0 )
{
2011-06-11 17:50:47 +00:00
if ( fi . TME & & fi . FBP = = 0x00000 & & fi . FPSM = = PSM_PSMCT16 & & fi . TBP0 = = 0x00000 & & fi . TPSM = = PSM_PSMCT16 & & fi . FBMSK = = 0x03FFF )
2009-02-09 21:15:56 +00:00
{
2011-06-11 17:50:47 +00:00
skip = 1000 ;
2009-02-09 21:15:56 +00:00
}
2009-03-22 13:10:31 +00:00
else if ( fi . TME & & fi . FBP = = 0x00000 & & fi . FPSM = = PSM_PSMCT32 & & fi . TBP0 = = 0x00000 & & fi . TPSM = = PSM_PSMCT32 & & fi . FBMSK = = 0xff000000 )
{
skip = 1 ; // blur
}
2010-02-26 14:38:13 +00:00
else if ( fi . FBP = = 0x00000 & & fi . FPSM = = PSM_PSMCT32 & & fi . TPSM = = PSM_PSMT8 & & ( ( fi . TZTST = = 2 & & fi . FBMSK = = 0x00FFFFFF ) | | ( fi . TZTST = = 1 & & fi . FBMSK = = 0x00FFFFFF ) | | ( fi . TZTST = = 3 & & fi . FBMSK = = 0xFF000000 ) ) )
{
skip = 1 ; // wall of fog
}
2015-05-24 11:24:32 +00:00
else if ( fi . TME & & ( fi . TPSM = = PSM_PSMZ32 | | fi . TPSM = = PSM_PSMZ24 | | fi . TPSM = = PSM_PSMZ16 | | fi . TPSM = = PSM_PSMZ16S ) )
{
// Equivalent to the UserHacks_AutoSkipDrawDepth hack but enabled by default
// http://forums.pcsx2.net/Thread-God-of-War-Red-line-rendering-explained
skip = 1 ;
}
2009-02-09 21:15:56 +00:00
}
2011-06-11 17:50:47 +00:00
else
{
if ( fi . TME & & fi . FBP = = 0x00000 & & fi . FPSM = = PSM_PSMCT16 )
{
skip = 3 ;
}
}
2009-02-09 21:15:56 +00:00
return true ;
}
2015-07-11 13:14:11 +00:00
bool GSC_GodOfWar2 ( const GSFrameInfo & fi , int & skip ) // DX ONLY
2009-04-10 19:55:05 +00:00
{
if ( skip = = 0 )
{
2009-05-11 21:10:08 +00:00
if ( fi . TME )
2009-04-10 19:55:05 +00:00
{
2011-06-25 08:31:42 +00:00
if ( fi . FBP = = 0x00100 & & fi . FPSM = = PSM_PSMCT16 & & fi . TBP0 = = 0x00100 & & fi . TPSM = = PSM_PSMCT16 // ntsc
2010-03-10 10:10:36 +00:00
| | fi . FBP = = 0x02100 & & fi . FPSM = = PSM_PSMCT16 & & fi . TBP0 = = 0x02100 & & fi . TPSM = = PSM_PSMCT16 ) // pal
2009-05-11 21:10:08 +00:00
{
2011-06-11 17:50:47 +00:00
skip = 1000 ; // shadows
2009-05-11 21:10:08 +00:00
}
2011-06-25 08:31:42 +00:00
if ( ( fi . FBP = = 0x00100 | | fi . FBP = = 0x02100 ) & & fi . FPSM = = PSM_PSMCT32 & & ( fi . TBP0 & 0x03000 ) = = 0x03000
2010-04-25 00:31:27 +00:00
& & ( fi . TPSM = = PSM_PSMT8 | | fi . TPSM = = PSM_PSMT4 )
2011-06-11 17:50:47 +00:00
& & ( ( fi . TZTST = = 2 & & fi . FBMSK = = 0x00FFFFFF ) | | ( fi . TZTST = = 1 & & fi . FBMSK = = 0x00FFFFFF ) | | ( fi . TZTST = = 3 & & fi . FBMSK = = 0xFF000000 ) ) )
{
2010-03-10 10:10:36 +00:00
skip = 1 ; // wall of fog
2009-05-11 21:10:08 +00:00
}
2015-06-04 16:52:58 +00:00
else if ( Aggresive & & fi . TPSM = = PSM_PSMCT24 & & fi . TME & & ( fi . FBP = = 0x1300 ) & & ( fi . TBP0 = = 0x0F00 | | fi . TBP0 = = 0x1300 | | fi . TBP0 = = 0x2b00 ) ) // || fi.FBP == 0x0100
2012-05-18 16:51:18 +00:00
{
2012-05-23 06:38:37 +00:00
skip = 1 ; // global haze/halo
2012-05-18 16:51:18 +00:00
}
2015-06-04 16:52:58 +00:00
else if ( Aggresive & & fi . TPSM = = PSM_PSMCT24 & & fi . TME & & ( fi . FBP = = 0x0100 ) & & ( fi . TBP0 = = 0x2b00 | | fi . TBP0 = = 0x2e80 ) ) //480P 2e80
2012-05-18 16:51:18 +00:00
{
2012-05-23 06:38:37 +00:00
skip = 1 ; // water effect and water vertical lines
2012-05-18 16:51:18 +00:00
}
2015-05-24 11:24:32 +00:00
else if ( fi . TME & & ( fi . TPSM = = PSM_PSMZ32 | | fi . TPSM = = PSM_PSMZ24 | | fi . TPSM = = PSM_PSMZ16 | | fi . TPSM = = PSM_PSMZ16S ) )
{
// Equivalent to the UserHacks_AutoSkipDrawDepth hack but enabled by default
// http://forums.pcsx2.net/Thread-God-of-War-Red-line-rendering-explained
skip = 1 ;
}
2009-04-11 08:54:48 +00:00
}
2009-04-10 19:55:05 +00:00
}
2011-06-11 17:50:47 +00:00
else
{
if ( fi . TME & & ( fi . FBP = = 0x00100 | | fi . FBP = = 0x02100 ) & & fi . FPSM = = PSM_PSMCT16 )
{
skip = 3 ;
}
}
2009-04-10 19:55:05 +00:00
return true ;
}
2015-07-11 13:14:11 +00:00
bool GSC_GiTS ( const GSFrameInfo & fi , int & skip ) // DX ONLY
2009-02-09 21:15:56 +00:00
{
if ( skip = = 0 )
{
if ( fi . TME & & fi . FBP = = 0x01400 & & fi . FPSM = = PSM_PSMCT16 & & fi . TBP0 = = 0x02e40 & & fi . TPSM = = PSM_PSMCT16 )
{
skip = 1315 ;
}
}
else
{
}
return true ;
}
bool GSC_Onimusha3 ( const GSFrameInfo & fi , int & skip )
{
if ( fi . TME /*&& (fi.FBP == 0x00000 || fi.FBP == 0x00700)*/ & & ( fi . TBP0 = = 0x01180 | | fi . TBP0 = = 0x00e00 | | fi . TBP0 = = 0x01000 | | fi . TBP0 = = 0x01200 ) & & ( fi . TPSM = = PSM_PSMCT32 | | fi . TPSM = = PSM_PSMCT24 ) )
{
skip = 1 ;
}
return true ;
}
bool GSC_TalesOfAbyss ( const GSFrameInfo & fi , int & skip )
{
if ( skip = = 0 )
{
if ( fi . TME & & ( fi . FBP = = 0x00000 | | fi . FBP = = 0x00e00 ) & & fi . TBP0 = = 0x01c00 & & fi . TPSM = = PSM_PSMT8 ) // copies the z buffer to the alpha channel of the fb
{
skip = 1000 ;
}
else if ( fi . TME & & ( fi . FBP = = 0x00000 | | fi . FBP = = 0x00e00 ) & & ( fi . TBP0 = = 0x03560 | | fi . TBP0 = = 0x038e0 ) & & fi . TPSM = = PSM_PSMCT32 )
{
skip = 1 ;
}
}
else
{
if ( fi . TME & & fi . TPSM ! = PSM_PSMT8 )
{
skip = 0 ;
}
}
return true ;
}
2015-07-11 13:14:11 +00:00
bool GSC_SonicUnleashed ( const GSFrameInfo & fi , int & skip ) // DX ONLY
2009-05-07 12:34:58 +00:00
{
if ( skip = = 0 )
{
2011-06-25 08:31:42 +00:00
if ( fi . TME & & fi . FPSM = = PSM_PSMCT16S & & fi . TBP0 = = 0x00000 & & fi . TPSM = = PSM_PSMCT16 )
2009-05-07 12:34:58 +00:00
{
skip = 1000 ; // shadow
}
}
else
{
2011-06-25 08:31:42 +00:00
if ( fi . TME & & fi . FBP = = 0x00000 & & fi . FPSM = = PSM_PSMCT16 & & fi . TPSM = = PSM_PSMCT16S )
2009-05-07 12:34:58 +00:00
{
skip = 2 ;
}
}
return true ;
}
2009-05-22 01:22:52 +00:00
2015-07-11 13:14:11 +00:00
bool GSC_SimpsonsGame ( const GSFrameInfo & fi , int & skip ) // DX ONLY
2011-04-25 13:47:29 +00:00
{
if ( skip = = 0 )
{
if ( fi . TME & & fi . FBP = = fi . TBP0 & & fi . FPSM = = fi . TPSM & & fi . TBP0 = = 0x03000 & & fi . TPSM = = PSM_PSMCT32 )
{
skip = 100 ;
}
}
else
{
if ( fi . TME & & fi . FBP = = 0x03000 & & fi . FPSM = = PSM_PSMCT32 & & fi . TPSM = = PSM_PSMT8H )
{
skip = 2 ;
}
}
return true ;
}
2009-06-11 00:08:23 +00:00
bool GSC_Genji ( const GSFrameInfo & fi , int & skip )
{
2011-12-27 08:28:32 +00:00
if ( ! skip & & fi . TME & & ( fi . FBP = = 0x700 | | fi . FBP = = 0x0 ) & & fi . TBP0 = = 0x1500 & & fi . TPSM )
skip = 1 ;
2009-06-11 00:08:23 +00:00
if ( skip = = 0 )
{
if ( fi . TME & & fi . FBP = = 0x01500 & & fi . FPSM = = PSM_PSMCT16 & & fi . TBP0 = = 0x00e00 & & fi . TPSM = = PSM_PSMZ16 )
{
2015-06-30 08:11:13 +00:00
// likely fixed in openGL (texture shuffle)
if ( Dx_only )
skip = 6 ;
else
return false ;
2012-05-18 16:51:18 +00:00
}
else if ( fi . TPSM = = PSM_PSMCT24 & & fi . TME = = 0x0001 & & fi . TBP0 = = fi . FBP )
{
2012-06-19 01:02:52 +00:00
skip = 1 ;
2012-05-18 16:51:18 +00:00
}
else if ( fi . TPSM = = PSM_PSMT8H & & fi . FBMSK = = 0 )
{
2012-06-19 01:02:52 +00:00
skip = 1 ;
2009-06-11 00:08:23 +00:00
}
}
else
{
}
return true ;
}
2015-07-11 13:14:11 +00:00
bool GSC_StarOcean3 ( const GSFrameInfo & fi , int & skip ) // DX ONLY
2009-07-01 21:14:12 +00:00
{
2015-05-25 10:37:48 +00:00
// The game emulate a stencil buffer with the alpha channel of the RT
// The operation of the stencil is selected with the palette
// For example -1 wrap will be [240, 16, 32, 48 ....]
// i.e. p[A>>4] = (A - 16) % 256
//
// The fastest and accurate solution will be to replace this pseudo stencil
// by a dedicated GPU draw call
// 1/ Use future GPU capabilities to do a "kind" of SW blending
// 2/ Use a real stencil/atomic image, and then compute the RT alpha value
//
// Both of those solutions will increase code complexity (and only avoid upscaling
// glitches)
2009-07-01 21:14:12 +00:00
if ( skip = = 0 )
{
if ( fi . TME & & fi . FBP = = fi . TBP0 & & fi . FPSM = = PSM_PSMCT32 & & fi . TPSM = = PSM_PSMT4HH )
{
skip = 1000 ; //
}
}
else
{
if ( ! ( fi . TME & & fi . FBP = = fi . TBP0 & & fi . FPSM = = PSM_PSMCT32 & & fi . TPSM = = PSM_PSMT4HH ) )
{
skip = 0 ;
}
}
return true ;
}
2015-07-11 13:14:11 +00:00
bool GSC_ValkyrieProfile2 ( const GSFrameInfo & fi , int & skip ) // DX ONLY
2009-07-02 00:47:50 +00:00
{
if ( skip = = 0 )
{
2011-04-14 15:12:06 +00:00
/*if(fi.TME && (fi.FBP == 0x018c0 || fi.FBP == 0x02180) && fi.FPSM == fi.TPSM && fi.TBP0 >= 0x03200 && fi.TPSM == PSM_PSMCT32) //NTSC only, !(fi.TBP0 == 0x03580 || fi.TBP0 == 0x03960)
{
skip = 1 ; //red garbage in lost forest, removes other effects...
2012-05-23 06:38:37 +00:00
}
2011-04-14 15:12:06 +00:00
if ( fi . TME & & fi . FPSM = = fi . TPSM & & fi . TPSM = = PSM_PSMCT16 & & fi . FBMSK = = 0x03FFF )
{
2012-05-23 06:38:37 +00:00
skip = 1 ; // //garbage in cutscenes, doesn't remove completely, better use "Alpha Hack"
} */
2009-07-02 00:47:50 +00:00
if ( fi . TME & & fi . FBP = = fi . TBP0 & & fi . FPSM = = PSM_PSMCT32 & & fi . TPSM = = PSM_PSMT4HH )
{
2015-05-25 10:37:48 +00:00
// GH: Hack is quite similar to GSC_StarOcean3. It is potentially the same issue.
2009-07-02 00:47:50 +00:00
skip = 1000 ; //
}
}
else
{
if ( ! ( fi . TME & & fi . FBP = = fi . TBP0 & & fi . FPSM = = PSM_PSMCT32 & & fi . TPSM = = PSM_PSMT4HH ) )
{
skip = 0 ;
}
}
return true ;
}
2015-07-11 13:14:11 +00:00
bool GSC_RadiataStories ( const GSFrameInfo & fi , int & skip ) // DX ONLY
2009-07-02 16:05:03 +00:00
{
if ( skip = = 0 )
{
2012-05-18 16:51:18 +00:00
if ( fi . TME & & fi . FPSM = = fi . TPSM & & fi . TPSM = = PSM_PSMCT16 & & fi . FBMSK = = 0x03FFF )
{
2012-06-19 01:02:52 +00:00
skip = 1 ;
2012-05-18 16:51:18 +00:00
}
2015-06-30 08:11:13 +00:00
else if ( fi . TME & & fi . FBP = = fi . TBP0 & & fi . FPSM = = PSM_PSMCT32 & & fi . TPSM = = PSM_PSMT4HH )
2009-07-02 16:05:03 +00:00
{
2015-05-25 10:37:48 +00:00
// GH: Hack is quite similar to GSC_StarOcean3. It is potentially the same issue.
2015-06-04 17:12:07 +00:00
// Fixed on openGL
2012-06-19 01:02:52 +00:00
skip = 1000 ;
2009-07-02 16:05:03 +00:00
}
}
else
{
if ( ! ( fi . TME & & fi . FBP = = fi . TBP0 & & fi . FPSM = = PSM_PSMCT32 & & fi . TPSM = = PSM_PSMT4HH ) )
{
skip = 0 ;
}
}
return true ;
}
2010-08-15 14:48:07 +00:00
bool GSC_HauntingGround ( const GSFrameInfo & fi , int & skip )
{
if ( skip = = 0 )
{
if ( fi . TME & & fi . FPSM = = fi . TPSM & & fi . TPSM = = PSM_PSMCT16S & & fi . FBMSK = = 0x03FFF )
{
2015-06-30 08:11:13 +00:00
if ( Dx_only )
skip = 1 ;
else
return false ;
2010-08-15 14:48:07 +00:00
}
else if ( fi . TME & & fi . FBP = = 0x3000 & & fi . TBP0 = = 0x3380 )
{
skip = 1 ; // bloom
}
2012-05-18 16:51:18 +00:00
else if ( fi . TME & & ( fi . FBP = = 0x2200 ) & & ( fi . TBP0 = = 0x3a80 ) & & fi . FPSM = = fi . TPSM & & fi . TPSM = = PSM_PSMCT32 )
{
2012-06-19 01:02:52 +00:00
skip = 1 ;
2012-05-18 16:51:18 +00:00
}
else if ( fi . FBP = = 0x2200 & & fi . TBP0 = = 0x3000 & & fi . TPSM = = PSM_PSMT8H & & fi . FBMSK = = 0 )
{
2012-06-19 01:02:52 +00:00
skip = 1 ;
2012-05-18 16:51:18 +00:00
}
else if ( fi . TME )
{
// depth textures (bully, mgs3s1 intro, Front Mission 5)
if ( ( fi . TPSM = = PSM_PSMZ32 | | fi . TPSM = = PSM_PSMZ24 | | fi . TPSM = = PSM_PSMZ16 | | fi . TPSM = = PSM_PSMZ16S ) | |
// General, often problematic post processing
( GSUtil : : HasSharedBits ( fi . FBP , fi . FPSM , fi . TBP0 , fi . TPSM ) ) )
{
skip = 1 ;
}
}
}
return true ;
}
bool GSC_EvangelionJo ( const GSFrameInfo & fi , int & skip )
{
if ( skip = = 0 )
{
if ( fi . TME & & fi . TBP0 = = 0x2BC0 | | ( fi . FBP = = 0 | | fi . FBP = = 0x1180 ) & & ( fi . FPSM | fi . TPSM ) = = 0 )
2010-08-15 14:48:07 +00:00
{
2011-02-18 01:56:05 +00:00
skip = 1 ;
2010-08-15 14:48:07 +00:00
}
}
return true ;
}
2015-07-11 13:14:11 +00:00
bool GSC_SuikodenTactics ( const GSFrameInfo & fi , int & skip ) // DX ONLY
2011-03-19 19:29:30 +00:00
{
if ( skip = = 0 )
{
2012-05-18 16:51:18 +00:00
if ( ! fi . TME & & fi . TPSM = = PSM_PSMT8H & & fi . FPSM = = 0 & &
fi . FBMSK = = 0x0FF000000 & & fi . TBP0 = = 0 & & GSUtil : : HasSharedBits ( fi . FBP , fi . FPSM , fi . TBP0 , fi . TPSM ) )
2011-03-19 19:29:30 +00:00
{
skip = 4 ;
}
}
return true ;
}
2012-05-18 16:51:18 +00:00
bool GSC_CaptainTsubasa ( const GSFrameInfo & fi , int & skip )
{
if ( skip = = 0 )
{
if ( fi . TME & & fi . FBP = = 0x1C00 & & ! fi . FBMSK )
{
skip = 1 ;
}
}
return true ;
}
bool GSC_Oneechanbara2Special ( const GSFrameInfo & fi , int & skip )
{
if ( skip = = 0 )
{
if ( fi . TPSM = = PSM_PSMCT24 & & fi . TME & & fi . FBP = = 0x01180 )
{
2012-06-19 01:02:52 +00:00
skip = 1 ;
2012-05-18 16:51:18 +00:00
}
}
return true ;
}
bool GSC_NarutimateAccel ( const GSFrameInfo & fi , int & skip )
{
if ( skip = = 0 )
{
if ( fi . TME & & fi . FBP = = 0x3800 & & fi . TBP0 = = 0 & & ( fi . FPSM | fi . TPSM ) = = 0 )
{
skip = 105 ;
}
else if ( ! fi . TME & & fi . FBP = = 0x3800 & & fi . TBP0 = = 0x1E00 & & fi . FPSM = = 0 & & fi . TPSM = = 49 & & fi . FBMSK = = 0xFF000000 )
{
skip = 1 ;
}
}
else
{
if ( fi . FBP = = 0 & & fi . TBP0 = = 0x3800 & & fi . TME & & ( fi . FPSM | fi . TPSM ) = = 0 )
{
skip = 1 ;
}
}
return true ;
}
bool GSC_Naruto ( const GSFrameInfo & fi , int & skip )
{
if ( skip = = 0 )
{
if ( fi . TME & & fi . FBP = = 0x3800 & & fi . TBP0 = = 0 & & ( fi . FPSM | fi . TPSM ) = = 0 )
{
skip = 105 ;
}
else if ( ! fi . TME & & fi . FBP = = 0x3800 & & fi . TBP0 = = 0x1E00 & & fi . FPSM = = 0 & & fi . TPSM = = 49 & & fi . FBMSK = = 0xFF000000 )
{
skip = 0 ;
}
}
else
{
if ( fi . FBP = = 0 & & fi . TBP0 = = 0x3800 & & fi . TME & & ( fi . FPSM | fi . TPSM ) = = 0 )
{
skip = 1 ;
}
}
return true ;
}
bool GSC_EternalPoison ( const GSFrameInfo & fi , int & skip )
{
if ( skip = = 0 )
{
2015-06-30 08:11:13 +00:00
// Texture shuffle ???
2012-05-18 16:51:18 +00:00
if ( fi . TPSM = = PSM_PSMCT16S & & fi . TBP0 = = 0x3200 )
{
2012-06-19 01:02:52 +00:00
skip = 1 ;
2012-05-18 16:51:18 +00:00
}
}
return true ;
}
2015-07-11 13:14:11 +00:00
bool GSC_LegoBatman ( const GSFrameInfo & fi , int & skip ) // DX ONLY
2012-05-18 16:51:18 +00:00
{
2015-06-04 16:52:58 +00:00
if ( Aggresive & & skip = = 0 )
2012-05-18 16:51:18 +00:00
{
if ( fi . TME & & fi . TPSM = = PSM_PSMZ16 & & fi . FPSM = = PSM_PSMCT16 & & fi . FBMSK = = 0x00000 )
{
2012-06-19 01:02:52 +00:00
skip = 3 ;
2012-05-18 16:51:18 +00:00
}
}
return true ;
}
bool GSC_SakuraTaisen ( const GSFrameInfo & fi , int & skip )
{
if ( skip = = 0 )
{
if ( ! fi . TME & & ( fi . FBP = = 0x0 | | fi . FBP = = 0x1180 ) & & ( fi . TBP0 ! = 0x3fc0 & & fi . TBP0 ! = 0x3c9a & & fi . TBP0 ! = 0x3dec /*fi.TBP0 ==0x38d0 || fi.TBP0==0x3912 ||fi.TBP0==0x3bdc ||fi.TBP0==0x3ab3 ||fi.TBP0<=0x3a92*/ ) & & fi . FPSM = = PSM_PSMCT32 & & ( fi . TPSM = = PSM_PSMT8 | | fi . TPSM = = PSM_PSMT4 ) & & ( fi . FBMSK = = 0x00FFFFFF | | ! fi . FBMSK ) )
{
skip = 0 ; //3dec 3fc0 3c9a
}
if ( ! fi . TME & & ( fi . FBP | fi . TBP0 ) ! = 0 & & ( fi . FBP | fi . TBP0 ) ! = 0x1180 & & ( fi . FBP | fi . TBP0 ) ! = 0x3be0 & & ( fi . FBP | fi . TBP0 ) ! = 0x3c80 & & fi . TBP0 ! = 0x3c9a & & ( fi . FBP | fi . TBP0 ) ! = 0x3d80 & & fi . TBP0 ! = 0x3dec & & fi . FPSM = = PSM_PSMCT32 & & ( fi . FBMSK = = 0 ) )
{
skip = 0 ; //3dec 3fc0 3c9a
}
if ( ! fi . TME & & ( fi . FBP | fi . TBP0 ) ! = 0 & & ( fi . FBP | fi . TBP0 ) ! = 0x1180 & & ( fi . FBP | fi . TBP0 ) ! = 0x3be0 & & ( fi . FBP | fi . TBP0 ) ! = 0x3c80 & & ( fi . FBP | fi . TBP0 ) ! = 0x3d80 & & fi . TBP0 ! = 0x3c9a & & fi . TBP0 ! = 0x3de & & fi . FPSM = = PSM_PSMCT32 & & ( fi . FBMSK = = 0 ) )
{
skip = 1 ; //3dec 3fc0 3c9a
}
else if ( fi . TME & & ( fi . FBP = = 0 | | fi . FBP = = 0x1180 ) & & fi . TBP0 = = 0x35B8 & & fi . TPSM = = PSM_PSMT4 )
{
skip = 1 ;
}
else
{
if ( ! fi . TME & & ( fi . FBP | fi . TBP0 ) = = 0x38d0 & & fi . FPSM = = PSM_PSMCT32 )
{
skip = 1 ; //3dec 3fc0 3c9a
}
}
}
return true ;
}
2015-07-11 13:14:11 +00:00
bool GSC_Tenchu ( const GSFrameInfo & fi , int & skip ) // DX ONLY
2011-03-27 12:53:53 +00:00
{
if ( skip = = 0 )
{
if ( fi . TME & & fi . TPSM = = PSM_PSMZ16 & & fi . FPSM = = PSM_PSMCT16 & & fi . FBMSK = = 0x03FFF )
{
skip = 3 ;
}
}
return true ;
}
2015-07-11 13:14:11 +00:00
bool GSC_Sly3 ( const GSFrameInfo & fi , int & skip ) // DX ONLY
2011-03-27 12:53:53 +00:00
{
if ( skip = = 0 )
{
2011-07-29 18:11:22 +00:00
if ( fi . TME & & ( fi . FBP = = 0x00000 | | fi . FBP = = 0x00700 | | fi . FBP = = 0x00a80 | | fi . FBP = = 0x00e00 ) & & fi . FPSM = = fi . TPSM & & ( fi . TBP0 = = 0x00000 | | fi . TBP0 = = 0x00700 | | fi . TBP0 = = 0x00a80 | | fi . TBP0 = = 0x00e00 ) & & fi . TPSM = = PSM_PSMCT16 )
2011-03-27 12:53:53 +00:00
{
2011-03-28 06:23:34 +00:00
skip = 1000 ;
}
}
else
{
if ( fi . TME & & fi . FPSM = = fi . TPSM & & fi . TPSM = = PSM_PSMCT16 & & fi . FBMSK = = 0x03FFF )
{
skip = 3 ;
2011-03-27 12:53:53 +00:00
}
}
2011-04-12 14:11:03 +00:00
2011-03-27 12:53:53 +00:00
return true ;
}
2015-07-11 13:14:11 +00:00
bool GSC_Sly2 ( const GSFrameInfo & fi , int & skip ) // DX ONLY
2011-03-27 12:53:53 +00:00
{
if ( skip = = 0 )
{
2011-04-12 14:11:03 +00:00
if ( fi . TME & & ( fi . FBP = = 0x00000 | | fi . FBP = = 0x00700 | | fi . FBP = = 0x00800 ) & & fi . FPSM = = fi . TPSM & & fi . TPSM = = PSM_PSMCT16 & & fi . FBMSK = = 0x03FFF )
2011-03-28 06:23:34 +00:00
{
skip = 1000 ;
}
}
else
{
if ( fi . TME & & fi . FPSM = = fi . TPSM & & fi . TPSM = = PSM_PSMCT16 & & fi . FBMSK = = 0x03FFF )
2011-03-27 12:53:53 +00:00
{
2011-03-28 06:23:34 +00:00
skip = 3 ;
2011-03-27 12:53:53 +00:00
}
}
return true ;
}
2012-05-18 16:51:18 +00:00
bool GSC_ShadowofRome ( const GSFrameInfo & fi , int & skip )
{
if ( skip = = 0 )
{
if ( fi . FBP & & fi . TPSM = = PSM_PSMT8H & & ( fi . FBMSK = = 0x00FFFFFF ) )
{
2012-06-19 01:02:52 +00:00
skip = 1 ;
2012-05-18 16:51:18 +00:00
}
else if ( fi . TME = = 0x0001 & & ( fi . TBP0 = = 0x1300 | | fi . TBP0 = = 0x0f00 ) & & fi . FBMSK > = 0xFFFFFF )
{
2012-06-19 01:02:52 +00:00
skip = 1 ;
2012-05-18 16:51:18 +00:00
}
2015-09-11 10:30:06 +00:00
else if ( fi . TME & & fi . FPSM = = PSM_PSMCT32 & & ( fi . TBP0 = = 0x0160 | | fi . TBP0 = = 0x01e0 | | fi . TBP0 < = 0x0800 ) & & fi . TPSM = = PSM_PSMT8 )
2012-05-18 16:51:18 +00:00
{
2012-06-19 01:02:52 +00:00
skip = 1 ;
2012-05-18 16:51:18 +00:00
}
else if ( fi . TME & & ( fi . TBP0 = = 0x0700 ) & & ( fi . TPSM = = PSM_PSMCT32 | | fi . TPSM = = PSM_PSMCT24 ) )
{
2012-06-19 01:02:52 +00:00
skip = 1 ;
2012-05-18 16:51:18 +00:00
}
}
return true ;
}
bool GSC_FFXII ( const GSFrameInfo & fi , int & skip )
{
2015-06-04 16:52:58 +00:00
if ( Aggresive & & skip = = 0 )
2012-05-18 16:51:18 +00:00
{
if ( fi . TME )
{
// depth textures (bully, mgs3s1 intro, Front Mission 5)
if ( ( fi . TPSM = = PSM_PSMZ32 | | fi . TPSM = = PSM_PSMZ24 | | fi . TPSM = = PSM_PSMZ16 | | fi . TPSM = = PSM_PSMZ16S ) | |
// General, often problematic post processing
( GSUtil : : HasSharedBits ( fi . FBP , fi . FPSM , fi . TBP0 , fi . TPSM ) ) )
{
skip = 1 ;
}
}
}
return true ;
}
bool GSC_FFX2 ( const GSFrameInfo & fi , int & skip )
{
2015-06-04 16:52:58 +00:00
if ( Aggresive & & skip = = 0 )
2012-05-18 16:51:18 +00:00
{
if ( fi . TME )
{
// depth textures (bully, mgs3s1 intro, Front Mission 5)
if ( ( fi . TPSM = = PSM_PSMZ32 | | fi . TPSM = = PSM_PSMZ24 | | fi . TPSM = = PSM_PSMZ16 | | fi . TPSM = = PSM_PSMZ16S ) | |
// General, often problematic post processing
( GSUtil : : HasSharedBits ( fi . FBP , fi . FPSM , fi . TBP0 , fi . TPSM ) ) )
{
skip = 1 ;
}
}
}
return true ;
}
bool GSC_FFX ( const GSFrameInfo & fi , int & skip )
{
2015-06-04 16:52:58 +00:00
if ( Aggresive & & skip = = 0 )
2012-05-18 16:51:18 +00:00
{
if ( fi . TME )
{
// depth textures (bully, mgs3s1 intro, Front Mission 5)
if ( ( fi . TPSM = = PSM_PSMZ32 | | fi . TPSM = = PSM_PSMZ24 | | fi . TPSM = = PSM_PSMZ16 | | fi . TPSM = = PSM_PSMZ16S ) | |
// General, often problematic post processing
( GSUtil : : HasSharedBits ( fi . FBP , fi . FPSM , fi . TBP0 , fi . TPSM ) ) )
{
skip = 1 ;
}
}
}
return true ;
}
2015-07-11 13:14:11 +00:00
bool GSC_DemonStone ( const GSFrameInfo & fi , int & skip ) // DX ONLY
2011-04-12 14:11:03 +00:00
{
if ( skip = = 0 )
{
if ( fi . TME & & fi . FBP = = 0x01400 & & fi . FPSM = = fi . TPSM & & ( fi . TBP0 = = 0x00000 | | fi . TBP0 = = 0x01000 ) & & fi . TPSM = = PSM_PSMCT16 )
{
skip = 1000 ;
}
}
else
{
if ( fi . TME & & ( fi . FBP = = 0x00000 | | fi . FBP = = 0x01000 ) & & fi . FPSM = = PSM_PSMCT32 )
{
skip = 2 ;
}
}
return true ;
}
2015-07-11 13:14:11 +00:00
bool GSC_BigMuthaTruckers ( const GSFrameInfo & fi , int & skip ) // DX ONLY
2011-04-12 14:11:03 +00:00
{
if ( skip = = 0 )
{
if ( fi . TME & & ( fi . FBP = = 0x00000 | | fi . FBP = = 0x00a00 ) & & fi . FPSM = = fi . TPSM & & fi . TPSM = = PSM_PSMCT16 )
{
skip = 3 ;
}
}
return true ;
}
2011-04-12 14:48:27 +00:00
bool GSC_TimeSplitters2 ( const GSFrameInfo & fi , int & skip )
{
if ( skip = = 0 )
{
2011-04-15 15:42:28 +00:00
if ( fi . TME & & ( fi . FBP = = 0x00000 | | fi . FBP = = 0x00e00 | | fi . FBP = = 0x01000 ) & & fi . FPSM = = fi . TPSM & & ( fi . TBP0 = = 0x00000 | | fi . TBP0 = = 0x00e00 | | fi . TBP0 = = 0x01000 ) & & fi . TPSM = = PSM_PSMCT32 & & fi . FBMSK = = 0x0FF000000 )
2011-04-12 14:48:27 +00:00
{
skip = 1 ;
}
}
return true ;
}
2015-07-11 13:14:11 +00:00
bool GSC_LordOfTheRingsTwoTowers ( const GSFrameInfo & fi , int & skip ) // DX ONLY
2011-04-15 15:42:28 +00:00
{
if ( skip = = 0 )
{
if ( fi . TME & & ( fi . FBP = = 0x01180 | | fi . FBP = = 0x01400 ) & & fi . FPSM = = fi . TPSM & & ( fi . TBP0 = = 0x00000 | | fi . TBP0 = = 0x01000 ) & & fi . TPSM = = PSM_PSMCT16 )
{
skip = 1000 ; //shadows
}
else if ( fi . TME & & fi . TPSM = = PSM_PSMZ16 & & fi . TBP0 = = 0x01400 & & fi . FPSM = = PSM_PSMCT16 & & fi . FBMSK = = 0x03FFF )
{
skip = 3 ; //wall of fog
}
}
else
{
if ( fi . TME & & ( fi . FBP = = 0x00000 | | fi . FBP = = 0x01000 ) & & ( fi . TBP0 = = 0x01180 | | fi . TBP0 = = 0x01400 ) & & fi . FPSM = = PSM_PSMCT32 )
{
skip = 2 ;
}
}
return true ;
}
2011-06-25 08:31:42 +00:00
bool GSC_LordOfTheRingsThirdAge ( const GSFrameInfo & fi , int & skip )
{
if ( skip = = 0 )
{
if ( ! fi . TME & & fi . FBP = = 0x03000 & & fi . FPSM = = PSM_PSMCT32 & & fi . TPSM = = PSM_PSMT4 & & fi . FBMSK = = 0xFF000000 )
{
skip = 1000 ; //shadows
}
}
else
{
if ( fi . TME & & ( fi . FBP = = 0x0 | | fi . FBP = = 0x00e00 | | fi . FBP = = 0x01000 ) & & fi . FPSM = = PSM_PSMCT32 & & fi . TBP0 = = 0x03000 & & fi . TPSM = = PSM_PSMCT24 )
{
skip = 1 ;
}
}
return true ;
}
2011-04-21 02:32:59 +00:00
bool GSC_RedDeadRevolver ( const GSFrameInfo & fi , int & skip )
{
if ( skip = = 0 )
{
if ( ! fi . TME & & ( fi . FBP = = 0x02420 | | fi . FBP = = 0x025e0 ) & & fi . FPSM = = PSM_PSMCT24 )
{
skip = 1200 ;
}
else if ( fi . TME & & ( fi . FBP = = 0x00800 | | fi . FBP = = 0x009c0 ) & & fi . FPSM = = fi . TPSM & & ( fi . TBP0 = = 0x01600 | | fi . TBP0 = = 0x017c0 ) & & fi . TPSM = = PSM_PSMCT32 )
{
skip = 2 ; //filter
}
else if ( fi . FBP = = 0x03700 & & fi . FPSM = = PSM_PSMCT32 & & fi . TPSM = = PSM_PSMCT24 )
{
skip = 2 ; //blur
}
}
else
{
if ( fi . TME & & ( fi . FBP = = 0x00800 | | fi . FBP = = 0x009c0 ) & & fi . FPSM = = PSM_PSMCT32 )
{
skip = 1 ;
}
}
return true ;
}
bool GSC_HeavyMetalThunder ( const GSFrameInfo & fi , int & skip )
{
if ( skip = = 0 )
{
if ( fi . TME & & fi . FBP = = 0x03100 & & fi . FPSM = = fi . TPSM & & fi . TBP0 = = 0x01c00 & & fi . TPSM = = PSM_PSMZ32 )
{
skip = 100 ;
}
}
else
{
if ( fi . TME & & fi . FBP = = 0x00e00 & & fi . FPSM = = fi . TPSM & & fi . TBP0 = = 0x02a00 & & fi . TPSM = = PSM_PSMCT32 )
{
skip = 1 ;
}
}
return true ;
}
2011-04-25 13:47:29 +00:00
bool GSC_BleachBladeBattlers ( const GSFrameInfo & fi , int & skip )
{
if ( skip = = 0 )
{
if ( fi . TME & & fi . FBP = = 0x01180 & & fi . FPSM = = fi . TPSM & & fi . TBP0 = = 0x03fc0 & & fi . TPSM = = PSM_PSMCT32 )
{
skip = 1 ;
}
}
return true ;
}
2015-07-11 13:14:11 +00:00
bool GSC_Castlevania ( const GSFrameInfo & fi , int & skip ) // DX ONLY
2011-04-25 13:47:29 +00:00
{
if ( skip = = 0 )
{
2015-05-26 15:03:13 +00:00
// This hack removes the shadows and globally darker image
// I think there are 2 issues on GSdx
//
// 1/ potential not correctly supported colclip.
//
// 2/ use of a 32 bits format to emulate a 16 bit formats
// For example, if you blend 64 time the value 4 on a dark destination pixels
//
// FMT32: 4*64 = 256 <= white pixels
//
// FMT16: output of blending will always be 0 because the 3 lsb of color is dropped.
// Therefore the pixel remains dark !!!
2012-05-18 16:51:18 +00:00
if ( fi . TME & & fi . FBP = = 0 & & fi . TBP0 & & fi . TPSM = = 10 & & fi . FBMSK = = 0xFFFFFF )
2011-04-25 13:47:29 +00:00
{
skip = 2 ;
}
}
return true ;
}
2016-02-06 16:32:12 +00:00
bool GSC_Black ( const GSFrameInfo & fi , int & skip ) // DX ONLY
2011-05-07 01:59:18 +00:00
{
if ( skip = = 0 )
{
2015-06-30 08:11:13 +00:00
// Note: the first part of the hack must be fixed in openGL (texture shuffle). Remains the 2nd part (HasSharedBits)
2011-05-07 18:14:07 +00:00
if ( fi . TME /*&& (fi.FBP == 0x00000 || fi.FBP == 0x008c0)*/ & & fi . FPSM = = PSM_PSMCT16 & & ( fi . TBP0 = = 0x01a40 | | fi . TBP0 = = 0x01b80 | | fi . TBP0 = = 0x030c0 ) & & fi . TPSM = = PSM_PSMZ16 | | ( GSUtil : : HasSharedBits ( fi . FBP , fi . FPSM , fi . TBP0 , fi . TPSM ) ) )
2011-05-07 01:59:18 +00:00
{
skip = 5 ;
}
}
else
{
2011-05-07 18:14:07 +00:00
if ( fi . TME & & ( fi . FBP = = 0x00000 | | fi . FBP = = 0x008c0 | | fi . FBP = = 0x0a00 ) & & fi . FPSM = = PSM_PSMCT32 & & fi . TPSM = = PSM_PSMT4 )
{
skip = 0 ;
}
else if ( ! fi . TME & & fi . FBP = = fi . TBP0 & & fi . FPSM = = PSM_PSMCT32 & & fi . TPSM = = PSM_PSMT8H )
2011-05-07 01:59:18 +00:00
{
skip = 0 ;
}
}
return true ;
}
2012-05-18 16:51:18 +00:00
bool GSC_CrashNburn ( const GSFrameInfo & fi , int & skip )
2011-06-25 08:31:42 +00:00
{
if ( skip = = 0 )
{
2012-05-18 16:51:18 +00:00
if ( fi . TME )
2011-08-11 12:54:57 +00:00
{
2012-05-18 16:51:18 +00:00
// depth textures (bully, mgs3s1 intro, Front Mission 5)
if ( ( fi . TPSM = = PSM_PSMZ32 | | fi . TPSM = = PSM_PSMZ24 | | fi . TPSM = = PSM_PSMZ16 | | fi . TPSM = = PSM_PSMZ16S ) | |
// General, often problematic post processing
( GSUtil : : HasSharedBits ( fi . FBP , fi . FPSM , fi . TBP0 , fi . TPSM ) ) )
{
skip = 1 ;
}
2011-08-11 12:54:57 +00:00
}
2011-06-25 08:31:42 +00:00
}
2012-05-18 16:51:18 +00:00
2011-06-25 08:31:42 +00:00
return true ;
}
2012-05-18 16:51:18 +00:00
bool GSC_TombRaider ( const GSFrameInfo & fi , int & skip )
2011-06-25 08:31:42 +00:00
{
if ( skip = = 0 )
{
2012-05-18 16:51:18 +00:00
if ( fi . TME & & fi . FBP = = 0x01000 & & fi . FPSM = = fi . TPSM & & fi . TPSM = = PSM_PSMCT32 )
2011-06-25 08:31:42 +00:00
{
2012-05-18 16:51:18 +00:00
skip = 1 ;
2011-06-25 08:31:42 +00:00
}
}
return true ;
}
2012-05-18 16:51:18 +00:00
bool GSC_TombRaiderLegend ( const GSFrameInfo & fi , int & skip )
2011-06-25 08:31:42 +00:00
{
if ( skip = = 0 )
{
2012-05-18 16:51:18 +00:00
if ( fi . TME & & fi . FBP = = 0x01000 & & fi . FPSM = = fi . TPSM & & fi . TPSM = = PSM_PSMCT32 & & ( fi . TBP0 = = 0x2b60 | | fi . TBP0 = = 0x2b80 | | fi . TBP0 = = 0x2E60 | | fi . TBP0 = = 0x3020 | | fi . TBP0 = = 0x3200 | | fi . TBP0 = = 0x3320 ) )
2011-06-25 08:31:42 +00:00
{
2012-06-19 01:02:52 +00:00
skip = 1 ;
2011-06-25 08:31:42 +00:00
}
2012-05-18 16:51:18 +00:00
else if ( fi . TPSM = = PSM_PSMCT32 & & ( fi . TPSM | fi . FBP ) = = 0x2fa0 & & ( fi . TBP0 = = 0x2bc0 ) & & fi . FBMSK = = 0 )
{
2012-06-19 01:02:52 +00:00
skip = 2 ;
2012-05-18 16:51:18 +00:00
}
} // ||fi.TBP0 ==0x2F00
2011-06-25 08:31:42 +00:00
return true ;
}
2012-05-18 16:51:18 +00:00
bool GSC_TombRaiderUnderWorld ( const GSFrameInfo & fi , int & skip )
2011-06-25 08:31:42 +00:00
{
if ( skip = = 0 )
{
2012-05-18 16:51:18 +00:00
if ( fi . TME & & fi . FBP = = 0x01000 & & fi . FPSM = = fi . TPSM & & fi . TPSM = = PSM_PSMCT32 & & ( fi . TBP0 = = 0x2B60 /*|| fi.TBP0 == 0x2EFF || fi.TBP0 ==0x2F00 || fi.TBP0 == 0x3020*/ | | fi . TBP0 > = 0x2C01 & & fi . TBP0 ! = 0x3029 & & fi . TBP0 ! = 0x302d ) )
2011-06-25 08:31:42 +00:00
{
2012-06-19 01:02:52 +00:00
skip = 1 ;
2011-06-25 08:31:42 +00:00
}
2012-05-18 16:51:18 +00:00
else if ( fi . TPSM = = PSM_PSMCT32 & & ( fi . TPSM | fi . FBP ) = = 0x2c00 & & ( fi . TBP0 = = 0x0ee0 ) & & fi . FBMSK = = 0 )
2011-06-25 08:31:42 +00:00
{
2012-06-19 01:02:52 +00:00
skip = 2 ;
2011-06-25 08:31:42 +00:00
}
2012-05-18 16:51:18 +00:00
/*else if(fi.TPSM == PSM_PSMCT16 && (fi.TPSM | fi.FBP)>=0x0 && (fi.TBP0 >=0x0) && fi.FBMSK ==0)
{
2012-06-19 01:02:52 +00:00
skip = 600 ;
2012-05-18 16:51:18 +00:00
} */
2011-06-25 08:31:42 +00:00
}
2012-05-18 16:51:18 +00:00
2011-06-25 08:31:42 +00:00
return true ;
}
2012-05-18 16:51:18 +00:00
bool GSC_SSX3 ( const GSFrameInfo & fi , int & skip )
2011-06-25 08:31:42 +00:00
{
2015-06-04 16:52:58 +00:00
if ( Aggresive & & skip = = 0 )
2011-06-25 08:31:42 +00:00
{
2012-05-18 16:51:18 +00:00
if ( fi . TME )
2011-06-25 08:31:42 +00:00
{
2012-05-18 16:51:18 +00:00
// depth textures (bully, mgs3s1 intro, Front Mission 5)
if ( ( fi . TPSM = = PSM_PSMZ32 | | fi . TPSM = = PSM_PSMZ24 | | fi . TPSM = = PSM_PSMZ16 | | fi . TPSM = = PSM_PSMZ16S ) | |
// General, often problematic post processing
( GSUtil : : HasSharedBits ( fi . FBP , fi . FPSM , fi . TBP0 , fi . TPSM ) ) )
{
skip = 1 ;
}
2011-06-25 08:31:42 +00:00
}
2012-05-18 16:51:18 +00:00
}
return true ;
}
bool GSC_FFVIIDoC ( const GSFrameInfo & fi , int & skip )
{
if ( skip = = 0 )
{
if ( fi . TME & & fi . FBP = = 0x01c00 & & fi . FPSM = = PSM_PSMCT32 & & fi . TBP0 = = 0x02c00 & & fi . TPSM = = PSM_PSMCT24 )
2011-06-25 08:31:42 +00:00
{
2012-05-18 16:51:18 +00:00
skip = 1 ;
}
if ( ! fi . TME & & fi . FBP = = 0x01c00 & & fi . FPSM = = PSM_PSMCT32 & & fi . TBP0 = = 0x01c00 & & fi . TPSM = = PSM_PSMCT24 )
{
//skip = 1;
2011-06-25 08:31:42 +00:00
}
}
return true ;
}
2011-07-01 04:50:32 +00:00
bool GSC_DevilMayCry3 ( const GSFrameInfo & fi , int & skip )
{
if ( skip = = 0 )
{
2015-06-30 08:11:13 +00:00
if ( Dx_only & & fi . TME & & fi . FBP = = 0x01800 & & fi . FPSM = = PSM_PSMCT16 & & fi . TBP0 = = 0x01000 & & fi . TPSM = = PSM_PSMZ16 )
2011-07-01 04:50:32 +00:00
{
skip = 32 ;
}
if ( fi . TME & & fi . FBP = = 0x01800 & & fi . FPSM = = PSM_PSMZ32 & & fi . TBP0 = = 0x0800 & & fi . TPSM = = PSM_PSMT8H )
{
skip = 16 ;
}
if ( fi . TME & & fi . FBP = = 0x01800 & & fi . FPSM = = PSM_PSMCT32 & & fi . TBP0 = = 0x0 & & fi . TPSM = = PSM_PSMT8H )
{
skip = 24 ;
}
}
return true ;
}
2012-05-18 16:51:18 +00:00
bool GSC_StarWarsForceUnleashed ( const GSFrameInfo & fi , int & skip )
{
if ( skip = = 0 )
{
if ( fi . TME & & ( fi . FBP = = 0x038a0 | | fi . FBP = = 0x03ae0 ) & & fi . FPSM = = fi . TPSM & & fi . TBP0 = = 0x02300 & & fi . TPSM = = PSM_PSMZ24 )
{
skip = 1000 ; //9, shadows
}
}
else
{
if ( fi . TME & & fi . FBP = = fi . TBP0 & & fi . FPSM = = fi . TPSM & & ( fi . TBP0 = = 0x034a0 | | fi . TBP0 = = 0x36e0 ) & & fi . TPSM = = PSM_PSMCT16 )
{
skip = 2 ;
}
}
return true ;
}
bool GSC_StarWarsBattlefront ( const GSFrameInfo & fi , int & skip )
{
if ( skip = = 0 )
{
if ( fi . TME & & ( fi . FBP > 0x0 & & fi . FBP < 0x01000 ) & & fi . FPSM = = PSM_PSMCT32 & & ( fi . TBP0 > 0x02000 & & fi . TBP0 < 0x03000 ) & & fi . TPSM = = PSM_PSMT8 )
{
skip = 1 ;
}
}
return true ;
}
bool GSC_StarWarsBattlefront2 ( const GSFrameInfo & fi , int & skip )
{
if ( skip = = 0 )
{
if ( fi . TME & & ( fi . FBP > 0x01000 & & fi . FBP < 0x02000 ) & & fi . FPSM = = PSM_PSMCT32 & & ( fi . TBP0 > 0x0 & & fi . TBP0 < 0x01000 ) & & fi . TPSM = = PSM_PSMT8 )
{
skip = 1 ;
}
if ( fi . TME & & ( fi . FBP > 0x01000 & & fi . FBP < 0x02000 ) & & fi . FPSM = = PSM_PSMZ32 & & ( fi . TBP0 > 0x0 & & fi . TBP0 < 0x01000 ) & & fi . TPSM = = PSM_PSMT8 )
{
skip = 1 ;
}
}
return true ;
}
bool GSC_BlackHawkDown ( const GSFrameInfo & fi , int & skip )
{
if ( skip = = 0 )
{
2015-06-30 08:11:13 +00:00
if ( Dx_only & & fi . TME & & fi . FBP = = 0x00800 & & fi . FPSM = = PSM_PSMCT16 & & fi . TBP0 = = 0x01800 & & fi . TPSM = = PSM_PSMZ16 )
2012-05-18 16:51:18 +00:00
{
skip = 2 ; //wall of fog
}
if ( fi . TME & & fi . FBP = = fi . TBP0 & & fi . FPSM = = PSM_PSMCT32 & & fi . TPSM = = PSM_PSMT8 )
{
skip = 5 ; //night filter
}
}
return true ;
}
2011-07-04 05:31:47 +00:00
bool GSC_Burnout ( const GSFrameInfo & fi , int & skip )
{
if ( skip = = 0 )
{
if ( fi . TME & & ( fi . FBP = = 0x01dc0 | | fi . FBP = = 0x02200 ) & & fi . FPSM = = fi . TPSM & & ( fi . TBP0 = = 0x01dc0 | | fi . TBP0 = = 0x02200 ) & & fi . TPSM = = PSM_PSMCT32 )
{
skip = 4 ;
}
2011-07-04 08:19:24 +00:00
else if ( fi . TME & & fi . FPSM = = PSM_PSMCT16 & & fi . TPSM = = PSM_PSMZ16 ) //fog
2011-07-04 05:31:47 +00:00
{
2015-06-30 08:11:13 +00:00
if ( ! Dx_only ) return false ;
2011-07-04 08:19:24 +00:00
if ( fi . FBP = = 0x00a00 & & fi . TBP0 = = 0x01e00 )
{
skip = 4 ; //pal
}
if ( fi . FBP = = 0x008c0 & & fi . TBP0 = = 0x01a40 )
{
skip = 3 ; //ntsc
}
2011-07-04 05:31:47 +00:00
}
else if ( fi . TME & & ( fi . FBP = = 0x02d60 | | fi . FBP = = 0x033a0 ) & & fi . FPSM = = fi . TPSM & & ( fi . TBP0 = = 0x02d60 | | fi . TBP0 = = 0x033a0 ) & & fi . TPSM = = PSM_PSMCT32 & & fi . FBMSK = = 0x0 )
{
skip = 2 ; //impact screen
}
}
2011-07-04 08:19:24 +00:00
return true ;
}
bool GSC_MidnightClub3 ( const GSFrameInfo & fi , int & skip )
{
if ( skip = = 0 )
{
if ( fi . TME & & ( fi . FBP > 0x01d00 & & fi . FBP < = 0x02a00 ) & & fi . FPSM = = PSM_PSMCT32 & & ( fi . FBP > = 0x01600 & & fi . FBP < 0x03260 ) & & fi . TPSM = = PSM_PSMT8H )
{
skip = 1 ;
}
}
2011-07-04 05:31:47 +00:00
return true ;
}
2015-07-11 13:14:11 +00:00
bool GSC_SpyroNewBeginning ( const GSFrameInfo & fi , int & skip ) // DX ONLY
2011-07-29 18:11:22 +00:00
{
if ( skip = = 0 )
{
if ( fi . TME & & fi . FBP = = fi . TBP0 & & fi . FPSM = = fi . TPSM & & fi . TBP0 = = 0x034a0 & & fi . TPSM = = PSM_PSMCT16 )
{
skip = 2 ;
}
}
return true ;
}
2015-07-11 13:14:11 +00:00
bool GSC_SpyroEternalNight ( const GSFrameInfo & fi , int & skip ) // DX ONLY
2011-07-29 18:11:22 +00:00
{
if ( skip = = 0 )
{
if ( fi . TME & & fi . FBP = = fi . TBP0 & & fi . FPSM = = fi . TPSM & & ( fi . TBP0 = = 0x034a0 | | fi . TBP0 = = 0x035a0 | | fi . TBP0 = = 0x036e0 ) & & fi . TPSM = = PSM_PSMCT16 )
{
skip = 2 ;
}
}
return true ;
}
bool GSC_TalesOfLegendia ( const GSFrameInfo & fi , int & skip )
{
if ( skip = = 0 )
{
if ( fi . TME & & ( fi . FBP = = 0x3f80 | | fi . FBP = = 0x03fa0 ) & & fi . FPSM = = PSM_PSMCT32 & & fi . TPSM = = PSM_PSMT8 )
{
skip = 3 ; //3, 9
}
if ( fi . TME & & fi . FBP = = 0x3800 & & fi . FPSM = = PSM_PSMCT32 & & fi . TPSM = = PSM_PSMZ32 )
{
skip = 2 ;
}
2012-05-18 16:51:18 +00:00
if ( fi . TME & & fi . FBP & & fi . FPSM = = PSM_PSMCT32 & & fi . TBP0 = = 0x3d80 )
{
2012-06-19 01:02:52 +00:00
skip = 1 ;
2012-05-18 16:51:18 +00:00
}
if ( fi . TME & & fi . FBP = = 0x1c00 & & ( fi . TBP0 = = 0x2e80 | | fi . TBP0 = = 0x2d80 ) & & fi . TPSM = = 0 & & fi . FBMSK = = 0xff000000 )
{
2012-06-19 01:02:52 +00:00
skip = 1 ;
2012-05-18 16:51:18 +00:00
}
if ( ! fi . TME & & fi . FBP = = 0x2a00 & & ( fi . TBP0 = = 0x1C00 ) & & fi . TPSM = = 0 & & fi . FBMSK = = 0x00FFFFFF )
{
2012-06-19 01:02:52 +00:00
skip = 1 ;
2012-05-18 16:51:18 +00:00
}
2011-07-29 18:11:22 +00:00
}
return true ;
}
2011-08-11 12:54:57 +00:00
bool GSC_NanoBreaker ( const GSFrameInfo & fi , int & skip )
{
if ( skip = = 0 )
{
2011-08-28 19:52:11 +00:00
if ( fi . TME & & fi . FBP = = 0x0 & & fi . FPSM = = PSM_PSMCT32 & & ( fi . TBP0 = = 0x03800 | | fi . TBP0 = = 0x03900 ) & & fi . TPSM = = PSM_PSMCT16S )
2011-08-11 12:54:57 +00:00
{
skip = 2 ;
}
}
return true ;
}
bool GSC_Kunoichi ( const GSFrameInfo & fi , int & skip )
{
if ( skip = = 0 )
{
2012-05-18 16:51:18 +00:00
if ( ! fi . TME & & ( fi . FBP = = 0x0 | | fi . FBP = = 0x00700 | | fi . FBP = = 0x00800 ) & & fi . FPSM = = PSM_PSMCT32 & & fi . FBMSK = = 0x00FFFFFF )
2011-08-11 12:54:57 +00:00
{
skip = 3 ;
}
2012-05-18 16:51:18 +00:00
if ( fi . TME & & ( fi . FBP = = 0x0700 | | fi . FBP = = 0 ) & & fi . TBP0 = = 0x0e00 & & fi . TPSM = = 0 & & fi . FBMSK = = 0 )
{
2012-06-19 01:02:52 +00:00
skip = 1 ;
2012-05-18 16:51:18 +00:00
}
if ( fi . TME )
{
// depth textures (bully, mgs3s1 intro, Front Mission 5)
if ( ( fi . TPSM = = PSM_PSMZ32 | | fi . TPSM = = PSM_PSMZ24 | | fi . TPSM = = PSM_PSMZ16 | | fi . TPSM = = PSM_PSMZ16S ) | |
// General, often problematic post processing
( GSUtil : : HasSharedBits ( fi . FBP , fi . FPSM , fi . TBP0 , fi . TPSM ) ) )
{
skip = 1 ;
}
}
}
else
{
if ( fi . TME & & ( fi . FBP = = 0x0e00 ) & & fi . FPSM = = PSM_PSMCT32 & & fi . FBMSK = = 0xFF000000 )
{
skip = 0 ;
}
2011-08-11 12:54:57 +00:00
}
return true ;
}
2011-09-06 01:22:40 +00:00
bool GSC_Yakuza ( const GSFrameInfo & fi , int & skip )
{
if ( 1
& & ! skip
& & ! fi . TME
& & ( 0
| | fi . FBP = = 0x1c20 & & fi . TBP0 = = 0xe00 //ntsc (EU and US DVDs)
| | fi . FBP = = 0x1e20 & & fi . TBP0 = = 0x1000 //pal1
| | fi . FBP = = 0x1620 & & fi . TBP0 = = 0x800 //pal2
)
& & fi . TPSM = = PSM_PSMZ24
& & fi . FPSM = = PSM_PSMCT32
/*
& & fi . FBMSK = = 0xffffff
& & fi . TZTST
& & ! GSUtil : : HasSharedBits ( fi . FBP , fi . FPSM , fi . TBP0 , fi . TPSM )
*/
)
{
2011-10-09 07:43:10 +00:00
skip = 3 ;
2011-09-06 01:22:40 +00:00
}
return true ;
}
bool GSC_Yakuza2 ( const GSFrameInfo & fi , int & skip )
{
if ( 1
& & ! skip
& & ! fi . TME
& & ( 0
| | fi . FBP = = 0x1c20 & & fi . TBP0 = = 0xe00 //ntsc (EU DVD)
| | fi . FBP = = 0x1e20 & & fi . TBP0 = = 0x1000 //pal1
| | fi . FBP = = 0x1620 & & fi . TBP0 = = 0x800 //pal2
)
& & fi . TPSM = = PSM_PSMZ24
& & fi . FPSM = = PSM_PSMCT32
/*
& & fi . FBMSK = = 0xffffff
& & fi . TZTST
& & ! GSUtil : : HasSharedBits ( fi . FBP , fi . FPSM , fi . TBP0 , fi . TPSM )
*/
)
{
skip = 17 ;
}
return true ;
}
2011-10-05 09:19:32 +00:00
bool GSC_SkyGunner ( const GSFrameInfo & fi , int & skip )
{
if ( skip = = 0 )
{
if ( ! fi . TME & & ! ( fi . FBP = = 0x0 | | fi . FBP = = 0x00800 | | fi . FBP = = 0x008c0 | | fi . FBP = = 0x03e00 ) & & fi . FPSM = = PSM_PSMCT32 & & ( fi . TBP0 = = 0x0 | | fi . TBP0 = = 0x01800 ) & & fi . TPSM = = PSM_PSMCT32 )
{
skip = 1 ; //Huge Vram usage
}
}
return true ;
}
bool GSC_JamesBondEverythingOrNothing ( const GSFrameInfo & fi , int & skip )
{
if ( skip = = 0 )
{
if ( fi . TME & & ( fi . FBP < 0x02000 & & ! ( fi . FBP = = 0x0 | | fi . FBP = = 0x00e00 ) ) & & fi . FPSM = = PSM_PSMCT32 & & ( fi . TBP0 > 0x01c00 & & fi . TBP0 < 0x03000 ) & & fi . TPSM = = PSM_PSMT8 )
{
skip = 1 ; //Huge Vram usage
}
}
return true ;
}
2012-05-18 16:51:18 +00:00
bool GSC_ZettaiZetsumeiToshi2 ( const GSFrameInfo & fi , int & skip )
{
if ( skip = = 0 )
{
if ( fi . TME & & fi . TPSM = = PSM_PSMCT16S & & ( fi . FBMSK > = 0x6FFFFFFF | | fi . FBMSK = = 0 ) )
{
skip = 1000 ;
}
else if ( fi . TME & & fi . TPSM = = PSM_PSMCT32 & & fi . FBMSK = = 0xFF000000 )
{
2012-06-19 01:02:52 +00:00
skip = 2 ;
2012-05-18 16:51:18 +00:00
}
else if ( ( fi . FBP | fi . TBP0 ) & & fi . FPSM = = fi . TPSM & & fi . TPSM = = PSM_PSMCT16 & & fi . FBMSK = = 0x3FFF )
{
2015-06-30 08:11:13 +00:00
// Note start of the effect (texture shuffle) is fixed in openGL but maybe not the extra draw
// call....
2012-05-18 16:51:18 +00:00
skip = 1000 ;
}
}
else
{
if ( ! fi . TME & & fi . TPSM = = PSM_PSMCT32 & & fi . FBP = = 0x1180 & & fi . TBP0 = = 0x1180 & & ( fi . FBMSK = = 0 ) )
{
skip = 0 ; //
}
if ( fi . TME & & fi . TPSM = = PSM_PSMT4 & & fi . FBP & & ( fi . TBP0 ! = 0x3753 ) )
{
skip = 0 ; //
}
if ( fi . TME & & fi . TPSM = = PSM_PSMT8H & & fi . FBP = = 0x22e0 & & fi . TBP0 = = 0x36e0 )
{
skip = 0 ; //
}
if ( ! fi . TME & & fi . TPSM = = PSM_PSMT8H & & fi . FBP = = 0x22e0 )
{
skip = 0 ; //
}
if ( fi . TME & & fi . TPSM = = PSM_PSMT8 & & ( fi . FBP = = 0x1180 | | fi . FBP = = 0 ) & & ( fi . TBP0 ! = 0x3764 & & fi . TBP0 ! = 0x370f ) )
{
skip = 0 ; //
}
if ( fi . TME & & fi . TPSM = = PSM_PSMCT16S & & ( fi . FBP = = 0x1180 ) )
{
skip = 2 ; //
}
}
return true ;
}
bool GSC_ShinOnimusha ( const GSFrameInfo & fi , int & skip )
{
if ( skip = = 0 )
{
if ( fi . TME & & fi . FBP = = 0x001000 & & ( fi . TBP0 = = 0 | | fi . TBP0 = = 0x0800 ) & & fi . TPSM = = PSM_PSMT8H & & fi . FBMSK = = 0x00FFFFFF )
{
2012-06-19 01:02:52 +00:00
skip = 0 ;
2012-05-18 16:51:18 +00:00
}
else if ( fi . TPSM = = PSM_PSMCT24 & & fi . TME & & fi . FBP = = 0x01000 ) // || fi.FBP == 0x00000
{
2012-06-19 01:02:52 +00:00
skip = 28 ; //28 30 56 64
2012-05-18 16:51:18 +00:00
}
else if ( fi . FBP & & fi . TPSM = = PSM_PSMT8H & & fi . FBMSK = = 0xFFFFFF )
{
2012-06-19 01:02:52 +00:00
skip = 0 ; //24 33 40 9
2012-05-18 16:51:18 +00:00
}
else if ( fi . TPSM = = PSM_PSMT8H & & fi . FBMSK = = 0xFF000000 )
{
2012-06-19 01:02:52 +00:00
skip = 1 ;
2012-05-18 16:51:18 +00:00
}
else if ( fi . TME & & ( fi . TBP0 = = 0x1400 | | fi . TBP0 = = 0x1000 | | fi . TBP0 = = 0x1200 ) & & ( fi . TPSM = = PSM_PSMCT32 | | fi . TPSM = = PSM_PSMCT24 ) )
{
skip = 1 ;
2012-06-19 01:02:52 +00:00
}
2012-05-18 16:51:18 +00:00
}
return true ;
}
2015-07-11 13:14:11 +00:00
bool GSC_XE3 ( const GSFrameInfo & fi , int & skip ) // DX ONLY
2012-05-18 16:51:18 +00:00
{
if ( skip = = 0 )
{
if ( fi . TPSM = = PSM_PSMT8H & & fi . FBMSK > = 0xEFFFFFFF )
{
2012-06-19 01:02:52 +00:00
skip = 73 ;
2012-05-18 16:51:18 +00:00
}
else if ( fi . TME & & fi . FBP = = 0x03800 & & fi . TBP0 & & fi . TPSM = = 0 & & fi . FBMSK = = 0 )
{
2012-06-19 01:02:52 +00:00
skip = 1 ;
2012-05-18 16:51:18 +00:00
}
/*else if(fi.TPSM ==0x00000 && PSM_PSMCT24 && fi.TME && fi.FBP == 0x03800)
{
2012-06-19 01:02:52 +00:00
skip = 1 ;
2012-05-18 16:51:18 +00:00
} */
/*else if(fi.TME ==0 && (fi.FBP ==0 ) && fi.FPSM == PSM_PSMCT32 && ( fi.TPSM == PSM_PSMT8 || fi.TPSM == PSM_PSMT4) && (fi.FBMSK == 0x00FFFFFF || fi.FBMSK == 0xFF000000))
{
2012-06-19 01:02:52 +00:00
skip = 1 ;
2012-05-18 16:51:18 +00:00
} */
else
{
if ( fi . TME )
{
// depth textures (bully, mgs3s1 intro, Front Mission 5)
if ( ( fi . TPSM = = PSM_PSMZ32 | | fi . TPSM = = PSM_PSMZ24 | | fi . TPSM = = PSM_PSMZ16 | | fi . TPSM = = PSM_PSMZ16S ) | |
// General, often problematic post processing
( GSUtil : : HasSharedBits ( fi . FBP , fi . FPSM , fi . TBP0 , fi . TPSM ) ) )
{
skip = 1 ;
}
}
}
}
return true ;
}
bool GSC_GetaWay ( const GSFrameInfo & fi , int & skip )
{
if ( skip = = 0 )
{
if ( ( fi . FBP = = 0 | | fi . FBP = = 0x1180 ) & & fi . TPSM = = PSM_PSMT8H & & fi . FBMSK = = 0 )
{
skip = 1 ;
}
}
return true ;
}
bool GSC_SakuraWarsSoLongMyLove ( const GSFrameInfo & fi , int & skip )
{
if ( skip = = 0 )
{
if ( fi . TME = = 0 & & fi . FBP ! = fi . TBP0 & & fi . TBP0 & & fi . FBMSK = = 0x00FFFFFF )
{
2012-06-19 01:02:52 +00:00
skip = 3 ;
2012-05-18 16:51:18 +00:00
}
else if ( fi . TME = = 0 & & fi . FBP = = fi . TBP0 & & ( fi . TBP0 = = 0x1200 | | fi . TBP0 = = 0x1180 | | fi . TBP0 = = 0 ) & & fi . FBMSK = = 0x00FFFFFF )
{
2012-06-19 01:02:52 +00:00
skip = 3 ;
2012-05-18 16:51:18 +00:00
}
else if ( fi . TME & & ( fi . FBP = = 0 | | fi . FBP = = 0x1180 ) & & fi . FPSM = = PSM_PSMCT32 & & fi . TBP0 = = 0x3F3F & & fi . TPSM = = PSM_PSMT8 )
{
2012-06-19 01:02:52 +00:00
skip = 1 ;
2012-05-18 16:51:18 +00:00
}
}
return true ;
}
bool GSC_FightingBeautyWulong ( const GSFrameInfo & fi , int & skip )
{
if ( skip = = 0 )
{
if ( fi . TME & & ( fi . TBP0 = = 0x0700 | | fi . TBP0 = = 0x0a80 ) & & ( fi . TPSM = = PSM_PSMCT32 | | fi . TPSM = = PSM_PSMCT24 ) )
{
skip = 1 ;
2012-06-19 01:02:52 +00:00
}
2012-05-18 16:51:18 +00:00
}
return true ;
}
bool GSC_TouristTrophy ( const GSFrameInfo & fi , int & skip )
{
if ( skip = = 0 )
{
if ( fi . TME & & fi . FBP > = 0x02f00 & & fi . FPSM = = PSM_PSMCT32 & & ( fi . TBP0 = = 0x00000 | | fi . TBP0 = = 0x01180 ) & & fi . TPSM = = PSM_PSMT8 )
{
skip = 770 ;
}
if ( fi . TME & & fi . FBP > = 0x02de0 & & fi . FPSM = = PSM_PSMCT32 & & ( fi . TBP0 = = 0 | | fi . TBP0 = = 0x1a40 | | fi . TBP0 = = 0x2300 ) & & fi . TPSM = = PSM_PSMT8 )
{
skip = 770 ; //480P
}
}
return true ;
}
bool GSC_GTASanAndreas ( const GSFrameInfo & fi , int & skip )
{
if ( skip = = 0 )
{
if ( fi . TME & & ( fi . FBP = = 0x0a00 | | fi . FBP = = 0x08c0 ) & & ( fi . TBP0 = = 0x1b80 | | fi . TBP0 = = 0x1a40 ) & & fi . FPSM = = fi . TPSM & & fi . TPSM = = PSM_PSMCT32 )
{
2012-06-19 01:02:52 +00:00
skip = 1 ;
2012-05-18 16:51:18 +00:00
}
}
return true ;
}
bool GSC_FrontMission5 ( const GSFrameInfo & fi , int & skip )
{
if ( skip = = 0 )
{
if ( fi . TPSM = = PSM_PSMT8H & & fi . FBMSK = = 0 )
{
2012-06-19 01:02:52 +00:00
skip = 1 ;
2012-05-18 16:51:18 +00:00
}
if ( fi . TME & & ( fi . FBP = = 0x1000 ) & & ( fi . TBP0 = = 0x2e00 | | fi . TBP0 = = 0x3200 ) & & fi . FPSM = = fi . TPSM & & fi . TPSM = = PSM_PSMCT32 )
{
2012-06-19 01:02:52 +00:00
skip = 1 ; //fi.TBP0 ==0x1f00
2012-05-18 16:51:18 +00:00
}
}
return true ;
}
bool GSC_GodHand ( const GSFrameInfo & fi , int & skip )
{
if ( skip = = 0 )
{
if ( fi . TME & & ( fi . FBP = = 0x0 ) & & ( fi . TBP0 = = 0x2800 ) & & fi . FPSM = = fi . TPSM & & fi . TPSM = = PSM_PSMCT32 )
{
2012-06-19 01:02:52 +00:00
skip = 1 ;
2012-05-18 16:51:18 +00:00
}
}
return true ;
}
bool GSC_KnightsOfTheTemple2 ( const GSFrameInfo & fi , int & skip )
{
if ( skip = = 0 )
{
if ( fi . TPSM = = PSM_PSMT8H & & fi . FBMSK = = 0 )
{
2012-06-19 01:02:52 +00:00
skip = 1 ;
2012-05-18 16:51:18 +00:00
}
else if ( fi . TPSM = = 0x00000 & & PSM_PSMCT24 & & fi . TME & & ( fi . FBP = = 0x3400 | | fi . FBP = = 0x3a00 ) )
{
2012-06-19 01:02:52 +00:00
skip = 1 ;
2012-05-18 16:51:18 +00:00
}
}
return true ;
}
bool GSC_UltramanFightingEvolution ( const GSFrameInfo & fi , int & skip )
{
if ( skip = = 0 )
{
if ( fi . TME & & fi . FBP = = 0x2a00 & & fi . FPSM = = PSM_PSMZ24 & & fi . TBP0 = = 0x1c00 & & fi . TPSM = = PSM_PSMZ24 )
{
2012-06-19 01:02:52 +00:00
skip = 5 ; // blur
2012-05-18 16:51:18 +00:00
}
}
return true ;
}
bool GSC_DeathByDegreesTekkenNinaWilliams ( const GSFrameInfo & fi , int & skip )
{
if ( skip = = 0 )
{
if ( fi . TME & & ( fi . FBP = = 0 ) & & fi . TBP0 = = 0x34a0 & & ( fi . TPSM = = PSM_PSMCT32 ) )
{
2012-06-19 01:02:52 +00:00
skip = 1 ;
2012-05-18 16:51:18 +00:00
}
else if ( ( fi . FBP = = 0x3500 ) & & fi . TPSM = = PSM_PSMT8 & & fi . FBMSK = = 0xFFFF00FF )
{
2012-06-19 01:02:52 +00:00
skip = 4 ;
2012-05-18 16:51:18 +00:00
}
}
if ( fi . TME )
{
if ( ( fi . FBP | fi . TBP0 | fi . FPSM | fi . TPSM ) & & ( fi . FBMSK = = 0x00FFFFFF ) )
{
2012-06-19 01:02:52 +00:00
skip = 1 ;
2012-05-18 16:51:18 +00:00
}
}
return true ;
}
bool GSC_AlpineRacer3 ( const GSFrameInfo & fi , int & skip )
{
if ( skip = = 0 )
{
2015-09-11 10:30:06 +00:00
if ( ! fi . TME & & fi . FBP = = 0 & & ( fi . FBMSK = = 0x0001 | | fi . FBMSK = = 0x00FFFFFF ) )
2012-05-18 16:51:18 +00:00
{
2012-06-19 01:02:52 +00:00
skip = 2 ;
2012-05-18 16:51:18 +00:00
}
}
return true ;
}
bool GSC_HummerBadlands ( const GSFrameInfo & fi , int & skip )
{
if ( skip = = 0 )
{
if ( fi . TME & & ( fi . FBP = = 0x0a00 ) & & ( fi . TBP0 = = 0x03200 | | fi . TBP0 = = 0x3700 ) & & fi . FPSM = = fi . TPSM & & fi . TPSM = = PSM_PSMCT32 )
{
2012-06-19 01:02:52 +00:00
skip = 1 ;
2012-05-18 16:51:18 +00:00
}
}
return true ;
}
bool GSC_SengokuBasara ( const GSFrameInfo & fi , int & skip )
{
if ( skip = = 0 )
{
if ( fi . TME & & ( fi . TBP0 = = 0x1800 ) & & fi . FBMSK = = 0xFF000000 )
{
2012-06-19 01:02:52 +00:00
skip = 1 ;
2012-05-18 16:51:18 +00:00
}
}
return true ;
}
2015-07-11 13:14:11 +00:00
bool GSC_Grandia3 ( const GSFrameInfo & fi , int & skip ) // DX ONLY
2012-05-18 16:51:18 +00:00
{
if ( skip = = 0 )
{
if ( fi . TME & & ( fi . FBP = = 0x0 | | fi . FBP = = 0x0e00 ) & & ( fi . TBP0 = = 0x2a00 | | fi . TBP0 = = 0x0e00 | | fi . TBP0 = = 0 ) & & fi . FPSM = = fi . TPSM & & fi . TPSM = = PSM_PSMCT32 )
{
2012-06-19 01:02:52 +00:00
skip = 1 ;
2012-05-18 16:51:18 +00:00
}
}
return true ;
}
bool GSC_FinalFightStreetwise ( const GSFrameInfo & fi , int & skip )
{
if ( skip = = 0 )
{
if ( ! fi . TME & & ( fi . FBP = = 0 | | fi . FBP = = 0x08c0 ) & & fi . FPSM = = PSM_PSMCT32 & & ( fi . TPSM = = PSM_PSMT8 | | fi . TPSM = = PSM_PSMT4 ) & & fi . FBMSK = = 0x00FFFFFF )
{
skip = 3 ;
}
}
return true ;
}
bool GSC_TalesofSymphonia ( const GSFrameInfo & fi , int & skip )
{
if ( skip = = 0 )
{
2015-09-11 10:30:06 +00:00
if ( fi . TME & & fi . FPSM = = PSM_PSMCT32 & & ( fi . TBP0 = = 0x2bc0 | | fi . TBP0 < = 0x0200 ) & & ( fi . FBMSK = = 0xFF000000 | | fi . FBMSK = = 0x00FFFFFF ) )
2012-05-18 16:51:18 +00:00
{
2012-06-19 01:02:52 +00:00
skip = 1 ; //fi.FBMSK==0
2012-05-18 16:51:18 +00:00
}
if ( fi . TME & & ( fi . TBP0 = = 0x1180 | | fi . TBP0 = = 0x1a40 | | fi . TBP0 = = 0x2300 ) & & fi . FBMSK > = 0xFF000000 )
{
2012-06-19 01:02:52 +00:00
skip = 1 ;
2012-05-18 16:51:18 +00:00
}
}
return true ;
}
GSdx: CRC hacks: duplicates/stuff:
- Console message for duplicate CRCs on our list.
- Removed trivial duplicates.
- Added some CRCs from comments on r5214
- Soul Calibur 2 now has the same crc hack as Soul Calibur 3.
We still need to address the following 7 duplicates (most were already there before r5214):
{0x7D4EA48F, HauntingGround, EU, 0},
{0x7D4EA48F, Genji, NoRegion, 0},
{0x7ACF7E03, ICO, NoRegion, 0},
{0x7ACF7E03, SpyroNewBeginning, NoRegion, 0},
{0x6BA2F6B9, ResidentEvil4, NoRegion, 0},
{0x6BA2F6B9, ResidentEvil4, EU, 0},
{0xD6385328, GodOfWar, US, 0},
{0xD6385328, GodOfWar, NoRegion, 0},
{0x1A85E924, GodOfWar, NoRegion, 0},
{0x1A85E924, DevilMayCry3, CH, 0},
{0x2F123FD8, GodOfWar2, RU, 0},
{0x2F123FD8, GodOfWar2, US, 0},
{0x23A97857, StarOcean3, US, 0},
{0x23A97857, StarOcean3, JPUNDUB, 0}
git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5217 96395faa-99c1-11dd-bbfe-3dabce05a288
2012-05-19 18:31:53 +00:00
bool GSC_SoulCalibur2 ( const GSFrameInfo & fi , int & skip )
{
if ( skip = = 0 )
{
if ( fi . TME )
{
// depth textures (bully, mgs3s1 intro, Front Mission 5)
if ( ( fi . TPSM = = PSM_PSMZ32 | | fi . TPSM = = PSM_PSMZ24 | | fi . TPSM = = PSM_PSMZ16 | | fi . TPSM = = PSM_PSMZ16S ) | |
// General, often problematic post processing
( GSUtil : : HasSharedBits ( fi . FBP , fi . FPSM , fi . TBP0 , fi . TPSM ) ) )
{
skip = 2 ;
}
}
}
return true ;
}
2012-05-18 16:51:18 +00:00
bool GSC_SoulCalibur3 ( const GSFrameInfo & fi , int & skip )
{
if ( skip = = 0 )
{
if ( fi . TME )
{
// depth textures (bully, mgs3s1 intro, Front Mission 5)
if ( ( fi . TPSM = = PSM_PSMZ32 | | fi . TPSM = = PSM_PSMZ24 | | fi . TPSM = = PSM_PSMZ16 | | fi . TPSM = = PSM_PSMZ16S ) | |
// General, often problematic post processing
( GSUtil : : HasSharedBits ( fi . FBP , fi . FPSM , fi . TBP0 , fi . TPSM ) ) )
{
skip = 2 ;
}
}
}
return true ;
}
bool GSC_Simple2000Vol114 ( const GSFrameInfo & fi , int & skip )
{
if ( skip = = 0 )
{
if ( fi . TME = = 0 & & ( fi . FBP = = 0x1500 ) & & ( fi . TBP0 = = 0x2c97 | | fi . TBP0 = = 0x2ace | | fi . TBP0 = = 0x03d0 | | fi . TBP0 = = 0x2448 ) & & ( fi . FBMSK = = 0x0000 ) )
{
2012-06-19 01:02:52 +00:00
skip = 1 ;
2012-05-18 16:51:18 +00:00
}
if ( fi . TME & & ( fi . FBP = = 0x0e00 ) & & ( fi . TBP0 = = 0x1000 ) & & ( fi . FBMSK = = 0x0000 ) )
{
2012-06-19 01:02:52 +00:00
skip = 1 ;
2012-05-18 16:51:18 +00:00
}
}
return true ;
}
2015-06-04 16:52:58 +00:00
2012-05-18 16:51:18 +00:00
bool GSC_UrbanReign ( const GSFrameInfo & fi , int & skip )
{
if ( skip = = 0 )
{
2015-09-10 14:28:33 +00:00
if ( fi . TME & & fi . FBP = = 0x0000 & & fi . TBP0 = = 0x3980 & & fi . FPSM = = fi . TPSM & & fi . TPSM = = PSM_PSMCT32 & & fi . FBMSK = = 0x0 )
2012-05-18 16:51:18 +00:00
{
2012-06-19 01:02:52 +00:00
skip = 1 ;
2012-05-18 16:51:18 +00:00
}
}
return true ;
}
2013-02-11 17:10:22 +00:00
bool GSC_SteambotChronicles ( const GSFrameInfo & fi , int & skip )
{
2013-03-02 11:51:14 +00:00
if ( skip = = 0 )
2013-02-11 17:10:22 +00:00
{
2013-03-02 11:51:14 +00:00
// Author: miseru99 on forums.pcsx2.net
if ( fi . TME & & fi . TPSM = = PSM_PSMCT16S )
2013-02-11 17:10:22 +00:00
{
2013-03-02 11:51:14 +00:00
if ( fi . FBP = = 0x1180 )
{
skip = 1 ; //1 deletes some of the glitched effects
}
else if ( fi . FBP = = 0 )
{
skip = 100 ; //deletes most others(too high deletes the buggy sea completely;c, too low causes glitches to be visible)
}
2015-06-04 16:52:58 +00:00
else if ( Aggresive & & fi . FBP ! = 0 ) //Agressive CRC
2013-03-02 11:51:14 +00:00
{
skip = 19 ; //"speedhack", makes the game very light, vaporized water can disappear when not looked at directly, possibly some interface still, other value to try: 6 breaks menu background, possibly nothing(?) during gameplay, but it's slower, hence not much of a speedhack anymore
}
2013-02-11 17:10:22 +00:00
}
}
return true ;
}
2015-06-04 16:52:58 +00:00
# undef Agressive
2011-12-16 19:13:58 +00:00
# ifdef ENABLE_DYNAMIC_CRC_HACK
GSdx: New: Dynamic CRC Hacks system (disabled by default).
See tools/dynacrchack/DynaCrcHack.c for full instructions.
For development of CRC hacks (and just for the fun of creating such a system), Allows GSdx to load and use CRC hack logic from an external DLL, and reload it, at runtime, whenever this DLL changes (but act normally if this DLL isn't found).
This external DLL is compiled from a single C source file (a sample is provided, containing the current MGS3 CRC hack logic). There's also a system to automatically compile this C file into the DLL whenever the C file is modified, thus creating a system of instant [save C file] -> [GSdx switches to the new logic].
It's actually a pretty cool system, and might have other usages where it's useful, for the sake of tests/development/tweaking, to modify code logic during runtime. The overhead of such system compared to pre-compiled code is very low (e.g., in the case of CRC hacks which are called thousands of times/sec, I couldn't notice any difference in performance).
Compilation of the C file is currently done using TCC (Tiny C Compiler - http://bellard.org/tcc/ - extremely fast, light and powerful). TCC itself needs to be downloaded separately (~250K download, no install required). The system currently supports Windows only.
git-svn-id: http://pcsx2.googlecode.com/svn/trunk@4914 96395faa-99c1-11dd-bbfe-3dabce05a288
2011-09-07 18:38:27 +00:00
# include <sys/stat.h>
/***************************************************************************
AutoReloadLibrary : Automatically reloads a dll if the file was modified .
Uses a temporary copy of the watched dll such that the original
can be modified while the copy is loaded and used .
NOTE : The API is not platform specific , but current implementation is Win32 .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
class AutoReloadLibrary
{
private :
string m_dllPath , m_loadedDllPath ;
DWORD m_minMsBetweenProbes ;
time_t m_lastFileModification ;
DWORD m_lastProbe ;
HMODULE m_library ;
string GetTempName ( )
{
string result = m_loadedDllPath + " .tmp " ; //default name
TCHAR tmpPath [ MAX_PATH ] , tmpName [ MAX_PATH ] ;
DWORD ret = GetTempPath ( MAX_PATH , tmpPath ) ;
if ( ret & & ret < = MAX_PATH & & GetTempFileName ( tmpPath , TEXT ( " GSdx " ) , 0 , tmpName ) )
result = tmpName ;
return result ;
} ;
void UnloadLib ( )
{
if ( ! m_library )
return ;
FreeLibrary ( m_library ) ;
m_library = NULL ;
// If can't delete (might happen when GSdx closes), schedule delete on reboot
if ( ! DeleteFile ( m_loadedDllPath . c_str ( ) ) )
MoveFileEx ( m_loadedDllPath . c_str ( ) , NULL , MOVEFILE_DELAY_UNTIL_REBOOT ) ;
}
public :
AutoReloadLibrary ( const string dllPath , const int minMsBetweenProbes = 100 )
: m_minMsBetweenProbes ( minMsBetweenProbes )
, m_dllPath ( dllPath )
, m_lastFileModification ( 0 )
, m_lastProbe ( 0 )
, m_library ( 0 )
{ } ;
~ AutoReloadLibrary ( ) { UnloadLib ( ) ; } ;
// If timeout has ellapsed, probe the dll for change, and reload if it was changed.
// If it returns true, then the dll was freed/reloaded, and any symbol addresse previously obtained is now invalid and needs to be re-obtained.
// Overhead is very low when when probe timeout has not ellapsed, and especially if current timestamp is supplied as argument.
// Note: there's no relation between the file modification date and currentMs value, so it need'nt neccessarily be an actual timestamp.
// Note: isChanged is guarenteed to return true at least once
// (even if the file doesn't exist, at which case the following GetSymbolAddress will return NULL)
bool isChanged ( const DWORD currentMs = 0 )
{
DWORD current = currentMs ? currentMs : GetTickCount ( ) ;
if ( current > = m_lastProbe & & ( current - m_lastProbe ) < m_minMsBetweenProbes )
return false ;
bool firstTime = ! m_lastProbe ;
m_lastProbe = current ;
struct stat s ;
if ( stat ( m_dllPath . c_str ( ) , & s ) )
{
// File doesn't exist or other error, unload dll
bool wasLoaded = m_library ? true : false ;
UnloadLib ( ) ;
return firstTime | | wasLoaded ; // Changed if previously loaded or the first time accessing this method (and file doesn't exist)
}
if ( m_lastFileModification = = s . st_mtime )
return false ;
m_lastFileModification = s . st_mtime ;
// File modified, reload
UnloadLib ( ) ;
if ( ! CopyFile ( m_dllPath . c_str ( ) , ( m_loadedDllPath = GetTempName ( ) ) . c_str ( ) , false ) )
return true ;
m_library = LoadLibrary ( m_loadedDllPath . c_str ( ) ) ;
return true ;
} ;
// Return value is NULL if the dll isn't loaded (failure or doesn't exist) or if the symbol isn't found.
void * GetSymbolAddress ( const char * name ) { return m_library ? GetProcAddress ( m_library , name ) : NULL ; } ;
} ;
// Use DynamicCrcHack function from a dll which can be modified while GSdx/PCSX2 is running.
// return value is true if the call succeeded or false otherwise (If the hack could not be invoked: no dll/function/etc).
// result contains the result of the hack call.
typedef uint32 ( __cdecl * DynaHackType ) ( uint32 , uint32 , uint32 , uint32 , uint32 , uint32 , uint32 , int32 * , uint32 , int32 ) ;
2012-05-19 08:04:12 +00:00
typedef uint32 ( __cdecl * DynaHackType2 ) ( uint32 , uint32 , uint32 , uint32 , uint32 , uint32 , uint32 , int32 * , uint32 , int32 , uint32 ) ; // Also accept CRC
GSdx: New: Dynamic CRC Hacks system (disabled by default).
See tools/dynacrchack/DynaCrcHack.c for full instructions.
For development of CRC hacks (and just for the fun of creating such a system), Allows GSdx to load and use CRC hack logic from an external DLL, and reload it, at runtime, whenever this DLL changes (but act normally if this DLL isn't found).
This external DLL is compiled from a single C source file (a sample is provided, containing the current MGS3 CRC hack logic). There's also a system to automatically compile this C file into the DLL whenever the C file is modified, thus creating a system of instant [save C file] -> [GSdx switches to the new logic].
It's actually a pretty cool system, and might have other usages where it's useful, for the sake of tests/development/tweaking, to modify code logic during runtime. The overhead of such system compared to pre-compiled code is very low (e.g., in the case of CRC hacks which are called thousands of times/sec, I couldn't notice any difference in performance).
Compilation of the C file is currently done using TCC (Tiny C Compiler - http://bellard.org/tcc/ - extremely fast, light and powerful). TCC itself needs to be downloaded separately (~250K download, no install required). The system currently supports Windows only.
git-svn-id: http://pcsx2.googlecode.com/svn/trunk@4914 96395faa-99c1-11dd-bbfe-3dabce05a288
2011-09-07 18:38:27 +00:00
2012-05-19 08:04:12 +00:00
bool IsInvokedDynamicCrcHack ( GSFrameInfo & fi , int & skip , int region , bool & result , uint32 crc )
GSdx: New: Dynamic CRC Hacks system (disabled by default).
See tools/dynacrchack/DynaCrcHack.c for full instructions.
For development of CRC hacks (and just for the fun of creating such a system), Allows GSdx to load and use CRC hack logic from an external DLL, and reload it, at runtime, whenever this DLL changes (but act normally if this DLL isn't found).
This external DLL is compiled from a single C source file (a sample is provided, containing the current MGS3 CRC hack logic). There's also a system to automatically compile this C file into the DLL whenever the C file is modified, thus creating a system of instant [save C file] -> [GSdx switches to the new logic].
It's actually a pretty cool system, and might have other usages where it's useful, for the sake of tests/development/tweaking, to modify code logic during runtime. The overhead of such system compared to pre-compiled code is very low (e.g., in the case of CRC hacks which are called thousands of times/sec, I couldn't notice any difference in performance).
Compilation of the C file is currently done using TCC (Tiny C Compiler - http://bellard.org/tcc/ - extremely fast, light and powerful). TCC itself needs to be downloaded separately (~250K download, no install required). The system currently supports Windows only.
git-svn-id: http://pcsx2.googlecode.com/svn/trunk@4914 96395faa-99c1-11dd-bbfe-3dabce05a288
2011-09-07 18:38:27 +00:00
{
static AutoReloadLibrary dll ( DYNA_DLL_PATH ) ;
static DynaHackType dllFunc = NULL ;
2012-05-19 08:04:12 +00:00
static DynaHackType2 dllFunc2 = NULL ;
GSdx: New: Dynamic CRC Hacks system (disabled by default).
See tools/dynacrchack/DynaCrcHack.c for full instructions.
For development of CRC hacks (and just for the fun of creating such a system), Allows GSdx to load and use CRC hack logic from an external DLL, and reload it, at runtime, whenever this DLL changes (but act normally if this DLL isn't found).
This external DLL is compiled from a single C source file (a sample is provided, containing the current MGS3 CRC hack logic). There's also a system to automatically compile this C file into the DLL whenever the C file is modified, thus creating a system of instant [save C file] -> [GSdx switches to the new logic].
It's actually a pretty cool system, and might have other usages where it's useful, for the sake of tests/development/tweaking, to modify code logic during runtime. The overhead of such system compared to pre-compiled code is very low (e.g., in the case of CRC hacks which are called thousands of times/sec, I couldn't notice any difference in performance).
Compilation of the C file is currently done using TCC (Tiny C Compiler - http://bellard.org/tcc/ - extremely fast, light and powerful). TCC itself needs to be downloaded separately (~250K download, no install required). The system currently supports Windows only.
git-svn-id: http://pcsx2.googlecode.com/svn/trunk@4914 96395faa-99c1-11dd-bbfe-3dabce05a288
2011-09-07 18:38:27 +00:00
if ( dll . isChanged ( ) )
{
2012-05-19 08:04:12 +00:00
dllFunc = ( DynaHackType ) dll . GetSymbolAddress ( " DynamicCrcHack " ) ;
dllFunc2 = ( DynaHackType2 ) dll . GetSymbolAddress ( " DynamicCrcHack2 " ) ;
printf ( " GSdx: Dynamic CRC-hacks%s: %s \n " ,
( ( dllFunc & & ! dllFunc2 ) ? " [Old dynaDLL - No CRC support] " : " " ) ,
dllFunc ? " Loaded OK (-> overriding internal hacks) " :
" Not available (-> using internal hacks) " ) ;
GSdx: New: Dynamic CRC Hacks system (disabled by default).
See tools/dynacrchack/DynaCrcHack.c for full instructions.
For development of CRC hacks (and just for the fun of creating such a system), Allows GSdx to load and use CRC hack logic from an external DLL, and reload it, at runtime, whenever this DLL changes (but act normally if this DLL isn't found).
This external DLL is compiled from a single C source file (a sample is provided, containing the current MGS3 CRC hack logic). There's also a system to automatically compile this C file into the DLL whenever the C file is modified, thus creating a system of instant [save C file] -> [GSdx switches to the new logic].
It's actually a pretty cool system, and might have other usages where it's useful, for the sake of tests/development/tweaking, to modify code logic during runtime. The overhead of such system compared to pre-compiled code is very low (e.g., in the case of CRC hacks which are called thousands of times/sec, I couldn't notice any difference in performance).
Compilation of the C file is currently done using TCC (Tiny C Compiler - http://bellard.org/tcc/ - extremely fast, light and powerful). TCC itself needs to be downloaded separately (~250K download, no install required). The system currently supports Windows only.
git-svn-id: http://pcsx2.googlecode.com/svn/trunk@4914 96395faa-99c1-11dd-bbfe-3dabce05a288
2011-09-07 18:38:27 +00:00
}
2012-05-19 08:04:12 +00:00
if ( ! dllFunc2 & & ! dllFunc )
GSdx: New: Dynamic CRC Hacks system (disabled by default).
See tools/dynacrchack/DynaCrcHack.c for full instructions.
For development of CRC hacks (and just for the fun of creating such a system), Allows GSdx to load and use CRC hack logic from an external DLL, and reload it, at runtime, whenever this DLL changes (but act normally if this DLL isn't found).
This external DLL is compiled from a single C source file (a sample is provided, containing the current MGS3 CRC hack logic). There's also a system to automatically compile this C file into the DLL whenever the C file is modified, thus creating a system of instant [save C file] -> [GSdx switches to the new logic].
It's actually a pretty cool system, and might have other usages where it's useful, for the sake of tests/development/tweaking, to modify code logic during runtime. The overhead of such system compared to pre-compiled code is very low (e.g., in the case of CRC hacks which are called thousands of times/sec, I couldn't notice any difference in performance).
Compilation of the C file is currently done using TCC (Tiny C Compiler - http://bellard.org/tcc/ - extremely fast, light and powerful). TCC itself needs to be downloaded separately (~250K download, no install required). The system currently supports Windows only.
git-svn-id: http://pcsx2.googlecode.com/svn/trunk@4914 96395faa-99c1-11dd-bbfe-3dabce05a288
2011-09-07 18:38:27 +00:00
return false ;
int32 skip32 = skip ;
bool hasSharedBits = GSUtil : : HasSharedBits ( fi . FBP , fi . FPSM , fi . TBP0 , fi . TPSM ) ;
2012-05-19 08:04:12 +00:00
if ( dllFunc2 )
result = dllFunc2 ( fi . FBP , fi . FPSM , fi . FBMSK , fi . TBP0 , fi . TPSM , fi . TZTST , ( uint32 ) fi . TME , & skip32 , ( uint32 ) region , ( uint32 ) ( hasSharedBits ? 1 : 0 ) , crc ) ? true : false ;
else
result = dllFunc ( fi . FBP , fi . FPSM , fi . FBMSK , fi . TBP0 , fi . TPSM , fi . TZTST , ( uint32 ) fi . TME , & skip32 , ( uint32 ) region , ( uint32 ) ( hasSharedBits ? 1 : 0 ) ) ? true : false ;
GSdx: New: Dynamic CRC Hacks system (disabled by default).
See tools/dynacrchack/DynaCrcHack.c for full instructions.
For development of CRC hacks (and just for the fun of creating such a system), Allows GSdx to load and use CRC hack logic from an external DLL, and reload it, at runtime, whenever this DLL changes (but act normally if this DLL isn't found).
This external DLL is compiled from a single C source file (a sample is provided, containing the current MGS3 CRC hack logic). There's also a system to automatically compile this C file into the DLL whenever the C file is modified, thus creating a system of instant [save C file] -> [GSdx switches to the new logic].
It's actually a pretty cool system, and might have other usages where it's useful, for the sake of tests/development/tweaking, to modify code logic during runtime. The overhead of such system compared to pre-compiled code is very low (e.g., in the case of CRC hacks which are called thousands of times/sec, I couldn't notice any difference in performance).
Compilation of the C file is currently done using TCC (Tiny C Compiler - http://bellard.org/tcc/ - extremely fast, light and powerful). TCC itself needs to be downloaded separately (~250K download, no install required). The system currently supports Windows only.
git-svn-id: http://pcsx2.googlecode.com/svn/trunk@4914 96395faa-99c1-11dd-bbfe-3dabce05a288
2011-09-07 18:38:27 +00:00
skip = skip32 ;
return true ;
}
# endif
2010-02-19 10:37:31 +00:00
bool GSState : : IsBadFrame ( int & skip , int UserHacks_SkipDraw )
2009-02-09 21:15:56 +00:00
{
GSFrameInfo fi ;
fi . FBP = m_context - > FRAME . Block ( ) ;
fi . FPSM = m_context - > FRAME . PSM ;
2009-03-22 13:10:31 +00:00
fi . FBMSK = m_context - > FRAME . FBMSK ;
2009-02-09 21:15:56 +00:00
fi . TME = PRIM - > TME ;
fi . TBP0 = m_context - > TEX0 . TBP0 ;
fi . TPSM = m_context - > TEX0 . PSM ;
2010-02-26 14:38:13 +00:00
fi . TZTST = m_context - > TEST . ZTST ;
2009-02-09 21:15:56 +00:00
static GetSkipCount map [ CRC : : TitleCount ] ;
2015-06-17 21:25:43 +00:00
if ( ! m_crcinited )
2009-02-09 21:15:56 +00:00
{
2015-06-17 21:25:43 +00:00
m_crcinited = true ;
2009-02-09 21:15:56 +00:00
memset ( map , 0 , sizeof ( map ) ) ;
2010-04-25 00:31:27 +00:00
2015-06-14 08:19:15 +00:00
if ( s_crc_hack_level > 1 ) {
2015-06-30 08:11:13 +00:00
map [ CRC : : AceCombat4 ] = GSC_AceCombat4 ;
map [ CRC : : AlpineRacer3 ] = GSC_AlpineRacer3 ;
map [ CRC : : BlackHawkDown ] = GSC_BlackHawkDown ;
map [ CRC : : BleachBladeBattlers ] = GSC_BleachBladeBattlers ;
map [ CRC : : BullyCC ] = GSC_BullyCC ; // Bully is fixed, maybe this one too?
map [ CRC : : BurnoutDominator ] = GSC_Burnout ;
map [ CRC : : BurnoutRevenge ] = GSC_Burnout ;
map [ CRC : : BurnoutTakedown ] = GSC_Burnout ;
map [ CRC : : CaptainTsubasa ] = GSC_CaptainTsubasa ;
map [ CRC : : CrashBandicootWoC ] = GSC_CrashBandicootWoC ;
map [ CRC : : CrashNburn ] = GSC_CrashNburn ;
2015-06-14 08:19:15 +00:00
map [ CRC : : DBZBT2 ] = GSC_DBZBT2 ;
map [ CRC : : DBZBT3 ] = GSC_DBZBT3 ;
2015-06-30 08:11:13 +00:00
map [ CRC : : DeathByDegreesTekkenNinaWilliams ] = GSC_DeathByDegreesTekkenNinaWilliams ;
map [ CRC : : DevilMayCry3 ] = GSC_DevilMayCry3 ;
map [ CRC : : EternalPoison ] = GSC_EternalPoison ;
map [ CRC : : EvangelionJo ] = GSC_EvangelionJo ;
map [ CRC : : FFVIIDoC ] = GSC_FFVIIDoC ;
map [ CRC : : FightingBeautyWulong ] = GSC_FightingBeautyWulong ;
map [ CRC : : FinalFightStreetwise ] = GSC_FinalFightStreetwise ;
map [ CRC : : FrontMission5 ] = GSC_FrontMission5 ;
map [ CRC : : Genji ] = GSC_Genji ;
map [ CRC : : GetaWayBlackMonday ] = GSC_GetaWay ;
map [ CRC : : GetaWay ] = GSC_GetaWay ;
map [ CRC : : GodHand ] = GSC_GodHand ;
2015-06-14 08:19:15 +00:00
map [ CRC : : GT3 ] = GSC_GT3 ;
2015-06-30 08:11:13 +00:00
map [ CRC : : GT4 ] = GSC_GT4 ;
map [ CRC : : GTASanAndreas ] = GSC_GTASanAndreas ;
2015-06-14 08:19:15 +00:00
map [ CRC : : GTConcept ] = GSC_GTConcept ;
map [ CRC : : HauntingGround ] = GSC_HauntingGround ;
2015-06-30 08:11:13 +00:00
map [ CRC : : HeavyMetalThunder ] = GSC_HeavyMetalThunder ;
map [ CRC : : HummerBadlands ] = GSC_HummerBadlands ;
map [ CRC : : ICO ] = GSC_ICO ;
map [ CRC : : IkkiTousen ] = GSC_IkkiTousen ;
map [ CRC : : JamesBondEverythingOrNothing ] = GSC_JamesBondEverythingOrNothing ;
map [ CRC : : KnightsOfTheTemple2 ] = GSC_KnightsOfTheTemple2 ;
map [ CRC : : Kunoichi ] = GSC_Kunoichi ;
map [ CRC : : LordOfTheRingsThirdAge ] = GSC_LordOfTheRingsThirdAge ;
map [ CRC : : Manhunt2 ] = GSC_Manhunt2 ;
map [ CRC : : MetalGearSolid3 ] = GSC_MetalGearSolid3 ;
map [ CRC : : MidnightClub3 ] = GSC_MidnightClub3 ;
map [ CRC : : NanoBreaker ] = GSC_NanoBreaker ;
2015-06-14 08:19:15 +00:00
map [ CRC : : NarutimateAccel ] = GSC_NarutimateAccel ;
map [ CRC : : Naruto ] = GSC_Naruto ;
2015-06-30 08:11:13 +00:00
map [ CRC : : Oneechanbara2Special ] = GSC_Oneechanbara2Special ;
map [ CRC : : Onimusha3 ] = GSC_Onimusha3 ;
map [ CRC : : RedDeadRevolver ] = GSC_RedDeadRevolver ;
map [ CRC : : ResidentEvil4 ] = GSC_ResidentEvil4 ;
map [ CRC : : SacredBlaze ] = GSC_SacredBlaze ;
2015-06-14 08:19:15 +00:00
map [ CRC : : SakuraTaisen ] = GSC_SakuraTaisen ;
2015-06-30 08:11:13 +00:00
map [ CRC : : SakuraWarsSoLongMyLove ] = GSC_SakuraWarsSoLongMyLove ;
map [ CRC : : SengokuBasara ] = GSC_SengokuBasara ;
2015-06-14 08:19:15 +00:00
map [ CRC : : ShadowofRome ] = GSC_ShadowofRome ;
2015-06-30 08:11:13 +00:00
map [ CRC : : ShinOnimusha ] = GSC_ShinOnimusha ;
map [ CRC : : Simple2000Vol114 ] = GSC_Simple2000Vol114 ;
map [ CRC : : SkyGunner ] = GSC_SkyGunner ;
map [ CRC : : SoulCalibur2 ] = GSC_SoulCalibur2 ;
map [ CRC : : SoulCalibur3 ] = GSC_SoulCalibur3 ;
map [ CRC : : Spartan ] = GSC_Spartan ;
map [ CRC : : StarWarsBattlefront2 ] = GSC_StarWarsBattlefront2 ;
map [ CRC : : StarWarsBattlefront ] = GSC_StarWarsBattlefront ;
map [ CRC : : StarWarsForceUnleashed ] = GSC_StarWarsForceUnleashed ;
map [ CRC : : SteambotChronicles ] = GSC_SteambotChronicles ;
map [ CRC : : TalesOfAbyss ] = GSC_TalesOfAbyss ;
map [ CRC : : TalesOfLegendia ] = GSC_TalesOfLegendia ;
map [ CRC : : TalesofSymphonia ] = GSC_TalesofSymphonia ;
map [ CRC : : Tekken5 ] = GSC_Tekken5 ;
2015-06-14 08:19:15 +00:00
map [ CRC : : TimeSplitters2 ] = GSC_TimeSplitters2 ;
map [ CRC : : TombRaiderAnniversary ] = GSC_TombRaider ;
map [ CRC : : TombRaiderLegend ] = GSC_TombRaiderLegend ;
2015-06-30 08:11:13 +00:00
map [ CRC : : TombRaiderUnderworld ] = GSC_TombRaiderUnderWorld ;
2015-06-14 08:19:15 +00:00
map [ CRC : : TouristTrophy ] = GSC_TouristTrophy ;
map [ CRC : : UltramanFightingEvolution ] = GSC_UltramanFightingEvolution ;
map [ CRC : : UrbanReign ] = GSC_UrbanReign ;
2015-06-30 08:11:13 +00:00
map [ CRC : : WildArms4 ] = GSC_WildArms4 ;
map [ CRC : : WildArms5 ] = GSC_WildArms5 ;
map [ CRC : : Yakuza2 ] = GSC_Yakuza2 ;
map [ CRC : : Yakuza ] = GSC_Yakuza ;
map [ CRC : : ZettaiZetsumeiToshi2 ] = GSC_ZettaiZetsumeiToshi2 ;
// Only Aggresive
map [ CRC : : FFX2 ] = GSC_FFX2 ;
map [ CRC : : FFX ] = GSC_FFX ;
map [ CRC : : FFXII ] = GSC_FFXII ;
2015-06-14 08:19:15 +00:00
map [ CRC : : SMTDDS1 ] = GSC_SMTNocturneDDS < 0x203BA820 > ;
map [ CRC : : SMTDDS2 ] = GSC_SMTNocturneDDS < 0x20435BF0 > ;
2015-06-30 08:11:13 +00:00
map [ CRC : : SMTNocturne ] = GSC_SMTNocturneDDS < 0x2054E870 > ;
map [ CRC : : SoTC ] = GSC_SoTC ;
map [ CRC : : SSX3 ] = GSC_SSX3 ;
2015-06-14 08:19:15 +00:00
}
2015-06-04 17:12:07 +00:00
// Hack that were fixed on openGL
if ( Dx_only ) {
2015-06-30 08:11:13 +00:00
map [ CRC : : Bully ] = GSC_Bully ;
2015-07-11 13:14:11 +00:00
map [ CRC : : GodOfWar2 ] = GSC_GodOfWar2 ;
2015-06-30 08:11:13 +00:00
map [ CRC : : LordOfTheRingsTwoTowers ] = GSC_LordOfTheRingsTwoTowers ;
map [ CRC : : Okami ] = GSC_Okami ;
map [ CRC : : SimpsonsGame ] = GSC_SimpsonsGame ;
2015-07-11 13:14:11 +00:00
map [ CRC : : SuikodenTactics ] = GSC_SuikodenTactics ;
map [ CRC : : XE3 ] = GSC_XE3 ;
2015-06-30 08:11:13 +00:00
// Not tested but must be fixed with texture shuffle
map [ CRC : : BigMuthaTruckers ] = GSC_BigMuthaTruckers ;
map [ CRC : : DemonStone ] = GSC_DemonStone ;
map [ CRC : : GiTS ] = GSC_GiTS ;
map [ CRC : : LegoBatman ] = GSC_LegoBatman ;
map [ CRC : : OnePieceGrandAdventure ] = GSC_OnePieceGrandAdventure ;
map [ CRC : : OnePieceGrandBattle ] = GSC_OnePieceGrandBattle ;
map [ CRC : : SFEX3 ] = GSC_SFEX3 ;
map [ CRC : : SpyroEternalNight ] = GSC_SpyroEternalNight ;
map [ CRC : : SpyroNewBeginning ] = GSC_SpyroNewBeginning ;
map [ CRC : : SonicUnleashed ] = GSC_SonicUnleashed ;
map [ CRC : : TenchuFS ] = GSC_Tenchu ;
map [ CRC : : TenchuWoH ] = GSC_Tenchu ;
// Those games might requires accurate fbmask
map [ CRC : : Sly2 ] = GSC_Sly2 ;
map [ CRC : : Sly3 ] = GSC_Sly3 ;
// Those games require accurate_colclip (perf)
2015-06-04 17:12:07 +00:00
map [ CRC : : CastlevaniaCoD ] = GSC_Castlevania ;
map [ CRC : : CastlevaniaLoI ] = GSC_Castlevania ;
2015-06-30 08:11:13 +00:00
map [ CRC : : GodOfWar ] = GSC_GodOfWar ;
2015-06-04 17:12:07 +00:00
2015-06-30 08:11:13 +00:00
// Those games emulate a stencil buffer with the alpha channel of the RT (Slow)
map [ CRC : : RadiataStories ] = GSC_RadiataStories ;
2015-06-04 17:12:07 +00:00
map [ CRC : : StarOcean3 ] = GSC_StarOcean3 ;
map [ CRC : : ValkyrieProfile2 ] = GSC_ValkyrieProfile2 ;
2015-06-30 08:11:13 +00:00
// Deprecated hack could be removed (Cutie)
map [ CRC : : Grandia3 ] = GSC_Grandia3 ;
2016-02-06 16:32:12 +00:00
// At least a part of the CRC is fixed with texture shuffle.
// The status of post-processing effect is unknown
map [ CRC : : Black ] = GSC_Black ;
2015-06-04 17:12:07 +00:00
}
2009-02-09 21:15:56 +00:00
}
// TODO: just set gsc in SetGameCRC once
GetSkipCount gsc = map [ m_game . title ] ;
2011-07-29 18:11:22 +00:00
g_crc_region = m_game . region ;
2009-02-09 21:15:56 +00:00
2011-12-21 23:35:30 +00:00
# ifdef ENABLE_DYNAMIC_CRC_HACK
2012-05-19 08:04:12 +00:00
bool res = false ; if ( IsInvokedDynamicCrcHack ( fi , skip , g_crc_region , res , m_crc ) ) { if ( ! res ) return false ; } else
GSdx: New: Dynamic CRC Hacks system (disabled by default).
See tools/dynacrchack/DynaCrcHack.c for full instructions.
For development of CRC hacks (and just for the fun of creating such a system), Allows GSdx to load and use CRC hack logic from an external DLL, and reload it, at runtime, whenever this DLL changes (but act normally if this DLL isn't found).
This external DLL is compiled from a single C source file (a sample is provided, containing the current MGS3 CRC hack logic). There's also a system to automatically compile this C file into the DLL whenever the C file is modified, thus creating a system of instant [save C file] -> [GSdx switches to the new logic].
It's actually a pretty cool system, and might have other usages where it's useful, for the sake of tests/development/tweaking, to modify code logic during runtime. The overhead of such system compared to pre-compiled code is very low (e.g., in the case of CRC hacks which are called thousands of times/sec, I couldn't notice any difference in performance).
Compilation of the C file is currently done using TCC (Tiny C Compiler - http://bellard.org/tcc/ - extremely fast, light and powerful). TCC itself needs to be downloaded separately (~250K download, no install required). The system currently supports Windows only.
git-svn-id: http://pcsx2.googlecode.com/svn/trunk@4914 96395faa-99c1-11dd-bbfe-3dabce05a288
2011-09-07 18:38:27 +00:00
# endif
2012-06-20 20:45:24 +00:00
if ( gsc & & ! gsc ( fi , skip ) )
2009-02-09 21:15:56 +00:00
{
return false ;
}
2010-02-19 10:37:31 +00:00
if ( skip = = 0 & & ( UserHacks_SkipDraw > 0 ) )
2009-02-09 21:15:56 +00:00
{
if ( fi . TME )
{
2010-02-19 15:45:23 +00:00
// depth textures (bully, mgs3s1 intro, Front Mission 5)
if ( ( fi . TPSM = = PSM_PSMZ32 | | fi . TPSM = = PSM_PSMZ24 | | fi . TPSM = = PSM_PSMZ16 | | fi . TPSM = = PSM_PSMZ16S ) | |
// General, often problematic post processing
( GSUtil : : HasSharedBits ( fi . FBP , fi . FPSM , fi . TBP0 , fi . TPSM ) ) )
2009-02-09 21:15:56 +00:00
{
2010-02-19 10:37:31 +00:00
skip = UserHacks_SkipDraw ;
2009-02-09 21:15:56 +00:00
}
}
}
2015-05-08 13:51:46 +00:00
# ifdef ENABLE_OGL_DEBUG
2015-06-17 19:17:52 +00:00
else if ( fi . TME ) {
2015-05-08 13:51:46 +00:00
if ( fi . TPSM = = PSM_PSMZ32 | | fi . TPSM = = PSM_PSMZ24 | | fi . TPSM = = PSM_PSMZ16 | | fi . TPSM = = PSM_PSMZ16S )
2015-05-25 15:31:27 +00:00
GL_INS ( " !!! Depth Texture 0x%x!!! " , fi . TPSM ) ;
2010-02-21 19:50:21 +00:00
}
2015-06-17 19:17:52 +00:00
# endif
2009-02-09 21:15:56 +00:00
if ( skip > 0 )
{
skip - - ;
return true ;
}
return false ;
}