Rice Video Plugin for GLES1.1
[mupen64plus-pandora.git] / source / rice_gles / src / DecodedMux.cpp
CommitLineData
d07c171f 1/*
2Copyright (C) 2002 Rice1964
3
4This program is free software; you can redistribute it and/or
5modify it under the terms of the GNU General Public License
6as published by the Free Software Foundation; either version 2
7of the License, or (at your option) any later version.
8
9This program is distributed in the hope that it will be useful,
10but WITHOUT ANY WARRANTY; without even the implied warranty of
11MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12GNU General Public License for more details.
13
14You should have received a copy of the GNU General Public License
15along with this program; if not, write to the Free Software
16Foundation, 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
28static 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
40static 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};
47static 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
54const 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
91const 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
105void 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
164int 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
190bool 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
206bool 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
225bool 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
242bool 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
259bool 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
265void 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
291CombinerFormatType 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
306void 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
326void 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
350void 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
367void 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
417void 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
704const char* MuxGroupStr[4] =
705{
706 "Color0",
707 "Alpha0",
708 "Color1",
709 "Alpha1",
710};
711
712char* 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
732void 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
770int 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
780int DecodedMux::HowManyTextures()
781{
782 int n=0;
783 if( isUsed(MUX_TEXEL0) ) n++;
784 if( isUsed(MUX_TEXEL1) ) n++;
785 return n;
786}
787
788int 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
803void 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
825uint32 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
839uint32 DecodedMux::GetCycle(int cycle)
840{
841 return m_dWords[cycle];
842}
843
844enum 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
856typedef struct
857{
858uint64 mux; // simplified
859ShadeConstMergeType op;
860} ShadeConstMergeMapType;
861
862ShadeConstMergeMapType 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
871void 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
886void 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
963void 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
973void 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
1075void 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
1126void 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
1176extern const char *translatedCombTypes[];
1177void 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
1184void 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
1236void DecodedMux::DisplayConstantsWithShade(uint32 flag,CombineChannel channel)
1237{
1238 DebuggerAppendMsg("Shade = %08X in %s channel",flag,channel==COLOR_CHANNEL?"color":"alpha");
1239}
1240#else
1241
1242extern const char *translatedCombTypes[];
1243void 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
1250void 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
1302void 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
1309void 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
1382void 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
1389void 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
1418void 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
1493void DecodedMux::ConvertLODFracTo0()
1494{
1495 ReplaceVal(MUX_LODFRAC,MUX_0);
1496 ReplaceVal(MUX_PRIMLODFRAC,MUX_0);
1497}
1498
1499
1500void 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