/[pcsx2_0.9.7]/trunk/plugins/zzogl-pg/opengl/ZZoglFlush.cpp
ViewVC logotype

Diff of /trunk/plugins/zzogl-pg/opengl/ZZoglFlush.cpp

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

--- trunk/plugins/zzogl-pg/opengl/ZZoglFlush.cpp	2010/09/13 18:34:58	184
+++ trunk/plugins/zzogl-pg/opengl/ZZoglFlush.cpp	2010/09/13 19:49:07	185
@@ -1,2989 +1,2989 @@
-/*  ZZ Open GL graphics plugin
- *  Copyright (c)2009-2010 zeydlitz@gmail.com, arcum42@gmail.com
- *  Based on Zerofrog's ZeroGS KOSMOS (c)2005-2008
- *
- *  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 of the License, or
- *  (at your option) any later version.
- *
- *  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.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
- */
-
-// Realization of Flush -- drawing function of GS
-
-#include <stdlib.h>
-
-#include "GS.h"
-#include "Mem.h"
-#include "zerogs.h"
-#include "targets.h"
-#include "ZZoglFlushHack.h"
-#include "ZZoglShaders.h"
-
-using namespace ZeroGS;
-
-//------------------ Defines
-#ifndef ZEROGS_DEVBUILD
-
-#define INC_GENVARS()
-#define INC_TEXVARS()
-#define INC_ALPHAVARS()
-#define INC_RESOLVE()
-
-#define g_bUpdateEffect 0
-#define g_bSaveTex 0
-bool g_bSaveTrans = 0;
-#define g_bSaveResolved 0
-
-#else // defined(ZEROGS_DEVBUILD)
-
-#define INC_GENVARS() ++g_nGenVars
-#define INC_TEXVARS() ++g_nTexVars
-#define INC_ALPHAVARS() ++g_nAlphaVars
-#define INC_RESOLVE() ++g_nResolve
-
-bool g_bSaveTrans = 0;
-bool g_bUpdateEffect = 0;
-bool g_bSaveTex = 0;	// saves the curent texture
-bool g_bSaveResolved = 0;
-#endif // !defined(ZEROGS_DEVBUILD)
-
-#define STENCIL_ALPHABIT	1	   // if set, dest alpha >= 0x80
-#define STENCIL_PIXELWRITE  2	   // if set, pixel just written (reset after every Flush)
-#define STENCIL_FBA		 4	   // if set, just written pixel's alpha >= 0 (reset after every Flush)
-#define STENCIL_SPECIAL	 8	   // if set, indicates that pixel passed its alpha test (reset after every Flush)
-//#define STENCIL_PBE		   16
-#define STENCIL_CLEAR	   (2|4|8|16)
-
-void Draw(const VB& curvb)
-{
-	glDrawArrays(primtype[curvb.curprim.prim], 0, curvb.nCount);
-}
-
-#define GL_BLEND_RGB(src, dst) { \
-	s_srcrgb = src; \
-	s_dstrgb = dst; \
-	zgsBlendFuncSeparateEXT(s_srcrgb, s_dstrgb, s_srcalpha, s_dstalpha); \
-}
-
-#define GL_BLEND_ALPHA(src, dst) { \
-	s_srcalpha = src; \
-	s_dstalpha = dst; \
-	zgsBlendFuncSeparateEXT(s_srcrgb, s_dstrgb, s_srcalpha, s_dstalpha); \
-}
-
-#define GL_BLEND_ALL(srcrgb, dstrgb, srcalpha, dstalpha) { \
-	s_srcrgb = srcrgb; \
-	s_dstrgb = dstrgb; \
-	s_srcalpha = srcalpha; \
-	s_dstalpha = dstalpha; \
-	zgsBlendFuncSeparateEXT(s_srcrgb, s_dstrgb, s_srcalpha, s_dstalpha); \
-}
-
-#define GL_ZTEST(enable) { \
-	if (enable) glEnable(GL_DEPTH_TEST); \
-	else glDisable(GL_DEPTH_TEST); \
-}
-
-#define GL_ALPHATEST(enable) { \
-	if( enable ) glEnable(GL_ALPHA_TEST); \
-	else glDisable(GL_ALPHA_TEST); \
-}
-
-#define GL_BLENDEQ_RGB(eq) { \
-	s_rgbeq = eq; \
-	zgsBlendEquationSeparateEXT(s_rgbeq, s_alphaeq); \
-}
-
-#define GL_BLENDEQ_ALPHA(eq) { \
-	s_alphaeq = eq; \
-	zgsBlendEquationSeparateEXT(s_rgbeq, s_alphaeq); \
-}
-
-#define COLORMASK_RED	  	1
-#define COLORMASK_GREEN	 	2
-#define COLORMASK_BLUE	  	4
-#define COLORMASK_ALPHA	 	8
-#define GL_COLORMASK(mask) glColorMask(!!((mask)&COLORMASK_RED), !!((mask)&COLORMASK_GREEN), !!((mask)&COLORMASK_BLUE), !!((mask)&COLORMASK_ALPHA))
-
-// ----------------- Types
-//------------------ Dummies
-
-//------------------ variables
-
-extern int g_nDepthBias;
-extern float g_fBlockMult; // used for old cards, that do not support Alpha-32float textures. We store block data in u16 and use it.
-bool g_bUpdateStencil = 1;
-//u32 g_SaveFrameNum = 0;									// ZZ
-
-extern ZZshProgram g_psprog;							// 2 -- ZZ
-
-// local alpha blending settings
-static GLenum s_rgbeq, s_alphaeq; // set by zgsBlendEquationSeparateEXT			// ZZ
-
-
-static const u32 blendalpha[3] = { GL_SRC_ALPHA, GL_DST_ALPHA, GL_CONSTANT_COLOR_EXT };	// ZZ
-static const u32 blendinvalpha[3] = { GL_ONE_MINUS_SRC_ALPHA, GL_ONE_MINUS_DST_ALPHA, GL_ONE_MINUS_CONSTANT_COLOR_EXT }; //ZZ
-static const u32 g_dwAlphaCmp[] = { GL_NEVER, GL_ALWAYS, GL_LESS, GL_LEQUAL, GL_EQUAL, GL_GEQUAL, GL_GREATER, GL_NOTEQUAL };    // ZZ
-
-// used for afail case
-static const u32 g_dwReverseAlphaCmp[] = { GL_ALWAYS, GL_NEVER, GL_GEQUAL, GL_GREATER, GL_NOTEQUAL, GL_LESS, GL_LEQUAL, GL_EQUAL };
-static const u32 g_dwZCmp[] = { GL_NEVER, GL_ALWAYS, GL_GEQUAL, GL_GREATER };
-
-/////////////////////
-// graphics resources
-#define s_bForceTexFlush 1					// ZZ
-static u32 s_ptexCurSet[2] = {0};
-static u32 s_ptexNextSet[2] = {0};				// ZZ
-
-
-extern vector<u32> s_vecTempTextures;		   // temporary textures, released at the end of every frame
-extern bool s_bTexFlush;
-bool s_bWriteDepth = false;
-bool s_bDestAlphaTest = false;
-int s_ClutResolve = 0;						// ZZ
-int g_nDepthUsed = 0; 						// ffx2 pal movies
-int s_nWriteDepthCount = 0;					// ZZ
-int s_nWriteDestAlphaTest = 0;					// ZZ
-
-////////////////////
-// State parameters
-static Vector vAlphaBlendColor;	 // used for GPU_COLOR
-
-static bool bNeedBlendFactorInAlpha;	  // set if the output source alpha is different from the real source alpha (only when blend factor > 0x80)
-static u32 s_dwColorWrite = 0xf;			// the color write mask of the current target
-
-typedef union
-{
-	struct
-	{
-		u8 _bNeedAlphaColor;		// set if vAlphaBlendColor needs to be set
-		u8 _b2XAlphaTest;		   // Only valid when bNeedAlphaColor is set. if 1st bit set set, double all alpha testing values
-		// otherwise alpha testing needs to be done separately.
-		u8 _bDestAlphaColor;		// set to 1 if blending with dest color (process only one tri at a time). If 2, dest alpha is always 1.
-		u8 _bAlphaClamping;	 // if first bit is set, do min; if second bit, do max
-	};
-
-	u32 _bAlphaState;
-} g_flag_vars;
-
-g_flag_vars g_vars;
-
-//#define bNeedAlphaColor g_vars._bNeedAlphaColor
-#define b2XAlphaTest g_vars._b2XAlphaTest
-#define bDestAlphaColor g_vars._bDestAlphaColor
-#define bAlphaClamping g_vars._bAlphaClamping
-
-int g_PrevBitwiseTexX = -1, g_PrevBitwiseTexY = -1; // textures stored in SAMP_BITWISEANDX and SAMP_BITWISEANDY		// ZZ
-
-//static alphaInfo s_alphaInfo;												// ZZ
-
-extern u8* g_pbyGSClut;
-extern int ppf;
-
-int s_nWireframeCount = 0;
-
-//------------------ Namespace
-
-namespace ZeroGS
-{
-
-VB vb[2];
-float fiTexWidth[2], fiTexHeight[2];	// current tex width and height
-
-//u8 s_AAx = 0, s_AAy = 0; // if AAy is set, then AAx has to be set
-Point AA = {0,0};
-
-int icurctx = -1;
-
-extern CRangeManager s_RangeMngr; // manages overwritten memory				// zz
-void FlushTransferRanges(const tex0Info* ptex);						//zz
-
-RenderFormatType GetRenderFormat() { return g_RenderFormatType; }					//zz
-
-// use to update the state
-void SetTexVariables(int context, FRAGMENTSHADER* pfragment);			// zz
-void SetTexInt(int context, FRAGMENTSHADER* pfragment, int settexint);		// zz
-void SetAlphaVariables(const alphaInfo& ainfo);					// zzz
-void ResetAlphaVariables();
-
-inline void SetAlphaTestInt(pixTest curtest);
-
-inline void RenderAlphaTest(const VB& curvb, ZZshParameter sOneColor);
-inline void RenderStencil(const VB& curvb, u32 dwUsingSpecialTesting);
-inline void ProcessStencil(const VB& curvb);
-inline void RenderFBA(const VB& curvb, ZZshParameter sOneColor);
-inline void ProcessFBA(const VB& curvb, ZZshParameter sOneColor);			// zz
-
-
-}
-
-//------------------ Code
-
-inline float AlphaReferedValue(int aref)
-{
-	return b2XAlphaTest ? min(1.0f, (float)aref / 127.5f) : (float)aref / 255.0f ;
-}
-
-inline void SetAlphaTest(const pixTest& curtest)
-{
-	// if s_dwColorWrite is nontrivial, than we should not off alphatest.
-	// This fix GOW and Okami.
-	if (!curtest.ate && USEALPHATESTING && (s_dwColorWrite != 2 && s_dwColorWrite != 14))
-	{
-		glDisable(GL_ALPHA_TEST);
-	}
-	else
-	{
-		glEnable(GL_ALPHA_TEST);
-		glAlphaFunc(g_dwAlphaCmp[curtest.atst], AlphaReferedValue(curtest.aref));
-	}
-}
- 
-// Return, if tcc, aem or psm mode told us, than Alpha test should be used
-// if tcc == 0 than no alpha used, aem used for alpha expanding and I am not sure
-// that it's correct, psm -- color mode,
-inline bool IsAlphaTestExpansion(tex0Info tex0)
-{
-	return (tex0.tcc && gs.texa.aem && PSMT_ALPHAEXP(PIXEL_STORAGE_FORMAT(tex0)));
-}
-
-// Switch wireframe rendering off for first flush, so it's draw few solid primitives
-inline void SwitchWireframeOff()
-{
-	if (conf.wireframe())
-	{
-		if (s_nWireframeCount > 0)
-		{
-			glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
-		}
-	}
-}
-
-// Switch wireframe rendering on, look at previous function
-inline void SwitchWireframeOn()
-{
-	if (conf.wireframe())
-	{
-		if (s_nWireframeCount > 0)
-		{
-			glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
-			--s_nWireframeCount;
-		}
-	}
-}
-
-int GetTexFilter(const tex1Info& tex1)
-{
-	// always force
-	if (conf.bilinear == 2) return 1;
-
-	int texfilter = 0;
-
-	if (conf.bilinear && ptexBilinearBlocks != 0)
-	{
-		if (tex1.mmin <= 1)
-			texfilter = tex1.mmin | tex1.mmag;
-		else
-			texfilter = tex1.mmag ? ((tex1.mmin + 2) & 5) : tex1.mmin;
-
-		texfilter = texfilter == 1 || texfilter == 4 || texfilter == 5;
-	}
-
-	return texfilter;
-}
-
-void ZeroGS::ReloadEffects()
-{
-#ifdef ZEROGS_DEVBUILD
-
-	for (int i = 0; i < ARRAY_SIZE(ppsTexture); ++i)
-	{
-		SAFE_RELEASE_PROG(ppsTexture[i].prog);
-	}
-
-	memset(ppsTexture, 0, sizeof(ppsTexture));
-
-	LoadExtraEffects();
-#endif
-}
-
-long BufferNumber = 0;
-
-// This is a debug function. It prints all buffer info and save current texture into the file, then prints the file name.
-inline void VisualBufferMessage(int context)
-{
-#if defined(WRITE_PRIM_LOGS) && defined(_DEBUG)
-	BufferNumber++;
-	ZeroGS::VB& curvb = vb[context];
-	static const char* patst[8] = { "NEVER", "ALWAYS", "LESS", "LEQUAL", "EQUAL", "GEQUAL", "GREATER", "NOTEQUAL"};
-	static const char* pztst[4] = { "NEVER", "ALWAYS", "GEQUAL", "GREATER" };
-	static const char* pafail[4] = { "KEEP", "FB_ONLY", "ZB_ONLY", "RGB_ONLY" };
-	ZZLog::Debug_Log("**Drawing ctx %d, num %d, fbp: 0x%x, zbp: 0x%x, fpsm: %d, zpsm: %d, fbw: %d", context, vb[context].nCount, curvb.prndr->fbp, curvb.zbuf.zbp, curvb.prndr->psm, curvb.zbuf.psm, curvb.prndr->fbw);
-	ZZLog::Debug_Log("prim: prim=%x iip=%x tme=%x fge=%x abe=%x aa1=%x fst=%x ctxt=%x fix=%x",
-					 curvb.curprim.prim, curvb.curprim.iip, curvb.curprim.tme, curvb.curprim.fge, curvb.curprim.abe, curvb.curprim.aa1, curvb.curprim.fst, curvb.curprim.ctxt, curvb.curprim.fix);
-	ZZLog::Debug_Log("test: ate:%d, atst: %s, aref: %d, afail: %s, date: %d, datm: %d, zte: %d, ztst: %s, fba: %d",
-					 curvb.test.ate, patst[curvb.test.atst], curvb.test.aref, pafail[curvb.test.afail], curvb.test.date, curvb.test.datm, curvb.test.zte, pztst[curvb.test.ztst], curvb.fba.fba);
-	ZZLog::Debug_Log("alpha: A%d B%d C%d D%d FIX:%d pabe: %d; aem: %d, ta0: %d, ta1: %d\n", curvb.alpha.a, curvb.alpha.b, curvb.alpha.c, curvb.alpha.d, curvb.alpha.fix, gs.pabe, gs.texa.aem, gs.texa.ta[0], gs.texa.ta[1]);
-	ZZLog::Debug_Log("tex0: tbp0=0x%x, tbw=%d, psm=0x%x, tw=%d, th=%d, tcc=%d, tfx=%d, cbp=0x%x, cpsm=0x%x, csm=%d, csa=%d, cld=%d",
-					 curvb.tex0.tbp0, curvb.tex0.tbw, curvb.tex0.psm, curvb.tex0.tw,
-					 curvb.tex0.th, curvb.tex0.tcc, curvb.tex0.tfx, curvb.tex0.cbp,
-					 curvb.tex0.cpsm, curvb.tex0.csm, curvb.tex0.csa, curvb.tex0.cld);
-	char* Name;
-//	if (g_bSaveTex) {
-//		if (g_bSaveTex == 1)
-	Name = NamedSaveTex(&curvb.tex0, 1);
-//		else
-//			Name = NamedSaveTex(&curvb.tex0, 0);
-	ZZLog::Error_Log("TGA name '%s'.", Name);
-	free(Name);
-//	}
-//	ZZLog::Debug_Log("frame: %d, buffer %ld.\n", g_SaveFrameNum, BufferNumber);
-	ZZLog::Debug_Log("buffer %ld.\n", BufferNumber);
-#endif
-}
-
-inline void SaveRendererTarget(VB& curvb)
-{
-#ifdef _DEBUG
-
-//	if (g_bSaveFlushedFrame & 0x80000000)
-//	{
-//		char str[255];
-//		sprintf(str, "rndr%d.tga", g_SaveFrameNum);
-//		SaveRenderTarget(str, curvb.prndr->fbw, curvb.prndr->fbh, 0);
-//	}
-
-#endif
-}
-
-// Stop effects in Developers mode
-inline void FlushUpdateEffect()
-{
-#if defined(DEVBUILD)
-
-	if (g_bUpdateEffect)
-	{
-		ReloadEffects();
-		g_bUpdateEffect = 0;
-	}
-
-#endif
-}
-
-// Check, maybe we cold skip flush
-inline bool IsFlushNoNeed(VB& curvb, const pixTest& curtest)
-{
-	if (curvb.nCount == 0 || (curtest.zte && curtest.ztst == 0) || IsBadFrame(curvb))
-	{
-		curvb.nCount = 0;
-		return true;
-	}
-
-	return false;
-}
-
-// Transfer targets, that are located in current texture.
-inline void FlushTransferRangesHelper(VB& curvb)
-{
-	if (s_RangeMngr.ranges.size() > 0)
-	{
-		// don't want infinite loop, so set nCount to 0.
-		u32 prevcount = curvb.nCount;
-		curvb.nCount = 0;
-
-		FlushTransferRanges(curvb.curprim.tme ? &curvb.tex0 : NULL);
-
-		curvb.nCount += prevcount;
-	}
-}
-
-// If set bit for texture checking, do it. Maybe it's all.
-inline bool FushTexDataHelper(VB& curvb)
-{
-	if (curvb.bNeedFrameCheck || curvb.bNeedZCheck)
-	{
-		curvb.CheckFrame(curvb.curprim.tme ? curvb.tex0.tbp0 : 0);
-	}
-
-	if (curvb.bNeedTexCheck)    // Zeydlitz want to try this
-	{
-		curvb.FlushTexData();
-
-		if (curvb.nCount == 0) return true;
-	}
-
-	return false;
-}
-
-// Null target mean that we do something really bad.
-inline bool FlushCheckForNULLTarget(VB& curvb, int context)
-{
-	if ((curvb.prndr == NULL) || (curvb.pdepth == NULL))
-	{
-		ERROR_LOG_SPAMA("Current render target NULL (ctx: %d)", context);
-		curvb.nCount = 0;
-		return true;
-	}
-
-	return false;
-}
-
-// O.k. A set of resolutions, we do before real flush. We do RangeManager, FrameCheck and
-// ZCheck before this.
-inline bool FlushInitialTest(VB& curvb, const pixTest& curtest, int context)
-{
-	GL_REPORT_ERRORD();
-	assert(context >= 0 && context <= 1);
-
-	FlushUpdateEffect();
-
-	if (IsFlushNoNeed(curvb, curtest)) return true;
-
-	FlushTransferRangesHelper(curvb);
-
-	if (FushTexDataHelper(curvb)) return true;
-
-	GL_REPORT_ERRORD();
-
-	if (FlushCheckForNULLTarget(curvb, context)) return true;
-
-	return false;
-}
-
-// Try to different approach if texture target was not found
-inline CRenderTarget* FlushReGetTarget(int& tbw, int& tbp0, int& tpsm, VB& curvb)
-{
-	// This was incorrect code
-	CRenderTarget* ptextarg = NULL;
-
-	if ((ptextarg == NULL) && (tpsm == PSMT8) && (conf.settings().reget))
-	{
-		// check for targets with half the width. Break Valkyrie Chronicles
-		ptextarg = s_RTs.GetTarg(tbp0, tbw / 2, curvb);
-
-		if (ptextarg == NULL)
-		{
-			tbp0 &= ~0x7ff;
-			ptextarg = s_RTs.GetTarg(tbp0, tbw / 2, curvb); // mgs3 hack
-
-			if (ptextarg == NULL)
-			{
-				// check the next level (mgs3)
-				tbp0 &= ~0xfff;
-				ptextarg = s_RTs.GetTarg(tbp0, tbw / 2, curvb); // mgs3 hack
-			}
-
-			if (ptextarg != NULL && ptextarg->start > tbp0*256)
-			{
-				// target beyond range, so ignore
-				ptextarg = NULL;
-			}
-		}
-	}
-
-
-	if (PSMT_ISZTEX(tpsm) && (ptextarg == NULL))
-	{
-		// try depth
-		ptextarg = s_DepthRTs.GetTarg(tbp0, tbw, curvb);
-	}
-
-	if ((ptextarg == NULL) && (conf.settings().texture_targs))
-	{
-		// check if any part of the texture intersects the current target
-		if (!PSMT_ISCLUT(tpsm) && (curvb.tex0.tbp0 >= curvb.frame.fbp) && ((curvb.tex0.tbp0) < curvb.prndr->end))
-		{
-			ptextarg = curvb.prndr;
-		}
-	}
-
-#ifdef _DEBUG
-	if (tbp0 == 0x3600 && tbw == 0x100)
-	{
-		if (ptextarg == NULL)
-		{
-			printf("Miss %x 0x%x %d\n", tbw, tbp0, tpsm);
-
-			typedef map<u32, CRenderTarget*> MAPTARGETS;
-
-			for (MAPTARGETS::iterator itnew = s_RTs.mapTargets.begin(); itnew != s_RTs.mapTargets.end(); ++itnew)
-			{
-				printf("\tRender %x 0x%x %x\n", itnew->second->fbw, itnew->second->fbp, itnew->second->psm);
-			}
-
-			for (MAPTARGETS::iterator itnew = s_DepthRTs.mapTargets.begin(); itnew != s_DepthRTs.mapTargets.end(); ++itnew)
-			{
-				printf("\tDepth %x 0x%x %x\n", itnew->second->fbw, itnew->second->fbp, itnew->second->psm);
-			}
-
-			printf("\tCurvb 0x%x 0x%x 0x%x %x\n", curvb.frame.fbp, curvb.prndr->end, curvb.prndr->fbp, curvb.prndr->fbw);
-		}
-		else
-			printf("Hit  %x 0x%x %x\n", tbw, tbp0, tpsm);
-	}
-
-#endif
-
-	return ptextarg;
-}
-
-// Find target to draw a texture, it's highly p
-inline CRenderTarget* FlushGetTarget(VB& curvb)
-{
-	int tbw, tbp0, tpsm;
-
-	CRenderTarget* ptextarg = NULL;
-
-	if (!curvb.curprim.tme) return ptextarg;
-
-	if (curvb.bNeedTexCheck)
-	{
-		printf("How it is possible?\n");
-		// not yet initied, but still need to get correct target! (xeno3 ingame)
-		tbp0 = ZZOglGet_tbp0_TexBits(curvb.uNextTex0Data[0]);
-		tbw  = ZZOglGet_tbw_TexBitsMult(curvb.uNextTex0Data[0]);
-		tpsm = ZZOglGet_psm_TexBitsFix(curvb.uNextTex0Data[0]);
-	}
-	else
-	{
-		tbw = curvb.tex0.tbw;
-		tbp0 = curvb.tex0.tbp0;
-		tpsm = curvb.tex0.psm;
-	}
-
-	ptextarg = s_RTs.GetTarg(tbp0, tbw, curvb);
-
-	if (ptextarg == NULL)
-		ptextarg = FlushReGetTarget(tbw, tbp0, tpsm, curvb);
-
-	if ((ptextarg != NULL) && !(ptextarg->status & CRenderTarget::TS_NeedUpdate))
-	{
-		if (PSMT_BITMODE(tpsm) == 4)   // handle 8h cluts
-		{
-			// don't support clut targets, read from mem
-			// 4hl - kh2 check - from dx version -- arcum42
-
-			if (tpsm == PSMT4 && s_ClutResolve <= 1)
-			{
-				// xenosaga requires 2 resolves
-				u32 prevcount = curvb.nCount;
-				curvb.nCount = 0;
-				ptextarg->Resolve();
-				s_ClutResolve++;
-				curvb.nCount += prevcount;
-			}
-
-			ptextarg = NULL;
-		}
-		else
-		{
-			if (ptextarg == curvb.prndr)
-			{
-				// need feedback
-				curvb.prndr->CreateFeedback();
-
-				if (s_bWriteDepth && (curvb.pdepth != NULL))
-					curvb.pdepth->SetRenderTarget(1);
-				else
-					ResetRenderTarget(1);
-			}
-		}
-	}
-	else 
-	{
-		ptextarg = NULL;
-	}
-
-	return ptextarg;
-}
-
-// Set target for current context
-inline void FlushSetContextTarget(VB& curvb, int context)
-{
-	if (!curvb.bVarsSetTarg)
-	{
-		SetContextTarget(context);
-	}
-	else
-	{
-		assert(curvb.pdepth != NULL);
-
-		if (curvb.pdepth->status & CRenderTarget::TS_Virtual)
-		{
-			if (!curvb.zbuf.zmsk)
-			{
-				CRenderTarget* ptemp = s_DepthRTs.Promote(GetFrameKey(curvb.pdepth));
-				assert(ptemp == curvb.pdepth);
-			}
-			else
-			{
-				curvb.pdepth->status &= ~CRenderTarget::TS_NeedUpdate;
-			}
-		}
-
-		if ((curvb.pdepth->status & CRenderTarget::TS_NeedUpdate) || (curvb.prndr->status & CRenderTarget::TS_NeedUpdate))
-			SetContextTarget(context);
-	}
-
-	assert(!(curvb.prndr->status&CRenderTarget::TS_NeedUpdate));
-
-	curvb.prndr->status = 0;
-
-	if (curvb.pdepth != NULL)
-	{
-#ifdef _DEBUG
-		// Reduce an assert to a warning.
-		if (curvb.pdepth->status & CRenderTarget::TS_NeedUpdate)
-		{
-			ZZLog::Debug_Log("In FlushSetContextTarget, pdepth has TS_NeedUpdate set.");
-		}
-#endif
-		if (!curvb.zbuf.zmsk)
-		{
-			assert(!(curvb.pdepth->status & CRenderTarget::TS_Virtual));
-			curvb.pdepth->status = 0;
-		}
-	}
-}
-
-inline void FlushSetStream(VB& curvb)
-{
-	glBindBuffer(GL_ARRAY_BUFFER, g_vboBuffers[g_nCurVBOIndex]);
-	g_nCurVBOIndex = (g_nCurVBOIndex + 1) % g_vboBuffers.size();
-	glBufferData(GL_ARRAY_BUFFER, curvb.nCount * sizeof(VertexGPU), curvb.pBufferData, GL_STREAM_DRAW);
-//	void* pdata = glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY);
-//	memcpy_amd(pdata, curvb.pBufferData, curvb.nCount * sizeof(VertexGPU));
-//	glUnmapBuffer(GL_ARRAY_BUFFER);
-	SET_STREAM();
-	
-	GL_REPORT_ERRORD();
-}
-
-int SetMaskR = 0x0;
-int SetMaskG = 0x0;
-int SetMaskB = 0x0;
-// Set color mask. Really, it's not as good as PS2 one.
-inline void FlushSetColorMask(VB& curvb)
-{
-	s_dwColorWrite = (PSMT_BITMODE(curvb.prndr->psm) == 1) ? (COLORMASK_BLUE | COLORMASK_GREEN | COLORMASK_RED) : 0xf;
-
-	int maskR = ZZOglGet_fbmRed_FrameBits(curvb.frame.fbm);
-	int maskG = ZZOglGet_fbmGreen_FrameBits(curvb.frame.fbm);
-	int maskB = ZZOglGet_fbmBlue_FrameBits(curvb.frame.fbm);
-	int maskA = ZZOglGet_fbmAlpha_FrameBits(curvb.frame.fbm);
-
-	if (maskR == 0xff) s_dwColorWrite &= ~COLORMASK_RED;
-	if (maskG == 0xff) s_dwColorWrite &= ~COLORMASK_GREEN;
-	if (maskB == 0xff) s_dwColorWrite &= ~COLORMASK_BLUE;
-
-	if ((maskA == 0xff) || (curvb.curprim.abe && (curvb.test.atst == 2 && curvb.test.aref == 128)))
-		s_dwColorWrite &= ~COLORMASK_ALPHA;
-
-	GL_COLORMASK(s_dwColorWrite);
-}
-
-// Set Scissors for scissor test.
-inline void FlushSetScissorRect(VB& curvb)
-{
-	Rect& scissor = curvb.prndr->scissorrect;
-	glScissor(scissor.x, scissor.y, scissor.w, scissor.h);
-}
-
-// Prior really doing something check context
-inline void FlushDoContextJob(VB& curvb, int context)
-{
-	SaveRendererTarget(curvb);
-
-	FlushSetContextTarget(curvb, context);
-	icurctx = context;
-
-	FlushSetStream(curvb);
-	FlushSetColorMask(curvb);
-	FlushSetScissorRect(curvb);
-}
-
-// Set 1 is Alpha test is EQUAL and alpha should be proceed with care.
-inline int FlushGetExactcolor(const pixTest curtest)
-{
-	if (!(g_nPixelShaderVer&SHADER_REDUCED))
-		// ffx2 breaks when ==7
-		return ((curtest.ate && curtest.aref <= 128) && (curtest.atst == 4));//||curtest.atst==7);
-
-	return 0;
-}
-
-// fill the buffer by decoding the clut
-inline void FlushDecodeClut(VB& curvb, GLuint& ptexclut)
-{
-	glGenTextures(1, &ptexclut);
-	glBindTexture(GL_TEXTURE_2D, ptexclut);
-	vector<char> data(PSMT_ISHALF_STORAGE(curvb.tex0) ? 512 : 1024);
-
-	if (ptexclut != 0)
-	{
-
-		int nClutOffset = 0, clutsize;
-		int entries = PSMT_IS8CLUT(curvb.tex0.psm) ? 256 : 16;
-
-		if (curvb.tex0.csm && curvb.tex0.csa)
-			printf("ERROR, csm1\n");
-
-		if (PSMT_IS32BIT(curvb.tex0.cpsm))   // 32 bit
-		{
-			nClutOffset = 64 * curvb.tex0.csa;
-			clutsize = min(entries, 256 - curvb.tex0.csa * 16) * 4;
-		}
-		else
-		{
-			nClutOffset = 64 * (curvb.tex0.csa & 15) + (curvb.tex0.csa >= 16 ? 2 : 0);
-			clutsize = min(entries, 512 - curvb.tex0.csa * 16) * 2;
-		}
-
-		if (PSMT_IS32BIT(curvb.tex0.cpsm))   // 32 bit
-		{
-			memcpy_amd(&data[0], g_pbyGSClut + nClutOffset, clutsize);
-		}
-		else
-		{
-			u16* pClutBuffer = (u16*)(g_pbyGSClut + nClutOffset);
-			u16* pclut = (u16*) & data[0];
-			int left = ((u32)nClutOffset & 2) ? 0 : ((nClutOffset & 0x3ff) / 2) + clutsize - 512;
-
-			if (left > 0) clutsize -= left;
-
-			while (clutsize > 0)
-			{
-				pclut[0] = pClutBuffer[0];
-				pclut++;
-				pClutBuffer += 2;
-				clutsize -= 2;
-			}
-
-			if (left > 0)
-			{
-				pClutBuffer = (u16*)(g_pbyGSClut + 2);
-
-				while (left > 0)
-				{
-					pclut[0] = pClutBuffer[0];
-					left -= 2;
-					pClutBuffer += 2;
-					pclut++;
-				}
-			}
-		}
-
-		GLenum tempType = PSMT_ISHALF_STORAGE(curvb.tex0) ? GL_UNSIGNED_SHORT_5_5_5_1 : GL_UNSIGNED_BYTE;
-		Texture2D(4, 256, 1, GL_RGBA, tempType, &data[0]);
-		
-		s_vecTempTextures.push_back(ptexclut);
-
-		if (g_bSaveTex) SaveTexture("clut.tga", GL_TEXTURE_2D, ptexclut, 256, 1);
-
-		setTex2DWrap(GL_REPEAT);
-		setTex2DFilters(GL_LINEAR);
-	}
-}
-
-inline int FlushGetShaderType(VB& curvb, CRenderTarget* ptextarg, GLuint& ptexclut)
-{
-	if (PSMT_ISCLUT(curvb.tex0.psm) && !(conf.settings().no_target_clut))
-	{
-		FlushDecodeClut(curvb, ptexclut);
-
-		if (!(g_nPixelShaderVer&SHADER_REDUCED) && PSMT_ISHALF(ptextarg->psm))
-		{
-			return 4;
-		}
-		else
-		{
-			// Valkyrie
-			return 2;
-		}
-	}
-
-	if (PSMT_ISHALF_STORAGE(curvb.tex0) != PSMT_ISHALF(ptextarg->psm) && (!(g_nPixelShaderVer&SHADER_REDUCED) || !curvb.curprim.fge))
-	{
-		if (PSMT_ISHALF_STORAGE(curvb.tex0))
-		{
-			// converting from 32->16
-			// Radiata Chronicles
-			return 3;
-		}
-		else
-		{
-			// converting from 16->32
-			// Star Ward: Force
-			return 0;
-		}
-	}
-
-	return 1;
-}
-
-
-//Set page offsets depends on shader type.
-inline Vector FlushSetPageOffset(FRAGMENTSHADER* pfragment, int shadertype, CRenderTarget* ptextarg)
-{
-	SetShaderCaller("FlushSetPageOffset");
-
-	Vector vpageoffset;
-	vpageoffset.w = 0;
-
-	switch (shadertype)
-	{
-		case 3:
-			vpageoffset.x = -0.1f / 256.0f;
-			vpageoffset.y = -0.001f / 256.0f;
-			vpageoffset.z = -0.1f / (ptextarg->fbh);
-			vpageoffset.w = 0.0f;
-			break;
-
-		case 4:
-			vpageoffset.x = 2;
-			vpageoffset.y = 1;
-			vpageoffset.z = 0;
-			vpageoffset.w = 0.0001f;
-			break;
-	}
-
-	// zoe2
-	if (PSMT_ISZTEX(ptextarg->psm)) vpageoffset.w = -1.0f;
-
-	ZZshSetParameter4fv(pfragment->fPageOffset, vpageoffset, "g_fPageOffset");
-
-	return vpageoffset;
-}
-
-//Set texture offsets depends omn shader type.
-inline Vector FlushSetTexOffset(FRAGMENTSHADER* pfragment, int shadertype, VB& curvb, CRenderTarget* ptextarg)
-{
-	SetShaderCaller("FlushSetTexOffset");
-	Vector v;
-
-	if (shadertype == 3)
-	{
-		Vector v;
-		v.x = 16.0f / (float)curvb.tex0.tw;
-		v.y = 16.0f / (float)curvb.tex0.th;
-		v.z = 0.5f * v.x;
-		v.w = 0.5f * v.y;
-		ZZshSetParameter4fv(pfragment->fTexOffset, v, "g_fTexOffset");
-	}
-	else if (shadertype == 4)
-	{
-		Vector v;
-		v.x = 16.0f / (float)ptextarg->fbw;
-		v.y = 16.0f / (float)ptextarg->fbh;
-		v.z = -1;
-		v.w = 8.0f / (float)ptextarg->fbh;
-		ZZshSetParameter4fv(pfragment->fTexOffset, v, "g_fTexOffset");
-	}
-
-	return v;
-}
-
-// Set dimension (Real!) of texture. z and w
-inline Vector FlushTextureDims(FRAGMENTSHADER* pfragment, int shadertype, VB& curvb, CRenderTarget* ptextarg)
-{
-	SetShaderCaller("FlushTextureDims");
-	Vector vTexDims;
-	vTexDims.x = (float)RW(curvb.tex0.tw) ;
-	vTexDims.y = (float)RH(curvb.tex0.th) ;
-
-	// look at the offset of tbp0 from fbp
-
-	if (curvb.tex0.tbp0 <= ptextarg->fbp)
-	{
-		vTexDims.z = 0;//-0.5f/(float)ptextarg->fbw;
-		vTexDims.w = 0;//0.2f/(float)ptextarg->fbh;
-	}
-	else
-	{
-		//u32 tbp0 = curvb.tex0.tbp0 >> 5; // align to a page
-		int blockheight =  PSMT_ISHALF(ptextarg->psm) ? 64 : 32;
-		int ycoord = ((curvb.tex0.tbp0 - ptextarg->fbp) / (32 * (ptextarg->fbw >> 6))) * blockheight;
-		int xcoord = (((curvb.tex0.tbp0 - ptextarg->fbp) % (32 * (ptextarg -> fbw >> 6)))) * 2;
-		vTexDims.z = (float)xcoord;
-		vTexDims.w = (float)ycoord;
-	}
-
-	if (shadertype == 4)
-		vTexDims.z += 8.0f;
-
-	ZZshSetParameter4fv(pfragment->fTexDims, vTexDims, "g_fTexDims");
-
-	return vTexDims;
-}
-
-// Apply TEX1 mmag and mmin -- filter for expanding/reducing texture
-// We ignore all settings, only NEAREST (0) is used
-inline void FlushApplyResizeFilter(VB& curvb, u32& dwFilterOpts, CRenderTarget* ptextarg, int context)
-{
-	u32 ptexset = (ptextarg == curvb.prndr) ? ptextarg->ptexFeedback : ptextarg->ptex;
-	s_ptexCurSet[context] = ptexset;
-
-	if ((!curvb.tex1.mmag) || (!curvb.tex1.mmin))
-		glBindTexture(GL_TEXTURE_RECTANGLE_NV, ptexset);
-
-	if (!curvb.tex1.mmag)
-	{
-		glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
-		dwFilterOpts |= 1;
-	}
-
-	if (!curvb.tex1.mmin)
-	{
-		glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
-		dwFilterOpts |= 2;
-	}
-}
-
-
-// Usage existing targets depends on several tricks, 32-16 conversion and CLUTing, so we need to handle it.
-inline FRAGMENTSHADER* FlushUseExistRenderTarget(VB& curvb, CRenderTarget* ptextarg, u32& dwFilterOpts, int exactcolor, int context)
-{
-	if (ptextarg->IsDepth())
-		SetWriteDepth();
-
-	GLuint ptexclut = 0;
-
-	//int psm = PIXEL_STORAGE_FORMAT(curvb.tex0);
-	int shadertype = FlushGetShaderType(curvb, ptextarg, ptexclut);
-
-	FRAGMENTSHADER* pfragment = LoadShadeEffect(shadertype, 0, curvb.curprim.fge,
-								IsAlphaTestExpansion(curvb.tex0), exactcolor, curvb.clamp, context, NULL);
-
-	Vector vpageoffset = FlushSetPageOffset(pfragment, shadertype, ptextarg);
-
-	Vector v = FlushSetTexOffset(pfragment, shadertype, curvb, ptextarg);
-
-	Vector vTexDims = FlushTextureDims(pfragment, shadertype, curvb, ptextarg);
-
-	if (pfragment->sCLUT != NULL && ptexclut != 0)
-		ZZshGLSetTextureParameter(pfragment->sCLUT, ptexclut, "CLUT");
-
-	FlushApplyResizeFilter(curvb, dwFilterOpts, ptextarg, context);
-
-	if (g_bSaveTex)
-		SaveTexture("tex.tga", GL_TEXTURE_RECTANGLE_NV,
-					ptextarg == curvb.prndr ? ptextarg->ptexFeedback : ptextarg->ptex, RW(ptextarg->fbw), RH(ptextarg->fbh));
-
-	return pfragment;
-}
-
-// Usage most major shader.
-inline FRAGMENTSHADER* FlushMadeNewTarget(VB& curvb, int exactcolor, int context)
-{
-	// save the texture
-	if (g_bSaveTex)
-	{
-		if (g_bSaveTex == 1)
-		{
-			SaveTex(&curvb.tex0, 1);
-			/*CMemoryTarget* pmemtarg = */
-			g_MemTargs.GetMemoryTarget(curvb.tex0, 0);
-		}
-		else 
-		{
-			SaveTex(&curvb.tex0, 0);
-		}
-	}
-
-	FRAGMENTSHADER* pfragment = LoadShadeEffect(0, GetTexFilter(curvb.tex1), curvb.curprim.fge,
-								IsAlphaTestExpansion(curvb.tex0), exactcolor, curvb.clamp, context, NULL);
-
-	if (pfragment == NULL)
-		ZZLog::Error_Log("Could not find memory target shader.");
-
-	return pfragment;
-}
-
-// We made an shader, so now need to put all common variables.
-inline void FlushSetTexture(VB& curvb, FRAGMENTSHADER* pfragment, CRenderTarget* ptextarg, int context)
-{
-	SetTexVariables(context, pfragment);
-	SetTexInt(context, pfragment, ptextarg == NULL);
-
-	// have to enable the texture parameters(curtest.atst)
-	if( curvb.ptexClamp[0] != 0 ) 
-		ZZshGLSetTextureParameter(pfragment->sBitwiseANDX, curvb.ptexClamp[0], "Clamp 0");
-	
-	if( curvb.ptexClamp[1] != 0 ) 
-		ZZshGLSetTextureParameter(pfragment->sBitwiseANDY, curvb.ptexClamp[1], "Clamp 1");
-	
-	if( pfragment->sMemory != NULL && s_ptexCurSet[context] != 0) 
-		ZZshGLSetTextureParameter(pfragment->sMemory, s_ptexCurSet[context], "Clamp memory");
-
-}
-
-// Reset program and texture variables;
-inline void FlushBindProgramm(FRAGMENTSHADER* pfragment, int context)
-{
-	vb[context].bTexConstsSync = 0;
-	vb[context].bVarsTexSync = 0;
-
-	ZZshSetPixelShader(pfragment->prog);
-}
-
-inline FRAGMENTSHADER* FlushRendererStage(VB& curvb, u32& dwFilterOpts, CRenderTarget* ptextarg, int exactcolor, int context)
-{
-
-	FRAGMENTSHADER* pfragment = NULL;
-
-	// set the correct pixel shaders
-
-	if (curvb.curprim.tme)
-	{
-		if (ptextarg != NULL)
-			pfragment = FlushUseExistRenderTarget(curvb, ptextarg, dwFilterOpts, exactcolor, context);
-		else
-			pfragment = FlushMadeNewTarget(curvb, exactcolor, context);
-
-		if (pfragment == NULL)
-		{
-			ZZLog::Error_Log("Shader is not found.");
-//			return NULL;
-		}
-
-		FlushSetTexture(curvb, pfragment, ptextarg, context);
-	}
-	else
-	{
-		pfragment = &ppsRegular[curvb.curprim.fge + 2 * s_bWriteDepth];
-	}
-
-	GL_REPORT_ERRORD();
-
-	// set the shaders
-	SetShaderCaller("FlushRendererStage");
-	ZZshSetVertexShader(pvs[2 * ((curvb.curprim._val >> 1) & 3) + 8 * s_bWriteDepth + context]);
-	FlushBindProgramm(pfragment, context);
-
-	GL_REPORT_ERRORD();
-	return pfragment;
-}
-
-inline bool AlphaCanRenderStencil(VB& curvb)
-{
-	return g_bUpdateStencil && (PSMT_BITMODE(curvb.prndr->psm) != 1) &&
-		   !ZZOglGet_fbmHighByte(curvb.frame.fbm) && !(conf.settings().no_stencil);
-}
-
-inline void AlphaSetStencil(bool DoIt)
-{
-	if (DoIt)
-	{
-		glEnable(GL_STENCIL_TEST);
-		GL_STENCILFUNC(GL_ALWAYS, 0, 0);
-		glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
-	}
-	else glDisable(GL_STENCIL_TEST);
-}
-
-inline void AlphaSetDepthTest(VB& curvb, const pixTest curtest, FRAGMENTSHADER* pfragment)
-{
-	glDepthMask(!curvb.zbuf.zmsk && curtest.zte);
-	//	&& curtest.zte &&  (curtest.ztst > 1) );
-
-	if (curtest.zte)
-	{
-		if (curtest.ztst > 1) g_nDepthUsed = 2;
-		if ((curtest.ztst == 2) ^(g_nDepthBias != 0))
-		{
-			g_nDepthBias = (curtest.ztst == 2);
-			//SETRS(D3DRS_DEPTHBIAS, g_nDepthBias?FtoDW(0.0003f):FtoDW(0.000015f));
-		}
-
-		glDepthFunc(g_dwZCmp[curtest.ztst]);
-	}
-
-	GL_ZTEST(curtest.zte);
-
-	if (s_bWriteDepth)
-	{
-		if (!curvb.zbuf.zmsk)
-			curvb.pdepth->SetRenderTarget(1);
-		else
-			ResetRenderTarget(1);
-	}
-}
-
-inline u32 AlphaSetupBlendTest(VB& curvb)
-{
-	if (curvb.curprim.abe)
-		SetAlphaVariables(curvb.alpha);
-	else
-		glDisable(GL_BLEND);
-
-	u32 oldabe = curvb.curprim.abe;
-
-	if (gs.pabe)
-	{
-		//ZZLog::Error_Log("PABE!");
-		curvb.curprim.abe = 1;
-		glEnable(GL_BLEND);
-	}
-
-	return oldabe;
-}
-
-inline void AlphaRenderFBA(VB& curvb, FRAGMENTSHADER* pfragment, bool s_bDestAlphaTest, bool bCanRenderStencil)
-{
-	// needs to be before RenderAlphaTest
-	if ((gs.pabe) || (curvb.fba.fba && !ZZOglGet_fbmHighByte(curvb.frame.fbm)) || (s_bDestAlphaTest && bCanRenderStencil))
-	{
-		RenderFBA(curvb, pfragment->sOneColor);
-	}
-
-}
-
-inline u32 AlphaRenderAlpha(VB& curvb, const pixTest curtest, FRAGMENTSHADER* pfragment, int exactcolor)
-{
-	SetShaderCaller("AlphaRenderAlpha");
-	u32 dwUsingSpecialTesting = 0;
-
-	if (curvb.curprim.abe)
-	{
-		if ((bNeedBlendFactorInAlpha || ((curtest.ate && curtest.atst > 1) && (curtest.aref > 0x80))))
-		{
-			// need special stencil processing for the alpha
-			RenderAlphaTest(curvb, pfragment->sOneColor);
-			dwUsingSpecialTesting = 1;
-		}
-
-		// harvest fishing
-		Vector v = vAlphaBlendColor;
-
-		if (exactcolor)
-		{
-			v.y *= 255;
-			v.w *= 255;
-		}
-
-		ZZshSetParameter4fv(pfragment->sOneColor, v, "g_fOneColor");
-	}
-	else
-	{
-		// not using blending so set to defaults
-		Vector v = exactcolor ? Vector(1, 510 * 255.0f / 256.0f, 0, 0) : Vector(1, 2 * 255.0f / 256.0f, 0, 0);
-		ZZshSetParameter4fv(pfragment->sOneColor, v, "g_fOneColor");
-
-	}
-
-	return dwUsingSpecialTesting;
-}
-
-inline void AlphaRenderStencil(VB& curvb, bool s_bDestAlphaTest, bool bCanRenderStencil, u32 dwUsingSpecialTesting)
-{
-	if (s_bDestAlphaTest && bCanRenderStencil)
-	{
-		// if not 24bit and can write to high alpha bit
-		RenderStencil(curvb, dwUsingSpecialTesting);
-	}
-	else
-	{
-		s_stencilref = STENCIL_SPECIAL;
-		s_stencilmask = STENCIL_SPECIAL;
-
-		// setup the stencil to only accept the test pixels
-
-		if (dwUsingSpecialTesting)
-		{
-			glEnable(GL_STENCIL_TEST);
-			glStencilMask(STENCIL_PIXELWRITE);
-			GL_STENCILFUNC(GL_EQUAL, STENCIL_SPECIAL | STENCIL_PIXELWRITE, STENCIL_SPECIAL);
-			glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
-		}
-	}
-
-#ifdef _DEBUG
-	if (bDestAlphaColor == 1)
-	{
-		ZZLog::Debug_Log("Dest alpha blending! Manipulate alpha here.");
-	}
-
-#endif
-
-	if (bCanRenderStencil && gs.pabe)
-	{
-		// only render the pixels with alpha values >= 0x80
-		GL_STENCILFUNC(GL_EQUAL, s_stencilref | STENCIL_FBA, s_stencilmask | STENCIL_FBA);
-	}
-
-	GL_REPORT_ERRORD();
-}
-
-inline void AlphaTest(VB& curvb)
-{
-//	printf ("%d %d %d %d %d\n", curvb.test.date, curvb.test.datm, gs.texa.aem, curvb.test.ate, curvb.test.atst );
-
-//	return;
-	// Zeydlitz changed this with a reason! It's an "Alpha more than 1 hack."
-	if (curvb.test.ate == 1 && curvb.test.atst == 1 && curvb.test.date == 1)
-	{
-		if (curvb.test.datm == 1)
-		{
-			glAlphaFunc(GL_GREATER, 1.0f);
-		}
-		else
-		{
-			glAlphaFunc(GL_LESS, 1.0f);
-			printf("%d %d %d\n", curvb.test.date, curvb.test.datm, gs.texa.aem);
-		}
-	}
-
-	if (!curvb.test.ate || curvb.test.atst > 0)
-	{
-		Draw(curvb);
-	}
-
-	GL_REPORT_ERRORD();
-}
-
-inline void AlphaPabe(VB& curvb, FRAGMENTSHADER* pfragment, int exactcolor)
-{
-	if (gs.pabe)
-	{
-		SetShaderCaller("AlphaPabe");
-		// only render the pixels with alpha values < 0x80
-		glDisable(GL_BLEND);
-		GL_STENCILFUNC_SET();
-
-		Vector v;
-		v.x = 1;
-		v.y = 2;
-		v.z = 0;
-		v.w = 0;
-
-		if (exactcolor) v.y *= 255;
-
-		ZZshSetParameter4fv(pfragment->sOneColor, v, "g_fOneColor");
-
-		Draw(curvb);
-
-		// reset
-		if (!s_stencilmask) s_stencilfunc = GL_ALWAYS;
-
-		GL_STENCILFUNC_SET();
-	}
-
-	GL_REPORT_ERRORD();
-}
-
-// Alpha Failure does not work properly on this cases. True means that no failure job should be done.
-// First three cases are trivial manual.
-inline bool AlphaFailureIgnore(const pixTest curtest)
-{
-	if ((!curtest.ate) || (curtest.atst == 1) || (curtest.afail == 0)) return true;
-
-	if (conf.settings().no_alpha_fail && ((s_dwColorWrite < 8) || (s_dwColorWrite == 15 && curtest.atst == 5 && (curtest.aref == 64))))
-		return true;
-
-//	old and seemingly incorrect code.
-//	if ((s_dwColorWrite < 8 && s_dwColorWrite !=8) && curtest.afail == 1)
-//		return true;
-//	if ((s_dwColorWrite == 0xf) && curtest.atst == 5 && curtest.afail == 1 && !(conf.settings() & GAME_REGETHACK))
-//		return true;
-	return false;
-}
-
-// more work on alpha failure case
-inline void AlphaFailureTestJob(VB& curvb, const pixTest curtest,  FRAGMENTSHADER* pfragment, int exactcolor, bool bCanRenderStencil, int oldabe)
-{
-	// Note, case when ate == 1, atst == 0 and afail > 0 in documentation wrote as failure case. But it seems that
-	// either doc's are incorrect or this case has some issues.
-	if (AlphaFailureIgnore(curtest)) return;
-
-#ifdef NOALFAFAIL
-	ZZLog::Error_Log("Alpha job here %d %d %d %d %d %d", s_dwColorWrite, curtest.atst, curtest.afail, curtest.aref, gs.pabe, s_bWriteDepth);
-
-//	return;
-#endif
-
-	SetShaderCaller("AlphaFailureTestJob");
-
-	// need to reverse the test and disable some targets
-	glAlphaFunc(g_dwReverseAlphaCmp[curtest.atst], AlphaReferedValue(curtest.aref));
-
-	if (curtest.afail & 1)     // front buffer update only
-	{
-		if (curtest.afail == 3) glColorMask(1, 1, 1, 0);// disable alpha
-
-		glDepthMask(0);
-
-		if (s_bWriteDepth) ResetRenderTarget(1);
-	}
-	else
-	{
-		// zbuffer update only
-		glColorMask(0, 0, 0, 0);
-	}
-
-	if (gs.pabe && bCanRenderStencil)
-	{
-		// only render the pixels with alpha values >= 0x80
-		Vector v = vAlphaBlendColor;
-
-		if (exactcolor) { v.y *= 255; v.w *= 255; }
-
-		ZZshSetParameter4fv(pfragment->sOneColor, v, "g_fOneColor");
-
-		glEnable(GL_BLEND);
-		GL_STENCILFUNC(GL_EQUAL, s_stencilref | STENCIL_FBA, s_stencilmask | STENCIL_FBA);
-	}
-
-	Draw(curvb);
-
-	GL_REPORT_ERRORD();
-
-	if (gs.pabe)
-	{
-		// only render the pixels with alpha values < 0x80
-		glDisable(GL_BLEND);
-		GL_STENCILFUNC_SET();
-
-		Vector v;
-		v.x = 1;
-		v.y = 2;
-		v.z = 0;
-		v.w = 0;
-
-		if (exactcolor) v.y *= 255;
-
-		ZZshSetParameter4fv(pfragment->sOneColor, v, "g_fOneColor");
-
-		Draw(curvb);
-
-		// reset
-		if (oldabe) glEnable(GL_BLEND);
-
-		if (!s_stencilmask) s_stencilfunc = GL_ALWAYS;
-
-		GL_STENCILFUNC_SET();
-	}
-
-	// restore
-	if ((curtest.afail & 1) && !curvb.zbuf.zmsk)
-	{
-		glDepthMask(1);
-
-		if (s_bWriteDepth)
-		{
-			assert(curvb.pdepth != NULL);
-			curvb.pdepth->SetRenderTarget(1);
-		}
-	}
-
-	GL_COLORMASK(s_dwColorWrite);
-
-	// not needed anymore since rest of ops concentrate on image processing
-
-	GL_REPORT_ERRORD();
-}
-
-inline void AlphaSpecialTesting(VB& curvb, FRAGMENTSHADER* pfragment, u32 dwUsingSpecialTesting, int exactcolor)
-{
-	if (dwUsingSpecialTesting)
-	{
-		SetShaderCaller("AlphaSpecialTesting");
-
-		// render the real alpha
-		glDisable(GL_ALPHA_TEST);
-		glColorMask(0, 0, 0, 1);
-
-		if (s_bWriteDepth)
-		{
-			ResetRenderTarget(1);
-		}
-
-		glDepthMask(0);
-
-		glStencilFunc(GL_EQUAL, STENCIL_SPECIAL | STENCIL_PIXELWRITE, STENCIL_SPECIAL | STENCIL_PIXELWRITE);
-		glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
-
-		Vector v = Vector(0, exactcolor ? 510.0f : 2.0f, 0, 0);
-		ZZshSetParameter4fv(pfragment->sOneColor, v, "g_fOneColor");
-		Draw(curvb);
-
-		// don't need to restore
-	}
-
-	GL_REPORT_ERRORD();
-}
-
-inline void AlphaDestinationTest(VB& curvb, FRAGMENTSHADER* pfragment, bool s_bDestAlphaTest, bool bCanRenderStencil)
-{
-	if (s_bDestAlphaTest)
-	{
-		if ((s_dwColorWrite & COLORMASK_ALPHA))
-		{
-			if (curvb.fba.fba)
-				ProcessFBA(curvb, pfragment->sOneColor);
-			else if (bCanRenderStencil)
-				// finally make sure all entries are 1 when the dest alpha >= 0x80 (if fba is 1, this is already the case)
-				ProcessStencil(curvb);
-		}
-	}
-	else if ((s_dwColorWrite & COLORMASK_ALPHA) && curvb.fba.fba)
-		ProcessFBA(curvb, pfragment->sOneColor);
-
-	if (bDestAlphaColor == 1)
-	{
-		// need to reset the dest colors to their original counter parts
-		//WARN_LOG("Need to reset dest alpha color\n");
-	}
-}
-
-inline void AlphaSaveTarget(VB& curvb)
-{
-#ifdef _DEBUG
-	return; // Do nothing
-
-//	if( g_bSaveFlushedFrame & 0xf ) {
-//#ifdef _WIN32
-//		CreateDirectory("frames", NULL);
-//#else
-//		char* strdir="";
-//		sprintf(strdir, "mkdir %s", "frames");
-//		system(strdir);
-//#endif
-//		char str[255];
-//		sprintf(str, "frames/frame%.4d.tga", g_SaveFrameNum++);
-
-//		//glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, 0 ); // switch to the backbuffer
-//		//glFlush();
-//		//SaveTexture("tex.jpg", GL_TEXTURE_RECTANGLE_NV, curvb.prndr->ptex, RW(curvb.prndr->fbw), RH(curvb.prndr->fbh));
-//		SaveRenderTarget(str, RW(curvb.prndr->fbw), RH(curvb.prndr->fbh), 0);
-//	}
-#endif
-}
-
-inline void AlphaColorClamping(VB& curvb, const pixTest curtest)
-{
-	// clamp the final colors, when enabled ffx2 credits mess up
-	//if (gs.colclamp) ZZLog::Error_Log("ColClamp!");
-	if ((curvb.curprim.abe && bAlphaClamping) && (GetRenderFormat() != RFT_byte8) && !(conf.settings().no_color_clamp))   // if !colclamp, skip
-	{
-		//ZZLog::Error_Log("Clamped.");
-		ResetAlphaVariables();
-
-		// if processing the clamping case, make sure can write to the front buffer
-		glDisable(GL_STENCIL_TEST);
-		glEnable(GL_BLEND);
-		glDisable(GL_ALPHA_TEST);
-		glDisable(GL_DEPTH_TEST);
-		glDepthMask(0);
-		glColorMask(1, 1, 1, 0);
-
-		if (s_bWriteDepth) ResetRenderTarget(1);
-
-		SetShaderCaller("AlphaColorClamping");
-
-		ZZshSetPixelShader(ppsOne.prog);
-		GL_BLEND_RGB(GL_ONE, GL_ONE);
-
-		float f;
-
-		if (bAlphaClamping & 1)    // min
-		{
-			f = 0;
-			ZZshSetParameter4fv(ppsOne.sOneColor, &f, "g_fOneColor");
-			GL_BLENDEQ_RGB(GL_MAX_EXT);
-			Draw(curvb);
-		}
-
-		// bios shows white screen
-		if (bAlphaClamping & 2)    // max
-		{
-			f = 1;
-			ZZshSetParameter4fv(ppsOne.sOneColor, &f, "g_fOneColor");
-			GL_BLENDEQ_RGB(GL_MIN_EXT);
-			Draw(curvb);
-		}
-
-		if (!curvb.zbuf.zmsk)
-		{
-			glDepthMask(1);
-
-			if (s_bWriteDepth)
-			{
-				assert(curvb.pdepth != NULL);
-				curvb.pdepth->SetRenderTarget(1);
-			}
-		}
-
-		if (curvb.test.ate && USEALPHATESTING) glEnable(GL_ALPHA_TEST);
-
-		GL_ZTEST(curtest.zte);
-	}
-}
-
-inline void FlushUndoFiter(u32 dwFilterOpts)
-{
-	if (dwFilterOpts)
-	{
-		// undo filter changes (binding didn't change)
-		if (dwFilterOpts & 1) glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
-		if (dwFilterOpts & 2) glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
-	}
-}
-
-// This is the most important function! It draws all collected info onscreen.
-void ZeroGS::Flush(int context)
-{
-	FUNCLOG
-	VB& curvb = vb[context];
-	const pixTest curtest = curvb.test;
-
-	if (FlushInitialTest(curvb, curtest, context)) return;
-
-	VisualBufferMessage(context);
-
-	GL_REPORT_ERRORD();
-
-	CRenderTarget* ptextarg = FlushGetTarget(curvb);
-
-	SwitchWireframeOff();
-	FlushDoContextJob(curvb, context);
-
-	u32 dwUsingSpecialTesting = 0, dwFilterOpts = 0;
-	int exactcolor = FlushGetExactcolor(curtest);
-
-	FRAGMENTSHADER* pfragment = FlushRendererStage(curvb, dwFilterOpts, ptextarg, exactcolor, context);
-
-	bool bCanRenderStencil = AlphaCanRenderStencil(curvb);
-
-	if (curtest.date || gs.pabe) SetDestAlphaTest();
-
-	AlphaSetStencil(s_bDestAlphaTest && bCanRenderStencil);
-	AlphaSetDepthTest(curvb, curtest, pfragment);						// Error!
-	SetAlphaTest(curtest);
-
-	u32 oldabe = AlphaSetupBlendTest(curvb);					// Unavoidable
-
-	// needs to be before RenderAlphaTest
-	AlphaRenderFBA(curvb, pfragment, s_bDestAlphaTest, bCanRenderStencil);
-
-	dwUsingSpecialTesting =	AlphaRenderAlpha(curvb, curtest, pfragment, exactcolor);			// Unavoidable
-	AlphaRenderStencil(curvb, s_bDestAlphaTest, bCanRenderStencil, dwUsingSpecialTesting);
-	AlphaTest(curvb);								// Unavoidable
-	AlphaPabe(curvb, pfragment, exactcolor);
-	AlphaFailureTestJob(curvb, curtest, pfragment, exactcolor, bCanRenderStencil, oldabe);
-	AlphaSpecialTesting(curvb, pfragment, dwUsingSpecialTesting, exactcolor);
-	AlphaDestinationTest(curvb, pfragment, s_bDestAlphaTest, bCanRenderStencil);
-	AlphaSaveTarget(curvb);
-	
-	GL_REPORT_ERRORD();
-
-	AlphaColorClamping(curvb, curtest);
-	FlushUndoFiter(dwFilterOpts);
-
-	ppf += curvb.nCount + 0x100000;
-
-	curvb.nCount = 0;
-	curvb.curprim.abe = oldabe;
-
-	SwitchWireframeOn();
-
-	GL_REPORT_ERRORD();
-}
-
-void ZeroGS::FlushBoth()
-{
-	Flush(0);
-	Flush(1);
-}
-
-inline void ZeroGS::RenderFBA(const VB& curvb, ZZshParameter sOneColor)
-{
-	// add fba to all pixels
-	GL_STENCILFUNC(GL_ALWAYS, STENCIL_FBA, 0xff);
-	glStencilMask(STENCIL_CLEAR);
-	glStencilOp(GL_ZERO, GL_KEEP, GL_REPLACE);
-
-	glDisable(GL_DEPTH_TEST);
-	glDepthMask(0);
-	glColorMask(0, 0, 0, 0);
-
-	if (s_bWriteDepth) ResetRenderTarget(1);
-
-	SetShaderCaller("RenderFBA");
-
-	glEnable(GL_ALPHA_TEST);
-
-	glAlphaFunc(GL_GEQUAL, 1);
-
-	Vector v(1,2,0,0);
-
-	ZZshSetParameter4fv(sOneColor, v, "g_fOneColor");
-
-	Draw(curvb);
-
-	SetAlphaTest(curvb.test);
-
-	// reset (not necessary)
-	GL_COLORMASK(s_dwColorWrite);
-
-	glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
-
-	if (!curvb.zbuf.zmsk)
-	{
-		glDepthMask(1);
-
-		assert(curvb.pdepth != NULL);
-
-		if (s_bWriteDepth) curvb.pdepth->SetRenderTarget(1);
-	}
-
-	GL_ZTEST(curvb.test.zte);
-}
-
-__forceinline void ZeroGS::RenderAlphaTest(const VB& curvb, ZZshParameter sOneColor)
-{
-	if (!g_bUpdateStencil) return;
-
-	if ((curvb.test.ate) && (curvb.test.afail == 1)) glDisable(GL_ALPHA_TEST);
-
-	glDepthMask(0);
-
-	glColorMask(0, 0, 0, 0);
-
-	if (s_bWriteDepth) ResetRenderTarget(1);
-
-	SetShaderCaller("RenderAlphaTest");
-
-	Vector v(1,2,0,0);
-
-	ZZshSetParameter4fv(sOneColor, v, "g_fOneColor");
-
-	// or a 1 to the stencil buffer wherever alpha passes
-	glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
-
-	s_stencilfunc = GL_ALWAYS;
-
-	glEnable(GL_STENCIL_TEST);
-
-	if (!s_bDestAlphaTest)
-	{
-		// clear everything
-		s_stencilref = 0;
-		glStencilMask(STENCIL_CLEAR);
-		glDisable(GL_ALPHA_TEST);
-		GL_STENCILFUNC_SET();
-		Draw(curvb);
-
-		if (curvb.test.ate && curvb.test.afail != 1 && USEALPHATESTING) glEnable(GL_ALPHA_TEST);
-	}
-
-	if (curvb.test.ate && curvb.test.atst > 1 && curvb.test.aref > 0x80)
-	{
-		v = Vector(1,1,0,0);
-		ZZshSetParameter4fv(sOneColor, v, "g_fOneColor");
-		glAlphaFunc(g_dwAlphaCmp[curvb.test.atst], AlphaReferedValue(curvb.test.aref));
-	}
-
-	s_stencilref = STENCIL_SPECIAL;
-
-	glStencilMask(STENCIL_SPECIAL);
-	GL_STENCILFUNC_SET();
-	glDisable(GL_DEPTH_TEST);
-
-	Draw(curvb);
-
-	if (curvb.test.zte) glEnable(GL_DEPTH_TEST);
-
-	GL_ALPHATEST(0);
-
-	GL_COLORMASK(s_dwColorWrite);
-
-	if (!curvb.zbuf.zmsk)
-	{
-		glDepthMask(1);
-
-		// set rt next level
-
-		if (s_bWriteDepth) curvb.pdepth->SetRenderTarget(1);
-	}
-}
-
-inline void ZeroGS::RenderStencil(const VB& curvb, u32 dwUsingSpecialTesting)
-{
-	//NOTE: This stencil hack for dest alpha testing ONLY works when
-	// the geometry in one DrawPrimitive call does not overlap
-
-	// mark the stencil buffer for the new data's bits (mark 4 if alpha is >= 0xff)
-	// mark 4 if a pixel was written (so that the stencil buf can be changed with new values)
-	glStencilMask(STENCIL_PIXELWRITE);
-	glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
-
-	s_stencilmask = (curvb.test.date ? STENCIL_ALPHABIT : 0) | (dwUsingSpecialTesting ? STENCIL_SPECIAL : 0);
-	s_stencilfunc = s_stencilmask ? GL_EQUAL : GL_ALWAYS;
-
-	s_stencilref = curvb.test.date * curvb.test.datm | STENCIL_PIXELWRITE | (dwUsingSpecialTesting ? STENCIL_SPECIAL : 0);
-	GL_STENCILFUNC_SET();
-}
-
-inline void ZeroGS::ProcessStencil(const VB& curvb)
-{
-	assert(!curvb.fba.fba);
-
-	// set new alpha bit
-	glStencilMask(STENCIL_ALPHABIT);
-	GL_STENCILFUNC(GL_EQUAL, STENCIL_PIXELWRITE, STENCIL_PIXELWRITE | STENCIL_FBA);
-	glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
-
-	glDisable(GL_DEPTH_TEST);
-	glDepthMask(0);
-	glColorMask(0, 0, 0, 0);
-
-	if (s_bWriteDepth) ResetRenderTarget(1);
-
-	GL_ALPHATEST(0);
-
-	SetShaderCaller("ProcessStencil");
-
-	ZZshSetPixelShader(ppsOne.prog);
-	Draw(curvb);
-
-	// process when alpha >= 0xff
-	GL_STENCILFUNC(GL_EQUAL, STENCIL_PIXELWRITE | STENCIL_FBA | STENCIL_ALPHABIT, STENCIL_PIXELWRITE | STENCIL_FBA);
-	Draw(curvb);
-
-	// clear STENCIL_PIXELWRITE bit
-	glStencilMask(STENCIL_CLEAR);
-
-	GL_STENCILFUNC(GL_ALWAYS, 0, STENCIL_PIXELWRITE | STENCIL_FBA);
-	Draw(curvb);
-
-	// restore state
-	GL_COLORMASK(s_dwColorWrite);
-
-	if (curvb.test.ate && USEALPHATESTING) glEnable(GL_ALPHA_TEST);
-
-	if (!curvb.zbuf.zmsk)
-	{
-		glDepthMask(1);
-
-		if (s_bWriteDepth)
-		{
-			assert(curvb.pdepth != NULL);
-			curvb.pdepth->SetRenderTarget(1);
-		}
-	}
-
-	GL_ZTEST(curvb.test.zte);
-
-	glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
-}
-
-__forceinline void ZeroGS::ProcessFBA(const VB& curvb, ZZshParameter sOneColor)
-{
-	if ((curvb.frame.fbm&0x80000000)) return;
-
-	// add fba to all pixels that were written and alpha was less than 0xff
-	glStencilMask(STENCIL_ALPHABIT);
-	glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
-	GL_STENCILFUNC(GL_EQUAL, STENCIL_FBA | STENCIL_PIXELWRITE | STENCIL_ALPHABIT, STENCIL_PIXELWRITE | STENCIL_FBA);
-	glDisable(GL_DEPTH_TEST);
-
-	glDepthMask(0);
-	glColorMask(0, 0, 0, 1);
-
-	if (s_bWriteDepth) ResetRenderTarget(1);
-
-	SetShaderCaller("ProcessFBA");
-
-	// processes the pixels with ALPHA < 0x80*2
-	glEnable(GL_ALPHA_TEST);
-	glAlphaFunc(GL_LEQUAL, 1);
-
-	// add 1 to dest
-	GL_BLEND_ALPHA(GL_ONE, GL_ONE);
-	GL_BLENDEQ_ALPHA(GL_FUNC_ADD);
-
-	float f = 1;
-	ZZshSetParameter4fv(sOneColor, &f, "g_fOneColor");
-	ZZshSetPixelShader(ppsOne.prog);
-	Draw(curvb);
-	glDisable(GL_ALPHA_TEST);
-
-	// reset bits
-	glStencilMask(STENCIL_CLEAR);
-	GL_STENCILFUNC(GL_GREATER, 0, STENCIL_PIXELWRITE | STENCIL_FBA);
-	glStencilOp(GL_KEEP, GL_KEEP, GL_ZERO);
-	Draw(curvb);
-
-	if (curvb.test.atst && USEALPHATESTING)
-	{
-		glEnable(GL_ALPHA_TEST);
-		glAlphaFunc(g_dwAlphaCmp[curvb.test.atst], AlphaReferedValue(curvb.test.aref));
-	}
-
-	// restore (SetAlphaVariables)
-	GL_BLEND_ALPHA(GL_ONE, GL_ZERO);
-
-	if (vAlphaBlendColor.y < 0) GL_BLENDEQ_ALPHA(GL_FUNC_REVERSE_SUBTRACT);
-
-	// reset (not necessary)
-	GL_COLORMASK(s_dwColorWrite);
-
-	if (!curvb.zbuf.zmsk)
-	{
-		glDepthMask(1);
-
-		if (s_bWriteDepth) curvb.pdepth->SetRenderTarget(1);
-	}
-
-	GL_ZTEST(curvb.test.zte);
-}
-
-void ZeroGS::SetContextTarget(int context)
-{
-	FUNCLOG
-	VB& curvb = vb[context];
-	GL_REPORT_ERRORD();
-
-	if (curvb.prndr == NULL)
-		curvb.prndr = s_RTs.GetTarg(curvb.frame, 0, get_maxheight(curvb.gsfb.fbp, curvb.gsfb.fbw, curvb.gsfb.psm));
-
-	// make sure targets are valid
-	if (curvb.pdepth == NULL)
-	{
-		frameInfo f;
-		f.fbp = curvb.zbuf.zbp;
-		f.fbw = curvb.frame.fbw;
-		f.fbh = curvb.prndr->fbh;
-		f.psm = curvb.zbuf.psm;
-		f.fbm = 0;
-		curvb.pdepth = (CDepthTarget*)s_DepthRTs.GetTarg(f, CRenderTargetMngr::TO_DepthBuffer | CRenderTargetMngr::TO_StrictHeight |
-					   (curvb.zbuf.zmsk ? CRenderTargetMngr::TO_Virtual : 0), get_maxheight(curvb.zbuf.zbp, curvb.gsfb.fbw, 0));
-	}
-
-	assert(curvb.prndr != NULL && curvb.pdepth != NULL);
-
-	if (curvb.pdepth->fbh != curvb.prndr->fbh) ZZLog::Debug_Log("(curvb.pdepth->fbh(0x%x) != curvb.prndr->fbh(0x%x))", curvb.pdepth->fbh, curvb.prndr->fbh);
-	//assert(curvb.pdepth->fbh == curvb.prndr->fbh);
-
-	if (curvb.pdepth->status & CRenderTarget::TS_Virtual)
-	{
-
-		if (!curvb.zbuf.zmsk)
-		{
-			CRenderTarget* ptemp = s_DepthRTs.Promote(curvb.pdepth->fbp | (curvb.pdepth->fbw << 16));
-			assert(ptemp == curvb.pdepth);
-		}
-		else
-		{
-			curvb.pdepth->status &= ~CRenderTarget::TS_NeedUpdate;
-		}
-	}
-
-	bool bSetTarg = 1;
-
-	if (curvb.pdepth->status & CRenderTarget::TS_NeedUpdate)
-	{
-		assert(!(curvb.pdepth->status & CRenderTarget::TS_Virtual));
-
-		// don't update if virtual
-		curvb.pdepth->Update(context, curvb.prndr);
-		bSetTarg = 0;
-	}
-
-	GL_REPORT_ERRORD();
-
-	if (curvb.prndr->status & CRenderTarget::TS_NeedUpdate)
-	{
-		/*		if(bSetTarg) {
-		*			printf ( " Here\n ");
-		*			if(s_bWriteDepth) {
-		*				curvb.pdepth->SetRenderTarget(1);
-		*				curvb.pdepth->SetDepthStencilSurface();
-		*			}
-		*			else
-		*				curvb.pdepth->SetDepthStencilSurface();
-		*		}*/
-		curvb.prndr->Update(context, curvb.pdepth);
-	}
-	else
-	{
-
-		//if( (vb[0].prndr != vb[1].prndr && vb[!context].bVarsSetTarg) || !vb[context].bVarsSetTarg )
-		curvb.prndr->SetRenderTarget(0);
-		//if( bSetTarg && ((vb[0].pdepth != vb[1].pdepth && vb[!context].bVarsSetTarg) || !vb[context].bVarsSetTarg) )
-		curvb.pdepth->SetDepthStencilSurface();
-
-		if (conf.mrtdepth && ZeroGS::IsWriteDepth()) curvb.pdepth->SetRenderTarget(1);
-		if (s_ptexCurSet[0] == curvb.prndr->ptex) s_ptexCurSet[0] = 0;
-		if (s_ptexCurSet[1] == curvb.prndr->ptex) s_ptexCurSet[1] = 0;
-
-		curvb.prndr->SetViewport();
-	}
-
-	curvb.prndr->SetTarget(curvb.frame.fbp, curvb.scissor, context);
-
-	if ((curvb.zbuf.zbp - curvb.pdepth->fbp) != (curvb.frame.fbp - curvb.prndr->fbp) && curvb.test.zte)
-		ZZLog::Warn_Log("Frame and zbuf not aligned.");
-
-	curvb.bVarsSetTarg = true;
-
-	if (vb[!context].prndr != curvb.prndr) vb[!context].bVarsSetTarg = false;
-
-#ifdef _DEBUG
-	// These conditions happen often enough that we'll just warn about it rather then abort in Debug mode.
-	if (curvb.prndr->status & CRenderTarget::TS_NeedUpdate) 
-	{
-		ZZLog::Debug_Log("In SetContextTarget, prndr is ending with TS_NeedUpdate set.");
-	}
-	
-	if (curvb.pdepth != NULL && (curvb.pdepth->status & CRenderTarget::TS_NeedUpdate))
-	{
-		ZZLog::Debug_Log("In SetContextTarget, pdepth is ending with TS_NeedUpdate set.");
-	}
-#endif
-
-	GL_REPORT_ERRORD();
-}
-
-
-void ZeroGS::SetTexInt(int context, FRAGMENTSHADER* pfragment, int settexint)
-{
-	FUNCLOG
-
-	if (settexint)
-	{
-		tex0Info& tex0 = vb[context].tex0;
-
-		CMemoryTarget* pmemtarg = g_MemTargs.GetMemoryTarget(tex0, 1);
-
-		if (vb[context].bVarsTexSync)
-		{
-			if (vb[context].pmemtarg != pmemtarg)
-			{
-				SetTexVariablesInt(context, GetTexFilter(vb[context].tex1), tex0, true, pfragment, s_bForceTexFlush);
-				vb[context].bVarsTexSync = true;
-			}
-		}
-		else
-		{
-			SetTexVariablesInt(context, GetTexFilter(vb[context].tex1), tex0, false, pfragment, s_bForceTexFlush);
-			vb[context].bVarsTexSync = true;
-
-			INC_TEXVARS();
-		}
-	}
-	else
-	{
-		vb[context].bVarsTexSync = false;
-	}
-}
-
-// clamp relies on texture width
-void ZeroGS::SetTexClamping(int context, FRAGMENTSHADER* pfragment)
-{
-	FUNCLOG
-	SetShaderCaller("SetTexClamping");
-	clampInfo* pclamp = &ZeroGS::vb[context].clamp;
-	Vector v, v2;
-	v.x = v.y = 0;
-	u32* ptex = ZeroGS::vb[context].ptexClamp;
-	ptex[0] = ptex[1] = 0;
-
-	float fw = ZeroGS::vb[context].tex0.tw ;
-	float fh = ZeroGS::vb[context].tex0.th ;
-
-	switch (pclamp->wms)
-	{
-		case 0:
-			v2.x = -1e10;
-			v2.z = 1e10;
-			break;
-
-		case 1: // pclamp
-			// suikoden5 movie text
-			v2.x = 0;
-			v2.z = 1 - 0.5f / fw;
-			break;
-
-		case 2: // reg pclamp
-			v2.x = (pclamp->minu + 0.5f) / fw;
-			v2.z = (pclamp->maxu - 0.5f) / fw;
-			break;
-
-		case 3: // region rep x
-			v.x = 0.9999f;
-			v.z = (float)fw;
-			v2.x = (float)GPU_TEXMASKWIDTH / fw;
-			v2.z = pclamp->maxu / fw;
-			int correctMinu = pclamp->minu & (~pclamp->maxu);		// (A && B) || C == (A && (B && !C)) + C
-
-			if (correctMinu != g_PrevBitwiseTexX)
-			{
-				g_PrevBitwiseTexX = correctMinu;
-				ptex[0] = ZeroGS::s_BitwiseTextures.GetTex(correctMinu, 0);
-			}
-
-			break;
-	}
-
-	switch (pclamp->wmt)
-	{
-
-		case 0:
-			v2.y = -1e10;
-			v2.w = 1e10;
-			break;
-
-		case 1: // pclamp
-			// suikoden5 movie text
-			v2.y = 0;
-			v2.w = 1 - 0.5f / fh;
-			break;
-
-		case 2: // reg pclamp
-			v2.y = (pclamp->minv + 0.5f) / fh;
-			v2.w = (pclamp->maxv - 0.5f) / fh;
-			break;
-
-		case 3: // region rep y
-			v.y = 0.9999f;
-			v.w = (float)fh;
-			v2.y = (float)GPU_TEXMASKWIDTH / fh;
-			v2.w = pclamp->maxv / fh;
-			int correctMinv = pclamp->minv & (~pclamp->maxv);		// (A && B) || C == (A && (B && !C)) + C
-
-			if (correctMinv != g_PrevBitwiseTexY)
-			{
-				g_PrevBitwiseTexY = correctMinv;
-				ptex[1] = ZeroGS::s_BitwiseTextures.GetTex(correctMinv, ptex[0]);
-			}
-			break;
-	}
-
-	if (pfragment->fTexWrapMode != 0)
-		ZZshSetParameter4fv(pfragment->fTexWrapMode, v, "g_fTexWrapMode");
-
-	if (pfragment->fClampExts != 0)
-		ZZshSetParameter4fv(pfragment->fClampExts, v2, "g_fClampExts");
-
-
-}
-
-// Fixme should be in Vector lib
-inline bool equal_vectors(Vector a, Vector b)
-{
-	if (abs(a.x - b.x) + abs(a.y - b.y) + abs(a.z - b.z) + abs(a.w - b.w) < 0.01)
-		return true;
-	else
-		return false;
-}
-
-int CheckTexArray[4][2][2][2] = {{{{0, }}}};
-void ZeroGS::SetTexVariables(int context, FRAGMENTSHADER* pfragment)
-{
-	FUNCLOG
-
-	if (!vb[context].curprim.tme) return;
-
-	assert(!vb[context].bNeedTexCheck);
-
-	Vector v, v2;
-
-	tex0Info& tex0 = vb[context].tex0;
-
-	//float fw = (float)tex0.tw;
-	//float fh = (float)tex0.th;
-
-	if (!vb[context].bTexConstsSync)
-	{
-		SetShaderCaller("SetTexVariables");
-
-		// alpha and texture highlighting
-		Vector valpha, valpha2 ;
-
-		// if clut, use the frame format
-		int psm = PIXEL_STORAGE_FORMAT(tex0);
-
-//		ZZLog::Error_Log( "A %d psm, is-clut %d. cpsm %d | %d %d", psm,  PSMT_ISCLUT(psm), tex0.cpsm,  tex0.tfx, tex0.tcc );
-
-		Vector vblack;
-		vblack.x = vblack.y = vblack.z = vblack.w = 10;
-
-		/* tcc -- Tecture Color Component 0=RGB, 1=RGBA + use Alpha from TEXA reg when not in PSM
-		 * tfx -- Texture Function (0=modulate, 1=decal, 2=hilight, 3=hilight2)
-		 *
-		 * valpha2 =  0 0 2 1     0 0 2 1
-		 *            1 0 0 0     1 1 0 0
-		 *            0 0 2 0     0 1 2 0
-		 *            0 0 2 0     0 1 2 0
-		 *
-		 *              0        1,!nNeed         1, psm=2, 10                1, psm=1
-		 * valpha =   0 0 0 1     0 2 0 0        2ta0  2ta1-2ta0 0 0          2ta0 0 0 0
-		 *            0 0 0 1     0 1 0 0         ta0   ta1-ta0  0 0           ta0 0 0 0
-		 *	      0 0 1 1     0 1 1 1                        1 1           ta0 0 1 1
-		 *	      0 0 1 1     0 1 1 0                        1 0           ta0 0 1 0
-		*/
-
-		valpha2.x = (tex0.tfx == 1) ;
-		valpha2.y = (tex0.tcc == 1) && (tex0.tfx != 0) ;
-		valpha2.z = (tex0.tfx != 1) * 2 ;
-		valpha2.w = (tex0.tfx == 0) ;
-
-		if (tex0.tcc == 0 || !PSMT_ALPHAEXP(psm))
-		{
-			valpha.x = 0 ;
-			valpha.y = (!!tex0.tcc) * (1 + (tex0.tfx == 0)) ;
-		}
-		else
-		{
-			valpha.x = (gs.texa.fta[0])  * (1 + (tex0.tfx == 0)) ;
-			valpha.y = (gs.texa.fta[psm != PSMCT24] - gs.texa.fta[0]) * (1 + (tex0.tfx == 0)) ;
-
-		}
-
-		valpha.z = (tex0.tfx >= 3) ;
-
-		valpha.w = (tex0.tcc == 0) || (tex0.tcc == 1 && tex0.tfx == 2) ;
-
-		if (tex0.tcc && gs.texa.aem && psm == PSMCT24)
-			vblack.w = 0;
-
-		/*
-		// Test, old code.
-				Vector valpha3, valpha4;
-		 		switch(tex0.tfx) {
-					case 0:
-						valpha3.z = 0; valpha3.w = 0;
-						valpha4.x = 0; valpha4.y = 0;
-						valpha4.z = 2; valpha4.w = 1;
-
-						break;
-					case 1:
-						valpha3.z = 0; valpha3.w = 1;
-						valpha4.x = 1; valpha4.y = 0;
-						valpha4.z = 0; valpha4.w = 0;
-
-						break;
-					case 2:
-						valpha3.z = 1; valpha3.w = 1.0f;
-						valpha4.x = 0; valpha4.y = tex0.tcc ? 1.0f : 0.0f;
-						valpha4.z = 2; valpha4.w = 0;
-
-						break;
-
-					case 3:
-						valpha3.z = 1; valpha3.w = tex0.tcc ? 0.0f : 1.0f;
-						valpha4.x = 0; valpha4.y = tex0.tcc ? 1.0f : 0.0f;
-						valpha4.z = 2; valpha4.w = 0;
-
-						break;
-				}
-				if( tex0.tcc ) {
-
-					if( tex0.tfx == 1 ) {
-						//mode.x = 10;
-						valpha3.z = 0; valpha3.w = 0;
-						valpha4.x = 1; valpha4.y = 1;
-						valpha4.z = 0; valpha4.w = 0;
-					}
-
-					if( PSMT_ALPHAEXP(psm) ) {
-
-						if( tex0.tfx == 0 ) {
-							// make sure alpha is mult by two when the output is Cv = Ct*Cf
-							valpha3.x = 2*gs.texa.fta[0];
-							// if 24bit, always choose ta[0]
-							valpha3.y = 2*gs.texa.fta[psm != 1];
-							valpha3.y -= valpha.x;
-						}
-						else {
-							valpha3.x = gs.texa.fta[0];
-							// if 24bit, always choose ta[0]
-							valpha3.y = gs.texa.fta[psm != 1];
-							valpha3.y -= valpha.x;
-						}
-					}
-					else {
-						if( tex0.tfx == 0 ) {
-							valpha3.x = 0;
-							valpha3.y = 2;
-						}
-						else {
-							valpha3.x = 0;
-							valpha3.y = 1;
-						}
-					}
-				}
-				else {
-
-					// reset alpha to color
-					valpha3.x = valpha3.y = 0;
-					valpha3.w = 1;
-				}
-
-				if ( equal_vectors(valpha, valpha3) && equal_vectors(valpha2, valpha4) ) {
-					if (CheckTexArray[tex0.tfx][tex0.tcc][psm!=1][PSMT_ALPHAEXP(psm)] == 0) {
-						printf ( "Good issue %d %d %d %d\n", tex0.tfx,  tex0.tcc, psm, PSMT_ALPHAEXP(psm) );
-						CheckTexArray[tex0.tfx][tex0.tcc][psm!=1][PSMT_ALPHAEXP(psm) ] = 1;
-					}
-				}
-				else if (CheckTexArray[tex0.tfx][tex0.tcc][psm!=1][PSMT_ALPHAEXP(psm)] == -1) {
-					printf ("Bad array, %d %d %d %d\n\tolf valpha %f, %f, %f, %f : valpha2 %f %f %f %f\n\tnew valpha %f, %f, %f, %f : valpha2 %f %f %f %f\n",
-						 tex0.tfx,  tex0.tcc, psm, PSMT_ALPHAEXP(psm),
-					 	valpha3.x, valpha3.y, valpha3.z, valpha3.w, valpha4.x, valpha4.y, valpha4.z, valpha4.w,
-					 	valpha.x, valpha.y, valpha.z, valpha.w,  valpha2.x, valpha2.y, valpha2.z, valpha2.w);
-					CheckTexArray[tex0.tfx][tex0.tcc][psm!=1][PSMT_ALPHAEXP(psm)] = -1 ;
-				}
-
-		// Test;*/
-
-		ZZshSetParameter4fv(pfragment->fTexAlpha, valpha, "g_fTexAlpha");
-		ZZshSetParameter4fv(pfragment->fTexAlpha2, valpha2, "g_fTexAlpha2");
-
-		if (IsAlphaTestExpansion(tex0))
-			ZZshSetParameter4fv(pfragment->fTestBlack, vblack, "g_fTestBlack");
-
-		SetTexClamping(context, pfragment);
-
-		vb[context].bTexConstsSync = true;
-	}
-
-	if (s_bTexFlush)
-	{
-		if (PSMT_ISCLUT(tex0.psm))
-			texClutWrite(context);
-		else
-			s_bTexFlush = false;
-	}
-}
-
-void ZeroGS::SetTexVariablesInt(int context, int bilinear, const tex0Info& tex0, bool CheckVB, FRAGMENTSHADER* pfragment, int force)
-{
-	FUNCLOG
-	Vector v;
-	CMemoryTarget* pmemtarg = g_MemTargs.GetMemoryTarget(tex0, 1);
-
-	assert( pmemtarg != NULL && pfragment != NULL && pmemtarg->ptex != NULL);	
-	if (pmemtarg == NULL || pfragment == NULL || pmemtarg->ptex == NULL)
-	{
-		ZZLog::Error_Log("SetTexVariablesInt error.");
-		return;
-	}
-	
-	if (CheckVB && vb[context].pmemtarg == pmemtarg) return;
-
-	SetShaderCaller("SetTexVariablesInt");
-
-	float fw = (float)tex0.tw;
-	float fh = (float)tex0.th;
-
-	bool bUseBilinear = bilinear > 1 || (bilinear && conf.bilinear);
-
-	if (bUseBilinear)
-	{
-		v.x = (float)fw;
-		v.y = (float)fh;
-		v.z = 1.0f / (float)fw;
-		v.w = 1.0f / (float)fh;
-
-		if (pfragment->fRealTexDims)
-			ZZshSetParameter4fv(pfragment->fRealTexDims, v, "g_fRealTexDims");
-		else
-			ZZshSetParameter4fv(cgGetNamedParameter(pfragment->prog,"g_fRealTexDims"),v, "g_fRealTexDims");	
-	}
-
-	if (m_Blocks[tex0.psm].bpp == 0)
-	{
-		ZZLog::Error_Log("Undefined tex psm 0x%x!", tex0.psm);
-		return;
-	}
-
-	const BLOCK& b = m_Blocks[tex0.psm];
-
-	float fbw = (float)tex0.tbw;
-
-	Vector vTexDims;
-
-	vTexDims.x = b.vTexDims.x * (fw);
-	vTexDims.y = b.vTexDims.y * (fh);
-	vTexDims.z = (float)BLOCK_TEXWIDTH * (0.002f / 64.0f + 0.01f / 128.0f);
-	vTexDims.w = (float)BLOCK_TEXHEIGHT * 0.1f / 512.0f;
-
-	if (bUseBilinear)
-	{
-		vTexDims.x *= 1 / 128.0f;
-		vTexDims.y *= 1 / 512.0f;
-		vTexDims.z *= 1 / 128.0f;
-		vTexDims.w *= 1 / 512.0f;
-	}
-
-	float g_fitexwidth = g_fiGPU_TEXWIDTH / (float)pmemtarg->widthmult;
-
-	//float g_texwidth = GPU_TEXWIDTH*(float)pmemtarg->widthmult;
-
-	float fpage = tex0.tbp0 * (64.0f * g_fitexwidth);// + 0.05f * g_fitexwidth;
-	float fpageint = floorf(fpage);
-	//int starttbp = (int)fpage;
-
-	// 2048 is number of words to span one page
-	//float fblockstride = (2048.0f /(float)(g_texwidth*BLOCK_TEXWIDTH)) * b.vTexDims.x * fbw;
-
-	float fblockstride = (2048.0f / (float)(GPU_TEXWIDTH * (float)pmemtarg->widthmult * BLOCK_TEXWIDTH)) * b.vTexDims.x * fbw;
-
-	assert(fblockstride >= 1.0f);
-
-	v.x = (float)(2048 * g_fitexwidth);
-	v.y = fblockstride;
-	v.z = g_fBlockMult / (float)pmemtarg->widthmult;
-	v.w = fpage - fpageint ;
-
-	if (g_fBlockMult > 1)
-	{
-		// make sure to divide by mult (since the G16R16 texture loses info)
-		v.z *= b.bpp * (1 / 32.0f);
-	}
-
-	ZZshSetParameter4fv(pfragment->fTexDims, vTexDims, "g_fTexDims");
-
-//	ZZshSetParameter4fv(pfragment->fTexBlock, b.vTexBlock, "g_fTexBlock"); // I change it, and it's working. Seems casting from Vector to float[4] is ok.
-	ZZshSetParameter4fv(pfragment->fTexBlock, &b.vTexBlock.x, "g_fTexBlock");
-	ZZshSetParameter4fv(pfragment->fTexOffset, v, "g_fTexOffset");
-
-	// get hardware texture dims
-	//int texheight = (pmemtarg->realheight+pmemtarg->widthmult-1)/pmemtarg->widthmult;
-	int texwidth = GPU_TEXWIDTH * pmemtarg->widthmult * pmemtarg->channels;
-
-	v.y = 1.0f;
-	v.x = (fpageint - (float)pmemtarg->realy / (float)pmemtarg->widthmult + 0.5f);//*v.y;
-	v.z = (float)texwidth;
-
-	/*	if( !(g_nPixelShaderVer & SHADER_ACCURATE) || bUseBilinear ) {
-			if (tex0.psm == PSMT4 )
-				v.w = 0.0f;
-			else
-				v.w = 0.25f;
-			}
-		else
-			v.w = 0.5f;*/
-	v.w = 0.5f;
-
-	ZZshSetParameter4fv(pfragment->fPageOffset, v, "g_fPageOffset");
-
-	if (force)
-		s_ptexCurSet[context] = pmemtarg->ptex->tex;
-	else
-		s_ptexNextSet[context] = pmemtarg->ptex->tex;
-
-	vb[context].pmemtarg = pmemtarg;
-
-	vb[context].bVarsTexSync = false;
-}
-
-#define SET_ALPHA_COLOR_FACTOR(sign) \
-{ \
-	switch(a.c) \
-	{ \
-		case 0: \
-			vAlphaBlendColor.y = (sign) ? 2.0f*255.0f/256.0f : -2.0f*255.0f/256.0f; \
-			s_srcalpha = GL_ONE; \
-			s_alphaeq = (sign) ? GL_FUNC_ADD : GL_FUNC_REVERSE_SUBTRACT; \
-			break; \
-			\
-		case 1: \
-			/* if in 24 bit mode, dest alpha should be one */ \
-			switch(PSMT_BITMODE(vb[icurctx].prndr->psm)) \
-			{ \
-				case 0: \
-					bDestAlphaColor = (a.d!=2)&&((a.a==a.d)||(a.b==a.d)); \
-					break; \
-					\
-				case 1: \
-					/* dest alpha should be one */ \
-					bDestAlphaColor = 2; \
-					break; \
-					/* default: 16bit surface, so returned alpha is ok */ \
-			} \
-		break; \
-		\
-		case 2: \
-			bNeedBlendFactorInAlpha = true; /* should disable alpha channel writing */ \
-			vAlphaBlendColor.y = 0; \
-			vAlphaBlendColor.w = (sign) ? (float)a.fix * (2.0f/255.0f) : (float)a.fix * (-2.0f/255.0f); \
-			usec = 0; /* change so that alpha comes from source*/ \
-		break; \
-	} \
-} \
- 
-//if( a.fix <= 0x80 ) { \
-// dwTemp = (a.fix*2)>255?255:(a.fix*2); \
-// dwTemp = dwTemp|(dwTemp<<8)|(dwTemp<<16)|0x80000000; \
-// printf("bfactor: %8.8x\n", dwTemp); \
-// glBlendColorEXT(dwTemp); \
-// } \
-// else { \
-
-void ZeroGS::ResetAlphaVariables() {
-	FUNCLOG
-}
-
-inline void ZeroGS::NeedFactor(int w)
-{
-	if (bDestAlphaColor == 2)
-	{
-		bNeedBlendFactorInAlpha = (w + 1) ? true : false;
-		vAlphaBlendColor.y = 0;
-		vAlphaBlendColor.w = (float)w;
-	}
-}
-
-//static int CheckArray[48][2] = {{0,}};
-
-void ZeroGS::SetAlphaVariables(const alphaInfo& a)
-{
-	FUNCLOG
-	bool alphaenable = true;
-
-	// TODO: negative color when not clamping turns to positive???
-	g_vars._bAlphaState = 0; // set all to zero
-	bNeedBlendFactorInAlpha = false;
-	b2XAlphaTest = 1;
-	//u32 dwTemp = 0xffffffff;
-	bDestAlphaColor = 0;
-
-	// default
-	s_srcalpha = GL_ONE;
-	s_dstalpha = GL_ZERO;
-	s_alphaeq = GL_FUNC_ADD;
-	s_rgbeq = 1;
-
-//	s_alphaInfo = a;
-	vAlphaBlendColor = Vector(1, 2 * 255.0f / 256.0f, 0, 0);
-	u32 usec = a.c;
-
-
-	/*
-	 * Alpha table
-	 *           a   +  b   +  d
-	 *           	    S          		   D
-	 *     0     a     -a      1    |   0      0      0
-	 *     1     0      0      0    |   a     -a      1
-	 *     2     0      0      0    |   0      0      0
-	 *
-	 *							d = 0 Cs
-	 *   a   b   	0 Cs	   				   1 Cd        		2 0
-	 *   			   	              | 			 	       |
-	 * 0 000:  a+-a+ 1 | 0+ 0+ 0 = 	    1         | 010: a+ 0+ 1 | 0+-a+ 0 = 1-(-a)(+)(-a) | 020: a+ 0+ 1 | 0+ 0+ 0 = 1-(-a) (+)  0
-	 * 1 100:  0+-a+ 1 | a+ 0+ 0 = 1-a (+) a      | 110: 0+ 0+ 1 | a+-a+ 0 =        1      | 120: 0+ 0+ 1 | a+ 0+ 0 = 1      (+)  a
-	 * 2 200:  0+-a+ 1 | 0+ 0+ 0 = 1-a (+) 0      | 210: 0+ 0+ 1 | 0+-a+ 0 = 1     (-)  a  | 220: 0+ 0+ 1 | 0+ 0+ 0 =         1
-	 *
-	 *							d = 1 Cd
-	 *		0		              |	1				       | 		2
-	 * 0 001:  a+-a+ 0 | 0+ 0+ 1 = 0   (+) 1      | 011: a+ 0+ 0 | 0+-a+ 1 = a     (+) 1-a | 021: a+ 0+ 0 | 0+ 0+ 1 = a      (+)  1
-	 * 1 101:  0+-a+ 0 | a+ 0+ 1 = (-a)(+) 1-(-a) | 111: 0+ 0+ 0 | a+-a+ 1 = 0     (+) 1   | 121: 0+ 0+ 0 | a+ 0+ 1 = 0      (+)  1-(-a)
-	 * 2 201:  0+-a+ 0 | 0+ 0+ 1 = a   (R-)1      | 211: 0+ 0+ 0 | 0+-a+ 1 = 0     (+) 1-a | 221: 0+ 0+ 0 | 0+ 0+ 1 = 0	 (+)  1
-	 *
-	 *							d = 2 0
-	 *		0			      |			1		       |		2
-	 * 0 002:  a+-a+ 0 | 0+ 0+ 0 =      0         | 012: a+ 0+ 0 | 0+-a+ 0 = a     (-) a   | 022: a+ 0+ 0 | 0+ 0+ 0 = a      (+)  0
-	 * 1 102:  0+-a+ 0 | a+ 0+ 0 = a  (R-) a      | 112: 0+ 0+ 0 | a+-a+ 0 =        0      | 122: 0+ 0+ 0 | a+ 0+ 0 = 0      (+)  a
-	 * 2 202:  0+-a+ 0 | 0+ 0+ 0 = a  (R-) 0      | 212: 0+ 0+ 0 | 0+-a+ 0 = 0     (-) a   | 222: 0+ 0+ 0 | 0+ 0+ 0 =         0
-	 *
-	 *  Formulae is: (a-b) * (c /32) + d
-	 *  		0	1	2
-	 *  a		Cs	Cd	0
-	 *  b		Cs	Cd	0
-	 *  c		As	Ad	ALPHA.FIX
-	 *  d		Cs	Cd	0
-	 *
-	 *  We want to emulate Cs * F1(alpha)  + Cd * F2(alpha)  by  OpenGl blending: (Cs * Ss (+,-,R-) Cd * Sd)
-	 *  SET_ALPHA_COLOR_FACTOR(sign) set Set A (as As>>7, Ad>>7 or FIX>>7) with sign.
-	 *  So we could use 1+a as one_minus_alpha and -a as alpha.
-	 *
-	 */
-	int code = (a.a * 16) + (a.b * 4) + a.d ;
-
-#define one_minus_alpha  (bDestAlphaColor == 2) ? GL_ONE_MINUS_SRC_ALPHA : blendinvalpha[usec]
-#define alpha   	 (bDestAlphaColor == 2) ? GL_SRC_ALPHA : blendalpha[usec]
-#define one 		 (bDestAlphaColor == 2) ? GL_ONE : blendalpha[usec]
-#define	zero 		 (bDestAlphaColor == 2) ? GL_ZERO : blendinvalpha[usec]
-
-	switch (code)
-	{
-
-		case 0: // 000				// Cs -- nothing changed
-		case 20: // 110 = 16+4=20		// Cs
-		case 40:   // 220 = 32+8=40		// Cs
-		{
-			alphaenable = false;
-			break;
-		}
-
-		case 2: //002				// 0  -- should be zero
-		case 22: //112				// 0
-		case 42:   //222 = 32+8+2 =42		// 0
-		{
-			s_rgbeq = GL_FUNC_ADD;
-			s_srcrgb = GL_ZERO;
-			s_dstrgb = GL_ZERO;
-			break;
-		}
-
-		case 1: //001				 // Cd  -- Should be destination alpha
-		case 21: //111, 			 // Cd  -- 0*Source + 1*Desrinarion
-		case 41:   //221 = 32+8+1=41		 // Cd  --
-		{
-			s_rgbeq = GL_FUNC_ADD;
-			s_srcrgb = GL_ZERO;
-			s_dstrgb = GL_ONE;
-			break;
-		}
-
-		case 4:    // 010			 // (Cs-Cd)*A+Cs = Cs * (A + 1) - Cd * A
-		{
-			bAlphaClamping = 3;
-			SET_ALPHA_COLOR_FACTOR(0);	 // a = -A
-
-			s_rgbeq = GL_FUNC_ADD;		 // Cs*(1-a)+Cd*a
-			s_srcrgb = one_minus_alpha ;
-			s_dstrgb = alpha;
-
-			NeedFactor(-1);
-			break;
-		}
-
-		case 5:   // 011			// (Cs-Cd)*A+Cs = Cs * A + Cd * (1-A)
-		{
-			bAlphaClamping = 3; // all testing
-			SET_ALPHA_COLOR_FACTOR(1);
-
-			s_rgbeq = GL_FUNC_ADD;
-			s_srcrgb = alpha;
-			s_dstrgb = one_minus_alpha;
-
-			NeedFactor(1);
-			break;
-		}
-
-		case 6:   //012				// (Cs-Cd)*FIX
-		{
-			bAlphaClamping = 3;
-			SET_ALPHA_COLOR_FACTOR(1);
-
-			s_rgbeq = GL_FUNC_SUBTRACT;
-			s_srcrgb = alpha;
-			s_dstrgb = alpha;
-
-			break;
-		}
-
-		case 8:   //020				// Cs*A+Cs = Cs * (1+A)
-		{
-			bAlphaClamping = 2; // max testing
-			SET_ALPHA_COLOR_FACTOR(0);	// Zeyflitz change this! a = -A
-				
-			s_rgbeq = GL_FUNC_ADD;
-			s_srcrgb = one_minus_alpha;	// Cs*(1-a).
-			s_dstrgb = GL_ZERO;
-
-//			NeedFactor(1);
-			break;
-		}
-
-		case 9:   //021				// Cs*A+Cd
-		{
-			bAlphaClamping = 2; // max testing
-			SET_ALPHA_COLOR_FACTOR(1);
-				
-			s_rgbeq = GL_FUNC_ADD;
-			s_srcrgb = alpha;			// ZZ change it to.
-			s_dstrgb = GL_ONE;
-			break;
-		}
-
-		case 10:   //022			// Cs*A
-		{
-			bAlphaClamping = 2; // max testing
-			SET_ALPHA_COLOR_FACTOR(1);
-
-			s_rgbeq = GL_FUNC_ADD;
-			s_srcrgb = alpha;
-			s_dstrgb = GL_ZERO;
-			break;
-		}
-
-		case 16:   //100
-		{
-			bAlphaClamping = 3;
-			SET_ALPHA_COLOR_FACTOR(1);
-
-			s_rgbeq = GL_FUNC_ADD;
-			s_srcrgb = one_minus_alpha;
-			s_dstrgb = alpha;
-
-			NeedFactor(1);
-			break;
-		}
-
-		case 17:   //101
-		{
-			bAlphaClamping = 3; // all testing
-			SET_ALPHA_COLOR_FACTOR(0);
-
-			s_rgbeq = GL_FUNC_ADD;
-			s_srcrgb = alpha;
-			s_dstrgb = one_minus_alpha;
-
-			NeedFactor(-1);
-			break;
-		}
-
-		case 18:   //102
-		{
-			bAlphaClamping = 3;
-			SET_ALPHA_COLOR_FACTOR(1);
-
-			s_rgbeq = GL_FUNC_REVERSE_SUBTRACT;
-			s_srcrgb = alpha;
-			s_dstrgb = alpha;
-
-			break;
-		}
-
-		case 24:   //120 = 16+8
-		{
-			bAlphaClamping = 2; // max testing
-			SET_ALPHA_COLOR_FACTOR(1);
-				
-			s_rgbeq = GL_FUNC_ADD;
-			s_srcrgb = GL_ONE;
-			s_dstrgb = alpha;
-			break;
-		}
-
-		case 25:   //121				// Cd*(1+A)
-		{
-			bAlphaClamping = 2; // max testing
-			SET_ALPHA_COLOR_FACTOR(0);
-
-			s_rgbeq = GL_FUNC_ADD;
-			s_srcrgb = GL_ZERO;
-			s_dstrgb = one_minus_alpha;
-
-//			 NeedFactor(-1);
-			break;
-		}
-
-		case 26:   //122
-		{
-			bAlphaClamping = 2;
-			SET_ALPHA_COLOR_FACTOR(1);
-
-			s_rgbeq = GL_FUNC_ADD;
-			s_srcrgb = GL_ZERO;
-			s_dstrgb = alpha;
-			break;
-		}
-
-		case 32:  // 200 = 32
-		{
-			bAlphaClamping = 1; // min testing
-			SET_ALPHA_COLOR_FACTOR(1);
-
-			s_rgbeq = GL_FUNC_ADD;
-			s_srcrgb = one_minus_alpha;
-			s_dstrgb = GL_ZERO;
-			break;
-		}
-
-		case 33:  //201					// -Cs*A + Cd
-		{
-			bAlphaClamping = 1; // min testing
-			SET_ALPHA_COLOR_FACTOR(1);
-
-			s_rgbeq = GL_FUNC_REVERSE_SUBTRACT;
-			s_srcrgb = alpha;
-			s_dstrgb = GL_ONE;
-			break;
-		}
-
-		case 34:  //202
-		case 38:  //212
-		{
-			bAlphaClamping = 1; // min testing -- negative values
-
-			s_rgbeq = GL_FUNC_ADD;
-			s_srcrgb = GL_ZERO;
-			s_dstrgb = GL_ZERO;
-			break;
-		}
-
-		case 36:  //210
-		{
-			bAlphaClamping = 1; // min testing
-			SET_ALPHA_COLOR_FACTOR(1);
-
-			s_rgbeq = GL_FUNC_SUBTRACT;
-			s_srcrgb = GL_ONE;
-			s_dstrgb = alpha;
-			break;
-		}
-
-		case 37:  //211
-		{
-			bAlphaClamping = 1; // min testing
-			SET_ALPHA_COLOR_FACTOR(1);
-
-			s_rgbeq = GL_FUNC_ADD;
-			s_srcrgb = GL_ZERO;
-			s_dstrgb = one_minus_alpha;
-			break;
-		}
-
-		default:
-		{
-			ZZLog::Error_Log("Bad alpha code %d | %d %d %d", code, a.a, a.b, a.d);
-		}
-	}
-
-	/*
-		int t_rgbeq = GL_FUNC_ADD;
-		int t_srcrgb = GL_ONE;
-		int t_dstrgb = GL_ZERO;
-		int tAlphaClamping = 0;
-
-		if( a.a == a.b )
-		{ // just d remains
-			if( a.d == 0 ) 	{}
-			else
-			{
-				t_dstrgb = a.d == 1 ? GL_ONE : GL_ZERO;
-				t_srcrgb = GL_ZERO;
-				t_rgbeq = GL_FUNC_ADD; 			//a) (001) (111) (221) b) (002) (112) (222)
-			}
-			goto EndSetAlpha;
-		}
-		else if( a.d == 2 )
-		{ // zero
-			if( a.a == 2 )
-			{
-				// zero all color
-				t_srcrgb = GL_ZERO;
-				t_dstrgb = GL_ZERO;
-				goto EndSetAlpha;			// (202) (212)
-			}
-			else if( a.b == 2 )
-			{
-				//b2XAlphaTest = 1;		// a) (022)			// b) (122)
-				SET_ALPHA_COLOR_FACTOR(1);
-
-				if( bDestAlphaColor == 2 )
-				{
-					t_rgbeq = GL_FUNC_ADD;
-					t_srcrgb = a.a == 0 ? GL_ONE : GL_ZERO;
-					t_dstrgb = a.a == 0 ? GL_ZERO : GL_ONE;
-				}
-				else
-				{
-					tAlphaClamping = 2;
-					t_rgbeq = GL_FUNC_ADD;
-					t_srcrgb = a.a == 0 ? blendalpha[usec] : GL_ZERO;
-					t_dstrgb = a.a == 0 ? GL_ZERO : blendalpha[usec];
-				}
-
-				goto EndSetAlpha;
-			}
-
-			// nothing is zero, so must do some real blending	//b2XAlphaTest = 1;		//a) (012) 	//b) (102)
-			tAlphaClamping = 3;
-
-			SET_ALPHA_COLOR_FACTOR(1);
-
-			t_rgbeq = a.a == 0 ? GL_FUNC_SUBTRACT : GL_FUNC_REVERSE_SUBTRACT;
-			t_srcrgb = bDestAlphaColor == 2 ? GL_ONE : blendalpha[usec];
-			t_dstrgb = bDestAlphaColor == 2 ? GL_ONE : blendalpha[usec];
-		}
-		else if( a.a == 2 )
-		{ // zero
-
-			//b2XAlphaTest = 1;
-			tAlphaClamping = 1; // min testing
-
-			SET_ALPHA_COLOR_FACTOR(1);
-
-			if( a.b == a.d )
-			{
-				// can get away with 1-A
-				// a.a == a.d == 2!! (200) (211)
-				t_rgbeq = GL_FUNC_ADD;
-				t_srcrgb = (a.b == 0 && bDestAlphaColor != 2) ? blendinvalpha[usec] : GL_ZERO;
-				t_dstrgb = (a.b == 0 || bDestAlphaColor == 2) ? GL_ZERO : blendinvalpha[usec];
-			}
-			else
-			{
-				// a) (201) b)(210)
-				t_rgbeq = a.b==0 ? GL_FUNC_REVERSE_SUBTRACT : GL_FUNC_SUBTRACT;
-				t_srcrgb = (a.b == 0 && bDestAlphaColor != 2) ? blendalpha[usec] : GL_ONE;
-				t_dstrgb = (a.b == 0 || bDestAlphaColor == 2 ) ? GL_ONE : blendalpha[usec];
-			}
-		}
-		else if( a.b == 2 )
-		{
-			tAlphaClamping = 2; // max testing
-
-			SET_ALPHA_COLOR_FACTOR(a.a!=a.d);
-
-			if( a.a == a.d )
-			{
-				// can get away with 1+A, but need to set alpha to negative
-				// a)(020)
-				// b)(121)
-				t_rgbeq = GL_FUNC_ADD;
-
-				if( bDestAlphaColor == 2 )
-				{
-					t_srcrgb = (a.a == 0) ? GL_ONE_MINUS_SRC_ALPHA : GL_ZERO;
-					t_dstrgb = (a.a == 0) ? GL_ZERO : GL_ONE_MINUS_SRC_ALPHA;
-				}
-				else
-				{
-					t_srcrgb = a.a == 0 ? blendinvalpha[usec] : GL_ZERO;
-					t_dstrgb = a.a == 0 ? GL_ZERO : blendinvalpha[usec];
-				}
-			}
-			else
-			{
-				//a)(021) 			//b)(120) 			//b2XAlphaTest = 1;
-				t_rgbeq = GL_FUNC_ADD;
-				t_srcrgb = (a.a == 0 && bDestAlphaColor != 2) ? blendalpha[usec] : GL_ONE;
-				t_dstrgb = (a.a == 0 || bDestAlphaColor == 2) ? GL_ONE : blendalpha[usec];
-			}
-		}
-		else
-		{
-			// all 3 components are valid!
-			tAlphaClamping = 3; // all testing
-			SET_ALPHA_COLOR_FACTOR(a.a!=a.d);
-
-			if( a.a == a.d )
-			{
-				// can get away with 1+A, but need to set alpha to negative		// a) 010,	// b) 101
-				t_rgbeq = GL_FUNC_ADD;
-
-				if( bDestAlphaColor == 2 )
-				{
-					// all ones
-					t_srcrgb = a.a == 0 ? GL_ONE_MINUS_SRC_ALPHA : GL_SRC_ALPHA;
-					t_dstrgb = a.a == 0 ? GL_SRC_ALPHA : GL_ONE_MINUS_SRC_ALPHA;
-				}
-				else
-				{
-					t_srcrgb = a.a == 0 ? blendinvalpha[usec] : blendalpha[usec];
-					t_dstrgb = a.a == 0 ? blendalpha[usec] : blendinvalpha[usec];
-				}
-			}
-			else
-			{
-				t_rgbeq = GL_FUNC_ADD;		// a) 011 		// b) 100 			//
-				if( bDestAlphaColor == 2 )
-				{
-					// all ones
-					t_srcrgb = a.a != 0 ? GL_ONE_MINUS_SRC_ALPHA : GL_SRC_ALPHA;
-					t_dstrgb = a.a != 0 ? GL_SRC_ALPHA : GL_ONE_MINUS_SRC_ALPHA;
-				}
-				else
-				{
-					//b2XAlphaTest = 1;
-					t_srcrgb = a.a != 0 ? blendinvalpha[usec] : blendalpha[usec];
-					t_dstrgb = a.a != 0 ? blendalpha[usec] : blendinvalpha[usec];
-				}
-			}
-		}
-		EndSetAlpha:
-
-
-		if ( alphaenable && (t_rgbeq != s_rgbeq || s_srcrgb != t_srcrgb || t_dstrgb != s_dstrgb || tAlphaClamping != bAlphaClamping)) {
-			if (CheckArray[code][(bDestAlphaColor==2)] != -1) {
-			printf ( "A code %d, 0x%x, 0x%x, 0x%x, 0x%x %d\n", code, alpha, one_minus_alpha, one, zero, bDestAlphaColor );
-			printf ( "       Difference %d %d %d %d | 0x%x  0x%x | 0x%x  0x%x | 0x%x  0x%x | %d %d\n",
-				code, a.a, a.b, a.d,
-				t_rgbeq, s_rgbeq, t_srcrgb, s_srcrgb, t_dstrgb, s_dstrgb, tAlphaClamping, bAlphaClamping);
-			CheckArray[code][(bDestAlphaColor==2)] = -1;
-			}
-		}
-		else
-		if (CheckArray[code][(bDestAlphaColor==2)] == 0){
-			printf ( "Add good code %d %d, psm %d  destA %d\n", code, a.c, vb[icurctx].prndr->psm, bDestAlphaColor);
-			CheckArray[code][(bDestAlphaColor==2)] = 1;
-		}*/
-
-
-	if (alphaenable)
-	{
-		zgsBlendFuncSeparateEXT(s_srcrgb, s_dstrgb, s_srcalpha, s_dstalpha);
-		zgsBlendEquationSeparateEXT(s_rgbeq, s_alphaeq);
-		glEnable(GL_BLEND); // always set
-	}
-	else
-	{
-		glDisable(GL_BLEND);
-	}
-
-	INC_ALPHAVARS();
-}
-
-void ZeroGS::SetWriteDepth()
-{
-	FUNCLOG
-
-	if (conf.mrtdepth)
-	{
-		s_bWriteDepth = true;
-		s_nWriteDepthCount = 4;
-	}
-}
-
-bool ZeroGS::IsWriteDepth()
-{
-	FUNCLOG
-	return s_bWriteDepth;
-}
-
-bool ZeroGS::IsWriteDestAlphaTest()
-{
-	FUNCLOG
-	return s_bDestAlphaTest;
-}
-
-void ZeroGS::SetDestAlphaTest()
-{
-	FUNCLOG
-	s_bDestAlphaTest = true;
-	s_nWriteDestAlphaTest = 4;
-}
-
-void ZeroGS::SetTexFlush()
-{
-	FUNCLOG
-	s_bTexFlush = true;
-
-//	if( PSMT_ISCLUT(vb[0].tex0.psm) )
-//		texClutWrite(0);
-//	if( PSMT_ISCLUT(vb[1].tex0.psm) )
-//		texClutWrite(1);
-
-	if (!s_bForceTexFlush)
-	{
-		if (s_ptexCurSet[0] != s_ptexNextSet[0]) s_ptexCurSet[0] = s_ptexNextSet[0];
-		if (s_ptexCurSet[1] != s_ptexNextSet[1]) s_ptexCurSet[1] = s_ptexNextSet[1];
-	}
-}
-
+/*  ZZ Open GL graphics plugin
+ *  Copyright (c)2009-2010 zeydlitz@gmail.com, arcum42@gmail.com
+ *  Based on Zerofrog's ZeroGS KOSMOS (c)2005-2008
+ *
+ *  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 of the License, or
+ *  (at your option) any later version.
+ *
+ *  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.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+// Realization of Flush -- drawing function of GS
+
+#include <stdlib.h>
+
+#include "GS.h"
+#include "Mem.h"
+#include "zerogs.h"
+#include "targets.h"
+#include "ZZoglFlushHack.h"
+#include "ZZoglShaders.h"
+
+using namespace ZeroGS;
+
+//------------------ Defines
+#ifndef ZEROGS_DEVBUILD
+
+#define INC_GENVARS()
+#define INC_TEXVARS()
+#define INC_ALPHAVARS()
+#define INC_RESOLVE()
+
+#define g_bUpdateEffect 0
+#define g_bSaveTex 0
+bool g_bSaveTrans = 0;
+#define g_bSaveResolved 0
+
+#else // defined(ZEROGS_DEVBUILD)
+
+#define INC_GENVARS() ++g_nGenVars
+#define INC_TEXVARS() ++g_nTexVars
+#define INC_ALPHAVARS() ++g_nAlphaVars
+#define INC_RESOLVE() ++g_nResolve
+
+bool g_bSaveTrans = 0;
+bool g_bUpdateEffect = 0;
+bool g_bSaveTex = 0;	// saves the curent texture
+bool g_bSaveResolved = 0;
+#endif // !defined(ZEROGS_DEVBUILD)
+
+#define STENCIL_ALPHABIT	1	   // if set, dest alpha >= 0x80
+#define STENCIL_PIXELWRITE  2	   // if set, pixel just written (reset after every Flush)
+#define STENCIL_FBA		 4	   // if set, just written pixel's alpha >= 0 (reset after every Flush)
+#define STENCIL_SPECIAL	 8	   // if set, indicates that pixel passed its alpha test (reset after every Flush)
+//#define STENCIL_PBE		   16
+#define STENCIL_CLEAR	   (2|4|8|16)
+
+void Draw(const VB& curvb)
+{
+	glDrawArrays(primtype[curvb.curprim.prim], 0, curvb.nCount);
+}
+
+#define GL_BLEND_RGB(src, dst) { \
+	s_srcrgb = src; \
+	s_dstrgb = dst; \
+	zgsBlendFuncSeparateEXT(s_srcrgb, s_dstrgb, s_srcalpha, s_dstalpha); \
+}
+
+#define GL_BLEND_ALPHA(src, dst) { \
+	s_srcalpha = src; \
+	s_dstalpha = dst; \
+	zgsBlendFuncSeparateEXT(s_srcrgb, s_dstrgb, s_srcalpha, s_dstalpha); \
+}
+
+#define GL_BLEND_ALL(srcrgb, dstrgb, srcalpha, dstalpha) { \
+	s_srcrgb = srcrgb; \
+	s_dstrgb = dstrgb; \
+	s_srcalpha = srcalpha; \
+	s_dstalpha = dstalpha; \
+	zgsBlendFuncSeparateEXT(s_srcrgb, s_dstrgb, s_srcalpha, s_dstalpha); \
+}
+
+#define GL_ZTEST(enable) { \
+	if (enable) glEnable(GL_DEPTH_TEST); \
+	else glDisable(GL_DEPTH_TEST); \
+}
+
+#define GL_ALPHATEST(enable) { \
+	if( enable ) glEnable(GL_ALPHA_TEST); \
+	else glDisable(GL_ALPHA_TEST); \
+}
+
+#define GL_BLENDEQ_RGB(eq) { \
+	s_rgbeq = eq; \
+	zgsBlendEquationSeparateEXT(s_rgbeq, s_alphaeq); \
+}
+
+#define GL_BLENDEQ_ALPHA(eq) { \
+	s_alphaeq = eq; \
+	zgsBlendEquationSeparateEXT(s_rgbeq, s_alphaeq); \
+}
+
+#define COLORMASK_RED	  	1
+#define COLORMASK_GREEN	 	2
+#define COLORMASK_BLUE	  	4
+#define COLORMASK_ALPHA	 	8
+#define GL_COLORMASK(mask) glColorMask(!!((mask)&COLORMASK_RED), !!((mask)&COLORMASK_GREEN), !!((mask)&COLORMASK_BLUE), !!((mask)&COLORMASK_ALPHA))
+
+// ----------------- Types
+//------------------ Dummies
+
+//------------------ variables
+
+extern int g_nDepthBias;
+extern float g_fBlockMult; // used for old cards, that do not support Alpha-32float textures. We store block data in u16 and use it.
+bool g_bUpdateStencil = 1;
+//u32 g_SaveFrameNum = 0;									// ZZ
+
+extern ZZshProgram g_psprog;							// 2 -- ZZ
+
+// local alpha blending settings
+static GLenum s_rgbeq, s_alphaeq; // set by zgsBlendEquationSeparateEXT			// ZZ
+
+
+static const u32 blendalpha[3] = { GL_SRC_ALPHA, GL_DST_ALPHA, GL_CONSTANT_COLOR_EXT };	// ZZ
+static const u32 blendinvalpha[3] = { GL_ONE_MINUS_SRC_ALPHA, GL_ONE_MINUS_DST_ALPHA, GL_ONE_MINUS_CONSTANT_COLOR_EXT }; //ZZ
+static const u32 g_dwAlphaCmp[] = { GL_NEVER, GL_ALWAYS, GL_LESS, GL_LEQUAL, GL_EQUAL, GL_GEQUAL, GL_GREATER, GL_NOTEQUAL };    // ZZ
+
+// used for afail case
+static const u32 g_dwReverseAlphaCmp[] = { GL_ALWAYS, GL_NEVER, GL_GEQUAL, GL_GREATER, GL_NOTEQUAL, GL_LESS, GL_LEQUAL, GL_EQUAL };
+static const u32 g_dwZCmp[] = { GL_NEVER, GL_ALWAYS, GL_GEQUAL, GL_GREATER };
+
+/////////////////////
+// graphics resources
+#define s_bForceTexFlush 1					// ZZ
+static u32 s_ptexCurSet[2] = {0};
+static u32 s_ptexNextSet[2] = {0};				// ZZ
+
+
+extern vector<u32> s_vecTempTextures;		   // temporary textures, released at the end of every frame
+extern bool s_bTexFlush;
+bool s_bWriteDepth = false;
+bool s_bDestAlphaTest = false;
+int s_ClutResolve = 0;						// ZZ
+int g_nDepthUsed = 0; 						// ffx2 pal movies
+int s_nWriteDepthCount = 0;					// ZZ
+int s_nWriteDestAlphaTest = 0;					// ZZ
+
+////////////////////
+// State parameters
+static Vector vAlphaBlendColor;	 // used for GPU_COLOR
+
+static bool bNeedBlendFactorInAlpha;	  // set if the output source alpha is different from the real source alpha (only when blend factor > 0x80)
+static u32 s_dwColorWrite = 0xf;			// the color write mask of the current target
+
+typedef union
+{
+	struct
+	{
+		u8 _bNeedAlphaColor;		// set if vAlphaBlendColor needs to be set
+		u8 _b2XAlphaTest;		   // Only valid when bNeedAlphaColor is set. if 1st bit set set, double all alpha testing values
+		// otherwise alpha testing needs to be done separately.
+		u8 _bDestAlphaColor;		// set to 1 if blending with dest color (process only one tri at a time). If 2, dest alpha is always 1.
+		u8 _bAlphaClamping;	 // if first bit is set, do min; if second bit, do max
+	};
+
+	u32 _bAlphaState;
+} g_flag_vars;
+
+g_flag_vars g_vars;
+
+//#define bNeedAlphaColor g_vars._bNeedAlphaColor
+#define b2XAlphaTest g_vars._b2XAlphaTest
+#define bDestAlphaColor g_vars._bDestAlphaColor
+#define bAlphaClamping g_vars._bAlphaClamping
+
+int g_PrevBitwiseTexX = -1, g_PrevBitwiseTexY = -1; // textures stored in SAMP_BITWISEANDX and SAMP_BITWISEANDY		// ZZ
+
+//static alphaInfo s_alphaInfo;												// ZZ
+
+extern u8* g_pbyGSClut;
+extern int ppf;
+
+int s_nWireframeCount = 0;
+
+//------------------ Namespace
+
+namespace ZeroGS
+{
+
+VB vb[2];
+float fiTexWidth[2], fiTexHeight[2];	// current tex width and height
+
+//u8 s_AAx = 0, s_AAy = 0; // if AAy is set, then AAx has to be set
+Point AA = {0,0};
+
+int icurctx = -1;
+
+extern CRangeManager s_RangeMngr; // manages overwritten memory				// zz
+void FlushTransferRanges(const tex0Info* ptex);						//zz
+
+RenderFormatType GetRenderFormat() { return g_RenderFormatType; }					//zz
+
+// use to update the state
+void SetTexVariables(int context, FRAGMENTSHADER* pfragment);			// zz
+void SetTexInt(int context, FRAGMENTSHADER* pfragment, int settexint);		// zz
+void SetAlphaVariables(const alphaInfo& ainfo);					// zzz
+void ResetAlphaVariables();
+
+inline void SetAlphaTestInt(pixTest curtest);
+
+inline void RenderAlphaTest(const VB& curvb, ZZshParameter sOneColor);
+inline void RenderStencil(const VB& curvb, u32 dwUsingSpecialTesting);
+inline void ProcessStencil(const VB& curvb);
+inline void RenderFBA(const VB& curvb, ZZshParameter sOneColor);
+inline void ProcessFBA(const VB& curvb, ZZshParameter sOneColor);			// zz
+
+
+}
+
+//------------------ Code
+
+inline float AlphaReferedValue(int aref)
+{
+	return b2XAlphaTest ? min(1.0f, (float)aref / 127.5f) : (float)aref / 255.0f ;
+}
+
+inline void SetAlphaTest(const pixTest& curtest)
+{
+	// if s_dwColorWrite is nontrivial, than we should not off alphatest.
+	// This fix GOW and Okami.
+	if (!curtest.ate && USEALPHATESTING && (s_dwColorWrite != 2 && s_dwColorWrite != 14))
+	{
+		glDisable(GL_ALPHA_TEST);
+	}
+	else
+	{
+		glEnable(GL_ALPHA_TEST);
+		glAlphaFunc(g_dwAlphaCmp[curtest.atst], AlphaReferedValue(curtest.aref));
+	}
+}
+ 
+// Return, if tcc, aem or psm mode told us, than Alpha test should be used
+// if tcc == 0 than no alpha used, aem used for alpha expanding and I am not sure
+// that it's correct, psm -- color mode,
+inline bool IsAlphaTestExpansion(tex0Info tex0)
+{
+	return (tex0.tcc && gs.texa.aem && PSMT_ALPHAEXP(PIXEL_STORAGE_FORMAT(tex0)));
+}
+
+// Switch wireframe rendering off for first flush, so it's draw few solid primitives
+inline void SwitchWireframeOff()
+{
+	if (conf.wireframe())
+	{
+		if (s_nWireframeCount > 0)
+		{
+			glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
+		}
+	}
+}
+
+// Switch wireframe rendering on, look at previous function
+inline void SwitchWireframeOn()
+{
+	if (conf.wireframe())
+	{
+		if (s_nWireframeCount > 0)
+		{
+			glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
+			--s_nWireframeCount;
+		}
+	}
+}
+
+int GetTexFilter(const tex1Info& tex1)
+{
+	// always force
+	if (conf.bilinear == 2) return 1;
+
+	int texfilter = 0;
+
+	if (conf.bilinear && ptexBilinearBlocks != 0)
+	{
+		if (tex1.mmin <= 1)
+			texfilter = tex1.mmin | tex1.mmag;
+		else
+			texfilter = tex1.mmag ? ((tex1.mmin + 2) & 5) : tex1.mmin;
+
+		texfilter = texfilter == 1 || texfilter == 4 || texfilter == 5;
+	}
+
+	return texfilter;
+}
+
+void ZeroGS::ReloadEffects()
+{
+#ifdef ZEROGS_DEVBUILD
+
+	for (int i = 0; i < ARRAY_SIZE(ppsTexture); ++i)
+	{
+		SAFE_RELEASE_PROG(ppsTexture[i].prog);
+	}
+
+	memset(ppsTexture, 0, sizeof(ppsTexture));
+
+	LoadExtraEffects();
+#endif
+}
+
+long BufferNumber = 0;
+
+// This is a debug function. It prints all buffer info and save current texture into the file, then prints the file name.
+inline void VisualBufferMessage(int context)
+{
+#if defined(WRITE_PRIM_LOGS) && defined(_DEBUG)
+	BufferNumber++;
+	ZeroGS::VB& curvb = vb[context];
+	static const char* patst[8] = { "NEVER", "ALWAYS", "LESS", "LEQUAL", "EQUAL", "GEQUAL", "GREATER", "NOTEQUAL"};
+	static const char* pztst[4] = { "NEVER", "ALWAYS", "GEQUAL", "GREATER" };
+	static const char* pafail[4] = { "KEEP", "FB_ONLY", "ZB_ONLY", "RGB_ONLY" };
+	ZZLog::Debug_Log("**Drawing ctx %d, num %d, fbp: 0x%x, zbp: 0x%x, fpsm: %d, zpsm: %d, fbw: %d", context, vb[context].nCount, curvb.prndr->fbp, curvb.zbuf.zbp, curvb.prndr->psm, curvb.zbuf.psm, curvb.prndr->fbw);
+	ZZLog::Debug_Log("prim: prim=%x iip=%x tme=%x fge=%x abe=%x aa1=%x fst=%x ctxt=%x fix=%x",
+					 curvb.curprim.prim, curvb.curprim.iip, curvb.curprim.tme, curvb.curprim.fge, curvb.curprim.abe, curvb.curprim.aa1, curvb.curprim.fst, curvb.curprim.ctxt, curvb.curprim.fix);
+	ZZLog::Debug_Log("test: ate:%d, atst: %s, aref: %d, afail: %s, date: %d, datm: %d, zte: %d, ztst: %s, fba: %d",
+					 curvb.test.ate, patst[curvb.test.atst], curvb.test.aref, pafail[curvb.test.afail], curvb.test.date, curvb.test.datm, curvb.test.zte, pztst[curvb.test.ztst], curvb.fba.fba);
+	ZZLog::Debug_Log("alpha: A%d B%d C%d D%d FIX:%d pabe: %d; aem: %d, ta0: %d, ta1: %d\n", curvb.alpha.a, curvb.alpha.b, curvb.alpha.c, curvb.alpha.d, curvb.alpha.fix, gs.pabe, gs.texa.aem, gs.texa.ta[0], gs.texa.ta[1]);
+	ZZLog::Debug_Log("tex0: tbp0=0x%x, tbw=%d, psm=0x%x, tw=%d, th=%d, tcc=%d, tfx=%d, cbp=0x%x, cpsm=0x%x, csm=%d, csa=%d, cld=%d",
+					 curvb.tex0.tbp0, curvb.tex0.tbw, curvb.tex0.psm, curvb.tex0.tw,
+					 curvb.tex0.th, curvb.tex0.tcc, curvb.tex0.tfx, curvb.tex0.cbp,
+					 curvb.tex0.cpsm, curvb.tex0.csm, curvb.tex0.csa, curvb.tex0.cld);
+	char* Name;
+//	if (g_bSaveTex) {
+//		if (g_bSaveTex == 1)
+	Name = NamedSaveTex(&curvb.tex0, 1);
+//		else
+//			Name = NamedSaveTex(&curvb.tex0, 0);
+	ZZLog::Error_Log("TGA name '%s'.", Name);
+	free(Name);
+//	}
+//	ZZLog::Debug_Log("frame: %d, buffer %ld.\n", g_SaveFrameNum, BufferNumber);
+	ZZLog::Debug_Log("buffer %ld.\n", BufferNumber);
+#endif
+}
+
+inline void SaveRendererTarget(VB& curvb)
+{
+#ifdef _DEBUG
+
+//	if (g_bSaveFlushedFrame & 0x80000000)
+//	{
+//		char str[255];
+//		sprintf(str, "rndr%d.tga", g_SaveFrameNum);
+//		SaveRenderTarget(str, curvb.prndr->fbw, curvb.prndr->fbh, 0);
+//	}
+
+#endif
+}
+
+// Stop effects in Developers mode
+inline void FlushUpdateEffect()
+{
+#if defined(DEVBUILD)
+
+	if (g_bUpdateEffect)
+	{
+		ReloadEffects();
+		g_bUpdateEffect = 0;
+	}
+
+#endif
+}
+
+// Check, maybe we cold skip flush
+inline bool IsFlushNoNeed(VB& curvb, const pixTest& curtest)
+{
+	if (curvb.nCount == 0 || (curtest.zte && curtest.ztst == 0) || IsBadFrame(curvb))
+	{
+		curvb.nCount = 0;
+		return true;
+	}
+
+	return false;
+}
+
+// Transfer targets, that are located in current texture.
+inline void FlushTransferRangesHelper(VB& curvb)
+{
+	if (s_RangeMngr.ranges.size() > 0)
+	{
+		// don't want infinite loop, so set nCount to 0.
+		u32 prevcount = curvb.nCount;
+		curvb.nCount = 0;
+
+		FlushTransferRanges(curvb.curprim.tme ? &curvb.tex0 : NULL);
+
+		curvb.nCount += prevcount;
+	}
+}
+
+// If set bit for texture checking, do it. Maybe it's all.
+inline bool FushTexDataHelper(VB& curvb)
+{
+	if (curvb.bNeedFrameCheck || curvb.bNeedZCheck)
+	{
+		curvb.CheckFrame(curvb.curprim.tme ? curvb.tex0.tbp0 : 0);
+	}
+
+	if (curvb.bNeedTexCheck)    // Zeydlitz want to try this
+	{
+		curvb.FlushTexData();
+
+		if (curvb.nCount == 0) return true;
+	}
+
+	return false;
+}
+
+// Null target mean that we do something really bad.
+inline bool FlushCheckForNULLTarget(VB& curvb, int context)
+{
+	if ((curvb.prndr == NULL) || (curvb.pdepth == NULL))
+	{
+		ERROR_LOG_SPAMA("Current render target NULL (ctx: %d)", context);
+		curvb.nCount = 0;
+		return true;
+	}
+
+	return false;
+}
+
+// O.k. A set of resolutions, we do before real flush. We do RangeManager, FrameCheck and
+// ZCheck before this.
+inline bool FlushInitialTest(VB& curvb, const pixTest& curtest, int context)
+{
+	GL_REPORT_ERRORD();
+	assert(context >= 0 && context <= 1);
+
+	FlushUpdateEffect();
+
+	if (IsFlushNoNeed(curvb, curtest)) return true;
+
+	FlushTransferRangesHelper(curvb);
+
+	if (FushTexDataHelper(curvb)) return true;
+
+	GL_REPORT_ERRORD();
+
+	if (FlushCheckForNULLTarget(curvb, context)) return true;
+
+	return false;
+}
+
+// Try to different approach if texture target was not found
+inline CRenderTarget* FlushReGetTarget(int& tbw, int& tbp0, int& tpsm, VB& curvb)
+{
+	// This was incorrect code
+	CRenderTarget* ptextarg = NULL;
+
+	if ((ptextarg == NULL) && (tpsm == PSMT8) && (conf.settings().reget))
+	{
+		// check for targets with half the width. Break Valkyrie Chronicles
+		ptextarg = s_RTs.GetTarg(tbp0, tbw / 2, curvb);
+
+		if (ptextarg == NULL)
+		{
+			tbp0 &= ~0x7ff;
+			ptextarg = s_RTs.GetTarg(tbp0, tbw / 2, curvb); // mgs3 hack
+
+			if (ptextarg == NULL)
+			{
+				// check the next level (mgs3)
+				tbp0 &= ~0xfff;
+				ptextarg = s_RTs.GetTarg(tbp0, tbw / 2, curvb); // mgs3 hack
+			}
+
+			if (ptextarg != NULL && ptextarg->start > tbp0*256)
+			{
+				// target beyond range, so ignore
+				ptextarg = NULL;
+			}
+		}
+	}
+
+
+	if (PSMT_ISZTEX(tpsm) && (ptextarg == NULL))
+	{
+		// try depth
+		ptextarg = s_DepthRTs.GetTarg(tbp0, tbw, curvb);
+	}
+
+	if ((ptextarg == NULL) && (conf.settings().texture_targs))
+	{
+		// check if any part of the texture intersects the current target
+		if (!PSMT_ISCLUT(tpsm) && (curvb.tex0.tbp0 >= curvb.frame.fbp) && ((curvb.tex0.tbp0) < curvb.prndr->end))
+		{
+			ptextarg = curvb.prndr;
+		}
+	}
+
+#ifdef _DEBUG
+	if (tbp0 == 0x3600 && tbw == 0x100)
+	{
+		if (ptextarg == NULL)
+		{
+			printf("Miss %x 0x%x %d\n", tbw, tbp0, tpsm);
+
+			typedef map<u32, CRenderTarget*> MAPTARGETS;
+
+			for (MAPTARGETS::iterator itnew = s_RTs.mapTargets.begin(); itnew != s_RTs.mapTargets.end(); ++itnew)
+			{
+				printf("\tRender %x 0x%x %x\n", itnew->second->fbw, itnew->second->fbp, itnew->second->psm);
+			}
+
+			for (MAPTARGETS::iterator itnew = s_DepthRTs.mapTargets.begin(); itnew != s_DepthRTs.mapTargets.end(); ++itnew)
+			{
+				printf("\tDepth %x 0x%x %x\n", itnew->second->fbw, itnew->second->fbp, itnew->second->psm);
+			}
+
+			printf("\tCurvb 0x%x 0x%x 0x%x %x\n", curvb.frame.fbp, curvb.prndr->end, curvb.prndr->fbp, curvb.prndr->fbw);
+		}
+		else
+			printf("Hit  %x 0x%x %x\n", tbw, tbp0, tpsm);
+	}
+
+#endif
+
+	return ptextarg;
+}
+
+// Find target to draw a texture, it's highly p
+inline CRenderTarget* FlushGetTarget(VB& curvb)
+{
+	int tbw, tbp0, tpsm;
+
+	CRenderTarget* ptextarg = NULL;
+
+	if (!curvb.curprim.tme) return ptextarg;
+
+	if (curvb.bNeedTexCheck)
+	{
+		printf("How it is possible?\n");
+		// not yet initied, but still need to get correct target! (xeno3 ingame)
+		tbp0 = ZZOglGet_tbp0_TexBits(curvb.uNextTex0Data[0]);
+		tbw  = ZZOglGet_tbw_TexBitsMult(curvb.uNextTex0Data[0]);
+		tpsm = ZZOglGet_psm_TexBitsFix(curvb.uNextTex0Data[0]);
+	}
+	else
+	{
+		tbw = curvb.tex0.tbw;
+		tbp0 = curvb.tex0.tbp0;
+		tpsm = curvb.tex0.psm;
+	}
+
+	ptextarg = s_RTs.GetTarg(tbp0, tbw, curvb);
+
+	if (ptextarg == NULL)
+		ptextarg = FlushReGetTarget(tbw, tbp0, tpsm, curvb);
+
+	if ((ptextarg != NULL) && !(ptextarg->status & CRenderTarget::TS_NeedUpdate))
+	{
+		if (PSMT_BITMODE(tpsm) == 4)   // handle 8h cluts
+		{
+			// don't support clut targets, read from mem
+			// 4hl - kh2 check - from dx version -- arcum42
+
+			if (tpsm == PSMT4 && s_ClutResolve <= 1)
+			{
+				// xenosaga requires 2 resolves
+				u32 prevcount = curvb.nCount;
+				curvb.nCount = 0;
+				ptextarg->Resolve();
+				s_ClutResolve++;
+				curvb.nCount += prevcount;
+			}
+
+			ptextarg = NULL;
+		}
+		else
+		{
+			if (ptextarg == curvb.prndr)
+			{
+				// need feedback
+				curvb.prndr->CreateFeedback();
+
+				if (s_bWriteDepth && (curvb.pdepth != NULL))
+					curvb.pdepth->SetRenderTarget(1);
+				else
+					ResetRenderTarget(1);
+			}
+		}
+	}
+	else 
+	{
+		ptextarg = NULL;
+	}
+
+	return ptextarg;
+}
+
+// Set target for current context
+inline void FlushSetContextTarget(VB& curvb, int context)
+{
+	if (!curvb.bVarsSetTarg)
+	{
+		SetContextTarget(context);
+	}
+	else
+	{
+		assert(curvb.pdepth != NULL);
+
+		if (curvb.pdepth->status & CRenderTarget::TS_Virtual)
+		{
+			if (!curvb.zbuf.zmsk)
+			{
+				CRenderTarget* ptemp = s_DepthRTs.Promote(GetFrameKey(curvb.pdepth));
+				assert(ptemp == curvb.pdepth);
+			}
+			else
+			{
+				curvb.pdepth->status &= ~CRenderTarget::TS_NeedUpdate;
+			}
+		}
+
+		if ((curvb.pdepth->status & CRenderTarget::TS_NeedUpdate) || (curvb.prndr->status & CRenderTarget::TS_NeedUpdate))
+			SetContextTarget(context);
+	}
+
+	assert(!(curvb.prndr->status&CRenderTarget::TS_NeedUpdate));
+
+	curvb.prndr->status = 0;
+
+	if (curvb.pdepth != NULL)
+	{
+#ifdef _DEBUG
+		// Reduce an assert to a warning.
+		if (curvb.pdepth->status & CRenderTarget::TS_NeedUpdate)
+		{
+			ZZLog::Debug_Log("In FlushSetContextTarget, pdepth has TS_NeedUpdate set.");
+		}
+#endif
+		if (!curvb.zbuf.zmsk)
+		{
+			assert(!(curvb.pdepth->status & CRenderTarget::TS_Virtual));
+			curvb.pdepth->status = 0;
+		}
+	}
+}
+
+inline void FlushSetStream(VB& curvb)
+{
+	glBindBuffer(GL_ARRAY_BUFFER, g_vboBuffers[g_nCurVBOIndex]);
+	g_nCurVBOIndex = (g_nCurVBOIndex + 1) % g_vboBuffers.size();
+	glBufferData(GL_ARRAY_BUFFER, curvb.nCount * sizeof(VertexGPU), curvb.pBufferData, GL_STREAM_DRAW);
+//	void* pdata = glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY);
+//	memcpy_amd(pdata, curvb.pBufferData, curvb.nCount * sizeof(VertexGPU));
+//	glUnmapBuffer(GL_ARRAY_BUFFER);
+	SET_STREAM();
+	
+	GL_REPORT_ERRORD();
+}
+
+int SetMaskR = 0x0;
+int SetMaskG = 0x0;
+int SetMaskB = 0x0;
+// Set color mask. Really, it's not as good as PS2 one.
+inline void FlushSetColorMask(VB& curvb)
+{
+	s_dwColorWrite = (PSMT_BITMODE(curvb.prndr->psm) == 1) ? (COLORMASK_BLUE | COLORMASK_GREEN | COLORMASK_RED) : 0xf;
+
+	int maskR = ZZOglGet_fbmRed_FrameBits(curvb.frame.fbm);
+	int maskG = ZZOglGet_fbmGreen_FrameBits(curvb.frame.fbm);
+	int maskB = ZZOglGet_fbmBlue_FrameBits(curvb.frame.fbm);
+	int maskA = ZZOglGet_fbmAlpha_FrameBits(curvb.frame.fbm);
+
+	if (maskR == 0xff) s_dwColorWrite &= ~COLORMASK_RED;
+	if (maskG == 0xff) s_dwColorWrite &= ~COLORMASK_GREEN;
+	if (maskB == 0xff) s_dwColorWrite &= ~COLORMASK_BLUE;
+
+	if ((maskA == 0xff) || (curvb.curprim.abe && (curvb.test.atst == 2 && curvb.test.aref == 128)))
+		s_dwColorWrite &= ~COLORMASK_ALPHA;
+
+	GL_COLORMASK(s_dwColorWrite);
+}
+
+// Set Scissors for scissor test.
+inline void FlushSetScissorRect(VB& curvb)
+{
+	Rect& scissor = curvb.prndr->scissorrect;
+	glScissor(scissor.x, scissor.y, scissor.w, scissor.h);
+}
+
+// Prior really doing something check context
+inline void FlushDoContextJob(VB& curvb, int context)
+{
+	SaveRendererTarget(curvb);
+
+	FlushSetContextTarget(curvb, context);
+	icurctx = context;
+
+	FlushSetStream(curvb);
+	FlushSetColorMask(curvb);
+	FlushSetScissorRect(curvb);
+}
+
+// Set 1 is Alpha test is EQUAL and alpha should be proceed with care.
+inline int FlushGetExactcolor(const pixTest curtest)
+{
+	if (!(g_nPixelShaderVer&SHADER_REDUCED))
+		// ffx2 breaks when ==7
+		return ((curtest.ate && curtest.aref <= 128) && (curtest.atst == 4));//||curtest.atst==7);
+
+	return 0;
+}
+
+// fill the buffer by decoding the clut
+inline void FlushDecodeClut(VB& curvb, GLuint& ptexclut)
+{
+	glGenTextures(1, &ptexclut);
+	glBindTexture(GL_TEXTURE_2D, ptexclut);
+	vector<char> data(PSMT_ISHALF_STORAGE(curvb.tex0) ? 512 : 1024);
+
+	if (ptexclut != 0)
+	{
+
+		int nClutOffset = 0, clutsize;
+		int entries = PSMT_IS8CLUT(curvb.tex0.psm) ? 256 : 16;
+
+		if (curvb.tex0.csm && curvb.tex0.csa)
+			printf("ERROR, csm1\n");
+
+		if (PSMT_IS32BIT(curvb.tex0.cpsm))   // 32 bit
+		{
+			nClutOffset = 64 * curvb.tex0.csa;
+			clutsize = min(entries, 256 - curvb.tex0.csa * 16) * 4;
+		}
+		else
+		{
+			nClutOffset = 64 * (curvb.tex0.csa & 15) + (curvb.tex0.csa >= 16 ? 2 : 0);
+			clutsize = min(entries, 512 - curvb.tex0.csa * 16) * 2;
+		}
+
+		if (PSMT_IS32BIT(curvb.tex0.cpsm))   // 32 bit
+		{
+			memcpy_amd(&data[0], g_pbyGSClut + nClutOffset, clutsize);
+		}
+		else
+		{
+			u16* pClutBuffer = (u16*)(g_pbyGSClut + nClutOffset);
+			u16* pclut = (u16*) & data[0];
+			int left = ((u32)nClutOffset & 2) ? 0 : ((nClutOffset & 0x3ff) / 2) + clutsize - 512;
+
+			if (left > 0) clutsize -= left;
+
+			while (clutsize > 0)
+			{
+				pclut[0] = pClutBuffer[0];
+				pclut++;
+				pClutBuffer += 2;
+				clutsize -= 2;
+			}
+
+			if (left > 0)
+			{
+				pClutBuffer = (u16*)(g_pbyGSClut + 2);
+
+				while (left > 0)
+				{
+					pclut[0] = pClutBuffer[0];
+					left -= 2;
+					pClutBuffer += 2;
+					pclut++;
+				}
+			}
+		}
+
+		GLenum tempType = PSMT_ISHALF_STORAGE(curvb.tex0) ? GL_UNSIGNED_SHORT_5_5_5_1 : GL_UNSIGNED_BYTE;
+		Texture2D(4, 256, 1, GL_RGBA, tempType, &data[0]);
+		
+		s_vecTempTextures.push_back(ptexclut);
+
+		if (g_bSaveTex) SaveTexture("clut.tga", GL_TEXTURE_2D, ptexclut, 256, 1);
+
+		setTex2DWrap(GL_REPEAT);
+		setTex2DFilters(GL_LINEAR);
+	}
+}
+
+inline int FlushGetShaderType(VB& curvb, CRenderTarget* ptextarg, GLuint& ptexclut)
+{
+	if (PSMT_ISCLUT(curvb.tex0.psm) && !(conf.settings().no_target_clut))
+	{
+		FlushDecodeClut(curvb, ptexclut);
+
+		if (!(g_nPixelShaderVer&SHADER_REDUCED) && PSMT_ISHALF(ptextarg->psm))
+		{
+			return 4;
+		}
+		else
+		{
+			// Valkyrie
+			return 2;
+		}
+	}
+
+	if (PSMT_ISHALF_STORAGE(curvb.tex0) != PSMT_ISHALF(ptextarg->psm) && (!(g_nPixelShaderVer&SHADER_REDUCED) || !curvb.curprim.fge))
+	{
+		if (PSMT_ISHALF_STORAGE(curvb.tex0))
+		{
+			// converting from 32->16
+			// Radiata Chronicles
+			return 3;
+		}
+		else
+		{
+			// converting from 16->32
+			// Star Ward: Force
+			return 0;
+		}
+	}
+
+	return 1;
+}
+
+
+//Set page offsets depends on shader type.
+inline Vector FlushSetPageOffset(FRAGMENTSHADER* pfragment, int shadertype, CRenderTarget* ptextarg)
+{
+	SetShaderCaller("FlushSetPageOffset");
+
+	Vector vpageoffset;
+	vpageoffset.w = 0;
+
+	switch (shadertype)
+	{
+		case 3:
+			vpageoffset.x = -0.1f / 256.0f;
+			vpageoffset.y = -0.001f / 256.0f;
+			vpageoffset.z = -0.1f / (ptextarg->fbh);
+			vpageoffset.w = 0.0f;
+			break;
+
+		case 4:
+			vpageoffset.x = 2;
+			vpageoffset.y = 1;
+			vpageoffset.z = 0;
+			vpageoffset.w = 0.0001f;
+			break;
+	}
+
+	// zoe2
+	if (PSMT_ISZTEX(ptextarg->psm)) vpageoffset.w = -1.0f;
+
+	ZZshSetParameter4fv(pfragment->fPageOffset, vpageoffset, "g_fPageOffset");
+
+	return vpageoffset;
+}
+
+//Set texture offsets depends omn shader type.
+inline Vector FlushSetTexOffset(FRAGMENTSHADER* pfragment, int shadertype, VB& curvb, CRenderTarget* ptextarg)
+{
+	SetShaderCaller("FlushSetTexOffset");
+	Vector v;
+
+	if (shadertype == 3)
+	{
+		Vector v;
+		v.x = 16.0f / (float)curvb.tex0.tw;
+		v.y = 16.0f / (float)curvb.tex0.th;
+		v.z = 0.5f * v.x;
+		v.w = 0.5f * v.y;
+		ZZshSetParameter4fv(pfragment->fTexOffset, v, "g_fTexOffset");
+	}
+	else if (shadertype == 4)
+	{
+		Vector v;
+		v.x = 16.0f / (float)ptextarg->fbw;
+		v.y = 16.0f / (float)ptextarg->fbh;
+		v.z = -1;
+		v.w = 8.0f / (float)ptextarg->fbh;
+		ZZshSetParameter4fv(pfragment->fTexOffset, v, "g_fTexOffset");
+	}
+
+	return v;
+}
+
+// Set dimension (Real!) of texture. z and w
+inline Vector FlushTextureDims(FRAGMENTSHADER* pfragment, int shadertype, VB& curvb, CRenderTarget* ptextarg)
+{
+	SetShaderCaller("FlushTextureDims");
+	Vector vTexDims;
+	vTexDims.x = (float)RW(curvb.tex0.tw) ;
+	vTexDims.y = (float)RH(curvb.tex0.th) ;
+
+	// look at the offset of tbp0 from fbp
+
+	if (curvb.tex0.tbp0 <= ptextarg->fbp)
+	{
+		vTexDims.z = 0;//-0.5f/(float)ptextarg->fbw;
+		vTexDims.w = 0;//0.2f/(float)ptextarg->fbh;
+	}
+	else
+	{
+		//u32 tbp0 = curvb.tex0.tbp0 >> 5; // align to a page
+		int blockheight =  PSMT_ISHALF(ptextarg->psm) ? 64 : 32;
+		int ycoord = ((curvb.tex0.tbp0 - ptextarg->fbp) / (32 * (ptextarg->fbw >> 6))) * blockheight;
+		int xcoord = (((curvb.tex0.tbp0 - ptextarg->fbp) % (32 * (ptextarg -> fbw >> 6)))) * 2;
+		vTexDims.z = (float)xcoord;
+		vTexDims.w = (float)ycoord;
+	}
+
+	if (shadertype == 4)
+		vTexDims.z += 8.0f;
+
+	ZZshSetParameter4fv(pfragment->fTexDims, vTexDims, "g_fTexDims");
+
+	return vTexDims;
+}
+
+// Apply TEX1 mmag and mmin -- filter for expanding/reducing texture
+// We ignore all settings, only NEAREST (0) is used
+inline void FlushApplyResizeFilter(VB& curvb, u32& dwFilterOpts, CRenderTarget* ptextarg, int context)
+{
+	u32 ptexset = (ptextarg == curvb.prndr) ? ptextarg->ptexFeedback : ptextarg->ptex;
+	s_ptexCurSet[context] = ptexset;
+
+	if ((!curvb.tex1.mmag) || (!curvb.tex1.mmin))
+		glBindTexture(GL_TEXTURE_RECTANGLE_NV, ptexset);
+
+	if (!curvb.tex1.mmag)
+	{
+		glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+		dwFilterOpts |= 1;
+	}
+
+	if (!curvb.tex1.mmin)
+	{
+		glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+		dwFilterOpts |= 2;
+	}
+}
+
+
+// Usage existing targets depends on several tricks, 32-16 conversion and CLUTing, so we need to handle it.
+inline FRAGMENTSHADER* FlushUseExistRenderTarget(VB& curvb, CRenderTarget* ptextarg, u32& dwFilterOpts, int exactcolor, int context)
+{
+	if (ptextarg->IsDepth())
+		SetWriteDepth();
+
+	GLuint ptexclut = 0;
+
+	//int psm = PIXEL_STORAGE_FORMAT(curvb.tex0);
+	int shadertype = FlushGetShaderType(curvb, ptextarg, ptexclut);
+
+	FRAGMENTSHADER* pfragment = LoadShadeEffect(shadertype, 0, curvb.curprim.fge,
+								IsAlphaTestExpansion(curvb.tex0), exactcolor, curvb.clamp, context, NULL);
+
+	Vector vpageoffset = FlushSetPageOffset(pfragment, shadertype, ptextarg);
+
+	Vector v = FlushSetTexOffset(pfragment, shadertype, curvb, ptextarg);
+
+	Vector vTexDims = FlushTextureDims(pfragment, shadertype, curvb, ptextarg);
+
+	if (pfragment->sCLUT != NULL && ptexclut != 0)
+		ZZshGLSetTextureParameter(pfragment->sCLUT, ptexclut, "CLUT");
+
+	FlushApplyResizeFilter(curvb, dwFilterOpts, ptextarg, context);
+
+	if (g_bSaveTex)
+		SaveTexture("tex.tga", GL_TEXTURE_RECTANGLE_NV,
+					ptextarg == curvb.prndr ? ptextarg->ptexFeedback : ptextarg->ptex, RW(ptextarg->fbw), RH(ptextarg->fbh));
+
+	return pfragment;
+}
+
+// Usage most major shader.
+inline FRAGMENTSHADER* FlushMadeNewTarget(VB& curvb, int exactcolor, int context)
+{
+	// save the texture
+	if (g_bSaveTex)
+	{
+		if (g_bSaveTex == 1)
+		{
+			SaveTex(&curvb.tex0, 1);
+			/*CMemoryTarget* pmemtarg = */
+			g_MemTargs.GetMemoryTarget(curvb.tex0, 0);
+		}
+		else 
+		{
+			SaveTex(&curvb.tex0, 0);
+		}
+	}
+
+	FRAGMENTSHADER* pfragment = LoadShadeEffect(0, GetTexFilter(curvb.tex1), curvb.curprim.fge,
+								IsAlphaTestExpansion(curvb.tex0), exactcolor, curvb.clamp, context, NULL);
+
+	if (pfragment == NULL)
+		ZZLog::Error_Log("Could not find memory target shader.");
+
+	return pfragment;
+}
+
+// We made an shader, so now need to put all common variables.
+inline void FlushSetTexture(VB& curvb, FRAGMENTSHADER* pfragment, CRenderTarget* ptextarg, int context)
+{
+	SetTexVariables(context, pfragment);
+	SetTexInt(context, pfragment, ptextarg == NULL);
+
+	// have to enable the texture parameters(curtest.atst)
+	if( curvb.ptexClamp[0] != 0 ) 
+		ZZshGLSetTextureParameter(pfragment->sBitwiseANDX, curvb.ptexClamp[0], "Clamp 0");
+	
+	if( curvb.ptexClamp[1] != 0 ) 
+		ZZshGLSetTextureParameter(pfragment->sBitwiseANDY, curvb.ptexClamp[1], "Clamp 1");
+	
+	if( pfragment->sMemory != NULL && s_ptexCurSet[context] != 0) 
+		ZZshGLSetTextureParameter(pfragment->sMemory, s_ptexCurSet[context], "Clamp memory");
+
+}
+
+// Reset program and texture variables;
+inline void FlushBindProgramm(FRAGMENTSHADER* pfragment, int context)
+{
+	vb[context].bTexConstsSync = 0;
+	vb[context].bVarsTexSync = 0;
+
+	ZZshSetPixelShader(pfragment->prog);
+}
+
+inline FRAGMENTSHADER* FlushRendererStage(VB& curvb, u32& dwFilterOpts, CRenderTarget* ptextarg, int exactcolor, int context)
+{
+
+	FRAGMENTSHADER* pfragment = NULL;
+
+	// set the correct pixel shaders
+
+	if (curvb.curprim.tme)
+	{
+		if (ptextarg != NULL)
+			pfragment = FlushUseExistRenderTarget(curvb, ptextarg, dwFilterOpts, exactcolor, context);
+		else
+			pfragment = FlushMadeNewTarget(curvb, exactcolor, context);
+
+		if (pfragment == NULL)
+		{
+			ZZLog::Error_Log("Shader is not found.");
+//			return NULL;
+		}
+
+		FlushSetTexture(curvb, pfragment, ptextarg, context);
+	}
+	else
+	{
+		pfragment = &ppsRegular[curvb.curprim.fge + 2 * s_bWriteDepth];
+	}
+
+	GL_REPORT_ERRORD();
+
+	// set the shaders
+	SetShaderCaller("FlushRendererStage");
+	ZZshSetVertexShader(pvs[2 * ((curvb.curprim._val >> 1) & 3) + 8 * s_bWriteDepth + context]);
+	FlushBindProgramm(pfragment, context);
+
+	GL_REPORT_ERRORD();
+	return pfragment;
+}
+
+inline bool AlphaCanRenderStencil(VB& curvb)
+{
+	return g_bUpdateStencil && (PSMT_BITMODE(curvb.prndr->psm) != 1) &&
+		   !ZZOglGet_fbmHighByte(curvb.frame.fbm) && !(conf.settings().no_stencil);
+}
+
+inline void AlphaSetStencil(bool DoIt)
+{
+	if (DoIt)
+	{
+		glEnable(GL_STENCIL_TEST);
+		GL_STENCILFUNC(GL_ALWAYS, 0, 0);
+		glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
+	}
+	else glDisable(GL_STENCIL_TEST);
+}
+
+inline void AlphaSetDepthTest(VB& curvb, const pixTest curtest, FRAGMENTSHADER* pfragment)
+{
+	glDepthMask(!curvb.zbuf.zmsk && curtest.zte);
+	//	&& curtest.zte &&  (curtest.ztst > 1) );
+
+	if (curtest.zte)
+	{
+		if (curtest.ztst > 1) g_nDepthUsed = 2;
+		if ((curtest.ztst == 2) ^(g_nDepthBias != 0))
+		{
+			g_nDepthBias = (curtest.ztst == 2);
+			//SETRS(D3DRS_DEPTHBIAS, g_nDepthBias?FtoDW(0.0003f):FtoDW(0.000015f));
+		}
+
+		glDepthFunc(g_dwZCmp[curtest.ztst]);
+	}
+
+	GL_ZTEST(curtest.zte);
+
+	if (s_bWriteDepth)
+	{
+		if (!curvb.zbuf.zmsk)
+			curvb.pdepth->SetRenderTarget(1);
+		else
+			ResetRenderTarget(1);
+	}
+}
+
+inline u32 AlphaSetupBlendTest(VB& curvb)
+{
+	if (curvb.curprim.abe)
+		SetAlphaVariables(curvb.alpha);
+	else
+		glDisable(GL_BLEND);
+
+	u32 oldabe = curvb.curprim.abe;
+
+	if (gs.pabe)
+	{
+		//ZZLog::Error_Log("PABE!");
+		curvb.curprim.abe = 1;
+		glEnable(GL_BLEND);
+	}
+
+	return oldabe;
+}
+
+inline void AlphaRenderFBA(VB& curvb, FRAGMENTSHADER* pfragment, bool s_bDestAlphaTest, bool bCanRenderStencil)
+{
+	// needs to be before RenderAlphaTest
+	if ((gs.pabe) || (curvb.fba.fba && !ZZOglGet_fbmHighByte(curvb.frame.fbm)) || (s_bDestAlphaTest && bCanRenderStencil))
+	{
+		RenderFBA(curvb, pfragment->sOneColor);
+	}
+
+}
+
+inline u32 AlphaRenderAlpha(VB& curvb, const pixTest curtest, FRAGMENTSHADER* pfragment, int exactcolor)
+{
+	SetShaderCaller("AlphaRenderAlpha");
+	u32 dwUsingSpecialTesting = 0;
+
+	if (curvb.curprim.abe)
+	{
+		if ((bNeedBlendFactorInAlpha || ((curtest.ate && curtest.atst > 1) && (curtest.aref > 0x80))))
+		{
+			// need special stencil processing for the alpha
+			RenderAlphaTest(curvb, pfragment->sOneColor);
+			dwUsingSpecialTesting = 1;
+		}
+
+		// harvest fishing
+		Vector v = vAlphaBlendColor;
+
+		if (exactcolor)
+		{
+			v.y *= 255;
+			v.w *= 255;
+		}
+
+		ZZshSetParameter4fv(pfragment->sOneColor, v, "g_fOneColor");
+	}
+	else
+	{
+		// not using blending so set to defaults
+		Vector v = exactcolor ? Vector(1, 510 * 255.0f / 256.0f, 0, 0) : Vector(1, 2 * 255.0f / 256.0f, 0, 0);
+		ZZshSetParameter4fv(pfragment->sOneColor, v, "g_fOneColor");
+
+	}
+
+	return dwUsingSpecialTesting;
+}
+
+inline void AlphaRenderStencil(VB& curvb, bool s_bDestAlphaTest, bool bCanRenderStencil, u32 dwUsingSpecialTesting)
+{
+	if (s_bDestAlphaTest && bCanRenderStencil)
+	{
+		// if not 24bit and can write to high alpha bit
+		RenderStencil(curvb, dwUsingSpecialTesting);
+	}
+	else
+	{
+		s_stencilref = STENCIL_SPECIAL;
+		s_stencilmask = STENCIL_SPECIAL;
+
+		// setup the stencil to only accept the test pixels
+
+		if (dwUsingSpecialTesting)
+		{
+			glEnable(GL_STENCIL_TEST);
+			glStencilMask(STENCIL_PIXELWRITE);
+			GL_STENCILFUNC(GL_EQUAL, STENCIL_SPECIAL | STENCIL_PIXELWRITE, STENCIL_SPECIAL);
+			glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
+		}
+	}
+
+#ifdef _DEBUG
+	if (bDestAlphaColor == 1)
+	{
+		ZZLog::Debug_Log("Dest alpha blending! Manipulate alpha here.");
+	}
+
+#endif
+
+	if (bCanRenderStencil && gs.pabe)
+	{
+		// only render the pixels with alpha values >= 0x80
+		GL_STENCILFUNC(GL_EQUAL, s_stencilref | STENCIL_FBA, s_stencilmask | STENCIL_FBA);
+	}
+
+	GL_REPORT_ERRORD();
+}
+
+inline void AlphaTest(VB& curvb)
+{
+//	printf ("%d %d %d %d %d\n", curvb.test.date, curvb.test.datm, gs.texa.aem, curvb.test.ate, curvb.test.atst );
+
+//	return;
+	// Zeydlitz changed this with a reason! It's an "Alpha more than 1 hack."
+	if (curvb.test.ate == 1 && curvb.test.atst == 1 && curvb.test.date == 1)
+	{
+		if (curvb.test.datm == 1)
+		{
+			glAlphaFunc(GL_GREATER, 1.0f);
+		}
+		else
+		{
+			glAlphaFunc(GL_LESS, 1.0f);
+			printf("%d %d %d\n", curvb.test.date, curvb.test.datm, gs.texa.aem);
+		}
+	}
+
+	if (!curvb.test.ate || curvb.test.atst > 0)
+	{
+		Draw(curvb);
+	}
+
+	GL_REPORT_ERRORD();
+}
+
+inline void AlphaPabe(VB& curvb, FRAGMENTSHADER* pfragment, int exactcolor)
+{
+	if (gs.pabe)
+	{
+		SetShaderCaller("AlphaPabe");
+		// only render the pixels with alpha values < 0x80
+		glDisable(GL_BLEND);
+		GL_STENCILFUNC_SET();
+
+		Vector v;
+		v.x = 1;
+		v.y = 2;
+		v.z = 0;
+		v.w = 0;
+
+		if (exactcolor) v.y *= 255;
+
+		ZZshSetParameter4fv(pfragment->sOneColor, v, "g_fOneColor");
+
+		Draw(curvb);
+
+		// reset
+		if (!s_stencilmask) s_stencilfunc = GL_ALWAYS;
+
+		GL_STENCILFUNC_SET();
+	}
+
+	GL_REPORT_ERRORD();
+}
+
+// Alpha Failure does not work properly on this cases. True means that no failure job should be done.
+// First three cases are trivial manual.
+inline bool AlphaFailureIgnore(const pixTest curtest)
+{
+	if ((!curtest.ate) || (curtest.atst == 1) || (curtest.afail == 0)) return true;
+
+	if (conf.settings().no_alpha_fail && ((s_dwColorWrite < 8) || (s_dwColorWrite == 15 && curtest.atst == 5 && (curtest.aref == 64))))
+		return true;
+
+//	old and seemingly incorrect code.
+//	if ((s_dwColorWrite < 8 && s_dwColorWrite !=8) && curtest.afail == 1)
+//		return true;
+//	if ((s_dwColorWrite == 0xf) && curtest.atst == 5 && curtest.afail == 1 && !(conf.settings() & GAME_REGETHACK))
+//		return true;
+	return false;
+}
+
+// more work on alpha failure case
+inline void AlphaFailureTestJob(VB& curvb, const pixTest curtest,  FRAGMENTSHADER* pfragment, int exactcolor, bool bCanRenderStencil, int oldabe)
+{
+	// Note, case when ate == 1, atst == 0 and afail > 0 in documentation wrote as failure case. But it seems that
+	// either doc's are incorrect or this case has some issues.
+	if (AlphaFailureIgnore(curtest)) return;
+
+#ifdef NOALFAFAIL
+	ZZLog::Error_Log("Alpha job here %d %d %d %d %d %d", s_dwColorWrite, curtest.atst, curtest.afail, curtest.aref, gs.pabe, s_bWriteDepth);
+
+//	return;
+#endif
+
+	SetShaderCaller("AlphaFailureTestJob");
+
+	// need to reverse the test and disable some targets
+	glAlphaFunc(g_dwReverseAlphaCmp[curtest.atst], AlphaReferedValue(curtest.aref));
+
+	if (curtest.afail & 1)     // front buffer update only
+	{
+		if (curtest.afail == 3) glColorMask(1, 1, 1, 0);// disable alpha
+
+		glDepthMask(0);
+
+		if (s_bWriteDepth) ResetRenderTarget(1);
+	}
+	else
+	{
+		// zbuffer update only
+		glColorMask(0, 0, 0, 0);
+	}
+
+	if (gs.pabe && bCanRenderStencil)
+	{
+		// only render the pixels with alpha values >= 0x80
+		Vector v = vAlphaBlendColor;
+
+		if (exactcolor) { v.y *= 255; v.w *= 255; }
+
+		ZZshSetParameter4fv(pfragment->sOneColor, v, "g_fOneColor");
+
+		glEnable(GL_BLEND);
+		GL_STENCILFUNC(GL_EQUAL, s_stencilref | STENCIL_FBA, s_stencilmask | STENCIL_FBA);
+	}
+
+	Draw(curvb);
+
+	GL_REPORT_ERRORD();
+
+	if (gs.pabe)
+	{
+		// only render the pixels with alpha values < 0x80
+		glDisable(GL_BLEND);
+		GL_STENCILFUNC_SET();
+
+		Vector v;
+		v.x = 1;
+		v.y = 2;
+		v.z = 0;
+		v.w = 0;
+
+		if (exactcolor) v.y *= 255;
+
+		ZZshSetParameter4fv(pfragment->sOneColor, v, "g_fOneColor");
+
+		Draw(curvb);
+
+		// reset
+		if (oldabe) glEnable(GL_BLEND);
+
+		if (!s_stencilmask) s_stencilfunc = GL_ALWAYS;
+
+		GL_STENCILFUNC_SET();
+	}
+
+	// restore
+	if ((curtest.afail & 1) && !curvb.zbuf.zmsk)
+	{
+		glDepthMask(1);
+
+		if (s_bWriteDepth)
+		{
+			assert(curvb.pdepth != NULL);
+			curvb.pdepth->SetRenderTarget(1);
+		}
+	}
+
+	GL_COLORMASK(s_dwColorWrite);
+
+	// not needed anymore since rest of ops concentrate on image processing
+
+	GL_REPORT_ERRORD();
+}
+
+inline void AlphaSpecialTesting(VB& curvb, FRAGMENTSHADER* pfragment, u32 dwUsingSpecialTesting, int exactcolor)
+{
+	if (dwUsingSpecialTesting)
+	{
+		SetShaderCaller("AlphaSpecialTesting");
+
+		// render the real alpha
+		glDisable(GL_ALPHA_TEST);
+		glColorMask(0, 0, 0, 1);
+
+		if (s_bWriteDepth)
+		{
+			ResetRenderTarget(1);
+		}
+
+		glDepthMask(0);
+
+		glStencilFunc(GL_EQUAL, STENCIL_SPECIAL | STENCIL_PIXELWRITE, STENCIL_SPECIAL | STENCIL_PIXELWRITE);
+		glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
+
+		Vector v = Vector(0, exactcolor ? 510.0f : 2.0f, 0, 0);
+		ZZshSetParameter4fv(pfragment->sOneColor, v, "g_fOneColor");
+		Draw(curvb);
+
+		// don't need to restore
+	}
+
+	GL_REPORT_ERRORD();
+}
+
+inline void AlphaDestinationTest(VB& curvb, FRAGMENTSHADER* pfragment, bool s_bDestAlphaTest, bool bCanRenderStencil)
+{
+	if (s_bDestAlphaTest)
+	{
+		if ((s_dwColorWrite & COLORMASK_ALPHA))
+		{
+			if (curvb.fba.fba)
+				ProcessFBA(curvb, pfragment->sOneColor);
+			else if (bCanRenderStencil)
+				// finally make sure all entries are 1 when the dest alpha >= 0x80 (if fba is 1, this is already the case)
+				ProcessStencil(curvb);
+		}
+	}
+	else if ((s_dwColorWrite & COLORMASK_ALPHA) && curvb.fba.fba)
+		ProcessFBA(curvb, pfragment->sOneColor);
+
+	if (bDestAlphaColor == 1)
+	{
+		// need to reset the dest colors to their original counter parts
+		//WARN_LOG("Need to reset dest alpha color\n");
+	}
+}
+
+inline void AlphaSaveTarget(VB& curvb)
+{
+#ifdef _DEBUG
+	return; // Do nothing
+
+//	if( g_bSaveFlushedFrame & 0xf ) {
+//#ifdef _WIN32
+//		CreateDirectory("frames", NULL);
+//#else
+//		char* strdir="";
+//		sprintf(strdir, "mkdir %s", "frames");
+//		system(strdir);
+//#endif
+//		char str[255];
+//		sprintf(str, "frames/frame%.4d.tga", g_SaveFrameNum++);
+
+//		//glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, 0 ); // switch to the backbuffer
+//		//glFlush();
+//		//SaveTexture("tex.jpg", GL_TEXTURE_RECTANGLE_NV, curvb.prndr->ptex, RW(curvb.prndr->fbw), RH(curvb.prndr->fbh));
+//		SaveRenderTarget(str, RW(curvb.prndr->fbw), RH(curvb.prndr->fbh), 0);
+//	}
+#endif
+}
+
+inline void AlphaColorClamping(VB& curvb, const pixTest curtest)
+{
+	// clamp the final colors, when enabled ffx2 credits mess up
+	//if (gs.colclamp) ZZLog::Error_Log("ColClamp!");
+	if ((curvb.curprim.abe && bAlphaClamping) && (GetRenderFormat() != RFT_byte8) && !(conf.settings().no_color_clamp))   // if !colclamp, skip
+	{
+		//ZZLog::Error_Log("Clamped.");
+		ResetAlphaVariables();
+
+		// if processing the clamping case, make sure can write to the front buffer
+		glDisable(GL_STENCIL_TEST);
+		glEnable(GL_BLEND);
+		glDisable(GL_ALPHA_TEST);
+		glDisable(GL_DEPTH_TEST);
+		glDepthMask(0);
+		glColorMask(1, 1, 1, 0);
+
+		if (s_bWriteDepth) ResetRenderTarget(1);
+
+		SetShaderCaller("AlphaColorClamping");
+
+		ZZshSetPixelShader(ppsOne.prog);
+		GL_BLEND_RGB(GL_ONE, GL_ONE);
+
+		float f;
+
+		if (bAlphaClamping & 1)    // min
+		{
+			f = 0;
+			ZZshSetParameter4fv(ppsOne.sOneColor, &f, "g_fOneColor");
+			GL_BLENDEQ_RGB(GL_MAX_EXT);
+			Draw(curvb);
+		}
+
+		// bios shows white screen
+		if (bAlphaClamping & 2)    // max
+		{
+			f = 1;
+			ZZshSetParameter4fv(ppsOne.sOneColor, &f, "g_fOneColor");
+			GL_BLENDEQ_RGB(GL_MIN_EXT);
+			Draw(curvb);
+		}
+
+		if (!curvb.zbuf.zmsk)
+		{
+			glDepthMask(1);
+
+			if (s_bWriteDepth)
+			{
+				assert(curvb.pdepth != NULL);
+				curvb.pdepth->SetRenderTarget(1);
+			}
+		}
+
+		if (curvb.test.ate && USEALPHATESTING) glEnable(GL_ALPHA_TEST);
+
+		GL_ZTEST(curtest.zte);
+	}
+}
+
+inline void FlushUndoFiter(u32 dwFilterOpts)
+{
+	if (dwFilterOpts)
+	{
+		// undo filter changes (binding didn't change)
+		if (dwFilterOpts & 1) glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+		if (dwFilterOpts & 2) glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+	}
+}
+
+// This is the most important function! It draws all collected info onscreen.
+void ZeroGS::Flush(int context)
+{
+	FUNCLOG
+	VB& curvb = vb[context];
+	const pixTest curtest = curvb.test;
+
+	if (FlushInitialTest(curvb, curtest, context)) return;
+
+	VisualBufferMessage(context);
+
+	GL_REPORT_ERRORD();
+
+	CRenderTarget* ptextarg = FlushGetTarget(curvb);
+
+	SwitchWireframeOff();
+	FlushDoContextJob(curvb, context);
+
+	u32 dwUsingSpecialTesting = 0, dwFilterOpts = 0;
+	int exactcolor = FlushGetExactcolor(curtest);
+
+	FRAGMENTSHADER* pfragment = FlushRendererStage(curvb, dwFilterOpts, ptextarg, exactcolor, context);
+
+	bool bCanRenderStencil = AlphaCanRenderStencil(curvb);
+
+	if (curtest.date || gs.pabe) SetDestAlphaTest();
+
+	AlphaSetStencil(s_bDestAlphaTest && bCanRenderStencil);
+	AlphaSetDepthTest(curvb, curtest, pfragment);						// Error!
+	SetAlphaTest(curtest);
+
+	u32 oldabe = AlphaSetupBlendTest(curvb);					// Unavoidable
+
+	// needs to be before RenderAlphaTest
+	AlphaRenderFBA(curvb, pfragment, s_bDestAlphaTest, bCanRenderStencil);
+
+	dwUsingSpecialTesting =	AlphaRenderAlpha(curvb, curtest, pfragment, exactcolor);			// Unavoidable
+	AlphaRenderStencil(curvb, s_bDestAlphaTest, bCanRenderStencil, dwUsingSpecialTesting);
+	AlphaTest(curvb);								// Unavoidable
+	AlphaPabe(curvb, pfragment, exactcolor);
+	AlphaFailureTestJob(curvb, curtest, pfragment, exactcolor, bCanRenderStencil, oldabe);
+	AlphaSpecialTesting(curvb, pfragment, dwUsingSpecialTesting, exactcolor);
+	AlphaDestinationTest(curvb, pfragment, s_bDestAlphaTest, bCanRenderStencil);
+	AlphaSaveTarget(curvb);
+	
+	GL_REPORT_ERRORD();
+
+	AlphaColorClamping(curvb, curtest);
+	FlushUndoFiter(dwFilterOpts);
+
+	ppf += curvb.nCount + 0x100000;
+
+	curvb.nCount = 0;
+	curvb.curprim.abe = oldabe;
+
+	SwitchWireframeOn();
+
+	GL_REPORT_ERRORD();
+}
+
+void ZeroGS::FlushBoth()
+{
+	Flush(0);
+	Flush(1);
+}
+
+inline void ZeroGS::RenderFBA(const VB& curvb, ZZshParameter sOneColor)
+{
+	// add fba to all pixels
+	GL_STENCILFUNC(GL_ALWAYS, STENCIL_FBA, 0xff);
+	glStencilMask(STENCIL_CLEAR);
+	glStencilOp(GL_ZERO, GL_KEEP, GL_REPLACE);
+
+	glDisable(GL_DEPTH_TEST);
+	glDepthMask(0);
+	glColorMask(0, 0, 0, 0);
+
+	if (s_bWriteDepth) ResetRenderTarget(1);
+
+	SetShaderCaller("RenderFBA");
+
+	glEnable(GL_ALPHA_TEST);
+
+	glAlphaFunc(GL_GEQUAL, 1);
+
+	Vector v(1,2,0,0);
+
+	ZZshSetParameter4fv(sOneColor, v, "g_fOneColor");
+
+	Draw(curvb);
+
+	SetAlphaTest(curvb.test);
+
+	// reset (not necessary)
+	GL_COLORMASK(s_dwColorWrite);
+
+	glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
+
+	if (!curvb.zbuf.zmsk)
+	{
+		glDepthMask(1);
+
+		assert(curvb.pdepth != NULL);
+
+		if (s_bWriteDepth) curvb.pdepth->SetRenderTarget(1);
+	}
+
+	GL_ZTEST(curvb.test.zte);
+}
+
+__forceinline void ZeroGS::RenderAlphaTest(const VB& curvb, ZZshParameter sOneColor)
+{
+	if (!g_bUpdateStencil) return;
+
+	if ((curvb.test.ate) && (curvb.test.afail == 1)) glDisable(GL_ALPHA_TEST);
+
+	glDepthMask(0);
+
+	glColorMask(0, 0, 0, 0);
+
+	if (s_bWriteDepth) ResetRenderTarget(1);
+
+	SetShaderCaller("RenderAlphaTest");
+
+	Vector v(1,2,0,0);
+
+	ZZshSetParameter4fv(sOneColor, v, "g_fOneColor");
+
+	// or a 1 to the stencil buffer wherever alpha passes
+	glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
+
+	s_stencilfunc = GL_ALWAYS;
+
+	glEnable(GL_STENCIL_TEST);
+
+	if (!s_bDestAlphaTest)
+	{
+		// clear everything
+		s_stencilref = 0;
+		glStencilMask(STENCIL_CLEAR);
+		glDisable(GL_ALPHA_TEST);
+		GL_STENCILFUNC_SET();
+		Draw(curvb);
+
+		if (curvb.test.ate && curvb.test.afail != 1 && USEALPHATESTING) glEnable(GL_ALPHA_TEST);
+	}
+
+	if (curvb.test.ate && curvb.test.atst > 1 && curvb.test.aref > 0x80)
+	{
+		v = Vector(1,1,0,0);
+		ZZshSetParameter4fv(sOneColor, v, "g_fOneColor");
+		glAlphaFunc(g_dwAlphaCmp[curvb.test.atst], AlphaReferedValue(curvb.test.aref));
+	}
+
+	s_stencilref = STENCIL_SPECIAL;
+
+	glStencilMask(STENCIL_SPECIAL);
+	GL_STENCILFUNC_SET();
+	glDisable(GL_DEPTH_TEST);
+
+	Draw(curvb);
+
+	if (curvb.test.zte) glEnable(GL_DEPTH_TEST);
+
+	GL_ALPHATEST(0);
+
+	GL_COLORMASK(s_dwColorWrite);
+
+	if (!curvb.zbuf.zmsk)
+	{
+		glDepthMask(1);
+
+		// set rt next level
+
+		if (s_bWriteDepth) curvb.pdepth->SetRenderTarget(1);
+	}
+}
+
+inline void ZeroGS::RenderStencil(const VB& curvb, u32 dwUsingSpecialTesting)
+{
+	//NOTE: This stencil hack for dest alpha testing ONLY works when
+	// the geometry in one DrawPrimitive call does not overlap
+
+	// mark the stencil buffer for the new data's bits (mark 4 if alpha is >= 0xff)
+	// mark 4 if a pixel was written (so that the stencil buf can be changed with new values)
+	glStencilMask(STENCIL_PIXELWRITE);
+	glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
+
+	s_stencilmask = (curvb.test.date ? STENCIL_ALPHABIT : 0) | (dwUsingSpecialTesting ? STENCIL_SPECIAL : 0);
+	s_stencilfunc = s_stencilmask ? GL_EQUAL : GL_ALWAYS;
+
+	s_stencilref = curvb.test.date * curvb.test.datm | STENCIL_PIXELWRITE | (dwUsingSpecialTesting ? STENCIL_SPECIAL : 0);
+	GL_STENCILFUNC_SET();
+}
+
+inline void ZeroGS::ProcessStencil(const VB& curvb)
+{
+	assert(!curvb.fba.fba);
+
+	// set new alpha bit
+	glStencilMask(STENCIL_ALPHABIT);
+	GL_STENCILFUNC(GL_EQUAL, STENCIL_PIXELWRITE, STENCIL_PIXELWRITE | STENCIL_FBA);
+	glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
+
+	glDisable(GL_DEPTH_TEST);
+	glDepthMask(0);
+	glColorMask(0, 0, 0, 0);
+
+	if (s_bWriteDepth) ResetRenderTarget(1);
+
+	GL_ALPHATEST(0);
+
+	SetShaderCaller("ProcessStencil");
+
+	ZZshSetPixelShader(ppsOne.prog);
+	Draw(curvb);
+
+	// process when alpha >= 0xff
+	GL_STENCILFUNC(GL_EQUAL, STENCIL_PIXELWRITE | STENCIL_FBA | STENCIL_ALPHABIT, STENCIL_PIXELWRITE | STENCIL_FBA);
+	Draw(curvb);
+
+	// clear STENCIL_PIXELWRITE bit
+	glStencilMask(STENCIL_CLEAR);
+
+	GL_STENCILFUNC(GL_ALWAYS, 0, STENCIL_PIXELWRITE | STENCIL_FBA);
+	Draw(curvb);
+
+	// restore state
+	GL_COLORMASK(s_dwColorWrite);
+
+	if (curvb.test.ate && USEALPHATESTING) glEnable(GL_ALPHA_TEST);
+
+	if (!curvb.zbuf.zmsk)
+	{
+		glDepthMask(1);
+
+		if (s_bWriteDepth)
+		{
+			assert(curvb.pdepth != NULL);
+			curvb.pdepth->SetRenderTarget(1);
+		}
+	}
+
+	GL_ZTEST(curvb.test.zte);
+
+	glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
+}
+
+__forceinline void ZeroGS::ProcessFBA(const VB& curvb, ZZshParameter sOneColor)
+{
+	if ((curvb.frame.fbm&0x80000000)) return;
+
+	// add fba to all pixels that were written and alpha was less than 0xff
+	glStencilMask(STENCIL_ALPHABIT);
+	glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
+	GL_STENCILFUNC(GL_EQUAL, STENCIL_FBA | STENCIL_PIXELWRITE | STENCIL_ALPHABIT, STENCIL_PIXELWRITE | STENCIL_FBA);
+	glDisable(GL_DEPTH_TEST);
+
+	glDepthMask(0);
+	glColorMask(0, 0, 0, 1);
+
+	if (s_bWriteDepth) ResetRenderTarget(1);
+
+	SetShaderCaller("ProcessFBA");
+
+	// processes the pixels with ALPHA < 0x80*2
+	glEnable(GL_ALPHA_TEST);
+	glAlphaFunc(GL_LEQUAL, 1);
+
+	// add 1 to dest
+	GL_BLEND_ALPHA(GL_ONE, GL_ONE);
+	GL_BLENDEQ_ALPHA(GL_FUNC_ADD);
+
+	float f = 1;
+	ZZshSetParameter4fv(sOneColor, &f, "g_fOneColor");
+	ZZshSetPixelShader(ppsOne.prog);
+	Draw(curvb);
+	glDisable(GL_ALPHA_TEST);
+
+	// reset bits
+	glStencilMask(STENCIL_CLEAR);
+	GL_STENCILFUNC(GL_GREATER, 0, STENCIL_PIXELWRITE | STENCIL_FBA);
+	glStencilOp(GL_KEEP, GL_KEEP, GL_ZERO);
+	Draw(curvb);
+
+	if (curvb.test.atst && USEALPHATESTING)
+	{
+		glEnable(GL_ALPHA_TEST);
+		glAlphaFunc(g_dwAlphaCmp[curvb.test.atst], AlphaReferedValue(curvb.test.aref));
+	}
+
+	// restore (SetAlphaVariables)
+	GL_BLEND_ALPHA(GL_ONE, GL_ZERO);
+
+	if (vAlphaBlendColor.y < 0) GL_BLENDEQ_ALPHA(GL_FUNC_REVERSE_SUBTRACT);
+
+	// reset (not necessary)
+	GL_COLORMASK(s_dwColorWrite);
+
+	if (!curvb.zbuf.zmsk)
+	{
+		glDepthMask(1);
+
+		if (s_bWriteDepth) curvb.pdepth->SetRenderTarget(1);
+	}
+
+	GL_ZTEST(curvb.test.zte);
+}
+
+void ZeroGS::SetContextTarget(int context)
+{
+	FUNCLOG
+	VB& curvb = vb[context];
+	GL_REPORT_ERRORD();
+
+	if (curvb.prndr == NULL)
+		curvb.prndr = s_RTs.GetTarg(curvb.frame, 0, get_maxheight(curvb.gsfb.fbp, curvb.gsfb.fbw, curvb.gsfb.psm));
+
+	// make sure targets are valid
+	if (curvb.pdepth == NULL)
+	{
+		frameInfo f;
+		f.fbp = curvb.zbuf.zbp;
+		f.fbw = curvb.frame.fbw;
+		f.fbh = curvb.prndr->fbh;
+		f.psm = curvb.zbuf.psm;
+		f.fbm = 0;
+		curvb.pdepth = (CDepthTarget*)s_DepthRTs.GetTarg(f, CRenderTargetMngr::TO_DepthBuffer | CRenderTargetMngr::TO_StrictHeight |
+					   (curvb.zbuf.zmsk ? CRenderTargetMngr::TO_Virtual : 0), get_maxheight(curvb.zbuf.zbp, curvb.gsfb.fbw, 0));
+	}
+
+	assert(curvb.prndr != NULL && curvb.pdepth != NULL);
+
+	if (curvb.pdepth->fbh != curvb.prndr->fbh) ZZLog::Debug_Log("(curvb.pdepth->fbh(0x%x) != curvb.prndr->fbh(0x%x))", curvb.pdepth->fbh, curvb.prndr->fbh);
+	//assert(curvb.pdepth->fbh == curvb.prndr->fbh);
+
+	if (curvb.pdepth->status & CRenderTarget::TS_Virtual)
+	{
+
+		if (!curvb.zbuf.zmsk)
+		{
+			CRenderTarget* ptemp = s_DepthRTs.Promote(curvb.pdepth->fbp | (curvb.pdepth->fbw << 16));
+			assert(ptemp == curvb.pdepth);
+		}
+		else
+		{
+			curvb.pdepth->status &= ~CRenderTarget::TS_NeedUpdate;
+		}
+	}
+
+	bool bSetTarg = 1;
+
+	if (curvb.pdepth->status & CRenderTarget::TS_NeedUpdate)
+	{
+		assert(!(curvb.pdepth->status & CRenderTarget::TS_Virtual));
+
+		// don't update if virtual
+		curvb.pdepth->Update(context, curvb.prndr);
+		bSetTarg = 0;
+	}
+
+	GL_REPORT_ERRORD();
+
+	if (curvb.prndr->status & CRenderTarget::TS_NeedUpdate)
+	{
+		/*		if(bSetTarg) {
+		*			printf ( " Here\n ");
+		*			if(s_bWriteDepth) {
+		*				curvb.pdepth->SetRenderTarget(1);
+		*				curvb.pdepth->SetDepthStencilSurface();
+		*			}
+		*			else
+		*				curvb.pdepth->SetDepthStencilSurface();
+		*		}*/
+		curvb.prndr->Update(context, curvb.pdepth);
+	}
+	else
+	{
+
+		//if( (vb[0].prndr != vb[1].prndr && vb[!context].bVarsSetTarg) || !vb[context].bVarsSetTarg )
+		curvb.prndr->SetRenderTarget(0);
+		//if( bSetTarg && ((vb[0].pdepth != vb[1].pdepth && vb[!context].bVarsSetTarg) || !vb[context].bVarsSetTarg) )
+		curvb.pdepth->SetDepthStencilSurface();
+
+		if (conf.mrtdepth && ZeroGS::IsWriteDepth()) curvb.pdepth->SetRenderTarget(1);
+		if (s_ptexCurSet[0] == curvb.prndr->ptex) s_ptexCurSet[0] = 0;
+		if (s_ptexCurSet[1] == curvb.prndr->ptex) s_ptexCurSet[1] = 0;
+
+		curvb.prndr->SetViewport();
+	}
+
+	curvb.prndr->SetTarget(curvb.frame.fbp, curvb.scissor, context);
+
+	if ((curvb.zbuf.zbp - curvb.pdepth->fbp) != (curvb.frame.fbp - curvb.prndr->fbp) && curvb.test.zte)
+		ZZLog::Warn_Log("Frame and zbuf not aligned.");
+
+	curvb.bVarsSetTarg = true;
+
+	if (vb[!context].prndr != curvb.prndr) vb[!context].bVarsSetTarg = false;
+
+#ifdef _DEBUG
+	// These conditions happen often enough that we'll just warn about it rather then abort in Debug mode.
+	if (curvb.prndr->status & CRenderTarget::TS_NeedUpdate) 
+	{
+		ZZLog::Debug_Log("In SetContextTarget, prndr is ending with TS_NeedUpdate set.");
+	}
+	
+	if (curvb.pdepth != NULL && (curvb.pdepth->status & CRenderTarget::TS_NeedUpdate))
+	{
+		ZZLog::Debug_Log("In SetContextTarget, pdepth is ending with TS_NeedUpdate set.");
+	}
+#endif
+
+	GL_REPORT_ERRORD();
+}
+
+
+void ZeroGS::SetTexInt(int context, FRAGMENTSHADER* pfragment, int settexint)
+{
+	FUNCLOG
+
+	if (settexint)
+	{
+		tex0Info& tex0 = vb[context].tex0;
+
+		CMemoryTarget* pmemtarg = g_MemTargs.GetMemoryTarget(tex0, 1);
+
+		if (vb[context].bVarsTexSync)
+		{
+			if (vb[context].pmemtarg != pmemtarg)
+			{
+				SetTexVariablesInt(context, GetTexFilter(vb[context].tex1), tex0, true, pfragment, s_bForceTexFlush);
+				vb[context].bVarsTexSync = true;
+			}
+		}
+		else
+		{
+			SetTexVariablesInt(context, GetTexFilter(vb[context].tex1), tex0, false, pfragment, s_bForceTexFlush);
+			vb[context].bVarsTexSync = true;
+
+			INC_TEXVARS();
+		}
+	}
+	else
+	{
+		vb[context].bVarsTexSync = false;
+	}
+}
+
+// clamp relies on texture width
+void ZeroGS::SetTexClamping(int context, FRAGMENTSHADER* pfragment)
+{
+	FUNCLOG
+	SetShaderCaller("SetTexClamping");
+	clampInfo* pclamp = &ZeroGS::vb[context].clamp;
+	Vector v, v2;
+	v.x = v.y = 0;
+	u32* ptex = ZeroGS::vb[context].ptexClamp;
+	ptex[0] = ptex[1] = 0;
+
+	float fw = ZeroGS::vb[context].tex0.tw ;
+	float fh = ZeroGS::vb[context].tex0.th ;
+
+	switch (pclamp->wms)
+	{
+		case 0:
+			v2.x = -1e10;
+			v2.z = 1e10;
+			break;
+
+		case 1: // pclamp
+			// suikoden5 movie text
+			v2.x = 0;
+			v2.z = 1 - 0.5f / fw;
+			break;
+
+		case 2: // reg pclamp
+			v2.x = (pclamp->minu + 0.5f) / fw;
+			v2.z = (pclamp->maxu - 0.5f) / fw;
+			break;
+
+		case 3: // region rep x
+			v.x = 0.9999f;
+			v.z = (float)fw;
+			v2.x = (float)GPU_TEXMASKWIDTH / fw;
+			v2.z = pclamp->maxu / fw;
+			int correctMinu = pclamp->minu & (~pclamp->maxu);		// (A && B) || C == (A && (B && !C)) + C
+
+			if (correctMinu != g_PrevBitwiseTexX)
+			{
+				g_PrevBitwiseTexX = correctMinu;
+				ptex[0] = ZeroGS::s_BitwiseTextures.GetTex(correctMinu, 0);
+			}
+
+			break;
+	}
+
+	switch (pclamp->wmt)
+	{
+
+		case 0:
+			v2.y = -1e10;
+			v2.w = 1e10;
+			break;
+
+		case 1: // pclamp
+			// suikoden5 movie text
+			v2.y = 0;
+			v2.w = 1 - 0.5f / fh;
+			break;
+
+		case 2: // reg pclamp
+			v2.y = (pclamp->minv + 0.5f) / fh;
+			v2.w = (pclamp->maxv - 0.5f) / fh;
+			break;
+
+		case 3: // region rep y
+			v.y = 0.9999f;
+			v.w = (float)fh;
+			v2.y = (float)GPU_TEXMASKWIDTH / fh;
+			v2.w = pclamp->maxv / fh;
+			int correctMinv = pclamp->minv & (~pclamp->maxv);		// (A && B) || C == (A && (B && !C)) + C
+
+			if (correctMinv != g_PrevBitwiseTexY)
+			{
+				g_PrevBitwiseTexY = correctMinv;
+				ptex[1] = ZeroGS::s_BitwiseTextures.GetTex(correctMinv, ptex[0]);
+			}
+			break;
+	}
+
+	if (pfragment->fTexWrapMode != 0)
+		ZZshSetParameter4fv(pfragment->fTexWrapMode, v, "g_fTexWrapMode");
+
+	if (pfragment->fClampExts != 0)
+		ZZshSetParameter4fv(pfragment->fClampExts, v2, "g_fClampExts");
+
+
+}
+
+// Fixme should be in Vector lib
+inline bool equal_vectors(Vector a, Vector b)
+{
+	if (abs(a.x - b.x) + abs(a.y - b.y) + abs(a.z - b.z) + abs(a.w - b.w) < 0.01)
+		return true;
+	else
+		return false;
+}
+
+int CheckTexArray[4][2][2][2] = {{{{0, }}}};
+void ZeroGS::SetTexVariables(int context, FRAGMENTSHADER* pfragment)
+{
+	FUNCLOG
+
+	if (!vb[context].curprim.tme) return;
+
+	assert(!vb[context].bNeedTexCheck);
+
+	Vector v, v2;
+
+	tex0Info& tex0 = vb[context].tex0;
+
+	//float fw = (float)tex0.tw;
+	//float fh = (float)tex0.th;
+
+	if (!vb[context].bTexConstsSync)
+	{
+		SetShaderCaller("SetTexVariables");
+
+		// alpha and texture highlighting
+		Vector valpha, valpha2 ;
+
+		// if clut, use the frame format
+		int psm = PIXEL_STORAGE_FORMAT(tex0);
+
+//		ZZLog::Error_Log( "A %d psm, is-clut %d. cpsm %d | %d %d", psm,  PSMT_ISCLUT(psm), tex0.cpsm,  tex0.tfx, tex0.tcc );
+
+		Vector vblack;
+		vblack.x = vblack.y = vblack.z = vblack.w = 10;
+
+		/* tcc -- Tecture Color Component 0=RGB, 1=RGBA + use Alpha from TEXA reg when not in PSM
+		 * tfx -- Texture Function (0=modulate, 1=decal, 2=hilight, 3=hilight2)
+		 *
+		 * valpha2 =  0 0 2 1     0 0 2 1
+		 *            1 0 0 0     1 1 0 0
+		 *            0 0 2 0     0 1 2 0
+		 *            0 0 2 0     0 1 2 0
+		 *
+		 *              0        1,!nNeed         1, psm=2, 10                1, psm=1
+		 * valpha =   0 0 0 1     0 2 0 0        2ta0  2ta1-2ta0 0 0          2ta0 0 0 0
+		 *            0 0 0 1     0 1 0 0         ta0   ta1-ta0  0 0           ta0 0 0 0
+		 *	      0 0 1 1     0 1 1 1                        1 1           ta0 0 1 1
+		 *	      0 0 1 1     0 1 1 0                        1 0           ta0 0 1 0
+		*/
+
+		valpha2.x = (tex0.tfx == 1) ;
+		valpha2.y = (tex0.tcc == 1) && (tex0.tfx != 0) ;
+		valpha2.z = (tex0.tfx != 1) * 2 ;
+		valpha2.w = (tex0.tfx == 0) ;
+
+		if (tex0.tcc == 0 || !PSMT_ALPHAEXP(psm))
+		{
+			valpha.x = 0 ;
+			valpha.y = (!!tex0.tcc) * (1 + (tex0.tfx == 0)) ;
+		}
+		else
+		{
+			valpha.x = (gs.texa.fta[0])  * (1 + (tex0.tfx == 0)) ;
+			valpha.y = (gs.texa.fta[psm != PSMCT24] - gs.texa.fta[0]) * (1 + (tex0.tfx == 0)) ;
+
+		}
+
+		valpha.z = (tex0.tfx >= 3) ;
+
+		valpha.w = (tex0.tcc == 0) || (tex0.tcc == 1 && tex0.tfx == 2) ;
+
+		if (tex0.tcc && gs.texa.aem && psm == PSMCT24)
+			vblack.w = 0;
+
+		/*
+		// Test, old code.
+				Vector valpha3, valpha4;
+		 		switch(tex0.tfx) {
+					case 0:
+						valpha3.z = 0; valpha3.w = 0;
+						valpha4.x = 0; valpha4.y = 0;
+						valpha4.z = 2; valpha4.w = 1;
+
+						break;
+					case 1:
+						valpha3.z = 0; valpha3.w = 1;
+						valpha4.x = 1; valpha4.y = 0;
+						valpha4.z = 0; valpha4.w = 0;
+
+						break;
+					case 2:
+						valpha3.z = 1; valpha3.w = 1.0f;
+						valpha4.x = 0; valpha4.y = tex0.tcc ? 1.0f : 0.0f;
+						valpha4.z = 2; valpha4.w = 0;
+
+						break;
+
+					case 3:
+						valpha3.z = 1; valpha3.w = tex0.tcc ? 0.0f : 1.0f;
+						valpha4.x = 0; valpha4.y = tex0.tcc ? 1.0f : 0.0f;
+						valpha4.z = 2; valpha4.w = 0;
+
+						break;
+				}
+				if( tex0.tcc ) {
+
+					if( tex0.tfx == 1 ) {
+						//mode.x = 10;
+						valpha3.z = 0; valpha3.w = 0;
+						valpha4.x = 1; valpha4.y = 1;
+						valpha4.z = 0; valpha4.w = 0;
+					}
+
+					if( PSMT_ALPHAEXP(psm) ) {
+
+						if( tex0.tfx == 0 ) {
+							// make sure alpha is mult by two when the output is Cv = Ct*Cf
+							valpha3.x = 2*gs.texa.fta[0];
+							// if 24bit, always choose ta[0]
+							valpha3.y = 2*gs.texa.fta[psm != 1];
+							valpha3.y -= valpha.x;
+						}
+						else {
+							valpha3.x = gs.texa.fta[0];
+							// if 24bit, always choose ta[0]
+							valpha3.y = gs.texa.fta[psm != 1];
+							valpha3.y -= valpha.x;
+						}
+					}
+					else {
+						if( tex0.tfx == 0 ) {
+							valpha3.x = 0;
+							valpha3.y = 2;
+						}
+						else {
+							valpha3.x = 0;
+							valpha3.y = 1;
+						}
+					}
+				}
+				else {
+
+					// reset alpha to color
+					valpha3.x = valpha3.y = 0;
+					valpha3.w = 1;
+				}
+
+				if ( equal_vectors(valpha, valpha3) && equal_vectors(valpha2, valpha4) ) {
+					if (CheckTexArray[tex0.tfx][tex0.tcc][psm!=1][PSMT_ALPHAEXP(psm)] == 0) {
+						printf ( "Good issue %d %d %d %d\n", tex0.tfx,  tex0.tcc, psm, PSMT_ALPHAEXP(psm) );
+						CheckTexArray[tex0.tfx][tex0.tcc][psm!=1][PSMT_ALPHAEXP(psm) ] = 1;
+					}
+				}
+				else if (CheckTexArray[tex0.tfx][tex0.tcc][psm!=1][PSMT_ALPHAEXP(psm)] == -1) {
+					printf ("Bad array, %d %d %d %d\n\tolf valpha %f, %f, %f, %f : valpha2 %f %f %f %f\n\tnew valpha %f, %f, %f, %f : valpha2 %f %f %f %f\n",
+						 tex0.tfx,  tex0.tcc, psm, PSMT_ALPHAEXP(psm),
+					 	valpha3.x, valpha3.y, valpha3.z, valpha3.w, valpha4.x, valpha4.y, valpha4.z, valpha4.w,
+					 	valpha.x, valpha.y, valpha.z, valpha.w,  valpha2.x, valpha2.y, valpha2.z, valpha2.w);
+					CheckTexArray[tex0.tfx][tex0.tcc][psm!=1][PSMT_ALPHAEXP(psm)] = -1 ;
+				}
+
+		// Test;*/
+
+		ZZshSetParameter4fv(pfragment->fTexAlpha, valpha, "g_fTexAlpha");
+		ZZshSetParameter4fv(pfragment->fTexAlpha2, valpha2, "g_fTexAlpha2");
+
+		if (IsAlphaTestExpansion(tex0))
+			ZZshSetParameter4fv(pfragment->fTestBlack, vblack, "g_fTestBlack");
+
+		SetTexClamping(context, pfragment);
+
+		vb[context].bTexConstsSync = true;
+	}
+
+	if (s_bTexFlush)
+	{
+		if (PSMT_ISCLUT(tex0.psm))
+			texClutWrite(context);
+		else
+			s_bTexFlush = false;
+	}
+}
+
+void ZeroGS::SetTexVariablesInt(int context, int bilinear, const tex0Info& tex0, bool CheckVB, FRAGMENTSHADER* pfragment, int force)
+{
+	FUNCLOG
+	Vector v;
+	CMemoryTarget* pmemtarg = g_MemTargs.GetMemoryTarget(tex0, 1);
+
+	assert( pmemtarg != NULL && pfragment != NULL && pmemtarg->ptex != NULL);	
+	if (pmemtarg == NULL || pfragment == NULL || pmemtarg->ptex == NULL)
+	{
+		ZZLog::Error_Log("SetTexVariablesInt error.");
+		return;
+	}
+	
+	if (CheckVB && vb[context].pmemtarg == pmemtarg) return;
+
+	SetShaderCaller("SetTexVariablesInt");
+
+	float fw = (float)tex0.tw;
+	float fh = (float)tex0.th;
+
+	bool bUseBilinear = bilinear > 1 || (bilinear && conf.bilinear);
+
+	if (bUseBilinear)
+	{
+		v.x = (float)fw;
+		v.y = (float)fh;
+		v.z = 1.0f / (float)fw;
+		v.w = 1.0f / (float)fh;
+
+		if (pfragment->fRealTexDims)
+			ZZshSetParameter4fv(pfragment->fRealTexDims, v, "g_fRealTexDims");
+		else
+			ZZshSetParameter4fv(cgGetNamedParameter(pfragment->prog,"g_fRealTexDims"),v, "g_fRealTexDims");	
+	}
+
+	if (m_Blocks[tex0.psm].bpp == 0)
+	{
+		ZZLog::Error_Log("Undefined tex psm 0x%x!", tex0.psm);
+		return;
+	}
+
+	const BLOCK& b = m_Blocks[tex0.psm];
+
+	float fbw = (float)tex0.tbw;
+
+	Vector vTexDims;
+
+	vTexDims.x = b.vTexDims.x * (fw);
+	vTexDims.y = b.vTexDims.y * (fh);
+	vTexDims.z = (float)BLOCK_TEXWIDTH * (0.002f / 64.0f + 0.01f / 128.0f);
+	vTexDims.w = (float)BLOCK_TEXHEIGHT * 0.1f / 512.0f;
+
+	if (bUseBilinear)
+	{
+		vTexDims.x *= 1 / 128.0f;
+		vTexDims.y *= 1 / 512.0f;
+		vTexDims.z *= 1 / 128.0f;
+		vTexDims.w *= 1 / 512.0f;
+	}
+
+	float g_fitexwidth = g_fiGPU_TEXWIDTH / (float)pmemtarg->widthmult;
+
+	//float g_texwidth = GPU_TEXWIDTH*(float)pmemtarg->widthmult;
+
+	float fpage = tex0.tbp0 * (64.0f * g_fitexwidth);// + 0.05f * g_fitexwidth;
+	float fpageint = floorf(fpage);
+	//int starttbp = (int)fpage;
+
+	// 2048 is number of words to span one page
+	//float fblockstride = (2048.0f /(float)(g_texwidth*BLOCK_TEXWIDTH)) * b.vTexDims.x * fbw;
+
+	float fblockstride = (2048.0f / (float)(GPU_TEXWIDTH * (float)pmemtarg->widthmult * BLOCK_TEXWIDTH)) * b.vTexDims.x * fbw;
+
+	assert(fblockstride >= 1.0f);
+
+	v.x = (float)(2048 * g_fitexwidth);
+	v.y = fblockstride;
+	v.z = g_fBlockMult / (float)pmemtarg->widthmult;
+	v.w = fpage - fpageint ;
+
+	if (g_fBlockMult > 1)
+	{
+		// make sure to divide by mult (since the G16R16 texture loses info)
+		v.z *= b.bpp * (1 / 32.0f);
+	}
+
+	ZZshSetParameter4fv(pfragment->fTexDims, vTexDims, "g_fTexDims");
+
+//	ZZshSetParameter4fv(pfragment->fTexBlock, b.vTexBlock, "g_fTexBlock"); // I change it, and it's working. Seems casting from Vector to float[4] is ok.
+	ZZshSetParameter4fv(pfragment->fTexBlock, &b.vTexBlock.x, "g_fTexBlock");
+	ZZshSetParameter4fv(pfragment->fTexOffset, v, "g_fTexOffset");
+
+	// get hardware texture dims
+	//int texheight = (pmemtarg->realheight+pmemtarg->widthmult-1)/pmemtarg->widthmult;
+	int texwidth = GPU_TEXWIDTH * pmemtarg->widthmult * pmemtarg->channels;
+
+	v.y = 1.0f;
+	v.x = (fpageint - (float)pmemtarg->realy / (float)pmemtarg->widthmult + 0.5f);//*v.y;
+	v.z = (float)texwidth;
+
+	/*	if( !(g_nPixelShaderVer & SHADER_ACCURATE) || bUseBilinear ) {
+			if (tex0.psm == PSMT4 )
+				v.w = 0.0f;
+			else
+				v.w = 0.25f;
+			}
+		else
+			v.w = 0.5f;*/
+	v.w = 0.5f;
+
+	ZZshSetParameter4fv(pfragment->fPageOffset, v, "g_fPageOffset");
+
+	if (force)
+		s_ptexCurSet[context] = pmemtarg->ptex->tex;
+	else
+		s_ptexNextSet[context] = pmemtarg->ptex->tex;
+
+	vb[context].pmemtarg = pmemtarg;
+
+	vb[context].bVarsTexSync = false;
+}
+
+#define SET_ALPHA_COLOR_FACTOR(sign) \
+{ \
+	switch(a.c) \
+	{ \
+		case 0: \
+			vAlphaBlendColor.y = (sign) ? 2.0f*255.0f/256.0f : -2.0f*255.0f/256.0f; \
+			s_srcalpha = GL_ONE; \
+			s_alphaeq = (sign) ? GL_FUNC_ADD : GL_FUNC_REVERSE_SUBTRACT; \
+			break; \
+			\
+		case 1: \
+			/* if in 24 bit mode, dest alpha should be one */ \
+			switch(PSMT_BITMODE(vb[icurctx].prndr->psm)) \
+			{ \
+				case 0: \
+					bDestAlphaColor = (a.d!=2)&&((a.a==a.d)||(a.b==a.d)); \
+					break; \
+					\
+				case 1: \
+					/* dest alpha should be one */ \
+					bDestAlphaColor = 2; \
+					break; \
+					/* default: 16bit surface, so returned alpha is ok */ \
+			} \
+		break; \
+		\
+		case 2: \
+			bNeedBlendFactorInAlpha = true; /* should disable alpha channel writing */ \
+			vAlphaBlendColor.y = 0; \
+			vAlphaBlendColor.w = (sign) ? (float)a.fix * (2.0f/255.0f) : (float)a.fix * (-2.0f/255.0f); \
+			usec = 0; /* change so that alpha comes from source*/ \
+		break; \
+	} \
+} \
+ 
+//if( a.fix <= 0x80 ) { \
+// dwTemp = (a.fix*2)>255?255:(a.fix*2); \
+// dwTemp = dwTemp|(dwTemp<<8)|(dwTemp<<16)|0x80000000; \
+// printf("bfactor: %8.8x\n", dwTemp); \
+// glBlendColorEXT(dwTemp); \
+// } \
+// else { \
+
+void ZeroGS::ResetAlphaVariables() {
+	FUNCLOG
+}
+
+inline void ZeroGS::NeedFactor(int w)
+{
+	if (bDestAlphaColor == 2)
+	{
+		bNeedBlendFactorInAlpha = (w + 1) ? true : false;
+		vAlphaBlendColor.y = 0;
+		vAlphaBlendColor.w = (float)w;
+	}
+}
+
+//static int CheckArray[48][2] = {{0,}};
+
+void ZeroGS::SetAlphaVariables(const alphaInfo& a)
+{
+	FUNCLOG
+	bool alphaenable = true;
+
+	// TODO: negative color when not clamping turns to positive???
+	g_vars._bAlphaState = 0; // set all to zero
+	bNeedBlendFactorInAlpha = false;
+	b2XAlphaTest = 1;
+	//u32 dwTemp = 0xffffffff;
+	bDestAlphaColor = 0;
+
+	// default
+	s_srcalpha = GL_ONE;
+	s_dstalpha = GL_ZERO;
+	s_alphaeq = GL_FUNC_ADD;
+	s_rgbeq = 1;
+
+//	s_alphaInfo = a;
+	vAlphaBlendColor = Vector(1, 2 * 255.0f / 256.0f, 0, 0);
+	u32 usec = a.c;
+
+
+	/*
+	 * Alpha table
+	 *           a   +  b   +  d
+	 *           	    S          		   D
+	 *     0     a     -a      1    |   0      0      0
+	 *     1     0      0      0    |   a     -a      1
+	 *     2     0      0      0    |   0      0      0
+	 *
+	 *							d = 0 Cs
+	 *   a   b   	0 Cs	   				   1 Cd        		2 0
+	 *   			   	              | 			 	       |
+	 * 0 000:  a+-a+ 1 | 0+ 0+ 0 = 	    1         | 010: a+ 0+ 1 | 0+-a+ 0 = 1-(-a)(+)(-a) | 020: a+ 0+ 1 | 0+ 0+ 0 = 1-(-a) (+)  0
+	 * 1 100:  0+-a+ 1 | a+ 0+ 0 = 1-a (+) a      | 110: 0+ 0+ 1 | a+-a+ 0 =        1      | 120: 0+ 0+ 1 | a+ 0+ 0 = 1      (+)  a
+	 * 2 200:  0+-a+ 1 | 0+ 0+ 0 = 1-a (+) 0      | 210: 0+ 0+ 1 | 0+-a+ 0 = 1     (-)  a  | 220: 0+ 0+ 1 | 0+ 0+ 0 =         1
+	 *
+	 *							d = 1 Cd
+	 *		0		              |	1				       | 		2
+	 * 0 001:  a+-a+ 0 | 0+ 0+ 1 = 0   (+) 1      | 011: a+ 0+ 0 | 0+-a+ 1 = a     (+) 1-a | 021: a+ 0+ 0 | 0+ 0+ 1 = a      (+)  1
+	 * 1 101:  0+-a+ 0 | a+ 0+ 1 = (-a)(+) 1-(-a) | 111: 0+ 0+ 0 | a+-a+ 1 = 0     (+) 1   | 121: 0+ 0+ 0 | a+ 0+ 1 = 0      (+)  1-(-a)
+	 * 2 201:  0+-a+ 0 | 0+ 0+ 1 = a   (R-)1      | 211: 0+ 0+ 0 | 0+-a+ 1 = 0     (+) 1-a | 221: 0+ 0+ 0 | 0+ 0+ 1 = 0	 (+)  1
+	 *
+	 *							d = 2 0
+	 *		0			      |			1		       |		2
+	 * 0 002:  a+-a+ 0 | 0+ 0+ 0 =      0         | 012: a+ 0+ 0 | 0+-a+ 0 = a     (-) a   | 022: a+ 0+ 0 | 0+ 0+ 0 = a      (+)  0
+	 * 1 102:  0+-a+ 0 | a+ 0+ 0 = a  (R-) a      | 112: 0+ 0+ 0 | a+-a+ 0 =        0      | 122: 0+ 0+ 0 | a+ 0+ 0 = 0      (+)  a
+	 * 2 202:  0+-a+ 0 | 0+ 0+ 0 = a  (R-) 0      | 212: 0+ 0+ 0 | 0+-a+ 0 = 0     (-) a   | 222: 0+ 0+ 0 | 0+ 0+ 0 =         0
+	 *
+	 *  Formulae is: (a-b) * (c /32) + d
+	 *  		0	1	2
+	 *  a		Cs	Cd	0
+	 *  b		Cs	Cd	0
+	 *  c		As	Ad	ALPHA.FIX
+	 *  d		Cs	Cd	0
+	 *
+	 *  We want to emulate Cs * F1(alpha)  + Cd * F2(alpha)  by  OpenGl blending: (Cs * Ss (+,-,R-) Cd * Sd)
+	 *  SET_ALPHA_COLOR_FACTOR(sign) set Set A (as As>>7, Ad>>7 or FIX>>7) with sign.
+	 *  So we could use 1+a as one_minus_alpha and -a as alpha.
+	 *
+	 */
+	int code = (a.a * 16) + (a.b * 4) + a.d ;
+
+#define one_minus_alpha  (bDestAlphaColor == 2) ? GL_ONE_MINUS_SRC_ALPHA : blendinvalpha[usec]
+#define alpha   	 (bDestAlphaColor == 2) ? GL_SRC_ALPHA : blendalpha[usec]
+#define one 		 (bDestAlphaColor == 2) ? GL_ONE : blendalpha[usec]
+#define	zero 		 (bDestAlphaColor == 2) ? GL_ZERO : blendinvalpha[usec]
+
+	switch (code)
+	{
+
+		case 0: // 000				// Cs -- nothing changed
+		case 20: // 110 = 16+4=20		// Cs
+		case 40:   // 220 = 32+8=40		// Cs
+		{
+			alphaenable = false;
+			break;
+		}
+
+		case 2: //002				// 0  -- should be zero
+		case 22: //112				// 0
+		case 42:   //222 = 32+8+2 =42		// 0
+		{
+			s_rgbeq = GL_FUNC_ADD;
+			s_srcrgb = GL_ZERO;
+			s_dstrgb = GL_ZERO;
+			break;
+		}
+
+		case 1: //001				 // Cd  -- Should be destination alpha
+		case 21: //111, 			 // Cd  -- 0*Source + 1*Desrinarion
+		case 41:   //221 = 32+8+1=41		 // Cd  --
+		{
+			s_rgbeq = GL_FUNC_ADD;
+			s_srcrgb = GL_ZERO;
+			s_dstrgb = GL_ONE;
+			break;
+		}
+
+		case 4:    // 010			 // (Cs-Cd)*A+Cs = Cs * (A + 1) - Cd * A
+		{
+			bAlphaClamping = 3;
+			SET_ALPHA_COLOR_FACTOR(0);	 // a = -A
+
+			s_rgbeq = GL_FUNC_ADD;		 // Cs*(1-a)+Cd*a
+			s_srcrgb = one_minus_alpha ;
+			s_dstrgb = alpha;
+
+			NeedFactor(-1);
+			break;
+		}
+
+		case 5:   // 011			// (Cs-Cd)*A+Cs = Cs * A + Cd * (1-A)
+		{
+			bAlphaClamping = 3; // all testing
+			SET_ALPHA_COLOR_FACTOR(1);
+
+			s_rgbeq = GL_FUNC_ADD;
+			s_srcrgb = alpha;
+			s_dstrgb = one_minus_alpha;
+
+			NeedFactor(1);
+			break;
+		}
+
+		case 6:   //012				// (Cs-Cd)*FIX
+		{
+			bAlphaClamping = 3;
+			SET_ALPHA_COLOR_FACTOR(1);
+
+			s_rgbeq = GL_FUNC_SUBTRACT;
+			s_srcrgb = alpha;
+			s_dstrgb = alpha;
+
+			break;
+		}
+
+		case 8:   //020				// Cs*A+Cs = Cs * (1+A)
+		{
+			bAlphaClamping = 2; // max testing
+			SET_ALPHA_COLOR_FACTOR(0);	// Zeyflitz change this! a = -A
+				
+			s_rgbeq = GL_FUNC_ADD;
+			s_srcrgb = one_minus_alpha;	// Cs*(1-a).
+			s_dstrgb = GL_ZERO;
+
+//			NeedFactor(1);
+			break;
+		}
+
+		case 9:   //021				// Cs*A+Cd
+		{
+			bAlphaClamping = 2; // max testing
+			SET_ALPHA_COLOR_FACTOR(1);
+				
+			s_rgbeq = GL_FUNC_ADD;
+			s_srcrgb = alpha;			// ZZ change it to.
+			s_dstrgb = GL_ONE;
+			break;
+		}
+
+		case 10:   //022			// Cs*A
+		{
+			bAlphaClamping = 2; // max testing
+			SET_ALPHA_COLOR_FACTOR(1);
+
+			s_rgbeq = GL_FUNC_ADD;
+			s_srcrgb = alpha;
+			s_dstrgb = GL_ZERO;
+			break;
+		}
+
+		case 16:   //100
+		{
+			bAlphaClamping = 3;
+			SET_ALPHA_COLOR_FACTOR(1);
+
+			s_rgbeq = GL_FUNC_ADD;
+			s_srcrgb = one_minus_alpha;
+			s_dstrgb = alpha;
+
+			NeedFactor(1);
+			break;
+		}
+
+		case 17:   //101
+		{
+			bAlphaClamping = 3; // all testing
+			SET_ALPHA_COLOR_FACTOR(0);
+
+			s_rgbeq = GL_FUNC_ADD;
+			s_srcrgb = alpha;
+			s_dstrgb = one_minus_alpha;
+
+			NeedFactor(-1);
+			break;
+		}
+
+		case 18:   //102
+		{
+			bAlphaClamping = 3;
+			SET_ALPHA_COLOR_FACTOR(1);
+
+			s_rgbeq = GL_FUNC_REVERSE_SUBTRACT;
+			s_srcrgb = alpha;
+			s_dstrgb = alpha;
+
+			break;
+		}
+
+		case 24:   //120 = 16+8
+		{
+			bAlphaClamping = 2; // max testing
+			SET_ALPHA_COLOR_FACTOR(1);
+				
+			s_rgbeq = GL_FUNC_ADD;
+			s_srcrgb = GL_ONE;
+			s_dstrgb = alpha;
+			break;
+		}
+
+		case 25:   //121				// Cd*(1+A)
+		{
+			bAlphaClamping = 2; // max testing
+			SET_ALPHA_COLOR_FACTOR(0);
+
+			s_rgbeq = GL_FUNC_ADD;
+			s_srcrgb = GL_ZERO;
+			s_dstrgb = one_minus_alpha;
+
+//			 NeedFactor(-1);
+			break;
+		}
+
+		case 26:   //122
+		{
+			bAlphaClamping = 2;
+			SET_ALPHA_COLOR_FACTOR(1);
+
+			s_rgbeq = GL_FUNC_ADD;
+			s_srcrgb = GL_ZERO;
+			s_dstrgb = alpha;
+			break;
+		}
+
+		case 32:  // 200 = 32
+		{
+			bAlphaClamping = 1; // min testing
+			SET_ALPHA_COLOR_FACTOR(1);
+
+			s_rgbeq = GL_FUNC_ADD;
+			s_srcrgb = one_minus_alpha;
+			s_dstrgb = GL_ZERO;
+			break;
+		}
+
+		case 33:  //201					// -Cs*A + Cd
+		{
+			bAlphaClamping = 1; // min testing
+			SET_ALPHA_COLOR_FACTOR(1);
+
+			s_rgbeq = GL_FUNC_REVERSE_SUBTRACT;
+			s_srcrgb = alpha;
+			s_dstrgb = GL_ONE;
+			break;
+		}
+
+		case 34:  //202
+		case 38:  //212
+		{
+			bAlphaClamping = 1; // min testing -- negative values
+
+			s_rgbeq = GL_FUNC_ADD;
+			s_srcrgb = GL_ZERO;
+			s_dstrgb = GL_ZERO;
+			break;
+		}
+
+		case 36:  //210
+		{
+			bAlphaClamping = 1; // min testing
+			SET_ALPHA_COLOR_FACTOR(1);
+
+			s_rgbeq = GL_FUNC_SUBTRACT;
+			s_srcrgb = GL_ONE;
+			s_dstrgb = alpha;
+			break;
+		}
+
+		case 37:  //211
+		{
+			bAlphaClamping = 1; // min testing
+			SET_ALPHA_COLOR_FACTOR(1);
+
+			s_rgbeq = GL_FUNC_ADD;
+			s_srcrgb = GL_ZERO;
+			s_dstrgb = one_minus_alpha;
+			break;
+		}
+
+		default:
+		{
+			ZZLog::Error_Log("Bad alpha code %d | %d %d %d", code, a.a, a.b, a.d);
+		}
+	}
+
+	/*
+		int t_rgbeq = GL_FUNC_ADD;
+		int t_srcrgb = GL_ONE;
+		int t_dstrgb = GL_ZERO;
+		int tAlphaClamping = 0;
+
+		if( a.a == a.b )
+		{ // just d remains
+			if( a.d == 0 ) 	{}
+			else
+			{
+				t_dstrgb = a.d == 1 ? GL_ONE : GL_ZERO;
+				t_srcrgb = GL_ZERO;
+				t_rgbeq = GL_FUNC_ADD; 			//a) (001) (111) (221) b) (002) (112) (222)
+			}
+			goto EndSetAlpha;
+		}
+		else if( a.d == 2 )
+		{ // zero
+			if( a.a == 2 )
+			{
+				// zero all color
+				t_srcrgb = GL_ZERO;
+				t_dstrgb = GL_ZERO;
+				goto EndSetAlpha;			// (202) (212)
+			}
+			else if( a.b == 2 )
+			{
+				//b2XAlphaTest = 1;		// a) (022)			// b) (122)
+				SET_ALPHA_COLOR_FACTOR(1);
+
+				if( bDestAlphaColor == 2 )
+				{
+					t_rgbeq = GL_FUNC_ADD;
+					t_srcrgb = a.a == 0 ? GL_ONE : GL_ZERO;
+					t_dstrgb = a.a == 0 ? GL_ZERO : GL_ONE;
+				}
+				else
+				{
+					tAlphaClamping = 2;
+					t_rgbeq = GL_FUNC_ADD;
+					t_srcrgb = a.a == 0 ? blendalpha[usec] : GL_ZERO;
+					t_dstrgb = a.a == 0 ? GL_ZERO : blendalpha[usec];
+				}
+
+				goto EndSetAlpha;
+			}
+
+			// nothing is zero, so must do some real blending	//b2XAlphaTest = 1;		//a) (012) 	//b) (102)
+			tAlphaClamping = 3;
+
+			SET_ALPHA_COLOR_FACTOR(1);
+
+			t_rgbeq = a.a == 0 ? GL_FUNC_SUBTRACT : GL_FUNC_REVERSE_SUBTRACT;
+			t_srcrgb = bDestAlphaColor == 2 ? GL_ONE : blendalpha[usec];
+			t_dstrgb = bDestAlphaColor == 2 ? GL_ONE : blendalpha[usec];
+		}
+		else if( a.a == 2 )
+		{ // zero
+
+			//b2XAlphaTest = 1;
+			tAlphaClamping = 1; // min testing
+
+			SET_ALPHA_COLOR_FACTOR(1);
+
+			if( a.b == a.d )
+			{
+				// can get away with 1-A
+				// a.a == a.d == 2!! (200) (211)
+				t_rgbeq = GL_FUNC_ADD;
+				t_srcrgb = (a.b == 0 && bDestAlphaColor != 2) ? blendinvalpha[usec] : GL_ZERO;
+				t_dstrgb = (a.b == 0 || bDestAlphaColor == 2) ? GL_ZERO : blendinvalpha[usec];
+			}
+			else
+			{
+				// a) (201) b)(210)
+				t_rgbeq = a.b==0 ? GL_FUNC_REVERSE_SUBTRACT : GL_FUNC_SUBTRACT;
+				t_srcrgb = (a.b == 0 && bDestAlphaColor != 2) ? blendalpha[usec] : GL_ONE;
+				t_dstrgb = (a.b == 0 || bDestAlphaColor == 2 ) ? GL_ONE : blendalpha[usec];
+			}
+		}
+		else if( a.b == 2 )
+		{
+			tAlphaClamping = 2; // max testing
+
+			SET_ALPHA_COLOR_FACTOR(a.a!=a.d);
+
+			if( a.a == a.d )
+			{
+				// can get away with 1+A, but need to set alpha to negative
+				// a)(020)
+				// b)(121)
+				t_rgbeq = GL_FUNC_ADD;
+
+				if( bDestAlphaColor == 2 )
+				{
+					t_srcrgb = (a.a == 0) ? GL_ONE_MINUS_SRC_ALPHA : GL_ZERO;
+					t_dstrgb = (a.a == 0) ? GL_ZERO : GL_ONE_MINUS_SRC_ALPHA;
+				}
+				else
+				{
+					t_srcrgb = a.a == 0 ? blendinvalpha[usec] : GL_ZERO;
+					t_dstrgb = a.a == 0 ? GL_ZERO : blendinvalpha[usec];
+				}
+			}
+			else
+			{
+				//a)(021) 			//b)(120) 			//b2XAlphaTest = 1;
+				t_rgbeq = GL_FUNC_ADD;
+				t_srcrgb = (a.a == 0 && bDestAlphaColor != 2) ? blendalpha[usec] : GL_ONE;
+				t_dstrgb = (a.a == 0 || bDestAlphaColor == 2) ? GL_ONE : blendalpha[usec];
+			}
+		}
+		else
+		{
+			// all 3 components are valid!
+			tAlphaClamping = 3; // all testing
+			SET_ALPHA_COLOR_FACTOR(a.a!=a.d);
+
+			if( a.a == a.d )
+			{
+				// can get away with 1+A, but need to set alpha to negative		// a) 010,	// b) 101
+				t_rgbeq = GL_FUNC_ADD;
+
+				if( bDestAlphaColor == 2 )
+				{
+					// all ones
+					t_srcrgb = a.a == 0 ? GL_ONE_MINUS_SRC_ALPHA : GL_SRC_ALPHA;
+					t_dstrgb = a.a == 0 ? GL_SRC_ALPHA : GL_ONE_MINUS_SRC_ALPHA;
+				}
+				else
+				{
+					t_srcrgb = a.a == 0 ? blendinvalpha[usec] : blendalpha[usec];
+					t_dstrgb = a.a == 0 ? blendalpha[usec] : blendinvalpha[usec];
+				}
+			}
+			else
+			{
+				t_rgbeq = GL_FUNC_ADD;		// a) 011 		// b) 100 			//
+				if( bDestAlphaColor == 2 )
+				{
+					// all ones
+					t_srcrgb = a.a != 0 ? GL_ONE_MINUS_SRC_ALPHA : GL_SRC_ALPHA;
+					t_dstrgb = a.a != 0 ? GL_SRC_ALPHA : GL_ONE_MINUS_SRC_ALPHA;
+				}
+				else
+				{
+					//b2XAlphaTest = 1;
+					t_srcrgb = a.a != 0 ? blendinvalpha[usec] : blendalpha[usec];
+					t_dstrgb = a.a != 0 ? blendalpha[usec] : blendinvalpha[usec];
+				}
+			}
+		}
+		EndSetAlpha:
+
+
+		if ( alphaenable && (t_rgbeq != s_rgbeq || s_srcrgb != t_srcrgb || t_dstrgb != s_dstrgb || tAlphaClamping != bAlphaClamping)) {
+			if (CheckArray[code][(bDestAlphaColor==2)] != -1) {
+			printf ( "A code %d, 0x%x, 0x%x, 0x%x, 0x%x %d\n", code, alpha, one_minus_alpha, one, zero, bDestAlphaColor );
+			printf ( "       Difference %d %d %d %d | 0x%x  0x%x | 0x%x  0x%x | 0x%x  0x%x | %d %d\n",
+				code, a.a, a.b, a.d,
+				t_rgbeq, s_rgbeq, t_srcrgb, s_srcrgb, t_dstrgb, s_dstrgb, tAlphaClamping, bAlphaClamping);
+			CheckArray[code][(bDestAlphaColor==2)] = -1;
+			}
+		}
+		else
+		if (CheckArray[code][(bDestAlphaColor==2)] == 0){
+			printf ( "Add good code %d %d, psm %d  destA %d\n", code, a.c, vb[icurctx].prndr->psm, bDestAlphaColor);
+			CheckArray[code][(bDestAlphaColor==2)] = 1;
+		}*/
+
+
+	if (alphaenable)
+	{
+		zgsBlendFuncSeparateEXT(s_srcrgb, s_dstrgb, s_srcalpha, s_dstalpha);
+		zgsBlendEquationSeparateEXT(s_rgbeq, s_alphaeq);
+		glEnable(GL_BLEND); // always set
+	}
+	else
+	{
+		glDisable(GL_BLEND);
+	}
+
+	INC_ALPHAVARS();
+}
+
+void ZeroGS::SetWriteDepth()
+{
+	FUNCLOG
+
+	if (conf.mrtdepth)
+	{
+		s_bWriteDepth = true;
+		s_nWriteDepthCount = 4;
+	}
+}
+
+bool ZeroGS::IsWriteDepth()
+{
+	FUNCLOG
+	return s_bWriteDepth;
+}
+
+bool ZeroGS::IsWriteDestAlphaTest()
+{
+	FUNCLOG
+	return s_bDestAlphaTest;
+}
+
+void ZeroGS::SetDestAlphaTest()
+{
+	FUNCLOG
+	s_bDestAlphaTest = true;
+	s_nWriteDestAlphaTest = 4;
+}
+
+void ZeroGS::SetTexFlush()
+{
+	FUNCLOG
+	s_bTexFlush = true;
+
+//	if( PSMT_ISCLUT(vb[0].tex0.psm) )
+//		texClutWrite(0);
+//	if( PSMT_ISCLUT(vb[1].tex0.psm) )
+//		texClutWrite(1);
+
+	if (!s_bForceTexFlush)
+	{
+		if (s_ptexCurSet[0] != s_ptexNextSet[0]) s_ptexCurSet[0] = s_ptexNextSet[0];
+		if (s_ptexCurSet[1] != s_ptexNextSet[1]) s_ptexCurSet[1] = s_ptexNextSet[1];
+	}
+}
+

 

  ViewVC Help
Powered by ViewVC 1.1.22