Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
alexbevi
GitHub Repository: alexbevi/BizHawk
Path: blob/master/libmupen64plus/mupen64plus-video-rice/src/DecodedMux.cpp
2 views
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
1560
1561