Path: blob/master/libmupen64plus/mupen64plus-video-rice/src/GeneralCombiner.cpp
2 views
/*1Copyright (C) 2003 Rice196423This program is free software; you can redistribute it and/or4modify it under the terms of the GNU General Public License5as published by the Free Software Foundation; either version 26of the License, or (at your option) any later version.78This program is distributed in the hope that it will be useful,9but WITHOUT ANY WARRANTY; without even the implied warranty of10MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the11GNU General Public License for more details.1213You should have received a copy of the GNU General Public License14along with this program; if not, write to the Free Software15Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.16*/1718#include <algorithm>1920#include "GeneralCombiner.h"21#include "Combiner.h"22#include "Debugger.h"2324extern const int numOf3StageCombiners;25extern const int numOf2StageCombiners;26extern GeneralCombinerInfo CombinerTable2Stages[];27extern GeneralCombinerInfo CombinerTable3Stages[];2829CGeneralCombiner::CGeneralCombiner()30{31m_lastGeneralIndex=0;32m_ppGeneralDecodedMux=NULL;3334m_bTxtOpAdd=true;35m_bTxtOpSub=false;36m_bTxtOpLerp=false;37m_bTxtOpAddSmooth=false;38m_bTxtOpBlendCurAlpha=false;39m_bTxtOpBlendDifAlpha=true;40m_bTxtOpBlendFacAlpha=false;41m_bTxtOpBlendTxtAlpha=true;42m_bTxtOpMulAdd=false;4344m_dwGeneralMaxStages=2;45}4647bool isTex(uint32 val)48{49return ( (val&MUX_MASK) == MUX_TEXEL0 || (val&MUX_MASK) == MUX_TEXEL1 );50}51int toTex(uint32 val)52{53return (val&MUX_MASK)-MUX_TEXEL0;54}5556bool isComb(uint32 val)57{58return (val&MUX_MASK)==MUX_COMBINED;59}6061#ifdef DEBUGGER62const char* BlendFuncStr[] = {63"Enable both",64"Disable alpha",65"Disable color",66"Disable both",67"Color one",68"Alpha one",69};70const char* cmopstrs[] = {71"Sel",72"Mod",73"Add",74"Sub",75"Lerp",76"AddSmooth",77"BlCurA",78"BlDifA",79"BlFacA",80"BlTexA",81"MulAdd",82};8384void CGeneralCombiner::General_DisplayBlendingStageInfo(GeneralCombinerInfo &gci)85{86char str1[30],str2[30],str3[30];87DebuggerAppendMsg("\nStages:%d, Alpha:%s, Factor:%s, Specular:%s Dif Color:0x%X Dif Alpha:0x%X\n",88gci.nStages, BlendFuncStr[gci.blendingFunc], DecodedMux::FormatStr((uint8)gci.TFactor,str1),89DecodedMux::FormatStr((uint8)gci.specularPostOp,str2), gci.m_dwShadeColorChannelFlag, gci.m_dwShadeAlphaChannelFlag);9091for( int i=0; i<gci.nStages; i++ )92{93GeneralCombineStage &s = gci.stages[i];94DebuggerAppendMsg("%d:Color: %s - %s, %s, %s%s\n", i,95cmopstrs[s.colorOp.op], DecodedMux::FormatStr((uint8)s.colorOp.Arg1, str1), s.colorOp.Arg2==CM_IGNORE?"":DecodedMux::FormatStr((uint8)s.colorOp.Arg2, str2),96s.colorOp.Arg0==CM_IGNORE?"":DecodedMux::FormatStr((uint8)s.colorOp.Arg0, str3),97s.dwTexture!=0?" -Tex1":"");98}99100for( int i=0; i<gci.nStages; i++ )101{102GeneralCombineStage &s = gci.stages[i];103DebuggerAppendMsg("%d:Alpha: %s - %s, %s, %s%s\n", i,104cmopstrs[s.alphaOp.op], DecodedMux::FormatStr((uint8)s.alphaOp.Arg1, str1),105s.alphaOp.Arg2==CM_IGNORE?"":DecodedMux::FormatStr((uint8)s.alphaOp.Arg2, str2),106s.alphaOp.Arg0==CM_IGNORE?"":DecodedMux::FormatStr((uint8)s.alphaOp.Arg0, str3),107s.dwTexture!=0?" -Tex1":"");108}109TRACE0("\n\n");110}111#endif112113114///////////////////////////////////////115// Combiner gci generating functions //116///////////////////////////////////////117118bool textureUsedInStage[8][2];119bool resultIsGood;120121void CGeneralCombiner::GenCI_Init(GeneralCombinerInfo &gci)122{123gci.specularPostOp=gci.TFactor=MUX_0;124125gci.blendingFunc = ENABLE_BOTH;126resultIsGood = true;127128//After the mux is reformated and simplified, we can use it to generate combine stages129//return false if we can not generate it130131for( int i=0; i<8; i++)132{133gci.stages[i].dwTexture = 0;134textureUsedInStage[i][0] = false; // For color135textureUsedInStage[i][1] = false; // For alpha136gci.stages[i].bTextureUsed = false;137gci.stages[i].dwTexture = 0;138gci.stages[i].colorOp.op = gci.stages[i].alphaOp.op = CM_REPLACE;139gci.stages[i].colorOp.Arg1 = gci.stages[i].alphaOp.Arg1 = MUX_COMBINED;140gci.stages[i].colorOp.Arg2 = gci.stages[i].alphaOp.Arg2 = CM_IGNORE;141gci.stages[i].colorOp.Arg0 = gci.stages[i].alphaOp.Arg0 = CM_IGNORE;142}143144DecodedMux &mux = *(*m_ppGeneralDecodedMux);145146// Check some special cases of alpha channel147if( mux.splitType[N64Cycle0Alpha]==CM_FMT_TYPE_D && mux.splitType[N64Cycle1Alpha]==CM_FMT_TYPE_NOT_USED )148{149//if( mux.m_n64Combiners[N64Cycle0Alpha].d == MUX_0 )150// gci.blendingFunc = DISABLE_COLOR;151//else152if( mux.m_n64Combiners[N64Cycle0Alpha].d == MUX_1 )153gci.blendingFunc = DISABLE_ALPHA;154}155else if( mux.splitType[N64Cycle1Alpha]==CM_FMT_TYPE_D )156{157//if( mux.m_n64Combiners[N64Cycle1Alpha].d == MUX_0 )158// gci.blendingFunc = DISABLE_COLOR;159//else160if( mux.m_n64Combiners[N64Cycle1Alpha].d == MUX_1 )161gci.blendingFunc = DISABLE_ALPHA;162}163164if( mux.splitType[N64Cycle0RGB]==CM_FMT_TYPE_D && mux.splitType[N64Cycle1RGB]==CM_FMT_TYPE_NOT_USED )165{166if( mux.m_n64Combiners[N64Cycle0RGB].d == MUX_0 )167gci.blendingFunc = DISABLE_COLOR;168}169170}171172int CGeneralCombiner::GenCI_Type_D(int curN64Stage, int curStage, GeneralCombinerInfo &gci)173{174N64CombinerType &m = (*m_ppGeneralDecodedMux)->m_n64Combiners[curN64Stage];175StageOperate *op = ((StageOperate*)(&(gci.stages[curStage].colorOp))) + (curN64Stage%2);176if( ( m.d == MUX_0 || m.d == MUX_1 ) && curN64Stage==1 )177{178//if( m.d == MUX_0 )179// gci.blendingFunc = DISABLE_COLOR;180//if( m.d == MUX_1 )181// gci.blendingFunc = DISABLE_ALPHA;182183op->op = CM_REPLACE;184op->Arg1 = MUX_COMBINED;185op->Arg2 = CM_IGNORE;186op->Arg0 = CM_IGNORE;187}188else189{190if( isTex(m.d) ) Check1TxtrForAlpha(curN64Stage, curStage, gci, toTex(m.d));191op = ((StageOperate*)(&(gci.stages[curStage].colorOp))) + (curN64Stage%2);192193op->op = CM_REPLACE;194op->Arg1 = m.d;195op->Arg2 = CM_IGNORE;196op->Arg0 = CM_IGNORE;197}198199if( !gci.stages[curStage].bTextureUsed )200gci.stages[curStage].dwTexture = GetTexelNumber(m);201textureUsedInStage[curStage][curN64Stage%2] = IsTxtrUsed(m);202return curStage;203}204205int CGeneralCombiner::GenCI_Type_A_MOD_C(int curN64Stage, int curStage, GeneralCombinerInfo &gci, uint32 dxop)206{207N64CombinerType &m = (*m_ppGeneralDecodedMux)->m_n64Combiners[curN64Stage];208StageOperate *op = ((StageOperate*)(&(gci.stages[curStage].colorOp))) + (curN64Stage%2);209210if( CountTexel1Cycle(m) == 2 )211{212// As we can not use both texture in one stage213// we split them to two stages214// Stage1: SELECT txt1215// Stage2: MOD txt2216217if( gci.stages[curStage].bTextureUsed && gci.stages[curStage].dwTexture != (unsigned int)toTex(m.a) )218swap(m.a,m.c);219220op->op =CM_REPLACE;221op->Arg1 = m.a;222op->Arg2 = CM_IGNORE;223op->Arg0 = CM_IGNORE;224gci.stages[curStage].dwTexture = toTex(m.a);225textureUsedInStage[curStage][curN64Stage%2] = true;226227NextStage(curStage);228Check1TxtrForAlpha(curN64Stage, curStage, gci, toTex(m.c));229op = ((StageOperate*)(&(gci.stages[curStage].colorOp))) + (curN64Stage%2);230231op->op =dxop;232op->Arg1 = (m.c);233op->Arg2 = MUX_COMBINED;234op->Arg0 = CM_IGNORE;235gci.stages[curStage].dwTexture = toTex(m.c);236textureUsedInStage[curStage][curN64Stage%2] = true;237}238else239{240if( CountTexel1Cycle(m) == 1)241{242Check1TxtrForAlpha(curN64Stage, curStage, gci, GetTexelNumber(m));243op = ((StageOperate*)(&(gci.stages[curStage].colorOp))) + (curN64Stage%2);244}245246op->op = dxop;247op->Arg1 = (m.a);248op->Arg2 = (m.c);249op->Arg0 = CM_IGNORE;250if( !gci.stages[curStage].bTextureUsed )251gci.stages[curStage].dwTexture = GetTexelNumber(m);252textureUsedInStage[curStage][curN64Stage%2] = IsTxtrUsed(m);253}254255return curStage;256}257int CGeneralCombiner::GenCI_Type_A_ADD_D(int curN64Stage, int curStage, GeneralCombinerInfo &gci)258{259uint32 opToUse = m_bTxtOpAdd?CM_ADD:CM_MODULATE;260N64CombinerType &m = (*m_ppGeneralDecodedMux)->m_n64Combiners[curN64Stage];261swap(m.c, m.d);262curStage = GenCI_Type_A_MOD_C(curN64Stage, curStage, gci, opToUse);263swap(m.c, m.d);264return curStage;265}266267int CGeneralCombiner::GenCI_Type_A_SUB_B(int curN64Stage, int curStage, GeneralCombinerInfo &gci)268{269N64CombinerType &m = (*m_ppGeneralDecodedMux)->m_n64Combiners[curN64Stage];270if( !m_bTxtOpSub )271{272swap(m.c, m.b);273curStage = GenCI_Type_A_MOD_C(curN64Stage, curStage, gci);274swap(m.c, m.b);275return curStage;276}277278StageOperate *op = ((StageOperate*)(&(gci.stages[curStage].colorOp))) + (curN64Stage%2);279280if( CountTexel1Cycle(m) == 2 )281{282Check1TxtrForAlpha(curN64Stage, curStage, gci, toTex(m.b));283op = ((StageOperate*)(&(gci.stages[curStage].colorOp))) + (curN64Stage%2);284285op->op =CM_REPLACE;286op->Arg1 = (m.b);287op->Arg2 = CM_IGNORE;288op->Arg0 = CM_IGNORE;289gci.stages[curStage].dwTexture = toTex(m.b);290textureUsedInStage[curStage][curN64Stage%2] = true;291292NextStage(curStage);293Check1TxtrForAlpha(curN64Stage, curStage, gci, toTex(m.a));294op = ((StageOperate*)(&(gci.stages[curStage].colorOp))) + (curN64Stage%2);295296op->op =CM_SUBTRACT;297op->Arg1 = (m.a);298op->Arg2 = MUX_COMBINED;299op->Arg0 = CM_IGNORE;300gci.stages[curStage].dwTexture = toTex(m.a);301textureUsedInStage[curStage][curN64Stage%2] = true;302}303else304{305if( CountTexel1Cycle(m) == 1)306{307Check1TxtrForAlpha(curN64Stage, curStage, gci, GetTexelNumber(m));308op = ((StageOperate*)(&(gci.stages[curStage].colorOp))) + (curN64Stage%2);309}310311op->op = CM_SUBTRACT;312op->Arg1 = (m.a);313op->Arg2 = (m.b);314op->Arg0 = CM_IGNORE;315if( !gci.stages[curStage].bTextureUsed )316gci.stages[curStage].dwTexture = GetTexelNumber(m);317textureUsedInStage[curStage][curN64Stage%2] = IsTxtrUsed(m);318}319return curStage;320}321322int CGeneralCombiner::GenCI_Type_A_MOD_C_ADD_D(int curN64Stage, int curStage, GeneralCombinerInfo &gci)323{324N64CombinerType &m = (*m_ppGeneralDecodedMux)->m_n64Combiners[curN64Stage];325StageOperate *op = ((StageOperate*)(&(gci.stages[curStage].colorOp))) + (curN64Stage%2);326327if( !m_bTxtOpMulAdd )328{329N64CombinerType save = m;330m.d = MUX_0;331curStage = GenCI_Type_A_MOD_C(curN64Stage, curStage, gci);332m = save;333m.c = MUX_0;334m.a = MUX_COMBINED;335NextStage(curStage);336curStage = GenCI_Type_A_ADD_D(curN64Stage, curStage, gci);337m = save;338return curStage;339}340341if( CountTexel1Cycle(m) == 2 )342{343if( !gci.stages[curStage].bTextureUsed )344{345gci.stages[curStage].dwTexture = 0;346gci.stages[curStage].bTextureUsed = true;347}348349op->op = CM_REPLACE;350op->Arg2 = CM_IGNORE;351op->Arg0 = CM_IGNORE;352op->Arg1 = MUX_TEXEL0 + gci.stages[curStage].dwTexture ;353354N64CombinerType m2 = m;355356uint8* vals = (uint8*)&m2;357for( int i=0; i<4; i++ )358{359if( (unsigned int)(vals[i]&MUX_MASK) == MUX_TEXEL0 + gci.stages[curStage].dwTexture )360{361vals[i] = MUX_COMBINED | (vals[i]&0xe0);362}363}364365NextStage(curStage);366367Check1TxtrForAlpha(curN64Stage, curStage, gci, GetTexelNumber(m2));368op = ((StageOperate*)(&(gci.stages[curStage].colorOp))) + (curN64Stage%2);369370op->op = CM_MULTIPLYADD;371op->Arg1 = m2.a;372op->Arg2 = m2.c;373op->Arg0 = m2.d;374if( !gci.stages[curStage].bTextureUsed )375gci.stages[curStage].dwTexture = GetTexelNumber(m2);376textureUsedInStage[curStage][curN64Stage%2] = IsTxtrUsed(m2);377}378else379{380Check1TxtrForAlpha(curN64Stage, curStage, gci, GetTexelNumber(m));381op = ((StageOperate*)(&(gci.stages[curStage].colorOp))) + (curN64Stage%2);382383op->op = CM_MULTIPLYADD;384op->Arg1 = (m.a);385op->Arg2 = (m.c);386op->Arg0 = (m.d);387if( !gci.stages[curStage].bTextureUsed )388gci.stages[curStage].dwTexture = GetTexelNumber(m);389textureUsedInStage[curStage][curN64Stage%2] = IsTxtrUsed(m);390}391392return curStage;393}394395396int CGeneralCombiner::GenCI_Type_A_LERP_B_C(int curN64Stage, int curStage, GeneralCombinerInfo &gci)397{398N64CombinerType &m = (*m_ppGeneralDecodedMux)->m_n64Combiners[curN64Stage];399StageOperate *op = ((StageOperate*)(&(gci.stages[curStage].colorOp))) + (curN64Stage%2);400401N64CombinerType save = m;402403if( CountTexel1Cycle(m) == 2 )404{405// There are two textures406int texToUse = CheckWhichTexToUseInThisStage(curN64Stage, curStage, gci);407op->op =CM_REPLACE;408op->Arg1 = (MUX_TEXEL0+texToUse);409op->Arg2 = CM_IGNORE;410op->Arg0 = CM_IGNORE;411gci.stages[curStage].dwTexture = texToUse;412textureUsedInStage[curStage][curN64Stage%2] = true;413414(*m_ppGeneralDecodedMux)->ReplaceVal(MUX_TEXEL0+texToUse, MUX_COMBINED, curN64Stage);415NextStage(curStage);416Check1TxtrForAlpha(curN64Stage, curStage, gci, GetTexelNumber(m));417op = ((StageOperate*)(&(gci.stages[curStage].colorOp))) + (curN64Stage%2);418}419420// Now we have only 1 texture left421422Check1TxtrForAlpha(curN64Stage, curStage, gci, GetTexelNumber(m));423op = ((StageOperate*)(&(gci.stages[curStage].colorOp))) + (curN64Stage%2);424425if( m.a == MUX_1 )426{427op->op = CM_ADDSMOOTH;428op->Arg1 = (m.b);429op->Arg2 = (m.c);430op->Arg0 = CM_IGNORE;431}432else if( m.a == MUX_0 )433{434op->op = CM_MODULATE;435m.a = 0;436op->Arg1 = (m.b);437op->Arg2 = (m.c^MUX_COMPLEMENT);438op->Arg0 = CM_IGNORE;439}440else441{442if( ((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 ) )443{444if( curN64Stage == 2 && (m.c&MUX_ALPHAREPLICATE) == 0 )445{446op->op = CM_MODULATE;447op->Arg1 = m.b;448op->Arg2 = m.c|MUX_COMPLEMENT;449op->Arg0 = CM_IGNORE;450resultIsGood = false;451}452else453{454if( (m.c&MUX_MASK)==MUX_SHADE )455{456op->op = CM_BLENDDIFFUSEALPHA;457}458else if( (m.c&MUX_MASK) == MUX_COMBINED )459{460op->op = CM_BLENDCURRENTALPHA;461}462else if( (m.c&MUX_MASK) == MUX_TEXEL0 )463{464op->op = CM_BLENDTEXTUREALPHA;465}466else if( (m.c&MUX_MASK)==MUX_TEXEL1 )467{468op->op = CM_BLENDTEXTUREALPHA;469}470else471{472op->op = CM_BLENDDIFFUSEALPHA;473}474op->Arg1 = (m.a);475op->Arg2 = (m.b);476op->Arg0 = m.c|MUX_ALPHAREPLICATE;477}478}479else480{481if( ((m.c&MUX_ALPHAREPLICATE) || (curN64Stage%2)==1 || m_bTxtOpLerp == false) && ((((m.c&MUX_MASK)==MUX_ENV) || ((m.c&MUX_MASK)==MUX_PRIM)) ))482{483op->op = CM_BLENDFACTORALPHA;484op->Arg1 = (m.a);485op->Arg2 = (m.b);486op->Arg0 = m.c|MUX_ALPHAREPLICATE;487}488else489{490op->op = CM_INTERPOLATE;491op->Arg0 = (m.c);492op->Arg1 = (m.a);493op->Arg2 = (m.b);494}495}496}497gci.stages[curStage].dwTexture = GetTexelNumber(m);498textureUsedInStage[curStage][curN64Stage%2] = IsTxtrUsed(m);499500m = save;501return curStage;502}503504505int CGeneralCombiner::GenCI_Type_A_B_C_D(int curN64Stage, int curStage, GeneralCombinerInfo &gci)506{507N64CombinerType &m = (*m_ppGeneralDecodedMux)->m_n64Combiners[curN64Stage];508StageOperate *op = ((StageOperate*)(&(gci.stages[curStage].colorOp))) + (curN64Stage%2);509510N64CombinerType save = m;511if( CountTexel1Cycle(m) == 2 )512{513if( isTex(m.a) && !isTex(m.c) && curN64Stage == 0 && isTex(m.d) && toTex(m.a) != toTex(m.d) )514{515if( m_dwGeneralMaxStages >= 4 )516{517op->op = CM_SUBTRACT;518op->Arg1 = m.a;519op->Arg2 = m.b;520op->Arg0 = CM_IGNORE;521gci.stages[curStage].dwTexture = toTex(m.a);522textureUsedInStage[curStage][curN64Stage%2] = true;523NextStage(curStage);524op = ((StageOperate*)(&(gci.stages[curStage].colorOp))) + (curN64Stage%2);525op->op = CM_MULTIPLYADD;526op->Arg1 = MUX_COMBINED;527op->Arg2 = m.c;528op->Arg0 = m.d;529gci.stages[curStage].dwTexture = toTex(m.d);530textureUsedInStage[curStage][curN64Stage%2] = true;531resultIsGood = true;532}533else534{535op->op = CM_MODULATE;536op->Arg1 = m.a;537op->Arg2 = m.c;538op->Arg0 = CM_IGNORE;539gci.stages[curStage].dwTexture = toTex(m.a);540textureUsedInStage[curStage][curN64Stage%2] = true;541NextStage(curStage);542op = ((StageOperate*)(&(gci.stages[curStage].colorOp))) + (curN64Stage%2);543op->op = CM_ADD;544op->Arg1 = MUX_COMBINED;545op->Arg2 = m.d;546op->Arg0 = CM_IGNORE;547gci.stages[curStage].dwTexture = toTex(m.d);548textureUsedInStage[curStage][curN64Stage%2] = true;549resultIsGood = false;550}551}552else553{554// There are two textures555int texToUse = CheckWhichTexToUseInThisStage(curN64Stage, curStage, gci);556op->op =CM_REPLACE;557op->Arg1 = (MUX_TEXEL0+texToUse);558op->Arg2 = CM_IGNORE;559op->Arg0 = CM_IGNORE;560gci.stages[curStage].dwTexture = texToUse;561textureUsedInStage[curStage][curN64Stage%2] = true;562563(*m_ppGeneralDecodedMux)->ReplaceVal(MUX_TEXEL0+texToUse, MUX_COMBINED, curN64Stage);564565NextStage(curStage);566Check1TxtrForAlpha(curN64Stage, curStage, gci, GetTexelNumber(m));567op = ((StageOperate*)(&(gci.stages[curStage].colorOp))) + (curN64Stage%2);568569m.a = MUX_COMBINED;570m.c = MUX_TEXEL0+(1-texToUse);571m.b = m.d = 0;572curStage = GenCI_Type_A_MOD_C(curN64Stage, curStage, gci);573}574}575else if( CountTexel1Cycle(m) == 1 )576{577if( m_dwGeneralMaxStages < 4 )578{579Check1TxtrForAlpha(curN64Stage, curStage, gci, GetTexelNumber(m));580op->Arg1 = (MUX_TEXEL0+GetTexelNumber(m));581if( (*m_ppGeneralDecodedMux)->isUsedInCycle(MUX_SHADE, curN64Stage) )582{583op->op =CM_MODULATE;584op->Arg2 = MUX_SHADE;585}586else587{588op->op =CM_REPLACE;589op->Arg2 = 0;590}591op->Arg0 = CM_IGNORE;592gci.stages[curStage].dwTexture = GetTexelNumber(m);593textureUsedInStage[curStage][curN64Stage%2] = true;594}595else596{597curStage = GenCI_Type_A_SUB_B_MOD_C(curN64Stage, curStage, gci);598m.a = MUX_COMBINED;599NextStage(curStage);600curStage = GenCI_Type_A_ADD_D(curN64Stage, curStage, gci);601}602}603else604{605m.d = 0;606curStage = GenCI_Type_A_SUB_B_MOD_C(curN64Stage, curStage, gci);607m = save;608m.a = MUX_COMBINED;609m.b = m.c = 0;610NextStage(curStage);611curStage = GenCI_Type_A_ADD_D(curN64Stage, curStage, gci);612}613614m = save;615return curStage;616}617618int CGeneralCombiner::GenCI_Type_A_SUB_B_ADD_D(int curN64Stage, int curStage, GeneralCombinerInfo &gci)619{620N64CombinerType &m = (*m_ppGeneralDecodedMux)->m_n64Combiners[curN64Stage];621622N64CombinerType save = m;623m.d = MUX_0;624curStage = GenCI_Type_A_SUB_B(curN64Stage, curStage, gci);625m = save;626m.a = MUX_COMBINED;627m.b = MUX_0;628NextStage(curStage);629curStage = GenCI_Type_A_ADD_D(curN64Stage, curStage, gci);630m = save;631632return curStage;633}634635636int CGeneralCombiner::GenCI_Type_A_ADD_B_MOD_C(int curN64Stage, int curStage, GeneralCombinerInfo &gci)637{638N64CombinerType &m = (*m_ppGeneralDecodedMux)->m_n64Combiners[curN64Stage];639640N64CombinerType save = m;641m.d = m.b; m.b = 0;642curStage = GenCI_Type_A_ADD_D(curN64Stage, curStage, gci);643m = save;644m.b = MUX_0;645m.a = MUX_COMBINED;646NextStage(curStage);647curStage = GenCI_Type_A_MOD_C(curN64Stage, curStage, gci);648m = save;649650return curStage;651}652653int CGeneralCombiner::GenCI_Type_A_B_C_A(int curN64Stage, int curStage, GeneralCombinerInfo &gci)654{655// We can not do too much with this type, it is not a bad idea to use LERP to simplify it.656//return GenCI_Type_A_LERP_B_C(curN64Stage, curStage, gci);657return GenCI_Type_A_B_C_D(curN64Stage, curStage, gci);658}659660int CGeneralCombiner::GenCI_Type_A_SUB_B_MOD_C(int curN64Stage, int curStage, GeneralCombinerInfo &gci)661{662N64CombinerType &m = (*m_ppGeneralDecodedMux)->m_n64Combiners[curN64Stage];663664N64CombinerType save = m;665m.c = MUX_0;666curStage = GenCI_Type_A_SUB_B(curN64Stage, curStage, gci);667m = save;668m.b = MUX_0;669m.a = MUX_COMBINED;670NextStage(curStage);671curStage = GenCI_Type_A_MOD_C(curN64Stage, curStage, gci);672m = save;673674return curStage;675}676677/////////////////////////////////////678// End of gci generating functions //679/////////////////////////////////////680681682void CGeneralCombiner::SkipStage(StageOperate &op, int &curStage)683{684op.op = CM_REPLACE;685op.Arg1 = MUX_COMBINED;686op.Arg2 = CM_IGNORE;687op.Arg0 = CM_IGNORE;688NextStage(curStage);689}690691void CGeneralCombiner::NextStage(int &curStage)692{693if( curStage < m_dwGeneralMaxStages-1 )694{695curStage++;696}697else698{699curStage++;700resultIsGood = false;701TRACE0("Stage overflow");702}703}704705void CGeneralCombiner::Check1TxtrForAlpha(int curN64Stage, int &curStage, GeneralCombinerInfo &gci, int tex)706{707N64CombinerType &m = (*m_ppGeneralDecodedMux)->m_n64Combiners[curN64Stage];708if( curN64Stage%2 && IsTxtrUsed(m) )709{710while (curStage<m_dwGeneralMaxStages-1 && textureUsedInStage[curStage][0] && gci.stages[curStage].dwTexture != (unsigned int)(tex) )711{712StageOperate &op = ((StageOperate*)(&(gci.stages[curStage].colorOp)))[curN64Stage%2];713SkipStage(op, curStage);714}715}716}717718719int CGeneralCombiner::Check2TxtrForAlpha(int curN64Stage, int &curStage, GeneralCombinerInfo &gci, int tex1, int tex2)720{721N64CombinerType &m = (*m_ppGeneralDecodedMux)->m_n64Combiners[curN64Stage];722if( curN64Stage%2 && IsTxtrUsed(m) )723{724if( tex1 == tex2 )725{726while (curStage<m_dwGeneralMaxStages-1 && textureUsedInStage[curStage][0] && gci.stages[curStage].dwTexture != (unsigned int)tex1 )727{728StageOperate &op = ((StageOperate*)(&(gci.stages[curStage].colorOp)))[curN64Stage%2];729SkipStage(op, curStage);730}731return 1;732}733else734{735int stage1 = curStage;736int stage2 = curStage;737738while (stage1<m_dwGeneralMaxStages-1 && textureUsedInStage[stage1][0] && gci.stages[stage1].dwTexture != (unsigned int)tex1 )739{740StageOperate &op = ((StageOperate*)(&(gci.stages[stage1].colorOp)))[curN64Stage%2];741SkipStage(op, stage1);742}743744while (stage2<m_dwGeneralMaxStages-1 && textureUsedInStage[stage2][0] && gci.stages[stage2].dwTexture != (unsigned int)tex2 )745{746StageOperate &op = ((StageOperate*)(&(gci.stages[stage2].colorOp)))[curN64Stage%2];747SkipStage(op, stage2);748}749750if( stage1 <= stage2 )751{752curStage = stage1;753return 1;754}755else756{757curStage = stage2;758return 2;759}760}761}762else763{764return 0;765}766}767768769int CGeneralCombiner::CheckWhichTexToUseInThisStage(int curN64Stage, int curStage, GeneralCombinerInfo &gci)770{771// There are two texels to used, which one I should use in the current DirectX stage?772if( curN64Stage%2 )773{774if( !textureUsedInStage[curStage][0] )775return 0;776else777return gci.stages[curStage].dwTexture;778}779else780{781return 0;782}783}784785/*786*787*/788789int CGeneralCombiner::ParseDecodedMux()790{791GeneralCombinerInfo gci;792int stages[2];793794DecodedMux &mux = *(*m_ppGeneralDecodedMux);795796GenCI_Init(gci);797798for( int i=0; i<2; i++ )799{800//i=0 Color Channel801//i=1 Alpha Channel802803stages[i] = 0;804int n=0; //stage count805806for( int j=0; j<2; j++ )807{808switch( mux.splitType[i+j*2] )809{810case CM_FMT_TYPE_NOT_USED:811continue;812case CM_FMT_TYPE_D: // = D813// Alpha channel is using different texture from color channel814// and the color channel has already used texture, so alpha815// channel can not use different texture for this stage anymore,816// alpha channel need to skip a stage817n = GenCI_Type_D(j*2+i, n, gci);818if( j==0 && mux.splitType[i+2] != CM_FMT_TYPE_NOT_USED ) NextStage(n); else n++;819break;820case CM_FMT_TYPE_A_ADD_D: // = A+D821n=GenCI_Type_A_ADD_D(j*2+i, n, gci);822if( j==0 && mux.splitType[i+2] != CM_FMT_TYPE_NOT_USED ) NextStage(n); else n++;823break;824case CM_FMT_TYPE_A_MOD_C: // = A*C can mapped to MOD(arg1,arg2)825n=GenCI_Type_A_MOD_C(j*2+i, n, gci);826if( j==0 && mux.splitType[i+2] != CM_FMT_TYPE_NOT_USED ) NextStage(n); else n++;827break;828case CM_FMT_TYPE_A_SUB_B: // = A-B can mapped to SUB(arg1,arg2)829n=GenCI_Type_A_SUB_B(j*2+i, n, gci);830if( j==0 && mux.splitType[i+2] != CM_FMT_TYPE_NOT_USED ) NextStage(n); else n++;831break;832case CM_FMT_TYPE_A_MOD_C_ADD_D: // = A*C+D can mapped to MULTIPLYADD(arg1,arg2,arg0)833n=GenCI_Type_A_MOD_C_ADD_D(j*2+i, n, gci);834if( j==0 && mux.splitType[i+2] != CM_FMT_TYPE_NOT_USED ) NextStage(n); else n++;835break;836case CM_FMT_TYPE_A_LERP_B_C: // = (A-B)*C+B can mapped to LERP(arg1,arg2,arg0)837// or mapped to BLENDALPHA(arg1,arg2) if C is838// alpha channel or DIF, TEX, FAC, CUR839n=GenCI_Type_A_LERP_B_C(j*2+i, n, gci);840if( j==0 && mux.splitType[i+2] != CM_FMT_TYPE_NOT_USED ) NextStage(n); else n++;841break;842case CM_FMT_TYPE_A_SUB_B_ADD_D: // = A-B+C can not map very well in 1 stage843n=GenCI_Type_A_SUB_B_ADD_D(j*2+i, n, gci);844if( j==0 && mux.splitType[i+2] != CM_FMT_TYPE_NOT_USED ) NextStage(n); else n++;845break;846case CM_FMT_TYPE_A_SUB_B_MOD_C: // = (A-B)*C can not map very well in 1 stage847n=GenCI_Type_A_SUB_B_MOD_C(j*2+i, n, gci);848if( j==0 && mux.splitType[i+2] != CM_FMT_TYPE_NOT_USED ) NextStage(n); else n++;849break;850case CM_FMT_TYPE_A_ADD_B_MOD_C:851n=GenCI_Type_A_ADD_B_MOD_C(j*2+i, n, gci);852if( j==0 && mux.splitType[i+2] != CM_FMT_TYPE_NOT_USED ) NextStage(n); else n++;853break;854case CM_FMT_TYPE_A_B_C_A:855n=GenCI_Type_A_B_C_A(j*2+i, n, gci);856if( j==0 && mux.splitType[i+2] != CM_FMT_TYPE_NOT_USED ) NextStage(n); else n++;857break;858case CM_FMT_TYPE_A_B_C_D: // = (A-B)*C+D can not map very well in 1 stage859n=GenCI_Type_A_B_C_D(j*2+i, n, gci);860if( j==0 && mux.splitType[i+2] != CM_FMT_TYPE_NOT_USED ) NextStage(n); else n++;861break;862default:863break;864}865}866stages[i] = n;867}868869gci.nStages = max(stages[0], stages[1]);870if( gci.nStages > m_dwGeneralMaxStages )871{872resultIsGood = false;873gci.nStages = m_dwGeneralMaxStages;874}875876if( mux.m_ColorTextureFlag[0] != 0 || mux.m_ColorTextureFlag[1] != 0 )877{878resultIsGood = false;879}880881// The bResultIsGoodWithinStages is for Semi-Pixel shader combiner, don't move the code down882gci.bResultIsGoodWithinStages = resultIsGood;883if( mux.HowManyConstFactors() > 1 || gci.specularPostOp != MUX_0 || gci.blendingFunc != ENABLE_BOTH )884{885gci.bResultIsGoodWithinStages = false;886}887888if( gci.nStages > stages[0] ) // Color has less stages889{890for( int i=stages[0]; i<gci.nStages; i++ )891{892gci.stages[i].colorOp.op = CM_REPLACE;893gci.stages[i].colorOp.Arg1 = MUX_COMBINED;894gci.stages[i].colorOp.Arg2 = CM_IGNORE;895gci.stages[i].colorOp.Arg0 = CM_IGNORE;896}897}898899if( gci.nStages > stages[1] ) // Color has less stages900{901for( int i=stages[1]; i<gci.nStages; i++ )902{903gci.stages[i].alphaOp.op = CM_REPLACE;904gci.stages[i].alphaOp.Arg1 = MUX_COMBINED;905gci.stages[i].alphaOp.Arg2 = CM_IGNORE;906gci.stages[i].alphaOp.Arg0 = CM_IGNORE;907}908}909910for( int i=0;i<gci.nStages;i++)911{912gci.stages[i].bTextureUsed = IsTextureUsedInStage(gci.stages[i]);913}914915if( !resultIsGood && gci.nStages >= m_dwGeneralMaxStages )916{917extern int noOfTwoStages;918extern GeneralCombinerInfo twostages[];919920for( int k=0; k<noOfTwoStages; k++ )921{922GeneralCombinerInfo &info = twostages[k];923if( (mux.m_dwMux0 == info.dwMux0 && mux.m_dwMux1 == info.dwMux1) ||924(info.dwMux0+info.dwMux1 == 0 && info.muxDWords[0] == mux.m_dWords[0] &&925info.muxDWords[1] == mux.m_dWords[1] && info.muxDWords[2] == mux.m_dWords[2] &&926info.muxDWords[3] == mux.m_dWords[3] && info.m_dwShadeAlphaChannelFlag == mux.m_dwShadeAlphaChannelFlag &&927info.m_dwShadeColorChannelFlag == mux.m_dwShadeColorChannelFlag ) )928{929memcpy(&gci, &info, sizeof(GeneralCombinerInfo) );930resultIsGood = true;931break;932}933}934}935936#ifdef DEBUGGER937if( !resultIsGood )938{939DecodedMux &mux = *(*m_ppGeneralDecodedMux);940// Generated combiner mode is not good enough within the limited stages941DebuggerAppendMsg("\n/*");942mux.DisplayMuxString("Overflowed");943mux.DisplaySimpliedMuxString("Overflowed");944DebuggerAppendMsg("Generated combiners:");945General_DisplayBlendingStageInfo(gci);946DebuggerAppendMsg("*/\n");947DebuggerAppendMsg("\n\n");948DebuggerAppendMsg("{\n\t0x%08X, 0x%08X, 0x%08X, 0x%08X,\t// Simplified mux\n\t0x%08X, 0x%08X,\t\t// 64bit Mux\n",949mux.m_dWords[0],mux.m_dWords[1],mux.m_dWords[2],mux.m_dWords[3],mux.m_dwMux0,mux.m_dwMux1);950DebuggerAppendMsg("\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",9512,mux.m_dwShadeColorChannelFlag, mux.m_dwShadeAlphaChannelFlag,mux.m_ColorTextureFlag[0],mux.m_ColorTextureFlag[1]);952DebuggerAppendMsg("\t{\n\t\t{MOD(T0,DIF), MOD(T0,DIF), 0, true}, // Stage 0\n");953DebuggerAppendMsg("\t\t{MOD(T0,DIF), SKIP, 1, true}, // Stage 1\n\t}\n},");954}955#else956if( !resultIsGood )957{958FILE *fp=NULL;959fp = fopen("C:\\rice\\RiceVideoMUX.log","a");960if( fp )961{962fprintf(fp,"\n/*\n");963mux.LogMuxString("Overflowed",fp);964fprintf(fp,"\n\n");965mux.LogSimpliedMuxString("Overflowed",fp);966fprintf(fp,"Generated combiners:");967//General_DisplayBlendingStageInfo(gci);968fprintf(fp,"\n*/\n");969fprintf(fp,"\n");970fprintf(fp,"{\n\t0x%08X, 0x%08X, 0x%08X, 0x%08X,\t// Simplified mux\n\t0x%08X, 0x%08X,\t\t// 64bit Mux\n",971mux.m_dWords[0],mux.m_dWords[1],mux.m_dWords[2],mux.m_dWords[3],mux.m_dwMux0,mux.m_dwMux1);972fprintf(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",9732,mux.m_dwShadeColorChannelFlag, mux.m_dwShadeAlphaChannelFlag,mux.m_ColorTextureFlag[0],mux.m_ColorTextureFlag[1]);974fprintf(fp,"\t{\n\t\t{MOD(T0,DIF), MOD(T0,DIF), 0, true}, // Stage 0\n");975fprintf(fp,"\t\t{LERP(T1,CUR,DIF), SKIP, 1, true}, // Stage 1\n\t}\n},");976977fclose(fp);978}979}980#endif981982return SaveParserResult(gci);983}984985986bool CGeneralCombiner::IsTextureUsedInStage(GeneralCombineStage &stage)987{988if( (stage.colorOp.Arg1&MUX_MASK)==MUX_TEXEL0 || (stage.colorOp.Arg2&MUX_MASK)==MUX_TEXEL0 || (stage.colorOp.Arg0 &MUX_MASK)==MUX_TEXEL0 ||989(stage.alphaOp.Arg1&MUX_MASK)==MUX_TEXEL0 || (stage.alphaOp.Arg2&MUX_MASK)==MUX_TEXEL0 || (stage.alphaOp.Arg0 &MUX_MASK)==MUX_TEXEL0 ||990(stage.colorOp.Arg1&MUX_MASK)==MUX_TEXEL1 || (stage.colorOp.Arg2&MUX_MASK)==MUX_TEXEL1 || (stage.colorOp.Arg0 &MUX_MASK)==MUX_TEXEL1 ||991(stage.alphaOp.Arg1&MUX_MASK)==MUX_TEXEL1 || (stage.alphaOp.Arg2&MUX_MASK)==MUX_TEXEL1 || (stage.alphaOp.Arg0 &MUX_MASK)==MUX_TEXEL1 )992{993return true;994}995else996return false;997}9989991000int CGeneralCombiner::SaveParserResult(GeneralCombinerInfo &result)1001{1002result.muxDWords[0] = (*m_ppGeneralDecodedMux)->m_dWords[0];1003result.muxDWords[1] = (*m_ppGeneralDecodedMux)->m_dWords[1];1004result.muxDWords[2] = (*m_ppGeneralDecodedMux)->m_dWords[2];1005result.muxDWords[3] = (*m_ppGeneralDecodedMux)->m_dWords[3];1006result.m_dwShadeAlphaChannelFlag = (*m_ppGeneralDecodedMux)->m_dwShadeAlphaChannelFlag;1007result.m_dwShadeColorChannelFlag = (*m_ppGeneralDecodedMux)->m_dwShadeColorChannelFlag;1008result.colorTextureFlag[0] = (*m_ppGeneralDecodedMux)->m_ColorTextureFlag[0];1009result.colorTextureFlag[1] = (*m_ppGeneralDecodedMux)->m_ColorTextureFlag[1];1010result.dwMux0 = (*m_ppGeneralDecodedMux)->m_dwMux0;1011result.dwMux1 = (*m_ppGeneralDecodedMux)->m_dwMux1;10121013m_vCompiledCombinerStages.push_back(result);1014m_lastGeneralIndex = m_vCompiledCombinerStages.size()-1;10151016return m_lastGeneralIndex;1017}101810191020int CGeneralCombiner::FindCompiledMux( )1021{1022#ifdef DEBUGGER1023if( debuggerDropCombiners || debuggerDropGeneralCombiners )1024{1025m_vCompiledCombinerStages.clear();1026//m_dwLastMux0 = m_dwLastMux1 = 0;1027debuggerDropCombiners = false;1028debuggerDropGeneralCombiners = false;1029}1030#endif10311032for( uint32 i=0; i<m_vCompiledCombinerStages.size(); i++ )1033{1034if( m_vCompiledCombinerStages[i].dwMux0 == (*m_ppGeneralDecodedMux)->m_dwMux0 && m_vCompiledCombinerStages[i].dwMux1 == (*m_ppGeneralDecodedMux)->m_dwMux1 )1035{1036m_lastGeneralIndex = i;1037return i;1038}1039}10401041return -1;1042}1043104410451046bool LM_textureUsedInStage[8];1047void CGeneralCombiner::LM_GenCI_Init(GeneralCombinerInfo &gci)1048{1049gci.specularPostOp=gci.TFactor=MUX_0;10501051gci.blendingFunc = ENABLE_BOTH;10521053for( int i=0; i<8; i++)1054{1055gci.stages[i].dwTexture = 0;1056LM_textureUsedInStage[i] = false;1057}1058}105910601061//#define fillstage(opr,a1,a2,a3) {op->op=opr;op->Arg1=a1;op->Arg2=a2;op->Arg0=a3;curStage++;}1062inline void FillStage(StageOperate &op, uint32 opr, uint32 a1, uint32 a2, uint32 a3)1063{1064op.op = opr;1065op.Arg1 = a1;1066op.Arg2 = a2;1067op.Arg0 = a3;1068}10691070/************************************************************************/1071/* New functions, will generate stages within stage limited */1072/* and return the number of stages used. */1073/************************************************************************/1074int CGeneralCombiner::LM_GenCI_Type_D(N64CombinerType &m, int curStage, int limit, int channel, bool checktexture, GeneralCombinerInfo &gci)1075{1076int originalstage=curStage;1077StageOperate *op = ((StageOperate*)(&(gci.stages[curStage]))) + channel;1078if( checktexture && LM_Check1TxtrForAlpha(curStage, gci, m.d ) )1079{1080if( limit > 1 )1081{1082FillStage(*op,CM_REPLACE,MUX_COMBINED,CM_IGNORE,CM_IGNORE);1083curStage++;1084op = ((StageOperate*)(&(gci.stages[curStage]))) + channel;1085FillStage(*op,CM_REPLACE,m.d,CM_IGNORE,CM_IGNORE);1086}1087else1088{1089// It is not allowed to use two stages, what to do?1090// It should not happen anyway1091TRACE0("Check me here, at LM_GenCI_Type_D");1092}1093}1094else1095{1096FillStage(*op,CM_REPLACE,m.d,CM_IGNORE,CM_IGNORE);1097}10981099gci.stages[curStage].dwTexture = GetTexelNumber(m);1100LM_textureUsedInStage[curStage] = IsTxtrUsed(m);1101curStage++;11021103return curStage-originalstage;1104}1105int CGeneralCombiner::LM_GenCI_Type_A_MOD_C(N64CombinerType &m, int curStage, int limit, int channel, bool checktexture, GeneralCombinerInfo &gci, uint32 dxop)1106{1107int originalstage=curStage;1108StageOperate *op = ((StageOperate*)(&(gci.stages[curStage].colorOp))) + channel;11091110int numberOfTex = CountTexel1Cycle(m);11111112if( numberOfTex == 2 )1113{1114// As we can not use both texture in one stage1115// we split them to two stages1116// Stage1: SELECT txt11117// Stage2: MOD txt211181119if( checktexture )1120{1121if( LM_Check1TxtrForAlpha(curStage, gci, m.a ) )1122{1123FillStage(*op,CM_REPLACE,m.c,CM_IGNORE,CM_IGNORE);1124gci.stages[curStage].dwTexture = toTex(m.c);1125LM_textureUsedInStage[curStage] = true;1126curStage++;11271128op = ((StageOperate*)(&(gci.stages[curStage].colorOp))) + channel;1129FillStage(*op,dxop,m.a,MUX_COMBINED,CM_IGNORE);1130gci.stages[curStage].dwTexture = toTex(m.a);1131LM_textureUsedInStage[curStage] = true;1132curStage++;1133}1134else1135{1136FillStage(*op,CM_REPLACE,m.a,CM_IGNORE,CM_IGNORE);1137gci.stages[curStage].dwTexture = toTex(m.a);1138LM_textureUsedInStage[curStage] = true;1139curStage++;11401141op = ((StageOperate*)(&(gci.stages[curStage].colorOp))) + channel;1142FillStage(*op,dxop,m.c,MUX_COMBINED,CM_IGNORE);1143gci.stages[curStage].dwTexture = toTex(m.c);1144LM_textureUsedInStage[curStage] = true;1145curStage++;1146}1147}1148else1149{1150FillStage(*op,CM_REPLACE,m.a,CM_IGNORE,CM_IGNORE);1151gci.stages[curStage].dwTexture = toTex(m.a);1152LM_textureUsedInStage[curStage] = true;1153curStage++;11541155op = ((StageOperate*)(&(gci.stages[curStage].colorOp))) + channel;1156FillStage(*op,dxop,m.c,MUX_COMBINED,CM_IGNORE);1157gci.stages[curStage].dwTexture = toTex(m.c);1158LM_textureUsedInStage[curStage] = true;1159curStage++;1160}1161}1162else if( numberOfTex == 1)1163{1164if( checktexture )1165{1166if( isTex(m.a) )1167{1168if( LM_Check1TxtrForAlpha(curStage, gci, m.a ) )1169{1170FillStage(*op,CM_REPLACE,m.c,CM_IGNORE,CM_IGNORE);1171curStage++;11721173op = ((StageOperate*)(&(gci.stages[curStage].colorOp))) + channel;1174FillStage(*op,dxop,m.a,MUX_COMBINED,CM_IGNORE);1175gci.stages[curStage].dwTexture = toTex(m.a);1176LM_textureUsedInStage[curStage] = true;1177curStage++;1178}1179else1180{1181FillStage(*op,CM_REPLACE,m.a,CM_IGNORE,CM_IGNORE);1182gci.stages[curStage].dwTexture = toTex(m.a);1183LM_textureUsedInStage[curStage] = true;1184curStage++;11851186op = ((StageOperate*)(&(gci.stages[curStage].colorOp))) + channel;1187FillStage(*op,dxop,m.c,MUX_COMBINED,CM_IGNORE);1188curStage++;1189}1190}1191else1192{1193if( LM_Check1TxtrForAlpha(curStage, gci, m.c ) )1194{1195FillStage(*op,CM_REPLACE,m.a,CM_IGNORE,CM_IGNORE);1196curStage++;11971198op = ((StageOperate*)(&(gci.stages[curStage].colorOp))) + channel;1199FillStage(*op,dxop,m.c,MUX_COMBINED,CM_IGNORE);1200gci.stages[curStage].dwTexture = toTex(m.c);1201LM_textureUsedInStage[curStage] = true;1202curStage++;1203}1204else1205{1206FillStage(*op,CM_REPLACE,m.c,CM_IGNORE,CM_IGNORE);1207gci.stages[curStage].dwTexture = toTex(m.c);1208LM_textureUsedInStage[curStage] = true;1209curStage++;12101211op = ((StageOperate*)(&(gci.stages[curStage].colorOp))) + channel;1212FillStage(*op,dxop,m.a,MUX_COMBINED,CM_IGNORE);1213curStage++;1214}1215}1216}1217else1218{1219if( isTex(m.a) )1220{1221FillStage(*op,CM_REPLACE,m.a,CM_IGNORE,CM_IGNORE);1222gci.stages[curStage].dwTexture = toTex(m.a);1223LM_textureUsedInStage[curStage] = true;1224curStage++;12251226op = ((StageOperate*)(&(gci.stages[curStage].colorOp))) + channel;1227FillStage(*op,dxop,m.c,MUX_COMBINED,CM_IGNORE);1228curStage++;1229}1230else1231{1232FillStage(*op,CM_REPLACE,m.c,CM_IGNORE,CM_IGNORE);1233gci.stages[curStage].dwTexture = toTex(m.c);1234LM_textureUsedInStage[curStage] = true;1235curStage++;12361237op = ((StageOperate*)(&(gci.stages[curStage].colorOp))) + channel;1238FillStage(*op,dxop,m.a,MUX_COMBINED,CM_IGNORE);1239curStage++;1240}12411242}1243}1244else1245{1246FillStage(*op,dxop,m.a,m.c,CM_IGNORE);1247curStage++;1248}12491250return curStage-originalstage;1251}1252int CGeneralCombiner::LM_GenCI_Type_A_ADD_D(N64CombinerType &m, int curStage, int limit, int channel, bool checktexture, GeneralCombinerInfo &gci)1253{1254return 0;1255}1256int CGeneralCombiner::LM_GenCI_Type_A_SUB_B(N64CombinerType &m, int curStage, int limit, int channel, bool checktexture, GeneralCombinerInfo &gci)1257{1258return 0;1259}1260int CGeneralCombiner::LM_GenCI_Type_A_LERP_B_C(N64CombinerType &m, int curStage, int limit, int channel, bool checktexture, GeneralCombinerInfo &gci)1261{1262return 0;1263}1264int CGeneralCombiner::LM_GenCI_Type_A_MOD_C_ADD_D(N64CombinerType &m, int curStage, int limit, int channel, bool checktexture, GeneralCombinerInfo &gci)1265{1266return 0;1267}1268int CGeneralCombiner::LM_GenCI_Type_A_SUB_B_ADD_D(N64CombinerType &m, int curStage, int limit, int channel, bool checktexture, GeneralCombinerInfo &gci)1269{1270return 0;1271}1272int CGeneralCombiner::LM_GenCI_Type_A_SUB_B_MOD_C(N64CombinerType &m, int curStage, int limit, int channel, bool checktexture, GeneralCombinerInfo &gci)1273{1274return 0;1275}1276int CGeneralCombiner::LM_GenCI_Type_A_ADD_B_MOD_C(N64CombinerType &m, int curStage, int limit, int channel, bool checktexture, GeneralCombinerInfo &gci)1277{1278return 0;1279}1280int CGeneralCombiner::LM_GenCI_Type_A_B_C_D(N64CombinerType &m, int curStage, int limit, int channel, bool checktexture, GeneralCombinerInfo &gci)1281{1282return 0;1283}1284int CGeneralCombiner::LM_GenCI_Type_A_B_C_A(N64CombinerType &m, int curStage, int limit, int channel, bool checktexture, GeneralCombinerInfo &gci)1285{1286return 0;1287}12881289int CGeneralCombiner::LM_ParseDecodedMux()1290{1291return 0;1292}12931294bool CGeneralCombiner::LM_Check1TxtrForAlpha(int curStage, GeneralCombinerInfo &gci, uint32 val )1295{1296return !( isTex(val) && LM_textureUsedInStage[curStage] && gci.stages[curStage].dwTexture != (unsigned int)toTex(val) );1297}129812991300void CGeneralCombiner::LM_SkipStage(StageOperate &op)1301{1302op.op = CM_REPLACE;1303op.Arg1 = MUX_COMBINED;1304op.Arg2 = CM_IGNORE;1305op.Arg0 = CM_IGNORE;1306}1307130813091310