Path: blob/master/libmupen64plus/mupen64plus-video-rice/src/Combiner.cpp
2 views
/*1Copyright (C) 2002 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.1617*/1819#include "Combiner.h"20#include "Config.h"21#include "RenderBase.h"2223//static BOOL g_bHiliteRGBAHack = FALSE;242526#ifdef DEBUGGER27const char *constStrs[] = {28"MUX_0",29"MUX_1",30"MUX_COMBINED",31"MUX_TEXEL0",32"MUX_TEXEL1",33"MUX_PRIM",34"MUX_SHADE",35"MUX_ENV",36"MUX_COMBALPHA",37"MUX_T0_ALPHA",38"MUX_T1_ALPHA",39"MUX_PRIM_ALPHA",40"MUX_SHADE_ALPHA",41"MUX_ENV_ALPHA",42"MUX_LODFRAC",43"MUX_PRIMLODFRAC",44"MUX_K5",45"MUX_UNK",46};4748const char *cycleTypeStrs[] = {49"1 Cycle",50"2 Cycle",51"Copy Mode",52"Fill Mode"53};5455const char* constStr(uint32 op)56{57if(op<=MUX_UNK)58return constStrs[op];59else60return "Invalid-Const";61}62#endif6364void swap(uint8 &a, uint8 &b)65{66uint8 c=a;67a=b;68b=c;69}707172//========================================================================7374//========================================================================7576inline IColor GetIColor(uint8 flag, uint32 curCol)77{78IColor newc;79switch(flag&MUX_MASK)80{81case MUX_0:82newc = 0;83break;84case MUX_1:85newc = 0xFFFFFFFF;86break;87case MUX_PRIM:88newc = gRDP.primitiveColor;89break;90case MUX_ENV:91newc = gRDP.envColor;92break;93case MUX_COMBINED:94case MUX_SHADE:95newc = curCol;96break;97case MUX_K5:98newc = 0xFFFFFFFF;99break;100case MUX_UNK:101newc = curCol;102if( options.enableHackForGames == HACK_FOR_CONKER )103newc = 0xFFFFFFFF;104break;105default:106newc = curCol;107break;108}109110if( flag&MUX_COMPLEMENT )111{112newc.Complement();113}114115if( flag&MUX_ALPHAREPLICATE )116{117newc.AlphaReplicate();118}119120return newc;121}122123COLOR CalculateConstFactor(uint32 colorOp, uint32 alphaOp, uint32 curCol)124{125N64CombinerType m;126IColor color(curCol);127IColor alpha(curCol);128129// For color channel130*(uint32*)&m = colorOp;131if( m.c != MUX_0 && m.a!=m.b)132{133if( m.a != MUX_0 ) color = GetIColor(m.a, curCol);134if( m.b != MUX_0 ) color -= GetIColor(m.b, curCol);135if( m.c != MUX_1 ) color *= GetIColor(m.c, curCol);136}137if( m.d != MUX_0 ) color += GetIColor(m.d, curCol);138139// For alpha channel140*(uint32*)&m = alphaOp;141if( m.c != MUX_0 && m.a!=m.b)142{143if( m.a != MUX_0 ) alpha = GetIColor(m.a, curCol);144if( m.b != MUX_0 ) alpha -= GetIColor(m.b, curCol);145if( m.c != MUX_1 ) alpha *= GetIColor(m.c, curCol);146}147if( m.d != MUX_0 ) alpha += GetIColor(m.d, curCol);148149return (COLOR)(((uint32)color&0x00FFFFFF)|((uint32)alpha&0xFF000000));150}151152153COLOR CColorCombiner::GetConstFactor(uint32 colorFlag, uint32 alphaFlag, uint32 defaultColor)154{155// Allows a combine mode to select what TFACTOR should be156uint32 color = defaultColor;157uint32 alpha = defaultColor;158159switch (colorFlag&MUX_MASK)160{161case MUX_0:162break;163case MUX_FORCE_0:164color = 0;165break;166case MUX_1:167color = 0xFFFFFFFF;168break;169case MUX_PRIM:170color = gRDP.primitiveColor;171break;172case MUX_ENV:173color = gRDP.envColor;174break;175case MUX_LODFRAC:176color = COLOR_RGBA(gRDP.LODFrac, gRDP.LODFrac, gRDP.LODFrac, gRDP.LODFrac);177break;178case MUX_PRIMLODFRAC:179color = COLOR_RGBA(gRDP.primLODFrac, gRDP.primLODFrac, gRDP.primLODFrac, gRDP.primLODFrac);180break;181case MUX_PRIM_ALPHA:182{183IColor col(gRDP.primitiveColor);184col.AlphaReplicate();185color = (COLOR)col;186}187break;188case MUX_ENV_ALPHA:189{190IColor col(gRDP.envColor);191col.AlphaReplicate();192color = (COLOR)col;193}194break;195case MUX_K5:196color = 0xFFFFFFFF;197break;198case MUX_UNK:199color = defaultColor;200if( options.enableHackForGames == HACK_FOR_CONKER ) color = 0xFFFFFFFF;201break;202default:203color = defaultColor;204break;205}206207if( colorFlag & MUX_COMPLEMENT )208{209color = 0xFFFFFFFF - color;210}211if( colorFlag & MUX_ALPHAREPLICATE )212{213color = color>>24;214color = color | (color<<8) | (color <<16) | (color<<24);215}216217color &= 0x00FFFFFF; // For color channel only, not the alpha channel218219220switch (alphaFlag&MUX_MASK)221{222case MUX_0:223break;224case MUX_FORCE_0:225alpha = 0;226break;227case MUX_1:228alpha = 0xFFFFFFFF;229break;230case MUX_PRIM:231alpha = gRDP.primitiveColor;232break;233case MUX_ENV:234alpha = gRDP.envColor;235break;236case MUX_LODFRAC:237alpha = COLOR_RGBA(gRDP.LODFrac, gRDP.LODFrac, gRDP.LODFrac, gRDP.LODFrac);238break;239case MUX_PRIMLODFRAC:240alpha = COLOR_RGBA(gRDP.primLODFrac, gRDP.primLODFrac, gRDP.primLODFrac, gRDP.primLODFrac);241break;242case MUX_PRIM_ALPHA:243{244IColor col(gRDP.primitiveColor);245col.AlphaReplicate();246alpha = (COLOR)col;247}248break;249case MUX_ENV_ALPHA:250{251IColor col(gRDP.envColor);252col.AlphaReplicate();253alpha = (COLOR)col;254}255break;256default:257alpha = defaultColor;258break;259}260261if( alphaFlag & MUX_COMPLEMENT )262{263alpha = 0xFFFFFFFF - alpha;264}265266alpha &= 0xFF000000;267268return (color|alpha);269}270271//*****************************************************************************272//273//*****************************************************************************274bool gUsingPrimColour = false;275bool gUsingEnvColour = false;276277int CountTexel1Cycle(N64CombinerType &m)278{279int hasTexel[2];280uint8 *p = (uint8*)&m;281282for( int i=0; i<2; i++)283{284hasTexel[i]=0;285for( int j=0; j<4; j++)286{287if( (p[j]&MUX_MASK) == MUX_TEXEL0+i )288{289hasTexel[i]=1;290break;291}292}293}294295return hasTexel[0]+hasTexel[1];296}297298uint32 GetTexelNumber(N64CombinerType &m)299{300if( (m.a&MUX_MASK) == MUX_TEXEL1 || (m.b&MUX_MASK) == MUX_TEXEL1 || (m.c&MUX_MASK) == MUX_TEXEL1 || (m.d&MUX_MASK) == MUX_TEXEL1 )301return TEX_1;302else303return TEX_0;304}305306bool IsTxtrUsed(N64CombinerType &m)307{308if( (m.a&MUX_MASK) == MUX_TEXEL1 || (m.b&MUX_MASK) == MUX_TEXEL1 || (m.c&MUX_MASK) == MUX_TEXEL1 || (m.d&MUX_MASK) == MUX_TEXEL1 )309return true;310if( (m.a&MUX_MASK) == MUX_TEXEL0 || (m.b&MUX_MASK) == MUX_TEXEL0 || (m.c&MUX_MASK) == MUX_TEXEL0 || (m.d&MUX_MASK) == MUX_TEXEL0 )311return true;312else313return false;314}315316//========================================================================317318void CColorCombiner::InitCombinerMode(void)319{320#ifdef DEBUGGER321LOG_UCODE(cycleTypeStrs[gRDP.otherMode.cycle_type]);322if( debuggerDropDecodedMux )323{324UpdateCombiner(m_pDecodedMux->m_dwMux0, m_pDecodedMux->m_dwMux1);325}326#endif327328if( currentRomOptions.bNormalCombiner )329{330DisableCombiner();331}332else if( gRDP.otherMode.cycle_type == CYCLE_TYPE_COPY )333{334InitCombinerCycleCopy();335m_bCycleChanged = true;336}337else if ( gRDP.otherMode.cycle_type == CYCLE_TYPE_FILL )338//else if ( gRDP.otherMode.cycle_type == CYCLE_TYPE_FILL && gRSP.ucode != 5 ) //hack339{340InitCombinerCycleFill();341m_bCycleChanged = true;342}343else344{345InitCombinerCycle12();346m_bCycleChanged = false;347}348}349350351bool bConkerHideShadow=false;352void CColorCombiner::UpdateCombiner(uint32 dwMux0, uint32 dwMux1)353{354#ifdef DEBUGGER355if( debuggerDropDecodedMux )356{357debuggerDropDecodedMux = false;358m_pDecodedMux->m_dwMux0 = m_pDecodedMux->m_dwMux1 = 0;359m_DecodedMuxList.clear();360}361#endif362363DecodedMux &m_decodedMux = *m_pDecodedMux;364if( m_decodedMux.m_dwMux0 != dwMux0 || m_decodedMux.m_dwMux1 != dwMux1 )365{366if( options.enableHackForGames == HACK_FOR_DR_MARIO )367{368// Hack for Dr. Mario369if( dwMux1 == 0xfffcf239 &&370((m_decodedMux.m_dwMux0 == dwMux0 && dwMux0 == 0x00ffffff &&371m_decodedMux.m_dwMux1 != dwMux1 && m_decodedMux.m_dwMux1 == 0xfffcf279 ) ||372(m_decodedMux.m_dwMux0 == 0x00ffb3ff && m_decodedMux.m_dwMux1 == 0xff64fe7f && dwMux0 == 0x00ffffff ) ))373{374//dwMux1 = 0xffcf23A;375dwMux1 = 0xfffcf438;376}377}378uint64 mux64 = (((uint64)dwMux1)<<32)+dwMux0;379int index=m_DecodedMuxList.find(mux64);380381if( options.enableHackForGames == HACK_FOR_CONKER )382{383// Conker's shadow, to disable the shadow384//Mux=0x00ffe9ff Used in CONKER BFD385//Color0: (0 - 0) * 0 + SHADE386//Color1: (0 - 0) * 0 + SHADE387//Alpha0: (1 - TEXEL0) * SHADE + 0388//Alpha1: (1 - TEXEL0) * SHADE + 0389if( dwMux1 == 0xffd21f0f && dwMux0 == 0x00ffe9ff )390{391bConkerHideShadow = true;392}393else394{395bConkerHideShadow = false;396}397}398399if( index >= 0 )400{401m_decodedMux = m_DecodedMuxList[index];402}403else404{405m_decodedMux.Decode(dwMux0, dwMux1);406m_decodedMux.splitType[0] = CM_FMT_TYPE_NOT_CHECKED;407m_decodedMux.splitType[1] = CM_FMT_TYPE_NOT_CHECKED;408m_decodedMux.splitType[2] = CM_FMT_TYPE_NOT_CHECKED;409m_decodedMux.splitType[3] = CM_FMT_TYPE_NOT_CHECKED;410411m_decodedMux.Hack();412413if( !m_bSupportMultiTexture )414{415m_decodedMux.ReplaceVal(MUX_TEXEL1, MUX_TEXEL0);416m_decodedMux.ReplaceVal(MUX_LODFRAC,1);417m_decodedMux.ReplaceVal(MUX_PRIMLODFRAC,1);418}419420m_decodedMux.Simplify();421if( m_supportedStages>1)422m_decodedMux.SplitComplexStages();423424m_DecodedMuxList.add(m_decodedMux.m_u64Mux, *m_pDecodedMux);425#ifdef DEBUGGER426if( logCombiners )427{428TRACE0("Add a new mux");429DisplayMuxString();430}431#endif432}433434m_bTex0Enabled = m_decodedMux.m_bTexel0IsUsed;435m_bTex1Enabled = m_decodedMux.m_bTexel1IsUsed;436m_bTexelsEnable = m_bTex0Enabled||m_bTex1Enabled;437438gRSP.bProcessDiffuseColor = (m_decodedMux.m_dwShadeColorChannelFlag != MUX_0 || m_decodedMux.m_dwShadeAlphaChannelFlag != MUX_0);439gRSP.bProcessSpecularColor = false;440}441}442443444#ifdef DEBUGGER445void CColorCombiner::DisplayMuxString(void)446{447if( gRDP.otherMode.cycle_type == CYCLE_TYPE_COPY)448{449TRACE0("COPY Mode\n");450}451else if( gRDP.otherMode.cycle_type == CYCLE_TYPE_FILL)452{453TRACE0("FILL Mode\n");454}455456m_pDecodedMux->DisplayMuxString("Used");457}458459void CColorCombiner::DisplaySimpleMuxString(void)460{461m_pDecodedMux->DisplaySimpliedMuxString("Used");462}463#endif464465466467