Rice GLES2 (from mupen64plus-ae) plugin. Compile but doesn't works well on the OpenPa...
[mupen64plus-pandora.git] / source / gles2rice / src / DecodedMux.cpp
1 /*
2 Copyright (C) 2002 Rice1964
3
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.
8
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.
13
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.
17 */
18
19 #include <algorithm>
20
21 #include "GeneralCombiner.h"
22 #include "Combiner.h"
23 #include "Config.h"
24 #include "RenderBase.h"
25
26 #define ALLOW_USE_TEXTURE_FOR_CONSTANTS
27
28 static const uint8 sc_Mux32[32] = 
29 {
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
38 };
39
40 static const uint8 sc_Mux16[16] = 
41 {
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 
46 };
47 static const uint8 sc_Mux8[8] = 
48 {
49     MUX_COMBINED, MUX_TEXEL0,   MUX_TEXEL1, MUX_PRIM,
50     MUX_SHADE,    MUX_ENV,      MUX_1,      MUX_0
51 };
52
53
54 const char * translatedCombTypes[] =
55 {
56     "0",
57     "1",
58     "COMBINED",
59     "TEXEL0",
60     "TEXEL1",
61     "PRIM",
62     "SHADE",
63     "ENV",
64     "COMBALPHA",
65     "T0_ALPHA_wrong",
66     "T1_ALPHA_wrong",
67     "PRIM_ALPHA_wrong",
68     "SHADE_ALPHA_wrong",
69     "ENV_ALPHA_wrong",
70     "LODFRAC",
71     "PRIMLODFRAC",
72     "K5",
73     "UNK",
74     "FACTOR_PRIM_MINUS_ENV",
75     "FACTOR_ENV_MINUS_PRIM",
76     "FACTOR_1_MINUS_PRIM",
77     "FACTOR_0_MINUS_PRIM",
78     "FACTOR_1_MINUS_ENV",
79     "FACTOR_0_MINUS_ENV",
80     "FACTOR_1_MINUS_PRIMALPHA",
81     "FACTOR_1_MINUS_ENVALPHA",
82     "FACTOR_HALF",
83     "PRIM_X_PRIMALPHA",
84     "1_MINUS_PRIM_X_ENV_PLUS_PRIM",
85     "ENV_X_PRIM",
86     "PRIM_X_1_MINUS_ENV",
87     "PRIM_X_PRIM",
88     "ENV_X_ENV",
89 };
90
91 const char* muxTypeStrs[] = {
92     "CM_FMT_TYPE_NOT_USED",
93     "CM_FMT_TYPE1_D",
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",
103 };
104
105 void DecodedMux::Decode(uint32 dwMux0, uint32 dwMux1)
106 {
107     m_dwMux0 = dwMux0;
108     m_dwMux1 = dwMux1;
109
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
114     
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
119     
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
124     
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
129
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];
137     
138     aA0    = sc_Mux8[aA0];
139     bA0    = sc_Mux8[bA0];
140     cA0    = sc_Mux8[cA0];
141     dA0    = sc_Mux8[dA0];
142     
143     aRGB1  = sc_Mux16[aRGB1];
144     bRGB1  = sc_Mux16[bRGB1];
145     cRGB1  = sc_Mux32[cRGB1];
146     dRGB1  = sc_Mux8[dRGB1];
147     
148     aA1    = sc_Mux8[aA1];
149     bA1    = sc_Mux8[bA1];
150     cA1    = sc_Mux8[cA1];
151     dA1    = sc_Mux8[dA1];
152
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);
157
158     m_dwShadeColorChannelFlag = 0;
159     m_dwShadeAlphaChannelFlag = 0;
160     m_ColorTextureFlag[0] = 0;
161     m_ColorTextureFlag[1] = 0;
162 }
163
164 int DecodedMux::Count(uint8 val, int cycle, uint8 mask)
165 {
166     uint8* pmux = m_bytes;
167     int count=0;
168     int start=0;
169     int end=16;
170
171     if( cycle >= 0 )
172     {
173         start = cycle*4;
174         end = start+4;
175     }
176
177
178     for( int i=start; i<end; i++ )
179     {
180         if( (pmux[i]&mask) == (val&mask) )
181         {
182             count++;
183         }
184     }
185
186     return count;
187 }
188
189
190 bool DecodedMux::isUsed(uint8 val, uint8 mask)
191 {
192     uint8* pmux = m_bytes;
193     bool isUsed = false;
194     for( int i=0; i<16; i++ )
195     {
196         if( (pmux[i]&mask) == (val&mask) )
197         {
198             isUsed = true;
199             break;
200         }
201     }
202
203     return isUsed;
204 }
205
206 bool DecodedMux::isUsedInAlphaChannel(uint8 val, uint8 mask)
207 {
208     uint8* pmux = m_bytes;
209     bool isUsed = false;
210     for( int i=0; i<16; i++ )
211     {
212         if( (i/4)%2 == 0 )
213             continue;   //Don't test color channel
214
215         if( (pmux[i]&mask) == (val&mask) )
216         {
217             isUsed = true;
218             break;
219         }
220     }
221
222     return isUsed;
223 }
224
225 bool DecodedMux::isUsedInColorChannel(uint8 val, uint8 mask)
226 {
227     uint8* pmux = m_bytes;
228     bool isUsed = false;
229     for( int i=0; i<16; i++ )
230     {
231         if( (i/4)%2 == 0 && (pmux[i]&mask) == (val&mask) )
232         {
233             isUsed = true;
234             break;
235         }
236     }
237
238     return isUsed;
239 }
240
241
242 bool DecodedMux::isUsedInCycle(uint8 val, int cycle, CombineChannel channel, uint8 mask)
243 {
244     cycle *=2;
245     if( channel == ALPHA_CHANNEL ) cycle++;
246
247     uint8* pmux = m_bytes;
248     for( int i=0; i<4; i++ )
249     {
250         if( (pmux[i+cycle*4]&mask) == (val&mask) )
251         {
252             return true;
253         }
254     }
255
256     return false;
257 }
258
259 bool DecodedMux::isUsedInCycle(uint8 val, int cycle, uint8 mask)
260 {
261     return isUsedInCycle(val, cycle/2, cycle%2?ALPHA_CHANNEL:COLOR_CHANNEL, mask);
262 }
263
264
265 void DecodedMux::ConvertComplements()
266 {
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 )
269     {
270         aRGB0 = bRGB0|MUX_COMPLEMENT;
271         bRGB0 = MUX_0;
272     }
273     if( aRGB1 != MUX_1 && bRGB1 != MUX_0 )
274     {
275         aRGB1 = bRGB1|MUX_COMPLEMENT;
276         bRGB1 = MUX_0;
277     }
278     if( aA0 != MUX_1 && bA0 != MUX_0 )
279     {
280         aA0 = bA0|MUX_COMPLEMENT;
281         bA0 = MUX_0;
282     }
283     if( aA1 != MUX_1 && bA1 != MUX_0 )
284     {
285         aA1 = bA1|MUX_COMPLEMENT;
286         bA1 = MUX_0;
287     }
288 }
289
290
291 CombinerFormatType DecodedMux::GetCombinerFormatType(uint32 cycle)
292 {
293     //Analyze the formula
294     /*
295     C=0                 = D
296     A==B                = D
297     B=0, C=1, D=0       = A
298     A=1, B=0, D=0       = C
299     C=1, B==D           = A
300     A=1, C=1, D=0       = 1-B
301     D = 1               = 1
302     */
303     return CM_FMT_TYPE_D;
304 }
305
306 void DecodedMuxForPixelShader::Simplify(void)
307 {
308     CheckCombineInCycle1();
309     //Reformat();
310
311     if( g_curRomInfo.bTexture1Hack )
312     {
313         ReplaceVal(MUX_TEXEL1,MUX_TEXEL0,2);
314         ReplaceVal(MUX_TEXEL1,MUX_TEXEL0,3);
315     }
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;
321
322     m_bTexel0IsUsed = isUsed(MUX_TEXEL0);
323     m_bTexel1IsUsed = isUsed(MUX_TEXEL1);
324 }
325
326 void DecodedMuxForSemiPixelShader::Reset(void)
327 {
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;
333
334     Hack();
335
336     gRSP.bProcessDiffuseColor = false;
337     gRSP.bProcessSpecularColor = false;
338
339     CheckCombineInCycle1();
340     if( g_curRomInfo.bTexture1Hack )
341     {
342         ReplaceVal(MUX_TEXEL1,MUX_TEXEL0,2);
343         ReplaceVal(MUX_TEXEL1,MUX_TEXEL0,3);
344     }
345
346     m_bTexel0IsUsed = isUsed(MUX_TEXEL0);
347     m_bTexel1IsUsed = isUsed(MUX_TEXEL1);
348 }
349
350 void DecodedMuxForOGL14V2::Simplify(void)
351 {
352     CheckCombineInCycle1();
353     if( g_curRomInfo.bTexture1Hack )
354     {
355         ReplaceVal(MUX_TEXEL1,MUX_TEXEL0,2);
356         ReplaceVal(MUX_TEXEL1,MUX_TEXEL0,3);
357     }
358     Reformat();
359
360     UseTextureForConstant();
361     Reformat();
362
363     m_bTexel0IsUsed = isUsed(MUX_TEXEL0);
364     m_bTexel1IsUsed = isUsed(MUX_TEXEL1);
365 }
366
367 void DecodedMux::Simplify(void)
368 {
369     CheckCombineInCycle1();
370     if( gRDP.otherMode.text_lod )
371         ConvertLODFracTo0();
372     if( g_curRomInfo.bTexture1Hack )
373     {
374         ReplaceVal(MUX_TEXEL1,MUX_TEXEL0,2);
375         ReplaceVal(MUX_TEXEL1,MUX_TEXEL0,3);
376     }
377     Reformat();
378
379     UseShadeForConstant();
380     Reformat();
381
382     if( m_dwShadeColorChannelFlag == MUX_0 )
383     {
384         MergeShadeWithConstants();
385         Reformat();
386     }
387
388 #ifdef ALLOW_USE_TEXTURE_FOR_CONSTANTS
389     UseTextureForConstant();
390     for( int i=0; i<2; i++ )
391     {
392         if( m_ColorTextureFlag[i] != 0 )
393         {
394             if( m_dwShadeColorChannelFlag == m_ColorTextureFlag[i] )
395             {
396                 ReplaceVal(MUX_SHADE,MUX_TEXEL0+i,N64Cycle0RGB);
397                 ReplaceVal(MUX_SHADE,MUX_TEXEL0+i,N64Cycle1RGB);
398                 m_dwShadeColorChannelFlag = 0;
399             }
400             if( m_dwShadeAlphaChannelFlag == m_ColorTextureFlag[i] )
401             {
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;
407             }
408         }
409     }
410     Reformat();
411 #endif
412
413     m_bTexel0IsUsed = isUsed(MUX_TEXEL0);
414     m_bTexel1IsUsed = isUsed(MUX_TEXEL1);
415 }
416
417 void DecodedMux::Reformat(bool do_complement)
418 {
419     if( m_dWords[N64Cycle0RGB] == m_dWords[N64Cycle1RGB] )
420     {
421         aRGB1 = MUX_0;
422         bRGB1 = MUX_0;
423         cRGB1 = MUX_0;
424         dRGB1 = MUX_COMBINED;
425         splitType[N64Cycle1RGB] = CM_FMT_TYPE_NOT_USED;
426     }
427
428     if( m_dWords[N64Cycle0Alpha] == m_dWords[N64Cycle1Alpha] )
429     {
430         aA1 = MUX_0;
431         bA1 = MUX_0;
432         cA1 = MUX_0;
433         dA1 = MUX_COMBINED;
434         splitType[N64Cycle1Alpha] = CM_FMT_TYPE_NOT_USED;
435     }
436
437     for( int i=0; i<4; i++ )
438     {
439         if( splitType[i] == CM_FMT_TYPE_NOT_USED )
440         {
441             continue;   //Skip this, it is not used
442         }
443
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 ) 
449         {
450             m.a = m.b;
451             m.b = m.d = 0;
452             //Hack for Mario Tennis
453             if( options.enableHackForGames == HACK_FOR_MARIO_TENNIS && m.c == MUX_TEXEL1 )
454             {
455                 if( do_complement )
456                     m.c = MUX_TEXEL0|MUX_COMPLEMENT;
457                 else
458                 {
459                     m.a = m.c;
460                     m.c = m.b;
461                     m.b = m.a;
462                     m.a = MUX_1;
463                 }
464             }
465             //m.c ^= MUX_COMPLEMENT;
466         }
467
468         //Type 1    == D
469         //Analyze the formula
470         //Check Type 1
471         //D = 1             = D(=1)
472         //C=0               = D
473         //A==B              = D
474         //B=0, C=1, D=0     = A
475         //C=1, B==D         = A
476         //A=1, B=0, D=0     = C
477         //A=1, C=1, D=0     = 1-B
478
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)) )
481         {
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;
485         }
486         else if( (m.b == MUX_0 && m.c == MUX_1 && m.d == MUX_0 ) || ( m.c == MUX_1 && m.b==m.d ) )
487         {
488             splitType[i] = CM_FMT_TYPE_D;   //All Type 1 will be changed to = D
489             m.d = m.a;
490             m.a =  m.b = m.c = MUX_0;
491             if( m.d == MUX_COMBINED && i>=N64Cycle1RGB )    splitType[i] = CM_FMT_TYPE_NOT_USED;
492         }
493         else if( m.a == MUX_1 && m.b == MUX_0 && m.d == MUX_0 )
494         {
495             splitType[i] = CM_FMT_TYPE_D;   //All Type 1 will be changed to = D
496             m.d = m.c;
497             m.a =  m.b = m.c = MUX_0;
498             if( m.d == MUX_COMBINED && i>=N64Cycle1RGB )    splitType[i] = CM_FMT_TYPE_NOT_USED;
499         }
500         else if( m.a == MUX_1 && m.c == MUX_1 && m.d == MUX_0 && do_complement )
501         {
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;
506         }
507
508         if( splitType[i] == CM_FMT_TYPE_NOT_USED )
509             continue;
510
511         if( splitType[i] == CM_FMT_TYPE_D )
512         {
513             if( (i == N64Cycle0RGB || i == N64Cycle0Alpha) && splitType[i+2]!=CM_FMT_TYPE_NOT_USED )    //Cycle 1's Color or Alpha
514             {
515                 uint8 saveD = m.d;
516                 for( int j=0; j<4; j++ )
517                 {
518                     if( (m_bytes[j+i*4+8]&MUX_MASK) == MUX_COMBINED )
519                     {
520                         m_bytes[j+i*4+8] = saveD|(m_bytes[j+i*4+8]&0xC0);   //Replace cycle's CMB with D from cycle 1
521                     }
522                 }
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
528                 continue;
529             }
530
531             if( (i==2 || i == 3) && (m.d&MUX_MASK) == MUX_COMBINED )
532             {
533                 splitType[i] = CM_FMT_TYPE_NOT_USED;
534             }
535             continue;
536         }
537
538
539         //Type 2: A+D   ' ADD
540         //B=0, C=1          = A+D
541         //A=1, B=0          = C+D
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 )
544         {
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);
547             continue;
548         }
549
550         if( m.a == MUX_1 && m.b == MUX_0 )
551         {
552             m.a = m.c;          //Change format A+D
553             m.c = MUX_1;
554             if( m.d == MUX_TEXEL0 || m.d == MUX_TEXEL1 )    swap(m.a, m.d);
555             continue;
556         }
557
558
559         //Type 3: A*C
560         //B=0, D=0          = A*C
561         //A=1, D=0          = (1-A)*C
562         splitType[i] = CM_FMT_TYPE_A_MOD_C;         //A*C
563         if( m.b == MUX_0 && m.d == MUX_0 )
564         {
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);
567             continue;
568         }
569
570         if( m.a == MUX_1 && m.d == MUX_0 && do_complement )
571         {
572             m.a = m.b^MUX_COMPLEMENT;
573             m.b = MUX_0;
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);
576             continue;
577         }
578
579         //Type 4: A-B   ' SUB
580         //C=1, D=0          = A-B
581         splitType[i] = CM_FMT_TYPE_A_SUB_B;         //A-B
582         if( m.c == MUX_1 && m.d == MUX_0 )
583         {
584             continue;
585         }
586
587         //Type 5: A*C+D , ' MULTIPLYADD
588         //B=0               = A*C+D
589         //A=1               = (1-B) * C + D
590         splitType[i] = CM_FMT_TYPE_A_MOD_C_ADD_D;
591         if( m.b == MUX_0 )
592         {
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); 
595             continue;
596         }
597
598         if( m.a == MUX_1 && m.b!=m.d && do_complement )
599         {
600             m.a = m.b^MUX_COMPLEMENT;
601             m.b = MUX_0;
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); 
604             continue;
605         }
606
607         //Type 6: (A-B)*C+B Map to LERP, or BLENDALPHA
608         //D==B
609         splitType[i] = CM_FMT_TYPE_A_LERP_B_C;
610         if( m.b == m.d )
611         {
612             continue;
613         }
614
615
616         //Type 7: A-B+D
617         //C=1               = A-B+D
618         splitType[i] = CM_FMT_TYPE_A_SUB_B_ADD_D;
619         if( m.c == MUX_1 )
620         {
621             if( m.c == MUX_TEXEL0 || m.c == MUX_TEXEL1 )    swap(m.a, m.c);
622             continue;
623         }
624
625         //Type 8: (A-B)*C
626         splitType[i] = CM_FMT_TYPE_A_SUB_B_MOD_C;
627         if( m.d == MUX_0 )
628         {
629             continue;
630         }
631
632         if( m.c == m.d && do_complement )   // (A-B)*C+C   ==> (A + B|C ) * C
633         {
634             m.d = MUX_0;
635             m.b |= MUX_COMPLEMENT;
636             continue;
637         }
638
639         if( m.a == m.d )
640         {
641             splitType[i] = CM_FMT_TYPE_A_B_C_A;
642             continue;
643         }
644
645         //Type 9: (A-B)*C+D
646         splitType[i] = CM_FMT_TYPE_A_B_C_D;
647     }
648
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) )
651     {
652         //Replace cycle 1 color with cycle 2 color because we have already replace cycle2's cmb 
653         aRGB0 = aRGB1;
654         bRGB0 = bRGB1;
655         cRGB0 = cRGB1;
656         dRGB0 = dRGB1;
657         aRGB1 = MUX_0;
658         bRGB1 = MUX_0;
659         cRGB1 = MUX_0;
660         dRGB1 = MUX_COMBINED;
661         splitType[0] = splitType[2];
662         splitType[2] = CM_FMT_TYPE_NOT_USED;
663     }
664
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) )
667     {
668         //Replace cycle 1 alpha with cycle 2 alpha because we have already replace cycle2's cmb 
669         aA0 = aA1;
670         bA0 = bA1;
671         cA0 = cA1;
672         dA0 = dA1;
673         aA1 = MUX_0;
674         bA1 = MUX_0;
675         cA1 = MUX_0;
676         dA1 = MUX_COMBINED;
677         splitType[1] = splitType[3];
678         splitType[3] = CM_FMT_TYPE_NOT_USED;
679     }
680
681     if( splitType[0] == CM_FMT_TYPE_A_MOD_C && splitType[2] == CM_FMT_TYPE_A_ADD_D )
682     {
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;
689     }
690
691     if( splitType[1] == CM_FMT_TYPE_A_MOD_C && splitType[3] == CM_FMT_TYPE_A_ADD_D )
692     {
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;
699     }
700     
701     mType = max(max(max(splitType[0], splitType[1]),splitType[2]),splitType[3]);
702 }
703
704 const char* MuxGroupStr[4] =
705 {
706     "Color0",
707     "Alpha0",
708     "Color1",
709     "Alpha1",
710 };
711
712 char* DecodedMux::FormatStr(uint8 val, char *buf)
713 {
714     if( val == CM_IGNORE_BYTE )
715     {
716         strcpy(buf," ");
717     }
718     else
719     {
720         strcpy(buf, translatedCombTypes[val&MUX_MASK]);
721         if( val&MUX_ALPHAREPLICATE )
722             strcat(buf,"|A");
723         if( val&MUX_COMPLEMENT )
724             strcat(buf,"|C");
725         if( val&MUX_NEG )
726             strcat(buf,"|N");
727     }
728
729     return buf;
730 }
731
732 void DecodedMux::Display(bool simplified,FILE *fp)
733 {
734     DecodedMux decodedMux;
735     DecodedMux *mux;
736     if( simplified )
737     {
738         mux = this;
739     }
740     else
741     {
742         decodedMux.Decode(m_dwMux0, m_dwMux1);
743         mux = &decodedMux;
744     }
745
746     char buf0[30];
747     char buf1[30];
748     char buf2[30];
749     char buf3[30];
750
751     for( int i=0; i<2; i++ )
752     {
753         for(int j=0;j<2;j++)
754         {
755             N64CombinerType &m = mux->m_n64Combiners[i+2*j];
756             if( fp )
757             {
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));
760             }
761             else
762             {
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));
765             }
766         }
767     }
768 }
769
770 int DecodedMux::HowManyConstFactors()
771 {
772     int n=0;
773     if( isUsed(MUX_PRIM) ) n++;
774     if( isUsed(MUX_ENV) ) n++;
775     if( isUsed(MUX_LODFRAC) ) n++;
776     if( isUsed(MUX_PRIMLODFRAC) ) n++;
777     return n;
778 }
779
780 int DecodedMux::HowManyTextures()
781 {
782     int n=0;
783     if( isUsed(MUX_TEXEL0) ) n++;
784     if( isUsed(MUX_TEXEL1) ) n++;
785     return n;
786 }
787
788 int DecodedMux::CountTexels(void)
789 {
790     int count=0;
791
792     for( int i=0; i<4; i++ )
793     {
794         N64CombinerType &m = m_n64Combiners[i];
795         count = max(count, ::CountTexel1Cycle(m));
796         if( count == 2 ) 
797             break;
798     }
799
800     return count;
801 }
802
803 void DecodedMux::ReplaceVal(uint8 val1, uint8 val2, int cycle, uint8 mask)
804 {
805     int start = 0;
806     int end = 16;
807
808     if( cycle >= 0 )
809     {
810         start = cycle*4;
811         end = start+4;
812     }
813
814     uint8* pmux = m_bytes;
815     for( int i=start; i<end; i++ )
816     {
817         if( (pmux[i]&mask) == (val1&mask) )
818         {
819             pmux[i] &= (~mask);
820             pmux[i] |= val2;
821         }
822     }
823 }
824
825 uint32 DecodedMux::GetCycle(int cycle, CombineChannel channel)
826 {
827     uint32* pmux = m_dWords;
828     if( channel == COLOR_CHANNEL )
829     {
830         return pmux[cycle*2];
831     }
832     else
833     {
834         return pmux[cycle*2+1];
835     }
836
837 }
838
839 uint32 DecodedMux::GetCycle(int cycle)
840 {
841     return m_dWords[cycle];
842 }
843
844 enum ShadeConstMergeType
845 {
846     SHADE_DO_NOTHING,
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,
853     SHADE_MOD_ENV,
854 };
855
856 typedef struct 
857 {
858 uint64 mux; // simplified
859 ShadeConstMergeType op;
860 } ShadeConstMergeMapType;
861
862 ShadeConstMergeMapType MergeShadeWithConstantsMaps[] =
863 {
864 {0, SHADE_DO_NOTHING},
865 {0x0007000600070006LL, SHADE_MOD_ENV}, // SHADE * ENV
866 };
867
868 // 0x05070501, 0x00070006       //(1 - PRIM) * ENV + PRIM
869 // 0x00050003, 0x00050003       //(TEXEL0 - 0) * PRIM + 0
870
871 void DecodedMux::MergeShadeWithConstants(void)
872 {
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
878
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
881
882     if( m_bShadeIsUsed[0] ) MergeShadeWithConstantsInChannel(COLOR_CHANNEL);
883     if( m_bShadeIsUsed[1] ) MergeShadeWithConstantsInChannel(ALPHA_CHANNEL);
884 }
885
886 void DecodedMux::MergeShadeWithConstantsInChannel(CombineChannel channel)
887 {
888     bool usedIn[2];
889     uint32 cycleVal;
890     int cycleNum;
891
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) )
895     {
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
898         return; 
899     }
900
901     if( usedIn[0] ) { cycleVal = GetCycle(channel);cycleNum=0;}
902     else            {cycleVal = GetCycle(channel+2);cycleNum=1;}
903
904
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
907
908     if( cycleVal == 0x06000000 || isUsedInCycle(MUX_COMBINED,channel+cycleNum*2) )  // (0-0)*0+Shade
909     {
910         return;
911     }
912
913     //Now we can merge shade with consts
914     for( int i=0; i<2; i++ )
915     {
916         if( usedIn[i] )
917         {
918             N64CombinerType &m = m_n64Combiners[channel+i*2];
919             if( isUsedInCycle(MUX_TEXEL0,i*2+channel) || isUsedInCycle(MUX_TEXEL1,i*2+channel) )
920             {
921                 if( (m.a&MUX_MASK) == MUX_TEXEL0 || (m.a&MUX_MASK) == MUX_TEXEL1 )
922                 {
923                     // m.a is texel, can not merge constant with shade
924                     return;
925                 }
926                 else if( (m.b&MUX_MASK) == MUX_TEXEL0 || (m.b&MUX_MASK) == MUX_TEXEL1 )
927                 {
928                     // m.b is texel, can not merge constant with shade
929                     return;
930                 }
931                 else if(( (m.c&MUX_MASK) == MUX_TEXEL0 || (m.c&MUX_MASK) == MUX_TEXEL1 ) )
932                 {
933                     if( (m.d&MUX_MASK) != MUX_SHADE )
934                     {
935                         cycleVal &= 0x0000FFFF;     // A-B
936                     }
937                     else if( (m.a&MUX_MASK) == MUX_SHADE || (m.b&MUX_MASK) == MUX_SHADE )
938                     {
939                         return;
940                     }
941                 }
942                 else if( (m.d&MUX_MASK) == MUX_TEXEL0 || (m.d&MUX_MASK) == MUX_TEXEL1 )
943                 {
944                     cycleVal &= 0x00FFFFFF;     // (A-B)*C
945                 }
946             }
947             else
948             {
949                 m.a = m.b = m.c = MUX_0;
950                 m.d = MUX_SHADE;
951                 splitType[i*2+channel] = CM_FMT_TYPE_D;
952             }
953         }
954     }
955
956     if( channel == COLOR_CHANNEL )
957         m_dwShadeColorChannelFlag = cycleVal;
958     else
959         m_dwShadeAlphaChannelFlag = cycleVal;
960 }
961
962
963 void DecodedMux::MergeConstants(void)
964 {
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
968
969     // This function should be called after the MergeShadeWithConstants() function
970 }
971
972
973 void DecodedMux::UseShadeForConstant(void)
974 {
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
977
978     bool doAlphaChannel = true;
979     uint8 mask = (uint8)~MUX_COMPLEMENT;
980
981     int constants = 0;
982     if( isUsed(MUX_ENV) ) constants++;
983     if( isUsed(MUX_PRIM) ) constants++;
984     if( isUsed(MUX_LODFRAC) ) constants++;
985     if( isUsed(MUX_PRIMLODFRAC) ) constants++;
986
987     bool forceToUsed = constants>m_maxConstants;
988
989     if( !isUsedInColorChannel(MUX_SHADE) && (forceToUsed || max(splitType[0], splitType[2]) >= CM_FMT_TYPE_A_MOD_C_ADD_D) )
990     {
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 )
994         {
995             if( countPrim >= countEnv )
996             {
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;
1001             }
1002             else if( countEnv>0 )
1003             {
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;
1008             }
1009
1010             if( isUsedInColorChannel(MUX_SHADE|MUX_ALPHAREPLICATE, mask) )
1011             {
1012                 m_dwShadeAlphaChannelFlag = m_dwShadeColorChannelFlag;
1013                 ReplaceVal((uint8)m_dwShadeColorChannelFlag, MUX_SHADE, N64Cycle0Alpha);
1014                 ReplaceVal((uint8)m_dwShadeColorChannelFlag, MUX_SHADE, N64Cycle1Alpha);
1015                 doAlphaChannel = false;
1016             }
1017         }
1018     }
1019
1020     if( doAlphaChannel && !isUsedInAlphaChannel(MUX_SHADE) && !isUsedInColorChannel(MUX_SHADE|MUX_ALPHAREPLICATE,MUX_MASK_WITH_ALPHA))
1021     {
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);
1024
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 ) )
1027         {
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 )
1033             {
1034                 if( countPrim>0 && m_dwShadeColorChannelFlag == MUX_PRIM )
1035                 {
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;
1042                 }               
1043                 else if( countEnv>0 && m_dwShadeColorChannelFlag == MUX_ENV )
1044                 {
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;
1051                 }               
1052                 else if( countPrim >= countEnv )
1053                 {
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;
1060                 }
1061                 else if( countEnv>0 )
1062                 {
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;
1069                 }
1070             }
1071         }
1072     }
1073 }
1074
1075 void DecodedMux::UseTextureForConstant(void)
1076 {
1077     int numofconst = HowManyConstFactors();
1078     int numOftex = HowManyTextures();
1079
1080     if( numofconst > m_maxConstants && numOftex < m_maxTextures )
1081     {
1082         // We can use a texture for a constant
1083         for( int i=0; i<2 && numofconst > m_maxConstants ; i++ )
1084         {
1085             if( isUsed(MUX_TEXEL0+i) )
1086             {
1087                 continue;   // can not use this texture
1088             }
1089
1090             if( isUsed(MUX_PRIM) )
1091             {
1092                 ReplaceVal(MUX_PRIM, MUX_TEXEL0+i);
1093                 m_ColorTextureFlag[i] = MUX_PRIM;
1094                 numofconst--;
1095                 continue;
1096             }
1097
1098             if( isUsed(MUX_ENV) )
1099             {
1100                 ReplaceVal(MUX_ENV, MUX_TEXEL0+i);
1101                 m_ColorTextureFlag[i] = MUX_ENV;
1102                 numofconst--;
1103                 continue;
1104             }
1105
1106             if( isUsed(MUX_LODFRAC) )
1107             {
1108                 ReplaceVal(MUX_LODFRAC, MUX_TEXEL0+i);
1109                 m_ColorTextureFlag[i] = MUX_LODFRAC;
1110                 numofconst--;
1111                 continue;
1112             }
1113
1114             if( isUsed(MUX_PRIMLODFRAC) )
1115             {
1116                 ReplaceVal(MUX_PRIMLODFRAC, MUX_TEXEL0+i);
1117                 m_ColorTextureFlag[i] = MUX_PRIMLODFRAC;
1118                 numofconst--;
1119                 continue;
1120             }
1121         }
1122     }
1123 }
1124
1125
1126 void DecodedMuxForOGL14V2::UseTextureForConstant(void)
1127 {
1128     bool envused = isUsed(MUX_ENV);
1129     bool lodused = isUsed(MUX_LODFRAC);
1130     
1131     int numofconst = 0;
1132     if( envused ) numofconst++;
1133     if( lodused ) numofconst++;
1134
1135     int numOftex = HowManyTextures();
1136
1137     if( numofconst > 0 && numOftex < 2 )
1138     {
1139         // We can use a texture for a constant
1140         for( int i=0; i<2 && numofconst > 0 ; i++ )
1141         {
1142             if( isUsed(MUX_TEXEL0+i) )
1143             {
1144                 continue;   // can not use this texture
1145             }
1146
1147             if( envused )
1148             {
1149                 ReplaceVal(MUX_ENV, MUX_TEXEL0+i);
1150                 m_ColorTextureFlag[i] = MUX_ENV;
1151                 numofconst--;
1152                 envused = false;
1153                 continue;
1154             }
1155
1156             if( isUsed(MUX_LODFRAC) )
1157             {
1158                 ReplaceVal(MUX_LODFRAC, MUX_TEXEL0+i);
1159                 m_ColorTextureFlag[i] = MUX_LODFRAC;
1160                 numofconst--;
1161                 continue;
1162             }
1163
1164             if( isUsed(MUX_PRIMLODFRAC) )
1165             {
1166                 ReplaceVal(MUX_PRIMLODFRAC, MUX_TEXEL0+i);
1167                 m_ColorTextureFlag[i] = MUX_PRIMLODFRAC;
1168                 numofconst--;
1169                 continue;
1170             }
1171         }
1172     }
1173 }
1174
1175 #ifdef DEBUGGER
1176 extern const char *translatedCombTypes[];
1177 void DecodedMux::DisplayMuxString(const char *prompt)
1178 {
1179     DebuggerAppendMsg("//Mux=0x%08x%08x\t%s in %s\n", m_dwMux0, m_dwMux1, prompt, g_curRomInfo.szGameName);
1180     Display(false);
1181     TRACE0("\n");
1182 }
1183
1184 void DecodedMux::DisplaySimpliedMuxString(const char *prompt)
1185 {
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]);
1188     Display(true);
1189     DebuggerAppendMsg("Simplfied type: %s", muxTypeStrs[mType]);
1190     if( m_dwShadeColorChannelFlag != 0 )
1191     {
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")
1200         else
1201             DisplayConstantsWithShade(m_dwShadeColorChannelFlag,COLOR_CHANNEL);
1202     }
1203     if( m_dwShadeAlphaChannelFlag != 0 )
1204     {
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")
1213         else
1214             DisplayConstantsWithShade(m_dwShadeAlphaChannelFlag,ALPHA_CHANNEL);
1215     }
1216
1217     for( int i=0; i<2; i++ )
1218     {
1219         if( m_ColorTextureFlag[i] != 0 )
1220         {
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)
1229         }
1230     }
1231
1232
1233     TRACE0("\n");
1234 }
1235
1236 void DecodedMux::DisplayConstantsWithShade(uint32 flag,CombineChannel channel)
1237 {
1238     DebuggerAppendMsg("Shade = %08X in %s channel",flag,channel==COLOR_CHANNEL?"color":"alpha");
1239 }
1240 #else
1241
1242 extern const char *translatedCombTypes[];
1243 void DecodedMux::LogMuxString(const char *prompt, FILE *fp)
1244 {
1245     fprintf(fp,"//Mux=0x%08x%08x\t%s in %s\n", m_dwMux0, m_dwMux1, prompt, g_curRomInfo.szGameName);
1246     Display(false,fp);
1247     TRACE0("\n");
1248 }
1249
1250 void DecodedMux::LogSimpliedMuxString(const char *prompt, FILE *fp)
1251 {
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]);
1254     Display(true,fp);
1255     fprintf(fp,"Simplfied type: %s", muxTypeStrs[mType]);
1256     if( m_dwShadeColorChannelFlag != 0 )
1257     {
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")
1266         else
1267         LogConstantsWithShade(m_dwShadeColorChannelFlag,COLOR_CHANNEL,fp);
1268     }
1269     if( m_dwShadeAlphaChannelFlag != 0 )
1270     {
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")
1279         else
1280         LogConstantsWithShade(m_dwShadeAlphaChannelFlag,ALPHA_CHANNEL,fp);
1281     }
1282
1283     for( int i=0; i<2; i++ )
1284     {
1285         if( m_ColorTextureFlag[i] != 0 )
1286         {
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)
1295         }
1296     }
1297
1298
1299     TRACE0("\n");
1300 }
1301
1302 void DecodedMux::LogConstantsWithShade(uint32 flag,CombineChannel channel, FILE *fp)
1303 {
1304     fprintf(fp,"Shade = %08X in %s channel",flag,channel==COLOR_CHANNEL?"color":"alpha");
1305 }
1306 #endif
1307
1308
1309 void DecodedMux::To_AB_Add_CD_Format(void)  // Use by TNT,Geforce
1310 {
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
1314
1315     for( int i=0; i<2; i++ )
1316     {
1317         N64CombinerType &m0 = m_n64Combiners[i];
1318         N64CombinerType &m1 = m_n64Combiners[i+2];
1319         switch( splitType[i] )
1320         {
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 )
1323             {
1324                 m1.a = m0.d;
1325                 m1.d = MUX_COMBINED;
1326                 splitType[i+2] = CM_FMT_TYPE_A_ADD_D;
1327
1328                 m0.d = MUX_0;
1329                 splitType[i] = CM_FMT_TYPE_A_SUB_B;
1330             }
1331             else if( splitType[i+2] == CM_FMT_TYPE_A_MOD_C )
1332             {
1333                 if( (m1.c&MUX_MASK) == MUX_COMBINED )   swap(m1.a, m1.c);
1334                 m1.b = m1.d = m1.c;
1335                 m1.c = (m0.d | (m1.a & (~MUX_MASK)));
1336                 splitType[i+2] = CM_FMT_TYPE_AB_ADD_CD;
1337
1338                 m0.d = MUX_0;
1339                 splitType[i] = CM_FMT_TYPE_A_SUB_B;
1340             }
1341             break;
1342         case CM_FMT_TYPE_A_SUB_B_MOD_C:     // = (A-B)*C    can not map very well in 1 stage
1343             m0.d = m0.b;
1344             m0.b = m0.c;
1345             splitType[i] = CM_FMT_TYPE_AB_SUB_CD;
1346             break;
1347         case CM_FMT_TYPE_A_ADD_B_MOD_C:     // = (A+B)*C    can not map very well in 1 stage
1348             m0.d = m0.b;
1349             m0.b = m0.c;
1350             splitType[i] = CM_FMT_TYPE_AB_ADD_CD;
1351             break;
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 )
1355             {
1356                 m1.a = m0.d;
1357                 m1.d = MUX_COMBINED;
1358                 splitType[i+2] = CM_FMT_TYPE_A_ADD_D;
1359
1360                 m0.d = m0.b;
1361                 m0.b = m0.c;
1362                 splitType[i] = CM_FMT_TYPE_AB_SUB_CD;
1363             }
1364             else if( splitType[i+2] == CM_FMT_TYPE_A_MOD_C )
1365             {
1366                 if( (m1.c&MUX_MASK) == MUX_COMBINED )   swap(m1.a, m1.c);
1367                 m1.b = m1.d = m1.c;
1368                 m1.c = (m0.d | (m1.a & (~MUX_MASK)));
1369                 splitType[i+2] = CM_FMT_TYPE_AB_ADD_CD;
1370
1371                 m0.d = m0.b;
1372                 m0.b = m0.c;
1373                 splitType[i] = CM_FMT_TYPE_AB_ADD_CD;
1374             }
1375             break;
1376          default:
1377            break;
1378         }
1379     }
1380 }
1381
1382 void DecodedMux::To_AB_Add_C_Format(void)   // Use by ATI Radeon
1383 {
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
1387 }
1388
1389 void DecodedMux::CheckCombineInCycle1(void)
1390 {
1391     if( isUsedInCycle(MUX_COMBINED,0,COLOR_CHANNEL) )
1392     {
1393         ReplaceVal(MUX_COMBINED, MUX_SHADE, 0);
1394     }
1395
1396     if( isUsedInCycle(MUX_COMBALPHA,0,COLOR_CHANNEL) )
1397     {
1398         ReplaceVal(MUX_COMBALPHA, MUX_SHADE|MUX_ALPHAREPLICATE, 0);
1399     }
1400
1401     if( isUsedInCycle(MUX_COMBINED,0,ALPHA_CHANNEL) )
1402     {
1403         if( cA0 == MUX_COMBINED && cRGB0 == MUX_LODFRAC && bRGB0 == dRGB0 && bA0 == dA0 )
1404         {
1405             cA0 = MUX_LODFRAC;
1406         }
1407         else
1408         {
1409             ReplaceVal(MUX_COMBINED, MUX_SHADE, 1);
1410         }
1411     }
1412     if( isUsedInCycle(MUX_COMBALPHA,0,ALPHA_CHANNEL) )
1413     {
1414         ReplaceVal(MUX_COMBALPHA, MUX_SHADE, 1);
1415     }
1416 }
1417
1418 void DecodedMux::SplitComplexStages()
1419 {
1420     for( int i=0; i<2; i++) // Color channel and alpha channel
1421     {
1422         if( splitType[i+2] != CM_FMT_TYPE_NOT_USED )    
1423             continue;
1424
1425         N64CombinerType &m = m_n64Combiners[i];
1426         N64CombinerType &m2 = m_n64Combiners[i+2];
1427         
1428         switch( splitType[i] )
1429         {
1430         case CM_FMT_TYPE_A_MOD_C_ADD_D:     // = A*C+D      can mapped to MULTIPLYADD(arg1,arg2,arg0)
1431             m2.a = m.d;
1432             m2.d = MUX_COMBINED;
1433             m2.c = MUX_1;
1434             m2.b = 0;
1435             splitType[i+2] = CM_FMT_TYPE_A_ADD_D;
1436             m.d = MUX_0;
1437             splitType[i] = CM_FMT_TYPE_A_MOD_C;
1438             break;
1439         case CM_FMT_TYPE_A_SUB_B_ADD_D:     // = A-B+D      can not map very well in 1 stage
1440             m2.a = m.d;
1441             m2.d = MUX_COMBINED;
1442             m2.c = MUX_1;
1443             m2.b=0;
1444             splitType[i+2] = CM_FMT_TYPE_A_ADD_D;
1445             m.d = MUX_0;
1446             splitType[i] = CM_FMT_TYPE_A_SUB_B;
1447             break;
1448         case CM_FMT_TYPE_A_SUB_B_MOD_C:     // = (A-B)*C    can not map very well in 1 stage
1449             m2.a = m.c;
1450             m2.c = MUX_COMBINED;
1451             m2.d = m2.b=0;
1452             splitType[i+2] = CM_FMT_TYPE_A_MOD_C;
1453             m.c = MUX_1;
1454             splitType[i] = CM_FMT_TYPE_A_SUB_B;
1455             break;
1456         case CM_FMT_TYPE_A_ADD_B_MOD_C:     // = (A+B)*C    can not map very well in 1 stage
1457             m2.a = m.c;
1458             m2.c = MUX_COMBINED;
1459             m2.d = m2.b = 0;
1460             splitType[i+2] = CM_FMT_TYPE_A_MOD_C;
1461             m.c = MUX_1;
1462             m.d = m.b;
1463             m.b = MUX_0;
1464             splitType[i] = CM_FMT_TYPE_A_ADD_D;
1465             break;
1466         case CM_FMT_TYPE_A_B_C_D:           // = (A-B)*C+D  can not map very well in 1 stage
1467             m2.a = m.d;
1468             m2.d = MUX_COMBINED;
1469             m2.c = MUX_1;
1470             m2.b = 0;
1471             splitType[i+2] = CM_FMT_TYPE_A_ADD_D;
1472             m.d = MUX_0;
1473             splitType[i] = CM_FMT_TYPE_A_SUB_B_MOD_C;
1474             break;
1475         case CM_FMT_TYPE_A_B_C_A:           // = (A-B)*C+A  can not map very well in 1 stage
1476             m2.a = m.d;
1477             m2.d = MUX_COMBINED;
1478             m2.c = MUX_1;
1479             m2.b = 0;
1480             splitType[i+2] = CM_FMT_TYPE_A_ADD_D;
1481             m.d = MUX_0;
1482             splitType[i] = CM_FMT_TYPE_A_SUB_B_MOD_C;
1483             break;
1484          default:
1485            break;
1486         }
1487     }
1488     //Reformat();
1489     //UseShadeForConstant();
1490 }
1491
1492
1493 void DecodedMux::ConvertLODFracTo0()
1494 {
1495     ReplaceVal(MUX_LODFRAC,MUX_0);
1496     ReplaceVal(MUX_PRIMLODFRAC,MUX_0);
1497 }
1498
1499
1500 void DecodedMux::Hack(void)
1501 {
1502     if( options.enableHackForGames == HACK_FOR_TONYHAWK )
1503     {
1504         if( gRSP.curTile == 1 )
1505         {
1506             ReplaceVal(MUX_TEXEL1, MUX_TEXEL0);
1507         }
1508     }
1509     else if( options.enableHackForGames == HACK_FOR_ZELDA || options.enableHackForGames == HACK_FOR_ZELDA_MM)
1510     {
1511         if( m_dwMux1 == 0xfffd9238 && m_dwMux0 == 0x00ffadff )
1512         {
1513             ReplaceVal(MUX_TEXEL1, MUX_TEXEL0);
1514         }
1515         else if( m_dwMux1 == 0xff5bfff8 && m_dwMux0 == 0x00121603 )
1516         {
1517             // The Zelda road trace
1518             ReplaceVal(MUX_TEXEL1, MUX_0);
1519         }
1520     }
1521     else if( options.enableHackForGames == HACK_FOR_MARIO_TENNIS )
1522     {
1523         if( m_dwMux1 == 0xffebdbc0 && m_dwMux0 == 0x00ffb9ff )
1524         {
1525             // Player shadow
1526             //m_decodedMux.dRGB0 = MUX_TEXEL0;
1527             //m_decodedMux.dRGB1 = MUX_COMBINED;
1528             cA1 = MUX_TEXEL0;
1529         }
1530     }
1531     else if( options.enableHackForGames == HACK_FOR_MARIO_GOLF )
1532     {
1533         // Hack for Mario Golf
1534         if( m_dwMux1 == 0xf1ffca7e || m_dwMux0 == 0x00115407 )
1535         {
1536             // The grass
1537             ReplaceVal(MUX_TEXEL0, MUX_TEXEL1);
1538         }
1539     }
1540     else if( options.enableHackForGames == HACK_FOR_TOPGEARRALLY )
1541     {
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 )
1548         {
1549             // The grass
1550             //ReplaceVal(MUX_TEXEL0, MUX_TEXEL1);
1551             dA1 = MUX_COMBINED;
1552             //aA1 = MUX_COMBINED;
1553             //cA1 = MUX_TEXEL1;
1554             //dA1 = MUX_0;
1555             cRGB1 = MUX_TEXEL0;
1556         }
1557     }
1558 }
1559