Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
alexbevi
GitHub Repository: alexbevi/BizHawk
Path: blob/master/libmupen64plus/mupen64plus-video-rice/src/Combiner.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
20
#include "Combiner.h"
21
#include "Config.h"
22
#include "RenderBase.h"
23
24
//static BOOL g_bHiliteRGBAHack = FALSE;
25
26
27
#ifdef DEBUGGER
28
const char *constStrs[] = {
29
"MUX_0",
30
"MUX_1",
31
"MUX_COMBINED",
32
"MUX_TEXEL0",
33
"MUX_TEXEL1",
34
"MUX_PRIM",
35
"MUX_SHADE",
36
"MUX_ENV",
37
"MUX_COMBALPHA",
38
"MUX_T0_ALPHA",
39
"MUX_T1_ALPHA",
40
"MUX_PRIM_ALPHA",
41
"MUX_SHADE_ALPHA",
42
"MUX_ENV_ALPHA",
43
"MUX_LODFRAC",
44
"MUX_PRIMLODFRAC",
45
"MUX_K5",
46
"MUX_UNK",
47
};
48
49
const char *cycleTypeStrs[] = {
50
"1 Cycle",
51
"2 Cycle",
52
"Copy Mode",
53
"Fill Mode"
54
};
55
56
const char* constStr(uint32 op)
57
{
58
if(op<=MUX_UNK)
59
return constStrs[op];
60
else
61
return "Invalid-Const";
62
}
63
#endif
64
65
void swap(uint8 &a, uint8 &b)
66
{
67
uint8 c=a;
68
a=b;
69
b=c;
70
}
71
72
73
//========================================================================
74
75
//========================================================================
76
77
inline IColor GetIColor(uint8 flag, uint32 curCol)
78
{
79
IColor newc;
80
switch(flag&MUX_MASK)
81
{
82
case MUX_0:
83
newc = 0;
84
break;
85
case MUX_1:
86
newc = 0xFFFFFFFF;
87
break;
88
case MUX_PRIM:
89
newc = gRDP.primitiveColor;
90
break;
91
case MUX_ENV:
92
newc = gRDP.envColor;
93
break;
94
case MUX_COMBINED:
95
case MUX_SHADE:
96
newc = curCol;
97
break;
98
case MUX_K5:
99
newc = 0xFFFFFFFF;
100
break;
101
case MUX_UNK:
102
newc = curCol;
103
if( options.enableHackForGames == HACK_FOR_CONKER )
104
newc = 0xFFFFFFFF;
105
break;
106
default:
107
newc = curCol;
108
break;
109
}
110
111
if( flag&MUX_COMPLEMENT )
112
{
113
newc.Complement();
114
}
115
116
if( flag&MUX_ALPHAREPLICATE )
117
{
118
newc.AlphaReplicate();
119
}
120
121
return newc;
122
}
123
124
COLOR CalculateConstFactor(uint32 colorOp, uint32 alphaOp, uint32 curCol)
125
{
126
N64CombinerType m;
127
IColor color(curCol);
128
IColor alpha(curCol);
129
130
// For color channel
131
*(uint32*)&m = colorOp;
132
if( m.c != MUX_0 && m.a!=m.b)
133
{
134
if( m.a != MUX_0 ) color = GetIColor(m.a, curCol);
135
if( m.b != MUX_0 ) color -= GetIColor(m.b, curCol);
136
if( m.c != MUX_1 ) color *= GetIColor(m.c, curCol);
137
}
138
if( m.d != MUX_0 ) color += GetIColor(m.d, curCol);
139
140
// For alpha channel
141
*(uint32*)&m = alphaOp;
142
if( m.c != MUX_0 && m.a!=m.b)
143
{
144
if( m.a != MUX_0 ) alpha = GetIColor(m.a, curCol);
145
if( m.b != MUX_0 ) alpha -= GetIColor(m.b, curCol);
146
if( m.c != MUX_1 ) alpha *= GetIColor(m.c, curCol);
147
}
148
if( m.d != MUX_0 ) alpha += GetIColor(m.d, curCol);
149
150
return (COLOR)(((uint32)color&0x00FFFFFF)|((uint32)alpha&0xFF000000));
151
}
152
153
154
COLOR CColorCombiner::GetConstFactor(uint32 colorFlag, uint32 alphaFlag, uint32 defaultColor)
155
{
156
// Allows a combine mode to select what TFACTOR should be
157
uint32 color = defaultColor;
158
uint32 alpha = defaultColor;
159
160
switch (colorFlag&MUX_MASK)
161
{
162
case MUX_0:
163
break;
164
case MUX_FORCE_0:
165
color = 0;
166
break;
167
case MUX_1:
168
color = 0xFFFFFFFF;
169
break;
170
case MUX_PRIM:
171
color = gRDP.primitiveColor;
172
break;
173
case MUX_ENV:
174
color = gRDP.envColor;
175
break;
176
case MUX_LODFRAC:
177
color = COLOR_RGBA(gRDP.LODFrac, gRDP.LODFrac, gRDP.LODFrac, gRDP.LODFrac);
178
break;
179
case MUX_PRIMLODFRAC:
180
color = COLOR_RGBA(gRDP.primLODFrac, gRDP.primLODFrac, gRDP.primLODFrac, gRDP.primLODFrac);
181
break;
182
case MUX_PRIM_ALPHA:
183
{
184
IColor col(gRDP.primitiveColor);
185
col.AlphaReplicate();
186
color = (COLOR)col;
187
}
188
break;
189
case MUX_ENV_ALPHA:
190
{
191
IColor col(gRDP.envColor);
192
col.AlphaReplicate();
193
color = (COLOR)col;
194
}
195
break;
196
case MUX_K5:
197
color = 0xFFFFFFFF;
198
break;
199
case MUX_UNK:
200
color = defaultColor;
201
if( options.enableHackForGames == HACK_FOR_CONKER ) color = 0xFFFFFFFF;
202
break;
203
default:
204
color = defaultColor;
205
break;
206
}
207
208
if( colorFlag & MUX_COMPLEMENT )
209
{
210
color = 0xFFFFFFFF - color;
211
}
212
if( colorFlag & MUX_ALPHAREPLICATE )
213
{
214
color = color>>24;
215
color = color | (color<<8) | (color <<16) | (color<<24);
216
}
217
218
color &= 0x00FFFFFF; // For color channel only, not the alpha channel
219
220
221
switch (alphaFlag&MUX_MASK)
222
{
223
case MUX_0:
224
break;
225
case MUX_FORCE_0:
226
alpha = 0;
227
break;
228
case MUX_1:
229
alpha = 0xFFFFFFFF;
230
break;
231
case MUX_PRIM:
232
alpha = gRDP.primitiveColor;
233
break;
234
case MUX_ENV:
235
alpha = gRDP.envColor;
236
break;
237
case MUX_LODFRAC:
238
alpha = COLOR_RGBA(gRDP.LODFrac, gRDP.LODFrac, gRDP.LODFrac, gRDP.LODFrac);
239
break;
240
case MUX_PRIMLODFRAC:
241
alpha = COLOR_RGBA(gRDP.primLODFrac, gRDP.primLODFrac, gRDP.primLODFrac, gRDP.primLODFrac);
242
break;
243
case MUX_PRIM_ALPHA:
244
{
245
IColor col(gRDP.primitiveColor);
246
col.AlphaReplicate();
247
alpha = (COLOR)col;
248
}
249
break;
250
case MUX_ENV_ALPHA:
251
{
252
IColor col(gRDP.envColor);
253
col.AlphaReplicate();
254
alpha = (COLOR)col;
255
}
256
break;
257
default:
258
alpha = defaultColor;
259
break;
260
}
261
262
if( alphaFlag & MUX_COMPLEMENT )
263
{
264
alpha = 0xFFFFFFFF - alpha;
265
}
266
267
alpha &= 0xFF000000;
268
269
return (color|alpha);
270
}
271
272
//*****************************************************************************
273
//
274
//*****************************************************************************
275
bool gUsingPrimColour = false;
276
bool gUsingEnvColour = false;
277
278
int CountTexel1Cycle(N64CombinerType &m)
279
{
280
int hasTexel[2];
281
uint8 *p = (uint8*)&m;
282
283
for( int i=0; i<2; i++)
284
{
285
hasTexel[i]=0;
286
for( int j=0; j<4; j++)
287
{
288
if( (p[j]&MUX_MASK) == MUX_TEXEL0+i )
289
{
290
hasTexel[i]=1;
291
break;
292
}
293
}
294
}
295
296
return hasTexel[0]+hasTexel[1];
297
}
298
299
uint32 GetTexelNumber(N64CombinerType &m)
300
{
301
if( (m.a&MUX_MASK) == MUX_TEXEL1 || (m.b&MUX_MASK) == MUX_TEXEL1 || (m.c&MUX_MASK) == MUX_TEXEL1 || (m.d&MUX_MASK) == MUX_TEXEL1 )
302
return TEX_1;
303
else
304
return TEX_0;
305
}
306
307
bool IsTxtrUsed(N64CombinerType &m)
308
{
309
if( (m.a&MUX_MASK) == MUX_TEXEL1 || (m.b&MUX_MASK) == MUX_TEXEL1 || (m.c&MUX_MASK) == MUX_TEXEL1 || (m.d&MUX_MASK) == MUX_TEXEL1 )
310
return true;
311
if( (m.a&MUX_MASK) == MUX_TEXEL0 || (m.b&MUX_MASK) == MUX_TEXEL0 || (m.c&MUX_MASK) == MUX_TEXEL0 || (m.d&MUX_MASK) == MUX_TEXEL0 )
312
return true;
313
else
314
return false;
315
}
316
317
//========================================================================
318
319
void CColorCombiner::InitCombinerMode(void)
320
{
321
#ifdef DEBUGGER
322
LOG_UCODE(cycleTypeStrs[gRDP.otherMode.cycle_type]);
323
if( debuggerDropDecodedMux )
324
{
325
UpdateCombiner(m_pDecodedMux->m_dwMux0, m_pDecodedMux->m_dwMux1);
326
}
327
#endif
328
329
if( currentRomOptions.bNormalCombiner )
330
{
331
DisableCombiner();
332
}
333
else if( gRDP.otherMode.cycle_type == CYCLE_TYPE_COPY )
334
{
335
InitCombinerCycleCopy();
336
m_bCycleChanged = true;
337
}
338
else if ( gRDP.otherMode.cycle_type == CYCLE_TYPE_FILL )
339
//else if ( gRDP.otherMode.cycle_type == CYCLE_TYPE_FILL && gRSP.ucode != 5 ) //hack
340
{
341
InitCombinerCycleFill();
342
m_bCycleChanged = true;
343
}
344
else
345
{
346
InitCombinerCycle12();
347
m_bCycleChanged = false;
348
}
349
}
350
351
352
bool bConkerHideShadow=false;
353
void CColorCombiner::UpdateCombiner(uint32 dwMux0, uint32 dwMux1)
354
{
355
#ifdef DEBUGGER
356
if( debuggerDropDecodedMux )
357
{
358
debuggerDropDecodedMux = false;
359
m_pDecodedMux->m_dwMux0 = m_pDecodedMux->m_dwMux1 = 0;
360
m_DecodedMuxList.clear();
361
}
362
#endif
363
364
DecodedMux &m_decodedMux = *m_pDecodedMux;
365
if( m_decodedMux.m_dwMux0 != dwMux0 || m_decodedMux.m_dwMux1 != dwMux1 )
366
{
367
if( options.enableHackForGames == HACK_FOR_DR_MARIO )
368
{
369
// Hack for Dr. Mario
370
if( dwMux1 == 0xfffcf239 &&
371
((m_decodedMux.m_dwMux0 == dwMux0 && dwMux0 == 0x00ffffff &&
372
m_decodedMux.m_dwMux1 != dwMux1 && m_decodedMux.m_dwMux1 == 0xfffcf279 ) ||
373
(m_decodedMux.m_dwMux0 == 0x00ffb3ff && m_decodedMux.m_dwMux1 == 0xff64fe7f && dwMux0 == 0x00ffffff ) ))
374
{
375
//dwMux1 = 0xffcf23A;
376
dwMux1 = 0xfffcf438;
377
}
378
}
379
uint64 mux64 = (((uint64)dwMux1)<<32)+dwMux0;
380
int index=m_DecodedMuxList.find(mux64);
381
382
if( options.enableHackForGames == HACK_FOR_CONKER )
383
{
384
// Conker's shadow, to disable the shadow
385
//Mux=0x00ffe9ff Used in CONKER BFD
386
//Color0: (0 - 0) * 0 + SHADE
387
//Color1: (0 - 0) * 0 + SHADE
388
//Alpha0: (1 - TEXEL0) * SHADE + 0
389
//Alpha1: (1 - TEXEL0) * SHADE + 0
390
if( dwMux1 == 0xffd21f0f && dwMux0 == 0x00ffe9ff )
391
{
392
bConkerHideShadow = true;
393
}
394
else
395
{
396
bConkerHideShadow = false;
397
}
398
}
399
400
if( index >= 0 )
401
{
402
m_decodedMux = m_DecodedMuxList[index];
403
}
404
else
405
{
406
m_decodedMux.Decode(dwMux0, dwMux1);
407
m_decodedMux.splitType[0] = CM_FMT_TYPE_NOT_CHECKED;
408
m_decodedMux.splitType[1] = CM_FMT_TYPE_NOT_CHECKED;
409
m_decodedMux.splitType[2] = CM_FMT_TYPE_NOT_CHECKED;
410
m_decodedMux.splitType[3] = CM_FMT_TYPE_NOT_CHECKED;
411
412
m_decodedMux.Hack();
413
414
if( !m_bSupportMultiTexture )
415
{
416
m_decodedMux.ReplaceVal(MUX_TEXEL1, MUX_TEXEL0);
417
m_decodedMux.ReplaceVal(MUX_LODFRAC,1);
418
m_decodedMux.ReplaceVal(MUX_PRIMLODFRAC,1);
419
}
420
421
m_decodedMux.Simplify();
422
if( m_supportedStages>1)
423
m_decodedMux.SplitComplexStages();
424
425
m_DecodedMuxList.add(m_decodedMux.m_u64Mux, *m_pDecodedMux);
426
#ifdef DEBUGGER
427
if( logCombiners )
428
{
429
TRACE0("Add a new mux");
430
DisplayMuxString();
431
}
432
#endif
433
}
434
435
m_bTex0Enabled = m_decodedMux.m_bTexel0IsUsed;
436
m_bTex1Enabled = m_decodedMux.m_bTexel1IsUsed;
437
m_bTexelsEnable = m_bTex0Enabled||m_bTex1Enabled;
438
439
gRSP.bProcessDiffuseColor = (m_decodedMux.m_dwShadeColorChannelFlag != MUX_0 || m_decodedMux.m_dwShadeAlphaChannelFlag != MUX_0);
440
gRSP.bProcessSpecularColor = false;
441
}
442
}
443
444
445
#ifdef DEBUGGER
446
void CColorCombiner::DisplayMuxString(void)
447
{
448
if( gRDP.otherMode.cycle_type == CYCLE_TYPE_COPY)
449
{
450
TRACE0("COPY Mode\n");
451
}
452
else if( gRDP.otherMode.cycle_type == CYCLE_TYPE_FILL)
453
{
454
TRACE0("FILL Mode\n");
455
}
456
457
m_pDecodedMux->DisplayMuxString("Used");
458
}
459
460
void CColorCombiner::DisplaySimpleMuxString(void)
461
{
462
m_pDecodedMux->DisplaySimpliedMuxString("Used");
463
}
464
#endif
465
466
467