2 Copyright (C) 2002 Rice1964
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21 #include "GeneralCombiner.h"
24 #include "RenderBase.h"
26 #define ALLOW_USE_TEXTURE_FOR_CONSTANTS
28 static const uint8 sc_Mux32[32] =
30 MUX_COMBINED, MUX_TEXEL0, MUX_TEXEL1, MUX_PRIM,
31 MUX_SHADE, MUX_ENV, MUX_1, MUX_COMBINED|MUX_ALPHAREPLICATE,
32 MUX_TEXEL0|MUX_ALPHAREPLICATE, MUX_TEXEL1|MUX_ALPHAREPLICATE, MUX_PRIM|MUX_ALPHAREPLICATE, MUX_SHADE|MUX_ALPHAREPLICATE,
33 MUX_ENV|MUX_ALPHAREPLICATE, MUX_LODFRAC, MUX_PRIMLODFRAC, MUX_K5, // Actually k5
34 MUX_UNK, MUX_UNK, MUX_UNK, MUX_UNK,
35 MUX_UNK, MUX_UNK, MUX_UNK, MUX_UNK,
36 MUX_UNK, MUX_UNK, MUX_UNK, MUX_UNK,
37 MUX_UNK, MUX_UNK, MUX_UNK, MUX_0
40 static const uint8 sc_Mux16[16] =
42 MUX_COMBINED, MUX_TEXEL0, MUX_TEXEL1, MUX_PRIM,
43 MUX_SHADE, MUX_ENV, MUX_1, MUX_COMBALPHA,
44 MUX_TEXEL0|MUX_ALPHAREPLICATE, MUX_TEXEL1|MUX_ALPHAREPLICATE, MUX_PRIM|MUX_ALPHAREPLICATE, MUX_SHADE|MUX_ALPHAREPLICATE,
45 MUX_ENV|MUX_ALPHAREPLICATE, MUX_LODFRAC, MUX_PRIMLODFRAC, MUX_0
47 static const uint8 sc_Mux8[8] =
49 MUX_COMBINED, MUX_TEXEL0, MUX_TEXEL1, MUX_PRIM,
50 MUX_SHADE, MUX_ENV, MUX_1, MUX_0
54 const char * translatedCombTypes[] =
74 "FACTOR_PRIM_MINUS_ENV",
75 "FACTOR_ENV_MINUS_PRIM",
76 "FACTOR_1_MINUS_PRIM",
77 "FACTOR_0_MINUS_PRIM",
80 "FACTOR_1_MINUS_PRIMALPHA",
81 "FACTOR_1_MINUS_ENVALPHA",
84 "1_MINUS_PRIM_X_ENV_PLUS_PRIM",
91 const char* muxTypeStrs[] = {
92 "CM_FMT_TYPE_NOT_USED",
94 "CM_FMT_TYPE2_A_ADD_D",
95 "CM_FMT_TYPE3_A_MOD_C",
96 "CM_FMT_TYPE4_A_SUB_B",
97 "CM_FMT_TYPE5_A_MOD_C_ADD_D",
98 "CM_FMT_TYPE6_A_LERP_B_C",
99 "CM_FMT_TYPE7_A_SUB_B_ADD_D",
100 "CM_FMT_TYPE8_A_SUB_B_MOD_C",
101 "CM_FMT_TYPE9_A_B_C_D",
102 "CM_FMT_TYPE_NOT_CHECKED",
105 void DecodedMux::Decode(uint32 dwMux0, uint32 dwMux1)
110 aRGB0 = uint8((dwMux0>>20)&0x0F); // c1 c1 // a0
111 bRGB0 = uint8((dwMux1>>28)&0x0F); // c1 c2 // b0
112 cRGB0 = uint8((dwMux0>>15)&0x1F); // c1 c3 // c0
113 dRGB0 = uint8((dwMux1>>15)&0x07); // c1 c4 // d0
115 aA0 = uint8((dwMux0>>12)&0x07); // c1 a1 // Aa0
116 bA0 = uint8((dwMux1>>12)&0x07); // c1 a2 // Ab0
117 cA0 = uint8((dwMux0>>9 )&0x07); // c1 a3 // Ac0
118 dA0 = uint8((dwMux1>>9 )&0x07); // c1 a4 // Ad0
120 aRGB1 = uint8((dwMux0>>5 )&0x0F); // c2 c1 // a1
121 bRGB1 = uint8((dwMux1>>24)&0x0F); // c2 c2 // b1
122 cRGB1 = uint8((dwMux0 )&0x1F); // c2 c3 // c1
123 dRGB1 = uint8((dwMux1>>6 )&0x07); // c2 c4 // d1
125 aA1 = uint8((dwMux1>>21)&0x07); // c2 a1 // Aa1
126 bA1 = uint8((dwMux1>>3 )&0x07); // c2 a2 // Ab1
127 cA1 = uint8((dwMux1>>18)&0x07); // c2 a3 // Ac1
128 dA1 = uint8((dwMux1 )&0x07); // c2 a4 // Ad1
130 //This fuction will translate the decode mux info further, so we can use
131 //the decode data better.
132 //Will translate A,B,C,D to unified presentation
133 aRGB0 = sc_Mux16[aRGB0];
134 bRGB0 = sc_Mux16[bRGB0];
135 cRGB0 = sc_Mux32[cRGB0];
136 dRGB0 = sc_Mux8[dRGB0];
143 aRGB1 = sc_Mux16[aRGB1];
144 bRGB1 = sc_Mux16[bRGB1];
145 cRGB1 = sc_Mux32[cRGB1];
146 dRGB1 = sc_Mux8[dRGB1];
153 m_bShadeIsUsed[1] = isUsedInAlphaChannel(MUX_SHADE);
154 m_bShadeIsUsed[0] = isUsedInColorChannel(MUX_SHADE);
155 m_bTexel0IsUsed = isUsed(MUX_TEXEL0);
156 m_bTexel1IsUsed = isUsed(MUX_TEXEL1);
158 m_dwShadeColorChannelFlag = 0;
159 m_dwShadeAlphaChannelFlag = 0;
160 m_ColorTextureFlag[0] = 0;
161 m_ColorTextureFlag[1] = 0;
164 int DecodedMux::Count(uint8 val, int cycle, uint8 mask)
166 uint8* pmux = m_bytes;
178 for( int i=start; i<end; i++ )
180 if( (pmux[i]&mask) == (val&mask) )
190 bool DecodedMux::isUsed(uint8 val, uint8 mask)
192 uint8* pmux = m_bytes;
194 for( int i=0; i<16; i++ )
196 if( (pmux[i]&mask) == (val&mask) )
206 bool DecodedMux::isUsedInAlphaChannel(uint8 val, uint8 mask)
208 uint8* pmux = m_bytes;
210 for( int i=0; i<16; i++ )
213 continue; //Don't test color channel
215 if( (pmux[i]&mask) == (val&mask) )
225 bool DecodedMux::isUsedInColorChannel(uint8 val, uint8 mask)
227 uint8* pmux = m_bytes;
229 for( int i=0; i<16; i++ )
231 if( (i/4)%2 == 0 && (pmux[i]&mask) == (val&mask) )
242 bool DecodedMux::isUsedInCycle(uint8 val, int cycle, CombineChannel channel, uint8 mask)
245 if( channel == ALPHA_CHANNEL ) cycle++;
247 uint8* pmux = m_bytes;
248 for( int i=0; i<4; i++ )
250 if( (pmux[i+cycle*4]&mask) == (val&mask) )
259 bool DecodedMux::isUsedInCycle(uint8 val, int cycle, uint8 mask)
261 return isUsedInCycle(val, cycle/2, cycle%2?ALPHA_CHANNEL:COLOR_CHANNEL, mask);
265 void DecodedMux::ConvertComplements()
267 //For (A-B)*C+D, if A=1, then we can convert A-B to Ac-0
268 if( aRGB0 != MUX_1 && bRGB0 != MUX_0 )
270 aRGB0 = bRGB0|MUX_COMPLEMENT;
273 if( aRGB1 != MUX_1 && bRGB1 != MUX_0 )
275 aRGB1 = bRGB1|MUX_COMPLEMENT;
278 if( aA0 != MUX_1 && bA0 != MUX_0 )
280 aA0 = bA0|MUX_COMPLEMENT;
283 if( aA1 != MUX_1 && bA1 != MUX_0 )
285 aA1 = bA1|MUX_COMPLEMENT;
291 CombinerFormatType DecodedMux::GetCombinerFormatType(uint32 cycle)
293 //Analyze the formula
303 return CM_FMT_TYPE_D;
306 void DecodedMuxForPixelShader::Simplify(void)
308 CheckCombineInCycle1();
311 if( g_curRomInfo.bTexture1Hack )
313 ReplaceVal(MUX_TEXEL1,MUX_TEXEL0,2);
314 ReplaceVal(MUX_TEXEL1,MUX_TEXEL0,3);
316 splitType[0] = CM_FMT_TYPE_NOT_USED;
317 splitType[1] = CM_FMT_TYPE_NOT_USED;
318 splitType[2] = CM_FMT_TYPE_NOT_USED;
319 splitType[3] = CM_FMT_TYPE_NOT_USED;
320 mType = CM_FMT_TYPE_NOT_USED;
322 m_bTexel0IsUsed = isUsed(MUX_TEXEL0);
323 m_bTexel1IsUsed = isUsed(MUX_TEXEL1);
326 void DecodedMuxForSemiPixelShader::Reset(void)
328 Decode(m_dwMux0, m_dwMux1);
329 splitType[0] = CM_FMT_TYPE_NOT_CHECKED;
330 splitType[1] = CM_FMT_TYPE_NOT_CHECKED;
331 splitType[2] = CM_FMT_TYPE_NOT_CHECKED;
332 splitType[3] = CM_FMT_TYPE_NOT_CHECKED;
336 gRSP.bProcessDiffuseColor = false;
337 gRSP.bProcessSpecularColor = false;
339 CheckCombineInCycle1();
340 if( g_curRomInfo.bTexture1Hack )
342 ReplaceVal(MUX_TEXEL1,MUX_TEXEL0,2);
343 ReplaceVal(MUX_TEXEL1,MUX_TEXEL0,3);
346 m_bTexel0IsUsed = isUsed(MUX_TEXEL0);
347 m_bTexel1IsUsed = isUsed(MUX_TEXEL1);
350 void DecodedMuxForOGL14V2::Simplify(void)
352 CheckCombineInCycle1();
353 if( g_curRomInfo.bTexture1Hack )
355 ReplaceVal(MUX_TEXEL1,MUX_TEXEL0,2);
356 ReplaceVal(MUX_TEXEL1,MUX_TEXEL0,3);
360 UseTextureForConstant();
363 m_bTexel0IsUsed = isUsed(MUX_TEXEL0);
364 m_bTexel1IsUsed = isUsed(MUX_TEXEL1);
367 void DecodedMux::Simplify(void)
369 CheckCombineInCycle1();
370 if( gRDP.otherMode.text_lod )
372 if( g_curRomInfo.bTexture1Hack )
374 ReplaceVal(MUX_TEXEL1,MUX_TEXEL0,2);
375 ReplaceVal(MUX_TEXEL1,MUX_TEXEL0,3);
379 UseShadeForConstant();
382 if( m_dwShadeColorChannelFlag == MUX_0 )
384 MergeShadeWithConstants();
388 #ifdef ALLOW_USE_TEXTURE_FOR_CONSTANTS
389 UseTextureForConstant();
390 for( int i=0; i<2; i++ )
392 if( m_ColorTextureFlag[i] != 0 )
394 if( m_dwShadeColorChannelFlag == m_ColorTextureFlag[i] )
396 ReplaceVal(MUX_SHADE,MUX_TEXEL0+i,N64Cycle0RGB);
397 ReplaceVal(MUX_SHADE,MUX_TEXEL0+i,N64Cycle1RGB);
398 m_dwShadeColorChannelFlag = 0;
400 if( m_dwShadeAlphaChannelFlag == m_ColorTextureFlag[i] )
402 ReplaceVal(MUX_SHADE,MUX_TEXEL0+i,N64Cycle0Alpha);
403 ReplaceVal(MUX_SHADE,MUX_TEXEL0+i,N64Cycle1Alpha);
404 ReplaceVal(MUX_SHADE|MUX_ALPHAREPLICATE,(MUX_TEXEL0+i)|MUX_ALPHAREPLICATE,N64Cycle0RGB,MUX_MASK_WITH_ALPHA);
405 ReplaceVal(MUX_SHADE|MUX_ALPHAREPLICATE,(MUX_TEXEL0+i)|MUX_ALPHAREPLICATE,N64Cycle1RGB,MUX_MASK_WITH_ALPHA);
406 m_dwShadeAlphaChannelFlag = 0;
413 m_bTexel0IsUsed = isUsed(MUX_TEXEL0);
414 m_bTexel1IsUsed = isUsed(MUX_TEXEL1);
417 void DecodedMux::Reformat(bool do_complement)
419 if( m_dWords[N64Cycle0RGB] == m_dWords[N64Cycle1RGB] )
424 dRGB1 = MUX_COMBINED;
425 splitType[N64Cycle1RGB] = CM_FMT_TYPE_NOT_USED;
428 if( m_dWords[N64Cycle0Alpha] == m_dWords[N64Cycle1Alpha] )
434 splitType[N64Cycle1Alpha] = CM_FMT_TYPE_NOT_USED;
437 for( int i=0; i<4; i++ )
439 if( splitType[i] == CM_FMT_TYPE_NOT_USED )
441 continue; //Skip this, it is not used
444 N64CombinerType &m = m_n64Combiners[i];
445 //if( m.a == MUX_0 || m.c == MUX_0 || m.a == m.b ) m.a = m.b = m.c = MUX_0;
446 if( m.c == MUX_0 || m.a == m.b ) m.a = m.b = m.c = MUX_0;
447 if( do_complement && (m.b == MUX_1 || m.d == MUX_1) ) m.a = m.b = m.c = MUX_0;
448 if( m.a == MUX_0 && m.b == m.d )
452 //Hack for Mario Tennis
453 if( options.enableHackForGames == HACK_FOR_MARIO_TENNIS && m.c == MUX_TEXEL1 )
456 m.c = MUX_TEXEL0|MUX_COMPLEMENT;
465 //m.c ^= MUX_COMPLEMENT;
469 //Analyze the formula
477 //A=1, C=1, D=0 = 1-B
479 splitType[i] = CM_FMT_TYPE_NOT_CHECKED; //All Type 1 will be changed to = D
480 if( m.c == MUX_0 || m.a==m.b || ( do_complement && (m.d == MUX_1 || m.b==MUX_1)) )
482 splitType[i] = CM_FMT_TYPE_D; //All Type 1 will be changed to = D
483 m.a = m.b = m.c = MUX_0;
484 if( m.d == MUX_COMBINED && i>=N64Cycle1RGB ) splitType[i] = CM_FMT_TYPE_NOT_USED;
486 else if( (m.b == MUX_0 && m.c == MUX_1 && m.d == MUX_0 ) || ( m.c == MUX_1 && m.b==m.d ) )
488 splitType[i] = CM_FMT_TYPE_D; //All Type 1 will be changed to = D
490 m.a = m.b = m.c = MUX_0;
491 if( m.d == MUX_COMBINED && i>=N64Cycle1RGB ) splitType[i] = CM_FMT_TYPE_NOT_USED;
493 else if( m.a == MUX_1 && m.b == MUX_0 && m.d == MUX_0 )
495 splitType[i] = CM_FMT_TYPE_D; //All Type 1 will be changed to = D
497 m.a = m.b = m.c = MUX_0;
498 if( m.d == MUX_COMBINED && i>=N64Cycle1RGB ) splitType[i] = CM_FMT_TYPE_NOT_USED;
500 else if( m.a == MUX_1 && m.c == MUX_1 && m.d == MUX_0 && do_complement )
502 splitType[i] = CM_FMT_TYPE_D; //All Type 1 will be changed to = D
503 m.d = m.b^MUX_COMPLEMENT;
504 m.a = m.b = m.c = MUX_0;
505 if( m.d == MUX_COMBINED && i>=N64Cycle1RGB ) splitType[i] = CM_FMT_TYPE_NOT_USED;
508 if( splitType[i] == CM_FMT_TYPE_NOT_USED )
511 if( splitType[i] == CM_FMT_TYPE_D )
513 if( (i == N64Cycle0RGB || i == N64Cycle0Alpha) && splitType[i+2]!=CM_FMT_TYPE_NOT_USED ) //Cycle 1's Color or Alpha
516 for( int j=0; j<4; j++ )
518 if( (m_bytes[j+i*4+8]&MUX_MASK) == MUX_COMBINED )
520 m_bytes[j+i*4+8] = saveD|(m_bytes[j+i*4+8]&0xC0); //Replace cycle's CMB with D from cycle 1
523 m_dWords[i] = m_dWords[i+2];
524 splitType[i+2]=CM_FMT_TYPE_NOT_USED;
525 m_dWords[i+2] = 0x02000000;
526 i=i-1; // Throw the first cycle result away, use 2nd cycle for the 1st cycle
527 // and then redo the 1st cycle
531 if( (i==2 || i == 3) && (m.d&MUX_MASK) == MUX_COMBINED )
533 splitType[i] = CM_FMT_TYPE_NOT_USED;
542 splitType[i] = CM_FMT_TYPE_A_ADD_D; //All Type 2 will be changed to = A+D
543 if( m.b == MUX_0 && m.c == MUX_1 )
545 if( m.d == MUX_TEXEL0 || m.d == MUX_TEXEL1 ) swap(m.a, m.d);
546 if( m.a == MUX_COMBINED ) swap(m.a, m.d);
550 if( m.a == MUX_1 && m.b == MUX_0 )
552 m.a = m.c; //Change format A+D
554 if( m.d == MUX_TEXEL0 || m.d == MUX_TEXEL1 ) swap(m.a, m.d);
562 splitType[i] = CM_FMT_TYPE_A_MOD_C; //A*C
563 if( m.b == MUX_0 && m.d == MUX_0 )
565 if( m.c == MUX_TEXEL0 || m.c == MUX_TEXEL1 ) swap(m.a, m.c);
566 if( m.a == MUX_COMBINED ) swap(m.a, m.c);
570 if( m.a == MUX_1 && m.d == MUX_0 && do_complement )
572 m.a = m.b^MUX_COMPLEMENT;
574 if( m.c == MUX_TEXEL0 || m.c == MUX_TEXEL1 ) swap(m.a, m.c);
575 if( m.a == MUX_COMBINED ) swap(m.a, m.c);
581 splitType[i] = CM_FMT_TYPE_A_SUB_B; //A-B
582 if( m.c == MUX_1 && m.d == MUX_0 )
587 //Type 5: A*C+D , ' MULTIPLYADD
589 //A=1 = (1-B) * C + D
590 splitType[i] = CM_FMT_TYPE_A_MOD_C_ADD_D;
593 if( m.c == MUX_TEXEL0 || m.c == MUX_TEXEL1 ) swap(m.a, m.c);
594 if( m.a == MUX_COMBINED ) swap(m.a, m.c);
598 if( m.a == MUX_1 && m.b!=m.d && do_complement )
600 m.a = m.b^MUX_COMPLEMENT;
602 if( m.c == MUX_TEXEL0 || m.c == MUX_TEXEL1 ) swap(m.a, m.c);
603 if( m.a == MUX_COMBINED ) swap(m.a, m.c);
607 //Type 6: (A-B)*C+B Map to LERP, or BLENDALPHA
609 splitType[i] = CM_FMT_TYPE_A_LERP_B_C;
618 splitType[i] = CM_FMT_TYPE_A_SUB_B_ADD_D;
621 if( m.c == MUX_TEXEL0 || m.c == MUX_TEXEL1 ) swap(m.a, m.c);
626 splitType[i] = CM_FMT_TYPE_A_SUB_B_MOD_C;
632 if( m.c == m.d && do_complement ) // (A-B)*C+C ==> (A + B|C ) * C
635 m.b |= MUX_COMPLEMENT;
641 splitType[i] = CM_FMT_TYPE_A_B_C_A;
646 splitType[i] = CM_FMT_TYPE_A_B_C_D;
649 if( (splitType[0] == CM_FMT_TYPE_D && splitType[2]!= CM_FMT_TYPE_NOT_USED ) || //Cycle 1 Color
650 (isUsedInCycle(MUX_COMBINED,1,COLOR_CHANNEL) == false && isUsedInCycle(MUX_COMBINED,1,ALPHA_CHANNEL) == false && splitType[2]!= CM_FMT_TYPE_NOT_USED) )
652 //Replace cycle 1 color with cycle 2 color because we have already replace cycle2's cmb
660 dRGB1 = MUX_COMBINED;
661 splitType[0] = splitType[2];
662 splitType[2] = CM_FMT_TYPE_NOT_USED;
665 if( (splitType[1] == CM_FMT_TYPE_D && splitType[3]!= CM_FMT_TYPE_NOT_USED ) || //Cycle 2 Alpha
666 ( isUsedInCycle(MUX_COMBINED,1,ALPHA_CHANNEL) == false && isUsedInCycle(MUX_COMBINED|MUX_ALPHAREPLICATE,1,COLOR_CHANNEL,MUX_MASK_WITH_ALPHA) == false && splitType[3]!= CM_FMT_TYPE_NOT_USED) )
668 //Replace cycle 1 alpha with cycle 2 alpha because we have already replace cycle2's cmb
677 splitType[1] = splitType[3];
678 splitType[3] = CM_FMT_TYPE_NOT_USED;
681 if( splitType[0] == CM_FMT_TYPE_A_MOD_C && splitType[2] == CM_FMT_TYPE_A_ADD_D )
683 m_n64Combiners[0].d = (m_n64Combiners[2].a & MUX_MASK) == MUX_COMBINED ? m_n64Combiners[2].d : m_n64Combiners[2].a;
684 splitType[0] = CM_FMT_TYPE_A_MOD_C_ADD_D;
685 splitType[2] = CM_FMT_TYPE_NOT_USED;
686 m_n64Combiners[2].a = MUX_0;
687 m_n64Combiners[2].c = MUX_0;
688 m_n64Combiners[2].d = MUX_COMBINED;
691 if( splitType[1] == CM_FMT_TYPE_A_MOD_C && splitType[3] == CM_FMT_TYPE_A_ADD_D )
693 m_n64Combiners[1].d = (m_n64Combiners[3].a & MUX_MASK) == MUX_COMBINED ? m_n64Combiners[3].d : m_n64Combiners[3].a;
694 splitType[1] = CM_FMT_TYPE_A_MOD_C_ADD_D;
695 splitType[3] = CM_FMT_TYPE_NOT_USED;
696 m_n64Combiners[3].a = MUX_0;
697 m_n64Combiners[3].c = MUX_0;
698 m_n64Combiners[3].d = MUX_COMBINED;
701 mType = max(max(max(splitType[0], splitType[1]),splitType[2]),splitType[3]);
704 const char* MuxGroupStr[4] =
712 char* DecodedMux::FormatStr(uint8 val, char *buf)
714 if( val == CM_IGNORE_BYTE )
720 strcpy(buf, translatedCombTypes[val&MUX_MASK]);
721 if( val&MUX_ALPHAREPLICATE )
723 if( val&MUX_COMPLEMENT )
732 void DecodedMux::Display(bool simplified,FILE *fp)
734 DecodedMux decodedMux;
742 decodedMux.Decode(m_dwMux0, m_dwMux1);
751 for( int i=0; i<2; i++ )
755 N64CombinerType &m = mux->m_n64Combiners[i+2*j];
758 fprintf(fp,"%s: (%s - %s) * %s + %s\n", MuxGroupStr[i+2*j], FormatStr(m.a,buf0),
759 FormatStr(m.b,buf1), FormatStr(m.c,buf2), FormatStr(m.d,buf3));
763 DebuggerAppendMsg("%s: (%s - %s) * %s + %s\n", MuxGroupStr[i+2*j], FormatStr(m.a,buf0),
764 FormatStr(m.b,buf1), FormatStr(m.c,buf2), FormatStr(m.d,buf3));
770 int DecodedMux::HowManyConstFactors()
773 if( isUsed(MUX_PRIM) ) n++;
774 if( isUsed(MUX_ENV) ) n++;
775 if( isUsed(MUX_LODFRAC) ) n++;
776 if( isUsed(MUX_PRIMLODFRAC) ) n++;
780 int DecodedMux::HowManyTextures()
783 if( isUsed(MUX_TEXEL0) ) n++;
784 if( isUsed(MUX_TEXEL1) ) n++;
788 int DecodedMux::CountTexels(void)
792 for( int i=0; i<4; i++ )
794 N64CombinerType &m = m_n64Combiners[i];
795 count = max(count, ::CountTexel1Cycle(m));
803 void DecodedMux::ReplaceVal(uint8 val1, uint8 val2, int cycle, uint8 mask)
814 uint8* pmux = m_bytes;
815 for( int i=start; i<end; i++ )
817 if( (pmux[i]&mask) == (val1&mask) )
825 uint32 DecodedMux::GetCycle(int cycle, CombineChannel channel)
827 uint32* pmux = m_dWords;
828 if( channel == COLOR_CHANNEL )
830 return pmux[cycle*2];
834 return pmux[cycle*2+1];
839 uint32 DecodedMux::GetCycle(int cycle)
841 return m_dWords[cycle];
844 enum ShadeConstMergeType
847 SHADE_ADD_PRIM, // Shade+PRIM
848 SHADE_ADD_ENV, // Shade+ENV
849 SHADE_ADD_PRIM_ALPHA, // Shade+PRIM_ALPHA
850 SHADE_ADD_ENV_ALPHA, // Shade+ENV_ALPHA
851 SHADE_MINUS_PRIM_PLUS_ENV,
852 SHADE_MINUS_ENV_PLUS_PRIM,
858 uint64 mux; // simplified
859 ShadeConstMergeType op;
860 } ShadeConstMergeMapType;
862 ShadeConstMergeMapType MergeShadeWithConstantsMaps[] =
864 {0, SHADE_DO_NOTHING},
865 {0x0007000600070006LL, SHADE_MOD_ENV}, // SHADE * ENV
868 // 0x05070501, 0x00070006 //(1 - PRIM) * ENV + PRIM
869 // 0x00050003, 0x00050003 //(TEXEL0 - 0) * PRIM + 0
871 void DecodedMux::MergeShadeWithConstants(void)
873 // This function should be called afte the mux has been simplified
874 // The goal of this function is to merge as many as possible constants with shade
875 // so to reduce the totally number of constants to 0 or 1
876 // And at the same time, to reduce the complexity of the whole mux
877 // so we can implement the mux easiler when lower end video cards
879 // We can only try to merge shade with constants for:
880 // 1 cycle mode or 2 cycle mode and shade is not used in the 2nd cycle
882 if( m_bShadeIsUsed[0] ) MergeShadeWithConstantsInChannel(COLOR_CHANNEL);
883 if( m_bShadeIsUsed[1] ) MergeShadeWithConstantsInChannel(ALPHA_CHANNEL);
886 void DecodedMux::MergeShadeWithConstantsInChannel(CombineChannel channel)
892 usedIn[0] = isUsedInCycle(MUX_SHADE,channel);
893 usedIn[1] = isUsedInCycle(MUX_SHADE,channel+2);
894 if( usedIn[0] && usedIn[1] && GetCycle(channel)!=GetCycle(channel+2) )
896 //Shade is used in more than 1 cycles, and the ways it is used are different
897 //in cycles, so we can not merge shade with const factors
901 if( usedIn[0] ) { cycleVal = GetCycle(channel);cycleNum=0;}
902 else {cycleVal = GetCycle(channel+2);cycleNum=1;}
905 //Update to here, Shade is either used only in 1 cycle, or the way it is used are totally
906 //the same in different cycles
908 if( cycleVal == 0x06000000 || isUsedInCycle(MUX_COMBINED,channel+cycleNum*2) ) // (0-0)*0+Shade
913 //Now we can merge shade with consts
914 for( int i=0; i<2; i++ )
918 N64CombinerType &m = m_n64Combiners[channel+i*2];
919 if( isUsedInCycle(MUX_TEXEL0,i*2+channel) || isUsedInCycle(MUX_TEXEL1,i*2+channel) )
921 if( (m.a&MUX_MASK) == MUX_TEXEL0 || (m.a&MUX_MASK) == MUX_TEXEL1 )
923 // m.a is texel, can not merge constant with shade
926 else if( (m.b&MUX_MASK) == MUX_TEXEL0 || (m.b&MUX_MASK) == MUX_TEXEL1 )
928 // m.b is texel, can not merge constant with shade
931 else if(( (m.c&MUX_MASK) == MUX_TEXEL0 || (m.c&MUX_MASK) == MUX_TEXEL1 ) )
933 if( (m.d&MUX_MASK) != MUX_SHADE )
935 cycleVal &= 0x0000FFFF; // A-B
937 else if( (m.a&MUX_MASK) == MUX_SHADE || (m.b&MUX_MASK) == MUX_SHADE )
942 else if( (m.d&MUX_MASK) == MUX_TEXEL0 || (m.d&MUX_MASK) == MUX_TEXEL1 )
944 cycleVal &= 0x00FFFFFF; // (A-B)*C
949 m.a = m.b = m.c = MUX_0;
951 splitType[i*2+channel] = CM_FMT_TYPE_D;
956 if( channel == COLOR_CHANNEL )
957 m_dwShadeColorChannelFlag = cycleVal;
959 m_dwShadeAlphaChannelFlag = cycleVal;
963 void DecodedMux::MergeConstants(void)
965 // This function should be called afte the mux has been simplified
966 // The goal of this function is to merge remain constants and to reduce the
967 // total number of constants, so we can implement the mux easiler
969 // This function should be called after the MergeShadeWithConstants() function
973 void DecodedMux::UseShadeForConstant(void)
975 // If shade is not used in the mux, we can use it for constants
976 // This function should be called after constants have been merged
978 bool doAlphaChannel = true;
979 uint8 mask = (uint8)~MUX_COMPLEMENT;
982 if( isUsed(MUX_ENV) ) constants++;
983 if( isUsed(MUX_PRIM) ) constants++;
984 if( isUsed(MUX_LODFRAC) ) constants++;
985 if( isUsed(MUX_PRIMLODFRAC) ) constants++;
987 bool forceToUsed = constants>m_maxConstants;
989 if( !isUsedInColorChannel(MUX_SHADE) && (forceToUsed || max(splitType[0], splitType[2]) >= CM_FMT_TYPE_A_MOD_C_ADD_D) )
991 int countEnv = Count(MUX_ENV, N64Cycle0RGB, mask) + Count(MUX_ENV, N64Cycle1RGB, mask);
992 int countPrim = Count(MUX_PRIM, N64Cycle0RGB, mask) + Count(MUX_PRIM, N64Cycle1RGB, mask);
993 if( countEnv+countPrim > 0 )
995 if( countPrim >= countEnv )
997 //TRACE0("Use Shade for PRIM in color channel");
998 ReplaceVal(MUX_PRIM, MUX_SHADE, N64Cycle0RGB);
999 ReplaceVal(MUX_PRIM, MUX_SHADE, N64Cycle1RGB);
1000 m_dwShadeColorChannelFlag = MUX_PRIM;
1002 else if( countEnv>0 )
1004 //TRACE0("Use Shade for ENV in color channel");
1005 ReplaceVal(MUX_ENV, MUX_SHADE, N64Cycle0RGB);
1006 ReplaceVal(MUX_ENV, MUX_SHADE, N64Cycle1RGB);
1007 m_dwShadeColorChannelFlag = MUX_ENV;
1010 if( isUsedInColorChannel(MUX_SHADE|MUX_ALPHAREPLICATE, mask) )
1012 m_dwShadeAlphaChannelFlag = m_dwShadeColorChannelFlag;
1013 ReplaceVal((uint8)m_dwShadeColorChannelFlag, MUX_SHADE, N64Cycle0Alpha);
1014 ReplaceVal((uint8)m_dwShadeColorChannelFlag, MUX_SHADE, N64Cycle1Alpha);
1015 doAlphaChannel = false;
1020 if( doAlphaChannel && !isUsedInAlphaChannel(MUX_SHADE) && !isUsedInColorChannel(MUX_SHADE|MUX_ALPHAREPLICATE,MUX_MASK_WITH_ALPHA))
1022 int countEnv = Count(MUX_ENV|MUX_ALPHAREPLICATE, N64Cycle0RGB, mask) + Count(MUX_ENV|MUX_ALPHAREPLICATE, N64Cycle1RGB, mask);
1023 int countPrim = Count(MUX_PRIM|MUX_ALPHAREPLICATE, N64Cycle0RGB, mask) + Count(MUX_PRIM|MUX_ALPHAREPLICATE, N64Cycle1RGB, mask);
1025 if( forceToUsed || max(splitType[1], splitType[3]) >= CM_FMT_TYPE_A_MOD_C_ADD_D ||
1026 (max(splitType[0], splitType[2]) >= CM_FMT_TYPE_A_MOD_C_ADD_D && countEnv+countPrim > 0 ) )
1028 countEnv = Count(MUX_ENV, N64Cycle0Alpha) + Count(MUX_ENV, N64Cycle1Alpha) +
1029 Count(MUX_ENV|MUX_ALPHAREPLICATE, N64Cycle0RGB, mask) + Count(MUX_ENV|MUX_ALPHAREPLICATE, N64Cycle1RGB, mask);
1030 countPrim = Count(MUX_PRIM, N64Cycle0Alpha) + Count(MUX_PRIM, N64Cycle1Alpha) +
1031 Count(MUX_PRIM|MUX_ALPHAREPLICATE, N64Cycle0RGB, mask) + Count(MUX_PRIM|MUX_ALPHAREPLICATE, N64Cycle1RGB, mask);
1032 if( countEnv+countPrim > 0 )
1034 if( countPrim>0 && m_dwShadeColorChannelFlag == MUX_PRIM )
1036 //TRACE0("Use Shade for PRIM in alpha channel");
1037 ReplaceVal(MUX_PRIM, MUX_SHADE, N64Cycle0Alpha);
1038 ReplaceVal(MUX_PRIM, MUX_SHADE, N64Cycle1Alpha);
1039 ReplaceVal(MUX_PRIM|MUX_ALPHAREPLICATE, MUX_SHADE|MUX_ALPHAREPLICATE, N64Cycle0RGB, mask);
1040 ReplaceVal(MUX_PRIM|MUX_ALPHAREPLICATE, MUX_SHADE|MUX_ALPHAREPLICATE, N64Cycle1RGB, mask);
1041 m_dwShadeAlphaChannelFlag = MUX_PRIM;
1043 else if( countEnv>0 && m_dwShadeColorChannelFlag == MUX_ENV )
1045 //TRACE0("Use Shade for PRIM in alpha channel");
1046 ReplaceVal(MUX_ENV, MUX_SHADE, N64Cycle0Alpha);
1047 ReplaceVal(MUX_ENV, MUX_SHADE, N64Cycle1Alpha);
1048 ReplaceVal(MUX_ENV|MUX_ALPHAREPLICATE, MUX_SHADE|MUX_ALPHAREPLICATE, N64Cycle0RGB, mask);
1049 ReplaceVal(MUX_ENV|MUX_ALPHAREPLICATE, MUX_SHADE|MUX_ALPHAREPLICATE, N64Cycle1RGB, mask);
1050 m_dwShadeAlphaChannelFlag = MUX_ENV;
1052 else if( countPrim >= countEnv )
1054 //TRACE0("Use Shade for PRIM in alpha channel");
1055 ReplaceVal(MUX_PRIM, MUX_SHADE, N64Cycle0Alpha);
1056 ReplaceVal(MUX_PRIM, MUX_SHADE, N64Cycle1Alpha);
1057 ReplaceVal(MUX_PRIM|MUX_ALPHAREPLICATE, MUX_SHADE|MUX_ALPHAREPLICATE, N64Cycle0RGB, mask);
1058 ReplaceVal(MUX_PRIM|MUX_ALPHAREPLICATE, MUX_SHADE|MUX_ALPHAREPLICATE, N64Cycle1RGB, mask);
1059 m_dwShadeAlphaChannelFlag = MUX_PRIM;
1061 else if( countEnv>0 )
1063 //TRACE0("Use Shade for ENV in alpha channel");
1064 ReplaceVal(MUX_ENV, MUX_SHADE, N64Cycle0Alpha);
1065 ReplaceVal(MUX_ENV, MUX_SHADE, N64Cycle1Alpha);
1066 ReplaceVal(MUX_ENV|MUX_ALPHAREPLICATE, MUX_SHADE|MUX_ALPHAREPLICATE, N64Cycle0RGB, mask);
1067 ReplaceVal(MUX_ENV|MUX_ALPHAREPLICATE, MUX_SHADE|MUX_ALPHAREPLICATE, N64Cycle1RGB, mask);
1068 m_dwShadeAlphaChannelFlag = MUX_ENV;
1075 void DecodedMux::UseTextureForConstant(void)
1077 int numofconst = HowManyConstFactors();
1078 int numOftex = HowManyTextures();
1080 if( numofconst > m_maxConstants && numOftex < m_maxTextures )
1082 // We can use a texture for a constant
1083 for( int i=0; i<2 && numofconst > m_maxConstants ; i++ )
1085 if( isUsed(MUX_TEXEL0+i) )
1087 continue; // can not use this texture
1090 if( isUsed(MUX_PRIM) )
1092 ReplaceVal(MUX_PRIM, MUX_TEXEL0+i);
1093 m_ColorTextureFlag[i] = MUX_PRIM;
1098 if( isUsed(MUX_ENV) )
1100 ReplaceVal(MUX_ENV, MUX_TEXEL0+i);
1101 m_ColorTextureFlag[i] = MUX_ENV;
1106 if( isUsed(MUX_LODFRAC) )
1108 ReplaceVal(MUX_LODFRAC, MUX_TEXEL0+i);
1109 m_ColorTextureFlag[i] = MUX_LODFRAC;
1114 if( isUsed(MUX_PRIMLODFRAC) )
1116 ReplaceVal(MUX_PRIMLODFRAC, MUX_TEXEL0+i);
1117 m_ColorTextureFlag[i] = MUX_PRIMLODFRAC;
1126 void DecodedMuxForOGL14V2::UseTextureForConstant(void)
1128 bool envused = isUsed(MUX_ENV);
1129 bool lodused = isUsed(MUX_LODFRAC);
1132 if( envused ) numofconst++;
1133 if( lodused ) numofconst++;
1135 int numOftex = HowManyTextures();
1137 if( numofconst > 0 && numOftex < 2 )
1139 // We can use a texture for a constant
1140 for( int i=0; i<2 && numofconst > 0 ; i++ )
1142 if( isUsed(MUX_TEXEL0+i) )
1144 continue; // can not use this texture
1149 ReplaceVal(MUX_ENV, MUX_TEXEL0+i);
1150 m_ColorTextureFlag[i] = MUX_ENV;
1156 if( isUsed(MUX_LODFRAC) )
1158 ReplaceVal(MUX_LODFRAC, MUX_TEXEL0+i);
1159 m_ColorTextureFlag[i] = MUX_LODFRAC;
1164 if( isUsed(MUX_PRIMLODFRAC) )
1166 ReplaceVal(MUX_PRIMLODFRAC, MUX_TEXEL0+i);
1167 m_ColorTextureFlag[i] = MUX_PRIMLODFRAC;
1176 extern const char *translatedCombTypes[];
1177 void DecodedMux::DisplayMuxString(const char *prompt)
1179 DebuggerAppendMsg("//Mux=0x%08x%08x\t%s in %s\n", m_dwMux0, m_dwMux1, prompt, g_curRomInfo.szGameName);
1184 void DecodedMux::DisplaySimpliedMuxString(const char *prompt)
1186 DebuggerAppendMsg("//Simplied Mux=0x%08x%08x\t%s in %s\n", m_dwMux0, m_dwMux1, prompt, g_curRomInfo.szGameName);
1187 DebuggerAppendMsg("Simplied DWORDs=%08X, %08X, %08X, %08X", m_dWords[0],m_dWords[1],m_dWords[2],m_dWords[3]);
1189 DebuggerAppendMsg("Simplfied type: %s", muxTypeStrs[mType]);
1190 if( m_dwShadeColorChannelFlag != 0 )
1192 if( m_dwShadeColorChannelFlag == MUX_ENV )
1193 TRACE0("Shade = ENV in color channel")
1194 else if( m_dwShadeColorChannelFlag == MUX_PRIM )
1195 TRACE0("Shade = PRIM in color channel")
1196 else if( m_dwShadeColorChannelFlag == MUX_LODFRAC )
1197 TRACE0("Shade = MUX_LODFRAC in color channel")
1198 else if( m_dwShadeColorChannelFlag == MUX_PRIMLODFRAC )
1199 TRACE0("Shade = MUX_PRIMLODFRAC in color channel")
1201 DisplayConstantsWithShade(m_dwShadeColorChannelFlag,COLOR_CHANNEL);
1203 if( m_dwShadeAlphaChannelFlag != 0 )
1205 if( m_dwShadeAlphaChannelFlag == MUX_ENV )
1206 TRACE0("Shade = ENV in alpha channel")
1207 else if( m_dwShadeAlphaChannelFlag == MUX_PRIM )
1208 TRACE0("Shade = PRIM in alpha channel")
1209 else if( m_dwShadeAlphaChannelFlag == MUX_LODFRAC )
1210 TRACE0("Shade = MUX_LODFRAC in alpha channel")
1211 else if( m_dwShadeAlphaChannelFlag == MUX_PRIMLODFRAC )
1212 TRACE0("Shade = MUX_PRIMLODFRAC in alpha channel")
1214 DisplayConstantsWithShade(m_dwShadeAlphaChannelFlag,ALPHA_CHANNEL);
1217 for( int i=0; i<2; i++ )
1219 if( m_ColorTextureFlag[i] != 0 )
1221 if( m_ColorTextureFlag[i] == MUX_ENV )
1222 TRACE1("Tex %d = ENV", i)
1223 else if( m_ColorTextureFlag[i] == MUX_PRIM )
1224 TRACE1("Tex %d = PRIM", i)
1225 else if( m_ColorTextureFlag[i] == MUX_LODFRAC )
1226 TRACE1("Tex %d = MUX_LODFRAC", i)
1227 else if( m_ColorTextureFlag[i] == MUX_PRIMLODFRAC )
1228 TRACE1("Tex %d = MUX_PRIMLODFRAC", i)
1236 void DecodedMux::DisplayConstantsWithShade(uint32 flag,CombineChannel channel)
1238 DebuggerAppendMsg("Shade = %08X in %s channel",flag,channel==COLOR_CHANNEL?"color":"alpha");
1242 extern const char *translatedCombTypes[];
1243 void DecodedMux::LogMuxString(const char *prompt, FILE *fp)
1245 fprintf(fp,"//Mux=0x%08x%08x\t%s in %s\n", m_dwMux0, m_dwMux1, prompt, g_curRomInfo.szGameName);
1250 void DecodedMux::LogSimpliedMuxString(const char *prompt, FILE *fp)
1252 fprintf(fp,"//Simplied Mux=0x%08x%08x\t%s in %s\n", m_dwMux0, m_dwMux1, prompt, g_curRomInfo.szGameName);
1253 fprintf(fp,"Simplied DWORDs=%08X, %08X, %08X, %08X\n", m_dWords[0],m_dWords[1],m_dWords[2],m_dWords[3]);
1255 fprintf(fp,"Simplfied type: %s", muxTypeStrs[mType]);
1256 if( m_dwShadeColorChannelFlag != 0 )
1258 if( m_dwShadeColorChannelFlag == MUX_ENV )
1259 TRACE0("Shade = ENV in color channel")
1260 else if( m_dwShadeColorChannelFlag == MUX_PRIM )
1261 TRACE0("Shade = PRIM in color channel")
1262 else if( m_dwShadeColorChannelFlag == MUX_LODFRAC )
1263 TRACE0("Shade = MUX_LODFRAC in color channel")
1264 else if( m_dwShadeColorChannelFlag == MUX_PRIMLODFRAC )
1265 TRACE0("Shade = MUX_PRIMLODFRAC in color channel")
1267 LogConstantsWithShade(m_dwShadeColorChannelFlag,COLOR_CHANNEL,fp);
1269 if( m_dwShadeAlphaChannelFlag != 0 )
1271 if( m_dwShadeAlphaChannelFlag == MUX_ENV )
1272 TRACE0("Shade = ENV in alpha channel")
1273 else if( m_dwShadeAlphaChannelFlag == MUX_PRIM )
1274 TRACE0("Shade = PRIM in alpha channel")
1275 else if( m_dwShadeAlphaChannelFlag == MUX_LODFRAC )
1276 TRACE0("Shade = MUX_LODFRAC in alpha channel")
1277 else if( m_dwShadeAlphaChannelFlag == MUX_PRIMLODFRAC )
1278 TRACE0("Shade = MUX_PRIMLODFRAC in alpha channel")
1280 LogConstantsWithShade(m_dwShadeAlphaChannelFlag,ALPHA_CHANNEL,fp);
1283 for( int i=0; i<2; i++ )
1285 if( m_ColorTextureFlag[i] != 0 )
1287 if( m_ColorTextureFlag[i] == MUX_ENV )
1288 TRACE1("Tex %d = ENV", i)
1289 else if( m_ColorTextureFlag[i] == MUX_PRIM )
1290 TRACE1("Tex %d = PRIM", i)
1291 else if( m_ColorTextureFlag[i] == MUX_LODFRAC )
1292 TRACE1("Tex %d = MUX_LODFRAC", i)
1293 else if( m_ColorTextureFlag[i] == MUX_PRIMLODFRAC )
1294 TRACE1("Tex %d = MUX_PRIMLODFRAC", i)
1302 void DecodedMux::LogConstantsWithShade(uint32 flag,CombineChannel channel, FILE *fp)
1304 fprintf(fp,"Shade = %08X in %s channel",flag,channel==COLOR_CHANNEL?"color":"alpha");
1309 void DecodedMux::To_AB_Add_CD_Format(void) // Use by TNT,Geforce
1311 // This function should be called after calling reformat
1312 // This function will not be called by default, can be called optionally
1313 // by TNT/Geforce combiner compilers
1315 for( int i=0; i<2; i++ )
1317 N64CombinerType &m0 = m_n64Combiners[i];
1318 N64CombinerType &m1 = m_n64Combiners[i+2];
1319 switch( splitType[i] )
1321 case CM_FMT_TYPE_A_SUB_B_ADD_D: // = A-B+D can not map very well in 1 stage
1322 if( splitType[i+2] == CM_FMT_TYPE_NOT_USED )
1325 m1.d = MUX_COMBINED;
1326 splitType[i+2] = CM_FMT_TYPE_A_ADD_D;
1329 splitType[i] = CM_FMT_TYPE_A_SUB_B;
1331 else if( splitType[i+2] == CM_FMT_TYPE_A_MOD_C )
1333 if( (m1.c&MUX_MASK) == MUX_COMBINED ) swap(m1.a, m1.c);
1335 m1.c = (m0.d | (m1.a & (~MUX_MASK)));
1336 splitType[i+2] = CM_FMT_TYPE_AB_ADD_CD;
1339 splitType[i] = CM_FMT_TYPE_A_SUB_B;
1342 case CM_FMT_TYPE_A_SUB_B_MOD_C: // = (A-B)*C can not map very well in 1 stage
1345 splitType[i] = CM_FMT_TYPE_AB_SUB_CD;
1347 case CM_FMT_TYPE_A_ADD_B_MOD_C: // = (A+B)*C can not map very well in 1 stage
1350 splitType[i] = CM_FMT_TYPE_AB_ADD_CD;
1352 case CM_FMT_TYPE_A_B_C_D: // = (A-B)*C+D
1353 case CM_FMT_TYPE_A_B_C_A: // = (A-B)*C+D
1354 if( splitType[i+2] == CM_FMT_TYPE_NOT_USED )
1357 m1.d = MUX_COMBINED;
1358 splitType[i+2] = CM_FMT_TYPE_A_ADD_D;
1362 splitType[i] = CM_FMT_TYPE_AB_SUB_CD;
1364 else if( splitType[i+2] == CM_FMT_TYPE_A_MOD_C )
1366 if( (m1.c&MUX_MASK) == MUX_COMBINED ) swap(m1.a, m1.c);
1368 m1.c = (m0.d | (m1.a & (~MUX_MASK)));
1369 splitType[i+2] = CM_FMT_TYPE_AB_ADD_CD;
1373 splitType[i] = CM_FMT_TYPE_AB_ADD_CD;
1382 void DecodedMux::To_AB_Add_C_Format(void) // Use by ATI Radeon
1384 // This function should be called after calling reformat
1385 // This function will not be called by default, can be called optionally
1386 // by ATI combiner compilers
1389 void DecodedMux::CheckCombineInCycle1(void)
1391 if( isUsedInCycle(MUX_COMBINED,0,COLOR_CHANNEL) )
1393 ReplaceVal(MUX_COMBINED, MUX_SHADE, 0);
1396 if( isUsedInCycle(MUX_COMBALPHA,0,COLOR_CHANNEL) )
1398 ReplaceVal(MUX_COMBALPHA, MUX_SHADE|MUX_ALPHAREPLICATE, 0);
1401 if( isUsedInCycle(MUX_COMBINED,0,ALPHA_CHANNEL) )
1403 if( cA0 == MUX_COMBINED && cRGB0 == MUX_LODFRAC && bRGB0 == dRGB0 && bA0 == dA0 )
1409 ReplaceVal(MUX_COMBINED, MUX_SHADE, 1);
1412 if( isUsedInCycle(MUX_COMBALPHA,0,ALPHA_CHANNEL) )
1414 ReplaceVal(MUX_COMBALPHA, MUX_SHADE, 1);
1418 void DecodedMux::SplitComplexStages()
1420 for( int i=0; i<2; i++) // Color channel and alpha channel
1422 if( splitType[i+2] != CM_FMT_TYPE_NOT_USED )
1425 N64CombinerType &m = m_n64Combiners[i];
1426 N64CombinerType &m2 = m_n64Combiners[i+2];
1428 switch( splitType[i] )
1430 case CM_FMT_TYPE_A_MOD_C_ADD_D: // = A*C+D can mapped to MULTIPLYADD(arg1,arg2,arg0)
1432 m2.d = MUX_COMBINED;
1435 splitType[i+2] = CM_FMT_TYPE_A_ADD_D;
1437 splitType[i] = CM_FMT_TYPE_A_MOD_C;
1439 case CM_FMT_TYPE_A_SUB_B_ADD_D: // = A-B+D can not map very well in 1 stage
1441 m2.d = MUX_COMBINED;
1444 splitType[i+2] = CM_FMT_TYPE_A_ADD_D;
1446 splitType[i] = CM_FMT_TYPE_A_SUB_B;
1448 case CM_FMT_TYPE_A_SUB_B_MOD_C: // = (A-B)*C can not map very well in 1 stage
1450 m2.c = MUX_COMBINED;
1452 splitType[i+2] = CM_FMT_TYPE_A_MOD_C;
1454 splitType[i] = CM_FMT_TYPE_A_SUB_B;
1456 case CM_FMT_TYPE_A_ADD_B_MOD_C: // = (A+B)*C can not map very well in 1 stage
1458 m2.c = MUX_COMBINED;
1460 splitType[i+2] = CM_FMT_TYPE_A_MOD_C;
1464 splitType[i] = CM_FMT_TYPE_A_ADD_D;
1466 case CM_FMT_TYPE_A_B_C_D: // = (A-B)*C+D can not map very well in 1 stage
1468 m2.d = MUX_COMBINED;
1471 splitType[i+2] = CM_FMT_TYPE_A_ADD_D;
1473 splitType[i] = CM_FMT_TYPE_A_SUB_B_MOD_C;
1475 case CM_FMT_TYPE_A_B_C_A: // = (A-B)*C+A can not map very well in 1 stage
1477 m2.d = MUX_COMBINED;
1480 splitType[i+2] = CM_FMT_TYPE_A_ADD_D;
1482 splitType[i] = CM_FMT_TYPE_A_SUB_B_MOD_C;
1489 //UseShadeForConstant();
1493 void DecodedMux::ConvertLODFracTo0()
1495 ReplaceVal(MUX_LODFRAC,MUX_0);
1496 ReplaceVal(MUX_PRIMLODFRAC,MUX_0);
1500 void DecodedMux::Hack(void)
1502 if( options.enableHackForGames == HACK_FOR_TONYHAWK )
1504 if( gRSP.curTile == 1 )
1506 ReplaceVal(MUX_TEXEL1, MUX_TEXEL0);
1509 else if( options.enableHackForGames == HACK_FOR_ZELDA || options.enableHackForGames == HACK_FOR_ZELDA_MM)
1511 if( m_dwMux1 == 0xfffd9238 && m_dwMux0 == 0x00ffadff )
1513 ReplaceVal(MUX_TEXEL1, MUX_TEXEL0);
1515 else if( m_dwMux1 == 0xff5bfff8 && m_dwMux0 == 0x00121603 )
1517 // The Zelda road trace
1518 ReplaceVal(MUX_TEXEL1, MUX_0);
1521 else if( options.enableHackForGames == HACK_FOR_MARIO_TENNIS )
1523 if( m_dwMux1 == 0xffebdbc0 && m_dwMux0 == 0x00ffb9ff )
1526 //m_decodedMux.dRGB0 = MUX_TEXEL0;
1527 //m_decodedMux.dRGB1 = MUX_COMBINED;
1531 else if( options.enableHackForGames == HACK_FOR_MARIO_GOLF )
1533 // Hack for Mario Golf
1534 if( m_dwMux1 == 0xf1ffca7e || m_dwMux0 == 0x00115407 )
1537 ReplaceVal(MUX_TEXEL0, MUX_TEXEL1);
1540 else if( options.enableHackForGames == HACK_FOR_TOPGEARRALLY )
1542 //Mux=0x00317e025ffef3fa Used in TOP GEAR RALLY
1543 //Color0: (PRIM - ENV) * TEXEL1 + ENV
1544 //Color1: (COMBINED - 0) * TEXEL1 + 0
1545 //Alpha0: (0 - 0) * 0 + TEXEL0
1546 //Alpha1: (0 - 0) * 0 + TEXEL1
1547 if( m_dwMux1 == 0x5ffef3fa || m_dwMux0 == 0x00317e02 )
1550 //ReplaceVal(MUX_TEXEL0, MUX_TEXEL1);
1552 //aA1 = MUX_COMBINED;