mupen64plus-oldsvn/rice_video/GeneralCombiner.cpp
Scott Knauert edcef05047 Changes: Fixed nearly all warnings in Rice (Issue 24) except
one pointer arithmetic one in TextureFilters.cpp (see tracker).
Once that is fixed Issue 24 in current form can be closed.

Testing done: Code compiles for normal and debug use without 
any -Wall warnings and seems to yield the same results and previous 
svn on my r300.
2008-04-04 19:18:54 +00:00

1327 lines
38 KiB
C++

/*
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 "stdafx.h"
#include "GeneralCombiner.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 _DEBUG
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; i<gci.nStages; i++ )
{
GeneralCombineStage &s = gci.stages[i];
DebuggerAppendMsg("%d:Color: %s - %s, %s, %s%s\n", i,
cmopstrs[s.colorOp.op], DecodedMux::FormatStr((uint8)s.colorOp.Arg1, str1), s.colorOp.Arg2==CM_IGNORE?"":DecodedMux::FormatStr((uint8)s.colorOp.Arg2, str2),
s.colorOp.Arg0==CM_IGNORE?"":DecodedMux::FormatStr((uint8)s.colorOp.Arg0, str3),
s.dwTexture!=0?" -Tex1":"");
}
for( int i=0; i<gci.nStages; i++ )
{
GeneralCombineStage &s = gci.stages[i];
DebuggerAppendMsg("%d:Alpha: %s - %s, %s, %s%s\n", i,
cmopstrs[s.alphaOp.op], DecodedMux::FormatStr((uint8)s.alphaOp.Arg1, str1),
s.alphaOp.Arg2==CM_IGNORE?"":DecodedMux::FormatStr((uint8)s.alphaOp.Arg2, str2),
s.alphaOp.Arg0==CM_IGNORE?"":DecodedMux::FormatStr((uint8)s.alphaOp.Arg0, str3),
s.dwTexture!=0?" -Tex1":"");
}
TRACE0("\n\n");
}
#endif
/*
* Combiner gci generating functions
*/
bool textureUsedInStage[8][2];
bool resultIsGood;
void CGeneralCombiner::GenCI_Init(GeneralCombinerInfo &gci)
{
gci.specularPostOp=gci.TFactor=MUX_0;
gci.blendingFunc = ENABLE_BOTH;
resultIsGood = true;
//After the mux is reformated and simplified, we can use it to generate combine stages
//return false if we can not generate it
for( int i=0; i<8; i++)
{
gci.stages[i].dwTexture = 0;
textureUsedInStage[i][0] = false; // For color
textureUsedInStage[i][1] = false; // For alpha
gci.stages[i].bTextureUsed = false;
gci.stages[i].dwTexture = 0;
gci.stages[i].colorOp.op = gci.stages[i].alphaOp.op = CM_REPLACE;
gci.stages[i].colorOp.Arg1 = gci.stages[i].alphaOp.Arg1 = MUX_COMBINED;
gci.stages[i].colorOp.Arg2 = gci.stages[i].alphaOp.Arg2 = CM_IGNORE;
gci.stages[i].colorOp.Arg0 = gci.stages[i].alphaOp.Arg0 = CM_IGNORE;
}
DecodedMux &mux = *(*m_ppGeneralDecodedMux);
// Check some special cases of alpha channel
if( mux.splitType[N64Cycle0Alpha]==CM_FMT_TYPE_D && mux.splitType[N64Cycle1Alpha]==CM_FMT_TYPE_NOT_USED )
{
//if( mux.m_n64Combiners[N64Cycle0Alpha].d == MUX_0 )
// gci.blendingFunc = DISABLE_COLOR;
//else
if( mux.m_n64Combiners[N64Cycle0Alpha].d == MUX_1 )
gci.blendingFunc = DISABLE_ALPHA;
}
else if( mux.splitType[N64Cycle1Alpha]==CM_FMT_TYPE_D )
{
//if( mux.m_n64Combiners[N64Cycle1Alpha].d == MUX_0 )
// gci.blendingFunc = DISABLE_COLOR;
//else
if( mux.m_n64Combiners[N64Cycle1Alpha].d == MUX_1 )
gci.blendingFunc = DISABLE_ALPHA;
}
if( mux.splitType[N64Cycle0RGB]==CM_FMT_TYPE_D && mux.splitType[N64Cycle1RGB]==CM_FMT_TYPE_NOT_USED )
{
if( mux.m_n64Combiners[N64Cycle0RGB].d == MUX_0 )
gci.blendingFunc = DISABLE_COLOR;
}
}
int CGeneralCombiner::GenCI_Type_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.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;
}
/*
*
*/
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 (curStage<m_dwGeneralMaxStages-1 && textureUsedInStage[curStage][0] && gci.stages[curStage].dwTexture != (unsigned int)(tex) )
{
StageOperate &op = ((StageOperate*)(&(gci.stages[curStage].colorOp)))[curN64Stage%2];
SkipStage(op, curStage);
}
}
}
int CGeneralCombiner::Check2TxtrForAlpha(int curN64Stage, int &curStage, GeneralCombinerInfo &gci, int tex1, int tex2)
{
N64CombinerType &m = (*m_ppGeneralDecodedMux)->m_n64Combiners[curN64Stage];
if( curN64Stage%2 && IsTxtrUsed(m) )
{
if( tex1 == tex2 )
{
while (curStage<m_dwGeneralMaxStages-1 && textureUsedInStage[curStage][0] && gci.stages[curStage].dwTexture != (unsigned int)tex1 )
{
StageOperate &op = ((StageOperate*)(&(gci.stages[curStage].colorOp)))[curN64Stage%2];
SkipStage(op, curStage);
}
return 1;
}
else
{
int stage1 = curStage;
int stage2 = curStage;
while (stage1<m_dwGeneralMaxStages-1 && textureUsedInStage[stage1][0] && gci.stages[stage1].dwTexture != (unsigned int)tex1 )
{
StageOperate &op = ((StageOperate*)(&(gci.stages[stage1].colorOp)))[curN64Stage%2];
SkipStage(op, stage1);
}
while (stage2<m_dwGeneralMaxStages-1 && textureUsedInStage[stage2][0] && gci.stages[stage2].dwTexture != (unsigned int)tex2 )
{
StageOperate &op = ((StageOperate*)(&(gci.stages[stage2].colorOp)))[curN64Stage%2];
SkipStage(op, stage2);
}
if( stage1 <= stage2 )
{
curStage = stage1;
return 1;
}
else
{
curStage = stage2;
return 2;
}
}
}
else
{
return 0;
}
}
int CGeneralCombiner::CheckWhichTexToUseInThisStage(int curN64Stage, int curStage, GeneralCombinerInfo &gci)
{
// There are two texels to used, which one I should use in the current DirectX stage?
if( curN64Stage%2 )
{
if( !textureUsedInStage[curStage][0] )
return 0;
else
return gci.stages[curStage].dwTexture;
}
else
{
return 0;
}
}
/*
*
*/
int CGeneralCombiner::ParseDecodedMux()
{
GeneralCombinerInfo gci;
int i,j;
int stages[2];
DecodedMux &mux = *(*m_ppGeneralDecodedMux);
GenCI_Init(gci);
for( i=0; i<2; i++ )
{
//i=0 Color Channel
//i=1 Alpha Channel
stages[i] = 0;
int n=0; //stage count
for( j=0; j<2; j++ )
{
switch( mux.splitType[i+j*2] )
{
case CM_FMT_TYPE_NOT_USED:
continue;
case CM_FMT_TYPE_D: // = D
// Alpha channel is using different texture from color channel
// and the color channel has already used texture, so alpha
// channel can not use different texture for this stage anymore,
// alpha channel need to skip a stage
n = GenCI_Type_D(j*2+i, n, gci);
if( j==0 && mux.splitType[i+2] != CM_FMT_TYPE_NOT_USED ) NextStage(n); else n++;
break;
case CM_FMT_TYPE_A_ADD_D: // = A+D
n=GenCI_Type_A_ADD_D(j*2+i, n, gci);
if( j==0 && mux.splitType[i+2] != CM_FMT_TYPE_NOT_USED ) NextStage(n); else n++;
break;
case CM_FMT_TYPE_A_MOD_C: // = A*C can mapped to MOD(arg1,arg2)
n=GenCI_Type_A_MOD_C(j*2+i, n, gci);
if( j==0 && mux.splitType[i+2] != CM_FMT_TYPE_NOT_USED ) NextStage(n); else n++;
break;
case CM_FMT_TYPE_A_SUB_B: // = A-B can mapped to SUB(arg1,arg2)
n=GenCI_Type_A_SUB_B(j*2+i, n, gci);
if( j==0 && mux.splitType[i+2] != CM_FMT_TYPE_NOT_USED ) NextStage(n); else n++;
break;
case CM_FMT_TYPE_A_MOD_C_ADD_D: // = A*C+D can mapped to MULTIPLYADD(arg1,arg2,arg0)
n=GenCI_Type_A_MOD_C_ADD_D(j*2+i, n, gci);
if( j==0 && mux.splitType[i+2] != CM_FMT_TYPE_NOT_USED ) NextStage(n); else n++;
break;
case CM_FMT_TYPE_A_LERP_B_C: // = (A-B)*C+B can mapped to LERP(arg1,arg2,arg0)
// or mapped to BLENDALPHA(arg1,arg2) if C is
// alpha channel or DIF, TEX, FAC, CUR
n=GenCI_Type_A_LERP_B_C(j*2+i, n, gci);
if( j==0 && mux.splitType[i+2] != CM_FMT_TYPE_NOT_USED ) NextStage(n); else n++;
break;
case CM_FMT_TYPE_A_SUB_B_ADD_D: // = A-B+C can not map very well in 1 stage
n=GenCI_Type_A_SUB_B_ADD_D(j*2+i, n, gci);
if( j==0 && mux.splitType[i+2] != CM_FMT_TYPE_NOT_USED ) NextStage(n); else n++;
break;
case CM_FMT_TYPE_A_SUB_B_MOD_C: // = (A-B)*C can not map very well in 1 stage
n=GenCI_Type_A_SUB_B_MOD_C(j*2+i, n, gci);
if( j==0 && mux.splitType[i+2] != CM_FMT_TYPE_NOT_USED ) NextStage(n); else n++;
break;
case CM_FMT_TYPE_A_ADD_B_MOD_C:
n=GenCI_Type_A_ADD_B_MOD_C(j*2+i, n, gci);
if( j==0 && mux.splitType[i+2] != CM_FMT_TYPE_NOT_USED ) NextStage(n); else n++;
break;
case CM_FMT_TYPE_A_B_C_A:
n=GenCI_Type_A_B_C_A(j*2+i, n, gci);
if( j==0 && mux.splitType[i+2] != CM_FMT_TYPE_NOT_USED ) NextStage(n); else n++;
break;
case CM_FMT_TYPE_A_B_C_D: // = (A-B)*C+D can not map very well in 1 stage
n=GenCI_Type_A_B_C_D(j*2+i, n, gci);
if( j==0 && mux.splitType[i+2] != CM_FMT_TYPE_NOT_USED ) NextStage(n); else n++;
break;
default:
break;
}
}
stages[i] = n;
}
gci.nStages = max(stages[0], stages[1]);
if( gci.nStages > 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<gci.nStages; i++ )
{
gci.stages[i].colorOp.op = CM_REPLACE;
gci.stages[i].colorOp.Arg1 = MUX_COMBINED;
gci.stages[i].colorOp.Arg2 = CM_IGNORE;
gci.stages[i].colorOp.Arg0 = CM_IGNORE;
}
}
if( gci.nStages > stages[1] ) //Color has less stages
{
for( int i=stages[1]; i<gci.nStages; i++ )
{
gci.stages[i].alphaOp.op = CM_REPLACE;
gci.stages[i].alphaOp.Arg1 = MUX_COMBINED;
gci.stages[i].alphaOp.Arg2 = CM_IGNORE;
gci.stages[i].alphaOp.Arg0 = CM_IGNORE;
}
}
for( i=0;i<gci.nStages;i++)
{
gci.stages[i].bTextureUsed = IsTextureUsedInStage(gci.stages[i]);
}
if( !resultIsGood && gci.nStages >= m_dwGeneralMaxStages )
{
extern int noOfTwoStages;
extern GeneralCombinerInfo twostages[];
for( int k=0; k<noOfTwoStages; k++ )
{
GeneralCombinerInfo &info = twostages[k];
if( (mux.m_dwMux0 == info.dwMux0 && mux.m_dwMux1 == info.dwMux1) ||
(info.dwMux0+info.dwMux1 == 0 && info.muxDWords[0] == mux.m_dWords[0] &&
info.muxDWords[1] == mux.m_dWords[1] && info.muxDWords[2] == mux.m_dWords[2] &&
info.muxDWords[3] == mux.m_dWords[3] && info.m_dwShadeAlphaChannelFlag == mux.m_dwShadeAlphaChannelFlag &&
info.m_dwShadeColorChannelFlag == mux.m_dwShadeColorChannelFlag ) )
{
memcpy(&gci, &info, sizeof(GeneralCombinerInfo) );
resultIsGood = true;
break;
}
}
}
#ifdef _DEBUG
if( !resultIsGood )
{
DecodedMux &mux = *(*m_ppGeneralDecodedMux);
// Generated combiner mode is not good enough within the limited stages
DebuggerAppendMsg("\n/*");
mux.DisplayMuxString("Overflowed");
mux.DisplaySimpliedMuxString("Overflowed");
DebuggerAppendMsg("Generated combiners:");
General_DisplayBlendingStageInfo(gci);
DebuggerAppendMsg("*/\n");
DebuggerAppendMsg("\n\n");
DebuggerAppendMsg("{\n\t0x%08X, 0x%08X, 0x%08X, 0x%08X,\t// Simplified mux\n\t0x%08X, 0x%08X,\t\t// 64bit Mux\n",
mux.m_dWords[0],mux.m_dWords[1],mux.m_dWords[2],mux.m_dWords[3],mux.m_dwMux0,mux.m_dwMux1);
DebuggerAppendMsg("\t%d,\t// number of stages\n\tENABLE_BOTH,\n\t0,\t\t// Constant color\n\t0x%08X, 0x%08X, 0,\t// Shade and specular color flags\n\t0x%08X, 0x%08X,\t// constant color texture flags\n",
2,mux.m_dwShadeColorChannelFlag, mux.m_dwShadeAlphaChannelFlag,mux.m_ColorTextureFlag[0],mux.m_ColorTextureFlag[1]);
DebuggerAppendMsg("\t{\n\t\t{MOD(T0,DIF), MOD(T0,DIF), 0, true}, // Stage 0\n");
DebuggerAppendMsg("\t\t{MOD(T0,DIF), SKIP, 1, true}, // Stage 1\n\t}\n},");
}
#else
if( !resultIsGood )
{
FILE *fp=NULL;
fp = fopen("C:\\rice\\RiceVideoMUX.log","a");
if( fp )
{
fprintf(fp,"\n/*\n");
mux.LogMuxString("Overflowed",fp);
fprintf(fp,"\n\n");
mux.LogSimpliedMuxString("Overflowed",fp);
fprintf(fp,"Generated combiners:");
//General_DisplayBlendingStageInfo(gci);
fprintf(fp,"\n*/\n");
fprintf(fp,"\n");
fprintf(fp,"{\n\t0x%08X, 0x%08X, 0x%08X, 0x%08X,\t// Simplified mux\n\t0x%08X, 0x%08X,\t\t// 64bit Mux\n",
mux.m_dWords[0],mux.m_dWords[1],mux.m_dWords[2],mux.m_dWords[3],mux.m_dwMux0,mux.m_dwMux1);
fprintf(fp,"\t%d,\t// number of stages\n\tENABLE_BOTH,\n\tMUX_ENV,\t\t// Constant color\n\t0x%08X, 0x%08X, 0,\t// Shade and specular color flags\n\t0x%08X, 0x%08X,\t// constant color texture flags\n",
2,mux.m_dwShadeColorChannelFlag, mux.m_dwShadeAlphaChannelFlag,mux.m_ColorTextureFlag[0],mux.m_ColorTextureFlag[1]);
fprintf(fp,"\t{\n\t\t{MOD(T0,DIF), MOD(T0,DIF), 0, true}, // Stage 0\n");
fprintf(fp,"\t\t{LERP(T1,CUR,DIF), SKIP, 1, true}, // Stage 1\n\t}\n},");
fclose(fp);
}
}
#endif
return SaveParserResult(gci);
}
bool CGeneralCombiner::IsTextureUsedInStage(GeneralCombineStage &stage)
{
if( (stage.colorOp.Arg1&MUX_MASK)==MUX_TEXEL0 || (stage.colorOp.Arg2&MUX_MASK)==MUX_TEXEL0 || (stage.colorOp.Arg0 &MUX_MASK)==MUX_TEXEL0 ||
(stage.alphaOp.Arg1&MUX_MASK)==MUX_TEXEL0 || (stage.alphaOp.Arg2&MUX_MASK)==MUX_TEXEL0 || (stage.alphaOp.Arg0 &MUX_MASK)==MUX_TEXEL0 ||
(stage.colorOp.Arg1&MUX_MASK)==MUX_TEXEL1 || (stage.colorOp.Arg2&MUX_MASK)==MUX_TEXEL1 || (stage.colorOp.Arg0 &MUX_MASK)==MUX_TEXEL1 ||
(stage.alphaOp.Arg1&MUX_MASK)==MUX_TEXEL1 || (stage.alphaOp.Arg2&MUX_MASK)==MUX_TEXEL1 || (stage.alphaOp.Arg0 &MUX_MASK)==MUX_TEXEL1 )
{
return true;
}
else
return false;
}
int CGeneralCombiner::SaveParserResult(GeneralCombinerInfo &result)
{
result.muxDWords[0] = (*m_ppGeneralDecodedMux)->m_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 _DEBUG
if( debuggerDropCombiners || debuggerDropGeneralCombiners )
{
m_vCompiledCombinerStages.clear();
//m_dwLastMux0 = m_dwLastMux1 = 0;
debuggerDropCombiners = false;
debuggerDropGeneralCombiners = false;
}
#endif
for( uint32 i=0; i<m_vCompiledCombinerStages.size(); i++ )
{
if( m_vCompiledCombinerStages[i].dwMux0 == (*m_ppGeneralDecodedMux)->m_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()
{
GeneralCombinerInfo gci;
DecodedMux &mux = *(*m_ppGeneralDecodedMux);
// Check some special cases of alpha channel
if( mux.splitType[N64Cycle0Alpha]==CM_FMT_TYPE_D && mux.splitType[N64Cycle1Alpha]==CM_FMT_TYPE_NOT_USED )
{
//if( mux.m_n64Combiners[N64Cycle0Alpha].d == MUX_0 )
// gci.blendingFunc = DISABLE_COLOR;
//else
if( mux.m_n64Combiners[N64Cycle0Alpha].d == MUX_1 )
gci.blendingFunc = DISABLE_ALPHA;
}
else if( mux.splitType[N64Cycle1Alpha]==CM_FMT_TYPE_D )
{
//if( mux.m_n64Combiners[N64Cycle1Alpha].d == MUX_0 )
// gci.blendingFunc = DISABLE_COLOR;
//else
if( mux.m_n64Combiners[N64Cycle1Alpha].d == MUX_1 )
gci.blendingFunc = DISABLE_ALPHA;
}
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;
}