X-Git-Url: https://notaz.gp2x.de/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=source%2Frice_gles%2Fsrc%2FGeneralCombiner.cpp;fp=source%2Frice_gles%2Fsrc%2FGeneralCombiner.cpp;h=9329bd2b6171e6acc908c76033ced7c9595996c0;hb=d07c171fa694cae985ad7045f9ce2b2f1a5699b4;hp=0000000000000000000000000000000000000000;hpb=ca22e7b76883b946060a6b40bb8709c1981e1cf6;p=mupen64plus-pandora.git diff --git a/source/rice_gles/src/GeneralCombiner.cpp b/source/rice_gles/src/GeneralCombiner.cpp new file mode 100644 index 0000000..9329bd2 --- /dev/null +++ b/source/rice_gles/src/GeneralCombiner.cpp @@ -0,0 +1,1308 @@ +/* +Copyright (C) 2003 Rice1964 + +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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include + +#include "GeneralCombiner.h" +#include "Combiner.h" +#include "Debugger.h" + +extern const int numOf3StageCombiners; +extern const int numOf2StageCombiners; +extern GeneralCombinerInfo CombinerTable2Stages[]; +extern GeneralCombinerInfo CombinerTable3Stages[]; + +CGeneralCombiner::CGeneralCombiner() +{ + m_lastGeneralIndex=0; + m_ppGeneralDecodedMux=NULL; + + m_bTxtOpAdd=true; + m_bTxtOpSub=false; + m_bTxtOpLerp=false; + m_bTxtOpAddSmooth=false; + m_bTxtOpBlendCurAlpha=false; + m_bTxtOpBlendDifAlpha=true; + m_bTxtOpBlendFacAlpha=false; + m_bTxtOpBlendTxtAlpha=true; + m_bTxtOpMulAdd=false; + + m_dwGeneralMaxStages=2; +} + +bool isTex(uint32 val) +{ + return ( (val&MUX_MASK) == MUX_TEXEL0 || (val&MUX_MASK) == MUX_TEXEL1 ); +} +int toTex(uint32 val) +{ + return (val&MUX_MASK)-MUX_TEXEL0; +} + +bool isComb(uint32 val) +{ + return (val&MUX_MASK)==MUX_COMBINED; +} + +#ifdef DEBUGGER +const char* BlendFuncStr[] = { + "Enable both", + "Disable alpha", + "Disable color", + "Disable both", + "Color one", + "Alpha one", +}; +const char* cmopstrs[] = { + "Sel", + "Mod", + "Add", + "Sub", + "Lerp", + "AddSmooth", + "BlCurA", + "BlDifA", + "BlFacA", + "BlTexA", + "MulAdd", +}; + +void CGeneralCombiner::General_DisplayBlendingStageInfo(GeneralCombinerInfo &gci) +{ + char str1[30],str2[30],str3[30]; + DebuggerAppendMsg("\nStages:%d, Alpha:%s, Factor:%s, Specular:%s Dif Color:0x%X Dif Alpha:0x%X\n", + gci.nStages, BlendFuncStr[gci.blendingFunc], DecodedMux::FormatStr((uint8)gci.TFactor,str1), + DecodedMux::FormatStr((uint8)gci.specularPostOp,str2), gci.m_dwShadeColorChannelFlag, gci.m_dwShadeAlphaChannelFlag); + + for( int i=0; im_n64Combiners[curN64Stage]; + StageOperate *op = ((StageOperate*)(&(gci.stages[curStage].colorOp))) + (curN64Stage%2); + if( ( m.d == MUX_0 || m.d == MUX_1 ) && curN64Stage==1 ) + { + //if( m.d == MUX_0 ) + // gci.blendingFunc = DISABLE_COLOR; + //if( m.d == MUX_1 ) + // gci.blendingFunc = DISABLE_ALPHA; + + op->op = CM_REPLACE; + op->Arg1 = MUX_COMBINED; + op->Arg2 = CM_IGNORE; + op->Arg0 = CM_IGNORE; + } + else + { + if( isTex(m.d) ) Check1TxtrForAlpha(curN64Stage, curStage, gci, toTex(m.d)); + op = ((StageOperate*)(&(gci.stages[curStage].colorOp))) + (curN64Stage%2); + + op->op = CM_REPLACE; + op->Arg1 = m.d; + op->Arg2 = CM_IGNORE; + op->Arg0 = CM_IGNORE; + } + + if( !gci.stages[curStage].bTextureUsed ) + gci.stages[curStage].dwTexture = GetTexelNumber(m); + textureUsedInStage[curStage][curN64Stage%2] = IsTxtrUsed(m); + return curStage; +} + +int CGeneralCombiner::GenCI_Type_A_MOD_C(int curN64Stage, int curStage, GeneralCombinerInfo &gci, uint32 dxop) +{ + N64CombinerType &m = (*m_ppGeneralDecodedMux)->m_n64Combiners[curN64Stage]; + StageOperate *op = ((StageOperate*)(&(gci.stages[curStage].colorOp))) + (curN64Stage%2); + + if( CountTexel1Cycle(m) == 2 ) + { + // As we can not use both texture in one stage + // we split them to two stages + // Stage1: SELECT txt1 + // Stage2: MOD txt2 + + if( gci.stages[curStage].bTextureUsed && gci.stages[curStage].dwTexture != (unsigned int)toTex(m.a) ) + swap(m.a,m.c); + + op->op =CM_REPLACE; + op->Arg1 = m.a; + op->Arg2 = CM_IGNORE; + op->Arg0 = CM_IGNORE; + gci.stages[curStage].dwTexture = toTex(m.a); + textureUsedInStage[curStage][curN64Stage%2] = true; + + NextStage(curStage); + Check1TxtrForAlpha(curN64Stage, curStage, gci, toTex(m.c)); + op = ((StageOperate*)(&(gci.stages[curStage].colorOp))) + (curN64Stage%2); + + op->op =dxop; + op->Arg1 = (m.c); + op->Arg2 = MUX_COMBINED; + op->Arg0 = CM_IGNORE; + gci.stages[curStage].dwTexture = toTex(m.c); + textureUsedInStage[curStage][curN64Stage%2] = true; + } + else + { + if( CountTexel1Cycle(m) == 1) + { + Check1TxtrForAlpha(curN64Stage, curStage, gci, GetTexelNumber(m)); + op = ((StageOperate*)(&(gci.stages[curStage].colorOp))) + (curN64Stage%2); + } + + op->op = dxop; + op->Arg1 = (m.a); + op->Arg2 = (m.c); + op->Arg0 = CM_IGNORE; + if( !gci.stages[curStage].bTextureUsed ) + gci.stages[curStage].dwTexture = GetTexelNumber(m); + textureUsedInStage[curStage][curN64Stage%2] = IsTxtrUsed(m); + } + + return curStage; +} +int CGeneralCombiner::GenCI_Type_A_ADD_D(int curN64Stage, int curStage, GeneralCombinerInfo &gci) +{ + uint32 opToUse = m_bTxtOpAdd?CM_ADD:CM_MODULATE; + N64CombinerType &m = (*m_ppGeneralDecodedMux)->m_n64Combiners[curN64Stage]; + swap(m.c, m.d); + curStage = GenCI_Type_A_MOD_C(curN64Stage, curStage, gci, opToUse); + swap(m.c, m.d); + return curStage; +} + +int CGeneralCombiner::GenCI_Type_A_SUB_B(int curN64Stage, int curStage, GeneralCombinerInfo &gci) +{ + N64CombinerType &m = (*m_ppGeneralDecodedMux)->m_n64Combiners[curN64Stage]; + if( !m_bTxtOpSub ) + { + swap(m.c, m.b); + curStage = GenCI_Type_A_MOD_C(curN64Stage, curStage, gci); + swap(m.c, m.b); + return curStage; + } + + StageOperate *op = ((StageOperate*)(&(gci.stages[curStage].colorOp))) + (curN64Stage%2); + + if( CountTexel1Cycle(m) == 2 ) + { + Check1TxtrForAlpha(curN64Stage, curStage, gci, toTex(m.b)); + op = ((StageOperate*)(&(gci.stages[curStage].colorOp))) + (curN64Stage%2); + + op->op =CM_REPLACE; + op->Arg1 = (m.b); + op->Arg2 = CM_IGNORE; + op->Arg0 = CM_IGNORE; + gci.stages[curStage].dwTexture = toTex(m.b); + textureUsedInStage[curStage][curN64Stage%2] = true; + + NextStage(curStage); + Check1TxtrForAlpha(curN64Stage, curStage, gci, toTex(m.a)); + op = ((StageOperate*)(&(gci.stages[curStage].colorOp))) + (curN64Stage%2); + + op->op =CM_SUBTRACT; + op->Arg1 = (m.a); + op->Arg2 = MUX_COMBINED; + op->Arg0 = CM_IGNORE; + gci.stages[curStage].dwTexture = toTex(m.a); + textureUsedInStage[curStage][curN64Stage%2] = true; + } + else + { + if( CountTexel1Cycle(m) == 1) + { + Check1TxtrForAlpha(curN64Stage, curStage, gci, GetTexelNumber(m)); + op = ((StageOperate*)(&(gci.stages[curStage].colorOp))) + (curN64Stage%2); + } + + op->op = CM_SUBTRACT; + op->Arg1 = (m.a); + op->Arg2 = (m.b); + op->Arg0 = CM_IGNORE; + if( !gci.stages[curStage].bTextureUsed ) + gci.stages[curStage].dwTexture = GetTexelNumber(m); + textureUsedInStage[curStage][curN64Stage%2] = IsTxtrUsed(m); + } + return curStage; +} + +int CGeneralCombiner::GenCI_Type_A_MOD_C_ADD_D(int curN64Stage, int curStage, GeneralCombinerInfo &gci) +{ + N64CombinerType &m = (*m_ppGeneralDecodedMux)->m_n64Combiners[curN64Stage]; + StageOperate *op = ((StageOperate*)(&(gci.stages[curStage].colorOp))) + (curN64Stage%2); + + if( !m_bTxtOpMulAdd ) + { + N64CombinerType save = m; + m.d = MUX_0; + curStage = GenCI_Type_A_MOD_C(curN64Stage, curStage, gci); + m = save; + m.c = MUX_0; + m.a = MUX_COMBINED; + NextStage(curStage); + curStage = GenCI_Type_A_ADD_D(curN64Stage, curStage, gci); + m = save; + return curStage; + } + + if( CountTexel1Cycle(m) == 2 ) + { + if( !gci.stages[curStage].bTextureUsed ) + { + gci.stages[curStage].dwTexture = 0; + gci.stages[curStage].bTextureUsed = true; + } + + op->op = CM_REPLACE; + op->Arg2 = CM_IGNORE; + op->Arg0 = CM_IGNORE; + op->Arg1 = MUX_TEXEL0 + gci.stages[curStage].dwTexture ; + + N64CombinerType m2 = m; + + uint8* vals = (uint8*)&m2; + for( int i=0; i<4; i++ ) + { + if( (unsigned int)(vals[i]&MUX_MASK) == MUX_TEXEL0 + gci.stages[curStage].dwTexture ) + { + vals[i] = MUX_COMBINED | (vals[i]&0xe0); + } + } + + NextStage(curStage); + + Check1TxtrForAlpha(curN64Stage, curStage, gci, GetTexelNumber(m2)); + op = ((StageOperate*)(&(gci.stages[curStage].colorOp))) + (curN64Stage%2); + + op->op = CM_MULTIPLYADD; + op->Arg1 = m2.a; + op->Arg2 = m2.c; + op->Arg0 = m2.d; + if( !gci.stages[curStage].bTextureUsed ) + gci.stages[curStage].dwTexture = GetTexelNumber(m2); + textureUsedInStage[curStage][curN64Stage%2] = IsTxtrUsed(m2); + } + else + { + Check1TxtrForAlpha(curN64Stage, curStage, gci, GetTexelNumber(m)); + op = ((StageOperate*)(&(gci.stages[curStage].colorOp))) + (curN64Stage%2); + + op->op = CM_MULTIPLYADD; + op->Arg1 = (m.a); + op->Arg2 = (m.c); + op->Arg0 = (m.d); + if( !gci.stages[curStage].bTextureUsed ) + gci.stages[curStage].dwTexture = GetTexelNumber(m); + textureUsedInStage[curStage][curN64Stage%2] = IsTxtrUsed(m); + } + + return curStage; +} + + +int CGeneralCombiner::GenCI_Type_A_LERP_B_C(int curN64Stage, int curStage, GeneralCombinerInfo &gci) +{ + N64CombinerType &m = (*m_ppGeneralDecodedMux)->m_n64Combiners[curN64Stage]; + StageOperate *op = ((StageOperate*)(&(gci.stages[curStage].colorOp))) + (curN64Stage%2); + + N64CombinerType save = m; + + if( CountTexel1Cycle(m) == 2 ) + { + // There are two textures + int texToUse = CheckWhichTexToUseInThisStage(curN64Stage, curStage, gci); + op->op =CM_REPLACE; + op->Arg1 = (MUX_TEXEL0+texToUse); + op->Arg2 = CM_IGNORE; + op->Arg0 = CM_IGNORE; + gci.stages[curStage].dwTexture = texToUse; + textureUsedInStage[curStage][curN64Stage%2] = true; + + (*m_ppGeneralDecodedMux)->ReplaceVal(MUX_TEXEL0+texToUse, MUX_COMBINED, curN64Stage); + NextStage(curStage); + Check1TxtrForAlpha(curN64Stage, curStage, gci, GetTexelNumber(m)); + op = ((StageOperate*)(&(gci.stages[curStage].colorOp))) + (curN64Stage%2); + } + + // Now we have only 1 texture left + + Check1TxtrForAlpha(curN64Stage, curStage, gci, GetTexelNumber(m)); + op = ((StageOperate*)(&(gci.stages[curStage].colorOp))) + (curN64Stage%2); + + if( m.a == MUX_1 ) + { + op->op = CM_ADDSMOOTH; + op->Arg1 = (m.b); + op->Arg2 = (m.c); + op->Arg0 = CM_IGNORE; + } + else if( m.a == MUX_0 ) + { + op->op = CM_MODULATE; + m.a = 0; + op->Arg1 = (m.b); + op->Arg2 = (m.c^MUX_COMPLEMENT); + op->Arg0 = CM_IGNORE; + } + else + { + if( ((m.c&MUX_ALPHAREPLICATE) || (curN64Stage%2)==1 || m_bTxtOpLerp == false) && ((m.c&MUX_MASK)==MUX_SHADE || (m.c&MUX_MASK)==MUX_COMBINED || (m.c&MUX_MASK)==MUX_TEXEL0 || (m.c&MUX_MASK)==MUX_TEXEL1 ) ) + { + if( curN64Stage == 2 && (m.c&MUX_ALPHAREPLICATE) == 0 ) + { + op->op = CM_MODULATE; + op->Arg1 = m.b; + op->Arg2 = m.c|MUX_COMPLEMENT; + op->Arg0 = CM_IGNORE; + resultIsGood = false; + } + else + { + if( (m.c&MUX_MASK)==MUX_SHADE ) + { + op->op = CM_BLENDDIFFUSEALPHA; + } + else if( (m.c&MUX_MASK) == MUX_COMBINED ) + { + op->op = CM_BLENDCURRENTALPHA; + } + else if( (m.c&MUX_MASK) == MUX_TEXEL0 ) + { + op->op = CM_BLENDTEXTUREALPHA; + } + else if( (m.c&MUX_MASK)==MUX_TEXEL1 ) + { + op->op = CM_BLENDTEXTUREALPHA; + } + else + { + op->op = CM_BLENDDIFFUSEALPHA; + } + op->Arg1 = (m.a); + op->Arg2 = (m.b); + op->Arg0 = m.c|MUX_ALPHAREPLICATE; + } + } + else + { + if( ((m.c&MUX_ALPHAREPLICATE) || (curN64Stage%2)==1 || m_bTxtOpLerp == false) && ((((m.c&MUX_MASK)==MUX_ENV) || ((m.c&MUX_MASK)==MUX_PRIM)) )) + { + op->op = CM_BLENDFACTORALPHA; + op->Arg1 = (m.a); + op->Arg2 = (m.b); + op->Arg0 = m.c|MUX_ALPHAREPLICATE; + } + else + { + op->op = CM_INTERPOLATE; + op->Arg0 = (m.c); + op->Arg1 = (m.a); + op->Arg2 = (m.b); + } + } + } + gci.stages[curStage].dwTexture = GetTexelNumber(m); + textureUsedInStage[curStage][curN64Stage%2] = IsTxtrUsed(m); + + m = save; + return curStage; +} + + +int CGeneralCombiner::GenCI_Type_A_B_C_D(int curN64Stage, int curStage, GeneralCombinerInfo &gci) +{ + N64CombinerType &m = (*m_ppGeneralDecodedMux)->m_n64Combiners[curN64Stage]; + StageOperate *op = ((StageOperate*)(&(gci.stages[curStage].colorOp))) + (curN64Stage%2); + + N64CombinerType save = m; + if( CountTexel1Cycle(m) == 2 ) + { + if( isTex(m.a) && !isTex(m.c) && curN64Stage == 0 && isTex(m.d) && toTex(m.a) != toTex(m.d) ) + { + if( m_dwGeneralMaxStages >= 4 ) + { + op->op = CM_SUBTRACT; + op->Arg1 = m.a; + op->Arg2 = m.b; + op->Arg0 = CM_IGNORE; + gci.stages[curStage].dwTexture = toTex(m.a); + textureUsedInStage[curStage][curN64Stage%2] = true; + NextStage(curStage); + op = ((StageOperate*)(&(gci.stages[curStage].colorOp))) + (curN64Stage%2); + op->op = CM_MULTIPLYADD; + op->Arg1 = MUX_COMBINED; + op->Arg2 = m.c; + op->Arg0 = m.d; + gci.stages[curStage].dwTexture = toTex(m.d); + textureUsedInStage[curStage][curN64Stage%2] = true; + resultIsGood = true; + } + else + { + op->op = CM_MODULATE; + op->Arg1 = m.a; + op->Arg2 = m.c; + op->Arg0 = CM_IGNORE; + gci.stages[curStage].dwTexture = toTex(m.a); + textureUsedInStage[curStage][curN64Stage%2] = true; + NextStage(curStage); + op = ((StageOperate*)(&(gci.stages[curStage].colorOp))) + (curN64Stage%2); + op->op = CM_ADD; + op->Arg1 = MUX_COMBINED; + op->Arg2 = m.d; + op->Arg0 = CM_IGNORE; + gci.stages[curStage].dwTexture = toTex(m.d); + textureUsedInStage[curStage][curN64Stage%2] = true; + resultIsGood = false; + } + } + else + { + // There are two textures + int texToUse = CheckWhichTexToUseInThisStage(curN64Stage, curStage, gci); + op->op =CM_REPLACE; + op->Arg1 = (MUX_TEXEL0+texToUse); + op->Arg2 = CM_IGNORE; + op->Arg0 = CM_IGNORE; + gci.stages[curStage].dwTexture = texToUse; + textureUsedInStage[curStage][curN64Stage%2] = true; + + (*m_ppGeneralDecodedMux)->ReplaceVal(MUX_TEXEL0+texToUse, MUX_COMBINED, curN64Stage); + + NextStage(curStage); + Check1TxtrForAlpha(curN64Stage, curStage, gci, GetTexelNumber(m)); + op = ((StageOperate*)(&(gci.stages[curStage].colorOp))) + (curN64Stage%2); + + m.a = MUX_COMBINED; + m.c = MUX_TEXEL0+(1-texToUse); + m.b = m.d = 0; + curStage = GenCI_Type_A_MOD_C(curN64Stage, curStage, gci); + } + } + else if( CountTexel1Cycle(m) == 1 ) + { + if( m_dwGeneralMaxStages < 4 ) + { + Check1TxtrForAlpha(curN64Stage, curStage, gci, GetTexelNumber(m)); + op->Arg1 = (MUX_TEXEL0+GetTexelNumber(m)); + if( (*m_ppGeneralDecodedMux)->isUsedInCycle(MUX_SHADE, curN64Stage) ) + { + op->op =CM_MODULATE; + op->Arg2 = MUX_SHADE; + } + else + { + op->op =CM_REPLACE; + op->Arg2 = 0; + } + op->Arg0 = CM_IGNORE; + gci.stages[curStage].dwTexture = GetTexelNumber(m); + textureUsedInStage[curStage][curN64Stage%2] = true; + } + else + { + curStage = GenCI_Type_A_SUB_B_MOD_C(curN64Stage, curStage, gci); + m.a = MUX_COMBINED; + NextStage(curStage); + curStage = GenCI_Type_A_ADD_D(curN64Stage, curStage, gci); + } + } + else + { + m.d = 0; + curStage = GenCI_Type_A_SUB_B_MOD_C(curN64Stage, curStage, gci); + m = save; + m.a = MUX_COMBINED; + m.b = m.c = 0; + NextStage(curStage); + curStage = GenCI_Type_A_ADD_D(curN64Stage, curStage, gci); + } + + m = save; + return curStage; +} + +int CGeneralCombiner::GenCI_Type_A_SUB_B_ADD_D(int curN64Stage, int curStage, GeneralCombinerInfo &gci) +{ + N64CombinerType &m = (*m_ppGeneralDecodedMux)->m_n64Combiners[curN64Stage]; + + N64CombinerType save = m; + m.d = MUX_0; + curStage = GenCI_Type_A_SUB_B(curN64Stage, curStage, gci); + m = save; + m.a = MUX_COMBINED; + m.b = MUX_0; + NextStage(curStage); + curStage = GenCI_Type_A_ADD_D(curN64Stage, curStage, gci); + m = save; + + return curStage; +} + + +int CGeneralCombiner::GenCI_Type_A_ADD_B_MOD_C(int curN64Stage, int curStage, GeneralCombinerInfo &gci) +{ + N64CombinerType &m = (*m_ppGeneralDecodedMux)->m_n64Combiners[curN64Stage]; + + N64CombinerType save = m; + m.d = m.b; m.b = 0; + curStage = GenCI_Type_A_ADD_D(curN64Stage, curStage, gci); + m = save; + m.b = MUX_0; + m.a = MUX_COMBINED; + NextStage(curStage); + curStage = GenCI_Type_A_MOD_C(curN64Stage, curStage, gci); + m = save; + + return curStage; +} + +int CGeneralCombiner::GenCI_Type_A_B_C_A(int curN64Stage, int curStage, GeneralCombinerInfo &gci) +{ + // We can not do too much with this type, it is not a bad idea to use LERP to simplify it. + //return GenCI_Type_A_LERP_B_C(curN64Stage, curStage, gci); + return GenCI_Type_A_B_C_D(curN64Stage, curStage, gci); +} + +int CGeneralCombiner::GenCI_Type_A_SUB_B_MOD_C(int curN64Stage, int curStage, GeneralCombinerInfo &gci) +{ + N64CombinerType &m = (*m_ppGeneralDecodedMux)->m_n64Combiners[curN64Stage]; + + N64CombinerType save = m; + m.c = MUX_0; + curStage = GenCI_Type_A_SUB_B(curN64Stage, curStage, gci); + m = save; + m.b = MUX_0; + m.a = MUX_COMBINED; + NextStage(curStage); + curStage = GenCI_Type_A_MOD_C(curN64Stage, curStage, gci); + m = save; + + return curStage; +} + + ///////////////////////////////////// + // End of gci generating functions // + ///////////////////////////////////// + + +void CGeneralCombiner::SkipStage(StageOperate &op, int &curStage) +{ + op.op = CM_REPLACE; + op.Arg1 = MUX_COMBINED; + op.Arg2 = CM_IGNORE; + op.Arg0 = CM_IGNORE; + NextStage(curStage); +} + +void CGeneralCombiner::NextStage(int &curStage) +{ + if( curStage < m_dwGeneralMaxStages-1 ) + { + curStage++; + } + else + { + curStage++; + resultIsGood = false; + TRACE0("Stage overflow"); + } +} + +void CGeneralCombiner::Check1TxtrForAlpha(int curN64Stage, int &curStage, GeneralCombinerInfo &gci, int tex) +{ + N64CombinerType &m = (*m_ppGeneralDecodedMux)->m_n64Combiners[curN64Stage]; + if( curN64Stage%2 && IsTxtrUsed(m) ) + { + while (curStagem_n64Combiners[curN64Stage]; + if( curN64Stage%2 && IsTxtrUsed(m) ) + { + if( tex1 == tex2 ) + { + while (curStage m_dwGeneralMaxStages ) + { + resultIsGood = false; + gci.nStages = m_dwGeneralMaxStages; + } + + if( mux.m_ColorTextureFlag[0] != 0 || mux.m_ColorTextureFlag[1] != 0 ) + { + resultIsGood = false; + } + + // The bResultIsGoodWithinStages is for Semi-Pixel shader combiner, don't move the code down + gci.bResultIsGoodWithinStages = resultIsGood; + if( mux.HowManyConstFactors() > 1 || gci.specularPostOp != MUX_0 || gci.blendingFunc != ENABLE_BOTH ) + { + gci.bResultIsGoodWithinStages = false; + } + + if( gci.nStages > stages[0] ) // Color has less stages + { + for( int i=stages[0]; i stages[1] ) // Color has less stages + { + for( int i=stages[1]; i= m_dwGeneralMaxStages ) + { + extern int noOfTwoStages; + extern GeneralCombinerInfo twostages[]; + + for( int k=0; km_dWords[0]; + result.muxDWords[1] = (*m_ppGeneralDecodedMux)->m_dWords[1]; + result.muxDWords[2] = (*m_ppGeneralDecodedMux)->m_dWords[2]; + result.muxDWords[3] = (*m_ppGeneralDecodedMux)->m_dWords[3]; + result.m_dwShadeAlphaChannelFlag = (*m_ppGeneralDecodedMux)->m_dwShadeAlphaChannelFlag; + result.m_dwShadeColorChannelFlag = (*m_ppGeneralDecodedMux)->m_dwShadeColorChannelFlag; + result.colorTextureFlag[0] = (*m_ppGeneralDecodedMux)->m_ColorTextureFlag[0]; + result.colorTextureFlag[1] = (*m_ppGeneralDecodedMux)->m_ColorTextureFlag[1]; + result.dwMux0 = (*m_ppGeneralDecodedMux)->m_dwMux0; + result.dwMux1 = (*m_ppGeneralDecodedMux)->m_dwMux1; + + m_vCompiledCombinerStages.push_back(result); + m_lastGeneralIndex = m_vCompiledCombinerStages.size()-1; + + return m_lastGeneralIndex; +} + + +int CGeneralCombiner::FindCompiledMux( ) +{ +#ifdef DEBUGGER + if( debuggerDropCombiners || debuggerDropGeneralCombiners ) + { + m_vCompiledCombinerStages.clear(); + //m_dwLastMux0 = m_dwLastMux1 = 0; + debuggerDropCombiners = false; + debuggerDropGeneralCombiners = false; + } +#endif + + for( uint32 i=0; im_dwMux0 && m_vCompiledCombinerStages[i].dwMux1 == (*m_ppGeneralDecodedMux)->m_dwMux1 ) + { + m_lastGeneralIndex = i; + return i; + } + } + + return -1; +} + + + +bool LM_textureUsedInStage[8]; +void CGeneralCombiner::LM_GenCI_Init(GeneralCombinerInfo &gci) +{ + gci.specularPostOp=gci.TFactor=MUX_0; + + gci.blendingFunc = ENABLE_BOTH; + + for( int i=0; i<8; i++) + { + gci.stages[i].dwTexture = 0; + LM_textureUsedInStage[i] = false; + } +} + + +//#define fillstage(opr,a1,a2,a3) {op->op=opr;op->Arg1=a1;op->Arg2=a2;op->Arg0=a3;curStage++;} +inline void FillStage(StageOperate &op, uint32 opr, uint32 a1, uint32 a2, uint32 a3) +{ + op.op = opr; + op.Arg1 = a1; + op.Arg2 = a2; + op.Arg0 = a3; +} + +/************************************************************************/ +/* New functions, will generate stages within stage limited */ +/* and return the number of stages used. */ +/************************************************************************/ +int CGeneralCombiner::LM_GenCI_Type_D(N64CombinerType &m, int curStage, int limit, int channel, bool checktexture, GeneralCombinerInfo &gci) +{ + int originalstage=curStage; + StageOperate *op = ((StageOperate*)(&(gci.stages[curStage]))) + channel; + if( checktexture && LM_Check1TxtrForAlpha(curStage, gci, m.d ) ) + { + if( limit > 1 ) + { + FillStage(*op,CM_REPLACE,MUX_COMBINED,CM_IGNORE,CM_IGNORE); + curStage++; + op = ((StageOperate*)(&(gci.stages[curStage]))) + channel; + FillStage(*op,CM_REPLACE,m.d,CM_IGNORE,CM_IGNORE); + } + else + { + // It is not allowed to use two stages, what to do? + // It should not happen anyway + TRACE0("Check me here, at LM_GenCI_Type_D"); + } + } + else + { + FillStage(*op,CM_REPLACE,m.d,CM_IGNORE,CM_IGNORE); + } + + gci.stages[curStage].dwTexture = GetTexelNumber(m); + LM_textureUsedInStage[curStage] = IsTxtrUsed(m); + curStage++; + + return curStage-originalstage; +} +int CGeneralCombiner::LM_GenCI_Type_A_MOD_C(N64CombinerType &m, int curStage, int limit, int channel, bool checktexture, GeneralCombinerInfo &gci, uint32 dxop) +{ + int originalstage=curStage; + StageOperate *op = ((StageOperate*)(&(gci.stages[curStage].colorOp))) + channel; + + int numberOfTex = CountTexel1Cycle(m); + + if( numberOfTex == 2 ) + { + // As we can not use both texture in one stage + // we split them to two stages + // Stage1: SELECT txt1 + // Stage2: MOD txt2 + + if( checktexture ) + { + if( LM_Check1TxtrForAlpha(curStage, gci, m.a ) ) + { + FillStage(*op,CM_REPLACE,m.c,CM_IGNORE,CM_IGNORE); + gci.stages[curStage].dwTexture = toTex(m.c); + LM_textureUsedInStage[curStage] = true; + curStage++; + + op = ((StageOperate*)(&(gci.stages[curStage].colorOp))) + channel; + FillStage(*op,dxop,m.a,MUX_COMBINED,CM_IGNORE); + gci.stages[curStage].dwTexture = toTex(m.a); + LM_textureUsedInStage[curStage] = true; + curStage++; + } + else + { + FillStage(*op,CM_REPLACE,m.a,CM_IGNORE,CM_IGNORE); + gci.stages[curStage].dwTexture = toTex(m.a); + LM_textureUsedInStage[curStage] = true; + curStage++; + + op = ((StageOperate*)(&(gci.stages[curStage].colorOp))) + channel; + FillStage(*op,dxop,m.c,MUX_COMBINED,CM_IGNORE); + gci.stages[curStage].dwTexture = toTex(m.c); + LM_textureUsedInStage[curStage] = true; + curStage++; + } + } + else + { + FillStage(*op,CM_REPLACE,m.a,CM_IGNORE,CM_IGNORE); + gci.stages[curStage].dwTexture = toTex(m.a); + LM_textureUsedInStage[curStage] = true; + curStage++; + + op = ((StageOperate*)(&(gci.stages[curStage].colorOp))) + channel; + FillStage(*op,dxop,m.c,MUX_COMBINED,CM_IGNORE); + gci.stages[curStage].dwTexture = toTex(m.c); + LM_textureUsedInStage[curStage] = true; + curStage++; + } + } + else if( numberOfTex == 1) + { + if( checktexture ) + { + if( isTex(m.a) ) + { + if( LM_Check1TxtrForAlpha(curStage, gci, m.a ) ) + { + FillStage(*op,CM_REPLACE,m.c,CM_IGNORE,CM_IGNORE); + curStage++; + + op = ((StageOperate*)(&(gci.stages[curStage].colorOp))) + channel; + FillStage(*op,dxop,m.a,MUX_COMBINED,CM_IGNORE); + gci.stages[curStage].dwTexture = toTex(m.a); + LM_textureUsedInStage[curStage] = true; + curStage++; + } + else + { + FillStage(*op,CM_REPLACE,m.a,CM_IGNORE,CM_IGNORE); + gci.stages[curStage].dwTexture = toTex(m.a); + LM_textureUsedInStage[curStage] = true; + curStage++; + + op = ((StageOperate*)(&(gci.stages[curStage].colorOp))) + channel; + FillStage(*op,dxop,m.c,MUX_COMBINED,CM_IGNORE); + curStage++; + } + } + else + { + if( LM_Check1TxtrForAlpha(curStage, gci, m.c ) ) + { + FillStage(*op,CM_REPLACE,m.a,CM_IGNORE,CM_IGNORE); + curStage++; + + op = ((StageOperate*)(&(gci.stages[curStage].colorOp))) + channel; + FillStage(*op,dxop,m.c,MUX_COMBINED,CM_IGNORE); + gci.stages[curStage].dwTexture = toTex(m.c); + LM_textureUsedInStage[curStage] = true; + curStage++; + } + else + { + FillStage(*op,CM_REPLACE,m.c,CM_IGNORE,CM_IGNORE); + gci.stages[curStage].dwTexture = toTex(m.c); + LM_textureUsedInStage[curStage] = true; + curStage++; + + op = ((StageOperate*)(&(gci.stages[curStage].colorOp))) + channel; + FillStage(*op,dxop,m.a,MUX_COMBINED,CM_IGNORE); + curStage++; + } + } + } + else + { + if( isTex(m.a) ) + { + FillStage(*op,CM_REPLACE,m.a,CM_IGNORE,CM_IGNORE); + gci.stages[curStage].dwTexture = toTex(m.a); + LM_textureUsedInStage[curStage] = true; + curStage++; + + op = ((StageOperate*)(&(gci.stages[curStage].colorOp))) + channel; + FillStage(*op,dxop,m.c,MUX_COMBINED,CM_IGNORE); + curStage++; + } + else + { + FillStage(*op,CM_REPLACE,m.c,CM_IGNORE,CM_IGNORE); + gci.stages[curStage].dwTexture = toTex(m.c); + LM_textureUsedInStage[curStage] = true; + curStage++; + + op = ((StageOperate*)(&(gci.stages[curStage].colorOp))) + channel; + FillStage(*op,dxop,m.a,MUX_COMBINED,CM_IGNORE); + curStage++; + } + + } + } + else + { + FillStage(*op,dxop,m.a,m.c,CM_IGNORE); + curStage++; + } + + return curStage-originalstage; +} +int CGeneralCombiner::LM_GenCI_Type_A_ADD_D(N64CombinerType &m, int curStage, int limit, int channel, bool checktexture, GeneralCombinerInfo &gci) +{ + return 0; +} +int CGeneralCombiner::LM_GenCI_Type_A_SUB_B(N64CombinerType &m, int curStage, int limit, int channel, bool checktexture, GeneralCombinerInfo &gci) +{ + return 0; +} +int CGeneralCombiner::LM_GenCI_Type_A_LERP_B_C(N64CombinerType &m, int curStage, int limit, int channel, bool checktexture, GeneralCombinerInfo &gci) +{ + return 0; +} +int CGeneralCombiner::LM_GenCI_Type_A_MOD_C_ADD_D(N64CombinerType &m, int curStage, int limit, int channel, bool checktexture, GeneralCombinerInfo &gci) +{ + return 0; +} +int CGeneralCombiner::LM_GenCI_Type_A_SUB_B_ADD_D(N64CombinerType &m, int curStage, int limit, int channel, bool checktexture, GeneralCombinerInfo &gci) +{ + return 0; +} +int CGeneralCombiner::LM_GenCI_Type_A_SUB_B_MOD_C(N64CombinerType &m, int curStage, int limit, int channel, bool checktexture, GeneralCombinerInfo &gci) +{ + return 0; +} +int CGeneralCombiner::LM_GenCI_Type_A_ADD_B_MOD_C(N64CombinerType &m, int curStage, int limit, int channel, bool checktexture, GeneralCombinerInfo &gci) +{ + return 0; +} +int CGeneralCombiner::LM_GenCI_Type_A_B_C_D(N64CombinerType &m, int curStage, int limit, int channel, bool checktexture, GeneralCombinerInfo &gci) +{ + return 0; +} +int CGeneralCombiner::LM_GenCI_Type_A_B_C_A(N64CombinerType &m, int curStage, int limit, int channel, bool checktexture, GeneralCombinerInfo &gci) +{ + return 0; +} + +int CGeneralCombiner::LM_ParseDecodedMux() +{ + return 0; +} + +bool CGeneralCombiner::LM_Check1TxtrForAlpha(int curStage, GeneralCombinerInfo &gci, uint32 val ) +{ + return !( isTex(val) && LM_textureUsedInStage[curStage] && gci.stages[curStage].dwTexture != (unsigned int)toTex(val) ); +} + + +void CGeneralCombiner::LM_SkipStage(StageOperate &op) +{ + op.op = CM_REPLACE; + op.Arg1 = MUX_COMBINED; + op.Arg2 = CM_IGNORE; + op.Arg0 = CM_IGNORE; +} +